Working ASF skeleton project.
authorethereal <ethereal@ethv.net>
Thu, 6 Nov 2014 08:32:14 +0000 (00:32 -0800)
committerethereal <ethereal@ethv.net>
Thu, 6 Nov 2014 08:32:14 +0000 (00:32 -0800)
90 files changed:
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
asf/common/services/clock/osc.h [new file with mode: 0644]
asf/common/services/clock/pll.h [new file with mode: 0644]
asf/common/services/clock/sam3n/osc.h [new file with mode: 0644]
asf/common/services/clock/sam3n/pll.h [new file with mode: 0644]
asf/common/services/clock/sam3n/sysclk.c [new file with mode: 0644]
asf/common/services/clock/sam3n/sysclk.h [new file with mode: 0644]
asf/common/services/clock/sysclk.h [new file with mode: 0644]
asf/common/utils/interrupt.h [new file with mode: 0644]
asf/common/utils/interrupt/interrupt_sam_nvic.h [new file with mode: 0644]
asf/common/utils/parts.h [new file with mode: 0644]
asf/sam/drivers/pdc/pdc.c [new file with mode: 0644]
asf/sam/drivers/pdc/pdc.h [new file with mode: 0644]
asf/sam/drivers/pio/pio.c [new file with mode: 0644]
asf/sam/drivers/pio/pio.h [new file with mode: 0644]
asf/sam/drivers/pmc/pmc.c [new file with mode: 0644]
asf/sam/drivers/pmc/pmc.h [new file with mode: 0644]
asf/sam/drivers/pwm/pwm.c [new file with mode: 0644]
asf/sam/drivers/pwm/pwm.h [new file with mode: 0644]
asf/sam/drivers/spi/spi.c [new file with mode: 0644]
asf/sam/drivers/spi/spi.h [new file with mode: 0644]
asf/sam/drivers/wdt/wdt.c [new file with mode: 0644]
asf/sam/drivers/wdt/wdt.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_adc.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_chipid.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_dacc.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_efc.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_gpbr.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_matrix.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_pdc.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_pio.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_pmc.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_pwm.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_rstc.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_rtc.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_rtt.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_spi.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_supc.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_tc.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_twi.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_uart.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_usart.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/component/component_wdt.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_adc.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_chipid.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_dacc.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_efc.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_gpbr.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_matrix.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_pioa.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_piob.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_pmc.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_pwm.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_rstc.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_rtc.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_rtt.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_spi.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_supc.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_tc0.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_twi0.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_twi1.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_uart0.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_uart1.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_usart0.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/instance/instance_wdt.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/pio/pio_sam3n2a.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/sam3n.h [new file with mode: 0644]
asf/sam/utils/cmsis/sam3n/include/sam3n2a.h [new file with mode: 0644]
asf/sam/utils/compiler.h [new file with mode: 0644]
asf/sam/utils/header_files/io.h [new file with mode: 0644]
asf/sam/utils/preprocessor/mrepeat.h [new file with mode: 0644]
asf/sam/utils/preprocessor/preprocessor.h [new file with mode: 0644]
asf/sam/utils/preprocessor/stringz.h [new file with mode: 0644]
asf/sam/utils/preprocessor/tpaste.h [new file with mode: 0644]
asf/thirdparty/CMSIS/Include/core_cm3.h [new file with mode: 0644]
asf/thirdparty/CMSIS/Include/core_cmFunc.h [new file with mode: 0644]
asf/thirdparty/CMSIS/Include/core_cmInstr.h [new file with mode: 0644]
asf/thirdparty/CMSIS/Lib/GCC/libarm_cortexM3l_math.a [new file with mode: 0644]
board.h [new file with mode: 0644]
conf_clock.h [new file with mode: 0644]
conf_dma.h [new file with mode: 0644]
exceptions.c [new file with mode: 0644]
exceptions.h [new file with mode: 0644]
flash.ld [new file with mode: 0644]
main.c [new file with mode: 0644]
startup_sam3n.c [new file with mode: 0644]
system_sam3n.c [new file with mode: 0644]
system_sam3n.h [new file with mode: 0644]
util.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..b120abc
--- /dev/null
@@ -0,0 +1,3 @@
+output.bin
+output.elf
+*.o
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..760b88f
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,50 @@
+.PHONY: all
+
+DFLAGS=-D__SAM3N2A__
+INCFLAGS=\
+       -Iasf/common/utils/ \
+       -Iasf/sam/utils/ \
+       -Iasf/sam/utils/header_files \
+       -Iasf/sam/utils/preprocessor \
+       -Iasf/sam/utils/cmsis/sam3n/include \
+       -Iasf/thirdparty/CMSIS/Include \
+       -I.
+WFLAGS=-Wextra -Wall -Wno-unused-parameter
+
+DRIVER_INC=\
+       -Iasf/sam/drivers/pio/ \
+       -Iasf/sam/drivers/pmc/ \
+       -Iasf/sam/drivers/spi/ \
+       -Iasf/sam/drivers/pdc/ \
+       -Iasf/sam/drivers/pwm/ \
+       -Iasf/sam/drivers/wdt/ \
+       -Iasf/common/services/clock
+DRIVER_SRC=\
+       asf/sam/drivers/pio/pio.c \
+       asf/sam/drivers/pmc/pmc.c \
+       asf/sam/drivers/spi/spi.c \
+       asf/sam/drivers/pdc/pdc.c \
+       asf/sam/drivers/pwm/pwm.c \
+       asf/sam/drivers/wdt/wdt.c \
+       asf/common/services/clock/sam3n/sysclk.c
+
+CFLAGS=$(DFLAGS) $(INCFLAGS) $(WFLAGS) $(DRIVER_INC) -mcpu=cortex-m3 -mthumb -std=c11
+
+LDFLAGS=-Lasf/thirdparty/CMSIS/Lib/GCC -larm_cortexM3l_math --entry=Reset_Handler
+
+CPREFIX=arm-none-eabi-
+CC=$(CPREFIX)gcc
+LD=$(CPREFIX)ld
+OBJCOPY=$(CPREFIX)objcopy
+
+SOURCE_FILES=exceptions.c startup_sam3n.c system_sam3n.c main.c util.c $(DRIVER_SRC)
+#OBJECT_FILES=$(add_prefix obj/ $(basename $(SOURCE_FILES:.c=.o)))
+OBJECT_FILES=$(SOURCE_FILES:.c=.o)
+
+all: $(OBJECT_FILES) flash.ld
+       $(LD) $(LDFLAGS) -Tflash.ld $(OBJECT_FILES) -o output.elf
+       $(OBJCOPY) -O binary output.elf output.bin
+
+.PHONY: clean
+clean:
+       -rm -f $(OBJECT_FILES) output.elf
diff --git a/asf/common/services/clock/osc.h b/asf/common/services/clock/osc.h
new file mode 100644 (file)
index 0000000..1ba6567
--- /dev/null
@@ -0,0 +1,174 @@
+/**
+ * \file
+ *
+ * \brief Oscillator management
+ *
+ * Copyright (c) 2010-2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+#ifndef OSC_H_INCLUDED
+#define OSC_H_INCLUDED
+
+#include "parts.h"
+#include "conf_clock.h"
+
+#if SAM3S
+# include "sam3s/osc.h"
+#elif SAM3XA
+# include "sam3x/osc.h"
+#elif SAM3U
+# include "sam3u/osc.h"
+#elif SAM3N
+# include "sam3n/osc.h"
+#elif SAM4S
+# include "sam4s/osc.h"
+#elif SAM4E
+# include "sam4e/osc.h"
+#elif SAM4C
+# include "sam4c/osc.h"
+#elif SAM4CM
+# include "sam4cm/osc.h"
+#elif SAM4CP
+# include "sam4cp/osc.h"
+#elif SAM4L
+# include "sam4l/osc.h"
+#elif SAM4N
+# include "sam4n/osc.h"
+#elif SAMG
+# include "samg/osc.h"
+#elif (UC3A0 || UC3A1)
+# include "uc3a0_a1/osc.h"
+#elif UC3A3
+# include "uc3a3_a4/osc.h"
+#elif UC3B
+# include "uc3b0_b1/osc.h"
+#elif UC3C
+# include "uc3c/osc.h"
+#elif UC3D
+# include "uc3d/osc.h"
+#elif UC3L
+# include "uc3l/osc.h"
+#elif XMEGA
+# include "xmega/osc.h"
+#else
+# error Unsupported chip type
+#endif
+
+/**
+ * \ingroup clk_group
+ * \defgroup osc_group Oscillator Management
+ *
+ * This group contains functions and definitions related to configuring
+ * and enabling/disabling on-chip oscillators. Internal RC-oscillators,
+ * external crystal oscillators and external clock generators are
+ * supported by this module. What all of these have in common is that
+ * they swing at a fixed, nominal frequency which is normally not
+ * adjustable.
+ *
+ * \par Example: Enabling an oscillator
+ *
+ * The following example demonstrates how to enable the external
+ * oscillator on XMEGA A and wait for it to be ready to use. The
+ * oscillator identifiers are platform-specific, so while the same
+ * procedure is used on all platforms, the parameter to osc_enable()
+ * will be different from device to device.
+ * \code
+       osc_enable(OSC_ID_XOSC);
+       osc_wait_ready(OSC_ID_XOSC); \endcode
+ *
+ * \section osc_group_board Board-specific Definitions
+ * If external oscillators are used, the board code must provide the
+ * following definitions for each of those:
+ *   - \b BOARD_<osc name>_HZ: The nominal frequency of the oscillator.
+ *   - \b BOARD_<osc name>_STARTUP_US: The startup time of the
+ *     oscillator in microseconds.
+ *   - \b BOARD_<osc name>_TYPE: The type of oscillator connected, i.e.
+ *     whether it's a crystal or external clock, and sometimes what kind
+ *     of crystal it is. The meaning of this value is platform-specific.
+ *
+ * @{
+ */
+
+//! \name Oscillator Management
+//@{
+/**
+ * \fn void osc_enable(uint8_t id)
+ * \brief Enable oscillator \a id
+ *
+ * The startup time and mode value is automatically determined based on
+ * definitions in the board code.
+ */
+/**
+ * \fn void osc_disable(uint8_t id)
+ * \brief Disable oscillator \a id
+ */
+/**
+ * \fn osc_is_ready(uint8_t id)
+ * \brief Determine whether oscillator \a id is ready.
+ * \retval true Oscillator \a id is running and ready to use as a clock
+ * source.
+ * \retval false Oscillator \a id is not running.
+ */
+/**
+ * \fn uint32_t osc_get_rate(uint8_t id)
+ * \brief Return the frequency of oscillator \a id in Hz
+ */
+
+#ifndef __ASSEMBLY__
+
+/**
+ * \brief Wait until the oscillator identified by \a id is ready
+ *
+ * This function will busy-wait for the oscillator identified by \a id
+ * to become stable and ready to use as a clock source.
+ *
+ * \param id A number identifying the oscillator to wait for.
+ */
+static inline void osc_wait_ready(uint8_t id)
+{
+       while (!osc_is_ready(id)) {
+               /* Do nothing */
+       }
+}
+
+#endif /* __ASSEMBLY__ */
+
+//@}
+
+//! @}
+
+#endif /* OSC_H_INCLUDED */
diff --git a/asf/common/services/clock/pll.h b/asf/common/services/clock/pll.h
new file mode 100644 (file)
index 0000000..ced6070
--- /dev/null
@@ -0,0 +1,330 @@
+/**
+ * \file
+ *
+ * \brief PLL management
+ *
+ * Copyright (c) 2010-2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+#ifndef CLK_PLL_H_INCLUDED
+#define CLK_PLL_H_INCLUDED
+
+#include "parts.h"
+#include "conf_clock.h"
+
+#if SAM3S
+# include "sam3s/pll.h"
+#elif SAM3XA
+# include "sam3x/pll.h"
+#elif SAM3U
+# include "sam3u/pll.h"
+#elif SAM3N
+# include "sam3n/pll.h"
+#elif SAM4S
+# include "sam4s/pll.h"
+#elif SAM4E
+# include "sam4e/pll.h"
+#elif SAM4C
+# include "sam4c/pll.h"
+#elif SAM4CM
+# include "sam4cm/pll.h"
+#elif SAM4CP
+# include "sam4cp/pll.h"
+#elif SAM4L
+# include "sam4l/pll.h"
+#elif SAM4N
+# include "sam4n/pll.h"
+#elif SAMG
+# include "samg/pll.h"
+#elif (UC3A0 || UC3A1)
+# include "uc3a0_a1/pll.h"
+#elif UC3A3
+# include "uc3a3_a4/pll.h"
+#elif UC3B
+# include "uc3b0_b1/pll.h"
+#elif UC3C
+# include "uc3c/pll.h"
+#elif UC3D
+# include "uc3d/pll.h"
+#elif (UC3L0128 || UC3L0256 || UC3L3_L4)
+# include "uc3l/pll.h"
+#elif XMEGA
+# include "xmega/pll.h"
+#else
+# error Unsupported chip type
+#endif
+
+/**
+ * \ingroup clk_group
+ * \defgroup pll_group PLL Management
+ *
+ * This group contains functions and definitions related to configuring
+ * and enabling/disabling on-chip PLLs. A PLL will take an input signal
+ * (the \em source), optionally divide the frequency by a configurable
+ * \em divider, and then multiply the frequency by a configurable \em
+ * multiplier.
+ *
+ * Some devices don't support input dividers; specifying any other
+ * divisor than 1 on these devices will result in an assertion failure.
+ * Other devices may have various restrictions to the frequency range of
+ * the input and output signals.
+ *
+ * \par Example: Setting up PLL0 with default parameters
+ *
+ * The following example shows how to configure and enable PLL0 using
+ * the default parameters specified using the configuration symbols
+ * listed above.
+ * \code
+       pll_enable_config_defaults(0); \endcode
+ *
+ * To configure, enable PLL0 using the default parameters and to disable
+ * a specific feature like Wide Bandwidth Mode (a UC3A3-specific
+ * PLL option.), you can use this initialization process.
+ * \code
+       struct pll_config pllcfg;
+       if (pll_is_locked(pll_id)) {
+               return; // Pll already running
+       }
+       pll_enable_source(CONFIG_PLL0_SOURCE);
+       pll_config_defaults(&pllcfg, 0);
+       pll_config_set_option(&pllcfg, PLL_OPT_WBM_DISABLE);
+       pll_enable(&pllcfg, 0);
+       pll_wait_for_lock(0); \endcode
+ *
+ * When the last function call returns, PLL0 is ready to be used as the
+ * main system clock source.
+ *
+ * \section pll_group_config Configuration Symbols
+ *
+ * Each PLL has a set of default parameters determined by the following
+ * configuration symbols in the application's configuration file:
+ *   - \b CONFIG_PLLn_SOURCE: The default clock source connected to the
+ *     input of PLL \a n. Must be one of the values defined by the
+ *     #pll_source enum.
+ *   - \b CONFIG_PLLn_MUL: The default multiplier (loop divider) of PLL
+ *     \a n.
+ *   - \b CONFIG_PLLn_DIV: The default input divider of PLL \a n.
+ *
+ * These configuration symbols determine the result of calling
+ * pll_config_defaults() and pll_get_default_rate().
+ *
+ * @{
+ */
+
+//! \name Chip-specific PLL characteristics
+//@{
+/**
+ * \def PLL_MAX_STARTUP_CYCLES
+ * \brief Maximum PLL startup time in number of slow clock cycles
+ */
+/**
+ * \def NR_PLLS
+ * \brief Number of on-chip PLLs
+ */
+
+/**
+ * \def PLL_MIN_HZ
+ * \brief Minimum frequency that the PLL can generate
+ */
+/**
+ * \def PLL_MAX_HZ
+ * \brief Maximum frequency that the PLL can generate
+ */
+/**
+ * \def PLL_NR_OPTIONS
+ * \brief Number of PLL option bits
+ */
+//@}
+
+/**
+ * \enum pll_source
+ * \brief PLL clock source
+ */
+
+//! \name PLL configuration
+//@{
+
+/**
+ * \struct pll_config
+ * \brief Hardware-specific representation of PLL configuration.
+ *
+ * This structure contains one or more device-specific values
+ * representing the current PLL configuration. The contents of this
+ * structure is typically different from platform to platform, and the
+ * user should not access any fields except through the PLL
+ * configuration API.
+ */
+
+/**
+ * \fn void pll_config_init(struct pll_config *cfg,
+ *              enum pll_source src, unsigned int div, unsigned int mul)
+ * \brief Initialize PLL configuration from standard parameters.
+ *
+ * \note This function may be defined inline because it is assumed to be
+ * called very few times, and usually with constant parameters. Inlining
+ * it will in such cases reduce the code size significantly.
+ *
+ * \param cfg The PLL configuration to be initialized.
+ * \param src The oscillator to be used as input to the PLL.
+ * \param div PLL input divider.
+ * \param mul PLL loop divider (i.e. multiplier).
+ *
+ * \return A configuration which will make the PLL run at
+ * (\a mul / \a div) times the frequency of \a src
+ */
+/**
+ * \def pll_config_defaults(cfg, pll_id)
+ * \brief Initialize PLL configuration using default parameters.
+ *
+ * After this function returns, \a cfg will contain a configuration
+ * which will make the PLL run at (CONFIG_PLLx_MUL / CONFIG_PLLx_DIV)
+ * times the frequency of CONFIG_PLLx_SOURCE.
+ *
+ * \param cfg The PLL configuration to be initialized.
+ * \param pll_id Use defaults for this PLL.
+ */
+/**
+ * \def pll_get_default_rate(pll_id)
+ * \brief Get the default rate in Hz of \a pll_id
+ */
+/**
+ * \fn void pll_config_set_option(struct pll_config *cfg,
+ *              unsigned int option)
+ * \brief Set the PLL option bit \a option in the configuration \a cfg.
+ *
+ * \param cfg The PLL configuration to be changed.
+ * \param option The PLL option bit to be set.
+ */
+/**
+ * \fn void pll_config_clear_option(struct pll_config *cfg,
+ *              unsigned int option)
+ * \brief Clear the PLL option bit \a option in the configuration \a cfg.
+ *
+ * \param cfg The PLL configuration to be changed.
+ * \param option The PLL option bit to be cleared.
+ */
+/**
+ * \fn void pll_config_read(struct pll_config *cfg, unsigned int pll_id)
+ * \brief Read the currently active configuration of \a pll_id.
+ *
+ * \param cfg The configuration object into which to store the currently
+ * active configuration.
+ * \param pll_id The ID of the PLL to be accessed.
+ */
+/**
+ * \fn void pll_config_write(const struct pll_config *cfg,
+ *              unsigned int pll_id)
+ * \brief Activate the configuration \a cfg on \a pll_id
+ *
+ * \param cfg The configuration object representing the PLL
+ * configuration to be activated.
+ * \param pll_id The ID of the PLL to be updated.
+ */
+
+//@}
+
+//! \name Interaction with the PLL hardware
+//@{
+/**
+ * \fn void pll_enable(const struct pll_config *cfg,
+ *              unsigned int pll_id)
+ * \brief Activate the configuration \a cfg and enable PLL \a pll_id.
+ *
+ * \param cfg The PLL configuration to be activated.
+ * \param pll_id The ID of the PLL to be enabled.
+ */
+/**
+ * \fn void pll_disable(unsigned int pll_id)
+ * \brief Disable the PLL identified by \a pll_id.
+ *
+ * After this function is called, the PLL identified by \a pll_id will
+ * be disabled. The PLL configuration stored in hardware may be affected
+ * by this, so if the caller needs to restore the same configuration
+ * later, it should either do a pll_config_read() before disabling the
+ * PLL, or remember the last configuration written to the PLL.
+ *
+ * \param pll_id The ID of the PLL to be disabled.
+ */
+/**
+ * \fn bool pll_is_locked(unsigned int pll_id)
+ * \brief Determine whether the PLL is locked or not.
+ *
+ * \param pll_id The ID of the PLL to check.
+ *
+ * \retval true The PLL is locked and ready to use as a clock source
+ * \retval false The PLL is not yet locked, or has not been enabled.
+ */
+/**
+ * \fn void pll_enable_source(enum pll_source src)
+ * \brief Enable the source of the pll.
+ * The source is enabled, if the source is not already running.
+ *
+ * \param src The ID of the PLL source to enable.
+ */
+/**
+ * \fn void pll_enable_config_defaults(unsigned int pll_id)
+ * \brief Enable the pll with the default configuration.
+ * PLL is enabled, if the PLL is not already locked.
+ *
+ * \param pll_id The ID of the PLL to enable.
+ */
+
+/**
+ * \brief Wait for PLL \a pll_id to become locked
+ *
+ * \todo Use a timeout to avoid waiting forever and hanging the system
+ *
+ * \param pll_id The ID of the PLL to wait for.
+ *
+ * \retval STATUS_OK The PLL is now locked.
+ * \retval ERR_TIMEOUT Timed out waiting for PLL to become locked.
+ */
+static inline int pll_wait_for_lock(unsigned int pll_id)
+{
+       Assert(pll_id < NR_PLLS);
+
+       while (!pll_is_locked(pll_id)) {
+               /* Do nothing */
+       }
+
+       return 0;
+}
+
+//@}
+//! @}
+
+#endif /* CLK_PLL_H_INCLUDED */
diff --git a/asf/common/services/clock/sam3n/osc.h b/asf/common/services/clock/sam3n/osc.h
new file mode 100644 (file)
index 0000000..ef61a92
--- /dev/null
@@ -0,0 +1,244 @@
+/**
+ * \file
+ *
+ * \brief Chip-specific oscillator management functions.
+ *
+ * Copyright (c) 2011 - 2013 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#ifndef CHIP_OSC_H_INCLUDED
+#define CHIP_OSC_H_INCLUDED
+
+#include "board.h"
+#include "pmc.h"
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+/*
+ * Below BOARD_XXX macros are related to the specific board, and
+ * should be defined by the board code, otherwise default value are used.
+ */
+#if !defined(BOARD_FREQ_SLCK_XTAL)
+#  warning The board slow clock xtal frequency has not been defined.
+#  define BOARD_FREQ_SLCK_XTAL      (32768UL)
+#endif
+
+#if !defined(BOARD_FREQ_SLCK_BYPASS)
+#  warning The board slow clock bypass frequency has not been defined.
+#  define BOARD_FREQ_SLCK_BYPASS    (32768UL)
+#endif
+
+#if !defined(BOARD_FREQ_MAINCK_XTAL)
+#  warning The board main clock xtal frequency has not been defined.
+#  define BOARD_FREQ_MAINCK_XTAL    (12000000UL)
+#endif
+
+#if !defined(BOARD_FREQ_MAINCK_BYPASS)
+#  warning The board main clock bypass frequency has not been defined.
+#  define BOARD_FREQ_MAINCK_BYPASS  (12000000UL)
+#endif
+
+#if !defined(BOARD_OSC_STARTUP_US)
+#  warning The board main clock xtal startup time has not been defined.
+#  define BOARD_OSC_STARTUP_US      (15625UL)
+#endif
+
+/**
+ * \weakgroup osc_group
+ * @{
+ */
+
+//! \name Oscillator identifiers
+//@{
+#define OSC_SLCK_32K_RC             0    //!< Internal 32kHz RC oscillator.
+#define OSC_SLCK_32K_XTAL           1    //!< External 32kHz crystal oscillator.
+#define OSC_SLCK_32K_BYPASS         2    //!< External 32kHz bypass oscillator.
+#define OSC_MAINCK_4M_RC            3    //!< Internal 4MHz RC oscillator.
+#define OSC_MAINCK_8M_RC            4    //!< Internal 8MHz RC oscillator.
+#define OSC_MAINCK_12M_RC           5    //!< Internal 12MHz RC oscillator.
+#define OSC_MAINCK_XTAL             6    //!< External crystal oscillator.
+#define OSC_MAINCK_BYPASS           7    //!< External bypass oscillator.
+//@}
+
+//! \name Oscillator clock speed in hertz
+//@{
+#define OSC_SLCK_32K_RC_HZ          CHIP_FREQ_SLCK_RC               //!< Internal 32kHz RC oscillator.
+#define OSC_SLCK_32K_XTAL_HZ        BOARD_FREQ_SLCK_XTAL            //!< External 32kHz crystal oscillator.
+#define OSC_SLCK_32K_BYPASS_HZ      BOARD_FREQ_SLCK_BYPASS          //!< External 32kHz bypass oscillator.
+#define OSC_MAINCK_4M_RC_HZ         CHIP_FREQ_MAINCK_RC_4MHZ        //!< Internal 4MHz RC oscillator.
+#define OSC_MAINCK_8M_RC_HZ         CHIP_FREQ_MAINCK_RC_8MHZ        //!< Internal 8MHz RC oscillator.
+#define OSC_MAINCK_12M_RC_HZ        CHIP_FREQ_MAINCK_RC_12MHZ       //!< Internal 12MHz RC oscillator.
+#define OSC_MAINCK_XTAL_HZ          BOARD_FREQ_MAINCK_XTAL          //!< External crystal oscillator.
+#define OSC_MAINCK_BYPASS_HZ        BOARD_FREQ_MAINCK_BYPASS        //!< External bypass oscillator.
+//@}
+
+static inline void osc_enable(uint32_t ul_id)
+{
+       switch (ul_id) {
+       case OSC_SLCK_32K_RC:
+               break;
+
+       case OSC_SLCK_32K_XTAL:
+               pmc_switch_sclk_to_32kxtal(PMC_OSC_XTAL);
+               break;
+
+       case OSC_SLCK_32K_BYPASS:
+               pmc_switch_sclk_to_32kxtal(PMC_OSC_BYPASS);
+               break;
+
+
+       case OSC_MAINCK_4M_RC:
+               pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_4_MHz);
+               break;
+
+       case OSC_MAINCK_8M_RC:
+               pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_8_MHz);
+               break;
+
+       case OSC_MAINCK_12M_RC:
+               pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_12_MHz);
+               break;
+
+
+       case OSC_MAINCK_XTAL:
+               pmc_switch_mainck_to_xtal(PMC_OSC_XTAL,
+                       pmc_us_to_moscxtst(BOARD_OSC_STARTUP_US,
+                               OSC_SLCK_32K_RC_HZ));
+               break;
+
+       case OSC_MAINCK_BYPASS:
+               pmc_switch_mainck_to_xtal(PMC_OSC_BYPASS,
+                       pmc_us_to_moscxtst(BOARD_OSC_STARTUP_US,
+                               OSC_SLCK_32K_RC_HZ));
+               break;
+       }
+}
+
+static inline void osc_disable(uint32_t ul_id)
+{
+       switch (ul_id) {
+       case OSC_SLCK_32K_RC:
+       case OSC_SLCK_32K_XTAL:
+       case OSC_SLCK_32K_BYPASS:
+               break;
+
+       case OSC_MAINCK_4M_RC:
+       case OSC_MAINCK_8M_RC:
+       case OSC_MAINCK_12M_RC:
+               pmc_osc_disable_fastrc();
+               break;
+
+       case OSC_MAINCK_XTAL:
+               pmc_osc_disable_xtal(PMC_OSC_XTAL);
+               break;
+
+       case OSC_MAINCK_BYPASS:
+               pmc_osc_disable_xtal(PMC_OSC_BYPASS);
+               break;
+       }
+}
+
+static inline bool osc_is_ready(uint32_t ul_id)
+{
+       switch (ul_id) {
+       case OSC_SLCK_32K_RC:
+               return 1;
+
+       case OSC_SLCK_32K_XTAL:
+       case OSC_SLCK_32K_BYPASS:
+               return pmc_osc_is_ready_32kxtal();
+
+       case OSC_MAINCK_4M_RC:
+       case OSC_MAINCK_8M_RC:
+       case OSC_MAINCK_12M_RC:
+       case OSC_MAINCK_XTAL:
+       case OSC_MAINCK_BYPASS:
+               return pmc_osc_is_ready_mainck();
+       }
+
+       return 0;
+}
+
+static inline uint32_t osc_get_rate(uint32_t ul_id)
+{
+       switch (ul_id) {
+       case OSC_SLCK_32K_RC:
+               return OSC_SLCK_32K_RC_HZ;
+
+       case OSC_SLCK_32K_XTAL:
+               return BOARD_FREQ_SLCK_XTAL;
+
+       case OSC_SLCK_32K_BYPASS:
+               return BOARD_FREQ_SLCK_BYPASS;
+
+       case OSC_MAINCK_4M_RC:
+               return OSC_MAINCK_4M_RC_HZ;
+
+       case OSC_MAINCK_8M_RC:
+               return OSC_MAINCK_8M_RC_HZ;
+
+       case OSC_MAINCK_12M_RC:
+               return OSC_MAINCK_12M_RC_HZ;
+
+       case OSC_MAINCK_XTAL:
+               return BOARD_FREQ_MAINCK_XTAL;
+
+       case OSC_MAINCK_BYPASS:
+               return BOARD_FREQ_MAINCK_BYPASS;
+       }
+
+       return 0;
+}
+
+//! @}
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+}
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+#endif /* CHIP_OSC_H_INCLUDED */
diff --git a/asf/common/services/clock/sam3n/pll.h b/asf/common/services/clock/sam3n/pll.h
new file mode 100644 (file)
index 0000000..0424377
--- /dev/null
@@ -0,0 +1,227 @@
+/**
+ * \file
+ *
+ * \brief Chip-specific PLL definitions.
+ *
+ * Copyright (c) 2011 - 2013 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#ifndef CHIP_PLL_H_INCLUDED
+#define CHIP_PLL_H_INCLUDED
+
+#include <osc.h>
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+/**
+ * \weakgroup pll_group
+ * @{
+ */
+
+#define PLL_OUTPUT_MIN_HZ   60000000
+#define PLL_OUTPUT_MAX_HZ   130000000
+
+#define PLL_INPUT_MIN_HZ    3500000
+#define PLL_INPUT_MAX_HZ    20000000
+
+#define NR_PLLS             1
+#define PLLA_ID             0
+
+#define PLL_COUNT           0x3fU
+
+enum pll_source {
+       PLL_SRC_MAINCK_4M_RC        = OSC_MAINCK_4M_RC,     //!< Internal 4MHz RC oscillator.
+       PLL_SRC_MAINCK_8M_RC        = OSC_MAINCK_8M_RC,     //!< Internal 8MHz RC oscillator.
+       PLL_SRC_MAINCK_12M_RC       = OSC_MAINCK_12M_RC,    //!< Internal 12MHz RC oscillator.
+       PLL_SRC_MAINCK_XTAL         = OSC_MAINCK_XTAL,      //!< External crystal oscillator.
+       PLL_SRC_MAINCK_BYPASS       = OSC_MAINCK_BYPASS,    //!< External bypass oscillator.
+       PLL_NR_SOURCES,                                     //!< Number of PLL sources.
+};
+
+struct pll_config {
+       uint32_t ctrl;
+};
+
+#define pll_get_default_rate(pll_id)                                       \
+       ((osc_get_rate(CONFIG_PLL##pll_id##_SOURCE)                            \
+                       * CONFIG_PLL##pll_id##_MUL)                                    \
+                       / CONFIG_PLL##pll_id##_DIV)
+
+/**
+ * \note The SAM3N PLL hardware interprets mul as mul+1. For readability the hardware mul+1
+ * is hidden in this implementation. Use mul as mul effective value.
+ */
+static inline void pll_config_init(struct pll_config *p_cfg,
+               enum pll_source e_src, uint32_t ul_div, uint32_t ul_mul)
+{
+       uint32_t vco_hz;
+
+       Assert(e_src < PLL_NR_SOURCES);
+
+       /* Calculate internal VCO frequency */
+       vco_hz = osc_get_rate(e_src) / ul_div;
+       Assert(vco_hz >= PLL_INPUT_MIN_HZ);
+       Assert(vco_hz <= PLL_INPUT_MAX_HZ);
+
+       vco_hz *= ul_mul;
+       Assert(vco_hz >= PLL_OUTPUT_MIN_HZ);
+       Assert(vco_hz <= PLL_OUTPUT_MAX_HZ);
+
+       /* PMC hardware will automatically make it mul+1 */
+       p_cfg->ctrl = CKGR_PLLAR_MULA(ul_mul - 1) | CKGR_PLLAR_DIVA(ul_div) | CKGR_PLLAR_PLLACOUNT(PLL_COUNT);
+}
+
+#define pll_config_defaults(cfg, pll_id)                                   \
+       pll_config_init(cfg,                                                   \
+                       CONFIG_PLL##pll_id##_SOURCE,                                   \
+                       CONFIG_PLL##pll_id##_DIV,                                      \
+                       CONFIG_PLL##pll_id##_MUL)
+
+static inline void pll_config_read(struct pll_config *p_cfg, uint32_t ul_pll_id)
+{
+       Assert(ul_pll_id < NR_PLLS);
+
+       if (ul_pll_id == PLLA_ID) {
+               p_cfg->ctrl = PMC->CKGR_PLLAR;
+       }
+}
+
+static inline void pll_config_write(const struct pll_config *p_cfg, uint32_t ul_pll_id)
+{
+       Assert(ul_pll_id < NR_PLLS);
+
+       if (ul_pll_id == PLLA_ID) {
+               pmc_disable_pllack(); // Always stop PLL first!
+               PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | p_cfg->ctrl;
+       }
+}
+
+static inline void pll_enable(const struct pll_config *p_cfg, uint32_t ul_pll_id)
+{
+       Assert(ul_pll_id < NR_PLLS);
+
+       if (ul_pll_id == PLLA_ID) {
+               pmc_disable_pllack(); // Always stop PLL first!
+               PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | p_cfg->ctrl;
+       }
+}
+
+/**
+ * \note This will only disable the selected PLL, not the underlying oscillator (mainck).
+ */
+static inline void pll_disable(uint32_t ul_pll_id)
+{
+       Assert(ul_pll_id < NR_PLLS);
+
+       if (ul_pll_id == PLLA_ID) {
+               pmc_disable_pllack();
+       }
+}
+
+static inline uint32_t pll_is_locked(uint32_t ul_pll_id)
+{
+       Assert(ul_pll_id < NR_PLLS);
+
+       if (ul_pll_id == PLLA_ID) {
+               return pmc_is_locked_pllack();
+       }
+       else {
+               return 0;
+       }
+}
+
+static inline void pll_enable_source(enum pll_source e_src)
+{
+       switch (e_src) {
+       case PLL_SRC_MAINCK_4M_RC:
+       case PLL_SRC_MAINCK_8M_RC:
+       case PLL_SRC_MAINCK_12M_RC:
+       case PLL_SRC_MAINCK_XTAL:
+       case PLL_SRC_MAINCK_BYPASS:
+               osc_enable(e_src);
+               osc_wait_ready(e_src);
+               break;
+
+       default:
+               Assert(false);
+               break;
+       }
+}
+
+static inline void pll_enable_config_defaults(unsigned int ul_pll_id)
+{
+       struct pll_config pllcfg;
+
+       if (pll_is_locked(ul_pll_id)) {
+               return; // Pll already running
+       }
+       switch (ul_pll_id) {
+#ifdef CONFIG_PLL0_SOURCE
+       case 0:
+               pll_enable_source(CONFIG_PLL0_SOURCE);
+               pll_config_init(&pllcfg,
+                               CONFIG_PLL0_SOURCE,
+                               CONFIG_PLL0_DIV,
+                               CONFIG_PLL0_MUL);
+               break;
+#endif
+       default:
+               Assert(false);
+               break;
+       }
+       pll_enable(&pllcfg, ul_pll_id);
+       while (!pll_is_locked(ul_pll_id));
+}
+
+//! @}
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+}
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+#endif /* CHIP_PLL_H_INCLUDED */
diff --git a/asf/common/services/clock/sam3n/sysclk.c b/asf/common/services/clock/sam3n/sysclk.c
new file mode 100644 (file)
index 0000000..8bad482
--- /dev/null
@@ -0,0 +1,220 @@
+/**
+ * \file
+ *
+ * \brief Chip-specific system clock management functions.
+ *
+ * Copyright (c) 2011 - 2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#include <sysclk.h>
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+/**
+ * \weakgroup sysclk_group
+ * @{
+ */
+
+#if defined(CONFIG_SYSCLK_DEFAULT_RETURNS_SLOW_OSC)
+/**
+ * \brief boolean signalling that the sysclk_init is done.
+ */
+uint32_t sysclk_initialized = 0;
+#endif
+
+/**
+ * \brief Set system clock prescaler configuration
+ *
+ * This function will change the system clock prescaler configuration to
+ * match the parameters.
+ *
+ * \note The parameters to this function are device-specific.
+ *
+ * \param cpu_shift The CPU clock will be divided by \f$2^{mck\_pres}\f$
+ */
+void sysclk_set_prescalers(uint32_t ul_pres)
+{
+       pmc_mck_set_prescaler(ul_pres);
+       SystemCoreClockUpdate();
+}
+
+/**
+ * \brief Change the source of the main system clock.
+ *
+ * \param src The new system clock source. Must be one of the constants
+ * from the <em>System Clock Sources</em> section.
+ */
+void sysclk_set_source(uint32_t ul_src)
+{
+       switch (ul_src) {
+       case SYSCLK_SRC_SLCK_RC:
+       case SYSCLK_SRC_SLCK_XTAL:
+       case SYSCLK_SRC_SLCK_BYPASS:
+               pmc_mck_set_source(PMC_MCKR_CSS_SLOW_CLK);
+               break;
+
+       case SYSCLK_SRC_MAINCK_4M_RC:
+       case SYSCLK_SRC_MAINCK_8M_RC:
+       case SYSCLK_SRC_MAINCK_12M_RC:
+       case SYSCLK_SRC_MAINCK_XTAL:
+       case SYSCLK_SRC_MAINCK_BYPASS:
+               pmc_mck_set_source(PMC_MCKR_CSS_MAIN_CLK);
+               break;
+
+       case SYSCLK_SRC_PLLACK:
+               pmc_mck_set_source(PMC_MCKR_CSS_PLLA_CLK);
+               break;
+       }
+
+       SystemCoreClockUpdate();
+}
+
+#if defined(CONFIG_USBCLK_SOURCE)
+#  warning SAM3N has no USB peripheral, please remove CONFIG_USBCLK_SOURCE
+#endif
+#if defined(CONFIG_USBCLK_SOURCE) || defined(__DOXYGEN__)
+/**
+ * \brief Enable USB clock.
+ *
+ * \note SAM3N has no USB peripheral, nothing is done here
+ */
+void sysclk_enable_usb(void)
+{
+}
+
+/**
+ * \brief Disable the USB clock.
+ *
+ * \note SAM3N has no USB peripheral, nothing is done here
+ */
+void sysclk_disable_usb(void)
+{
+}
+#endif // CONFIG_USBCLK_SOURCE
+
+void sysclk_init(void)
+{
+       /* Set flash wait state to max in case the below clock switching. */
+       system_init_flash(CHIP_FREQ_CPU_MAX);
+
+       /* Config system clock setting */
+       if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_SLCK_RC) {
+               osc_enable(OSC_SLCK_32K_RC);
+               osc_wait_ready(OSC_SLCK_32K_RC);
+               pmc_switch_mck_to_sclk(CONFIG_SYSCLK_PRES);
+       }
+
+       else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_SLCK_XTAL) {
+               osc_enable(OSC_SLCK_32K_XTAL);
+               osc_wait_ready(OSC_SLCK_32K_XTAL);
+               pmc_switch_mck_to_sclk(CONFIG_SYSCLK_PRES);
+       }
+
+       else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_SLCK_BYPASS) {
+               osc_enable(OSC_SLCK_32K_BYPASS);
+               osc_wait_ready(OSC_SLCK_32K_BYPASS);
+               pmc_switch_mck_to_sclk(CONFIG_SYSCLK_PRES);
+       }
+
+       else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_4M_RC) {
+               /* Already running from SYSCLK_SRC_MAINCK_4M_RC */
+       }
+
+       else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_8M_RC) {
+               osc_enable(OSC_MAINCK_8M_RC);
+               osc_wait_ready(OSC_MAINCK_8M_RC);
+               pmc_switch_mck_to_mainck(CONFIG_SYSCLK_PRES);
+       }
+
+       else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_12M_RC) {
+               osc_enable(OSC_MAINCK_12M_RC);
+               osc_wait_ready(OSC_MAINCK_12M_RC);
+               pmc_switch_mck_to_mainck(CONFIG_SYSCLK_PRES);
+       }
+
+       else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_XTAL) {
+               osc_enable(OSC_MAINCK_XTAL);
+               osc_wait_ready(OSC_MAINCK_XTAL);
+               pmc_switch_mck_to_mainck(CONFIG_SYSCLK_PRES);
+       }
+
+       else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_BYPASS) {
+               osc_enable(OSC_MAINCK_BYPASS);
+               osc_wait_ready(OSC_MAINCK_BYPASS);
+               pmc_switch_mck_to_mainck(CONFIG_SYSCLK_PRES);
+       }
+
+#ifdef CONFIG_PLL0_SOURCE
+       else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_PLLACK) {
+               struct pll_config pllcfg;
+
+               pll_enable_source(CONFIG_PLL0_SOURCE);
+               pll_config_defaults(&pllcfg, 0);
+               pll_enable(&pllcfg, 0);
+               pll_wait_for_lock(0);
+               pmc_switch_mck_to_pllack(CONFIG_SYSCLK_PRES);
+       }
+#endif
+
+       /* Update the SystemFrequency variable */
+       SystemCoreClockUpdate();
+
+       /* Set a flash wait state depending on the new cpu frequency */
+       system_init_flash(sysclk_get_cpu_hz());
+
+#if (defined CONFIG_SYSCLK_DEFAULT_RETURNS_SLOW_OSC)
+       /* Signal that the internal frequencies are setup */
+       sysclk_initialized = 1;
+#endif
+}
+
+//! @}
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+}
+#endif
+/**INDENT-ON**/
+/// @endcond
diff --git a/asf/common/services/clock/sam3n/sysclk.h b/asf/common/services/clock/sam3n/sysclk.h
new file mode 100644 (file)
index 0000000..234b75a
--- /dev/null
@@ -0,0 +1,369 @@
+/**
+ * \file
+ *
+ * \brief Chip-specific system clock management functions.
+ *
+ * Copyright (c) 2011 - 2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#ifndef CHIP_SYSCLK_H_INCLUDED
+#define CHIP_SYSCLK_H_INCLUDED
+
+#include <osc.h>
+#include <pll.h>
+
+/**
+ * \page sysclk_quickstart Quick Start Guide for the System Clock Management service (SAM3N)
+ *
+ * This is the quick start guide for the \ref sysclk_group "System Clock Management"
+ * service, with step-by-step instructions on how to configure and use the service for
+ * specific use cases.
+ *
+ * \section sysclk_quickstart_usecases System Clock Management use cases
+ * - \ref sysclk_quickstart_basic
+ *
+ * \section sysclk_quickstart_basic Basic usage of the System Clock Management service
+ * This section will present a basic use case for the System Clock Management service.
+ * This use case will configure the main system clock to 48MHz, using an internal PLL
+ * module to multiply the frequency of a crystal attached to the microcontroller.
+ *
+ * \subsection sysclk_quickstart_use_case_1_prereq Prerequisites
+ *  - None
+ *
+ * \subsection sysclk_quickstart_use_case_1_setup_steps Initialization code
+ * Add to the application initialization code:
+ * \code
+       sysclk_init();
+\endcode
+ *
+ * \subsection sysclk_quickstart_use_case_1_setup_steps_workflow Workflow
+ * -# Configure the system clocks according to the settings in conf_clock.h:
+ *    \code sysclk_init(); \endcode
+ *
+ * \subsection sysclk_quickstart_use_case_1_example_code Example code
+ *   Add or uncomment the following in your conf_clock.h header file, commenting out all other
+ *   definitions of the same symbol(s):
+ *   \code
+          #define CONFIG_SYSCLK_SOURCE        SYSCLK_SRC_PLLACK
+
+          // Fpll0 = (Fclk * PLL_mul) / PLL_div
+          #define CONFIG_PLL0_SOURCE          PLL_SRC_MAINCK_XTAL
+          #define CONFIG_PLL0_MUL             (48000000UL / BOARD_FREQ_MAINCK_XTAL)
+          #define CONFIG_PLL0_DIV             1
+
+          // Fbus = Fsys / BUS_div
+          #define CONFIG_SYSCLK_PRES          SYSCLK_PRES_1
+\endcode
+ *
+ * \subsection sysclk_quickstart_use_case_1_example_workflow Workflow
+ *  -# Configure the main system clock to use the output of the PLL module as its source:
+ *   \code #define CONFIG_SYSCLK_SOURCE          SYSCLK_SRC_PLLACK \endcode
+ *  -# Configure the PLL module to use the fast external fast crystal oscillator as its source:
+ *   \code #define CONFIG_PLL0_SOURCE            PLL_SRC_MAINCK_XTAL \endcode
+ *  -# Configure the PLL module to multiply the external fast crystal oscillator frequency up to 48MHz:
+ *   \code
+       #define CONFIG_PLL0_MUL             (48000000UL / BOARD_FREQ_MAINCK_XTAL)
+       #define CONFIG_PLL0_DIV             1
+\endcode
+ *   \note For user boards, \c BOARD_FREQ_MAINCK_XTAL should be defined in the board \c conf_board.h configuration
+ *         file as the frequency of the fast crystal attached to the microcontroller.
+ *  -# Configure the main clock to run at the full 48MHz, disable scaling of the main system clock speed:
+ *    \code
+       #define CONFIG_SYSCLK_PRES         SYSCLK_PRES_1
+\endcode
+ *    \note Some dividers are powers of two, while others are integer division factors. Refer to the
+ *          formulas in the conf_clock.h template commented above each division define.
+ */
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+/**
+ * \weakgroup sysclk_group
+ * @{
+ */
+
+//! \name Configuration Symbols
+//@{
+/**
+ * \def CONFIG_SYSCLK_SOURCE
+ * \brief Initial/static main system clock source
+ *
+ * The main system clock will be configured to use this clock during
+ * initialization.
+ */
+#ifndef CONFIG_SYSCLK_SOURCE
+# define CONFIG_SYSCLK_SOURCE   SYSCLK_SRC_MAINCK_4M_RC
+#endif
+/**
+ * \def CONFIG_SYSCLK_PRES
+ * \brief Initial CPU clock divider (mck)
+ *
+ * The MCK will run at
+ * \f[
+ *   f_{MCK} = \frac{f_{sys}}{\mathrm{CONFIG\_SYSCLK\_PRES}}\,\mbox{Hz}
+ * \f]
+ * after initialization.
+ */
+#ifndef CONFIG_SYSCLK_PRES
+# define CONFIG_SYSCLK_PRES  0
+#endif
+
+//@}
+
+//! \name Master Clock Sources (MCK)
+//@{
+#define SYSCLK_SRC_SLCK_RC              0       //!< Internal 32kHz RC oscillator as master source clock
+#define SYSCLK_SRC_SLCK_XTAL            1       //!< External 32kHz crystal oscillator as master source clock
+#define SYSCLK_SRC_SLCK_BYPASS          2       //!< External 32kHz bypass oscillator as master source clock
+#define SYSCLK_SRC_MAINCK_4M_RC         3       //!< Internal 4MHz RC oscillator as master source clock
+#define SYSCLK_SRC_MAINCK_8M_RC         4       //!< Internal 8MHz RC oscillator as master source clock
+#define SYSCLK_SRC_MAINCK_12M_RC        5       //!< Internal 12MHz RC oscillator as master source clock
+#define SYSCLK_SRC_MAINCK_XTAL          6       //!< External crystal oscillator as master source clock
+#define SYSCLK_SRC_MAINCK_BYPASS        7       //!< External bypass oscillator as master source clock
+#define SYSCLK_SRC_PLLACK               8       //!< Use PLLACK as master source clock
+//@}
+
+//! \name Master Clock Prescalers (MCK)
+//@{
+#define SYSCLK_PRES_1                   PMC_MCKR_PRES_CLK_1     //!< Set master clock prescaler to 1
+#define SYSCLK_PRES_2                   PMC_MCKR_PRES_CLK_2     //!< Set master clock prescaler to 2
+#define SYSCLK_PRES_4                   PMC_MCKR_PRES_CLK_4     //!< Set master clock prescaler to 4
+#define SYSCLK_PRES_8                   PMC_MCKR_PRES_CLK_8     //!< Set master clock prescaler to 8
+#define SYSCLK_PRES_16                  PMC_MCKR_PRES_CLK_16    //!< Set master clock prescaler to 16
+#define SYSCLK_PRES_32                  PMC_MCKR_PRES_CLK_32    //!< Set master clock prescaler to 32
+#define SYSCLK_PRES_64                  PMC_MCKR_PRES_CLK_64    //!< Set master clock prescaler to 64
+#define SYSCLK_PRES_3                   PMC_MCKR_PRES_CLK_3     //!< Set master clock prescaler to 3
+//@}
+
+//! \name USB Clock Sources
+//@{
+#define USBCLK_SRC_PLL0       0     //!< Use PLLA
+//@}
+
+/**
+ * \def CONFIG_USBCLK_SOURCE
+ * \brief Configuration symbol for the USB generic clock source
+ *
+ * Sets the clock source to use for the USB. The source must also be properly
+ * configured.
+ *
+ * Define this to one of the \c USBCLK_SRC_xxx settings. Leave it undefined if
+ * USB is not required.
+ */
+#ifdef __DOXYGEN__
+# define CONFIG_USBCLK_SOURCE
+#endif
+
+/**
+ * \def CONFIG_USBCLK_DIV
+ * \brief Configuration symbol for the USB generic clock divider setting
+ *
+ * Sets the clock division for the USB generic clock. If a USB clock source is
+ * selected with CONFIG_USBCLK_SOURCE, this configuration symbol must also be
+ * defined.
+ */
+#ifdef __DOXYGEN__
+# define CONFIG_USBCLK_DIV
+#endif
+
+/**
+ * \name Querying the system clock
+ *
+ * The following functions may be used to query the current frequency of
+ * the system clock and the CPU and bus clocks derived from it.
+ * sysclk_get_main_hz() and sysclk_get_cpu_hz() can be assumed to be
+ * available on all platforms, although some platforms may define
+ * additional accessors for various chip-internal bus clocks. These are
+ * usually not intended to be queried directly by generic code.
+ */
+//@{
+
+/**
+ * \brief Return the current rate in Hz of the main system clock
+ *
+ * \todo This function assumes that the main clock source never changes
+ * once it's been set up, and that PLL0 always runs at the compile-time
+ * configured default rate. While this is probably the most common
+ * configuration, which we want to support as a special case for
+ * performance reasons, we will at some point need to support more
+ * dynamic setups as well.
+ */
+#if (defined CONFIG_SYSCLK_DEFAULT_RETURNS_SLOW_OSC)
+extern uint32_t sysclk_initialized;
+#endif
+static inline uint32_t sysclk_get_main_hz(void)
+{
+#if (defined CONFIG_SYSCLK_DEFAULT_RETURNS_SLOW_OSC)
+       if (!sysclk_initialized ) {
+               return OSC_MAINCK_4M_RC_HZ;
+       }
+#endif
+
+       /* Config system clock setting */
+       if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_SLCK_RC) {
+               return OSC_SLCK_32K_RC_HZ;
+       } else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_SLCK_XTAL) {
+               return OSC_SLCK_32K_XTAL_HZ;
+       } else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_SLCK_BYPASS) {
+               return OSC_SLCK_32K_BYPASS_HZ;
+       } else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_4M_RC) {
+               return OSC_MAINCK_4M_RC_HZ;
+       } else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_8M_RC) {
+               return OSC_MAINCK_8M_RC_HZ;
+       } else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_12M_RC) {
+               return OSC_MAINCK_12M_RC_HZ;
+       } else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_XTAL) {
+               return OSC_MAINCK_XTAL_HZ;
+       } else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_BYPASS) {
+               return OSC_MAINCK_BYPASS_HZ;
+       }
+#ifdef CONFIG_PLL0_SOURCE
+       else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_PLLACK) {
+               return pll_get_default_rate(0);
+       }
+#endif
+       else {
+               /* unhandled_case(CONFIG_SYSCLK_SOURCE); */
+               return 0;
+       }
+}
+
+/**
+ * \brief Return the current rate in Hz of the CPU clock
+ *
+ * \todo This function assumes that the CPU always runs at the system
+ * clock frequency. We want to support at least two more scenarios:
+ * Fixed CPU/bus clock dividers (config symbols) and dynamic CPU/bus
+ * clock dividers (which may change at run time). Ditto for all the bus
+ * clocks.
+ *
+ * \return Frequency of the CPU clock, in Hz.
+ */
+static inline uint32_t sysclk_get_cpu_hz(void)
+{
+       /* CONFIG_SYSCLK_PRES is the register value for setting the expected */
+       /* prescaler, not an immediate value. */
+       return sysclk_get_main_hz() /
+               ((CONFIG_SYSCLK_PRES == SYSCLK_PRES_3) ? 3 :
+                       (1 << (CONFIG_SYSCLK_PRES >> PMC_MCKR_PRES_Pos)));
+}
+
+/**
+ * \brief Retrieves the current rate in Hz of the peripheral clocks.
+ *
+ * \return Frequency of the peripheral clocks, in Hz.
+ */
+static inline uint32_t sysclk_get_peripheral_hz(void)
+{
+       /* CONFIG_SYSCLK_PRES is the register value for setting the expected */
+       /* prescaler, not an immediate value. */
+       return sysclk_get_main_hz() /
+               ((CONFIG_SYSCLK_PRES == SYSCLK_PRES_3) ? 3 :
+                       (1 << (CONFIG_SYSCLK_PRES >> PMC_MCKR_PRES_Pos)));
+}
+
+/**
+ * \brief Retrieves the current rate in Hz of the Peripheral Bus clock attached
+ *        to the specified peripheral.
+ *
+ * \param module Pointer to the module's base address.
+ *
+ * \return Frequency of the bus attached to the specified peripheral, in Hz.
+ */
+static inline uint32_t sysclk_get_peripheral_bus_hz(const volatile void *module)
+{
+       UNUSED(module);
+       return sysclk_get_peripheral_hz();
+}
+//@}
+
+//! \name Enabling and disabling synchronous clocks
+//@{
+
+/**
+ * \brief Enable a peripheral's clock.
+ *
+ * \param ul_id Id (number) of the peripheral clock.
+ */
+static inline void sysclk_enable_peripheral_clock(uint32_t ul_id)
+{
+       pmc_enable_periph_clk(ul_id);
+}
+
+/**
+ * \brief Disable a peripheral's clock.
+ *
+ * \param ul_id Id (number) of the peripheral clock.
+ */
+static inline void sysclk_disable_peripheral_clock(uint32_t ul_id)
+{
+       pmc_disable_periph_clk(ul_id);
+}
+
+//@}
+
+//! \name System Clock Source and Prescaler configuration
+//@{
+
+extern void sysclk_set_prescalers(uint32_t ul_pres);
+extern void sysclk_set_source(uint32_t ul_src);
+
+//@}
+
+extern void sysclk_enable_usb(void);
+extern void sysclk_disable_usb(void);
+
+extern void sysclk_init(void);
+
+//! @}
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+}
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+#endif /* CHIP_SYSCLK_H_INCLUDED */
diff --git a/asf/common/services/clock/sysclk.h b/asf/common/services/clock/sysclk.h
new file mode 100644 (file)
index 0000000..cc4cb8b
--- /dev/null
@@ -0,0 +1,183 @@
+/**
+ * \file
+ *
+ * \brief System clock management
+ *
+ * Copyright (c) 2010-2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+#ifndef SYSCLK_H_INCLUDED
+#define SYSCLK_H_INCLUDED
+
+#include "parts.h"
+#include "conf_clock.h"
+
+#if SAM3S
+# include "sam3s/sysclk.h"
+#elif SAM3U
+# include "sam3u/sysclk.h"
+#elif SAM3N
+# include "sam3n/sysclk.h"
+#elif SAM3XA
+# include "sam3x/sysclk.h"
+#elif SAM4S
+# include "sam4s/sysclk.h"
+#elif SAM4E
+# include "sam4e/sysclk.h"
+#elif SAM4C
+# include "sam4c/sysclk.h"
+#elif SAM4CM
+# include "sam4cm/sysclk.h"
+#elif SAM4CP
+# include "sam4cp/sysclk.h"
+#elif SAM4L
+# include "sam4l/sysclk.h"
+#elif SAM4N
+# include "sam4n/sysclk.h"
+#elif SAMG
+# include "samg/sysclk.h"
+#elif (UC3A0 || UC3A1)
+# include "uc3a0_a1/sysclk.h"
+#elif UC3A3
+# include "uc3a3_a4/sysclk.h"
+#elif UC3B
+# include "uc3b0_b1/sysclk.h"
+#elif UC3C
+# include "uc3c/sysclk.h"
+#elif UC3D
+# include "uc3d/sysclk.h"
+#elif UC3L
+# include "uc3l/sysclk.h"
+#elif XMEGA
+# include "xmega/sysclk.h"
+#elif MEGA
+# include "mega/sysclk.h"
+#else
+# error Unsupported chip type
+#endif
+
+/**
+ * \defgroup clk_group Clock Management
+ */
+
+/**
+ * \ingroup clk_group
+ * \defgroup sysclk_group System Clock Management
+ *
+ * See \ref sysclk_quickstart.
+ *
+ * The <em>sysclk</em> API covers the <em>system clock</em> and all
+ * clocks derived from it. The system clock is a chip-internal clock on
+ * which all <em>synchronous clocks</em>, i.e. CPU and bus/peripheral
+ * clocks, are based. The system clock is typically generated from one
+ * of a variety of sources, which may include crystal and RC oscillators
+ * as well as PLLs.  The clocks derived from the system clock are
+ * sometimes also known as <em>synchronous clocks</em>, since they
+ * always run synchronously with respect to each other, as opposed to
+ * <em>generic clocks</em> which may run from different oscillators or
+ * PLLs.
+ *
+ * Most applications should simply call sysclk_init() to initialize
+ * everything related to the system clock and its source (oscillator,
+ * PLL or DFLL), and leave it at that. More advanced applications, and
+ * platform-specific drivers, may require additional services from the
+ * clock system, some of which may be platform-specific.
+ *
+ * \section sysclk_group_platform Platform Dependencies
+ *
+ * The sysclk API is partially chip- or platform-specific. While all
+ * platforms provide mostly the same functionality, there are some
+ * variations around how different bus types and clock tree structures
+ * are handled.
+ *
+ * The following functions are available on all platforms with the same
+ * parameters and functionality. These functions may be called freely by
+ * portable applications, drivers and services:
+ *   - sysclk_init()
+ *   - sysclk_set_source()
+ *   - sysclk_get_main_hz()
+ *   - sysclk_get_cpu_hz()
+ *   - sysclk_get_peripheral_bus_hz()
+ *
+ * The following functions are available on all platforms, but there may
+ * be variations in the function signature (i.e. parameters) and
+ * behavior. These functions are typically called by platform-specific
+ * parts of drivers, and applications that aren't intended to be
+ * portable:
+ *   - sysclk_enable_peripheral_clock()
+ *   - sysclk_disable_peripheral_clock()
+ *   - sysclk_enable_module()
+ *   - sysclk_disable_module()
+ *   - sysclk_module_is_enabled()
+ *   - sysclk_set_prescalers()
+ *
+ * All other functions should be considered platform-specific.
+ * Enabling/disabling clocks to specific peripherals as well as
+ * determining the speed of these clocks should be done by calling
+ * functions provided by the driver for that peripheral.
+ *
+ * @{
+ */
+
+//! \name System Clock Initialization
+//@{
+/**
+ * \fn void sysclk_init(void)
+ * \brief Initialize the synchronous clock system.
+ *
+ * This function will initialize the system clock and its source. This
+ * includes:
+ *   - Mask all synchronous clocks except for any clocks which are
+ *     essential for normal operation (for example internal memory
+ *     clocks).
+ *   - Set up the system clock prescalers as specified by the
+ *     application's configuration file.
+ *   - Enable the clock source specified by the application's
+ *     configuration file (oscillator or PLL) and wait for it to become
+ *     stable.
+ *   - Set the main system clock source to the clock specified by the
+ *     application's configuration file.
+ *
+ * Since all non-essential peripheral clocks are initially disabled, it
+ * is the responsibility of the peripheral driver to re-enable any
+ * clocks that are needed for normal operation.
+ */
+//@}
+
+//! @}
+
+#endif /* SYSCLK_H_INCLUDED */
diff --git a/asf/common/utils/interrupt.h b/asf/common/utils/interrupt.h
new file mode 100644 (file)
index 0000000..3613a26
--- /dev/null
@@ -0,0 +1,139 @@
+/**
+ * \file
+ *
+ * \brief Global interrupt management for 8- and 32-bit AVR
+ *
+ * Copyright (c) 2010-2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+#ifndef UTILS_INTERRUPT_H
+#define UTILS_INTERRUPT_H
+
+#include <parts.h>
+
+#if XMEGA || MEGA || TINY
+#  include "interrupt/interrupt_avr8.h"
+#elif UC3
+#  include "interrupt/interrupt_avr32.h"
+#elif SAM
+#  include "interrupt/interrupt_sam_nvic.h"
+#else
+#  error Unsupported device.
+#endif
+
+/**
+ * \defgroup interrupt_group Global interrupt management
+ *
+ * This is a driver for global enabling and disabling of interrupts.
+ *
+ * @{
+ */
+
+#if defined(__DOXYGEN__)
+/**
+ * \def CONFIG_INTERRUPT_FORCE_INTC
+ * \brief Force usage of the ASF INTC driver
+ *
+ * Predefine this symbol when preprocessing to force the use of the ASF INTC driver.
+ * This is useful to ensure compatibility across compilers and shall be used only when required
+ * by the application needs.
+ */
+#  define CONFIG_INTERRUPT_FORCE_INTC
+#endif
+
+//! \name Global interrupt flags
+//@{
+/**
+ * \typedef irqflags_t
+ * \brief Type used for holding state of interrupt flag
+ */
+
+/**
+ * \def cpu_irq_enable
+ * \brief Enable interrupts globally
+ */
+
+/**
+ * \def cpu_irq_disable
+ * \brief Disable interrupts globally
+ */
+
+/**
+ * \fn irqflags_t cpu_irq_save(void)
+ * \brief Get and clear the global interrupt flags
+ *
+ * Use in conjunction with \ref cpu_irq_restore.
+ *
+ * \return Current state of interrupt flags.
+ *
+ * \note This function leaves interrupts disabled.
+ */
+
+/**
+ * \fn void cpu_irq_restore(irqflags_t flags)
+ * \brief Restore global interrupt flags
+ *
+ * Use in conjunction with \ref cpu_irq_save.
+ *
+ * \param flags State to set interrupt flag to.
+ */
+
+/**
+ * \fn bool cpu_irq_is_enabled_flags(irqflags_t flags)
+ * \brief Check if interrupts are globally enabled in supplied flags
+ *
+ * \param flags Currents state of interrupt flags.
+ *
+ * \return True if interrupts are enabled.
+ */
+
+/**
+ * \def cpu_irq_is_enabled
+ * \brief Check if interrupts are globally enabled
+ *
+ * \return True if interrupts are enabled.
+ */
+//@}
+
+//! @}
+
+/**
+ * \ingroup interrupt_group
+ * \defgroup interrupt_deprecated_group Deprecated interrupt definitions
+ */
+
+#endif /* UTILS_INTERRUPT_H */
diff --git a/asf/common/utils/interrupt/interrupt_sam_nvic.h b/asf/common/utils/interrupt/interrupt_sam_nvic.h
new file mode 100644 (file)
index 0000000..1b23b08
--- /dev/null
@@ -0,0 +1,186 @@
+/**
+ * \file
+ *
+ * \brief Global interrupt management for SAM D20, SAM3 and SAM4 (NVIC based)
+ *
+ * Copyright (c) 2012-2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#ifndef UTILS_INTERRUPT_INTERRUPT_H
+#define UTILS_INTERRUPT_INTERRUPT_H
+
+#include <compiler.h>
+#include <parts.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \weakgroup interrupt_group
+ *
+ * @{
+ */
+
+/**
+ * \name Interrupt Service Routine definition
+ *
+ * @{
+ */
+
+/**
+ * \brief Define service routine
+ *
+ * \note For NVIC devices the interrupt service routines are predefined to
+ *       add to vector table in binary generation, so there is no service
+ *       register at run time. The routine collections are in exceptions.h.
+ *
+ * Usage:
+ * \code
+       ISR(foo_irq_handler)
+       {
+            // Function definition
+            ...
+       }
+\endcode
+ *
+ * \param func Name for the function.
+ */
+#  define ISR(func)   \
+       void func (void)
+
+/**
+ * \brief Initialize interrupt vectors
+ *
+ * For NVIC the interrupt vectors are put in vector table. So nothing
+ * to do to initialize them, except defined the vector function with
+ * right name.
+ *
+ * This must be called prior to \ref irq_register_handler.
+ */
+#  define irq_initialize_vectors()   \
+       do {                             \
+       } while(0)
+
+/**
+ * \brief Register handler for interrupt
+ *
+ * For NVIC the interrupt vectors are put in vector table. So nothing
+ * to do to register them, except defined the vector function with
+ * right name.
+ *
+ * Usage:
+ * \code
+       irq_initialize_vectors();
+       irq_register_handler(foo_irq_handler);
+\endcode
+ *
+ * \note The function \a func must be defined with the \ref ISR macro.
+ * \note The functions prototypes can be found in the device exception header
+ *       files (exceptions.h).
+ */
+#  define irq_register_handler(int_num, int_prio)                      \
+       NVIC_ClearPendingIRQ(    (IRQn_Type)int_num);                      \
+       NVIC_SetPriority(    (IRQn_Type)int_num, int_prio);                \
+       NVIC_EnableIRQ(      (IRQn_Type)int_num);                          \
+
+//@}
+
+#  define cpu_irq_enable()                     \
+       do {                                       \
+               g_interrupt_enabled = true;            \
+               __DMB();                               \
+               __enable_irq();                        \
+       } while (0)
+#  define cpu_irq_disable()                    \
+       do {                                       \
+               __disable_irq();                       \
+               __DMB();                               \
+               g_interrupt_enabled = false;           \
+       } while (0)
+
+typedef uint32_t irqflags_t;
+
+#if !defined(__DOXYGEN__)
+extern volatile bool g_interrupt_enabled;
+#endif
+
+#define cpu_irq_is_enabled()    (__get_PRIMASK() == 0)
+
+static volatile uint32_t cpu_irq_critical_section_counter;
+static volatile bool     cpu_irq_prev_interrupt_state;
+
+static inline irqflags_t cpu_irq_save(void)
+{
+       irqflags_t flags = cpu_irq_is_enabled();
+       cpu_irq_disable();
+       return flags;
+}
+
+static inline bool cpu_irq_is_enabled_flags(irqflags_t flags)
+{
+       return (flags);
+}
+
+static inline void cpu_irq_restore(irqflags_t flags)
+{
+       if (cpu_irq_is_enabled_flags(flags))
+               cpu_irq_enable();
+}
+
+void cpu_irq_enter_critical(void);
+void cpu_irq_leave_critical(void);
+
+/**
+ * \weakgroup interrupt_deprecated_group
+ * @{
+ */
+
+#define Enable_global_interrupt()            cpu_irq_enable()
+#define Disable_global_interrupt()           cpu_irq_disable()
+#define Is_global_interrupt_enabled()        cpu_irq_is_enabled()
+
+//@}
+
+//@}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UTILS_INTERRUPT_INTERRUPT_H */
diff --git a/asf/common/utils/parts.h b/asf/common/utils/parts.h
new file mode 100644 (file)
index 0000000..3304a74
--- /dev/null
@@ -0,0 +1,1242 @@
+/**
+ * \file
+ *
+ * \brief Atmel part identification macros
+ *
+ * Copyright (C) 2012-2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#ifndef ATMEL_PARTS_H
+#define ATMEL_PARTS_H
+
+/**
+ * \defgroup part_macros_group Atmel part identification macros
+ *
+ * This collection of macros identify which series and families that the various
+ * Atmel parts belong to. These can be used to select part-dependent sections of
+ * code at compile time.
+ *
+ * @{
+ */
+
+/**
+ * \name Convenience macros for part checking
+ * @{
+ */
+/* ! Check GCC and IAR part definition for 8-bit AVR */
+#define AVR8_PART_IS_DEFINED(part) \
+       (defined(__ ## part ## __) || defined(__AVR_ ## part ## __))
+
+/* ! Check GCC and IAR part definition for 32-bit AVR */
+#define AVR32_PART_IS_DEFINED(part) \
+       (defined(__AT32 ## part ## __) || defined(__AVR32_ ## part ## __))
+
+/* ! Check GCC and IAR part definition for SAM */
+#define SAM_PART_IS_DEFINED(part) (defined(__ ## part ## __))
+/** @} */
+
+/**
+ * \defgroup uc3_part_macros_group AVR UC3 parts
+ * @{
+ */
+
+/**
+ * \name AVR UC3 A series
+ * @{
+ */
+#define UC3A0 (        \
+               AVR32_PART_IS_DEFINED(UC3A0128) || \
+               AVR32_PART_IS_DEFINED(UC3A0256) || \
+               AVR32_PART_IS_DEFINED(UC3A0512) \
+               )
+
+#define UC3A1 (        \
+               AVR32_PART_IS_DEFINED(UC3A1128) || \
+               AVR32_PART_IS_DEFINED(UC3A1256) || \
+               AVR32_PART_IS_DEFINED(UC3A1512) \
+               )
+
+#define UC3A3 (        \
+               AVR32_PART_IS_DEFINED(UC3A364)   || \
+               AVR32_PART_IS_DEFINED(UC3A364S)  || \
+               AVR32_PART_IS_DEFINED(UC3A3128)  || \
+               AVR32_PART_IS_DEFINED(UC3A3128S) || \
+               AVR32_PART_IS_DEFINED(UC3A3256)  || \
+               AVR32_PART_IS_DEFINED(UC3A3256S) \
+               )
+
+#define UC3A4 (        \
+               AVR32_PART_IS_DEFINED(UC3A464)   || \
+               AVR32_PART_IS_DEFINED(UC3A464S)  || \
+               AVR32_PART_IS_DEFINED(UC3A4128)  || \
+               AVR32_PART_IS_DEFINED(UC3A4128S) || \
+               AVR32_PART_IS_DEFINED(UC3A4256)  || \
+               AVR32_PART_IS_DEFINED(UC3A4256S) \
+               )
+/** @} */
+
+/**
+ * \name AVR UC3 B series
+ * @{
+ */
+#define UC3B0 (        \
+               AVR32_PART_IS_DEFINED(UC3B064)  || \
+               AVR32_PART_IS_DEFINED(UC3B0128) || \
+               AVR32_PART_IS_DEFINED(UC3B0256) || \
+               AVR32_PART_IS_DEFINED(UC3B0512) \
+               )
+
+#define UC3B1 (        \
+               AVR32_PART_IS_DEFINED(UC3B164)  || \
+               AVR32_PART_IS_DEFINED(UC3B1128) || \
+               AVR32_PART_IS_DEFINED(UC3B1256) || \
+               AVR32_PART_IS_DEFINED(UC3B1512) \
+               )
+/** @} */
+
+/**
+ * \name AVR UC3 C series
+ * @{
+ */
+#define UC3C0 (        \
+               AVR32_PART_IS_DEFINED(UC3C064C)  || \
+               AVR32_PART_IS_DEFINED(UC3C0128C) || \
+               AVR32_PART_IS_DEFINED(UC3C0256C) || \
+               AVR32_PART_IS_DEFINED(UC3C0512C) \
+               )
+
+#define UC3C1 (        \
+               AVR32_PART_IS_DEFINED(UC3C164C)  || \
+               AVR32_PART_IS_DEFINED(UC3C1128C) || \
+               AVR32_PART_IS_DEFINED(UC3C1256C) || \
+               AVR32_PART_IS_DEFINED(UC3C1512C) \
+               )
+
+#define UC3C2 (        \
+               AVR32_PART_IS_DEFINED(UC3C264C)  || \
+               AVR32_PART_IS_DEFINED(UC3C2128C) || \
+               AVR32_PART_IS_DEFINED(UC3C2256C) || \
+               AVR32_PART_IS_DEFINED(UC3C2512C) \
+               )
+/** @} */
+
+/**
+ * \name AVR UC3 D series
+ * @{
+ */
+#define UC3D3 (        \
+               AVR32_PART_IS_DEFINED(UC64D3)  || \
+               AVR32_PART_IS_DEFINED(UC128D3) \
+               )
+
+#define UC3D4 (        \
+               AVR32_PART_IS_DEFINED(UC64D4)  || \
+               AVR32_PART_IS_DEFINED(UC128D4) \
+               )
+/** @} */
+
+/**
+ * \name AVR UC3 L series
+ * @{
+ */
+#define UC3L0 (        \
+               AVR32_PART_IS_DEFINED(UC3L016) || \
+               AVR32_PART_IS_DEFINED(UC3L032) || \
+               AVR32_PART_IS_DEFINED(UC3L064) \
+               )
+
+#define UC3L0128 ( \
+               AVR32_PART_IS_DEFINED(UC3L0128) \
+               )
+
+#define UC3L0256 ( \
+               AVR32_PART_IS_DEFINED(UC3L0256) \
+               )
+
+#define UC3L3 (        \
+               AVR32_PART_IS_DEFINED(UC64L3U)  || \
+               AVR32_PART_IS_DEFINED(UC128L3U) || \
+               AVR32_PART_IS_DEFINED(UC256L3U) \
+               )
+
+#define UC3L4 (        \
+               AVR32_PART_IS_DEFINED(UC64L4U)  || \
+               AVR32_PART_IS_DEFINED(UC128L4U) || \
+               AVR32_PART_IS_DEFINED(UC256L4U) \
+               )
+
+#define UC3L3_L4 (UC3L3 || UC3L4)
+/** @} */
+
+/**
+ * \name AVR UC3 families
+ * @{
+ */
+/** AVR UC3 A family */
+#define UC3A (UC3A0 || UC3A1 || UC3A3 || UC3A4)
+
+/** AVR UC3 B family */
+#define UC3B (UC3B0 || UC3B1)
+
+/** AVR UC3 C family */
+#define UC3C (UC3C0 || UC3C1 || UC3C2)
+
+/** AVR UC3 D family */
+#define UC3D (UC3D3 || UC3D4)
+
+/** AVR UC3 L family */
+#define UC3L (UC3L0 || UC3L0128 || UC3L0256 || UC3L3_L4)
+/** @} */
+
+/** AVR UC3 product line */
+#define UC3  (UC3A || UC3B || UC3C || UC3D || UC3L)
+
+/** @} */
+
+/**
+ * \defgroup xmega_part_macros_group AVR XMEGA parts
+ * @{
+ */
+
+/**
+ * \name AVR XMEGA A series
+ * @{
+ */
+#define XMEGA_A1 ( \
+               AVR8_PART_IS_DEFINED(ATxmega64A1)  || \
+               AVR8_PART_IS_DEFINED(ATxmega128A1) \
+               )
+
+#define XMEGA_A3 ( \
+               AVR8_PART_IS_DEFINED(ATxmega64A3)  || \
+               AVR8_PART_IS_DEFINED(ATxmega128A3) || \
+               AVR8_PART_IS_DEFINED(ATxmega192A3) || \
+               AVR8_PART_IS_DEFINED(ATxmega256A3) \
+               )
+
+#define XMEGA_A3B ( \
+               AVR8_PART_IS_DEFINED(ATxmega256A3B) \
+               )
+
+#define XMEGA_A4 ( \
+               AVR8_PART_IS_DEFINED(ATxmega16A4) || \
+               AVR8_PART_IS_DEFINED(ATxmega32A4) \
+               )
+/** @} */
+
+/**
+ * \name AVR XMEGA AU series
+ * @{
+ */
+#define XMEGA_A1U ( \
+               AVR8_PART_IS_DEFINED(ATxmega64A1U)  || \
+               AVR8_PART_IS_DEFINED(ATxmega128A1U) \
+               )
+
+#define XMEGA_A3U ( \
+               AVR8_PART_IS_DEFINED(ATxmega64A3U)  || \
+               AVR8_PART_IS_DEFINED(ATxmega128A3U) || \
+               AVR8_PART_IS_DEFINED(ATxmega192A3U) || \
+               AVR8_PART_IS_DEFINED(ATxmega256A3U) \
+               )
+
+#define XMEGA_A3BU ( \
+               AVR8_PART_IS_DEFINED(ATxmega256A3BU) \
+               )
+
+#define XMEGA_A4U ( \
+               AVR8_PART_IS_DEFINED(ATxmega16A4U)  || \
+               AVR8_PART_IS_DEFINED(ATxmega32A4U)  || \
+               AVR8_PART_IS_DEFINED(ATxmega64A4U)  || \
+               AVR8_PART_IS_DEFINED(ATxmega128A4U) \
+               )
+/** @} */
+
+/**
+ * \name AVR XMEGA B series
+ * @{
+ */
+#define XMEGA_B1  ( \
+               AVR8_PART_IS_DEFINED(ATxmega64B1)  || \
+               AVR8_PART_IS_DEFINED(ATxmega128B1) \
+               )
+
+#define XMEGA_B3  ( \
+               AVR8_PART_IS_DEFINED(ATxmega64B3)  || \
+               AVR8_PART_IS_DEFINED(ATxmega128B3) \
+               )
+/** @} */
+
+/**
+ * \name AVR XMEGA C series
+ * @{
+ */
+#define XMEGA_C3 ( \
+               AVR8_PART_IS_DEFINED(ATxmega384C3)  || \
+               AVR8_PART_IS_DEFINED(ATxmega256C3)  || \
+               AVR8_PART_IS_DEFINED(ATxmega192C3)  || \
+               AVR8_PART_IS_DEFINED(ATxmega128C3)  || \
+               AVR8_PART_IS_DEFINED(ATxmega64C3)   || \
+               AVR8_PART_IS_DEFINED(ATxmega32C3) \
+               )
+
+#define XMEGA_C4 ( \
+               AVR8_PART_IS_DEFINED(ATxmega32C4)  || \
+               AVR8_PART_IS_DEFINED(ATxmega16C4) \
+               )
+/** @} */
+
+/**
+ * \name AVR XMEGA D series
+ * @{
+ */
+#define XMEGA_D3 ( \
+               AVR8_PART_IS_DEFINED(ATxmega32D3)  || \
+               AVR8_PART_IS_DEFINED(ATxmega64D3)  || \
+               AVR8_PART_IS_DEFINED(ATxmega128D3) || \
+               AVR8_PART_IS_DEFINED(ATxmega192D3) || \
+               AVR8_PART_IS_DEFINED(ATxmega256D3) || \
+               AVR8_PART_IS_DEFINED(ATxmega384D3) \
+               )
+
+#define XMEGA_D4 ( \
+               AVR8_PART_IS_DEFINED(ATxmega16D4)  || \
+               AVR8_PART_IS_DEFINED(ATxmega32D4)  || \
+               AVR8_PART_IS_DEFINED(ATxmega64D4)  || \
+               AVR8_PART_IS_DEFINED(ATxmega128D4) \
+               )
+/** @} */
+
+/**
+ * \name AVR XMEGA E series
+ * @{
+ */
+#define XMEGA_E5 ( \
+               AVR8_PART_IS_DEFINED(ATxmega8E5)   || \
+               AVR8_PART_IS_DEFINED(ATxmega16E5)  || \
+               AVR8_PART_IS_DEFINED(ATxmega32E5)     \
+       )
+/** @} */
+
+
+/**
+ * \name AVR XMEGA families
+ * @{
+ */
+/** AVR XMEGA A family */
+#define XMEGA_A (XMEGA_A1 || XMEGA_A3 || XMEGA_A3B || XMEGA_A4)
+
+/** AVR XMEGA AU family */
+#define XMEGA_AU (XMEGA_A1U || XMEGA_A3U || XMEGA_A3BU || XMEGA_A4U)
+
+/** AVR XMEGA B family */
+#define XMEGA_B (XMEGA_B1 || XMEGA_B3)
+
+/** AVR XMEGA C family */
+#define XMEGA_C (XMEGA_C3 || XMEGA_C4)
+
+/** AVR XMEGA D family */
+#define XMEGA_D (XMEGA_D3 || XMEGA_D4)
+
+/** AVR XMEGA E family */
+#define XMEGA_E (XMEGA_E5)
+/** @} */
+
+
+/** AVR XMEGA product line */
+#define XMEGA (XMEGA_A || XMEGA_AU || XMEGA_B || XMEGA_C || XMEGA_D || XMEGA_E)
+
+/** @} */
+
+/**
+ * \defgroup mega_part_macros_group megaAVR parts
+ *
+ * \note These megaAVR groupings are based on the groups in AVR Libc for the
+ * part header files. They are not names of official megaAVR device series or
+ * families.
+ *
+ * @{
+ */
+
+/**
+ * \name ATmegaxx0/xx1 subgroups
+ * @{
+ */
+#define MEGA_XX0 ( \
+               AVR8_PART_IS_DEFINED(ATmega640)  || \
+               AVR8_PART_IS_DEFINED(ATmega1280) || \
+               AVR8_PART_IS_DEFINED(ATmega2560) \
+               )
+
+#define MEGA_XX1 ( \
+               AVR8_PART_IS_DEFINED(ATmega1281) || \
+               AVR8_PART_IS_DEFINED(ATmega2561) \
+               )
+/** @} */
+
+/**
+ * \name megaAVR groups
+ * @{
+ */
+/** ATmegaxx0/xx1 group */
+#define MEGA_XX0_1 (MEGA_XX0 || MEGA_XX1)
+
+/** ATmegaxx4 group */
+#define MEGA_XX4 ( \
+               AVR8_PART_IS_DEFINED(ATmega164A)  || \
+               AVR8_PART_IS_DEFINED(ATmega164PA) || \
+               AVR8_PART_IS_DEFINED(ATmega324A)  || \
+               AVR8_PART_IS_DEFINED(ATmega324PA) || \
+               AVR8_PART_IS_DEFINED(ATmega644)   || \
+               AVR8_PART_IS_DEFINED(ATmega644A)  || \
+               AVR8_PART_IS_DEFINED(ATmega644PA) || \
+               AVR8_PART_IS_DEFINED(ATmega1284P)   || \
+               AVR8_PART_IS_DEFINED(ATmega128RFA1) \
+               )
+
+/** ATmegaxx4 group */
+#define MEGA_XX4_A ( \
+               AVR8_PART_IS_DEFINED(ATmega164A)  || \
+               AVR8_PART_IS_DEFINED(ATmega164PA) || \
+               AVR8_PART_IS_DEFINED(ATmega324A)  || \
+               AVR8_PART_IS_DEFINED(ATmega324PA) || \
+               AVR8_PART_IS_DEFINED(ATmega644A)  || \
+               AVR8_PART_IS_DEFINED(ATmega644PA) || \
+               AVR8_PART_IS_DEFINED(ATmega1284P) \
+               )
+
+/** ATmegaxx8 group */
+#define MEGA_XX8 ( \
+               AVR8_PART_IS_DEFINED(ATmega48)    || \
+               AVR8_PART_IS_DEFINED(ATmega48A)   || \
+               AVR8_PART_IS_DEFINED(ATmega48PA)  || \
+               AVR8_PART_IS_DEFINED(ATmega88)    || \
+               AVR8_PART_IS_DEFINED(ATmega88A)   || \
+               AVR8_PART_IS_DEFINED(ATmega88PA)  || \
+               AVR8_PART_IS_DEFINED(ATmega168)   || \
+               AVR8_PART_IS_DEFINED(ATmega168A)  || \
+               AVR8_PART_IS_DEFINED(ATmega168PA) || \
+               AVR8_PART_IS_DEFINED(ATmega328)   || \
+               AVR8_PART_IS_DEFINED(ATmega328P) \
+               )
+
+/** ATmegaxx8A/P/PA group */
+#define MEGA_XX8_A ( \
+               AVR8_PART_IS_DEFINED(ATmega48A)   || \
+               AVR8_PART_IS_DEFINED(ATmega48PA)  || \
+               AVR8_PART_IS_DEFINED(ATmega88A)   || \
+               AVR8_PART_IS_DEFINED(ATmega88PA)  || \
+               AVR8_PART_IS_DEFINED(ATmega168A)  || \
+               AVR8_PART_IS_DEFINED(ATmega168PA) || \
+               AVR8_PART_IS_DEFINED(ATmega328P) \
+               )
+
+/** ATmegaxx group */
+#define MEGA_XX ( \
+               AVR8_PART_IS_DEFINED(ATmega16)   || \
+               AVR8_PART_IS_DEFINED(ATmega16A)  || \
+               AVR8_PART_IS_DEFINED(ATmega32)   || \
+               AVR8_PART_IS_DEFINED(ATmega32A)  || \
+               AVR8_PART_IS_DEFINED(ATmega64)   || \
+               AVR8_PART_IS_DEFINED(ATmega64A)  || \
+               AVR8_PART_IS_DEFINED(ATmega128)  || \
+               AVR8_PART_IS_DEFINED(ATmega128A) \
+               )
+
+/** ATmegaxxA/P/PA group */
+#define MEGA_XX_A ( \
+               AVR8_PART_IS_DEFINED(ATmega16A)  || \
+               AVR8_PART_IS_DEFINED(ATmega32A)  || \
+               AVR8_PART_IS_DEFINED(ATmega64A)  || \
+               AVR8_PART_IS_DEFINED(ATmega128A) \
+               )
+/** ATmegaxxRFA1 group */
+#define MEGA_RFA1 ( \
+               AVR8_PART_IS_DEFINED(ATmega128RFA1) \
+               )
+
+/** ATmegaxxRFR2 group */
+#define MEGA_RFR2 ( \
+               AVR8_PART_IS_DEFINED(ATmega64RFR2)   || \
+               AVR8_PART_IS_DEFINED(ATmega128RFR2)  || \
+               AVR8_PART_IS_DEFINED(ATmega256RFR2)  || \
+               AVR8_PART_IS_DEFINED(ATmega644RFR2)  || \
+               AVR8_PART_IS_DEFINED(ATmega1284RFR2) || \
+               AVR8_PART_IS_DEFINED(ATmega2564RFR2) \
+               )
+
+
+/** ATmegaxxRFxx group */
+#define MEGA_RF (MEGA_RFA1 || MEGA_RFR2)
+
+/**
+ * \name ATmegaxx_un0/un1/un2 subgroups
+ * @{
+ */
+#define MEGA_XX_UN0 ( \
+               AVR8_PART_IS_DEFINED(ATmega16)    || \
+               AVR8_PART_IS_DEFINED(ATmega16A)   || \
+               AVR8_PART_IS_DEFINED(ATmega32)    || \
+               AVR8_PART_IS_DEFINED(ATmega32A) \
+               )
+
+/** ATmegaxx group without power reduction and
+ *  And interrupt sense register.
+ */
+#define MEGA_XX_UN1 ( \
+               AVR8_PART_IS_DEFINED(ATmega64)    || \
+               AVR8_PART_IS_DEFINED(ATmega64A)   || \
+               AVR8_PART_IS_DEFINED(ATmega128)   || \
+               AVR8_PART_IS_DEFINED(ATmega128A) \
+               )
+
+/** ATmegaxx group without power reduction and
+ *  And interrupt sense register.
+ */
+#define MEGA_XX_UN2 ( \
+               AVR8_PART_IS_DEFINED(ATmega169P)  || \
+               AVR8_PART_IS_DEFINED(ATmega169PA) || \
+               AVR8_PART_IS_DEFINED(ATmega329P)  || \
+               AVR8_PART_IS_DEFINED(ATmega329PA) \
+               )
+
+/** Devices added to complete megaAVR offering.
+ *  Please do not use this group symbol as it is not intended
+ *  to be permanent: the devices should be regrouped.
+ */
+#define MEGA_UNCATEGORIZED ( \
+               AVR8_PART_IS_DEFINED(AT90CAN128)     || \
+               AVR8_PART_IS_DEFINED(AT90CAN32)      || \
+               AVR8_PART_IS_DEFINED(AT90CAN64)      || \
+               AVR8_PART_IS_DEFINED(AT90PWM1)       || \
+               AVR8_PART_IS_DEFINED(AT90PWM216)     || \
+               AVR8_PART_IS_DEFINED(AT90PWM2B)      || \
+               AVR8_PART_IS_DEFINED(AT90PWM316)     || \
+               AVR8_PART_IS_DEFINED(AT90PWM3B)      || \
+               AVR8_PART_IS_DEFINED(AT90PWM81)      || \
+               AVR8_PART_IS_DEFINED(AT90USB1286)    || \
+               AVR8_PART_IS_DEFINED(AT90USB1287)    || \
+               AVR8_PART_IS_DEFINED(AT90USB162)     || \
+               AVR8_PART_IS_DEFINED(AT90USB646)     || \
+               AVR8_PART_IS_DEFINED(AT90USB647)     || \
+               AVR8_PART_IS_DEFINED(AT90USB82)      || \
+               AVR8_PART_IS_DEFINED(ATmega1284)     || \
+               AVR8_PART_IS_DEFINED(ATmega162)      || \
+               AVR8_PART_IS_DEFINED(ATmega164P)     || \
+               AVR8_PART_IS_DEFINED(ATmega165A)     || \
+               AVR8_PART_IS_DEFINED(ATmega165P)     || \
+               AVR8_PART_IS_DEFINED(ATmega165PA)    || \
+               AVR8_PART_IS_DEFINED(ATmega168P)     || \
+               AVR8_PART_IS_DEFINED(ATmega169A)     || \
+               AVR8_PART_IS_DEFINED(ATmega16M1)     || \
+               AVR8_PART_IS_DEFINED(ATmega16U2)     || \
+               AVR8_PART_IS_DEFINED(ATmega16U4)     || \
+               AVR8_PART_IS_DEFINED(ATmega256RFA2)  || \
+               AVR8_PART_IS_DEFINED(ATmega324P)     || \
+               AVR8_PART_IS_DEFINED(ATmega325)      || \
+               AVR8_PART_IS_DEFINED(ATmega3250)     || \
+               AVR8_PART_IS_DEFINED(ATmega3250A)    || \
+               AVR8_PART_IS_DEFINED(ATmega3250P)    || \
+               AVR8_PART_IS_DEFINED(ATmega3250PA)   || \
+               AVR8_PART_IS_DEFINED(ATmega325A)     || \
+               AVR8_PART_IS_DEFINED(ATmega325P)     || \
+               AVR8_PART_IS_DEFINED(ATmega325PA)    || \
+               AVR8_PART_IS_DEFINED(ATmega329)      || \
+               AVR8_PART_IS_DEFINED(ATmega3290)     || \
+               AVR8_PART_IS_DEFINED(ATmega3290A)    || \
+               AVR8_PART_IS_DEFINED(ATmega3290P)    || \
+               AVR8_PART_IS_DEFINED(ATmega3290PA)   || \
+               AVR8_PART_IS_DEFINED(ATmega329A)     || \
+               AVR8_PART_IS_DEFINED(ATmega32M1)     || \
+               AVR8_PART_IS_DEFINED(ATmega32U2)     || \
+               AVR8_PART_IS_DEFINED(ATmega32U4)     || \
+               AVR8_PART_IS_DEFINED(ATmega48P)      || \
+               AVR8_PART_IS_DEFINED(ATmega644P)     || \
+               AVR8_PART_IS_DEFINED(ATmega645)      || \
+               AVR8_PART_IS_DEFINED(ATmega6450)     || \
+               AVR8_PART_IS_DEFINED(ATmega6450A)    || \
+               AVR8_PART_IS_DEFINED(ATmega6450P)    || \
+               AVR8_PART_IS_DEFINED(ATmega645A)     || \
+               AVR8_PART_IS_DEFINED(ATmega645P)     || \
+               AVR8_PART_IS_DEFINED(ATmega649)      || \
+               AVR8_PART_IS_DEFINED(ATmega6490)     || \
+               AVR8_PART_IS_DEFINED(ATmega6490A)    || \
+               AVR8_PART_IS_DEFINED(ATmega6490P)    || \
+               AVR8_PART_IS_DEFINED(ATmega649A)     || \
+               AVR8_PART_IS_DEFINED(ATmega649P)     || \
+               AVR8_PART_IS_DEFINED(ATmega64M1)     || \
+               AVR8_PART_IS_DEFINED(ATmega64RFA2)   || \
+               AVR8_PART_IS_DEFINED(ATmega8)        || \
+               AVR8_PART_IS_DEFINED(ATmega8515)     || \
+               AVR8_PART_IS_DEFINED(ATmega8535)     || \
+               AVR8_PART_IS_DEFINED(ATmega88P)      || \
+               AVR8_PART_IS_DEFINED(ATmega8A)       || \
+               AVR8_PART_IS_DEFINED(ATmega8U2)         \
+       )
+
+/** Unspecified group */
+#define MEGA_UNSPECIFIED (MEGA_XX_UN0 || MEGA_XX_UN1 || MEGA_XX_UN2 || \
+       MEGA_UNCATEGORIZED)
+
+/** @} */
+
+/** megaAVR product line */
+#define MEGA (MEGA_XX0_1 || MEGA_XX4 || MEGA_XX8 || MEGA_XX || MEGA_RF || \
+       MEGA_UNSPECIFIED)
+
+/** @} */
+
+/**
+ * \defgroup tiny_part_macros_group tinyAVR parts
+ *
+ * @{
+ */
+
+/**
+ * \name tinyAVR groups
+ * @{
+ */
+
+/** Devices added to complete tinyAVR offering.
+ *  Please do not use this group symbol as it is not intended
+ *  to be permanent: the devices should be regrouped.
+ */
+#define TINY_UNCATEGORIZED ( \
+               AVR8_PART_IS_DEFINED(ATtiny10)    || \
+               AVR8_PART_IS_DEFINED(ATtiny13)    || \
+               AVR8_PART_IS_DEFINED(ATtiny13A)   || \
+               AVR8_PART_IS_DEFINED(ATtiny1634)  || \
+               AVR8_PART_IS_DEFINED(ATtiny167)   || \
+               AVR8_PART_IS_DEFINED(ATtiny20)    || \
+               AVR8_PART_IS_DEFINED(ATtiny2313)  || \
+               AVR8_PART_IS_DEFINED(ATtiny2313A) || \
+               AVR8_PART_IS_DEFINED(ATtiny24)    || \
+               AVR8_PART_IS_DEFINED(ATtiny24A)   || \
+               AVR8_PART_IS_DEFINED(ATtiny25)    || \
+               AVR8_PART_IS_DEFINED(ATtiny26)    || \
+               AVR8_PART_IS_DEFINED(ATtiny261)   || \
+               AVR8_PART_IS_DEFINED(ATtiny261A)  || \
+               AVR8_PART_IS_DEFINED(ATtiny4)     || \
+               AVR8_PART_IS_DEFINED(ATtiny40)    || \
+               AVR8_PART_IS_DEFINED(ATtiny4313)  || \
+               AVR8_PART_IS_DEFINED(ATtiny43U)   || \
+               AVR8_PART_IS_DEFINED(ATtiny44)    || \
+               AVR8_PART_IS_DEFINED(ATtiny44A)   || \
+               AVR8_PART_IS_DEFINED(ATtiny45)    || \
+               AVR8_PART_IS_DEFINED(ATtiny461)   || \
+               AVR8_PART_IS_DEFINED(ATtiny461A)  || \
+               AVR8_PART_IS_DEFINED(ATtiny48)    || \
+               AVR8_PART_IS_DEFINED(ATtiny5)     || \
+               AVR8_PART_IS_DEFINED(ATtiny828)   || \
+               AVR8_PART_IS_DEFINED(ATtiny84)    || \
+               AVR8_PART_IS_DEFINED(ATtiny84A)   || \
+               AVR8_PART_IS_DEFINED(ATtiny85)    || \
+               AVR8_PART_IS_DEFINED(ATtiny861)   || \
+               AVR8_PART_IS_DEFINED(ATtiny861A)  || \
+               AVR8_PART_IS_DEFINED(ATtiny87)    || \
+               AVR8_PART_IS_DEFINED(ATtiny88)    || \
+               AVR8_PART_IS_DEFINED(ATtiny9)        \
+       )
+
+/** @} */
+
+/** tinyAVR product line */
+#define TINY (TINY_UNCATEGORIZED)
+
+/** @} */
+
+/**
+ * \defgroup sam_part_macros_group SAM parts
+ * @{
+ */
+
+/**
+ * \name SAM3S series
+ * @{
+ */
+#define SAM3S1 ( \
+               SAM_PART_IS_DEFINED(SAM3S1A) || \
+               SAM_PART_IS_DEFINED(SAM3S1B) || \
+               SAM_PART_IS_DEFINED(SAM3S1C) \
+               )
+
+#define SAM3S2 ( \
+               SAM_PART_IS_DEFINED(SAM3S2A) || \
+               SAM_PART_IS_DEFINED(SAM3S2B) || \
+               SAM_PART_IS_DEFINED(SAM3S2C) \
+               )
+
+#define SAM3S4 ( \
+               SAM_PART_IS_DEFINED(SAM3S4A) || \
+               SAM_PART_IS_DEFINED(SAM3S4B) || \
+               SAM_PART_IS_DEFINED(SAM3S4C) \
+               )
+
+#define SAM3S8 ( \
+               SAM_PART_IS_DEFINED(SAM3S8B) || \
+               SAM_PART_IS_DEFINED(SAM3S8C) \
+               )
+
+#define SAM3SD8 ( \
+               SAM_PART_IS_DEFINED(SAM3SD8B) || \
+               SAM_PART_IS_DEFINED(SAM3SD8C) \
+               )
+/** @} */
+
+/**
+ * \name SAM3U series
+ * @{
+ */
+#define SAM3U1 ( \
+               SAM_PART_IS_DEFINED(SAM3U1C) || \
+               SAM_PART_IS_DEFINED(SAM3U1E) \
+               )
+
+#define SAM3U2 ( \
+               SAM_PART_IS_DEFINED(SAM3U2C) || \
+               SAM_PART_IS_DEFINED(SAM3U2E) \
+               )
+
+#define SAM3U4 ( \
+               SAM_PART_IS_DEFINED(SAM3U4C) || \
+               SAM_PART_IS_DEFINED(SAM3U4E) \
+               )
+/** @} */
+
+/**
+ * \name SAM3N series
+ * @{
+ */
+#define SAM3N00 ( \
+               SAM_PART_IS_DEFINED(SAM3N00A) ||        \
+               SAM_PART_IS_DEFINED(SAM3N00B) \
+               )
+
+#define SAM3N0 ( \
+               SAM_PART_IS_DEFINED(SAM3N0A) || \
+               SAM_PART_IS_DEFINED(SAM3N0B) || \
+               SAM_PART_IS_DEFINED(SAM3N0C) \
+               )
+
+#define SAM3N1 ( \
+               SAM_PART_IS_DEFINED(SAM3N1A) || \
+               SAM_PART_IS_DEFINED(SAM3N1B) || \
+               SAM_PART_IS_DEFINED(SAM3N1C) \
+               )
+
+#define SAM3N2 ( \
+               SAM_PART_IS_DEFINED(SAM3N2A) || \
+               SAM_PART_IS_DEFINED(SAM3N2B) || \
+               SAM_PART_IS_DEFINED(SAM3N2C) \
+               )
+
+#define SAM3N4 ( \
+               SAM_PART_IS_DEFINED(SAM3N4A) || \
+               SAM_PART_IS_DEFINED(SAM3N4B) || \
+               SAM_PART_IS_DEFINED(SAM3N4C) \
+               )
+/** @} */
+
+/**
+ * \name SAM3X series
+ * @{
+ */
+#define SAM3X4 ( \
+               SAM_PART_IS_DEFINED(SAM3X4C) || \
+               SAM_PART_IS_DEFINED(SAM3X4E) \
+               )
+
+#define SAM3X8 ( \
+               SAM_PART_IS_DEFINED(SAM3X8C) || \
+               SAM_PART_IS_DEFINED(SAM3X8E) || \
+               SAM_PART_IS_DEFINED(SAM3X8H) \
+               )
+/** @} */
+
+/**
+ * \name SAM3A series
+ * @{
+ */
+#define SAM3A4 ( \
+               SAM_PART_IS_DEFINED(SAM3A4C) \
+               )
+
+#define SAM3A8 ( \
+               SAM_PART_IS_DEFINED(SAM3A8C) \
+               )
+/** @} */
+
+/**
+ * \name SAM4S series
+ * @{
+ */
+#define SAM4S2 ( \
+               SAM_PART_IS_DEFINED(SAM4S2A) || \
+               SAM_PART_IS_DEFINED(SAM4S2B) || \
+               SAM_PART_IS_DEFINED(SAM4S2C) \
+               )
+
+#define SAM4S4 ( \
+               SAM_PART_IS_DEFINED(SAM4S4A) || \
+               SAM_PART_IS_DEFINED(SAM4S4B) || \
+               SAM_PART_IS_DEFINED(SAM4S4C) \
+               )
+
+#define SAM4S8 ( \
+               SAM_PART_IS_DEFINED(SAM4S8B) || \
+               SAM_PART_IS_DEFINED(SAM4S8C) \
+               )
+
+#define SAM4S16 ( \
+               SAM_PART_IS_DEFINED(SAM4S16B) || \
+               SAM_PART_IS_DEFINED(SAM4S16C) \
+               )
+
+#define SAM4SA16 ( \
+               SAM_PART_IS_DEFINED(SAM4SA16B) || \
+               SAM_PART_IS_DEFINED(SAM4SA16C)    \
+       )
+
+#define SAM4SD16 ( \
+               SAM_PART_IS_DEFINED(SAM4SD16B) || \
+               SAM_PART_IS_DEFINED(SAM4SD16C)    \
+       )
+
+#define SAM4SD32 ( \
+               SAM_PART_IS_DEFINED(SAM4SD32B) || \
+               SAM_PART_IS_DEFINED(SAM4SD32C)    \
+       )
+/** @} */
+
+/**
+ * \name SAM4L series
+ * @{
+ */
+#define SAM4LS ( \
+               SAM_PART_IS_DEFINED(SAM4LS2A) || \
+               SAM_PART_IS_DEFINED(SAM4LS2B) || \
+               SAM_PART_IS_DEFINED(SAM4LS2C) || \
+               SAM_PART_IS_DEFINED(SAM4LS4A) || \
+               SAM_PART_IS_DEFINED(SAM4LS4B) || \
+               SAM_PART_IS_DEFINED(SAM4LS4C) || \
+               SAM_PART_IS_DEFINED(SAM4LS8A) || \
+               SAM_PART_IS_DEFINED(SAM4LS8B) || \
+               SAM_PART_IS_DEFINED(SAM4LS8C)    \
+               )
+
+#define SAM4LC ( \
+               SAM_PART_IS_DEFINED(SAM4LC2A) || \
+               SAM_PART_IS_DEFINED(SAM4LC2B) || \
+               SAM_PART_IS_DEFINED(SAM4LC2C) || \
+               SAM_PART_IS_DEFINED(SAM4LC4A) || \
+               SAM_PART_IS_DEFINED(SAM4LC4B) || \
+               SAM_PART_IS_DEFINED(SAM4LC4C) || \
+               SAM_PART_IS_DEFINED(SAM4LC8A) || \
+               SAM_PART_IS_DEFINED(SAM4LC8B) || \
+               SAM_PART_IS_DEFINED(SAM4LC8C)    \
+               )
+/** @} */
+
+/**
+ * \name SAMD20 series
+ * @{
+ */
+#define SAMD20J ( \
+               SAM_PART_IS_DEFINED(SAMD20J14) || \
+               SAM_PART_IS_DEFINED(SAMD20J15) || \
+               SAM_PART_IS_DEFINED(SAMD20J16) || \
+               SAM_PART_IS_DEFINED(SAMD20J17) || \
+               SAM_PART_IS_DEFINED(SAMD20J18) \
+       )
+
+#define SAMD20G ( \
+               SAM_PART_IS_DEFINED(SAMD20G14)  || \
+               SAM_PART_IS_DEFINED(SAMD20G15)  || \
+               SAM_PART_IS_DEFINED(SAMD20G16)  || \
+               SAM_PART_IS_DEFINED(SAMD20G17)  || \
+               SAM_PART_IS_DEFINED(SAMD20G17U) || \
+               SAM_PART_IS_DEFINED(SAMD20G18)  || \
+               SAM_PART_IS_DEFINED(SAMD20G18U) \
+       )
+
+#define SAMD20E ( \
+               SAM_PART_IS_DEFINED(SAMD20E14) || \
+               SAM_PART_IS_DEFINED(SAMD20E15) || \
+               SAM_PART_IS_DEFINED(SAMD20E16) || \
+               SAM_PART_IS_DEFINED(SAMD20E17) || \
+               SAM_PART_IS_DEFINED(SAMD20E18) || \
+               SAM_PART_IS_DEFINED(SAMD20E1F) \
+       )
+/** @} */
+
+/**
+ * \name SAMD21 series
+ * @{
+ */
+#define SAMD21J ( \
+               SAM_PART_IS_DEFINED(SAMD21J15A) || \
+               SAM_PART_IS_DEFINED(SAMD21J16A) || \
+               SAM_PART_IS_DEFINED(SAMD21J17A) || \
+               SAM_PART_IS_DEFINED(SAMD21J18A) \
+       )
+
+#define SAMD21G ( \
+               SAM_PART_IS_DEFINED(SAMD21G15A) || \
+               SAM_PART_IS_DEFINED(SAMD21G16A) || \
+               SAM_PART_IS_DEFINED(SAMD21G17A) || \
+               SAM_PART_IS_DEFINED(SAMD21G18A) \
+       )
+
+#define SAMD21E ( \
+               SAM_PART_IS_DEFINED(SAMD21E15A) || \
+               SAM_PART_IS_DEFINED(SAMD21E16A) || \
+               SAM_PART_IS_DEFINED(SAMD21E17A) || \
+               SAM_PART_IS_DEFINED(SAMD21E18A) \
+       )
+/** @} */
+
+/**
+ * \name SAMR21 series
+ * @{
+ */
+#define SAMR21G ( \
+               SAM_PART_IS_DEFINED(SAMR21G16A) || \
+               SAM_PART_IS_DEFINED(SAMR21G17A) || \
+               SAM_PART_IS_DEFINED(SAMR21G18A) \
+       )
+
+#define SAMR21E ( \
+               SAM_PART_IS_DEFINED(SAMR21E16A) || \
+               SAM_PART_IS_DEFINED(SAMR21E17A) || \
+               SAM_PART_IS_DEFINED(SAMR21E18A) \
+       )
+/** @} */
+
+/**
+ * \name SAMD10 series
+ * @{
+ */
+#define SAMD10C ( \
+               SAM_PART_IS_DEFINED(SAMD10C12A) || \
+               SAM_PART_IS_DEFINED(SAMD10C13A) || \
+               SAM_PART_IS_DEFINED(SAMD10C14A) \
+       )
+
+#define SAMD10DS ( \
+               SAM_PART_IS_DEFINED(SAMD10D12AS) || \
+               SAM_PART_IS_DEFINED(SAMD10D13AS) || \
+               SAM_PART_IS_DEFINED(SAMD10D14AS) \
+       )
+
+#define SAMD10DM ( \
+               SAM_PART_IS_DEFINED(SAMD10D12AM) || \
+               SAM_PART_IS_DEFINED(SAMD10D13AM) || \
+               SAM_PART_IS_DEFINED(SAMD10D14AM) \
+       )
+/** @} */
+
+/**
+ * \name SAMD11 series
+ * @{
+ */
+#define SAMD11C ( \
+               SAM_PART_IS_DEFINED(SAMD11C14A) \
+       )
+
+#define SAMD11DS ( \
+               SAM_PART_IS_DEFINED(SAMD11D14AS) \
+       )
+
+#define SAMD11DM ( \
+               SAM_PART_IS_DEFINED(SAMD11D14AM) \
+       )
+/** @} */
+
+/**
+ * \name SAM4E series
+ * @{
+ */
+#define SAM4E8 ( \
+               SAM_PART_IS_DEFINED(SAM4E8C) || \
+               SAM_PART_IS_DEFINED(SAM4E8E) \
+               )
+
+#define SAM4E16 ( \
+               SAM_PART_IS_DEFINED(SAM4E16C) || \
+               SAM_PART_IS_DEFINED(SAM4E16E) \
+               )
+/** @} */
+
+/**
+ * \name SAM4N series
+ * @{
+ */
+#define SAM4N8 ( \
+               SAM_PART_IS_DEFINED(SAM4N8A) || \
+               SAM_PART_IS_DEFINED(SAM4N8B) || \
+               SAM_PART_IS_DEFINED(SAM4N8C) \
+               )
+
+#define SAM4N16 ( \
+               SAM_PART_IS_DEFINED(SAM4N16B) || \
+               SAM_PART_IS_DEFINED(SAM4N16C) \
+               )
+/** @} */
+
+/**
+ * \name SAM4C series
+ * @{
+ */
+#define SAM4C8_0 ( \
+               SAM_PART_IS_DEFINED(SAM4C8C_0) \
+               )
+
+#define SAM4C8_1 ( \
+               SAM_PART_IS_DEFINED(SAM4C8C_1) \
+               )
+
+#define SAM4C8 (SAM4C8_0 || SAM4C8_1)
+
+#define SAM4C16_0 ( \
+               SAM_PART_IS_DEFINED(SAM4C16C_0) \
+               )
+
+#define SAM4C16_1 ( \
+               SAM_PART_IS_DEFINED(SAM4C16C_1) \
+               )
+
+#define SAM4C16 (SAM4C16_0 || SAM4C16_1)
+
+#define SAM4C32_0 ( \
+               SAM_PART_IS_DEFINED(SAM4C32C_0) ||\
+               SAM_PART_IS_DEFINED(SAM4C32E_0) \
+               )
+
+#define SAM4C32_1 ( \
+               SAM_PART_IS_DEFINED(SAM4C32C_1) ||\
+               SAM_PART_IS_DEFINED(SAM4C32E_1) \
+               )
+
+
+#define SAM4C32 (SAM4C32_0 || SAM4C32_1)
+
+/** @} */
+
+/**
+ * \name SAM4CM series
+ * @{
+ */
+#define SAM4CMP8_0 ( \
+               SAM_PART_IS_DEFINED(SAM4CMP8C_0) \
+               )
+
+#define SAM4CMP8_1 ( \
+               SAM_PART_IS_DEFINED(SAM4CMP8C_1) \
+               )
+
+#define SAM4CMP8 (SAM4CMP8_0 || SAM4CMP8_1)
+
+#define SAM4CMP16_0 ( \
+               SAM_PART_IS_DEFINED(SAM4CMP16C_0) \
+               )
+
+#define SAM4CMP16_1 ( \
+               SAM_PART_IS_DEFINED(SAM4CMP16C_1) \
+               )
+
+#define SAM4CMP16 (SAM4CMP16_0 || SAM4CMP16_1)
+
+#define SAM4CMP32_0 ( \
+               SAM_PART_IS_DEFINED(SAM4CMP32C_0) \
+               )
+
+#define SAM4CMP32_1 ( \
+               SAM_PART_IS_DEFINED(SAM4CMP32C_1) \
+               )
+
+#define SAM4CMP32 (SAM4CMP32_0 || SAM4CMP32_1)
+
+#define SAM4CMS8_0 ( \
+               SAM_PART_IS_DEFINED(SAM4CMS8C_0) \
+               )
+
+#define SAM4CMS8_1 ( \
+               SAM_PART_IS_DEFINED(SAM4CMS8C_1) \
+               )
+
+#define SAM4CMS8 (SAM4CMS8_0 || SAM4CMS8_1)
+
+#define SAM4CMS16_0 ( \
+               SAM_PART_IS_DEFINED(SAM4CMS16C_0) \
+               )
+
+#define SAM4CMS16_1 ( \
+               SAM_PART_IS_DEFINED(SAM4CMS16C_1) \
+               )
+
+#define SAM4CMS16 (SAM4CMS16_0 || SAM4CMS16_1)
+
+#define SAM4CMS32_0 ( \
+               SAM_PART_IS_DEFINED(SAM4CMS32C_0) \
+               )
+
+#define SAM4CMS32_1 ( \
+               SAM_PART_IS_DEFINED(SAM4CMS32C_1) \
+               )
+
+#define SAM4CMS32 (SAM4CMS32_0 || SAM4CMS32_1)
+
+/** @} */
+
+/**
+ * \name SAM4CP series
+ * @{
+ */
+#define SAM4CP16_0 ( \
+               SAM_PART_IS_DEFINED(SAM4CP16B_0) \
+               )
+
+#define SAM4CP16_1 ( \
+               SAM_PART_IS_DEFINED(SAM4CP16B_1) \
+               )
+
+#define SAM4CP16 (SAM4CP16_0 || SAM4CP16_1)
+/** @} */
+
+/**
+ * \name SAMG series
+ * @{
+ */
+#define SAMG51 ( \
+               SAM_PART_IS_DEFINED(SAMG51G18) \
+               )
+
+#define SAMG53 ( \
+               SAM_PART_IS_DEFINED(SAMG53G19) ||\
+               SAM_PART_IS_DEFINED(SAMG53N19) \
+               )
+
+#define SAMG54 ( \
+               SAM_PART_IS_DEFINED(SAMG54G19) ||\
+               SAM_PART_IS_DEFINED(SAMG54J19) ||\
+               SAM_PART_IS_DEFINED(SAMG54N19) \
+)
+/** @} */
+/**
+ * \name SAM families
+ * @{
+ */
+/** SAM3S Family */
+#define SAM3S (SAM3S1 || SAM3S2 || SAM3S4 || SAM3S8 || SAM3SD8)
+
+/** SAM3U Family */
+#define SAM3U (SAM3U1 || SAM3U2 || SAM3U4)
+
+/** SAM3N Family */
+#define SAM3N (SAM3N00 || SAM3N0 || SAM3N1 || SAM3N2 || SAM3N4)
+
+/** SAM3XA Family */
+#define SAM3XA (SAM3X4 || SAM3X8 || SAM3A4 || SAM3A8)
+
+/** SAM4S Family */
+#define SAM4S (SAM4S2 || SAM4S4 || SAM4S8 || SAM4S16 || SAM4SA16 || SAM4SD16 || SAM4SD32)
+
+/** SAM4L Family */
+#define SAM4L (SAM4LS || SAM4LC)
+
+/** SAMD20 Family */
+#define SAMD20 (SAMD20J || SAMD20G || SAMD20E)
+
+/** SAMD21 Family */
+#define SAMD21 (SAMD21J || SAMD21G || SAMD21E)
+
+/** SAMD10 Family */
+#define SAMD10 (SAMD10C || SAMD10DS || SAMD10DM)
+
+/** SAMD11 Family */
+#define SAMD11 (SAMD11C || SAMD11DS || SAMD11DM)
+
+/** SAMD Family */
+#define SAMD   (SAMD20 || SAMD21 || SAMD10 || SAMD11)
+
+/** SAMR21 Family */
+#define SAMR21 (SAMR21G || SAMR21E)
+
+/** SAM4E Family */
+#define SAM4E (SAM4E8 || SAM4E16)
+
+/** SAM4N Family */
+#define SAM4N (SAM4N8 || SAM4N16)
+
+/** SAM4C Family */
+#define SAM4C_0 (SAM4C8_0 || SAM4C16_0 || SAM4C32_0)
+#define SAM4C_1 (SAM4C8_1 || SAM4C16_1 || SAM4C32_1)
+#define SAM4C   (SAM4C8 || SAM4C16 || SAM4C32)
+
+/** SAM4CM Family */
+#define SAM4CM_0 (SAM4CMP8_0 || SAM4CMP16_0 || SAM4CMP32_0 || SAM4CMS8_0 || \
+                       SAM4CMS16_0 || SAM4CMS32_0)
+#define SAM4CM_1 (SAM4CMP8_1 || SAM4CMP16_1 || SAM4CMP32_1 || SAM4CMS8_1 || \
+                       SAM4CMS16_1 || SAM4CMS32_1)
+#define SAM4CM   (SAM4CMP8 || SAM4CMP16 || SAM4CMP32 || SAM4CMS8 || \
+                       SAM4CMS16 || SAM4CMS32)
+
+/** SAM4CP Family */
+#define SAM4CP_0 (SAM4CP16_0)
+#define SAM4CP_1 (SAM4CP16_1)
+#define SAM4CP   (SAM4CP16)
+
+/** SAMG Family */
+#define SAMG (SAMG51 || SAMG53 || SAMG54)
+
+/** SAM0 product line (cortex-m0+) */
+#define SAM0 (SAMD20 || SAMD21 || SAMR21 || SAMD10 || SAMD11)
+
+/** @} */
+
+/** SAM product line */
+#define SAM (SAM3S || SAM3U || SAM3N || SAM3XA || SAM4S || SAM4L || SAM4E || \
+               SAM0 || SAM4N || SAM4C || SAM4CM || SAM4CP || SAMG)
+
+/** @} */
+
+/** @} */
+
+/** @} */
+
+#endif /* ATMEL_PARTS_H */
diff --git a/asf/sam/drivers/pdc/pdc.c b/asf/sam/drivers/pdc/pdc.c
new file mode 100644 (file)
index 0000000..054222f
--- /dev/null
@@ -0,0 +1,331 @@
+/**
+ * \file
+ *
+ * \brief SAM4 Peripheral DMA Controller (PDC) driver.
+ *
+ * Copyright (c) 2011-2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#include "pdc.h"
+
+/// @cond
+/**INDENT-OFF**/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+/**
+ * \brief Configure PDC for data transmit.
+ *
+ * \param[out] p_pdc        Device structure pointer
+ * \param[in] p_packet      Pointer to packet information for current buffer register
+ *                          set, NULL to let them as is.
+ * \param[in] p_next_packet Pointer to packet information for next buffer register
+ *                          set, NULL to let them as is.
+ */
+void pdc_tx_init(
+               Pdc *p_pdc,
+               pdc_packet_t *p_packet,
+               pdc_packet_t *p_next_packet)
+{
+       /* Validate inputs. */
+       Assert(p_pdc);
+       
+       if (p_packet) {
+               p_pdc->PERIPH_TPR = p_packet->ul_addr;
+               p_pdc->PERIPH_TCR = p_packet->ul_size;
+       }
+       if (p_next_packet) {
+               p_pdc->PERIPH_TNPR = p_next_packet->ul_addr;
+               p_pdc->PERIPH_TNCR = p_next_packet->ul_size;
+       }
+}
+
+/**
+ * \brief Configure PDC for data receive.
+ *
+ * \param[out] p_pdc        Device structure pointer
+ * \param[in] p_packet      Pointer to packet information for current buffer register
+ *                          set, NULL to let them as is.
+ * \param[in] p_next_packet Pointer to packet information for next buffer register
+ *                          set, NULL to let them as is.
+ */
+void pdc_rx_init(
+               Pdc *p_pdc,
+               pdc_packet_t *p_packet,
+               pdc_packet_t *p_next_packet)
+{
+       /* Validate inputs. */
+       Assert(p_pdc);
+       
+       if (p_packet) {
+               p_pdc->PERIPH_RPR = p_packet->ul_addr;
+               p_pdc->PERIPH_RCR = p_packet->ul_size;
+       }
+       if (p_next_packet) {
+               p_pdc->PERIPH_RNPR = p_next_packet->ul_addr;
+               p_pdc->PERIPH_RNCR = p_next_packet->ul_size;
+       }
+}
+
+/**
+ * \brief Clear PDC buffer receive counter.
+ *
+ * \param[out] p_pdc Device structure pointer
+ */
+void pdc_rx_clear_cnt(
+               Pdc *p_pdc)
+{
+       /* Validate inputs. */
+       Assert(p_pdc);
+       
+       p_pdc->PERIPH_RNCR = 0;
+       p_pdc->PERIPH_RCR = 0;
+}
+
+/**
+ * \brief Enable PDC transfers (TX and/or RX).
+ *
+ * \note It is forbidden to set both TXTEN and RXTEN for a half duplex
+ * peripheral.
+ *
+ * \param[out] p_pdc     Device structure pointer
+ * \param[in] ul_controls Transfer directions
+ *                        (bit PERIPH_PTCR_RXTEN and bit PERIPH_PTCR_TXTEN)
+ */
+void pdc_enable_transfer(
+               Pdc *p_pdc,
+               uint32_t ul_controls)
+{
+       /* Validate inputs. */
+       Assert(p_pdc);
+       
+       p_pdc->PERIPH_PTCR =
+                       ul_controls & (PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
+}
+
+/**
+ * \brief Disable PDC transfers (TX and/or RX).
+ *
+ * \param[out] p_pdc      Device structure pointer
+ * \param[in] ul_controls Transfer directions
+ *                        (bit PERIPH_PTCR_TXTDIS, bit PERIPH_PTCR_TXTDIS)
+ */
+void pdc_disable_transfer(
+               Pdc *p_pdc,
+               uint32_t ul_controls)
+{
+       /* Validate inputs. */
+       Assert(p_pdc);
+       
+       p_pdc->PERIPH_PTCR =
+                       ul_controls & (PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
+}
+
+/**
+ * \brief Read PDC status.
+ *
+ * \param[in] p_pdc Device structure pointer
+ *
+ * \return PDC status register bit map.
+ *
+ * <table>
+ * <tr>
+ * <th>Name</th>
+ * <th>Description</th>
+ * <th>Bit</th>
+ * </tr>
+ * <tr>
+ *   <td>RXTEN</td>
+ *   <td>Receiver Transfer Enabled</td>
+ *   <td>8</td>
+ * </tr>
+ * <tr>
+ *   <td>TXTEN</td>
+ *   <td>Transmitter Transfer Enabled</td>
+ *   <td>1</td>
+ * </tr>
+ * </table>
+ *
+ */
+uint32_t pdc_read_status(
+               Pdc *p_pdc)
+{
+       /* Validate inputs. */
+       Assert(p_pdc);
+       
+       return p_pdc->PERIPH_PTSR;
+}
+
+/**
+ * \brief Return Receive Pointer Register (RPR) value.
+ *
+ * \param[in] p_pdc Device structure pointer
+ *
+ * \return Receive Pointer Register value.
+ */
+uint32_t pdc_read_rx_ptr(
+               Pdc *p_pdc)
+{
+       /* Validate inputs. */
+       Assert(p_pdc);
+       
+       return p_pdc->PERIPH_RPR;
+}
+
+/**
+ * \brief Return Receive Counter Register (RCR) value.
+ *
+ * \param[in] p_pdc Device structure pointer
+ *
+ * \return Receive Counter Register value.
+ */
+uint32_t pdc_read_rx_counter(
+               Pdc *p_pdc)
+{
+       /* Validate inputs. */
+       Assert(p_pdc);
+       
+       return p_pdc->PERIPH_RCR;
+}
+
+/**
+ * \brief Return Transmit Pointer Register (TPR) value.
+ *
+ * \param[in] p_pdc Device structure pointer
+ *
+ * \return Transmit Pointer Register value.
+ */
+uint32_t pdc_read_tx_ptr(
+               Pdc *p_pdc)
+{
+       /* Validate inputs. */
+       Assert(p_pdc);
+       
+       return p_pdc->PERIPH_TPR;
+}
+
+/**
+ * \brief Return Transmit Counter Register (TCR) value.
+ *
+ * \param[in] p_pdc Device structure pointer
+ *
+ * \return Transmit Counter Register value.
+ */
+uint32_t pdc_read_tx_counter(
+               Pdc *p_pdc)
+{
+       /* Validate inputs. */
+       Assert(p_pdc);
+       
+       return p_pdc->PERIPH_TCR;
+}
+
+/**
+ * \brief Return Receive Next Pointer Register (RNPR) value.
+ *
+ * \param[in] p_pdc Device structure pointer
+ *
+ * \return Receive Next Pointer Register value.
+ */
+uint32_t pdc_read_rx_next_ptr(
+               Pdc *p_pdc)
+{
+       /* Validate inputs. */
+       Assert(p_pdc);
+       
+       return p_pdc->PERIPH_RNPR;
+}
+
+/**
+ * \brief Return Receive Next Counter Register (RNCR) value.
+ *
+ * \param[in] p_pdc Device structure pointer
+ *
+ * \return Receive Next Counter Register value.
+ */
+uint32_t pdc_read_rx_next_counter(
+               Pdc *p_pdc)
+{
+       /* Validate inputs. */
+       Assert(p_pdc);
+       
+       return p_pdc->PERIPH_RNCR;
+}
+
+/**
+ * \brief Return Transmit Next Pointer Register (TNPR) value.
+ *
+ * \param[in] p_pdc Device structure pointer
+ *
+ * \return Transmit Next Pointer Register value.
+ */
+uint32_t pdc_read_tx_next_ptr(
+               Pdc *p_pdc)
+{
+       /* Validate inputs. */
+       Assert(p_pdc);
+       
+       return p_pdc->PERIPH_TNPR;
+}
+
+/**
+ * \brief Return Transmit Next Counter Register (TNCR) value.
+ *
+ * \param[in] p_pdc Device structure pointer
+ *
+ * \return Transmit Next Counter Register value.
+ */
+uint32_t pdc_read_tx_next_counter(
+               Pdc *p_pdc)
+{
+       /* Validate inputs. */
+       Assert(p_pdc);
+       
+       return p_pdc->PERIPH_TNCR;
+}
+
+/// @cond
+/**INDENT-OFF**/
+#ifdef __cplusplus
+}
+#endif
+/**INDENT-ON**/
+/// @endcond
diff --git a/asf/sam/drivers/pdc/pdc.h b/asf/sam/drivers/pdc/pdc.h
new file mode 100644 (file)
index 0000000..9d69ceb
--- /dev/null
@@ -0,0 +1,302 @@
+/**
+ * \file
+ *
+ * \brief SAM4 Peripheral DMA Controller (PDC) driver.
+ *
+ * Copyright (c) 2011-2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#ifndef PDC_H_INCLUDED
+#define PDC_H_INCLUDED
+
+/**
+ * \defgroup asfdoc_sam_drivers_pdc_group Peripheral DMA Controller (PDC)
+ * This driver for SAM4 devices provides an interface for the configuration and
+ * management of the the Peripheral DMA Controller (PDC) module.
+ *
+ * The PDC transfers data between on-chip serial peripherals and the on and/or
+ * off-chip memories. The link between the PDC and a serial peripheral is
+ * operated by the AHB to ABP bridge.
+ *
+ * This module:
+ * - Performs transfers to/from APB communication serial peripherals
+ * - Supports half-duplex and full-duplex peripherals
+ *
+ * The outline of this documentation is as follows:
+ *  - \ref asfdoc_sam_drivers_pdc_prerequisites
+ *  - \ref asfdoc_sam_drivers_pdc_module_overview
+ *  - \ref asfdoc_sam_drivers_pdc_special_considerations
+ *  - \ref asfdoc_sam_drivers_pdc_extra_info
+ *  - \ref asfdoc_sam_drivers_pdc_examples
+ *  - \ref asfdoc_sam_drivers_pdc_api_overview
+ *
+ *
+ * \section asfdoc_sam_drivers_pdc_prerequisites Prerequisites
+ *
+ * There are no prerequisites for this module.
+ *
+ *
+ * \section asfdoc_sam_drivers_pdc_module_overview Module Overview
+ * The user interface of each PDC channel is integrated into the user interface
+ * of the peripheral it serves. The user interface of unidirectional channels
+ * (receive only or transmit only), contains two 32-bit memory pointers and
+ * two 16-bit counters, one set (pointer, counter) for current transfer and
+ * one set (pointer, counter) for next transfer. The bidirectional channel
+ * user interface contains four 32-bit memory pointers and four 16-bit counters.
+ * Each set (pointer, counter) is used by current transmit, next transmit,
+ * current receive and next receive. Using the PDC removes processor overhead
+ * by reducing its intervention during the transfer. This significantly reduces
+ * the number of clock cycles required for a data transfer, which improves
+ * microcontroller performance. To launch a transfer, the peripheral triggers
+ * its associated PDC channels by using transmit and receive signals.
+ * When the programmed data is transferred, an end of transfer interrupt is
+ * generated by the peripheral itself.
+ *
+ * \section asfdoc_sam_drivers_pdc_special_considerations Special Considerations
+ *
+ *
+ * \section asfdoc_sam_drivers_pdc_extra_info Extra Information
+
+ * For extra information, see \ref asfdoc_sam_drivers_pdc_extra. This includes:
+ *  - \ref asfdoc_sam_drivers_pdc_extra_acronyms
+ *  - \ref asfdoc_sam_drivers_pdc_extra_dependencies
+ *  - \ref asfdoc_sam_drivers_pdc_extra_errata
+ *  - \ref asfdoc_sam_drivers_pdc_extra_history
+ *
+ * \section asfdoc_sam_drivers_pdc_examples Examples
+ *
+ * For a list of examples related to this driver, see
+ * \ref asfdoc_sam_drivers_pdc_exqsg.
+ *
+ *
+ * \section asfdoc_sam_drivers_pdc_api_overview API Overview
+ * @{
+ */
+
+#include <compiler.h>
+
+/// @cond
+/**INDENT-OFF**/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+/**
+ * \brief PDC data packet for transfer.
+ */
+typedef struct pdc_packet {
+       /** Start address of the transfer packet data. */
+       uint32_t ul_addr;
+       /** Transfer packet size (in units of the peripheral data width). */
+       uint32_t ul_size;
+} pdc_packet_t;
+
+void pdc_tx_init(Pdc *p_pdc, pdc_packet_t *p_packet,
+               pdc_packet_t *p_next_packet);
+void pdc_rx_init(Pdc *p_pdc, pdc_packet_t *p_packet,
+               pdc_packet_t *p_next_packet);
+void pdc_rx_clear_cnt(Pdc *p_pdc);
+void pdc_enable_transfer(Pdc *p_pdc, uint32_t ul_controls);
+void pdc_disable_transfer(Pdc *p_pdc, uint32_t ul_controls);
+uint32_t pdc_read_status(Pdc *p_pdc);
+uint32_t pdc_read_rx_ptr(Pdc *p_pdc);
+uint32_t pdc_read_rx_counter(Pdc *p_pdc);
+uint32_t pdc_read_tx_ptr(Pdc *p_pdc);
+uint32_t pdc_read_tx_counter(Pdc *p_pdc);
+uint32_t pdc_read_rx_next_ptr(Pdc *p_pdc);
+uint32_t pdc_read_rx_next_counter(Pdc *p_pdc);
+uint32_t pdc_read_tx_next_ptr(Pdc *p_pdc);
+uint32_t pdc_read_tx_next_counter(Pdc *p_pdc);
+
+/// @cond
+/**INDENT-OFF**/
+#ifdef __cplusplus
+}
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+/** @} */
+/**
+ * \page asfdoc_sam_drivers_pdc_extra Extra Information for Peripheral DMA Controller
+ *
+ * \section asfdoc_sam_drivers_pdc_extra_acronyms Acronyms
+ * Below is a table listing the acronyms used in this module, along with their
+ * intended meanings.
+ *
+ * <table>
+ *  <tr>
+ *      <th>Acronym</th>
+ *      <th>Definition</th>
+ * </tr>
+ * </tr>
+ * <tr>
+ *      <td>AHB</td>
+ *      <td>Advanced High-performance Bus</td>
+ * </tr>
+ * <tr>
+ *      <td>AMBA</td>
+ *      <td> Advanced Microcontroller Bus Architecture</td>
+ * </tr>
+ * <tr>
+ *      <td>QSG</td>
+ *      <td>Quick Start Guide</td>
+ *
+ * </tr>
+ * <tr>
+ *   <td>RCR</td>
+ *   <td>Receive Counter Register</td>
+ * </tr>
+ * <tr>
+ *   <td>RNCR</td>
+ *   <td>Return Receive Next Counter Register</td>
+ * </tr>
+ * <tr>
+ *   <td>RNPR</td>
+ *   <td>Receive Next Pointer Register</td>
+ * </tr>
+ * <tr>
+ *   <td>RPR</td>
+ *   <td>Receive Pointer Register</td>
+ * </tr>
+ * <tr>
+ *   <td>TCR</td>
+ *   <td>Transmit Counter Register</td>
+ * </tr>
+ * <tr>
+ *   <td>TNCR</td>
+ *   <td>Transmit Next Counter Register</td>
+ * </tr>
+ * <tr>
+ *   <td>TNPR</td>
+ *   <td>Transmit Next Pointer Register</td>
+ * </tr>
+ * <tr>
+ *   <td>TPR</td>
+ *   <td>Transmit Pointer Register</td>
+ * </tr>
+ * </table>
+ *
+ *
+ * \section asfdoc_sam_drivers_pdc_extra_dependencies Dependencies
+ * This driver has the following dependencies:
+ *
+ *  - None
+ *
+ *
+ * \section asfdoc_sam_drivers_pdc_extra_errata Errata
+ * There are no errata related to this driver.
+ *
+ *
+ * \section asfdoc_sam_drivers_pdc_extra_history Module History
+ * An overview of the module history is presented in the table below, with
+ * details on the enhancements and fixes made to the module since its first
+ * release. The current version of this corresponds to the newest version in
+ * the table.
+ *
+ * <table>
+ *     <tr>
+ *             <th>Changelog</th>
+ *     </tr>
+ *     <tr>
+ *             <td>Initial document release</td>
+ *     </tr>
+ * </table>
+ *
+ *
+ *
+ * \page asfdoc_sam_pmc_quickstart Quickstart guide for SAM4
+ * This is the quickstart guide for the "PDC driver" with step-by-step
+ * instructions on how to configure and use the driver.
+ *
+ * \section asfdoc_sam_pmc_quickstart_basic_use_case Basic Use Case
+ *
+ * A handler is required for the interrupt, below is a simple example
+ * \snippet pdc_uart_example.c int_handler
+ *
+ * First initialise the board:
+ *
+ * \snippet pdc_uart_example.c board_setup
+ *
+ * Now setup the PDC registers
+ * \snippet pdc_uart_example.c pdc_config
+ *
+ * Enable UART IRQ
+ * \snippet pdc_uart_example.c uart_irq
+ *
+ * and enable UART interrupt
+ * \snippet pdc_uart_example.c uart_nvic_irq
+ *
+ * Once the required number of bytes have been transferred an interupt is
+ * triggered and the handler will run.  In the interim programme to do
+ * something else, or be busy waiting
+ *
+ * \snippet pdc_uart_example.c busy_waiting
+ *
+ * \page asfdoc_sam_drivers_pdc_exqsg Examples for Peripheral DMA Controller
+ *
+ * This is a list of the available Quick Start guides (QSGs) and example
+ * applications for \ref asfdoc_sam_drivers_pdc_group. QSGs are simple examples with
+ * step-by-step instructions to configure and use this driver in a selection of
+ * use cases. Note that QSGs can be compiled as a standalone application or be
+ * added to the user application.
+ *
+ *  - \subpage asfdoc_sam_drivers_pdc_example
+ *
+ *
+ * \page asfdoc_sam_drivers_pdc_document_revision_history Document Revision History
+ *
+ * <table>
+ *     <tr>
+ *             <th>Doc. Rev.</td>
+ *             <th>Date</td>
+ *             <th>Comments</td>
+ *     </tr>
+ *     <tr>
+ *             <td>42316A</td>
+ *             <td>05/2014</td>
+ *             <td>Initial document release</td>
+ *     </tr>
+ * </table>
+ *
+ */
+
+#endif /* PDC_H_INCLUDED */
diff --git a/asf/sam/drivers/pio/pio.c b/asf/sam/drivers/pio/pio.c
new file mode 100644 (file)
index 0000000..a4e049e
--- /dev/null
@@ -0,0 +1,1179 @@
+/**
+ * \file
+ *
+ * \brief Parallel Input/Output (PIO) Controller driver for SAM.
+ *
+ * Copyright (c) 2011 - 2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#include "pio.h"
+
+#ifndef PIO_WPMR_WPKEY_PASSWD
+#  define PIO_WPMR_WPKEY_PASSWD PIO_WPMR_WPKEY(0x50494Fu)
+#endif
+
+/**
+ * \defgroup sam_drivers_pio_group Peripheral Parallel Input/Output (PIO) Controller
+ *
+ * \par Purpose
+ *
+ * The Parallel Input/Output Controller (PIO) manages up to 32 fully
+ * programmable input/output lines. Each I/O line may be dedicated as a
+ * general-purpose I/O or be assigned to a function of an embedded peripheral.
+ * This assures effective optimization of the pins of a product.
+ *
+ * @{
+ */
+
+#ifndef FREQ_SLOW_CLOCK_EXT
+/* External slow clock frequency (hz) */
+#define FREQ_SLOW_CLOCK_EXT 32768
+#endif
+
+/**
+ * \brief Configure PIO internal pull-up.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Bitmask of one or more pin(s) to configure.
+ * \param ul_pull_up_enable Indicates if the pin(s) internal pull-up shall be
+ * configured.
+ */
+void pio_pull_up(Pio *p_pio, const uint32_t ul_mask,
+               const uint32_t ul_pull_up_enable)
+{
+       /* Enable the pull-up(s) if necessary */
+       if (ul_pull_up_enable) {
+               p_pio->PIO_PUER = ul_mask;
+       } else {
+               p_pio->PIO_PUDR = ul_mask;
+       }
+}
+
+/**
+ * \brief Configure Glitch or Debouncing filter for the specified input(s).
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Bitmask of one or more pin(s) to configure.
+ * \param ul_cut_off Cuts off frequency for debouncing filter.
+ */
+void pio_set_debounce_filter(Pio *p_pio, const uint32_t ul_mask,
+               const uint32_t ul_cut_off)
+{
+#if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM)
+       /* Set Debouncing, 0 bit field no effect */
+       p_pio->PIO_IFSCER = ul_mask;
+#elif (SAM3XA || SAM3U)
+       /* Set Debouncing, 0 bit field no effect */
+       p_pio->PIO_DIFSR = ul_mask;
+#else
+#error "Unsupported device"
+#endif
+
+       /*
+        * The debouncing filter can filter a pulse of less than 1/2 Period of a
+        * programmable Divided Slow Clock:
+        * Tdiv_slclk = ((DIV+1)*2).Tslow_clock
+        */
+       p_pio->PIO_SCDR = PIO_SCDR_DIV((FREQ_SLOW_CLOCK_EXT /
+                       (2 * (ul_cut_off))) - 1);
+}
+
+/**
+ * \brief Set a high output level on all the PIOs defined in ul_mask.
+ * This has no immediate effects on PIOs that are not output, but the PIO
+ * controller will save the value if they are changed to outputs.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Bitmask of one or more pin(s) to configure.
+ */
+void pio_set(Pio *p_pio, const uint32_t ul_mask)
+{
+       p_pio->PIO_SODR = ul_mask;
+}
+
+/**
+ * \brief Set a low output level on all the PIOs defined in ul_mask.
+ * This has no immediate effects on PIOs that are not output, but the PIO
+ * controller will save the value if they are changed to outputs.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Bitmask of one or more pin(s) to configure.
+ */
+void pio_clear(Pio *p_pio, const uint32_t ul_mask)
+{
+       p_pio->PIO_CODR = ul_mask;
+}
+
+/**
+ * \brief Return 1 if one or more PIOs of the given Pin instance currently have
+ * a high level; otherwise returns 0. This method returns the actual value that
+ * is being read on the pin. To return the supposed output value of a pin, use
+ * pio_get_output_data_status() instead.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_type PIO type.
+ * \param ul_mask Bitmask of one or more pin(s) to configure.
+ *
+ * \retval 1 at least one PIO currently has a high level.
+ * \retval 0 all PIOs have a low level.
+ */
+uint32_t pio_get(Pio *p_pio, const pio_type_t ul_type,
+               const uint32_t ul_mask)
+{
+       uint32_t ul_reg;
+
+       if ((ul_type == PIO_OUTPUT_0) || (ul_type == PIO_OUTPUT_1)) {
+               ul_reg = p_pio->PIO_ODSR;
+       } else {
+               ul_reg = p_pio->PIO_PDSR;
+       }
+
+       if ((ul_reg & ul_mask) == 0) {
+               return 0;
+       } else {
+               return 1;
+       }
+}
+
+/**
+ * \brief Configure IO of a PIO controller as being controlled by a specific
+ * peripheral.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_type PIO type.
+ * \param ul_mask Bitmask of one or more pin(s) to configure.
+ */
+void pio_set_peripheral(Pio *p_pio, const pio_type_t ul_type,
+               const uint32_t ul_mask)
+{
+       uint32_t ul_sr;
+
+       /* Disable interrupts on the pin(s) */
+       p_pio->PIO_IDR = ul_mask;
+
+#if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM)
+       switch (ul_type) {
+       case PIO_PERIPH_A:
+               ul_sr = p_pio->PIO_ABCDSR[0];
+               p_pio->PIO_ABCDSR[0] &= (~ul_mask & ul_sr);
+
+               ul_sr = p_pio->PIO_ABCDSR[1];
+               p_pio->PIO_ABCDSR[1] &= (~ul_mask & ul_sr);
+               break;
+
+       case PIO_PERIPH_B:
+               ul_sr = p_pio->PIO_ABCDSR[0];
+               p_pio->PIO_ABCDSR[0] = (ul_mask | ul_sr);
+
+               ul_sr = p_pio->PIO_ABCDSR[1];
+               p_pio->PIO_ABCDSR[1] &= (~ul_mask & ul_sr);
+               break;
+#if (!SAMG)
+       case PIO_PERIPH_C:
+               ul_sr = p_pio->PIO_ABCDSR[0];
+               p_pio->PIO_ABCDSR[0] &= (~ul_mask & ul_sr);
+
+               ul_sr = p_pio->PIO_ABCDSR[1];
+               p_pio->PIO_ABCDSR[1] = (ul_mask | ul_sr);
+               break;
+
+       case PIO_PERIPH_D:
+               ul_sr = p_pio->PIO_ABCDSR[0];
+               p_pio->PIO_ABCDSR[0] = (ul_mask | ul_sr);
+
+               ul_sr = p_pio->PIO_ABCDSR[1];
+               p_pio->PIO_ABCDSR[1] = (ul_mask | ul_sr);
+               break;
+#endif
+               /* Other types are invalid in this function */
+       case PIO_INPUT:
+       case PIO_OUTPUT_0:
+       case PIO_OUTPUT_1:
+       case PIO_NOT_A_PIN:
+               return;
+       }
+#elif (SAM3XA|| SAM3U)
+       switch (ul_type) {
+       case PIO_PERIPH_A:
+               ul_sr = p_pio->PIO_ABSR;
+               p_pio->PIO_ABSR &= (~ul_mask & ul_sr);
+               break;
+
+       case PIO_PERIPH_B:
+               ul_sr = p_pio->PIO_ABSR;
+               p_pio->PIO_ABSR = (ul_mask | ul_sr);
+               break;
+
+               // other types are invalid in this function
+       case PIO_INPUT:
+       case PIO_OUTPUT_0:
+       case PIO_OUTPUT_1:
+       case PIO_NOT_A_PIN:
+               return;
+       }
+#else
+#error "Unsupported device"
+#endif
+
+       /* Remove the pins from under the control of PIO */
+       p_pio->PIO_PDR = ul_mask;
+}
+
+/**
+ * \brief Configure one or more pin(s) or a PIO controller as inputs.
+ * Optionally, the corresponding internal pull-up(s) and glitch filter(s) can
+ * be enabled.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Bitmask indicating which pin(s) to configure as input(s).
+ * \param ul_attribute PIO attribute(s).
+ */
+void pio_set_input(Pio *p_pio, const uint32_t ul_mask,
+               const uint32_t ul_attribute)
+{
+       pio_disable_interrupt(p_pio, ul_mask);
+       pio_pull_up(p_pio, ul_mask, ul_attribute & PIO_PULLUP);
+
+       /* Enable Input Filter if necessary */
+       if (ul_attribute & (PIO_DEGLITCH | PIO_DEBOUNCE)) {
+               p_pio->PIO_IFER = ul_mask;
+       } else {
+               p_pio->PIO_IFDR = ul_mask;
+       }
+
+#if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM)
+       /* Enable de-glitch or de-bounce if necessary */
+       if (ul_attribute & PIO_DEGLITCH) {
+               p_pio->PIO_IFSCDR = ul_mask;
+       } else {
+               if (ul_attribute & PIO_DEBOUNCE) {
+                       p_pio->PIO_IFSCER = ul_mask;
+               }
+       }
+#elif (SAM3XA|| SAM3U)
+       /* Enable de-glitch or de-bounce if necessary */
+       if (ul_attribute & PIO_DEGLITCH) {
+               p_pio->PIO_SCIFSR = ul_mask;
+       } else {
+               if (ul_attribute & PIO_DEBOUNCE) {
+                       p_pio->PIO_DIFSR = ul_mask;
+               }
+       }
+#else
+#error "Unsupported device"
+#endif
+
+       /* Configure pin as input */
+       p_pio->PIO_ODR = ul_mask;
+       p_pio->PIO_PER = ul_mask;
+}
+
+/**
+ * \brief Configure one or more pin(s) of a PIO controller as outputs, with
+ * the given default value. Optionally, the multi-drive feature can be enabled
+ * on the pin(s).
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Bitmask indicating which pin(s) to configure.
+ * \param ul_default_level Default level on the pin(s).
+ * \param ul_multidrive_enable Indicates if the pin(s) shall be configured as
+ * open-drain.
+ * \param ul_pull_up_enable Indicates if the pin shall have its pull-up
+ * activated.
+ */
+void pio_set_output(Pio *p_pio, const uint32_t ul_mask,
+               const uint32_t ul_default_level,
+               const uint32_t ul_multidrive_enable,
+               const uint32_t ul_pull_up_enable)
+{
+       pio_disable_interrupt(p_pio, ul_mask);
+       pio_pull_up(p_pio, ul_mask, ul_pull_up_enable);
+
+       /* Enable multi-drive if necessary */
+       if (ul_multidrive_enable) {
+               p_pio->PIO_MDER = ul_mask;
+       } else {
+               p_pio->PIO_MDDR = ul_mask;
+       }
+
+       /* Set default value */
+       if (ul_default_level) {
+               p_pio->PIO_SODR = ul_mask;
+       } else {
+               p_pio->PIO_CODR = ul_mask;
+       }
+
+       /* Configure pin(s) as output(s) */
+       p_pio->PIO_OER = ul_mask;
+       p_pio->PIO_PER = ul_mask;
+}
+
+/**
+ * \brief Perform complete pin(s) configuration; general attributes and PIO init
+ * if necessary.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_type PIO type.
+ * \param ul_mask Bitmask of one or more pin(s) to configure.
+ * \param ul_attribute Pins attributes.
+ *
+ * \return Whether the pin(s) have been configured properly.
+ */
+uint32_t pio_configure(Pio *p_pio, const pio_type_t ul_type,
+               const uint32_t ul_mask, const uint32_t ul_attribute)
+{
+       /* Configure pins */
+       switch (ul_type) {
+       case PIO_PERIPH_A:
+       case PIO_PERIPH_B:
+#if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAM4CP || SAM4CM)
+       case PIO_PERIPH_C:
+       case PIO_PERIPH_D:
+#endif
+               pio_set_peripheral(p_pio, ul_type, ul_mask);
+               pio_pull_up(p_pio, ul_mask, (ul_attribute & PIO_PULLUP));
+               break;
+
+       case PIO_INPUT:
+               pio_set_input(p_pio, ul_mask, ul_attribute);
+               break;
+
+       case PIO_OUTPUT_0:
+       case PIO_OUTPUT_1:
+               pio_set_output(p_pio, ul_mask, (ul_type == PIO_OUTPUT_1),
+                               (ul_attribute & PIO_OPENDRAIN) ? 1 : 0,
+                               (ul_attribute & PIO_PULLUP) ? 1 : 0);
+               break;
+
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+/**
+ * \brief Return 1 if one or more PIOs of the given Pin are configured to
+ * output a high level (even if they are not output).
+ * To get the actual value of the pin, use PIO_Get() instead.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Bitmask of one or more pin(s).
+ *
+ * \retval 1 At least one PIO is configured to output a high level.
+ * \retval 0 All PIOs are configured to output a low level.
+ */
+uint32_t pio_get_output_data_status(const Pio *p_pio,
+               const uint32_t ul_mask)
+{
+       if ((p_pio->PIO_ODSR & ul_mask) == 0) {
+               return 0;
+       } else {
+               return 1;
+       }
+}
+
+/**
+ * \brief Configure PIO pin multi-driver.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Bitmask of one or more pin(s) to configure.
+ * \param ul_multi_driver_enable Indicates if the pin(s) multi-driver shall be
+ * configured.
+ */
+void pio_set_multi_driver(Pio *p_pio, const uint32_t ul_mask,
+               const uint32_t ul_multi_driver_enable)
+{
+       /* Enable the multi-driver if necessary */
+       if (ul_multi_driver_enable) {
+               p_pio->PIO_MDER = ul_mask;
+       } else {
+               p_pio->PIO_MDDR = ul_mask;
+       }
+}
+
+/**
+ * \brief Get multi-driver status.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ *
+ * \return The multi-driver mask value.
+ */
+uint32_t pio_get_multi_driver_status(const Pio *p_pio)
+{
+       return p_pio->PIO_MDSR;
+}
+
+
+#if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM)
+/**
+ * \brief Configure PIO pin internal pull-down.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Bitmask of one or more pin(s) to configure.
+ * \param ul_pull_down_enable Indicates if the pin(s) internal pull-down shall
+ * be configured.
+ */
+void pio_pull_down(Pio *p_pio, const uint32_t ul_mask,
+               const uint32_t ul_pull_down_enable)
+{
+       /* Enable the pull-down if necessary */
+       if (ul_pull_down_enable) {
+               p_pio->PIO_PPDER = ul_mask;
+       } else {
+               p_pio->PIO_PPDDR = ul_mask;
+       }
+}
+#endif
+
+/**
+ * \brief Enable PIO output write for synchronous data output.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Bitmask of one or more pin(s) to configure.
+ */
+void pio_enable_output_write(Pio *p_pio, const uint32_t ul_mask)
+{
+       p_pio->PIO_OWER = ul_mask;
+}
+
+/**
+ * \brief Disable PIO output write.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Bitmask of one or more pin(s) to configure.
+ */
+void pio_disable_output_write(Pio *p_pio, const uint32_t ul_mask)
+{
+       p_pio->PIO_OWDR = ul_mask;
+}
+
+/**
+ * \brief Read PIO output write status.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ *
+ * \return The output write mask value.
+ */
+uint32_t pio_get_output_write_status(const Pio *p_pio)
+{
+       return p_pio->PIO_OWSR;
+}
+
+/**
+ * \brief Synchronously write on output pins.
+ * \note Only bits unmasked by PIO_OWSR (Output Write Status Register) are
+ * written.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Bitmask of one or more pin(s) to configure.
+ */
+void pio_sync_output_write(Pio *p_pio, const uint32_t ul_mask)
+{
+       p_pio->PIO_ODSR = ul_mask;
+}
+
+#if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM)
+/**
+ * \brief Configure PIO pin schmitt trigger. By default the Schmitt trigger is
+ * active.
+ * Disabling the Schmitt Trigger is requested when using the QTouch Library.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Bitmask of one or more pin(s) to configure.
+ */
+void pio_set_schmitt_trigger(Pio *p_pio, const uint32_t ul_mask)
+{
+       p_pio->PIO_SCHMITT = ul_mask;
+}
+
+/**
+ * \brief Get PIO pin schmitt trigger status.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ *
+ * \return The schmitt trigger mask value.
+ */
+uint32_t pio_get_schmitt_trigger(const Pio *p_pio)
+{
+       return p_pio->PIO_SCHMITT;
+}
+#endif
+
+/**
+ * \brief Configure the given interrupt source.
+ * Interrupt can be configured to trigger on rising edge, falling edge,
+ * high level, low level or simply on level change.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Interrupt source bit map.
+ * \param ul_attr Interrupt source attributes.
+ */
+void pio_configure_interrupt(Pio *p_pio, const uint32_t ul_mask,
+               const uint32_t ul_attr)
+{
+       /* Configure additional interrupt mode registers. */
+       if (ul_attr & PIO_IT_AIME) {
+               /* Enable additional interrupt mode. */
+               p_pio->PIO_AIMER = ul_mask;
+
+               /* If bit field of the selected pin is 1, set as
+                  Rising Edge/High level detection event. */
+               if (ul_attr & PIO_IT_RE_OR_HL) {
+                       /* Rising Edge or High Level */
+                       p_pio->PIO_REHLSR = ul_mask;
+               } else {
+                       /* Falling Edge or Low Level */
+                       p_pio->PIO_FELLSR = ul_mask;
+               }
+
+               /* If bit field of the selected pin is 1, set as
+                  edge detection source. */
+               if (ul_attr & PIO_IT_EDGE) {
+                       /* Edge select */
+                       p_pio->PIO_ESR = ul_mask;
+               } else {
+                       /* Level select */
+                       p_pio->PIO_LSR = ul_mask;
+               }
+       } else {
+               /* Disable additional interrupt mode. */
+               p_pio->PIO_AIMDR = ul_mask;
+       }
+}
+
+/**
+ * \brief Enable the given interrupt source.
+ * The PIO must be configured as an NVIC interrupt source as well.
+ * The status register of the corresponding PIO controller is cleared
+ * prior to enabling the interrupt.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Interrupt sources bit map.
+ */
+void pio_enable_interrupt(Pio *p_pio, const uint32_t ul_mask)
+{
+       p_pio->PIO_ISR;
+       p_pio->PIO_IER = ul_mask;
+}
+
+/**
+ * \brief Disable a given interrupt source, with no added side effects.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Interrupt sources bit map.
+ */
+void pio_disable_interrupt(Pio *p_pio, const uint32_t ul_mask)
+{
+       p_pio->PIO_IDR = ul_mask;
+}
+
+/**
+ * \brief Read PIO interrupt status.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ *
+ * \return The interrupt status mask value.
+ */
+uint32_t pio_get_interrupt_status(const Pio *p_pio)
+{
+       return p_pio->PIO_ISR;
+}
+
+/**
+ * \brief Read PIO interrupt mask.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ *
+ * \return The interrupt mask value.
+ */
+uint32_t pio_get_interrupt_mask(const Pio *p_pio)
+{
+       return p_pio->PIO_IMR;
+}
+
+/**
+ * \brief Set additional interrupt mode.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Interrupt sources bit map.
+ * \param ul_attribute Pin(s) attributes.
+ */
+void pio_set_additional_interrupt_mode(Pio *p_pio,
+               const uint32_t ul_mask, const uint32_t ul_attribute)
+{
+       /* Enables additional interrupt mode if needed */
+       if (ul_attribute & PIO_IT_AIME) {
+               /* Enables additional interrupt mode */
+               p_pio->PIO_AIMER = ul_mask;
+
+               /* Configures the Polarity of the event detection */
+               /* (Rising/Falling Edge or High/Low Level) */
+               if (ul_attribute & PIO_IT_RE_OR_HL) {
+                       /* Rising Edge or High Level */
+                       p_pio->PIO_REHLSR = ul_mask;
+               } else {
+                       /* Falling Edge or Low Level */
+                       p_pio->PIO_FELLSR = ul_mask;
+               }
+
+               /* Configures the type of event detection (Edge or Level) */
+               if (ul_attribute & PIO_IT_EDGE) {
+                       /* Edge select */
+                       p_pio->PIO_ESR = ul_mask;
+               } else {
+                       /* Level select */
+                       p_pio->PIO_LSR = ul_mask;
+               }
+       } else {
+               /* Disable additional interrupt mode */
+               p_pio->PIO_AIMDR = ul_mask;
+       }
+}
+
+#ifndef PIO_WPMR_WPKEY_PASSWD
+#define PIO_WPMR_WPKEY_PASSWD    PIO_WPMR_WPKEY(0x50494FU)
+#endif
+
+/**
+ * \brief Enable or disable write protect of PIO registers.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_enable 1 to enable, 0 to disable.
+ */
+void pio_set_writeprotect(Pio *p_pio, const uint32_t ul_enable)
+{
+       p_pio->PIO_WPMR = PIO_WPMR_WPKEY_PASSWD | ul_enable;
+}
+
+/**
+ * \brief Read write protect status.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ *
+ * \return Return write protect status.
+ */
+uint32_t pio_get_writeprotect_status(const Pio *p_pio)
+{
+       return p_pio->PIO_WPSR;
+}
+
+/**
+ * \brief Return the value of a pin.
+ *
+ * \param ul_pin The pin number.
+ *
+ * \return The pin value.
+ *
+ * \note If pin is output: a pull-up or pull-down could hide the actual value.
+ *       The function \ref pio_get can be called to get the actual pin output
+ *       level.
+ * \note If pin is input: PIOx must be clocked to sample the signal.
+ *       See PMC driver.
+ */
+uint32_t pio_get_pin_value(uint32_t ul_pin)
+{
+       Pio *p_pio = pio_get_pin_group(ul_pin);
+
+       return (p_pio->PIO_PDSR >> (ul_pin & 0x1F)) & 1;
+}
+
+/**
+ * \brief Drive a GPIO pin to 1.
+ *
+ * \param ul_pin The pin index.
+ *
+ * \note The function \ref pio_configure_pin must be called beforehand.
+ */
+void pio_set_pin_high(uint32_t ul_pin)
+{
+       Pio *p_pio = pio_get_pin_group(ul_pin);
+
+       /* Value to be driven on the I/O line: 1. */
+       p_pio->PIO_SODR = 1 << (ul_pin & 0x1F);
+}
+
+/**
+ * \brief Drive a GPIO pin to 0.
+ *
+ * \param ul_pin The pin index.
+ *
+ * \note The function \ref pio_configure_pin must be called before.
+ */
+void pio_set_pin_low(uint32_t ul_pin)
+{
+       Pio *p_pio = pio_get_pin_group(ul_pin);
+
+       /* Value to be driven on the I/O line: 0. */
+       p_pio->PIO_CODR = 1 << (ul_pin & 0x1F);
+}
+
+/**
+ * \brief Toggle a GPIO pin.
+ *
+ * \param ul_pin The pin index.
+ *
+ * \note The function \ref pio_configure_pin must be called before.
+ */
+void pio_toggle_pin(uint32_t ul_pin)
+{
+       Pio *p_pio = pio_get_pin_group(ul_pin);
+
+       if (p_pio->PIO_ODSR & (1 << (ul_pin & 0x1F))) {
+               /* Value to be driven on the I/O line: 0. */
+               p_pio->PIO_CODR = 1 << (ul_pin & 0x1F);
+       } else {
+               /* Value to be driven on the I/O line: 1. */
+               p_pio->PIO_SODR = 1 << (ul_pin & 0x1F);
+       }
+}
+
+/**
+ * \brief Perform complete pin(s) configuration; general attributes and PIO init
+ * if necessary.
+ *
+ * \param ul_pin Bitmask of one or more pin(s) to configure.
+ * \param ul_flags Pins attributes.
+ *
+ * \return Whether the pin(s) have been configured properly.
+ */
+uint32_t pio_configure_pin(uint32_t ul_pin, const uint32_t ul_flags)
+{
+       Pio *p_pio = pio_get_pin_group(ul_pin);
+
+       /* Configure pins */
+       switch (ul_flags & PIO_TYPE_Msk) {
+       case PIO_TYPE_PIO_PERIPH_A:
+               pio_set_peripheral(p_pio, PIO_PERIPH_A, (1 << (ul_pin & 0x1F)));
+               pio_pull_up(p_pio, (1 << (ul_pin & 0x1F)),
+                               (ul_flags & PIO_PULLUP));
+               break;
+       case PIO_TYPE_PIO_PERIPH_B:
+               pio_set_peripheral(p_pio, PIO_PERIPH_B, (1 << (ul_pin & 0x1F)));
+               pio_pull_up(p_pio, (1 << (ul_pin & 0x1F)),
+                               (ul_flags & PIO_PULLUP));
+               break;
+#if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAM4CP || SAM4CM)
+       case PIO_TYPE_PIO_PERIPH_C:
+               pio_set_peripheral(p_pio, PIO_PERIPH_C, (1 << (ul_pin & 0x1F)));
+               pio_pull_up(p_pio, (1 << (ul_pin & 0x1F)),
+                               (ul_flags & PIO_PULLUP));
+               break;
+       case PIO_TYPE_PIO_PERIPH_D:
+               pio_set_peripheral(p_pio, PIO_PERIPH_D, (1 << (ul_pin & 0x1F)));
+               pio_pull_up(p_pio, (1 << (ul_pin & 0x1F)),
+                               (ul_flags & PIO_PULLUP));
+               break;
+#endif
+
+       case PIO_TYPE_PIO_INPUT:
+               pio_set_input(p_pio, (1 << (ul_pin & 0x1F)), ul_flags);
+               break;
+
+       case PIO_TYPE_PIO_OUTPUT_0:
+       case PIO_TYPE_PIO_OUTPUT_1:
+               pio_set_output(p_pio, (1 << (ul_pin & 0x1F)),
+                               ((ul_flags & PIO_TYPE_PIO_OUTPUT_1)
+                               == PIO_TYPE_PIO_OUTPUT_1) ? 1 : 0,
+                               (ul_flags & PIO_OPENDRAIN) ? 1 : 0,
+                               (ul_flags & PIO_PULLUP) ? 1 : 0);
+               break;
+
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+/**
+ * \brief Drive a GPIO port to 1.
+ *
+ * \param p_pio Base address of the PIO port.
+ * \param ul_mask Bitmask of one or more pin(s) to toggle.
+ */
+void pio_set_pin_group_high(Pio *p_pio, uint32_t ul_mask)
+{
+       /* Value to be driven on the I/O line: 1. */
+       p_pio->PIO_SODR = ul_mask;
+}
+
+/**
+ * \brief Drive a GPIO port to 0.
+ *
+ * \param p_pio Base address of the PIO port.
+ * \param ul_mask Bitmask of one or more pin(s) to toggle.
+ */
+void pio_set_pin_group_low(Pio *p_pio, uint32_t ul_mask)
+{
+       /* Value to be driven on the I/O line: 0. */
+       p_pio->PIO_CODR = ul_mask;
+}
+
+/**
+ * \brief Toggle a GPIO group.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Bitmask of one or more pin(s) to configure.
+ */
+void pio_toggle_pin_group(Pio *p_pio, uint32_t ul_mask)
+{
+       if (p_pio->PIO_ODSR & ul_mask) {
+               /* Value to be driven on the I/O line: 0. */
+               p_pio->PIO_CODR = ul_mask;
+       } else {
+               /* Value to be driven on the I/O line: 1. */
+               p_pio->PIO_SODR = ul_mask;
+       }
+}
+
+/**
+ * \brief Perform complete pin(s) configuration; general attributes and PIO init
+ * if necessary.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Bitmask of one or more pin(s) to configure.
+ * \param ul_flags Pin(s) attributes.
+ *
+ * \return Whether the pin(s) have been configured properly.
+ */
+uint32_t pio_configure_pin_group(Pio *p_pio,
+               uint32_t ul_mask, const uint32_t ul_flags)
+{
+       /* Configure pins */
+       switch (ul_flags & PIO_TYPE_Msk) {
+       case PIO_TYPE_PIO_PERIPH_A:
+               pio_set_peripheral(p_pio, PIO_PERIPH_A, ul_mask);
+               pio_pull_up(p_pio, ul_mask, (ul_flags & PIO_PULLUP));
+               break;
+       case PIO_TYPE_PIO_PERIPH_B:
+               pio_set_peripheral(p_pio, PIO_PERIPH_B, ul_mask);
+               pio_pull_up(p_pio, ul_mask, (ul_flags & PIO_PULLUP));
+               break;
+#if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAM4CP || SAM4CM)
+       case PIO_TYPE_PIO_PERIPH_C:
+               pio_set_peripheral(p_pio, PIO_PERIPH_C, ul_mask);
+               pio_pull_up(p_pio, ul_mask, (ul_flags & PIO_PULLUP));
+               break;
+       case PIO_TYPE_PIO_PERIPH_D:
+               pio_set_peripheral(p_pio, PIO_PERIPH_D, ul_mask);
+               pio_pull_up(p_pio, ul_mask, (ul_flags & PIO_PULLUP));
+               break;
+#endif
+
+       case PIO_TYPE_PIO_INPUT:
+               pio_set_input(p_pio, ul_mask, ul_flags);
+               break;
+
+       case PIO_TYPE_PIO_OUTPUT_0:
+       case PIO_TYPE_PIO_OUTPUT_1:
+               pio_set_output(p_pio, ul_mask,
+                               ((ul_flags & PIO_TYPE_PIO_OUTPUT_1)
+                               == PIO_TYPE_PIO_OUTPUT_1) ? 1 : 0,
+                               (ul_flags & PIO_OPENDRAIN) ? 1 : 0,
+                               (ul_flags & PIO_PULLUP) ? 1 : 0);
+               break;
+
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+/**
+ * \brief Enable interrupt for a GPIO pin.
+ *
+ * \param ul_pin The pin index.
+ *
+ * \note The function \ref gpio_configure_pin must be called before.
+ */
+void pio_enable_pin_interrupt(uint32_t ul_pin)
+{
+       Pio *p_pio = pio_get_pin_group(ul_pin);
+
+       p_pio->PIO_IER = 1 << (ul_pin & 0x1F);
+}
+
+
+/**
+ * \brief Disable interrupt for a GPIO pin.
+ *
+ * \param ul_pin The pin index.
+ *
+ * \note The function \ref gpio_configure_pin must be called before.
+ */
+void pio_disable_pin_interrupt(uint32_t ul_pin)
+{
+       Pio *p_pio = pio_get_pin_group(ul_pin);
+
+       p_pio->PIO_IDR = 1 << (ul_pin & 0x1F);
+}
+
+
+/**
+ * \brief Return GPIO port for a GPIO pin.
+ *
+ * \param ul_pin The pin index.
+ *
+ * \return Pointer to \ref Pio struct for GPIO port.
+ */
+Pio *pio_get_pin_group(uint32_t ul_pin)
+{
+       Pio *p_pio;
+
+#if (SAM4C || SAM4CP)
+#  ifdef ID_PIOD
+       if (ul_pin > PIO_PC9_IDX) {
+               p_pio = PIOD;
+       } else if (ul_pin > PIO_PB31_IDX) {
+#  else
+       if  (ul_pin > PIO_PB31_IDX) {
+#  endif
+               p_pio = PIOC;
+       } else {
+               p_pio = (Pio *)((uint32_t)PIOA + (PIO_DELTA * (ul_pin >> 5)));
+       }
+#elif (SAM4CM)
+       if (ul_pin > PIO_PB21_IDX) {
+               p_pio = PIOC;
+       } else {
+               p_pio = (Pio *)((uint32_t)PIOA + (PIO_DELTA * (ul_pin >> 5)));
+       }
+#else
+       p_pio = (Pio *)((uint32_t)PIOA + (PIO_DELTA * (ul_pin >> 5)));
+#endif
+       return p_pio;
+}
+
+/**
+ * \brief Return GPIO port peripheral ID for a GPIO pin.
+ *
+ * \param ul_pin The pin index.
+ *
+ * \return GPIO port peripheral ID.
+ */
+uint32_t pio_get_pin_group_id(uint32_t ul_pin)
+{
+       uint32_t ul_id;
+
+#if (SAM4C || SAM4CP)
+#  ifdef ID_PIOD
+       if (ul_pin > PIO_PC9_IDX) {
+               ul_id = ID_PIOD;
+       } else if (ul_pin > PIO_PB31_IDX) {
+#  else
+       if (ul_pin > PIO_PB31_IDX) {
+#  endif
+               ul_id = ID_PIOC;
+       } else {
+               ul_id = ID_PIOA + (ul_pin >> 5);
+       }
+#elif (SAM4CM)
+       if (ul_pin > PIO_PB21_IDX) {
+               ul_id = ID_PIOC;
+       } else {
+               ul_id = ID_PIOA + (ul_pin >> 5);
+       }
+#else
+       ul_id = ID_PIOA + (ul_pin >> 5);
+#endif
+       return ul_id;
+}
+
+
+/**
+ * \brief Return GPIO port pin mask for a GPIO pin.
+ *
+ * \param ul_pin The pin index.
+ *
+ * \return GPIO port pin mask.
+ */
+uint32_t pio_get_pin_group_mask(uint32_t ul_pin)
+{
+       uint32_t ul_mask = 1 << (ul_pin & 0x1F);
+       return ul_mask;
+}
+
+#if (SAM3S || SAM4S || SAM4E)
+/* Capture mode enable flag */
+uint32_t pio_capture_enable_flag;
+
+/**
+ * \brief Configure PIO capture mode.
+ * \note PIO capture mode will be disabled automatically.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mode Bitmask of one or more modes.
+ */
+void pio_capture_set_mode(Pio *p_pio, uint32_t ul_mode)
+{
+       ul_mode &= (~PIO_PCMR_PCEN); /* Disable PIO capture mode */
+       p_pio->PIO_PCMR = ul_mode;
+}
+
+/**
+ * \brief Enable PIO capture mode.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ */
+void pio_capture_enable(Pio *p_pio)
+{
+       p_pio->PIO_PCMR |= PIO_PCMR_PCEN;
+       pio_capture_enable_flag = true;
+}
+
+/**
+ * \brief Disable PIO capture mode.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ */
+void pio_capture_disable(Pio *p_pio)
+{
+       p_pio->PIO_PCMR &= (~PIO_PCMR_PCEN);
+       pio_capture_enable_flag = false;
+}
+
+/**
+ * \brief Read from Capture Reception Holding Register.
+ * \note Data presence should be tested before any read attempt.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param pul_data Pointer to store the data.
+ *
+ * \retval 0 Success.
+ * \retval 1 I/O Failure, Capture data is not ready.
+ */
+uint32_t pio_capture_read(const Pio *p_pio, uint32_t *pul_data)
+{
+       /* Check if the data is ready */
+       if ((p_pio->PIO_PCISR & PIO_PCISR_DRDY) == 0) {
+               return 1;
+       }
+
+       /* Read data */
+       *pul_data = p_pio->PIO_PCRHR;
+       return 0;
+}
+
+/**
+ * \brief Enable the given interrupt source of PIO capture. The status
+ * register of the corresponding PIO capture controller is cleared prior
+ * to enabling the interrupt.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Interrupt sources bit map.
+ */
+void pio_capture_enable_interrupt(Pio *p_pio, const uint32_t ul_mask)
+{
+       p_pio->PIO_PCISR;
+       p_pio->PIO_PCIER = ul_mask;
+}
+
+/**
+ * \brief Disable a given interrupt source of PIO capture.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ * \param ul_mask Interrupt sources bit map.
+ */
+void pio_capture_disable_interrupt(Pio *p_pio, const uint32_t ul_mask)
+{
+       p_pio->PIO_PCIDR = ul_mask;
+}
+
+/**
+ * \brief Read PIO interrupt status of PIO capture.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ *
+ * \return The interrupt status mask value.
+ */
+uint32_t pio_capture_get_interrupt_status(const Pio *p_pio)
+{
+       return p_pio->PIO_PCISR;
+}
+
+/**
+ * \brief Read PIO interrupt mask of PIO capture.
+ *
+ * \param p_pio Pointer to a PIO instance.
+ *
+ * \return The interrupt mask value.
+ */
+uint32_t pio_capture_get_interrupt_mask(const Pio *p_pio)
+{
+       return p_pio->PIO_PCIMR;
+}
+
+/**
+ * \brief Get PDC registers base address.
+ *
+ * \param p_pio Pointer to an PIO peripheral.
+ *
+ * \return PIOA PDC register base address.
+ */
+Pdc *pio_capture_get_pdc_base(const Pio *p_pio)
+{
+       UNUSED(p_pio); /* Stop warning */
+       return PDC_PIOA;
+}
+#endif
+
+#if (SAM4C || SAM4CP || SAM4CM)
+/**
+ * \brief Set PIO IO drive.
+ *
+ * \param p_pio Pointer to an PIO peripheral.
+ * \param ul_line Line index (0..31).
+ * \param mode IO drive mode.
+ */
+void pio_set_io_drive(Pio *p_pio, uint32_t ul_line,
+               enum pio_io_drive_mode mode)
+{
+       if (ul_line > 15) {
+               p_pio->PIO_DRIVER2 &= ~(3 << ((ul_line - 15) * 2));
+               p_pio->PIO_DRIVER2 |= mode << ((ul_line - 15) * 2);
+       } else {
+               p_pio->PIO_DRIVER1 &= ~(3 << (ul_line * 2));
+               p_pio->PIO_DRIVER1 |= mode << (ul_line * 2);
+       }
+}
+#endif
+
+//@}
+
diff --git a/asf/sam/drivers/pio/pio.h b/asf/sam/drivers/pio/pio.h
new file mode 100644 (file)
index 0000000..9ecb770
--- /dev/null
@@ -0,0 +1,350 @@
+/**
+ * \file
+ *
+ * \brief Parallel Input/Output (PIO) Controller driver for SAM.
+ *
+ * Copyright (c) 2011 - 2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#ifndef PIO_H_INCLUDED
+#define PIO_H_INCLUDED
+
+#include "compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Compute PIO register length */
+#define PIO_DELTA   ((uint32_t) PIOB - (uint32_t) PIOA)
+
+/* GPIO Support */
+#define PIO_TYPE_Pos                  27
+/* PIO Type Mask */
+#define PIO_TYPE_Msk                  (0xFu << PIO_TYPE_Pos)
+/* The pin is not a function pin. */
+#define PIO_TYPE_NOT_A_PIN            (0x0u << PIO_TYPE_Pos)
+/* The pin is controlled by the peripheral A. */
+#define PIO_TYPE_PIO_PERIPH_A         (0x1u << PIO_TYPE_Pos)
+/* The pin is controlled by the peripheral B. */
+#define PIO_TYPE_PIO_PERIPH_B         (0x2u << PIO_TYPE_Pos)
+/* The pin is controlled by the peripheral C. */
+#define PIO_TYPE_PIO_PERIPH_C         (0x3u << PIO_TYPE_Pos)
+/* The pin is controlled by the peripheral D. */
+#define PIO_TYPE_PIO_PERIPH_D         (0x4u << PIO_TYPE_Pos)
+/* The pin is an input. */
+#define PIO_TYPE_PIO_INPUT            (0x5u << PIO_TYPE_Pos)
+/* The pin is an output and has a default level of 0. */
+#define PIO_TYPE_PIO_OUTPUT_0         (0x6u << PIO_TYPE_Pos)
+/* The pin is an output and has a default level of 1. */
+#define PIO_TYPE_PIO_OUTPUT_1         (0x7u << PIO_TYPE_Pos)
+
+typedef enum _pio_type {
+       PIO_NOT_A_PIN   = PIO_TYPE_NOT_A_PIN,
+       PIO_PERIPH_A    = PIO_TYPE_PIO_PERIPH_A,
+       PIO_PERIPH_B    = PIO_TYPE_PIO_PERIPH_B,
+#if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAM4CP || SAM4CM)
+       PIO_PERIPH_C    = PIO_TYPE_PIO_PERIPH_C,
+       PIO_PERIPH_D    = PIO_TYPE_PIO_PERIPH_D,
+#endif
+       PIO_INPUT       = PIO_TYPE_PIO_INPUT,
+       PIO_OUTPUT_0    = PIO_TYPE_PIO_OUTPUT_0,
+       PIO_OUTPUT_1    = PIO_TYPE_PIO_OUTPUT_1
+} pio_type_t;
+
+/*  Default pin configuration (no attribute). */
+#define PIO_DEFAULT             (0u << 0)
+/*  The internal pin pull-up is active. */
+#define PIO_PULLUP              (1u << 0)
+/*  The internal glitch filter is active. */
+#define PIO_DEGLITCH            (1u << 1)
+/*  The pin is open-drain. */
+#define PIO_OPENDRAIN           (1u << 2)
+
+/*  The internal debouncing filter is active. */
+#define PIO_DEBOUNCE            (1u << 3)
+
+/*  Enable additional interrupt modes. */
+#define PIO_IT_AIME             (1u << 4)
+
+/*  Interrupt High Level/Rising Edge detection is active. */
+#define PIO_IT_RE_OR_HL         (1u << 5)
+/*  Interrupt Edge detection is active. */
+#define PIO_IT_EDGE             (1u << 6)
+
+/*  Low level interrupt is active */
+#define PIO_IT_LOW_LEVEL        (0               | 0 | PIO_IT_AIME)
+/*  High level interrupt is active */
+#define PIO_IT_HIGH_LEVEL       (PIO_IT_RE_OR_HL | 0 | PIO_IT_AIME)
+/*  Falling edge interrupt is active */
+#define PIO_IT_FALL_EDGE        (0               | PIO_IT_EDGE | PIO_IT_AIME)
+/*  Rising edge interrupt is active */
+#define PIO_IT_RISE_EDGE        (PIO_IT_RE_OR_HL | PIO_IT_EDGE | PIO_IT_AIME)
+
+/*
+ *  The #attribute# field is a bitmask that can either be set to PIO_DEFAULT,
+ *  or combine (using bitwise OR '|') any number of the following constants:
+ *     - PIO_PULLUP
+ *     - PIO_DEGLITCH
+ *     - PIO_DEBOUNCE
+ *     - PIO_OPENDRAIN
+ *     - PIO_IT_LOW_LEVEL
+ *     - PIO_IT_HIGH_LEVEL
+ *     - PIO_IT_FALL_EDGE
+ *     - PIO_IT_RISE_EDGE
+ */
+void pio_pull_up(Pio *p_pio, const uint32_t ul_mask,
+               const uint32_t ul_pull_up_enable);
+void pio_set_debounce_filter(Pio *p_pio, const uint32_t ul_mask,
+               const uint32_t ul_cut_off);
+void pio_set(Pio *p_pio, const uint32_t ul_mask);
+void pio_clear(Pio *p_pio, const uint32_t ul_mask);
+uint32_t pio_get(Pio *p_pio, const pio_type_t ul_type,
+               const uint32_t ul_mask);
+void pio_set_peripheral(Pio *p_pio, const pio_type_t ul_type,
+               const uint32_t ul_mask);
+void pio_set_input(Pio *p_pio, const uint32_t ul_mask,
+               const uint32_t ul_attribute);
+void pio_set_output(Pio *p_pio, const uint32_t ul_mask,
+               const uint32_t ul_default_level,
+               const uint32_t ul_multidrive_enable,
+               const uint32_t ul_pull_up_enable);
+uint32_t pio_configure(Pio *p_pio, const pio_type_t ul_type,
+               const uint32_t ul_mask, const uint32_t ul_attribute);
+uint32_t pio_get_output_data_status(const Pio *p_pio,
+               const uint32_t ul_mask);
+void pio_set_multi_driver(Pio *p_pio, const uint32_t ul_mask,
+               const uint32_t ul_multi_driver_enable);
+uint32_t pio_get_multi_driver_status(const Pio *p_pio);
+
+#if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM)
+void pio_pull_down(Pio *p_pio, const uint32_t ul_mask,
+               const uint32_t ul_pull_down_enable);
+#endif
+
+void pio_enable_output_write(Pio *p_pio, const uint32_t ul_mask);
+void pio_disable_output_write(Pio *p_pio, const uint32_t ul_mask);
+uint32_t pio_get_output_write_status(const Pio *p_pio);
+void pio_sync_output_write(Pio *p_pio, const uint32_t ul_mask);
+
+#if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM)
+void pio_set_schmitt_trigger(Pio *p_pio, const uint32_t ul_mask);
+uint32_t pio_get_schmitt_trigger(const Pio *p_pio);
+#endif
+
+void pio_configure_interrupt(Pio *p_pio, const uint32_t ul_mask,
+               const uint32_t ul_attr);
+void pio_enable_interrupt(Pio *p_pio, const uint32_t ul_mask);
+void pio_disable_interrupt(Pio *p_pio, const uint32_t ul_mask);
+uint32_t pio_get_interrupt_status(const Pio *p_pio);
+uint32_t pio_get_interrupt_mask(const Pio *p_pio);
+void pio_set_additional_interrupt_mode(Pio *p_pio,
+               const uint32_t ul_mask, const uint32_t ul_attribute);
+void pio_set_writeprotect(Pio *p_pio, const uint32_t ul_enable);
+uint32_t pio_get_writeprotect_status(const Pio *p_pio);
+
+#if (SAM3S || SAM4S || SAM4E)
+void pio_capture_set_mode(Pio *p_pio, uint32_t ul_mode);
+void pio_capture_enable(Pio *p_pio);
+void pio_capture_disable(Pio *p_pio);
+uint32_t pio_capture_read(const Pio *p_pio, uint32_t * pul_data);
+void pio_capture_enable_interrupt(Pio *p_pio, const uint32_t ul_mask);
+void pio_capture_disable_interrupt(Pio * p_pio, const uint32_t ul_mask);
+uint32_t pio_capture_get_interrupt_status(const Pio *p_pio);
+uint32_t pio_capture_get_interrupt_mask(const Pio *p_pio);
+Pdc *pio_capture_get_pdc_base(const Pio *p_pio);
+#endif
+
+/* GPIO Support */
+uint32_t pio_get_pin_value(uint32_t pin);
+void pio_set_pin_high(uint32_t pin);
+void pio_set_pin_low(uint32_t pin);
+void pio_toggle_pin(uint32_t pin);
+void pio_enable_pin_interrupt(uint32_t pin);
+void pio_disable_pin_interrupt(uint32_t pin);
+Pio *pio_get_pin_group(uint32_t pin);
+uint32_t pio_get_pin_group_id(uint32_t pin);
+uint32_t pio_get_pin_group_mask(uint32_t pin);
+uint32_t pio_configure_pin(uint32_t ul_pin, const uint32_t ul_flags);
+void pio_set_pin_group_high(Pio *p_pio, uint32_t ul_mask);
+void pio_set_pin_group_low(Pio *p_pio, uint32_t ul_mask);
+void pio_toggle_pin_group(Pio *p_pio, uint32_t ul_mask);
+uint32_t pio_configure_pin_group(Pio *p_pio, uint32_t ul_mask,
+               const uint32_t ul_flags);
+
+#if (SAM4C || SAM4CP || SAM4CM)
+enum pio_io_drive_mode {
+       PIO_IO_DRIVE_HIGH = 0,
+       PIO_IO_DRIVE_MEDIUM,
+       PIO_IO_DRIVE_LOW,
+};
+void pio_set_io_drive(Pio *p_pio, uint32_t ul_line,
+               enum pio_io_drive_mode mode);
+#endif
+
+/**
+ * \page sam_pio_quickstart Quick Start Guide for the SAM PIO driver
+ *
+ * This is the quick start guide for the \ref sam_drivers_pio_group "PIO Driver",
+ * with step-by-step instructions on how to configure and use the driver for
+ * specific use cases.
+ *
+ * The section described below can be compiled into e.g. the main application
+ * loop or any other function that will need to interface with the IO port.
+ *
+ * \section sam_pio_usecases PIO use cases
+ * - \ref sam_pio_quickstart_basic
+ * - \ref sam_pio_quickstart_use_case_2
+ *
+ * \section sam_pio_quickstart_basic Basic usage of the PIO driver
+ * This section will present a basic use case for the PIO driver. This use case
+ * will configure pin 23 on port A as output and pin 16 as an input with pullup,
+ * and then toggle the output pin's value to match that of the input pin.
+ *
+ * \subsection sam_pio_quickstart_use_case_1_prereq Prerequisites
+ *  - \ref group_pmc "Power Management Controller driver"
+ *
+ * \subsection sam_pio_quickstart_use_case_1_setup_steps Initialization code
+ * Add to the application initialization code:
+ * \code
+           pmc_enable_periph_clk(ID_PIOA);
+
+           pio_set_output(PIOA, PIO_PA23, LOW, DISABLE, ENABLE);
+           pio_set_input(PIOA, PIO_PA16, PIO_PULLUP);
+\endcode
+ *
+ * \subsection sam_pio_quickstart_use_case_1_setup_steps_workflow Workflow
+ * -# Enable the module clock to the PIOA peripheral:
+ *    \code pmc_enable_periph_clk(ID_PIOA); \endcode
+ * -# Set pin 23 direction on PIOA as output, default low level:
+ *     \code pio_set_output(PIOA, PIO_PA23, LOW, DISABLE, ENABLE); \endcode
+ * -# Set pin 16 direction on PIOA as input, with pullup:
+ *     \code pio_set_input(PIOA, PIO_PA16, PIO_PULLUP); \endcode
+ *
+ * \subsection sam_pio_quickstart_use_case_1_example_code Example code
+ *   Set the state of output pin 23 to match input pin 16:
+ *   \code
+       if (pio_get(PIOA, PIO_TYPE_PIO_INPUT, PIO_PA16))
+           pio_clear(PIOA, PIO_PA23);
+       else
+           pio_set(PIOA, PIO_PA23);
+\endcode
+ *
+ * \subsection sam_pio_quickstart_use_case_1_example_workflow Workflow
+ * -# We check the value of the pin:
+ *     \code
+       if (pio_get(PIOA, PIO_TYPE_PIO_INPUT, PIO_PA16))
+\endcode
+ * -# Then we set the new output value based on the read pin value:
+ *     \code
+           pio_clear(PIOA, PIO_PA23);
+       else
+           pio_set(PIOA, PIO_PA23);
+\endcode
+ */
+
+/**
+ * \page sam_pio_quickstart_use_case_2 Advanced use case - Interrupt driven edge detection
+ *
+ * \section sam_pio_quickstart_use_case_2 Advanced Use Case 1
+ * This section will present a more advanced use case for the PIO driver. This use case
+ * will configure pin 23 on port A as output and pin 16 as an input with pullup,
+ * and then toggle the output pin's value to match that of the input pin using the interrupt
+ * controller within the device.
+ *
+ * \subsection sam_pio_quickstart_use_case_2_prereq Prerequisites
+ *  - \ref group_pmc "Power Management Controller driver"
+ *
+ * \subsection sam_pio_quickstart_use_case_2_setup_steps Initialization code
+ * Add to the application initialization code:
+ * \code
+        pmc_enable_periph_clk(ID_PIOA);
+
+        pio_set_output(PIOA, PIO_PA23, LOW, DISABLE, ENABLE);
+        pio_set_input(PIOA, PIO_PA16, PIO_PULLUP);
+
+        pio_handler_set(PIOA, ID_PIOA, PIO_PA16, PIO_IT_EDGE, pin_edge_handler);
+        pio_enable_interrupt(PIOA, PIO_PA16);
+
+        NVIC_EnableIRQ(PIOA_IRQn);
+\endcode
+ *
+ * \subsection sam_pio_quickstart_use_case_2_setup_steps_workflow Workflow
+ * -# Enable the module clock to the PIOA peripheral:
+ *    \code pmc_enable_periph_clk(ID_PIOA); \endcode
+ * -# Set pin 23 direction on PIOA as output, default low level:
+ *     \code pio_set_output(PIOA, PIO_PA23, LOW, DISABLE, ENABLE); \endcode
+ * -# Set pin 16 direction on PIOA as input, with pullup:
+ *     \code pio_set_input(PIOA, PIO_PA16, PIO_PULLUP); \endcode
+ * -# Configure the input pin 16 interrupt mode and handler:
+ *     \code pio_handler_set(PIOA, ID_PIOA, PIO_PA16, PIO_IT_EDGE, pin_edge_handler); \endcode
+ * -# Enable the interrupt for the configured input pin:
+ *     \code pio_enable_interrupt(PIOA, PIO_PA16); \endcode
+ * -# Enable interrupt handling from the PIOA module:
+ *     \code NVIC_EnableIRQ(PIOA_IRQn); \endcode
+ *
+ * \subsection sam_pio_quickstart_use_case_2_example_code Example code
+ * Add the following function to your application:
+ * \code
+       void pin_edge_handler(void)
+       {
+           if (pio_get(PIOA, PIO_TYPE_PIO_INPUT, PIO_PA16))
+               pio_clear(PIOA, PIO_PA23);
+           else
+               pio_set(PIOA, PIO_PA23);
+       }
+\endcode
+ *
+ * \subsection sam_pio_quickstart_use_case_2_example_workflow Workflow
+ * -# We check the value of the pin:
+ *     \code
+       if (pio_get(PIOA, PIO_TYPE_PIO_INPUT, PIO_PA16))
+\endcode
+ * -# Then we set the new output value based on the read pin value:
+ *     \code
+           pio_clear(PIOA, PIO_PA23);
+       else
+           pio_set(PIOA, PIO_PA23);
+\endcode
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PIO_H_INCLUDED */
diff --git a/asf/sam/drivers/pmc/pmc.c b/asf/sam/drivers/pmc/pmc.c
new file mode 100644 (file)
index 0000000..06e254b
--- /dev/null
@@ -0,0 +1,1489 @@
+/**
+ * \file
+ *
+ * \brief Power Management Controller (PMC) driver for SAM.
+ *
+ * Copyright (c) 2011 - 2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#include "pmc.h"
+
+#if (SAM3N)
+# define MAX_PERIPH_ID    31
+#elif (SAM3XA)
+# define MAX_PERIPH_ID    44
+#elif (SAM3U)
+# define MAX_PERIPH_ID    29
+#elif (SAM3S || SAM4S)
+# define MAX_PERIPH_ID    34
+#elif (SAM4E)
+# define MAX_PERIPH_ID    47
+#elif (SAM4N)
+# define MAX_PERIPH_ID    31
+#elif (SAM4C || SAM4CM || SAM4CP)
+# define MAX_PERIPH_ID    43
+#elif (SAMG51)
+# define MAX_PERIPH_ID    47
+#elif (SAMG53)
+# define MAX_PERIPH_ID    47
+#elif (SAMG54)
+# define MAX_PERIPH_ID    47
+#endif
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+/**
+ * \defgroup sam_drivers_pmc_group Power Management Controller (PMC)
+ *
+ * \par Purpose
+ *
+ * The Power Management Controller (PMC) optimizes power consumption by
+ * controlling all system and user peripheral clocks. The PMC enables/disables
+ * the clock inputs to many of the peripherals and the Cortex-M Processor.
+ *
+ * @{
+ */
+
+/**
+ * \brief Set the prescaler of the MCK.
+ *
+ * \param ul_pres Prescaler value.
+ */
+void pmc_mck_set_prescaler(uint32_t ul_pres)
+{
+       PMC->PMC_MCKR =
+                       (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;
+       while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
+}
+
+/**
+ * \brief Set the source of the MCK.
+ *
+ * \param ul_source Source selection value.
+ */
+void pmc_mck_set_source(uint32_t ul_source)
+{
+       PMC->PMC_MCKR =
+                       (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) | ul_source;
+       while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
+}
+
+/**
+ * \brief Switch master clock source selection to slow clock.
+ *
+ * \param ul_pres Processor clock prescaler.
+ *
+ * \retval 0 Success.
+ * \retval 1 Timeout error.
+ */
+uint32_t pmc_switch_mck_to_sclk(uint32_t ul_pres)
+{
+       uint32_t ul_timeout;
+
+       PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |
+                       PMC_MCKR_CSS_SLOW_CLK;
+       for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
+                       --ul_timeout) {
+               if (ul_timeout == 0) {
+                       return 1;
+               }
+       }
+
+       PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;
+       for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
+                       --ul_timeout) {
+               if (ul_timeout == 0) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * \brief Switch master clock source selection to main clock.
+ *
+ * \param ul_pres Processor clock prescaler.
+ *
+ * \retval 0 Success.
+ * \retval 1 Timeout error.
+ */
+uint32_t pmc_switch_mck_to_mainck(uint32_t ul_pres)
+{
+       uint32_t ul_timeout;
+
+       PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |
+                       PMC_MCKR_CSS_MAIN_CLK;
+       for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
+                       --ul_timeout) {
+               if (ul_timeout == 0) {
+                       return 1;
+               }
+       }
+
+       PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;
+       for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
+                       --ul_timeout) {
+               if (ul_timeout == 0) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * \brief Switch master clock source selection to PLLA clock.
+ *
+ * \param ul_pres Processor clock prescaler.
+ *
+ * \retval 0 Success.
+ * \retval 1 Timeout error.
+ */
+uint32_t pmc_switch_mck_to_pllack(uint32_t ul_pres)
+{
+       uint32_t ul_timeout;
+
+       PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;
+       for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
+                       --ul_timeout) {
+               if (ul_timeout == 0) {
+                       return 1;
+               }
+       }
+
+       PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |
+                       PMC_MCKR_CSS_PLLA_CLK;
+
+       for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
+                       --ul_timeout) {
+               if (ul_timeout == 0) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+#if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)
+/**
+ * \brief Switch master clock source selection to PLLB clock.
+ *
+ * \param ul_pres Processor clock prescaler.
+ *
+ * \retval 0 Success.
+ * \retval 1 Timeout error.
+ */
+uint32_t pmc_switch_mck_to_pllbck(uint32_t ul_pres)
+{
+       uint32_t ul_timeout;
+
+       PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;
+       for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
+                       --ul_timeout) {
+               if (ul_timeout == 0) {
+                       return 1;
+               }
+       }
+
+       PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |
+                       PMC_MCKR_CSS_PLLB_CLK;
+       for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
+                       --ul_timeout) {
+               if (ul_timeout == 0) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+#endif
+
+#if (SAM3XA || SAM3U)
+/**
+ * \brief Switch master clock source selection to UPLL clock.
+ *
+ * \param ul_pres Processor clock prescaler.
+ *
+ * \retval 0 Success.
+ * \retval 1 Timeout error.
+ */
+uint32_t pmc_switch_mck_to_upllck(uint32_t ul_pres)
+{
+       uint32_t ul_timeout;
+
+       PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;
+       for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
+                       --ul_timeout) {
+               if (ul_timeout == 0) {
+                       return 1;
+               }
+       }
+
+       PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |
+                       PMC_MCKR_CSS_UPLL_CLK;
+       for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
+                       --ul_timeout) {
+               if (ul_timeout == 0) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+#endif
+
+/**
+ * \brief Switch slow clock source selection to external 32k (Xtal or Bypass).
+ *
+ * \note This function disables the PLLs.
+ *
+ * \note Switching SCLK back to 32krc is only possible by shutting down the
+ *       VDDIO power supply.
+ *
+ * \param ul_bypass 0 for Xtal, 1 for bypass.
+ */
+void pmc_switch_sclk_to_32kxtal(uint32_t ul_bypass)
+{
+       /* Set Bypass mode if required */
+       if (ul_bypass == 1) {
+               SUPC->SUPC_MR |= SUPC_MR_KEY_PASSWD |
+                       SUPC_MR_OSCBYPASS;
+       }
+
+       SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_XTALSEL;
+}
+
+/**
+ * \brief Check if the external 32k Xtal is ready.
+ *
+ * \retval 1 External 32k Xtal is ready.
+ * \retval 0 External 32k Xtal is not ready.
+ */
+uint32_t pmc_osc_is_ready_32kxtal(void)
+{
+       return ((SUPC->SUPC_SR & SUPC_SR_OSCSEL)
+                       && (PMC->PMC_SR & PMC_SR_OSCSELS));
+}
+
+/**
+ * \brief Switch main clock source selection to internal fast RC.
+ *
+ * \param ul_moscrcf Fast RC oscillator(4/8/12Mhz).
+ *
+ * \retval 0 Success.
+ * \retval 1 Timeout error.
+ * \retval 2 Invalid frequency.
+ */
+void pmc_switch_mainck_to_fastrc(uint32_t ul_moscrcf)
+{
+       /* Enable Fast RC oscillator but DO NOT switch to RC now */
+       PMC->CKGR_MOR |= (CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCRCEN);
+
+       /* Wait the Fast RC to stabilize */
+       while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));
+
+       /* Change Fast RC oscillator frequency */
+       PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCF_Msk) |
+                       CKGR_MOR_KEY_PASSWD | ul_moscrcf;
+
+       /* Wait the Fast RC to stabilize */
+       while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));
+
+       /* Switch to Fast RC */
+       PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCSEL) |
+                       CKGR_MOR_KEY_PASSWD;
+}
+
+/**
+ * \brief Enable fast RC oscillator.
+ *
+ * \param ul_rc Fast RC oscillator(4/8/12Mhz).
+ */
+void pmc_osc_enable_fastrc(uint32_t ul_rc)
+{
+       /* Enable Fast RC oscillator but DO NOT switch to RC */
+       PMC->CKGR_MOR |= (CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCRCEN);
+       /* Wait the Fast RC to stabilize */
+       while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));
+
+       /* Change Fast RC oscillator frequency */
+       PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCF_Msk) |
+                       CKGR_MOR_KEY_PASSWD | ul_rc;
+       /* Wait the Fast RC to stabilize */
+       while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));
+}
+
+/**
+ * \brief Disable the internal fast RC.
+ */
+void pmc_osc_disable_fastrc(void)
+{
+       /* Disable Fast RC oscillator */
+       PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCEN &
+                                       ~CKGR_MOR_MOSCRCF_Msk)
+                               | CKGR_MOR_KEY_PASSWD;
+}
+
+/**
+ * \brief Check if the main fastrc is ready.
+ *
+ * \retval 0 Xtal is not ready, otherwise ready.
+ */
+uint32_t pmc_osc_is_ready_fastrc(void)
+{
+       return (PMC->PMC_SR & PMC_SR_MOSCRCS);
+}
+
+/**
+ * \brief Enable main XTAL oscillator.
+ *
+ * \param ul_xtal_startup_time Xtal start-up time, in number of slow clocks.
+ */
+void pmc_osc_enable_main_xtal(uint32_t ul_xtal_startup_time)
+{
+       uint32_t mor = PMC->CKGR_MOR;
+       mor &= ~(CKGR_MOR_MOSCXTBY|CKGR_MOR_MOSCXTEN);
+       mor |= CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTEN |
+                       CKGR_MOR_MOSCXTST(ul_xtal_startup_time);
+       PMC->CKGR_MOR = mor;
+       /* Wait the main Xtal to stabilize */
+       while (!(PMC->PMC_SR & PMC_SR_MOSCXTS));
+}
+
+/**
+ * \brief Bypass main XTAL.
+ */
+void pmc_osc_bypass_main_xtal(void)
+{
+       uint32_t mor = PMC->CKGR_MOR;
+       mor &= ~(CKGR_MOR_MOSCXTBY|CKGR_MOR_MOSCXTEN);
+       mor |= CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTBY;
+       /* Enable Crystal oscillator but DO NOT switch now. Keep MOSCSEL to 0 */
+       PMC->CKGR_MOR = mor;
+       /* The MOSCXTS in PMC_SR is automatically set */
+}
+
+/**
+ * \brief Disable the main Xtal.
+ */
+void pmc_osc_disable_main_xtal(void)
+{
+       uint32_t mor = PMC->CKGR_MOR;
+       mor &= ~(CKGR_MOR_MOSCXTBY|CKGR_MOR_MOSCXTEN);
+       PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | mor;
+}
+
+/**
+ * \brief Check if the main crystal is bypassed.
+ *
+ * \retval 0 Xtal is bypassed, otherwise not.
+ */
+uint32_t pmc_osc_is_bypassed_main_xtal(void)
+{
+       return (PMC->CKGR_MOR & CKGR_MOR_MOSCXTBY);
+}
+
+/**
+ * \brief Check if the main crystal is ready.
+ *
+ * \note If main crystal is bypassed, it's always ready.
+ *
+ * \retval 0 main crystal is not ready, otherwise ready.
+ */
+uint32_t pmc_osc_is_ready_main_xtal(void)
+{
+       return (PMC->PMC_SR & PMC_SR_MOSCXTS);
+}
+
+/**
+ * \brief Switch main clock source selection to external Xtal/Bypass.
+ *
+ * \note The function may switch MCK to SCLK if MCK source is MAINCK to avoid
+ *       any system crash.
+ *
+ * \note If used in Xtal mode, the Xtal is automatically enabled.
+ *
+ * \param ul_bypass 0 for Xtal, 1 for bypass.
+ *
+ * \retval 0 Success.
+ * \retval 1 Timeout error.
+ */
+void pmc_switch_mainck_to_xtal(uint32_t ul_bypass,
+               uint32_t ul_xtal_startup_time)
+{
+       /* Enable Main Xtal oscillator */
+       if (ul_bypass) {
+               PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |
+                               CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTBY |
+                               CKGR_MOR_MOSCSEL;
+       } else {
+               PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTBY) |
+                               CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTEN |
+                               CKGR_MOR_MOSCXTST(ul_xtal_startup_time);
+               /* Wait the Xtal to stabilize */
+               while (!(PMC->PMC_SR & PMC_SR_MOSCXTS));
+
+               PMC->CKGR_MOR |= CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCSEL;
+       }
+}
+
+/**
+ * \brief Disable the external Xtal.
+ *
+ * \param ul_bypass 0 for Xtal, 1 for bypass.
+ */
+void pmc_osc_disable_xtal(uint32_t ul_bypass)
+{
+       /* Disable xtal oscillator */
+       if (ul_bypass) {
+               PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTBY) |
+                               CKGR_MOR_KEY_PASSWD;
+       } else {
+               PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |
+                               CKGR_MOR_KEY_PASSWD;
+       }
+}
+
+/**
+ * \brief Check if the MAINCK is ready. Depending on MOSCEL, MAINCK can be one
+ * of Xtal, bypass or internal RC.
+ *
+ * \retval 1 Xtal is ready.
+ * \retval 0 Xtal is not ready.
+ */
+uint32_t pmc_osc_is_ready_mainck(void)
+{
+       return PMC->PMC_SR & PMC_SR_MOSCSELS;
+}
+
+/**
+ * \brief Select Main Crystal or internal RC as main clock source.
+ *
+ * \note This function will not enable/disable RC or Main Crystal.
+ *
+ * \param ul_xtal_rc 0 internal RC is selected, otherwise Main Crystal.
+ */
+void pmc_mainck_osc_select(uint32_t ul_xtal_rc)
+{
+       uint32_t mor = PMC->CKGR_MOR;
+       if (ul_xtal_rc) {
+               mor |=  CKGR_MOR_MOSCSEL;
+       } else {
+               mor &= ~CKGR_MOR_MOSCSEL;
+       }
+       PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | mor;
+}
+
+/**
+ * \brief Enable PLLA clock.
+ *
+ * \param mula PLLA multiplier.
+ * \param pllacount PLLA counter.
+ * \param diva Divider.
+ */
+void pmc_enable_pllack(uint32_t mula, uint32_t pllacount, uint32_t diva)
+{
+       /* first disable the PLL to unlock the lock */
+       pmc_disable_pllack();
+
+#if (SAM4C || SAM4CM || SAM4CP || SAMG)
+       PMC->CKGR_PLLAR = CKGR_PLLAR_PLLAEN(diva) |
+                       CKGR_PLLAR_PLLACOUNT(pllacount) | CKGR_PLLAR_MULA(mula);
+#else
+       PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_DIVA(diva) |
+                       CKGR_PLLAR_PLLACOUNT(pllacount) | CKGR_PLLAR_MULA(mula);
+#endif
+       while ((PMC->PMC_SR & PMC_SR_LOCKA) == 0);
+}
+
+/**
+ * \brief Disable PLLA clock.
+ */
+void pmc_disable_pllack(void)
+{
+#if (SAM4C || SAM4CM || SAM4CP || SAMG)
+       PMC->CKGR_PLLAR = CKGR_PLLAR_MULA(0);
+#else
+       PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0);
+#endif
+}
+
+/**
+ * \brief Is PLLA locked?
+ *
+ * \retval 0 Not locked.
+ * \retval 1 Locked.
+ */
+uint32_t pmc_is_locked_pllack(void)
+{
+       return (PMC->PMC_SR & PMC_SR_LOCKA);
+}
+
+#if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)
+/**
+ * \brief Enable PLLB clock.
+ *
+ * \param mulb PLLB multiplier.
+ * \param pllbcount PLLB counter.
+ * \param divb Divider.
+ */
+void pmc_enable_pllbck(uint32_t mulb, uint32_t pllbcount, uint32_t divb)
+{
+       /* first disable the PLL to unlock the lock */
+       pmc_disable_pllbck();
+
+       PMC->CKGR_PLLBR =
+                       CKGR_PLLBR_DIVB(divb) | CKGR_PLLBR_PLLBCOUNT(pllbcount)
+                       | CKGR_PLLBR_MULB(mulb);
+       while ((PMC->PMC_SR & PMC_SR_LOCKB) == 0);
+}
+
+/**
+ * \brief Disable PLLB clock.
+ */
+void pmc_disable_pllbck(void)
+{
+       PMC->CKGR_PLLBR = CKGR_PLLBR_MULB(0);
+}
+
+/**
+ * \brief Is PLLB locked?
+ *
+ * \retval 0 Not locked.
+ * \retval 1 Locked.
+ */
+uint32_t pmc_is_locked_pllbck(void)
+{
+       return (PMC->PMC_SR & PMC_SR_LOCKB);
+}
+#endif
+
+#if (SAM3XA || SAM3U)
+/**
+ * \brief Enable UPLL clock.
+ */
+void pmc_enable_upll_clock(void)
+{
+       PMC->CKGR_UCKR = CKGR_UCKR_UPLLCOUNT(3) | CKGR_UCKR_UPLLEN;
+
+       /* Wait UTMI PLL Lock Status */
+       while (!(PMC->PMC_SR & PMC_SR_LOCKU));
+}
+
+/**
+ * \brief Disable UPLL clock.
+ */
+void pmc_disable_upll_clock(void)
+{
+       PMC->CKGR_UCKR &= ~CKGR_UCKR_UPLLEN;
+}
+
+/**
+ * \brief Is UPLL locked?
+ *
+ * \retval 0 Not locked.
+ * \retval 1 Locked.
+ */
+uint32_t pmc_is_locked_upll(void)
+{
+       return (PMC->PMC_SR & PMC_SR_LOCKU);
+}
+#endif
+
+/**
+ * \brief Enable the specified peripheral clock.
+ *
+ * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).
+ *
+ * \param ul_id Peripheral ID (ID_xxx).
+ *
+ * \retval 0 Success.
+ * \retval 1 Invalid parameter.
+ */
+uint32_t pmc_enable_periph_clk(uint32_t ul_id)
+{
+       if (ul_id > MAX_PERIPH_ID) {
+               return 1;
+       }
+
+       if (ul_id < 32) {
+               if ((PMC->PMC_PCSR0 & (1u << ul_id)) != (1u << ul_id)) {
+                       PMC->PMC_PCER0 = 1 << ul_id;
+               }
+#if (SAM3S || SAM3XA || SAM4S || SAM4E || SAM4C || SAM4CM || SAM4CP)
+       } else {
+               ul_id -= 32;
+               if ((PMC->PMC_PCSR1 & (1u << ul_id)) != (1u << ul_id)) {
+                       PMC->PMC_PCER1 = 1 << ul_id;
+               }
+#endif
+       }
+
+       return 0;
+}
+
+/**
+ * \brief Disable the specified peripheral clock.
+ *
+ * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).
+ *
+ * \param ul_id Peripheral ID (ID_xxx).
+ *
+ * \retval 0 Success.
+ * \retval 1 Invalid parameter.
+ */
+uint32_t pmc_disable_periph_clk(uint32_t ul_id)
+{
+       if (ul_id > MAX_PERIPH_ID) {
+               return 1;
+       }
+
+       if (ul_id < 32) {
+               if ((PMC->PMC_PCSR0 & (1u << ul_id)) == (1u << ul_id)) {
+                       PMC->PMC_PCDR0 = 1 << ul_id;
+               }
+#if (SAM3S || SAM3XA || SAM4S || SAM4E || SAM4C || SAM4CM || SAM4CP)
+       } else {
+               ul_id -= 32;
+               if ((PMC->PMC_PCSR1 & (1u << ul_id)) == (1u << ul_id)) {
+                       PMC->PMC_PCDR1 = 1 << ul_id;
+               }
+#endif
+       }
+       return 0;
+}
+
+/**
+ * \brief Enable all peripheral clocks.
+ */
+void pmc_enable_all_periph_clk(void)
+{
+       PMC->PMC_PCER0 = PMC_MASK_STATUS0;
+       while ((PMC->PMC_PCSR0 & PMC_MASK_STATUS0) != PMC_MASK_STATUS0);
+
+#if (SAM3S || SAM3XA || SAM4S || SAM4E || SAM4C || SAM4CM || SAM4CP)
+       PMC->PMC_PCER1 = PMC_MASK_STATUS1;
+       while ((PMC->PMC_PCSR1 & PMC_MASK_STATUS1) != PMC_MASK_STATUS1);
+#endif
+}
+
+/**
+ * \brief Disable all peripheral clocks.
+ */
+void pmc_disable_all_periph_clk(void)
+{
+       PMC->PMC_PCDR0 = PMC_MASK_STATUS0;
+       while ((PMC->PMC_PCSR0 & PMC_MASK_STATUS0) != 0);
+
+#if (SAM3S || SAM3XA || SAM4S || SAM4E || SAM4C || SAM4CM || SAM4CP)
+       PMC->PMC_PCDR1 = PMC_MASK_STATUS1;
+       while ((PMC->PMC_PCSR1 & PMC_MASK_STATUS1) != 0);
+#endif
+}
+
+/**
+ * \brief Check if the specified peripheral clock is enabled.
+ *
+ * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).
+ *
+ * \param ul_id Peripheral ID (ID_xxx).
+ *
+ * \retval 0 Peripheral clock is disabled or unknown.
+ * \retval 1 Peripheral clock is enabled.
+ */
+uint32_t pmc_is_periph_clk_enabled(uint32_t ul_id)
+{
+       if (ul_id > MAX_PERIPH_ID) {
+               return 0;
+       }
+
+#if (SAM3S || SAM3XA || SAM4S || SAM4E || SAM4C || SAM4CM || SAM4CP)
+       if (ul_id < 32) {
+#endif
+               if ((PMC->PMC_PCSR0 & (1u << ul_id))) {
+                       return 1;
+               } else {
+                       return 0;
+               }
+#if (SAM3S || SAM3XA || SAM4S || SAM4E || SAM4C || SAM4CM || SAM4CP)
+       } else {
+               ul_id -= 32;
+               if ((PMC->PMC_PCSR1 & (1u << ul_id))) {
+                       return 1;
+               } else {
+                       return 0;
+               }
+       }
+#endif
+}
+
+/**
+ * \brief Set the prescaler for the specified programmable clock.
+ *
+ * \param ul_id Peripheral ID.
+ * \param ul_pres Prescaler value.
+ */
+void pmc_pck_set_prescaler(uint32_t ul_id, uint32_t ul_pres)
+{
+       PMC->PMC_PCK[ul_id] =
+                       (PMC->PMC_PCK[ul_id] & ~PMC_PCK_PRES_Msk) | ul_pres;
+       while ((PMC->PMC_SCER & (PMC_SCER_PCK0 << ul_id))
+                       && !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)));
+}
+
+/**
+ * \brief Set the source oscillator for the specified programmable clock.
+ *
+ * \param ul_id Peripheral ID.
+ * \param ul_source Source selection value.
+ */
+void pmc_pck_set_source(uint32_t ul_id, uint32_t ul_source)
+{
+       PMC->PMC_PCK[ul_id] =
+                       (PMC->PMC_PCK[ul_id] & ~PMC_PCK_CSS_Msk) | ul_source;
+       while ((PMC->PMC_SCER & (PMC_SCER_PCK0 << ul_id))
+                       && !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)));
+}
+
+/**
+ * \brief Switch programmable clock source selection to slow clock.
+ *
+ * \param ul_id Id of the programmable clock.
+ * \param ul_pres Programmable clock prescaler.
+ *
+ * \retval 0 Success.
+ * \retval 1 Timeout error.
+ */
+uint32_t pmc_switch_pck_to_sclk(uint32_t ul_id, uint32_t ul_pres)
+{
+       uint32_t ul_timeout;
+
+       PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_SLOW_CLK | ul_pres;
+       for (ul_timeout = PMC_TIMEOUT;
+       !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)); --ul_timeout) {
+               if (ul_timeout == 0) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * \brief Switch programmable clock source selection to main clock.
+ *
+ * \param ul_id Id of the programmable clock.
+ * \param ul_pres Programmable clock prescaler.
+ *
+ * \retval 0 Success.
+ * \retval 1 Timeout error.
+ */
+uint32_t pmc_switch_pck_to_mainck(uint32_t ul_id, uint32_t ul_pres)
+{
+       uint32_t ul_timeout;
+
+       PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_MAIN_CLK | ul_pres;
+       for (ul_timeout = PMC_TIMEOUT;
+       !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)); --ul_timeout) {
+               if (ul_timeout == 0) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * \brief Switch programmable clock source selection to PLLA clock.
+ *
+ * \param ul_id Id of the programmable clock.
+ * \param ul_pres Programmable clock prescaler.
+ *
+ * \retval 0 Success.
+ * \retval 1 Timeout error.
+ */
+uint32_t pmc_switch_pck_to_pllack(uint32_t ul_id, uint32_t ul_pres)
+{
+       uint32_t ul_timeout;
+
+       PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_PLLA_CLK | ul_pres;
+       for (ul_timeout = PMC_TIMEOUT;
+       !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)); --ul_timeout) {
+               if (ul_timeout == 0) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+#if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)
+/**
+ * \brief Switch programmable clock source selection to PLLB clock.
+ *
+ * \param ul_id Id of the programmable clock.
+ * \param ul_pres Programmable clock prescaler.
+ *
+ * \retval 0 Success.
+ * \retval 1 Timeout error.
+ */
+uint32_t pmc_switch_pck_to_pllbck(uint32_t ul_id, uint32_t ul_pres)
+{
+       uint32_t ul_timeout;
+
+       PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_PLLB_CLK | ul_pres;
+       for (ul_timeout = PMC_TIMEOUT;
+                       !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id));
+                       --ul_timeout) {
+               if (ul_timeout == 0) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+#endif
+
+#if (SAM3XA || SAM3U)
+/**
+ * \brief Switch programmable clock source selection to UPLL clock.
+ *
+ * \param ul_id Id of the programmable clock.
+ * \param ul_pres Programmable clock prescaler.
+ *
+ * \retval 0 Success.
+ * \retval 1 Timeout error.
+ */
+uint32_t pmc_switch_pck_to_upllck(uint32_t ul_id, uint32_t ul_pres)
+{
+       uint32_t ul_timeout;
+
+       PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_UPLL_CLK | ul_pres;
+       for (ul_timeout = PMC_TIMEOUT;
+                       !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id));
+                       --ul_timeout) {
+               if (ul_timeout == 0) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+#endif
+
+/**
+ * \brief Enable the specified programmable clock.
+ *
+ * \param ul_id Id of the programmable clock.
+ */
+void pmc_enable_pck(uint32_t ul_id)
+{
+       PMC->PMC_SCER = PMC_SCER_PCK0 << ul_id;
+}
+
+/**
+ * \brief Disable the specified programmable clock.
+ *
+ * \param ul_id Id of the programmable clock.
+ */
+void pmc_disable_pck(uint32_t ul_id)
+{
+       PMC->PMC_SCDR = PMC_SCER_PCK0 << ul_id;
+}
+
+/**
+ * \brief Enable all programmable clocks.
+ */
+void pmc_enable_all_pck(void)
+{
+       PMC->PMC_SCER = PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2;
+}
+
+/**
+ * \brief Disable all programmable clocks.
+ */
+void pmc_disable_all_pck(void)
+{
+       PMC->PMC_SCDR = PMC_SCDR_PCK0 | PMC_SCDR_PCK1 | PMC_SCDR_PCK2;
+}
+
+/**
+ * \brief Check if the specified programmable clock is enabled.
+ *
+ * \param ul_id Id of the programmable clock.
+ *
+ * \retval 0 Programmable clock is disabled or unknown.
+ * \retval 1 Programmable clock is enabled.
+ */
+uint32_t pmc_is_pck_enabled(uint32_t ul_id)
+{
+       if (ul_id > 2) {
+               return 0;
+       }
+
+       return (PMC->PMC_SCSR & (PMC_SCSR_PCK0 << ul_id));
+}
+
+#if (SAM4C || SAM4CM || SAM4CP)
+/**
+ * \brief Enable Coprocessor Clocks.
+ */
+void pmc_enable_cpck(void)
+{
+       PMC->PMC_SCER = PMC_SCER_CPCK | PMC_SCER_CPKEY_PASSWD;
+}
+
+/**
+ * \brief Disable Coprocessor Clocks.
+ */
+void pmc_disable_cpck(void)
+{
+       PMC->PMC_SCDR = PMC_SCDR_CPCK | PMC_SCDR_CPKEY_PASSWD;
+}
+
+/**
+ * \brief Check if the Coprocessor Clocks is enabled.
+ *
+ * \retval 0 Coprocessor Clocks is disabled.
+ * \retval 1 Coprocessor Clocks is enabled.
+ */
+bool pmc_is_cpck_enabled(void)
+{
+       if(PMC->PMC_SCSR & PMC_SCSR_CPCK) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+/**
+ * \brief Enable Coprocessor Bus Master Clocks.
+ */
+void pmc_enable_cpbmck(void)
+{
+       PMC->PMC_SCER = PMC_SCER_CPCK | PMC_SCER_CPKEY_PASSWD;
+}
+
+/**
+ * \brief Disable Coprocessor Bus Master Clocks.
+ */
+void pmc_disable_cpbmck(void)
+{
+       PMC->PMC_SCDR = PMC_SCDR_CPCK | PMC_SCDR_CPKEY_PASSWD;
+}
+
+/**
+ * \brief Check if the Coprocessor Bus Master Clocks is enabled.
+ *
+ * \retval 0 Coprocessor Bus Master Clocks is disabled.
+ * \retval 1 Coprocessor Bus Master Clocks is enabled.
+ */
+bool pmc_is_cpbmck_enabled(void)
+{
+       if(PMC->PMC_SCSR & PMC_SCSR_CPBMCK) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+/**
+ * \brief Set the prescaler for the Coprocessor Master Clock.
+ *
+ * \param ul_pres Prescaler value.
+ */
+void pmc_cpck_set_prescaler(uint32_t ul_pres)
+{
+       PMC->PMC_MCKR =
+                       (PMC->PMC_MCKR & (~PMC_MCKR_CPPRES_Msk)) | PMC_MCKR_CPPRES(ul_pres);
+}
+
+/**
+ * \brief Set the source for the Coprocessor Master Clock.
+ *
+ * \param ul_source Source selection value.
+ */
+void pmc_cpck_set_source(uint32_t ul_source)
+{
+       PMC->PMC_MCKR =
+                       (PMC->PMC_MCKR & (~PMC_MCKR_CPCSS_Msk)) | ul_source;
+}
+#endif
+
+#if (SAM3S || SAM3XA || SAM4S || SAM4E)
+/**
+ * \brief Switch UDP (USB) clock source selection to PLLA clock.
+ *
+ * \param ul_usbdiv Clock divisor.
+ */
+void pmc_switch_udpck_to_pllack(uint32_t ul_usbdiv)
+{
+       PMC->PMC_USB = PMC_USB_USBDIV(ul_usbdiv);
+}
+#endif
+
+#if (SAM3S || SAM4S)
+/**
+ * \brief Switch UDP (USB) clock source selection to PLLB clock.
+ *
+ * \param ul_usbdiv Clock divisor.
+ */
+void pmc_switch_udpck_to_pllbck(uint32_t ul_usbdiv)
+{
+       PMC->PMC_USB = PMC_USB_USBDIV(ul_usbdiv) | PMC_USB_USBS;
+}
+#endif
+
+#if (SAM3XA)
+/**
+ * \brief Switch UDP (USB) clock source selection to UPLL clock.
+ *
+ * \param ul_usbdiv Clock divisor.
+ */
+void pmc_switch_udpck_to_upllck(uint32_t ul_usbdiv)
+{
+       PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(ul_usbdiv);
+}
+#endif
+
+#if (SAM3S || SAM3XA || SAM4S || SAM4E)
+/**
+ * \brief Enable UDP (USB) clock.
+ */
+void pmc_enable_udpck(void)
+{
+# if (SAM3S || SAM4S || SAM4E)
+       PMC->PMC_SCER = PMC_SCER_UDP;
+# else
+       PMC->PMC_SCER = PMC_SCER_UOTGCLK;
+# endif
+}
+
+/**
+ * \brief Disable UDP (USB) clock.
+ */
+void pmc_disable_udpck(void)
+{
+# if (SAM3S || SAM4S || SAM4E)
+       PMC->PMC_SCDR = PMC_SCDR_UDP;
+# else
+       PMC->PMC_SCDR = PMC_SCDR_UOTGCLK;
+# endif
+}
+#endif
+
+/**
+ * \brief Enable PMC interrupts.
+ *
+ * \param ul_sources Interrupt sources bit map.
+ */
+void pmc_enable_interrupt(uint32_t ul_sources)
+{
+       PMC->PMC_IER = ul_sources;
+}
+
+/**
+ * \brief Disable PMC interrupts.
+ *
+ * \param ul_sources Interrupt sources bit map.
+ */
+void pmc_disable_interrupt(uint32_t ul_sources)
+{
+       PMC->PMC_IDR = ul_sources;
+}
+
+/**
+ * \brief Get PMC interrupt mask.
+ *
+ * \return The interrupt mask value.
+ */
+uint32_t pmc_get_interrupt_mask(void)
+{
+       return PMC->PMC_IMR;
+}
+
+/**
+ * \brief Get current status.
+ *
+ * \return The current PMC status.
+ */
+uint32_t pmc_get_status(void)
+{
+       return PMC->PMC_SR;
+}
+
+/**
+ * \brief Set the wake-up inputs for fast startup mode registers
+ *        (event generation).
+ *
+ * \param ul_inputs Wake up inputs to enable.
+ */
+void pmc_set_fast_startup_input(uint32_t ul_inputs)
+{
+       ul_inputs &= PMC_FAST_STARTUP_Msk;
+       PMC->PMC_FSMR |= ul_inputs;
+}
+
+/**
+ * \brief Clear the wake-up inputs for fast startup mode registers
+ *        (remove event generation).
+ *
+ * \param ul_inputs Wake up inputs to disable.
+ */
+void pmc_clr_fast_startup_input(uint32_t ul_inputs)
+{
+       ul_inputs &= PMC_FAST_STARTUP_Msk;
+       PMC->PMC_FSMR &= ~ul_inputs;
+}
+
+#if (SAM4C || SAM4CM || SAM4CP)
+/**
+ * \brief Set the wake-up inputs of coprocessor for fast startup mode registers
+ *        (event generation).
+ *
+ * \param ul_inputs Wake up inputs to enable.
+ */
+void pmc_cp_set_fast_startup_input(uint32_t ul_inputs)
+{
+       ul_inputs &= PMC_FAST_STARTUP_Msk;
+       PMC->PMC_CPFSMR |= ul_inputs;
+}
+
+/**
+ * \brief Clear the wake-up inputs of coprocessor for fast startup mode registers
+ *        (remove event generation).
+ *
+ * \param ul_inputs Wake up inputs to disable.
+ */
+void pmc_cp_clr_fast_startup_input(uint32_t ul_inputs)
+{
+       ul_inputs &= PMC_FAST_STARTUP_Msk;
+       PMC->PMC_CPFSMR &= ~ul_inputs;
+}
+#endif
+
+#if (!SAMG)
+/**
+ * \brief Enable Sleep Mode.
+ * Enter condition: (WFE or WFI) + (SLEEPDEEP bit = 0) + (LPM bit = 0)
+ *
+ * \param uc_type 0 for wait for interrupt, 1 for wait for event.
+ * \note For SAM4S, SAM4C, SAM4CM, SAM4CP and SAM4E series,
+ * since only WFI is effective, uc_type = 1 will be treated as uc_type = 0.
+ */
+void pmc_enable_sleepmode(uint8_t uc_type)
+{
+#if !(SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAM4CP)
+       PMC->PMC_FSMR &= (uint32_t) ~ PMC_FSMR_LPM; // Enter Sleep mode
+#endif
+       SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk; // Deep sleep
+
+#if (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAM4CP)
+       UNUSED(uc_type);
+       __WFI();
+#else
+       if (uc_type == 0) {
+               __WFI();
+       } else {
+               __WFE();
+       }
+#endif
+}
+#endif
+
+#if (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAMG || SAM4CP)
+static uint32_t ul_flash_in_wait_mode = PMC_WAIT_MODE_FLASH_DEEP_POWERDOWN;
+/**
+ * \brief Set the embedded flash state in wait mode
+ *
+ * \param ul_flash_state PMC_WAIT_MODE_FLASH_STANDBY flash in standby mode,
+ * PMC_WAIT_MODE_FLASH_DEEP_POWERDOWN flash in deep power down mode.
+ */
+void pmc_set_flash_in_wait_mode(uint32_t ul_flash_state)
+{
+       ul_flash_in_wait_mode = ul_flash_state;
+}
+
+/**
+ * \brief Enable Wait Mode. Enter condition: (WAITMODE bit = 1) +
+ * (SLEEPDEEP bit = 0) + FLPM
+ *
+ * \note In this function the FWS is reset to 0 to get best flash access
+ * performance while running on fast wake up RC clock. Make sure the
+ * non-zero FWS value is saved before invoking this function, and restored
+ * after system woken up, to avoid flash access error.
+ * See \ref pmc_sleep() for entering different sleep modes.
+ */
+void pmc_enable_waitmode(void)
+{
+       uint32_t i;
+
+       /* Flash in wait mode */
+       i = PMC->PMC_FSMR;
+       i &= ~PMC_FSMR_FLPM_Msk;
+       i |= ul_flash_in_wait_mode;
+       PMC->PMC_FSMR = i;
+
+       /* Clear SLEEPDEEP bit */
+       SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk;
+
+       /* Set the WAITMODE bit = 1 */
+       PMC->CKGR_MOR |= CKGR_MOR_KEY_PASSWD | CKGR_MOR_WAITMODE;
+
+       /* Waiting for Master Clock Ready MCKRDY = 1 */
+       while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
+
+       /* Waiting for MOSCRCEN bit cleared is strongly recommended
+        * to ensure that the core will not execute undesired instructions
+        */
+       for (i = 0; i < 500; i++) {
+               __NOP();
+       }
+       while (!(PMC->CKGR_MOR & CKGR_MOR_MOSCRCEN));
+
+#if (!SAMG)
+       /* Restore Flash in idle mode */
+       i = PMC->PMC_FSMR;
+       i &= ~PMC_FSMR_FLPM_Msk;
+       i |= PMC_WAIT_MODE_FLASH_IDLE;
+       PMC->PMC_FSMR = i;
+#endif
+}
+#else
+/**
+ * \brief Enable Wait Mode. Enter condition: WFE + (SLEEPDEEP bit = 0) +
+ * (LPM bit = 1)
+ */
+void pmc_enable_waitmode(void)
+{
+       uint32_t i;
+
+       PMC->PMC_FSMR |= PMC_FSMR_LPM; /* Enter Wait mode */
+       SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk; /* Deep sleep */
+
+       __WFE();
+
+       /* Waiting for MOSCRCEN bit cleared is strongly recommended
+        * to ensure that the core will not execute undesired instructions
+        */
+       for (i = 0; i < 500; i++) {
+               __NOP();
+       }
+       while (!(PMC->CKGR_MOR & CKGR_MOR_MOSCRCEN));
+
+}
+#endif
+
+#if (!SAMG)
+/**
+ * \brief Enable Backup Mode. Enter condition: WFE/(VROFF bit = 1) +
+ * (SLEEPDEEP bit = 1)
+ */
+void pmc_enable_backupmode(void)
+{
+#if (SAM4C || SAM4CM || SAM4CP)
+       uint32_t tmp = SUPC->SUPC_MR & ~(SUPC_MR_BUPPOREN | SUPC_MR_KEY_Msk);
+       SUPC->SUPC_MR = tmp | SUPC_MR_KEY_PASSWD;
+       while (SUPC->SUPC_SR & SUPC_SR_BUPPORS);
+#endif
+       SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
+#if (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAM4CP)
+       SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_VROFF_STOP_VREG;
+       __WFE();
+       __WFI();
+#else
+       __WFE();
+#endif
+}
+#endif
+
+/**
+ * \brief Enable Clock Failure Detector.
+ */
+void pmc_enable_clock_failure_detector(void)
+{
+       uint32_t ul_reg = PMC->CKGR_MOR;
+
+       PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | CKGR_MOR_CFDEN | ul_reg;
+}
+
+/**
+ * \brief Disable Clock Failure Detector.
+ */
+void pmc_disable_clock_failure_detector(void)
+{
+       uint32_t ul_reg = PMC->CKGR_MOR & (~CKGR_MOR_CFDEN);
+
+       PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | ul_reg;
+}
+
+#if (SAM4N || SAM4C || SAM4CM || SAM4CP)
+/**
+ * \brief Enable Slow Crystal Oscillator Frequency Monitoring.
+ */
+void pmc_enable_sclk_osc_freq_monitor(void)
+{
+       uint32_t ul_reg = PMC->CKGR_MOR;
+
+       PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | CKGR_MOR_XT32KFME | ul_reg;
+}
+
+/**
+ * \brief Disable Slow Crystal Oscillator Frequency Monitoring.
+ */
+void pmc_disable_sclk_osc_freq_monitor(void)
+{
+       uint32_t ul_reg = PMC->CKGR_MOR & (~CKGR_MOR_XT32KFME);
+
+       PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | ul_reg;
+}
+#endif
+
+/**
+ * \brief Enable or disable write protect of PMC registers.
+ *
+ * \param ul_enable 1 to enable, 0 to disable.
+ */
+void pmc_set_writeprotect(uint32_t ul_enable)
+{
+       if (ul_enable) {
+               PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD | PMC_WPMR_WPEN;
+       } else {
+               PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD;
+       }
+}
+
+/**
+ * \brief Return write protect status.
+ *
+ * \retval 0 Protection disabled.
+ * \retval 1 Protection enabled.
+ */
+uint32_t pmc_get_writeprotect_status(void)
+{
+       return PMC->PMC_WPMR & PMC_WPMR_WPEN;
+}
+
+#if (SAMG53 || SAMG54)
+/**
+ * \brief Enable the specified peripheral clock.
+ *
+ * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).
+ *
+ * \param ul_id Peripheral ID (ID_xxx).
+ *
+ * \retval 0 Success.
+ * \retval 1 Fail.
+ */
+uint32_t pmc_enable_sleepwalking(uint32_t ul_id)
+{
+       uint32_t temp;
+
+       if ((8 <= ul_id) && (ul_id<= 29)) {
+               temp = pmc_get_active_status();
+               if (temp & (1 << ul_id)) {
+                       return 1;
+               }
+               PMC->PMC_SLPWK_ER0 = 1 << ul_id;
+               temp = pmc_get_active_status();
+               if (temp & (1 << ul_id)) {
+                       pmc_disable_sleepwalking(ul_id);
+                       return 1;
+               }
+               return 0;
+       } else {
+               return 1;
+       }
+}
+
+/**
+ * \brief Disable the sleepwalking of specified peripheral.
+ *
+ * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).
+ *
+ * \param ul_id Peripheral ID (ID_xxx).
+ *
+ * \retval 0 Success.
+ * \retval 1 Invalid parameter.
+ */
+uint32_t pmc_disable_sleepwalking(uint32_t ul_id)
+{
+       if ((8 <= ul_id) && (ul_id<= 29)) {
+               PMC->PMC_SLPWK_DR0 = 1 << ul_id;
+               return 0;
+       } else {
+               return 1;
+       }
+}
+
+/**
+ * \brief Return peripheral sleepwalking enable status.
+ *
+ * \return the status register value.
+ */
+uint32_t pmc_get_sleepwalking_status(void)
+{
+       return PMC->PMC_SLPWK_SR0;
+}
+
+/**
+ * \brief Return peripheral active status.
+ *
+ * \return the status register value.
+ */
+uint32_t pmc_get_active_status(void)
+{
+       return PMC->PMC_SLPWK_ASR0;
+}
+
+#endif
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+}
+#endif
+/**INDENT-ON**/
+/// @endcond
diff --git a/asf/sam/drivers/pmc/pmc.h b/asf/sam/drivers/pmc/pmc.h
new file mode 100644 (file)
index 0000000..75cd323
--- /dev/null
@@ -0,0 +1,524 @@
+/**
+ * \file
+ *
+ * \brief Power Management Controller (PMC) driver for SAM.
+ *
+ * Copyright (c) 2011 - 2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#ifndef PMC_H_INCLUDED
+#define PMC_H_INCLUDED
+
+#include "compiler.h"
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+/** Bit mask for peripheral clocks (PCER0) */
+#define PMC_MASK_STATUS0        (0xFFFFFFFC)
+
+/** Bit mask for peripheral clocks (PCER1) */
+#define PMC_MASK_STATUS1        (0xFFFFFFFF)
+
+/** Loop counter timeout value */
+#define PMC_TIMEOUT             (2048)
+
+/** Key to unlock CKGR_MOR register */
+#ifndef CKGR_MOR_KEY_PASSWD
+#define CKGR_MOR_KEY_PASSWD    CKGR_MOR_KEY(0x37U)
+#endif
+
+/** Key used to write SUPC registers */
+#ifndef SUPC_CR_KEY_PASSWD
+#define SUPC_CR_KEY_PASSWD    SUPC_CR_KEY(0xA5U)
+#endif
+
+#ifndef SUPC_MR_KEY_PASSWD
+#define SUPC_MR_KEY_PASSWD    SUPC_MR_KEY(0xA5U)
+#endif
+
+/** Mask to access fast startup input */
+#define PMC_FAST_STARTUP_Msk    (0x7FFFFu)
+
+/** PMC_WPMR Write Protect KEY, unlock it */
+#ifndef PMC_WPMR_WPKEY_PASSWD
+#define PMC_WPMR_WPKEY_PASSWD    PMC_WPMR_WPKEY((uint32_t) 0x504D43)
+#endif
+
+/** Using external oscillator */
+#define PMC_OSC_XTAL            0
+
+/** Oscillator in bypass mode */
+#define PMC_OSC_BYPASS          1
+
+#define PMC_PCK_0               0 /* PCK0 ID */
+#define PMC_PCK_1               1 /* PCK1 ID */
+#define PMC_PCK_2               2 /* PCK2 ID */
+
+#if (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAMG || SAM4CP)
+/** Flash state in Wait Mode */
+#define PMC_WAIT_MODE_FLASH_STANDBY         PMC_FSMR_FLPM_FLASH_STANDBY
+#define PMC_WAIT_MODE_FLASH_DEEP_POWERDOWN  PMC_FSMR_FLPM_FLASH_DEEP_POWERDOWN
+#define PMC_WAIT_MODE_FLASH_IDLE            PMC_FSMR_FLPM_FLASH_IDLE
+#endif
+
+/** Convert startup time from us to MOSCXTST */
+#define pmc_us_to_moscxtst(startup_us, slowck_freq)      \
+       ((startup_us * slowck_freq / 8 / 1000000) < 0x100 ?  \
+               (startup_us * slowck_freq / 8 / 1000000) : 0xFF)
+
+/**
+ * \name Master clock (MCK) Source and Prescaler configuration
+ *
+ * \note The following functions may be used to select the clock source and
+ * prescaler for the master clock.
+ */
+//@{
+
+void pmc_mck_set_prescaler(uint32_t ul_pres);
+void pmc_mck_set_source(uint32_t ul_source);
+uint32_t pmc_switch_mck_to_sclk(uint32_t ul_pres);
+uint32_t pmc_switch_mck_to_mainck(uint32_t ul_pres);
+uint32_t pmc_switch_mck_to_pllack(uint32_t ul_pres);
+#if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)
+uint32_t pmc_switch_mck_to_pllbck(uint32_t ul_pres);
+#endif
+#if (SAM3XA || SAM3U)
+uint32_t pmc_switch_mck_to_upllck(uint32_t ul_pres);
+#endif
+#if (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAMG || SAM4CP)
+void pmc_set_flash_in_wait_mode(uint32_t ul_flash_state);
+#endif
+
+
+//@}
+
+/**
+ * \name Slow clock (SLCK) oscillator and configuration
+ *
+ */
+//@{
+
+void pmc_switch_sclk_to_32kxtal(uint32_t ul_bypass);
+uint32_t pmc_osc_is_ready_32kxtal(void);
+
+//@}
+
+/**
+ * \name Main Clock (MAINCK) oscillator and configuration
+ *
+ */
+//@{
+
+void pmc_switch_mainck_to_fastrc(uint32_t ul_moscrcf);
+void pmc_osc_enable_fastrc(uint32_t ul_rc);
+void pmc_osc_disable_fastrc(void);
+uint32_t pmc_osc_is_ready_fastrc(void);
+void pmc_osc_enable_main_xtal(uint32_t ul_xtal_startup_time);
+void pmc_osc_bypass_main_xtal(void);
+void pmc_osc_disable_main_xtal(void);
+uint32_t pmc_osc_is_bypassed_main_xtal(void);
+uint32_t pmc_osc_is_ready_main_xtal(void);
+void pmc_switch_mainck_to_xtal(uint32_t ul_bypass,
+               uint32_t ul_xtal_startup_time);
+void pmc_osc_disable_xtal(uint32_t ul_bypass);
+uint32_t pmc_osc_is_ready_mainck(void);
+void pmc_mainck_osc_select(uint32_t ul_xtal_rc);
+
+//@}
+
+/**
+ * \name PLL oscillator and configuration
+ *
+ */
+//@{
+
+void pmc_enable_pllack(uint32_t mula, uint32_t pllacount, uint32_t diva);
+void pmc_disable_pllack(void);
+uint32_t pmc_is_locked_pllack(void);
+
+#if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)
+void pmc_enable_pllbck(uint32_t mulb, uint32_t pllbcount, uint32_t divb);
+void pmc_disable_pllbck(void);
+uint32_t pmc_is_locked_pllbck(void);
+#endif
+
+#if (SAM3XA || SAM3U)
+void pmc_enable_upll_clock(void);
+void pmc_disable_upll_clock(void);
+uint32_t pmc_is_locked_upll(void);
+#endif
+
+//@}
+
+/**
+ * \name Peripherals clock configuration
+ *
+ */
+//@{
+
+uint32_t pmc_enable_periph_clk(uint32_t ul_id);
+uint32_t pmc_disable_periph_clk(uint32_t ul_id);
+void pmc_enable_all_periph_clk(void);
+void pmc_disable_all_periph_clk(void);
+uint32_t pmc_is_periph_clk_enabled(uint32_t ul_id);
+
+//@}
+
+/**
+ * \name Programmable clock Source and Prescaler configuration
+ *
+ * The following functions may be used to select the clock source and
+ * prescaler for the specified programmable clock.
+ */
+//@{
+
+void pmc_pck_set_prescaler(uint32_t ul_id, uint32_t ul_pres);
+void pmc_pck_set_source(uint32_t ul_id, uint32_t ul_source);
+uint32_t pmc_switch_pck_to_sclk(uint32_t ul_id, uint32_t ul_pres);
+uint32_t pmc_switch_pck_to_mainck(uint32_t ul_id, uint32_t ul_pres);
+uint32_t pmc_switch_pck_to_pllack(uint32_t ul_id, uint32_t ul_pres);
+#if (SAM4C || SAM4CM || SAM4CP)
+void pmc_enable_cpck(void);
+void pmc_disable_cpck(void);
+bool pmc_is_cpck_enabled(void);
+void pmc_enable_cpbmck(void);
+void pmc_disable_cpbmck(void);
+bool pmc_is_cpbmck_enabled(void);
+void pmc_cpck_set_prescaler(uint32_t ul_pres);
+void pmc_cpck_set_source(uint32_t ul_source);
+#endif
+#if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)
+uint32_t pmc_switch_pck_to_pllbck(uint32_t ul_id, uint32_t ul_pres);
+#endif
+#if (SAM3XA || SAM3U)
+uint32_t pmc_switch_pck_to_upllck(uint32_t ul_id, uint32_t ul_pres);
+#endif
+void pmc_enable_pck(uint32_t ul_id);
+void pmc_disable_pck(uint32_t ul_id);
+void pmc_enable_all_pck(void);
+void pmc_disable_all_pck(void);
+uint32_t pmc_is_pck_enabled(uint32_t ul_id);
+
+//@}
+
+/**
+ * \name USB clock configuration
+ *
+ */
+//@{
+
+#if (SAM3S || SAM3XA || SAM4S || SAM4E)
+void pmc_switch_udpck_to_pllack(uint32_t ul_usbdiv);
+#endif
+#if (SAM3S || SAM4S)
+void pmc_switch_udpck_to_pllbck(uint32_t ul_usbdiv);
+#endif
+#if (SAM3XA)
+void pmc_switch_udpck_to_upllck(uint32_t ul_usbdiv);
+#endif
+#if (SAM3S || SAM3XA || SAM4S || SAM4E)
+void pmc_enable_udpck(void);
+void pmc_disable_udpck(void);
+#endif
+
+//@}
+
+/**
+ * \name Interrupt and status management
+ *
+ */
+//@{
+
+void pmc_enable_interrupt(uint32_t ul_sources);
+void pmc_disable_interrupt(uint32_t ul_sources);
+uint32_t pmc_get_interrupt_mask(void);
+uint32_t pmc_get_status(void);
+
+//@}
+
+/**
+ * \name Power management
+ *
+ * The following functions are used to configure sleep mode and additional
+ * wake up inputs.
+ */
+//@{
+
+void pmc_set_fast_startup_input(uint32_t ul_inputs);
+void pmc_clr_fast_startup_input(uint32_t ul_inputs);
+#if (SAM4C || SAM4CM || SAM4CP)
+void pmc_cp_set_fast_startup_input(uint32_t ul_inputs);
+void pmc_cp_clr_fast_startup_input(uint32_t ul_inputs);
+#endif
+#if (!SAMG)
+void pmc_enable_sleepmode(uint8_t uc_type);
+#endif
+void pmc_enable_waitmode(void);
+#if (!SAMG)
+void pmc_enable_backupmode(void);
+#endif
+//@}
+
+/**
+ * \name Failure detector
+ *
+ */
+//@{
+
+void pmc_enable_clock_failure_detector(void);
+void pmc_disable_clock_failure_detector(void);
+
+//@}
+
+#if (SAM4N || SAM4C || SAM4CM || SAM4CP)
+/**
+ * \name Slow Crystal Oscillator Frequency Monitoring
+ *
+ */
+//@{
+
+void pmc_enable_sclk_osc_freq_monitor(void);
+void pmc_disable_sclk_osc_freq_monitor(void);
+
+//@}
+#endif
+
+/**
+ * \name Write protection
+ *
+ */
+//@{
+
+void pmc_set_writeprotect(uint32_t ul_enable);
+uint32_t pmc_get_writeprotect_status(void);
+
+//@}
+
+#if (SAMG53 || SAMG54)
+/**
+ * \name Sleepwalking configuration
+ *
+ */
+//@{
+
+uint32_t pmc_enable_sleepwalking(uint32_t ul_id);
+uint32_t pmc_disable_sleepwalking(uint32_t ul_id);
+uint32_t pmc_get_sleepwalking_status(void);
+uint32_t pmc_get_active_status(void);
+
+//@}
+#endif
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+}
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+//! @}
+
+/**
+ * \page sam_pmc_quickstart Quick start guide for the SAM PMC module
+ *
+ * This is the quick start guide for the \ref sam_drivers_pmc_group "PMC module",
+ * with step-by-step instructions on how to configure and use the driver in a
+ * selection of use cases.
+ *
+ * The use cases contain several code fragments. The code fragments in the
+ * steps for setup can be copied into a custom initialization function, while
+ * the steps for usage can be copied into, e.g., the main application function.
+ *
+ * \section pmc_use_cases PMC use cases
+ * - \ref pmc_basic_use_case Basic use case - Switch Main Clock sources
+ * - \ref pmc_use_case_2 Advanced use case - Configure Programmable Clocks
+ *
+ * \section pmc_basic_use_case Basic use case - Switch Main Clock sources
+ * In this use case, the PMC module is configured for a variety of system clock
+ * sources and speeds. A LED is used to visually indicate the current clock
+ * speed as the source is switched.
+ *
+ * \section pmc_basic_use_case_setup Setup
+ *
+ * \subsection pmc_basic_use_case_setup_prereq Prerequisites
+ * -# \ref gpio_group "General Purpose I/O Management (gpio)"
+ *
+ * \subsection pmc_basic_use_case_setup_code Code
+ * The following function needs to be added to the user application, to flash a
+ * board LED a variable number of times at a rate given in CPU ticks.
+ *
+ * \code
+        #define FLASH_TICK_COUNT   0x00012345
+
+        void flash_led(uint32_t tick_count, uint8_t flash_count)
+        {
+            SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
+            SysTick->LOAD = tick_count;
+
+            while (flash_count--)
+            {
+                gpio_toggle_pin(LED0_GPIO);
+                while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
+                gpio_toggle_pin(LED0_GPIO);
+                while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
+            }
+        }
+\endcode
+ *
+ * \section pmc_basic_use_case_usage Use case
+ *
+ * \subsection pmc_basic_use_case_usage_code Example code
+ * Add to application C-file:
+ * \code
+       for (;;)
+       {
+           pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_12_MHz);
+           flash_led(FLASH_TICK_COUNT, 5);
+           pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_8_MHz);
+           flash_led(FLASH_TICK_COUNT, 5);
+           pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_4_MHz);
+           flash_led(FLASH_TICK_COUNT, 5);
+           pmc_switch_mainck_to_xtal(0);
+           flash_led(FLASH_TICK_COUNT, 5);
+       }
+\endcode
+ *
+ * \subsection pmc_basic_use_case_usage_flow Workflow
+ * -# Wrap the code in an infinite loop:
+ *   \code
+       for (;;)
+\endcode
+ * -# Switch the Master CPU frequency to the internal 12MHz RC oscillator, flash
+ *    a LED on the board several times:
+ *   \code
+       pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_12_MHz);
+       flash_led(FLASH_TICK_COUNT, 5);
+\endcode
+ * -# Switch the Master CPU frequency to the internal 8MHz RC oscillator, flash
+ *    a LED on the board several times:
+ *   \code
+       pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_8_MHz);
+       flash_led(FLASH_TICK_COUNT, 5);
+\endcode
+ * -# Switch the Master CPU frequency to the internal 4MHz RC oscillator, flash
+ *    a LED on the board several times:
+ *   \code
+       pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_4_MHz);
+       flash_led(FLASH_TICK_COUNT, 5);
+\endcode
+ * -# Switch the Master CPU frequency to the external crystal oscillator, flash
+ *    a LED on the board several times:
+ *   \code
+       pmc_switch_mainck_to_xtal(0, BOARD_OSC_STARTUP_US);
+       flash_led(FLASH_TICK_COUNT, 5);
+\endcode
+ *
+ * \section pmc_use_case_2 Use case #2 - Configure Programmable Clocks
+ * In this use case, the PMC module is configured to start the Slow Clock from
+ * an attached 32KHz crystal, and start one of the Programmable Clock modules
+ * sourced from the Slow Clock divided down with a prescale factor of 64.
+ *
+ * \section pmc_use_case_2_setup Setup
+ *
+ * \subsection pmc_use_case_2_setup_prereq Prerequisites
+ * -# \ref pio_group "Parallel Input/Output Controller (pio)"
+ *
+ * \subsection pmc_use_case_2_setup_code Code
+ * The following code must be added to the user application:
+ * \code
+       pio_set_peripheral(PIOA, PIO_PERIPH_B, PIO_PA17);
+\endcode
+ *
+ * \subsection pmc_use_case_2_setup_code_workflow Workflow
+ * -# Configure the PCK1 pin to output on a specific port pin (in this case,
+ *    PIOA pin 17) of the microcontroller.
+ *   \code
+       pio_set_peripheral(PIOA, PIO_PERIPH_B, PIO_PA17);
+\endcode
+ *   \note The peripheral selection and pin will vary according to your selected
+ *       SAM device model. Refer to the "Peripheral Signal Multiplexing on I/O
+ *       Lines" of your device's datasheet.
+ *
+ * \section pmc_use_case_2_usage Use case
+ * The generated PCK1 clock output can be viewed on an oscilloscope attached to
+ * the correct pin of the microcontroller.
+ *
+ * \subsection pmc_use_case_2_usage_code Example code
+ * Add to application C-file:
+ * \code
+         pmc_switch_sclk_to_32kxtal(PMC_OSC_XTAL);
+         pmc_switch_pck_to_sclk(PMC_PCK_1, PMC_PCK_PRES_CLK_64);
+         pmc_enable_pck(PMC_PCK_1);
+
+         for (;;)
+         {
+             // Do Nothing
+         }
+\endcode
+ *
+ * \subsection pmc_use_case_2_usage_flow Workflow
+ * -# Switch the Slow Clock source input to an external 32KHz crystal:
+ *   \code
+       pmc_switch_sclk_to_32kxtal(PMC_OSC_XTAL);
+\endcode
+ * -# Switch the Programmable Clock module PCK1 source clock to the Slow Clock,
+ *    with a prescaler of 64:
+ *   \code
+       pmc_switch_pck_to_sclk(PMC_PCK_1, PMC_PCK_PRES_CLK_64);
+\endcode
+ * -# Enable Programmable Clock module PCK1:
+ *   \code
+       pmc_enable_pck(PMC_PCK_1);
+\endcode
+ * -# Enter an infinite loop:
+ *   \code
+       for (;;)
+       {
+          // Do Nothing
+       }
+\endcode
+ */
+
+#endif /* PMC_H_INCLUDED */
diff --git a/asf/sam/drivers/pwm/pwm.c b/asf/sam/drivers/pwm/pwm.c
new file mode 100644 (file)
index 0000000..a726827
--- /dev/null
@@ -0,0 +1,1108 @@
+/**
+ * \file
+ *
+ * \brief Pulse Width Modulation (PWM) driver for SAM.
+ *
+ * Copyright (c) 2011-2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#include "pwm.h"
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+/**
+ * \defgroup sam_drivers_pwm_group Pulse Width Modulation (PWM)
+ *
+ * See \ref sam_pwm_quickstart.
+ *
+ * Driver for the PWM (Pulse Width Modulation). This driver provides access to the
+ * main features of the PWM controller.
+ *
+ * @{
+ */
+
+#ifndef PWM_WPCR_WPKEY_PASSWD
+#  define PWM_WPCR_WPKEY_PASSWD 0x50574D00
+#endif
+
+#ifndef PWM_WPCR_WPCMD_DISABLE_SW_PROT
+#  define PWM_WPCR_WPCMD_DISABLE_SW_PROT (PWM_WPCR_WPCMD(0))
+#endif
+
+#ifndef PWM_WPCR_WPCMD_ENABLE_SW_PROT
+#  define PWM_WPCR_WPCMD_ENABLE_SW_PROT (PWM_WPCR_WPCMD(1))
+#endif
+
+#ifndef PWM_WPCR_WPCMD_ENABLE_HW_PROT
+#  define PWM_WPCR_WPCMD_ENABLE_HW_PROT (PWM_WPCR_WPCMD(2))
+#endif
+
+#define PWM_CLOCK_DIV_MAX  256
+#define PWM_CLOCK_PRE_MAX  11
+
+/**
+ * \brief Find a prescaler/divisor couple to generate the desired ul_frequency
+ * from ul_mck.
+ *
+ * \param ul_frequency Desired frequency in Hz.
+ * \param ul_mck Master clock frequency in Hz.
+ *
+ * \retval Return the value to be set in the PWM Clock Register (PWM Mode Register for
+ * SAM3N/SAM4N/SAM4C/SAM4CP/SAM4CM) or PWM_INVALID_ARGUMENT if the configuration cannot be met.
+ */
+static uint32_t pwm_clocks_generate(uint32_t ul_frequency, uint32_t ul_mck)
+{
+       uint32_t ul_divisors[PWM_CLOCK_PRE_MAX] =
+                       {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 };
+       uint32_t ul_pre = 0;
+       uint32_t ul_div;
+
+       /* Find prescaler and divisor values */
+       do {
+               ul_div = (ul_mck / ul_divisors[ul_pre]) / ul_frequency;
+               if (ul_div <= PWM_CLOCK_DIV_MAX) {
+                       break;
+               }
+               ul_pre++;
+       } while (ul_pre < PWM_CLOCK_PRE_MAX);
+
+       /* Return result */
+       if (ul_pre < PWM_CLOCK_PRE_MAX) {
+               return ul_div | (ul_pre << 8);
+       } else {
+               return PWM_INVALID_ARGUMENT;
+       }
+}
+
+/**
+ * \brief Initialize the PWM source clock (clock A and clock B).
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param clock_config PWM clock configuration.
+ *
+ * \retval 0 if initialization succeeds, otherwise fails.
+ */
+uint32_t pwm_init(Pwm *p_pwm, pwm_clock_t *clock_config)
+{
+       uint32_t clock = 0;
+       uint32_t result;
+
+       /* Clock A */
+       if (clock_config->ul_clka != 0) {
+               result = pwm_clocks_generate(clock_config->ul_clka, clock_config->ul_mck);
+               if (result == PWM_INVALID_ARGUMENT) {
+                       return result;
+               }
+
+               clock = result;
+       }
+
+       /* Clock B */
+       if (clock_config->ul_clkb != 0) {
+               result = pwm_clocks_generate(clock_config->ul_clkb, clock_config->ul_mck);
+
+               if (result == PWM_INVALID_ARGUMENT) {
+                       return result;
+               }
+
+               clock |= (result << 16);
+       }
+#if (SAM3N || SAM4N || SAM4C || SAM4CP || SAM4CM)
+       p_pwm->PWM_MR = clock;
+#else
+       p_pwm->PWM_CLK = clock;
+#endif
+       return 0;
+}
+
+/**
+ * \brief Initialize one PWM channel.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param p_channel Configurations of the specified PWM channel.
+ *
+ * \retval 0 if initialization succeeds, otherwise fails.
+ */
+uint32_t pwm_channel_init(Pwm *p_pwm, pwm_channel_t *p_channel)
+{
+       uint32_t tmp_reg = 0;
+       uint32_t ch_num = p_channel->channel;
+
+       /* Channel Mode/Clock Register */
+       tmp_reg = (p_channel->ul_prescaler & 0xF) |
+                       (p_channel->polarity << 9) |
+#if (SAM3U || SAM3S || SAM3XA || SAM4S || SAM4E)
+                       (p_channel->counter_event) |
+                       (p_channel->b_deadtime_generator << 16) |
+                       (p_channel->b_pwmh_output_inverted << 17) |
+                       (p_channel->b_pwml_output_inverted << 18) |
+#endif
+                       (p_channel->alignment);
+       p_pwm->PWM_CH_NUM[ch_num].PWM_CMR = tmp_reg;
+
+       /* Channel Duty Cycle Register */
+       p_pwm->PWM_CH_NUM[ch_num].PWM_CDTY = p_channel->ul_duty;
+
+       /* Channel Period Register */
+       p_pwm->PWM_CH_NUM[ch_num].PWM_CPRD = p_channel->ul_period;
+       
+#if (SAM3U || SAM3S || SAM3XA || SAM4S || SAM4E)
+       /* Channel Dead Time Register */
+       if (p_channel->b_deadtime_generator) {
+               p_pwm->PWM_CH_NUM[ch_num].PWM_DT =
+                               PWM_DT_DTL(p_channel->
+                               us_deadtime_pwml) | PWM_DT_DTH(p_channel->
+                               us_deadtime_pwmh);
+       }
+
+       /* Output Selection Register */
+       tmp_reg  = p_pwm->PWM_OS & (~((PWM_OS_OSH0 | PWM_OS_OSL0) << ch_num));
+       tmp_reg |= ((p_channel->output_selection.b_override_pwmh) << ch_num) |
+                       (((p_channel->output_selection.b_override_pwml) << ch_num)
+                                       << 16);
+       p_pwm->PWM_OS = tmp_reg;
+
+       /* Output Override Value Register */
+       tmp_reg  = p_pwm->PWM_OOV & (~((PWM_OOV_OOVH0 | PWM_OOV_OOVL0) << ch_num));
+       tmp_reg |= ((p_channel->output_selection.override_level_pwmh) << ch_num) |
+                       (((p_channel->output_selection.override_level_pwml) << ch_num)
+                                       << 16);
+       p_pwm->PWM_OOV = tmp_reg;
+
+       /* Sync Channels Mode Register */
+       uint32_t channel = (1 << ch_num);
+       if (p_channel->b_sync_ch) {
+               p_pwm->PWM_SCM |= channel;
+       } else {
+               p_pwm->PWM_SCM &= ~((uint32_t) channel);
+       }
+
+       /* Fault Protection Value Register */
+#if (SAM4E)
+       if (p_channel->ul_fault_output_pwmh == PWM_HIGHZ) {
+               p_pwm->PWM_FPV2 |= (0x01 << ch_num);
+       } else {
+               p_pwm->PWM_FPV2 &= ~(0x01 << ch_num);
+               if (p_channel->ul_fault_output_pwmh == PWM_HIGH) {
+                       p_pwm->PWM_FPV1 |= (0x01 << ch_num);
+               } else {
+                       p_pwm->PWM_FPV1 &= (~(0x01 << ch_num));
+               }
+       }
+       if (p_channel->ul_fault_output_pwml == PWM_HIGHZ) {
+               p_pwm->PWM_FPV2 |= ((0x01 << ch_num) << 16);
+       } else {
+               p_pwm->PWM_FPV2 &= ~((0x01 << ch_num) << 16);
+               if (p_channel->ul_fault_output_pwml == PWM_HIGH) {
+                       p_pwm->PWM_FPV1 |= ((0x01 << ch_num) << 16);
+               } else {
+                       p_pwm->PWM_FPV1 &= (~((0x01 << ch_num) << 16));
+               }
+       }
+#else
+       if (p_channel->ul_fault_output_pwmh == PWM_HIGH) {
+               p_pwm->PWM_FPV |= (0x01 << ch_num);
+       } else {
+               p_pwm->PWM_FPV &= (~(0x01 << ch_num));
+       }
+       if (p_channel->ul_fault_output_pwml == PWM_HIGH) {
+               p_pwm->PWM_FPV |= ((0x01 << ch_num) << 16);
+       } else {
+               p_pwm->PWM_FPV &= (~((0x01 << ch_num) << 16));
+       }
+#endif
+       /* Fault Protection Enable Register */
+       uint32_t fault_enable_reg = 0;
+#if (SAM3XA)
+       if (ch_num < 4) {
+               ch_num *= 8;
+               fault_enable_reg = p_pwm->PWM_FPE1;
+               fault_enable_reg &= ~(0xFF << ch_num);
+               fault_enable_reg |= ((p_channel->fault_id) << ch_num);
+               p_pwm->PWM_FPE1 = fault_enable_reg;
+       } else {
+               ch_num -= 4;
+               ch_num *= 8;
+               fault_enable_reg = p_pwm->PWM_FPE2;
+               fault_enable_reg &= ~(0xFF << ch_num);
+               fault_enable_reg |= ((p_channel->fault_id) << ch_num);
+               p_pwm->PWM_FPE2 = fault_enable_reg;
+       }
+#endif
+
+#if (SAM3U || SAM3S || SAM4S || SAM4E)
+       ch_num *= 8;
+       fault_enable_reg = p_pwm->PWM_FPE;
+       fault_enable_reg &= ~(0xFF << ch_num);
+       fault_enable_reg |= ((p_channel->fault_id) << ch_num);
+       p_pwm->PWM_FPE = fault_enable_reg;
+#endif
+#endif
+
+#if SAM4E
+       if (!ch_num) {
+               if (p_channel->spread_spectrum_mode ==
+                               PWM_SPREAD_SPECTRUM_MODE_RANDOM) {
+                       p_pwm->PWM_SSPR = PWM_SSPR_SPRD(p_channel->ul_spread) |
+                                       PWM_SSPR_SPRDM;
+               } else {
+                       p_pwm->PWM_SSPR = PWM_SSPR_SPRD(p_channel->ul_spread);
+               }
+       }
+       p_pwm->PWM_CH_NUM_0X400[ch_num].PWM_CAE =
+                       PWM_CAE_ADEDGV(p_channel->ul_additional_edge) |
+                       p_channel->additional_edge_mode;
+#endif
+
+       return 0;
+}
+
+/**
+ * \brief Change the period of the PWM channel.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param p_channel Configurations of the specified PWM channel.
+ * \param ul_period New period value.
+ *
+ * \retval 0 if changing succeeds, otherwise fails.
+ */
+uint32_t pwm_channel_update_period(Pwm *p_pwm, pwm_channel_t *p_channel,
+               uint32_t ul_period)
+{
+       uint32_t ch_num = p_channel->channel;
+
+       /** Check parameter */
+       if (p_channel->ul_duty > ul_period) {
+               return PWM_INVALID_ARGUMENT;
+       } else {
+               /* Save new period value */
+               p_channel->ul_period = ul_period;
+
+#if (SAM3N || SAM4N || SAM4C || SAM4CP || SAM4CM)
+               /* Set CPD bit to change period value */
+               p_pwm->PWM_CH_NUM[ch_num].PWM_CMR |= PWM_CMR_CPD;
+
+               p_pwm->PWM_CH_NUM[ch_num].PWM_CUPD = ul_period;
+#else
+               p_pwm->PWM_CH_NUM[ch_num].PWM_CPRDUPD = ul_period;
+#endif
+       }
+
+       return 0;
+}
+
+/**
+ * \brief Change the duty cycle of the PWM channel.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param p_channel Configurations of the specified PWM channel.
+ * \param ul_duty New duty cycle value.
+ *
+ * \retval 0 if changing succeeds, otherwise fails.
+ */
+uint32_t pwm_channel_update_duty(Pwm *p_pwm, pwm_channel_t *p_channel,
+               uint32_t ul_duty)
+{
+       uint32_t ch_num = p_channel->channel;
+
+               /** Check parameter */
+       if (p_channel->ul_period < ul_duty) {
+               return PWM_INVALID_ARGUMENT;
+       } else {
+               /* Save new duty cycle value */
+               p_channel->ul_duty = ul_duty;
+
+#if (SAM3N || SAM4N || SAM4C || SAM4CP || SAM4CM)
+               /* Clear CPD bit to change duty cycle value */
+               uint32_t mode = p_pwm->PWM_CH_NUM[ch_num].PWM_CMR;
+               mode &= ~PWM_CMR_CPD;
+               p_pwm->PWM_CH_NUM[ch_num].PWM_CMR = mode;
+
+               p_pwm->PWM_CH_NUM[ch_num].PWM_CUPD = ul_duty;
+#else
+               p_pwm->PWM_CH_NUM[ch_num].PWM_CDTYUPD = ul_duty;
+#endif
+       }
+
+       return 0;
+}
+
+/**
+ * \brief Return channel counter value.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param p_channel Configurations of the specified PWM channel.
+ *
+ * \return channel Counter value.
+ */
+uint32_t pwm_channel_get_counter(Pwm *p_pwm, pwm_channel_t *p_channel)
+{
+       return p_pwm->PWM_CH_NUM[p_channel->channel].PWM_CCNT;
+}
+
+
+/**
+ * \brief Enable the PWM channel.
+ *
+ * \note The PWM channel should be initialized by pwm_channel_init() before it is enabled.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param ul_channel PWM channel number to enable.
+ */
+void pwm_channel_enable(Pwm *p_pwm, uint32_t ul_channel)
+{
+       p_pwm->PWM_ENA = (1 << ul_channel);
+}
+
+/**
+ * \brief Disable the PWM channel.
+ *
+ * \note A disabled PWM channel can be re-initialized using pwm_channel_init().
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param ul_channel PWM channel number to disable.
+ */
+void pwm_channel_disable(Pwm *p_pwm, uint32_t ul_channel)
+{
+       p_pwm->PWM_DIS = (1 << ul_channel);
+}
+
+
+/**
+ * \brief Check which PWM channel is enabled.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param p_channel Configurations of the specified PWM channel.
+ *
+ * \return Bitmask of enabled PWM channel(s).
+ */
+uint32_t pwm_channel_get_status(Pwm *p_pwm)
+{
+       return p_pwm->PWM_SR;
+}
+
+/**
+ * \brief Get channel counter event and fault protection trigger interrupt status.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ *
+ * \return Channel counter event and fault protection trigger interrupt status.
+ */
+uint32_t pwm_channel_get_interrupt_status(Pwm *p_pwm)
+{
+#if (SAM3N || SAM4N || SAM4C || SAM4CP || SAM4CM)
+       return p_pwm->PWM_ISR;
+#else
+       return p_pwm->PWM_ISR1;
+#endif
+}
+
+/**
+ * \brief Get channel counter event and fault protection trigger interrupt mask.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ *
+ * \return Channel counter event and fault protection trigger interrupt mask.
+ */
+uint32_t pwm_channel_get_interrupt_mask(Pwm *p_pwm)
+{
+#if (SAM3N || SAM4N || SAM4C || SAM4CP || SAM4CM)
+       return p_pwm->PWM_IMR;
+#else
+       return p_pwm->PWM_IMR1;
+#endif
+}
+
+/**
+ * \brief Enable the interrupt of a channel counter event and fault protection.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param ul_event Channel number to enable counter event interrupt.
+ * \param ul_fault Channel number to enable fault protection interrupt(ignored
+ * by SAM3N/SAM4N/SAM4C/SAM4CP/SAM4CM).
+ */
+void pwm_channel_enable_interrupt(Pwm *p_pwm, uint32_t ul_event,
+               uint32_t ul_fault)
+{
+#if (SAM3N || SAM4N || SAM4C || SAM4CP || SAM4CM)
+       p_pwm->PWM_IER = (1 << ul_event);
+       /* avoid Cppcheck Warning */
+       UNUSED(ul_fault);
+#else
+       p_pwm->PWM_IER1 = (1 << ul_event) | (1 << (ul_fault + 16));
+#endif
+}
+
+
+/**
+ * \brief Disable the interrupt of a channel counter event and fault protection.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param ul_event Bitmask of channel number to disable counter event interrupt.
+ * \param ul_fault Bitmask of channel number to disable fault protection
+ * interrupt(ignored by SAM3N/SAM4N/SAM4C/SAM4CP/SAM4CM).
+ */
+void pwm_channel_disable_interrupt(Pwm *p_pwm, uint32_t ul_event,
+               uint32_t ul_fault)
+{
+#if (SAM3N || SAM4N || SAM4C || SAM4CP || SAM4CM)
+       p_pwm->PWM_IDR = (1 << ul_event);
+       /* avoid Cppcheck Warning */
+       UNUSED(ul_fault);
+#else
+       p_pwm->PWM_IDR1 = (1 << ul_event) | (1 << (ul_fault + 16));
+#endif
+}
+
+
+#if (SAM3U || SAM3S || SAM3XA || SAM4S || SAM4E)
+/**
+ * \brief Change output selection of the PWM channel.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param p_channel Configurations of the specified PWM channel.
+ * \param p_output New PWM channel output selection.
+ * \param b_sync Boolean of changing of output selection. Set true to change the output synchronously (at the beginning of the next PWM period). Set false to change the output asynchronously (at the end of the execution of the function).
+ */
+void pwm_channel_update_output(Pwm *p_pwm, pwm_channel_t *p_channel,
+               pwm_output_t *p_output, bool b_sync)
+{
+       uint32_t ch_num = p_channel->channel;
+       uint32_t channel = (1 << ch_num);
+
+       bool override_pwmh = p_output->b_override_pwmh;
+       bool override_pwml = p_output->b_override_pwml;
+       uint32_t pwmh = p_output->override_level_pwmh;
+       uint32_t pwml = p_output->override_level_pwml;
+
+       /* Save new output configuration */
+       p_channel->output_selection.b_override_pwmh = override_pwmh;
+       p_channel->output_selection.b_override_pwml = override_pwml;
+       p_channel->output_selection.override_level_pwmh = (pwm_level_t) pwmh;
+       p_channel->output_selection.override_level_pwml = (pwm_level_t) pwml;
+
+       /* Change override output level */
+       uint32_t override_value = p_pwm->PWM_OOV;
+       override_value &= ~((PWM_OOV_OOVH0 | PWM_OOV_OOVL0) << ch_num);
+       override_value |= (((pwml << 16) | pwmh) << ch_num);
+       p_pwm->PWM_OOV = override_value;
+
+       /* Apply new output selection */
+       if (override_pwml && override_pwmh) {
+               b_sync ? (p_pwm->PWM_OSSUPD =
+                               (channel | (channel << 16))) : (p_pwm->PWM_OSS =
+                               (channel | (channel << 16)));
+       } else {
+               b_sync ? (p_pwm->PWM_OSCUPD =
+                               (channel | (channel << 16))) : (p_pwm->PWM_OSC =
+                               (channel | (channel << 16)));
+       }
+}
+
+/**
+ * \brief Change dead-time value for PWM outputs.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param p_channel Configurations of the specified PWM channel.
+ * \param us_deadtime_pwmh New dead-time value for PWMH output.
+ * \param us_deadtime_pwml New dead-time value for PWML output.
+ */
+void pwm_channel_update_dead_time(Pwm *p_pwm, pwm_channel_t *p_channel,
+               uint16_t us_deadtime_pwmh, uint16_t us_deadtime_pwml)
+{
+       /* Save new dead time value */
+       p_channel->us_deadtime_pwmh = us_deadtime_pwmh;
+       p_channel->us_deadtime_pwml = us_deadtime_pwml;
+
+       /* Write channel dead time update register */
+       p_pwm->PWM_CH_NUM[p_channel->channel].PWM_DTUPD =
+                       PWM_DTUPD_DTLUPD(us_deadtime_pwml) |
+                       PWM_DTUPD_DTHUPD(us_deadtime_pwmh);
+}
+
+
+
+/**
+ * \brief Initialize the behavior of a fault input.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param p_fault Configurations of a fault input.
+ *
+ * \retval 0 if configuration succeeds, otherwise fails.
+ */
+uint32_t pwm_fault_init(Pwm *p_pwm, pwm_fault_t *p_fault)
+{
+       uint32_t fault_id = p_fault->fault_id;
+       uint32_t fault_reg = p_pwm->PWM_FMR;
+
+       /** Polarity of fault input */
+       if (p_fault->polarity == PWM_HIGH) {
+               fault_reg |= fault_id;
+       } else {
+               fault_reg &= ~fault_id;
+       }
+       /** Boolean of clearing fault flag */
+       if (p_fault->b_clear) {
+               fault_reg |= (fault_id << 8);
+       } else {
+               fault_reg &= ~(fault_id << 8);
+       }
+       /** Boolean of fault filtering */
+       if (p_fault->b_filtered) {
+               fault_reg |= (fault_id << 16);
+       } else {
+               fault_reg &= ~(fault_id << 16);
+       }
+
+       p_pwm->PWM_FMR = fault_reg;
+
+       return 0;
+}
+
+/**
+ * \brief Get fault status.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ *
+ * \return Bitmask of IDs of all active faulty.
+ */
+uint32_t pwm_fault_get_status(Pwm *p_pwm)
+{
+       return ((p_pwm->PWM_FSR >> 8) & 0xFF);
+}
+
+/**
+ * \brief Get the level of a fault input.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param id Faulty ID.
+ *
+ * \return Level of the fault input.
+ */
+pwm_level_t pwm_fault_get_input_level(Pwm *p_pwm, pwm_fault_id_t id)
+{
+       uint32_t fault_status_reg = p_pwm->PWM_FSR;
+       fault_status_reg >>= id;
+
+       return ((fault_status_reg & 1) ? PWM_HIGH : PWM_LOW);
+}
+
+/**
+ * \brief Clear a fault input.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param id Faulty ID.
+ */
+void pwm_fault_clear_status(Pwm *p_pwm, pwm_fault_id_t id)
+{
+       p_pwm->PWM_FCR = id;
+}
+
+/**
+ * \brief Initialize PWM comparison unit.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param p_cmp Configurations of PWM comparison tagged by unit.
+ *
+ * \retval 0 if initialization succeeds, otherwise fails.
+ */
+uint32_t pwm_cmp_init(Pwm *p_pwm, pwm_cmp_t *p_cmp)
+{
+       uint32_t unit = p_cmp->unit;
+
+       p_pwm->PWM_CMP[unit].PWM_CMPV = PWM_CMPV_CV(p_cmp->ul_value) |
+                       (p_cmp->b_is_decrementing << 24);
+
+       p_pwm->PWM_CMP[unit].PWM_CMPM = PWM_CMPM_CTR(p_cmp->ul_trigger) |
+                       PWM_CMPM_CPR(p_cmp->ul_period) |
+                       PWM_CMPM_CUPR(p_cmp->ul_update_period);
+
+       /** Boolean of generating a match pulse */
+       if (p_cmp->b_pulse_on_line_0) {
+               p_pwm->PWM_ELMR[0] |= (1 << unit);
+       } else {
+               p_pwm->PWM_ELMR[0] &= ~((uint32_t) (1 << unit));
+       }
+       /** Boolean of generating a match pulse */
+       if (p_cmp->b_pulse_on_line_1) {
+               p_pwm->PWM_ELMR[1] |= (1 << unit);
+       } else {
+               p_pwm->PWM_ELMR[1] &= ~((uint32_t) (1 << unit));
+       }
+
+       /** Boolean of comparison enable */
+       if (p_cmp->b_enable) {
+               p_pwm->PWM_CMP[unit].PWM_CMPM |= PWM_CMPM_CEN;
+       } else {
+               p_pwm->PWM_CMP[unit].PWM_CMPM &= ~PWM_CMPM_CEN;
+       }
+
+       return 0;
+}
+
+
+/**
+ * \brief Change the setting of PWM comparison.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param p_cmp Configurations of PWM comparison tagged by unit.
+ *
+ * \retval 0 if changing succeeds, otherwise fails.
+ */
+uint32_t pwm_cmp_change_setting(Pwm *p_pwm, pwm_cmp_t *p_cmp)
+{
+       uint32_t unit = p_cmp->unit;
+
+       p_pwm->PWM_CMP[unit].PWM_CMPVUPD = PWM_CMPV_CV(p_cmp->ul_value) |
+                       (p_cmp->b_is_decrementing << 24);
+
+       p_pwm->PWM_CMP[unit].PWM_CMPMUPD = PWM_CMPM_CTR(p_cmp->ul_trigger) |
+                       PWM_CMPM_CPR(p_cmp->ul_period) |
+                       PWM_CMPM_CUPR(p_cmp->ul_update_period);
+
+       /** Boolean of generating a match pulse */
+       if (p_cmp->b_pulse_on_line_0) {
+               p_pwm->PWM_ELMR[0] |= (1 << unit);
+       } else {
+               p_pwm->PWM_ELMR[0] &= ~((uint32_t) (1 << unit));
+       }
+       /** Boolean of generating a match pulse */
+       if (p_cmp->b_pulse_on_line_1) {
+               p_pwm->PWM_ELMR[1] |= (1 << unit);
+       } else {
+               p_pwm->PWM_ELMR[1] &= ~((uint32_t) (1 << unit));
+       }
+
+       /** Boolean of comparison enable */
+       if (p_cmp->b_enable) {
+               p_pwm->PWM_CMP[unit].PWM_CMPMUPD |= PWM_CMPM_CEN;
+       } else {
+               p_pwm->PWM_CMP[unit].PWM_CMPMUPD &= ~PWM_CMPM_CEN;
+       }
+
+       return 0;
+}
+
+
+/**
+ * \brief Report the value of the comparison period counter.
+ *
+ * \param p_pwm        Pointer to a PWM instance.
+ * \param ul_cmp_unit PWM comparison unit number.
+ *
+ * \return Value of the comparison period counter.
+ */
+uint32_t pwm_cmp_get_period_counter(Pwm *p_pwm, uint32_t ul_cmp_unit)
+{
+       return (PWM_CMPM_CPRCNT(p_pwm->PWM_CMP[ul_cmp_unit].PWM_CMPM)
+                       >> PWM_CMPM_CPRCNT_Pos);
+}
+
+/**
+ * \brief Report the value of the comparison update period counter.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param ul_cmp_unit PWM comparison unit number.
+ *
+ * \return Value of the comparison update period counter.
+ */
+uint32_t pwm_cmp_get_update_counter(Pwm *p_pwm, uint32_t ul_cmp_unit)
+{
+       return (PWM_CMPM_CUPRCNT(p_pwm->PWM_CMP[ul_cmp_unit].PWM_CMPM)
+                       >> PWM_CMPM_CUPRCNT_Pos);
+}
+
+
+/**
+ * \brief Enable the interrupt of comparison.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param ul_sources Bitmask of comparison unit.
+ * \param type PWM_CMP_MATCH enables the match interrupt of the unit. PWM_CMP_UPDATE enables the update interrupt of the comparison unit.
+ */
+void pwm_cmp_enable_interrupt(Pwm *p_pwm, uint32_t ul_sources,
+               pwm_cmp_interrupt_t type)
+{
+       if (type == PWM_CMP_MATCH) {
+               p_pwm->PWM_IER2 = ((1 << ul_sources) << 8);
+       } else if (type == PWM_CMP_UPDATE) {
+               p_pwm->PWM_IER2 = ((1 << ul_sources) << 16);
+       } else {
+               /* Do Nothing */
+       }
+}
+
+
+/**
+ * \brief Disable the interrupt of comparison.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param ul_sources Bitmask of comparison unit.
+ * \param type PWM_CMP_MATCH disables the match interrupt of the unit. PWM_CMP_UPDATE disables the update interrupt of the comparison unit.
+ */
+void pwm_cmp_disable_interrupt(Pwm *p_pwm, uint32_t ul_sources,
+               pwm_cmp_interrupt_t type)
+{
+       if (type == PWM_CMP_MATCH) {
+               p_pwm->PWM_IDR2 = ((1 << ul_sources) << 8);
+       } else if (type == PWM_CMP_UPDATE) {
+               p_pwm->PWM_IDR2 = ((1 << ul_sources) << 16);
+       } else {
+               /* Do Nothing */
+       }
+}
+
+
+/**
+ * \brief Set PDC transfer request mode.
+ *
+ * \note If configure Synchronous channels update mode as 'PWM_SYNC_UPDATE_MODE_0' or 'PWM_SYNC_UPDATE_MODE_1' via pwm_sync_init(), ul_pdc_request will be ignored and PDC transfer request will never occur.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param request_mode PDC transfer request mode.
+ * \param ul_cmp_unit PWM comparison unit number for PDC transfer request.
+ */
+void pwm_pdc_set_request_mode(Pwm *p_pwm, pwm_pdc_request_mode_t request_mode,
+               uint32_t ul_cmp_unit)
+{
+       uint32_t sync_mode = p_pwm->PWM_SCM;
+
+       sync_mode &= ~(PWM_SCM_PTRCS_Msk | PWM_SCM_PTRM);
+       sync_mode |= (PWM_SCM_PTRCS(ul_cmp_unit) | request_mode);
+
+       p_pwm->PWM_SCM = sync_mode;
+}
+
+
+
+/**
+ * \brief Enable the interrupt of PDC transfer.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param ul_sources Bitmask of PWM PDC transfer interrupt sources.
+ */
+void pwm_pdc_enable_interrupt(Pwm *p_pwm, uint32_t ul_sources)
+{
+       p_pwm->PWM_IER2 = ul_sources;
+}
+
+/**
+ * \brief Disable the interrupt of PDC transfer.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param ul_sources Bitmask of PWM PDC transfer interrupt sources.
+ */
+void pwm_pdc_disable_interrupt(Pwm *p_pwm, uint32_t ul_sources)
+{
+       p_pwm->PWM_IDR2 = ul_sources;
+}
+
+/**
+ * \brief Initialize synchronous channels update mode and period.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param mode Synchronous channels update mode.
+ * \param ul_update_period Time between each update of the synchronous channels.
+ *
+ * \retval 0 if initialization succeeds, otherwise fails.
+ */
+uint32_t pwm_sync_init(Pwm *p_pwm, pwm_sync_update_mode_t mode,
+               uint32_t ul_update_period)
+{
+       uint32_t sync_mode = p_pwm->PWM_SCM;
+
+       sync_mode &= ~PWM_SCM_UPDM_Msk;
+       sync_mode |= mode;
+
+       p_pwm->PWM_SCM = sync_mode;
+
+       p_pwm->PWM_SCUP = PWM_SCUP_UPR(ul_update_period);
+
+       return 0;
+}
+
+/**
+ * \brief Unlock the update of synchronous channels.
+ *
+ * \note After unlock, synchronous channels will be updated at the next PWM period.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ */
+void pwm_sync_unlock_update(Pwm *p_pwm)
+{
+       p_pwm->PWM_SCUC = PWM_SCUC_UPDULOCK;
+}
+
+/**
+ * \brief Change the wanted time between each update of the synchronous channels.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param ul_update_period Time between each update of the synchronous channels.
+ */
+void pwm_sync_change_period(Pwm *p_pwm, uint32_t ul_update_period)
+{
+       p_pwm->PWM_SCUPUPD = PWM_SCUPUPD_UPRUPD(ul_update_period);
+}
+
+/**
+ * \brief Get the value of the synchronization update period counter.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ *
+ * \return Value of the synchronization update Period Counter.
+ */
+uint32_t pwm_sync_get_period_counter(Pwm *p_pwm)
+{
+       return PWM_SCUP_UPRCNT(p_pwm->PWM_SCUP);
+}
+
+/**
+ * \brief Enable the interrupt of synchronous channel.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param ul_sources Bitmask of PWM synchronous channels interrupt sources.
+ */
+void pwm_sync_enable_interrupt(Pwm *p_pwm, uint32_t ul_sources)
+{
+       p_pwm->PWM_IER2 = ul_sources;
+}
+
+/**
+ * \brief Disable the interrupt of synchronous channels.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param ul_sources Bitmask of PWM synchronous channels interrupt sources.
+ */
+void pwm_sync_disable_interrupt(Pwm *p_pwm, uint32_t ul_sources)
+{
+       p_pwm->PWM_IDR2 = ul_sources;
+}
+
+/**
+ * \brief Enable PWM write protect.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param ul_group Bitmask of PWM register group.
+ * \param b_sw Boolean of software protect. True for software protect and false for hardware protect.
+ */
+void pwm_enable_protect(Pwm *p_pwm, uint32_t ul_group, bool b_sw)
+{
+       uint32_t wp = 0;
+
+       if (b_sw) {
+               wp = PWM_WPCR_WPKEY_PASSWD | (ul_group << 2) |
+                               PWM_WPCR_WPCMD_ENABLE_SW_PROT;
+       } else {
+               wp = PWM_WPCR_WPKEY_PASSWD | (ul_group << 2) |
+                               PWM_WPCR_WPCMD_ENABLE_HW_PROT;
+       }
+
+       p_pwm->PWM_WPCR = wp;
+}
+
+/**
+ * \brief Disable PWM write protect.
+ *
+ * \note Only a hardware reset of PWM controller (handled by PMC) can disable hardware write protect.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param ul_group Bitmask of PWM register group.
+ */
+void pwm_disable_protect(Pwm *p_pwm, uint32_t ul_group)
+{
+       p_pwm->PWM_WPCR = PWM_WPCR_WPKEY_PASSWD
+                        | (ul_group << 2) | PWM_WPCR_WPCMD_DISABLE_SW_PROT;
+}
+
+/**
+ * \brief Get PWM write protect status.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param p_protect Pointer to a structure stored PWM protect status.
+ *
+ * \retval 0 Protection disabled.
+ * \retval 1 Protection enabled.
+ */
+bool pwm_get_protect_status(Pwm *p_pwm, pwm_protect_t *p_protect)
+{
+       uint32_t wpsr = p_pwm->PWM_WPSR;
+
+       p_protect->ul_hw_status = (wpsr >> 8) & 0x3F;
+       /** Bitmask of PWM register group for write protect software status */
+       p_protect->ul_sw_status = (wpsr & 0x3F);
+
+       if ((PWM_WPSR_WPVS & wpsr) == PWM_WPSR_WPVS) {
+               p_protect->ul_offset =
+                               (wpsr & PWM_WPSR_WPVSRC_Msk) >>
+                               PWM_WPSR_WPVSRC_Pos;
+               return true;
+       } else {
+               return false;
+       }
+}
+
+/**
+ * \brief Get interrupt status of PDC transfer, synchronous channels and comparison.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ *
+ * \return Interrupt status of PDC transfer, synchronous channels and comparison.
+ */
+uint32_t pwm_get_interrupt_status(Pwm *p_pwm)
+{
+       return p_pwm->PWM_ISR2;
+}
+
+/**
+ * \brief Get interrupt mask of PDC transfer, synchronous channels and comparison.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ *
+ * \return Interrupt mask of PDC transfer, synchronous channels and comparison.
+ */
+uint32_t pwm_get_interrupt_mask(Pwm *p_pwm)
+{
+       return p_pwm->PWM_IMR2;
+}
+#endif
+
+#if (SAM3S || SAM3XA || SAM4S || SAM4E)
+/**
+ * \brief Initialize PWM stepper motor mode.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param pair PWM channels used by stepper motor.
+ * \param b_enable_gray Set true to enable gray count generation. Set false to disable it.
+ * \param b_down Set true to use down counter. Set false to use up counter.
+ */
+void pwm_stepper_motor_init(Pwm *p_pwm, pwm_stepper_motor_pair_t pair,
+               bool b_enable_gray, bool b_down)
+{
+       uint32_t motor = p_pwm->PWM_SMMR;
+
+       motor &= ~((PWM_SMMR_GCEN0 | PWM_SMMR_DOWN0) << pair);
+       motor |= ((b_enable_gray | (b_down << 16)) << pair);
+
+       p_pwm->PWM_SMMR = motor;
+}
+#endif
+
+#if SAM4E
+/**
+ * \brief Change spread spectrum value.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param p_channel Configurations of the specified PWM channel.
+ * \param ul_spread New spread spectrum value.
+ */
+void pwm_channel_update_spread(Pwm *p_pwm, pwm_channel_t *p_channel,
+               uint32_t ul_spread)
+{
+       /* Save new spread spectrum value */
+       p_channel->ul_spread = ul_spread;
+
+       /* Write spread spectrum update register */
+       p_pwm->PWM_SSPUP = PWM_SSPUP_SPRDUP(ul_spread);
+}
+
+/**
+ * \brief Change additional edge value and mode.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param p_channel Configurations of the specified PWM channel.
+ * \param ul_additional_edge New additional edge value.
+ * \param additional_edge_mode New additional edge mode.
+ */
+void pwm_channel_update_additional_edge(Pwm *p_pwm, pwm_channel_t *p_channel,
+               uint32_t ul_additional_edge,
+               pwm_additional_edge_mode_t additional_edge_mode)
+{
+       /* Save new additional edge value */
+       p_channel->ul_additional_edge = ul_additional_edge;
+       p_channel->additional_edge_mode = additional_edge_mode;
+
+       /* Write channel additional edge update register */
+       p_pwm->PWM_CH_NUM_0X400[p_channel->channel].PWM_CAEUPD =
+                       PWM_CAEUPD_ADEDGVUP(ul_additional_edge) | additional_edge_mode;
+}
+
+/**
+ * \brief Change polarity mode.
+ *
+ * \param p_pwm Pointer to a PWM instance.
+ * \param p_channel Configurations of the specified PWM channel.
+ * \param polarity_inversion_flag Polarity invertion.
+ * \param polarity_flag Polarity value.
+ */
+void pwm_channel_update_polarity_mode(Pwm *p_pwm, pwm_channel_t *p_channel,
+               bool polarity_inversion_flag, pwm_level_t polarity_value)
+{
+       if (polarity_inversion_flag) {
+               /* Set polarity inversion to the update register */
+               p_pwm->PWM_CH_NUM_0X400[p_channel->channel].PWM_CMUPD =
+                               PWM_CMUPD_CPOLINVUP;
+       } else {
+               /* Save new polarity value */
+               p_channel->polarity = polarity_value;
+
+               /* Write new polarity value to update register */
+               if (polarity_value == PWM_HIGH) {
+                       p_pwm->PWM_CH_NUM_0X400[p_channel->channel].PWM_CMUPD =
+                                       PWM_CMUPD_CPOLUP;
+               } else {
+                       p_pwm->PWM_CH_NUM_0X400[p_channel->channel].PWM_CMUPD = 0;
+               }
+       }
+}
+#endif
+
+//@}
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+}
+#endif
+/**INDENT-ON**/
+/// @endcond
diff --git a/asf/sam/drivers/pwm/pwm.h b/asf/sam/drivers/pwm/pwm.h
new file mode 100644 (file)
index 0000000..ded104f
--- /dev/null
@@ -0,0 +1,644 @@
+/**
+ * \file
+ *
+ * \brief Pulse Width Modulation (PWM) driver for SAM.
+ *
+ * Copyright (c) 2011-2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#ifndef PWM_H_INCLUDED
+#define PWM_H_INCLUDED
+
+#include "compiler.h"
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+#define PWM_INVALID_ARGUMENT  0xFFFF
+
+/** Definitions for PWM channel number */
+typedef enum _pwm_ch_t {
+       PWM_CHANNEL_0 = 0,
+       PWM_CHANNEL_1 = 1,
+       PWM_CHANNEL_2 = 2,
+       PWM_CHANNEL_3 = 3,
+#if (SAM3XA)
+       PWM_CHANNEL_4 = 4,
+       PWM_CHANNEL_5 = 5,
+       PWM_CHANNEL_6 = 6,
+       PWM_CHANNEL_7 = 7
+#endif /* (SAM3XA) */
+} pwm_ch_t;
+
+/** Definitions for PWM channel alignment */
+typedef enum {
+       PWM_ALIGN_LEFT = (0 << 8),   /* The period is left aligned. */
+       PWM_ALIGN_CENTER = (1 << 8)  /* The period is center aligned. */
+} pwm_align_t;
+
+/** Definitions for PWM level */
+typedef enum {
+       PWM_LOW = LOW,     /* Low level */
+       PWM_HIGH = HIGH,  /* High level */
+#if SAM4E
+       PWM_HIGHZ,  /* High Impedance */
+#endif
+} pwm_level_t;
+
+/** Input parameters when initializing PWM */
+typedef struct {
+       /** Frequency of clock A in Hz (set 0 to turn it off) */
+       uint32_t ul_clka;
+       /** Frequency of clock B in Hz (set 0 to turn it off) */
+       uint32_t ul_clkb;
+       /** Frequency of master clock in Hz */
+       uint32_t ul_mck;
+} pwm_clock_t;
+
+#if (SAM3U || SAM3S || SAM3XA || SAM4S || SAM4E)
+/** Definitions for PWM channels used by motor stepper */
+typedef enum {
+       PWM_STEPPER_MOTOR_CH_0_1 = 0,  /* Channel 0 and 1 */
+       PWM_STEPPER_MOTOR_CH_2_3 = 1,  /* Channel 2 and 3 */
+#if (SAM3XA)
+       PWM_STEPPER_MOTOR_CH_4_5 = 2,  /* Channel 4 and 5 */
+       PWM_STEPPER_MOTOR_CH_6_7 = 3   /* Channel 6 and 7 */
+#endif /* (SAM3XA) */
+} pwm_stepper_motor_pair_t;
+
+/** Definitions for PWM synchronous channels update mode */
+typedef enum {
+       PWM_SYNC_UPDATE_MODE_0 = PWM_SCM_UPDM_MODE0,
+       PWM_SYNC_UPDATE_MODE_1 = PWM_SCM_UPDM_MODE1,
+       PWM_SYNC_UPDATE_MODE_2 = PWM_SCM_UPDM_MODE2
+} pwm_sync_update_mode_t;
+
+/** Definitions for PWM event */
+typedef enum {
+       PWM_EVENT_PERIOD_END = (0 << 10),      /* The channel counter event occurs at the end of the PWM period. */
+       PWM_EVENT_PERIOD_HALF_END = (1 << 10)  /* The channel counter event occurs at the half of the PWM period. */
+} pwm_counter_event_t;
+
+/** Definitions for PWM fault input ID */
+typedef enum {
+#if (SAM3U)
+       PWM_FAULT_MAINOSC = (1 << 0),
+       PWM_FAULT_PWMFI2 = (1 << 1),
+       PWM_FAULT_PWMFI0 = (1 << 2),
+       PWM_FAULT_PWMFI1 = (1 << 3)
+#elif (SAM3S || SAM4S || SAM4E)
+       PWM_FAULT_PWMFI1 = (1 << 0),
+       PWM_FAULT_MAINOSC = (1 << 1),
+       PWM_FAULT_ADC = (1 << 2),
+       PWM_FAULT_ACC = (1 << 3),
+       PWM_FAULT_TIMER_0 = (1 << 4),
+       PWM_FAULT_TIMER_1 = (1 << 5)
+#elif (SAM3XA)
+       PWM_FAULT_PWMFI0 = (1 << 0),
+       PWM_FAULT_PWMFI1 = (1 << 1),
+       PWM_FAULT_PWMFI2 = (1 << 2),
+       PWM_FAULT_MAINOSC = (1 << 3),
+       PWM_FAULT_ADC = (1 << 4),
+       PWM_FAULT_TIMER_0 = (1 << 5)
+#endif
+} pwm_fault_id_t;
+
+/** Definitions of PWM register group */
+typedef enum {
+       PWM_GROUP_CLOCK = (1 << 0),
+       PWM_GROUP_DISABLE = (1 << 1),
+       PWM_GROUP_MODE = (1 << 2),
+       PWM_GROUP_PERIOD = (1 << 3),
+       PWM_GROUP_DEAD_TIME = (1 << 4),
+       PWM_GROUP_FAULT = (1 << 5)
+} pwm_protect_reg_group_t;
+
+/** Definitions for PWM comparison interrupt */
+typedef enum {
+       PWM_CMP_MATCH = 8,   /* Comparison unit match */
+       PWM_CMP_UPDATE = 16  /* Comparison unit update */
+} pwm_cmp_interrupt_t;
+
+/** Definitions for PWM comparison unit */
+typedef enum {
+       PWM_CMP_UNIT_0 = 0,
+       PWM_CMP_UNIT_1 = 1,
+       PWM_CMP_UNIT_2 = 2,
+       PWM_CMP_UNIT_3 = 3,
+       PWM_CMP_UNIT_4 = 4,
+       PWM_CMP_UNIT_5 = 5,
+       PWM_CMP_UNIT_6 = 6,
+       PWM_CMP_UNIT_7 = 7
+} pmc_cmp_unit_t;
+
+/** Definitions for PWM PDC transfer request mode */
+typedef enum {
+       PWM_PDC_UPDATE_PERIOD_ELAPSED = (0 << 20),  /* PDC transfer request is set as soon as the update period elapses. */
+       PWM_PDC_COMPARISON_MATCH = (1 << 20)  /* PDC transfer request is set as soon as the selected comparison matches. */
+} pwm_pdc_request_mode_t;
+
+/** Definitions for PWM PDC transfer interrupt */
+typedef enum {
+       PWM_PDC_TX_END = (1 << 1),   /* PDC Tx end */
+       PWM_PDC_TX_EMPTY = (1 << 2)  /* PDC Tx buffer empty */
+} pwm_pdc_interrupt_t;
+
+/** Definitions for PWM synchronous channels interrupt */
+typedef enum {
+       PWM_SYNC_WRITE_READY = (1 << 0),  /* Write Ready for Synchronous Channels Update */
+       PWM_SYNC_UNDERRUN = (1 << 3)      /* Synchronous Channels Update Underrun Error */
+} pwm_sync_interrupt_t;
+
+#if SAM4E
+typedef enum {
+       PWM_SPREAD_SPECTRUM_MODE_TRIANGULAR = 0,
+       PWM_SPREAD_SPECTRUM_MODE_RANDOM
+} pwm_spread_spectrum_mode_t;
+typedef enum {
+       PWM_ADDITIONAL_EDGE_MODE_INC = PWM_CAE_ADEDGM_INC,
+       PWM_ADDITIONAL_EDGE_MODE_DEC = PWM_CAE_ADEDGM_DEC,
+       PWM_ADDITIONAL_EDGE_MODE_BOTH = PWM_CAE_ADEDGM_BOTH,
+} pwm_additional_edge_mode_t;
+#endif
+
+/** Configurations of a PWM channel output */
+typedef struct {
+       /** Boolean of using override output as PWMH */
+       bool b_override_pwmh;
+       /** Boolean of using override output as PWML */
+       bool b_override_pwml;
+       /** Level of override output for PWMH */
+       pwm_level_t override_level_pwmh;
+       /** Level of override output for PWML */
+       pwm_level_t override_level_pwml;
+} pwm_output_t;
+
+/** Configurations of PWM comparison */
+typedef struct {
+       /** Comparison unit number */
+       uint32_t unit;
+       /** Boolean of comparison enable */
+       bool b_enable;
+       /** Comparison value */
+       uint32_t ul_value;
+       /** Comparison mode */
+       bool b_is_decrementing;
+       /** Comparison trigger value */
+       uint32_t ul_trigger;
+       /** Comparison period value */
+       uint32_t ul_period;
+       /** Comparison update period value */
+       uint32_t ul_update_period;
+       /** Boolean of generating a match pulse on PWM event line 0 */
+       bool b_pulse_on_line_0;
+       /** Boolean of generating a match pulse on PWM event line 1 */
+       bool b_pulse_on_line_1;
+} pwm_cmp_t;
+
+/** Configuration of PWM fault input behaviors */
+typedef struct {
+       /** Fault ID */
+       pwm_fault_id_t fault_id;
+       /** Polarity of fault input */
+       pwm_level_t polarity;
+       /** Boolean of clearing fault flag */
+       bool b_clear;
+       /** Boolean of fault filtering */
+       bool b_filtered;
+} pwm_fault_t;
+
+/** Structure of PWM write-protect information */
+typedef struct {
+       /** Bitmask of PWM register group for write protect hardware status */
+       uint32_t ul_hw_status;
+       /** Bitmask of PWM register group for write protect software status */
+       uint32_t ul_sw_status;
+       /** Offset address of PWM register in which a write access has been attempted */
+       uint32_t ul_offset;
+} pwm_protect_t;
+#endif /* (SAM3U || SAM3S || SAM3XA) */
+
+/** Input parameters when configuring a PWM channel mode */
+typedef struct {
+       /** Channel number */
+       uint32_t channel;
+       /** Channel prescaler */
+       uint32_t ul_prescaler;
+    /** Channel alignment */
+       pwm_align_t alignment;
+    /** Channel initial polarity */
+       pwm_level_t polarity;
+       /** Duty Cycle Value */
+       uint32_t ul_duty;
+       /** Period Cycle Value */
+       uint32_t ul_period;
+
+#if (SAM3U || SAM3S || SAM3XA || SAM4S || SAM4E)
+    /** Channel counter event */
+       pwm_counter_event_t counter_event;
+    /** Boolean of channel dead-time generator */
+       bool b_deadtime_generator;
+    /** Boolean of channel dead-time PWMH output inverted */
+       bool b_pwmh_output_inverted;
+    /** Boolean of channel dead-time PWML output inverted */
+       bool b_pwml_output_inverted;
+       /** Dead-time Value for PWMH Output */
+       uint16_t us_deadtime_pwmh;
+       /** Dead-time Value for PWML Output */
+       uint16_t us_deadtime_pwml;
+       /** Channel output */
+       pwm_output_t output_selection;
+       /** Boolean of Synchronous Channel */
+       bool b_sync_ch;
+       /** Fault ID of the channel */
+       pwm_fault_id_t fault_id;
+       /** Channel PWMH output level in fault protection */
+       pwm_level_t ul_fault_output_pwmh;
+       /** Channel PWML output level in fault protection */
+       pwm_level_t ul_fault_output_pwml;
+#endif /* (SAM3U || SAM3S || SAM3XA || SAM4S || SAM4E) */
+#if SAM4E
+       /** Spread Spectrum Value */
+       uint32_t ul_spread;
+       /** Spread Spectrum Mode */
+       pwm_spread_spectrum_mode_t spread_spectrum_mode;
+       /** Additional Edge Value */
+       uint32_t ul_additional_edge;
+       /** Additional Edge Mode */
+       pwm_additional_edge_mode_t additional_edge_mode;
+#endif
+} pwm_channel_t;
+
+
+uint32_t pwm_init(Pwm *p_pwm, pwm_clock_t *clock_config);
+uint32_t pwm_channel_init(Pwm *p_pwm, pwm_channel_t *p_channel);
+uint32_t pwm_channel_update_period(Pwm *p_pwm, pwm_channel_t *p_channel,
+               uint32_t ul_period);
+uint32_t pwm_channel_update_duty(Pwm *p_pwm, pwm_channel_t *p_channel,
+               uint32_t ul_duty);
+uint32_t pwm_channel_get_counter(Pwm *p_pwm, pwm_channel_t *p_channel);
+void pwm_channel_enable(Pwm *p_pwm, uint32_t ul_channel);
+void pwm_channel_disable(Pwm *p_pwm, uint32_t ul_channel);
+uint32_t pwm_channel_get_status(Pwm *p_pwm);
+uint32_t pwm_channel_get_interrupt_status(Pwm *p_pwm);
+uint32_t pwm_channel_get_interrupt_mask(Pwm *p_pwm);
+void pwm_channel_enable_interrupt(Pwm *p_pwm, uint32_t ul_event,
+               uint32_t ul_fault);
+void pwm_channel_disable_interrupt(Pwm *p_pwm, uint32_t ul_event,
+               uint32_t ul_fault);
+
+#if (SAM3U || SAM3S || SAM3XA || SAM4S || SAM4E)
+void pwm_channel_update_output(Pwm *p_pwm, pwm_channel_t *p_channel,
+               pwm_output_t *p_output, bool b_sync);
+void pwm_channel_update_dead_time(Pwm *p_pwm, pwm_channel_t *p_channel,
+               uint16_t us_deadtime_pwmh, uint16_t us_deadtime_pwml);
+
+uint32_t pwm_fault_init(Pwm *p_pwm, pwm_fault_t *p_fault);
+uint32_t pwm_fault_get_status(Pwm *p_pwm);
+pwm_level_t pwm_fault_get_input_level(Pwm *p_pwm, pwm_fault_id_t id);
+void pwm_fault_clear_status(Pwm *p_pwm, pwm_fault_id_t id);
+
+uint32_t pwm_cmp_init(Pwm *p_pwm, pwm_cmp_t *p_cmp);
+uint32_t pwm_cmp_change_setting(Pwm *p_pwm, pwm_cmp_t *p_cmp);
+uint32_t pwm_cmp_get_period_counter(Pwm *p_pwm, uint32_t ul_cmp_unit);
+uint32_t pwm_cmp_get_update_counter(Pwm *p_pwm, uint32_t ul_cmp_unit);
+void pwm_cmp_enable_interrupt(Pwm *p_pwm, uint32_t ul_sources,
+               pwm_cmp_interrupt_t type);
+void pwm_cmp_disable_interrupt(Pwm *p_pwm, uint32_t ul_sources,
+               pwm_cmp_interrupt_t type);
+void pwm_pdc_set_request_mode(Pwm *p_pwm, pwm_pdc_request_mode_t request_mode,
+               uint32_t ul_cmp_unit);
+
+void pwm_pdc_enable_interrupt(Pwm *p_pwm, uint32_t ul_sources);
+void pwm_pdc_disable_interrupt(Pwm *p_pwm, uint32_t ul_sources);
+
+uint32_t pwm_sync_init(Pwm *p_pwm, pwm_sync_update_mode_t mode,
+               uint32_t ul_update_period);
+void pwm_sync_unlock_update(Pwm *p_pwm);
+void pwm_sync_change_period(Pwm *p_pwm, uint32_t ul_update_period);
+uint32_t pwm_sync_get_period_counter(Pwm * p_pwm);
+void pwm_sync_enable_interrupt(Pwm *p_pwm, uint32_t ul_sources);
+void pwm_sync_disable_interrupt(Pwm *p_pwm, uint32_t ul_sources);
+
+void pwm_enable_protect(Pwm *p_pwm, uint32_t ul_group, bool b_sw);
+void pwm_disable_protect(Pwm *p_pwm, uint32_t ul_group);
+bool pwm_get_protect_status(Pwm *p_pwm, pwm_protect_t * p_protect);
+
+uint32_t pwm_get_interrupt_status(Pwm *p_pwm);
+uint32_t pwm_get_interrupt_mask(Pwm *p_pwm);
+#endif /* (SAM3U || SAM3S || SAM3XA || SAM4S || SAM4E) */
+
+#if (SAM3S || SAM3XA || SAM4S || SAM4E)
+void pwm_stepper_motor_init(Pwm *p_pwm, pwm_stepper_motor_pair_t pair,
+               bool b_enable_gray, bool b_down);
+#endif /* (SAM3S || SAM3XA || SAM4S || SAM4E) */
+
+#if SAM4E
+void pwm_channel_update_spread(Pwm *p_pwm, pwm_channel_t *p_channel,
+               uint32_t ul_spread);
+void pwm_channel_update_additional_edge(Pwm *p_pwm, pwm_channel_t *p_channel,
+               uint32_t ul_additional_edge,
+               pwm_additional_edge_mode_t additional_edge_mode);
+void pwm_channel_update_polarity_mode(Pwm *p_pwm, pwm_channel_t *p_channel,
+               bool polarity_inversion_flag, pwm_level_t polarity_value);
+#endif
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+}
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+/**
+ * \page sam_pwm_quickstart Quickstart guide for SAM PWM module
+ *
+ * This is the quickstart guide for the \ref sam_drivers_pwm_group "PWM module",
+ * with step-by-step instructions on how to configure and use the drivers in a
+ * selection of use cases.
+ *
+ * The use cases contain several code fragments. The code fragments in the
+ * steps for setup can be copied into a custom initialization function, while
+ * the steps for usage can be copied into, e.g., the main application function.
+ *
+ * \section pwm_basic_use_case Basic use case
+ * In this basic use case, the PWM module is configured to:
+ * - Output a square wave on PWM channel 0
+ * - The frequency of the square wave is 1KHz, 50% duty cycle
+ * - Clock A as the source clock
+ * - The output wave can be checked on the selected output pin
+ *
+ * \section pwm_basic_use_case_setup Setup steps
+ *
+ * \subsection pwm_basic_use_case_setup_prereq Prerequisites
+ *  - \ref group_pmc "Power Management Controller driver"
+ *  - \ref gpio_group "General Purpose I/O Management (gpio)"
+ *
+ * \subsection pwm_basic_use_case_setup_code Example code
+ * Add this PWM initialization code at the beginning of the main function:
+ * \code
+           pwm_channel_t pwm_channel_instance;
+
+           pmc_enable_periph_clk(ID_PWM);
+
+           pwm_channel_disable(PWM, PWM_CHANNEL_0);
+
+           pwm_clock_t clock_setting = {
+               .ul_clka = 1000 * 100,
+               .ul_clkb = 0,
+               .ul_mck = 48000000
+           };
+           pwm_init(PWM, &clock_setting);
+
+           pwm_channel_instance.ul_prescaler = PWM_CMR_CPRE_CLKA;
+           pwm_channel_instance.ul_period = 100;
+           pwm_channel_instance.ul_duty = 50;
+           pwm_channel_instance.channel = PWM_CHANNEL_0;
+           pwm_channel_init(PWM, &pwm_channel_instance);
+\endcode
+ *
+ * \subsection pwm_basic_use_case_setup_flow Workflow
+ * -# Define the PWM channel instance in order to configure channel 0:
+ *   - \code pwm_channel_t pwm_channel_instance; \endcode
+ * -# Enable the module clock for the PWM peripheral:
+ *   - \code pmc_enable_periph_clk(ID_PWM); \endcode
+ * -# Disable PWM channel 0:
+ *   - \code pwm_channel_disable(PWM, PWM_CHANNEL_0); \endcode
+ * -# Setup clock for PWM module:
+ *   - \code
+       pwm_clock_t clock_setting = {
+           .ul_clka = 1000 * 100,
+           .ul_clkb = 0,
+           .ul_mck = 48000000
+       };
+       pwm_init(PWM, &clock_setting);
+\endcode
+ *   - \note 1. Only Clock A is configured (clock B is not used).
+ * 2. The expected frequency is 1KHz, system main clock is assumed to be 48MHz.
+ * -# Initialize channel instance and configure PWM channel 0, selecting clock A
+ * as its source clock and setting the duty cycle at 50%:
+ *   - \code
+       pwm_channel_instance.ul_prescaler = PWM_CMR_CPRE_CLKA;
+       pwm_channel_instance.ul_period = 100;
+       pwm_channel_instance.ul_duty = 50;
+       pwm_channel_instance.channel = PWM_CHANNEL_0;
+       pwm_channel_init(PWM, &pwm_channel_instance);
+\endcode
+ *   - \note 1. Period is left-aligned and output waveform starts at a low level.
+ * 2. The pwm_channel_instance can be re-used to configure other PWM channels
+ * after setting the required parameters.
+ *
+ * \section pwm_basic_use_case_usage Usage steps
+ *
+ * \subsection pwm_basic_use_case_usage_code Example code
+ * Add to, e.g., main loop in application C-file:
+ * \code
+       pwm_channel_enable(PWM, PWM_CHANNEL_0);
+\endcode
+ *
+ * \subsection pwm_basic_use_case_usage_flow Workflow
+ * -# Enable PWM channel 0 and output square wave on this channel:
+ *   - \code pwm_channel_enable(PWM, PWM_CHANNEL_0); \endcode
+ *
+ * \section pwm_use_cases Advanced use cases
+ * For more advanced use of the pwm driver, see the following use cases:
+ * - \subpage pwm_use_case_1 : PWM channel 0 outputs square wave and duty cycle
+ *  is updated in the PWM ISR.
+ */
+
+/**
+ * \page pwm_use_case_1 Use case #1
+ *
+ * In this use case, the PWM module is configured to:
+ * - Output a square wave on PWM channel 0
+ * - The frequency of the square wave is 1KHz
+ * - The duty cycle is changed in the PWM ISR
+ * - Clock A as the source clock
+ * - The output wave can be checked on the selected output pin
+ *
+ * \section pwm_use_case_1_setup Setup steps
+ *
+ * \subsection pwm_use_case_1_setup_prereq Prerequisites
+ *  - \ref group_pmc "Power Management Controller driver"
+ *  - \ref gpio_group "General Purpose I/O Management (gpio)"
+ *
+ * \subsection pwm_use_case_1_setup_code Example code
+ * Add to application C-file:
+ * \code
+       pwm_channel_t pwm_channel_instance;
+\endcode
+ *
+ * \code
+           void PWM_Handler(void)
+           {
+               static uint32_t ul_duty = 0;
+               uint32_t ul_status;
+               static uint8_t uc_countn = 0;
+               static uint8_t uc_flag = 1;
+
+               ul_status = pwm_channel_get_interrupt_status(PWM);
+               if ((ul_status & PWM_CHANNEL_0) == PWM_CHANNEL_0) {
+                   uc_count++;
+                   if (uc_count == 10) {
+                       if (uc_flag) {
+                           ul_duty++;
+                           if (ul_duty == 100) {
+                               uc_flag = 0;
+                           }
+                       } else {
+                           ul_duty--;
+                           if (ul_duty == 0) {
+                               uc_flag = 1;
+                           }
+                       }
+                       uc_count = 0;
+                       pwm_channel_instance.channel = PWM_CHANNEL_0;
+                       pwm_channel_update_duty(PWM, &pwm_channel_instance, ul_duty);
+                   }
+               }
+           }
+\endcode
+ *
+ * \code
+           pmc_enable_periph_clk(ID_PWM);
+
+           pwm_channel_disable(PWM, PWM_CHANNEL_0);
+
+           pwm_clock_t clock_setting = {
+               .ul_clka = 1000 * 100,
+               .ul_clkb = 0,
+               .ul_mck = 48000000
+           };
+           pwm_init(PWM, &clock_setting);
+
+           pwm_channel_instance.ul_prescaler = PWM_CMR_CPRE_CLKA;
+           pwm_channel_instance.ul_period = 100;
+           pwm_channel_instance.ul_duty = 0;
+           pwm_channel_instance.channel = PWM_CHANNEL_0;
+           pwm_channel_init(PWM, &pwm_channel_instance);
+
+           pwm_channel_enable_interrupt(PWM, PWM_CHANNEL_0, 0);
+\endcode
+ *
+ * \subsection pwm_use_case_1_setup_flow Workflow
+ * -# Define the PWM channel instance in order to configure channel 0:
+ *   - \code pwm_channel_t pwm_channel_instance; \endcode
+ * -# Define the PWM interrupt handler in the application:
+ *   - \code void PWM_Handler(void); \endcode
+ * -# In PWM_Handler(), get PWM interrupt status:
+ *   - \code ul_status = pwm_channel_get_interrupt_status(PWM); \endcode
+ * -# In PWM_Handler(), check whether the PWM channel 0 interrupt has occurred:
+ *   - \code
+       if ((ul_status & PWM_CHANNEL_0) == PWM_CHANNEL_0) {
+       }
+\endcode
+ * -# In PWM_Handler(), if the PWM channel 0 interrupt has occurred, update the ul_duty value:
+ *   - \code
+       uc_count++;
+       if (uc_count == 10) {
+           if (uc_flag) {
+               ul_duty++;
+               if (ul_duty >= 100) {
+                   uc_flag = 0;
+               }
+           } else {
+               ul_duty--;
+               if (ul_duty == 0) {
+                   uc_flag = 1;
+               }
+           }
+       }
+\endcode
+ * -# In PWM_Handler(), if the ul_duty value has been updated, change the square wave duty:
+ *   - \code
+       pwm_channel_instance.channel = PWM_CHANNEL_0;
+       pwm_channel_update_duty(PWM, &pwm_channel_instance, ul_duty);
+\endcode
+ * -# Enable the PWM clock:
+ *   - \code pmc_enable_periph_clk(ID_PWM); \endcode
+ * -# Disable PWM channel 0:
+ *   - \code pwm_channel_disable(PWM, PWM_CHANNEL_0); \endcode
+ * -# Setup clock for PWM module:
+ *   - \code
+       pwm_clock_t clock_setting = {
+           .ul_clka = 1000 * 100,
+           .ul_clkb = 0,
+           .ul_mck = 48000000
+       };
+       pwm_init(PWM, &clock_setting);
+\endcode
+ *   - \note 1. Only Clock A is configured (clock B is not used).
+ * 2. The expected frequency is 1KHz, system main clock is assumed to be 48Mhz.
+ * -# Initialize channel instance and configure PWM channel 0, selecting clock A
+ * as its source clock and setting the initial ducy as 0%:
+ *   - \code
+       pwm_channel_instance.ul_prescaler = PWM_CMR_CPRE_CLKA;
+       pwm_channel_instance.ul_period = 100;
+       pwm_channel_instance.ul_duty = 0;
+       pwm_channel_instance.channel = PWM_CHANNEL_0;
+       pwm_channel_init(PWM, &pwm_channel_instance);
+\endcode
+ *   - \note 1. Period is left-aligned and output waveform starts at a low level.
+ * 2. The pwm_channel_instance can be re-used to configure other PWM channels
+ * after setting the required parameters.
+ * -# Enable channel 0 interrupt:
+ *   - \code pwm_channel_enable_interrupt(PWM, PWM_CHANNEL_0, 0); \endcode
+ *   - \note 1.In order to enable the PWM interrupt, the NVIC must be configured
+ * to enable the PWM interrupt. 2. When the channel 0 counter reaches the channel
+ * period, the interrupt (counter event) will occur.
+ *
+ * \section pwm_use_case_1_usage Usage steps
+ *
+ * \subsection pwm_use_case_1_usage_code Example code
+ * \code
+       pwm_channel_enable(PWM, PWM_CHANNEL_0);
+\endcode
+ *
+ * \subsection pwn_use_case_1_usage_flow Workflow
+ * -# Enable PWM channel 0 and output square wave on this channel:
+ *   - \code pwm_channel_enable(PWM, PWM_CHANNEL_0); \endcode
+ *
+ */
+
+#endif /* PWM_H_INCLUDED */
diff --git a/asf/sam/drivers/spi/spi.c b/asf/sam/drivers/spi/spi.c
new file mode 100644 (file)
index 0000000..f87ee25
--- /dev/null
@@ -0,0 +1,371 @@
+/**
+ * \file
+ *
+ * \brief Serial Peripheral Interface (SPI) driver for SAM.
+ *
+ * Copyright (c) 2011-2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#include "spi.h"
+#include "sysclk.h"
+
+/**
+ * \defgroup sam_drivers_spi_group Serial Peripheral Interface (SPI)
+ *
+ * See \ref sam_spi_quickstart.
+ *
+ * The SPI circuit is a synchronous serial data link that provides communication
+ * with external devices in Master or Slave mode. Connection to Peripheral DMA
+ * Controller channel capabilities optimizes data transfers.
+ *
+ * @{
+ */
+#ifndef SPI_WPMR_WPKEY_PASSWD
+#define SPI_WPMR_WPKEY_PASSWD SPI_WPMR_WPKEY((uint32_t) 0x535049)
+#endif
+
+/**
+ * \brief Enable SPI clock.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+void spi_enable_clock(Spi *p_spi)
+{
+#if (SAM4S || SAM3S || SAM3N || SAM3U || SAM4E || SAM4N || SAMG)
+       UNUSED(p_spi);
+       sysclk_enable_peripheral_clock(ID_SPI);
+#elif (SAM3XA || SAM4C || SAM4CP || SAM4CM)
+       if (p_spi == SPI0) {
+               sysclk_enable_peripheral_clock(ID_SPI0);
+       }
+       #ifdef SPI1
+       else if (p_spi == SPI1) {
+               sysclk_enable_peripheral_clock(ID_SPI1);
+       }
+       #endif
+#elif SAM4L
+       sysclk_enable_peripheral_clock(p_spi);
+#endif
+}
+
+/**
+ * \brief Disable SPI clock.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+void spi_disable_clock(Spi *p_spi)
+{
+#if (SAM4S || SAM3S || SAM3N || SAM3U || SAM4E || SAM4N || SAMG)
+       UNUSED(p_spi);
+       sysclk_disable_peripheral_clock(ID_SPI);
+#elif (SAM3XA || SAM4C || SAM4CP || SAM4CM)
+       if (p_spi == SPI0) {
+               sysclk_disable_peripheral_clock(ID_SPI0);
+       }
+       #ifdef SPI1
+       else if (p_spi == SPI1) {
+               sysclk_disable_peripheral_clock(ID_SPI1);
+       }
+       #endif
+#elif SAM4L
+       sysclk_disable_peripheral_clock(p_spi);
+#endif
+}
+
+/**
+ * \brief Set Peripheral Chip Select (PCS) value.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ * \param ul_value Peripheral Chip Select value.
+ *                 If PCS decode mode is not used, use \ref spi_get_pcs to build
+ *                 the value to use.
+ *                 On reset the decode mode is not enabled.
+ *                 The decode mode can be enabled/disabled by follow functions:
+ *                 \ref spi_enable_peripheral_select_decode,
+ *                 \ref spi_disable_peripheral_select_decode.
+ */
+void spi_set_peripheral_chip_select_value(Spi *p_spi, uint32_t ul_value)
+{
+       p_spi->SPI_MR &= (~SPI_MR_PCS_Msk);
+       p_spi->SPI_MR |= SPI_MR_PCS(ul_value);
+}
+
+/**
+ * \brief Set delay between chip selects (in number of MCK clocks).
+ *  If DLYBCS <= 6, 6 MCK clocks will be inserted by default.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ * \param ul_delay Delay between chip selects (in number of MCK clocks).
+ */
+void spi_set_delay_between_chip_select(Spi *p_spi, uint32_t ul_delay)
+{
+       p_spi->SPI_MR &= (~SPI_MR_DLYBCS_Msk);
+       p_spi->SPI_MR |= SPI_MR_DLYBCS(ul_delay);
+}
+
+/**
+ * \brief Read the received data and it's peripheral chip select value.
+ * While SPI works in fixed peripheral select mode, the peripheral chip select
+ * value is meaningless.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ * \param data Pointer to the location where to store the received data word.
+ * \param p_pcs Pointer to fill Peripheral Chip Select Value.
+ *
+ * \retval SPI_OK on Success.
+ * \retval SPI_ERROR_TIMEOUT on Time-out.
+ */
+spi_status_t spi_read(Spi *p_spi, uint16_t *us_data, uint8_t *p_pcs)
+{
+       uint32_t timeout = SPI_TIMEOUT;
+       static uint32_t reg_value;
+
+       while (!(p_spi->SPI_SR & SPI_SR_RDRF)) {
+               if (!timeout--) {
+                       return SPI_ERROR_TIMEOUT;
+               }
+       }
+
+       reg_value = p_spi->SPI_RDR;
+       if (spi_get_peripheral_select_mode(p_spi)) {
+               *p_pcs = (uint8_t) ((reg_value & SPI_RDR_PCS_Msk) >> SPI_RDR_PCS_Pos);
+       }
+       *us_data = (uint16_t) (reg_value & SPI_RDR_RD_Msk);
+
+       return SPI_OK;
+}
+
+/**
+ * \brief Write the transmitted data with specified peripheral chip select value.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ * \param us_data The data to transmit.
+ * \param uc_pcs Peripheral Chip Select Value while SPI works in peripheral select
+ * mode, otherwise it's meaningless.
+ * \param uc_last Indicate whether this data is the last one while SPI is working
+ * in variable peripheral select mode.
+ *
+ * \retval SPI_OK on Success.
+ * \retval SPI_ERROR_TIMEOUT on Time-out.
+ */
+spi_status_t spi_write(Spi *p_spi, uint16_t us_data,
+               uint8_t uc_pcs, uint8_t uc_last)
+{
+       uint32_t timeout = SPI_TIMEOUT;
+       uint32_t value;
+
+       while (!(p_spi->SPI_SR & SPI_SR_TDRE)) {
+               if (!timeout--) {
+                       return SPI_ERROR_TIMEOUT;
+               }
+       }
+
+       if (spi_get_peripheral_select_mode(p_spi)) {
+               value = SPI_TDR_TD(us_data) | SPI_TDR_PCS(uc_pcs);
+               if (uc_last) {
+                       value |= SPI_TDR_LASTXFER;
+               }
+       } else {
+               value = SPI_TDR_TD(us_data);
+       }
+
+       p_spi->SPI_TDR = value;
+
+       return SPI_OK;
+}
+
+/**
+ * \brief Set clock default state.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ * \param ul_pcs_ch Peripheral Chip Select channel (0~3).
+ * \param ul_polarity Default clock state is logical one(high)/zero(low).
+ */
+void spi_set_clock_polarity(Spi *p_spi, uint32_t ul_pcs_ch,
+               uint32_t ul_polarity)
+{
+       if (ul_polarity) {
+               p_spi->SPI_CSR[ul_pcs_ch] |= SPI_CSR_CPOL;
+       } else {
+               p_spi->SPI_CSR[ul_pcs_ch] &= (~SPI_CSR_CPOL);
+       }
+}
+
+/**
+ * \brief Set Data Capture Phase.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ *  \param ul_pcs_ch Peripheral Chip Select channel (0~3).
+ *  \param ul_phase Data capture on the rising/falling edge of clock.
+ */
+void spi_set_clock_phase(Spi *p_spi, uint32_t ul_pcs_ch, uint32_t ul_phase)
+{
+       if (ul_phase) {
+               p_spi->SPI_CSR[ul_pcs_ch] |= SPI_CSR_NCPHA;
+       } else {
+               p_spi->SPI_CSR[ul_pcs_ch] &= (~SPI_CSR_NCPHA);
+       }
+}
+
+/**
+ * \brief Configure CS behavior for SPI transfer (\ref spi_cs_behavior_t).
+ *
+ * \param p_spi Pointer to an SPI instance.
+ * \param ul_pcs_ch Peripheral Chip Select channel (0~3).
+ * \param ul_cs_behavior Behavior of the Chip Select after transfer.
+ */
+void spi_configure_cs_behavior(Spi *p_spi, uint32_t ul_pcs_ch,
+               uint32_t ul_cs_behavior)
+{
+       if (ul_cs_behavior == SPI_CS_RISE_FORCED) {
+               p_spi->SPI_CSR[ul_pcs_ch] &= (~SPI_CSR_CSAAT);
+               p_spi->SPI_CSR[ul_pcs_ch] |= SPI_CSR_CSNAAT;
+       } else if (ul_cs_behavior == SPI_CS_RISE_NO_TX) {
+               p_spi->SPI_CSR[ul_pcs_ch] &= (~SPI_CSR_CSAAT);
+               p_spi->SPI_CSR[ul_pcs_ch] &= (~SPI_CSR_CSNAAT);
+       } else if (ul_cs_behavior == SPI_CS_KEEP_LOW) {
+               p_spi->SPI_CSR[ul_pcs_ch] |= SPI_CSR_CSAAT;
+       }
+}
+
+/**
+ * \brief Set number of bits per transfer.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ * \param ul_pcs_ch Peripheral Chip Select channel (0~3).
+ * \param ul_bits Number of bits (8~16), use the pattern defined
+ *        in the device header file.
+ */
+void spi_set_bits_per_transfer(Spi *p_spi, uint32_t ul_pcs_ch,
+               uint32_t ul_bits)
+{
+       p_spi->SPI_CSR[ul_pcs_ch] &= (~SPI_CSR_BITS_Msk);
+       p_spi->SPI_CSR[ul_pcs_ch] |= ul_bits;
+}
+
+/**
+ * \brief Calculate the baudrate divider.
+ *
+ * \param baudrate Baudrate value.
+ * \param mck      SPI module input clock frequency (MCK clock, Hz).
+ *
+ * \return Divider or error code.
+ *   \retval > 0  Success.
+ *   \retval < 0  Error.
+ */
+int16_t spi_calc_baudrate_div(const uint32_t baudrate, uint32_t mck)
+{
+       int baud_div = div_ceil(mck, baudrate);
+
+       /* The value of baud_div is from 1 to 255 in the SCBR field. */
+       if (baud_div <= 0 || baud_div > 255) {
+               return -1;
+       }
+
+       return baud_div;
+}
+
+/**
+ * \brief Set Serial Clock Baud Rate divider value (SCBR).
+ *
+ * \param p_spi Pointer to an SPI instance.
+ * \param ul_pcs_ch Peripheral Chip Select channel (0~3).
+ * \param uc_baudrate_divider Baudrate divider from MCK.
+ */
+void spi_set_baudrate_div(Spi *p_spi, uint32_t ul_pcs_ch,
+               uint8_t uc_baudrate_divider)
+{
+       p_spi->SPI_CSR[ul_pcs_ch] &= (~SPI_CSR_SCBR_Msk);
+       p_spi->SPI_CSR[ul_pcs_ch] |= SPI_CSR_SCBR(uc_baudrate_divider);
+}
+
+/**
+ * \brief Configure timing for SPI transfer.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ * \param ul_pcs_ch Peripheral Chip Select channel (0~3).
+ * \param uc_dlybs Delay before SPCK (in number of MCK clocks).
+ * \param uc_dlybct Delay between consecutive transfers (in number of MCK clocks).
+ */
+void spi_set_transfer_delay(Spi *p_spi, uint32_t ul_pcs_ch,
+               uint8_t uc_dlybs, uint8_t uc_dlybct)
+{
+       p_spi->SPI_CSR[ul_pcs_ch] &= ~(SPI_CSR_DLYBS_Msk | SPI_CSR_DLYBCT_Msk);
+       p_spi->SPI_CSR[ul_pcs_ch] |= SPI_CSR_DLYBS(uc_dlybs)
+                       | SPI_CSR_DLYBCT(uc_dlybct);
+}
+
+
+/**
+ * \brief Enable or disable write protection of SPI registers.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ * \param ul_enable 1 to enable, 0 to disable.
+ */
+void spi_set_writeprotect(Spi *p_spi, uint32_t ul_enable)
+{
+#if SAM4L
+       if (ul_enable) {
+               p_spi->SPI_WPCR = SPI_WPCR_SPIWPKEY_VALUE | SPI_WPCR_SPIWPEN;
+       } else {
+               p_spi->SPI_WPCR = SPI_WPCR_SPIWPKEY_VALUE;
+       }
+#else
+       if (ul_enable) {
+               p_spi->SPI_WPMR = SPI_WPMR_WPKEY_PASSWD | SPI_WPMR_WPEN;
+       } else {
+               p_spi->SPI_WPMR = SPI_WPMR_WPKEY_PASSWD;
+       }
+#endif
+}
+
+/**
+ * \brief Indicate write protect status.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ *
+ * \return SPI_WPSR value.
+ */
+uint32_t spi_get_writeprotect_status(Spi *p_spi)
+{
+       return p_spi->SPI_WPSR;
+}
+
+/**
+ * @}
+ */
diff --git a/asf/sam/drivers/spi/spi.h b/asf/sam/drivers/spi/spi.h
new file mode 100644 (file)
index 0000000..34cf334
--- /dev/null
@@ -0,0 +1,625 @@
+/**
+ * \file
+ *
+ * \brief Serial Peripheral Interface (SPI) driver for SAM.
+ *
+ * Copyright (c) 2011-2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#ifndef SPI_H_INCLUDED
+#define SPI_H_INCLUDED
+
+#include "compiler.h"
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+/** Time-out value (number of attempts). */
+#define SPI_TIMEOUT       15000
+
+/** Status codes used by the SPI driver. */
+typedef enum
+{
+       SPI_ERROR = -1,
+       SPI_OK = 0,
+       SPI_ERROR_TIMEOUT = 1,
+       SPI_ERROR_ARGUMENT,
+       SPI_ERROR_OVERRUN,
+       SPI_ERROR_MODE_FAULT,
+       SPI_ERROR_OVERRUN_AND_MODE_FAULT
+} spi_status_t;
+
+/** SPI Chip Select behavior modes while transferring. */
+typedef enum spi_cs_behavior {
+       /** CS does not rise until a new transfer is requested on different chip select. */
+       SPI_CS_KEEP_LOW = SPI_CSR_CSAAT,
+       /** CS rises if there is no more data to transfer. */
+       SPI_CS_RISE_NO_TX = 0,
+       /** CS is de-asserted systematically during a time DLYBCS. */
+       SPI_CS_RISE_FORCED = SPI_CSR_CSNAAT
+} spi_cs_behavior_t;
+
+/**
+ * \brief Generate Peripheral Chip Select Value from Chip Select ID
+ * \note When chip select n is working, PCS bit n is set to low level.
+ *
+ * \param chip_sel_id The chip select number used
+ */
+#define spi_get_pcs(chip_sel_id) ((~(1u<<(chip_sel_id)))&0xF)
+
+/**
+ * \brief Reset SPI and set it to Slave mode.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+static inline void spi_reset(Spi *p_spi)
+{
+       p_spi->SPI_CR = SPI_CR_SWRST;
+}
+
+/**
+ * \brief Enable SPI.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+static inline void spi_enable(Spi *p_spi)
+{
+       p_spi->SPI_CR = SPI_CR_SPIEN;
+}
+
+/**
+ * \brief Disable SPI.
+ *
+ * \note CS is de-asserted, which indicates that the last data is done, and user
+ * should check TX_EMPTY before disabling SPI.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+static inline void spi_disable(Spi *p_spi)
+{
+       p_spi->SPI_CR = SPI_CR_SPIDIS;
+}
+
+/**
+ * \brief Issue a LASTXFER command.
+ *  The next transfer is the last transfer and after that CS is de-asserted.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+static inline void spi_set_lastxfer(Spi *p_spi)
+{
+       p_spi->SPI_CR = SPI_CR_LASTXFER;
+}
+
+/**
+ * \brief Set SPI to Master mode.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+static inline void spi_set_master_mode(Spi *p_spi)
+{
+       p_spi->SPI_MR |= SPI_MR_MSTR;
+}
+
+/**
+ * \brief Set SPI to Slave mode.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+static inline void spi_set_slave_mode(Spi *p_spi)
+{
+       p_spi->SPI_MR &= (~SPI_MR_MSTR);
+}
+
+/**
+ * \brief Get SPI work mode.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ *
+ * \return 1 for master mode, 0 for slave mode.
+ */
+static inline uint32_t spi_get_mode(Spi *p_spi)
+{
+       if (p_spi->SPI_MR & SPI_MR_MSTR) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+/**
+ * \brief Set Variable Peripheral Select.
+ * Peripheral Chip Select can be controlled by SPI_TDR.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+static inline void spi_set_variable_peripheral_select(Spi *p_spi)
+{
+       p_spi->SPI_MR |= SPI_MR_PS;
+}
+
+/**
+ * \brief Set Fixed Peripheral Select.
+ *  Peripheral Chip Select is controlled by SPI_MR.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+static inline void spi_set_fixed_peripheral_select(Spi *p_spi)
+{
+       p_spi->SPI_MR &= (~SPI_MR_PS);
+}
+
+/**
+ * \brief Get Peripheral Select mode.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ *
+ * \return 1 for Variable mode, 0 for fixed mode.
+ */
+static inline uint32_t spi_get_peripheral_select_mode(Spi *p_spi)
+{
+       if (p_spi->SPI_MR & SPI_MR_PS) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+/**
+ * \brief Enable Peripheral Select Decode.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+static inline void spi_enable_peripheral_select_decode(Spi *p_spi)
+{
+       p_spi->SPI_MR |= SPI_MR_PCSDEC;
+}
+
+/**
+ * \brief Disable Peripheral Select Decode.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+static inline void spi_disable_peripheral_select_decode(Spi *p_spi)
+{
+       p_spi->SPI_MR &= (~SPI_MR_PCSDEC);
+}
+
+/**
+ * \brief Get Peripheral Select Decode mode.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ *
+ * \return 1 for decode mode, 0 for direct mode.
+ */
+static inline uint32_t spi_get_peripheral_select_decode_setting(Spi *p_spi)
+{
+       if (p_spi->SPI_MR & SPI_MR_PCSDEC) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+/**
+ * \brief Enable Mode Fault Detection.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+static inline void spi_enable_mode_fault_detect(Spi *p_spi)
+{
+       p_spi->SPI_MR &= (~SPI_MR_MODFDIS);
+}
+
+/**
+ * \brief Disable Mode Fault Detection.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+static inline void spi_disable_mode_fault_detect(Spi *p_spi)
+{
+       p_spi->SPI_MR |= SPI_MR_MODFDIS;
+}
+
+/**
+ * \brief Check if mode fault detection is enabled.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ *
+ * \return 1 for disabled, 0 for enabled.
+ */
+static inline uint32_t spi_get_mode_fault_detect_setting(Spi *p_spi)
+{
+       if (p_spi->SPI_MR & SPI_MR_MODFDIS) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+/**
+ * \brief Enable waiting RX_EMPTY before transfer starts.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+static inline void spi_enable_tx_on_rx_empty(Spi *p_spi)
+{
+       p_spi->SPI_MR |= SPI_MR_WDRBT;
+}
+
+/**
+ * \brief Disable waiting RX_EMPTY before transfer starts.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+static inline void spi_disable_tx_on_rx_empty(Spi *p_spi)
+{
+       p_spi->SPI_MR &= (~SPI_MR_WDRBT);
+}
+
+/**
+ * \brief Check if SPI waits RX_EMPTY before transfer starts.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ *
+ * \return 1 for SPI waits, 0 for no wait.
+ */
+static inline uint32_t spi_get_tx_on_rx_empty_setting(Spi *p_spi)
+{
+       if (p_spi->SPI_MR & SPI_MR_WDRBT) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+/**
+ * \brief Enable loopback mode.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+static inline void spi_enable_loopback(Spi *p_spi)
+{
+       p_spi->SPI_MR |= SPI_MR_LLB;
+}
+
+/**
+ * \brief Disable loopback mode.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ */
+static inline void spi_disable_loopback(Spi *p_spi)
+{
+       p_spi->SPI_MR &= (~SPI_MR_LLB);
+}
+
+void spi_enable_clock(Spi *p_spi);
+void spi_disable_clock(Spi *p_spi);
+void spi_set_peripheral_chip_select_value(Spi *p_spi, uint32_t ul_value);
+void spi_set_delay_between_chip_select(Spi *p_spi, uint32_t ul_delay);
+spi_status_t spi_read(Spi *p_spi, uint16_t *us_data, uint8_t *p_pcs);
+spi_status_t spi_write(Spi *p_spi, uint16_t us_data, uint8_t uc_pcs,
+               uint8_t uc_last);
+
+/**
+ * \brief Read status register.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ *
+ * \return SPI status register value.
+ */
+static inline uint32_t spi_read_status(Spi *p_spi)
+{
+       return p_spi->SPI_SR;
+}
+
+/**
+ * \brief Test if the SPI is enabled.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ *
+ * \return 1 if the SPI is enabled, otherwise 0.
+ */
+static inline uint32_t spi_is_enabled(Spi *p_spi)
+{
+       if (p_spi->SPI_SR & SPI_SR_SPIENS) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+/**
+ * \brief Put one data to a SPI peripheral.
+ *
+ * \param p_spi Base address of the SPI instance.
+ * \param data The data byte to be loaded
+ *
+ */
+static inline void spi_put(Spi *p_spi, uint16_t data)
+{
+       p_spi->SPI_TDR = SPI_TDR_TD(data);
+}
+
+/** \brief Get one data to a SPI peripheral.
+ *
+ * \param p_spi Base address of the SPI instance.
+ * \return The data byte
+ *
+ */
+static inline uint16_t spi_get(Spi *p_spi)
+{
+       return (p_spi->SPI_RDR & SPI_RDR_RD_Msk);
+}
+
+/**
+ * \brief Check if all transmissions are complete.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ *
+ * \retval 1 if transmissions are complete.
+ * \retval 0 if transmissions are not complete.
+ */
+static inline uint32_t spi_is_tx_empty(Spi *p_spi)
+{
+       if (p_spi->SPI_SR & SPI_SR_TXEMPTY) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+/**
+ * \brief Check if all transmissions are ready.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ *
+ * \retval 1 if transmissions are complete.
+ * \retval 0 if transmissions are not complete.
+ */
+static inline uint32_t spi_is_tx_ready(Spi *p_spi)
+{
+       if (p_spi->SPI_SR & SPI_SR_TDRE) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+/**
+ * \brief Check if the SPI contains a received character.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ *
+ * \return 1 if the SPI Receive Holding Register is full, otherwise 0.
+ */
+static inline uint32_t spi_is_rx_full(Spi *p_spi)
+{
+       if (p_spi->SPI_SR & SPI_SR_RDRF) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+/**
+ * \brief Check if all receptions are ready.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ *
+ * \return 1 if the SPI Receiver is ready, otherwise 0.
+ */
+static inline uint32_t spi_is_rx_ready(Spi *p_spi)
+{
+       if ((p_spi->SPI_SR & (SPI_SR_RDRF | SPI_SR_TXEMPTY))
+                       == (SPI_SR_RDRF | SPI_SR_TXEMPTY)) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+/**
+ * \brief Enable SPI interrupts.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ * \param ul_sources Interrupts to be enabled.
+ */
+static inline void spi_enable_interrupt(Spi *p_spi, uint32_t ul_sources)
+{
+       p_spi->SPI_IER = ul_sources;
+}
+
+/**
+ * \brief Disable SPI interrupts.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ * \param ul_sources Interrupts to be disabled.
+ */
+static inline void spi_disable_interrupt(Spi *p_spi, uint32_t ul_sources)
+{
+       p_spi->SPI_IDR = ul_sources;
+}
+
+/**
+ * \brief Read SPI interrupt mask.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ *
+ * \return The interrupt mask value.
+ */
+static inline uint32_t spi_read_interrupt_mask(Spi *p_spi)
+{
+       return p_spi->SPI_IMR;
+}
+
+void spi_set_clock_polarity(Spi *p_spi, uint32_t ul_pcs_ch,
+               uint32_t ul_polarity);
+void spi_set_clock_phase(Spi *p_spi, uint32_t ul_pcs_ch, uint32_t ul_phase);
+void spi_configure_cs_behavior(Spi *p_spi, uint32_t ul_pcs_ch,
+               uint32_t ul_cs_behavior);
+void spi_set_bits_per_transfer(Spi *p_spi, uint32_t ul_pcs_ch, uint32_t ul_bits);
+int16_t spi_calc_baudrate_div(const uint32_t baudrate, uint32_t mck);
+void spi_set_baudrate_div(Spi *p_spi, uint32_t ul_pcs_ch,
+               uint8_t uc_baudrate_divider);
+void spi_set_transfer_delay(Spi *p_spi, uint32_t ul_pcs_ch, uint8_t uc_dlybs,
+               uint8_t uc_dlybct);
+
+#if (SAM3S || SAM3N || SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM)
+/**
+ * \brief Get PDC registers base address.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ *
+ * \return PDC registers base for PDC driver to access.
+ */
+static inline Pdc *spi_get_pdc_base(Spi *p_spi)
+{
+       return (Pdc *)&(p_spi->SPI_RPR);
+}
+#endif
+
+#if (SAM3U  || SAM3XA)
+/**
+ * \brief Get transmit data register address for DMA operation.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ *
+ * \return Transmit address for DMA access.
+ */
+static inline void *spi_get_tx_access(Spi *p_spi)
+{
+       return (void *)&(p_spi->SPI_TDR);
+}
+
+/**
+ * \brief Get receive data register address for DMA operation.
+ *
+ * \param p_spi Pointer to an SPI instance.
+ *
+ * \return Receive address for DMA access.
+ */
+static inline void *spi_get_rx_access(Spi *p_spi)
+{
+       return (void *)&(p_spi->SPI_RDR);
+}
+#endif
+
+void spi_set_writeprotect(Spi *p_spi, uint32_t ul_enable);
+uint32_t spi_get_writeprotect_status(Spi *p_spi);
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+}
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+/**
+ * \page sam_spi_quickstart Quickstart guide for SAM SPI driver
+ *
+ * This is the quickstart guide for the \ref spi_group "SAM SPI driver",
+ * with step-by-step instructions on how to configure and use the driver in a
+ * selection of use cases.
+ *
+ * The use cases contain several code fragments. The code fragments in the
+ * steps for setup can be copied into a custom initialization function, while
+ * the steps for usage can be copied into, e.g.the main application function.
+ *
+ * \section spi_basic_use_case Basic use case
+ * In this basic use case, the SPI module are configured for:
+ * - Master mode
+ * - Interrupt-based handling
+ *
+ * \subsection sam_spi_quickstart_prereq Prerequisites
+ * -# \ref sysclk_group "System Clock Management (Sysclock)"
+ *
+ * \section spi_basic_use_case_setup Setup steps
+ * \subsection spi_basic_use_case_setup_code Example code
+ * Add to application C-file:
+ * \code
+          void spi_master_init(Spi *p_spi)
+          {
+              spi_enable_clock(p_spi);
+              spi_reset(p_spi);
+              spi_set_master_mode(p_spi);
+              spi_disable_mode_fault_detect(p_spi);
+              spi_disable_loopback(p_spi);
+              spi_set_peripheral_chip_select_value(p_spi,
+                                                   spi_get_pcs(DEFAULT_CHIP_ID));
+              spi_set_fixed_peripheral_select(p_spi);
+              spi_disable_peripheral_select_decode(p_spi);
+              spi_set_delay_between_chip_select(p_spi, CONFIG_SPI_MASTER_DELAY_BCS);
+          }
+          void spi_master_setup_device(Spi *p_spi, struct spi_device *device,
+              spi_flags_t flags, uint32_t baud_rate, board_spi_select_id_t sel_id)
+          {
+              spi_set_transfer_delay(p_spi, device->id, CONFIG_SPI_MASTER_DELAY_BS,
+                                     CONFIG_SPI_MASTER_DELAY_BCT);
+
+              spi_set_bits_per_transfer(p_spi, device->id, CONFIG_SPI_MASTER_BITS_PER_TRANSFER);
+              spi_set_baudrate_div(p_spi, device->id,
+                                   spi_calc_baudrate_div(baud_rate, sysclk_get_cpu_hz()));
+
+              spi_configure_cs_behavior(p_spi, device->id, SPI_CS_KEEP_LOW);
+
+              spi_set_clock_polarity(p_spi, device->id, flags >> 1);
+              spi_set_clock_phase(p_spi, device->id, ((flags & 0x1) ^ 0x1));
+          }
+\endcode
+ *
+ * \subsection spi_basic_use_case_setup_flow Workflow
+ * -# Initialize the SPI in master mode:
+ *   - \code
+       void spi_master_init(SPI_EXAMPLE);
+\endcode
+ * -# Set up an SPI device:
+ *   - \code void spi_master_setup_device(SPI_EXAMPLE, &SPI_DEVICE_EXAMPLE,
+               SPI_MODE_0, SPI_EXAMPLE_BAUDRATE, 0); \endcode
+ *   - \note The returned device descriptor structure must be passed to the driver
+ *      whenever that device should be used as current slave device.
+ * -# Enable SPI module:
+ *   - \code spi_enable(SPI_EXAMPLE); \endcode
+ */
+#endif /* SPI_H_INCLUDED */
diff --git a/asf/sam/drivers/wdt/wdt.c b/asf/sam/drivers/wdt/wdt.c
new file mode 100644 (file)
index 0000000..bce2ccb
--- /dev/null
@@ -0,0 +1,169 @@
+/**
+ * \file
+ *
+ * \brief Watchdog Timer (WDT) driver for SAM.
+ *
+ * Copyright (c) 2011-2014 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL AT