summaryrefslogtreecommitdiffstats
path: root/bsps/arm
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-22 15:11:43 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-23 15:18:42 +0200
commit54aabb70eb9ad64d3bcb9f95968de6a4473ebe3b (patch)
treeb331279d24731b596df743fb7752d67bc30f3545 /bsps/arm
parentbsp/altera-cyclone-v: Move hwlib to bsps (diff)
downloadrtems-54aabb70eb9ad64d3bcb9f95968de6a4473ebe3b.tar.bz2
bsp/atsam: Move libraries to bsps
This patch is a part of the BSP source reorganization. Update #3285.
Diffstat (limited to 'bsps/arm')
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/board.h45
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/board_v71_xult.h778
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/bmp.h119
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/board_lowlevel.h47
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/board_memories.h52
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/cs2100.h93
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/dbg_console.h55
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/frame_buffer.h83
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/gmacb_phy.h114
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/gmii.h116
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/ili9488.h106
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_dma.h92
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_ebi.h63
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_ebi_dma.h55
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_reg.h131
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_spi.h69
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_spi_dma.h56
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/image_sensor_inf.h136
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/lcd_color.h109
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/lcd_draw.h186
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/lcd_font.h108
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/lcd_font10x14.h45
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/lcd_gimp_image.h42
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/lcdd.h52
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/led.h72
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/math.h42
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/mcan_config.h126
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/rtc_calib.h49
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/s25fl1.h255
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/include/wm8904.h160
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/resources_v71/system_samv71.c318
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/source/board_lowlevel.c434
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/source/board_memories.c293
-rw-r--r--bsps/arm/atsam/contrib/libraries/libboard/source/dbg_console.c564
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/acc.c159
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/aes.c286
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/afe_dma.c256
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/afec.c458
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/dac_dma.c238
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/efc.c280
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/exceptions.c214
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/flashd.c595
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/gmac.c685
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/gmacd.c1054
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/hsmci.c569
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/icm.c234
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/isi.c385
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/mcan.c1175
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/mediaLB.c58
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/mpu.c168
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/pio.c499
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/pio_capture.c255
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/pio_it.c283
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/pmc.c597
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/pwmc.c579
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/qspi.c757
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/qspi_dma.c619
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/rstc.c167
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/rtc.c452
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/rtt.c134
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/sdramc.c212
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/spi.c282
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/spi_dma.c392
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/ssc.c219
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/supc.c193
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/tc.c213
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/trng.c122
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/twi.c382
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/twid.c752
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/uart.c232
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/uart_dma.c616
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/usart.c466
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/usart_dma.c600
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/wdt.c133
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/xdma_hardware_interface.c158
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/xdmad.c495
-rw-r--r--bsps/arm/atsam/contrib/utils/utility.h111
-rw-r--r--bsps/arm/atsam/start/iocopy.c49
78 files changed, 21848 insertions, 0 deletions
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/board.h b/bsps/arm/atsam/contrib/libraries/libboard/board.h
new file mode 100644
index 0000000000..d69d21276a
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/board.h
@@ -0,0 +1,45 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+#ifndef _BOARD_H_
+#define _BOARD_H_
+
+#ifdef __rtems__
+#include <bspopts.h>
+#endif /* __rtems__ */
+#if defined(BOARD_SAMV71_XULT)
+ #include "board_v71_xult.h"
+#elif defined(BOARD_SAME70_XPLD)
+ #include "board_e70_xpld.h"
+#else
+ #error "board definition not correct!"
+#endif
+
+#endif /* #ifndef _BOARD_H_ */
+
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/board_v71_xult.h b/bsps/arm/atsam/contrib/libraries/libboard/board_v71_xult.h
new file mode 100644
index 0000000000..6492191000
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/board_v71_xult.h
@@ -0,0 +1,778 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \page samv7_Xplained_ultra_board_desc SAM V71 Xplained Ultra - Board
+ * Description
+ *
+ * \section Purpose
+ *
+ * This file is dedicated to describe the SAM V71 Xplained Ultra board.
+ *
+ * \section Contents
+ *
+ * - For SAM V71 Xplained Ultra board information, see
+ * \subpage samv7_Xplained_ultra_board_info.
+ * - For operating frequency information, see \subpage samv7_Xplained_ultra_opfreq.
+ * - For using portable PIO definitions, see \subpage samv7_Xplained_ultra_piodef.
+ * - For using GMAC PIO definitions, see \subpage samv7_Xplained_ultra_gmac.
+ * - For using ISI definitions, see \subpage samv7_Xplained_ultra_isi.
+ * - For on-board memories, see \subpage samv7_Xplained_ultra_mem.
+ * - Several USB definitions are included here,
+ * see \subpage samv7_Xplained_ultra_usb.
+ * - For External components, see \subpage samv7_Xplained_ultra_extcomp.
+ * - For Individual chip definition, see \subpage samv7_Xplained_ultra_chipdef.
+ *
+ * To get more software details and the full list of parameters related to the
+ * SAM V71 Xplained Ultra board configuration, please have a look at the source
+ * file:
+ * \ref board.h, \ref board_v71_xult.h\n
+ *
+ * \section Usage
+ *
+ * - The code for booting the board is provided by startup_samv71.c and
+ * board_lowlevel.c.
+ * - For using board PIOs, board characteristics (clock, etc.) and external
+ * components, see board.h, board_v71_xult.h.
+ * - For manipulating memories, see board_memories.h.
+ *
+ * This file can be used as a template and modified to fit a custom board, with
+ * specific PIOs usage or memory connections.
+ */
+
+/**
+ * \file board.h
+ *
+ * Definition of SAM V71 Xplained Ultra board characteristics, PIOs and
+ * external components interface.
+ */
+
+#ifndef _BOARD_V71_XULT_H_
+#define _BOARD_V71_XULT_H_
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+#include "include/board_lowlevel.h"
+#include "include/board_memories.h"
+#include "include/led.h"
+#include "include/gmii.h"
+#include "include/gmacb_phy.h"
+#include "include/dbg_console.h"
+#include "include/bmp.h"
+#include "include/lcdd.h"
+#include "include/ili9488.h"
+#include "include/ili9488_reg.h"
+#include "include/ili9488_spi.h"
+#include "include/ili9488_ebi.h"
+#include "include/ili9488_dma.h"
+#include "include/ili9488_spi_dma.h"
+#include "include/ili9488_ebi_dma.h"
+#include "include/frame_buffer.h"
+#include "include/lcd_color.h"
+#include "include/lcd_draw.h"
+#include "include/lcd_font10x14.h"
+#include "include/lcd_font.h"
+#include "include/lcd_gimp_image.h"
+#include "include/rtc_calib.h"
+#include "include/wm8904.h"
+#include "include/cs2100.h"
+#include "include/s25fl1.h"
+#include "include/image_sensor_inf.h"
+#include "include/iso7816_4.h"
+
+#ifndef __rtems__
+#if defined (__GNUC__)
+ #include "include/syscalls.h"
+#endif
+#endif /* __rtems__ */
+/*----------------------------------------------------------------------------
+ * Definitions
+ *----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/**
+ * \page samv7_Xplained_ultra_board_info "SAM V71 Xplained Ultra - Board informations"
+ * This page lists several definition related to the board description.
+ *
+ * \section Definitions
+ * - \ref BOARD_NAME
+ */
+
+/** Name of the board */
+#define BOARD_NAME "SAM V71 Xplained Ultra"
+#define NO_PUSHBUTTON
+#ifndef __rtems__
+/*----------------------------------------------------------------------------*/
+/**
+ * \page samv7_Xplained_ultra_opfreq "SAM V71 Xplained Ultra - Operating frequencies"
+ * This page lists several definition related to the board operating frequency
+ * (when using the initialization done by board_lowlevel.c).
+ *
+ * \section Definitions
+ * - \ref BOARD_MAINOSC
+ * - \ref BOARD_MCK
+ */
+
+/** Frequency of the board main oscillator */
+#define BOARD_MAINOSC 12000000
+
+/** Master clock frequency (when using board_lowlevel.c) */
+
+#ifdef MCK_123MHZ
+ #define BOARD_MCK 123000000
+#else
+ #define BOARD_MCK 150000000
+#endif
+
+#if (BOARD_MCK==123000000)
+
+ #define PLL_MUL 0x16
+ #define PLL_DIV 0x01
+
+#else // 300MHz(PCK) and 150MHz(MCK) by default
+
+ #define PLL_MUL 0x19
+ #define PLL_DIV 0x01
+
+#endif
+#else /* __rtems__ */
+#include <bsp/atsam-clock-config.h>
+#endif /* __rtems__ */
+
+/*----------------------------------------------------------------------------*/
+/**
+ * \page samv7_Xplained_ultra_piodef "SAM V71 Xplained Ultra - PIO definitions"
+ * This pages lists all the PIOs definitions contained in board.h. The constants
+ * are named using the following convention: PIN_* for a constant which defines
+ * a single Pin instance (but may include several PIOs sharing the same
+ * controller), and PINS_* for a list of Pin instances.
+ *
+ * UART0
+ * - \ref PINS_UART0
+ *
+ * UART4
+ * - \ref PINS_UART4
+ *
+ * LEDs
+ * - \ref PIN_LED_0
+ * - \ref PIN_LED_1
+ * - \ref PINS_LEDS
+ *
+ * Push buttons
+ * - \ref PIN_PUSHBUTTON_0
+ * - \ref PIN_PUSHBUTTON_1
+ * - \ref PINS_PUSHBUTTONS
+ * - \ref PUSHBUTTON_BP0
+ * - \ref PUSHBUTTON_BP1
+ *
+ * PWMC
+ * - \ref PIN_PWMC_PWMH0
+ * - \ref PIN_PWMC_PWMH1
+ * - \ref PIN_PWM_LED0
+ * - \ref PIN_PWM_LED1
+ * - \ref CHANNEL_PWM_LED0
+ * - \ref CHANNEL_PWM_LED1
+ *
+ * SPI
+ * - \ref PIN_SPI_MISO
+ * - \ref PIN_SPI_MOSI
+ * - \ref PIN_SPI_SPCK
+ * - \ref PINS_SPI
+ *
+ * PCK0
+ * - \ref PIN_PCK0
+ * - \ref PIN_PCK1
+ * - \ref PIN_PCK2
+ *
+ * PIO PARALLEL CAPTURE
+ * - \ref PIN_PIODCEN1
+ * - \ref PIN_PIODCEN2
+ *
+ * TWI
+ * - \ref TWI_V3XX
+ * - \ref PIN_TWI_TWD0
+ * - \ref PIN_TWI_TWCK0
+ * - \ref PINS_TWI0
+ * - \ref PIN_TWI_TWD1
+ * - \ref PIN_TWI_TWCK1
+ * - \ref PINS_TWI1
+ *
+ * USART0
+ * - \ref PIN_USART0_RXD
+ * - \ref PIN_USART0_TXD
+ * - \ref PIN_USART0_CTS
+ * - \ref PIN_USART0_RTS
+ * - \ref PIN_USART0_SCK
+ *
+ * USART1
+ * - \ref PIN_USART1_RXD
+ * - \ref PIN_USART1_TXD
+ * - \ref PIN_USART1_CTS
+ * - \ref PIN_USART1_RTS
+ * - \ref PIN_USART1_SCK
+ *
+ * USART2
+ * - \ref PIN_USART2_RXD
+ * - \ref PIN_USART2_TXD
+ * - \ref PIN_USART2_CTS
+ * - \ref PIN_USART2_RTS
+ * - \ref PIN_USART2_SCK
+ *
+ * SSC
+ * - \ref PIN_SSC_TD
+ * - \ref PIN_SSC_TK
+ * - \ref PIN_SSC_TF
+ * - \ref PIN_SSC_RD
+ * - \ref PIN_SSC_RK
+ * - \ref PIN_SSC_RF
+ * - \ref PIN_SSC_TD
+ * - \ref PINS_SSC_CODEC
+ *
+ * MCAN
+ * - \ref PIN_MCAN0_TXD
+ * - \ref PIN_MCAN0_RXD
+ * - \ref PIN_MCAN1_TXD
+ * - \ref PIN_MCAN1_RXD
+ */
+
+/** SSC pin Transmitter Data (TD) */
+#define PIN_SSC_TD {PIO_PD26B_TD, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+/** SSC pin Transmitter Clock (TK) */
+#define PIN_SSC_TK {PIO_PB1D_TK, PIOB, ID_PIOB, PIO_PERIPH_D, PIO_DEFAULT}
+/** SSC pin Transmitter FrameSync (TF) */
+#define PIN_SSC_TF {PIO_PB0D_TF, PIOB, ID_PIOB, PIO_PERIPH_D, PIO_DEFAULT}
+/** SSC pin RD */
+#define PIN_SSC_RD {PIO_PA10C_RD, PIOA, ID_PIOA, PIO_PERIPH_C, PIO_DEFAULT}
+/** SSC pin RK */
+#define PIN_SSC_RK {PIO_PA22A_RK, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/** SSC pin RF */
+#define PIN_SSC_RF {PIO_PD24B_RF, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+
+/** SSC pins definition for codec. */
+#define PINS_SSC_CODEC \
+ {PIN_SSC_TD, PIN_SSC_TK, PIN_SSC_TF, PIN_SSC_RD, PIN_SSC_RK, PIN_SSC_RF}
+
+/** UART pins (UTXD0 and URXD0) definitions, PA9,10. */
+#define PINS_UART0 \
+ {PIO_PA9A_URXD0 | PIO_PA10A_UTXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/** UART pins (UTXD4 and URXD4) definitions, PD19,18. */
+#define PINS_UART4 \
+ {PIO_PD18C_URXD4 | PIO_PD19C_UTXD4, PIOD, ID_PIOD, PIO_PERIPH_C, PIO_DEFAULT}
+
+/* LED pins definitions */
+#define LED_YELLOW0 0
+#define LED_YELLOW1 1
+
+/** LED #0 pin definition (YELLOW). */
+#define PIN_LED_0 {PIO_PC9, PIOC, ID_PIOC, PIO_OUTPUT_1, PIO_DEFAULT}
+/** LED #1 pin definition (YELLOW). */
+#define PIN_LED_1 {PIO_PA23, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+
+/** List of all LEDs definitions. */
+#define PINS_LEDS {PIN_LED_0, PIN_LED_1}
+
+/** Number of LEDs */
+#define LED_NUM 2
+
+/**
+ * Push button #0 definition.
+ * Attributes = pull-up + debounce + interrupt on rising edge.
+ */
+#define PIN_PUSHBUTTON_0 \
+ {PIO_PA9, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE | PIO_IT_FALL_EDGE}
+/**
+ * Push button #1 definition.
+ * Attributes = pull-up + debounce + interrupt on rising edge.
+ */
+#define PIN_PUSHBUTTON_1 \
+ {PIO_PB12, PIOB, ID_PIOB, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE | PIO_IT_FALL_EDGE}
+
+/** List of all push button definitions. */
+#define PINS_PUSHBUTTONS {PIN_PUSHBUTTON_0, PIN_PUSHBUTTON_1}
+
+/** Push button #0 index. */
+#define PUSHBUTTON_BP0 0
+/** Push button #1 index. */
+#define PUSHBUTTON_BP1 1
+
+/** Number of Buttons */
+#define BUTTON_NUM 2
+
+/** Index of wakeup source */
+#define WKUP_IDX 6
+
+/** PWMC PWM0 pin definition: Output High. */
+#define PIN_PWMC_PWMH0 {PIO_PD20A_PWMH0, PIOD, ID_PIOD, PIO_PERIPH_A, PIO_DEFAULT}
+/** PWMC PWM1 pin definition: Output High. */
+#define PIN_PWMC_PWMH1 {PIO_PD21A_PWMH1, PIOD, ID_PIOD, PIO_PERIPH_A, PIO_DEFAULT}
+/** PWM pins definition for LED0 */
+#define PIN_PWM_LED0 PIN_PWMC_PWMH0
+/** PWM pins definition for LED1 */
+#define PIN_PWM_LED1 PIN_PWMC_PWMH1
+/** PWM channel for LED0 */
+#define CHANNEL_PWM_LED0 0
+/** PWM channel for LED1 */
+#define CHANNEL_PWM_LED1 1
+
+/** SPI MISO pin definition. */
+#define PIN_SPI_MISO {PIO_PD20B_SPI0_MISO, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+/** SPI MOSI pin definition. */
+#define PIN_SPI_MOSI {PIO_PD21B_SPI0_MOSI, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+/** SPI SPCK pin definition. */
+#define PIN_SPI_SPCK {PIO_PD22B_SPI0_SPCK, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+/** SPI chip select pin definition. */
+#define PIN_SPI_NPCS0 {PIO_PB2D_SPI0_NPCS0, PIOB, ID_PIOB, PIO_PERIPH_D, PIO_DEFAULT}
+#define PIN_SPI_NPCS1 {PIO_PD25B_SPI0_NPCS1, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+#define PIN_SPI_NPCS3 {PIO_PD27B_SPI0_NPCS3, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+
+/** List of SPI pin definitions (MISO, MOSI & SPCK). */
+#define PINS_SPI PIN_SPI_MISO, PIN_SPI_MOSI, PIN_SPI_SPCK
+
+/** PCK0 */
+#define PIN_PCK0 {PIO_PB13B_PCK0, PIOB, ID_PIOB, PIO_PERIPH_B, PIO_DEFAULT}
+/** PCK1 */
+#define PIN_PCK1 {PIO_PA17B_PCK1, PIOB, ID_PIOB, PIO_PERIPH_B, PIO_DEFAULT}
+/** PCK2 */
+#define PIN_PCK2 {PIO_PA18B_PCK2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+
+
+/** PIO PARALLEL CAPTURE */
+/** Parallel Capture Mode Data Enable1 */
+#define PIN_PIODCEN1 PIO_PA15
+/** Parallel Capture Mode Data Enable2 */
+#define PIN_PIODCEN2 PIO_PA16
+
+/** TWI version 3.xx */
+#define TWI_V3XX
+/** TWI0 data pin */
+#define PIN_TWI_TWD0 {PIO_PA3A_TWD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/** TWI0 clock pin */
+#define PIN_TWI_TWCK0 {PIO_PA4A_TWCK0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/** TWI0 pins */
+#define PINS_TWI0 {PIN_TWI_TWD0, PIN_TWI_TWCK0}
+
+/** TWI1 data pin */
+#define PIN_TWI_TWD1 {PIO_PB4A_TWD1, PIOB, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT}
+/** TWI1 clock pin */
+#define PIN_TWI_TWCK1 {PIO_PB5A_TWCK1, PIOB, ID_PIOB, PIO_PERIPH_A,PIO_DEFAULT}
+/** TWI1 pins */
+#define PINS_TWI1 {PIN_TWI_TWD1, PIN_TWI_TWCK1}
+
+/** USART0 pin RX */
+#define PIN_USART0_RXD {PIO_PB0C_RXD0, PIOB, ID_PIOB, PIO_PERIPH_C, PIO_DEFAULT}
+/** USART0 pin TX */
+#define PIN_USART0_TXD {PIO_PB1C_TXD0, PIOB, ID_PIOB, PIO_PERIPH_C, PIO_DEFAULT}
+/** USART0 pin CTS */
+#define PIN_USART0_CTS {PIO_PB2C_CTS0, PIOB, ID_PIOB, PIO_PERIPH_C, PIO_DEFAULT}
+/** USART0 pin RTS */
+#define PIN_USART0_RTS {PIO_PB3C_RTS0, PIOB, ID_PIOB, PIO_PERIPH_C, PIO_DEFAULT}
+/** USART0 pin SCK */
+#define PIN_USART0_SCK {PIO_PB13C_SCK0, PIOB, ID_PIOB, PIO_PERIPH_C,PIO_DEFAULT}
+
+/** USART1 pin RX */
+#define PIN_USART1_RXD {PIO_PA21A_RXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/** USART1 pin TX */
+#define PIN_USART1_TXD {PIO_PB4D_TXD1, PIOB, ID_PIOB, PIO_PERIPH_D, PIO_DEFAULT}
+/** USART1 pin CTS */
+#define PIN_USART1_CTS {PIO_PA25A_CTS1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/** USART1 pin RTS */
+#define PIN_USART1_RTS {PIO_PA24A_RTS1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/** USART1 pin ENABLE */
+#define PIN_USART1_EN {PIO_PA23A_SCK1, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+/** USART1 pin SCK */
+#define PIN_USART1_SCK {PIO_PA23A_SCK1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+
+/** USART2 pin RX */
+#define PIN_USART2_RXD {PIO_PD15B_RXD2, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+/** USART2 pin TX */
+#define PIN_USART2_TXD {PIO_PD16B_TXD2, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+/** USART2 pin CTS */
+#define PIN_USART2_CTS {PIO_PD19B_CTS2, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+/** USART2 pin RTS */
+#define PIN_USART2_RTS {PIO_PD18B_RTS2, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+/** USART2 pin SCK */
+#define PIN_USART2_SCK {PIO_PD17B_SCK2, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+
+/*Pins for USART0 as 7816 mode*/
+/** PIN used for reset the smartcard */
+#define PIN_ISO7816_RSTMC {PIO_PB2C_CTS0, PIOB, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT}
+/** Pins used for connect the smartcard */
+#define PINS_ISO7816 PIN_USART0_TXD, PIN_USART0_SCK,PIN_ISO7816_RSTMC
+
+/** MCAN0 pin Transmit Data (TXD) */
+#define PIN_MCAN0_TXD {PIO_PB2A_CANTX0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/** MCAN0 pin Receive Data (RXD) */
+#define PIN_MCAN0_RXD {PIO_PB3A_CANRX0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+
+/** MCAN1 pin Transmit Data (TXD) */
+#define PIN_MCAN1_TXD {PIO_PC14C_CANTX1, PIOC, ID_PIOC, PIO_PERIPH_C, PIO_DEFAULT}
+/** MCAN1 pin Receive Data (RXD) */
+#define PIN_MCAN1_RXD {PIO_PC12C_CANRX1, PIOC, ID_PIOC, PIO_PERIPH_C, PIO_DEFAULT}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * \page samv7_Xplained_ultra_gmac "SAM V71 Xplained Ultra - GMAC"
+ * \section GMAC
+ * - \ref BOARD_GMAC_PHY_ADDR
+ * - \ref BOARD_GMAC_PHY_COMP_KSZ8061RNB
+ * - \ref BOARD_GMAC_MODE_RMII
+ * - \ref BOARD_GMAC_PINS
+ * - \ref BOARD_GMAC_RESET_PIN
+ *
+ */
+/** PHY address */
+#define BOARD_GMAC_PHY_ADDR 1
+/** PHY Component */
+#define BOARD_GMAC_PHY_COMP_KSZ8061RNB 1
+/** Board GMAC power control - ALWAYS ON */
+#define BOARD_GMAC_POWER_ALWAYS_ON
+/** Board GMAC work mode - RMII/MII (1 / 0) */
+#define BOARD_GMAC_MODE_RMII 1
+
+/** The PIN list of PIO for GMAC */
+#define BOARD_GMAC_PINS \
+ { (PIO_PD0A_GTXCK | PIO_PD1A_GTXEN | PIO_PD2A_GTX0 | PIO_PD3A_GTX1 \
+ | PIO_PD4A_GRXDV | PIO_PD5A_GRX0 | PIO_PD6A_GRX1 | PIO_PD7A_GRXER \
+ | PIO_PD8A_GMDC | PIO_PD9A_GMDIO),PIOD, ID_PIOD, PIO_PERIPH_A, PIO_DEFAULT}, \
+ {PIO_PC30, PIOC, ID_PIOC, PIO_INPUT, PIO_PULLUP},\
+ {PIO_PA29, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
+
+/** The PIN list of PIO for GMAC */
+#define BOARD_GMAC_RESET_PIN {PIO_PC10, PIOC, ID_PIOC, PIO_OUTPUT_1, PIO_PULLUP}
+
+/** The runtime pin configure list for GMAC */
+#define BOARD_GMAC_RUN_PINS BOARD_GMAC_PINS
+
+
+/*----------------------------------------------------------------------------*/
+/**
+ * \page samv7_Xplained_ultra_isi "SAM V71 Xplained Ultra - ISI"
+ * This page lists all the IO definitions connected to ISI module.
+ * ISI
+ * - \ref PIN_ISI_D0
+ * - \ref PIN_ISI_D1
+ * - \ref PIN_ISI_D2
+ * - \ref PIN_ISI_D3
+ * - \ref PIN_ISI_D4
+ * - \ref PIN_ISI_D5
+ * - \ref PIN_ISI_D6
+ * - \ref PIN_ISI_D7
+ * - \ref PIN_ISI_D8
+ * - \ref PIN_ISI_D9
+ * - \ref BOARD_ISI_VSYNC
+ * - \ref BOARD_ISI_HSYNC
+ * - \ref BOARD_ISI_PCK
+ * - \ref BOARD_ISI_PINS
+ *
+ */
+#define PIN_ISI_D0 {PIO_PD22D_ISI_D0, PIOD, ID_PIOD, PIO_PERIPH_D, PIO_PULLUP}
+#define PIN_ISI_D1 {PIO_PD21D_ISI_D1, PIOD, ID_PIOD, PIO_PERIPH_D, PIO_PULLUP}
+#define PIN_ISI_D2 {PIO_PB3D_ISI_D2, PIOB, ID_PIOB, PIO_PERIPH_D, PIO_PULLUP}
+#define PIN_ISI_D3 {PIO_PA9B_ISI_D3, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_PULLUP}
+#define PIN_ISI_D4 {PIO_PA5B_ISI_D4, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_PULLUP}
+#define PIN_ISI_D5 {PIO_PD11D_ISI_D5, PIOD, ID_PIOD, PIO_PERIPH_D, PIO_PULLUP}
+#define PIN_ISI_D6 {PIO_PD12D_ISI_D6, PIOD, ID_PIOD, PIO_PERIPH_D, PIO_PULLUP}
+#define PIN_ISI_D7 {PIO_PA27D_ISI_D7, PIOA, ID_PIOA, PIO_PERIPH_D, PIO_PULLUP}
+#define PIN_ISI_D8 {PIO_PD27D_ISI_D8, PIOD, ID_PIOD, PIO_PERIPH_D, PIO_PULLUP}
+#define PIN_ISI_D9 {PIO_PD28D_ISI_D9, PIOD, ID_PIOD, PIO_PERIPH_D, PIO_PULLUP}
+
+#define BOARD_ISI_VSYNC {PIO_PD25D_ISI_VSYNC, PIOD, ID_PIOD, PIO_PERIPH_D, PIO_DEFAULT}
+#define BOARD_ISI_HSYNC {PIO_PD24D_ISI_HSYNC, PIOD, ID_PIOD, PIO_PERIPH_D, PIO_DEFAULT}
+#define BOARD_ISI_PCK {PIO_PA24D_ISI_PCK, PIOA, ID_PIOA, PIO_PERIPH_D, PIO_DEFAULT}
+
+#define BOARD_ISI_PCK0 { PIO_PA6B_PCK0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT }
+#define BOARD_ISI_RST { 1 << 13, PIOB, ID_PIOB, PIO_OUTPUT_1, PIO_DEFAULT }
+#define BOARD_ISI_PWD { 1 << 19, PIOC, ID_PIOC, PIO_OUTPUT_1, PIO_DEFAULT }
+
+#define BOARD_ISI_PINS \
+ PIN_ISI_D0, PIN_ISI_D1, PIN_ISI_D2,PIN_ISI_D3,PIN_ISI_D4, PIN_ISI_D5,\
+ PIN_ISI_D6,PIN_ISI_D7,PIN_ISI_D8, PIN_ISI_D9,BOARD_ISI_VSYNC ,\
+ BOARD_ISI_HSYNC ,BOARD_ISI_PCK, BOARD_ISI_RST, BOARD_ISI_PWD,BOARD_ISI_PCK0
+
+/*----------------------------------------------------------------------------*/
+/**
+ * \page samv7_Xplained_ultra_usb "SAM V71 Xplained Ultra - USB device"
+ *
+ * \section Definitions
+ * - \ref BOARD_USB_BMATTRIBUTES
+ *
+ * \section vBus
+ * - \ref PIN_USB_VBUS
+ *
+ */
+
+/**
+ * USB attributes configuration descriptor (bus or self powered,
+ * remote wakeup)
+ */
+#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_SELFPOWERED_NORWAKEUP
+
+/** USB VBus monitoring pin definition. */
+#define PIN_USB_VBUS {PIO_PC16, PIOC, ID_PIOC, PIO_INPUT, PIO_DEFAULT}
+
+
+/*----------------------------------------------------------------------------*/
+/**
+ * \page samv7_Xplained_ultra_extcomp "SAM V71 Xplained Ultra - External components"
+ * This page lists the definitions related to external on-board components
+ * located in the board.h file for the SAM V71 Xplained Ultra board.
+ *
+ * LCD
+ */
+/** Indicates board has an ILI9325 external component to manage LCD. */
+#define BOARD_LCD_ILI9488
+//#define BOARD_LCD_SPI_EXT1
+#define BOARD_LCD_SPI_EXT2
+
+/** SPI pin definition for LCD */
+#if defined (BOARD_LCD_SPI_EXT1)
+/** SPI MISO pin definition. */
+#define LCD_SPI_MISO {PIO_PD20B_SPI0_MISO, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+/** SPI MOSI pin definition. */
+#define LCD_SPI_MOSI {PIO_PD21B_SPI0_MOSI, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+/** SPI SPCK pin definition. */
+#define LCD_SPI_SPCK {PIO_PD22B_SPI0_SPCK, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+/** SPI chip select pin definition. */
+#define LCD_SPI_NPCS {PIO_PD27B_SPI0_NPCS3, PIOD, ID_PIOD, PIO_PERIPH_B,PIO_DEFAULT}
+
+/** SPI chip select pin definition. */
+#define LCD_SPI_NPCS {PIO_PD25B_SPI0_NPCS1, PIOD, ID_PIOD, PIO_PERIPH_B,PIO_DEFAULT}
+
+/** LCD pins definition. */
+#define BOARD_SPI_LCD_PINS {LCD_SPI_MISO, LCD_SPI_MOSI, LCD_SPI_SPCK, LCD_SPI_NPCS}
+
+/** Back-light pin definition. */
+
+#define BOARD_SPI_LCD_BACKLIGHT_PIN \
+ {PIO_PA0A_PWMC0_PWMH0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+
+/** PWMC PWM0 pin definition: Output Low. */
+#define LCD_SPI_PIN_RESET {PIO_PD28, PIOD, ID_PIOD, PIO_OUTPUT_1, PIO_DEFAULT}
+
+/** PWM channel for LED0 */
+#define CHANNEL_PWM_LCD 0
+
+#endif
+/*ENDIF BOARD_LCD_SPI_EXT1 */
+
+#if defined (BOARD_LCD_SPI_EXT2)
+/** SPI MISO pin definition. */
+#define LCD_SPI_MISO {PIO_PD20B_SPI0_MISO, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+/** SPI MOSI pin definition. */
+#define LCD_SPI_MOSI {PIO_PD21B_SPI0_MOSI, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+/** SPI SPCK pin definition. */
+#define LCD_SPI_SPCK {PIO_PD22B_SPI0_SPCK, PIOD, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT}
+/** SPI chip select pin definition. */
+#define LCD_SPI_NPCS {PIO_PD27B_SPI0_NPCS3, PIOD, ID_PIOD, PIO_PERIPH_B,PIO_DEFAULT}
+
+/** LCD pins definition. */
+#define BOARD_SPI_LCD_PINS {LCD_SPI_MISO, LCD_SPI_MOSI, LCD_SPI_SPCK, LCD_SPI_NPCS}
+
+/** Back-light pin definition. */
+
+#define BOARD_SPI_LCD_PIN_BACKLIGHT \
+ {PIO_PC19B_PWMC0_PWMH2, PIOC, ID_PIOC, PIO_OUTPUT_1, PIO_DEFAULT}
+
+/** PWMC PWM0 pin definition: Output Low. */
+#define LCD_SPI_PIN_RESET {PIO_PA24, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+
+/** LCD command/data select pin */
+#define BOARD_SPI_LCD_PIN_CDS {PIO_PA6, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+
+/** PWM channel for LED0 */
+#define CHANNEL_PWM_LCD 2
+
+#endif
+/*ENDIF BOARD_LCD_SPI_EXT2 */
+
+/** SMC pin definition for LCD */
+/** LCD data pin */
+#define PIN_EBI_LCD_DATAL {0xFF, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_PULLUP}
+#define PIN_EBI_LCD_DATAH_0 {0x3F, PIOE, ID_PIOE, PIO_PERIPH_A, PIO_PULLUP}
+#define PIN_EBI_LCD_DATAH_1 {PIO_PA15A_D14|PIO_PA16A_D15, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_PULLUP}
+/** LCD WE pin */
+#define PIN_EBI_LCD_NWE {PIO_PC8A_NWE, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_PULLUP}
+/** LCD RD pin */
+#define PIN_EBI_LCD_NRD {PIO_PC11A_NRD, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_PULLUP}
+/* LCD CS pin (NCS3) */
+#define PIN_EBI_LCD_CS {PIO_PD19A_NCS3, PIOD, ID_PIOD, PIO_PERIPH_A, PIO_PULLUP}
+/** LCD command/data select pin */
+#define BOARD_EBI_LCD_PIN_CDS {PIO_PC30, PIOC, ID_PIOC, PIO_OUTPUT_1, PIO_DEFAULT}
+/** Back-light pin definition. */
+#define BOARD_EBI_LCD_PIN_BACKLIGHT {PIO_PC9B_TIOB7, PIOC, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT}
+/** LCD reset pin */
+#define LCD_EBI_PIN_RESET {PIO_PC13, PIOC, ID_PIOC, PIO_OUTPUT_1, PIO_DEFAULT}
+
+/** LCD pins definition. */
+#define BOARD_EBI_LCD_PINS \
+ {PIN_EBI_LCD_DATAL, PIN_EBI_LCD_DATAH_0, PIN_EBI_LCD_DATAH_1, \
+ PIN_EBI_LCD_NWE,PIN_EBI_LCD_NRD,PIN_EBI_LCD_CS}
+
+
+/** Display width in pixels. */
+#define BOARD_LCD_WIDTH 320
+/** Display height in pixels. */
+#define BOARD_LCD_HEIGHT 480
+
+
+/*----------------------------------------------------------------------------*/
+/**
+ * \page samv7_Xplained_ultra_mem "SAM V71 Xplained Ultra - Memories"
+ * This page lists definitions related to internal & external on-board memories.
+ * \section SDRAM
+ * - \ref PIN_SDRAM_D0_7
+ * - \ref PIN_SDRAM_D8_13
+ * - \ref PIN_SDRAM_D14_15
+ * - \ref PIN_SDRAM_A0_9
+ * - \ref PIN_SDRAM_SDA10
+ * - \ref PIN_SDRAM_CAS
+ * - \ref PIN_SDRAM_RAS
+ * - \ref PIN_SDRAM_SDCKE
+ * - \ref PIN_SDRAM_SDCK
+ * - \ref PIN_SDRAM_SDSC
+ * - \ref PIN_SDRAM_NBS0
+ * - \ref PIN_SDRAM_NBS1
+ * - \ref PIN_SDRAM_SDWE
+ * - \ref PIN_SDRAM_BA0
+ *
+ * \section SDMMC
+ * - \ref BOARD_MCI_PIN_CD
+ * - \ref BOARD_MCI_PIN_CK
+ * - \ref BOARD_MCI_PINS_SLOTA
+ * - \ref BOARD_SD_PINS
+ *
+ * \section QSPI
+ * - \ref PINS_QSPI_IO
+ * - \ref PINS_QSPI_IO3
+ * - \ref PINS_QSPI
+ */
+
+/** List of all SDRAM pin definitions. */
+#define BOARD_SDRAM_SIZE (2*1024*1024)
+#define PIN_SDRAM_D0_7 {0x000000FF, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_DEFAULT}
+#define PIN_SDRAM_D8_13 {0x0000003F, PIOE, ID_PIOE, PIO_PERIPH_A, PIO_DEFAULT}
+#define PIN_SDRAM_D14_15 {0x00018000, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+#define PIN_SDRAM_A0_9 {0x3FF00000, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_DEFAULT}
+#define PIN_SDRAM_SDA10 {0x00002000, PIOD, ID_PIOD, PIO_PERIPH_C, PIO_DEFAULT}
+
+#define PIN_SDRAM_CAS {0x00020000, PIOD, ID_PIOD, PIO_PERIPH_C, PIO_DEFAULT}
+#define PIN_SDRAM_RAS {0x00010000, PIOD, ID_PIOD, PIO_PERIPH_C, PIO_DEFAULT}
+#define PIN_SDRAM_SDCKE {0x00004000, PIOD, ID_PIOD, PIO_PERIPH_C, PIO_DEFAULT}
+#define PIN_SDRAM_SDCK {0x00800000, PIOD, ID_PIOD, PIO_PERIPH_C, PIO_DEFAULT}
+#define PIN_SDRAM_SDSC {0x00008000, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_DEFAULT}
+#define PIN_SDRAM_NBS0 {0x00040000, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_DEFAULT}
+#define PIN_SDRAM_NBS1 {0x00008000, PIOD, ID_PIOD, PIO_PERIPH_C, PIO_DEFAULT}
+#define PIN_SDRAM_SDWE {0x20000000, PIOD, ID_PIOD, PIO_PERIPH_C, PIO_DEFAULT}
+#define PIN_SDRAM_BA0 {0x00100000, PIOA, ID_PIOA, PIO_PERIPH_C, PIO_DEFAULT}
+
+#define BOARD_SDRAM_PINS PIN_SDRAM_D0_7, PIN_SDRAM_D8_13 , PIN_SDRAM_D14_15,\
+ PIN_SDRAM_A0_9, PIN_SDRAM_SDA10, PIN_SDRAM_BA0, \
+ PIN_SDRAM_CAS, PIN_SDRAM_RAS, PIN_SDRAM_SDCKE,PIN_SDRAM_SDCK,\
+ PIN_SDRAM_SDSC,PIN_SDRAM_NBS0 ,PIN_SDRAM_NBS1,PIN_SDRAM_SDWE
+
+
+/** List of all MCI pin definitions. */
+
+/** MCI0 Card detect pin definition. (PE5) */
+#define BOARD_MCI_PIN_CD {PIO_PD18, PIOD, ID_PIOD, PIO_INPUT, PIO_PULLUP}
+/** MCI0 Clock . */
+#define BOARD_MCI_PIN_CK {PIO_PA25D_MCCK, PIOA, ID_PIOA, PIO_PERIPH_D, PIO_DEFAULT}
+
+/** MCI0 Solt A IO pins definition. (PC4-PC13) */
+#define BOARD_MCI_PINS_SLOTA \
+ {(PIO_PA30C_MCDA0 | PIO_PA31C_MCDA1 | PIO_PA26C_MCDA2 | PIO_PA27C_MCDA3 | PIO_PA28C_MCCDA),\
+ PIOA, ID_PIOA, PIO_PERIPH_C, PIO_DEFAULT}
+
+/** MCI pins that shall be configured to access the SD card. */
+#define BOARD_SD_PINS {BOARD_MCI_PINS_SLOTA, BOARD_MCI_PIN_CK}
+/** MCI Card Detect pin. */
+#define BOARD_SD_PIN_CD BOARD_MCI_PIN_CD
+/** Total number of MCI interface */
+#define BOARD_NUM_MCI 1
+
+/** List of all SQPI pin definitions. */
+#define PINS_QSPI_IO \
+ {(PIO_PA11A_QCS | PIO_PA13A_QIO0 | PIO_PA12A_QIO1 | PIO_PA17A_QIO2 | PIO_PA14A_QSCK),\
+ PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+#define PINS_QSPI_IO3 {PIO_PD31A_QIO3, PIOD, ID_PIOD, PIO_PERIPH_A, PIO_DEFAULT}
+#define PINS_QSPI {PINS_QSPI_IO, PINS_QSPI_IO3}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * \page samv7_Xplained_ultra_chipdef "SAM V71 Xplained Ultra - Individual chip definition"
+ * This page lists the definitions related to different chip's definition
+ *
+ * \section USART
+ * - \ref BOARD_PIN_USART_RXD
+ * - \ref BOARD_PIN_USART_TXD
+ * - \ref BOARD_PIN_USART_CTS
+ * - \ref BOARD_PIN_USART_RTS
+ * - \ref BOARD_PIN_USART_EN
+ * - \ref BOARD_USART_BASE
+ * - \ref BOARD_ID_USART
+ */
+
+/** Rtc */
+#define BOARD_RTC_ID ID_RTC
+
+/** TWI ID for QTouch application to use */
+#define BOARD_ID_TWI_AT42 ID_TWI0
+/** TWI Base for QTouch application to use */
+#define BOARD_BASE_TWI_AT42 TWI0
+/** TWI pins for QTouch application to use */
+#define BOARD_PINS_TWI_AT42 PINS_TWI0
+
+/** USART RX pin for application */
+#define BOARD_PIN_USART_RXD PIN_USART1_RXD
+/** USART TX pin for application */
+#define BOARD_PIN_USART_TXD PIN_USART1_TXD
+/** USART CTS pin for application */
+#define BOARD_PIN_USART_CTS PIN_USART1_CTS
+/** USART RTS pin for application */
+#define BOARD_PIN_USART_RTS PIN_USART1_RTS
+/** USART ENABLE pin for application */
+#define BOARD_PIN_USART_EN PIN_USART1_EN
+/** USART Base for application */
+#define BOARD_USART_BASE USART1
+/** USART ID for application */
+#define BOARD_ID_USART ID_USART1
+
+
+
+/*----------------------------------------------------------------------------*/
+/*
+* USB pins
+*/
+#define PINS_VBUS_EN {PIO_PC16, PIOC, ID_PIOC, PIO_OUTPUT_1, PIO_DEFAULT}
+#endif /* #ifndef _BOARD_V71_XULT_H_ */
+
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/bmp.h b/bsps/arm/atsam/contrib/libraries/libboard/include/bmp.h
new file mode 100644
index 0000000000..973c6f2fe2
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/bmp.h
@@ -0,0 +1,119 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ * \section Purpose
+ *
+ * Utility for BMP
+ *
+ */
+
+#ifndef BMP_H
+#define BMP_H
+
+/** BMP magic number ('BM'). */
+#define BMP_TYPE 0x4D42
+
+/** headerSize must be set to 40 */
+#define BITMAPINFOHEADER 40
+
+/*------------------------------------------------------------------------------
+ * Exported types
+ *------------------------------------------------------------------------------*/
+
+#pragma pack(1)
+
+/** BMP (Windows) Header Format */
+typedef struct _BMPHeader {
+ /* signature, must be 4D42 hex */
+ uint16_t type;
+ /* size of BMP file in bytes (unreliable) */
+ uint32_t fileSize;
+ /* reserved, must be zero */
+ uint16_t reserved1;
+ /* reserved, must be zero */
+ uint16_t reserved2;
+ /* offset to start of image data in bytes */
+ uint32_t offset;
+ /* size of BITMAPINFOHEADER structure, must be 40 */
+ uint32_t headerSize;
+ /* image width in pixels */
+ uint32_t width;
+ /* image height in pixels */
+ uint32_t height;
+ /* number of planes in the image, must be 1 */
+ uint16_t planes;
+ /* number of bits per pixel (1, 4, 8, 16, 24, 32) */
+ uint16_t bits;
+ /* compression type (0=none, 1=RLE-8, 2=RLE-4) */
+ uint32_t compression;
+ /* size of image data in bytes (including padding) */
+ uint32_t imageSize;
+ /* horizontal resolution in pixels per meter (unreliable) */
+ uint32_t xresolution;
+ /* vertical resolution in pixels per meter (unreliable) */
+ uint32_t yresolution;
+ /* number of colors in image, or zero */
+ uint32_t ncolours;
+ /* number of important colors, or zero */
+ uint32_t importantcolours;
+} BMPHeader;
+
+#pragma pack()
+
+/*------------------------------------------------------------------------------
+ * Exported functions
+ *------------------------------------------------------------------------------*/
+extern uint8_t BMP_IsValid(void *file);
+extern uint32_t BMP_GetFileSize(void *file);
+
+extern uint8_t BMP_Decode(
+ void *file,
+ uint8_t *buffer,
+ uint32_t width,
+ uint32_t height,
+ uint8_t bpp);
+
+extern void WriteBMPheader(
+ uint32_t *pAddressHeader,
+ uint32_t bmpHSize,
+ uint32_t bmpVSize,
+ uint8_t nbByte_Pixels);
+
+extern void BMP_displayHeader(uint32_t *pAddressHeader);
+extern void RGB565toBGR555(
+ uint8_t *fileSource,
+ uint8_t *fileDestination,
+ uint32_t width,
+ uint32_t height,
+ uint8_t bpp);
+
+#endif //#ifndef BMP_H
+
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/board_lowlevel.h b/bsps/arm/atsam/contrib/libraries/libboard/include/board_lowlevel.h
new file mode 100644
index 0000000000..6c4e12a59c
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/board_lowlevel.h
@@ -0,0 +1,47 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Interface for the low-level initialization function.
+ *
+ */
+
+#ifndef BOARD_LOWLEVEL_H
+#define BOARD_LOWLEVEL_H
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+extern void LowLevelInit(void);
+extern void _SetupMemoryRegion(void);
+
+#endif /* BOARD_LOWLEVEL_H */
+
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/board_memories.h b/bsps/arm/atsam/contrib/libraries/libboard/include/board_memories.h
new file mode 100644
index 0000000000..72f8da55c6
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/board_memories.h
@@ -0,0 +1,52 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Interface for memories configuration on board.
+ *
+ */
+
+#ifndef BOARD_MEMORIES_H
+#define BOARD_MEMORIES_H
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+#ifndef __rtems__
+extern void BOARD_ConfigureSdram(void);
+#else /* __rtems__ */
+extern void BOARD_ConfigureSdram(void) ATSAM_START_SRAM_SECTION;
+#endif /* __rtems__ */
+extern uint32_t BOARD_SdramValidation(uint32_t baseAddr, uint32_t size);
+
+#endif /* #ifndef BOARD_MEMORIES_H */
+
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/cs2100.h b/bsps/arm/atsam/contrib/libraries/libboard/include/cs2100.h
new file mode 100644
index 0000000000..0f66401096
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/cs2100.h
@@ -0,0 +1,93 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Implementation WM8904 driver.
+ *
+ */
+
+#ifndef CS2100_H
+#define CS2100_H
+
+#include "board.h"
+
+/*----------------------------------------------------------------------------
+ * Definitions
+ *----------------------------------------------------------------------------*/
+
+#define CS2100_SLAVE_ADDRESS 0x4E
+
+/** ID and Rev register*/
+#define CS2100_REG_ID 0x01
+
+/** VMID control 0 register*/
+#define CS2100_REG_CTRL 0x02
+
+/** MIC Bias control 0 register*/
+#define CS2100_REG_DEV_CFG1 0x03
+
+/** Bias control 1 register*/
+#define CS2100_REG_CFG 0x05
+
+/** Power management control 0 register*/
+#define CS2100_REG_32_BIT_RATIO_1 0x06
+/** Power management control 0 register*/
+#define CS2100_REG_32_BIT_RATIO_2 0x07
+/** Power management control 0 register*/
+#define CS2100_REG_32_BIT_RATIO_3 0x08
+/** Power management control 0 register*/
+#define CS2100_REG_32_BIT_RATIO_4 0x09
+/** Power management control 2 register*/
+#define CS2100_REG_FUNC_CFG1 0x16
+/** Power management control 3 register*/
+#define CS2100_REG_FUNC_CFG2 0x17
+/** Power management control 3 register*/
+#define CS2100_REG_FUNC_CFG3 0x1E
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+extern uint16_t CS2100_Read(
+ Twid *pTwid,
+ uint32_t device,
+ uint32_t regAddr);
+
+extern void CS2100_Write(
+ Twid *pTwid,
+ uint32_t device,
+ uint32_t regAddr,
+ uint16_t data);
+
+extern uint8_t CS2100_Init(Twid *pTwid, uint32_t device, uint32_t PCK);
+#endif // CS2100_H
+
+
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/dbg_console.h b/bsps/arm/atsam/contrib/libraries/libboard/include/dbg_console.h
new file mode 100644
index 0000000000..833cec030e
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/dbg_console.h
@@ -0,0 +1,55 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Include function prototype for the UART console.
+ */
+
+#ifndef _DBG_CONSOLE_
+#define _DBG_CONSOLE_
+
+#include <stdint.h>
+
+extern void DBG_Configure(uint32_t dwBaudrate, uint32_t dwMasterClock);
+extern void DBG_PutChar(uint8_t uc);
+extern uint32_t DBG_GetChar(void);
+extern uint32_t DBG_IsRxReady(void);
+
+
+extern void DBG_DumpFrame(uint8_t *pucFrame, uint32_t dwSize);
+extern void DBG_DumpMemory(uint8_t *pucBuffer, uint32_t dwSize,
+ uint32_t dwAddress);
+extern uint32_t DBG_GetInteger(int32_t *pdwValue);
+extern uint32_t DBG_GetIntegerMinMax(int32_t *pdwValue, int32_t dwMin,
+ int32_t dwMax);
+extern uint32_t DBG_GetHexa32(uint32_t *pdwValue);
+
+#endif /* _DBG_CONSOLE_ */
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/frame_buffer.h b/bsps/arm/atsam/contrib/libraries/libboard/include/frame_buffer.h
new file mode 100644
index 0000000000..9938736794
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/frame_buffer.h
@@ -0,0 +1,83 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Interface of frame buffer driver.
+ *
+ */
+
+#ifndef _FRAME_BUFFER_
+#define _FRAME_BUFFER_
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+extern void FB_SetFrameBuffer(
+ LcdColor_t *pBuffer,
+ uint8_t ucWidth,
+ uint8_t ucHeight);
+
+extern void FB_SetColor(uint32_t color);
+
+extern uint32_t FB_DrawLine (
+ uint32_t dwX1,
+ uint32_t dwY1,
+ uint32_t dwX2,
+ uint32_t dwY2);
+
+extern uint32_t FB_DrawPixel(uint32_t x, uint32_t y);
+extern uint32_t FB_DrawCircle(uint32_t x, uint32_t y, uint32_t r);
+extern uint32_t FB_DrawFilledCircle(
+ uint32_t dwX,
+ uint32_t dwY,
+ uint32_t dwRadius);
+
+extern uint32_t FB_DrawRectangle(
+ uint32_t dwX1,
+ uint32_t dwY1,
+ uint32_t dwX2,
+ uint32_t dwY2);
+
+extern uint32_t FB_DrawFilledRectangle(
+ uint32_t dwX1,
+ uint32_t dwY1,
+ uint32_t dwX2,
+ uint32_t dwY2);
+
+extern uint32_t FB_DrawPicture(
+ uint32_t dwX1,
+ uint32_t dwY1,
+ uint32_t dwX2,
+ uint32_t dwY2,
+ const void *pBuffer);
+
+#endif /* #ifndef _FRAME_BUFFER_ */
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/gmacb_phy.h b/bsps/arm/atsam/contrib/libraries/libboard/include/gmacb_phy.h
new file mode 100644
index 0000000000..24fbe94f71
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/gmacb_phy.h
@@ -0,0 +1,114 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \file */
+
+/** \addtogroup gmacb_module Ethernet GMACB Driver
+ *@{
+ * Implement GEMAC PHY driver, that initialize the PHY to prepare for
+ * Ethernet transfer.
+ *
+ * \section Usage
+ * -# EMAC related pins and Driver should be initialized at first.
+ * -# Initialize GMACB Driver instance by invoking GMACB_Init().
+ * -# Initialize PHY connected via GMACB_InitPhy(), PHY address is
+ * automatically adjusted by attempt to read.
+ * -# Perform PHY auto negotiate through GMACB_AutoNegotiate(), so
+ * connection established.
+ *
+ *
+ * Related files:\n
+ * \ref gmacb.h\n
+ * \ref gmacb.c\n
+ * \ref gmii.h.\n
+ *
+ */
+/**@}*/
+
+#ifndef _GMACB_PHY_H
+#define _GMACB_PHY_H
+
+
+/*---------------------------------------------------------------------------
+ * Headers
+ *---------------------------------------------------------------------------*/
+
+#include "board.h"
+
+/*---------------------------------------------------------------------------
+ * Definitions
+ *---------------------------------------------------------------------------*/
+
+/** The reset length setting for external reset configuration */
+#define GMACB_RESET_LENGTH 0xD
+
+/*---------------------------------------------------------------------------
+ * Types
+ *---------------------------------------------------------------------------*/
+
+
+/** The DM9161 instance */
+typedef struct _GMacb {
+ /**< Driver */
+ sGmacd *pGmacd;
+ /** The retry & timeout settings */
+ uint32_t retryMax;
+ /** PHY address (pre-defined by pins on reset) */
+ uint8_t phyAddress;
+} GMacb;
+
+/*---------------------------------------------------------------------------
+ * Exported functions
+ *---------------------------------------------------------------------------*/
+extern void GMACB_SetupTimeout(GMacb *pMacb, uint32_t toMax);
+
+extern void GMACB_Init(GMacb *pMacb, sGmacd *pGmacd, uint8_t phyAddress);
+
+extern uint8_t GMACB_InitPhy(
+ GMacb *pMacb,
+ uint32_t mck,
+ const Pin *pResetPins,
+ uint32_t nbResetPins,
+ const Pin *pEmacPins,
+ uint32_t nbEmacPins);
+
+extern uint8_t GMACB_AutoNegotiate(GMacb *pMacb);
+
+extern uint8_t GMACB_GetLinkSpeed(GMacb *pMacb, uint8_t applySettings);
+
+extern uint8_t GMACB_Send(GMacb *pMacb, void *pBuffer, uint32_t size);
+
+extern uint32_t GMACB_Poll(GMacb *pMacb, uint8_t *pBuffer, uint32_t size);
+
+extern void GMACB_DumpRegisters(GMacb *pMacb);
+
+extern uint8_t GMACB_ResetPhy(GMacb *pMacb);
+
+#endif // #ifndef _GMACB_H
+
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/gmii.h b/bsps/arm/atsam/contrib/libraries/libboard/include/gmii.h
new file mode 100644
index 0000000000..e346143452
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/gmii.h
@@ -0,0 +1,116 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+#ifndef _GMII_DEFINE_H
+#define _GMII_DEFINE_H
+
+
+/*---------------------------------------------------------------------------
+ * Definitions
+ *---------------------------------------------------------------------------*/
+
+//IEEE defined Registers
+#define GMII_BMCR 0x0 // Basic Mode Control Register
+#define GMII_BMSR 0x1 // Basic Mode Status Register
+#define GMII_PHYID1R 0x2 // PHY Identifier Register 1
+#define GMII_PHYID2R 0x3 // PHY Identifier Register 2
+#define GMII_ANAR 0x4 // Auto_Negotiation Advertisement Register
+#define GMII_ANLPAR 0x5 // Auto_negotiation Link Partner Ability Register
+#define GMII_ANER 0x6 // Auto-negotiation Expansion Register
+#define GMII_ANNPR 0x7 // Auto-negotiation Next Page Register
+#define GMII_ANLPNPAR 0x8 // Auto_negotiation Link Partner Next Page Ability Register
+#define GMII_AFEC0R 0x11 // AFE Control 0 Register
+#define GMII_AFEC3R 0x14 // AFE Control 3 Register
+#define GMII_RXERCR 0x15 // RXER Counter Register
+#define GMII_OMSSR 0x17 // Operation Mode Strap Status Register
+#define GMII_ECR 0x18 // Expanded Control Register
+#define GMII_ICSR 0x1B // Interrupt Control/Status Register
+#define GMII_FC 0x1C // Function Control
+#define GMII_LCSR 0x1D // LinkMD® Control/Status Register
+#define GMII_PC1R 0x1E // PHY Control 1 Register
+#define GMII_PC2R 0x1F // PHY Control 2 Register
+
+// PHY ID Identifier Register
+#define GMII_LSB_MASK 0x0U
+// definitions: MII_PHYID1
+#define GMII_OUI_MSB 0x0022
+// definitions: MII_PHYID2
+#define GMII_OUI_LSB 0x1572 // KSZ8061 PHY Id2
+
+// Basic Mode Control Register (BMCR)
+// Bit definitions: MII_BMCR
+#define GMII_RESET (1 << 15) // 1= Software Reset; 0=Normal Operation
+#define GMII_LOOPBACK (1 << 14) // 1=loopback Enabled; 0=Normal Operation
+#define GMII_SPEED_SELECT_LSB (1 << 13) // 1,0=1000Mbps 0,1=100Mbps; 0,0=10Mbps
+#define GMII_AUTONEG (1 << 12) // Auto-negotiation Enable
+#define GMII_POWER_DOWN (1 << 11) // 1=Power down 0=Normal operation
+#define GMII_ISOLATE (1 << 10) // 1 = Isolates 0 = Normal operation
+#define GMII_RESTART_AUTONEG (1 << 9) // 1 = Restart auto-negotiation 0 = Normal operation
+#define GMII_DUPLEX_MODE (1 << 8) // 1 = Full duplex operation 0 = Normal operation
+// Reserved 7 // Read as 0, ignore on write
+#define GMII_SPEED_SELECT_MSB (1 << 6) //
+// Reserved 5 to 0 // Read as 0, ignore on write
+
+
+// Basic Mode Status Register (BMSR)
+// Bit definitions: MII_BMSR
+#define GMII_100BASE_T4 (1 << 15) // 100BASE-T4 Capable
+#define GMII_100BASE_TX_FD (1 << 14) // 100BASE-TX Full Duplex Capable
+#define GMII_100BASE_T4_HD (1 << 13) // 100BASE-TX Half Duplex Capable
+#define GMII_10BASE_T_FD (1 << 12) // 10BASE-T Full Duplex Capable
+#define GMII_10BASE_T_HD (1 << 11) // 10BASE-T Half Duplex Capable
+// Reserved 10 to 9 // Read as 0, ignore on write
+#define GMII_EXTEND_STATUS (1 << 8) // 1 = Extend Status Information In Reg 15
+// Reserved 7
+#define GMII_MF_PREAMB_SUPPR (1 << 6) // MII Frame Preamble Suppression
+#define GMII_AUTONEG_COMP (1 << 5) // Auto-negotiation Complete
+#define GMII_REMOTE_FAULT (1 << 4) // Remote Fault
+#define GMII_AUTONEG_ABILITY (1 << 3) // Auto Configuration Ability
+#define GMII_LINK_STATUS (1 << 2) // Link Status
+#define GMII_JABBER_DETECT (1 << 1) // Jabber Detect
+#define GMII_EXTEND_CAPAB (1 << 0) // Extended Capability
+
+// Auto-negotiation Advertisement Register (ANAR)
+// Auto-negotiation Link Partner Ability Register (ANLPAR)
+// Bit definitions: MII_ANAR, MII_ANLPAR
+#define GMII_NP (1 << 15) // Next page Indication
+// Reserved 7
+#define GMII_RF (1 << 13) // Remote Fault
+// Reserved 12 // Write as 0, ignore on read
+#define GMII_PAUSE_MASK (3 << 11) // 0,0 = No Pause 1,0 = Asymmetric Pause(link partner)
+ // 0,1 = Symmetric Pause 1,1 = Symmetric&Asymmetric Pause(local device)
+#define GMII_T4 (1 << 9) // 100BASE-T4 Support
+#define GMII_TX_FDX (1 << 8) // 100BASE-TX Full Duplex Support
+#define GMII_TX_HDX (1 << 7) // 100BASE-TX Support
+#define GMII_10_FDX (1 << 6) // 10BASE-T Full Duplex Support
+#define GMII_10_HDX (1 << 5) // 10BASE-T Support
+// Selector 4 to 0 // Protocol Selection Bits
+#define GMII_AN_IEEE_802_3 0x00001
+
+#endif // #ifndef _MII_DEFINE_H
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488.h b/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488.h
new file mode 100644
index 0000000000..3729933013
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488.h
@@ -0,0 +1,106 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Interface of ILI9488 driver.
+ *
+ */
+
+#ifndef _ILI9488_H_
+#define _ILI9488_H_
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "board.h"
+
+#include <stdint.h>
+
+
+/*----------------------------------------------------------------------------
+ * Definitions
+ *----------------------------------------------------------------------------*/
+
+#define ILI9488_SPIMODE 0
+#define ILI9488_EBIMODE 1
+
+/* ILI9325 ID code */
+#define ILI9488_DEVICE_CODE 0x9488
+
+#define ILI9488_LCD_WIDTH 320
+#define ILI9488_LCD_HEIGHT 480
+#define ILI9488_SELF_TEST_OK 0xC0
+
+/* EBI chip select for LCD */
+#define SMC_EBI_LCD_CS 3
+
+/*----------------------------------------------------------------------------
+ * Types
+ *----------------------------------------------------------------------------*/
+typedef enum {
+ AccessInst = 0,
+ AccessRead,
+ AccessWrite
+} AccessIli_t;
+
+typedef union _union_type {
+ uint32_t value;
+ struct {
+ uint8_t byte_8;
+ uint8_t byte_l6;
+ uint8_t byte_24;
+ uint8_t byte_32;
+ } byte;
+ struct {
+ uint16_t half_word_l;
+ uint16_t half_word_h;
+ } half_word;
+} union_type;
+typedef volatile uint8_t REG8;
+
+typedef uint32_t LcdColor_t;
+
+/*----------------------------------------------------------------------------
+ * Marcos
+ *----------------------------------------------------------------------------*/
+/* Pixel cache used to speed up communication */
+#define LCD_DATA_CACHE_SIZE BOARD_LCD_WIDTH
+
+/*----------------------------------------------------------------------------
+ * Function Marcos
+ *----------------------------------------------------------------------------*/
+#define get_0b_to_8b(x) (((union_type*)&(x))->byte.byte_8)
+#define get_8b_to_16b(x) (((union_type*)&(x))->byte.byte_l6)
+#define get_16b_to_24b(x) (((union_type*)&(x))->byte.byte_24)
+#define get_24b_to_32b(x) (((union_type*)&(x))->byte.byte_32)
+
+#endif /* #ifndef ILI9488 */
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_dma.h b/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_dma.h
new file mode 100644
index 0000000000..72719b86a3
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_dma.h
@@ -0,0 +1,92 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Interface of ILI9488 driver.
+ *
+ */
+
+#ifndef _ILI9488_DMA_H_
+#define _ILI9488_DMA_H_
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "board.h"
+#include <stdint.h>
+
+/*------------------------------------------------------------------------------
+ * Definitions
+ *----------------------------------------------------------------------------*/
+/** An unspecified error has occurred.*/
+#define ILI9488_ERROR_DMA_ALLOCATE_CHANNEL 1
+#define ILI9488_ERROR_DMA_CONFIGURE 2
+#define ILI9488_ERROR_DMA_TRANSFER 3
+#define ILI9488_ERROR_DMA_SIZE 4
+
+#define ILI9488_SPI SPI0
+#define ILI9488_SPI_ID ID_SPI0
+
+/* EBI BASE ADDRESS for SMC LCD */
+#define ILI9488_BASE_ADDRESS 0x63000000
+
+/*------------------------------------------------------------------------------
+ * Types
+ *----------------------------------------------------------------------------*/
+
+typedef struct _ILI9488_dma {
+ /** Pointer to DMA driver */
+ sXdmad *xdmaD;
+ /** ili9488 Tx channel */
+ uint32_t ili9488DmaTxChannel;
+ /** ili9488 Rx channel */
+ uint32_t ili9488DmaRxChannel;
+ /** ili9488 Tx/Rx configure descriptor */
+ sXdmadCfg xdmadRxCfg, xdmadTxCfg;
+ /** ili9488 dma interrupt */
+ uint32_t xdmaInt;
+ /** Pointer to SPI Hardware registers */
+ Spi *pSpiHw;
+ /** SPI Id as defined in the product datasheet */
+ uint8_t spiId;
+} sIli9488Dma;
+
+typedef struct _ILI9488_ctl {
+ /** ili9488 Command/Data mode */
+ volatile uint32_t cmdOrDataFlag;
+ /** ili9488 Rx done */
+ volatile uint32_t rxDoneFlag;
+ /** ili9488 Tx done */
+ volatile uint32_t txDoneFlag;
+} sIli9488DmaCtl;
+
+#endif /* #ifndef ILI9488_DMA */
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_ebi.h b/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_ebi.h
new file mode 100644
index 0000000000..bb87806df4
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_ebi.h
@@ -0,0 +1,63 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Interface of ILI9488 driver.
+ *
+ */
+
+#ifndef _ILI9488_EBI_H_
+#define _ILI9488_EBI_H_
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "board.h"
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+extern uint32_t ILI9488_EbiReadChipId (void);
+extern uint32_t ILI9488_EbiInitialize(sXdmad *dmad);
+extern void ILI9488_EbiSetPixelFormat(uint16_t format);
+extern void ILI9488_EbiSetCursor(uint16_t x, uint16_t y);
+extern void ILI9488_EbiSetWindow(uint16_t dwX, uint16_t dwY,
+ uint16_t dwWidth, uint16_t dwHeight);
+extern void ILI9488_EbiSetFullWindow(void);
+extern void ILI9488_EbiOn(void);
+extern void ILI9488_EbiOff(void);
+extern void ILI9488_EbiSetDisplayLandscape(uint8_t dwRGB,
+ uint8_t LandscaprMode);
+
+#endif /* #ifndef ILI9488_EBI */
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_ebi_dma.h b/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_ebi_dma.h
new file mode 100644
index 0000000000..660b8c89d8
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_ebi_dma.h
@@ -0,0 +1,55 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Interface of ILI9488 driver.
+ *
+ */
+
+#ifndef _ILI9488_EBI_DMA_H_
+#define _ILI9488_EBI_DMA_H_
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "board.h"
+#include <stdint.h>
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+extern uint8_t ILI9488_EbiInitializeWithDma(sXdmad *dmad);
+extern uint8_t ILI9488_EbiDmaTxTransfer(uint16_t *pTxBuffer, uint32_t wTxSize);
+extern uint8_t ILI9488_EbiDmaRxTransfer(uint32_t *pRxBuffer, uint32_t wRxSize);
+extern uint8_t ILI9488_EbiSendCommand(uint16_t Instr, uint16_t *pTxData,
+ uint32_t *pRxData, AccessIli_t ReadWrite, uint32_t size);
+#endif /* #ifndef ILI9488_EBI_DMA */
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_reg.h b/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_reg.h
new file mode 100644
index 0000000000..4ec9ae3a4f
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_reg.h
@@ -0,0 +1,131 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+#ifndef ILI9488_REG_H_INCLUDED
+#define ILI9488_REG_H_INCLUDED
+
+/* Level 1 Commands (from the display Datasheet) */
+#define ILI9488_CMD_NOP 0x00
+#define ILI9488_CMD_SOFTWARE_RESET 0x01
+#define ILI9488_CMD_READ_DISP_ID 0x04
+#define ILI9488_CMD_READ_ERROR_DSI 0x05
+#define ILI9488_CMD_READ_DISP_STATUS 0x09
+#define ILI9488_CMD_READ_DISP_POWER_MODE 0x0A
+#define ILI9488_CMD_READ_DISP_MADCTRL 0x0B
+#define ILI9488_CMD_READ_DISP_PIXEL_FORMAT 0x0C
+#define ILI9488_CMD_READ_DISP_IMAGE_MODE 0x0D
+#define ILI9488_CMD_READ_DISP_SIGNAL_MODE 0x0E
+#define ILI9488_CMD_READ_DISP_SELF_DIAGNOSTIC 0x0F
+#define ILI9488_CMD_ENTER_SLEEP_MODE 0x10
+#define ILI9488_CMD_SLEEP_OUT 0x11
+#define ILI9488_CMD_PARTIAL_MODE_ON 0x12
+#define ILI9488_CMD_NORMAL_DISP_MODE_ON 0x13
+#define ILI9488_CMD_DISP_INVERSION_OFF 0x20
+#define ILI9488_CMD_DISP_INVERSION_ON 0x21
+#define ILI9488_CMD_PIXEL_OFF 0x22
+#define ILI9488_CMD_PIXEL_ON 0x23
+#define ILI9488_CMD_DISPLAY_OFF 0x28
+#define ILI9488_CMD_DISPLAY_ON 0x29
+#define ILI9488_CMD_COLUMN_ADDRESS_SET 0x2A
+#define ILI9488_CMD_PAGE_ADDRESS_SET 0x2B
+#define ILI9488_CMD_MEMORY_WRITE 0x2C
+#define ILI9488_CMD_MEMORY_READ 0x2E
+#define ILI9488_CMD_PARTIAL_AREA 0x30
+#define ILI9488_CMD_VERT_SCROLL_DEFINITION 0x33
+#define ILI9488_CMD_TEARING_EFFECT_LINE_OFF 0x34
+#define ILI9488_CMD_TEARING_EFFECT_LINE_ON 0x35
+#define ILI9488_CMD_MEMORY_ACCESS_CONTROL 0x36
+#define ILI9488_CMD_VERT_SCROLL_START_ADDRESS 0x37
+#define ILI9488_CMD_IDLE_MODE_OFF 0x38
+#define ILI9488_CMD_IDLE_MODE_ON 0x39
+#define ILI9488_CMD_COLMOD_PIXEL_FORMAT_SET 0x3A
+#define ILI9488_CMD_WRITE_MEMORY_CONTINUE 0x3C
+#define ILI9488_CMD_READ_MEMORY_CONTINUE 0x3E
+#define ILI9488_CMD_SET_TEAR_SCANLINE 0x44
+#define ILI9488_CMD_GET_SCANLINE 0x45
+#define ILI9488_CMD_WRITE_DISPLAY_BRIGHTNESS 0x51
+#define ILI9488_CMD_READ_DISPLAY_BRIGHTNESS 0x52
+#define ILI9488_CMD_WRITE_CTRL_DISPLAY 0x53
+#define ILI9488_CMD_READ_CTRL_DISPLAY 0x54
+#define ILI9488_CMD_WRITE_CONTENT_ADAPT_BRIGHTNESS 0x55
+#define ILI9488_CMD_READ_CONTENT_ADAPT_BRIGHTNESS 0x56
+#define ILI9488_CMD_WRITE_MIN_CAB_LEVEL 0x5E
+#define ILI9488_CMD_READ_MIN_CAB_LEVEL 0x5F
+#define ILI9488_CMD_READ_ABC_SELF_DIAG_RES 0x68
+#define ILI9488_CMD_READ_ID1 0xDA
+#define ILI9488_CMD_READ_ID2 0xDB
+#define ILI9488_CMD_READ_ID3 0xDC
+
+/* Level 2 Commands (from the display Datasheet) */
+#define ILI9488_CMD_INTERFACE_MODE_CONTROL 0xB0
+#define ILI9488_CMD_FRAME_RATE_CONTROL_NORMAL 0xB1
+#define ILI9488_CMD_FRAME_RATE_CONTROL_IDLE_8COLOR 0xB2
+#define ILI9488_CMD_FRAME_RATE_CONTROL_PARTIAL 0xB3
+#define ILI9488_CMD_DISPLAY_INVERSION_CONTROL 0xB4
+#define ILI9488_CMD_BLANKING_PORCH_CONTROL 0xB5
+#define ILI9488_CMD_DISPLAY_FUNCTION_CONTROL 0xB6
+#define ILI9488_CMD_ENTRY_MODE_SET 0xB7
+#define ILI9488_CMD_BACKLIGHT_CONTROL_1 0xB9
+#define ILI9488_CMD_BACKLIGHT_CONTROL_2 0xBA
+#define ILI9488_CMD_HS_LANES_CONTROL 0xBE
+#define ILI9488_CMD_POWER_CONTROL_1 0xC0
+#define ILI9488_CMD_POWER_CONTROL_2 0xC1
+#define ILI9488_CMD_POWER_CONTROL_NORMAL_3 0xC2
+#define ILI9488_CMD_POWER_CONTROL_IDEL_4 0xC3
+#define ILI9488_CMD_POWER_CONTROL_PARTIAL_5 0xC4
+#define ILI9488_CMD_VCOM_CONTROL_1 0xC5
+#define ILI9488_CMD_CABC_CONTROL_1 0xC6
+#define ILI9488_CMD_CABC_CONTROL_2 0xC8
+#define ILI9488_CMD_CABC_CONTROL_3 0xC9
+#define ILI9488_CMD_CABC_CONTROL_4 0xCA
+#define ILI9488_CMD_CABC_CONTROL_5 0xCB
+#define ILI9488_CMD_CABC_CONTROL_6 0xCC
+#define ILI9488_CMD_CABC_CONTROL_7 0xCD
+#define ILI9488_CMD_CABC_CONTROL_8 0xCE
+#define ILI9488_CMD_CABC_CONTROL_9 0xCF
+#define ILI9488_CMD_NVMEM_WRITE 0xD0
+#define ILI9488_CMD_NVMEM_PROTECTION_KEY 0xD1
+#define ILI9488_CMD_NVMEM_STATUS_READ 0xD2
+#define ILI9488_CMD_READ_ID4 0xD3
+#define ILI9488_CMD_ADJUST_CONTROL_1 0xD7
+#define ILI9488_CMD_READ_ID_VERSION 0xD8
+#define ILI9488_CMD_POSITIVE_GAMMA_CORRECTION 0xE0
+#define ILI9488_CMD_NEGATIVE_GAMMA_CORRECTION 0xE1
+#define ILI9488_CMD_DIGITAL_GAMMA_CONTROL_1 0xE2
+#define ILI9488_CMD_DIGITAL_GAMMA_CONTROL_2 0xE3
+#define ILI9488_CMD_SET_IMAGE_FUNCTION 0xE9
+#define ILI9488_CMD_ADJUST_CONTROL_2 0xF2
+#define ILI9488_CMD_ADJUST_CONTROL_3 0xF7
+#define ILI9488_CMD_ADJUST_CONTROL_4 0xF8
+#define ILI9488_CMD_ADJUST_CONTROL_5 0xF9
+#define ILI9488_CMD_SPI_READ_SETTINGS 0xFB
+#define ILI9488_CMD_ADJUST_CONTROL_6 0xFC
+#define ILI9488_CMD_ADJUST_CONTROL_7 0xFF
+
+#endif /* ILI9488_REGS_H_INCLUDED */
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_spi.h b/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_spi.h
new file mode 100644
index 0000000000..db55960313
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_spi.h
@@ -0,0 +1,69 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Interface of ILI9488 driver.
+ *
+ */
+
+#ifndef _ILI9488_SPI_H_
+#define _ILI9488_SPI_H_
+
+/*------------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "board.h"
+
+/*------------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+extern uint32_t ILI9488_SpiReadChipId (void);
+extern uint32_t ILI9488_SpiInitialize(sXdmad *dmad);
+extern void ILI9488_SpiSetPixelFormat(uint8_t format);
+extern void ILI9488_SpiNop(void);
+extern void ILI9488_SpiWriteMemory(const uint8_t *pBuf, uint32_t size);
+extern void ILI9488_SpiReadMemory(const uint8_t *pBuf, uint32_t size);
+extern void ILI9488_SpiSetCursor(uint16_t x, uint16_t y);
+extern void ILI9488_SpiSetWindow(
+ uint16_t dwX,
+ uint16_t dwY,
+ uint16_t dwWidth,
+ uint16_t dwHeight);
+
+extern void ILI9488_SpiSetFullWindow(void);
+extern void ILI9488_SpiOn(void);
+extern void ILI9488_SpiOff(void);
+extern void ILI9488_SpiSetDisplayLandscape(
+ uint8_t dwRGB, uint8_t LandscaprMode);
+extern void ILI9488_SetPixelColor(uint32_t x, uint32_t y, uint32_t color);
+
+#endif /* #ifndef ILI9488_SPI */
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_spi_dma.h b/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_spi_dma.h
new file mode 100644
index 0000000000..1eec6f759c
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_spi_dma.h
@@ -0,0 +1,56 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Interface of ILI9488 DMA driver.
+ *
+ */
+
+#ifndef _ILI9488_SPI_DMA_H_
+#define _ILI9488_SPI_DMA_H_
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "board.h"
+#include <stdint.h>
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+extern uint8_t ILI9488_SpiInitializeWithDma(sXdmad *dmad);
+extern uint8_t ILI9488_SpiDmaTxTransfer(uint8_t *pTxBuffer, uint32_t wTxSize);
+extern uint8_t ILI9488_SpiDmaRxTransfer(uint32_t *pRxBuffer, uint32_t wRxSize);
+extern uint8_t ILI9488_SpiSendCommand(uint8_t Instr, uint8_t *pTxData,
+ uint32_t *pRxData, AccessIli_t ReadWrite, uint32_t size);
+
+#endif /* #ifndef ILI9488_SPI_DMA */
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/image_sensor_inf.h b/bsps/arm/atsam/contrib/libraries/libboard/include/image_sensor_inf.h
new file mode 100644
index 0000000000..3a7f5b5447
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/image_sensor_inf.h
@@ -0,0 +1,136 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+#include "board.h"
+
+
+/*---------------------------------------------------------------------------
+ * Definition
+ *---------------------------------------------------------------------------*/
+#define SENDOR_SUPPORTED_OUTPUTS 7
+
+/** terminating list entry for register in configuration file */
+#define SENSOR_REG_TERM 0xFF
+/** terminating list entry for value in configuration file */
+#define SENSOR_VAL_TERM 0xFF
+
+/*----------------------------------------------------------------------------
+ * Types
+ *----------------------------------------------------------------------------*/
+
+/** Sensor type */
+typedef enum _sensorType {
+ SENSOR_COMS = 0,
+ SENSOR_CCD
+} sensorType_t;
+
+/** Sensor status or return code */
+typedef enum _sensorStatus {
+ SENSOR_OK = 0, /**< Operation is successful */
+ SENSOR_TWI_ERROR,
+ SENSOR_ID_ERROR,
+ SENSOR_RESOLUTION_NOT_SUPPORTED
+} sendorStatus_t;
+
+/** Sensor TWI mode */
+typedef enum _sensorTwiMode {
+ SENSOR_TWI_REG_BYTE_DATA_BYTE = 0,
+ SENSOR_TWI_REG_2BYTE_DATA_BYTE,
+ SENSOR_TWI_REG_BYTE_DATA_2BYTE
+} sensorTwiMode_t;
+
+/** Sensor resolution */
+typedef enum _sensorResolution {
+ QVGA = 0,
+ VGA,
+ SVGA,
+ XGA,
+ WXGA,
+ UVGA
+} sensorOutputResolution_t;
+
+/** Sensor output format */
+typedef enum _sensorOutputFormat {
+ RAW_BAYER_12_BIT = 0,
+ RAW_BAYER_10_BIT,
+ YUV_422_8_BIT,
+ YUV_422_10_BIT,
+ MONO_12_BIT
+} sensorOutputFormat_t;
+
+/** define a structure for sensor register initialization values */
+typedef struct _sensor_reg {
+ uint16_t reg; /* Register to be written */
+ uint16_t val; /* value to be written */
+} sensorReg_t;
+
+typedef struct _sensor_output {
+ uint8_t type; /** Index 0: normal, 1: AF setting*/
+ sensorOutputResolution_t output_resolution; /** sensor output resolution */
+ sensorOutputFormat_t output_format; /** sensor output format */
+ uint8_t supported; /** supported for current output_resolution*/
+ uint32_t output_width; /** output width */
+ uint32_t output_height; /** output height */
+ const sensorReg_t *output_setting; /** sensor registers setting */
+} sensorOutput_t;
+
+/** define a structure for sensor profile */
+typedef struct _sensor_profile {
+ sensorType_t cmos_ccd; /** Sensor type for CMOS sensor or CCD */
+ sensorTwiMode_t twi_inf_mode; /** TWI interface mode */
+ uint32_t twi_slave_addr; /** TWI slave address */
+ uint16_t pid_high_reg; /** Register address for product ID high byte */
+ uint16_t pid_low_reg; /** Register address for product ID low byte*/
+ uint16_t pid_high; /** product ID high byte */
+ uint16_t pid_low; /** product ID low byte */
+ uint16_t version_mask; /** version mask */
+ const sensorOutput_t
+ *outputConf[SENDOR_SUPPORTED_OUTPUTS]; /** sensor settings */
+} sensorProfile_t;
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+extern sendorStatus_t sensor_twi_write_regs(Twid *pTwid,
+ const sensorReg_t *pReglist);
+
+extern sendorStatus_t sensor_twi_read_regs(Twid *pTwid,
+ const sensorReg_t *pReglist);
+
+extern sendorStatus_t sensor_setup(Twid *pTwid,
+ const sensorProfile_t *sensor_profile,
+ sensorOutputResolution_t resolution);
+
+extern sendorStatus_t sensor_get_output(sensorOutputFormat_t *format,
+ uint32_t *width,
+ uint32_t *height,
+ sensorOutputResolution_t resolution);
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/lcd_color.h b/bsps/arm/atsam/contrib/libraries/libboard/include/lcd_color.h
new file mode 100644
index 0000000000..23a9c84ca4
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/lcd_color.h
@@ -0,0 +1,109 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+#ifndef COLOR_H
+#define COLOR_H
+
+/**
+ * \file
+ *
+ * RGB 24-bits color table definition.
+ *
+ */
+
+/*
+ * RGB 24 Bpp
+ * RGB 888
+ * R7R6R5R4 R3R2R1R0 G7G6G5G4 G3G2G1G0 B7B6B5B4 B3B2B1B0
+ */
+
+#define COLOR_BLACK 0x000000
+#define COLOR_WHITE 0xFFFFFF
+
+#define COLOR_BLUE 0x0000FF
+#define COLOR_GREEN 0x00FF00
+#define COLOR_RED 0xFF0000
+
+#define COLOR_NAVY 0x000080
+#define COLOR_DARKBLUE 0x00008B
+#define COLOR_DARKGREEN 0x006400
+#define COLOR_DARKCYAN 0x008B8B
+#define COLOR_CYAN 0x00FFFF
+#define COLOR_TURQUOISE 0x40E0D0
+#define COLOR_INDIGO 0x4B0082
+#define COLOR_DARKRED 0x800000
+#define COLOR_OLIVE 0x808000
+#define COLOR_GRAY 0x808080
+#define COLOR_SKYBLUE 0x87CEEB
+#define COLOR_BLUEVIOLET 0x8A2BE2
+#define COLOR_LIGHTGREEN 0x90EE90
+#define COLOR_DARKVIOLET 0x9400D3
+#define COLOR_YELLOWGREEN 0x9ACD32
+#define COLOR_BROWN 0xA52A2A
+#define COLOR_DARKGRAY 0xA9A9A9
+#define COLOR_SIENNA 0xA0522D
+#define COLOR_LIGHTBLUE 0xADD8E6
+#define COLOR_GREENYELLOW 0xADFF2F
+#define COLOR_SILVER 0xC0C0C0
+#define COLOR_LIGHTGREY 0xD3D3D3
+#define COLOR_LIGHTCYAN 0xE0FFFF
+#define COLOR_VIOLET 0xEE82EE
+#define COLOR_AZUR 0xF0FFFF
+#define COLOR_BEIGE 0xF5F5DC
+#define COLOR_MAGENTA 0xFF00FF
+#define COLOR_TOMATO 0xFF6347
+#define COLOR_GOLD 0xFFD700
+#define COLOR_ORANGE 0xFFA500
+#define COLOR_SNOW 0xFFFAFA
+#define COLOR_YELLOW 0xFFFF00
+
+#define BLACK 0x0000
+#define BLUE 0x001F
+#define RED 0xF800
+#define GREEN 0x07E0
+#define WHITE 0xFFFF
+
+/* level is in [0; 31]*/
+#define BLUE_LEV(level) ((level)&BLUE)
+#define GREEN_LEV(level) ((((level)*2)<<5)&GREEN)
+#define RED_LEV(level) (((level)<<(5+6))&RED)
+#define GRAY_LEV(level) (BLUE_LEV(level) | GREEN_LEV(level) | RED_LEV(level))
+
+#define RGB_24_TO_RGB565(RGB) \
+ (((RGB >>19)<<11) | (((RGB & 0x00FC00) >>5)) | (RGB & 0x00001F))
+#define RGB_24_TO_18BIT(RGB) \
+ (((RGB >>16)&0xFC) | (((RGB & 0x00FF00) >>10) << 10) | (RGB & 0x0000FC)<<16)
+#define RGB_16_TO_18BIT(RGB) \
+ (((((RGB >>11)*63)/31)<<18) | (RGB & 0x00FC00) | (((RGB & 0x00001F)*63)/31))
+#define BGR_TO_RGB_18BIT(RGB) \
+ (RGB & 0xFF0000) | ((RGB & 0x00FF00) >> 8) | ((RGB & 0x0000FC) >> 16))
+#define BGR_16_TO_18BITRGB(RGB) BGR_TO_RGB_18BIT(RGB_16_TO_18BIT(RGB))
+
+
+#endif /* #define COLOR_H */
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/lcd_draw.h b/bsps/arm/atsam/contrib/libraries/libboard/include/lcd_draw.h
new file mode 100644
index 0000000000..52f83ee120
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/lcd_draw.h
@@ -0,0 +1,186 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Interface for draw function on LCD.
+ *
+ */
+
+#ifndef DRAW_H
+#define DRAW_H
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+#include "board.h"
+#include <stdint.h>
+#include "lcd_gimp_image.h"
+
+/*----------------------------------------------------------------------------
+ * Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Horizontal direction line definition */
+#define DIRECTION_HLINE 0
+/** Vertical direction line definition */
+#define DIRECTION_VLINE 1
+
+typedef struct _rect {
+ uint32_t x;
+ uint32_t y;
+ uint32_t width;
+ uint32_t height;
+} rect;
+
+COMPILER_PACK_SET(1)
+typedef struct _rgb {
+ uint8_t b;
+ uint8_t g;
+ uint8_t r;
+} sBGR;
+COMPILER_PACK_RESET()
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+extern void LCDD_SetUpdateWindowSize(rect rc);
+
+extern void LCDD_UpdateWindow(void);
+
+extern void LCDD_UpdatePartialWindow(uint8_t *pbuf, uint32_t size);
+
+extern void LCDD_DrawRectangleWithFill(
+ uint16_t *pbuf,
+ uint32_t dwX,
+ uint32_t dwY,
+ uint32_t dwWidth,
+ uint32_t dwHeight,
+ uint32_t dwColor);
+
+extern uint32_t LCDD_DrawCircle(
+ uint16_t *pbuf,
+ uint32_t x,
+ uint32_t y,
+ uint32_t r,
+ uint32_t color);
+
+extern uint32_t LCD_DrawFilledCircle(
+ uint16_t *pbuf,
+ uint32_t dwX,
+ uint32_t dwY,
+ uint32_t dwRadius,
+ uint32_t color);
+
+extern void LCDD_DrawString(
+ uint16_t *pbuf,
+ uint32_t x,
+ uint32_t y,
+ const uint8_t *pString,
+ uint32_t color);
+
+extern void LCDD_GetStringSize(
+ const uint8_t *pString,
+ uint32_t *pWidth,
+ uint32_t *pHeight);
+
+extern void LCDD_BitBlt(
+ uint16_t *pbuf,
+ uint32_t dst_x,
+ uint32_t dst_y,
+ uint32_t dst_w,
+ uint32_t dst_h,
+ const LcdColor_t *src,
+ uint32_t src_x,
+ uint32_t src_y,
+ uint32_t src_w,
+ uint32_t src_h);
+
+extern void LCDD_BitBltAlphaBlend(uint16_t *pbuf,
+ uint32_t dst_x,
+ uint32_t dst_y,
+ uint32_t dst_w,
+ uint32_t dst_h,
+ const LcdColor_t *src,
+ uint32_t src_x,
+ uint32_t src_y,
+ uint32_t src_w,
+ uint32_t src_h,
+ uint32_t alpha);
+extern void LCDD_DrawImage(
+ uint16_t *pbuf,
+ uint32_t dwX,
+ uint32_t dwY,
+ const LcdColor_t *pImage,
+ uint32_t dwWidth,
+ uint32_t dwHeight);
+
+extern void LCDD_DrawPixel(
+ uint16_t *pbuf,
+ uint32_t x,
+ uint32_t y,
+ uint32_t color);
+
+extern void LCDD_DrawLine(
+ uint16_t *pbuf,
+ uint32_t dwX1,
+ uint32_t dwY1,
+ uint32_t dwX2,
+ uint32_t dwY2,
+ uint32_t color);
+
+extern uint32_t LCDD_DrawLineBresenham(
+ uint16_t *pbuf,
+ uint32_t dwX1,
+ uint32_t dwY1,
+ uint32_t dwX2,
+ uint32_t dwY2,
+ uint32_t color);
+
+extern void LCDD_DrawRectangle(
+ uint16_t *pbuf,
+ uint32_t x,
+ uint32_t y,
+ uint32_t width,
+ uint32_t height,
+ uint32_t color);
+
+extern void LCDD_SetCavasBuffer(
+ void *pBuffer,
+ uint32_t wBufferSize);
+
+extern void LCDD_DrawStraightLine(
+ uint16_t *pbuf,
+ uint32_t dwX1,
+ uint32_t dwY1,
+ uint32_t dwX2,
+ uint32_t dwY2 ,
+ uint32_t color);
+#endif /* #ifndef DRAW_H */
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/lcd_font.h b/bsps/arm/atsam/contrib/libraries/libboard/include/lcd_font.h
new file mode 100644
index 0000000000..dbcef91ed3
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/lcd_font.h
@@ -0,0 +1,108 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Interface for draw font on LCD.
+ *
+ */
+
+/**
+ *
+ * \section Purpose
+ *
+ * The font.h files declares a font structure and a LCDD_DrawChar function
+ * that must be implemented by a font definition file to be used with the
+ * LCDD_DrawString method of draw.h.
+ *
+ * The font10x14.c implements the necessary variable and function for a 10x14
+ * font.
+ *
+ * \section Usage
+ *
+ * -# Declare a gFont global variable with the necessary Font information.
+ * -# Implement an LCDD_DrawChar function which displays the specified
+ * character on the LCD.
+ * -# Use the LCDD_DrawString method defined in draw.h to display a complete
+ * string.
+ */
+
+#ifndef _LCD_FONT_
+#define _LCD_FONT_
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------------------
+ * Types
+ *----------------------------------------------------------------------------*/
+
+
+/** \brief Describes the font (width, height, supported characters, etc.) used by
+ * the LCD driver draw API.
+ */
+typedef struct _Font {
+ /* Font width in pixels. */
+ uint8_t width;
+ /* Font height in pixels. */
+ uint8_t height;
+} Font;
+
+/*----------------------------------------------------------------------------
+ * Variables
+ *----------------------------------------------------------------------------*/
+
+/** Global variable describing the font being instanced. */
+extern const Font gFont;
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+extern void LCDD_DrawChar(
+ uint16_t *pCanvasBuffer,
+ uint32_t x,
+ uint32_t y,
+ uint8_t c,
+ uint32_t color);
+
+extern void LCD_DrawString(
+ uint16_t *pCanvasBuffer,
+ uint32_t dwX,
+ uint32_t dwY,
+ const uint8_t *pString,
+ uint32_t color);
+
+
+#endif /* #ifndef LCD_FONT_ */
+
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/lcd_font10x14.h b/bsps/arm/atsam/contrib/libraries/libboard/include/lcd_font10x14.h
new file mode 100644
index 0000000000..7676b5c7c4
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/lcd_font10x14.h
@@ -0,0 +1,45 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Font 10x14 table definition.
+ *
+ */
+
+#ifndef _LCD_FONT_10x14_
+#define _LCD_FONT_10x14_
+
+#include <stdint.h>
+
+/** Char set of font 10x14 */
+extern const uint8_t pCharset10x14[];
+
+#endif /* #ifdef _LCD_FONT_10x14_ */
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/lcd_gimp_image.h b/bsps/arm/atsam/contrib/libraries/libboard/include/lcd_gimp_image.h
new file mode 100644
index 0000000000..7b95ba8c49
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/lcd_gimp_image.h
@@ -0,0 +1,42 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+#ifndef _GIMP_IMAGE_
+#define _GIMP_IMAGE_
+
+#include <stdint.h>
+
+typedef struct _SGIMPImage {
+ uint32_t dwWidth;
+ uint32_t dwHeight;
+ uint32_t dwBytes_per_pixel; /* 3:RGB, 4:RGBA */
+ uint8_t *pucPixel_data;
+} SGIMPImage;
+
+#endif // _GIMP_IMAGE_
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/lcdd.h b/bsps/arm/atsam/contrib/libraries/libboard/include/lcdd.h
new file mode 100644
index 0000000000..c7cebcad6c
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/lcdd.h
@@ -0,0 +1,52 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Interface for LCD driver.
+ *
+ */
+
+#ifndef LCDD_H
+#define LCDD_H
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+extern void LCDD_Initialize(uint8_t lcdMode, sXdmad *dmad, uint8_t cRotate);
+
+extern void LCDD_On(void);
+
+extern void LCDD_Off(void);
+
+extern void LCDD_SetBacklight (uint32_t step);
+
+#endif /* #ifndef LCDD_H */
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/led.h b/bsps/arm/atsam/contrib/libraries/libboard/include/led.h
new file mode 100644
index 0000000000..d64f12c2d4
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/led.h
@@ -0,0 +1,72 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * \section Purpose
+ *
+ * Small set of functions for simple and portable LED usage.
+ *
+ * \section Usage
+ *
+ * -# Configure one or more LEDs using LED_Configure and
+ * LED_ConfigureAll.
+ * -# Set, clear and toggle LEDs using LED_Set, LED_Clear and
+ * LED_Toggle.
+ *
+ * LEDs are numbered starting from 0; the number of LEDs depend on the
+ * board being used. All the functions defined here will compile properly
+ * regardless of whether the LED is defined or not; they will simply
+ * return 0 when a LED which does not exist is given as an argument.
+ * Also, these functions take into account how each LED is connected on to
+ * board; thus, \ref LED_Set might change the level on the corresponding pin
+ * to 0 or 1, but it will always light the LED on; same thing for the other
+ * methods.
+ */
+
+#ifndef _LED_
+#define _LED_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+extern uint32_t LED_Configure(uint32_t dwLed);
+
+extern uint32_t LED_Set(uint32_t dwLed);
+
+extern uint32_t LED_Clear(uint32_t dwLed);
+
+extern uint32_t LED_Toggle(uint32_t dwLed);
+
+#endif /* #ifndef LED_H */
+
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/math.h b/bsps/arm/atsam/contrib/libraries/libboard/include/math.h
new file mode 100644
index 0000000000..e8f442f55b
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/math.h
@@ -0,0 +1,42 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+#ifndef _MATH_
+#define _MATH_
+
+/*------------------------------------------------------------------------------
+ * Exported functions
+ *------------------------------------------------------------------------------*/
+
+extern uint32_t min(uint32_t dwA, uint32_t dwB);
+extern uint32_t absv(int32_t lValue);
+extern uint32_t power(uint32_t dwX, uint32_t dwY);
+
+#endif /* #ifndef _MATH_ */
+
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/mcan_config.h b/bsps/arm/atsam/contrib/libraries/libboard/include/mcan_config.h
new file mode 100644
index 0000000000..7b2dc92e19
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/mcan_config.h
@@ -0,0 +1,126 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * \section Purpose
+ *
+ * Interface for configuring and using Timer Counter (TC) peripherals.
+ *
+ * \section Usage
+ * -# Optionally, use TC_FindMckDivisor() to let the program find the best
+ * TCCLKS field value automatically.
+ * -# Configure a Timer Counter in the desired mode using TC_Configure().
+ * -# Start or stop the timer clock using TC_Start() and TC_Stop().
+ */
+
+#ifndef _MCAN_CONFIG_
+#define _MCAN_CONFIG_
+
+/*------------------------------------------------------------------------------
+ * Headers
+ *------------------------------------------------------------------------------*/
+
+
+/*------------------------------------------------------------------------------
+ * Global functions
+ *------------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Programmable Clock Source for Baud Rate is Common To Both MCAN Controllers */
+#define MCAN_PROG_CLK_PRESCALER 1 /* /1 to /256 */
+// select one of the following for the programmable clock source
+//#define MCAN_PROG_CLK_SELECT PMC_PCK_CSS_SLOW_CLK
+//#define MCAN_PROG_CLK_SELECT PMC_PCK_CSS_MAIN_CLK
+//#define MCAN_PROG_CLK_SELECT PMC_PCK_CSS_PLLA_CLK
+//#define MCAN_PROG_CLK_SELECT PMC_PCK_CSS_UPLL_CLK
+#define MCAN_PROG_CLK_SELECT PMC_PCK_CSS_MCK
+#define MCAN_PROG_CLK_FREQ_HZ \
+ ((float) 150000000 / (float) MCAN_PROG_CLK_PRESCALER)
+
+#define MCAN0_BIT_RATE_BPS 500000
+#define MCAN0_PROP_SEG 2
+#define MCAN0_PHASE_SEG1 11
+#define MCAN0_PHASE_SEG2 11
+#define MCAN0_SYNC_JUMP 4
+
+#define MCAN0_FAST_BIT_RATE_BPS 2000000
+#define MCAN0_FAST_PROP_SEG 2
+#define MCAN0_FAST_PHASE_SEG1 4
+#define MCAN0_FAST_PHASE_SEG2 4
+#define MCAN0_FAST_SYNC_JUMP 2
+
+#define MCAN0_NMBR_STD_FLTS 8 /* 128 max filters */
+#define MCAN0_NMBR_EXT_FLTS 8 /* 64 max filters */
+#define MCAN0_NMBR_RX_FIFO0_ELMTS 0 /* # of elements, 64 elements max */
+#define MCAN0_NMBR_RX_FIFO1_ELMTS 0 /* # of elements, 64 elements max */
+#define MCAN0_NMBR_RX_DED_BUF_ELMTS 16 /* # of elements, 64 elements max */
+#define MCAN0_NMBR_TX_EVT_FIFO_ELMTS 0 /* # of elements, 32 elements max */
+#define MCAN0_NMBR_TX_DED_BUF_ELMTS 4 /* # of elements, 32 elements max */
+#define MCAN0_NMBR_TX_FIFO_Q_ELMTS 0 /* # of elements, 32 elements max */
+#define MCAN0_RX_FIFO0_ELMT_SZ 8 /* 8, 12, 16, 20, 24, 32, 48, 64 bytes */
+#define MCAN0_RX_FIFO1_ELMT_SZ 8 /* 8, 12, 16, 20, 24, 32, 48, 64 bytes */
+#define MCAN0_RX_BUF_ELMT_SZ 8 /* 8, 12, 16, 20, 24, 32, 48, 64 bytes */
+#define MCAN0_TX_BUF_ELMT_SZ 8 /* 8, 12, 16, 20, 24, 32, 48, 64 bytes */
+
+#define MCAN1_BIT_RATE_BPS 500000
+#define MCAN1_PROP_SEG 2
+#define MCAN1_PHASE_SEG1 11
+#define MCAN1_PHASE_SEG2 11
+#define MCAN1_SYNC_JUMP 4
+
+#define MCAN1_FAST_BIT_RATE_BPS 2000000
+#define MCAN1_FAST_PROP_SEG 2
+#define MCAN1_FAST_PHASE_SEG1 4
+#define MCAN1_FAST_PHASE_SEG2 4
+#define MCAN1_FAST_SYNC_JUMP 2
+
+#define MCAN1_NMBR_STD_FLTS 8 /* 128 max filters */
+#define MCAN1_NMBR_EXT_FLTS 8 /* 64 max filters */
+#define MCAN1_NMBR_RX_FIFO0_ELMTS 12 /* # of elements, 64 elements max */
+#define MCAN1_NMBR_RX_FIFO1_ELMTS 0 /* # of elements, 64 elements max */
+#define MCAN1_NMBR_RX_DED_BUF_ELMTS 4 /* # of elements, 64 elements max */
+#define MCAN1_NMBR_TX_EVT_FIFO_ELMTS 0 /* # of elements, 32 elements max */
+#define MCAN1_NMBR_TX_DED_BUF_ELMTS 4 /* # of elements, 32 elements max */
+#define MCAN1_NMBR_TX_FIFO_Q_ELMTS 4 /* # of elements, 32 elements max */
+#define MCAN1_RX_FIFO0_ELMT_SZ 8 /* 8, 12, 16, 20, 24, 32, 48, 64 bytes */
+#define MCAN1_RX_FIFO1_ELMT_SZ 8 /* 8, 12, 16, 20, 24, 32, 48, 64 bytes */
+#define MCAN1_RX_BUF_ELMT_SZ 64 /* 8, 12, 16, 20, 24, 32, 48, 64 bytes */
+#define MCAN1_TX_BUF_ELMT_SZ 32 /* 8, 12, 16, 20, 24, 32, 48, 64 bytes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #ifndef _MCAN_CONFIG_ */
+
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/rtc_calib.h b/bsps/arm/atsam/contrib/libraries/libboard/include/rtc_calib.h
new file mode 100644
index 0000000000..04b67cdd37
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/rtc_calib.h
@@ -0,0 +1,49 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Interface for Real Time Clock calibration (RTC) .
+ *
+ */
+
+/** RTC crystal **/
+
+
+typedef struct {
+ int8_t Tempr;
+ int16_t PPM;
+ uint8_t NEGPPM;
+ uint8_t HIGHPPM;
+ uint16_t CORRECTION;
+} RTC_PPMLookup;
+
+
+extern void RTC_ClockCalibration(Rtc *pRtc, int32_t CurrentTempr);
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/s25fl1.h b/bsps/arm/atsam/contrib/libraries/libboard/include/s25fl1.h
new file mode 100644
index 0000000000..3a6b65f540
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/s25fl1.h
@@ -0,0 +1,255 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Interface for the S25fl1 Serial Flash driver.
+ *
+ */
+
+#ifndef S25FL1_H
+#define S25FL1_H
+#define USE_QSPI_DMA
+/*----------------------------------------------------------------------------
+ * Macros
+ *----------------------------------------------------------------------------*/
+
+#define Size(pAt25) ((pAt25)->pDesc->size)
+#define PageSize(pAt25) ((pAt25)->pDesc->pageSize)
+#define BlockSize(pAt25) ((pAt25)->pDesc->blockSize)
+#define Name(pAt25) ((pAt25)->pDesc->name)
+#define ManId(pAt25) (((pAt25)->pDesc->jedecId) & 0xFF)
+#define PageNumber(pAt25) (Size(pAt25) / PageSize(pAt25))
+#define BlockNumber(pAt25) (Size(pAt25) / BlockSize(pAt25))
+#define PagePerBlock(pAt25) (BlockSize(pAt25) / PageSize(pAt25))
+#define BlockEraseCmd(pAt25) ((pAt25)->pDesc->blockEraseCmd)
+
+/*----------------------------------------------------------------------------
+ * Local definitions
+ *----------------------------------------------------------------------------*/
+
+/** Device is protected, operation cannot be carried out. */
+#define ERROR_PROTECTED 1
+/** Device is busy executing a command. */
+#define ERROR_BUSY 2
+/** There was a problem while trying to program page data. */
+#define ERROR_PROGRAM 3
+/** There was an SPI communication error. */
+#define ERROR_SPI 4
+
+/** Device ready/busy status bit. */
+#define STATUS_RDYBSY (1 << 0)
+/** Device is ready. */
+#define STATUS_RDYBSY_READY (0 << 0)
+/** Device is busy with internal operations. */
+#define STATUS_RDYBSY_BUSY (1 << 0)
+/** Write enable latch status bit. */
+#define STATUS_WEL (1 << 1)
+/** Device is not write enabled. */
+#define STATUS_WEL_DISABLED (0 << 1)
+/** Device is write enabled. */
+#define STATUS_WEL_ENABLED (1 << 1)
+/** Software protection status bit-field. */
+#define STATUS_SWP (3 << 2)
+/** All sectors are software protected. */
+#define STATUS_SWP_PROTALL (3 << 2)
+/** Some sectors are software protected. */
+#define STATUS_SWP_PROTSOME (1 << 2)
+/** No sector is software protected. */
+#define STATUS_SWP_PROTNONE (0 << 2)
+/** Write protect pin status bit. */
+#define STATUS_WPP (1 << 4)
+/** Write protect signal is not asserted. */
+#define STATUS_WPP_NOTASSERTED (0 << 4)
+/** Write protect signal is asserted. */
+#define STATUS_WPP_ASSERTED (1 << 4)
+/** Erase/program error bit. */
+#define STATUS_EPE (1 << 5)
+/** Erase or program operation was successful. */
+#define STATUS_EPE_SUCCESS (0 << 5)
+/** Erase or program error detected. */
+#define STATUS_EPE_ERROR (1 << 5)
+/** Sector protection registers locked bit. */
+#define STATUS_SPRL (1 << 7)
+/** Sector protection registers are unlocked. */
+#define STATUS_SPRL_UNLOCKED (0 << 7)
+/** Sector protection registers are locked. */
+#define STATUS_SPRL_LOCKED (1 << 7)
+
+/** Quad enable bit */
+#define STATUS_QUAD_ENABLE (1 << 1)
+/** Quad enable bit */
+#define STATUS_WRAP_ENABLE (0 << 4)
+
+/** Latency control bits */
+#define STATUS_LATENCY_CTRL (0xF << 0)
+
+#define STATUS_WRAP_BYTE (1 << 5)
+
+#define BLOCK_PROTECT_Msk (7 << 2)
+
+#define TOP_BTM_PROTECT_Msk (1 << 5)
+
+#define SEC_PROTECT_Msk (1 << 6)
+
+#define CHIP_PROTECT_Msk (0x1F << 2)
+
+/** Read array command code. */
+#define READ_ARRAY 0x0B
+/** Read array (low frequency) command code. */
+#define READ_ARRAY_LF 0x03
+/** Fast Read array command code. */
+#define READ_ARRAY_DUAL 0x3B
+/** Fast Read array command code. */
+#define READ_ARRAY_QUAD 0x6B
+/** Fast Read array command code. */
+#define READ_ARRAY_DUAL_IO 0xBB
+/** Fast Read array command code. */
+#define READ_ARRAY_QUAD_IO 0xEB
+/** Block erase command code (4K block). */
+#define BLOCK_ERASE_4K 0x20
+/** Block erase command code (32K block). */
+#define BLOCK_ERASE_32K 0x52
+/** Block erase command code (64K block). */
+#define BLOCK_ERASE_64K 0xD8
+/** Chip erase command code 1. */
+#define CHIP_ERASE_1 0x60
+/** Chip erase command code 2. */
+#define CHIP_ERASE_2 0xC7
+/** Byte/page program command code. */
+#define BYTE_PAGE_PROGRAM 0x02
+/** Sequential program mode command code 1. */
+#define SEQUENTIAL_PROGRAM_1 0xAD
+/** Sequential program mode command code 2. */
+#define SEQUENTIAL_PROGRAM_2 0xAF
+/** Write enable command code. */
+#define WRITE_ENABLE 0x06
+/** Write disable command code. */
+#define WRITE_DISABLE 0x04
+/** Protect sector command code. */
+#define PROTECT_SECTOR 0x36
+/** Unprotected sector command code. */
+#define UNPROTECT_SECTOR 0x39
+/** Read sector protection registers command code. */
+#define READ_SECTOR_PROT 0x3C
+/** Read status register command code. */
+#define READ_STATUS_1 0x05
+/** Read status register command code. */
+#define READ_STATUS_2 0x35
+/** Read status register command code. */
+#define READ_STATUS_3 0x33
+/** Write status register command code. */
+#define WRITE_STATUS 0x01
+/** Read manufacturer and device ID command code. */
+#define READ_JEDEC_ID 0x9F
+/** Deep power-down command code. */
+#define DEEP_PDOWN 0xB9
+/** Resume from deep power-down command code. */
+#define RES_DEEP_PDOWN 0xAB
+/** Resume from deep power-down command code. */
+#define SOFT_RESET_ENABLE 0x66
+/** Resume from deep power-down command code. */
+#define SOFT_RESET 0x99
+/** Resume from deep power-down command code. */
+#define WRAP_ENABLE 0x77
+/** Continuous Read Mode Reset command code. */
+#define CONT_MODE_RESET 0xFF
+
+/** SPI Flash Manufacturer JEDEC ID */
+#define ATMEL_SPI_FLASH 0x1F
+#define ST_SPI_FLASH 0x20
+#define WINBOND_SPI_FLASH 0xEF
+#define MACRONIX_SPI_FLASH 0xC2
+#define SST_SPI_FLASH 0xBF
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+uint32_t S25FL1D_ReadJedecId(void);
+
+void S25FL1D_InitFlashInterface(uint8_t Mode);
+
+void S25FL1D_SoftReset(void);
+
+void S25FL1D_ContReadModeReset(void);
+unsigned char S25FL1D_Unprotect(void);
+
+unsigned char S25FL1D_Protect(uint32_t StartAddr, uint32_t Size);
+
+void S25FL1D_QuadMode(uint8_t Enable);
+
+void S25FL1D_EnableWrap(uint8_t ByetAlign);
+
+void S25FL1D_SetReadLatencyControl(uint8_t Latency);
+
+unsigned char S25FL1D_EraseChip(void);
+
+unsigned char S25FL1D_EraseSector(unsigned int address);
+
+unsigned char S25FL1D_Erase64KBlock(unsigned int address);
+
+unsigned char S25FL1D_Write(
+ uint32_t *pData,
+ uint32_t size,
+ uint32_t address,
+ uint8_t Secure);
+
+extern unsigned char S25FL1D_Read(
+ uint32_t *pData,
+ uint32_t size,
+ uint32_t address);
+
+extern unsigned char S25FL1D_ReadDual(
+ uint32_t *pData,
+ uint32_t size,
+ uint32_t address);
+
+extern unsigned char S25FL1D_ReadQuad(
+ uint32_t *pData,
+ uint32_t size,
+ uint32_t address);
+
+extern unsigned char S25FL1D_ReadDualIO(
+ uint32_t *pData,
+ uint32_t size,
+ uint32_t address,
+ uint8_t ContMode,
+ uint8_t Secure);
+
+extern unsigned char S25FL1D_ReadQuadIO(
+ uint32_t *pData,
+ uint32_t size,
+ uint32_t address,
+ uint8_t ContMode,
+ uint8_t Secure);
+
+#endif // #ifndef S25FL1_H
+
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/include/wm8904.h b/bsps/arm/atsam/contrib/libraries/libboard/include/wm8904.h
new file mode 100644
index 0000000000..1cf73cd34e
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/include/wm8904.h
@@ -0,0 +1,160 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Implementation WM8904 driver.
+ *
+ */
+
+#ifndef WM8904_H
+#define WM8904_H
+
+#include "board.h"
+
+/*----------------------------------------------------------------------------
+ * Definitions
+ *----------------------------------------------------------------------------*/
+#define WM8904_CSB_STATE (0x0 << 0)
+
+/** Slave address */
+#define WM8904_SLAVE_ADDRESS 0x1a | WM8904_CSB_STATE
+#define CS2100_SLAVE_ADDRESS 0x4E
+
+
+/** Reset register*/
+#define WM8904_REG_RESET 0x00
+
+/** Bias control 0 register*/
+#define WM8904_REG_BIAS_CTRL0 0x04
+
+/** VMID control 0 register*/
+#define WM8904_REG_VMID_CTRL0 0x05
+
+/** MIC Bias control 0 register*/
+#define WM8904_REG_MICBIAS_CTRL0 0x06
+
+/** Bias control 1 register*/
+#define WM8904_REG_BIAS_CTRL1 0x07
+
+/** Power management control 0 register*/
+#define WM8904_REG_POWER_MANG0 0x0C
+/** Power management control 2 register*/
+#define WM8904_REG_POWER_MANG2 0x0E
+/** Power management control 3 register*/
+#define WM8904_REG_POWER_MANG3 0x0F
+/** Power management control 6 register*/
+#define WM8904_REG_POWER_MANG6 0x12
+
+/** Clock rate0 register*/
+#define WM8904_REG_CLOCK_RATE0 0x14
+/** Clock rate1 register*/
+#define WM8904_REG_CLOCK_RATE1 0x15
+
+/** Clock rate2 register*/
+#define WM8904_REG_CLOCK_RATE2 0x16
+
+/** Audio interface0 register*/
+#define WM8904_REG_AUD_INF0 0x18
+
+/** Audio interface1 register*/
+#define WM8904_REG_AUD_INF1 0x19
+/** Audio interface2 register*/
+#define WM8904_REG_AUD_INF2 0x1A
+/** Audio interface3 register*/
+#define WM8904_REG_AUD_INF3 0x1B
+
+/** ADC digital 0 register*/
+#define WM8904_REG_ADC_DIG0 0x20
+/** ADC digital 1 register*/
+#define WM8904_REG_ADC_DIG1 0x21
+
+/** Analogue left input 0 register*/
+#define WM8904_REG_ANALOGUE_LIN0 0x2C
+/** Analogue right input 0 register*/
+#define WM8904_REG_ANALOGUE_RIN0 0x2D
+
+/** Analogue left input 1 register*/
+#define WM8904_REG_ANALOGUE_LIN1 0x2E
+/** Analogue right input 1 register*/
+#define WM8904_REG_ANALOGUE_RIN1 0x2F
+
+/** Analogue left output 1 register*/
+#define WM8904_REG_ANALOGUE_LOUT1 0x39
+/** Analogue right output 1 register*/
+#define WM8904_REG_ANALOGUE_ROUT1 0x3A
+
+/** Analogue left output 2 register*/
+#define WM8904_REG_ANALOGUE_LOUT2 0x3B
+/** Analogue right output 2 register*/
+#define WM8904_REG_ANALOGUE_ROUT2 0x3C
+
+/** Analogue output 12 ZC register*/
+#define WM8904_REG_ANALOGUE_OUT12ZC 0x3D
+
+/** DC servo 0 register*/
+#define WM8904_REG_DC_SERVO0 0x43
+
+/** Analogue HP 0 register*/
+#define WM8904_REG_ANALOGUE_HP0 0x5A
+
+/** Charge pump 0 register*/
+#define WM8904_REG_CHARGE_PUMP0 0x62
+
+/** Class W 0 register*/
+#define WM8904_REG_CLASS0 0x68
+
+/** FLL control 1 register*/
+#define WM8904_REG_FLL_CRTL1 0x74
+/** FLL control 2 register*/
+#define WM8904_REG_FLL_CRTL2 0x75
+/** FLL control 3 register*/
+#define WM8904_REG_FLL_CRTL3 0x76
+/** FLL control 4 register*/
+#define WM8904_REG_FLL_CRTL4 0x77
+/** FLL control 5 register*/
+#define WM8904_REG_FLL_CRTL5 0x78
+
+/** DUMMY register*/
+#define WM8904_REG_END 0xFF
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+extern uint16_t WM8904_Read(Twid *pTwid, uint32_t device, uint32_t regAddr);
+extern void WM8904_Write(Twid *pTwid, uint32_t device, uint32_t regAddr,
+ uint16_t data);
+extern uint8_t WM8904_Init(Twid *pTwid, uint32_t device, uint32_t PCK);
+extern uint8_t WM8904_VolumeSet(Twid *pTwid, uint32_t device, uint16_t value);
+extern void WM8904_IN2R_IN1L(Twid *pTwid, uint32_t device);
+#endif // WM8904_H
+
+
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/resources_v71/system_samv71.c b/bsps/arm/atsam/contrib/libraries/libboard/resources_v71/system_samv71.c
new file mode 100644
index 0000000000..19c5a947b5
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/resources_v71/system_samv71.c
@@ -0,0 +1,318 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+#ifndef __rtems__
+#include "samv71.h"
+#else /* __rtems__ */
+#include <chip.h>
+#endif /* __rtems__ */
+
+/* @cond 0 */
+/**INDENT-OFF**/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**INDENT-ON**/
+ /* @endcond */
+
+ /* %ATMEL_SYSTEM% */
+ /* Clock Settings (600MHz PLL VDDIO 3.3V and VDDCORE 1.2V) */
+ /* Clock Settings (300MHz HCLK, 150MHz MCK)=> PRESC = 2, MDIV = 2 */
+#define SYS_BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8U))
+#ifndef __rtems__
+#if BOARD_MCK == 123000000
+ /* For example usb_video, PLLA/HCLK/MCK clock is set to 492/246/123MHz to achieve
+ the maximum performance, for other examples the clock is set to 300/300/150MHz */
+ #define SYS_BOARD_PLLAR (CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0x28U) | \
+ CKGR_PLLAR_PLLACOUNT(0x3fU) | CKGR_PLLAR_DIVA(0x1U))
+
+#define SYS_BOARD_MCKR_MDIV (PMC_MCKR_MDIV_PCK_DIV2)
+ #define SYS_BOARD_MCKR (PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK \
+ | SYS_BOARD_MCKR_MDIV)
+#elif BOARD_MCK == 150000000
+ #define SYS_BOARD_PLLAR (CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0x18U) | \
+ CKGR_PLLAR_PLLACOUNT(0x3fU) | CKGR_PLLAR_DIVA(0x1U))
+
+#define SYS_BOARD_MCKR_MDIV (PMC_MCKR_MDIV_PCK_DIV2)
+ #define SYS_BOARD_MCKR (PMC_MCKR_PRES_CLK_1 | PMC_MCKR_CSS_PLLA_CLK \
+ | SYS_BOARD_MCKR_MDIV)
+#else
+ #error "unexpected Main Clock (MCK) frequency"
+#endif
+
+ uint32_t SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;
+#else /* __rtems__ */
+#define SYS_BOARD_MCKR_MDIV ((atsam_clock_config.mckr_init) & PMC_MCKR_MDIV_Msk)
+#define SYS_BOARD_MCKR (atsam_clock_config.mckr_init)
+#define SYS_BOARD_PLLAR (atsam_clock_config.pllar_init)
+#endif /* __rtems__ */
+#define USBCLK_DIV 10
+
+ /**
+ * \brief Setup the microcontroller system.
+ * Initialize the System and update the SystemFrequency variable.
+ */
+#ifndef __rtems__
+ void SystemInit(void)
+#else /* __rtems__ */
+ void ATSAM_START_SRAM_SECTION SystemInit(void)
+#endif /* __rtems__ */
+{
+ uint32_t read_MOR;
+ /* Set FWS according to SYS_BOARD_MCKR configuration */
+ EFC->EEFC_FMR = EEFC_FMR_FWS(5);
+
+ /* Before switching MAIN OSC on external crystal : enable it and don't
+ * disable at the same time RC OSC in case of if MAIN OSC is still using RC
+ * OSC
+ */
+
+#if ATSAM_SLOWCLOCK_USE_XTAL == 1
+ read_MOR = PMC->CKGR_MOR;
+ /* enable external crystal - enable RC OSC */
+ read_MOR |= (CKGR_MOR_KEY_PASSWD | CKGR_MOR_XT32KFME);
+ PMC->CKGR_MOR = read_MOR;
+
+ /* Select XTAL 32k instead of internal slow RC 32k for slow clock */
+ if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST) {
+ SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_XTALSEL_CRYSTAL_SEL;
+
+ while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL));
+ }
+#endif
+
+ /* Initialize main oscillator */
+ if (!(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)) {
+ PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | SYS_BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN |
+ CKGR_MOR_MOSCXTEN;
+
+ while (!(PMC->PMC_SR & PMC_SR_MOSCXTS)) {
+ }
+ }
+
+ /* Switch to 3-20MHz Xtal oscillator */
+ PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | SYS_BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN |
+ CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL;
+
+ while (!(PMC->PMC_SR & PMC_SR_MOSCSELS)) {
+ }
+
+ PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) |
+ PMC_MCKR_CSS_MAIN_CLK;
+
+ while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
+ }
+
+ /* Initialize PLLA */
+ PMC->CKGR_PLLAR = SYS_BOARD_PLLAR;
+
+ while (!(PMC->PMC_SR & PMC_SR_LOCKA)) {
+ }
+
+ /* Switch to main clock: DO NOT modify MDIV and CSS feild at the same access */
+ PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_MDIV_Msk) |
+ SYS_BOARD_MCKR_MDIV;
+ PMC->PMC_MCKR = (SYS_BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
+
+ while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
+ }
+
+ /* Switch to PLLA */
+ PMC->PMC_MCKR = SYS_BOARD_MCKR;
+
+ while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) {
+ }
+
+#ifndef __rtems__
+ SystemCoreClock = CHIP_FREQ_CPU_MAX;
+#endif /* __rtems__ */
+}
+
+#ifndef __rtems__
+void SystemCoreClockUpdate(void)
+{
+ /* Determine clock frequency according to clock register values */
+ switch (PMC->PMC_MCKR & (uint32_t) PMC_MCKR_CSS_Msk) {
+ case PMC_MCKR_CSS_SLOW_CLK: /* Slow clock */
+ if (SUPC->SUPC_SR & SUPC_SR_OSCSEL)
+ SystemCoreClock = CHIP_FREQ_XTAL_32K;
+ else
+ SystemCoreClock = CHIP_FREQ_SLCK_RC;
+
+ break;
+
+ case PMC_MCKR_CSS_MAIN_CLK: /* Main clock */
+ if (PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)
+ SystemCoreClock = CHIP_FREQ_XTAL_12M;
+ else {
+ SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;
+
+ switch (PMC->CKGR_MOR & CKGR_MOR_MOSCRCF_Msk) {
+ case CKGR_MOR_MOSCRCF_4_MHz:
+ break;
+
+ case CKGR_MOR_MOSCRCF_8_MHz:
+ SystemCoreClock *= 2U;
+ break;
+
+ case CKGR_MOR_MOSCRCF_12_MHz:
+ SystemCoreClock *= 3U;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ break;
+
+ case PMC_MCKR_CSS_PLLA_CLK: /* PLLA clock */
+ if (PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)
+ SystemCoreClock = CHIP_FREQ_XTAL_12M;
+ else {
+ SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;
+
+ switch (PMC->CKGR_MOR & CKGR_MOR_MOSCRCF_Msk) {
+ case CKGR_MOR_MOSCRCF_4_MHz:
+ break;
+
+ case CKGR_MOR_MOSCRCF_8_MHz:
+ SystemCoreClock *= 2U;
+ break;
+
+ case CKGR_MOR_MOSCRCF_12_MHz:
+ SystemCoreClock *= 3U;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if ((uint32_t) (PMC->PMC_MCKR & (uint32_t) PMC_MCKR_CSS_Msk) ==
+ PMC_MCKR_CSS_PLLA_CLK) {
+ SystemCoreClock *= ((((PMC->CKGR_PLLAR) & CKGR_PLLAR_MULA_Msk) >>
+ CKGR_PLLAR_MULA_Pos) + 1U);
+ SystemCoreClock /= ((((PMC->CKGR_PLLAR) & CKGR_PLLAR_DIVA_Msk) >>
+ CKGR_PLLAR_DIVA_Pos));
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ if ((PMC->PMC_MCKR & PMC_MCKR_PRES_Msk) == PMC_MCKR_PRES_CLK_3)
+ SystemCoreClock /= 3U;
+ else
+ SystemCoreClock >>= ((PMC->PMC_MCKR & PMC_MCKR_PRES_Msk) >> PMC_MCKR_PRES_Pos);
+}
+#endif /* __rtems__ */
+/**
+ * Initialize flash.
+ */
+void system_init_flash(uint32_t ul_clk)
+{
+ /* Set FWS for embedded Flash access according to operating frequency */
+ if (ul_clk < CHIP_FREQ_FWS_0)
+ EFC->EEFC_FMR = EEFC_FMR_FWS(0) | EEFC_FMR_CLOE;
+ else {
+ if (ul_clk < CHIP_FREQ_FWS_1)
+ EFC->EEFC_FMR = EEFC_FMR_FWS(1) | EEFC_FMR_CLOE;
+ else {
+ if (ul_clk < CHIP_FREQ_FWS_2)
+ EFC->EEFC_FMR = EEFC_FMR_FWS(2) | EEFC_FMR_CLOE;
+ else {
+ if (ul_clk < CHIP_FREQ_FWS_3)
+ EFC->EEFC_FMR = EEFC_FMR_FWS(3) | EEFC_FMR_CLOE;
+ else {
+ if (ul_clk < CHIP_FREQ_FWS_4)
+ EFC->EEFC_FMR = EEFC_FMR_FWS(4) | EEFC_FMR_CLOE;
+ else
+ EFC->EEFC_FMR = EEFC_FMR_FWS(5) | EEFC_FMR_CLOE;
+ }
+ }
+ }
+ }
+}
+
+/**
+ * \brief Enable USB clock.
+ *
+ * \param pll_id Source of the USB clock.
+ * \param div Actual clock divisor. Must be superior to 0.
+ */
+void sysclk_enable_usb(void)
+{
+ /* Disable FS USB clock*/
+ PMC->PMC_SCDR = PMC_SCDR_USBCLK;
+
+ /* Enable PLL 480 MHz */
+ PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);
+
+ /* Wait that PLL is considered locked by the PMC */
+ while (!(PMC->PMC_SR & PMC_SR_LOCKU));
+
+ /* USB clock register: USB Clock Input is UTMI PLL */
+ PMC->PMC_USB = (PMC_USB_USBS | PMC_USB_USBDIV(USBCLK_DIV - 1));
+
+ PMC->PMC_SCER = PMC_SCER_USBCLK;
+}
+
+
+/**
+ * \brief Disables USB clock.
+ *
+ *
+ * \param pll_id Source of the USB clock.
+ * \param div Actual clock divisor. Must be superior to 0.
+ */
+void sysclk_disable_usb(void)
+{
+ /* Disable FS USB clock*/
+ PMC->PMC_SCDR = PMC_SCDR_USBCLK;
+
+ /* Enable PLL 480 MHz */
+ PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);
+
+ /* Wait that PLL is considered locked by the PMC */
+ while (!(PMC->PMC_SR & PMC_SR_LOCKU));
+
+ /* USB clock register: USB Clock Input is UTMI PLL */
+ PMC->PMC_USB = (PMC_USB_USBS | PMC_USB_USBDIV(USBCLK_DIV - 1));
+}
+
+/* @cond 0 */
+/**INDENT-OFF**/
+#ifdef __cplusplus
+}
+#endif
+/**INDENT-ON**/
+/* @endcond */
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/source/board_lowlevel.c b/bsps/arm/atsam/contrib/libraries/libboard/source/board_lowlevel.c
new file mode 100644
index 0000000000..cbdf41ba73
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/source/board_lowlevel.c
@@ -0,0 +1,434 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Provides the low-level initialization function that called on chip startup.
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#ifndef __rtems__
+#include "board.h"
+#else /* __rtems__ */
+#define MPU_HAS_NOCACHE_REGION
+#include <chip.h>
+#include <include/board_lowlevel.h>
+#endif /* __rtems__ */
+
+
+#if defined(ENABLE_TCM) && defined(__GNUC__)
+ extern char _itcm_lma, _sitcm, _eitcm;
+#endif
+
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+/* Default memory map
+ NO. Address range Memory region Memory type Shareable? Cache policy
+ 1 0x00000000- 0x1FFFFFFF Code Normal
+ 0x00000000- 0x003FFFFF ITCM
+ 0x00400000- 0x005FFFFF Internal flash Normal Not shareable WB
+ 2 0x20000000- 0x3FFFFFFF SRAM Normal
+ 0x20000000- 0x203FFFFF DTCM
+ 0x20400000- 0x2043FFFF First Partition Normal Not shareable WB
+ if MPU_HAS_NOCACHE_REGION is defined
+ 0x20440000- 0x2045EFFF Second Partition Normal Not shareable WB
+ 0x2045F000- 0x2045FFFF Nocache SRAM Normal Shareable
+ if MPU_HAS_NOCACHE_REGION is NOT defined
+ 0x20440000- 0x2045FFFF Second Partition Normal Not shareable WB
+ 3 0x40000000- 0x5FFFFFFF Peripheral Device Shareable
+ 4 0x60000000- 0x7FFFFFFF RAM
+ 0x60000000- 0x6FFFFFFF External EBI Strongly-ordered Shareable
+ 0x70000000- 0x7FFFFFFF SDRAM Normal Shareable WBWA
+ 5 0x80000000- 0x9FFFFFFF QSPI Strongly-ordered Shareable
+ 6 0xA0100000- 0xA01FFFFF USBHS RAM Device Shareable
+ 7 0xE0000000- 0xFFFFFFFF System - -
+ */
+
+/**
+ * \brief Set up a memory region.
+ */
+void _SetupMemoryRegion(void)
+{
+
+ uint32_t dwRegionBaseAddr;
+ uint32_t dwRegionAttr;
+
+ memory_barrier();
+
+ /***************************************************
+ ITCM memory region --- Normal
+ START_Addr:- 0x00000000UL
+ END_Addr:- 0x003FFFFFUL
+ ****************************************************/
+
+ dwRegionBaseAddr =
+ ITCM_START_ADDRESS |
+ MPU_REGION_VALID |
+ MPU_DEFAULT_ITCM_REGION; // 1
+
+#ifdef __rtems__
+ if (ITCM_END_ADDRESS + 1 != ITCM_START_ADDRESS) {
+#endif /* __rtems__ */
+ dwRegionAttr =
+ MPU_AP_PRIVILEGED_READ_WRITE |
+ MPU_CalMPURegionSize(ITCM_END_ADDRESS - ITCM_START_ADDRESS) |
+ MPU_REGION_ENABLE;
+#ifdef __rtems__
+ } else {
+ dwRegionAttr = MPU_REGION_DISABLE;
+ }
+#endif /* __rtems__ */
+
+ MPU_SetRegion(dwRegionBaseAddr, dwRegionAttr);
+
+
+ /****************************************************
+ Internal flash memory region --- Normal read-only
+ (update to Strongly ordered in write accesses)
+ START_Addr:- 0x00400000UL
+ END_Addr:- 0x005FFFFFUL
+ ******************************************************/
+
+ dwRegionBaseAddr =
+ IFLASH_START_ADDRESS |
+ MPU_REGION_VALID |
+ MPU_DEFAULT_IFLASH_REGION; //2
+
+ dwRegionAttr =
+ MPU_AP_READONLY |
+ INNER_NORMAL_WB_NWA_TYPE(NON_SHAREABLE) |
+ MPU_CalMPURegionSize(IFLASH_END_ADDRESS - IFLASH_START_ADDRESS) |
+ MPU_REGION_ENABLE;
+
+ MPU_SetRegion(dwRegionBaseAddr, dwRegionAttr);
+
+ /****************************************************
+ DTCM memory region --- Normal
+ START_Addr:- 0x20000000L
+ END_Addr:- 0x203FFFFFUL
+ ******************************************************/
+
+ /* DTCM memory region */
+ dwRegionBaseAddr =
+ DTCM_START_ADDRESS |
+ MPU_REGION_VALID |
+ MPU_DEFAULT_DTCM_REGION; //3
+
+#ifdef __rtems__
+ if (DTCM_END_ADDRESS + 1 != DTCM_START_ADDRESS) {
+#endif /* __rtems__ */
+ dwRegionAttr =
+ MPU_AP_PRIVILEGED_READ_WRITE |
+ INNER_NORMAL_NOCACHE_TYPE(NON_SHAREABLE) |
+ MPU_CalMPURegionSize(DTCM_END_ADDRESS - DTCM_START_ADDRESS) |
+ MPU_REGION_ENABLE;
+#ifdef __rtems__
+ } else {
+ dwRegionAttr = MPU_REGION_DISABLE;
+ }
+#endif /* __rtems__ */
+
+ MPU_SetRegion(dwRegionBaseAddr, dwRegionAttr);
+
+
+ /****************************************************
+ SRAM Cacheable memory region --- Normal
+ START_Addr:- 0x20400000UL
+ END_Addr:- 0x2043FFFFUL
+ ******************************************************/
+ /* SRAM memory region */
+ dwRegionBaseAddr =
+ SRAM_FIRST_START_ADDRESS |
+ MPU_REGION_VALID |
+ MPU_DEFAULT_SRAM_REGION_1; //4
+
+ dwRegionAttr =
+ MPU_AP_FULL_ACCESS |
+ INNER_NORMAL_WB_NWA_TYPE(NON_SHAREABLE) |
+ MPU_CalMPURegionSize(SRAM_FIRST_END_ADDRESS - SRAM_FIRST_START_ADDRESS)
+ | MPU_REGION_ENABLE;
+
+ MPU_SetRegion(dwRegionBaseAddr, dwRegionAttr);
+
+
+ /****************************************************
+ Internal SRAM second partition memory region --- Normal
+ START_Addr:- 0x20440000UL
+ END_Addr:- 0x2045FFFFUL
+ ******************************************************/
+#ifndef __rtems__
+ /* SRAM memory region */
+ dwRegionBaseAddr =
+ SRAM_SECOND_START_ADDRESS |
+ MPU_REGION_VALID |
+ MPU_DEFAULT_SRAM_REGION_2; //5
+
+ dwRegionAttr =
+ MPU_AP_FULL_ACCESS |
+ INNER_NORMAL_WB_NWA_TYPE(NON_SHAREABLE) |
+ MPU_CalMPURegionSize(SRAM_SECOND_END_ADDRESS - SRAM_SECOND_START_ADDRESS) |
+ MPU_REGION_ENABLE;
+
+ MPU_SetRegion(dwRegionBaseAddr, dwRegionAttr);
+#else /* __rtems__ */
+ /* NOTE: The first SRAM region is increased so it covers the whole SRAM. If
+ * the SRAM is something odd (like 384k on the SAME70Q21), the next higher
+ * power of two will be used (in the example: 512k). That removes the need of
+ * the second SRAM region. There is currently no memory after the SRAM so that
+ * shouldn't be a problem. */
+#endif /* __rtems__ */
+
+#ifdef MPU_HAS_NOCACHE_REGION
+ dwRegionBaseAddr =
+ SRAM_NOCACHE_START_ADDRESS |
+ MPU_REGION_VALID |
+ MPU_NOCACHE_SRAM_REGION; //11
+
+ dwRegionAttr =
+ MPU_AP_FULL_ACCESS |
+ INNER_OUTER_NORMAL_NOCACHE_TYPE(SHAREABLE) |
+ MPU_CalMPURegionSize(NOCACHE_SRAM_REGION_SIZE) |
+ MPU_REGION_ENABLE;
+
+ MPU_SetRegion(dwRegionBaseAddr, dwRegionAttr);
+#endif
+
+ /****************************************************
+ Peripheral memory region --- DEVICE Shareable
+ START_Addr:- 0x40000000UL
+ END_Addr:- 0x5FFFFFFFUL
+ ******************************************************/
+ dwRegionBaseAddr =
+ PERIPHERALS_START_ADDRESS |
+ MPU_REGION_VALID |
+ MPU_PERIPHERALS_REGION; //6
+
+ dwRegionAttr = MPU_AP_FULL_ACCESS |
+ MPU_REGION_EXECUTE_NEVER |
+ SHAREABLE_DEVICE_TYPE |
+ MPU_CalMPURegionSize(PERIPHERALS_END_ADDRESS - PERIPHERALS_START_ADDRESS)
+ | MPU_REGION_ENABLE;
+
+ MPU_SetRegion(dwRegionBaseAddr, dwRegionAttr);
+
+#ifdef __rtems__
+ dwRegionBaseAddr =
+ SYSTEM_START_ADDRESS |
+ MPU_REGION_VALID |
+ MPU_SYSTEM_REGION;
+
+ dwRegionAttr = MPU_AP_FULL_ACCESS |
+ MPU_REGION_EXECUTE_NEVER |
+ SHAREABLE_DEVICE_TYPE |
+ MPU_CalMPURegionSize(SYSTEM_END_ADDRESS - SYSTEM_START_ADDRESS)
+ | MPU_REGION_ENABLE;
+
+ MPU_SetRegion(dwRegionBaseAddr, dwRegionAttr);
+#endif /* __rtems__ */
+
+ /****************************************************
+ External EBI memory memory region --- Strongly Ordered
+ START_Addr:- 0x60000000UL
+ END_Addr:- 0x6FFFFFFFUL
+ ******************************************************/
+ dwRegionBaseAddr =
+ EXT_EBI_START_ADDRESS |
+ MPU_REGION_VALID |
+ MPU_EXT_EBI_REGION;
+
+ dwRegionAttr =
+ MPU_AP_FULL_ACCESS |
+ /* External memory Must be defined with 'Device' or 'Strongly Ordered'
+ attribute for write accesses (AXI) */
+ STRONGLY_ORDERED_SHAREABLE_TYPE |
+ MPU_CalMPURegionSize(EXT_EBI_END_ADDRESS - EXT_EBI_START_ADDRESS) |
+ MPU_REGION_ENABLE;
+
+ MPU_SetRegion(dwRegionBaseAddr, dwRegionAttr);
+
+ /****************************************************
+ SDRAM Cacheable memory region --- Normal
+ START_Addr:- 0x70000000UL
+ END_Addr:- 0x7FFFFFFFUL
+ ******************************************************/
+ dwRegionBaseAddr =
+ SDRAM_START_ADDRESS |
+ MPU_REGION_VALID |
+ MPU_DEFAULT_SDRAM_REGION; //7
+
+ dwRegionAttr =
+ MPU_AP_FULL_ACCESS |
+ INNER_NORMAL_WB_RWA_TYPE(SHAREABLE) |
+ MPU_CalMPURegionSize(SDRAM_END_ADDRESS - SDRAM_START_ADDRESS) |
+ MPU_REGION_ENABLE;
+
+ MPU_SetRegion(dwRegionBaseAddr, dwRegionAttr);
+
+ /****************************************************
+ QSPI memory region --- Normal
+ START_Addr:- 0x80000000UL
+ END_Addr:- 0x9FFFFFFFUL
+ ******************************************************/
+ dwRegionBaseAddr =
+ QSPI_START_ADDRESS |
+ MPU_REGION_VALID |
+ MPU_QSPIMEM_REGION; //8
+
+#ifdef __rtems__
+ if (QSPI_END_ADDRESS + 1 != QSPI_START_ADDRESS) {
+#endif /* __rtems__ */
+ dwRegionAttr =
+ MPU_AP_FULL_ACCESS |
+ INNER_NORMAL_WB_NWA_TYPE(SHAREABLE) |
+ MPU_CalMPURegionSize(QSPI_END_ADDRESS - QSPI_START_ADDRESS) |
+ MPU_REGION_ENABLE;
+#ifdef __rtems__
+ } else {
+ dwRegionAttr = MPU_REGION_DISABLE;
+ }
+#endif /* __rtems__ */
+
+ MPU_SetRegion(dwRegionBaseAddr, dwRegionAttr);
+
+
+ /****************************************************
+ USB RAM Memory region --- Device
+ START_Addr:- 0xA0100000UL
+ END_Addr:- 0xA01FFFFFUL
+ ******************************************************/
+ dwRegionBaseAddr =
+ USBHSRAM_START_ADDRESS |
+ MPU_REGION_VALID |
+ MPU_USBHSRAM_REGION; //9
+
+ dwRegionAttr =
+ MPU_AP_FULL_ACCESS |
+ MPU_REGION_EXECUTE_NEVER |
+ SHAREABLE_DEVICE_TYPE |
+ MPU_CalMPURegionSize(USBHSRAM_END_ADDRESS - USBHSRAM_START_ADDRESS) |
+ MPU_REGION_ENABLE;
+
+ MPU_SetRegion(dwRegionBaseAddr, dwRegionAttr);
+
+
+ /* Enable the memory management fault , Bus Fault, Usage Fault exception */
+ SCB->SHCSR |= (SCB_SHCSR_MEMFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk
+ | SCB_SHCSR_USGFAULTENA_Msk);
+
+ /* Enable the MPU region */
+#ifndef __rtems__
+ MPU_Enable(MPU_ENABLE | MPU_PRIVDEFENA);
+#else /* __rtems__ */
+ MPU_Enable(MPU_ENABLE);
+#endif /* __rtems__ */
+
+ memory_sync();
+}
+
+#ifdef ENABLE_TCM
+
+#if defined (__ICCARM__) /* IAR Ewarm */
+ #pragma section = "CSTACK"
+ #pragma section = "CSTACK_DTCM"
+ #define SRAM_STACK_BASE (__section_begin("CSTACK"))
+ #define DTCM_STACK_BASE (__section_begin("CSTACK_DTCM"))
+ #define SRAM_STACK_LIMIT (__section_end("CSTACK"))
+ #define DTCM_STACK_LIMIT (__section_end("CSTACK_DTCM"))
+#elif defined (__CC_ARM) /* MDK */
+ extern uint32_t Image$$ARM_LIB_STACK$$Base;
+ extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Limit;
+ extern uint32_t Image$$DTCM_STACK$$Base;
+ extern uint32_t Image$$DTCM_STACK$$ZI$$Limit;
+ #define SRAM_STACK_BASE (&Image$$ARM_LIB_STACK$$Base)
+ #define DTCM_STACK_BASE (&Image$$DTCM_STACK$$Base)
+ #define SRAM_STACK_LIMIT (&Image$$ARM_LIB_STACK$$ZI$$Limit)
+ #define DTCM_STACK_LIMIT (&Image$$DTCM_STACK$$ZI$$Limit)
+#elif defined (__GNUC__) /* GCC */
+ extern char _sdtcm_stack, _edtcm_stack, _sstack, _estack;
+ #define SRAM_STACK_BASE ((void *)(&_sstack))
+ #define DTCM_STACK_BASE ((void *)(&_sdtcm_stack))
+ #define SRAM_STACK_LIMIT ((void *)(&_estack))
+ #define DTCM_STACK_LIMIT ((void *)(&_edtcm_stack))
+#endif
+
+/** \brief Change stack's location to DTCM
+
+ The function changes the stack's location from SRAM to DTCM
+ */
+void TCM_StackInit(void);
+void TCM_StackInit(void)
+{
+ uint32_t offset = (uint32_t)SRAM_STACK_LIMIT - (uint32_t)DTCM_STACK_LIMIT;
+ volatile char *dst = (volatile char *)DTCM_STACK_LIMIT;
+ volatile char *src = (volatile char *)SRAM_STACK_LIMIT;
+
+ /* copy stack data from SRAM to DTCM */
+ while (src > (volatile char *)SRAM_STACK_BASE)
+ *--dst = *--src;
+
+ __set_MSP(__get_MSP() - offset);
+}
+
+#endif
+
+
+/**
+ * \brief Performs the low-level initialization of the chip.
+ */
+extern WEAK void LowLevelInit(void)
+{
+
+ SystemInit();
+#ifndef MPU_EXAMPLE_FEATURE
+ _SetupMemoryRegion();
+#endif
+
+#if defined(FFT_DEMO) && (defined(__GNUC__) || defined(__CC_ARM))
+ /* Enabling the FPU */
+ SCB->CPACR |= 0x00F00000;
+ __DSB();
+ __ISB();
+#endif
+
+#if defined(ENABLE_TCM) && defined(__GNUC__)
+ volatile char *dst = &_sitcm;
+ volatile char *src = &_itcm_lma;
+
+ /* copy code_TCM from flash to ITCM */
+ while (dst < &_eitcm)
+ *dst++ = *src++;
+
+#endif
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/source/board_memories.c b/bsps/arm/atsam/contrib/libraries/libboard/source/board_memories.c
new file mode 100644
index 0000000000..56e233736f
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/source/board_memories.c
@@ -0,0 +1,293 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Implementation of memories configuration on board.
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+#ifndef __rtems__
+#include "board.h"
+#else /* __rtems__ */
+#include <chip.h>
+#include <include/board_memories.h>
+#endif /* __rtems__ */
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+#define SDRAM_BA0 (1 << 20)
+#define SDRAM_BA1 (1 << 21)
+
+
+#ifndef __rtems__
+uint32_t BOARD_SdramValidation(uint32_t baseAddr, uint32_t size)
+{
+ uint32_t i;
+ uint32_t ret = 1;
+ uint32_t *ptr32 = (uint32_t *) baseAddr;
+ uint16_t *ptr16 = (uint16_t *) baseAddr;
+ uint8_t *ptr8 = (uint8_t *) baseAddr;
+ /* Test for 55AA55AA/AA55AA55 pattern */
+ printf(" Test for 55AA55AA/AA55AA55 pattern ... \n\r");
+
+ for (i = 0; i < size; i ++) {
+ if (i & 1)
+ ptr32[i] = 0x55AA55AA;
+ else
+ ptr32[i] = 0xAA55AA55;
+
+ memory_barrier()
+ }
+
+ for (i = 0; i < size; i++) {
+ if (i & 1) {
+ if (ptr32[i] != 0x55AA55AA) {
+ printf("-E- Expected:%x, read %x @ %x \n\r" ,
+ 0xAA55AA55, (unsigned)ptr32[i], (unsigned)(baseAddr + i));
+ ret = 0;
+
+ }
+ } else {
+ if (ptr32[i] != 0xAA55AA55) {
+ printf("-E- Expected:%x, read %x @ %x \n\r" ,
+ 0xAA55AA55 , (unsigned)ptr32[i], (unsigned)(baseAddr + i));
+ ret = 0;
+ }
+ }
+ }
+
+ if (!ret) return ret;
+
+ printf(" Test for BYTE accessing... \n\r");
+
+ /* Test for BYTE accessing */
+ for (i = 0; i < size; i ++)
+ ptr8[i] = (uint8_t)(i & 0xFF);
+
+ for (i = 0; i < size; i++) {
+ if (ptr8[i] != (uint8_t)(i & 0xFF)) {
+ printf("-E- Expected:%x, read %x @ %x \n\r" ,
+ (unsigned)(i & 0xFF), ptr8[i], (unsigned)(baseAddr + i));
+ ret = 0;
+ }
+ }
+
+ if (!ret) return ret;
+
+ printf(" Test for WORD accessing... \n\r");
+
+ /* Test for WORD accessing */
+ for (i = 0; i < size / 2; i ++)
+ ptr16[i] = (uint16_t)(i & 0xFFFF);
+
+ for (i = 0; i < size / 2; i++) {
+ if (ptr16[i] != (uint16_t)(i & 0xFFFF)) {
+ printf("-E- Expected:%x, read %x @ %x \n\r" ,
+ (unsigned)(i & 0xFFFF), ptr16[i], (unsigned)(baseAddr + i));
+ ret = 0;
+ }
+ }
+
+ if (!ret) return ret;
+
+ printf(" Test for DWORD accessing... \n\r");
+
+ /* Test for DWORD accessing */
+ for (i = 0; i < size / 4; i ++) {
+ ptr32[i] = (uint32_t)(i & 0xFFFFFFFF);
+ memory_barrier()
+ }
+
+ for (i = 0; i < size / 4; i++) {
+ if (ptr32[i] != (uint32_t)(i & 0xFFFFFFFF)) {
+ printf("-E- Expected:%x, read %x @ %x \n\r" ,
+ (unsigned)(i & 0xFFFFFFFF), (unsigned)ptr32[i], (unsigned)(baseAddr + i));
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+#endif /* __rtems__ */
+
+
+/**
+ * \brief Configures the EBI for SDRAM (IS42S16100E-7B) access.
+ */
+
+
+void BOARD_ConfigureSdram(void)
+{
+#ifndef __rtems__
+ const Pin pinsSdram[] = {BOARD_SDRAM_PINS};
+#endif /* __rtems__ */
+ volatile uint32_t i;
+ volatile uint8_t *pSdram = (uint8_t *) SDRAM_CS_ADDR;
+
+ /* Configure PIO */
+#ifndef __rtems__
+ PIO_Configure(pinsSdram, PIO_LISTSIZE(pinsSdram));
+#endif /* __rtems__ */
+ PMC_EnablePeripheral(ID_SDRAMC);
+ MATRIX->CCFG_SMCNFCS = CCFG_SMCNFCS_SDRAMEN;
+
+ /* 1. SDRAM features must be set in the configuration register:
+ asynchronous timings (TRC, TRAS, etc.), number of columns, rows,
+ CAS latency, and the data bus width. */
+#ifndef __rtems__
+ SDRAMC->SDRAMC_CR =
+ SDRAMC_CR_NC_COL8 // 8 column bits
+ | SDRAMC_CR_NR_ROW11 // 12 row bits (4K)
+ | SDRAMC_CR_CAS_LATENCY3 // CAS Latency 3
+ | SDRAMC_CR_NB_BANK2 // 2 banks
+ | SDRAMC_CR_DBW // 16 bit
+ | SDRAMC_CR_TWR(5)
+ | SDRAMC_CR_TRC_TRFC(13) // 63ns min
+ | SDRAMC_CR_TRP(5) // Command period (PRE to ACT) 21 ns min
+ | SDRAMC_CR_TRCD(
+ 5) // Active Command to read/Write Command delay time 21ns min
+ | SDRAMC_CR_TRAS(9) // Command period (ACT to PRE) 42ns min
+ | SDRAMC_CR_TXSR(15U); // Exit self-refresh to active time 70ns Min
+#else /* __rtems__ */
+ SDRAMC->SDRAMC_CR = BOARD_Sdram_Config.sdramc_cr;
+#endif /* __rtems__ */
+
+ /* 2. For mobile SDRAM, temperature-compensated self refresh (TCSR), drive
+ strength (DS) and partial array self refresh (PASR) must be set in the
+ Low Power Register. */
+
+ /* 3. The SDRAM memory type must be set in the Memory Device Register.*/
+#ifndef __rtems__
+ SDRAMC->SDRAMC_MDR = SDRAMC_MDR_MD_SDRAM;
+#else /* __rtems__ */
+ SDRAMC->SDRAMC_MDR = BOARD_Sdram_Config.sdramc_mdr;
+#endif /* __rtems__ */
+
+ /* 4. A minimum pause of 200 ¦Ìs is provided to precede any signal toggle.*/
+ for (i = 0; i < 100000; i++);
+
+ /* 5. (1)A NOP command is issued to the SDRAM devices. The application must
+ set Mode to 1 in the Mode Register and perform a write access to
+ any SDRAM address.*/
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_NOP;
+#ifdef __rtems__
+ (void) SDRAMC->SDRAMC_MR;
+ __DMB();
+#endif /* __rtems__ */
+ *pSdram = 0;
+
+ for (i = 0; i < 100000; i++);
+
+ /* 6. An All Banks Precharge command is issued to the SDRAM devices.
+ The application must set Mode to 2 in the Mode Register and perform a write
+ access to any SDRAM address. */
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_ALLBANKS_PRECHARGE;
+#ifdef __rtems__
+ (void) SDRAMC->SDRAMC_MR;
+ __DMB();
+#endif /* __rtems__ */
+ *pSdram = 0;
+
+ for (i = 0; i < 100000; i++);
+
+ /* 7. Eight auto-refresh (CBR) cycles are provided. The application must
+ set the Mode to 4 in the Mode Register and perform a write access to any
+ SDRAM location eight times.*/
+ for (i = 0; i < 8; i++) {
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_AUTO_REFRESH;
+#ifdef __rtems__
+ (void) SDRAMC->SDRAMC_MR;
+ __DMB();
+#endif /* __rtems__ */
+ *pSdram = 0;
+ }
+
+ for (i = 0; i < 100000; i++);
+
+ /*8. A Mode Register set (MRS) cycle is issued to program the parameters of
+ the SDRAM devices, in particular CAS latency and burst length. The
+ application must set Mode to 3 in the Mode Register and perform a write
+ access to the SDRAM. The write address must be chosen so that BA[1:0]
+ are set to 0. For example, with a 16-bit 128 MB SDRAM (12 rows, 9 columns,
+ 4 banks) bank address, the SDRAM write access should be done at the address
+ 0x70000000.*/
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_LOAD_MODEREG;
+#ifdef __rtems__
+ (void) SDRAMC->SDRAMC_MR;
+ __DMB();
+#endif /* __rtems__ */
+ *pSdram = 0;
+
+ for (i = 0; i < 100000; i++);
+
+ /*9. For mobile SDRAM initialization, an Extended Mode Register set (EMRS)
+ cycle is issued to program the SDRAM parameters (TCSR, PASR, DS). The
+ application must set Mode to 5 in the Mode Register and perform a write
+ access to the SDRAM. The write address must be chosen so that BA[1] or BA[0]
+ are set to 1.
+ For example, with a 16-bit 128 MB SDRAM, (12 rows, 9 columns, 4 banks) bank
+ address the SDRAM write access should be done at the address 0x70800000 or
+ 0x70400000. */
+ //SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_EXT_LOAD_MODEREG;
+ // *((uint8_t *)(pSdram + SDRAM_BA0)) = 0;
+
+ /* 10. The application must go into Normal Mode, setting Mode to 0 in the
+ Mode Register and performing a write access at any location in the SDRAM. */
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_NORMAL;
+#ifdef __rtems__
+ (void) SDRAMC->SDRAMC_MR;
+ __DMB();
+#endif /* __rtems__ */
+ *pSdram = 0;
+
+ for (i = 0; i < 100000; i++);
+
+ /* 11. Write the refresh rate into the count field in the SDRAMC Refresh
+ Timer register. (Refresh rate = delay between refresh cycles).
+ The SDRAM device requires a refresh every 15.625 ¦Ìs or 7.81 ¦Ìs.
+ With a 100 MHz frequency, the Refresh Timer Counter Register must be set
+ with the value 1562(15.625 ¦Ìs x 100 MHz) or 781(7.81 ¦Ìs x 100 MHz). */
+ // For IS42S16100E, 2048 refresh cycle every 32ms, every 15.625 ¦Ìs
+ /* ((32 x 10(^-3))/2048) x150 x (10^6) */
+#ifndef __rtems__
+ SDRAMC->SDRAMC_TR = 1562;
+ SDRAMC->SDRAMC_CFR1 |= SDRAMC_CFR1_UNAL;
+#else /* __rtems__ */
+ SDRAMC->SDRAMC_TR = BOARD_Sdram_Config.sdramc_tr;
+ SDRAMC->SDRAMC_CFR1 = BOARD_Sdram_Config.sdramc_cfr1;
+#endif /* __rtems__ */
+ /* After initialization, the SDRAM devices are fully functional. */
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libboard/source/dbg_console.c b/bsps/arm/atsam/contrib/libraries/libboard/source/dbg_console.c
new file mode 100644
index 0000000000..852cd4f90d
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libboard/source/dbg_console.c
@@ -0,0 +1,564 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Implements UART console.
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#ifndef __rtems__
+#include "board.h"
+#else /* __rtems__ */
+#include <chip.h>
+#include <include/dbg_console.h>
+#endif /* __rtems__ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+/*----------------------------------------------------------------------------
+ * Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Console baud rate always using 115200. */
+
+
+#ifndef __rtems__
+#define CONSOLE_BAUDRATE 115200
+
+/** EDBG used USART1 as the console, but LON support on USART1 only */
+#ifndef USART_LON
+ #define CONSOLE_EDBG
+#endif
+
+#if defined CONSOLE_EDBG
+ #define CONSOLE_ON_USART
+#else
+ #define CONSOLE_ON_UART
+#endif
+
+#if defined CONSOLE_ON_UART
+ #if defined SSC_AUDIO || defined USART_LON
+ /** Usart Hw interface used by the console (UART4). */
+ #define CONSOLE_UART UART4
+
+ /** Pins description corresponding to Rxd,Txd, (UART pins) */
+ #define CONSOLE_PINS {PINS_UART4}
+
+ #define CONSOLE_ID ID_UART4
+ #else
+ /** Usart Hw interface used by the console (UART0). */
+ #define CONSOLE_UART UART0
+
+ /** Pins description corresponding to Rxd,Txd, (UART pins) */
+ #define CONSOLE_PINS {PINS_UART0}
+
+ #define CONSOLE_ID ID_UART0
+
+ #endif
+#endif
+
+#if defined CONSOLE_ON_USART
+
+/** USART1 pin RX */
+#define PIN_USART1_RXD_DBG \
+ {PIO_PA21A_RXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/** USART1 pin TX */
+#define PIN_USART1_TXD_DBG \
+ {PIO_PB4D_TXD1, PIOB, ID_PIOB, PIO_PERIPH_D, PIO_DEFAULT}
+#define PINS_USART1 PIN_USART1_TXD_DBG, PIN_USART1_RXD_DBG
+
+/** Usart Hw interface used by the console (Usart0). */
+#define CONSOLE_Usart USART1
+
+/** Pins description corresponding to Rxd,Txd, (Usart pins) */
+#define CONSOLE_PINS {PINS_USART1}
+
+#define CONSOLE_ID ID_USART1
+#endif
+#else /* __rtems__ */
+#define CONSOLE_BAUDRATE ATSAM_CONSOLE_BAUD
+#if ATSAM_CONSOLE_DEVICE_TYPE == 1
+ #define CONSOLE_ON_UART
+ #if ATSAM_CONSOLE_DEVICE_INDEX == 4
+ #define CONSOLE_UART UART4
+ #define CONSOLE_ID ID_UART4
+ #elif ATSAM_CONSOLE_DEVICE_INDEX == 3
+ #define CONSOLE_UART UART3
+ #define CONSOLE_ID ID_UART3
+ #elif ATSAM_CONSOLE_DEVICE_INDEX == 2
+ #define CONSOLE_UART UART2
+ #define CONSOLE_ID ID_UART2
+ #elif ATSAM_CONSOLE_DEVICE_INDEX == 1
+ #define CONSOLE_UART UART1
+ #define CONSOLE_ID ID_UART1
+ #else
+ #define CONSOLE_UART UART0
+ #define CONSOLE_ID ID_UART0
+ #endif
+#else
+ #define CONSOLE_ON_USART
+ #if ATSAM_CONSOLE_DEVICE_INDEX == 4
+ #define CONSOLE_Usart USART4
+ #define CONSOLE_ID ID_USART4
+ #elif ATSAM_CONSOLE_DEVICE_INDEX == 3
+ #define CONSOLE_Usart USART3
+ #define CONSOLE_ID ID_USART3
+ #elif ATSAM_CONSOLE_DEVICE_INDEX == 2
+ #define CONSOLE_Usart USART2
+ #define CONSOLE_ID ID_USART2
+ #elif ATSAM_CONSOLE_DEVICE_INDEX == 1
+ #define CONSOLE_Usart USART1
+ #define CONSOLE_ID ID_USART1
+ #else
+ #define CONSOLE_Usart USART0
+ #define CONSOLE_ID ID_USART0
+ #endif
+#endif
+#endif /* __rtems__ */
+
+
+/*----------------------------------------------------------------------------
+ * Variables
+ *----------------------------------------------------------------------------*/
+
+#ifndef __rtems__
+/** Is Console Initialized. */
+static uint8_t _ucIsConsoleInitialized = 0;
+#else /* __rtems__ */
+#define _ucIsConsoleInitialized 1
+#endif /* __rtems__ */
+
+/**
+ * \brief Configures an USART peripheral with the specified parameters.
+ *
+ * \param baudrate Baudrate at which the USART should operate (in Hz).
+ * \param masterClock Frequency of the system master clock (in Hz).
+ */
+extern void DBG_Configure(uint32_t baudrate, uint32_t masterClock)
+{
+
+#ifndef __rtems__
+ const Pin pPins[] = CONSOLE_PINS;
+#endif /* __rtems__ */
+#if defined CONSOLE_ON_UART
+ Uart *pUart = CONSOLE_UART;
+ /* Configure PIO */
+#ifndef __rtems__
+ PIO_Configure(pPins, PIO_LISTSIZE(pPins));
+#endif /* __rtems__ */
+
+ // Reset & disable receiver and transmitter, disable interrupts
+ pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RSTSTA;
+ pUart->UART_IDR = 0xFFFFFFFF;
+ PMC_EnablePeripheral(CONSOLE_ID);
+ pUart->UART_BRGR = (masterClock / baudrate) / 16;
+ // Configure mode register
+ pUart->UART_MR
+ = (UART_MR_CHMODE_NORMAL | UART_MR_PAR_NO
+ | UART_MR_BRSRCCK_PERIPH_CLK);
+ // Enable receiver and transmitter
+ pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
+#endif
+
+#if defined CONSOLE_ON_USART
+ Usart *pUsart = CONSOLE_Usart;
+ // Disable the MATRIX registers write protection
+#ifndef __rtems__
+ MATRIX->MATRIX_WPMR = MATRIX_WPMR_WPKEY_PASSWD;
+ MATRIX->CCFG_SYSIO |= CCFG_SYSIO_SYSIO4;
+
+ PIO_Configure(pPins, PIO_LISTSIZE(pPins));
+#endif /* __rtems__ */
+
+ // Reset & disable receiver and transmitter, disable interrupts
+ pUsart->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RSTSTA;
+ pUsart->US_IDR = 0xFFFFFFFF;
+ PMC_EnablePeripheral(CONSOLE_ID);
+ pUsart->US_BRGR = (masterClock / baudrate) / 16;
+
+ // Configure mode register
+ pUsart->US_MR
+ = (US_MR_USART_MODE_NORMAL | US_MR_PAR_NO | US_MR_USCLKS_MCK
+ | US_MR_CHRL_8_BIT);
+
+ // Enable receiver and transmitter
+ pUsart->US_CR = US_CR_RXEN | US_CR_TXEN;
+#endif
+#ifndef __rtems__
+ _ucIsConsoleInitialized = 1;
+
+ /* Disable buffering for printf(). */
+#if (defined (__GNUC__) && !defined (__SAMBA__))
+ setvbuf(stdout, (char *)NULL, _IONBF, 0);
+#endif
+#endif /* __rtems__ */
+}
+
+/**
+ * \brief Outputs a character on the UART line.
+ *
+ * \note This function is synchronous (i.e. uses polling).
+ * \param c Character to send.
+ */
+extern void DBG_PutChar(uint8_t c)
+{
+#if defined CONSOLE_ON_UART
+ Uart *pUart = CONSOLE_UART;
+
+ if (!_ucIsConsoleInitialized)
+ DBG_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
+
+ // Wait for the transmitter to be ready
+ while ((pUart->UART_SR & UART_SR_TXEMPTY) == 0);
+
+ // Send character
+ pUart->UART_THR = c;
+
+ // Wait for the transfer to complete
+ while ((pUart->UART_SR & UART_SR_TXEMPTY) == 0);
+
+#endif
+
+#if defined CONSOLE_ON_USART
+ Usart *pUsart = CONSOLE_Usart;
+
+ if (!_ucIsConsoleInitialized)
+ DBG_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
+
+ // Wait for the transmitter to be ready
+ while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0);
+
+ // Send character
+ pUsart->US_THR = c;
+
+ // Wait for the transfer to complete
+ while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0);
+
+#endif
+}
+
+/**
+ * \brief Input a character from the UART line.
+ *
+ * \note This function is synchronous
+ * \return character received.
+ */
+extern uint32_t DBG_GetChar(void)
+{
+#if defined CONSOLE_ON_UART
+ Uart *pUart = CONSOLE_UART;
+
+ if (!_ucIsConsoleInitialized)
+ DBG_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
+
+ while ((pUart->UART_SR & UART_SR_RXRDY) == 0);
+
+ return pUart->UART_RHR;
+#endif
+
+#if defined CONSOLE_ON_USART
+ Usart *pUsart = CONSOLE_Usart;
+
+ if (!_ucIsConsoleInitialized)
+ DBG_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
+
+ while ((pUsart->US_CSR & US_CSR_RXRDY) == 0);
+
+ return pUsart->US_RHR;
+#endif
+}
+
+/**
+ * \brief Check if there is Input from UART line.
+ *
+ * \return true if there is Input.
+ */
+extern uint32_t DBG_IsRxReady(void)
+{
+#if defined CONSOLE_ON_UART
+ Uart *pUart = CONSOLE_UART;
+
+ if (!_ucIsConsoleInitialized)
+ DBG_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
+
+ return (pUart->UART_SR & UART_SR_RXRDY);
+#endif
+
+#if defined CONSOLE_ON_USART
+ Usart *pUsart = CONSOLE_Usart;
+
+ if (!_ucIsConsoleInitialized)
+ DBG_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
+
+ return (pUsart->US_CSR & US_CSR_RXRDY);
+#endif
+}
+
+#ifndef __rtems__
+/**
+ * Displays the content of the given frame on the UART0.
+ *
+ * \param pucFrame Pointer to the frame to dump.
+ * \param dwSize Buffer size in bytes.
+ */
+extern void DBG_DumpFrame(uint8_t *pucFrame, uint32_t dwSize)
+{
+ uint32_t dw;
+
+ for (dw = 0; dw < dwSize; dw++)
+ printf("%02X ", pucFrame[dw]);
+
+ printf("\n\r");
+}
+
+/**
+ * Displays the content of the given buffer on the UART0.
+ *
+ * \param pucBuffer Pointer to the buffer to dump.
+ * \param dwSize Buffer size in bytes.
+ * \param dwAddress Start address to display
+ */
+extern void DBG_DumpMemory(uint8_t *pucBuffer, uint32_t dwSize,
+ uint32_t dwAddress)
+{
+ uint32_t i;
+ uint32_t j;
+ uint32_t dwLastLineStart;
+ uint8_t *pucTmp;
+
+ for (i = 0; i < (dwSize / 16); i++) {
+ printf("0x%08X: ", (unsigned int)(dwAddress + (i * 16)));
+ pucTmp = (uint8_t *)&pucBuffer[i * 16];
+
+ for (j = 0; j < 4; j++) {
+ printf("%02X%02X%02X%02X ",
+ pucTmp[0], pucTmp[1], pucTmp[2], pucTmp[3]);
+ pucTmp += 4;
+ }
+
+ pucTmp = (uint8_t *)&pucBuffer[i * 16];
+
+ for (j = 0; j < 16; j++)
+ DBG_PutChar(*pucTmp++);
+
+ printf("\n\r");
+ }
+
+ if ((dwSize % 16) != 0) {
+ dwLastLineStart = dwSize - (dwSize % 16);
+
+ printf("0x%08X: ", (unsigned int)(dwAddress + dwLastLineStart));
+
+ for (j = dwLastLineStart; j < dwLastLineStart + 16; j++) {
+ if ((j != dwLastLineStart) && (j % 4 == 0))
+ printf(" ");
+
+ if (j < dwSize)
+ printf("%02X", pucBuffer[j]);
+ else
+ printf(" ");
+ }
+
+ printf(" ");
+
+ for (j = dwLastLineStart; j < dwSize; j++)
+ DBG_PutChar(pucBuffer[j]);
+
+ printf("\n\r");
+ }
+}
+
+/**
+ * Reads an integer
+ *
+ * \param pdwValue Pointer to a integer variable to contain the input value.
+ *
+ * \return success(1) or failure(0)
+ */
+extern uint32_t DBG_GetInteger(int32_t *pdwValue)
+{
+ uint8_t ucKey;
+ uint8_t ucNum = 0;
+ int32_t dwValue = 0;
+ int32_t sign = 1;
+
+ while (1) {
+ ucKey = DBG_GetChar();
+ DBG_PutChar(ucKey);
+
+ if (((ucKey == '-') || (ucKey == '+')) && (ucNum == 0)) {
+ if (ucKey == '-')
+ sign = -1;
+ else
+ sign = 1;
+
+ ucNum++;
+ } else {
+ if (ucKey >= '0' && ucKey <= '9') {
+ dwValue = (dwValue * 10) + (ucKey - '0');
+ ucNum++;
+ } else {
+ if (ucKey == 0x0D || ucKey == ' ') {
+ if (ucNum == 0) {
+ printf("\n\rWrite a number and press ENTER or SPACE!\n\r");
+ return 0;
+ } else {
+ printf("\n\r");
+ *pdwValue = dwValue * sign;
+
+ return 1;
+ }
+ } else {
+ printf("\n\r'%c' not a number or sign(+/-)!\n\r", ucKey);
+ return 0;
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Reads an integer and check the value
+ *
+ * \param pdwValue Pointer to a integer variable to contain the input value.
+ * \param dwMin Minimum value
+ * \param dwMax Maximum value
+ *
+ * \return success(1) or failure(0)
+ */
+extern uint32_t DBG_GetIntegerMinMax(int32_t *pdwValue, int32_t dwMin,
+ int32_t dwMax)
+{
+ int32_t dwValue = 0;
+
+ if (DBG_GetInteger(&dwValue) == 0)
+ return 0;
+
+ if (dwValue < dwMin || dwValue > dwMax) {
+ printf("\n\rThe number have to be between %d and %d\n\r",
+ (int)dwMin, (int)dwMax);
+
+ return 0;
+ }
+
+ printf("\n\r");
+
+ *pdwValue = dwValue;
+
+ return 1;
+}
+
+/**
+ * Reads an hexadecimal number
+ *
+ * \param pdwValue Pointer to the uint32_t variable to contain the input value.
+ */
+extern uint32_t DBG_GetHexa32(uint32_t *pdwValue)
+{
+ uint8_t ucKey;
+ uint32_t dw = 0;
+ uint32_t dwValue = 0;
+
+ for (dw = 0; dw < 8; dw++) {
+ ucKey = DBG_GetChar();
+ DBG_PutChar(ucKey);
+
+ if (ucKey >= '0' && ucKey <= '9')
+ dwValue = (dwValue * 16) + (ucKey - '0');
+ else {
+ if (ucKey >= 'A' && ucKey <= 'F')
+ dwValue = (dwValue * 16) + (ucKey - 'A' + 10);
+ else {
+ if (ucKey >= 'a' && ucKey <= 'f')
+ dwValue = (dwValue * 16) + (ucKey - 'a' + 10);
+ else {
+ printf("\n\rIt is not a hexadecimal character!\n\r");
+
+ return 0;
+ }
+ }
+ }
+ }
+
+ printf("\n\r");
+ *pdwValue = dwValue;
+
+ return 1;
+}
+
+#if defined __ICCARM__ /* IAR Ewarm 5.41+ */
+/**
+ * \brief Outputs a character on the UART.
+ *
+ * \param c Character to output.
+ *
+ * \return The character that was output.
+ */
+extern WEAK signed int putchar(signed int c)
+{
+ DBG_PutChar(c);
+
+ return c;
+}
+
+#endif // defined __ICCARM__
+extern WEAK int puts(const char *ptr)
+{
+
+ for (; *ptr != 0; ptr++)
+ DBG_PutChar(*ptr);
+
+ return 0;
+
+}
+
+extern WEAK char *gets(char *ptr)
+{
+ uint8_t ch = 0;
+
+ while (ch != '\r') {
+ ch = DBG_GetChar();
+ DBG_PutChar(ch);
+ *(ptr++) = ch;
+ }
+
+ *ptr = '\0';
+ return 0;
+
+}
+
+
+#endif /* __rtems__ */
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/acc.c b/bsps/arm/atsam/contrib/libraries/libchip/source/acc.c
new file mode 100644
index 0000000000..694142bda3
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/acc.c
@@ -0,0 +1,159 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup acc_module Working with ACC
+ * \ingroup peripherals_module
+ * The ACC driver provides the interface to configure and use the ACC
+ * peripheral.\n
+ *
+ * It applies comparison on two inputs and gives a compare output.
+ *
+ * To Enable a ACC Comparison,the user has to follow these few steps:
+ * <ul>
+ * <li> Enable ACC peripheral clock by setting the corresponding bit in
+ * PMC_PCER1 (PMC Peripheral Clock Enable Register 1)
+ * </li>
+ * <li> Reset the controller by asserting ACC_CR_SWRST in ACC_CR(ACC Control
+ * Register) </li>
+ * <li> Configure the mode as following steps: </li>
+ * -# Select inputs for SELMINUS and SELPLUS in ACC_MR (ACC Mode Register).
+ * -# Enable Analog Comparator by setting ACEN in ACC_MR.
+ * -# Configure Edge Type to detect different compare output.
+ * </li>
+ * <li> Wait until the automatic mask period expires by polling MASK bit in
+ * ACC_ISR.
+ * </ul>
+ *
+ * For more accurate information, please look at the ACC section of the
+ * Datasheet.
+ *
+ * Related files :\n
+ * \ref acc.c\n
+ * \ref acc.h\n
+ */
+/*@{*/
+/*@}*/
+/**
+ * \file
+ *
+ * Implementation of Analog Comparator Controller (ACC).
+ *
+ */
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+#include "acc.h"
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Initialize the ACC controller
+ *
+ * \param pAcc Pointer to an Acc instance.
+ * \param idAcc ACC identifier
+ * \param ucSelplus input connected to inp, 0~7
+ * \param ucSelminus input connected to inm,0~7
+ * \param wAc_en Analog comparator enabled/disabled
+ * \param wEdge CF flag triggering mode
+ * \param wInvert INVert comparator output,use pattern defined in the device
+ * header file
+ */
+extern void ACC_Configure(Acc *pAcc, uint8_t idAcc, uint8_t ucSelplus,
+ uint8_t ucSelminus, uint16_t wAc_en, uint16_t wEdge, uint16_t wInvert)
+{
+ /* Enable peripheral clock*/
+ PMC->PMC_PCER1 = 1 << (idAcc - 32);
+
+ /* Reset the controller */
+ pAcc->ACC_CR |= ACC_CR_SWRST;
+
+ /* Write to the MR register */
+ ACC_CfgModeReg(pAcc,
+ ((ucSelplus << ACC_MR_SELPLUS_Pos) & ACC_MR_SELPLUS_Msk) |
+ ((ucSelminus << ACC_MR_SELMINUS_Pos) & ACC_MR_SELMINUS_Msk) |
+ ((wAc_en << 8) & ACC_MR_ACEN) |
+ ((wEdge << ACC_MR_EDGETYP_Pos) & ACC_MR_EDGETYP_Msk) |
+ ((wInvert << 12) & ACC_MR_INV));
+ /* set hysteresis and current option*/
+ pAcc->ACC_ACR = (ACC_ACR_ISEL_HISP
+ | ((0x01 << ACC_ACR_HYST_Pos) & ACC_ACR_HYST_Msk));
+
+ /* Automatic Output Masking Period*/
+ while (pAcc->ACC_ISR & (uint32_t)ACC_ISR_MASK);
+}
+
+/**
+ * Return the Channel Converted Data
+ * \param pAcc Pointer to an Acc instance.
+ * \param ucSelplus input applied on ACC SELPLUS
+ * \param ucSelminus input applied on ACC SELMINUS
+ */
+extern void ACC_SetComparisonPair(Acc *pAcc, uint8_t ucSelplus,
+ uint8_t ucSelminus)
+{
+ uint32_t dwTemp;
+
+ assert(ucSelplus < 8 && ucSelminus < 8);
+
+ dwTemp = pAcc->ACC_MR;
+ pAcc->ACC_MR =
+ dwTemp & (uint32_t) ((~ACC_MR_SELMINUS_Msk) & (~ACC_MR_SELPLUS_Msk));
+
+ pAcc->ACC_MR |= (((ucSelplus << ACC_MR_SELPLUS_Pos) & ACC_MR_SELPLUS_Msk) |
+ ((ucSelminus << ACC_MR_SELMINUS_Pos) & ACC_MR_SELMINUS_Msk));
+}
+
+/**
+ * Return Comparison Result
+ * \param pAcc Pointer to an Acc instance.
+ * \param dwStatus value of ACC_ISR
+ */
+extern uint32_t ACC_GetComparisonResult(Acc *pAcc, uint32_t dwStatus)
+{
+ uint32_t dwTemp = pAcc->ACC_MR;
+
+ if ((dwTemp & ACC_MR_INV) == ACC_MR_INV) {
+ if (dwStatus & ACC_ISR_SCO) {
+ return 0; /* inn>inp*/
+ } else {
+ return 1;/* inp>inn*/
+ }
+ } else {
+ if (dwStatus & ACC_ISR_SCO) {
+ return 1; /* inp>inn*/
+ } else {
+ return 0;/* inn>inp*/
+ }
+ }
+}
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/aes.c b/bsps/arm/atsam/contrib/libraries/libchip/source/aes.c
new file mode 100644
index 0000000000..0cba25d9d1
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/aes.c
@@ -0,0 +1,286 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup aes_module Working with AES
+ * \ingroup peripherals_module
+ * The AES driver provides the interface to configure and use the AES peripheral.
+ * \n
+ *
+ * The Advanced Encryption Standard (AES) specifies a FIPS-approved
+ * cryptographic algorithm that can be used to protect electronic data. The AES
+ * algorithm is a symmetric block cipher that can encrypt (encipher) and decrypt
+ * (decipher) information.
+ * Encryption converts data to an unintelligible form called ciphertext.
+ * Decrypting the ciphertext converts the data back into its original form,
+ * called plaintext. The CIPHER bit in the AES Mode Register (AES_MR) allows
+ * selection between the encryption and the decryption processes. The AES is
+ * capable of using cryptographic keys of 128/192/256 bits to encrypt and
+ * decrypt data in blocks of 128 bits.
+ * This 128-bit/192-bit/256-bit key is defined in the Key Registers (AES_KEYWRx)
+ * and set by AES_WriteKey(). The input to the encryption processes of the CBC,
+ * CFB, and OFB modes includes, in addition to the plaintext, a 128-bit data
+ * block called the initialization vector (IV),
+ * which must be set with AES_SetVector().
+ * The initialization vector is used in an initial step in the encryption of a
+ * message and in the corresponding decryption of the message.
+ * The Initialization Vector Registers are also used by the CTR mode to set the
+ * counter value.
+ *
+ * To Enable a AES encryption and decryption,the user has to follow these few
+ * steps:
+ * <ul>
+ * <li> A software triggered hardware reset of the AES interface is performed
+ * by AES_SoftReset().</li>
+ * <li> Configure AES algorithm mode, key mode, start mode and operation mode by
+ * AES_Configure(). </li>
+ * <li> Input AES data for encryption and decryption with function
+ * AES_SetInput() </li>
+ * <li> Set AES key with function AES_WriteKey(). </li>
+ * <li> To start the encryption or the decryption process with AES_Start()</li>
+ * <li> To get the encryption or decryption result by AES_GetOutput() </li>
+ * </ul>
+ *
+ *
+ * For more accurate information, please look at the AES section of the
+ * Datasheet.
+ *
+ * Related files :\n
+ * \ref aes.c\n
+ * \ref aes.h\n
+ */
+/*@{*/
+/*@}*/
+
+
+/**
+ * \file
+ *
+ * Implementation of Advanced Encryption Standard (AES)
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+#include "aes.h"
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Starts Manual encryption/decryption process.
+ */
+void AES_Start(void)
+{
+ AES->AES_CR = AES_CR_START;
+}
+
+/**
+ * \brief Resets the AES. A software triggered hardware reset of the AES
+ * interface is performed.
+ */
+void AES_SoftReset(void)
+{
+ AES->AES_CR = AES_CR_SWRST;
+}
+
+/**
+ * \brief Configures an AES peripheral with the specified parameters.
+ * \param mode Desired value for the AES mode register (see the datasheet).
+ */
+void AES_Configure(uint32_t mode)
+{
+ AES->AES_MR = mode;
+}
+
+/**
+ * \brief Enables the selected interrupts sources on a AES peripheral.
+ * \param sources Bitwise OR of selected interrupt sources.
+ */
+void AES_EnableIt(uint32_t sources)
+{
+ AES->AES_IER = sources;
+}
+
+/**
+ * \brief Disables the selected interrupts sources on a AES peripheral.
+ * \param sources Bitwise OR of selected interrupt sources.
+ */
+void AES_DisableIt(uint32_t sources)
+{
+ AES->AES_IDR = sources;
+}
+
+/**
+ * \brief Get the current status register of the given AES peripheral.
+ * \return AES status register.
+ */
+uint32_t AES_GetStatus(void)
+{
+ return AES->AES_ISR;
+}
+
+/**
+ * \brief Set the 128-bit/192-bit/256-bit cryptographic key used for
+ * encryption/decryption.
+ * \param pKey Pointer to a 16/24/32 bytes cipher key.
+ * \param keyLength length of key
+ */
+void AES_WriteKey(const uint32_t *pKey, uint32_t keyLength)
+{
+ AES->AES_KEYWR[0] = pKey[0];
+ AES->AES_KEYWR[1] = pKey[1];
+ AES->AES_KEYWR[2] = pKey[2];
+ AES->AES_KEYWR[3] = pKey[3];
+
+ if (keyLength >= 24) {
+ AES->AES_KEYWR[4] = pKey[4];
+ AES->AES_KEYWR[5] = pKey[5];
+ }
+
+ if (keyLength == 32) {
+ AES->AES_KEYWR[6] = pKey[6];
+ AES->AES_KEYWR[7] = pKey[7];
+ }
+}
+
+/**
+ * \brief Set the for 32-bit input Data allow to set the 128-bit data block
+ * used for encryption/decryption.
+ * \param data Pointer to the 16-bytes data to cipher/decipher.
+ */
+void AES_SetInput(uint32_t *data)
+{
+ uint8_t i;
+
+ for (i = 0; i < 4; i++)
+ AES->AES_IDATAR[i] = data[i];
+}
+
+/**
+ * \brief Get the four 32-bit data contain the 128-bit data block which
+ * has been encrypted/decrypted.
+ * \param data pointer to the word that has been encrypted/decrypted..
+ */
+void AES_GetOutput(uint32_t *data)
+{
+ uint8_t i;
+
+ for (i = 0; i < 4; i++)
+ data[i] = AES->AES_ODATAR[i];
+}
+
+/**
+ * \brief Set four 64-bit initialization vector data block, which is used by
+ * some modes of operation as an additional initial input.
+ * \param pVector point to the word of the initialization vector.
+ */
+void AES_SetVector(const uint32_t *pVector)
+{
+ AES->AES_IVR[0] = pVector[0];
+ AES->AES_IVR[1] = pVector[1];
+ AES->AES_IVR[2] = pVector[2];
+ AES->AES_IVR[3] = pVector[3];
+}
+
+/**
+ * \brief Set Length in bytes of the AAD data that is to be processed.
+ * \param len Length.
+ */
+void AES_SetAadLen(uint32_t len)
+{
+ AES->AES_AADLENR = len;
+}
+
+/**
+ * \brief Set Length in bytes of the Length in bytes of the
+ * plaintext/ciphertext (C) data that is to be processed..
+ * \param len Length.
+ */
+void AES_SetDataLen(uint32_t len)
+{
+ AES->AES_CLENR = len;
+}
+
+/**
+ * \brief Set The four 32-bit Hash Word registers expose the intermediate GHASH
+ * value. May be read to save the current GHASH value so processing can later be
+ * resumed, presumably on a later message fragment. modes of operation as an
+ * additional initial input.
+ * \param hash point to the word of the hash.
+ */
+void AES_SetGcmHash(uint32_t *hash)
+{
+ uint8_t i;
+
+ for (i = 0; i < 4; i++)
+ AES->AES_GHASHR[i] = hash[i];
+}
+
+
+/**
+ * \brief Get The four 32-bit Tag which contain the final 128-bit GCM
+ * Authentication tag ¡°T¡± when GCM processing is complete.
+ * \param tag point to the word of the tag.
+ */
+void AES_GetGcmTag(uint32_t *tag)
+{
+ uint8_t i;
+
+ for (i = 0; i < 4; i++)
+ tag[i] = AES->AES_TAGR[i];
+}
+
+/**
+ * \brief Reports the current value of the 32-bit GCM counter
+ * \param counter Point to value of GCM counter.
+ */
+void AES_GetGcmCounter(uint32_t *counter)
+{
+ *counter = AES->AES_CTRR;
+}
+
+
+/**
+ * \brief Get the four 32-bit data contain the 128-bit H value computed from
+ * the KEYW value
+ * \param data point to the word that has been encrypted/decrypted.
+ */
+void AES_GetGcmH(uint32_t *h)
+{
+ uint8_t i;
+
+ for (i = 0; i < 4; i++)
+ h[i] = AES->AES_GCMHR[i];
+}
+
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/afe_dma.c b/bsps/arm/atsam/contrib/libraries/libchip/source/afe_dma.c
new file mode 100644
index 0000000000..9dc3d3db79
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/afe_dma.c
@@ -0,0 +1,256 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup afe_dma_module Working with AFE (DMA support)
+ * \ingroup peripherals_module
+ * The afec driver provides the interface to configure and use the afecC
+ * peripheral with DMA support.\n
+ *
+ * For more accurate information, please look at the AFEC section of the
+ * Datasheet.
+ *
+ * Related files :\n
+ * \ref afe_dma.c\n
+ * \ref afe_dma.h\n
+ */
+/*@{*/
+/*@}*/
+/**
+ * \file
+ *
+ *
+ */
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+#include "afe_dma.h"
+#include "xdmad.h"
+
+#include <stdint.h>
+#include <assert.h>
+
+/* DMA driver instance */
+static uint32_t afeDmaRxChannel;
+
+/*----------------------------------------------------------------------------
+ * Local functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief AFE xDMA Rx callback
+ * Invoked on AFE DMA reception done.
+ * \param channel DMA channel.
+ * \param pArg Pointer to callback argument - Pointer to AfeDma instance.
+ */
+static void Afe_Rx_Cb(uint32_t channel, AfeDma *pArg)
+{
+ AfeCmd *pAfedCmd = pArg->pCurrentCommand;
+
+ if (channel != afeDmaRxChannel)
+ return;
+
+ /* Configure and enable interrupt on RC compare */
+ NVIC_ClearPendingIRQ(XDMAC_IRQn);
+ NVIC_DisableIRQ(XDMAC_IRQn);
+
+ /* Release the DMA channels */
+ XDMAD_FreeChannel(pArg->pXdmad, afeDmaRxChannel);
+ SCB_InvalidateDCache_by_Addr(pAfedCmd->pRxBuff, pAfedCmd->RxSize);
+ /* Release the dataflash semaphore */
+ pArg->semaphore++;
+
+ /* Invoke the callback associated with the current command */
+ if (pAfedCmd && pAfedCmd->callback)
+ pAfedCmd->callback(0, pAfedCmd->pArgument);
+}
+
+/**
+ * \brief Configure the DMA Channels: 0 RX.
+ * Channels are disabled after configure.
+ * \param pXdmad Pointer to a AfeDma instance
+ * \returns 0 if the dma channel configuration successfully; otherwise returns
+ * AFE_ERROR_XXX.
+ */
+static uint8_t _AfeConfigureDmaChannels(AfeDma *pAfed)
+{
+
+ /* Driver initialize */
+ XDMAD_FreeChannel(pAfed->pXdmad, afeDmaRxChannel);
+
+ /* Allocate a DMA channel for AFE0/1 RX. */
+ afeDmaRxChannel =
+ XDMAD_AllocateChannel(pAfed->pXdmad, pAfed->afeId, XDMAD_TRANSFER_MEMORY);
+
+ if (afeDmaRxChannel == XDMAD_ALLOC_FAILED)
+ return AFE_ERROR;
+
+ /* Setup callbacks for AFE0/1 RX */
+ XDMAD_SetCallback(pAfed->pXdmad, afeDmaRxChannel,
+ (XdmadTransferCallback)Afe_Rx_Cb, pAfed);
+
+ if (XDMAD_PrepareChannel(pAfed->pXdmad, afeDmaRxChannel))
+ return AFE_ERROR;
+
+ return AFE_OK;
+}
+
+/**
+ * \brief Configure the DMA source and destination with Linker List mode.
+ * \param pXdmad Pointer to a AfeDma instance
+ * \param pCommand Pointer to AfeCmd instance
+ * \param AfeCmd Pointer to command
+ */
+
+static uint8_t _Afe_configureLinkList(Afec *pAfeHw, void *pXdmad,
+ AfeCmd *pCommand)
+{
+ uint32_t xdmaCndc, xdmaInt;
+ sXdmadCfg xdmadRxCfg;
+ uint32_t afeId;
+
+ if ((unsigned int)pAfeHw == (unsigned int)AFEC0) afeId = ID_AFEC0;
+
+ if ((unsigned int)pAfeHw == (unsigned int)AFEC1) afeId = ID_AFEC1;
+
+ /* Setup RX Link List */
+ xdmadRxCfg.mbr_ubc = XDMA_UBC_NVIEW_NDV0 |
+ XDMA_UBC_NDE_FETCH_DIS |
+ XDMA_UBC_NDEN_UPDATED |
+ pCommand->RxSize;
+
+ xdmadRxCfg.mbr_da = (uint32_t)pCommand->pRxBuff;
+ xdmadRxCfg.mbr_sa = (uint32_t) & (pAfeHw->AFEC_LCDR);
+ xdmadRxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_PER2MEM |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_WORD |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_FIXED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_PERID(
+ XDMAIF_Get_ChannelNumber(afeId, XDMAD_TRANSFER_RX));
+
+ xdmadRxCfg.mbr_bc = 0;
+ xdmadRxCfg.mbr_sus = 0;
+ xdmadRxCfg.mbr_dus = 0;
+
+ xdmaInt = (XDMAC_CIE_BIE |
+ XDMAC_CIE_DIE |
+ XDMAC_CIE_FIE |
+ XDMAC_CIE_RBIE |
+ XDMAC_CIE_WBIE |
+ XDMAC_CIE_ROIE);
+ xdmaCndc = 0;
+
+ if (XDMAD_ConfigureTransfer(pXdmad, afeDmaRxChannel,
+ &xdmadRxCfg, xdmaCndc, 0, xdmaInt))
+ return AFE_ERROR;
+
+ return AFE_OK;
+}
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+
+/**
+ * \brief Initializes the AfeDma structure and the corresponding AFE & DMA .
+ * hardware select value.
+ * The driver will uses DMA channel 0 for RX .
+ * The DMA channels are freed automatically when no DMA command processing.
+ *
+ * \param pAfed Pointer to a AfeDma instance.
+ * \param pAfeHw Associated Afe peripheral.
+ * \param AfeId Afe peripheral identifier.
+ * \param pDmad Pointer to a Dmad instance.
+ */
+uint32_t Afe_ConfigureDma(AfeDma *pAfed ,
+ Afec *pAfeHw ,
+ uint8_t AfeId,
+ sXdmad *pXdmad)
+{
+ /* Initialize the Afe structure */
+ pAfed->pAfeHw = pAfeHw;
+ pAfed->afeId = AfeId;
+ pAfed->semaphore = 1;
+ pAfed->pCurrentCommand = 0;
+ assert(pXdmad == &XDMAD_Instance);
+ pAfed->pXdmad = pXdmad;
+ return 0;
+}
+
+/**
+ * \brief Starts a AFE transfer. This is a non blocking function. It will
+ * return as soon as the transfer is started.
+ *
+ * \param pAfed Pointer to a AfeDma instance.
+ * \param pCommand Pointer to the Afe command to execute.
+ * \returns 0 if the transfer has been started successfully; otherwise returns
+ * AFE_ERROR_LOCK is the driver is in use, or AFE_ERROR if the command is not
+ * valid.
+ */
+uint32_t Afe_SendData(AfeDma *pAfed, AfeCmd *pCommand)
+{
+ Afec *pAfeHw = pAfed->pAfeHw;
+
+ /* Try to get the dataflash semaphore */
+ if (pAfed->semaphore == 0)
+
+ return AFE_ERROR_LOCK;
+
+ pAfed->semaphore--;
+
+ // Initialize the callback
+ pAfed->pCurrentCommand = pCommand;
+
+ /* Initialize DMA controller using channel 0 for RX. */
+ if (_AfeConfigureDmaChannels(pAfed))
+ return AFE_ERROR_LOCK;
+
+ /* Configure and enable interrupt on RC compare */
+ NVIC_ClearPendingIRQ(XDMAC_IRQn);
+ NVIC_SetPriority(XDMAC_IRQn , 1);
+ NVIC_EnableIRQ(XDMAC_IRQn);
+
+ if (_Afe_configureLinkList(pAfeHw, pAfed->pXdmad, pCommand))
+ return AFE_ERROR_LOCK;
+
+ AFEC_StartConversion(pAfeHw);
+
+ /* Start DMA 0(RX) */
+ if (XDMAD_StartTransfer(pAfed->pXdmad, afeDmaRxChannel))
+ return AFE_ERROR_LOCK;
+
+ return AFE_OK;;
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/afec.c b/bsps/arm/atsam/contrib/libraries/libchip/source/afec.c
new file mode 100644
index 0000000000..d81d739a9f
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/afec.c
@@ -0,0 +1,458 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup AFEC_module Working with AFE
+ * \ingroup peripherals_module
+ * The AFE driver provides the interface to configure and use the AFE peripheral.
+ * \n
+ *
+ * It converts the analog input to digital format. The converted result could be
+ * 12bit or 10bit. The AFE supports up to 16 analog lines.
+ *
+ * To Enable a AFE conversion,the user has to follow these few steps:
+ * <ul>
+ * <li> Select an appropriate reference voltage on ADVREF </li>
+ * <li> Configure the AFE according to its requirements and special needs,which
+ * could be broken down into several parts:
+ * -# Select the resolution by setting or clearing AFEC_MR_LOWRES bit in
+ * AFEC_MR (Mode Register)
+ * -# Set AFE clock by setting AFEC_MR_PRESCAL bits in AFEC_MR, the clock is
+ * calculated with AFEClock = MCK / ((PRESCAL+1) * 2)
+ * -# Set Startup Time,Tracking Clock cycles and Transfer Clock respectively
+ * in AFEC_MR.
+ </li>
+ * <li> Start conversion by setting AFEC_CR_START in AFEC_CR. </li>
+ * </ul>
+ *
+ * For more accurate information, please look at the AFE section of the
+ * Datasheet.
+ *
+ * Related files :\n
+ * \ref afec.c\n
+ * \ref afec.h\n
+ * \ref afe_dma.c\n
+ * \ref afe_dma.h\n
+ */
+/*@{*/
+/*@}*/
+/**
+ * \file
+ *
+ * Implementation of Analog-to-Digital Converter (AFE).
+ *
+ */
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ *----------------------------------------------------------------------------*/
+
+/** Current working clock */
+static uint32_t dwAFEClock = 0;
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Initialize the AFE controller
+ *
+ * \param pAFE Pointer to an AFE instance.
+ * \param dwID AFE Index
+ */
+extern void AFEC_Initialize(Afec *pAFE, uint32_t dwID)
+{
+ /* Enable peripheral clock*/
+ PMC_EnablePeripheral(dwID);
+
+ /* Reset the controller */
+ pAFE->AFEC_CR = AFEC_CR_SWRST;
+
+ /* Reset Mode Register */
+ pAFE->AFEC_MR = 0;
+}
+
+/**
+ * \brief Set AFE clock.
+ *
+ * \param pAFE Pointer to an AFE instance.
+ * \param dwPres prescale value
+ * \param dwMck Board MCK (Hz)
+ *
+ * \return AFE clock
+ */
+
+extern uint32_t AFEC_SetClock(Afec *pAFE, uint32_t dwClk, uint32_t dwMck)
+{
+ uint32_t dwPres, dwMr;
+ /* Formula for PRESCAL is:
+ PRESCAL = peripheral clock/ fAFE Clock - 1 */
+
+ dwPres = (dwMck) / (dwClk) - 1;
+ dwMr = AFEC_MR_PRESCAL(dwPres);
+
+ if (dwMr == 0) return 0;
+
+ dwMr |= (pAFE->AFEC_MR & ~AFEC_MR_PRESCAL_Msk);
+ pAFE->AFEC_MR = dwMr;
+ dwAFEClock = dwMck / (dwPres + 1);
+ return dwAFEClock;
+}
+
+/**
+ * \brief Set AFE timing.
+ *
+ * \param pAFE Pointer to an AFE instance.
+ * \param dwStartup startup value
+ * \param dwTracking tracking value
+ * \param dwSettling settling value
+ */
+extern void AFEC_SetTiming(Afec *pAFE, uint32_t dwStartup, uint32_t dwTracking,
+ uint32_t dwSettling)
+{
+ uint32_t dwMr;
+
+ dwMr = pAFE->AFEC_MR;
+ dwMr &= (~AFEC_MR_STARTUP_Msk) & (~AFEC_MR_TRACKTIM_Msk) &
+ (~AFEC_MR_SETTLING_Msk);
+
+ /* Formula:
+ * Startup Time = startup value / AFEClock
+ * Transfer Time = (TRANSFER * 2 + 3) / AFEClock
+ * Tracking Time = (TRACKTIM + 1) / AFEClock
+ * Settling Time = settling value / AFEClock
+ */
+ dwMr |= dwStartup | dwTracking | dwSettling;
+ pAFE->AFEC_MR |= dwMr;
+}
+
+/**
+ * \brief Set AFE trigger.
+ *
+ * \param pAFE Pointer to an AFE instance.
+ * \param dwTrgSel Trigger selection
+ */
+extern void AFEC_SetTrigger(Afec *pAFE, uint32_t dwTrgSel)
+{
+ uint32_t dwMr;
+
+ dwMr = pAFE->AFEC_MR;
+ dwMr &= ~AFEC_MR_TRGSEL_Msk;
+ dwMr |= dwTrgSel;
+ pAFE->AFEC_MR |= dwMr;
+}
+
+
+/**
+ * \brief Enable/Disable sleep mode.
+ *
+ * \param pAFE Pointer to an AFE instance.
+ * \param bEnDis Enable/Disable sleep mode.
+ */
+extern void AFEC_SetSleepMode(Afec *pAFE, uint8_t bEnDis)
+{
+ if (bEnDis)
+ pAFE->AFEC_MR |= AFEC_MR_SLEEP;
+ else
+ pAFE->AFEC_MR &= ~AFEC_MR_SLEEP;
+}
+
+/**
+ * \brief Enable/Disable fast wake up.
+ *
+ * \param pAFE Pointer to an AFE instance.
+ * \param bEnDis Enable/Disable fast wake up in sleep mode.
+ */
+extern void AFEC_SetFastWakeup(Afec *pAFE, uint8_t bEnDis)
+{
+ if (bEnDis)
+ pAFE->AFEC_MR |= AFEC_MR_FWUP;
+ else
+ pAFE->AFEC_MR &= ~AFEC_MR_FWUP;
+}
+
+/**
+ * \brief Enable/Disable sequence mode.
+ *
+ * \param pAFE Pointer to an AFE instance.
+ * \param bEnDis Enable/Disable sequence mode.
+ */
+extern void AFEC_SetSequenceMode(Afec *pAFE, uint8_t bEnDis)
+{
+ if (bEnDis) {
+ /* User Sequence Mode: The sequence respects what is defined in
+ AFEC_SEQR1 and AFEC_SEQR2 */
+ pAFE->AFEC_MR |= AFEC_MR_USEQ;
+ } else {
+ /* Normal Mode: The controller converts channels in a simple
+ numeric order. */
+ pAFE->AFEC_MR &= ~AFEC_MR_USEQ;
+ }
+}
+
+/**
+ * \brief Set channel sequence.
+ *
+ * \param pAFE Pointer to an AFE instance.
+ * \param dwSEQ1 Sequence 1 ~ 8 channel number.
+ * \param dwSEQ2 Sequence 9 ~ 16 channel number.
+ */
+extern void AFEC_SetSequence(Afec *pAFE, uint32_t dwSEQ1, uint32_t dwSEQ2)
+{
+ pAFE->AFEC_SEQ1R = dwSEQ1;
+ pAFE->AFEC_SEQ2R = dwSEQ2;
+}
+
+/**
+ * \brief Set channel sequence by given channel list.
+ *
+ * \param pAFE Pointer to an AFE instance.
+ * \param ucChList Channel list.
+ * \param ucNumCh Number of channels in list.
+ */
+extern void AFEC_SetSequenceByList(Afec *pAFE, uint8_t ucChList[],
+ uint8_t ucNumCh)
+{
+ uint8_t i;
+ uint8_t ucShift;
+
+ pAFE->AFEC_SEQ1R = 0;
+
+ for (i = 0, ucShift = 0; i < 8; i ++, ucShift += 4) {
+ if (i >= ucNumCh) return;
+
+ pAFE->AFEC_SEQ1R |= ucChList[i] << ucShift;
+
+ }
+
+ pAFE->AFEC_SEQ2R = 0;
+
+ for (ucShift = 0; i < 16; i ++, ucShift += 4) {
+ if (i >= ucNumCh) return;
+
+ pAFE->AFEC_SEQ2R |= ucChList[i] << ucShift;
+ }
+}
+
+/**
+ * \brief Set analog change.
+ * IF enabled, it allows different analog settings for each channel,
+ * otherwise, DIFF0, GAIN0 and OFF0 are used for all channels.
+ *
+ * \param pAFE Pointer to an AFE instance.
+ * \param bEnDis Enable/Disable.
+ */
+extern void AFEC_SetAnalogChange(Afec *pAFE, uint8_t bEnDis)
+{
+ if (bEnDis)
+ pAFE->AFEC_MR |= AFEC_MR_ONE;
+ else
+ pAFE->AFEC_MR &= ~AFEC_MR_ONE;
+}
+
+/**
+ * \brief Set "TAG" mode, show channel number in last data or not.
+ *
+ * \param pAFE Pointer to an AFE instance.
+ * \param bEnDis Enable/Disable TAG value.
+ */
+extern void AFEC_SetTagEnable(Afec *pAFE, uint8_t bEnDis)
+{
+ if (bEnDis)
+ pAFE->AFEC_EMR |= AFEC_EMR_TAG;
+ else
+ pAFE->AFEC_EMR &= ~AFEC_EMR_TAG;
+}
+
+/**
+ * \brief Set compare channel.
+ *
+ * \param pAFE Pointer to an AFE instance.
+ * \param dwChannel channel number to be set,16 for all channels
+ */
+extern void AFEC_SetCompareChannel(Afec *pAFE, uint32_t dwChannel)
+{
+ assert(dwChannel <= 16);
+
+ if (dwChannel < 16) {
+ pAFE->AFEC_EMR &= ~(AFEC_EMR_CMPALL);
+ pAFE->AFEC_EMR &= ~(AFEC_EMR_CMPSEL_Msk);
+ pAFE->AFEC_EMR |= (dwChannel << AFEC_EMR_CMPSEL_Pos);
+ } else
+ pAFE->AFEC_EMR |= AFEC_EMR_CMPALL;
+}
+
+/**
+ * \brief Set compare mode.
+ *
+ * \param pAFE Pointer to an AFE instance.
+ * \param dwMode compare mode
+ */
+extern void AFEC_SetCompareMode(Afec *pAFE, uint32_t dwMode)
+{
+ pAFE->AFEC_EMR &= ~(AFEC_EMR_CMPMODE_Msk);
+ pAFE->AFEC_EMR |= (dwMode & AFEC_EMR_CMPMODE_Msk);
+}
+
+/**
+ * \brief Set comparison window.
+ *
+ * \param pAFE Pointer to an AFE instance.
+ * \param dwHi_Lo Comparison Window
+ */
+extern void AFEC_SetComparisonWindow(Afec *pAFE, uint32_t dwHi_Lo)
+{
+ pAFE->AFEC_CWR = dwHi_Lo;
+}
+
+/**
+ * \brief Return the Channel Converted Data
+ *
+ * \param pAFE Pointer to an AFE instance.
+ * \param dwChannel channel to get converted value
+ */
+extern uint32_t AFEC_GetConvertedData(Afec *pAFE, uint32_t dwChannel)
+{
+ uint32_t dwData = 0;
+ assert(dwChannel < 12);
+ pAFE->AFEC_CSELR = dwChannel;
+ dwData = pAFE->AFEC_CDR;
+
+ return dwData;
+}
+
+
+/**
+ * Sets the AFE startup time.
+ * \param pAFE Pointer to an AFE instance.
+ * \param dwUs Startup time in uS.
+ */
+void AFEC_SetStartupTime(Afec *pAFE, uint32_t dwUs)
+{
+ uint32_t dwStart;
+ uint32_t dwMr;
+
+ if (dwAFEClock == 0) return;
+
+ /* Formula for STARTUP is:
+ STARTUP = (time x AFECLK) / (1000000) - 1
+ Division multiplied by 10 for higher precision */
+
+ dwStart = (dwUs * dwAFEClock) / (100000);
+
+ if (dwStart % 10) dwStart /= 10;
+ else {
+ dwStart /= 10;
+
+ if (dwStart) dwStart --;
+ }
+
+ if (dwStart > 896) dwMr = AFEC_MR_STARTUP_SUT960;
+ else if (dwStart > 832) dwMr = AFEC_MR_STARTUP_SUT896;
+ else if (dwStart > 768) dwMr = AFEC_MR_STARTUP_SUT832;
+ else if (dwStart > 704) dwMr = AFEC_MR_STARTUP_SUT768;
+ else if (dwStart > 640) dwMr = AFEC_MR_STARTUP_SUT704;
+ else if (dwStart > 576) dwMr = AFEC_MR_STARTUP_SUT640;
+ else if (dwStart > 512) dwMr = AFEC_MR_STARTUP_SUT576;
+ else if (dwStart > 112) dwMr = AFEC_MR_STARTUP_SUT512;
+ else if (dwStart > 96) dwMr = AFEC_MR_STARTUP_SUT112;
+ else if (dwStart > 80) dwMr = AFEC_MR_STARTUP_SUT96;
+ else if (dwStart > 64) dwMr = AFEC_MR_STARTUP_SUT80;
+ else if (dwStart > 24) dwMr = AFEC_MR_STARTUP_SUT64;
+ else if (dwStart > 16) dwMr = AFEC_MR_STARTUP_SUT24;
+ else if (dwStart > 8) dwMr = AFEC_MR_STARTUP_SUT16;
+ else if (dwStart > 0) dwMr = AFEC_MR_STARTUP_SUT8;
+ else dwMr = AFEC_MR_STARTUP_SUT0;
+
+ dwMr |= pAFE->AFEC_MR & ~AFEC_MR_STARTUP_Msk;
+ pAFE->AFEC_MR = dwMr;
+}
+
+
+/**
+ * Set AFE tracking time
+ * \param pAFE Pointer to an AFE instance.
+ * \param dwNs Tracking time in nS.
+ */
+void AFEC_SetTrackingTime(Afec *pAFE, uint32_t dwNs)
+{
+ uint32_t dwShtim;
+ uint32_t dwMr;
+
+ if (dwAFEClock == 0) return;
+
+ /* Formula for SHTIM is:
+ SHTIM = (time x AFECLK) / (1000000000) - 1
+ Since 1 billion is close to the maximum value for an integer, we first
+ divide AFECLK by 1000 to avoid an overflow */
+ dwShtim = (dwNs * (dwAFEClock / 1000)) / 100000;
+
+ if (dwShtim % 10) dwShtim /= 10;
+ else {
+ dwShtim /= 10;
+
+ if (dwShtim) dwShtim --;
+ }
+
+ dwMr = AFEC_MR_TRACKTIM(dwShtim);
+ dwMr |= pAFE->AFEC_MR & ~AFEC_MR_TRACKTIM_Msk;
+ pAFE->AFEC_MR = dwMr;
+}
+
+/**
+ * \brief Set analog offset to be used for channel CSEL.
+ *
+ * \param afec Base address of the AFEC.
+ * \param dwChannel AFEC channel number.
+ * \param aoffset Analog offset value.
+ */
+void AFEC_SetAnalogOffset(Afec *pAFE, uint32_t dwChannel, uint32_t aoffset)
+{
+ assert(dwChannel < 12);
+ pAFE->AFEC_CSELR = dwChannel;
+ pAFE->AFEC_COCR = (aoffset & AFEC_COCR_AOFF_Msk);;
+}
+
+/**
+ * \brief Set analog offset to be used for channel CSEL.
+ *
+ * \param afec Base address of the AFEC.
+ * \param control Analog control value.
+ */
+void AFEC_SetAnalogControl(Afec *pAFE, uint32_t control)
+{
+ pAFE->AFEC_ACR = control;
+}
+
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/dac_dma.c b/bsps/arm/atsam/contrib/libraries/libchip/source/dac_dma.c
new file mode 100644
index 0000000000..5675499f95
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/dac_dma.c
@@ -0,0 +1,238 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup dacc_module Working with DACC
+ * \ingroup peripherals_module
+ * The DACC driver provides the interface to configure and use the DACC
+ * peripheral.\n
+ *
+ * The DACC(Digital-to-Analog Converter Controller) converts digital code to
+ * analog output.
+ * The data to be converted are sent in a common register for all channels.
+ * It offers up to 2 analog outputs.The output voltage ranges from (1/6)ADVREF
+ * to (5/6)ADVREF.
+ *
+ * To Enable a DACC conversion,the user has to follow these few steps:
+ * <ul>
+ * <li> Select an appropriate reference voltage on ADVREF </li>
+ * <li> Configure the DACC according to its requirements and special needs,
+ * which could be broken down into several parts:
+ * -# Enable DACC in free running mode by clearing TRGEN in DACC_MR;
+ * -# Configure Refresh Period through setting REFRESH fields
+ * in DACC_MR; The refresh mechanism is used to protect the output analog
+ * value from
+ * decreasing.
+ * -# Enable channels and write digital code to DACC_CDR,in free running mode,
+ * the conversion is started right after at least one channel is enabled and
+ * data is written .
+ </li>
+ * </ul>
+ *
+ * For more accurate information, please look at the DACC section of the
+ * Datasheet.
+ *
+ * Related files :\n
+ * \ref dac_dma.c\n
+ * \ref dac_dma.h\n
+ */
+/*@{*/
+/*@}*/
+/**
+ * \file
+ *
+ * Implementation of Digital-to-Analog Converter Controller (DACC).
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+#include <stdint.h>
+#include <assert.h>
+
+/* DMA driver instance */
+static uint32_t dacDmaTxChannel;
+static LinkedListDescriporView1 dmaWriteLinkList[256];
+/*----------------------------------------------------------------------------
+ * Local functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Configure the DMA Channels: 0 RX.
+ * Channels are disabled after configure.
+ * \returns 0 if the dma channel configuration successfully; otherwise returns
+ * DAC_ERROR_XXX.
+ */
+static uint8_t _DacConfigureDmaChannels(DacDma *pDacd)
+{
+
+ /* Driver initialize */
+ XDMAD_FreeChannel(pDacd->pXdmad, dacDmaTxChannel);
+
+ /* Allocate a DMA channel for DAC0/1 TX. */
+ dacDmaTxChannel =
+ XDMAD_AllocateChannel(pDacd->pXdmad, XDMAD_TRANSFER_MEMORY, ID_DACC);
+
+ if (dacDmaTxChannel == XDMAD_ALLOC_FAILED)
+ return DAC_ERROR;
+
+ if (XDMAD_PrepareChannel(pDacd->pXdmad, dacDmaTxChannel))
+ return DAC_ERROR;
+
+ return DAC_OK;
+}
+
+
+/**
+ * \brief Configure the DMA source and destination with Linker List mode.
+ *
+ * \param pBuffer Pointer to dac buffer
+ * \param size length of buffer
+ */
+
+static uint8_t _Dac_configureLinkList(Dacc *pDacHw, void *pXdmad,
+ DacCmd *pCommand)
+{
+ uint32_t xdmaCndc;
+ sXdmadCfg xdmadCfg;
+ uint32_t *pBuffer;
+ /* Setup TX Link List */
+ uint8_t i;
+ pBuffer = (uint32_t *)pCommand->pTxBuff;
+
+ for (i = 0; i < pCommand->TxSize; i++) {
+ dmaWriteLinkList[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1
+ | XDMA_UBC_NDE_FETCH_EN
+ | XDMA_UBC_NSEN_UPDATED
+ | XDMAC_CUBC_UBLEN(4);
+ dmaWriteLinkList[i].mbr_sa = (uint32_t)pBuffer;
+ dmaWriteLinkList[i].mbr_da =
+ (uint32_t) & (pDacHw->DACC_CDR[pCommand->dacChannel]);
+
+ if (i == (pCommand->TxSize - 1)) {
+ if (pCommand->loopback)
+ dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[0];
+ else
+ dmaWriteLinkList[i].mbr_nda = 0;
+ } else
+ dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[i + 1];
+
+ pBuffer++;
+ }
+
+ xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN
+ | XDMAC_CC_MBSIZE_SINGLE
+ | XDMAC_CC_DSYNC_MEM2PER
+ | XDMAC_CC_CSIZE_CHK_1
+ | XDMAC_CC_DWIDTH_WORD
+ | XDMAC_CC_SIF_AHB_IF1
+ | XDMAC_CC_DIF_AHB_IF1
+ | XDMAC_CC_SAM_INCREMENTED_AM
+ | XDMAC_CC_DAM_FIXED_AM
+ | XDMAC_CC_PERID(
+ XDMAIF_Get_ChannelNumber(ID_DACC, XDMAD_TRANSFER_TX));
+ xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1
+ | XDMAC_CNDC_NDE_DSCR_FETCH_EN
+ | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED
+ | XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED;
+ XDMAD_ConfigureTransfer(pXdmad, dacDmaTxChannel, &xdmadCfg, xdmaCndc,
+ (uint32_t)&dmaWriteLinkList[0], XDMAC_CIE_LIE);
+ return DAC_OK;
+}
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+/**
+ * \brief Initializes the DacDma structure and the corresponding DAC & DMA .
+ * hardware select value.
+ * The driver will uses DMA channel 0 for RX .
+ * The DMA channels are freed automatically when no DMA command processing.
+ *
+ * \param pDacd Pointer to a DacDma instance.
+ * \param pDacHw Associated Dac peripheral.
+ * \param DacId Dac peripheral identifier.
+ * \param pDmad Pointer to a Dmad instance.
+ */
+uint32_t Dac_ConfigureDma(DacDma *pDacd ,
+ Dacc *pDacHw ,
+ uint8_t DacId,
+ sXdmad *pXdmad)
+{
+ /* Initialize the Dac structure */
+ pDacd->pDacHw = pDacHw;
+ pDacd->dacId = DacId;
+ pDacd->semaphore = 1;
+ pDacd->pCurrentCommand = 0;
+ assert(pXdmad == &XDMAD_Instance);
+ pDacd->pXdmad = pXdmad;
+ return 0;
+}
+
+/**
+ * \brief Starts a DAC transfer. This is a non blocking function. It will
+ * return as soon as the transfer is started.
+ *
+ * \param pDacd Pointer to a DacDma instance.
+ * \param pCommand Pointer to the Dac command to execute.
+ * \returns 0 if the transfer has been started successfully; otherwise returns
+ * DAC_ERROR_LOCK is the driver is in use, or DAC_ERROR if the command is not
+ * valid.
+ */
+uint32_t Dac_SendData(DacDma *pDacd, DacCmd *pCommand)
+{
+ Dacc *pDacHw = pDacd->pDacHw;
+
+ /* Try to get the dataflash semaphore */
+ if (pDacd->semaphore == 0)
+ return DAC_ERROR_LOCK;
+
+ pDacd->semaphore--;
+
+ // Initialize the callback
+ pDacd->pCurrentCommand = pCommand;
+
+ /* Initialize DMA controller using channel 0 for RX. */
+ if (_DacConfigureDmaChannels(pDacd))
+ return DAC_ERROR_LOCK;
+
+ if (_Dac_configureLinkList(pDacHw, pDacd->pXdmad, pCommand))
+ return DAC_ERROR_LOCK;
+
+ SCB_CleanDCache();
+
+ /* Start DMA TX */
+ if (XDMAD_StartTransfer(pDacd->pXdmad, dacDmaTxChannel))
+ return DAC_ERROR_LOCK;
+
+ return DAC_OK;;
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/efc.c b/bsps/arm/atsam/contrib/libraries/libchip/source/efc.c
new file mode 100644
index 0000000000..a5eeccb752
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/efc.c
@@ -0,0 +1,280 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup efc_module Working with EEFC
+ * \ingroup peripherals_module
+ *
+ * The EEFC driver provides the interface to configure and use the EEFC
+ * peripheral.
+ *
+ * The user needs to set the number of wait states depending on the frequency
+ * used.\n
+ * Configure number of cycles for flash read/write operations in the FWS field
+ * of EEFC_FMR.
+ *
+ * It offers a function to send flash command to EEFC and waits for the
+ * flash to be ready.
+ *
+ * To send flash command, the user could do in either of following way:
+ * <ul>
+ * <li>Write a correct key, command and argument in EEFC_FCR. </li>
+ * <li>Or, Use IAP (In Application Programming) function which is executed from
+ * ROM directly, this allows flash programming to be done by code running in
+ * flash.</li>
+ * <li>Once the command is achieved, it can be detected even by polling
+ * EEFC_FSR or interrupt.
+ * </ul>
+ *
+ * The command argument could be a page number,GPNVM number or nothing, it
+ * depends on the command itself. Some useful functions in this driver could
+ * help user translate physical flash address into a page number and vice verse.
+ *
+ * For more accurate information, please look at the EEFC section of the
+ * Datasheet.
+ *
+ * Related files :\n
+ * \ref efc.c\n
+ * \ref efc.h.\n
+ */
+/*@{*/
+/*@}*/
+
+
+/**
+ * \file
+ *
+ * Implementation of Enhanced Embedded Flash Controller (EEFC).
+ *
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+#include "chip.h"
+
+#include <assert.h>
+
+
+/*----------------------------------------------------------------------------
+ * Macro
+ *----------------------------------------------------------------------------*/
+#define EEFC_FCR_FCMD(value) ((EEFC_FCR_FCMD_Msk & ((value) << EEFC_FCR_FCMD_Pos)))
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+extern void EFC_WriteFMR(Efc *efc, uint32_t dwFmr);
+
+#ifdef __ICCARM__
+ extern __ramfunc void EFC_WriteFMR(Efc *efc, uint32_t dwFmr)
+#else
+ __attribute__ ((section (".ramfunc")))
+ extern void EFC_WriteFMR(Efc *efc, uint32_t dwFmr)
+#endif
+{
+ efc->EEFC_FMR = dwFmr;
+}
+
+/**
+ * \brief Enables the flash ready interrupt source on the EEFC peripheral.
+ *
+ * \param efc Pointer to a Efc instance
+ */
+extern void EFC_EnableFrdyIt(Efc *efc)
+{
+ uint32_t dwFmr;
+
+ dwFmr = efc->EEFC_FMR |= EEFC_FMR_FRDY;
+ EFC_WriteFMR(efc, dwFmr);
+}
+
+/**
+ * \brief Disables the flash ready interrupt source on the EEFC peripheral.
+ *
+ * \param efc Pointer to a Efc instance
+ */
+extern void EFC_DisableFrdyIt(Efc *efc)
+{
+ uint32_t dwFmr;
+
+ dwFmr = efc->EEFC_FMR & (~EEFC_FMR_FRDY);
+ EFC_WriteFMR(efc, dwFmr);
+}
+
+
+/**
+ * \brief Set read/write wait state on the EEFC peripheral.
+ *
+ * \param efc Pointer to a Efc instance
+ * \param cycles the number of wait states in cycle.
+ */
+extern void EFC_SetWaitState(Efc *efc, uint8_t ucCycles)
+{
+ uint32_t dwFmr;
+
+ dwFmr = efc->EEFC_FMR;
+ dwFmr &= ~((uint32_t)EEFC_FMR_FWS_Msk);
+ dwFmr |= EEFC_FMR_FWS(ucCycles);
+ EFC_WriteFMR(efc, dwFmr);
+}
+
+/**
+ * \brief Returns the current status of the EEFC.
+ *
+ * \note Keep in mind that this function clears the value of some status bits
+ * (LOCKE, PROGE).
+ *
+ * \param efc Pointer to a Efc instance
+ */
+extern uint32_t EFC_GetStatus(Efc *efc)
+{
+ return efc->EEFC_FSR;
+}
+
+/**
+ * \brief Returns the result of the last executed command.
+ *
+ * \param efc Pointer to a Efc instance
+ */
+extern uint32_t EFC_GetResult(Efc *efc)
+{
+ return efc->EEFC_FRR;
+}
+
+/**
+ * \brief Translates the given address page and offset values.
+ * \note The resulting values are stored in the provided variables if they are
+ * not null.
+ *
+ * \param efc Pointer to a Efc instance
+ * \param address Address to translate.
+ * \param pPage First page accessed.
+ * \param pOffset Byte offset in first page.
+ */
+extern void EFC_TranslateAddress(Efc **ppEfc, uint32_t dwAddress,
+ uint16_t *pwPage,
+ uint16_t *pwOffset)
+{
+ assert(dwAddress >= IFLASH_ADDR);
+ assert(dwAddress <= (IFLASH_ADDR + IFLASH_SIZE));
+
+ /* Store values */
+ if (ppEfc)
+ *ppEfc = EFC;
+
+ if (pwPage)
+ *pwPage = (dwAddress - IFLASH_ADDR) / IFLASH_PAGE_SIZE;
+
+ if (pwOffset) {
+ *pwOffset = (dwAddress - IFLASH_ADDR) % IFLASH_PAGE_SIZE;;
+ }
+}
+
+
+/**
+ * \brief Computes the address of a flash access given the page and offset.
+ *
+ * \param efc Pointer to a Efc instance
+ * \param page Page number.
+ * \param offset Byte offset inside page.
+ * \param pAddress Computed address (optional).
+ */
+extern void EFC_ComputeAddress(Efc *efc, uint16_t wPage, uint16_t wOffset,
+ uint32_t *pdwAddress)
+{
+ uint32_t dwAddress;
+
+ /* Stop warning */
+ efc = efc;
+
+ assert(efc);
+ assert(wPage <= IFLASH_NB_OF_PAGES);
+ assert(wOffset < IFLASH_PAGE_SIZE);
+ dwAddress = IFLASH_ADDR + wPage * IFLASH_PAGE_SIZE + wOffset;
+
+ /* Store result */
+ if (pdwAddress != NULL)
+ *pdwAddress = dwAddress;
+}
+
+/**
+ * \brief Performs the given command and wait until its completion (or an error).
+ *
+ * \param efc Pointer to a Efc instance
+ * \param command Command to perform.
+ * \param argument Optional command argument.
+ *
+ * \return 0 if successful, otherwise returns an error code.
+ */
+
+extern uint32_t EFC_PerformCommand(Efc *efc, uint32_t dwCommand,
+ uint32_t dwArgument, uint32_t dwUseIAP)
+{
+ if (dwUseIAP != 0) {
+ /* Pointer on IAP function in ROM */
+ static uint32_t (*IAP_PerformCommand)(uint32_t, uint32_t);
+
+ IAP_PerformCommand = (uint32_t (*)(uint32_t, uint32_t))
+ * ((uint32_t *)CHIP_FLASH_IAP_ADDRESS);
+
+ if (efc == EFC) {
+ IAP_PerformCommand(0, EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(dwArgument)
+ | EEFC_FCR_FCMD(dwCommand));
+ }
+
+ return (efc->EEFC_FSR & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE | EEFC_FSR_FLERR));
+ } else {
+ uint32_t dwStatus;
+
+ efc->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(dwArgument)
+ | EEFC_FCR_FCMD(dwCommand);
+
+ do {
+ dwStatus = efc->EEFC_FSR;
+ } while ((dwStatus & EEFC_FSR_FRDY) != EEFC_FSR_FRDY);
+
+ return (dwStatus & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE | EEFC_FSR_FLERR));
+ }
+}
+
+/**
+ * \brief Set flash access mode.
+ *
+ * \param dwMode - 0:128-bit, (1<<24):64-bit
+ */
+extern void EFC_SetFlashAccessMode(Efc *efc, uint32_t dwMode)
+{
+ uint32_t dwFmr;
+
+ dwFmr = dwMode;
+ EFC_WriteFMR(efc, dwFmr);
+}
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/exceptions.c b/bsps/arm/atsam/contrib/libraries/libchip/source/exceptions.c
new file mode 100644
index 0000000000..cc5329f1da
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/exceptions.c
@@ -0,0 +1,214 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ * This file contains the default exception handlers.
+ *
+ * \note
+ * The exception handler has weak aliases.
+ * As they are weak aliases, any function with the same name will override
+ * this definition.
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Default NMI interrupt handler.
+ */
+void NMI_Handler(void)
+{
+ printf("\r\n-E- Enter NMI_Handler!");
+
+ while (1);
+}
+
+/**
+ * \brief This function back trace the stack to give exact address where fault
+ happened
+**/
+__STATIC_INLINE uint32_t StackUnwind(void)
+{
+ uint32_t Fault_Add;
+
+#if defined (__CC_ARM)
+ uint32_t temp;
+ __ASM("mrs temp, msp ");
+ __ASM{ ldr Fault_Add, [temp, #28]}
+#else
+ __ASM("mrs r0, msp ");
+ __ASM("ldr %0, [r0,#28]" : "=r" (Fault_Add));
+#endif
+ return Fault_Add;
+}
+
+/**
+ * \brief If Other Faults are enabled then HardFault error will look for those
+ * errors to give more detail about fault
+**/
+static void HardFault_reason(void)
+{
+ uint32_t CFSRValue;
+ TRACE_DEBUG("In Hard Fault Handler\n\r");
+ TRACE_DEBUG("SCB->HFSR = 0x%08x\n\r", SCB->HFSR);
+
+ if ((SCB->HFSR & SCB_HFSR_DEBUGEVT_Msk)) {
+ TRACE_DEBUG("Debug Event Hard Fault\n\r");
+ TRACE_DEBUG("SCB->DFSR = 0x%08x\n", SCB->DFSR);
+ }
+
+ if ((SCB->HFSR & SCB_HFSR_VECTTBL_Msk)) {
+ TRACE_DEBUG("Fault was due to vector table read on \
+ exception processing\n\r");
+ }
+
+ // Forced HardFault
+ if ((SCB->HFSR & SCB_HFSR_FORCED_Msk)) {
+ TRACE_DEBUG("Forced Hard Fault\n\r");
+ TRACE_DEBUG("SCB->CFSR = 0x%08x\n\r", SCB->CFSR);
+
+ // Usage Fault
+ if ((SCB->CFSR & SCB_CFSR_USGFAULTSR_Msk)) {
+ CFSRValue = SCB->CFSR;
+ TRACE_DEBUG("Usage fault: ");
+ CFSRValue >>= SCB_CFSR_USGFAULTSR_Pos;
+
+ if ((CFSRValue & (1 << 9)))
+ TRACE_DEBUG("Divide by zero\n\r");
+
+ if ((CFSRValue & (1 << 8)))
+ TRACE_DEBUG("Unaligned access error\n\r");
+
+ if ((CFSRValue & (1 << 3)))
+ TRACE_DEBUG("Coprocessor access error\n\r");
+
+ if ((CFSRValue & (1 << 2)))
+ TRACE_DEBUG("Integrity check error on EXC_RETURN\n\r");
+ }
+
+ // Bus Fault
+ if ((SCB->CFSR & SCB_CFSR_BUSFAULTSR_Msk)) {
+ CFSRValue = SCB->CFSR;
+ TRACE_DEBUG("Bus fault: ");
+ CFSRValue >>= SCB_CFSR_BUSFAULTSR_Pos;
+
+ if ((CFSRValue & (1 << 7)) && (CFSRValue & (1 << 1))) {
+ TRACE_DEBUG("Precise data access error. Bus Fault Address \
+ Register is: %x \n\r", SCB->BFAR);
+ }
+
+ if ((CFSRValue & (1 << 4)))
+ TRACE_DEBUG("Bus fault has occurred on exception entry\n\r");
+
+ if ((CFSRValue & (1 << 3)))
+ TRACE_DEBUG("bus fault has occurred on exception return\n\r");
+
+ if ((CFSRValue & (1 << 2)))
+ TRACE_DEBUG("Imprecise data access error\n\r");
+
+ if ((CFSRValue & (1 << 0))) {
+ TRACE_DEBUG("This bit indicates a bus fault on an instruction \
+ pre-fetch. \n\r");
+ }
+ }
+ }
+
+ // MemoryFault
+ if ((SCB->CFSR & SCB_CFSR_MEMFAULTSR_Msk)) {
+ CFSRValue = SCB->CFSR;
+ TRACE_DEBUG("Memory fault: ");
+ CFSRValue >>= SCB_CFSR_MEMFAULTSR_Pos;
+
+ if ((CFSRValue & (1 << 9)) != 0)
+ TRACE_DEBUG("Divide by zero\n\r");
+ }
+
+ __ISB();
+ __DMB();
+ __ASM volatile("BKPT #01");
+}
+/**
+ * \brief Default HardFault interrupt handler.
+ */
+
+void HardFault_Handler(void)
+{
+ printf("\n\rHardFault at address 0X%x\n\r", (int)StackUnwind());
+ __ISB();
+ __DMB();
+ HardFault_reason();
+}
+
+#ifndef MPU_EXAMPLE_FEATURE
+/**
+ * \brief Default MemManage interrupt handler.
+ */
+void MemManage_Handler(void)
+{
+ printf("\n\rMemoryMemFault (MPU fault) at address 0X%x\n\r",
+ (int)StackUnwind());
+ __ISB();
+ __DMB();
+ __ASM volatile("BKPT #01");
+}
+#endif
+
+/**
+ * \brief Default BusFault interrupt handler.
+ */
+void BusFault_Handler(void)
+{
+ __ASM("nop");
+ __ASM("nop");
+ printf("\n\rBus Fault at address 0X%x\n\r", (int)StackUnwind());
+
+ __ISB();
+ __DMB();
+ __ASM volatile("BKPT #01");
+}
+
+/**
+ * \brief Default UsageFault interrupt handler.
+ */
+void UsageFault_Handler(void)
+{
+ printf("\r\nUsage fault at address 0X%x", (int)StackUnwind());
+
+ __ISB();
+ __DMB();
+ __ASM volatile("BKPT #01");
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/flashd.c b/bsps/arm/atsam/contrib/libraries/libchip/source/flashd.c
new file mode 100644
index 0000000000..298b16ac17
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/flashd.c
@@ -0,0 +1,595 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup flashd_module Flash Memory Interface
+ * The flash driver manages the programming, erasing, locking and unlocking
+ * sequences with dedicated commands.
+ *
+ * To implement flash programming operation, the user has to follow these few
+ * steps :
+ * <ul>
+ * <li>Configure flash wait states to initializes the flash. </li>
+ * <li>Checks whether a region to be programmed is locked. </li>
+ * <li>Unlocks the user region to be programmed if the region have locked
+ * before.</li>
+ * <li>Erases the user page before program (optional).</li>
+ * <li>Writes the user page from the page buffer.</li>
+ * <li>Locks the region of programmed area if any.</li>
+ * </ul>
+ *
+ * Writing 8-bit and 16-bit data is not allowed and may lead to unpredictable
+ * data corruption.
+ * A check of this validity and padding for 32-bit alignment should be done in
+ * write algorithm.
+ * Lock/unlock range associated with the user address range is automatically
+ * translated.
+ *
+ * This security bit can be enabled through the command "Set General Purpose
+ * NVM Bit 0".
+ *
+ * A 128-bit factory programmed unique ID could be read to serve several
+ * purposes.
+ *
+ * The driver accesses the flash memory by calling the lowlevel module provided
+ * in \ref efc_module.
+ * For more accurate information, please look at the EEFC section of the
+ * Datasheet.
+ *
+ * Related files :\n
+ * \ref flashd.c\n
+ * \ref flashd.h.\n
+ * \ref efc.c\n
+ * \ref efc.h.\n
+ */
+/*@{*/
+/*@}*/
+
+
+/**
+ * \file
+ *
+ * The flash driver provides the unified interface for flash program operations.
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+#include "chip.h"
+
+#include <string.h>
+#include <assert.h>
+
+/*----------------------------------------------------------------------------
+ * Definitions
+ *----------------------------------------------------------------------------*/
+
+#define GPNVM_NUM_MAX 9
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ *----------------------------------------------------------------------------*/
+
+static uint32_t _pdwPageBuffer[IFLASH_PAGE_SIZE / sizeof(uint32_t)];
+static uint32_t _dwUseIAP = 1; /* Use IAP interface by default. */
+
+
+/*----------------------------------------------------------------------------
+ * Local functions
+ *----------------------------------------------------------------------------*/
+
+
+/**
+ * \brief Computes the lock range associated with the given address range.
+ *
+ * \param dwStart Start address of lock range.
+ * \param dwEnd End address of lock range.
+ * \param pdwActualStart Actual start address of lock range.
+ * \param pdwActualEnd Actual end address of lock range.
+ */
+static void ComputeLockRange(uint32_t dwStart, uint32_t dwEnd,
+ uint32_t *pdwActualStart, uint32_t *pdwActualEnd)
+{
+ Efc *pStartEfc;
+ Efc *pEndEfc;
+ uint16_t wStartPage;
+ uint16_t wEndPage;
+ uint16_t wNumPagesInRegion;
+ uint16_t wActualStartPage;
+ uint16_t wActualEndPage;
+
+ /* Convert start and end address in page numbers */
+ EFC_TranslateAddress(&pStartEfc, dwStart, &wStartPage, 0);
+ EFC_TranslateAddress(&pEndEfc, dwEnd, &wEndPage, 0);
+
+ /* Find out the first page of the first region to lock */
+ wNumPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
+ wActualStartPage = wStartPage - (wStartPage % wNumPagesInRegion);
+ wActualEndPage = wEndPage;
+
+ if ((wEndPage % wNumPagesInRegion) != 0)
+ wActualEndPage += wNumPagesInRegion - (wEndPage % wNumPagesInRegion);
+
+ /* Store actual page numbers */
+ EFC_ComputeAddress(pStartEfc, wActualStartPage, 0, pdwActualStart);
+ EFC_ComputeAddress(pEndEfc, wActualEndPage, 0, pdwActualEnd);
+ TRACE_DEBUG("Actual lock range is 0x%06X - 0x%06X\n\r",
+ (unsigned int)*pdwActualStart, (unsigned int)*pdwActualEnd);
+}
+
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Initializes the flash driver.
+ *
+ * \param dwMCk Master clock frequency in Hz.
+ * \param dwUseIAP 0: use EEFC controller interface, 1: use IAP interface.
+ * dwUseIAP should be set to 1 when running out of flash.
+ */
+
+extern void FLASHD_Initialize(uint32_t dwMCk, uint32_t dwUseIAP)
+{
+ dwMCk = dwMCk; /* avoid warnings */
+
+ EFC_DisableFrdyIt(EFC);
+ _dwUseIAP = dwUseIAP;
+}
+
+/**
+ * \brief Erases the entire flash.
+ *
+ * \param dwAddress Flash start address.
+ * \return 0 if successful; otherwise returns an error code.
+ */
+extern uint32_t FLASHD_Erase(uint32_t dwAddress)
+{
+ Efc *pEfc;
+ uint16_t wPage;
+ uint16_t wOffset;
+ uint32_t dwError;
+
+ assert((dwAddress >= IFLASH_ADDR)
+ || (dwAddress <= (IFLASH_ADDR + IFLASH_SIZE)));
+
+ /* Translate write address */
+ EFC_TranslateAddress(&pEfc, dwAddress, &wPage, &wOffset);
+ dwError = EFC_PerformCommand(pEfc, EFC_FCMD_EA, 0, _dwUseIAP);
+
+ return dwError;
+}
+
+/**
+ * \brief Erases flash by sector.
+ *
+ * \param dwAddress Start address of be erased sector.
+ *
+ * \return 0 if successful; otherwise returns an error code.
+ */
+extern uint32_t FLASHD_EraseSector(uint32_t dwAddress)
+{
+ Efc *pEfc;
+ uint16_t wPage;
+ uint16_t wOffset;
+ uint32_t dwError;
+
+ assert((dwAddress >= IFLASH_ADDR)
+ || (dwAddress <= (IFLASH_ADDR + IFLASH_SIZE)));
+
+ /* Translate write address */
+ EFC_TranslateAddress(&pEfc, dwAddress, &wPage, &wOffset);
+ dwError = EFC_PerformCommand(pEfc, EFC_FCMD_ES, wPage, _dwUseIAP);
+
+ return dwError;
+}
+
+/**
+ * \brief Erases flash by pages.
+ *
+ * \param dwAddress Start address of be erased pages.
+ * \param dwPageNum Number of pages to be erased with EPA command (4, 8, 16, 32)
+ *
+ * \return 0 if successful; otherwise returns an error code.
+ */
+extern uint32_t FLASHD_ErasePages(uint32_t dwAddress, uint32_t dwPageNum)
+{
+ Efc *pEfc;
+ uint16_t wPage;
+ uint16_t wOffset;
+ uint32_t dwError;
+ static uint32_t dwFarg;
+
+ assert((dwAddress >= IFLASH_ADDR)
+ || (dwAddress <= (IFLASH_ADDR + IFLASH_SIZE)));
+
+ /* Translate write address */
+ EFC_TranslateAddress(&pEfc, dwAddress, &wPage, &wOffset);
+
+ /* Get FARG field for EPA command:
+ * The first page to be erased is specified in the FARG[15:2] field of
+ * the MC_FCR register. The first page number must be modulo 4, 8,16 or 32
+ * according to the number of pages to erase at the same time.
+ *
+ * The 2 lowest bits of the FARG field define the number of pages to
+ * be erased (FARG[1:0]).
+ */
+ if (dwPageNum == 32) {
+ wPage &= ~(32u - 1u);
+ dwFarg = (wPage) | 3; /* 32 pages */
+ } else if (dwPageNum == 16) {
+ wPage &= ~(16u - 1u);
+ dwFarg = (wPage) | 2; /* 16 pages */
+ } else if (dwPageNum == 8) {
+ wPage &= ~(8u - 1u);
+ dwFarg = (wPage) | 1; /* 8 pages */
+ } else {
+ wPage &= ~(4u - 1u);
+ dwFarg = (wPage) | 0; /* 4 pages */
+ }
+
+ dwError = EFC_PerformCommand(pEfc, EFC_FCMD_EPA, dwFarg, _dwUseIAP);
+
+ return dwError;
+}
+
+
+/**
+ * \brief Writes a data buffer in the internal flash
+ *
+ * \note This function works in polling mode, and thus only returns when the
+ * data has been effectively written.
+ * \param address Write address.
+ * \param pBuffer Data buffer.
+ * \param size Size of data buffer in bytes.
+ * \return 0 if successful, otherwise returns an error code.
+ */
+extern uint32_t FLASHD_Write(uint32_t dwAddress,
+ const void *pvBuffer, uint32_t dwSize)
+{
+ Efc *pEfc;
+ uint16_t page;
+ uint16_t offset;
+ uint32_t writeSize;
+ uint32_t pageAddress;
+ uint16_t padding;
+ uint32_t dwError;
+ uint32_t dwIdx;
+ uint32_t *pAlignedDestination;
+ uint8_t *pucPageBuffer = (uint8_t *)_pdwPageBuffer;
+
+ assert(pvBuffer);
+ assert(dwAddress >= IFLASH_ADDR);
+ assert((dwAddress + dwSize) <= (IFLASH_ADDR + IFLASH_SIZE));
+
+ /* Translate write address */
+ EFC_TranslateAddress(&pEfc, dwAddress, &page, &offset);
+
+ /* Write all pages */
+ while (dwSize > 0) {
+ /* Copy data in temporary buffer to avoid alignment problems */
+ writeSize = min((uint32_t)IFLASH_PAGE_SIZE - offset, dwSize);
+ EFC_ComputeAddress(pEfc, page, 0, &pageAddress);
+ padding = IFLASH_PAGE_SIZE - offset - writeSize;
+
+ /* Pre-buffer data */
+ memcpy(pucPageBuffer, (void *) pageAddress, offset);
+
+ /* Buffer data */
+ memcpy(pucPageBuffer + offset, pvBuffer, writeSize);
+
+ /* Post-buffer data */
+ memcpy(pucPageBuffer + offset + writeSize,
+ (void *) (pageAddress + offset + writeSize), padding);
+
+ /* Write page
+ * Writing 8-bit and 16-bit data is not allowed and may
+ lead to unpredictable data corruption
+ */
+ pAlignedDestination = (uint32_t *)pageAddress;
+
+ for (dwIdx = 0; dwIdx < (IFLASH_PAGE_SIZE / sizeof(uint32_t)); ++ dwIdx) {
+ *pAlignedDestination++ = _pdwPageBuffer[dwIdx];
+ memory_barrier()
+ }
+
+ /* Cache coherence operation before flash write*/
+ SCB_CleanDCache_by_Addr((uint32_t *)pageAddress, IFLASH_PAGE_SIZE);
+
+ /* Note: It is not possible to use Erase and write Command (EWP) on all Flash
+ (this command is available on the First 2 Small Sector, 16K Bytes).
+ For the next block, Erase them first then use Write page command. */
+
+ /* Send writing command */
+ dwError = EFC_PerformCommand(pEfc, EFC_FCMD_WP, page, _dwUseIAP);
+
+ if (dwError)
+ return dwError;
+
+ /* Progression */
+ pvBuffer = (void *)((uint32_t) pvBuffer + writeSize);
+ dwSize -= writeSize;
+ page++;
+ offset = 0;
+ }
+
+ return 0;
+}
+
+/**
+ * \brief Locks all the regions in the given address range. The actual lock
+ * range is reported through two output parameters.
+ *
+ * \param start Start address of lock range.
+ * \param end End address of lock range.
+ * \param pActualStart Start address of the actual lock range (optional).
+ * \param pActualEnd End address of the actual lock range (optional).
+ * \return 0 if successful, otherwise returns an error code.
+ */
+extern uint32_t FLASHD_Lock(uint32_t start, uint32_t end,
+ uint32_t *pActualStart, uint32_t *pActualEnd)
+{
+ Efc *pEfc;
+ uint32_t actualStart, actualEnd;
+ uint16_t startPage, endPage;
+ uint32_t dwError;
+ uint16_t numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
+
+ /* Compute actual lock range and store it */
+ ComputeLockRange(start, end, &actualStart, &actualEnd);
+
+ if (pActualStart != NULL)
+ *pActualStart = actualStart;
+
+ if (pActualEnd != NULL)
+ *pActualEnd = actualEnd;
+
+ /* Compute page numbers */
+ EFC_TranslateAddress(&pEfc, actualStart, &startPage, 0);
+ EFC_TranslateAddress(0, actualEnd, &endPage, 0);
+
+ /* Lock all pages */
+ while (startPage < endPage) {
+ dwError = EFC_PerformCommand(pEfc, EFC_FCMD_SLB, startPage, _dwUseIAP);
+
+ if (dwError)
+ return dwError;
+
+ startPage += numPagesInRegion;
+ }
+
+ return 0;
+}
+
+/**
+ * \brief Unlocks all the regions in the given address range. The actual unlock
+ * range is reported through two output parameters.
+ * \param start Start address of unlock range.
+ * \param end End address of unlock range.
+ * \param pActualStart Start address of the actual unlock range (optional).
+ * \param pActualEnd End address of the actual unlock range (optional).
+ * \return 0 if successful, otherwise returns an error code.
+ */
+extern uint32_t FLASHD_Unlock(uint32_t start, uint32_t end,
+ uint32_t *pActualStart, uint32_t *pActualEnd)
+{
+ Efc *pEfc;
+ uint32_t actualStart, actualEnd;
+ uint16_t startPage, endPage;
+ uint32_t dwError;
+ uint16_t numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
+
+ /* Compute actual unlock range and store it */
+ ComputeLockRange(start, end, &actualStart, &actualEnd);
+
+ if (pActualStart != NULL)
+ *pActualStart = actualStart;
+
+ if (pActualEnd != NULL)
+ *pActualEnd = actualEnd;
+
+ /* Compute page numbers */
+ EFC_TranslateAddress(&pEfc, actualStart, &startPage, 0);
+ EFC_TranslateAddress(0, actualEnd, &endPage, 0);
+
+ /* Unlock all pages */
+ while (startPage < endPage) {
+ dwError = EFC_PerformCommand(pEfc, EFC_FCMD_CLB, startPage, _dwUseIAP);
+
+ if (dwError)
+ return dwError;
+
+ startPage += numPagesInRegion;
+ }
+
+ return 0;
+}
+
+/**
+ * \brief Returns the number of locked regions inside the given address range.
+ *
+ * \param start Start address of range
+ * \param end End address of range.
+ */
+extern uint32_t FLASHD_IsLocked(uint32_t start, uint32_t end)
+{
+ uint32_t i, j;
+ Efc *pEfc;
+ uint16_t startPage, endPage;
+ uint8_t startRegion, endRegion;
+ uint32_t numPagesInRegion;
+ uint32_t status[IFLASH_NB_OF_LOCK_BITS / 32u];
+ uint32_t numLockedRegions = 0;
+
+ assert(end >= start);
+ assert((start >= IFLASH_ADDR) && (end <= IFLASH_ADDR + IFLASH_SIZE));
+
+ /* Compute page numbers */
+ EFC_TranslateAddress(&pEfc, start, &startPage, 0);
+ EFC_TranslateAddress(0, end, &endPage, 0);
+
+ /* Compute region numbers */
+ numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
+ startRegion = startPage / numPagesInRegion;
+ endRegion = endPage / numPagesInRegion;
+
+ if ((endPage % numPagesInRegion) != 0)
+ endRegion++;
+
+ /* Retrieve lock status */
+ EFC_PerformCommand(pEfc, EFC_FCMD_GLB, 0, _dwUseIAP);
+
+ for (i = 0; i < (IFLASH_NB_OF_LOCK_BITS / 32u); i++)
+ status[i] = EFC_GetResult(pEfc);
+
+ /* Check status of each involved region */
+ while (startRegion < endRegion) {
+ i = startRegion / 32u;
+ j = startRegion % 32u;
+
+ if ((status[i] & (1 << j)) != 0)
+ numLockedRegions++;
+
+ startRegion++;
+ }
+
+ return numLockedRegions;
+}
+
+/**
+ * \brief Check if the given GPNVM bit is set or not.
+ *
+ * \param gpnvm GPNVM bit index.
+ * \returns 1 if the given GPNVM bit is currently set; otherwise returns 0.
+ */
+extern uint32_t FLASHD_IsGPNVMSet(uint8_t ucGPNVM)
+{
+ uint32_t dwStatus;
+
+ assert(ucGPNVM < GPNVM_NUM_MAX);
+
+ /* Get GPNVMs status */
+ EFC_PerformCommand(EFC, EFC_FCMD_GFB, 0, _dwUseIAP);
+ dwStatus = EFC_GetResult(EFC);
+
+ /* Check if GPNVM is set */
+ if ((dwStatus & (1 << ucGPNVM)) != 0)
+ return 1;
+ else
+ return 0;
+}
+
+/**
+ * \brief Sets the selected GPNVM bit.
+ *
+ * \param gpnvm GPNVM bit index.
+ * \returns 0 if successful; otherwise returns an error code.
+ */
+extern uint32_t FLASHD_SetGPNVM(uint8_t ucGPNVM)
+{
+ assert(ucGPNVM < GPNVM_NUM_MAX);
+
+ if (!FLASHD_IsGPNVMSet(ucGPNVM))
+ return EFC_PerformCommand(EFC, EFC_FCMD_SFB, ucGPNVM, _dwUseIAP);
+ else
+ return 0;
+}
+
+/**
+ * \brief Clears the selected GPNVM bit.
+ *
+ * \param gpnvm GPNVM bit index.
+ * \returns 0 if successful; otherwise returns an error code.
+ */
+extern uint32_t FLASHD_ClearGPNVM(uint8_t ucGPNVM)
+{
+ assert(ucGPNVM < GPNVM_NUM_MAX);
+
+ if (FLASHD_IsGPNVMSet(ucGPNVM))
+ return EFC_PerformCommand(EFC, EFC_FCMD_CFB, ucGPNVM, _dwUseIAP);
+ else
+ return 0;
+}
+
+/**
+ * \brief Read the unique ID.
+ *
+ * \param pdwUniqueID pointer on a 4bytes char containing the unique ID value.
+ * \returns 0 if successful; otherwise returns an error code.
+ */
+#ifdef __ICCARM__
+ extern __ramfunc uint32_t FLASHD_ReadUniqueID(uint32_t *pdwUniqueID)
+#else
+ __attribute__ ((section (".ramfunc")))
+ uint32_t FLASHD_ReadUniqueID(uint32_t *pdwUniqueID)
+#endif
+{
+ uint32_t status;
+
+ if (pdwUniqueID == NULL)
+ return 1;
+
+ pdwUniqueID[0] = 0;
+ pdwUniqueID[1] = 0;
+ pdwUniqueID[2] = 0;
+ pdwUniqueID[3] = 0;
+
+ /* Send the Start Read unique Identifier command (STUI) by writing the Flash
+ Command Register with the STUI command.*/
+ EFC->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EFC_FCMD_STUI;
+
+ /* When the Unique Identifier is ready to be read, the FRDY bit in the Flash
+ Programming Status Register (EEFC_FSR) falls. */
+ do {
+ status = EFC->EEFC_FSR;
+ } while ((status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY);
+
+ /* The Unique Identifier is located in the first 128 bits of the Flash
+ memory mapping. So, at the address 0x400000-0x40000F. */
+ pdwUniqueID[0] = *(uint32_t *)IFLASH_ADDR;
+ pdwUniqueID[1] = *(uint32_t *)(IFLASH_ADDR + 4);
+ pdwUniqueID[2] = *(uint32_t *)(IFLASH_ADDR + 8);
+ pdwUniqueID[3] = *(uint32_t *)(IFLASH_ADDR + 12);
+
+ /* To stop the Unique Identifier mode, the user needs to send the Stop Read
+ unique Identifier command (SPUI) by writing the Flash Command Register
+ with the SPUI command. */
+ EFC->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EFC_FCMD_SPUI;
+
+ /* When the Stop read Unique Unique Identifier command (SPUI) has been
+ performed, the FRDY bit in the Flash Programming Status Register (EEFC_FSR)
+ rises. */
+ do {
+ status = EFC->EEFC_FSR;
+ } while ((status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY);
+
+ return 0;
+}
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/gmac.c b/bsps/arm/atsam/contrib/libraries/libchip/source/gmac.c
new file mode 100644
index 0000000000..d7ce4f166d
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/gmac.c
@@ -0,0 +1,685 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \file */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+
+
+/*----------------------------------------------------------------------------
+ * Internal functions
+ *----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * Return 1 if PHY is idle
+ */
+uint8_t GMAC_IsIdle(Gmac *pGmac)
+{
+ return ((pGmac->GMAC_NSR & GMAC_NSR_IDLE) > 0);
+}
+
+
+/**
+ * Execute PHY maintenance command
+ */
+void GMAC_PHYMaintain(Gmac *pGmac,
+ uint8_t bPhyAddr,
+ uint8_t bRegAddr,
+ uint8_t bRW,
+ uint16_t wData)
+{
+ /* Wait until bus idle */
+ while ((pGmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);
+
+ /* Write maintain register */
+ pGmac->GMAC_MAN = (~GMAC_MAN_WZO & GMAC_MAN_CLTTO)
+ | (GMAC_MAN_OP(bRW ? 0x2 : 0x1))
+ | GMAC_MAN_WTN(0x02)
+ | GMAC_MAN_PHYA(bPhyAddr)
+ | GMAC_MAN_REGA(bRegAddr)
+ | GMAC_MAN_DATA(wData);
+}
+
+/**
+ * Return PHY maintenance data returned
+ */
+uint16_t GMAC_PHYData(Gmac *pGmac)
+{
+ /* Wait until bus idle */
+ while ((pGmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);
+
+ /* Return data */
+ return (uint16_t)(pGmac->GMAC_MAN & GMAC_MAN_DATA_Msk);
+}
+
+/**
+ * \brief Set MDC clock according to current board clock. Per 802.3, MDC should
+ * be less then 2.5MHz.
+ * \param pGmac Pointer to an Gmac instance.
+ * \param mck Mdc clock
+ * \return 1 if successfully, 0 if MDC clock not found.
+ */
+uint8_t GMAC_SetMdcClock(Gmac *pGmac, uint32_t mck)
+{
+ uint32_t clock_dividor;
+ pGmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
+
+ if (mck <= 20000000) {
+ clock_dividor = GMAC_NCFGR_CLK_MCK_8; // MDC clock = MCK/8
+ } else if (mck <= 40000000) {
+ clock_dividor = GMAC_NCFGR_CLK_MCK_16; // MDC clock = MCK/16
+ } else if (mck <= 80000000) {
+ clock_dividor = GMAC_NCFGR_CLK_MCK_32; // MDC clock = MCK/32
+ } else if (mck <= 160000000) {
+ clock_dividor = GMAC_NCFGR_CLK_MCK_64; // MDC clock = MCK/64
+ } else if (mck <= 240000000) {
+ clock_dividor = GMAC_NCFGR_CLK_MCK_96; // MDC clock = MCK/96
+ } else {
+ TRACE_ERROR("E: No valid MDC clock.\n\r");
+ return 0;
+ }
+
+ pGmac->GMAC_NCFGR = (pGmac->GMAC_NCFGR & (~GMAC_NCFGR_CLK_Msk)) | clock_dividor;
+ pGmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
+ return 1;
+}
+
+/**
+ * \brief Enable MDI with PHY
+ * \param pGmac Pointer to an Gmac instance.
+ */
+void GMAC_EnableMdio(Gmac *pGmac)
+{
+ pGmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
+ pGmac->GMAC_NCR |= GMAC_NCR_MPE;
+ pGmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
+}
+
+/**
+ * \brief Enable MDI with PHY
+ * \param pGmac Pointer to an Gmac instance.
+ */
+void GMAC_DisableMdio(Gmac *pGmac)
+{
+ pGmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
+ pGmac->GMAC_NCR &= ~GMAC_NCR_MPE;
+ pGmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
+}
+
+/**
+ * \brief Enable MII mode for GMAC, called once after auto negotiate
+ * \param pGmac Pointer to an Gmac instance.
+ */
+void GMAC_EnableMII(Gmac *pGmac)
+{
+ pGmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
+ pGmac->GMAC_UR &= ~GMAC_UR_RMII;
+ pGmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
+}
+
+/**
+ * \brief Enable GMII mode for GMAC, called once after auto negotiate
+ * \param pGmac Pointer to an Gmac instance.
+ */
+void GMAC_EnableGMII(Gmac *pGmac)
+{
+ pGmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
+ /* RGMII disable */
+ pGmac->GMAC_UR &= ~GMAC_UR_RMII;
+ pGmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
+}
+
+#define GMAC_NCFGR_GBE (0x1u << 10)
+/**
+ * \brief Enable RGMII mode for GMAC, called once after auto negotiate
+ * \param pGmac Pointer to an Gmac instance.
+ * \param duplex: 1 full duplex 0 half duplex
+ * \param speed: 0 10M 1 100M
+ */
+void GMAC_EnableRGMII(Gmac *pGmac, uint32_t duplex, uint32_t speed)
+{
+ pGmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
+
+ if (duplex == GMAC_DUPLEX_HALF)
+ pGmac->GMAC_NCFGR &= ~GMAC_NCFGR_FD;
+ else
+ pGmac->GMAC_NCFGR |= GMAC_NCFGR_FD;
+
+
+ if (speed == GMAC_SPEED_10M)
+ pGmac->GMAC_NCFGR &= ~GMAC_NCFGR_SPD;
+ else if (speed == GMAC_SPEED_100M)
+ pGmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;
+ else
+ pGmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;
+
+ /* RGMII enable */
+ pGmac->GMAC_UR = 0;
+ pGmac->GMAC_NCFGR &= ~GMAC_NCFGR_GBE;
+ pGmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
+ return;
+}
+
+/**
+ * \brief Setup the GMAC for the link : speed 100M/10M and Full/Half duplex
+ * \param pGmac Pointer to an Gmac instance.
+ * \param speed Link speed, 0 for 10M, 1 for 100M
+ * \param fullduplex 1 for Full Duplex mode
+ */
+void GMAC_SetLinkSpeed(Gmac *pGmac, uint8_t speed, uint8_t fullduplex)
+{
+ uint32_t ncfgr;
+ ncfgr = pGmac->GMAC_NCFGR;
+ ncfgr &= ~(GMAC_NCFGR_SPD | GMAC_NCFGR_FD);
+
+ if (speed)
+ ncfgr |= GMAC_NCFGR_SPD;
+
+ if (fullduplex)
+ ncfgr |= GMAC_NCFGR_FD;
+
+ pGmac->GMAC_NCFGR = ncfgr;
+ pGmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
+}
+
+/**
+ * \brief set local loop back
+ * \param pGmac Pointer to an Gmac instance.
+ */
+uint32_t GMAC_SetLocalLoopBack(Gmac *pGmac)
+{
+ pGmac->GMAC_NCR |= GMAC_NCR_LBL;
+ return 0;
+}
+
+/**
+ * Return interrupt mask.
+ */
+uint32_t GMAC_GetItMask(Gmac *pGmac, gmacQueList_t queueIdx)
+{
+ if (!queueIdx)
+ return pGmac->GMAC_IMR;
+ else
+ return pGmac->GMAC_IMRPQ[queueIdx - 1];
+}
+
+
+/**
+ * Return transmit status
+ */
+uint32_t GMAC_GetTxStatus(Gmac *pGmac)
+{
+ return pGmac->GMAC_TSR;
+}
+
+/**
+ * Clear transmit status
+ */
+void GMAC_ClearTxStatus(Gmac *pGmac, uint32_t dwStatus)
+{
+ pGmac->GMAC_TSR = dwStatus;
+}
+
+/**
+ * Return receive status
+ */
+uint32_t GMAC_GetRxStatus(Gmac *pGmac)
+{
+ return pGmac->GMAC_RSR;
+}
+
+/**
+ * Clear receive status
+ */
+void GMAC_ClearRxStatus(Gmac *pGmac, uint32_t dwStatus)
+{
+ pGmac->GMAC_RSR = dwStatus;
+}
+
+
+/**
+ * Enable/Disable GMAC receive.
+ */
+void GMAC_ReceiveEnable(Gmac *pGmac, uint8_t bEnaDis)
+{
+ if (bEnaDis) pGmac->GMAC_NCR |= GMAC_NCR_RXEN;
+ else pGmac->GMAC_NCR &= ~GMAC_NCR_RXEN;
+}
+
+/**
+ * Enable/Disable GMAC transmit.
+ */
+void GMAC_TransmitEnable(Gmac *pGmac, uint8_t bEnaDis)
+{
+ if (bEnaDis) pGmac->GMAC_NCR |= GMAC_NCR_TXEN;
+ else pGmac->GMAC_NCR &= ~GMAC_NCR_TXEN;
+}
+
+
+/**
+ * Set Rx Queue
+ */
+void GMAC_SetRxQueue(Gmac *pGmac, uint32_t dwAddr, gmacQueList_t queueIdx)
+{
+ if (!queueIdx)
+ pGmac->GMAC_RBQB = GMAC_RBQB_ADDR_Msk & dwAddr;
+ else
+ pGmac->GMAC_RBQBAPQ[queueIdx - 1] = GMAC_RBQB_ADDR_Msk & dwAddr;
+}
+
+/**
+ * Get Rx Queue Address
+ */
+uint32_t GMAC_GetRxQueue(Gmac *pGmac, gmacQueList_t queueIdx)
+{
+ if (!queueIdx)
+ return pGmac->GMAC_RBQB;
+ else
+ return pGmac->GMAC_RBQBAPQ[queueIdx - 1];
+}
+
+/**
+ * Set Tx Queue
+ */
+void GMAC_SetTxQueue(Gmac *pGmac, uint32_t dwAddr, gmacQueList_t queueIdx)
+{
+ if (!queueIdx)
+ pGmac->GMAC_TBQB = GMAC_TBQB_ADDR_Msk & dwAddr;
+ else
+ pGmac->GMAC_TBQBAPQ[queueIdx - 1] = GMAC_TBQB_ADDR_Msk & dwAddr;
+}
+
+/**
+ * Get Tx Queue
+ */
+uint32_t GMAC_GetTxQueue(Gmac *pGmac, gmacQueList_t queueIdx)
+{
+ if (!queueIdx)
+ return pGmac->GMAC_TBQB;
+ else
+ return pGmac->GMAC_TBQBAPQ[queueIdx - 1];
+}
+
+
+/**
+ * Write control value
+ */
+void GMAC_NetworkControl(Gmac *pGmac, uint32_t bmNCR)
+{
+ pGmac->GMAC_NCR = bmNCR;
+}
+
+
+/**
+ * Get control value
+ */
+uint32_t GMAC_GetNetworkControl(Gmac *pGmac)
+{
+ return pGmac->GMAC_NCR;
+}
+
+/**
+ * Enable interrupt(s).
+ */
+void GMAC_EnableIt(Gmac *pGmac, uint32_t dwSources, gmacQueList_t queueIdx)
+{
+ if (!queueIdx)
+ pGmac->GMAC_IER = dwSources;
+ else
+ pGmac->GMAC_IERPQ[queueIdx - 1] = dwSources;
+}
+
+/**
+ * Disable interrupt(s).
+ */
+void GMAC_DisableAllQueueIt(Gmac *pGmac, uint32_t dwSources)
+{
+ pGmac->GMAC_IDR = dwSources;
+ pGmac->GMAC_IDRPQ[0] = dwSources;
+ pGmac->GMAC_IDRPQ[1] = dwSources;
+}
+
+/**
+ * Disable interrupt(s).
+ */
+void GMAC_EnableAllQueueIt(Gmac *pGmac, uint32_t dwSources)
+{
+ pGmac->GMAC_IER = dwSources;
+ pGmac->GMAC_IERPQ[0] = dwSources;
+ pGmac->GMAC_IERPQ[1] = dwSources;
+}
+
+/**
+ * Disable interrupt(s).
+ */
+void GMAC_DisableIt(Gmac *pGmac, uint32_t dwSources, gmacQueList_t queueIdx)
+{
+ if (!queueIdx)
+ pGmac->GMAC_IDR = dwSources;
+ else
+ pGmac->GMAC_IDRPQ[queueIdx - 1] = dwSources;
+}
+
+/**
+ * Return interrupt status.
+ */
+uint32_t GMAC_GetItStatus(Gmac *pGmac, gmacQueList_t queueIdx)
+{
+ if (!queueIdx)
+ return pGmac->GMAC_ISR;
+ else
+ return pGmac->GMAC_ISRPQ[queueIdx - 1];
+}
+
+
+/**
+ * Set MAC Address
+ */
+void GMAC_SetAddress(Gmac *pGmac, uint8_t bIndex, uint8_t *pMacAddr)
+{
+ pGmac->GMAC_SA[bIndex].GMAC_SAB = (pMacAddr[3] << 24)
+ | (pMacAddr[2] << 16)
+ | (pMacAddr[1] << 8)
+ | (pMacAddr[0])
+ ;
+ pGmac->GMAC_SA[bIndex].GMAC_SAT = (pMacAddr[5] << 8)
+ | (pMacAddr[4])
+ ;
+}
+
+/**
+ * Set MAC Address via 2 DW
+ */
+void GMAC_SetAddress32(Gmac *pGmac, uint8_t bIndex, uint32_t dwMacT,
+ uint32_t dwMacB)
+{
+ pGmac->GMAC_SA[bIndex].GMAC_SAB = dwMacB;
+ pGmac->GMAC_SA[bIndex].GMAC_SAT = dwMacT;
+}
+
+/**
+ * Set MAC Address via int64
+ */
+void GMAC_SetAddress64(Gmac *pGmac, uint8_t bIndex, uint64_t ddwMac)
+{
+ pGmac->GMAC_SA[bIndex].GMAC_SAB = (uint32_t)ddwMac;
+ pGmac->GMAC_SA[bIndex].GMAC_SAT = (uint32_t)(ddwMac > 32);
+}
+
+
+/**
+ * Clear all statistics registers
+ */
+void GMAC_ClearStatistics(Gmac *pGmac)
+{
+ pGmac->GMAC_NCR |= GMAC_NCR_CLRSTAT;
+}
+
+/**
+ * Increase all statistics registers
+ */
+void GMAC_IncreaseStatistics(Gmac *pGmac)
+{
+ pGmac->GMAC_NCR |= GMAC_NCR_INCSTAT;
+}
+
+/**
+ * Enable/Disable statistics registers writing.
+ */
+void GMAC_StatisticsWriteEnable(Gmac *pGmac, uint8_t bEnaDis)
+{
+ if (bEnaDis) pGmac->GMAC_NCR |= GMAC_NCR_WESTAT;
+ else pGmac->GMAC_NCR &= ~GMAC_NCR_WESTAT;
+}
+
+
+/**
+ * Setup network configuration register
+ */
+void GMAC_Configure(Gmac *pGmac, uint32_t dwCfg)
+{
+ pGmac->GMAC_NCFGR = dwCfg;
+}
+
+
+/**
+ * Setup DMA configuration register
+ */
+void GMAC_SetDMAConfig(Gmac *pGmac, uint32_t dwDmaCfg, gmacQueList_t queueIdx)
+{
+ if (!queueIdx)
+ pGmac->GMAC_DCFGR = dwDmaCfg;
+ else
+ pGmac->GMAC_RBSRPQ[queueIdx - 1] = dwDmaCfg;
+}
+
+/**
+ * Return DMA configuration register
+ */
+uint32_t GMAC_GetDMAConfig(Gmac *pGmac, gmacQueList_t queueIdx)
+{
+ if (!queueIdx)
+ return pGmac->GMAC_DCFGR;
+ else
+ return pGmac->GMAC_RBSRPQ[queueIdx - 1];;
+}
+
+/**
+ * Return network configuration.
+ */
+uint32_t GMAC_GetConfigure(Gmac *pGmac)
+{
+ return pGmac->GMAC_NCFGR;
+}
+
+
+/**
+ * Start transmission
+ */
+void GMAC_TransmissionStart(Gmac *pGmac)
+{
+ pGmac->GMAC_NCR |= GMAC_NCR_TSTART;
+}
+
+/**
+ * Halt transmission
+ */
+void GMAC_TransmissionHalt(Gmac *pGmac)
+{
+ pGmac->GMAC_NCR |= GMAC_NCR_THALT;
+}
+
+
+/* Screener Register configurations */
+void GMAC_ClearScreener1Reg (Gmac *pGmac, gmacQueList_t queueIdx)
+{
+ pGmac->GMAC_ST1RPQ[queueIdx] = 0u;
+}
+
+void GMAC_WriteScreener1Reg(Gmac *pGmac, gmacQueList_t queueIdx,
+ uint32_t regVal)
+{
+ pGmac->GMAC_ST1RPQ[queueIdx] = regVal;
+}
+
+void GMAC_ClearScreener2Reg (Gmac *pGmac, gmacQueList_t queueIdx)
+{
+ pGmac->GMAC_ST2RPQ[queueIdx] = 0u;
+}
+
+void GMAC_WriteScreener2Reg (Gmac *pGmac, gmacQueList_t queueIdx,
+ uint32_t regVal)
+{
+ pGmac->GMAC_ST2RPQ[queueIdx] = regVal;
+}
+
+void GMAC_WriteEthTypeReg (Gmac *pGmac, gmacQueList_t queueIdx,
+ uint16_t etherType)
+{
+ pGmac->GMAC_ST2ER[queueIdx] = (uint32_t)etherType;
+}
+
+void GMAC_WriteCompareReg(Gmac *pGmac, gmacQueList_t queueIdx, uint32_t c0Reg,
+ uint16_t c1Reg)
+{
+ pGmac->GMAC_ST2COMP[queueIdx].GMAC_ST2COM0 = c0Reg;
+ pGmac->GMAC_ST2COMP[queueIdx].GMAC_ST2COM1 = (uint32_t)c1Reg;
+ memory_barrier();
+}
+
+/* CBS queue control APIs */
+void GMAC_EnableCbsQueA(Gmac *pGmac)
+{
+ pGmac->GMAC_CBSCR |= GMAC_CBSCR_QAE;
+}
+
+void GMAC_DisableCbsQueA(Gmac *pGmac)
+{
+ pGmac->GMAC_CBSCR &= ~GMAC_CBSCR_QAE;
+}
+
+void GMAC_EnableCbsQueB(Gmac *pGmac)
+{
+ pGmac->GMAC_CBSCR |= GMAC_CBSCR_QBE;
+}
+
+void GMAC_DisableCbsQueB(Gmac *pGmac)
+{
+ pGmac->GMAC_CBSCR &= ~GMAC_CBSCR_QBE;
+}
+
+
+void GMAC_ConfigIdleSlopeA(Gmac *pGmac, uint32_t idleSlopeA)
+{
+ /* 10/100 speeds use a 4-bit interface */
+ pGmac->GMAC_CBSISQA = idleSlopeA > 2u;
+}
+
+void GMAC_ConfigIdleSlopeB(Gmac *pGmac, uint32_t idleSlopeB)
+{
+ /* 10/100 speeds use a 4-bit interface */
+ pGmac->GMAC_CBSISQB = idleSlopeB > 2u;
+}
+
+void GMAC_SetTsuTmrIncReg(Gmac *pGmac, uint32_t nanoSec)
+{
+ pGmac->GMAC_TI = nanoSec;
+}
+
+uint16_t GMAC_GetPtpEvtMsgRxdMsbSec(Gmac *pGmac)
+{
+ return (uint16_t)(pGmac->GMAC_EFRSH & GMAC_EFRSH_RUD_Msk);
+}
+
+uint32_t GMAC_GetPtpEvtMsgRxdLsbSec(Gmac *pGmac)
+{
+ return (pGmac->GMAC_EFRSL & GMAC_EFRSL_RUD_Msk);
+}
+
+uint32_t GMAC_GetPtpEvtMsgRxdNanoSec(Gmac *pGmac)
+{
+ return (pGmac->GMAC_EFRN & GMAC_EFRN_RUD_Msk);
+}
+
+void GMAC_SetTsuCompare(Gmac *pGmac, uint32_t seconds47, uint32_t seconds31,
+ uint32_t nanosec)
+{
+ pGmac->GMAC_SCH = seconds47;
+ pGmac->GMAC_SCL = seconds31;
+ pGmac->GMAC_NSC = nanosec;
+ memory_barrier();
+}
+
+
+void GMAC_SetTsuCompareNanoSec(Gmac *pGmac, uint32_t nanosec)
+{
+ pGmac->GMAC_NSC = nanosec;
+}
+
+void GMAC_SetTsuCompareSec31(Gmac *pGmac, uint32_t seconds31)
+{
+ pGmac->GMAC_SCL = seconds31;
+}
+
+void GMAC_SetTsuCompareSec47(Gmac *pGmac, uint16_t seconds47)
+{
+ pGmac->GMAC_SCH = seconds47;
+}
+
+
+uint32_t GMAC_GetRxEvtFrameSec(Gmac *pGmac)
+{
+ return pGmac->GMAC_EFRSL;
+}
+
+uint32_t GMAC_GetRxEvtFrameNsec(Gmac *pGmac)
+{
+ return pGmac->GMAC_EFRN;
+}
+
+uint32_t GMAC_GetRxPeerEvtFrameSec(Gmac *pGmac)
+{
+ return pGmac->GMAC_PEFRSL;
+}
+
+uint32_t GMAC_GetRxPeerEvtFrameNsec(Gmac *pGmac)
+{
+ return pGmac->GMAC_PEFRN;
+}
+
+uint32_t GMAC_GetTxEvtFrameSec(Gmac *pGmac)
+{
+ return pGmac->GMAC_EFTSL;
+}
+
+uint32_t GMAC_GetTxEvtFrameNsec(Gmac *pGmac)
+{
+ return pGmac->GMAC_EFTN;
+}
+
+uint32_t GMAC_GetTxPeerEvtFrameSec(Gmac *pGmac)
+{
+ return pGmac->GMAC_PEFTSL;
+}
+
+uint32_t GMAC_GetTxPeerEvtFrameNsec(Gmac *pGmac)
+{
+ return pGmac->GMAC_PEFTN;
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/gmacd.c b/bsps/arm/atsam/contrib/libraries/libchip/source/gmacd.c
new file mode 100644
index 0000000000..850996813b
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/gmacd.c
@@ -0,0 +1,1054 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+ /** \file */
+
+/*---------------------------------------------------------------------------
+ * Headers
+ *---------------------------------------------------------------------------*/
+
+#include "chip.h"
+#include <string.h>
+
+/** \addtogroup gmacd_defines
+ @{*/
+
+
+/** ISO/IEC 14882:2003(E) - 5.6 Multiplicative operators:
+ * The binary / operator yields the quotient, and the binary % operator yields
+ * the remainder from the division of the first expression by the second.
+ * If the second operand of / or % is zero the behaviour is undefined; otherwise
+ * (a/b)*b + a%b is equal to a.
+ * If both operands are non-negative then the remainder is non-negative;
+ * if not, the sign of the remainder is implementation-defined 74).
+ */
+__STATIC_INLINE int fixed_mod(int a, int b)
+{
+ int rem = a % b;
+
+ while (rem < 0)
+ rem += b;
+
+ return rem;
+}
+
+/** Return count in buffer */
+#define GCIRC_CNT(head,tail,size) fixed_mod((head) - (tail), (size))
+
+/** Return space available, 0..size-1. always leave one free char as a
+ completely full buffer has head == tail, which is the same as empty */
+#define GCIRC_SPACE(head,tail,size) GCIRC_CNT((tail),((head)+1),(size))
+
+/** Return count up to the end of the buffer. Carefully avoid accessing head
+ and tail more than once, so they can change underneath us without returning
+ inconsistent results */
+#define GCIRC_CNT_TO_END(head,tail,size) \
+ ({int end = (size) - (tail); \
+ int n = fixed_mod((head) + end, (size)); \
+ n < end ? n : end;})
+
+/** Return space available up to the end of the buffer */
+#define GCIRC_SPACE_TO_END(head,tail,size) \
+ ({int end = (size) - 1 - (head); \
+ int n = fixed_mod(end + (tail), (size)); \
+ n <= end ? n : end+1;})
+
+/** Increment head or tail */
+#define GCIRC_INC(headortail,size) \
+ headortail++; \
+ if (headortail >= size) { \
+ headortail = 0; \
+ }
+
+/** Circular buffer is empty ? */
+#define GCIRC_EMPTY(head, tail) (head == tail)
+
+/** Clear circular buffer */
+#define GCIRC_CLEAR(head, tail) (head = tail = 0)
+
+/* This variable holds the write index into gPtpMsgTxQue */
+uint8_t ptpTxQueWriteIdx = 0u;
+uint8_t ptpTxQueReadIdx = 0u;
+
+/* This queue holds the transmit event messages */
+ptpMsgType gPtpMsgTxQue[EFRS_BUFFER_LEN];
+uint16_t gPtpMsgTxSeqId[EFRS_BUFFER_LEN];
+
+
+
+const uint32_t isrMasks[] = { GMAC_IMR_SFT, GMAC_IMR_DRQFT,
+ GMAC_IMR_PDRQFT , GMAC_IMR_PDRSFT
+ };
+
+/*---------------------------------------------------------------------------
+ * Local functions
+ *---------------------------------------------------------------------------*/
+
+/**
+ * \brief Disable TX & reset registers and descriptor list
+ * \param pDrv Pointer to GMAC Driver instance.
+ */
+static void GMACD_ResetTx(sGmacd *pDrv, gmacQueList_t queIdx)
+{
+ Gmac *pHw = pDrv->pHw;
+ uint8_t *pTxBuffer = pDrv->queueList[queIdx].pTxBuffer;
+ sGmacTxDescriptor *pTd = pDrv->queueList[queIdx].pTxD;
+ uint32_t Index;
+ uint32_t Address;
+
+ /* Disable TX */
+ GMAC_TransmitEnable(pHw, 0);
+
+ /* Setup the TX descriptors. */
+ GCIRC_CLEAR(pDrv->queueList[queIdx].wTxHead, pDrv->queueList[queIdx].wTxTail);
+
+ for (Index = 0; Index < pDrv->queueList[queIdx].wTxListSize; Index++) {
+ Address = (uint32_t)(&(pTxBuffer[Index *
+ pDrv->queueList[queIdx].wTxBufferSize]));
+ pTd[Index].addr = Address;
+ pTd[Index].status.val = (uint32_t)GMAC_TX_USED_BIT;
+ }
+
+ pTd[pDrv->queueList[queIdx].wTxListSize - 1].status.val =
+ GMAC_TX_USED_BIT | GMAC_TX_WRAP_BIT;
+
+ /* Transmit Buffer Queue Pointer Register */
+
+ GMAC_SetTxQueue(pHw, (uint32_t)pTd, queIdx);
+}
+
+/**
+ * \brief Disable RX & reset registers and descriptor list
+ * \param pDrv Pointer to GMAC Driver instance.
+ */
+static void GMACD_ResetRx(sGmacd *pDrv, gmacQueList_t queIdx)
+{
+ Gmac *pHw = pDrv->pHw;
+ uint8_t *pRxBuffer = pDrv->queueList[queIdx].pRxBuffer;
+ sGmacRxDescriptor *pRd = pDrv->queueList[queIdx].pRxD;
+
+ uint32_t Index;
+ uint32_t Address;
+
+ /* Disable RX */
+ GMAC_ReceiveEnable(pHw, 0);
+
+ /* Setup the RX descriptors. */
+ pDrv->queueList[queIdx].wRxI = 0;
+
+ for (Index = 0; Index < pDrv->queueList[queIdx].wRxListSize; Index++) {
+ Address = (uint32_t)(&(pRxBuffer[Index *
+ pDrv->queueList[queIdx].wRxBufferSize]));
+ /* Remove GMAC_RXD_bmOWNERSHIP and GMAC_RXD_bmWRAP */
+ pRd[Index].addr.val = Address & GMAC_ADDRESS_MASK;
+ pRd[Index].status.val = 0;
+ }
+
+ pRd[pDrv->queueList[queIdx].wRxListSize - 1].addr.val |= GMAC_RX_WRAP_BIT;
+
+ /* Receive Buffer Queue Pointer Register */
+ GMAC_SetRxQueue(pHw, (uint32_t)pRd, queIdx);
+}
+
+
+/**
+ * \brief Process successfully sent packets
+ * \param pGmacd Pointer to GMAC Driver instance.
+ */
+static void GMACD_TxCompleteHandler(sGmacd *pGmacd, gmacQueList_t qId)
+{
+ Gmac *pHw = pGmacd->pHw;
+ sGmacTxDescriptor *pTxTd;
+ fGmacdTransferCallback fTxCb;
+ uint32_t tsr;
+
+ /* Clear status */
+ tsr = GMAC_GetTxStatus(pHw);
+ GMAC_ClearTxStatus(pHw, tsr);
+
+ while (!GCIRC_EMPTY(
+ pGmacd->queueList[qId].wTxHead, pGmacd->queueList[qId].wTxTail)) {
+ pTxTd = &pGmacd->queueList[qId].pTxD[pGmacd->queueList[qId].wTxTail];
+
+ /* Exit if frame has not been sent yet:
+ * On TX completion, the GMAC set the USED bit only into the
+ * very first buffer descriptor of the sent frame.
+ * Otherwise it updates this descriptor with status error bits.
+ * This is the descriptor write back.
+ */
+ if ((pTxTd->status.val & GMAC_TX_USED_BIT) == 0)
+ break;
+
+ /* Process all buffers of the current transmitted frame */
+ while ((pTxTd->status.val & GMAC_TX_LAST_BUFFER_BIT) == 0) {
+ GCIRC_INC(pGmacd->queueList[qId].wTxTail,
+ pGmacd->queueList[qId].wTxListSize);
+ pTxTd = &pGmacd->queueList[qId].pTxD[pGmacd->queueList[qId].wTxTail];
+ memory_sync();
+ }
+
+ /* Notify upper layer that a frame has been sent */
+ fTxCb = pGmacd->queueList[qId].fTxCbList[pGmacd->queueList[qId].wTxTail];
+
+ if (fTxCb)
+ fTxCb(tsr);
+
+ /* Go to next frame */
+ GCIRC_INC(pGmacd->queueList[qId].wTxTail, pGmacd->queueList[qId].wTxListSize);
+ }
+
+ /* If a wakeup has been scheduled, notify upper layer that it can
+ send other packets, send will be successful. */
+ if (pGmacd->queueList[qId].fWakupCb &&
+ GCIRC_SPACE(pGmacd->queueList[qId].wTxHead,
+ pGmacd->queueList[qId].wTxTail,
+ pGmacd->queueList[qId].wTxListSize) >=
+ pGmacd->queueList[qId].bWakeupThreshold)
+ pGmacd->queueList[qId].fWakupCb();
+}
+
+
+/**
+ * \brief Reset TX queue when errors are detected
+ * \param pGmacd Pointer to GMAC Driver instance.
+ */
+static void GMACD_TxErrorHandler(sGmacd *pGmacd, gmacQueList_t qId)
+{
+ Gmac *pHw = pGmacd->pHw;
+ sGmacTxDescriptor *pTxTd;
+ fGmacdTransferCallback fTxCb;
+ uint32_t tsr;
+
+ /* Clear TXEN bit into the Network Configuration Register:
+ * this is a workaround to recover from TX lockups that
+ * occur on sama5d3 gmac (r1p24f2) when using scatter-gather.
+ * This issue has never been seen on sama5d4 gmac (r1p31).
+ */
+ GMAC_TransmitEnable(pHw, 0);
+
+ /* The following step should be optional since this function is called
+ * directly by the IRQ handler. Indeed, according to Cadence
+ * documentation, the transmission is halted on errors such as
+ * too many retries or transmit under run.
+ * However it would become mandatory if the call of this function
+ * were scheduled as a task by the IRQ handler (this is how Linux
+ * driver works). Then this function might compete with GMACD_Send().
+ *
+ * Setting bit 10, tx_halt, of the Network Control Register is not enough:
+ * We should wait for bit 3, tx_go, of the Transmit Status Register to
+ * be cleared at transmit completion if a frame is being transmitted.
+ */
+ GMAC_TransmissionHalt(pHw);
+
+ while (GMAC_GetTxStatus(pHw) & GMAC_TSR_TXGO);
+
+ /* Treat frames in TX queue including the ones that caused the error. */
+ while (!GCIRC_EMPTY(pGmacd->queueList[qId].wTxHead,
+ pGmacd->queueList[qId].wTxTail)) {
+ int tx_completed = 0;
+ pTxTd = &pGmacd->queueList[qId].pTxD[pGmacd->queueList[qId].wTxTail];
+
+ /* Check USED bit on the very first buffer descriptor to validate
+ * TX completion.
+ */
+ if (pTxTd->status.val & GMAC_TX_USED_BIT)
+ tx_completed = 1;
+
+ /* Go to the last buffer descriptor of the frame */
+ while ((pTxTd->status.val & GMAC_TX_LAST_BUFFER_BIT) == 0) {
+ GCIRC_INC(pGmacd->queueList[qId].wTxTail,
+ pGmacd->queueList[qId].wTxListSize);
+ pTxTd = &pGmacd->queueList[qId].pTxD[pGmacd->queueList[qId].wTxTail];
+ }
+
+ /* Notify upper layer that a frame status */
+ fTxCb = pGmacd->queueList[qId].fTxCbList[pGmacd->queueList[qId].wTxTail];
+
+ if (fTxCb)
+ fTxCb(tx_completed ? GMAC_TSR_TXCOMP : 0);
+
+ // TODO: which error to notify?
+
+ /* Go to next frame */
+ GCIRC_INC(pGmacd->queueList[qId].wTxTail, pGmacd->queueList[qId].wTxListSize);
+ }
+
+ /* Reset TX queue */
+ GMACD_ResetTx(pGmacd, qId);
+
+ /* Clear status */
+ tsr = GMAC_GetTxStatus(pHw);
+ GMAC_ClearTxStatus(pHw, tsr);
+
+ /* Now we are ready to start transmission again */
+ GMAC_TransmitEnable(pHw, 1);
+
+ if (pGmacd->queueList[qId].fWakupCb)
+ pGmacd->queueList[qId].fWakupCb();
+}
+
+
+/*---------------------------------------------------------------------------
+ * Exported functions
+ *---------------------------------------------------------------------------*/
+
+
+#ifndef PTP_1588_TX_DISABLE
+
+void GMACD_TxPtpEvtMsgCBRegister (sGmacd *pGmacd,
+ fGmacdTxPtpEvtCallBack pTxPtpEvtCb, gmacQueList_t queIdx)
+{
+ pGmacd->queueList[queIdx].fTxPtpEvtCb = pTxPtpEvtCb;
+}
+
+#endif /* #ifdef PTP_1588_TX_DISABLE */
+
+/**
+ * \brief GMAC Interrupt handler
+ * \param pGmacd Pointer to GMAC Driver instance.
+ */
+void GMACD_Handler(sGmacd *pGmacd, gmacQueList_t queIdx)
+{
+ Gmac *pHw = pGmacd->pHw;
+ uint32_t isr;
+ uint32_t rsr;
+
+ /* Interrupt Status Register is cleared on read */
+ while ((isr = GMAC_GetItStatus(pHw, queIdx)) != 0) {
+ /* Sync Frame Received - PTP */
+ if (0u != (isr & GMAC_ISR_SFR)) {
+ rsr = GMAC_ISR_SFR;
+ memory_barrier();
+
+ /* Invoke callbacks */
+ if (pGmacd->queueList[queIdx].fRxCb)
+ pGmacd->queueList[queIdx].fRxCb(rsr);
+ else {
+ }
+ } else {
+ }
+
+ /* Peer Delay Request Frame Received - PTP */
+ if (0u != (isr & GMAC_ISR_PDRQFR)) {
+ rsr = GMAC_ISR_PDRQFR;
+ memory_barrier();
+
+ /* Invoke callbacks */
+ if (pGmacd->queueList[queIdx].fRxCb)
+ pGmacd->queueList[queIdx].fRxCb(rsr);
+ else {
+ }
+ } else {
+ }
+
+ /* Peer Delay Response Frame Received - PTP */
+ if (0u != (isr & GMAC_ISR_PDRSFR)) {
+
+ rsr = GMAC_ISR_PDRSFR;
+ memory_barrier();
+
+ /* Invoke callbacks */
+ if (pGmacd->queueList[queIdx].fRxCb)
+ pGmacd->queueList[queIdx].fRxCb(rsr);
+ else {
+ }
+ } else {
+ }
+
+ if (0u != (isr & GMAC_ISR_TSU)) {
+ /* Invoke call back with flag set to TSU comparison interrupt */
+ rsr = GMAC_ISR_TSU;
+ memory_barrier();
+
+ /* Invoke callbacks */
+ if (pGmacd->queueList[queIdx].fRxCb)
+ pGmacd->queueList[queIdx].fRxCb(rsr);
+ else {
+ }
+ } else {
+ }
+
+ /* RX packet */
+ if (isr & GMAC_INT_RX_STATUS_BITS) {
+ /* Clear status */
+ rsr = GMAC_GetRxStatus(pHw);
+ GMAC_ClearRxStatus(pHw, rsr);
+
+ /* Invoke callback */
+ if (pGmacd->queueList[queIdx].fRxCb)
+ pGmacd->queueList[queIdx].fRxCb(rsr);
+ }
+
+ /* TX error */
+ if (isr & GMAC_INT_TX_STATUS_ERR_BITS) {
+ GMACD_TxErrorHandler(pGmacd, queIdx);
+ break;
+ }
+
+#ifndef PTP_1588_TX_DISABLE
+
+ /* Transmit of SYNC / PDELAY_REQ / PDELAY_RSP */
+ if (0u != (isr & isrMasks[gPtpMsgTxQue[ptpTxQueReadIdx]])) {
+ /* Invoke callback */
+ /* Check if it is possible for multiple messages to be triggered
+ within a single isr. If so, a loop may be needed to validate the top
+ of the queue with the actual interrupt that has been triggered */
+ /* while (0u != (isr & (GMAC_IMR_SFT | GMAC_IMR_PDRQFT | GMAC_IMR_PDRSFT))) { */
+ if (pGmacd->queueList[queIdx].fTxPtpEvtCb) {
+ switch (gPtpMsgTxQue[ptpTxQueReadIdx]) {
+ case SYNC_MSG_TYPE:
+ pGmacd->queueList[queIdx].fTxPtpEvtCb
+ (gPtpMsgTxQue[ptpTxQueReadIdx],
+ GMAC_GetTxEvtFrameSec(pHw),
+ GMAC_GetTxEvtFrameNsec(pHw),
+ gPtpMsgTxSeqId[ptpTxQueReadIdx]);
+ isr &= GMAC_IMR_SFT;
+ break;
+
+ case PDELAY_REQ_TYPE:
+ pGmacd->queueList[queIdx].fTxPtpEvtCb
+ (gPtpMsgTxQue[ptpTxQueReadIdx],
+ GMAC_GetTxPeerEvtFrameSec(pHw),
+ GMAC_GetTxPeerEvtFrameNsec(pHw),
+ gPtpMsgTxSeqId[ptpTxQueReadIdx]);
+ isr &= GMAC_IMR_PDRQFT;
+ break;
+
+ case PDELAY_RESP_TYPE:
+ pGmacd->queueList[queIdx].fTxPtpEvtCb
+ (gPtpMsgTxQue[ptpTxQueReadIdx],
+ GMAC_GetTxPeerEvtFrameSec(pHw),
+ GMAC_GetTxPeerEvtFrameNsec(pHw),
+ gPtpMsgTxSeqId[ptpTxQueReadIdx]);
+ isr &= GMAC_IMR_PDRSFT;
+ break;
+
+ default:
+ /* Only for Peer messages & sync messages */
+ break;
+ };
+ } else {
+ }
+
+ ptpTxQueReadIdx++;
+ ptpTxQueReadIdx &= (EFRS_BUFFER_LEN - 1);
+
+ } else {
+ /* if (0u != (isr & isrMasks[gPtpMsgTxQue[ptpTxQueReadIdx]])) */
+ }
+
+#endif /* #ifndef PTP_1588_TX_DISABLE */
+
+ /* TX packet */
+ if (isr & GMAC_IER_TCOMP)
+ GMACD_TxCompleteHandler(pGmacd, queIdx);
+
+ if (isr & GMAC_IER_HRESP)
+ TRACE_ERROR("HRESP\n\r");
+ }
+}
+
+
+/**
+ * \brief Initialize the GMAC with the Gmac controller address
+ * \param pGmacd Pointer to GMAC Driver instance.
+ * \param pHw Pointer to HW address for registers.
+ * \param bID HW ID for power management
+ * \param enableCAF Enable/Disable CopyAllFrame.
+ * \param enableNBC Enable/Disable NoBroadCast.
+ */
+void GMACD_Init(sGmacd *pGmacd,
+ Gmac *pHw,
+ uint8_t bID,
+ uint8_t enableCAF,
+ uint8_t enableNBC)
+{
+ uint32_t dwNcfgr;
+
+ /* Check parameters */
+ // assert(GRX_BUFFERS * GMAC_RX_UNITSIZE > GMAC_FRAME_LENTGH_MAX);
+
+ TRACE_DEBUG("GMAC_Init\n\r");
+
+ /* Initialize struct */
+ pGmacd->pHw = pHw;
+ pGmacd->bId = bID;
+
+ /* Power ON */
+ PMC_EnablePeripheral(bID);
+
+ /* Disable TX & RX and more */
+ GMAC_NetworkControl(pHw, 0);
+ GMAC_DisableAllQueueIt(pHw, ~0u);
+
+ GMAC_ClearStatistics(pHw);
+ /* Clear all status bits in the receive status register. */
+ GMAC_ClearRxStatus(pHw, GMAC_RSR_RXOVR | GMAC_RSR_REC
+ | GMAC_RSR_BNA | GMAC_RSR_HNO);
+
+ /* Clear all status bits in the transmit status register */
+ GMAC_ClearTxStatus(pHw, GMAC_TSR_UBR | GMAC_TSR_COL | GMAC_TSR_RLE
+ | GMAC_TSR_TXGO | GMAC_TSR_TFC | GMAC_TSR_TXCOMP
+ | GMAC_TSR_HRESP);
+
+ /* Clear All interrupts */
+ GMAC_GetItStatus(pHw, GMAC_QUE_0);
+ GMAC_GetItStatus(pHw, GMAC_QUE_1);
+ GMAC_GetItStatus(pHw, GMAC_QUE_2);
+
+ /* Enable the copy of data into the buffers
+ ignore broadcasts, and don't copy FCS. */
+ dwNcfgr = GMAC_NCFGR_FD | GMAC_NCFGR_DBW(0) | GMAC_NCFGR_CLK_MCK_64 |
+ GMAC_NCFGR_MAXFS | GMAC_NCFGR_PEN | GMAC_NCFGR_RFCS;
+
+ if (enableCAF)
+ dwNcfgr |= GMAC_NCFGR_CAF;
+
+ if (enableNBC)
+ dwNcfgr |= GMAC_NCFGR_NBC;
+
+ GMAC_Configure(pHw, dwNcfgr);
+}
+
+
+/**
+ * Initialize necessary allocated buffer lists for GMAC Driver to transfer data.
+ * Must be invoked after GMACD_Init() but before RX/TX start.
+ * Replace the deprecated GMACD_InitTransfer().
+ * \param pGmacd Pointer to GMAC Driver instance.
+ * \param pInit Pointer to sGmacInit.
+ * \param pInit Pointer to gmacQueList_t for different queue.
+ * \return GMACD_OK or GMACD_PARAM.
+ * \note If input address is not 8-byte aligned the address is automatically
+ * adjusted and the list size is reduced by one.
+ */
+uint8_t GMACD_InitTransfer(sGmacd *pGmacd, const sGmacInit *pInit,
+ gmacQueList_t queIdx)
+{
+ Gmac *pHw = pGmacd->pHw;
+ uint8_t *pRxBuffer = pInit->pRxBuffer;
+ sGmacRxDescriptor *pRxD = pInit->pRxD;
+ uint16_t wRxBufferSize = pInit->wRxBufferSize;
+ uint16_t wRxSize = pInit->wRxSize;
+ uint8_t *pTxBuffer = pInit->pTxBuffer;
+ sGmacTxDescriptor *pTxD = pInit->pTxD;
+ uint16_t wTxBufferSize = pInit->wTxBufferSize;
+ uint16_t wTxSize = pInit->wTxSize;
+ fGmacdTransferCallback *pTxCb = pInit->pTxCb;
+ uint32_t dwDmaCfg;
+
+ if (wRxSize <= 1 || wTxSize <= 1 || pTxCb == NULL) return GMACD_PARAM;
+
+ if (!wRxBufferSize || wRxBufferSize > 16 * 1024 || wRxBufferSize & 0x3f)
+ return GMACD_PARAM;
+
+ if (!wTxBufferSize)
+ return GMACD_PARAM;
+
+ if (pInit->bIsGem) {
+ if (!queIdx) {
+ dwDmaCfg = (GMAC_DCFGR_DRBS(wRxBufferSize >> 6))
+ | GMAC_DCFGR_RXBMS(3) | GMAC_DCFGR_TXPBMS;
+
+ switch (pInit->bDmaBurstLength) {
+ case 16:
+ dwDmaCfg |= GMAC_DCFGR_FBLDO_INCR16;
+ break;
+
+ case 8:
+ dwDmaCfg |= GMAC_DCFGR_FBLDO_INCR8;
+ break;
+
+ case 4:
+ dwDmaCfg |= GMAC_DCFGR_FBLDO_INCR4;
+ break;
+
+ case 1:
+ dwDmaCfg |= GMAC_DCFGR_FBLDO_SINGLE;
+ break;
+
+ default:
+ return GMACD_PARAM;
+ }
+ } else
+ dwDmaCfg = (GMAC_RBSRPQ_RBS(wRxBufferSize >> 6));
+
+ GMAC_SetDMAConfig(pHw, dwDmaCfg, queIdx);
+ }
+
+ pGmacd->queueList[queIdx].wRxBufferSize = wRxBufferSize;
+ pGmacd->queueList[queIdx].wTxBufferSize = wTxBufferSize;
+
+ /* Assign RX buffers */
+ if (((uint32_t)pRxBuffer & 0x7)
+ || ((uint32_t)pRxD & 0x7)) {
+ wRxSize --;
+ TRACE_DEBUG("RX list address adjusted\n\r");
+ }
+
+ pGmacd->queueList[queIdx].pRxBuffer = (uint8_t *)((uint32_t)pRxBuffer &
+ 0xFFFFFFF8);
+ pGmacd->queueList[queIdx].pRxD = (sGmacRxDescriptor *)((
+ uint32_t)pRxD & 0xFFFFFFF8);
+ pGmacd->queueList[queIdx].wRxListSize = wRxSize;
+
+ /* Assign TX buffers */
+ if (((uint32_t)pTxBuffer & 0x7)
+ || ((uint32_t)pTxD & 0x7)) {
+ wTxSize --;
+ TRACE_DEBUG("TX list address adjusted\n\r");
+ }
+
+ pGmacd->queueList[queIdx].pTxBuffer = (uint8_t *)((uint32_t)pTxBuffer &
+ 0xFFFFFFF8);
+ pGmacd->queueList[queIdx].pTxD = (sGmacTxDescriptor *)((
+ uint32_t)pTxD & 0xFFFFFFF8);
+ pGmacd->queueList[queIdx].wTxListSize = wTxSize;
+ pGmacd->queueList[queIdx].fTxCbList = pTxCb;
+
+ /* Reset TX & RX */
+ GMACD_ResetRx(pGmacd, queIdx);
+ GMACD_ResetTx(pGmacd, queIdx);
+
+ /* Setup the interrupts for RX/TX completion (and errors) */
+ switch (queIdx) {
+ case GMAC_QUE_0:
+ /* YBP: Que 0 should be configured last so as to enable transmit and
+ Receive in the NCR register */
+
+ /* Enable Rx and Tx, plus the status register. */
+ GMAC_TransmitEnable(pHw, 1);
+ GMAC_ReceiveEnable(pHw, 1);
+ GMAC_StatisticsWriteEnable(pHw, 1);
+
+ GMAC_EnableIt(pHw,
+ GMAC_INT_RX_BITS |
+ GMAC_INT_TX_BITS |
+ GMAC_INT_TX_ERR_BITS, GMAC_QUE_0);
+ break;
+
+ case GMAC_QUE_1:
+ GMAC_EnableIt(pHw,
+ GMAC_INT_RX_BITS |
+ GMAC_INT_TX_BITS |
+ GMAC_INT_TX_ERR_BITS, GMAC_QUE_1);
+ break;
+
+ case GMAC_QUE_2:
+ GMAC_EnableIt(pHw,
+ GMAC_INT_RX_BITS |
+ GMAC_INT_TX_BITS |
+ GMAC_INT_TX_ERR_BITS, GMAC_QUE_2);
+ break;
+ };
+
+ return GMACD_OK;
+}
+
+
+/**
+ * Reset TX & RX queue & statistics
+ * \param pGmacd Pointer to GMAC Driver instance.
+ */
+void GMACD_Reset(sGmacd *pGmacd)
+{
+ Gmac *pHw = pGmacd->pHw;
+
+ GMACD_ResetRx(pGmacd, GMAC_QUE_0);
+ GMACD_ResetRx(pGmacd, GMAC_QUE_1);
+ GMACD_ResetRx(pGmacd, GMAC_QUE_2);
+
+ GMACD_ResetTx(pGmacd, GMAC_QUE_0);
+ GMACD_ResetTx(pGmacd, GMAC_QUE_1);
+ GMACD_ResetTx(pGmacd, GMAC_QUE_2);
+
+ //memset((void*)&GmacStatistics, 0x00, sizeof(GmacStats));
+ GMAC_NetworkControl(pHw, GMAC_NCR_TXEN | GMAC_NCR_RXEN
+ | GMAC_NCR_WESTAT | GMAC_NCR_CLRSTAT);
+}
+
+/**
+ * \brief Send a frame split into buffers. If the frame size is larger than
+ * transfer buffer size error returned. If frame transfer status is monitored,
+ * specify callback for each frame.
+ * \param pGmacd Pointer to GMAC Driver instance.
+ * \param sgl Pointer to a scatter-gather list describing the buffers of the
+ * ethernet frame.
+ * \param fTxCb Pointer to callback function.
+ */
+uint8_t GMACD_SendSG(sGmacd *pGmacd,
+ const sGmacSGList *sgl,
+ fGmacdTransferCallback fTxCb,
+ gmacQueList_t queIdx)
+{
+ Gmac *pHw = pGmacd->pHw;
+ sGmacTxDescriptor *pTd = pGmacd->queueList[queIdx].pTxD;
+ sGmacTxDescriptor *pTxTd;
+ uint16_t wTxPos, wTxHead;
+ int i;
+
+ TRACE_DEBUG("%s\n\r", __FUNCTION__);
+
+ /* Check parameter */
+ if (!sgl->len) {
+ TRACE_ERROR("%s:: ethernet frame is empty.\r\n", __FUNCTION__);
+ return GMACD_PARAM;
+ }
+
+ if (sgl->len >= pGmacd->queueList[queIdx].wTxListSize) {
+ TRACE_ERROR("%s: ethernet frame has too many buffers.\r\n", __FUNCTION__);
+ return GMACD_PARAM;
+ }
+
+ /* Check available space */
+ if (GCIRC_SPACE(pGmacd->queueList[queIdx].wTxHead,
+ pGmacd->queueList[queIdx].wTxTail,
+ pGmacd->queueList[queIdx].wTxListSize) < (int)sgl->len)
+ return GMACD_TX_BUSY;
+
+ /* Tag end of TX queue */
+ wTxHead = fixed_mod(pGmacd->queueList[queIdx].wTxHead + sgl->len,
+ pGmacd->queueList[queIdx].wTxListSize);
+ wTxPos = wTxHead;
+ pGmacd->queueList[queIdx].fTxCbList[wTxPos] = NULL;
+ pTxTd = &pTd[wTxPos];
+ pTxTd->status.val = GMAC_TX_USED_BIT;
+
+ /* Update buffer descriptors in reverse order to avoid a race
+ * condition with hardware.
+ */
+ for (i = (int)(sgl->len - 1); i >= 0; --i) {
+ const sGmacSG *sg = &sgl->sg[i];
+ uint32_t status;
+
+ if (sg->size > pGmacd->queueList[queIdx].wTxBufferSize) {
+ TRACE_ERROR("%s: buffer size is too big.\r\n", __FUNCTION__);
+ return GMACD_PARAM;
+ }
+
+ if (wTxPos == 0)
+ wTxPos = pGmacd->queueList[queIdx].wTxListSize - 1;
+ else
+ wTxPos--;
+
+ /* Reset TX callback */
+ pGmacd->queueList[queIdx].fTxCbList[wTxPos] = NULL;
+
+ pTxTd = &pTd[wTxPos];
+#ifdef GMAC_ZERO_COPY
+ /** Update buffer descriptor address word:
+ * MUST be done before status word to avoid a race condition.
+ */
+ pTxTd->addr = (uint32_t)sg->pBuffer;
+
+#else
+
+ /* Copy data into transmission buffer */
+ if (sg->pBuffer && sg->size) {
+ memcpy((void *)pTxTd->addr, sg->pBuffer, sg->size);
+ SCB_CleanDCache_by_Addr((void *)pTxTd->addr, sg->size);
+ }
+
+#endif
+
+ /* Compute buffer descriptor status word */
+ status = sg->size & GMAC_LENGTH_FRAME;
+
+ if (i == (int)(sgl->len - 1)) {
+ status |= GMAC_TX_LAST_BUFFER_BIT;
+ pGmacd->queueList[queIdx].fTxCbList[wTxPos] = fTxCb;
+ }
+
+ if (wTxPos == pGmacd->queueList[queIdx].wTxListSize - 1)
+ status |= GMAC_TX_WRAP_BIT;
+
+ /* Update buffer descriptor status word: clear USED bit */
+ pTxTd->status.val = status;
+
+ memory_sync();
+ }
+
+ /* Update TX ring buffer pointers */
+ pGmacd->queueList[queIdx].wTxHead = wTxHead;
+ /* Now start to transmit if it is not already done */
+
+ GMAC_TransmissionStart(pHw);
+ return GMACD_OK;
+}
+
+/**
+ * \brief Send a packet with GMAC. If the packet size is larger than transfer
+ * buffer size error returned. If packet transfer status is monitored, specify
+ * callback for each packet.
+ * \param pGmacd Pointer to GMAC Driver instance.
+ * \param pBuffer The buffer to be send
+ * \param size The size of buffer to be send
+ * \param fTxCb Threshold Wakeup callback
+ * \return OK, Busy or invalid packet
+ */
+uint8_t GMACD_Send(sGmacd *pGmacd,
+ void *pBuffer,
+ uint32_t size,
+ fGmacdTransferCallback fTxCb,
+ gmacQueList_t queIdx)
+{
+ sGmacSGList sgl;
+ sGmacSG sg;
+
+ uint8_t *msgPtr;
+ ptpMsgType ptpMsg;
+ /* Init single entry scatter-gather list */
+ sg.size = size;
+ sg.pBuffer = pBuffer;
+ sgl.len = 1;
+ sgl.sg = &sg;
+
+
+
+#ifndef PTP_1588_TX_DISABLE
+
+ msgPtr = (uint8_t *)pBuffer;
+
+ if (0x88u == msgPtr[12] && 0xf7u == msgPtr[13]) {
+ /* Extract Tx PTP message type */
+ ptpMsg = (ptpMsgType)(msgPtr[14] & 0x0F);
+
+ if (ptpMsg == SYNC_MSG_TYPE || ptpMsg == PDELAY_REQ_TYPE
+ || ptpMsg == PDELAY_RESP_TYPE) {
+ /* Only add message to Tx queue of msg types that have
+ tx event ISRs enabled. */
+ gPtpMsgTxQue[ptpTxQueWriteIdx] = ptpMsg;
+
+ /* Copy the Sequence Id */
+ gPtpMsgTxSeqId[ptpTxQueWriteIdx] =
+ (uint16_t)(((uint16_t)msgPtr[44] << 8) | msgPtr[45]);
+ ptpTxQueWriteIdx++;
+ ptpTxQueWriteIdx &= (EFRS_BUFFER_LEN - 1u);
+ } else {
+ /* if (ptpMsg == SYNC_MSG_TYPE || ptpMsg == PDELAY_REQ_TYPE\
+ || ptpMsg == PDELAY_RESP_TYPE) { */
+ }
+ } else { /* if (0x88 == msgPtr[12] && 0xf7 == msgPtr[13]) { */
+ }
+
+#endif /* #ifndef PTP_1588_TX_DISABLE */
+ return GMACD_SendSG(pGmacd, &sgl, fTxCb, queIdx);
+}
+
+/**
+ * Return current load of TX.
+ * \param pGmacd Pointer to GMAC Driver instance.
+ */
+uint32_t GMACD_TxLoad(sGmacd *pGmacd, gmacQueList_t queIdx)
+{
+ uint16_t head = pGmacd->queueList[queIdx].wTxHead;
+ uint16_t tail = pGmacd->queueList[queIdx].wTxTail;
+ return GCIRC_CNT(head, tail, pGmacd->queueList[queIdx].wTxListSize);
+}
+
+/**
+ * \brief Receive a packet with GMAC.
+ * If not enough buffer for the packet, the remaining data is lost but right
+ * frame length is returned.
+ * \param pGmacd Pointer to GMAC Driver instance.
+ * \param pFrame Buffer to store the frame
+ * \param frameSize Size of the frame
+ * \param pRcvSize Received size
+ * \return OK, no data, or frame too small
+ */
+uint8_t GMACD_Poll(sGmacd *pGmacd,
+ uint8_t *pFrame,
+ uint32_t frameSize,
+ uint32_t *pRcvSize,
+ gmacQueList_t queIdx)
+{
+
+ uint16_t bufferLength;
+ uint32_t tmpFrameSize = 0;
+ uint8_t *pTmpFrame = 0;
+ uint32_t tmpIdx = pGmacd->queueList[queIdx].wRxI;
+ volatile sGmacRxDescriptor *pRxTd =
+ &pGmacd->queueList[queIdx].pRxD[pGmacd->queueList[queIdx].wRxI];
+
+ uint8_t isFrame = 0;
+
+ if (pFrame == NULL) return GMACD_PARAM;
+
+ /* Set the default return value */
+ *pRcvSize = 0;
+
+ /* Process received RxTd */
+ while ((pRxTd->addr.val & GMAC_RX_OWNERSHIP_BIT) == GMAC_RX_OWNERSHIP_BIT) {
+ /* A start of frame has been received, discard previous fragments */
+ if ((pRxTd->status.val & GMAC_RX_SOF_BIT) == GMAC_RX_SOF_BIT) {
+ /* Skip previous fragment */
+ while (tmpIdx != pGmacd->queueList[queIdx].wRxI) {
+ pRxTd =
+ &pGmacd->queueList[queIdx].pRxD[pGmacd->queueList[queIdx].wRxI];
+ pRxTd->addr.val &= ~(GMAC_RX_OWNERSHIP_BIT);
+ GCIRC_INC(pGmacd->queueList[queIdx].wRxI,
+ pGmacd->queueList[queIdx].wRxListSize);
+ }
+
+ pTmpFrame = pFrame;
+ tmpFrameSize = 0;
+ /* Start to gather buffers in a frame */
+ isFrame = 1;
+ }
+
+ /* Increment the pointer */
+ GCIRC_INC(tmpIdx, pGmacd->queueList[queIdx].wRxListSize);
+
+ /* Copy data in the frame buffer */
+ if (isFrame) {
+ if (tmpIdx == pGmacd->queueList[queIdx].wRxI) {
+ TRACE_INFO("no EOF (Invalid of buffers too small)\n\r");
+
+ do {
+ pRxTd =
+ &pGmacd->queueList[queIdx].pRxD[pGmacd->queueList[queIdx].wRxI];
+ pRxTd->addr.val &= ~(GMAC_RX_OWNERSHIP_BIT);
+ GCIRC_INC(pGmacd->queueList[queIdx].wRxI,
+ pGmacd->queueList[queIdx].wRxListSize);
+ } while (tmpIdx != pGmacd->queueList[queIdx].wRxI);
+
+ return GMACD_RX_NULL;
+ }
+
+ /* Copy the buffer into the application frame */
+ bufferLength = pGmacd->queueList[queIdx].wRxBufferSize;
+
+ if ((tmpFrameSize + bufferLength) > frameSize)
+ bufferLength = frameSize - tmpFrameSize;
+
+ SCB_InvalidateDCache_by_Addr((void *)(pRxTd->addr.val & GMAC_ADDRESS_MASK) ,
+ bufferLength);
+ memcpy(pTmpFrame, (void *)(pRxTd->addr.val & GMAC_ADDRESS_MASK),
+ bufferLength);
+ pTmpFrame += bufferLength;
+ tmpFrameSize += bufferLength;
+
+ /* An end of frame has been received, return the data */
+ if ((pRxTd->status.val & GMAC_RX_EOF_BIT) == GMAC_RX_EOF_BIT) {
+ /* Frame size from the GMAC */
+ *pRcvSize = (pRxTd->status.val & GMAC_LENGTH_FRAME);
+
+ /* Application frame buffer is too small all data have not been
+ copied */
+ if (tmpFrameSize < *pRcvSize)
+ return GMACD_SIZE_TOO_SMALL;
+
+ TRACE_DEBUG("packet %d-%d (%d)\n\r",
+ pGmacd->queueList[queIdx].wRxI, tmpIdx, *pRcvSize);
+
+ /* All data have been copied in the application frame buffer
+ => release TD */
+ while (pGmacd->queueList[queIdx].wRxI != tmpIdx) {
+ pRxTd =
+ &pGmacd->queueList[queIdx].pRxD[pGmacd->queueList[queIdx].wRxI];
+ pRxTd->addr.val &= ~(GMAC_RX_OWNERSHIP_BIT);
+ GCIRC_INC(pGmacd->queueList[queIdx].wRxI,
+ pGmacd->queueList[queIdx].wRxListSize);
+ }
+
+ return GMACD_OK;
+ }
+ } else {
+ /* SOF has not been detected, skip the fragment */
+ pRxTd->addr.val &= ~(GMAC_RX_OWNERSHIP_BIT);
+ pGmacd->queueList[queIdx].wRxI = tmpIdx;
+ }
+
+ /* Process the next buffer */
+ pRxTd = &pGmacd->queueList[queIdx].pRxD[tmpIdx];
+ }
+
+ return GMACD_RX_NULL;
+}
+
+/**
+ * \brief Registers pRxCb callback. Callback will be invoked after the next
+ * received frame. When GMAC_Poll() returns GMAC_RX_NO_DATA the application task
+ * call GMAC_Set_RxCb() to register pRxCb() callback and enters suspend state.
+ * The callback is in charge to resume the task once a new frame has been
+ * received. The next time GMAC_Poll() is called, it will be successful.
+ * \param pGmacd Pointer to GMAC Driver instance.
+ * \param fRxCb Pointer to callback function
+ * \return OK, no data, or frame too small
+ */
+
+void GMACD_SetRxCallback(sGmacd *pGmacd, fGmacdTransferCallback fRxCb,
+ gmacQueList_t queIdx)
+{
+ Gmac *pHw = pGmacd->pHw;
+
+ if (fRxCb == NULL) {
+ GMAC_DisableIt(pHw, GMAC_IDR_RCOMP, queIdx);
+ pGmacd->queueList[queIdx].fRxCb = NULL;
+ } else {
+ pGmacd->queueList[queIdx].fRxCb = fRxCb;
+ GMAC_EnableIt(pHw, GMAC_IER_RCOMP, queIdx);
+ }
+}
+
+/**
+ * Register/Clear TX wakeup callback.
+ *
+ * When GMACD_Send() returns GMACD_TX_BUSY (all TD busy) the application
+ * task calls GMACD_SetTxWakeupCallback() to register fWakeup() callback and
+ * enters suspend state. The callback is in charge to resume the task once
+ * several TD have been released. The next time GMACD_Send() will be called,
+ * it shall be successful.
+ *
+ * This function is usually invoked with NULL callback from the TX wakeup
+ * callback itself, to unregister. Once the callback has resumed the
+ * application task, there is no need to invoke the callback again.
+ *
+ * \param pGmacd Pointer to GMAC Driver instance.
+ * \param fWakeup Wakeup callback.
+ * \param bThreshold Number of free TD before wakeup callback invoked.
+ * \return GMACD_OK, GMACD_PARAM on parameter error.
+ */
+uint8_t GMACD_SetTxWakeupCallback(sGmacd *pGmacd,
+ fGmacdWakeupCallback fWakeup,
+ uint8_t bThreshold,
+ gmacQueList_t queIdx)
+{
+ if (fWakeup == NULL)
+ pGmacd->queueList[queIdx].fWakupCb = NULL;
+ else {
+ if (bThreshold <= pGmacd->queueList[queIdx].wTxListSize) {
+ pGmacd->queueList[queIdx].fWakupCb = fWakeup;
+ pGmacd->queueList[queIdx].bWakeupThreshold = bThreshold;
+ } else
+ return GMACD_PARAM;
+ }
+
+ return GMACD_OK;
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/hsmci.c b/bsps/arm/atsam/contrib/libraries/libchip/source/hsmci.c
new file mode 100644
index 0000000000..f6a88bacb4
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/hsmci.c
@@ -0,0 +1,569 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \file
+ *
+ * Implementation of High Speed MultiMedia Card Interface (HSMCI) controller.
+ */
+
+/*---------------------------------------------------------------------------
+ * Headers
+ *---------------------------------------------------------------------------*/
+
+#include "chip.h"
+#include <assert.h>
+
+/*---------------------------------------------------------------------------
+ * Exported functions
+ *---------------------------------------------------------------------------*/
+
+/** \addtogroup hsmci_functions
+ *@{
+ */
+
+/**
+ * \brief Enable Multi-Media Interface
+ *
+ * \param pRMci Pointer to a Hsmci instance
+ */
+extern void HSMCI_Enable(Hsmci *pRMci)
+{
+ pRMci->HSMCI_CR = HSMCI_CR_MCIEN;
+}
+
+/**
+ * \brief Disable Multi-Media Interface
+ *
+ * \param pRMci Pointer to a Hsmci instance
+ */
+extern void HSMCI_Disable(Hsmci *pRMci)
+{
+ pRMci->HSMCI_CR = HSMCI_CR_MCIDIS;
+
+}
+
+/**
+ * \brief Reset (& Disable) Multi-Media Interface
+ *
+ * \param mci Pointer to a Hsmci instance
+ * \param bBackup Backup registers values to keep previous settings, including
+ * _MR, _SDCR, _DTOR, _CSTOR, _DMA and _CFG.
+ */
+extern void HSMCI_Reset(Hsmci *pRMci, uint8_t bBackup)
+{
+ if (bBackup) {
+ uint32_t mr = pRMci->HSMCI_MR;
+ uint32_t dtor = pRMci->HSMCI_DTOR;
+ uint32_t sdcr = pRMci->HSMCI_SDCR;
+ uint32_t cstor = pRMci->HSMCI_CSTOR;
+ uint32_t dma = pRMci->HSMCI_DMA;
+ uint32_t cfg = pRMci->HSMCI_CFG;
+
+ pRMci->HSMCI_CR = HSMCI_CR_SWRST;
+
+ pRMci->HSMCI_MR = mr;
+ pRMci->HSMCI_DTOR = dtor;
+ pRMci->HSMCI_SDCR = sdcr;
+ pRMci->HSMCI_CSTOR = cstor;
+ pRMci->HSMCI_DMA = dma;
+ pRMci->HSMCI_CFG = cfg;
+ } else
+ pRMci->HSMCI_CR = HSMCI_CR_SWRST;
+}
+
+/**
+ * \brief Select slot
+ * \param pRMci Pointer to a Hsmci instance
+ * \param bSlot Slot ID (0~3 for A~D).
+ */
+extern void HSMCI_Select(Hsmci *pRMci, uint8_t bSlot, uint8_t bBusWidth)
+{
+ uint32_t dwSdcr;
+ dwSdcr = (HSMCI_SDCR_SDCSEL_Msk & bSlot);
+
+ switch (bBusWidth) {
+ case 1:
+ pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_1;
+ break;
+
+ case 4:
+ pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_4;
+ break;
+
+ case 8:
+ pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_8;
+ break;
+ }
+}
+
+/**
+ * \brief Set slot
+ * \param pRMci Pointer to a Hsmci instance
+ * \param bSlot Slot ID (0~3 for A~D).
+ */
+extern void HSMCI_SetSlot(Hsmci *pRMci, uint8_t bSlot)
+{
+ uint32_t dwSdcr = pRMci->HSMCI_SDCR & ~HSMCI_SDCR_SDCSEL_Msk;
+ pRMci->HSMCI_SDCR = dwSdcr | (HSMCI_SDCR_SDCSEL_Msk & bSlot);
+}
+
+/**
+ * \brief Set bus width of MCI
+ * \param pRMci Pointer to a Hsmci instance
+ * \param bBusWidth 1,4 or 8 (bits).
+ */
+extern void HSMCI_SetBusWidth(Hsmci *pRMci, uint8_t bBusWidth)
+{
+ uint32_t dwSdcr = pRMci->HSMCI_SDCR & ~HSMCI_SDCR_SDCBUS_Msk;
+
+ switch (bBusWidth) {
+ case 1:
+ pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_1;
+ break;
+
+ case 4:
+ pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_4;
+ break;
+
+ case 8:
+ pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_8;
+ break;
+ }
+}
+
+/**
+ * \brief Return bus width setting.
+ *
+ * \param pRMci Pointer to an MCI instance.
+ * \return 1, 4 or 8.
+ */
+extern uint8_t HSMCI_GetBusWidth(Hsmci *pRMci)
+{
+ switch (pRMci->HSMCI_SDCR & HSMCI_SDCR_SDCBUS_Msk) {
+ case HSMCI_SDCR_SDCBUS_1: return 1;
+
+ case HSMCI_SDCR_SDCBUS_4: return 4;
+
+ case HSMCI_SDCR_SDCBUS_8: return 8;
+ }
+
+ return 0;
+}
+
+/**
+ * \brief Configures a MCI peripheral as specified.
+ *
+ * \param pRMci Pointer to an MCI instance.
+ * \param dwMode Value of the MCI Mode register.
+ */
+extern void HSMCI_ConfigureMode(Hsmci *pRMci, uint32_t dwMode)
+{
+ pRMci->HSMCI_MR = dwMode;
+
+}
+
+/**
+ * \brief Return mode register
+ * \param pRMci Pointer to an MCI instance.
+ */
+extern uint32_t HSMCI_GetMode(Hsmci *pRMci)
+{
+ return pRMci->HSMCI_MR;
+}
+
+/**
+ * \brief Enable/Disable R/W proof
+ *
+ * \param pRMci Pointer to an MCI instance.
+ * \param bRdProof Read proof enable/disable.
+ * \param bWrProof Write proof enable/disable.
+ */
+extern void HSMCI_ProofEnable(Hsmci *pRMci, uint8_t bRdProof, uint8_t bWrProof)
+{
+ uint32_t mr = pRMci->HSMCI_MR;
+ pRMci->HSMCI_MR = (mr & (~(HSMCI_MR_WRPROOF | HSMCI_MR_RDPROOF)))
+ | (bRdProof ? HSMCI_MR_RDPROOF : 0)
+ | (bWrProof ? HSMCI_MR_WRPROOF : 0)
+ ;
+}
+
+/**
+ * \brief Padding value setting.
+ *
+ * \param pRMci Pointer to an MCI instance.
+ * \param bPadvEn Padding value 0xFF/0x00.
+ */
+extern void HSMCI_PadvCtl(Hsmci *pRMci, uint8_t bPadv)
+{
+ if (bPadv)
+ pRMci->HSMCI_MR |= HSMCI_MR_PADV;
+ else
+ pRMci->HSMCI_MR &= ~HSMCI_MR_PADV;
+}
+
+/**
+ * \brief Force byte transfer enable/disable.
+ *
+ * \param pRMci Pointer to an MCI instance.
+ * \param bFByteEn FBYTE enable/disable.
+ */
+extern void HSMCI_FByteEnable(Hsmci *pRMci, uint8_t bFByteEn)
+{
+ if (bFByteEn)
+ pRMci->HSMCI_MR |= HSMCI_MR_FBYTE;
+ else
+ pRMci->HSMCI_MR &= ~HSMCI_MR_FBYTE;
+}
+
+/**
+ * \brief Check if Force Byte mode enabled.
+ *
+ * \param pRMci Pointer to an MCI instance.
+ * \return 1 if _FBYTE is enabled.
+ */
+extern uint8_t HSMCI_IsFByteEnabled(Hsmci *pRMci)
+{
+ return ((pRMci->HSMCI_MR & HSMCI_MR_FBYTE) > 0);
+}
+
+/**
+ * \brief Set Clock Divider & Power save divider for MCI.
+ *
+ * \param pRMci Pointer to an MCI instance.
+ * \param bClkDiv Clock Divider value (0 ~ 255).
+ * \param bPwsDiv Power Saving Divider (1 ~ 7).
+ */
+extern void HSMCI_DivCtrl(Hsmci *pRMci, uint32_t bClkDiv, uint8_t bPwsDiv)
+{
+ uint32_t mr = pRMci->HSMCI_MR;
+ uint32_t clkdiv , clkodd;
+ clkdiv = bClkDiv - 2;
+ clkodd = (bClkDiv & 1) ? HSMCI_MR_CLKODD : 0;
+ clkdiv = clkdiv >> 1;
+
+ pRMci->HSMCI_MR = (mr & ~(HSMCI_MR_CLKDIV_Msk | HSMCI_MR_PWSDIV_Msk))
+ | HSMCI_MR_CLKDIV(clkdiv)
+ | HSMCI_MR_PWSDIV(bPwsDiv)
+ | clkodd
+ ;
+}
+
+/**
+ * \brief Enables one or more interrupt sources of MCI peripheral.
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \param sources Bitwise OR of selected interrupt sources.
+ */
+extern void HSMCI_EnableIt(Hsmci *pRMci, uint32_t dwSources)
+{
+ pRMci->HSMCI_IER = dwSources;
+}
+
+/**
+ * \brief Disable one or more interrupt sources of MCI peripheral.
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \param sources Bitwise OR of selected interrupt sources.
+ */
+extern void HSMCI_DisableIt(Hsmci *pRMci, uint32_t dwSources)
+{
+ pRMci->HSMCI_IDR = dwSources;
+}
+
+/**
+ * \brief Return the interrupt mask register.
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \return MCI interrupt mask register.
+ */
+extern uint32_t HSMCI_GetItMask(Hsmci *pRMci)
+{
+ return (pRMci->HSMCI_IMR);
+}
+
+/**
+ * \brief Set block len & count for transfer
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \param wBlkLen Block size.
+ * \param wCnt Block(byte) count.
+ */
+extern void HSMCI_ConfigureTransfer(Hsmci *pRMci,
+ uint16_t wBlkLen,
+ uint16_t wCnt)
+{
+ pRMci->HSMCI_BLKR = (wBlkLen << 16) | wCnt;
+}
+
+/**
+ * \brief Set block length
+ *
+ * Count is reset to 0.
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \param wBlkSize Block size.
+ */
+extern void HSMCI_SetBlockLen(Hsmci *pRMci, uint16_t wBlkSize)
+{
+ pRMci->HSMCI_BLKR = wBlkSize << 16;
+}
+
+/**
+ * \brief Set block (byte) count
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \param wBlkCnt Block(byte) count.
+ */
+extern void HSMCI_SetBlockCount(Hsmci *pRMci, uint16_t wBlkCnt)
+{
+ pRMci->HSMCI_BLKR |= wBlkCnt;
+}
+
+/**
+ * \brief Configure the Completion Signal Timeout
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \param dwConfigure Completion Signal Timeout configure.
+ */
+extern void HSMCI_ConfigureCompletionTO(Hsmci *pRMci, uint32_t dwConfigure)
+{
+ pRMci->HSMCI_CSTOR = dwConfigure;
+}
+
+/**
+ * \brief Configure the Data Timeout
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \param dwConfigure Data Timeout configure.
+ */
+extern void HSMCI_ConfigureDataTO(Hsmci *pRMci, uint32_t dwConfigure)
+{
+ pRMci->HSMCI_DTOR = dwConfigure;
+}
+
+/**
+ * \brief Send command
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \param dwCmd Command register value.
+ * \param dwArg Argument register value.
+ */
+extern void HSMCI_SendCmd(Hsmci *pRMci, uint32_t dwCmd, uint32_t dwArg)
+{
+ pRMci->HSMCI_ARGR = dwArg;
+ pRMci->HSMCI_CMDR = dwCmd;
+}
+
+
+/**
+ * \brief Return the response register.
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \return MCI response register.
+ */
+extern uint32_t HSMCI_GetResponse(Hsmci *pRMci)
+{
+ return pRMci->HSMCI_RSPR[0];
+}
+
+/**
+ * \brief Return the receive data register.
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \return MCI receive data register.
+ */
+extern uint32_t HSMCI_Read(Hsmci *pRMci)
+{
+ return pRMci->HSMCI_RDR;
+}
+
+/**
+ * \brief Read from FIFO
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \param pdwData Pointer to data buffer.
+ * \param dwSize Size of data buffer (in DWord).
+ */
+extern void HSMCI_ReadFifo(Hsmci *pRMci, uint8_t *pdwData, uint32_t dwSize)
+{
+ volatile uint32_t *pFIFO = (volatile uint32_t *)(pRMci->HSMCI_FIFO);
+ register uint32_t c4, c1;
+
+ if (dwSize == 0)
+ return;
+
+ c4 = dwSize >> 2;
+ c1 = dwSize & 0x3;
+
+ for (; c4; c4 --) {
+ *pdwData ++ = *pFIFO ++;
+ *pdwData ++ = *pFIFO ++;
+ *pdwData ++ = *pFIFO ++;
+ *pdwData ++ = *pFIFO ++;
+ }
+
+ for (; c1; c1 --)
+ *pdwData ++ = *pFIFO ++;
+}
+
+/**
+ * \brief Sends data through MCI peripheral.
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \param
+ */
+extern void HSMCI_Write(Hsmci *pRMci, uint32_t dwData)
+{
+ pRMci->HSMCI_TDR = dwData;
+}
+
+/**
+ * \brief Write to FIFO
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \param pdwData Pointer to data buffer.
+ * \param dwSize Size of data buffer (In DWord).
+ */
+extern void HSMCI_WriteFifo(Hsmci *pRMci, uint8_t *pdwData, uint32_t dwSize)
+{
+ volatile uint32_t *pFIFO = (volatile uint32_t *)(pRMci->HSMCI_FIFO);
+ register uint32_t c4, c1;
+
+ if (dwSize == 0)
+ return;
+
+ c4 = dwSize >> 2;
+ c1 = dwSize & 0x3;
+
+ for (; c4; c4 --) {
+ *pFIFO ++ = *pdwData ++;
+ *pFIFO ++ = *pdwData ++;
+ *pFIFO ++ = *pdwData ++;
+ *pFIFO ++ = *pdwData ++;
+ }
+
+ for (; c1; c1 --)
+ *pFIFO ++ = *pdwData ++;
+}
+
+/**
+ * \brief Return the status register.
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \return MCI status register.
+ */
+extern uint32_t HSMCI_GetStatus(Hsmci *pRMci)
+{
+ return pRMci->HSMCI_SR;
+}
+
+/**
+ * \brief Configure the HSMCI DMA
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \param dwConfigure Configure value.
+ */
+extern void HSMCI_ConfigureDma(Hsmci *pRMci, uint32_t dwConfigure)
+{
+ pRMci->HSMCI_DMA = dwConfigure;
+}
+
+/**
+ * \brief Enable the HSMCI DMA
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \param bEnable 1 to enable, 0 to disable.
+ */
+extern void HSMCI_EnableDma(Hsmci *pRMci, uint8_t bEnable)
+{
+ if (bEnable) {
+ pRMci->HSMCI_DMA |= HSMCI_DMA_DMAEN;//| HSMCI_DMA_CHKSIZE_32;
+ } else
+ pRMci->HSMCI_DMA &= ~HSMCI_DMA_DMAEN;
+}
+
+/**
+ * \brief Configure the HSMCI
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \param dwConfigure Configure value.
+ */
+extern void HSMCI_Configure(Hsmci *pRMci, uint32_t dwConfigure)
+{
+ pRMci->HSMCI_CFG = dwConfigure;
+}
+
+/**
+ * \brief Enable/Disable High-Speed mode for MCI
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \param bHsEnable Enable/Disable high-speed.
+ */
+extern void HSMCI_HsEnable(Hsmci *pRMci, uint8_t bHsEnable)
+{
+ if (bHsEnable)
+ pRMci->HSMCI_CFG |= HSMCI_CFG_HSMODE;
+ else
+ pRMci->HSMCI_CFG &= ~HSMCI_CFG_HSMODE;
+}
+
+/**
+ * \brief Check if High-speed mode is enabled on MCI
+ * \param pRMci Pointer to an Hsmci instance.
+ * \return 1
+ */
+extern uint8_t HSMCI_IsHsEnabled(Hsmci *pRMci)
+{
+ return ((pRMci->HSMCI_CFG & HSMCI_CFG_HSMODE) > 0);
+}
+
+/**
+ * \brief Configure the Write Protection Mode
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \param dwConfigure WP mode configure value.
+ */
+extern void HSMCI_ConfigureWP(Hsmci *pRMci, uint32_t dwConfigure)
+{
+ pRMci->HSMCI_WPMR = dwConfigure;
+}
+
+/**
+ * \brief Return the write protect status register.
+ *
+ * \param pRMci Pointer to an Hsmci instance.
+ * \return MCI write protect status register.
+ */
+extern uint32_t HSMCI_GetWPStatus(Hsmci *pRMci)
+{
+ return pRMci->HSMCI_WPSR;
+}
+
+/**@}*/
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/icm.c b/bsps/arm/atsam/contrib/libraries/libchip/source/icm.c
new file mode 100644
index 0000000000..ac61b95645
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/icm.c
@@ -0,0 +1,234 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup icm_module Working with ICM
+ * \ingroup peripherals_module
+ * The TWI driver provides the interface to True Random Number Generator (ICM)
+ * passes the American NIST Special Publication 800-22 and Die-hard
+ * Random Tests Suites.
+ * The ICM may be used as an entropy source for seeding an NIST approved DRNG
+ * (Deterministic RNG) as required by FIPS PUB 140-2 and 140-3. use the TWI
+ * peripheral.
+ *
+ * \section Usage
+ * <ul>
+ * <li> Configures a TWI peripheral to operate in master mode, at the given
+ * frequency (in Hz) using TWI_Configure(). </li>
+ * <li> Sends a STOP condition on the TWI using TWI_Stop().</li>
+ * <li> Starts a read operation on the TWI bus with the specified slave using
+ * TWI_StartRead(). Data must then be read using TWI_ReadByte() whenever
+ * a byte is available (poll using TWI_ByteReceived()).</li>
+ * <li> Starts a write operation on the TWI to access the selected slave using
+ * TWI_StartWrite(). A byte of data must be provided to start the write;
+ * other bytes are written next.</li>
+ * <li> Sends a byte of data to one of the TWI slaves on the bus using
+ * TWI_WriteByte().
+ * This function must be called once before TWI_StartWrite() with the first byte
+ * of data to send, then it ICMll be called repeatedly after that to send the
+ * remaining bytes.</li>
+ * <li> Check if a byte has been received and can be read on the given TWI
+ * peripheral using TWI_ByteReceived().<
+ * Check if a byte has been sent using TWI_ByteSent().</li>
+ * <li> Check if the current transmission is complete (the STOP has been sent)
+ * using TWI_TransferComplete().</li>
+ * <li> Enables & disable the selected interrupts sources on a TWI peripheral
+ * using TWI_EnableIt() and TWI_DisableIt().</li>
+ * <li> Get current status register of the given TWI peripheral using
+ * TWI_GetStatus(). Get current status register of the given TWI peripheral, but
+ * masking interrupt sources which are not currently enabled using
+ * TWI_GetMaskedStatus().</li>
+ * </ul>
+ * For more accurate information, please look at the TWI section of the
+ * Datasheet.
+ *
+ * Related files :\n
+ * \ref twi.c\n
+ * \ref twi.h.\n
+ */
+/*@{*/
+/*@}*/
+
+/**
+ * \file
+ *
+ * Implementation of True Random Number Generator (ICM)
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Enable ICM, the ICM controller is activated
+ */
+void ICM_Enable(void)
+{
+ ICM->ICM_CTRL = ICM_CTRL_ENABLE;
+}
+
+/**
+ * \brief Disable ICM, if a region is active, this region is terminated
+ */
+void ICM_Disable(void)
+{
+ ICM->ICM_CTRL = ICM_CTRL_DISABLE;
+}
+
+/**
+ * \brief Resets the ICM controller.
+ */
+void ICM_SoftReset(void)
+{
+ ICM->ICM_CTRL = ICM_CTRL_SWRST;
+}
+
+/**
+ * \brief Recompute Internal hash.
+ * \param region, When REHASH[region] is set to one, the region digest is
+ * re-computed.
+ * \note This bit is only available when Region monitoring is disabled.
+ */
+void ICM_ReComputeHash(uint8_t region)
+{
+ ICM->ICM_CTRL = ICM_CTRL_REHASH(region);
+}
+
+/**
+ * \brief Enable region monitoring for given region
+ * \param region, When bit RMEN[region] is set to one, the monitoring of Region
+ * is activated.
+ */
+void ICM_EnableMonitor(uint8_t region)
+{
+ ICM->ICM_CTRL = ICM_CTRL_RMEN(region);
+}
+
+/**
+ * \brief Disable region monitoring for given region
+ * \param region, When bit RMDIS[region] is set to one, the monitoring of
+ * Region is disabled.
+ */
+void ICM_DisableMonitor(uint8_t region)
+{
+ ICM->ICM_CTRL = ICM_CTRL_RMDIS(region);
+}
+
+/**
+ * \brief Configures an ICM peripheral with the specified parameters.
+ * \param mode Desired value for the ICM mode register (see the datasheet).
+ */
+void ICM_Configure(uint32_t mode)
+{
+ ICM->ICM_CFG = mode;
+}
+
+/**
+ * \brief Enables the selected interrupts sources on a ICM peripheral.
+ * \param sources Bitwise OR of selected interrupt sources.
+ */
+void ICM_EnableIt(uint32_t sources)
+{
+ ICM->ICM_IER = sources;
+}
+
+/**
+ * \brief Disables the selected interrupts sources on a ICM peripheral.
+ * \param sources Bitwise OR of selected interrupt sources.
+ */
+void ICM_DisableIt(uint32_t sources)
+{
+ ICM->ICM_IDR = sources;
+}
+
+/**
+ * \brief Get the current interrupt status register of the given ICM peripheral.
+ * \return ICM status register.
+ */
+uint32_t ICM_GetIntStatus(void)
+{
+ return ICM->ICM_ISR;
+}
+
+/**
+ * \brief Get the current status register of the given ICM peripheral.
+ * \return ICM status register.
+ */
+uint32_t ICM_GetStatus(void)
+{
+ return ICM->ICM_SR;
+}
+
+
+/**
+ * \brief Get the undefined access status register of the given ICM peripheral.
+ * \return ICM status register.
+ */
+uint32_t ICM_GetUStatus(void)
+{
+ return ICM->ICM_UASR;
+}
+
+/**
+ * \brief Set descriptor area start address register.
+ * \param addr start address
+ * \note The start address is a multiple of the total size of the data structure
+ * (64 bytes).
+ */
+void ICM_SetDescStartAddress(uint32_t addr)
+{
+ ICM->ICM_DSCR = addr;
+}
+
+/**
+ * \brief Set hash area start address register.
+ * \param addr start address
+ * \note This field points at the Hash memory location. The address must be a
+ * multiple of 128 bytes.
+ */
+void ICM_SetHashStartAddress(uint32_t addr)
+{
+ ICM->ICM_HASH = addr;
+}
+
+/**
+ * \brief Set ICM user initial Hash value register.
+ * \param val Initial Hash Value
+ */
+void ICM_SetInitHashValue(uint32_t val)
+{
+ ICM->ICM_UIHVAL[0] = ICM_UIHVAL_VAL(val);
+}
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/isi.c b/bsps/arm/atsam/contrib/libraries/libchip/source/isi.c
new file mode 100644
index 0000000000..52aed9772c
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/isi.c
@@ -0,0 +1,385 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+/*----------------------------------------------------------------------------
+ * Local functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Workaround for ISI CFG2 register read.
+ * \note The ISI_CFG2[31:27] can be written correctly, because the input writing
+ * data are assigned directly to the internal control bits as specified,
+ * the mismatch only happens in reading operation.
+ * [31:28] are shift right 1 bit, so [31:27] can be read from [30:27].
+ */
+__STATIC_INLINE uint32_t _ISI_GetCFG2_Workaround(void)
+{
+ uint32_t wrongfield;
+ wrongfield = ISI->ISI_CFG2 >> (ISI_CFG2_YCC_SWAP_Pos - 1);
+ return (ISI->ISI_CFG2 & 0x07FFFFFF) | (wrongfield << ISI_CFG2_YCC_SWAP_Pos);
+}
+
+/*----------------------------------------------------------------------------
+ * Export functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Enable ISI
+ */
+void ISI_Enable(void)
+{
+ ISI->ISI_CR |= ISI_CR_ISI_EN;
+
+ while ((ISI->ISI_SR & ISI_CR_ISI_EN) != ISI_CR_ISI_EN);
+}
+
+/**
+ * \brief Enable ISI Dma channel
+ * \param channel to be enabled
+ */
+void ISI_DmaChannelEnable(uint32_t channel)
+{
+ ISI->ISI_DMA_CHER |= channel;
+}
+
+/**
+ * \brief Disable ISI Dma channel
+ * \param channel to be disabled
+ */
+void ISI_DmaChannelDisable(uint32_t channel)
+{
+ ISI->ISI_DMA_CHDR |= channel;
+}
+
+/**
+ * \brief Disable ISI
+ */
+void ISI_Disable(void)
+{
+ /* Write one to this field to disable the module */
+ ISI->ISI_CR |= ISI_CR_ISI_DIS;
+
+ /* Software must poll DIS_DONE field in the ISI_STATUS register to verify that the command
+ has successfully completed.*/
+ while ((ISI->ISI_SR & ISI_SR_DIS_DONE) != ISI_SR_DIS_DONE);
+}
+
+
+/**
+ * \brief Enable ISI interrupt
+ * \param flag of interrupt to enable
+ */
+void ISI_EnableInterrupt(uint32_t flag)
+{
+ ISI->ISI_IER = flag;
+}
+
+/**
+ * \brief Disable ISI interrupt
+ * \param flag of interrupt to disable
+ */
+void ISI_DisableInterrupt(uint32_t flag)
+{
+ ISI->ISI_IDR = flag;
+}
+
+/**
+ * \brief Return ISI status register
+ * \return Status of ISI register
+ */
+uint32_t ISI_StatusRegister(void)
+{
+ return (ISI->ISI_SR);
+}
+
+/**
+ * \brief Enable Codec path for capture next frame
+ */
+void ISI_CodecPathFull(void)
+{
+ // The codec path is enabled and the next frame is captured.
+ // Both codec and preview data-paths are working simultaneously
+ ISI->ISI_CR |= ISI_CR_ISI_CDC;
+ ISI->ISI_CFG1 |= ISI_CFG1_FULL;
+}
+
+/**
+ * \brief Set frame rate
+ * \param frame frame rate capture
+ */
+void ISI_SetFrameRate(uint32_t frame)
+{
+ if (frame > 7) {
+ TRACE_ERROR("rate too big\n\r");
+ frame = 7;
+ }
+
+ ISI->ISI_CFG1 |= ISI_CFG1_FRATE(frame);
+}
+
+/**
+ * \brief Get the number of byte per pixels
+ * \param bmpRgb BMP type can be YUV or RGB
+ */
+uint8_t ISI_BytesForOnePixel(uint8_t bmpRgb)
+{
+ uint8_t nbByte_Pixel;
+
+ if (bmpRgb == RGB) {
+ if ((_ISI_GetCFG2_Workaround() & ISI_CFG2_RGB_MODE) == ISI_CFG2_RGB_MODE) {
+ // RGB: 5:6:5 16bits/pixels
+ nbByte_Pixel = 2;
+ } else {
+ // RGB: 8:8:8 24bits/pixels
+ nbByte_Pixel = 3;
+ }
+ } else {
+ // YUV: 2 pixels for 4 bytes
+ nbByte_Pixel = 2;
+ }
+
+ return nbByte_Pixel;
+}
+
+/**
+ * \brief Reset ISI
+ */
+void ISI_Reset(void)
+{
+ uint32_t timeout = 0;
+
+ // Resets the image sensor interface.
+ // Finish capturing the current frame and then shut down the module.
+ ISI->ISI_CR = ISI_CR_ISI_SRST | ISI_CR_ISI_DIS;
+
+ // wait Software reset has completed successfully.
+ while ((!(ISI->ISI_SR & ISI_SR_SRST))
+ && (timeout < 0x5000))
+ timeout++;
+
+ if (timeout == 0x5000)
+ TRACE_ERROR("ISI-Reset timeout\n\r");
+}
+
+
+/**
+ * \brief Set the windows blank
+ * \param hBlank pixel clock periods to wait before the beginning of a line.
+ * \param vBlank lines are skipped at the beginning of the frame.
+ */
+void ISI_SetBlank(uint8_t hBlank, uint8_t vBlank)
+{
+ ISI->ISI_CFG1 |= ISI_CFG1_SLD(hBlank) + ISI_CFG1_SFD(vBlank);
+}
+
+
+/**
+ * \brief Set vertical and horizontal Size of the Image Sensor
+ * \param hSize Horizontal size of the Image sensor [0..2047].
+ * \param vSize Vertical size of the Image sensor [0..2047].
+ */
+void ISI_SetSensorSize(uint32_t hSize, uint32_t vSize)
+{
+ uint32_t val;
+ val = _ISI_GetCFG2_Workaround();
+ val &= (~ISI_CFG2_IM_VSIZE_Msk);
+ val &= (~ISI_CFG2_IM_HSIZE_Msk);
+ // IM_VSIZE: Vertical size of the Image sensor [0..2047]
+ // Vertical size = IM_VSIZE + 1
+ // IM_HSIZE: Horizontal size of the Image sensor [0..2047]
+ // Horizontal size = IM_HSIZE + 1
+ ISI->ISI_CFG2 &= (~ISI_CFG2_IM_VSIZE_Msk);
+ ISI->ISI_CFG2 &= (~ISI_CFG2_IM_HSIZE_Msk);
+ ISI->ISI_CFG2 = val | ISI_CFG2_IM_VSIZE(vSize - 1) | ISI_CFG2_IM_HSIZE(
+ hSize - 1);
+}
+
+/**
+ * \brief Defines RGB pattern when RGB_MODE is set to 1.
+ * \param wRgbPixelMapping RGB pattern
+ */
+void ISI_RgbPixelMapping(uint32_t wRgbPixelMapping)
+{
+ ISI->ISI_CFG2 = _ISI_GetCFG2_Workaround() & (~ISI_CFG2_RGB_CFG_Msk);
+
+ if (wRgbPixelMapping != ISI_CFG2_RGB_CFG_DEFAULT)
+ ISI->ISI_CFG2 = _ISI_GetCFG2_Workaround() | wRgbPixelMapping
+ | ISI_CFG2_RGB_MODE;
+ else
+ ISI->ISI_CFG2 = _ISI_GetCFG2_Workaround();
+}
+
+/**
+ * \brief Enables RGB swap
+ * \param swapMode 0: D7-R7, 1: D0-R7
+ */
+void ISI_RgbSwapMode(uint32_t swapMode)
+{
+ ISI->ISI_CFG2 = _ISI_GetCFG2_Workaround() & (~ISI_CFG2_RGB_SWAP);
+
+ if (swapMode) ISI->ISI_CFG2 = _ISI_GetCFG2_Workaround() | ISI_CFG2_RGB_SWAP;
+}
+
+/**
+ * \brief Defines YCrCb swap format.
+ * \param wYuvSwapMode YUV Swap format
+ */
+void ISI_YCrCbFormat(uint32_t wYuvSwapMode)
+{
+ ISI->ISI_CFG2 = _ISI_GetCFG2_Workaround() & (~ISI_CFG2_YCC_SWAP_Msk);
+ ISI->ISI_CFG2 = _ISI_GetCFG2_Workaround() | wYuvSwapMode;
+}
+
+/**
+ * \brief Input image is assumed to be grayscale-coded.
+ * \param wPixelFormat 0: 2 pixels per word, 1:1 pixel per word.
+ */
+void ISI_setGrayScaleMode(uint32_t wPixelFormat)
+{
+ ISI->ISI_CFG2 = _ISI_GetCFG2_Workaround() | ISI_CFG2_GRAYSCALE;
+
+ if (wPixelFormat) ISI->ISI_CFG2 = _ISI_GetCFG2_Workaround() | ISI_CFG2_GS_MODE;
+
+}
+
+/**
+ * \brief Set data stream format.
+ * \param wStreamMode 0: YUV input, 1: RGB 8:8:8/5:6:5 input
+ */
+void ISI_setInputStream(uint32_t wStreamMode)
+{
+ ISI->ISI_CFG2 = _ISI_GetCFG2_Workaround() & (~ISI_CFG2_COL_SPACE);
+
+ if (wStreamMode) ISI->ISI_CFG2 = _ISI_GetCFG2_Workaround() | ISI_CFG2_COL_SPACE;
+}
+
+/**
+ * \brief Set preview size.
+ * \param hSize Horizontal Preview size (640 max only in RGB mode).
+ * \param vSize Vertical Preview size (480 max only in RGB mode).
+ */
+void ISI_setPreviewSize(uint32_t hSize, uint32_t vSize)
+{
+ if (hSize > 640) hSize = 640;
+
+ if (vSize > 480) vSize = 480;
+
+ ISI->ISI_PSIZE = ISI_PSIZE_PREV_VSIZE(vSize - 1) | ISI_PSIZE_PREV_HSIZE(
+ hSize - 1);
+}
+
+/**
+ * \brief calculate scaler factor automatically.
+ * \note The sensor size and preview size for LCD was configured before this setting.
+ */
+void ISI_calcScalerFactor(void)
+{
+ uint32_t hLcdSize, hSensorSize;
+ uint32_t hRatio;
+ hLcdSize = ((ISI->ISI_PSIZE & ISI_PSIZE_PREV_HSIZE_Msk) >>
+ ISI_PSIZE_PREV_HSIZE_Pos) + 1;
+ hSensorSize = ((_ISI_GetCFG2_Workaround() & ISI_CFG2_IM_HSIZE_Msk)
+ >> ISI_CFG2_IM_HSIZE_Pos) + 1;
+ hRatio = 1600 * hSensorSize / hLcdSize;
+ ISI->ISI_PDECF = (hRatio / 100);
+}
+
+/**
+ * \brief Configure DMA for preview path.
+ * \param baseFrameBufDesc Preview Descriptor Address.
+ * \param dmaCtrl DMA Preview Control.
+ * \param frameBufferStartAddr DMA Preview Base Address.
+ */
+void ISI_setDmaInPreviewPath(uint32_t baseFrameBufDesc,
+ uint32_t dmaCtrl, uint32_t frameBufferStartAddr)
+{
+ ISI->ISI_DMA_P_DSCR = baseFrameBufDesc;
+ ISI->ISI_DMA_P_CTRL = dmaCtrl;
+ ISI->ISI_DMA_P_ADDR = frameBufferStartAddr;
+}
+
+/**
+ * \brief Configure DMA for Codec path.
+ * \param baseFrameBufDesc Preview Descriptor Address.
+ * \param dmaCtrl DMA Preview Control.
+ * \param frameBufferStartAddr DMA Preview Base Address.
+ */
+void ISI_setDmaInCodecPath(uint32_t baseFrameBufDesc,
+ uint32_t dmaCtrl, uint32_t frameBufferStartAddr)
+{
+ ISI->ISI_DMA_C_DSCR = baseFrameBufDesc;
+ ISI->ISI_DMA_C_CTRL = dmaCtrl;
+ ISI->ISI_DMA_C_ADDR = frameBufferStartAddr;
+}
+
+/**
+ * \brief ISI set matrix for YUV to RGB color space for preview path.
+ * \param yuv2rgb structure of YUV to RBG parameters.
+ */
+void ISI_SetMatrix4Yuv2Rgb (ISI_Y2R *yuv2rgb)
+{
+ ISI->ISI_Y2R_SET0 = ISI_Y2R_SET0_C0(yuv2rgb->C0)
+ | ISI_Y2R_SET0_C1(yuv2rgb->C1)
+ | ISI_Y2R_SET0_C2(yuv2rgb->C2)
+ | ISI_Y2R_SET0_C3(yuv2rgb->C3);
+
+ ISI->ISI_Y2R_SET1 = ISI_Y2R_SET1_C4(yuv2rgb->C4)
+ | ((yuv2rgb->Yoff == 1) ? ISI_Y2R_SET1_Yoff : 0)
+ | ((yuv2rgb->Croff == 1) ? ISI_Y2R_SET1_Croff : 0)
+ | ((yuv2rgb->Cboff == 1) ? ISI_Y2R_SET1_Cboff : 0);
+}
+
+/**
+ * \brief ISI set matrix for RGB to YUV color space for codec path.
+ * \param rgb2yuv structure of RGB to YUV parameters.
+ */
+void ISI_SetMatrix4Rgb2Yuv (ISI_R2Y *rgb2yuv)
+{
+ ISI->ISI_R2Y_SET0 = ISI_R2Y_SET0_C0(rgb2yuv->C0)
+ | ISI_R2Y_SET0_C1(rgb2yuv->C1)
+ | ISI_R2Y_SET0_C2(rgb2yuv->C2)
+ | ((rgb2yuv->Roff == 1) ? ISI_R2Y_SET0_Roff : 0);
+
+ ISI->ISI_R2Y_SET1 = ISI_R2Y_SET1_C3(rgb2yuv->C3)
+ | ISI_R2Y_SET1_C4(rgb2yuv->C4)
+ | ISI_R2Y_SET1_C5(rgb2yuv->C5)
+ | ((rgb2yuv->Goff == 1) ? ISI_R2Y_SET1_Goff : 0);
+
+ ISI->ISI_R2Y_SET2 = ISI_R2Y_SET2_C6(rgb2yuv->C6)
+ | ISI_R2Y_SET2_C7(rgb2yuv->C7)
+ | ISI_R2Y_SET2_C8(rgb2yuv->C8)
+ | ((rgb2yuv->Boff == 1) ? ISI_R2Y_SET2_Boff : 0);
+}
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/mcan.c b/bsps/arm/atsam/contrib/libraries/libchip/source/mcan.c
new file mode 100644
index 0000000000..e91f73e871
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/mcan.c
@@ -0,0 +1,1175 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \file
+ * Implements functions for Controller Area Network (CAN)
+ * peripheral operations.
+ */
+/** \addtogroup can_module
+ *@{*/
+
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+#ifndef __rtems__
+#include "board.h"
+#endif /* __rtems__ */
+#include "chip.h"
+#include "mcan_config.h"
+#include <assert.h>
+/*---------------------------------------------------------------------------
+ * Definitions
+ *---------------------------------------------------------------------------*/
+#define MAILBOX_ADDRESS(address) (0xFFFC & (address))
+
+#define CAN_CLK_FREQ_HZ MCAN_PROG_CLK_FREQ_HZ
+
+#define MCAN0_TSEG1 (MCAN0_PROP_SEG + MCAN0_PHASE_SEG1)
+#define MCAN0_TSEG2 (MCAN0_PHASE_SEG2)
+#define MCAN0_BRP ((uint32_t) (((float) CAN_CLK_FREQ_HZ / \
+ ((float)(MCAN0_TSEG1 + MCAN0_TSEG2 + 3) *\
+ (float) MCAN0_BIT_RATE_BPS)) - 1))
+#define MCAN0_SJW (MCAN0_SYNC_JUMP - 1)
+#define MCAN0_FTSEG1 (MCAN0_FAST_PROP_SEG + MCAN0_FAST_PHASE_SEG1)
+#define MCAN0_FTSEG2 (MCAN0_FAST_PHASE_SEG2)
+#define MCAN0_FBRP ((uint32_t) (((float) CAN_CLK_FREQ_HZ / \
+ ((float)(MCAN0_FTSEG1 + MCAN0_FTSEG2 + 3) * \
+ (float) MCAN0_FAST_BIT_RATE_BPS)) - 1))
+#define MCAN0_FSJW (MCAN0_FAST_SYNC_JUMP - 1)
+
+#define MCAN0_STD_FLTS_WRDS (MCAN0_NMBR_STD_FLTS)
+/* 128 max filters */
+#define MCAN0_EXT_FLTS_WRDS (MCAN0_NMBR_EXT_FLTS * 2)
+/* 64 max filters */
+#define MCAN0_RX_FIFO0_WRDS (MCAN0_NMBR_RX_FIFO0_ELMTS * \
+ ((MCAN0_RX_FIFO0_ELMT_SZ/4) + 2))
+/* 64 elements max */
+#define MCAN0_RX_FIFO1_WRDS (MCAN0_NMBR_RX_FIFO1_ELMTS *\
+ ((MCAN0_RX_FIFO1_ELMT_SZ/4) + 2))
+/* 64 elements max */
+#define MCAN0_RX_DED_BUFS_WRDS (MCAN0_NMBR_RX_DED_BUF_ELMTS * \
+ ((MCAN0_RX_BUF_ELMT_SZ/4) + 2))
+/* 64 elements max */
+#define MCAN0_TX_EVT_FIFO_WRDS (MCAN0_NMBR_TX_EVT_FIFO_ELMTS * 2)
+/* 32 elements max */
+#define MCAN0_TX_DED_BUF_WRDS (MCAN0_NMBR_TX_DED_BUF_ELMTS * \
+ ((MCAN0_TX_BUF_ELMT_SZ/4) + 2))
+/* 32 elements max */
+#define MCAN0_TX_FIFO_Q_WRDS (MCAN0_NMBR_TX_FIFO_Q_ELMTS *\
+ ((MCAN0_TX_BUF_ELMT_SZ/4) + 2))
+/* 32 elements max */
+
+#define MCAN1_TSEG1 (MCAN1_PROP_SEG + MCAN1_PHASE_SEG1)
+#define MCAN1_TSEG2 (MCAN1_PHASE_SEG2)
+#define MCAN1_BRP ((uint32_t) (((float) CAN_CLK_FREQ_HZ / \
+ ((float)(MCAN1_TSEG1 + MCAN1_TSEG2 + 3) *\
+ (float) MCAN1_BIT_RATE_BPS)) - 1))
+#define MCAN1_SJW (MCAN1_SYNC_JUMP - 1)
+#define MCAN1_FTSEG1 (MCAN1_FAST_PROP_SEG + MCAN1_FAST_PHASE_SEG1)
+#define MCAN1_FTSEG2 (MCAN1_FAST_PHASE_SEG2)
+#define MCAN1_FBRP ((uint32_t) (((float) CAN_CLK_FREQ_HZ /\
+ ((float)(MCAN1_FTSEG1 + MCAN1_FTSEG2 + 3) *\
+ (float) MCAN1_FAST_BIT_RATE_BPS)) - 1))
+#define MCAN1_FSJW (MCAN1_FAST_SYNC_JUMP - 1)
+
+#define MCAN1_STD_FLTS_WRDS (MCAN1_NMBR_STD_FLTS)
+/* 128 max filters */
+#define MCAN1_EXT_FLTS_WRDS (MCAN1_NMBR_EXT_FLTS * 2)
+/* 64 max filters */
+#define MCAN1_RX_FIFO0_WRDS (MCAN1_NMBR_RX_FIFO0_ELMTS * \
+ ((MCAN1_RX_FIFO0_ELMT_SZ/4) + 2))
+/* 64 elements max */
+#define MCAN1_RX_FIFO1_WRDS (MCAN1_NMBR_RX_FIFO1_ELMTS *\
+ ((MCAN1_RX_FIFO1_ELMT_SZ/4) + 2))
+/* 64 elements max */
+#define MCAN1_RX_DED_BUFS_WRDS (MCAN1_NMBR_RX_DED_BUF_ELMTS * \
+ ((MCAN1_RX_BUF_ELMT_SZ/4) + 2))
+/* 64 elements max */
+#define MCAN1_TX_EVT_FIFO_WRDS (MCAN1_NMBR_TX_EVT_FIFO_ELMTS * 2)
+/* 32 elements max */
+#define MCAN1_TX_DED_BUF_WRDS (MCAN1_NMBR_TX_DED_BUF_ELMTS * \
+ ((MCAN1_TX_BUF_ELMT_SZ/4) + 2))
+/* 32 elements max */
+#define MCAN1_TX_FIFO_Q_WRDS (MCAN1_NMBR_TX_FIFO_Q_ELMTS * \
+ ((MCAN1_TX_BUF_ELMT_SZ/4) + 2))
+/* 32 elements max */
+
+/* validate CAN0 entries */
+#if (MCAN0_TSEG1 > 63)
+ #error "Invalid CAN0 TSEG1"
+#endif
+#if (MCAN0_TSEG2 > 15)
+ #error "Invalid CAN0 TSEG2"
+#endif
+#if (MCAN0_SJW > 15)
+ #error "Invalid CAN0 SJW"
+#endif
+#if (MCAN0_FTSEG1 > 15)
+ #error "Invalid CAN0 FTSEG1"
+#endif
+#if (MCAN0_FTSEG2 > 7)
+ #error "Invalid CAN0 FTSEG2"
+#endif
+#if (MCAN0_FSJW > 3)
+ #error "Invalid CAN0 FSJW"
+#endif
+
+#if (MCAN0_NMBR_STD_FLTS > 128)
+ #error "Invalid CAN0 # of Standard Filters"
+#endif
+#if (MCAN0_NMBR_EXT_FLTS > 64)
+ #error "Invalid CAN0 # of Extended Filters"
+#endif
+#if (MCAN0_NMBR_RX_FIFO0_ELMTS > 64)
+ #error "Invalid CAN0 # RX FIFO 0 ELEMENTS"
+#endif
+#if (MCAN0_NMBR_RX_FIFO1_ELMTS > 64)
+ #error "Invalid CAN0 # RX FIFO 0 ELEMENTS"
+#endif
+#if (MCAN0_NMBR_RX_DED_BUF_ELMTS > 64)
+ #error "Invalid CAN0 # RX BUFFER ELEMENTS"
+#endif
+#if (MCAN0_NMBR_TX_EVT_FIFO_ELMTS > 32)
+ #error "Invalid CAN0 # TX EVENT FIFO ELEMENTS"
+#endif
+#if ((MCAN0_NMBR_TX_DED_BUF_ELMTS + MCAN0_NMBR_TX_FIFO_Q_ELMTS) > 32)
+ #error "Invalid CAN0 # TX BUFFER ELEMENTS"
+#endif
+
+#if (8 == MCAN0_RX_FIFO0_ELMT_SZ)
+ #define MCAN0_RX_FIFO0_DATA_SIZE (0u)
+#elif (12 == MCAN0_RX_FIFO0_ELMT_SZ)
+ #define MCAN0_RX_FIFO0_DATA_SIZE (1u)
+#elif (16 == MCAN0_RX_FIFO0_ELMT_SZ)
+ #define MCAN0_RX_FIFO0_DATA_SIZE (2u)
+#elif (20 == MCAN0_RX_FIFO0_ELMT_SZ)
+ #define MCAN0_RX_FIFO0_DATA_SIZE (3u)
+#elif (24 == MCAN0_RX_FIFO0_ELMT_SZ)
+ #define MCAN0_RX_FIFO0_DATA_SIZE (4u)
+#elif (32 == MCAN0_RX_FIFO0_ELMT_SZ)
+ #define MCAN0_RX_FIFO0_DATA_SIZE (5u)
+#elif (48 == MCAN0_RX_FIFO0_ELMT_SZ)
+ #define MCAN0_RX_FIFO0_DATA_SIZE (6u)
+#elif (64 == MCAN0_RX_FIFO0_ELMT_SZ)
+ #define MCAN0_RX_FIFO0_DATA_SIZE (7u)
+#else
+ #error "Invalid CAN0 RX FIFO0 ELEMENT SIZE"
+#endif
+
+#if (8 == MCAN0_RX_FIFO1_ELMT_SZ)
+ #define MCAN0_RX_FIFO1_DATA_SIZE (0u)
+#elif (12 == MCAN0_RX_FIFO1_ELMT_SZ)
+ #define MCAN0_RX_FIFO1_DATA_SIZE (1u)
+#elif (16 == MCAN0_RX_FIFO1_ELMT_SZ)
+ #define MCAN0_RX_FIFO1_DATA_SIZE (2u)
+#elif (20 == MCAN0_RX_FIFO1_ELMT_SZ)
+ #define MCAN0_RX_FIFO1_DATA_SIZE (3u)
+#elif (24 == MCAN0_RX_FIFO1_ELMT_SZ)
+ #define MCAN0_RX_FIFO1_DATA_SIZE (4u)
+#elif (32 == MCAN0_RX_FIFO1_ELMT_SZ)
+ #define MCAN0_RX_FIFO1_DATA_SIZE (5u)
+#elif (48 == MCAN0_RX_FIFO1_ELMT_SZ)
+ #define MCAN0_RX_FIFO1_DATA_SIZE (6u)
+#elif (64 == MCAN0_RX_FIFO1_ELMT_SZ)
+ #define MCAN0_RX_FIFO1_DATA_SIZE (7u)
+#else
+ #error "Invalid CAN0 RX FIFO1 ELEMENT SIZE"
+#endif
+
+#if (8 == MCAN0_RX_BUF_ELMT_SZ)
+ #define MCAN0_RX_BUF_DATA_SIZE (0u)
+#elif (12 == MCAN0_RX_BUF_ELMT_SZ)
+ #define MCAN0_RX_BUF_DATA_SIZE (1u)
+#elif (16 == MCAN0_RX_BUF_ELMT_SZ)
+ #define MCAN0_RX_BUF_DATA_SIZE (2u)
+#elif (20 == MCAN0_RX_BUF_ELMT_SZ)
+ #define MCAN0_RX_BUF_DATA_SIZE (3u)
+#elif (24 == MCAN0_RX_BUF_ELMT_SZ)
+ #define MCAN0_RX_BUF_DATA_SIZE (4u)
+#elif (32 == MCAN0_RX_BUF_ELMT_SZ)
+ #define MCAN0_RX_BUF_DATA_SIZE (5u)
+#elif (48 == MCAN0_RX_BUF_ELMT_SZ)
+ #define MCAN0_RX_BUF_DATA_SIZE (6u)
+#elif (64 == MCAN0_RX_BUF_ELMT_SZ)
+ #define MCAN0_RX_BUF_DATA_SIZE (7u)
+#else
+ #error "Invalid CAN0 RX BUFFER ELEMENT SIZE"
+#endif
+
+#if (8 == MCAN0_TX_BUF_ELMT_SZ)
+ #define MCAN0_TX_BUF_DATA_SIZE (0u)
+#elif (12 == MCAN0_TX_BUF_ELMT_SZ)
+ #define MCAN0_TX_BUF_DATA_SIZE (1u)
+#elif (16 == MCAN0_TX_BUF_ELMT_SZ)
+ #define MCAN0_TX_BUF_DATA_SIZE (2u)
+#elif (20 == MCAN0_TX_BUF_ELMT_SZ)
+ #define MCAN0_TX_BUF_DATA_SIZE (3u)
+#elif (24 == MCAN0_TX_BUF_ELMT_SZ)
+ #define MCAN0_TX_BUF_DATA_SIZE (4u)
+#elif (32 == MCAN0_TX_BUF_ELMT_SZ)
+ #define MCAN0_TX_BUF_DATA_SIZE (5u)
+#elif (48 == MCAN0_TX_BUF_ELMT_SZ)
+ #define MCAN0_TX_BUF_DATA_SIZE (6u)
+#elif (64 == MCAN0_TX_BUF_ELMT_SZ)
+ #define MCAN0_TX_BUF_DATA_SIZE (7u)
+#else
+ #error "Invalid CAN0 TX BUFFER ELEMENT SIZE"
+#endif
+
+/* validate CAN1 entries */
+#if (MCAN1_TSEG1 > 63)
+ #error "Invalid CAN1 TSEG1"
+#endif
+#if (MCAN1_TSEG2 > 15)
+ #error "Invalid CAN1 TSEG2"
+#endif
+#if (MCAN1_SJW > 15)
+ #error "Invalid CAN1 SJW"
+#endif
+#if (MCAN1_FTSEG1 > 15)
+ #error "Invalid CAN1 FTSEG1"
+#endif
+#if (MCAN1_FTSEG2 > 7)
+ #error "Invalid CAN1 FTSEG2"
+#endif
+#if (MCAN1_FSJW > 3)
+ #error "Invalid CAN1 FSJW"
+#endif
+
+#if (MCAN1_NMBR_STD_FLTS > 128)
+ #error "Invalid CAN1 # of Standard Filters"
+#endif
+#if (MCAN1_NMBR_EXT_FLTS > 64)
+ #error "Invalid CAN1 # of Extended Filters"
+#endif
+#if (MCAN1_NMBR_RX_FIFO0_ELMTS > 64)
+ #error "Invalid CAN1 # RX FIFO 0 ELEMENTS"
+#endif
+#if (MCAN1_NMBR_RX_FIFO1_ELMTS > 64)
+ #error "Invalid CAN1 # RX FIFO 0 ELEMENTS"
+#endif
+#if (MCAN1_NMBR_RX_DED_BUF_ELMTS > 64)
+ #error "Invalid CAN1 # RX BUFFER ELEMENTS"
+#endif
+#if (MCAN1_NMBR_TX_EVT_FIFO_ELMTS > 32)
+ #error "Invalid CAN1 # TX EVENT FIFO ELEMENTS"
+#endif
+#if ((MCAN1_NMBR_TX_DED_BUF_ELMTS + MCAN1_NMBR_TX_FIFO_Q_ELMTS) > 32)
+ #error "Invalid CAN1 # TX BUFFER ELEMENTS"
+#endif
+
+#if (8 == MCAN1_RX_FIFO0_ELMT_SZ)
+ #define MCAN1_RX_FIFO0_DATA_SIZE (0u)
+#elif (12 == MCAN1_RX_FIFO0_ELMT_SZ)
+ #define MCAN1_RX_FIFO0_DATA_SIZE (1u)
+#elif (16 == MCAN1_RX_FIFO0_ELMT_SZ)
+ #define MCAN1_RX_FIFO0_DATA_SIZE (2u)
+#elif (20 == MCAN1_RX_FIFO0_ELMT_SZ)
+ #define MCAN1_RX_FIFO0_DATA_SIZE (3u)
+#elif (24 == MCAN1_RX_FIFO0_ELMT_SZ)
+ #define MCAN1_RX_FIFO0_DATA_SIZE (4u)
+#elif (32 == MCAN1_RX_FIFO0_ELMT_SZ)
+ #define MCAN1_RX_FIFO0_DATA_SIZE (5u)
+#elif (48 == MCAN1_RX_FIFO0_ELMT_SZ)
+ #define MCAN1_RX_FIFO0_DATA_SIZE (6u)
+#elif (64 == MCAN1_RX_FIFO0_ELMT_SZ)
+ #define MCAN1_RX_FIFO0_DATA_SIZE (7u)
+#else
+ #error "Invalid CAN1 RX FIFO0 ELEMENT SIZE"
+#endif
+
+#if (8 == MCAN1_RX_FIFO1_ELMT_SZ)
+ #define MCAN1_RX_FIFO1_DATA_SIZE (0u)
+#elif (12 == MCAN1_RX_FIFO1_ELMT_SZ)
+ #define MCAN1_RX_FIFO1_DATA_SIZE (1u)
+#elif (16 == MCAN1_RX_FIFO1_ELMT_SZ)
+ #define MCAN1_RX_FIFO1_DATA_SIZE (2u)
+#elif (20 == MCAN1_RX_FIFO1_ELMT_SZ)
+ #define MCAN1_RX_FIFO1_DATA_SIZE (3u)
+#elif (24 == MCAN1_RX_FIFO1_ELMT_SZ)
+ #define MCAN1_RX_FIFO1_DATA_SIZE (4u)
+#elif (32 == MCAN1_RX_FIFO1_ELMT_SZ)
+ #define MCAN1_RX_FIFO1_DATA_SIZE (5u)
+#elif (48 == MCAN1_RX_FIFO1_ELMT_SZ)
+ #define MCAN1_RX_FIFO1_DATA_SIZE (6u)
+#elif (64 == MCAN1_RX_FIFO1_ELMT_SZ)
+ #define MCAN1_RX_FIFO1_DATA_SIZE (7u)
+#else
+ #error "Invalid CAN1 RX FIFO1 ELEMENT SIZE"
+#endif
+
+#if (8 == MCAN1_RX_BUF_ELMT_SZ)
+ #define MCAN1_RX_BUF_DATA_SIZE (0u)
+#elif (12 == MCAN1_RX_BUF_ELMT_SZ)
+ #define MCAN1_RX_BUF_DATA_SIZE (1u)
+#elif (16 == MCAN1_RX_BUF_ELMT_SZ)
+ #define MCAN1_RX_BUF_DATA_SIZE (2u)
+#elif (20 == MCAN1_RX_BUF_ELMT_SZ)
+ #define MCAN1_RX_BUF_DATA_SIZE (3u)
+#elif (24 == MCAN1_RX_BUF_ELMT_SZ)
+ #define MCAN1_RX_BUF_DATA_SIZE (4u)
+#elif (32 == MCAN1_RX_BUF_ELMT_SZ)
+ #define MCAN1_RX_BUF_DATA_SIZE (5u)
+#elif (48 == MCAN1_RX_BUF_ELMT_SZ)
+ #define MCAN1_RX_BUF_DATA_SIZE (6u)
+#elif (64 == MCAN1_RX_BUF_ELMT_SZ)
+ #define MCAN1_RX_BUF_DATA_SIZE (7u)
+#else
+ #error "Invalid CAN1 RX BUFFER ELEMENT SIZE"
+#endif
+
+#if (8 == MCAN1_TX_BUF_ELMT_SZ)
+ #define MCAN1_TX_BUF_DATA_SIZE (0u)
+#elif (12 == MCAN1_TX_BUF_ELMT_SZ)
+ #define MCAN1_TX_BUF_DATA_SIZE (1u)
+#elif (16 == MCAN1_TX_BUF_ELMT_SZ)
+ #define MCAN1_TX_BUF_DATA_SIZE (2u)
+#elif (20 == MCAN1_TX_BUF_ELMT_SZ)
+ #define MCAN1_TX_BUF_DATA_SIZE (3u)
+#elif (24 == MCAN1_TX_BUF_ELMT_SZ)
+ #define MCAN1_TX_BUF_DATA_SIZE (4u)
+#elif (32 == MCAN1_TX_BUF_ELMT_SZ)
+ #define MCAN1_TX_BUF_DATA_SIZE (5u)
+#elif (48 == MCAN1_TX_BUF_ELMT_SZ)
+ #define MCAN1_TX_BUF_DATA_SIZE (6u)
+#elif (64 == MCAN1_TX_BUF_ELMT_SZ)
+ #define MCAN1_TX_BUF_DATA_SIZE (7u)
+#else
+ #error "Invalid CAN1 TX BUFFER ELEMENT SIZE"
+#endif
+
+#define CAN_11_BIT_ID_MASK (0x7FF)
+#define CAN_29_BIT_ID_MASK (0x1FFFFFFF)
+#define ELMT_SIZE_MASK (0x1F)
+/* max element size is 18 words, fits in 5 bits */
+
+#define BUFFER_XTD_MASK (0x40000000)
+#define BUFFER_EXT_ID_MASK (0x1FFFFFFF)
+#define BUFFER_STD_ID_MASK (0x1FFC0000)
+#define BUFFER_DLC_MASK (0x000F0000)
+#define BUFFER_RXTS_MASK (0x0000FFFF)
+
+#define STD_FILT_SFT_MASK (3U << 30)
+#define STD_FILT_SFT_RANGE (0U << 30)
+#define STD_FILT_SFT_DUAL (1U << 30)
+#define STD_FILT_SFT_CLASSIC (2U << 30)
+#define STD_FILT_SFEC_MASK (7U << 27)
+#define STD_FILT_SFEC_DISABLE (0U << 27)
+#define STD_FILT_SFEC_FIFO0 (1U << 27)
+#define STD_FILT_SFEC_FIFO1 (2U << 27)
+#define STD_FILT_SFEC_REJECT (3U << 27)
+#define STD_FILT_SFEC_PRIORITY (4U << 27)
+#define STD_FILT_SFEC_PRIORITY_FIFO0 (5U << 27)
+#define STD_FILT_SFEC_PRIORITY_FIFO1 (6U << 27)
+#define STD_FILT_SFEC_BUFFER (7U << 27)
+#define STD_FILT_SFID1_MASK (0x03FFU << 16)
+#define STD_FILT_SFID2_MASK (0x3FFU << 0)
+#define STD_FILT_SFID2_RX_BUFFER (0U << 9)
+#define STD_FILT_SFID2_DEBUG_A (1U << 9)
+#define STD_FILT_SFID2_DEBUG_B (2U << 9)
+#define STD_FILT_SFID2_DEBUG_C (3U << 9)
+#define STD_FILT_SFID2_BUFFER(nmbr) (nmbr & 0x3F)
+
+#define EXT_FILT_EFEC_MASK (7U << 29)
+#define EXT_FILT_EFEC_DISABLE (0U << 29)
+#define EXT_FILT_EFEC_FIFO0 (1U << 29)
+#define EXT_FILT_EFEC_FIFO1 (2U << 29)
+#define EXT_FILT_EFEC_REJECT (3U << 29)
+#define EXT_FILT_EFEC_PRIORITY (4U << 29)
+#define EXT_FILT_EFEC_PRIORITY_FIFO0 (5U << 29)
+#define EXT_FILT_EFEC_PRIORITY_FIFO1 (6U << 29)
+#define EXT_FILT_EFEC_BUFFER (7U << 29)
+#define EXT_FILT_EFID1_MASK (0x1FFFFFFF)
+#define EXT_FILT_EFT_MASK (3U << 30)
+#define EXT_FILT_EFT_RANGE (0U << 30)
+#define EXT_FILT_EFT_DUAL (1U << 30)
+#define EXT_FILT_EFT_CLASSIC (2U << 30)
+#define EXT_FILT_EFT_RANGE_NO_XIDAM (3U << 30)
+#define EXT_FILT_EFID2_MASK (0x1FFFFFFF)
+#define EXT_FILT_EFID2_RX_BUFFER (0U << 9)
+#define EXT_FILT_EFID2_DEBUG_A (1U << 9)
+#define EXT_FILT_EFID2_DEBUG_B (2U << 9)
+#define EXT_FILT_EFID2_DEBUG_C (3U << 9)
+#define EXT_FILT_EFID2_BUFFER(nmbr) (nmbr & 0x3F)
+
+
+/*---------------------------------------------------------------------------
+ * Internal variables
+ *---------------------------------------------------------------------------*/
+
+#ifndef __rtems__
+static const Pin pinsMcan0[] = {PIN_MCAN0_TXD, PIN_MCAN0_RXD };
+static const Pin pinsMcan1[] = {PIN_MCAN1_TXD, PIN_MCAN1_RXD };
+#endif /* __rtems__ */
+
+static uint32_t can0MsgRam[MCAN0_STD_FLTS_WRDS +
+ MCAN0_EXT_FLTS_WRDS +
+ MCAN0_RX_FIFO0_WRDS +
+ MCAN0_RX_FIFO1_WRDS +
+ MCAN0_RX_DED_BUFS_WRDS +
+ MCAN0_TX_EVT_FIFO_WRDS +
+ MCAN0_TX_DED_BUF_WRDS +
+ MCAN0_TX_FIFO_Q_WRDS];
+
+static uint32_t can1MsgRam[MCAN1_STD_FLTS_WRDS +
+ MCAN1_EXT_FLTS_WRDS +
+ MCAN1_RX_FIFO0_WRDS +
+ MCAN1_RX_FIFO1_WRDS +
+ MCAN1_RX_DED_BUFS_WRDS +
+ MCAN1_TX_EVT_FIFO_WRDS +
+ MCAN1_TX_DED_BUF_WRDS +
+ MCAN1_TX_FIFO_Q_WRDS];
+
+static const uint8_t dlcToMsgLength[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64 };
+
+const MCan_ConfigType mcan0Config = {
+ MCAN0,
+ MCAN_BTP_BRP(MCAN0_BRP) | MCAN_BTP_TSEG1(MCAN0_TSEG1) |
+ MCAN_BTP_TSEG2(MCAN0_TSEG2) | MCAN_BTP_SJW(MCAN0_SJW),
+ MCAN_FBTP_FBRP(MCAN0_FBRP) | MCAN_FBTP_FTSEG1(MCAN0_FTSEG1) |
+ MCAN_FBTP_FTSEG2(MCAN0_FTSEG2) | MCAN_FBTP_FSJW(MCAN0_FSJW),
+ MCAN0_NMBR_STD_FLTS,
+ MCAN0_NMBR_EXT_FLTS,
+ MCAN0_NMBR_RX_FIFO0_ELMTS,
+ MCAN0_NMBR_RX_FIFO1_ELMTS,
+ MCAN0_NMBR_RX_DED_BUF_ELMTS,
+ MCAN0_NMBR_TX_EVT_FIFO_ELMTS,
+ MCAN0_NMBR_TX_DED_BUF_ELMTS,
+ MCAN0_NMBR_TX_FIFO_Q_ELMTS,
+ (MCAN0_RX_FIFO0_DATA_SIZE << 29) | ((MCAN0_RX_FIFO0_ELMT_SZ / 4) + 2),
+ /* element size in WORDS */
+ (MCAN0_RX_FIFO1_DATA_SIZE << 29) | ((MCAN0_RX_FIFO1_ELMT_SZ / 4) + 2),
+ /* element size in WORDS */
+ (MCAN0_RX_BUF_DATA_SIZE << 29) | ((MCAN0_RX_BUF_ELMT_SZ / 4) + 2),
+ /* element size in WORDS */
+ (MCAN0_TX_BUF_DATA_SIZE << 29) | ((MCAN0_TX_BUF_ELMT_SZ / 4) + 2),
+ /* element size in WORDS */
+ {
+ &can0MsgRam[0],
+ &can0MsgRam[MCAN0_STD_FLTS_WRDS],
+ &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS],
+ &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS],
+ &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS +
+ MCAN0_RX_FIFO1_WRDS],
+ &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS +
+ MCAN0_RX_FIFO1_WRDS + MCAN0_RX_DED_BUFS_WRDS],
+ &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS +
+ MCAN0_RX_FIFO1_WRDS + MCAN0_RX_DED_BUFS_WRDS + MCAN0_TX_EVT_FIFO_WRDS],
+ &can0MsgRam[MCAN0_STD_FLTS_WRDS + MCAN0_EXT_FLTS_WRDS + MCAN0_RX_FIFO0_WRDS +
+ MCAN0_RX_FIFO1_WRDS + MCAN0_RX_DED_BUFS_WRDS + MCAN0_TX_EVT_FIFO_WRDS +
+ MCAN0_TX_DED_BUF_WRDS]
+ },
+};
+
+const MCan_ConfigType mcan1Config = {
+ MCAN1,
+ MCAN_BTP_BRP(MCAN1_BRP) | MCAN_BTP_TSEG1(MCAN1_TSEG1) |
+ MCAN_BTP_TSEG2(MCAN1_TSEG2) | MCAN_BTP_SJW(MCAN1_SJW),
+ MCAN_FBTP_FBRP(MCAN1_FBRP) | MCAN_FBTP_FTSEG1(MCAN1_FTSEG1) |
+ MCAN_FBTP_FTSEG2(MCAN1_FTSEG2) | MCAN_FBTP_FSJW(MCAN1_FSJW),
+ MCAN1_NMBR_STD_FLTS,
+ MCAN1_NMBR_EXT_FLTS,
+ MCAN1_NMBR_RX_FIFO0_ELMTS,
+ MCAN1_NMBR_RX_FIFO1_ELMTS,
+ MCAN0_NMBR_RX_DED_BUF_ELMTS,
+ MCAN1_NMBR_TX_EVT_FIFO_ELMTS,
+ MCAN1_NMBR_TX_DED_BUF_ELMTS,
+ MCAN1_NMBR_TX_FIFO_Q_ELMTS,
+ (MCAN1_RX_FIFO0_DATA_SIZE << 29) | ((MCAN1_RX_FIFO0_ELMT_SZ / 4) + 2),
+ /* element size in WORDS */
+ (MCAN1_RX_FIFO1_DATA_SIZE << 29) | ((MCAN1_RX_FIFO1_ELMT_SZ / 4) + 2),
+ /* element size in WORDS */
+ (MCAN1_RX_BUF_DATA_SIZE << 29) | ((MCAN1_RX_BUF_ELMT_SZ / 4) + 2),
+ /* element size in WORDS */
+ (MCAN1_TX_BUF_DATA_SIZE << 29) | ((MCAN1_TX_BUF_ELMT_SZ / 4) + 2),
+ /* element size in WORDS */
+ {
+ &can1MsgRam[0],
+ &can1MsgRam[MCAN1_STD_FLTS_WRDS],
+ &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS],
+ &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS],
+ &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS
+ + MCAN1_RX_FIFO1_WRDS],
+ &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS
+ + MCAN1_RX_FIFO1_WRDS + MCAN1_RX_DED_BUFS_WRDS],
+ &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS
+ + MCAN1_RX_FIFO1_WRDS + MCAN1_RX_DED_BUFS_WRDS + MCAN1_TX_EVT_FIFO_WRDS],
+ &can1MsgRam[MCAN1_STD_FLTS_WRDS + MCAN1_EXT_FLTS_WRDS + MCAN1_RX_FIFO0_WRDS
+ + MCAN1_RX_FIFO1_WRDS + MCAN1_RX_DED_BUFS_WRDS + MCAN1_TX_EVT_FIFO_WRDS
+ + MCAN1_TX_DED_BUF_WRDS]
+ },
+};
+
+
+/*---------------------------------------------------------------------------
+ * Exported Functions
+ *---------------------------------------------------------------------------*/
+/**
+* \brief Initializes the MCAN hardware for giving peripheral.
+* Default: Mixed mode TX Buffer + FIFO.
+*
+* \param mcanConfig Pointer to a MCAN instance.
+*/
+void MCAN_Init(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t regVal32;
+ uint32_t *pMsgRam;
+ uint32_t cntr;
+ IRQn_Type mCanLine0Irq;
+
+ /* Both MCAN controllers use programmable clock 5 to derive bit rate */
+ // select MCK divided by 1 as programmable clock 5 output
+ PMC->PMC_PCK[5] = PMC_PCK_PRES(MCAN_PROG_CLK_PRESCALER - 1) |
+ MCAN_PROG_CLK_SELECT;
+ PMC->PMC_SCER = PMC_SCER_PCK5;
+
+ if (MCAN0 == mcan) {
+#ifndef __rtems__
+ PIO_Configure(pinsMcan0, PIO_LISTSIZE(pinsMcan0));
+#endif /* __rtems__ */
+ // Enable MCAN peripheral clock
+ PMC_EnablePeripheral(ID_MCAN0);
+ // Configure Message RAM Base Address
+ regVal32 = MATRIX->CCFG_CAN0 & 0x000001FF;
+ MATRIX->CCFG_CAN0 = regVal32 |
+ ((uint32_t) mcanConfig->msgRam.pStdFilts & 0xFFFF0000);
+ mCanLine0Irq = MCAN0_IRQn;
+ } else if (MCAN1 == mcan) {
+#ifndef __rtems__
+ PIO_Configure(pinsMcan1, PIO_LISTSIZE(pinsMcan1));
+#endif /* __rtems__ */
+ // Enable MCAN peripheral clock
+ PMC_EnablePeripheral(ID_MCAN1);
+ // Configure Message RAM Base Address
+ regVal32 = MATRIX->CCFG_SYSIO & 0x0000FFFF;
+ MATRIX->CCFG_SYSIO = regVal32 | ((uint32_t) mcanConfig->msgRam.pStdFilts &
+ 0xFFFF0000);
+ mCanLine0Irq = MCAN1_IRQn;
+ } else
+ return;
+
+ /* Indicates Initialization state */
+ mcan->MCAN_CCCR = MCAN_CCCR_INIT_ENABLED;
+
+ do { regVal32 = mcan->MCAN_CCCR; }
+ while (0u == (regVal32 & MCAN_CCCR_INIT_ENABLED));
+
+ /* Enable writing to configuration registers */
+ mcan->MCAN_CCCR = MCAN_CCCR_INIT_ENABLED | MCAN_CCCR_CCE_CONFIGURABLE;
+
+ /* Global Filter Configuration: Reject remote frames, reject non-matching frames */
+ mcan->MCAN_GFC = MCAN_GFC_RRFE_REJECT | MCAN_GFC_RRFS_REJECT
+ | MCAN_GFC_ANFE(2) | MCAN_GFC_ANFS(2);
+
+ // Extended ID Filter AND mask
+ mcan->MCAN_XIDAM = 0x1FFFFFFF;
+
+ /* Interrupt configuration - leave initialization with all interrupts off */
+ // Disable all interrupts
+ mcan->MCAN_IE = 0;
+ mcan->MCAN_TXBTIE = 0x00000000;
+ // All interrupts directed to Line 0
+ mcan->MCAN_ILS = 0x00000000;
+ // Disable both interrupt LINE 0 & LINE 1
+ mcan->MCAN_ILE = 0x00;
+ // Clear all interrupt flags
+ mcan->MCAN_IR = 0xFFCFFFFF;
+ /* Enable NVIC - but no interrupts will happen since all sources are
+ disabled in MCAN_IE */
+ NVIC_ClearPendingIRQ(mCanLine0Irq);
+ NVIC_EnableIRQ(mCanLine0Irq);
+ NVIC_ClearPendingIRQ((IRQn_Type) (mCanLine0Irq + 1));
+ NVIC_EnableIRQ((IRQn_Type) (mCanLine0Irq + 1));
+
+ /* Configure CAN bit timing */
+ mcan->MCAN_BTP = mcanConfig->bitTiming;
+ mcan->MCAN_FBTP = mcanConfig->fastBitTiming;
+
+ /* Configure message RAM starting addresses & sizes */
+ mcan->MCAN_SIDFC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pStdFilts)
+ | MCAN_SIDFC_LSS(mcanConfig->nmbrStdFilts);
+ mcan->MCAN_XIDFC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pExtFilts)
+ | MCAN_XIDFC_LSE(mcanConfig->nmbrExtFilts);
+ mcan->MCAN_RXF0C = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pRxFifo0)
+ | MCAN_RXF0C_F0S(mcanConfig->nmbrFifo0Elmts);
+ // watermark interrupt off, blocking mode
+ mcan->MCAN_RXF1C = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pRxFifo1)
+ | MCAN_RXF1C_F1S(mcanConfig->nmbrFifo1Elmts);
+ // watermark interrupt off, blocking mode
+ mcan->MCAN_RXBC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pRxDedBuf);
+ mcan->MCAN_TXEFC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pTxEvtFifo)
+ | MCAN_TXEFC_EFS(mcanConfig->nmbrTxEvtFifoElmts);
+ // watermark interrupt off
+ mcan->MCAN_TXBC = MAILBOX_ADDRESS((uint32_t) mcanConfig->msgRam.pTxDedBuf)
+ | MCAN_TXBC_NDTB(mcanConfig->nmbrTxDedBufElmts)
+ | MCAN_TXBC_TFQS(mcanConfig->nmbrTxFifoQElmts);
+ mcan->MCAN_RXESC = ((mcanConfig->rxBufElmtSize >> (29 - MCAN_RXESC_RBDS_Pos)) &
+ MCAN_RXESC_RBDS_Msk) |
+ ((mcanConfig->rxFifo1ElmtSize >> (29 - MCAN_RXESC_F1DS_Pos)) &
+ MCAN_RXESC_F1DS_Msk) |
+ ((mcanConfig->rxFifo0ElmtSize >> (29 - MCAN_RXESC_F0DS_Pos)) &
+ MCAN_RXESC_F0DS_Msk);
+ mcan->MCAN_TXESC = ((mcanConfig->txBufElmtSize >> (29 - MCAN_TXESC_TBDS_Pos)) &
+ MCAN_TXESC_TBDS_Msk);
+
+ /* Configure Message Filters */
+ // ...Disable all standard filters
+ pMsgRam = mcanConfig->msgRam.pStdFilts;
+ cntr = mcanConfig->nmbrStdFilts;
+
+ while (cntr > 0) {
+ *pMsgRam++ = STD_FILT_SFEC_DISABLE;
+ cntr--;
+ }
+
+ // ...Disable all extended filters
+ pMsgRam = mcanConfig->msgRam.pExtFilts;
+ cntr = mcanConfig->nmbrExtFilts;
+
+ while (cntr > 0) {
+ *pMsgRam = EXT_FILT_EFEC_DISABLE;
+ pMsgRam = pMsgRam + 2;
+ cntr--;
+ }
+
+ mcan->MCAN_NDAT1 = 0xFFFFFFFF; // clear new (rx) data flags
+ mcan->MCAN_NDAT2 = 0xFFFFFFFF; // clear new (rx) data flags
+
+ regVal32 = mcan->MCAN_CCCR & ~(MCAN_CCCR_CME_Msk | MCAN_CCCR_CMR_Msk);
+ mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CME_ISO11898_1;
+ mcan->MCAN_CCCR = regVal32 | (MCAN_CCCR_CMR_ISO11898_1 |
+ MCAN_CCCR_CME_ISO11898_1);
+
+ __DSB();
+ __ISB();
+}
+
+/**
+ * \brief Enables a FUTURE switch to FD mode (tx & rx payloads up to 64 bytes)
+ * but transmits WITHOUT bit rate switching
+ * INIT must be set - so this should be called between MCAN_Init() and
+ * MCAN_Enable()
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_InitFdEnable(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t regVal32;
+
+ regVal32 = mcan->MCAN_CCCR & ~MCAN_CCCR_CME_Msk;
+ mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CME(1);
+}
+
+/**
+ * \brief Enables a FUTURE switch to FD mode (tx & rx payloads up to 64 bytes) and transmits
+ * WITH bit rate switching
+ * INIT must be set - so this should be called between MCAN_Init() and MCAN_Enable()
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_InitFdBitRateSwitchEnable(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t regVal32;
+
+ regVal32 = mcan->MCAN_CCCR & ~MCAN_CCCR_CME_Msk;
+ mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CME(2);
+}
+
+/**
+ * \brief Initializes the MCAN in loop back mode.
+ * INIT must be set - so this should be called between MCAN_Init() and
+ * MCAN_Enable()
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_InitLoopback(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+
+ mcan->MCAN_CCCR |= MCAN_CCCR_TEST_ENABLED;
+ //mcan->MCAN_CCCR |= MCAN_CCCR_MON_ENABLED; // for internal loop back
+ mcan->MCAN_TEST |= MCAN_TEST_LBCK_ENABLED;
+}
+
+/**
+ * \brief Initializes MCAN queue for TX
+ * INIT must be set - so this should be called between MCAN_Init() and
+ * MCAN_Enable()
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_InitTxQueue(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ mcan->MCAN_TXBC |= MCAN_TXBC_TFQM;
+}
+
+/**
+ * \brief Enable MCAN peripheral.
+ * INIT must be set - so this should be called between MCAN_Init()
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_Enable(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ mcan->MCAN_CCCR &= ~MCAN_CCCR_INIT_ENABLED;
+}
+
+/**
+ * \brief Requests switch to Iso11898-1 (standard / classic) mode (tx & rx
+ * payloads up to 8 bytes).
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_RequestIso11898_1(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t regVal32;
+
+ regVal32 = mcan->MCAN_CCCR & ~MCAN_CCCR_CMR_Msk;
+ mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CMR_ISO11898_1;
+
+ while ((mcan->MCAN_CCCR & (MCAN_CCCR_FDBS | MCAN_CCCR_FDO)) != 0)
+ { /* wait */ }
+}
+
+/**
+ * \brief Requests switch to FD mode (tx & rx payloads up to 64 bytes) but
+ * transmits WITHOUT bit
+ * rate switching. requested mode should have been enabled at initialization
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_RequestFd(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t regVal32;
+
+ if ((mcan->MCAN_CCCR & MCAN_CCCR_CME_Msk) == MCAN_CCCR_CME(1)) {
+ regVal32 = mcan->MCAN_CCCR & ~MCAN_CCCR_CMR_Msk;
+ mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CMR_FD;
+
+ while ((mcan->MCAN_CCCR & MCAN_CCCR_FDO) == 0) { /* wait */ }
+ }
+}
+
+/**
+ * \brief Request switch to FD mode (tx & rx payloads up to 64 bytes) and
+ * transmits WITH bit rate switching.
+ * requested mode should have been enabled at initialization
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_RequestFdBitRateSwitch(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t regVal32;
+
+ if ((mcan->MCAN_CCCR & MCAN_CCCR_CME_Msk) == MCAN_CCCR_CME(2)) {
+ regVal32 = mcan->MCAN_CCCR & ~MCAN_CCCR_CMR_Msk;
+ mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CMR_FD_BITRATE_SWITCH;
+
+ while ((mcan->MCAN_CCCR & (MCAN_CCCR_FDBS | MCAN_CCCR_FDO)) !=
+ (MCAN_CCCR_FDBS | MCAN_CCCR_FDO)) { /* wait */ }
+ }
+}
+
+/**
+ * \brief Switch on loop back mode.
+ * TEST must be set in MCAN_CCCR - e.g. by a prior call to MCAN_InitLoopback()
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_LoopbackOn(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ mcan->MCAN_TEST |= MCAN_TEST_LBCK_ENABLED;
+}
+
+/**
+ * \brief Switch off loop back mode.
+ * \param mcanConfig Pointer to a MCAN instance.
+ */
+void MCAN_LoopbackOff(const MCan_ConfigType *mcanConfig)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ mcan->MCAN_TEST &= ~MCAN_TEST_LBCK_ENABLED;
+}
+
+/**
+ * \brief Enable message line and message stored to Dedicated Receive Buffer
+ * Interrupt Line.
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param line Message line.
+ */
+void MCAN_IEnableMessageStoredToRxDedBuffer(const MCan_ConfigType *mcanConfig,
+ MCan_IntrLineType line)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+
+ if (line == CAN_INTR_LINE_0) {
+ mcan->MCAN_ILS &= ~MCAN_ILS_DRXL;
+ mcan->MCAN_ILE |= MCAN_ILE_EINT0;
+ } else {
+ // Interrupt Line 1
+ mcan->MCAN_ILS |= MCAN_ILS_DRXL;
+ mcan->MCAN_ILE |= MCAN_ILE_EINT1;
+ }
+
+ mcan->MCAN_IR = MCAN_IR_DRX; // clear previous flag
+ mcan->MCAN_IE |= MCAN_IE_DRXE; // enable it
+}
+
+/**
+ * \brief Configures a Dedicated TX Buffer.
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param buffer Pointer to buffer.
+ * \param id Message ID.
+ * \param idType Type of ID
+ * \param dlc Type of dlc.
+ */
+uint8_t *MCAN_ConfigTxDedBuffer(const MCan_ConfigType *mcanConfig,
+ uint8_t buffer, uint32_t id, MCan_IdType idType, MCan_DlcType dlc)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t *pThisTxBuf = 0;
+
+ if (buffer < mcanConfig->nmbrTxDedBufElmts) {
+ pThisTxBuf = mcanConfig->msgRam.pTxDedBuf + (buffer *
+ (mcanConfig->txBufElmtSize & ELMT_SIZE_MASK));
+
+ if (idType == CAN_STD_ID)
+ *pThisTxBuf++ = ((id << 18) & (CAN_11_BIT_ID_MASK << 18));
+ else
+ *pThisTxBuf++ = BUFFER_XTD_MASK | (id & CAN_29_BIT_ID_MASK);
+
+ *pThisTxBuf++ = (uint32_t) dlc << 16;
+ /* enable transmit from buffer to set TC interrupt bit in IR, but
+ interrupt will not happen unless TC interrupt is enabled*/
+ mcan->MCAN_TXBTIE = (1 << buffer);
+ }
+
+ return (uint8_t *) pThisTxBuf; // now it points to the data field
+}
+
+/**
+ * \brief Send Tx buffer.
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param buffer Pointer to buffer.
+ */
+void MCAN_SendTxDedBuffer(const MCan_ConfigType *mcanConfig, uint8_t buffer)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+
+ if (buffer < mcanConfig->nmbrTxDedBufElmts)
+ mcan->MCAN_TXBAR = (1 << buffer);
+}
+
+/**
+ * \brief Adds Message to TX Fifo / Queue
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param id Message ID.
+ * \param idType Type of ID
+ * \param dlc Type of dlc.
+ * \param data Pointer to data.
+ */
+uint32_t MCAN_AddToTxFifoQ(const MCan_ConfigType *mcanConfig,
+ uint32_t id, MCan_IdType idType, MCan_DlcType dlc, uint8_t *data)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t putIdx = 255;
+ uint32_t *pThisTxBuf = 0;
+ uint8_t *pTxData;
+ uint8_t msgLength;
+ uint8_t cnt;
+
+ // Configured for FifoQ and FifoQ not full?
+ if ((mcanConfig->nmbrTxFifoQElmts > 0) &&
+ ((mcan->MCAN_TXFQS & MCAN_TXFQS_TFQF) == 0)) {
+ putIdx = (mcan->MCAN_TXFQS & MCAN_TXFQS_TFQPI_Msk) >> MCAN_TXFQS_TFQPI_Pos;
+ pThisTxBuf = mcanConfig->msgRam.pTxDedBuf + (putIdx *
+ (mcanConfig->txBufElmtSize & ELMT_SIZE_MASK));
+
+ if (idType == CAN_STD_ID)
+ *pThisTxBuf++ = ((id << 18) & (CAN_11_BIT_ID_MASK << 18));
+ else
+ *pThisTxBuf++ = BUFFER_XTD_MASK | (id & CAN_29_BIT_ID_MASK);
+
+ *pThisTxBuf++ = (uint32_t) dlc << 16;
+ pTxData = (uint8_t *) pThisTxBuf;
+ msgLength = dlcToMsgLength[dlc];
+
+ for (cnt = 0; cnt < msgLength; cnt++)
+ *pTxData++ = *data++;
+
+ /* enable transmit from buffer to set TC interrupt bit in IR, but
+ interrupt will not happen unless TC interrupt is enabled */
+ mcan->MCAN_TXBTIE = (1 << putIdx);
+ // request to send
+ mcan->MCAN_TXBAR = (1 << putIdx);
+ }
+
+ return putIdx; // now it points to the data field
+}
+
+/**
+ * \brief Check if data transmitted from buffer/fifo/queue
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param buffer Pointer to data buffer.
+ */
+uint8_t MCAN_IsBufferTxd(const MCan_ConfigType *mcanConfig, uint8_t buffer)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+
+ return (mcan->MCAN_TXBTO & (1 << buffer));
+}
+
+/**
+ * \brief Configure RX Buffer Filter
+ * ID must match exactly for a RX Buffer Filter
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param buffer Pointer to data buffer.
+ * \param filter data of filter.
+ * \param idType Type of ID
+ */
+void MCAN_ConfigRxBufferFilter(const MCan_ConfigType *mcanConfig,
+ uint32_t buffer, uint32_t filter, uint32_t id, MCan_IdType idType)
+{
+ uint32_t *pThisRxFilt = 0;
+
+ if (buffer < mcanConfig->nmbrRxDedBufElmts) {
+ if (idType == CAN_STD_ID) {
+ if ((filter < mcanConfig->nmbrStdFilts)
+ && (id <= CAN_11_BIT_ID_MASK)) {
+ pThisRxFilt = mcanConfig->msgRam.pStdFilts + filter;
+ // 1 word per filter
+ *pThisRxFilt = STD_FILT_SFEC_BUFFER | (id << 16) |
+ STD_FILT_SFID2_RX_BUFFER | buffer;
+ }
+ } else {
+ // extended ID
+ if ((filter < mcanConfig->nmbrExtFilts) &&
+ (id <= CAN_29_BIT_ID_MASK)) {
+ pThisRxFilt = mcanConfig->msgRam.pExtFilts + (2 * filter);
+ // 2 words per filter
+ *pThisRxFilt++ = (uint32_t) EXT_FILT_EFEC_BUFFER | id;
+ *pThisRxFilt = EXT_FILT_EFID2_RX_BUFFER | buffer;
+ }
+ }
+ }
+}
+
+/**
+ * \brief Configure Classic Filter
+ * Classic Filters direct accepted messages to a FIFO & include both a ID and
+ * a ID mask
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param buffer Pointer to data buffer.
+ * \param fifo fifo Number.
+ * \param filter data of filter.
+ * \param idType Type of ID
+ * \param mask Mask to be match
+ */
+void MCAN_ConfigRxClassicFilter(const MCan_ConfigType *mcanConfig,
+ MCan_FifoType fifo, uint8_t filter, uint32_t id,
+ MCan_IdType idType, uint32_t mask)
+{
+ uint32_t *pThisRxFilt = 0;
+ uint32_t filterTemp;
+
+ if (idType == CAN_STD_ID) {
+ if ((filter < mcanConfig->nmbrStdFilts) && (id <= CAN_11_BIT_ID_MASK)
+ && (mask <= CAN_11_BIT_ID_MASK)) {
+ pThisRxFilt = mcanConfig->msgRam.pStdFilts + filter;
+ // 1 word per filter
+ filterTemp = (uint32_t) STD_FILT_SFT_CLASSIC | (id << 16) | mask;
+
+ if (fifo == CAN_FIFO_0)
+ *pThisRxFilt = STD_FILT_SFEC_FIFO0 | filterTemp;
+ else if (fifo == CAN_FIFO_1)
+ *pThisRxFilt = STD_FILT_SFEC_FIFO1 | filterTemp;
+ }
+ } else {
+ // extended ID
+ if ((filter < mcanConfig->nmbrExtFilts)
+ && (id <= CAN_29_BIT_ID_MASK)
+ && (mask <= CAN_29_BIT_ID_MASK)) {
+ pThisRxFilt = mcanConfig->msgRam.pExtFilts + (2 * filter);
+
+ // 2 words per filter
+ if (fifo == CAN_FIFO_0)
+ *pThisRxFilt++ = EXT_FILT_EFEC_FIFO0 | id;
+ else if (fifo == CAN_FIFO_1)
+ *pThisRxFilt++ = EXT_FILT_EFEC_FIFO1 | id;
+
+ *pThisRxFilt = (uint32_t) EXT_FILT_EFT_CLASSIC | mask;
+ }
+ }
+}
+
+/**
+ * \brief check if data received into buffer
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param buffer Pointer to data buffer.
+ */
+uint8_t MCAN_IsNewDataInRxDedBuffer(const MCan_ConfigType *mcanConfig,
+ uint8_t buffer)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+
+ if (buffer < 32)
+ return (mcan->MCAN_NDAT1 & (1 << buffer));
+ else if (buffer < 64)
+ return (mcan->MCAN_NDAT1 & (1 << (buffer - 32)));
+ else
+ return 0;
+}
+
+/**
+ * \brief Get Rx buffer
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param buffer Pointer to data buffer.
+ * \param pRxMailbox Pointer to rx Mailbox.
+ */
+void MCAN_GetRxDedBuffer(const MCan_ConfigType *mcanConfig,
+ uint8_t buffer, Mailbox64Type *pRxMailbox)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t *pThisRxBuf = 0;
+ uint32_t tempRy; // temp copy of RX buffer word
+ uint32_t dlc;
+ uint8_t *pRxData;
+ uint8_t idx;
+
+ if (buffer < mcanConfig->nmbrRxDedBufElmts) {
+ pThisRxBuf = mcanConfig->msgRam.pRxDedBuf
+ + (buffer * (mcanConfig->rxBufElmtSize & ELMT_SIZE_MASK));
+ tempRy = *pThisRxBuf++; // word R0 contains ID
+
+ if (tempRy & BUFFER_XTD_MASK) {
+ // extended ID?
+ pRxMailbox->info.id = tempRy & BUFFER_EXT_ID_MASK;
+ } else {
+ // standard ID
+ pRxMailbox->info.id = (tempRy & BUFFER_STD_ID_MASK) >> 18;
+ }
+
+ tempRy = *pThisRxBuf++; // word R1 contains DLC & time stamp
+ dlc = (tempRy & BUFFER_DLC_MASK) >> 16;
+ pRxMailbox->info.length = dlcToMsgLength[dlc];
+ pRxMailbox->info.timestamp = tempRy & BUFFER_RXTS_MASK;
+ // copy the data from the buffer to the mailbox
+ pRxData = (uint8_t *) pThisRxBuf;
+
+ SCB_CleanDCache_by_Addr((uint32_t *)pRxData, pRxMailbox->info.length);
+ SCB_CleanDCache_by_Addr((uint32_t *) & (pRxMailbox->data[0]),
+ pRxMailbox->info.length);
+
+ for (idx = 0; idx < pRxMailbox->info.length; idx++)
+ pRxMailbox->data[idx] = *pRxData++;
+
+ /* clear the new data flag for the buffer */
+
+ if (buffer < 32)
+ mcan->MCAN_NDAT1 = (1 << buffer);
+ else
+ mcan->MCAN_NDAT1 = (1 << (buffer - 32));
+
+ }
+}
+
+/**
+ * \brief Get from the receive FIFO and place in a application mailbox
+ * \param mcanConfig Pointer to a MCAN instance.
+ * \param fifo Fifo Number
+ * \param pRxMailbox Pointer to rx Mailbox.
+ * \return: # of fifo entries at the start of the function
+ * 0 -> FIFO was empty at start
+ * 1 -> FIFO had 1 entry at start, but is empty at finish
+ * 2 -> FIFO had 2 entries at start, has 1 entry at finish
+ */
+uint32_t MCAN_GetRxFifoBuffer(const MCan_ConfigType *mcanConfig,
+ MCan_FifoType fifo, Mailbox64Type *pRxMailbox)
+{
+ Mcan *mcan = mcanConfig->pMCan;
+ uint32_t *pThisRxBuf = 0;
+ uint32_t tempRy; // temp copy of RX buffer word
+ uint32_t dlc;
+ uint8_t *pRxData;
+ uint8_t idx;
+ uint32_t *fifo_ack_reg;
+ uint32_t get_index;
+ uint32_t fill_level;
+ uint32_t element_size;
+
+ // default: fifo empty
+ fill_level = 0;
+
+ if (fifo == CAN_FIFO_0) {
+ get_index = (mcan->MCAN_RXF0S & MCAN_RXF0S_F0GI_Msk) >> MCAN_RXF0S_F0GI_Pos;
+ fill_level = (mcan->MCAN_RXF0S & MCAN_RXF0S_F0FL_Msk) >> MCAN_RXF0S_F0FL_Pos;
+ pThisRxBuf = mcanConfig->msgRam.pRxFifo0;
+ element_size = mcanConfig->rxFifo0ElmtSize & ELMT_SIZE_MASK;
+ fifo_ack_reg = (uint32_t *) &mcan->MCAN_RXF0A;
+ } else if (fifo == CAN_FIFO_1) {
+ get_index = (mcan->MCAN_RXF1S & MCAN_RXF1S_F1GI_Msk) >> MCAN_RXF1S_F1GI_Pos;
+ fill_level = (mcan->MCAN_RXF1S & MCAN_RXF1S_F1FL_Msk) >> MCAN_RXF1S_F1FL_Pos;
+ pThisRxBuf = mcanConfig->msgRam.pRxFifo1;
+ element_size = mcanConfig->rxFifo1ElmtSize & ELMT_SIZE_MASK;
+ fifo_ack_reg = (uint32_t *) &mcan->MCAN_RXF1A;
+ }
+
+ if (fill_level > 0) {
+ pThisRxBuf = pThisRxBuf + (get_index * element_size);
+ tempRy = *pThisRxBuf++; // word R0 contains ID
+
+ if (tempRy & BUFFER_XTD_MASK) {
+ // extended ID?
+ pRxMailbox->info.id = tempRy & BUFFER_EXT_ID_MASK;
+ } else {
+ // standard ID
+ pRxMailbox->info.id = (tempRy & BUFFER_STD_ID_MASK) >> 18;
+ }
+
+ tempRy = *pThisRxBuf++; // word R1 contains DLC & timestamps
+ dlc = (tempRy & BUFFER_DLC_MASK) >> 16;
+ pRxMailbox->info.length = dlcToMsgLength[dlc];
+ pRxMailbox->info.timestamp = tempRy & BUFFER_RXTS_MASK;
+ /* copy the data from the buffer to the mailbox */
+ pRxData = (uint8_t *) pThisRxBuf;
+
+ for (idx = 0; idx < pRxMailbox->info.length; idx++)
+ pRxMailbox->data[idx] = *pRxData++;
+
+ // acknowledge reading the fifo entry
+ *fifo_ack_reg = get_index;
+ /* return entries remaining in FIFO */
+ }
+
+ return (fill_level);
+}
+
+/**@}*/
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/mediaLB.c b/bsps/arm/atsam/contrib/libraries/libchip/source/mediaLB.c
new file mode 100644
index 0000000000..d93bab7745
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/mediaLB.c
@@ -0,0 +1,58 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup mediaLB Working with MediaLB
+ * \ingroup peripherals_module
+ * The mediaLB driver provides the interface to configure and use the peripheral.
+ *
+ */
+/*@{*/
+/*@}*/
+
+/**
+ * \file
+ *
+ * Implementation of mediaLB controller.
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/mpu.c b/bsps/arm/atsam/contrib/libraries/libchip/source/mpu.c
new file mode 100644
index 0000000000..0083a5fd37
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/mpu.c
@@ -0,0 +1,168 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \file */
+
+/**
+ * \addtogroup mmu MMU Initialization
+ *
+ * \section Usage
+ *
+ * Translation Look-aside Buffers (TLBs) are an implementation technique that
+ * caches translations or translation table entries. TLBs avoid the requirement
+ * for every memory access to perform a translation table lookup.
+ * The ARM architecture does not specify the exact form of the TLB structures
+ * for any design. In a similar way to the requirements for caches, the
+ * architecture only defines certain principles for TLBs:
+ *
+ * The MMU supports memory accesses based on memory sections or pages:
+ * Super-sections Consist of 16MB blocks of memory. Support for Super sections
+ * is optional.
+ * -# Sections Consist of 1MB blocks of memory.
+ * -# Large pages Consist of 64KB blocks of memory.
+ * -# Small pages Consist of 4KB blocks of memory.
+ *
+ * Access to a memory region is controlled by the access permission bits and
+ * the domain field in the TLB entry.
+ * Memory region attributes
+ * Each TLB entry has an associated set of memory region attributes. These
+ * control accesses to the caches,
+ * how the write buffer is used, and if the memory region is Shareable and
+ * therefore must be kept coherent.
+ *
+ * Related files:\n
+ * \ref mmu.c\n
+ * \ref mmu.h \n
+ */
+
+/*-------------------------------------------------------------------------- */
+/* Headers */
+/*-------------------------------------------------------------------------- */
+#include <chip.h>
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+
+ *----------------------------------------------------------------------------*/
+/**
+ * \brief Enables the MPU module.
+ *
+ * \param dwMPUEnable Enable/Disable the memory region.
+ */
+void MPU_Enable(uint32_t dwMPUEnable)
+{
+ MPU->CTRL = dwMPUEnable;
+}
+
+/**
+ * \brief Set active memory region.
+ *
+ * \param dwRegionNum The memory region to be active.
+ */
+void MPU_SetRegionNum(uint32_t dwRegionNum)
+{
+ MPU->RNR = dwRegionNum;
+}
+
+/**
+ * \brief Disable the current active region.
+ */
+extern void MPU_DisableRegion(void)
+{
+ MPU->RASR &= 0xfffffffe;
+}
+
+/**
+ * \brief Setup a memory region.
+ *
+ * \param dwRegionBaseAddr Memory region base address.
+ * \param dwRegionAttr Memory region attributes.
+ */
+void MPU_SetRegion(uint32_t dwRegionBaseAddr, uint32_t dwRegionAttr)
+{
+ MPU->RBAR = dwRegionBaseAddr;
+ MPU->RASR = dwRegionAttr;
+}
+
+
+/**
+ * \brief Calculate region size for the RASR.
+ */
+uint32_t MPU_CalMPURegionSize(uint32_t dwActualSizeInBytes)
+{
+ uint32_t dwRegionSize = 32;
+ uint32_t dwReturnValue = 4;
+
+ while (dwReturnValue < 31) {
+ if (dwActualSizeInBytes <= dwRegionSize)
+ break;
+ else
+ dwReturnValue++;
+
+ dwRegionSize <<= 1;
+ }
+
+ return (dwReturnValue << 1);
+}
+
+
+/**
+ * \brief Update MPU regions.
+ *
+ * \return Unused (ANSI-C compatibility).
+ */
+void MPU_UpdateRegions(uint32_t dwRegionNum, uint32_t dwRegionBaseAddr,
+ uint32_t dwRegionAttr)
+{
+
+ /* Disable interrupt */
+ __disable_irq();
+
+ /* Clean up data and instruction buffer */
+ __DSB();
+ __ISB();
+
+ /* Set active region */
+ MPU_SetRegionNum(dwRegionNum);
+
+ /* Disable region */
+ MPU_DisableRegion();
+
+ /* Update region attribute */
+ MPU_SetRegion(dwRegionBaseAddr, dwRegionAttr);
+
+ /* Clean up data and instruction buffer to make the new region taking
+ effect at once */
+ __DSB();
+ __ISB();
+
+ /* Enable the interrupt */
+ __enable_irq();
+}
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/pio.c b/bsps/arm/atsam/contrib/libraries/libchip/source/pio.c
new file mode 100644
index 0000000000..d6df587464
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/pio.c
@@ -0,0 +1,499 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \file */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+#include "chip.h"
+
+/*----------------------------------------------------------------------------
+ * Local functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Configures one or more pin(s) of a PIO controller as being controlled by
+ * peripheral A. Optionally, the corresponding internal pull-up(s) can be enabled.
+ *
+ * \param pio Pointer to a PIO controller.
+ * \param mask Bitmask of one or more pin(s) to configure.
+ * \param enablePullUp Indicates if the pin(s) internal pull-up shall be
+ * configured.
+ */
+static void PIO_SetPeripheralA(
+ Pio *pio,
+ unsigned int mask,
+ unsigned char enablePullUp)
+{
+ unsigned int abcdsr;
+ /* Disable interrupts on the pin(s) */
+ pio->PIO_IDR = mask;
+
+ /* Enable the pull-up(s) if necessary */
+ if (enablePullUp)
+ pio->PIO_PUER = mask;
+ else
+ pio->PIO_PUDR = mask;
+
+ abcdsr = pio->PIO_ABCDSR[0];
+ pio->PIO_ABCDSR[0] &= (~mask & abcdsr);
+ abcdsr = pio->PIO_ABCDSR[1];
+ pio->PIO_ABCDSR[1] &= (~mask & abcdsr);
+ pio->PIO_PDR = mask;
+}
+
+/**
+ * \brief Configures one or more pin(s) of a PIO controller as being controlled
+ * by peripheral B. Optionally, the corresponding internal pull-up(s) can be
+ * enabled.
+ *
+ * \param pio Pointer to a PIO controller.
+ * \param mask Bitmask of one or more pin(s) to configure.
+ * \param enablePullUp Indicates if the pin(s) internal pull-up shall be
+ * configured.
+ */
+static void PIO_SetPeripheralB(
+ Pio *pio,
+ unsigned int mask,
+ unsigned char enablePullUp)
+{
+ unsigned int abcdsr;
+ /* Disable interrupts on the pin(s) */
+ pio->PIO_IDR = mask;
+
+ /* Enable the pull-up(s) if necessary */
+ if (enablePullUp)
+ pio->PIO_PUER = mask;
+ else
+ pio->PIO_PUDR = mask;
+
+ abcdsr = pio->PIO_ABCDSR[0];
+ pio->PIO_ABCDSR[0] = (mask | abcdsr);
+ abcdsr = pio->PIO_ABCDSR[1];
+ pio->PIO_ABCDSR[1] &= (~mask & abcdsr);
+
+ pio->PIO_PDR = mask;
+}
+
+/**
+ * \brief Configures one or more pin(s) of a PIO controller as being controlled
+ * by peripheral C. Optionally, the corresponding internal pull-up(s) can be
+ * enabled.
+ *
+ * \param pio Pointer to a PIO controller.
+ * \param mask Bitmask of one or more pin(s) to configure.
+ * \param enablePullUp Indicates if the pin(s) internal pull-up shall be
+ * configured.
+ */
+static void PIO_SetPeripheralC(
+ Pio *pio,
+ unsigned int mask,
+ unsigned char enablePullUp)
+{
+ unsigned int abcdsr;
+ /* Disable interrupts on the pin(s) */
+ pio->PIO_IDR = mask;
+
+ /* Enable the pull-up(s) if necessary */
+ if (enablePullUp)
+ pio->PIO_PUER = mask;
+ else
+ pio->PIO_PUDR = mask;
+
+ abcdsr = pio->PIO_ABCDSR[0];
+ pio->PIO_ABCDSR[0] &= (~mask & abcdsr);
+ abcdsr = pio->PIO_ABCDSR[1];
+ pio->PIO_ABCDSR[1] = (mask | abcdsr);
+
+ pio->PIO_PDR = mask;
+}
+
+/**
+ * \brief Configures one or more pin(s) of a PIO controller as being controlled
+ * by peripheral D. Optionally, the corresponding internal pull-up(s) can be
+ * enabled.
+ *
+ * \param pio Pointer to a PIO controller.
+ * \param mask Bitmask of one or more pin(s) to configure.
+ * \param enablePullUp Indicates if the pin(s) internal pull-up shall be
+ * configured.
+ */
+static void PIO_SetPeripheralD(
+ Pio *pio,
+ unsigned int mask,
+ unsigned char enablePullUp)
+{
+ unsigned int abcdsr;
+ /* Disable interrupts on the pin(s) */
+ pio->PIO_IDR = mask;
+
+ /* Enable the pull-up(s) if necessary */
+ if (enablePullUp)
+ pio->PIO_PUER = mask;
+ else
+ pio->PIO_PUDR = mask;
+
+ abcdsr = pio->PIO_ABCDSR[0];
+ pio->PIO_ABCDSR[0] = (mask | abcdsr);
+ abcdsr = pio->PIO_ABCDSR[1];
+ pio->PIO_ABCDSR[1] = (mask | abcdsr);
+
+ pio->PIO_PDR = mask;
+}
+
+/**
+ * \brief Configures 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 pio Pointer to a PIO controller.
+ * \param mask Bitmask indicating which pin(s) to configure as input(s).
+ * \param enablePullUp Indicates if the internal pull-up(s) must be enabled.
+ * \param enableFilter Indicates if the glitch filter(s) must be enabled.
+ */
+static void PIO_SetInput(
+ Pio *pio,
+ unsigned int mask,
+ unsigned char attribute)
+{
+ /* Disable interrupts */
+ pio->PIO_IDR = mask;
+
+ /* Enable pull-up(s) if necessary */
+ if (attribute & PIO_PULLUP)
+ pio->PIO_PUER = mask;
+ else
+ pio->PIO_PUDR = mask;
+
+ /* Enable Input Filter if necessary */
+ if (attribute & (PIO_DEGLITCH | PIO_DEBOUNCE))
+ pio->PIO_IFER = mask;
+ else
+ pio->PIO_IFDR = mask;
+
+ /* Enable de-glitch or de-bounce if necessary */
+ if (attribute & PIO_DEGLITCH)
+ pio->PIO_IFSCDR = mask;
+ else {
+ if (attribute & PIO_DEBOUNCE)
+ pio->PIO_IFSCER = mask;
+ }
+
+ /* Configure additional interrupt mode registers */
+ if (attribute & PIO_IT_AIME) {
+ // enable additional interrupt mode
+ pio->PIO_AIMER = mask;
+
+ // if bit field of selected pin is 1, set as Rising Edge/High level detection event
+ if (attribute & PIO_IT_RE_OR_HL)
+ pio->PIO_REHLSR = mask;
+ else
+ pio->PIO_FELLSR = mask;
+
+ /* if bit field of selected pin is 1, set as edge detection source */
+ if (attribute & PIO_IT_EDGE)
+ pio->PIO_ESR = mask;
+ else
+ pio->PIO_LSR = mask;
+ } else {
+ /* disable additional interrupt mode */
+ pio->PIO_AIMDR = mask;
+ }
+
+ /* Configure pin as input */
+ pio->PIO_ODR = mask;
+ pio->PIO_PER = mask;
+}
+
+/**
+ * \brief Configures 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 pio Pointer to a PIO controller.
+ * \param mask Bitmask indicating which pin(s) to configure.
+ * \param defaultValue Default level on the pin(s).
+ * \param enableMultiDrive Indicates if the pin(s) shall be configured as
+ * open-drain.
+ * \param enablePullUp Indicates if the pin shall have its pull-up activated.
+ */
+static void PIO_SetOutput(
+ Pio *pio,
+ unsigned int mask,
+ unsigned char defaultValue,
+ unsigned char enableMultiDrive,
+ unsigned char enablePullUp)
+{
+ /* Disable interrupts */
+ pio->PIO_IDR = mask;
+
+ /* Enable pull-up(s) if necessary */
+ if (enablePullUp)
+ pio->PIO_PUER = mask;
+ else
+ pio->PIO_PUDR = mask;
+
+ /* Enable multi-drive if necessary */
+ if (enableMultiDrive)
+ pio->PIO_MDER = mask;
+ else
+ pio->PIO_MDDR = mask;
+
+ /* Set default value */
+ if (defaultValue)
+ pio->PIO_SODR = mask;
+ else
+ pio->PIO_CODR = mask;
+
+ /* Configure pin(s) as output(s) */
+ pio->PIO_OER = mask;
+ pio->PIO_PER = mask;
+}
+
+/*----------------------------------------------------------------------------
+ * Global functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Configures a list of Pin instances, each of which can either hold a
+ * single pin or a group of pins, depending on the mask value; all pins are
+ * configured by this function. The size of the array must also be provided and
+ * is easily computed using PIO_LISTSIZE whenever its length is not known in
+ * advance.
+ *
+ * \param list Pointer to a list of Pin instances.
+ * \param size Size of the Pin list (calculated using PIO_LISTSIZE).
+ *
+ * \return 1 if the pins have been configured properly; otherwise 0.
+ */
+uint8_t PIO_Configure(const Pin *list, uint32_t size)
+{
+ /* Configure pins */
+ while (size > 0) {
+ switch (list->type) {
+ case PIO_PERIPH_A:
+ PIO_SetPeripheralA(list->pio,
+ list->mask,
+ (list->attribute & PIO_PULLUP) ? 1 : 0);
+ break;
+
+ case PIO_PERIPH_B:
+ PIO_SetPeripheralB(list->pio,
+ list->mask,
+ (list->attribute & PIO_PULLUP) ? 1 : 0);
+ break;
+
+ case PIO_PERIPH_C:
+ PIO_SetPeripheralC(list->pio,
+ list->mask,
+ (list->attribute & PIO_PULLUP) ? 1 : 0);
+ break;
+
+ case PIO_PERIPH_D:
+ PIO_SetPeripheralD(list->pio,
+ list->mask,
+ (list->attribute & PIO_PULLUP) ? 1 : 0);
+ break;
+
+ case PIO_INPUT:
+#ifndef __FPGA
+ PMC_EnablePeripheral(list->id);
+#endif
+ PIO_SetInput(list->pio,
+ list->mask,
+ list->attribute);
+ break;
+
+ case PIO_OUTPUT_0:
+ case PIO_OUTPUT_1:
+ PIO_SetOutput(list->pio,
+ list->mask,
+ (list->type == PIO_OUTPUT_1),
+ (list->attribute & PIO_OPENDRAIN) ? 1 : 0,
+ (list->attribute & PIO_PULLUP) ? 1 : 0);
+ break;
+
+ default: return 0;
+ }
+
+ list++;
+ size--;
+ }
+
+ return 1;
+}
+
+/**
+ * \brief Sets a high output level on all the PIOs defined in the given Pin
+ * instance.
+ * This has no immediate effects on PIOs that are not output, but the PIO
+ * controller will memorize the value they are changed to outputs.
+ *
+ * \param pin Pointer to a Pin instance describing one or more pins.
+ */
+void PIO_Set(const Pin *pin)
+{
+ pin->pio->PIO_SODR = pin->mask;
+}
+
+/**
+ * \brief Sets a low output level on all the PIOs defined in the given Pin
+ * instance.
+ * This has no immediate effects on PIOs that are not output, but the PIO
+ * controller will memorize the value they are changed to outputs.
+ *
+ * \param pin Pointer to a Pin instance describing one or more pins.
+ */
+void PIO_Clear(const Pin *pin)
+{
+ pin->pio->PIO_CODR = pin->mask;
+}
+
+/**
+ * \brief Returns 1 if one or more PIO 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_GetOutputDataStatus() instead.
+ *
+ * \param pin Pointer to a Pin instance describing one or more pins.
+ *
+ * \return 1 if the Pin instance contains at least one PIO that currently has
+ * a high level; otherwise 0.
+ */
+unsigned char PIO_Get(const Pin *pin)
+{
+ unsigned int reg;
+
+ if ((pin->type == PIO_OUTPUT_0) || (pin->type == PIO_OUTPUT_1))
+ reg = pin->pio->PIO_ODSR;
+ else
+ reg = pin->pio->PIO_PDSR;
+
+ if ((reg & pin->mask) == 0)
+ return 0;
+ else
+ return 1;
+}
+
+/**
+ * \brief Returns 1 if one or more PIO 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 pin Pointer to a Pin instance describing one or more pins.
+ *
+ * \return 1 if the Pin instance contains at least one PIO that is configured
+ * to output a high level; otherwise 0.
+ */
+unsigned char PIO_GetOutputDataStatus(const Pin *pin)
+{
+ if ((pin->pio->PIO_ODSR & pin->mask) == 0)
+ return 0;
+ else
+ return 1;
+}
+
+/**
+ * \brief Configures Glitch or Denouncing filter for input.
+ *
+ * \param pin Pointer to a Pin instance describing one or more pins.
+ * \param cuttoff Cut off frequency for denounce filter.
+ */
+void PIO_SetDebounceFilter(const Pin *pin, uint32_t cuttoff)
+{
+ Pio *pio = pin->pio;
+
+ pio->PIO_IFSCER = pin->mask; /* set Denouncing, 0 bit field no effect */
+ pio->PIO_SCDR = ((32678 / (2 * (cuttoff))) - 1) & 0x3FFF;
+ /* the lowest 14 bits work */
+}
+
+/**
+ * \brief Enable write protect.
+ *
+ * \param pin Pointer to a Pin instance describing one or more pins.
+ */
+void PIO_EnableWriteProtect(const Pin *pin)
+{
+ Pio *pio = pin->pio;
+
+ pio->PIO_WPMR = (PIO_WPMR_WPKEY_VALID | PIO_WPMR_WPEN_EN);
+}
+
+/**
+ * \brief Disable write protect.
+ *
+ * \param pin Pointer to a Pin instance describing one or more pins.
+ */
+
+void PIO_DisableWriteProtect(const Pin *pin)
+{
+ Pio *pio = pin->pio;
+
+ pio->PIO_WPMR = (PIO_WPMR_WPKEY_VALID | PIO_WPMR_WPEN_DIS);
+}
+
+/**
+ * \brief Get write protect violation information.
+ *
+ * \param pin Pointer to a Pin instance describing one or more pins.
+ */
+uint32_t PIO_GetWriteProtectViolationInfo(const Pin *pin)
+{
+ Pio *pio = pin->pio;
+ return (pio->PIO_WPSR);
+}
+
+/**
+ * \brief Set pin type
+ * the pin is controlled by the corresponding peripheral (A, B, C, D,E)
+ * \param pin Pointer to a Pin instance describing one or more pins.
+ * \param pinType PIO_PERIPH_A, PIO_PERIPH_B, ...
+ */
+void PIO_SetPinType(Pin *pin, uint8_t pinType)
+{
+ pin->type = pinType;
+}
+
+/**
+ * \brief Set the drive strength of the pin.
+ *
+ * \param pin Pointer to a Pin instance describing one or more pins.
+ * \param strength 0 for low drive strength or 1 for high drive strength.
+ */
+void PIO_SetDriveStrength(const Pin *pin, uint8_t strength)
+{
+ Pio *pio = pin->pio;
+
+ if (strength) {
+ pio->PIO_DRIVER |= pin->mask;
+ } else {
+ pio->PIO_DRIVER &= ~(pin->mask);
+ }
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/pio_capture.c b/bsps/arm/atsam/contrib/libraries/libchip/source/pio_capture.c
new file mode 100644
index 0000000000..10528c1bcc
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/pio_capture.c
@@ -0,0 +1,255 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup pio_capture_module Working with PIO Parallel Capture Mode
+ * \ingroup peripherals_module
+ * The PIO Parallel Capture Mode driver provides the interface to configure
+ * and use the PIO Parallel Capture Mode peripheral.\n
+ *
+ * The PIO Controller integrates an interface able to read data from a CMOS digital
+ * image sensor, a high-speed parallel ADC, a DSP synchronous port in synchronous
+ * mode, etc.... For better understanding and to ease reading, the following
+ * description uses an example with a CMOS digital image sensor
+ *
+ * To use the PIO Parallel Capture, the user has to follow these few steps:
+ * <ul>
+ * <li> Enable PIOA peripheral clock </li>
+ * <li> Configure the PDC </li>
+ * <li> Configure the PIO Capture interrupt </li>
+ * <li> Enable the PDC </li>
+ * <li> Enable the PIO Capture </li>
+ * <li> Wait for interrupt </li>
+ * <li> Disable the interrupt </li>
+ * <li> Read the DATA </li>
+ * </ul>
+ *
+ * For more accurate information, please look at the PIO Parallel Capture Mode
+ * section of the Datasheet.
+ *
+ * <b>API Usage:</b>
+ *
+ * -# Configurate the interrupt for PIOA, can be done by
+ * PIO_InitializeInterrupts()
+ * -# Initialize the PIO Parallel Capture API by filing the SpioCaptureInit
+ * structure
+ * options:
+ * - alwaysSampling: for sample data with or without take in account
+ * ENABLE pins.
+ * - halfSampling: for sample all data or only one time out of two
+ * -# Call PIO_CaptureInit() for init and enable the PDC, init the PIO capture.
+ * -# Call PIO_CaptureEnable() for enable the PIO Parallel Capture.
+ * -# When an interrupt is received, the PIO_CaptureHandler() is call and the
+ * respective callback is launch.
+ * -# When the transfer is complete, the user need to disable interrupt with
+ * PIO_CaptureDisableIt(). Otherwise, the PDC will send an interrupt.
+ * -# The data receive by the PIO Parallel Capture is inside the buffer passed
+ * in the PIO_CaptureInit().
+ *
+ * Related files :\n
+ * \ref pio_capture.c\n
+ * \ref pio_capture.h\n
+ */
+/*@{*/
+/*@}*/
+/**
+ * \file
+ *
+ * Implementation of PIO Parallel Capture.
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+#include <assert.h>
+
+#define PIO_PCISR_RXBUFF (0x1u<<3)
+#define PIO_PCISR_ENDRX (0x1u<<2)
+/*----------------------------------------------------------------------------
+ * Local Functions
+ *----------------------------------------------------------------------------*/
+/** Copy the API structure for interrupt handler */
+static SpioCaptureInit *_PioCaptureCopy;
+
+/*----------------------------------------------------------------------------
+ * Global Functions
+ *----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/**
+ * \brief The PIO_CaptureHandler must be called by the PIO Capture Interrupt
+ * Service Routine with the corresponding PIO Capture instance.
+ */
+/*----------------------------------------------------------------------------*/
+extern void PIO_CaptureHandler(void)
+{
+ volatile uint32_t pio_captureSr;
+ uint32_t k;
+
+ /* Read the status register*/
+ pio_captureSr = PIOA->PIO_PCISR;
+ k = pio_captureSr;
+ pio_captureSr = k & PIOA->PIO_PCIMR;
+
+ if (pio_captureSr & PIO_PCISR_DRDY) {
+ /* Parallel Capture Mode Data Ready */
+ if (_PioCaptureCopy->CbkDataReady != NULL)
+ _PioCaptureCopy->CbkDataReady(_PioCaptureCopy);
+ else
+ TRACE_DEBUG("IT PIO Capture Data Ready received (no callback)\n\r");
+ }
+
+ if (pio_captureSr & PIO_PCISR_OVRE) {
+ /* Parallel Capture Mode Overrun Error */
+ if (_PioCaptureCopy->CbkOverrun != NULL)
+ _PioCaptureCopy->CbkOverrun(_PioCaptureCopy);
+ else
+ TRACE_DEBUG("IT PIO Capture Overrun Error received (no callback)\n\r");
+ }
+
+ if (pio_captureSr & PIO_PCISR_RXBUFF) {
+ /* Reception Buffer Full */
+ if (_PioCaptureCopy->CbkBuffFull != NULL)
+ _PioCaptureCopy->CbkBuffFull(_PioCaptureCopy);
+ else {
+ TRACE_DEBUG("IT PIO Capture Reception Buffer Full received \
+ (no callback)\n\r");
+ }
+ }
+
+ if (pio_captureSr & PIO_PCISR_ENDRX) {
+ /* End of Reception Transfer */
+ if (_PioCaptureCopy->CbkEndReception != NULL)
+ _PioCaptureCopy->CbkEndReception(_PioCaptureCopy);
+ else {
+ TRACE_DEBUG("IT PIO Capture End of Reception Transfer \
+ received (no callback)\n\r");
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * \brief Disable Interrupt of the PIO Capture
+ * \param itToDisable : Interrupt to disable
+ */
+/*----------------------------------------------------------------------------*/
+void PIO_CaptureDisableIt(uint32_t itToDisable)
+{
+ /* Parallel capture mode is enabled */
+ PIOA->PIO_PCIDR = itToDisable;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * \brief Enable Interrupt of the PIO Capture
+ * \param itToEnable : Interrupt to enable
+ */
+/*----------------------------------------------------------------------------*/
+void PIO_CaptureEnableIt(uint32_t itToEnable)
+{
+ /* Parallel capture mode is enabled */
+ PIOA->PIO_PCIER = itToEnable;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * \brief Enable the PIO Capture
+ */
+/*----------------------------------------------------------------------------*/
+void PIO_CaptureEnable(void)
+{
+ /* PDC: Receive Pointer Register */
+ // PIOA->PIO_RPR = (uint32_t)_PioCaptureCopy->pData;
+ // /* PDC: Receive Counter Register */
+ // /* Starts peripheral data transfer if corresponding channel is active */
+ // PIOA->PIO_RCR = PIO_RCR_RXCTR(_PioCaptureCopy->dPDCsize);
+
+ /* Parallel capture mode is enabled */
+ PIOA->PIO_PCMR |= PIO_PCMR_PCEN;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * \brief Disable the PIO Capture
+ */
+/*----------------------------------------------------------------------------*/
+void PIO_CaptureDisable(void)
+{
+ /* Parallel capture mode is disabled */
+ PIOA->PIO_PCMR &= (uint32_t)(~PIO_PCMR_PCEN);
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * \brief Initialize the PIO Capture
+ * \param dsize :
+ * 0 = The reception data in the PIO_PCRHR register is a BYTE (8-bit).
+ * 1 = The reception data in the PIO_PCRHR register is a HALF-WORD (16-bit).
+ * 2/3 = The reception data in the PIO_PCRHR register is a WORD (32-bit).
+ * \param alwaysSampling: ALWYS: Parallel Capture Mode Always Sampling
+ * 0 = The parallel capture mode samples the data when both data enables are active.
+ * 1 = The parallel capture mode samples the data whatever the data enables are.
+ * \param halfSampling: HALFS: Parallel Capture Mode Half Sampling
+ * 0 = The parallel capture mode samples all the data.
+ * 1 = The parallel capture mode samples the data only one time out of two.
+ * \param modeFirstSample: FRSTS: Parallel Capture Mode First Sample
+ * This bit is useful only if the HALFS bit is set to 1. If data are numbered
+ * in the order that they are received with an index from 0 to n:
+ * 0 = Only data with an even index are sampled.
+ * 1 = Only data with an odd index are sampled.
+ */
+/*----------------------------------------------------------------------------*/
+void PIO_CaptureInit(SpioCaptureInit *pInit)
+{
+ PMC_EnablePeripheral(ID_PIOA);
+
+ assert((pInit->dsize < 0x4));
+ assert((pInit->alwaysSampling < 2));
+ assert((pInit->halfSampling < 2));
+ assert((pInit->modeFirstSample < 2));
+ /* Copy the API structure for interrupt handler */
+ _PioCaptureCopy = pInit;
+
+ if (pInit->CbkDataReady != NULL)
+ PIOA->PIO_PCIER = PIO_PCISR_DRDY;
+
+ if (pInit->CbkOverrun != NULL)
+ PIOA->PIO_PCIER = PIO_PCISR_OVRE;
+
+ if (pInit->CbkEndReception != NULL)
+ PIOA->PIO_PCIER = PIO_PCISR_ENDRX;
+
+ if (pInit->CbkBuffFull != NULL)
+ PIOA->PIO_PCIER = PIO_PCISR_RXBUFF;
+}
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/pio_it.c b/bsps/arm/atsam/contrib/libraries/libchip/source/pio_it.c
new file mode 100644
index 0000000000..2c619db136
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/pio_it.c
@@ -0,0 +1,283 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/*
+ * \file
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+#include <rtems/irq-extension.h>
+#include <rtems/sysinit.h>
+#include <bsp/fatal.h>
+
+/*----------------------------------------------------------------------------
+ * Local definitions
+ *----------------------------------------------------------------------------*/
+
+/* Maximum number of interrupt sources that can be defined. This
+ * constant can be increased, but the current value is the smallest possible
+ * that will be compatible with all existing projects. */
+#define MAX_INTERRUPT_SOURCES 7
+
+/*----------------------------------------------------------------------------
+ * Local types
+ *----------------------------------------------------------------------------*/
+
+/**
+ * Describes a PIO interrupt source, including the PIO instance triggering the
+ * interrupt and the associated interrupt handler.
+ */
+typedef struct _InterruptSource {
+ /* Pointer to the source pin instance. */
+ const Pin *pPin;
+
+ /* Interrupt handler. */
+ void (*handler)(const Pin *, void *arg);
+
+ void *arg;
+} InterruptSource;
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ *----------------------------------------------------------------------------*/
+
+/* List of interrupt sources. */
+static InterruptSource _aIntSources[MAX_INTERRUPT_SOURCES];
+
+/* Number of currently defined interrupt sources. */
+static uint32_t _dwNumSources = 0;
+
+/*----------------------------------------------------------------------------
+ * Local Functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Handles all interrupts on the given PIO controller.
+ * \param id PIO controller ID.
+ * \param pPio PIO controller base address.
+ */
+static void PIO_Interrupt(Pio *pPio, uint32_t id)
+{
+ uint32_t status;
+ size_t i;
+
+ status = pPio->PIO_ISR;
+ status &= pPio->PIO_IMR;
+
+ for (i = 0; status != 0 && i < MAX_INTERRUPT_SOURCES; ++i) {
+ const InterruptSource *is = &_aIntSources[i];
+ const Pin *pin = is->pPin;;
+
+ if (pin->id == id) {
+ uint32_t mask = pin->mask;
+
+ if ((status & mask) != 0) {
+ status &= ~mask;
+ (*is->handler)(pin, is->arg);
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * Global Functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Parallel IO Controller A interrupt handler
+ * \Redefined PIOA interrupt handler for NVIC interrupt table.
+ */
+static void PIOA_Interrupt(void *arg)
+{
+ PIO_Interrupt(arg, ID_PIOA);
+}
+
+/**
+ * \brief Parallel IO Controller B interrupt handler
+ * \Redefined PIOB interrupt handler for NVIC interrupt table.
+ */
+static void PIOB_Interrupt(void *arg)
+{
+ PIO_Interrupt(arg, ID_PIOB);
+}
+
+/**
+ * \brief Parallel IO Controller C interrupt handler
+ * \Redefined PIOC interrupt handler for NVIC interrupt table.
+ */
+static void PIOC_Interrupt(void *arg)
+{
+ PIO_Interrupt(arg, ID_PIOC);
+}
+
+
+/**
+ * \brief Parallel IO Controller D interrupt handler
+ * \Redefined PIOD interrupt handler for NVIC interrupt table.
+ */
+static void PIOD_Interrupt(void *arg)
+{
+ PIO_Interrupt(arg, ID_PIOD);
+}
+
+/**
+ * \brief Parallel IO Controller E interrupt handler
+ * \Redefined PIOE interrupt handler for NVIC interrupt table.
+ */
+static void PIOE_Interrupt(void *arg)
+{
+ PIO_Interrupt(arg, ID_PIOE);
+}
+
+static void PIO_SysInitializeInterrupts(void)
+{
+ rtems_status_code sc;
+
+ TRACE_DEBUG("PIO_Initialize()\n\r");
+
+ /* Configure PIO interrupt sources */
+ TRACE_DEBUG("PIO_Initialize: Configuring PIOA\n\r");
+ PMC_EnablePeripheral(ID_PIOA);
+ PIOA->PIO_ISR;
+ PIOA->PIO_IDR = 0xFFFFFFFF;
+ sc = rtems_interrupt_handler_install(
+ PIOA_IRQn,
+ "PIO A",
+ RTEMS_INTERRUPT_UNIQUE,
+ PIOA_Interrupt,
+ PIOA
+ );
+ if (sc != RTEMS_SUCCESSFUL) {
+ bsp_fatal(ATSAM_FATAL_PIO_IRQ_A);
+ }
+
+ TRACE_DEBUG("PIO_Initialize: Configuring PIOB\n\r");
+ PMC_EnablePeripheral(ID_PIOB);
+ PIOB->PIO_ISR;
+ PIOB->PIO_IDR = 0xFFFFFFFF;
+ sc = rtems_interrupt_handler_install(
+ PIOB_IRQn,
+ "PIO B",
+ RTEMS_INTERRUPT_UNIQUE,
+ PIOB_Interrupt,
+ PIOB
+ );
+ if (sc != RTEMS_SUCCESSFUL) {
+ bsp_fatal(ATSAM_FATAL_PIO_IRQ_B);
+ }
+
+ TRACE_DEBUG("PIO_Initialize: Configuring PIOC\n\r");
+ PMC_EnablePeripheral(ID_PIOC);
+ PIOC->PIO_ISR;
+ PIOC->PIO_IDR = 0xFFFFFFFF;
+ sc = rtems_interrupt_handler_install(
+ PIOC_IRQn,
+ "PIO C",
+ RTEMS_INTERRUPT_UNIQUE,
+ PIOC_Interrupt,
+ PIOC
+ );
+ if (sc != RTEMS_SUCCESSFUL) {
+ bsp_fatal(ATSAM_FATAL_PIO_IRQ_C);
+ }
+
+ TRACE_DEBUG("PIO_Initialize: Configuring PIOD\n\r");
+ PMC_EnablePeripheral(ID_PIOD);
+ PIOD->PIO_ISR;
+ PIOD->PIO_IDR = 0xFFFFFFFF;
+ sc = rtems_interrupt_handler_install(
+ PIOD_IRQn,
+ "PIO D",
+ RTEMS_INTERRUPT_UNIQUE,
+ PIOD_Interrupt,
+ PIOD
+ );
+ if (sc != RTEMS_SUCCESSFUL) {
+ bsp_fatal(ATSAM_FATAL_PIO_IRQ_D);
+ }
+
+ TRACE_DEBUG("PIO_Initialize: Configuring PIOE\n\r");
+ PMC_EnablePeripheral(ID_PIOE);
+ PIOE->PIO_ISR;
+ PIOE->PIO_IDR = 0xFFFFFFFF;
+ sc = rtems_interrupt_handler_install(
+ PIOE_IRQn,
+ "PIO E",
+ RTEMS_INTERRUPT_UNIQUE,
+ PIOE_Interrupt,
+ PIOE
+ );
+ if (sc != RTEMS_SUCCESSFUL) {
+ bsp_fatal(ATSAM_FATAL_PIO_IRQ_E);
+ }
+}
+
+RTEMS_SYSINIT_ITEM(PIO_SysInitializeInterrupts, RTEMS_SYSINIT_BSP_START,
+ RTEMS_SYSINIT_ORDER_LAST);
+
+/**
+ * Configures a PIO or a group of PIO to generate an interrupt on status
+ * change. The provided interrupt handler will be called with the triggering
+ * pin as its parameter (enabling different pin instances to share the same
+ * handler).
+ * \param pPin Pointer to a Pin instance.
+ * \param handler Interrupt handler function pointer.
+ * \param arg Pointer to interrupt handler argument
+ */
+void PIO_ConfigureIt(const Pin *pPin, void (*handler)(const Pin *, void *arg),
+ void *arg)
+{
+ InterruptSource *pSource;
+ rtems_interrupt_level level;
+
+ TRACE_DEBUG("PIO_ConfigureIt()\n\r");
+
+ rtems_interrupt_disable(level);
+
+ if (_dwNumSources == MAX_INTERRUPT_SOURCES) {
+ bsp_fatal(ATSAM_FATAL_PIO_CONFIGURE_IT);
+ }
+
+ pSource = &(_aIntSources[_dwNumSources]);
+ pSource->pPin = pPin;
+ pSource->handler = handler;
+ pSource->arg = arg;
+
+ _dwNumSources++;
+
+ rtems_interrupt_enable(level);
+
+ /* Define new source */
+ TRACE_DEBUG("PIO_ConfigureIt: Defining new source #%d.\n\r", _dwNumSources);
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/pmc.c b/bsps/arm/atsam/contrib/libraries/libchip/source/pmc.c
new file mode 100644
index 0000000000..08df61ef8a
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/pmc.c
@@ -0,0 +1,597 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup pmc_module Working with PMC
+ * The PMC driver provides the Interface to configure the Power Management
+ * Controller (PMC).
+ *
+ * \section Usage
+ * <ul>
+ * <li> Enables/Disable the clock of a peripheral by using
+ * PMC_EnablePeripheral() and PMC_DisablePeripheral().</li>
+ * <li> Enables/Disable the clock of all peripherals by using
+ * PMC_EnableAllPeripherals() and PMC_DisableAllPeripherals().</li>
+ * <li> Get status of a peripheral using PMC_IsPeriphEnabled().</li>
+ * <li> Manage the clocks using PMC_EnableExtOsc(), PMC_DisableExtOsc(),
+ * PMC_SelectExtOsc(), PMC_SelectExtBypassOsc(), PMC_EnableIntRC4_8_12MHz(),
+ * PMC_DisableIntRC4_8_12MHz(), PMC_SetPllaClock(), PMC_SetMckSelection(),
+ * PMC_DisableAllClocks(), PMC_ConfigureMckWithPlla(),
+ * PMC_EnableXT32KFME() and PMC_ConfigurePCK2().</li>
+ *
+ * </ul>
+ * For more accurate information, please look at the PMC section of the Datasheet.
+ *
+ * Related files :\n
+ * \ref pmc.c\n
+ * \ref pmc.h.\n
+*/
+
+/**
+* \file
+*
+* \section Purpose
+*
+* Interface for configuring and using Power Management Controller (PMC)
+* peripherals.
+*
+*/
+
+/**
+ * \file
+ *
+ * Implementation of Power Management Controller (PMC).
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+#include <assert.h>
+
+/*----------------------------------------------------------------------------
+ * Local definitions
+ *----------------------------------------------------------------------------*/
+
+#define MASK_STATUS0 0xFFFFFFFC
+#define MASK_STATUS1 0xFFFFFFFF
+
+/*----------------------------------------------------------------------------
+ * Local functions
+ *----------------------------------------------------------------------------*/
+/**
+ * \brief Switch MCK to PLLA clock.
+ */
+static void _PMC_SwitchMck2PllaClock(void)
+
+{
+ /* Select PLLA as input clock for MCK */
+ PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_PLLA_CLK;
+
+ /* Wait until the master clock is established */
+ while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
+}
+
+/**
+ * \brief Switch MCK to main clock.
+ */
+static void _PMC_SwitchMck2MainClock(void)
+{
+ /* Select Main Oscillator as input clock for MCK */
+ PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
+
+ /* Wait until the master clock is established */
+ while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
+
+ PMC->PMC_MCKR = PMC_MCKR_CSS_MAIN_CLK;
+
+ while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
+}
+
+/**
+ * \brief Switch MCK to slow clock.
+ */
+static void _PMC_SwitchMck2SlowClock(void)
+{
+ /* Select Slow Clock as input clock for MCK */
+ PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_SLOW_CLK;
+
+ /* Wait until the master clock is established */
+ while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
+}
+
+/**
+ * \brief Set prescaler for MCK.
+ *
+ * \param prescaler Master Clock prescaler
+ */
+static void _PMC_SetMckPrescaler(uint32_t prescaler)
+{
+ /* Change MCK Prescaler divider in PMC_MCKR register */
+ PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_PRES_Msk) | prescaler;
+
+ /* Wait until the master clock is established */
+ while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
+}
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Enables the clock of a peripheral. The peripheral ID is used
+ * to identify which peripheral is targeted.
+ *
+ * \note The ID must NOT be shifted (i.e. 1 << ID_xxx).
+ *
+ * \param id Peripheral ID (ID_xxx).
+ */
+void PMC_EnablePeripheral(uint32_t dwId)
+{
+ assert(dwId < 63);
+
+ if (dwId < 32) {
+ if ((PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId)) {
+ TRACE_DEBUG("PMC_EnablePeripheral: clock of peripheral" \
+ " %u is already enabled\n\r", (unsigned int)dwId);
+ } else
+ PMC->PMC_PCER0 = 1 << dwId;
+ } else {
+ dwId -= 32;
+
+ if ((PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId)) {
+ TRACE_DEBUG("PMC_EnablePeripheral: clock of peripheral" \
+ " %u is already enabled\n\r", (unsigned int)(dwId + 32));
+ } else
+ PMC->PMC_PCER1 = 1 << dwId;
+ }
+}
+
+/**
+ * \brief Disables the clock of a peripheral. The peripheral ID is used
+ * to identify which peripheral is targeted.
+ *
+ * \note The ID must NOT be shifted (i.e. 1 << ID_xxx).
+ *
+ * \param id Peripheral ID (ID_xxx).
+ */
+void PMC_DisablePeripheral(uint32_t dwId)
+{
+ assert(dwId < 63);
+
+ if (dwId < 32) {
+ if ((PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) != ((uint32_t)1 << dwId)) {
+ TRACE_DEBUG("PMC_DisablePeripheral: clock of peripheral" \
+ " %u is not enabled\n\r", (unsigned int)dwId);
+ } else
+ PMC->PMC_PCDR0 = 1 << dwId;
+ } else {
+ dwId -= 32;
+
+ if ((PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) != ((uint32_t)1 << dwId)) {
+ TRACE_DEBUG("PMC_DisablePeripheral: clock of peripheral"
+ " %u is not enabled\n\r", (unsigned int)(dwId + 32));
+ } else
+ PMC->PMC_PCDR1 = 1 << dwId;
+ }
+}
+
+/**
+ * \brief Enable all the periph clock via PMC.
+ */
+void PMC_EnableAllPeripherals(void)
+{
+ PMC->PMC_PCER0 = MASK_STATUS0;
+
+ while ((PMC->PMC_PCSR0 & MASK_STATUS0) != MASK_STATUS0);
+
+ PMC->PMC_PCER1 = MASK_STATUS1;
+
+ while ((PMC->PMC_PCSR1 & MASK_STATUS1) != MASK_STATUS1);
+
+ TRACE_DEBUG("Enable all periph clocks\n\r");
+}
+
+/**
+ * \brief Disable all the periph clock via PMC.
+ */
+void PMC_DisableAllPeripherals(void)
+{
+ PMC->PMC_PCDR0 = MASK_STATUS0;
+
+ while ((PMC->PMC_PCSR0 & MASK_STATUS0) != 0);
+
+ PMC->PMC_PCDR1 = MASK_STATUS1;
+
+ while ((PMC->PMC_PCSR1 & MASK_STATUS1) != 0);
+
+ TRACE_DEBUG("Disable all periph clocks\n\r");
+}
+
+/**
+ * \brief Get Periph Status for the given peripheral ID.
+ *
+ * \param id Peripheral ID (ID_xxx).
+ */
+uint32_t PMC_IsPeriphEnabled(uint32_t dwId)
+{
+ assert(dwId < ID_PERIPH_COUNT);
+
+ if (dwId < 32)
+ return (PMC->PMC_PCSR0 & (1 << dwId));
+ else
+ return (PMC->PMC_PCSR1 & (1 << (dwId - 32)));
+}
+
+
+/**
+ * \brief Enable external oscillator as main clock input.
+ */
+void PMC_EnableExtOsc(void)
+{
+ uint32_t read_MOR;
+
+ /* Before switching MAIN OSC on external crystal : enable it and don't disable
+ * at the same time RC OSC in case of if MAIN OSC is still using RC OSC
+ */
+
+ read_MOR = PMC->CKGR_MOR;
+ read_MOR &= ~CKGR_MOR_MOSCRCF_Msk;
+ /* reset MOSCRCF field in MOR register before select RC 12MHz */
+ read_MOR |= (CKGR_MOR_KEY_PASSWD
+ | CKGR_MOR_MOSCRCF_12_MHz
+ | CKGR_MOR_MOSCXTEN
+ | CKGR_MOR_MOSCRCEN
+ | CKGR_MOR_MOSCXTST(DEFAUTL_MAIN_OSC_COUNT));
+ /* enable external crystal - enable RC OSC */
+
+ PMC->CKGR_MOR = read_MOR;
+
+ while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));
+
+ /* wait end of RC oscillator stabilization */
+ while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
+
+ read_MOR |= CKGR_MOR_MOSCSEL;
+ /* select external crystal */
+
+ PMC->CKGR_MOR = read_MOR;
+
+ while (!(PMC->PMC_SR & PMC_SR_MOSCSELS));
+
+ /* Wait end of Main Oscillator Selection */
+ while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
+}
+
+/**
+ * \brief Disable external 12MHz oscillator.
+ */
+void PMC_DisableExtOsc(void)
+{
+ uint32_t read_MOR;
+
+ read_MOR = PMC->CKGR_MOR;
+ read_MOR &= ~CKGR_MOR_MOSCXTEN; /* disable main xtal osc */
+ PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | read_MOR;
+
+ while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
+}
+
+/**
+ * \brief Select external OSC.
+ */
+void PMC_SelectExtOsc(void)
+{
+ /* switch from internal RC 12 MHz to external OSC 12 MHz */
+ /* wait Main XTAL Oscillator stabilisation*/
+ if ((PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) == CKGR_MOR_MOSCSEL) {
+ PMC_DisableIntRC4_8_12MHz();
+ return;
+ }
+
+ /* enable external OSC 12 MHz */
+ PMC->CKGR_MOR |= CKGR_MOR_MOSCXTEN | CKGR_MOR_KEY_PASSWD;
+
+ /* wait Main CLK Ready */
+ while (!(PMC->CKGR_MCFR & CKGR_MCFR_MAINFRDY));
+
+ /* switch MAIN clock to external OSC 12 MHz*/
+ PMC->CKGR_MOR |= CKGR_MOR_MOSCSEL | CKGR_MOR_KEY_PASSWD;
+
+ /* wait MAIN clock status change for external OSC 12 MHz selection*/
+ while (!(PMC->PMC_SR & PMC_SR_MOSCSELS));
+
+ /* in case where MCK is running on MAIN CLK */
+ while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
+
+ PMC_DisableIntRC4_8_12MHz();
+}
+
+
+/**
+ * \brief Select external OSC.
+ */
+void PMC_SelectExtBypassOsc(void)
+{
+ volatile uint32_t timeout;
+
+ if ((PMC->CKGR_MOR & CKGR_MOR_MOSCXTBY) != CKGR_MOR_MOSCXTBY) {
+ PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD |
+ CKGR_MOR_MOSCRCEN |
+ CKGR_MOR_MOSCXTST(0xFF) |
+ CKGR_MOR_MOSCXTBY;
+ PMC->CKGR_MOR |= CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCSEL;
+
+ /* wait MAIN clock status change for external OSC 12 MHz selection*/
+ while (!(PMC->PMC_SR & PMC_SR_MOSCSELS));
+
+ // Check if an external clock is provided
+ for (timeout = 0; timeout < 0xffff; timeout++);
+
+ while (!(PMC->CKGR_MCFR & CKGR_MCFR_MAINFRDY));
+ }
+}
+
+/**
+ * \brief Enable internal 4/8/12MHz fast RC as main clock input.
+ *
+ * \param freqSelect fast RC frequency (FAST_RC_4MHZ, FAST_RC_8MHZ,
+ * FAST_RC_12MHZ).
+ */
+void PMC_EnableIntRC4_8_12MHz(uint32_t freqSelect)
+{
+ /* 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 | freqSelect;
+
+ /* 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;
+
+ /* wait MAIN clock status change for Fast RC oscillator */
+ while (!(PMC->PMC_SR & PMC_SR_MOSCSELS));
+
+ /* in case where MCK is running on MAIN CLK */
+ while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
+
+}
+
+/**
+ * \brief Disable internal 4/8/12MHz fast RC.
+ */
+void PMC_DisableIntRC4_8_12MHz(void)
+{
+ uint32_t read_MOR;
+
+ read_MOR = PMC->CKGR_MOR;
+
+ read_MOR &= ~CKGR_MOR_MOSCRCF_Msk; /* reset MOSCRCF field in MOR register */
+ read_MOR &= ~CKGR_MOR_MOSCRCEN; /* disable fast RC */
+ PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | read_MOR;
+
+ while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
+}
+
+/**
+ * \brief Configure PLLA clock by giving MUL and DIV.
+ * Disable PLLA when 'mul' set to 0.
+ *
+ * \param mul PLL multiplier factor.
+ * \param div PLL divider factor.
+ */
+void PMC_SetPllaClock(uint32_t mul, uint32_t div)
+{
+ if (mul != 0) {
+ /* Init PLL speed */
+ PMC->CKGR_PLLAR = CKGR_PLLAR_ONE
+ | CKGR_PLLAR_PLLACOUNT(DEFAUTL_PLLA_COUNT)
+ | CKGR_PLLAR_MULA(mul - 1)
+ | CKGR_PLLAR_DIVA(div);
+
+ /* Wait for PLL stabilization */
+ while (!(PMC->PMC_SR & PMC_SR_LOCKA));
+ } else {
+ PMC->CKGR_PLLAR = CKGR_PLLAR_ONE; /* disable PLL A */
+ }
+}
+
+/**
+ * \brief Selection of Master Clock.
+ *
+ * \param clockSource Master Clock source.
+ * \param prescaler Master Clock prescaler.
+ *
+ * \note
+ * The PMC_MCKR register must not be programmed in a single write
+ * operation (see. Product Data Sheet).
+ */
+void PMC_SetMckSelection(uint32_t clockSource, uint32_t prescaler)
+{
+ switch (clockSource) {
+ case PMC_MCKR_CSS_SLOW_CLK :
+ _PMC_SwitchMck2SlowClock();
+ _PMC_SetMckPrescaler(prescaler);
+ break;
+
+ case PMC_MCKR_CSS_MAIN_CLK :
+ _PMC_SwitchMck2MainClock();
+ _PMC_SetMckPrescaler(prescaler);
+ break;
+
+ case PMC_MCKR_CSS_PLLA_CLK :
+ _PMC_SetMckPrescaler(prescaler);
+ _PMC_SwitchMck2PllaClock();
+ break;
+ }
+}
+
+/**
+ * \brief Disable all clocks.
+ */
+void PMC_DisableAllClocks(void)
+{
+ uint32_t read_reg;
+
+ PMC->PMC_SCDR = PMC_SCDR_PCK0 | PMC_SCDR_PCK1 | PMC_SCDR_PCK2 | PMC_SCDR_PCK3 |
+ PMC_SCDR_PCK4 | PMC_SCDR_PCK5 | PMC_SCDR_PCK6; /* disable PCK */
+
+ _PMC_SwitchMck2MainClock();
+
+ PMC->CKGR_PLLAR = PMC->CKGR_PLLAR & ~CKGR_PLLAR_MULA_Msk; /* disable PLL A */
+
+ _PMC_SwitchMck2SlowClock();
+
+ read_reg = PMC->CKGR_MOR;
+ read_reg = (read_reg & ~CKGR_MOR_MOSCRCEN) | CKGR_MOR_KEY_PASSWD;
+ /* disable RC OSC */
+
+ PMC->CKGR_MOR = read_reg;
+
+ PMC_DisableAllPeripherals(); /* disable all peripheral clocks */
+}
+
+/**
+ * \brief Configure PLLA as clock input for MCK.
+ *
+ * \param mul PLL multiplier factor (not shifted, don't minus 1).
+ * \param div PLL divider factor (not shifted).
+ * \param prescaler Master Clock prescaler (shifted as in register).
+ */
+void PMC_ConfigureMckWithPlla(uint32_t mul, uint32_t div, uint32_t prescaler)
+{
+ /* First, select Main OSC as input clock for MCK */
+ _PMC_SwitchMck2MainClock();
+
+ /* Then, Set PLLA clock */
+ PMC_SetPllaClock(mul, div);
+
+ /* Wait until the master clock is established for the case we already
+ turn on the PLL */
+ while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
+
+ /* Finally, select PllA as input clock for MCK */
+ PMC_SetMckSelection(PMC_MCKR_CSS_PLLA_CLK, prescaler);
+}
+
+
+/**
+ * \brief Configure PLLA as clock input for MCK.
+ *
+ * \param mul PLL multiplier factor (not shifted, don't minus 1).
+ * \param div PLL divider factor (not shifted).
+ * \param prescaler Master Clock prescaler (shifted as in register).
+ */
+void PMC_EnableXT32KFME(void)
+{
+
+ uint32_t read_MOR;
+
+ /* Before switching MAIN OSC on external crystal : enable it and don't
+ disable at the same time RC OSC in case of if MAIN OSC is still using
+ RC OSC */
+
+ read_MOR = PMC->CKGR_MOR;
+
+ read_MOR |= (CKGR_MOR_KEY_PASSWD | CKGR_MOR_XT32KFME);
+ /* enable external crystal - enable RC OSC */
+
+ PMC->CKGR_MOR = read_MOR;
+
+}
+
+/**
+ * \brief Configure PLLA as clock input for MCK.
+ *
+ * \param mul PLL multiplier factor (not shifted, don't minus 1).
+ * \param div PLL divider factor (not shifted).
+ * \param prescaler Master Clock prescaler (shifted as in register).
+ */
+void PMC_ConfigurePCK0(uint32_t MasterClk, uint32_t prescaler)
+{
+ PMC->PMC_SCDR = PMC_SCDR_PCK0; /* disable PCK */
+
+ while ((PMC->PMC_SCSR)& PMC_SCSR_PCK0);
+
+ PMC->PMC_PCK[0] = MasterClk | prescaler;
+ PMC->PMC_SCER = PMC_SCER_PCK0;
+
+ while (!((PMC->PMC_SR) & PMC_SR_PCKRDY0));
+
+}
+
+
+/**
+ * \brief Configure PLLA as clock input for MCK.
+ *
+ * \param mul PLL multiplier factor (not shifted, don't minus 1).
+ * \param div PLL divider factor (not shifted).
+ * \param prescaler Master Clock prescaler (shifted as in register).
+ */
+void PMC_ConfigurePCK1(uint32_t MasterClk, uint32_t prescaler)
+{
+ PMC->PMC_SCDR = PMC_SCDR_PCK1; /* disable PCK */
+
+ while ((PMC->PMC_SCSR)& PMC_SCSR_PCK1);
+
+ PMC->PMC_PCK[1] = MasterClk | prescaler;
+ PMC->PMC_SCER = PMC_SCER_PCK1;
+
+ while (!((PMC->PMC_SR) & PMC_SR_PCKRDY1));
+
+}
+
+/**
+ * \brief Configure PLLA as clock input for MCK.
+ *
+ * \param mul PLL multiplier factor (not shifted, don't minus 1).
+ * \param div PLL divider factor (not shifted).
+ * \param prescaler Master Clock prescaler (shifted as in register).
+ */
+void PMC_ConfigurePCK2(uint32_t MasterClk, uint32_t prescaler)
+{
+ PMC->PMC_SCDR = PMC_SCDR_PCK2; /* disable PCK */
+
+ while ((PMC->PMC_SCSR)& PMC_SCSR_PCK2);
+
+ PMC->PMC_PCK[2] = MasterClk | prescaler;
+ PMC->PMC_SCER = PMC_SCER_PCK2;
+
+ while (!((PMC->PMC_SR) & PMC_SR_PCKRDY2));
+
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/pwmc.c b/bsps/arm/atsam/contrib/libraries/libchip/source/pwmc.c
new file mode 100644
index 0000000000..80759f84ea
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/pwmc.c
@@ -0,0 +1,579 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup pwm_module Working with PWM
+ * \ingroup peripherals_module
+ * The PWM driver provides the interface to configure and use the PWM
+ * peripheral.
+ *
+ * The PWM macrocell controls square output waveforms of 4 channels.
+ * Characteristics of output waveforms such as period, duty-cycle,
+ * dead-time can be configured.\n
+ * Some of PWM channels can be linked together as synchronous channel and
+ * duty-cycle of synchronous channels can be updated by PDC automatically.
+ *
+ * Before enabling the channels, they must have been configured first.
+ * The main settings include:
+ * <ul>
+ * <li>Configuration of the clock generator.</li>
+ * <li>Selection of the clock for each channel.</li>
+ * <li>Configuration of output waveform characteristics, such as period,
+ * duty-cycle etc.</li>
+ * <li>Configuration for synchronous channels if needed.</li>
+ * - Selection of the synchronous channels.
+ * - Selection of the moment when the WRDY flag and the corresponding PDC
+ * transfer request are set (PTRM and PTRCS in the PWM_SCM register).
+ * - Configuration of the update mode (UPDM in the PWM_SCM register).
+ * - Configuration of the update period (UPR in the PWM_SCUP register).
+ * </ul>
+ *
+ * After the channels is enabled, the user must use respective update registers
+ * to change the wave characteristics to prevent unexpected output waveform.
+ * i.e. PWM_CDTYUPDx register should be used if user want to change duty-cycle
+ * when the channel is enabled.
+ *
+ * For more accurate information, please look at the PWM section of the
+ * Datasheet.
+ *
+ * Related files :\n
+ * \ref pwmc.c\n
+ * \ref pwmc.h.\n
+ */
+/*@{*/
+/*@}*/
+
+/**
+ * \file
+ *
+ * Implementation of the Pulse Width Modulation Controller (PWM) peripheral.
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+#include <stdint.h>
+#include <assert.h>
+
+/*----------------------------------------------------------------------------
+ * Local functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Finds a prescaler/divisor couple to generate the desired frequency
+ * from MCK.
+ *
+ * Returns the value to enter in PWM_CLK or 0 if the configuration cannot be
+ * met.
+ *
+ * \param frequency Desired frequency in Hz.
+ * \param mck Master clock frequency in Hz.
+ */
+static uint16_t FindClockConfiguration(
+ uint32_t frequency,
+ uint32_t mck)
+{
+ uint32_t divisors[11] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024};
+ uint8_t divisor = 0;
+ uint32_t prescaler;
+
+ assert(frequency <= mck);
+
+ /* Find prescaler and divisor values */
+ prescaler = (mck / divisors[divisor]) / frequency;
+
+ while ((prescaler > 255) && (divisor < 11)) {
+ divisor++;
+ prescaler = (mck / divisors[divisor]) / frequency;
+ }
+
+ /* Return result */
+ if (divisor < 11) {
+ TRACE_DEBUG("Found divisor=%u and prescaler=%u for freq=%uHz\n\r",
+ divisors[divisor], prescaler, frequency);
+
+ return prescaler | (divisor << 8);
+ } else
+ return 0;
+}
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Configures PWM a channel with the given parameters, basic configure
+ * function.
+ *
+ * The PWM controller must have been clocked in the PMC prior to calling this
+ * function.
+ * Beware: this function disables the channel. It waits until disable is effective.
+ *
+ * \param channel Channel number.
+ * \param prescaler Channel prescaler.
+ * \param alignment Channel alignment.
+ * \param polarity Channel polarity.
+ */
+void PWMC_ConfigureChannel(
+ Pwm *pPwm,
+ uint8_t channel,
+ uint32_t prescaler,
+ uint32_t alignment,
+ uint32_t polarity)
+{
+ pPwm->PWM_CH_NUM[0].PWM_CMR = 1;
+
+ // assert(prescaler < PWM_CMR0_CPRE_MCKB);
+ assert((alignment & (uint32_t)~PWM_CMR_CALG) == 0);
+ assert((polarity & (uint32_t)~PWM_CMR_CPOL) == 0);
+
+ /* Disable channel (effective at the end of the current period) */
+ if ((pPwm->PWM_SR & (1 << channel)) != 0) {
+ pPwm->PWM_DIS = 1 << channel;
+
+ while ((pPwm->PWM_SR & (1 << channel)) != 0);
+ }
+
+ /* Configure channel */
+ pPwm->PWM_CH_NUM[channel].PWM_CMR = prescaler | alignment | polarity;
+}
+
+/**
+ * \brief Configures PWM a channel with the given parameters, extend configure
+ * function.
+ * The PWM controller must have been clocked in the PMC prior to calling this
+ * function.
+ * Beware: this function disables the channel. It waits until disable is effective.
+ *
+ * \param channel Channel number.
+ * \param prescaler Channel prescaler.
+ * \param alignment Channel alignment.
+ * \param polarity Channel polarity.
+ * \param countEventSelect Channel counter event selection.
+ * \param DTEnable Channel dead time generator enable.
+ * \param DTHInverte Channel Dead-Time PWMHx output Inverted.
+ * \param DTLInverte Channel Dead-Time PWMHx output Inverted.
+ */
+void PWMC_ConfigureChannelExt(
+ Pwm *pPwm,
+ uint8_t channel,
+ uint32_t prescaler,
+ uint32_t alignment,
+ uint32_t polarity,
+ uint32_t countEventSelect,
+ uint32_t DTEnable,
+ uint32_t DTHInverte,
+ uint32_t DTLInverte)
+{
+ // assert(prescaler < PWM_CMR0_CPRE_MCKB);
+ assert((alignment & (uint32_t)~PWM_CMR_CALG) == 0);
+ assert((polarity & (uint32_t)~PWM_CMR_CPOL) == 0);
+ assert((countEventSelect & (uint32_t)~PWM_CMR_CES) == 0);
+ assert((DTEnable & (uint32_t)~PWM_CMR_DTE) == 0);
+ assert((DTHInverte & (uint32_t)~PWM_CMR_DTHI) == 0);
+ assert((DTLInverte & (uint32_t)~PWM_CMR_DTLI) == 0);
+
+ /* Disable channel (effective at the end of the current period) */
+ if ((pPwm->PWM_SR & (1 << channel)) != 0) {
+ pPwm->PWM_DIS = 1 << channel;
+
+ while ((pPwm->PWM_SR & (1 << channel)) != 0);
+ }
+
+ /* Configure channel */
+ pPwm->PWM_CH_NUM[channel].PWM_CMR = prescaler | alignment | polarity |
+ countEventSelect | DTEnable | DTHInverte | DTLInverte;
+}
+
+/**
+ * \brief Configures PWM clocks A & B to run at the given frequencies.
+ *
+ * This function finds the best MCK divisor and prescaler values automatically.
+ *
+ * \param clka Desired clock A frequency (0 if not used).
+ * \param clkb Desired clock B frequency (0 if not used).
+ * \param mck Master clock frequency.
+ */
+void PWMC_ConfigureClocks(Pwm *pPwm, uint32_t clka, uint32_t clkb, uint32_t mck)
+{
+ uint32_t mode = 0;
+ uint32_t result;
+
+ /* Clock A */
+ if (clka != 0) {
+ result = FindClockConfiguration(clka, mck);
+ assert(result != 0);
+ mode |= result;
+ }
+
+ /* Clock B */
+ if (clkb != 0) {
+ result = FindClockConfiguration(clkb, mck);
+ assert(result != 0);
+ mode |= (result << 16);
+ }
+
+ /* Configure clocks */
+ TRACE_DEBUG("Setting PWM_CLK = 0x%08X\n\r", mode);
+ pPwm->PWM_CLK = mode;
+}
+
+/**
+ * \brief Sets the period value used by a PWM channel.
+ *
+ * This function writes directly to the CPRD register if the channel is disabled;
+ * otherwise, it uses the update register CPRDUPD.
+ *
+ * \param channel Channel number.
+ * \param period Period value.
+ */
+void PWMC_SetPeriod(Pwm *pPwm, uint8_t channel, uint16_t period)
+{
+ /* If channel is disabled, write to CPRD */
+ if ((pPwm->PWM_SR & (1 << channel)) == 0)
+
+ pPwm->PWM_CH_NUM[channel].PWM_CPRD = period;
+ else {
+ /* Otherwise use update register */
+ pPwm->PWM_CH_NUM[channel].PWM_CPRDUPD = period;
+ }
+}
+
+/**
+ * \brief Sets the duty cycle used by a PWM channel.
+ * This function writes directly to the CDTY register if the channel is disabled;
+ * otherwise it uses the update register CDTYUPD.
+ * Note that the duty cycle must always be inferior or equal to the channel
+ * period.
+ *
+ * \param channel Channel number.
+ * \param duty Duty cycle value.
+ */
+void PWMC_SetDutyCycle(Pwm *pPwm, uint8_t channel, uint16_t duty)
+{
+ assert(duty <= pPwm->PWM_CH_NUM[channel].PWM_CPRD);
+
+ /* If channel is disabled, write to CDTY */
+ if ((pPwm->PWM_SR & (1 << channel)) == 0)
+ pPwm->PWM_CH_NUM[channel].PWM_CDTY = duty;
+ else {
+ /* Otherwise use update register */
+ pPwm->PWM_CH_NUM[channel].PWM_CDTYUPD = duty;
+ }
+}
+
+/**
+ * \brief Sets the dead time used by a PWM channel.
+ * This function writes directly to the DT register if the channel is disabled;
+ * otherwise it uses the update register DTUPD.
+ * Note that the dead time must always be inferior or equal to the channel
+ * period.
+ *
+ * \param channel Channel number.
+ * \param timeH Dead time value for PWMHx output.
+ * \param timeL Dead time value for PWMLx output.
+ */
+void PWMC_SetDeadTime(Pwm *pPwm, uint8_t channel, uint16_t timeH,
+ uint16_t timeL)
+{
+ assert(timeH <= pPwm->PWM_CH_NUM[channel].PWM_CPRD);
+ assert(timeL <= pPwm->PWM_CH_NUM[channel].PWM_CPRD);
+
+ /* If channel is disabled, write to DT */
+ if ((pPwm->PWM_SR & (1 << channel)) == 0)
+ pPwm->PWM_CH_NUM[channel].PWM_DT = timeH | (timeL << 16);
+ else {
+ /* Otherwise use update register */
+ pPwm->PWM_CH_NUM[channel].PWM_DTUPD = timeH | (timeL << 16);
+ }
+}
+
+/**
+ * \brief Configures Synchronous channel with the given parameters.
+ * Beware: At this time, the channels should be disabled.
+ *
+ * \param channels Bitwise OR of Synchronous channels.
+ * \param updateMode Synchronous channel update mode.
+ * \param requestMode PDC transfer request mode.
+ * \param requestComparisonSelect PDC transfer request comparison selection.
+ */
+void PWMC_ConfigureSyncChannel(Pwm *pPwm,
+ uint32_t channels,
+ uint32_t updateMode,
+ uint32_t requestMode,
+ uint32_t requestComparisonSelect)
+{
+ pPwm->PWM_SCM = channels | updateMode | requestMode | requestComparisonSelect;
+}
+
+/**
+ * \brief Sets the update period of the synchronous channels.
+ * This function writes directly to the SCUP register if the channel #0 is disabled;
+ * otherwise it uses the update register SCUPUPD.
+ *
+ * \param period update period.
+ */
+void PWMC_SetSyncChannelUpdatePeriod(Pwm *pPwm, uint8_t period)
+{
+ /* If channel is disabled, write to SCUP */
+ if ((pPwm->PWM_SR & (1 << 0)) == 0)
+ pPwm->PWM_SCUP = period;
+ else {
+ /* Otherwise use update register */
+ pPwm->PWM_SCUPUPD = period;
+ }
+}
+
+/**
+ * \brief Sets synchronous channels update unlock.
+ *
+ * Note: If the UPDM field is set to 0, writing the UPDULOCK bit to 1
+ * triggers the update of the period value, the duty-cycle and
+ * the dead-time values of synchronous channels at the beginning
+ * of the next PWM period. If the field UPDM is set to 1 or 2,
+ * writing the UPDULOCK bit to 1 triggers only the update of
+ * the period value and of the dead-time values of synchronous channels.
+ * This bit is automatically reset when the update is done.
+ */
+void PWMC_SetSyncChannelUpdateUnlock(Pwm *pPwm)
+{
+ pPwm->PWM_SCUC = PWM_SCUC_UPDULOCK;
+}
+
+/**
+ * \brief Enables the given PWM channel.
+ *
+ * This does NOT enable the corresponding pin;this must be done in the user code.
+ *
+ * \param channel Channel number.
+ */
+void PWMC_EnableChannel(Pwm *pPwm, uint8_t channel)
+{
+ pPwm->PWM_ENA = 1 << channel;
+}
+
+/**
+ * \brief Disables the given PWM channel.
+ *
+ * Beware, channel will be effectively disabled at the end of the current period.
+ * Application can check channel is disabled using the following wait loop:
+ * while ((PWM->PWM_SR & (1 << channel)) != 0);
+ *
+ * \param channel Channel number.
+ */
+void PWMC_DisableChannel(Pwm *pPwm, uint8_t channel)
+{
+ pPwm->PWM_DIS = 1 << channel;
+}
+
+/**
+ * \brief Enables the period interrupt for the given PWM channel.
+ *
+ * \param channel Channel number.
+ */
+void PWMC_EnableChannelIt(Pwm *pPwm, uint8_t channel)
+{
+ pPwm->PWM_IER1 = 1 << channel;
+}
+
+/**
+ * \brief Return PWM Interrupt Status2 Register
+ *
+ */
+uint32_t PWMC_GetStatus2(Pwm *pPwm)
+{
+ return pPwm->PWM_ISR2;
+}
+
+/**
+ * \brief Disables the period interrupt for the given PWM channel.
+ *
+ * \param channel Channel number.
+ */
+void PWMC_DisableChannelIt(Pwm *pPwm, uint8_t channel)
+{
+ pPwm->PWM_IDR1 = 1 << channel;
+}
+
+/**
+ * \brief Enables the selected interrupts sources on a PWMC peripheral.
+ *
+ * \param sources1 Bitwise OR of selected interrupt sources of PWM_IER1.
+ * \param sources2 Bitwise OR of selected interrupt sources of PWM_IER2.
+ */
+void PWMC_EnableIt(Pwm *pPwm, uint32_t sources1, uint32_t sources2)
+{
+ pPwm->PWM_IER1 = sources1;
+ pPwm->PWM_IER2 = sources2;
+}
+
+/**
+ * \brief Disables the selected interrupts sources on a PWMC peripheral.
+ *
+ * \param sources1 Bitwise OR of selected interrupt sources of PWM_IDR1.
+ * \param sources2 Bitwise OR of selected interrupt sources of PWM_IDR2.
+ */
+void PWMC_DisableIt(Pwm *pPwm, uint32_t sources1, uint32_t sources2)
+{
+ pPwm->PWM_IDR1 = sources1;
+ pPwm->PWM_IDR2 = sources2;
+}
+
+/**
+ * \brief Set PWM output override value.
+ *
+ * \param value Bitwise OR of output override value.
+ */
+void PWMC_SetOverrideValue(Pwm *pPwm, uint32_t value)
+{
+ pPwm->PWM_OOV = value;
+}
+
+/**
+ * \brief Enable override output.
+ *
+ * \param value Bitwise OR of output selection.
+ * \param sync 0: enable the output asynchronously, 1: enable it synchronously
+ */
+void PWMC_EnableOverrideOutput(Pwm *pPwm, uint32_t value, uint32_t sync)
+{
+ if (sync)
+ pPwm->PWM_OSSUPD = value;
+ else
+ pPwm->PWM_OSS = value;
+}
+
+/**
+ * \brief Output Selection for override PWM output.
+ *
+ * \param value Bitwise OR of output override value.
+ */
+void PWMC_OutputOverrideSelection(Pwm *pPwm, uint32_t value)
+{
+ pPwm->PWM_OS = value;
+}
+
+
+/**
+ * \brief Disable override output.
+ *
+ * \param value Bitwise OR of output selection.
+ * \param sync 0: enable the output asynchronously, 1: enable it synchronously
+ */
+void PWMC_DisableOverrideOutput(Pwm *pPwm, uint32_t value, uint32_t sync)
+{
+ if (sync)
+
+ pPwm->PWM_OSCUPD = value;
+ else
+
+ pPwm->PWM_OSC = value;
+}
+
+/**
+ * \brief Set PWM fault mode.
+ *
+ * \param mode Bitwise OR of fault mode.
+ */
+void PWMC_SetFaultMode(Pwm *pPwm, uint32_t mode)
+{
+ pPwm->PWM_FMR = mode;
+}
+
+/**
+ * \brief PWM fault clear.
+ *
+ * \param fault Bitwise OR of fault to clear.
+ */
+void PWMC_FaultClear(Pwm *pPwm, uint32_t fault)
+{
+ pPwm->PWM_FCR = fault;
+}
+
+/**
+ * \brief Set PWM fault protection value.
+ *
+ * \param value Bitwise OR of fault protection value.
+ */
+void PWMC_SetFaultProtectionValue(Pwm *pPwm, uint32_t value)
+{
+ pPwm->PWM_FPV1 = value;
+}
+
+/**
+ * \brief Enable PWM fault protection.
+ *
+ * \param value Bitwise OR of FPEx[y].
+ */
+void PWMC_EnableFaultProtection(Pwm *pPwm, uint32_t value)
+{
+ pPwm->PWM_FPE = value;
+}
+
+/**
+ * \brief Configure comparison unit.
+ *
+ * \param x comparison x index
+ * \param value comparison x value.
+ * \param mode comparison x mode
+ */
+void PWMC_ConfigureComparisonUnit(Pwm *pPwm, uint32_t x, uint32_t value,
+ uint32_t mode)
+{
+ assert(x < 8);
+
+ /* If channel is disabled, write to CMPxM & CMPxV */
+ if ((pPwm->PWM_SR & (1 << 0)) == 0) {
+ pPwm->PWM_CMP[x].PWM_CMPM = mode;
+ pPwm->PWM_CMP[x].PWM_CMPV = value;
+ } else {
+ /* Otherwise use update register */
+ pPwm->PWM_CMP[x].PWM_CMPMUPD = mode;
+ pPwm->PWM_CMP[x].PWM_CMPVUPD = value;
+ }
+}
+
+/**
+ * \brief Configure event line mode.
+ *
+ * \param x Line x
+ * \param mode Bitwise OR of line mode selection
+ */
+void PWMC_ConfigureEventLineMode(Pwm *pPwm, uint32_t x, uint32_t mode)
+{
+ assert(x < 2);
+
+ if (x == 0)
+ pPwm->PWM_ELMR[0] = mode;
+ else if (x == 1)
+ pPwm->PWM_ELMR[1] = mode;
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/qspi.c b/bsps/arm/atsam/contrib/libraries/libchip/source/qspi.c
new file mode 100644
index 0000000000..314cfdf16c
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/qspi.c
@@ -0,0 +1,757 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup qspi_module Working with QSPI
+ * \ingroup peripherals_module
+ * The QSPI driver provides the interface to configure and use the QSPI
+ * peripheral.
+ *
+ * The Serial Peripheral Interface (QSPI) circuit is a synchronous serial
+ * data link that provides communication with external devices in Master
+ * or Slave Mode.
+ *
+ * To use the QSPI, the user has to follow these few steps:
+ * -# Enable the QSPI pins required by the application (see pio.h).
+ * -# Configure the QSPI using the \ref QSPI_Configure(). This enables the
+ * peripheral clock. The mode register is loaded with the given value.
+ * -# Configure all the necessary chip selects with \ref QSPI_ConfigureNPCS().
+ * -# Enable the QSPI by calling \ref QSPI_Enable().
+ * -# Send/receive data using \ref QSPI_Write() and \ref QSPI_Read(). Note that
+* \ref QSPI_Read()
+ * must be called after \ref QSPI_Write() to retrieve the last value read.
+ * -# Send/receive data using the PDC with the \ref QSPI_WriteBuffer() and
+ * \ref QSPI_ReadBuffer() functions.
+ * -# Disable the QSPI by calling \ref QSPI_Disable().
+ *
+ * For more accurate information, please look at the QSPI section of the
+ * Datasheet.
+ *
+ * Related files :\n
+ * \ref qspi.c\n
+ * \ref qspi.h.\n
+ */
+/*@{*/
+/*@}*/
+
+/**
+ * \file
+ *
+ * Implementation of Serial Peripheral Interface (QSPI) controller.
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+#include "stdlib.h"
+#include "string.h"
+
+#include <stdint.h>
+#include <bsp/iocopy.h>
+
+
+#define SCRAMBLE_KEY 0x0BADDEAD
+/*----------------------------------------------------------------------------
+ * Internal functions
+ *----------------------------------------------------------------------------*/
+
+
+
+/**
+ * \brief Configure QSPI/SPI mode
+ *
+ * \param pQspi Pointer to a Qspi instance.
+ */
+__STATIC_INLINE void QSPI_ConfigureMode(Qspi *pQspi, uint8_t dMode)
+{
+ assert(pQspi);
+ pQspi->QSPI_MR = dMode;
+}
+
+/**
+ * \brief Configure mode register of QSPI
+ *
+ * \param pQspi Pointer to a Qspi instance.
+ */
+__STATIC_INLINE void QSPI_Configure(Qspi *pQspi, uint32_t dwConfiguration)
+{
+ assert(pQspi);
+ pQspi->QSPI_MR |= dwConfiguration;
+}
+
+
+/**
+ * \brief Configures a instruction address for QSPI in QSPI mode
+ *
+ * \param pQspi Pointer to a Qspi instance.
+ * \param dwAddr Instruction Address
+ */
+__STATIC_INLINE void QSPI_SetInstAddr(Qspi *pQspi, uint32_t dwAddr)
+{
+ assert(pQspi);
+ pQspi->QSPI_IAR = dwAddr;
+}
+
+
+/**
+ * \brief Configures instruction register with a given command for QSPI
+ *
+ * \param pQspi Pointer to a Qspi instance.
+ * \param dwInst Instruction Code
+ * \param dwOpt Instruction Code option
+ */
+__STATIC_INLINE void QSPI_SetInst(Qspi *pQspi, uint8_t dwInst, uint8_t dwOpt)
+{
+ assert(pQspi);
+ pQspi->QSPI_ICR = (dwInst | QSPI_ICR_OPT(dwOpt));
+}
+
+/**
+ * \brief Configures instruction frame register of QSPI
+ *
+ * \param pQspi Pointer to a Qspi instance.
+ * \param pInstFrame Instruction Frame configuration
+ */
+__STATIC_INLINE void QSPI_SetInstFrame(Qspi *pQspi,
+ QspiInstFrame_t *pInstFrame)
+{
+ assert(pQspi);
+ pQspi->QSPI_IFR = pInstFrame->InstFrame.val;
+}
+
+/**
+ * \brief Reads the Instruction frame of QSPI
+ *
+ * \param pQspi Pointer to an Qspi instance.
+ */
+__STATIC_INLINE uint32_t QSPI_GetInstFrame(Qspi *pQspi)
+{
+ assert(pQspi);
+ return pQspi->QSPI_IFR;
+}
+
+/**
+ * \brief Read QSPI RDR register for SPI mode
+ *
+ * \param pQspi Pointer to an Qspi instance.
+ */
+__STATIC_INLINE uint16_t QSPI_ReadSPI(Qspi *pQspi)
+{
+ assert(pQspi);
+
+ while (!QSPI_GetStatus(pQspi, IsReceived));
+
+ return pQspi->QSPI_RDR;
+}
+
+
+/**
+ * \brief Write to QSPI Tx register in SPI mode
+ *
+ * \param pQspi Pointer to an Qspi instance.
+ * \param wData Data to transmit
+ */
+__STATIC_INLINE void QSPI_WriteSPI(Qspi *pQspi, uint16_t wData)
+{
+ assert(pQspi);
+
+ /* Send data */
+ while (!QSPI_GetStatus(pQspi, IsTxEmpty));
+
+ pQspi->QSPI_TDR = wData;
+
+ while (!QSPI_GetStatus(pQspi, IsTxSent));
+}
+
+/**
+ * \brief Configures QSPI scrambling with a given Key
+ *
+ * \param pQspi Pointer to an Qspi instance.
+ * \param wKey Key for scramble/unscramble
+ * \param EnableFlag Enable/disable scramble
+ * \param Random Add random value with given key
+ */
+__STATIC_INLINE void QSPI_ScrambleData(Qspi *pQspi, uint32_t wKey,
+ uint8_t EnableFlag, uint8_t Random)
+{
+ assert(pQspi);
+ assert(EnableFlag < 2);
+ assert(Random < 2);
+
+ if (EnableFlag)
+ pQspi->QSPI_SKR = wKey;
+
+ pQspi->QSPI_SMR = (EnableFlag | (Random << 1));
+}
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Enables a QSPI peripheral.
+ *
+ * \param pQspi Pointer to a Qspi instance.
+ */
+void QSPI_Enable(Qspi *pQspi)
+{
+ assert(pQspi);
+ pQspi->QSPI_CR = QSPI_CR_QSPIEN;
+
+ while (!(pQspi->QSPI_SR & QSPI_SR_QSPIENS));
+}
+
+/**
+ * \brief Disables a QSPI peripheral.
+ *
+ * \param pQspi Pointer to a Qspi instance.
+ */
+void QSPI_Disable(Qspi *pQspi)
+{
+ assert(pQspi);
+ pQspi->QSPI_CR = QSPI_CR_QSPIDIS;
+
+ while (pQspi->QSPI_SR & QSPI_SR_QSPIENS);
+}
+
+/**
+ * \brief Resets a QSPI peripheral.
+ *
+ * \param pQspi Pointer to a Qspi instance.
+ */
+void QSPI_SwReset(Qspi *pQspi)
+{
+ assert(pQspi);
+ pQspi->QSPI_CR = QSPI_CR_SWRST;
+}
+
+/**
+ * \brief Enables one or more interrupt sources of a QSPI peripheral.
+ *
+ * \param pQspi Pointer to a Qspi instance.
+ * \param sources Bitwise OR of selected interrupt sources.
+ */
+QspidStatus_t QSPI_EnableIt(Qspi *pQspi, uint32_t dwSources)
+{
+ assert(pQspi);
+ pQspi->QSPI_IER = dwSources;
+ return QSPI_SUCCESS;
+}
+
+/**
+ * \brief Disables one or more interrupt sources of a QSPI peripheral.
+ *
+ * \param pQspi Pointer to a Qspi instance.
+ * \param sources Bitwise OR of selected interrupt sources.
+ */
+QspidStatus_t QSPI_DisableIt(Qspi *pQspi, uint32_t dwSources)
+{
+ assert(pQspi);
+ pQspi->QSPI_IDR = dwSources;
+ return QSPI_SUCCESS;
+}
+
+/**
+ * \brief Return the interrupt mask register.
+ *
+ * \return Qspi interrupt mask register.
+ */
+uint32_t QSPI_GetItMask(Qspi *pQspi)
+{
+ assert(pQspi);
+ return (pQspi->QSPI_IMR);
+}
+
+/**
+ * \brief Returns enabled interrupt status
+ *
+ * \return Qspi interrupt mask register.
+ */
+uint32_t QSPI_GetEnabledItStatus(Qspi *pQspi)
+{
+ assert(pQspi);
+ return (pQspi->QSPI_IMR & QSPI_GetStatus(pQspi, (QspiStatus_t)0xFFFFFFFF));
+}
+
+/**
+ * \brief Get the current status register of the given QSPI peripheral.
+ * \note This resets the internal value of the status register, so further
+ * read may yield different values.
+ * \param pQspi Pointer to a Qspi instance.
+ * \param rStatus Compare status with given status bit
+ * \return QSPI status register.
+ */
+uint32_t QSPI_GetStatus(Qspi *pQspi, const QspiStatus_t rStatus)
+{
+ assert(pQspi);
+ return (pQspi->QSPI_SR & rStatus);
+}
+
+/**
+ * \brief Configures peripheral clock of a QSPI/SPI peripheral.
+ *
+ * \param pQspi Pointer to an Qspi instance.
+ * \param dwConfiguration Desired clock configuration.
+ */
+void QSPI_ConfigureClock(Qspi *pQspi, QspiClockMode_t ClockMode,
+ uint32_t dwClockCfg)
+{
+ assert(pQspi);
+ pQspi->QSPI_SCR = ClockMode;
+ pQspi->QSPI_SCR |= dwClockCfg;
+}
+
+/**
+ * \brief Configures QSPI/SPI
+ *
+ * \param pQspi Pointer to an Qspi instance.
+ * \param Mode Mode for QSPI or SPI
+ * \param dwConfiguration Config of SPI or QSPI mode
+ */
+QspidStatus_t QSPI_ConfigureInterface(Qspid_t *pQspid, QspiMode_t Mode,
+ uint32_t dwConfiguration)
+{
+ pQspid->pQspiHw = QSPI;
+ pQspid->qspiId = ID_QSPI;
+
+ QSPI_Disable(pQspid->pQspiHw);
+ QSPI_SwReset(pQspid->pQspiHw);
+
+ QSPI_ConfigureMode(pQspid->pQspiHw, Mode);
+ QSPI_Configure(pQspid->pQspiHw, dwConfiguration);
+
+ return QSPI_SUCCESS;
+}
+
+
+/**
+ * \brief Ends ongoing transfer by releasing CS of QSPI peripheral.
+ *
+ * \param pQspi Pointer to an Qspi instance.
+ */
+QspidStatus_t QSPI_EndTransfer(Qspi *pQspi)
+{
+ assert(pQspi);
+
+ while (!QSPI_GetStatus(pQspi, IsTxEmpty));
+
+ pQspi->QSPI_CR = QSPI_CR_LASTXFER;
+
+ return QSPI_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------------
+ * SPI functions
+ *----------------------------------------------------------------------------*/
+/**
+ * \brief Reads the data received by a SPI peripheral. This
+ * method must be called after a successful SPI_Write call.
+ *
+ * \param pQspid Pointer to a Qspi instance.
+ * \param pData Buffer to put read value
+ * \return Qspi status
+ */
+QspidStatus_t QSPI_SingleReadSPI(Qspid_t *pQspid, uint16_t *const pData)
+{
+ QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
+ Qspi *pQspi = pQspid->pQspiHw;
+ uint32_t NumOfAttempt = 0;
+ uint16_t Dummy = 0xFF;
+
+ for (;;) {
+ if (QSPI_GetStatus(pQspi, IsReceived)) {
+ *pData = QSPI_ReadSPI(pQspi);
+ QSPI_WriteSPI(pQspi, Dummy);
+ *pData = QSPI_ReadSPI(pQspi);
+ NumOfAttempt = 0;
+ Status = QSPI_SUCCESS;
+ } else {
+ if (NumOfAttempt > 0xFFFF) {
+ Status = QSPI_READ_ERROR;
+ TRACE_ERROR(" SPI Read Error \n\r");
+ break;
+ } else {
+ Status = QSPI_READ_ERROR;
+ NumOfAttempt++;
+ }
+ }
+ }
+
+ return Status;
+}
+
+/**
+ * \brief Reads multiple data received by a SPI peripheral. This
+ * method must be called after a successful SPI_Write call.
+ *
+ * \param pQspid Pointer to a Qspi instance.
+ * \param pData Pointer to read buffer
+ * \param NumOfBytes Num of bytes to read
+ *
+ * \return Qspi status
+ */
+QspidStatus_t QSPI_MultiReadSPI(Qspid_t *pQspid, uint16_t *const pData,
+ uint32_t NumOfBytes)
+{
+ QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
+ Qspi *pQspi = pQspid->pQspiHw;
+ uint32_t NumOfBytesRead = 0;
+ uint32_t NumOfAttempt = 0;
+ uint8_t *pwData = (uint8_t *)pData;
+ uint16_t Dummy = 0xFF;
+
+ /* Dummy read and write to discard first bytes recvd and start
+ receiving new data*/
+ Dummy = QSPI_ReadSPI(pQspi);
+ QSPI_WriteSPI(pQspi, Dummy);
+
+ for (; NumOfBytesRead < NumOfBytes;) {
+ if (QSPI_GetStatus(pQspi, IsTxSent)) {
+ *pwData = QSPI_ReadSPI(pQspi);
+
+ if (pQspi->QSPI_MR & QSPI_MR_NBBITS_Msk)
+ pwData += sizeof(uint16_t);
+ else
+ pwData += sizeof(uint8_t);
+
+ NumOfBytesRead++;
+ NumOfAttempt = 0;
+ Status = QSPI_SUCCESS;
+ QSPI_WriteSPI(pQspi, Dummy);
+ } else {
+ if (NumOfAttempt > 0xFFFF) {
+ Status = QSPI_READ_ERROR;
+ TRACE_ERROR(" SPI MultiRead Error \n\r");
+ break;
+ } else {
+ Status = QSPI_READ_ERROR;
+ NumOfAttempt++;
+ }
+ }
+ }
+
+ return Status;
+}
+
+/**
+ * \brief Sends a single data through a SPI peripheral.
+ *
+ * \param pQspid Pointer to a Qspi instance.
+ * \param pData Pointer to Tx data
+ *
+ * \return Qspi status
+ */
+QspidStatus_t QSPI_SingleWriteSPI(Qspid_t *pQspid, uint16_t const *pData)
+{
+ QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
+ Qspi *pQspi = pQspid->pQspiHw;
+ uint32_t NumOfAttempt = 0;
+
+ for (;;) {
+ if (QSPI_GetStatus(pQspi, IsTxSent)) {
+ QSPI_WriteSPI(pQspi, *pData);
+ NumOfAttempt = 0;
+ Status = QSPI_SUCCESS;
+ break;
+ } else {
+ Status = QSPI_BUSY_SENDING;
+ NumOfAttempt++;
+
+ if (NumOfAttempt > 0xFFFF) {
+ Status = QSPI_WRITE_ERROR;
+ TRACE_ERROR(" SPI Write Error \n\r");
+ break;
+ }
+ }
+ }
+
+ return Status;
+
+}
+
+/**
+ * \brief Sends multiple data through a SPI peripheral.
+ *
+ * \param pQspid Pointer to a Qspi instance.
+ * \param pData Pointer to a Tx buffer
+ * \param NumOfBytes Num of data to send.
+ */
+QspidStatus_t QSPI_MultiWriteSPI(Qspid_t *pQspid, uint16_t const *pData,
+ uint32_t NumOfBytes)
+{
+ QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
+ Qspi *pQspi = pQspid->pQspiHw;
+ uint32_t NumOfBytesWrite = 0;
+ uint32_t NumOfAttempt = 0;
+ uint8_t *pwData = (uint8_t *)pData;
+ uint8_t Addr_Inc = 0;
+
+ if (pQspi->QSPI_MR & QSPI_MR_NBBITS_Msk)
+ Addr_Inc = sizeof(uint16_t);
+ else
+ Addr_Inc = sizeof(uint8_t);
+
+ for (; NumOfBytesWrite < NumOfBytes;) {
+ if (QSPI_GetStatus(pQspi, IsTxEmpty)) {
+ QSPI_WriteSPI(pQspi, (uint16_t)*pwData);
+ pwData += Addr_Inc;
+ NumOfBytesWrite++;
+ NumOfAttempt = 0;
+ Status = QSPI_SUCCESS;
+ } else {
+ Status = QSPI_BUSY_SENDING;
+ NumOfAttempt++;
+
+ if (NumOfAttempt > 0xFFFF) {
+ Status = QSPI_WRITE_ERROR;
+ TRACE_ERROR(" SPI Multi Write Error \n\r");
+ break;
+ }
+ }
+ }
+
+ return Status;
+
+}
+
+/*----------------------------------------------------------------------------
+ * QSPI functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Send an instruction over QSPI (oly a flash command no data)
+ *
+ * \param pQspi Pointer to an Qspi instance.
+ * \param KeepCfg To keep Instruction fram value or restes to zero
+ *
+ * \return Returns 1 if At least one instruction end has been detected since
+ * the last read of QSPI_SR.; otherwise
+ * returns 0.
+ */
+QspidStatus_t QSPI_SendCommand(Qspid_t *pQspid, uint8_t const KeepCfg)
+{
+ QspiInstFrame_t *const pFrame = pQspid->pQspiFrame;
+ QspiMemCmd_t pCommand = pQspid->qspiCommand;
+ QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
+ uint32_t timeout = 15000;
+
+ if (pFrame->InstFrame.bm.bAddrEn)
+ QSPI_SetInstAddr(pQspid->pQspiHw, pFrame->Addr);
+
+ QSPI_SetInst(pQspid->pQspiHw, (pCommand.Instruction & 0xFF),
+ ((pCommand.Option >> QSPI_ICR_OPT_Pos) & 0xFF));
+ QSPI_SetInstFrame(pQspid->pQspiHw, pFrame);
+
+ memory_sync();
+
+ /*
+ * FIXME: Timeout has been introduced due to a problem that was detected
+ * when QSPI_SR_INSTRE was not detected and the function is stuck in an
+ * endless loop. This is still an open issue.
+ * peripheral clock: 50Mhz -> 20 ns period time.
+ * timeout: set to 15000 loop cycles => 300000 ns.
+ * with loop instructions, the delay increases to 1ms altogether.
+ */
+ while (!(pQspid->pQspiHw->QSPI_SR & QSPI_SR_INSTRE) && timeout > 0) {
+ --timeout;
+ }
+
+ if (timeout == 0) {
+ Status = QSPI_WRITE_ERROR;
+ }
+
+ // poll CR reg to know status if instruction has end
+ if (!KeepCfg)
+ pFrame->InstFrame.val = 0;
+
+ return Status;
+}
+
+
+
+/**
+ * \brief Send instruction over QSPI with data
+ *
+ * \param pQspi Pointer to an Qspi instance.
+ * \param KeepCfg To keep Instruction fram value or restes to zero
+ *
+ * \return Returns 1 if At least one instruction end has been detected
+ * since the last read of QSPI_SR.; otherwise returns 0.
+ */
+QspidStatus_t QSPI_SendCommandWithData(Qspid_t *pQspid, uint8_t const KeepCfg)
+{
+ QspiInstFrame_t *const pFrame = pQspid->pQspiFrame;
+ QspiMemCmd_t pCommand = pQspid->qspiCommand;
+ QspiBuffer_t pBuffer = pQspid->qspiBuffer;
+ uint32_t *pQspiBuffer = (uint32_t *)QSPIMEM_ADDR;
+ QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
+
+ //assert(pBuffer.pDataRx);
+ assert(pBuffer.pDataTx);
+
+ QSPI_SetInst(pQspid->pQspiHw, (pCommand.Instruction & 0xFF),
+ (pCommand.Option & 0xFF));
+ QSPI_SetInstFrame(pQspid->pQspiHw, pFrame);
+
+ QSPI_GetInstFrame(pQspid->pQspiHw);
+
+ // to synchronize system bus accesses
+ if (!KeepCfg)
+ pFrame->InstFrame.val = 0;
+
+ memcpy(pQspiBuffer , pBuffer.pDataTx , pBuffer.TxDataSize);
+ memory_sync();
+ QSPI_EndTransfer(pQspid->pQspiHw);
+
+ // End transmission after all data has been sent
+ while (!(pQspid->pQspiHw->QSPI_SR & QSPI_SR_INSTRE));
+
+ // poll CR reg to know status if instruction has end
+
+ return Status;
+}
+
+/**
+ * \brief Send instruction over QSPI to read data
+ *
+ * \param pQspi Pointer to an Qspi instance.
+ * \param KeepCfg To keep Instruction from value or resets to zero
+ *
+ * \return Returns 1 if At least one instruction end has been detected
+ * since the last read of QSPI_SR.; otherwise returns 0.
+ */
+QspidStatus_t QSPI_ReadCommand(Qspid_t *pQspid, uint8_t const KeepCfg)
+{
+ QspiInstFrame_t *const pFrame = pQspid->pQspiFrame;
+ QspiMemCmd_t pCommand = pQspid->qspiCommand;
+ QspiBuffer_t pBuffer = pQspid->qspiBuffer;
+ uint32_t *pQspiBuffer = (uint32_t *)QSPIMEM_ADDR;
+ QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
+
+ assert(pBuffer.pDataRx);
+
+ QSPI_SetInst(pQspid->pQspiHw, (pCommand.Instruction & 0xFF),
+ (pCommand.Option & 0xFF));
+ QSPI_SetInstFrame(pQspid->pQspiHw, pFrame);
+
+ QSPI_GetInstFrame(pQspid->pQspiHw);
+
+ // to synchronize system bus accesses
+ if (!KeepCfg)
+ pFrame->InstFrame.val = 0;
+
+ memcpy(pBuffer.pDataRx , pQspiBuffer, pBuffer.RxDataSize);
+ memory_sync();
+ QSPI_EndTransfer(pQspid->pQspiHw);
+
+ // End transmission after all data has been sent
+ while (!(pQspid->pQspiHw->QSPI_SR & QSPI_SR_INSTRE));
+
+ // poll CR reg to know status if instruction has end
+
+ return Status;
+}
+
+/**
+ * \brief Sends an instruction over QSPI and configures other related address
+* like Addr , Frame and synchronise bus access before data read or write
+ *
+ * \param pQspi Pointer to an Qspi instance.
+ * \param KeepCfg To keep Instruction from value or resets to zero
+ * \param ScrambleFlag Enable or disable scramble on QSPI
+ *
+ * \return Returns 1 if At least one instruction end has been detected since
+ * the last read of QSPI_SR.; otherwise returns 0.
+ */
+QspidStatus_t QSPI_EnableMemAccess(Qspid_t *pQspid, uint8_t const KeepCfg,
+ uint8_t ScrambleFlag)
+{
+ QspiInstFrame_t *const pFrame = pQspid->pQspiFrame;
+ QspiMemCmd_t pCommand = pQspid->qspiCommand;
+
+ QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
+
+ QSPI_SetInst(pQspid->pQspiHw, (pCommand.Instruction & 0xFF),
+ (pCommand.Option & 0xFF));
+
+ if (ScrambleFlag)
+ QSPI_ScrambleData(pQspid->pQspiHw, SCRAMBLE_KEY, ScrambleFlag, 1);
+
+ QSPI_SetInstFrame(pQspid->pQspiHw, pFrame);
+
+ QSPI_GetInstFrame(pQspid->pQspiHw);
+
+ // to synchronize system bus accesses
+ if (!KeepCfg)
+ pFrame->InstFrame.val = 0;
+
+ Status = QSPI_SUCCESS;
+ return Status;
+}
+
+/**
+ * \brief Writes or reads the QSPI memory (0x80000000) to transmit or
+ * receive data from Flash memory
+ * \param pQspi Pointer to an Qspi instance.
+ * \param ReadWrite Flag to indicate read/write QSPI memory access
+ *
+ * \return Returns 1 if At least one instruction end has been detected since
+ * the last read of QSPI_SR.; otherwise returns 0.
+ */
+QspidStatus_t QSPI_ReadWriteMem(Qspid_t *pQspid, Access_t const ReadWrite)
+{
+ QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
+ QspiInstFrame_t *const pFrame = pQspid->pQspiFrame;
+ void *pQspiMem = (void *)(QSPIMEM_ADDR | pFrame->Addr);
+ QspiBuffer_t pBuffer = pQspid->qspiBuffer;
+
+ assert(((ReadWrite > CmdAccess)
+ && (ReadWrite <= WriteAccess)) ? true : false);
+
+ if (ReadWrite == WriteAccess) {
+ atsam_copy_to_io(pQspiMem, pBuffer.pDataTx ,
+ pBuffer.TxDataSize);
+ } else {
+ atsam_copy_from_io(pBuffer.pDataRx, pQspiMem,
+ pBuffer.RxDataSize);
+ }
+ memory_sync();
+ QSPI_EndTransfer(pQspid->pQspiHw);
+
+ // End transmission after all data has been sent
+ while (!(pQspid->pQspiHw->QSPI_SR & QSPI_SR_INSTRE));
+
+ // poll CR reg to know status if instruction has end
+
+ Status = QSPI_SUCCESS;
+ return Status;
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/qspi_dma.c b/bsps/arm/atsam/contrib/libraries/libchip/source/qspi_dma.c
new file mode 100644
index 0000000000..12e217ebf0
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/qspi_dma.c
@@ -0,0 +1,619 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \addtogroup qspi_dma_module QSPI xDMA driver
+ * \ingroup peripherals_module
+ *
+ *
+ */
+
+/**
+ * \file
+ *
+ * Implementation for the SPI Flash with xDMA driver.
+ *
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+#ifdef __rtems__
+#include "../../../utils/utility.h"
+#endif /* __rtems__ */
+
+/*----------------------------------------------------------------------------
+ * Definitions
+ *----------------------------------------------------------------------------*/
+
+/** xDMA support */
+
+/** xDMA Link List size for SPI transmission*/
+#define DMA_QSPI_LLI 2
+
+/*-----------------------------------------------------------------------------
+ * QSPI DMA Local functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief SPI xDMA Rx callback
+ * Invoked on SPi DMA reception done.
+ * \param channel DMA channel.
+ * \param pArg Pointer to callback argument - Pointer to Spid instance.
+ */
+static void QSPID_Spi_Cb(uint32_t channel, QspiDma_t *pArg)
+{
+ Qspi *pQspiHw = pArg->Qspid.pQspiHw;
+
+ if (channel != pArg->RxChNum)
+ return;
+
+ /* Release the semaphore */
+ ReleaseMutex(pArg->progress);
+ QSPI_EndTransfer(pQspiHw);
+ SCB_InvalidateDCache_by_Addr((uint32_t *)pArg->Qspid.qspiBuffer.pDataRx,
+ pArg->Qspid.qspiBuffer.RxDataSize);
+ memory_sync();
+}
+
+
+/**
+ * \brief QSPI xDMA Tx callback
+ * Invoked on QSPi DMA Write done.
+ * \param channel DMA channel.
+ * \param pArg Pointer to callback argument - Pointer to Spid instance.
+ */
+static void QSPID_qspiTx_Cb(uint32_t channel, QspiDma_t *pArg)
+{
+ Qspi *pQspiHw = pArg->Qspid.pQspiHw;
+
+ if (channel != pArg->TxChNum)
+ return;
+
+ /* Release the semaphore */
+ ReleaseMutex(pArg->progress);
+ QSPI_EndTransfer(pQspiHw);
+
+ while (!QSPI_GetStatus(pArg->Qspid.pQspiHw, IsEofInst));
+
+ memory_sync();
+}
+
+
+/**
+ * \brief QSPI xDMA Rx callback
+ * Invoked on SPi DMA reception done.
+ * \param channel DMA channel.
+ * \param pArg Pointer to callback argument - Pointer to Spid instance.
+ */
+static void QSPID_qspiRx_Cb(uint32_t channel, QspiDma_t *pArg)
+{
+ Qspi *pQspiHw = pArg->Qspid.pQspiHw;
+
+ if (channel != pArg->RxChNum)
+ return;
+
+ /* Release the semaphore */
+ ReleaseMutex(pArg->progress);
+ QSPI_EndTransfer(pQspiHw);
+
+ while (!QSPI_GetStatus(pArg->Qspid.pQspiHw, IsEofInst));
+
+ SCB_InvalidateDCache_by_Addr((uint32_t *)pArg->Qspid.qspiBuffer.pDataRx,
+ pArg->Qspid.qspiBuffer.RxDataSize);
+ memory_sync();
+}
+
+/**
+ * \brief Configures the DMA for QSPI
+ *
+ * \param pQspidma Pointer to QSPI DMA structure
+ * \param Addr Address to Read or write of QSPI flash memory
+ * \param pBuffer Pointer input/output buffer
+ * \param ReadWrite Read or write memory flag
+ * \returns 0 if the dma multibuffer configuration successfully; otherwise returns
+ * QSPID_ERROR_XXX.
+ */
+static uint8_t QSPID_configureQpsiDma(QspiDma_t *pQspidma, uint32_t Addr,
+ QspiBuffer_t *pBuffer, Access_t const ReadWrite)
+{
+ sXdmadCfg xdmadCfg, xdmadRxCfg, xdmadTxCfg;
+ uint8_t chanNum;
+ uint8_t qspi_id = pQspidma->Qspid.qspiId;
+ Qspi *pQspiHw = pQspidma->Qspid.pQspiHw;
+ uint32_t xdmaCndc, xdmaInt, BurstSize, ChannelWidth;
+
+
+ /* Setup DMA for QSPI */
+
+ if (pQspidma->Qspid.qspiMode == QSPI_MR_SMM_SPI) {
+ // SPI mode
+ /* SPI TX DMA config */
+ xdmadTxCfg.mbr_sa = (uint32_t)pBuffer->pDataTx;
+ xdmadTxCfg.mbr_da = (uint32_t)&pQspiHw->QSPI_TDR;
+ xdmadTxCfg.mbr_ubc = (pBuffer->TxDataSize);
+
+ xdmadTxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_MEM2PER |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF0 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_INCREMENTED_AM |
+ XDMAC_CC_DAM_FIXED_AM |
+ XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber
+ (qspi_id, XDMAD_TRANSFER_TX));
+
+ xdmadTxCfg.mbr_bc = 0;
+ xdmadTxCfg.mbr_sus = 0;
+ xdmadTxCfg.mbr_dus = 0;
+
+ /* SPI RX DMA config */
+
+ xdmadRxCfg.mbr_da = (uint32_t)pBuffer->pDataRx;
+ xdmadRxCfg.mbr_sa = (uint32_t)&pQspiHw->QSPI_RDR;
+ xdmadRxCfg.mbr_ubc = (pBuffer->RxDataSize);
+ xdmadRxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_PER2MEM |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF0 |
+ XDMAC_CC_SAM_FIXED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber
+ (qspi_id, XDMAD_TRANSFER_RX));
+
+ xdmadRxCfg.mbr_bc = 0;
+ xdmadRxCfg.mbr_sus = 0;
+ xdmadRxCfg.mbr_dus = 0;
+ xdmaCndc = 0;
+ /* Put all interrupts on for non LLI list setup of DMA */
+ xdmaInt = (XDMAC_CIE_BIE |
+ XDMAC_CIE_RBIE |
+ XDMAC_CIE_WBIE |
+ XDMAC_CIE_ROIE);
+
+ memory_barrier();
+
+ if (XDMAD_ConfigureTransfer
+ (pQspidma->pXdmad, pQspidma->RxChNum, &xdmadRxCfg, xdmaCndc, 0, xdmaInt))
+ return QSPID_ERROR;
+
+ if (XDMAD_ConfigureTransfer
+ (pQspidma->pXdmad, pQspidma->TxChNum, &xdmadTxCfg, xdmaCndc, 0, xdmaInt))
+ return QSPID_ERROR;
+
+ return 0;
+
+ } else {
+ if (ReadWrite == WriteAccess) {
+ xdmadCfg.mbr_sa = (uint32_t)pBuffer->pDataTx;
+ xdmadCfg.mbr_da = (uint32_t)(QSPIMEM_ADDR | Addr);
+ xdmadCfg.mbr_ubc = (pBuffer->TxDataSize);
+ chanNum = pQspidma->TxChNum;
+ ChannelWidth = XDMAC_CC_DWIDTH_BYTE;
+ BurstSize = XDMAC_CC_MBSIZE_SIXTEEN;
+ } else if (ReadWrite == ReadAccess) {
+ xdmadCfg.mbr_da = (uint32_t)pBuffer->pDataRx;
+ xdmadCfg.mbr_sa = (uint32_t)(QSPIMEM_ADDR | Addr);
+ xdmadCfg.mbr_ubc = ((pBuffer->RxDataSize >> 2));
+ chanNum = pQspidma->RxChNum;
+ ChannelWidth = XDMAC_CC_DWIDTH_WORD;
+ BurstSize = XDMAC_CC_MBSIZE_SIXTEEN;
+ } else {
+ TRACE_ERROR(" QSPI error \n\r");
+ return 1;
+ }
+
+ xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_MEM_TRAN |
+ XDMAC_CC_MEMSET_NORMAL_MODE |
+ BurstSize |
+ ChannelWidth |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_INCREMENTED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM;
+
+ xdmadCfg.mbr_bc = 0;
+ xdmadCfg.mbr_sus = 0;
+ xdmadCfg.mbr_dus = 0;
+
+ xdmaCndc = 0;
+
+
+ /* Put all interrupts on for non LLI list setup of DMA */
+ xdmaInt = (XDMAC_CIE_BIE |
+ XDMAC_CIE_RBIE |
+ XDMAC_CIE_WBIE |
+ XDMAC_CIE_ROIE);
+
+ memory_barrier();
+
+ if (XDMAD_ConfigureTransfer(pQspidma->pXdmad, chanNum, &xdmadCfg, xdmaCndc, 0,
+ xdmaInt))
+ return QSPID_ERROR;
+
+ return 0;
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+/**
+ * \brief Initializes the pQspidma structure and the corresponding QSPI & DMA .
+ * hardware select value.
+ *
+ * \param pQspidma Pointer to a QspiDma_t instance.
+ * \param Mode Associated SPI peripheral.
+ * \param dwConf QSPI peripheral configuration.
+ * \param pXdmad Pointer to a Xdmad instance.
+ */
+uint32_t QSPID_Configure(QspiDma_t *pQspidma, QspiMode_t Mode,
+ uint32_t dwConf, sXdmad *pXdmad)
+{
+ /* Initialize the QSPI structure */
+
+ QSPI_ConfigureInterface(&pQspidma->Qspid, Mode, dwConf);
+
+ pQspidma->Qspid.qspiCommand.Instruction = 0;
+ pQspidma->Qspid.qspiCommand.Option = 0;
+
+ pQspidma->RxChNum = QSPID_CH_NOT_ENABLED;
+ pQspidma->TxChNum = QSPID_CH_NOT_ENABLED;
+
+ assert(pXdmad == &XDMAD_Instance);
+ pQspidma->pXdmad = pXdmad;
+
+ return QSPI_SUCCESS;
+}
+
+
+
+/**
+ * \brief Enables a QSPI Rx channel. This function will allocate a dma Rx
+ * channel for QSPI
+ *
+ * \param pQspidma Pointer to a Spid instance.
+
+ * \returns 0 if the transfer has been started successfully; otherwise returns
+ * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is not
+ * valid.
+ */
+uint32_t QSPID_EnableQspiRxChannel(QspiDma_t *pQspidma)
+{
+ static uint16_t DmaChannel;
+
+ /* Try to get the semaphore */
+ if (pQspidma->RxChNum != QSPID_CH_NOT_ENABLED)
+ return QSPID_ERROR_LOCK;
+
+ /* Allocate a DMA channel */
+ DmaChannel = XDMAD_AllocateChannel(
+ pQspidma->pXdmad, XDMAD_TRANSFER_MEMORY, XDMAD_TRANSFER_MEMORY);
+
+ if (DmaChannel == XDMAD_ALLOC_FAILED)
+ return QSPID_ERROR;
+
+ pQspidma->RxChNum = DmaChannel;
+ /* Setup callbacks*/
+ XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->RxChNum,
+ (XdmadTransferCallback)QSPID_qspiRx_Cb, pQspidma);
+
+ if (XDMAD_PrepareChannel(pQspidma->pXdmad, pQspidma->RxChNum))
+ return QSPID_ERROR;
+
+ return 0;
+}
+
+
+/**
+ * \brief Enables a QSPI Tx channel. This function will allocate a dma Tx
+ * channel for QSPI
+ *
+ * \param pQspidma Pointer to a Spid instance.
+
+ * \returns 0 if the transfer has been started successfully; otherwise returns
+ * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
+ * not valid.
+ */
+uint32_t QSPID_EnableQspiTxChannel(QspiDma_t *pQspidma)
+{
+ static uint16_t DmaChannel;
+
+ /* Try to get the semaphore */
+ if (pQspidma->TxChNum != QSPID_CH_NOT_ENABLED)
+ return QSPID_ERROR_LOCK;
+
+ /* Allocate a DMA channel */
+ DmaChannel = XDMAD_AllocateChannel(pQspidma->pXdmad,
+ XDMAD_TRANSFER_MEMORY, XDMAD_TRANSFER_MEMORY);
+
+ if (DmaChannel == XDMAD_ALLOC_FAILED)
+ return QSPID_ERROR;
+
+ pQspidma->TxChNum = DmaChannel;
+ /* Setup callbacks */
+ XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->TxChNum,
+ (XdmadTransferCallback)QSPID_qspiTx_Cb, pQspidma);
+
+ if (XDMAD_PrepareChannel(pQspidma->pXdmad, pQspidma->TxChNum))
+ return QSPID_ERROR;
+
+ return 0;
+}
+
+
+/**
+ * \brief Enables a QSPI SPI Rx channel. This function will allocate a dma
+ * Rx channel for QSPI SPI mode
+ *
+ * \param pQspidma Pointer to a Spid instance.
+
+ * \returns 0 if the transfer has been started successfully; otherwise returns
+ * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
+ * not valid.
+ */
+uint32_t QSPID_EnableSpiChannel(QspiDma_t *pQspidma)
+{
+ static uint16_t DmaChannel;
+
+ /* Try to get the semaphore */
+ if (pQspidma->RxChNum != QSPID_CH_NOT_ENABLED)
+ return QSPID_ERROR_LOCK;
+
+ /* Try to get the semaphore */
+ if (pQspidma->TxChNum != QSPID_CH_NOT_ENABLED)
+ return QSPID_ERROR_LOCK;
+
+ /* Allocate a DMA channel */
+ DmaChannel = XDMAD_AllocateChannel
+ (pQspidma->pXdmad, pQspidma->Qspid.qspiId, XDMAD_TRANSFER_MEMORY);
+
+ if (DmaChannel == XDMAD_ALLOC_FAILED)
+ return QSPID_ERROR;
+
+ pQspidma->RxChNum = DmaChannel;
+
+ /* Allocate a DMA channel */
+ DmaChannel = XDMAD_AllocateChannel(pQspidma->pXdmad,
+ XDMAD_TRANSFER_MEMORY, pQspidma->Qspid.qspiId);
+
+ if (DmaChannel == XDMAD_ALLOC_FAILED)
+ return QSPID_ERROR;
+
+ pQspidma->TxChNum = DmaChannel;
+
+ /* Setup callbacks*/
+ XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->RxChNum,
+ (XdmadTransferCallback)QSPID_Spi_Cb, pQspidma);
+
+ if (XDMAD_PrepareChannel(pQspidma->pXdmad, pQspidma->RxChNum))
+ return QSPID_ERROR;
+
+ /* Setup callbacks for SPI0/1 TX (ignored) */
+ XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->TxChNum, NULL, NULL);
+
+ if (XDMAD_PrepareChannel(pQspidma->pXdmad, pQspidma->TxChNum))
+ return QSPID_ERROR;
+
+ return 0;
+}
+
+
+/**
+ * \brief Disables a QSPI Rx channel. This function will de-allocate previous
+ * allocated dma Rx channel for QSPI
+ *
+ * \param pQspidma Pointer to a Spid instance.
+
+ * \returns 0 if the transfer has been started successfully; otherwise returns
+ * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
+ * not valid.
+ */
+uint32_t QSPID_DisableQspiRxChannel(QspiDma_t *pQspidma)
+{
+
+ XDMAC_SoftwareFlushReq(pQspidma->pXdmad->pXdmacs, pQspidma->RxChNum);
+ XDMAD_StopTransfer(pQspidma->pXdmad, pQspidma->RxChNum);
+
+ XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->RxChNum, NULL, NULL);
+
+
+ /* Free allocated DMA channel for QSPI RX. */
+ XDMAD_FreeChannel(pQspidma->pXdmad, pQspidma->RxChNum);
+
+ pQspidma->RxChNum = QSPID_CH_NOT_ENABLED;
+
+ return 0;
+}
+
+
+
+/**
+ * \brief Disables a QSPI Tx channel. This function will de-allocate previous
+ * allocated dma Tx channel for QSPI
+ *
+ * \param pQspidma Pointer to a Spid instance.
+
+ * \returns 0 if the transfer has been started successfully; otherwise returns
+ * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
+ * not valid.
+ */
+uint32_t QSPID_DisableQspiTxChannel(QspiDma_t *pQspidma)
+{
+
+ XDMAC_SoftwareFlushReq(pQspidma->pXdmad->pXdmacs, pQspidma->TxChNum);
+ XDMAD_StopTransfer(pQspidma->pXdmad, pQspidma->TxChNum);
+
+ XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->TxChNum, NULL, NULL);
+
+ /* Free allocated DMA channel for QSPI TX. */
+ XDMAD_FreeChannel(pQspidma->pXdmad, pQspidma->TxChNum);
+
+ pQspidma->TxChNum = QSPID_CH_NOT_ENABLED;
+
+ return 0;
+}
+
+
+/**
+ * \brief Disables a QSPI SPI Rx and Tx channels. This function will
+ * de-allocate privious allocated dma Rx, Txchannel for QSPI in SPI mode
+ *
+ * \param pQspidma Pointer to a Spid instance.
+
+ * \returns 0 if the transfer has been started successfully; otherwise returns
+ * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
+ * not valid.
+ */
+uint32_t QSPID_DisableSpiChannel(QspiDma_t *pQspidma)
+{
+
+ XDMAC_SoftwareFlushReq(pQspidma->pXdmad->pXdmacs, pQspidma->RxChNum);
+ //XDMAC_SoftwareFlushReq(pQspidma->pXdmad->pXdmacs, pQspidma->TxChNum);
+ XDMAD_StopTransfer(pQspidma->pXdmad, pQspidma->RxChNum);
+ XDMAD_StopTransfer(pQspidma->pXdmad, pQspidma->TxChNum);
+
+ XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->RxChNum, NULL, NULL);
+
+ /* Free allocated DMA channel for QSPI RX. */
+ XDMAD_FreeChannel(pQspidma->pXdmad, pQspidma->RxChNum);
+
+ XDMAD_FreeChannel(pQspidma->pXdmad, pQspidma->TxChNum);
+
+ pQspidma->RxChNum = QSPID_CH_NOT_ENABLED;
+ pQspidma->TxChNum = QSPID_CH_NOT_ENABLED;
+
+ return 0;
+}
+
+
+/**
+ * \brief Starts a QSPI read or write operation.
+ *
+ * \param pQspidma Pointer to a Qspid instance.
+ * \param ReadWrite Defines the memory access type
+ * \returns 0 if the transfer has been started successfully; otherwise returns
+ * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
+ * not valid.
+ */
+uint32_t QSPID_ReadWriteQSPI(QspiDma_t *pQspidma, Access_t const ReadWrite)
+{
+ QspiBuffer_t *pBuffer = &pQspidma->Qspid.qspiBuffer;
+ uint8_t chanNum;
+ uint32_t semTimer = 0x7FF;
+
+ //assert(pBuffer->pDataTx);
+
+ if (pQspidma->progress)
+ return QSPID_ERROR_LOCK;
+
+ LockMutex(pQspidma->progress, semTimer);
+
+ if (QSPID_configureQpsiDma
+ (pQspidma, pQspidma->Qspid.pQspiFrame->Addr, pBuffer, ReadWrite))
+ return QSPID_ERROR_LOCK;
+
+ if (ReadWrite == WriteAccess) {
+ chanNum = pQspidma->TxChNum;
+ SCB_CleanDCache_by_Addr((uint32_t *)pBuffer->pDataTx, pBuffer->TxDataSize);
+ } else {
+ if (ReadWrite != ReadAccess)
+ TRACE_ERROR("%s QSPI Access Error\n\r", __FUNCTION__);
+ chanNum = pQspidma->RxChNum;
+ }
+
+ /* Start DMA 0(RX) && 1(TX) */
+ if (XDMAD_StartTransfer(pQspidma->pXdmad, chanNum))
+ return QSPID_ERROR_LOCK;
+
+ return 0;
+}
+
+/**
+ * \brief Starts a SPI master transfer. This is a non blocking function. It will
+ * return as soon as the transfer is started.
+ *
+ * \param pSpid Pointer to a Spid instance.
+ * \param pCommand Pointer to the SPI command to execute.
+ * \returns 0 if the transfer has been started successfully; otherwise returns
+ * SPID_ERROR_LOCK is the driver is in use, or SPID_ERROR if the command is not
+ * valid.
+ */
+uint32_t QSPID_ReadWriteSPI(QspiDma_t *pQspidma, Access_t const ReadWrite)
+{
+ QspiBuffer_t *pBuffer = &pQspidma->Qspid.qspiBuffer;
+ uint32_t semTimer = 0x7FF;
+
+ assert(pBuffer->pDataRx);
+ assert(pBuffer->pDataTx);
+
+ /* Try to get the dataflash semaphore */
+ if (pQspidma->progress)
+
+ return QSPID_ERROR_LOCK;
+
+ LockMutex(pQspidma->progress, semTimer);
+
+ if (QSPID_configureQpsiDma
+ (pQspidma, pQspidma->Qspid.pQspiFrame->Addr, pBuffer, ReadWrite))
+ return QSPID_ERROR_LOCK;
+
+ SCB_CleanDCache_by_Addr((uint32_t *)pBuffer->pDataTx, pBuffer->TxDataSize);
+
+ /* Start DMA 0(RX) && 1(TX) */
+ if (XDMAD_StartTransfer(pQspidma->pXdmad, pQspidma->RxChNum))
+ return QSPID_ERROR_LOCK;
+
+ if (XDMAD_StartTransfer(pQspidma->pXdmad, pQspidma->TxChNum))
+ return QSPID_ERROR_LOCK;
+
+ return 0;
+}
+
+/**
+ * \brief Check if the QSPI driver is busy.
+ *
+ * \param pSpid Pointer to a Spid instance.
+ * \returns 1 if the SPI driver is currently busy executing a command; otherwise
+ */
+uint32_t QSPID_IsBusy(volatile uint8_t *QspiSemaphore)
+{
+ if (Is_LockFree(QspiSemaphore))
+ return 1;
+ else
+ return 0;
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/rstc.c b/bsps/arm/atsam/contrib/libraries/libchip/source/rstc.c
new file mode 100644
index 0000000000..fd35cdf974
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/rstc.c
@@ -0,0 +1,167 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \file */
+/*---------------------------------------------------------------------------
+ * Headers
+ *---------------------------------------------------------------------------*/
+
+#include <chip.h>
+
+
+/*---------------------------------------------------------------------------
+ * Exported functions
+ *---------------------------------------------------------------------------*/
+
+/**
+ * Configure the mode of the RSTC peripheral.
+ * The configuration is computed by the lib (RSTC_RMR_*).
+ * \param mr Desired mode configuration.
+ */
+void RSTC_ConfigureMode(uint32_t mr)
+{
+ Rstc *pHw = RSTC;
+ mr &= ~RSTC_MR_KEY_Msk;
+ pHw->RSTC_MR = mr | RSTC_MR_KEY_PASSWD;
+}
+
+/**
+ * Enable/Disable the detection of a low level on the pin NRST as User Reset
+ * \param enable 1 to enable & 0 to disable.
+ */
+void RSTC_SetUserResetEnable(uint8_t enable)
+{
+ Rstc *pHw = RSTC;
+ uint32_t mr = pHw->RSTC_MR & (~RSTC_MR_KEY_Msk);
+
+ if (enable)
+ mr |= RSTC_MR_URSTEN;
+ else
+ mr &= ~RSTC_MR_URSTEN;
+
+ pHw->RSTC_MR = mr | RSTC_MR_KEY_PASSWD;
+}
+
+/**
+ * Enable/Disable the interrupt of a User Reset (USRTS bit in RSTC_RST).
+ * \param enable 1 to enable & 0 to disable.
+ */
+void RSTC_SetUserResetInterruptEnable(uint8_t enable)
+{
+ Rstc *pHw = RSTC;
+ uint32_t mr = pHw->RSTC_MR & (~RSTC_MR_KEY_Msk);
+
+ if (enable)
+ mr |= RSTC_MR_URSTIEN;
+ else
+ mr &= ~RSTC_MR_URSTIEN;
+
+ pHw->RSTC_MR = mr | RSTC_MR_KEY_PASSWD;
+}
+
+/**
+ * Setup the external reset length. The length is asserted during a time of
+ * pow(2, powl+1) Slow Clock(32KHz). The duration is between 60us and 2s.
+ * \param powl Power length defined.
+ */
+void RSTC_SetExtResetLength(uint8_t powl)
+{
+ Rstc *pHw = RSTC;
+ uint32_t mr = pHw->RSTC_MR;
+ mr &= ~(RSTC_MR_KEY_Msk | RSTC_MR_ERSTL_Msk);
+ mr |= RSTC_MR_ERSTL(powl);
+ pHw->RSTC_MR = mr | RSTC_MR_KEY_PASSWD;
+}
+
+
+/**
+ * Resets the processor.
+ */
+void RSTC_ProcessorReset(void)
+{
+ Rstc *pHw = RSTC;
+ pHw->RSTC_CR = RSTC_CR_PROCRST | RSTC_CR_KEY_PASSWD;
+}
+
+
+/**
+ * Asserts the NRST pin for external resets.
+ */
+void RSTC_ExtReset(void)
+{
+ Rstc *pHw = RSTC;
+ pHw->RSTC_CR = RSTC_CR_EXTRST | RSTC_CR_KEY_PASSWD;
+}
+
+/**
+ * Return NRST pin level (1 or 0).
+ */
+uint8_t RSTC_GetNrstLevel(void)
+{
+ Rstc *pHw = RSTC;
+ return ((pHw->RSTC_SR & RSTC_SR_NRSTL) > 0);
+}
+
+/**
+ * Returns 1 if at least one high-to-low transition of NRST (User Reset) has
+ * been detected since the last read of RSTC_RSR.
+ */
+uint8_t RSTC_IsUserResetDetected(void)
+{
+ Rstc *pHw = RSTC;
+
+ if (pHw->RSTC_SR & RSTC_SR_URSTS)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * Return 1 if a software reset command is being performed by the reset
+ * controller. The reset controller is busy.
+ */
+uint8_t RSTC_IsBusy(void)
+{
+ Rstc *pHw = RSTC;
+
+ if (pHw->RSTC_SR & RSTC_SR_SRCMP)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * Get the status
+ */
+uint32_t RSTC_GetStatus(void)
+{
+ Rstc *pHw = RSTC;
+ return (pHw->RSTC_SR);
+}
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/rtc.c b/bsps/arm/atsam/contrib/libraries/libchip/source/rtc.c
new file mode 100644
index 0000000000..9527585217
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/rtc.c
@@ -0,0 +1,452 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup rtc_module Working with RTC
+ * \ingroup peripherals_module
+ * The RTC driver provides the interface to configure and use the RTC
+ * peripheral.
+ *
+ * It manages date, time, and alarms.\n
+ * This timer is clocked by the 32kHz system clock, and is not impacted by
+ * power management settings (PMC). To be accurate, it is better to use an
+ * external 32kHz crystal instead of the internal 32kHz RC.\n
+ *
+ * It uses BCD format, and time can be set in AM/PM or 24h mode through a
+ * configuration bit in the mode register.\n
+ *
+ * To update date or time, the user has to follow these few steps :
+ * <ul>
+ * <li>Set UPDTIM and/or UPDCAL bit(s) in RTC_CR,</li>
+ * <li>Polling or IRQ on the ACKUPD bit of RTC_CR,</li>
+ * <li>Clear ACKUPD bit in RTC_SCCR,</li>
+ * <li>Update Time and/or Calendar values in RTC_TIMR/RTC_CALR (BCD format),</li>
+ * <li>Clear UPDTIM and/or UPDCAL bit in RTC_CR.</li>
+ * </ul>
+ * An alarm can be set to happen on month, date, hours, minutes or seconds,
+ * by setting the proper "Enable" bit of each of these fields in the Time and
+ * Calendar registers.
+ * This allows a large number of configurations to be available for the user.
+ * Alarm occurrence can be detected even by polling or interrupt.
+ *
+ * A check of the validity of the date and time format and values written by
+ * the user is automatically done.
+ * Errors are reported through the Valid Entry Register.
+ *
+ * For more accurate information, please look at the RTC section of the
+ * Datasheet.
+ *
+ * Related files :\n
+ * \ref rtc.c\n
+ * \ref rtc.h.\n
+ */
+/*@{*/
+/*@}*/
+
+
+/**
+ * \file
+ *
+ * Implementation of Real Time Clock (RTC) controller.
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+#include <stdint.h>
+#include <assert.h>
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Sets the RTC in either 12 or 24 hour mode.
+ *
+ * \param mode Hour mode.
+ */
+extern void RTC_SetHourMode(Rtc *pRtc, uint32_t dwMode)
+{
+ assert((dwMode & 0xFFFFFFFE) == 0);
+
+ pRtc->RTC_MR = dwMode;
+}
+
+/**
+ * \brief Gets the RTC mode.
+ *
+ * \return Hour mode.
+ */
+extern uint32_t RTC_GetHourMode(Rtc *pRtc)
+{
+ uint32_t dwMode;
+
+ TRACE_DEBUG("RTC_SetHourMode()\n\r");
+
+ dwMode = pRtc->RTC_MR;
+ dwMode &= 0xFFFFFFFE;
+
+ return dwMode;
+}
+
+/**
+ * \brief Enables the selected interrupt sources of the RTC.
+ *
+ * \param sources Interrupt sources to enable.
+ */
+extern void RTC_EnableIt(Rtc *pRtc, uint32_t dwSources)
+{
+ assert((dwSources & (uint32_t)(~0x1F)) == 0);
+
+ TRACE_DEBUG("RTC_EnableIt()\n\r");
+
+ pRtc->RTC_IER = dwSources;
+}
+
+/**
+ * \brief Disables the selected interrupt sources of the RTC.
+ *
+ * \param sources Interrupt sources to disable.
+ */
+extern void RTC_DisableIt(Rtc *pRtc, uint32_t dwSources)
+{
+ assert((dwSources & (uint32_t)(~0x1F)) == 0);
+
+ TRACE_DEBUG("RTC_DisableIt()\n\r");
+
+ pRtc->RTC_IDR = dwSources;
+}
+
+/**
+ * \brief Sets the current time in the RTC.
+ *
+ * \note In successive update operations, the user must wait at least one second
+ * after resetting the UPDTIM/UPDCAL bit in the RTC_CR before setting these
+ * bits again. Please look at the RTC section of the datasheet for detail.
+ *
+ * \param ucHour Current hour in 12 or 24 hour mode.
+ * \param ucMinute Current minute.
+ * \param ucSecond Current second.
+ *
+ * \return 0 success, 1 fail to set
+ */
+extern int RTC_SetTime(Rtc *pRtc, uint8_t ucHour, uint8_t ucMinute,
+ uint8_t ucSecond)
+{
+ uint32_t dwTime = 0;
+ uint8_t ucHour_bcd;
+ uint8_t ucMin_bcd;
+ uint8_t ucSec_bcd;
+
+ TRACE_DEBUG("RTC_SetTime(%02d:%02d:%02d)\n\r", ucHour, ucMinute, ucSecond);
+
+ /* if 12-hour mode, set AMPM bit */
+ if ((pRtc->RTC_MR & RTC_MR_HRMOD) == RTC_MR_HRMOD) {
+ if (ucHour > 12) {
+ ucHour -= 12;
+ dwTime |= RTC_TIMR_AMPM;
+ }
+ }
+
+ ucHour_bcd = (ucHour % 10) | ((ucHour / 10) << 4);
+ ucMin_bcd = (ucMinute % 10) | ((ucMinute / 10) << 4);
+ ucSec_bcd = (ucSecond % 10) | ((ucSecond / 10) << 4);
+
+ /* value overflow */
+ if ((ucHour_bcd & (uint8_t)(~RTC_HOUR_BIT_LEN_MASK)) |
+ (ucMin_bcd & (uint8_t)(~RTC_MIN_BIT_LEN_MASK)) |
+ (ucSec_bcd & (uint8_t)(~RTC_SEC_BIT_LEN_MASK)))
+ return 1;
+
+ dwTime = ucSec_bcd | (ucMin_bcd << 8) | (ucHour_bcd << 16);
+
+ pRtc->RTC_CR |= RTC_CR_UPDTIM;
+
+ while ((pRtc->RTC_SR & RTC_SR_ACKUPD) != RTC_SR_ACKUPD);
+
+ pRtc->RTC_SCCR = RTC_SCCR_ACKCLR;
+ pRtc->RTC_TIMR = dwTime;
+ pRtc->RTC_CR &= (uint32_t)(~RTC_CR_UPDTIM);
+ pRtc->RTC_SCCR |= RTC_SCCR_SECCLR;
+
+ return (int)(pRtc->RTC_VER & RTC_VER_NVTIM);
+}
+
+/**
+ * \brief Retrieves the current time as stored in the RTC in several variables.
+ *
+ * \param pucHour If not null, current hour is stored in this variable.
+ * \param pucMinute If not null, current minute is stored in this variable.
+ * \param pucSecond If not null, current second is stored in this variable.
+ */
+extern void RTC_GetTime(Rtc *pRtc, uint8_t *pucHour,
+ uint8_t *pucMinute, uint8_t *pucSecond)
+{
+ uint32_t dwTime;
+
+ TRACE_DEBUG("RTC_GetTime()\n\r");
+
+ /* Get current RTC time */
+ dwTime = pRtc->RTC_TIMR;
+
+ while (dwTime != pRtc->RTC_TIMR)
+ dwTime = pRtc->RTC_TIMR;
+
+ /* Hour */
+ if (pucHour) {
+ *pucHour = ((dwTime & 0x00300000) >> 20) * 10
+ + ((dwTime & 0x000F0000) >> 16);
+
+ if ((dwTime & RTC_TIMR_AMPM) == RTC_TIMR_AMPM)
+ *pucHour += 12;
+ }
+
+ /* Minute */
+ if (pucMinute) {
+ *pucMinute = ((dwTime & 0x00007000) >> 12) * 10
+ + ((dwTime & 0x00000F00) >> 8);
+ }
+
+ /* Second */
+ if (pucSecond) {
+ *pucSecond = ((dwTime & 0x00000070) >> 4) * 10
+ + (dwTime & 0x0000000F);
+ }
+}
+
+/**
+ * \brief Sets a time alarm on the RTC.
+ * The match is performed only on the provided variables;
+ * Setting all pointers to 0 disables the time alarm.
+ *
+ * \note In AM/PM mode, the hour value must have bit #7 set for PM, cleared for
+ * AM (as expected in the time registers).
+ *
+ * \param pucHour If not null, the time alarm will hour-match this value.
+ * \param pucMinute If not null, the time alarm will minute-match this value.
+ * \param pucSecond If not null, the time alarm will second-match this value.
+ *
+ * \return 0 success, 1 fail to set
+ */
+extern int RTC_SetTimeAlarm(Rtc *pRtc, uint8_t *pucHour,
+ uint8_t *pucMinute, uint8_t *pucSecond)
+{
+ uint32_t dwAlarm = 0;
+
+ TRACE_DEBUG("RTC_SetTimeAlarm()\n\r");
+
+ /* Hour */
+ if (pucHour)
+ dwAlarm |= RTC_TIMALR_HOUREN | ((*pucHour / 10) << 20) | ((
+ *pucHour % 10) << 16);
+
+ /* Minute */
+ if (pucMinute) {
+ dwAlarm |= RTC_TIMALR_MINEN | ((*pucMinute / 10) << 12)
+ | ((*pucMinute % 10) << 8);
+ }
+
+ /* Second */
+ if (pucSecond)
+ dwAlarm |= RTC_TIMALR_SECEN | ((*pucSecond / 10) << 4) | (*pucSecond % 10);
+
+ pRtc->RTC_TIMALR = dwAlarm;
+
+ return (int)(pRtc->RTC_VER & RTC_VER_NVTIMALR);
+}
+
+/**
+ * \brief Retrieves the current year, month and day from the RTC.
+ * Month, day and week values are numbered starting at 1.
+ *
+ * \param pYwear Current year (optional).
+ * \param pucMonth Current month (optional).
+ * \param pucDay Current day (optional).
+ * \param pucWeek Current day in current week (optional).
+ */
+extern void RTC_GetDate(Rtc *pRtc, uint16_t *pwYear, uint8_t *pucMonth,
+ uint8_t *pucDay, uint8_t *pucWeek)
+{
+ uint32_t dwDate;
+
+ /* Get current date (multiple reads are necessary to insure a stable value) */
+ do {
+ dwDate = pRtc->RTC_CALR;
+ } while (dwDate != pRtc->RTC_CALR);
+
+ /* Retrieve year */
+ if (pwYear) {
+ *pwYear = (((dwDate >> 4) & 0x7) * 1000)
+ + ((dwDate & 0xF) * 100)
+ + (((dwDate >> 12) & 0xF) * 10)
+ + ((dwDate >> 8) & 0xF);
+ }
+
+ /* Retrieve month */
+ if (pucMonth)
+ *pucMonth = (((dwDate >> 20) & 1) * 10) + ((dwDate >> 16) & 0xF);
+
+ /* Retrieve day */
+ if (pucDay)
+ *pucDay = (((dwDate >> 28) & 0x3) * 10) + ((dwDate >> 24) & 0xF);
+
+ /* Retrieve week */
+ if (pucWeek)
+ *pucWeek = ((dwDate >> 21) & 0x7);
+}
+
+/**
+ * \brief Sets the current year, month and day in the RTC.
+ * Month, day and week values must be numbered starting from 1.
+ *
+ * \note In successive update operations, the user must wait at least one second
+ * after resetting the UPDTIM/UPDCAL bit in the RTC_CR before setting these
+ * bits again. Please look at the RTC section of the datasheet for detail.
+ *
+ * \param wYear Current year.
+ * \param ucMonth Current month.
+ * \param ucDay Current day.
+ * \param ucWeek Day number in current week.
+ *
+ * \return 0 success, 1 fail to set
+ */
+extern int RTC_SetDate(Rtc *pRtc, uint16_t wYear, uint8_t ucMonth,
+ uint8_t ucDay, uint8_t ucWeek)
+{
+ uint32_t wDate;
+ uint8_t ucCent_bcd;
+ uint8_t ucYear_bcd;
+ uint8_t ucMonth_bcd;
+ uint8_t ucDay_bcd;
+ uint8_t ucWeek_bcd;
+
+ ucCent_bcd = ((wYear / 100) % 10) | ((wYear / 1000) << 4);
+ ucYear_bcd = (wYear % 10) | (((wYear / 10) % 10) << 4);
+ ucMonth_bcd = ((ucMonth % 10) | (ucMonth / 10) << 4);
+ ucDay_bcd = ((ucDay % 10) | (ucDay / 10) << 4);
+ ucWeek_bcd = ((ucWeek % 10) | (ucWeek / 10) << 4);
+
+ /* value over flow */
+ if ((ucCent_bcd & (uint8_t)(~RTC_CENT_BIT_LEN_MASK)) |
+ (ucYear_bcd & (uint8_t)(~RTC_YEAR_BIT_LEN_MASK)) |
+ (ucMonth_bcd & (uint8_t)(~RTC_MONTH_BIT_LEN_MASK)) |
+ (ucWeek_bcd & (uint8_t)(~RTC_WEEK_BIT_LEN_MASK)) |
+ (ucDay_bcd & (uint8_t)(~RTC_DATE_BIT_LEN_MASK))
+ )
+ return 1;
+
+
+ /* Convert values to date register value */
+ wDate = ucCent_bcd |
+ (ucYear_bcd << 8) |
+ (ucMonth_bcd << 16) |
+ (ucWeek_bcd << 21) |
+ (ucDay_bcd << 24);
+
+ /* Update calendar register */
+ pRtc->RTC_CR |= RTC_CR_UPDCAL;
+
+ while ((pRtc->RTC_SR & RTC_SR_ACKUPD) != RTC_SR_ACKUPD);
+
+ pRtc->RTC_SCCR = RTC_SCCR_ACKCLR;
+ pRtc->RTC_CALR = wDate;
+ pRtc->RTC_CR &= (uint32_t)(~RTC_CR_UPDCAL);
+ pRtc->RTC_SCCR |= RTC_SCCR_SECCLR; /* clear SECENV in SCCR */
+
+ return (int)(pRtc->RTC_VER & RTC_VER_NVCAL);
+}
+
+/**
+ * \brief Sets a date alarm in the RTC.
+ * The alarm will match only the provided values;
+ * Passing a null-pointer disables the corresponding field match.
+ *
+ * \param pucMonth If not null, the RTC alarm will month-match this value.
+ * \param pucDay If not null, the RTC alarm will day-match this value.
+ *
+ * \return 0 success, 1 fail to set
+ */
+extern int RTC_SetDateAlarm(Rtc *pRtc, uint8_t *pucMonth, uint8_t *pucDay)
+{
+ uint32_t dwAlarm;
+
+ dwAlarm = ((pucMonth) || (pucDay)) ? (0) : (0x01010000);
+
+ TRACE_DEBUG("RTC_SetDateAlarm()\n\r");
+
+ /* Compute alarm field value */
+ if (pucMonth) {
+ dwAlarm |= RTC_CALALR_MTHEN | ((*pucMonth / 10) << 20)
+ | ((*pucMonth % 10) << 16);
+ }
+
+ if (pucDay) {
+ dwAlarm |= RTC_CALALR_DATEEN | ((*pucDay / 10) << 28)
+ | ((*pucDay % 10) << 24);
+ }
+
+ /* Set alarm */
+ pRtc->RTC_CALALR = dwAlarm;
+
+ return (int)(pRtc->RTC_VER & RTC_VER_NVCALALR);
+}
+
+/**
+ * \brief Clear flag bits of status clear command register in the RTC.
+ *
+ * \param mask Bits mask of cleared events
+ */
+extern void RTC_ClearSCCR(Rtc *pRtc, uint32_t dwMask)
+{
+ /* Clear all flag bits in status clear command register */
+ dwMask &= RTC_SCCR_ACKCLR | RTC_SCCR_ALRCLR | RTC_SCCR_SECCLR
+ | RTC_SCCR_TIMCLR | RTC_SCCR_CALCLR;
+
+ pRtc->RTC_SCCR = dwMask;
+}
+
+/**
+ * \brief Get flag bits of status register in the RTC.
+ *
+ * \param mask Bits mask of Status Register
+ *
+ * \return Status register & mask
+ */
+extern uint32_t RTC_GetSR(Rtc *pRtc, uint32_t dwMask)
+{
+ uint32_t dwEvent;
+
+ dwEvent = pRtc->RTC_SR;
+
+ return (dwEvent & dwMask);
+}
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/rtt.c b/bsps/arm/atsam/contrib/libraries/libchip/source/rtt.c
new file mode 100644
index 0000000000..8c6ae89e78
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/rtt.c
@@ -0,0 +1,134 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup rtt_module Working with RTT
+ * \ingroup peripherals_module
+ * The RTT driver provides the interface to configure and use the RTT
+ * peripheral.
+ *
+ * The Real-time Timer is used to count elapsed seconds.\n
+ * This timer is clocked by the 32kHz system clock divided by a programmable
+ * 16-bit value. To be accurate, it is better to use an
+ * external 32kHz crystal instead of the internal 32kHz RC.\n
+ *
+ * To count elapsed seconds, the user could follow these few steps:
+ * <ul>
+ * <li>Programming PTPRES in RTT_MR to feeding the timer with a 1Hz signal.</li>
+ * <li>Writing the bit RTTRST in RTT_MR to restart the timer with new settings.
+ * </li>
+ * </ul>
+ *
+ * An alarm can be set to happen on second by setting alarm value in RTT_AR.
+ * Alarm occurrence can be detected by polling or interrupt.
+ *
+ * For more accurate information, please look at the RTT section of the
+ * Datasheet.
+ *
+ * Related files :\n
+ * \ref rtt.c\n
+ * \ref rtt.h.\n
+ */
+/*@{*/
+/*@}*/
+
+/**
+ * \file
+ *
+ * Implementation of Real Time Timer (RTT) controller.
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+#include "chip.h"
+
+#include <assert.h>
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Changes the prescaler value of the given RTT and restarts it.
+ *
+ * \note This function disables RTT interrupt sources.
+ *
+ * \param rtt Pointer to a Rtt instance.
+ * \param prescaler Prescaler value for the RTT.
+ */
+void RTT_SetPrescaler(Rtt *rtt, uint16_t prescaler)
+{
+ rtt->RTT_MR = (prescaler | RTT_MR_RTTRST);
+}
+
+/**
+ * \brief Returns the current value of the RTT timer value.
+ *
+ * \param rtt Pointer to a Rtt instance.
+ */
+uint32_t RTT_GetTime(Rtt *rtt)
+{
+ return rtt->RTT_VR;
+}
+
+/**
+ * \brief Enables the specified RTT interrupt sources.
+ *
+ * \param rtt Pointer to a Rtt instance.
+ * \param sources Bitmask of interrupts to enable.
+ */
+void RTT_EnableIT(Rtt *rtt, uint32_t sources)
+{
+ assert((sources & 0x0004FFFF) == 0);
+ rtt->RTT_MR |= sources;
+}
+
+/**
+ * \brief Returns the status register value of the given RTT.
+ *
+ * \param rtt Pointer to an Rtt instance.
+ */
+uint32_t RTT_GetStatus(Rtt *rtt)
+{
+ return rtt->RTT_SR;
+}
+
+/**
+ * \brief Configures the RTT to generate an alarm at the given time.
+ *
+ * \param pRtt Pointer to an Rtt instance.
+ * \param time Alarm time.
+ */
+void RTT_SetAlarm(Rtt *pRtt, uint32_t time)
+{
+ assert(time > 0);
+
+ pRtt->RTT_AR = time - 1;
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/sdramc.c b/bsps/arm/atsam/contrib/libraries/libchip/source/sdramc.c
new file mode 100644
index 0000000000..ab5f2d8ec8
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/sdramc.c
@@ -0,0 +1,212 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup sdram_module
+ * The SDRAMC driver provides the Interface to configure the SDRAM Controller
+ * (SDRAMC).
+ * \section Usage
+ * <ul>
+ * <li> Configure SDRAM using SDRAMC_Configure().</li>
+
+ * </ul>
+ * For more accurate information, please look at the SDRAMC section of the
+ * Datasheet.
+ * Related files :\n
+ * \ref sdramc.c\n
+ * \ref sdramc.h.\n
+*/
+
+/**
+* \file
+*
+* \section Purpose
+*
+* Interface for configuring and using SDRAM Controller (SDRAMC).
+*
+*/
+
+/**
+ * \file
+ *
+ * Implementation of memories configuration on board.
+ *
+ */
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+#include "chip.h"
+#include "sdramc.h"
+
+/*----------------------------------------------------------------------------
+ * Local functions
+ *----------------------------------------------------------------------------*/
+/**
+ * \brief Calculate the sdram controller config register value.
+ * \param pMemory Pointer to the sdram structure.
+ * \return Configure register value.
+ */
+static uint32_t SDRAMC_compute_CR_value(SSdramc_Memory *pMemory)
+{
+ uint32_t dw = 0;
+
+ dw |= pMemory->cfg.dwColumnBits;
+ dw |= pMemory->cfg.dwRowBits;
+ dw |= pMemory->cfg.dwBanks; //NB, number of banks
+ dw |= pMemory->cfg.dwCAS; //CAS, CAS latency
+ dw |= pMemory->cfg.dwDataBusWidth; //DBW, data bus width
+ dw |= SDRAMC_CR_TWR(pMemory->cfg.dwWriteRecoveryDelay);
+ //TWR, Write Recovery Delay
+ dw |= SDRAMC_CR_TRC_TRFC(pMemory->cfg.dwRowCycleDelay_RowRefreshCycle);
+ //TRC_TRFC,Row Cycle Delay and Row Refresh Cycle
+ dw |= SDRAMC_CR_TRP(pMemory->cfg.dwRowPrechargeDelay);
+ //TRP, Row Precharge Delay
+ dw |= SDRAMC_CR_TRCD(pMemory->cfg.dwRowColumnDelay);
+ //TRCD, Row to Column Delay
+ dw |= SDRAMC_CR_TRAS(pMemory->cfg.dwActivePrechargeDelay);
+ //TRAS, Active to Precharge Delay
+ dw |= SDRAMC_CR_TXSR(pMemory->cfg.dwExitSelfRefreshActiveDelay);
+ //TXSR, Exit Self Refresh to Active Delay
+ return dw;
+}
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+/**
+ * \brief Configure and initialize the SDRAM controller.
+ * \param pMemory Pointer to the sdram structure.
+ * \param dwClockFrequency SDRAM clock frequency.
+ */
+extern void SDRAMC_Configure(SSdramc_Memory *pMemory,
+ uint32_t dwClockFrequency)
+{
+ volatile uint32_t dw;
+
+ /* SDRAM hardware init */
+ /* Enable peripheral clock */
+ PMC_EnablePeripheral(ID_SMC);
+
+ /* SDRAM device configure */
+ /* Step 1. */
+ /* Program the features of SDRAM device into the Configuration Register.*/
+ SDRAMC->SDRAMC_CR = SDRAMC_compute_CR_value(pMemory);
+
+ /* Step 2. */
+ /* For low-power SDRAM, temperature-compensated self refresh (TCSR),
+ drive strength (DS) and partial array self refresh (PASR) must be set
+ in the Low-power Register.*/
+ SDRAMC->SDRAMC_LPR = 0;
+
+ /* Step 3. */
+ /* Program the memory device type into the Memory Device Register */
+ SDRAMC->SDRAMC_MDR = SDRAMC_MDR_MD_SDRAM;
+
+ /* Step 4 */
+ /* A minimum pause of 200 ¦Ìs is provided to precede any signal toggle.
+ (6 core cycles per iteration) */
+ for (dw = 0; dw < ((dwClockFrequency / 1000000) * 200 / 6); dw++);
+
+ /* Step 5. */
+ /* A NOP command is issued to the SDR-SDRAM. Program NOP command into
+ Mode Register, the application must set Mode to 1 in the Mode Register.
+ Perform a write access to any SDR-SDRAM address to acknowledge this command.
+ Now the clock which drives SDR-SDRAM device is enabled.*/
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_NOP;
+ *(uint16_t *)(EBI_SDRAMC_ADDR) = 0;
+
+ /* Step 6. */
+ /* An all banks precharge command is issued to the SDR-SDRAM. Program all
+ banks precharge command into Mode Register, the application must set Mode to
+ 2 in the Mode Register . Perform a write access to any SDRSDRAM address to
+ acknowledge this command. */
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_ALLBANKS_PRECHARGE;
+ *(uint16_t *)(EBI_SDRAMC_ADDR) = 0x0;
+
+ /* add some delays after precharge */
+ for (dw = 0; dw < ((dwClockFrequency / 1000000) * 200 / 6); dw++);
+
+ /* Step 7. */
+ /* Eight auto-refresh (CBR) cycles are provided. Program the auto refresh
+ command (CBR) into Mode Register, the application must set Mode to 4 in
+ the Mode Register. Once in the idle state, eight AUTO REFRESH cycles must
+ be performed. */
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_AUTO_REFRESH;
+ *(uint16_t *)(EBI_SDRAMC_ADDR + 0) = 0x1;
+
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_AUTO_REFRESH;
+ *(uint16_t *)(EBI_SDRAMC_ADDR + 0) = 0x2;
+
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_AUTO_REFRESH;
+ *(uint16_t *)(EBI_SDRAMC_ADDR + 0) = 0x3;
+
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_AUTO_REFRESH;
+ *(uint16_t *)(EBI_SDRAMC_ADDR + 0) = 0x4;
+
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_AUTO_REFRESH;
+ *(uint16_t *)(EBI_SDRAMC_ADDR + 0) = 0x5;
+
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_AUTO_REFRESH;
+ *(uint16_t *)(EBI_SDRAMC_ADDR + 0) = 0x6;
+
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_AUTO_REFRESH;
+ *(uint16_t *)(EBI_SDRAMC_ADDR + 0) = 0x7;
+
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_AUTO_REFRESH;
+ *(uint16_t *)(EBI_SDRAMC_ADDR + 0) = 0x8;
+
+ /* Step 8. */
+ /* A Mode Register set (MRS) cycle is issued to program the parameters of
+ the SDRAM devices, in particular CAS latency and burst length. */
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_LOAD_MODEREG;
+ *(uint16_t *)(EBI_SDRAMC_ADDR + 0x22) = 0xcafe;
+
+ /* Step 9. */
+ /* For low-power SDR-SDRAM initialization, an Extended Mode Register set
+ (EMRS) cycle is issued to program the SDR-SDRAM parameters (TCSR, PASR, DS).
+ The write address must be chosen so that BA[1] is set to 1 and BA[0] is set
+ to 0 */
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_EXT_LOAD_MODEREG;
+ *((uint16_t *)(EBI_SDRAMC_ADDR + (1 << pMemory->cfg.dwBK1))) = 0;
+
+ /* Step 10. */
+ /* The application must go into Normal Mode, setting Mode to 0 in the Mode
+ Register and perform a write access at any location in the SDRAM to
+ acknowledge this command. */
+ SDRAMC->SDRAMC_MR = SDRAMC_MR_MODE_NORMAL;
+ *(uint16_t *)(EBI_SDRAMC_ADDR) = 0x0;
+
+ /* Step 11. */
+ /* Write the refresh rate into the count field in the SDRAMC Refresh
+ Timer register. Set Refresh timer 15.625 us*/
+ dw = dwClockFrequency / 1000u;
+ dw *= 15625u;
+ dw /= 1000000u;
+ SDRAMC->SDRAMC_TR = SDRAMC_TR_COUNT(dw);
+}
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/spi.c b/bsps/arm/atsam/contrib/libraries/libchip/source/spi.c
new file mode 100644
index 0000000000..4b6896f89f
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/spi.c
@@ -0,0 +1,282 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup spi_module Working with SPI
+ * The SPI driver provides the interface to configure and use the SPI
+ * peripheral.
+ *
+ * The Serial Peripheral Interface (SPI) circuit is a synchronous serial
+ * data link that provides communication with external devices in Master
+ * or Slave Mode.
+ *
+ * To use the SPI, the user has to follow these few steps:
+ * -# Enable the SPI pins required by the application (see pio.h).
+ * -# Configure the SPI using the \ref SPI_Configure(). This enables the
+ * peripheral clock. The mode register is loaded with the given value.
+ * -# Configure all the necessary chip selects with \ref SPI_ConfigureNPCS().
+ * -# Enable the SPI by calling \ref SPI_Enable().
+ * -# Send/receive data using \ref SPI_Write() and \ref SPI_Read(). Note that
+ * \ref SPI_Read()
+ * must be called after \ref SPI_Write() to retrieve the last value read.
+ * -# Disable the SPI by calling \ref SPI_Disable().
+ *
+ * For more accurate information, please look at the SPI section of the
+ * Datasheet.
+ *
+ * Related files :\n
+ * \ref spi.c\n
+ * \ref spi.h.\n
+ */
+/*@{*/
+/*@}*/
+
+/**
+ * \file
+ *
+ * Implementation of Serial Peripheral Interface (SPI) controller.
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Enables a SPI peripheral.
+ *
+ * \param spi Pointer to an SPI instance.
+ */
+extern void SPI_Enable(Spi *spi)
+{
+ spi->SPI_CR = SPI_CR_SPIEN;
+}
+
+/**
+ * \brief Disables a SPI peripheral.
+ *
+ * \param spi Pointer to an SPI instance.
+ */
+extern void SPI_Disable(Spi *spi)
+{
+ spi->SPI_CR = SPI_CR_SPIDIS;
+}
+
+/**
+ * \brief Enables one or more interrupt sources of a SPI peripheral.
+ *
+ * \param spi Pointer to an SPI instance.
+ * \param sources Bitwise OR of selected interrupt sources.
+ */
+extern void SPI_EnableIt(Spi *spi, uint32_t dwSources)
+{
+ spi->SPI_IER = dwSources;
+}
+
+/**
+ * \brief Disables one or more interrupt sources of a SPI peripheral.
+ *
+ * \param spi Pointer to an SPI instance.
+ * \param sources Bitwise OR of selected interrupt sources.
+ */
+extern void SPI_DisableIt(Spi *spi, uint32_t dwSources)
+{
+ spi->SPI_IDR = dwSources;
+}
+
+/**
+ * \brief Configures a SPI peripheral as specified. The configuration can be
+ * computed using several macros (see \ref spi_configuration_macros).
+ *
+ * \param spi Pointer to an SPI instance.
+ * \param id Peripheral ID of the SPI.
+ * \param configuration Value of the SPI configuration register.
+ */
+extern void SPI_Configure(Spi *spi, uint32_t dwId, uint32_t dwConfiguration)
+{
+ PMC_EnablePeripheral(dwId);
+
+ spi->SPI_CR = SPI_CR_SPIDIS;
+
+ /* Execute a software reset of the SPI twice */
+ spi->SPI_CR = SPI_CR_SWRST;
+ spi->SPI_CR = SPI_CR_SWRST;
+ spi->SPI_MR = dwConfiguration;
+}
+
+/**
+ * \brief Configures SPI chip select.
+ *
+ * \param spi Pointer to an SPI instance.
+ * \param cS Chip select of NPSCx.
+ */
+extern void SPI_ChipSelect(Spi *spi, uint8_t cS)
+{
+ spi->SPI_MR |= SPI_MR_PCS_Msk;
+ spi->SPI_MR &= ~(SPI_MR_PCS (cS));
+}
+
+/**
+ * \brief Configures SPI Mode Register.
+ *
+ * \param spi Pointer to an SPI instance.
+ * \param configuration Value of the SPI mode register.
+ */
+extern void SPI_SetMode(Spi *spi,
+ uint32_t dwConfiguration)
+{
+ spi->SPI_MR = dwConfiguration;
+}
+
+/**
+ * \brief Configures SPI to release last used CS line.
+ *
+ * \param spi Pointer to an SPI instance.
+ */
+extern void SPI_ReleaseCS(Spi *spi)
+{
+ spi->SPI_CR = SPI_CR_LASTXFER;
+}
+
+
+/**
+ * \brief Configures a chip select of a SPI peripheral. The chip select
+ * configuration is computed using several macros
+ * (see \ref spi_configuration_macros).
+ *
+ * \param spi Pointer to an SPI instance.
+ * \param npcs Chip select to configure (0, 1, 2 or 3).
+ * \param configuration Desired chip select configuration.
+ */
+void SPI_ConfigureNPCS(Spi *spi, uint32_t dwNpcs, uint32_t dwConfiguration)
+{
+ spi->SPI_CSR[dwNpcs] = dwConfiguration;
+}
+
+/**
+ * \brief Configures a chip select active mode of a SPI peripheral.
+ *
+ * \param spi Pointer to an SPI instance.
+ * \param dwNpcs Chip select to configure (0, 1, 2 or 3).
+ * \param bReleaseOnLast CS controlled by last transfer.
+ * SPI_ReleaseCS() is used to release CS.
+ */
+void SPI_ConfigureCSMode(Spi *spi, uint32_t dwNpcs, uint32_t bReleaseOnLast)
+{
+ if (bReleaseOnLast)
+ spi->SPI_CSR[dwNpcs] |= SPI_CSR_CSAAT;
+ else
+ spi->SPI_CSR[dwNpcs] &= ~SPI_CSR_CSAAT;
+}
+
+/**
+ * \brief Get the current status register of the given SPI peripheral.
+ * \note This resets the internal value of the status register, so further
+ * read may yield different values.
+ * \param spi Pointer to a Spi instance.
+ * \return SPI status register.
+ */
+extern uint32_t SPI_GetStatus(Spi *spi)
+{
+ return spi->SPI_SR;
+}
+
+/**
+ * \brief Reads and returns the last word of data received by a SPI peripheral.
+ * This method must be called after a successful SPI_Write call.
+ *
+ * \param spi Pointer to an Spi instance.
+ *
+ * \return read data.
+ */
+extern uint32_t SPI_Read(Spi *spi)
+{
+ while ((spi->SPI_SR & SPI_SR_RDRF) == 0);
+
+ return spi->SPI_RDR & 0xFFFF;
+}
+
+/**
+ * \brief Sends data through a SPI peripheral. If the SPI is configured to use a
+ * fixed peripheral select, the npcs value is meaningless. Otherwise,
+ * it identifies the component which shall be addressed.
+ *
+ * \param spi Pointer to an SPI instance.
+ * \param npcs Chip select of the component to address (0, 1, 2 or 3).
+ * \param data Word of data to send.
+ */
+extern void SPI_Write(Spi *spi, uint32_t dwNpcs, uint16_t wData)
+{
+ /* Send data */
+ while ((spi->SPI_SR & SPI_SR_TXEMPTY) == 0);
+
+ spi->SPI_TDR = wData | SPI_PCS(dwNpcs);
+
+ while ((spi->SPI_SR & SPI_SR_TDRE) == 0);
+}
+
+/**
+ * \brief Sends last data through a SPI peripheral.
+ * If the SPI is configured to use a fixed peripheral select, the npcs value is
+ * meaningless. Otherwise, it identifies the component which shall be addressed.
+ *
+ * \param spi Pointer to an SPI instance.
+ * \param npcs Chip select of the component to address (0, 1, 2 or 3).
+ * \param data Word of data to send.
+ */
+extern void SPI_WriteLast(Spi *spi, uint32_t dwNpcs, uint16_t wData)
+{
+ /* Send data */
+ while ((spi->SPI_SR & SPI_SR_TXEMPTY) == 0);
+
+ spi->SPI_TDR = wData | SPI_PCS(dwNpcs) | SPI_TDR_LASTXFER;
+
+ while ((spi->SPI_SR & SPI_SR_TDRE) == 0);
+}
+
+/**
+ * \brief Check if SPI transfer finish.
+ *
+ * \param spi Pointer to an SPI instance.
+ *
+ * \return Returns 1 if there is no pending write operation on the SPI;
+ * otherwise returns 0.
+ */
+extern uint32_t SPI_IsFinished(Spi *spi)
+{
+ return ((spi->SPI_SR & SPI_SR_TXEMPTY) != 0);
+}
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/spi_dma.c b/bsps/arm/atsam/contrib/libraries/libchip/source/spi_dma.c
new file mode 100644
index 0000000000..8cd9ed1ddd
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/spi_dma.c
@@ -0,0 +1,392 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \addtogroup spi_dma_module SPI xDMA driver
+ * \ingroup lib_spiflash
+ * \section Usage
+ *
+ * <ul>
+ * <li> SPID_Configure() initializes and configures the SPI peripheral and xDMA
+ * for data transfer.</li>
+ * <li> Configures the parameters for the device corresponding to the cs value
+ * by SPID_ConfigureCS(). </li>
+ * <li> Starts a SPI master transfer. This is a non blocking function
+ * SPID_SendCommand(). It will
+ * return as soon as the transfer is started..</li>
+ * </ul>
+ *
+ */
+
+/**
+ * \file
+ *
+ * Implementation for the SPI Flash with xDMA driver.
+ *
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+/*----------------------------------------------------------------------------
+ * Definitions
+ *----------------------------------------------------------------------------*/
+
+/** xDMA support */
+#define USE_SPI_DMA
+
+/** xDMA Link List size for SPI transmission*/
+#define DMA_SPI_LLI 2
+
+/*----------------------------------------------------------------------------
+ * Macros
+ *----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * Local Variables
+ *----------------------------------------------------------------------------*/
+
+
+/* DMA driver instance */
+static uint32_t spiDmaTxChannel;
+static uint32_t spiDmaRxChannel;
+
+/*----------------------------------------------------------------------------
+ * Local functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief SPI xDMA Rx callback
+ * Invoked on SPi DMA reception done.
+ * \param channel DMA channel.
+ * \param pArg Pointer to callback argument - Pointer to Spid instance.
+ */
+static void SPID_Rx_Cb(uint32_t channel, Spid *pArg)
+{
+ SpidCmd *pSpidCmd = pArg->pCurrentCommand;
+ Spi *pSpiHw = pArg->pSpiHw;
+
+ if (channel != spiDmaRxChannel)
+ return;
+
+ /* Disable the SPI TX & RX */
+ SPI_Disable (pSpiHw);
+ TRACE_INFO("SPI Rx DMA Callback has been called %d bytes received\n\r",
+ pArg->pCurrentCommand->RxSize);
+ /* Configure and enable interrupt on RC compare */
+ NVIC_ClearPendingIRQ(XDMAC_IRQn);
+ NVIC_DisableIRQ(XDMAC_IRQn);
+
+ /* Disable the SPI Peripheral */
+ PMC_DisablePeripheral (pArg->spiId);
+
+ /* Release CS */
+ SPI_ReleaseCS(pSpiHw);
+
+ /* Release the DMA channels */
+ XDMAD_FreeChannel(pArg->pXdmad, spiDmaRxChannel);
+ XDMAD_FreeChannel(pArg->pXdmad, spiDmaTxChannel);
+ SCB_InvalidateDCache_by_Addr((uint32_t *)pArg->pCurrentCommand->pRxBuff,
+ pArg->pCurrentCommand->RxSize);
+ /* Release the dataflash semaphore */
+ pArg->semaphore++;
+
+ printf(" %s\n\r", pArg->pCurrentCommand->pRxBuff);
+
+ /* Invoke the callback associated with the current command */
+ if (pSpidCmd && pSpidCmd->callback) {
+ //printf("p %d", pArg->semaphore);
+ pSpidCmd->callback(0, pSpidCmd->pArgument);
+ }
+}
+
+/**
+ * \brief Configure the DMA Channels: 0 RX, 1 TX.
+ * Channels are disabled after configure.
+ * \returns 0 if the dma channel configuration successfully; otherwise returns
+ * SPID_ERROR_XXX.
+ */
+static uint8_t _spid_configureDmaChannels(Spid *pSpid)
+{
+ /* Driver initialize */
+ XDMAD_FreeChannel(pSpid->pXdmad, spiDmaTxChannel);
+ XDMAD_FreeChannel(pSpid->pXdmad, spiDmaRxChannel);
+
+ /* Allocate a DMA channel for SPI0/1 TX. */
+ spiDmaTxChannel = XDMAD_AllocateChannel(pSpid->pXdmad,
+ XDMAD_TRANSFER_MEMORY, pSpid->spiId);
+
+ if (spiDmaTxChannel == XDMAD_ALLOC_FAILED)
+ return SPID_ERROR;
+
+ /* Allocate a DMA channel for SPI0/1 RX. */
+ spiDmaRxChannel =
+ XDMAD_AllocateChannel(pSpid->pXdmad, pSpid->spiId, XDMAD_TRANSFER_MEMORY);
+
+ if (spiDmaRxChannel == XDMAD_ALLOC_FAILED)
+ return SPID_ERROR;
+
+ /* Setup callbacks for SPI0/1 RX */
+ XDMAD_SetCallback(pSpid->pXdmad, spiDmaRxChannel,
+ (XdmadTransferCallback)SPID_Rx_Cb, pSpid);
+
+ if (XDMAD_PrepareChannel(pSpid->pXdmad, spiDmaRxChannel))
+ return SPID_ERROR;
+
+ /* Setup callbacks for SPI0/1 TX (ignored) */
+ XDMAD_SetCallback(pSpid->pXdmad, spiDmaTxChannel, NULL, NULL);
+
+ if (XDMAD_PrepareChannel(pSpid->pXdmad, spiDmaTxChannel))
+ return SPID_ERROR;
+
+ return 0;
+}
+
+/**
+ * \brief Configure the DMA source and destination with Linker List mode.
+ *
+ * \param pCommand Pointer to command
+ * \returns 0 if the dma multibuffer configuration successfully; otherwise
+ * returns SPID_ERROR_XXX.
+ */
+static uint8_t _spid_configureLinkList(Spi *pSpiHw, void *pXdmad,
+ SpidCmd *pCommand)
+{
+ sXdmadCfg xdmadRxCfg, xdmadTxCfg;
+ uint32_t xdmaCndc, xdmaInt;
+ uint32_t spiId;
+
+ if ((unsigned int)pSpiHw == (unsigned int)SPI0) spiId = ID_SPI0;
+
+ if ((unsigned int)pSpiHw == (unsigned int)SPI1) spiId = ID_SPI1;
+
+ /* Setup TX */
+
+ xdmadTxCfg.mbr_sa = (uint32_t)pCommand->pTxBuff;
+
+ xdmadTxCfg.mbr_da = (uint32_t)&pSpiHw->SPI_TDR;
+
+ xdmadTxCfg.mbr_ubc = XDMA_UBC_NVIEW_NDV0 |
+ XDMA_UBC_NDE_FETCH_DIS |
+ XDMA_UBC_NSEN_UPDATED | pCommand->TxSize;
+
+ xdmadTxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_MEM2PER |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_INCREMENTED_AM |
+ XDMAC_CC_DAM_FIXED_AM |
+ XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(spiId, XDMAD_TRANSFER_TX));
+
+
+ xdmadTxCfg.mbr_bc = 0;
+ xdmadTxCfg.mbr_sus = 0;
+ xdmadTxCfg.mbr_dus = 0;
+
+ /* Setup RX Link List */
+
+ xdmadRxCfg.mbr_ubc = XDMA_UBC_NVIEW_NDV0 |
+ XDMA_UBC_NDE_FETCH_DIS |
+ XDMA_UBC_NDEN_UPDATED | pCommand->RxSize;
+
+ xdmadRxCfg.mbr_da = (uint32_t)pCommand->pRxBuff;
+
+ xdmadRxCfg.mbr_sa = (uint32_t)&pSpiHw->SPI_RDR;
+ xdmadRxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_PER2MEM |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_FIXED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(spiId, XDMAD_TRANSFER_RX));
+
+
+ xdmadRxCfg.mbr_bc = 0;
+ xdmadRxCfg.mbr_sus = 0;
+ xdmadRxCfg.mbr_dus = 0;
+
+ xdmaCndc = 0;
+
+ /* Put all interrupts on for non LLI list setup of DMA */
+ xdmaInt = (XDMAC_CIE_BIE |
+ XDMAC_CIE_DIE |
+ XDMAC_CIE_FIE |
+ XDMAC_CIE_RBIE |
+ XDMAC_CIE_WBIE |
+ XDMAC_CIE_ROIE);
+
+ if (XDMAD_ConfigureTransfer(pXdmad, spiDmaRxChannel, &xdmadRxCfg, xdmaCndc, 0,
+ xdmaInt))
+ return SPID_ERROR;
+
+ if (XDMAD_ConfigureTransfer(pXdmad, spiDmaTxChannel, &xdmadTxCfg, xdmaCndc, 0,
+ xdmaInt))
+ return SPID_ERROR;
+
+ return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+/**
+ * \brief Initializes the Spid structure and the corresponding SPI & DMA hardware.
+ * select value.
+ * The driver will uses DMA channel 0 for RX and DMA channel 1 for TX.
+ * The DMA channels are freed automatically when no SPI command processing.
+ *
+ * \param pSpid Pointer to a Spid instance.
+ * \param pSpiHw Associated SPI peripheral.
+ * \param spiId SPI peripheral identifier.
+ * \param pDmad Pointer to a Dmad instance.
+ */
+uint32_t SPID_Configure(Spid *pSpid ,
+ Spi *pSpiHw ,
+ uint8_t spiId,
+ uint32_t spiMode,
+ sXdmad *pXdmad)
+{
+ /* Initialize the SPI structure */
+ pSpid->pSpiHw = pSpiHw;
+ pSpid->spiId = spiId;
+ pSpid->semaphore = 1;
+ pSpid->pCurrentCommand = 0;
+ assert(pXdmad == &XDMAD_Instance);
+ pSpid->pXdmad = pXdmad;
+
+ /* Enable the SPI Peripheral ,Execute a software reset of the SPI,
+ Configure SPI in Master Mode*/
+ SPI_Configure (pSpiHw, pSpid->spiId, spiMode);
+
+ return 0;
+}
+
+/**
+ * \brief Configures the parameters for the device corresponding to the cs value.
+ *
+ * \param pSpid Pointer to a Spid instance.
+ * \param cs number corresponding to the SPI chip select.
+ * \param csr SPI_CSR value to setup.
+ */
+void SPID_ConfigureCS(Spid *pSpid,
+ uint32_t dwCS,
+ uint32_t dwCsr)
+{
+ Spi *pSpiHw = pSpid->pSpiHw;
+
+ /* Enable the SPI Peripheral */
+ PMC_EnablePeripheral (pSpid->spiId);
+ /* Configure SPI Chip Select Register */
+ SPI_ConfigureNPCS(pSpiHw, dwCS, dwCsr);
+
+ /* Disable the SPI Peripheral */
+ PMC_DisablePeripheral (pSpid->spiId);
+
+}
+
+/**
+ * \brief Starts a SPI master transfer. This is a non blocking function. It will
+ * return as soon as the transfer is started.
+ *
+ * \param pSpid Pointer to a Spid instance.
+ * \param pCommand Pointer to the SPI command to execute.
+ * \returns 0 if the transfer has been started successfully; otherwise returns
+ * SPID_ERROR_LOCK is the driver is in use, or SPID_ERROR if the command is not
+ * valid.
+ */
+uint32_t SPID_SendCommand(Spid *pSpid, SpidCmd *pCommand)
+{
+ Spi *pSpiHw = pSpid->pSpiHw;
+
+ /* Try to get the dataflash semaphore */
+ if (pSpid->semaphore == 0)
+ return SPID_ERROR_LOCK;
+
+ pSpid->semaphore--;
+
+ /* Enable the SPI Peripheral */
+ PMC_EnablePeripheral (pSpid->spiId);
+
+ /* SPI chip select */
+ SPI_ChipSelect (pSpiHw, 1 << pCommand->spiCs);
+
+ // Initialize the callback
+ pSpid->pCurrentCommand = pCommand;
+
+ /* Initialize DMA controller using channel 0 for RX, 1 for TX. */
+ if (_spid_configureDmaChannels(pSpid))
+ return SPID_ERROR_LOCK;
+
+ /* Configure and enable interrupt on RC compare */
+ NVIC_ClearPendingIRQ(XDMAC_IRQn);
+ NVIC_SetPriority(XDMAC_IRQn , 1);
+ NVIC_EnableIRQ(XDMAC_IRQn);
+
+
+ if (_spid_configureLinkList(pSpiHw, pSpid->pXdmad, pCommand))
+ return SPID_ERROR_LOCK;
+
+ /* Enables the SPI to transfer and receive data. */
+ SPI_Enable (pSpiHw);
+ SCB_CleanDCache_by_Addr((uint32_t *)pCommand->pTxBuff, pCommand->TxSize);
+
+ /* Start DMA 0(RX) && 1(TX) */
+ if (XDMAD_StartTransfer(pSpid->pXdmad, spiDmaRxChannel))
+ return SPID_ERROR_LOCK;
+
+ if (XDMAD_StartTransfer(pSpid->pXdmad, spiDmaTxChannel))
+ return SPID_ERROR_LOCK;
+
+ return 0;
+}
+
+/**
+ * \brief Check if the SPI driver is busy.
+ *
+ * \param pSpid Pointer to a Spid instance.
+ * \returns 1 if the SPI driver is currently busy executing a command; otherwise
+ */
+uint32_t SPID_IsBusy(const Spid *pSpid)
+{
+ if (pSpid->semaphore == 0)
+ return 1;
+ else
+ return 0;
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/ssc.c b/bsps/arm/atsam/contrib/libraries/libchip/source/ssc.c
new file mode 100644
index 0000000000..08f1edde18
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/ssc.c
@@ -0,0 +1,219 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup ssc_module Working with SSC
+ * \ingroup peripherals_module
+ * The SSC driver provides the interface to configure and use the SSC
+ * peripheral.
+ *
+ * !Usage
+ *
+ * -# Enable the SSC interface pins.
+ * -# Configure the SSC to operate at a specific frequency by calling
+ * SSC_Configure(). This function enables the peripheral clock of the SSC,
+ * but not its PIOs.
+ * -# Configure the transmitter and/or the receiver using the
+ * SSC_ConfigureTransmitter() and SSC_ConfigureEmitter() functions.
+ * -# Enable the PIOs or the transmitter and/or the received.
+ * -# Enable the transmitter and/or the receiver using SSC_EnableTransmitter()
+ * and SSC_EnableReceiver()
+ * -# Send data through the transmitter using SSC_Write()
+ * -# Receive data from the receiver using SSC_Read()
+ * -# Disable the transmitter and/or the receiver using SSC_DisableTransmitter()
+ * and SSC_DisableReceiver()
+ *
+ * For more accurate information, please look at the SSC section of the
+ * Datasheet.
+ *
+ * Related files :\n
+ * \ref ssc.c\n
+ * \ref ssc.h.\n
+ */
+/*@{*/
+/*@}*/
+
+
+/**
+ * \file
+ *
+ * Implementation of Synchronous Serial (SSC) controller.
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Configures a SSC peripheral.If the divided clock is not used, the
+ * master clock frequency can be set to 0.
+ * \note The emitter and transmitter are disabled by this function.
+ * \param ssc Pointer to an SSC instance.
+ * \param bitRate bit rate.
+ * \param masterClock master clock.
+ */
+void SSC_Configure(Ssc *ssc, uint32_t bitRate, uint32_t masterClock)
+{
+ uint32_t id;
+ // uint32_t maxClock;
+ id = ID_SSC;
+ // maxClock = PMC_SetPeriMaxClock(id, masterClock);
+
+ /* Reset, disable receiver & transmitter */
+ ssc->SSC_CR = SSC_CR_RXDIS | SSC_CR_TXDIS | SSC_CR_SWRST;
+
+ /* Configure clock frequency */
+ if (bitRate != 0)
+ ssc->SSC_CMR = masterClock / (2 * bitRate);
+ else
+ ssc->SSC_CMR = 0;
+
+ /* Enable SSC peripheral clock */
+ PMC_EnablePeripheral(id);
+}
+
+/**
+ * \brief Configures the transmitter of a SSC peripheral.
+ * \param ssc Pointer to an SSC instance.
+ * \param tcmr Transmit Clock Mode Register value.
+ * \param tfmr Transmit Frame Mode Register value.
+ */
+void SSC_ConfigureTransmitter(Ssc *ssc, uint32_t tcmr, uint32_t tfmr)
+{
+ ssc->SSC_TCMR = tcmr;
+ ssc->SSC_TFMR = tfmr;
+}
+
+/**
+ * \brief Configures the receiver of a SSC peripheral.
+ * \param ssc Pointer to an SSC instance.
+ * \param rcmr Receive Clock Mode Register value.
+ * \param rfmr Receive Frame Mode Register value.
+ */
+void SSC_ConfigureReceiver(Ssc *ssc, uint32_t rcmr, uint32_t rfmr)
+{
+ ssc->SSC_RCMR = rcmr;
+ ssc->SSC_RFMR = rfmr;
+}
+
+/**
+ * \brief Enables the transmitter of a SSC peripheral.
+ * \param ssc Pointer to an SSC instance.
+ */
+void SSC_EnableTransmitter(Ssc *ssc)
+{
+ ssc->SSC_CR = SSC_CR_TXEN;
+}
+
+/**
+ * \brief Disables the transmitter of a SSC peripheral.
+ * \param ssc Pointer to an SSC instance.
+ */
+void SSC_DisableTransmitter(Ssc *ssc)
+{
+ ssc->SSC_CR = SSC_CR_TXDIS;
+}
+
+/**
+ * \brief Enables the receiver of a SSC peripheral.
+ * \param ssc Pointer to an SSC instance.
+ */
+void SSC_EnableReceiver(Ssc *ssc)
+{
+ ssc->SSC_CR = SSC_CR_RXEN;
+}
+
+/**
+ * \brief Disables the receiver of a SSC peripheral.
+ * \param ssc Pointer to an SSC instance.
+ */
+void SSC_DisableReceiver(Ssc *ssc)
+{
+ ssc->SSC_CR = SSC_CR_RXDIS;
+}
+
+/**
+ * \brief Enables one or more interrupt sources of a SSC peripheral.
+ * \param ssc Pointer to an SSC instance.
+ * \param sources Bitwise OR of selected interrupt sources.
+ */
+void SSC_EnableInterrupts(Ssc *ssc, uint32_t sources)
+{
+ ssc->SSC_IER = sources;
+}
+
+/**
+ * \brief Disables one or more interrupt sources of a SSC peripheral.
+ * \param ssc Pointer to an SSC instance.
+ * \param sources Bitwise OR of selected interrupt sources.
+ */
+void SSC_DisableInterrupts(Ssc *ssc, uint32_t sources)
+{
+ ssc->SSC_IDR = sources;
+}
+
+/**
+ * \brief Sends one data frame through a SSC peripheral. If another frame is currently
+ * being sent, this function waits for the previous transfer to complete.
+ * \param ssc Pointer to an SSC instance.
+ * \param frame Data frame to send.
+ */
+void SSC_Write(Ssc *ssc, uint32_t frame)
+{
+ while ((ssc->SSC_SR & SSC_SR_TXRDY) == 0);
+
+ ssc->SSC_THR = frame;
+}
+
+/**
+ * \brief Waits until one frame is received on a SSC peripheral, and returns it.
+ * \param ssc Pointer to an SSC instance.
+ */
+uint32_t SSC_Read(Ssc *ssc)
+{
+ while ((ssc->SSC_SR & SSC_SR_RXRDY) == 0);
+
+ return ssc->SSC_RHR;
+}
+
+/**
+ * \brief Return 1 if one frame is received, 0 otherwise.
+ * \param ssc Pointer to an SSC instance.
+ */
+uint8_t SSC_IsRxReady(Ssc *ssc)
+{
+ return ((ssc->SSC_SR & SSC_SR_RXRDY) > 0);
+}
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/supc.c b/bsps/arm/atsam/contrib/libraries/libchip/source/supc.c
new file mode 100644
index 0000000000..9c2ef98000
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/supc.c
@@ -0,0 +1,193 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+#include <assert.h>
+
+/*----------------------------------------------------------------------------
+ * Local functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Select external 32K Crystal.
+ *
+ */
+
+void SUPC_SelectExtCrystal32K(void)
+{
+ PMC_EnableXT32KFME();
+
+ /* Select XTAL 32k instead of internal slow RC 32k for slow clock */
+ if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST) {
+ SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_XTALSEL_CRYSTAL_SEL;
+
+ while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL));
+ }
+}
+
+/**
+ * \brief VROFF asserts the vddcore_nreset and stops the voltage regulator
+ *
+ */
+void SUPC_DisableVoltageReg(void)
+{
+ SUPC->SUPC_CR |= SUPC_CR_KEY_PASSWD | SUPC_CR_VROFF;
+}
+
+/**
+ * \brief Configures supply monitor
+ *
+ */
+void SUPC_ConfigSupplyMonitor(uint32_t Config)
+{
+ SUPC->SUPC_SMMR = Config;
+}
+
+
+/**
+ * \brief Disables supply monitor
+ *
+ */
+void SUPC_DisableSupplyMonitor(void)
+{
+ SUPC->SUPC_SMMR = SUPC_SMMR_SMSMPL_SMD;
+}
+
+
+/**
+ * \brief Enables/Disables Brownout detector
+ *
+ */
+void SUPC_BrownoutDetectEnable(uint8_t enable)
+{
+ if (enable)
+ SUPC->SUPC_MR = (SUPC_MR_BODDIS_ENABLE | SUPC_MR_KEY_PASSWD);
+ else
+ SUPC->SUPC_MR = (SUPC_MR_BODDIS_DISABLE | SUPC_MR_KEY_PASSWD);
+}
+
+/**
+ * \brief Enables Brownout Detector Reset
+ *
+ */
+void SUPC_BrownoutResetEnable(void)
+{
+ SUPC->SUPC_MR = (SUPC_MR_BODRSTEN_ENABLE | SUPC_MR_KEY_PASSWD);
+}
+
+
+/**
+ * \brief Enables/Disables Sram in backup mode
+ *
+ */
+void SUPC_SramBackupMode(uint8_t enable)
+{
+ if (enable)
+ SUPC->SUPC_MR = ((1 << 17) | SUPC_MR_KEY_PASSWD);
+ else
+ SUPC->SUPC_MR = ((0 << 17) | SUPC_MR_KEY_PASSWD);
+}
+
+/**
+ * \brief Bypass external 32.768KHz oscillator
+ *
+ */
+void SUPC_BypassXtal32KOsc(void)
+{
+ SUPC->SUPC_MR = (SUPC_MR_OSCBYPASS_BYPASS | SUPC_MR_KEY_PASSWD);
+}
+
+
+/**
+ * \brief Enables/Disables Wakeup mode
+ *
+ */
+void SUPC_EnablesWakeupMode(uint32_t Regs, uint8_t enable)
+{
+ if (enable)
+ SUPC->SUPC_WUMR |= Regs;
+ else
+ SUPC->SUPC_WUMR &= ~(uint32_t)Regs;
+}
+
+/**
+ * \brief Configure Wakeup denounce period
+ *
+ */
+void SUPC_SetWakeupDebounce(uint8_t period)
+{
+ SUPC->SUPC_WUMR |= ((period << SUPC_WUMR_WKUPDBC_Pos) & SUPC_WUMR_WKUPDBC_Msk);
+}
+
+/**
+ * \brief Configure Low-power denounce period
+ *
+ */
+void SUPC_SetLowPowerDebounce(uint8_t period)
+{
+ SUPC->SUPC_WUMR |= ((period << SUPC_WUMR_LPDBC_Pos) & SUPC_WUMR_LPDBC_Msk);
+}
+
+
+/**
+ * \brief Enables/Disables Wakeup Inputs
+ *
+ */
+void SUPC_EnablesWakeupInput(uint32_t Input, uint8_t enable)
+{
+ if (enable)
+ SUPC->SUPC_WUIR |= Input;
+ else
+ SUPC->SUPC_WUIR &= ~(uint32_t)Input;
+}
+
+/**
+ * \brief Checks if Crystal oscillator is selected as a slow clock
+ */
+
+uint8_t SUPC_IsSlowClkExtCrystal32K(void)
+{
+ return ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) >> 7);
+}
+
+/**
+ * \brief Checks if Crystal oscillator is selected as a slow clock
+ */
+
+uint8_t SUPC_Read_Status(uint32_t status)
+{
+ return (SUPC->SUPC_SR & status);
+}
+
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/tc.c b/bsps/arm/atsam/contrib/libraries/libchip/source/tc.c
new file mode 100644
index 0000000000..4ef9bd9f50
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/tc.c
@@ -0,0 +1,213 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup tc_module
+ * The TC driver provides the Interface to configure the Timer Counter (TC).
+ *
+ * \section Usage
+ * <ul>
+ * <li> Optionally, use TC_FindMckDivisor() to let the program find the best
+ * TCCLKS field value automatically.</li>
+ * <li> Configure a Timer Counter in the desired mode using TC_Configure().</li>
+ * <li> Start or stop the timer clock using TC_Start() and TC_Stop().</li>
+ *
+ * </ul>
+ * For more accurate information, please look at the TC section of the Datasheet.
+ *
+ * Related files :\n
+ * \ref tc.c\n
+ * \ref tc.h.\n
+*/
+
+/**
+* \file
+*
+* \section Purpose
+*
+* Interface for configuring and using Timer Counter (TC) peripherals.
+*
+* \section Usage
+* -# Optionally, use TC_FindMckDivisor() to let the program find the best
+* TCCLKS field value automatically.
+* -# Configure a Timer Counter in the desired mode using TC_Configure().
+* -# Start or stop the timer clock using TC_Start() and TC_Stop().
+*/
+
+/**
+ * \file
+ *
+ * Implementation of Timer Counter (TC).
+ *
+ */
+
+/*------------------------------------------------------------------------------
+ * Headers
+ *-----------------------------------------------------------------------------*/
+
+#ifndef __rtems__
+#include "board.h"
+#else /* __rtems__ */
+#include <chip.h>
+#endif /* __rtems__ */
+
+#include <assert.h>
+
+/*------------------------------------------------------------------------------
+ * Global functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Configures a Timer Counter Channel
+ *
+ * Configures a Timer Counter to operate in the given mode. Timer is stopped
+ * after configuration and must be restarted with TC_Start(). All the
+ * interrupts of the timer are also disabled.
+ *
+ * \param pTc Pointer to a Tc instance.
+ * \param channel Channel number.
+ * \param mode Operating mode (TC_CMR value).
+ */
+extern void TC_Configure(Tc *pTc, uint32_t dwChannel, uint32_t dwMode)
+{
+ TcChannel *pTcCh;
+
+ assert(dwChannel < (sizeof(pTc->TC_CHANNEL) / sizeof(
+ pTc->TC_CHANNEL[0])));
+ pTcCh = pTc->TC_CHANNEL + dwChannel;
+
+ /* Disable TC clock */
+ pTcCh->TC_CCR = TC_CCR_CLKDIS;
+
+ /* Disable interrupts */
+ pTcCh->TC_IDR = 0xFFFFFFFF;
+
+ /* Clear status register */
+ pTcCh->TC_SR;
+
+ /* Set mode */
+ pTcCh->TC_CMR = dwMode;
+}
+
+/**
+ * \brief Reset and Start the TC Channel
+ *
+ * Enables the timer clock and performs a software reset to start the counting.
+ *
+ * \param pTc Pointer to a Tc instance.
+ * \param dwChannel Channel number.
+ */
+extern void TC_Start(Tc *pTc, uint32_t dwChannel)
+{
+ TcChannel *pTcCh;
+
+ assert(dwChannel < (sizeof(pTc->TC_CHANNEL) / sizeof(
+ pTc->TC_CHANNEL[0])));
+
+ pTcCh = pTc->TC_CHANNEL + dwChannel;
+ pTcCh->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG;
+}
+
+/**
+ * \brief Stop TC Channel
+ *
+ * Disables the timer clock, stopping the counting.
+ *
+ * \param pTc Pointer to a Tc instance.
+ * \param dwChannel Channel number.
+ */
+extern void TC_Stop(Tc *pTc, uint32_t dwChannel)
+{
+ TcChannel *pTcCh;
+
+ assert(dwChannel < (sizeof(pTc->TC_CHANNEL) / sizeof(
+ pTc->TC_CHANNEL[0])));
+
+ pTcCh = pTc->TC_CHANNEL + dwChannel;
+ pTcCh->TC_CCR = TC_CCR_CLKDIS;
+}
+
+/**
+ * \brief Find best MCK divisor
+ *
+ * Finds the best MCK divisor given the timer frequency and MCK. The result
+ * is guaranteed to satisfy the following equation:
+ * \code
+ * (MCK / (DIV * 65536)) <= freq <= (MCK / DIV)
+ * \endcode
+ * with DIV being the highest possible value.
+ *
+ * \param dwFreq Desired timer frequency.
+ * \param dwMCk Master clock frequency.
+ * \param dwDiv Divisor value.
+ * \param dwTcClks TCCLKS field value for divisor.
+ * \param dwBoardMCK Board clock frequency.
+ *
+ * \return 1 if a proper divisor has been found, otherwise 0.
+ */
+extern uint32_t TC_FindMckDivisor(uint32_t dwFreq, uint32_t dwMCk,
+ uint32_t *dwDiv, uint32_t *dwTcClks, uint32_t dwBoardMCK)
+{
+ /*
+ TCCLKS:
+ 0 - PCK6: default source - Slow Clock; update according to actual case
+ 4 - SLCK: (slow clock) is either "Embedded 32kHz RC Oscillator" or
+ "32768Hz Crystal Oscillator"
+ */
+ const uint32_t adwDivisors[5] = { BOARD_MCK / 32768, 8, 32, 128, BOARD_MCK / 32768 };
+
+ uint32_t dwIndex = 0;
+ dwBoardMCK = dwBoardMCK;
+
+ /* Satisfy lower bound */
+ while (dwFreq < ((dwMCk / adwDivisors[dwIndex]) / 65536)) {
+ dwIndex++;
+
+ /* If no divisor can be found, return 0 */
+ if (dwIndex == (sizeof(adwDivisors) / sizeof(adwDivisors[0])))
+ return 0;
+ }
+
+ /* Try to maximize DIV while satisfying upper bound */
+ while (dwIndex < 4) {
+ if (dwFreq > (dwMCk / adwDivisors[dwIndex + 1]))
+ break;
+
+ dwIndex++;
+ }
+
+ /* Store results */
+ if (dwDiv)
+ *dwDiv = adwDivisors[dwIndex];
+
+ if (dwTcClks)
+ *dwTcClks = dwIndex;
+
+ return 1;
+}
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/trng.c b/bsps/arm/atsam/contrib/libraries/libchip/source/trng.c
new file mode 100644
index 0000000000..29dddccd77
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/trng.c
@@ -0,0 +1,122 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup rtng_module Working with RTNG
+ * \ingroup peripherals_module
+ * The TRNG driver provides the interface to configure and use the TRNG
+ * peripheral.\n
+ *
+ * The True Random Number Generator (TRNG) passes the American NIST Special
+ * Publication 800-22 and Diehard Random Tests Suites. As soon as the TRNG is
+ * enabled (TRNG_Enable()), the generator provides one 32-bit value every 84
+ * clock cycles. Interrupt trng_int can be enabled through TRNG_EnableIt()
+ * (respectively disabled in TRNG_IDR).
+ * This interrupt is set when a new random value is available and is cleared
+ * when the status register is read (TRNG_SR register). The flag DATRDY of
+ * the status register (TRNG_ISR) is set when the random data is ready to be
+ * read out on the 32-bit output data through TRNG_GetRandData().
+ *
+ * For more accurate information, please look at the SHA section of the
+ * Datasheet.
+ *
+ * Related files :\n
+ * \ref trng.c\n
+ * \ref trng.h\n
+ */
+/*@{*/
+/*@}*/
+
+/**
+ * \file
+ *
+ * Implementation of True Random Number Generator (TRNG)
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Enables the TRNG to provide Random Values.
+ * \param key This key is to be written when the ENABLE bit is set.
+ */
+void TRNG_Enable(void)
+{
+ TRNG->TRNG_CR = TRNG_CR_ENABLE | TRNG_CR_KEY_PASSWD;
+}
+
+/**
+ * \brief Disables the TRNG to provide Random Values.
+ * \param key This key is to be written when the DISABLE bit is set.
+ */
+void TRNG_Disable(void)
+{
+ TRNG->TRNG_CR = TRNG_CR_KEY_PASSWD;
+}
+
+/**
+ * \brief Data Ready Interrupt enable.
+ */
+void TRNG_EnableIt(void)
+{
+ TRNG->TRNG_IER = TRNG_IER_DATRDY;
+}
+
+/**
+ * \brief Data Ready Interrupt Disable.
+ */
+void TRNG_DisableIt(void)
+{
+ TRNG->TRNG_IDR = TRNG_IDR_DATRDY;
+}
+
+/**
+ * \brief Get the current status register of the given TRNG peripheral.
+ * \return TRNG status register.
+ */
+uint32_t TRNG_GetStatus(void)
+{
+ return TRNG->TRNG_ISR;
+}
+
+/**
+ * \brief Get the 32-bit Output Data from TRNG peripheral.
+ * \return TRNG output data.
+ */
+uint32_t TRNG_GetRandData(void)
+{
+ return TRNG->TRNG_ODATA;
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/twi.c b/bsps/arm/atsam/contrib/libraries/libchip/source/twi.c
new file mode 100644
index 0000000000..29faee684a
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/twi.c
@@ -0,0 +1,382 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup twi_module Working with TWI
+ * \ingroup peripherals_module
+ * The TWI driver provides the interface to configure and use the TWI
+ * peripheral.
+ *
+ * \section Usage
+ * <ul>
+ * <li> Configures a TWI peripheral to operate in master mode, at the given
+ * frequency (in Hz) using TWI_Configure(). </li>
+ * <li> Sends a STOP condition on the TWI using TWI_Stop().</li>
+ * <li> Starts a read operation on the TWI bus with the specified slave using
+ * TWI_StartRead(). Data must then be read using TWI_ReadByte() whenever
+ * a byte is available (poll using TWI_ByteReceived()).</li>
+ * <li> Starts a write operation on the TWI to access the selected slave using
+ * TWI_StartWrite(). A byte of data must be provided to start the write;
+ * other bytes are written next.</li>
+ * <li> Sends a byte of data to one of the TWI slaves on the bus using
+ * TWI_WriteByte().
+ * This function must be called once before TWI_StartWrite() with the first
+ * byte of data
+ * to send, then it shall be called repeatedly after that to send the
+ * remaining bytes.</li>
+ * <li> Check if a byte has been received and can be read on the given TWI
+ * peripheral using TWI_ByteReceived().<
+ * Check if a byte has been sent using TWI_ByteSent().</li>
+ * <li> Check if the current transmission is complete (the STOP has been sent)
+ * using TWI_TransferComplete().</li>
+ * <li> Enables & disable the selected interrupts sources on a TWI peripheral
+ * using TWI_EnableIt() and TWI_DisableIt().</li>
+ * <li> Get current status register of the given TWI peripheral using
+ * TWI_GetStatus(). Get current status register of the given TWI peripheral, but
+ * masking interrupt sources which are not currently enabled using
+ * TWI_GetMaskedStatus().</li>
+ * </ul>
+ * For more accurate information, please look at the TWI section of the
+ * Datasheet.
+ *
+ * Related files :\n
+ * \ref twi.c\n
+ * \ref twi.h.\n
+ */
+/*@{*/
+/*@}*/
+
+/**
+ * \file
+ *
+ * Implementation of Two Wire Interface (TWI).
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+#include <assert.h>
+
+#define TWIHS_IT (TWIHS_IER_TXCOMP | TWIHS_IER_TXCOMP | TWIHS_IER_RXRDY \
+ | TWIHS_IER_TXRDY | TWIHS_IER_SVACC | TWIHS_IER_GACC | \
+ TWIHS_IER_OVRE | TWIHS_IER_UNRE | TWIHS_IER_NACK | \
+ TWIHS_IER_ARBLST | TWIHS_IER_SCL_WS | TWIHS_IER_EOSACC | \
+ TWIHS_IER_MCACK | TWIHS_IER_TOUT | TWIHS_IER_PECERR |\
+ TWIHS_IER_SMBDAM | TWIHS_IER_SMBHHM)
+
+
+/** variable for control thether or not to set both START and STOP
+ * In single data byte master read, the START and STOP must both be set */
+uint32_t twi_send_stop = 0;
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Configures a TWI peripheral to operate in master mode, at the given
+ * frequency (in Hz). The duty cycle of the TWI clock is set to 50%.
+ * \param pTwi Pointer to an Twihs instance.
+ * \param twck Desired TWI clock frequency.
+ * \param mck Master clock frequency.
+ */
+void TWI_ConfigureMaster(Twihs *pTwi, uint32_t dwTwCk, uint32_t dwMCk)
+{
+ uint32_t dwCkDiv = 0;
+ uint32_t dwClDiv;
+ uint32_t dwOk = 0;
+
+ TRACE_DEBUG("TWI_ConfigureMaster()\n\r");
+ assert(pTwi);
+
+ /* Reset the TWI */
+ pTwi->TWIHS_CR = TWIHS_CR_SWRST;
+
+ /* Configure clock */
+ while (!dwOk) {
+ dwClDiv = ((dwMCk / (2 * dwTwCk)) - 4) / (1 << dwCkDiv);
+
+ if (dwClDiv <= 255)
+ dwOk = 1;
+ else
+ dwCkDiv++;
+ }
+
+ assert(dwCkDiv < 8);
+ TRACE_DEBUG("Using CKDIV = %u and CLDIV/CHDIV = %u\n\r", dwCkDiv, dwClDiv);
+
+ pTwi->TWIHS_CWGR = (dwCkDiv << 16) | (dwClDiv << 8) | dwClDiv;
+
+ /* TWI Slave Mode Disabled. */
+ pTwi->TWIHS_CR = TWIHS_CR_SVDIS;
+
+ /* Set master mode */
+ pTwi->TWIHS_CR = TWIHS_CR_MSEN;
+}
+
+/**
+ * \brief Configures a TWI peripheral to operate in slave mode.
+ * \param pTwi Pointer to an Twihs instance.
+ * \param slaveAddress Slave address.
+ */
+void TWI_ConfigureSlave(Twihs *pTwi, uint8_t slaveAddress)
+{
+ /* TWI software reset */
+ pTwi->TWIHS_CR = TWIHS_CR_SWRST;
+
+ /* Configure slave address. */
+ pTwi->TWIHS_SMR = TWIHS_SMR_SADR(slaveAddress);
+
+ /* TWI Master Mode Disabled*/
+ pTwi->TWIHS_CR = TWIHS_CR_MSDIS;
+
+ /* SVEN: TWI Slave Mode Enabled */
+ pTwi->TWIHS_CR = TWIHS_CR_SVEN;
+
+ assert((pTwi->TWIHS_CR & TWIHS_CR_SVDIS) != TWIHS_CR_SVDIS);
+}
+
+/**
+ * \brief Sends a STOP condition on the TWI.
+ * \param pTwi Pointer to an Twihs instance.
+ */
+void TWI_Stop(Twihs *pTwi)
+{
+ assert(pTwi != NULL);
+
+ pTwi->TWIHS_CR = TWIHS_CR_STOP;
+}
+
+/**
+ * \brief Starts a read operation on the TWI bus with the specified slave, it
+ * returns immediately. Data must then be read using TWI_ReadByte() whenever a
+ * byte is available (poll using TWI_ByteReceived()).
+ * \param pTwi Pointer to an Twihs instance.
+ * \param address Slave address on the bus.
+ * \param iaddress Optional internal address bytes.
+ * \param isize Number of internal address bytes.
+ */
+void TWI_StartRead(
+ Twihs *pTwi,
+ uint8_t address,
+ uint32_t iaddress,
+ uint8_t isize)
+{
+ assert(pTwi != NULL);
+ assert((address & 0x80) == 0);
+ assert((iaddress & 0xFF000000) == 0);
+ assert(isize < 4);
+
+ /* Set slave address and number of internal address bytes. */
+ pTwi->TWIHS_MMR = 0;
+ pTwi->TWIHS_MMR = (isize << 8) | TWIHS_MMR_MREAD | (address << 16);
+
+ /* Set internal address bytes */
+ pTwi->TWIHS_IADR = 0;
+ pTwi->TWIHS_IADR = iaddress;
+
+ /* Send START condition */
+ if (0 == twi_send_stop)
+ pTwi->TWIHS_CR = TWIHS_CR_START;
+ else {
+ twi_send_stop = 0;
+ pTwi->TWIHS_CR = TWIHS_CR_START | TWIHS_CR_STOP;
+ }
+}
+
+/**
+ * \brief Reads a byte from the TWI bus. The read operation must have been started
+ * using TWI_StartRead() and a byte must be available (check with TWI_ByteReceived()).
+ * \param pTwi Pointer to an Twihs instance.
+ * \return byte read.
+ */
+uint8_t TWI_ReadByte(Twihs *pTwi)
+{
+ assert(pTwi != NULL);
+
+ return pTwi->TWIHS_RHR;
+}
+
+/**
+ * \brief Sends a byte of data to one of the TWI slaves on the bus.
+ * \note This function must be called once before TWI_StartWrite() with
+ * the first byte of data to send, then it shall be called repeatedly
+ * after that to send the remaining bytes.
+ * \param pTwi Pointer to an Twihs instance.
+ * \param byte Byte to send.
+ */
+void TWI_WriteByte(Twihs *pTwi, uint8_t byte)
+{
+ assert(pTwi != NULL);
+
+ pTwi->TWIHS_THR = byte;
+}
+
+/**
+ * \brief Starts a write operation on the TWI to access the selected slave, then
+ * returns immediately. A byte of data must be provided to start the write;
+ * other bytes are written next.
+ * after that to send the remaining bytes.
+ * \param pTwi Pointer to an Twihs instance.
+ * \param address Address of slave to acccess on the bus.
+ * \param iaddress Optional slave internal address.
+ * \param isize Number of internal address bytes.
+ * \param byte First byte to send.
+ */
+void TWI_StartWrite(
+ Twihs *pTwi,
+ uint8_t address,
+ uint32_t iaddress,
+ uint8_t isize,
+ uint8_t byte)
+{
+ assert(pTwi != NULL);
+ assert((address & 0x80) == 0);
+ assert((iaddress & 0xFF000000) == 0);
+ assert(isize < 4);
+
+ /* Set slave address and number of internal address bytes. */
+ pTwi->TWIHS_MMR = 0;
+ pTwi->TWIHS_MMR = (isize << 8) | (address << 16);
+
+ /* Set internal address bytes. */
+ pTwi->TWIHS_IADR = 0;
+ pTwi->TWIHS_IADR = iaddress;
+
+ /* Write first byte to send.*/
+ TWI_WriteByte(pTwi, byte);
+}
+
+/**
+ * \brief Check if a byte have been received from TWI.
+ * \param pTwi Pointer to an Twihs instance.
+ * \return 1 if a byte has been received and can be read on the given TWI
+ * peripheral; otherwise, returns 0. This function resets the status register.
+ */
+uint8_t TWI_ByteReceived(Twihs *pTwi)
+{
+ return ((pTwi->TWIHS_SR & TWIHS_SR_RXRDY) == TWIHS_SR_RXRDY);
+}
+
+/**
+ * \brief Check if a byte have been sent to TWI.
+ * \param pTwi Pointer to an Twihs instance.
+ * \return 1 if a byte has been sent so another one can be stored for
+ * transmission; otherwise returns 0. This function clears the status register.
+ */
+uint8_t TWI_ByteSent(Twihs *pTwi)
+{
+ return ((pTwi->TWIHS_SR & TWIHS_SR_TXRDY) == TWIHS_SR_TXRDY);
+}
+
+/**
+ * \brief Check if current transmission is completed.
+ * \param pTwi Pointer to an Twihs instance.
+ * \return 1 if the current transmission is complete (the STOP has been sent);
+ * otherwise returns 0.
+ */
+uint8_t TWI_TransferComplete(Twihs *pTwi)
+{
+ return ((pTwi->TWIHS_SR & TWIHS_SR_TXCOMP) == TWIHS_SR_TXCOMP);
+}
+
+/**
+ * \brief Enables the selected interrupts sources on a TWI peripheral.
+ * \param pTwi Pointer to an Twihs instance.
+ * \param sources Bitwise OR of selected interrupt sources.
+ */
+void TWI_EnableIt(Twihs *pTwi, uint32_t sources)
+{
+ assert(pTwi != NULL);
+ assert((sources & TWIHS_IT));
+
+ pTwi->TWIHS_IER = sources;
+}
+
+/**
+ * \brief Disables the selected interrupts sources on a TWI peripheral.
+ * \param pTwi Pointer to an Twihs instance.
+ * \param sources Bitwise OR of selected interrupt sources.
+ */
+void TWI_DisableIt(Twihs *pTwi, uint32_t sources)
+{
+ assert(pTwi != NULL);
+ assert(sources & TWIHS_IT);
+
+ pTwi->TWIHS_IDR = sources;
+}
+
+/**
+ * \brief Get the current status register of the given TWI peripheral.
+ * \note This resets the internal value of the status register, so further
+ * read may yield different values.
+ * \param pTwi Pointer to an Twihs instance.
+ * \return TWI status register.
+ */
+uint32_t TWI_GetStatus(Twihs *pTwi)
+{
+ assert(pTwi != NULL);
+
+ return pTwi->TWIHS_SR;
+}
+
+/**
+ * \brief Returns the current status register of the given TWI peripheral, but
+ * masking interrupt sources which are not currently enabled.
+ * \note This resets the internal value of the status register, so further
+ * read may yield different values.
+ * \param pTwi Pointer to an Twihs instance.
+ */
+uint32_t TWI_GetMaskedStatus(Twihs *pTwi)
+{
+ uint32_t status;
+
+ assert(pTwi != NULL);
+
+ status = pTwi->TWIHS_SR;
+ status &= pTwi->TWIHS_IMR;
+
+ return status;
+}
+
+/**
+ * \brief Sends a STOP condition. STOP Condition is sent just after completing
+ * the current byte transmission in master read mode.
+ * \param pTwi Pointer to an Twihs instance.
+ */
+void TWI_SendSTOPCondition(Twihs *pTwi)
+{
+ assert(pTwi != NULL);
+
+ pTwi->TWIHS_CR |= TWIHS_CR_STOP;
+}
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/twid.c b/bsps/arm/atsam/contrib/libraries/libchip/source/twid.c
new file mode 100644
index 0000000000..4f770691c5
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/twid.c
@@ -0,0 +1,752 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+#include "chip.h"
+
+#include <assert.h>
+
+/*----------------------------------------------------------------------------
+ * Definition
+ *----------------------------------------------------------------------------*/
+#define TWITIMEOUTMAX 400
+static uint32_t dmaWriteChannel, dmaReadChannel;
+
+extern uint32_t twi_send_stop;
+
+/*----------------------------------------------------------------------------
+ * Types
+ *----------------------------------------------------------------------------*/
+
+/** TWI driver callback function.*/
+typedef void (*TwiCallback)(Async *);
+
+/** \brief TWI asynchronous transfer descriptor.*/
+typedef struct _AsyncTwi {
+
+ /** Asynchronous transfer status. */
+ volatile uint8_t status;
+ /** Callback function to invoke when transfer completes or fails.*/
+ TwiCallback callback;
+ /** Pointer to the data buffer.*/
+ uint8_t *pData;
+ /** Total number of bytes to transfer.*/
+ uint32_t num;
+ /** Number of already transferred bytes.*/
+ uint32_t transferred;
+
+} AsyncTwi;
+
+/**
+ * \brief Initializes a TWI DMA Read channel.
+ */
+static void TWID_DmaInitializeRead(TwihsDma *pTwiXdma)
+{
+ /* Allocate a XDMA channel, Read accesses into TWI_THR */
+ dmaReadChannel = XDMAD_AllocateChannel(pTwiXdma->pTwiDma, pTwiXdma->Twi_id,
+ XDMAD_TRANSFER_MEMORY);
+
+ if (dmaReadChannel == XDMAD_ALLOC_FAILED)
+ printf("-E- Can't allocate XDMA channel\n\r");
+
+ XDMAD_PrepareChannel(pTwiXdma->pTwiDma, dmaReadChannel);
+}
+
+/**
+ * \brief Initializes a TWI DMA write channel.
+ */
+static void TWID_DmaInitializeWrite(TwihsDma *pTwiXdma)
+{
+ /* Allocate a XDMA channel, Write accesses into TWI_THR */
+ dmaWriteChannel = XDMAD_AllocateChannel(pTwiXdma->pTwiDma,
+ XDMAD_TRANSFER_MEMORY,
+ pTwiXdma->Twi_id);
+
+ if (dmaWriteChannel == XDMAD_ALLOC_FAILED)
+ printf("-E- Can't allocate XDMA channel\n\r");
+
+ XDMAD_PrepareChannel(pTwiXdma->pTwiDma, dmaWriteChannel);
+}
+
+/**
+ * \brief Configure xDMA write linker list for TWI transfer.
+ */
+static uint8_t TWID_XdmaConfigureWrite(TwihsDma *pTwiXdma, uint8_t *buf,
+ uint32_t len)
+{
+ uint32_t xdmaCndc, Thr, xdmaInt;
+ sXdmadCfg xdmadTxCfg;
+
+ Thr = (uint32_t) & (TWIHS0->TWIHS_THR);
+
+ if (pTwiXdma->Twi_id == ID_TWIHS1)
+ Thr = (uint32_t) & (TWIHS1->TWIHS_THR);
+
+ if (pTwiXdma->Twi_id == ID_TWIHS2)
+ Thr = (uint32_t) & (TWIHS2->TWIHS_THR);
+
+ xdmadTxCfg.mbr_ubc = XDMA_UBC_NVIEW_NDV0 |
+ XDMA_UBC_NDE_FETCH_DIS |
+ XDMA_UBC_NSEN_UPDATED | len;
+
+ xdmadTxCfg.mbr_sa = (uint32_t)buf;
+ xdmadTxCfg.mbr_da = Thr;
+ xdmadTxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_MEM2PER |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_INCREMENTED_AM |
+ XDMAC_CC_DAM_FIXED_AM |
+ XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(
+ pTwiXdma->Twi_id, XDMAD_TRANSFER_TX));
+
+ xdmadTxCfg.mbr_bc = 0;
+ xdmadTxCfg.mbr_sus = 0;
+ xdmadTxCfg.mbr_dus = 0;
+ xdmaCndc = 0;
+
+ xdmaInt = (XDMAC_CIE_BIE |
+ XDMAC_CIE_RBIE |
+ XDMAC_CIE_WBIE);
+
+ if (XDMAD_ConfigureTransfer(pTwiXdma->pTwiDma, dmaWriteChannel,
+ &xdmadTxCfg, xdmaCndc, 0, xdmaInt))
+ return USARTD_ERROR;
+
+ return 0;
+}
+
+
+/**
+ * \brief Configure xDMA read linker list for TWI transfer.
+ */
+static uint8_t TWID_XdmaConfigureRead(TwihsDma *pTwiXdma, uint8_t *buf,
+ uint32_t len)
+{
+ uint32_t xdmaCndc, Rhr, xdmaInt;
+ sXdmadCfg xdmadRxCfg;
+
+ Rhr = (uint32_t) & (TWIHS0->TWIHS_RHR);
+
+ if (pTwiXdma->Twi_id == ID_TWIHS1)
+ Rhr = (uint32_t) & (TWIHS1->TWIHS_RHR);
+
+ if (pTwiXdma->Twi_id == ID_TWIHS2)
+ Rhr = (uint32_t) & (TWIHS2->TWIHS_RHR);
+
+ xdmadRxCfg.mbr_ubc = XDMA_UBC_NVIEW_NDV0 |
+ XDMA_UBC_NDE_FETCH_DIS |
+ XDMA_UBC_NDEN_UPDATED |
+ len;
+
+ xdmadRxCfg.mbr_da = (uint32_t)buf;
+ xdmadRxCfg.mbr_sa = Rhr;
+
+ xdmadRxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_DSYNC_PER2MEM |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_FIXED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(
+ pTwiXdma->Twi_id , XDMAD_TRANSFER_RX));
+
+ xdmadRxCfg.mbr_bc = 0;
+ xdmadRxCfg.mbr_sus = 0;
+ xdmadRxCfg.mbr_dus = 0;
+ xdmaCndc = 0;
+ xdmaInt = (XDMAC_CIE_BIE |
+ XDMAC_CIE_RBIE |
+ XDMAC_CIE_WBIE);
+
+ if (XDMAD_ConfigureTransfer(pTwiXdma->pTwiDma, dmaReadChannel,
+ &xdmadRxCfg, xdmaCndc, 0, xdmaInt))
+ return 1;
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------
+ * Global functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Returns 1 if the given transfer has ended; otherwise returns 0.
+ * \param pAsync Pointer to an Async instance.
+ */
+uint32_t ASYNC_IsFinished(Async *pAsync)
+{
+ return (pAsync->status != ASYNC_STATUS_PENDING);
+}
+
+/**
+ * \brief Initializes a TWI driver instance, using the given TWI peripheral.
+ * \note The peripheral must have been initialized properly before calling this
+ * function.
+ * \param pTwid Pointer to the Twid instance to initialize.
+ * \param pTwi Pointer to the TWI peripheral to use.
+ */
+void TWID_Initialize(Twid *pTwid, Twihs *pTwi)
+{
+ TRACE_DEBUG("TWID_Initialize()\n\r");
+ assert(pTwid != NULL);
+ assert(pTwi != NULL);
+
+ /* Initialize driver. */
+ pTwid->pTwi = pTwi;
+ pTwid->pTransfer = 0;
+}
+
+/**
+ * \brief Interrupt handler for a TWI peripheral. Manages asynchronous transfer
+ * occurring on the bus. This function MUST be called by the interrupt service
+ * routine of the TWI peripheral if asynchronous read/write are needed.
+ * \param pTwid Pointer to a Twid instance.
+ */
+void TWID_Handler(Twid *pTwid)
+{
+ uint8_t status;
+ AsyncTwi *pTransfer;
+ Twihs *pTwi;
+
+ assert(pTwid != NULL);
+
+ pTransfer = (AsyncTwi *)pTwid->pTransfer;
+ assert(pTransfer != NULL);
+ pTwi = pTwid->pTwi;
+ assert(pTwi != NULL);
+
+ /* Retrieve interrupt status */
+ status = TWI_GetMaskedStatus(pTwi);
+
+ /* Byte received */
+ if (TWI_STATUS_RXRDY(status)) {
+
+ pTransfer->pData[pTransfer->transferred] = TWI_ReadByte(pTwi);
+ pTransfer->transferred++;
+
+ /* check for transfer finish */
+ if (pTransfer->transferred == pTransfer->num) {
+
+ TWI_DisableIt(pTwi, TWIHS_IDR_RXRDY);
+ TWI_EnableIt(pTwi, TWIHS_IER_TXCOMP);
+ }
+ /* Last byte? */
+ else if (pTransfer->transferred == (pTransfer->num - 1))
+
+ TWI_Stop(pTwi);
+ }
+ /* Byte sent*/
+ else if (TWI_STATUS_TXRDY(status)) {
+
+ /* Transfer finished ? */
+ if (pTransfer->transferred == pTransfer->num) {
+
+ TWI_DisableIt(pTwi, TWIHS_IDR_TXRDY);
+ TWI_EnableIt(pTwi, TWIHS_IER_TXCOMP);
+ TWI_SendSTOPCondition(pTwi);
+ }
+ /* Bytes remaining */
+ else {
+
+ TWI_WriteByte(pTwi, pTransfer->pData[pTransfer->transferred]);
+ pTransfer->transferred++;
+ }
+ }
+ /* Transfer complete*/
+ else if (TWI_STATUS_TXCOMP(status)) {
+
+ TWI_DisableIt(pTwi, TWIHS_IDR_TXCOMP);
+ pTransfer->status = 0;
+
+ if (pTransfer->callback)
+ pTransfer->callback((Async *) pTransfer);
+
+ pTwid->pTransfer = 0;
+ }
+}
+
+/**
+ * \brief Asynchronously reads data from a slave on the TWI bus. An optional
+ * callback function is triggered when the transfer is complete.
+ * \param pTwid Pointer to a Twid instance.
+ * \param address TWI slave address.
+ * \param iaddress Optional slave internal address.
+ * \param isize Internal address size in bytes.
+ * \param pData Data buffer for storing received bytes.
+ * \param num Number of bytes to read.
+ * \param pAsync Asynchronous transfer descriptor.
+ * \return 0 if the transfer has been started; otherwise returns a TWI error code.
+ */
+uint8_t TWID_Read(
+ Twid *pTwid,
+ uint8_t address,
+ uint32_t iaddress,
+ uint8_t isize,
+ uint8_t *pData,
+ uint32_t num,
+ Async *pAsync)
+{
+ Twihs *pTwi;
+ AsyncTwi *pTransfer;
+ uint32_t startTime;
+ assert(pTwid != NULL);
+ pTwi = pTwid->pTwi;
+ pTransfer = (AsyncTwi *) pTwid->pTransfer;
+
+ assert((address & 0x80) == 0);
+ assert((iaddress & 0xFF000000) == 0);
+ assert(isize < 4);
+
+ /* Check that no transfer is already pending*/
+ if (pTransfer) {
+
+ TRACE_ERROR("TWID_Read: A transfer is already pending\n\r");
+ return TWID_ERROR_BUSY;
+ }
+
+ /* In single data byte master read, the START and STOP must both be set */
+ twi_send_stop = (num == 1) ? 1 : 0;
+
+ /* Asynchronous transfer*/
+ if (pAsync) {
+
+ /* Update the transfer descriptor */
+ pTwid->pTransfer = pAsync;
+ pTransfer = (AsyncTwi *) pAsync;
+ pTransfer->status = ASYNC_STATUS_PENDING;
+ pTransfer->pData = pData;
+ pTransfer->num = num;
+ pTransfer->transferred = 0;
+
+ /* Enable read interrupt and start the transfer */
+ TWI_EnableIt(pTwi, TWIHS_IER_RXRDY);
+ TWI_StartRead(pTwi, address, iaddress, isize);
+ }
+ /* Synchronous transfer*/
+ else {
+
+ /* Start read*/
+ TWI_StartRead(pTwi, address, iaddress, isize);
+
+ /* Read all bytes, setting STOP before the last byte*/
+ while (num > 0) {
+
+ /* Last byte ?*/
+ if (num == 1)
+ TWI_Stop(pTwi);
+
+ /* Wait for byte then read and store it*/
+ startTime = GetTicks();
+
+ while (!TWI_ByteReceived(pTwi)) {
+ if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
+ TRACE_ERROR("TWID Timeout BR\n\r");
+ break;
+ }
+ }
+
+ *pData++ = TWI_ReadByte(pTwi);
+ num--;
+ }
+
+ /* Wait for transfer to be complete */
+ startTime = GetTicks();
+
+ while (!TWI_TransferComplete(pTwi)) {
+ if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
+ TRACE_ERROR("TWID Timeout TC\n\r");
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * \brief Asynchronously sends data to a slave on the TWI bus. An optional
+ * callback function is invoked whenever the transfer is complete.
+ * \param pTwid Pointer to a Twid instance.
+ * \param address TWI slave address.
+ * \param iaddress Optional slave internal address.
+ * \param isize Number of internal address bytes.
+ * \param pData Data buffer for storing received bytes.
+ * \param num Data buffer to send.
+ * \param pAsync Asynchronous transfer descriptor.
+ * \return 0 if the transfer has been started; otherwise returns a TWI error code.
+ */
+uint8_t TWID_Write(
+ Twid *pTwid,
+ uint8_t address,
+ uint32_t iaddress,
+ uint8_t isize,
+ uint8_t *pData,
+ uint32_t num,
+ Async *pAsync)
+{
+ Twihs *pTwi = pTwid->pTwi;
+ uint32_t startTime;
+ AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer;
+
+ assert(pTwi != NULL);
+ assert((address & 0x80) == 0);
+ assert((iaddress & 0xFF000000) == 0);
+ assert(isize < 4);
+
+ /* Check that no transfer is already pending */
+ if (pTransfer) {
+ TRACE_ERROR("TWI_Write: A transfer is already pending\n\r");
+ return TWID_ERROR_BUSY;
+ }
+
+ /* Asynchronous transfer */
+ if (pAsync) {
+ /* Update the transfer descriptor */
+ pTwid->pTransfer = pAsync;
+ pTransfer = (AsyncTwi *) pAsync;
+ pTransfer->status = ASYNC_STATUS_PENDING;
+ pTransfer->pData = pData;
+ pTransfer->num = num;
+ pTransfer->transferred = 1;
+
+ /* Enable write interrupt and start the transfer */
+ TWI_StartWrite(pTwi, address, iaddress, isize, *pData);
+ TWI_EnableIt(pTwi, TWIHS_IER_TXRDY);
+
+ } else {
+ /* Synchronous transfer*/
+ // Start write
+ TWI_StartWrite(pTwi, address, iaddress, isize, *pData++);
+ num--;
+
+ /* Send all bytes */
+ while (num > 0) {
+ /* Wait before sending the next byte */
+ startTime = GetTicks();
+
+ while (!TWI_ByteSent(pTwi)) {
+ if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
+ TRACE_ERROR("TWID Timeout BS\n\r");
+ break;
+ }
+ }
+
+ TWI_WriteByte(pTwi, *pData++);
+ num--;
+ }
+
+ /* Wait for actual end of transfer */
+ startTime = GetTicks();
+ /* Send a STOP condition */
+ TWI_SendSTOPCondition(pTwi);
+
+ while (!TWI_TransferComplete(pTwi)) {
+ if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
+ TRACE_ERROR("TWID Timeout TC2\n\r");
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * \brief Initializes a TWI driver instance, using the given TWI peripheral.
+ * \note The peripheral must have been initialized properly before calling this
+ * function.
+ * \param pTwid Pointer to the Twid instance to initialize.
+ * \param pTwi Pointer to the TWI peripheral to use.
+ */
+void TWID_DmaInitialize(TwihsDma *pTwidma, Twihs *pTwi, uint8_t bPolling)
+{
+ TRACE_DEBUG("TWID_Initialize()\n\r");
+ assert(pTwidma != NULL);
+
+ if ((unsigned int)pTwi == (unsigned int)TWIHS0) pTwidma->Twi_id = ID_TWIHS0;
+
+ if ((unsigned int)pTwi == (unsigned int)TWIHS1) pTwidma->Twi_id = ID_TWIHS1;
+
+ if ((unsigned int)pTwi == (unsigned int)TWIHS2) pTwidma->Twi_id = ID_TWIHS2;
+
+ /* Initialize driver. */
+ pTwidma->pTwid->pTwi = pTwi;
+ pTwidma->pTwid->pTransfer = 0;
+
+ assert(!bPolling);
+}
+
+/**
+ * \brief Asynchronously reads data from a slave on the TWI bus. An optional
+ * callback function is triggered when the transfer is complete.
+ * \param pTwid Pointer to a Twid instance.
+ * \param address TWI slave address.
+ * \param iaddress Optional slave internal address.
+ * \param isize Internal address size in bytes.
+ * \param pData Data buffer for storing received bytes.
+ * \param num Number of bytes to read.
+ * \param pAsync Asynchronous transfer descriptor.
+ * \param TWI_ID TWI ID for TWI0, TWIHS1, TWIHS2.
+ * \return 0 if the transfer has been started; otherwise returns a TWI error code.
+ */
+uint8_t TWID_DmaRead(
+ TwihsDma *pTwiXdma,
+ uint8_t address,
+ uint32_t iaddress,
+ uint8_t isize,
+ uint8_t *pData,
+ uint32_t num,
+ Async *pAsync)
+{
+ Twihs *pTwi;
+ AsyncTwi *pTransfer;
+ uint32_t status, startTime;
+
+ assert(pTwiXdma->pTwid != NULL);
+ pTwi = pTwiXdma->pTwid->pTwi;
+ pTransfer = (AsyncTwi *) pTwiXdma->pTwid->pTransfer;
+
+ assert((address & 0x80) == 0);
+ assert((iaddress & 0xFF000000) == 0);
+ assert(isize < 4);
+
+ /* Check that no transfer is already pending*/
+ if (pTransfer) {
+
+ TRACE_ERROR("TWID_Read: A transfer is already pending\n\r");
+ return TWID_ERROR_BUSY;
+ }
+
+ /* Asynchronous transfer*/
+ if (pAsync) {
+ /* Update the transfer descriptor */
+ pTwiXdma->pTwid->pTransfer = pAsync;
+ pTransfer = (AsyncTwi *) pAsync;
+ pTransfer->status = ASYNC_STATUS_PENDING;
+ pTransfer->pData = pData;
+ pTransfer->num = num;
+ pTransfer->transferred = 0;
+
+ /* Enable read interrupt and start the transfer */
+ TWI_EnableIt(pTwi, TWIHS_IER_RXRDY);
+ TWI_StartRead(pTwi, address, iaddress, isize);
+ } else {
+ /* Synchronous transfer*/
+ TWID_DmaInitializeRead(pTwiXdma);
+ TWID_XdmaConfigureRead(pTwiXdma, pData, (num - 2));
+
+ /* Start read*/
+ XDMAD_StartTransfer(pTwiXdma->pTwiDma, dmaReadChannel);
+ TWI_StartRead(pTwi, address, iaddress, isize);
+
+ startTime = GetTicks();
+ status = XDMAD_IsTransferDone(pTwiXdma->pTwiDma, dmaReadChannel);
+
+ while (status != XDMAD_OK) {
+ status = XDMAD_IsTransferDone(pTwiXdma->pTwiDma, dmaReadChannel);
+
+ if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
+ TRACE_ERROR("TWID DMA not done\n\r");
+ break;
+ }
+ }
+
+ if (XDMAD_OK == status)
+ SCB_InvalidateDCache_by_Addr((uint32_t *)pData, (num - 2));
+
+ status = TWI_GetStatus(pTwi);
+ startTime = GetTicks();
+
+ while (!(status & TWIHS_SR_RXRDY)) {
+ status = TWI_GetStatus(pTwi);
+
+ if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
+ TRACE_ERROR("TWID DMA not done\n\r");
+ break;
+ }
+ }
+
+ TWI_Stop(pTwi);
+
+ pData[num - 2] = TWI_ReadByte(pTwi);
+ status = TWI_GetStatus(pTwi);
+ startTime = GetTicks();
+
+ while (!(status & TWIHS_SR_RXRDY)) {
+ status = TWI_GetStatus(pTwi);
+
+ if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
+ TRACE_ERROR("TWID Timeout Read\n\r");
+ break;
+ }
+ }
+
+ pData[num - 1] = TWI_ReadByte(pTwi);
+ status = TWI_GetStatus(pTwi);
+ startTime = GetTicks();
+
+ while (!(status & TWIHS_SR_TXCOMP)) {
+ status = TWI_GetStatus(pTwi);
+
+ if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
+ TRACE_ERROR("TWID Timeout Read\n\r");
+ break;
+ }
+ }
+
+ XDMAD_StopTransfer(pTwiXdma->pTwiDma, dmaReadChannel);
+ XDMAD_FreeChannel(pTwiXdma->pTwiDma, dmaWriteChannel);
+ }
+
+ return 0;
+}
+
+/**
+ * \brief Asynchronously sends data to a slave on the TWI bus. An optional
+ * callback function is invoked whenever the transfer is complete.
+ * \param pTwid Pointer to a Twid instance.
+ * \param address TWI slave address.
+ * \param iaddress Optional slave internal address.
+ * \param isize Number of internal address bytes.
+ * \param pData Data buffer for storing received bytes.
+ * \param num Data buffer to send.
+ * \param pAsync Asynchronous transfer descriptor.
+ * \param TWI_ID TWIHS ID for TWIHS0, TWIHS1, TWIHS2.
+ * \return 0 if the transfer has been started; otherwise returns a TWI error code.
+ */
+uint8_t TWID_DmaWrite(
+ TwihsDma *pTwiXdma,
+ uint8_t address,
+ uint32_t iaddress,
+ uint8_t isize,
+ uint8_t *pData,
+ uint32_t num,
+ Async *pAsync)
+{
+ Twihs *pTwi = pTwiXdma->pTwid->pTwi;
+ AsyncTwi *pTransfer = (AsyncTwi *) pTwiXdma->pTwid->pTransfer;
+ uint32_t status, startTime;
+ //uint8_t singleTransfer = 0;
+ assert(pTwi != NULL);
+ assert((address & 0x80) == 0);
+ assert((iaddress & 0xFF000000) == 0);
+ assert(isize < 4);
+
+ // if (num == 1) singleTransfer = 1;
+ /* Check that no transfer is already pending */
+ if (pTransfer) {
+
+ TRACE_ERROR("TWI_Write: A transfer is already pending\n\r");
+ return TWID_ERROR_BUSY;
+ }
+
+ /* Asynchronous transfer */
+ if (pAsync) {
+
+ /* Update the transfer descriptor */
+ pTwiXdma->pTwid->pTransfer = pAsync;
+ pTransfer = (AsyncTwi *) pAsync;
+ pTransfer->status = ASYNC_STATUS_PENDING;
+ pTransfer->pData = pData;
+ pTransfer->num = num;
+ pTransfer->transferred = 1;
+
+ /* Enable write interrupt and start the transfer */
+ TWI_StartWrite(pTwi, address, iaddress, isize, *pData);
+ TWI_EnableIt(pTwi, TWIHS_IER_TXRDY);
+ } else {
+ /* Synchronous transfer*/
+ TWID_DmaInitializeWrite(pTwiXdma);
+ TWID_XdmaConfigureWrite(pTwiXdma, pData, (num - 1));
+ /* Set slave address and number of internal address bytes. */
+ pTwi->TWIHS_MMR = 0;
+ pTwi->TWIHS_MMR = (isize << 8) | (address << 16);
+
+ /* Set internal address bytes. */
+ pTwi->TWIHS_IADR = 0;
+ pTwi->TWIHS_IADR = iaddress;
+
+ // cache maintenance before starting DMA Xfr
+ SCB_CleanDCache_by_Addr((uint32_t *)pData, (num - 1));
+ startTime = GetTicks();
+
+ XDMAD_StartTransfer(pTwiXdma->pTwiDma, dmaWriteChannel);
+
+ while ((XDMAD_IsTransferDone(pTwiXdma->pTwiDma, dmaWriteChannel))) {
+ if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
+ TRACE_ERROR("TWID DMA not done, Channel State is %d\n\r",
+ pTwiXdma->pTwiDma->XdmaChannels[dmaWriteChannel].state);
+ break;
+ }
+ }
+
+ status = TWI_GetStatus(pTwi);
+ startTime = GetTicks();
+
+ while (!(status & TWIHS_SR_TXRDY)) {
+ status = TWI_GetStatus(pTwi);
+
+ if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
+ TRACE_ERROR("TWID Timeout TXRDY\n\r");
+ break;
+ }
+ }
+
+ /* Send a STOP condition */
+ TWI_Stop(pTwi);
+
+ TWI_WriteByte(pTwi, pData[num - 1]);
+ status = TWI_GetStatus(pTwi);
+ startTime = GetTicks();
+
+ while (!(status & TWIHS_SR_TXCOMP)) {
+ status = TWI_GetStatus(pTwi);
+
+ if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) {
+ TRACE_ERROR("TWID Timeout Write\n\r");
+ break;
+ }
+ }
+
+ XDMAD_StopTransfer(pTwiXdma->pTwiDma, dmaWriteChannel);
+ XDMAD_FreeChannel(pTwiXdma->pTwiDma, dmaWriteChannel);
+
+ }
+
+ return 0;
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/uart.c b/bsps/arm/atsam/contrib/libraries/libchip/source/uart.c
new file mode 100644
index 0000000000..43f6522977
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/uart.c
@@ -0,0 +1,232 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Implementation of UART (Universal Asynchronous Receiver Transmitter)
+ * controller.
+ *
+ */
+/*------------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+#include "chip.h"
+
+#include <assert.h>
+#include <string.h>
+
+/*------------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Configures an UART peripheral with the specified parameters.
+ *
+ *
+ * \param uart Pointer to the UART peripheral to configure.
+ * \param mode Desired value for the UART mode register (see the datasheet).
+ * \param baudrate Baudrate at which the UART should operate (in Hz).
+ * \param masterClock Frequency of the system master clock (in Hz).
+ */
+void UART_Configure(Uart *uart,
+ uint32_t mode,
+ uint32_t baudrate,
+ uint32_t masterClock)
+{
+ /* Reset and disable receiver & transmitter*/
+ uart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX
+ | UART_CR_RXDIS | UART_CR_TXDIS | UART_CR_RSTSTA;
+
+ uart->UART_IDR = 0xFFFFFFFF;
+
+ /* Configure mode*/
+ uart->UART_MR = mode;
+
+ /* Configure baudrate*/
+ uart->UART_BRGR = (masterClock / baudrate) / 16;
+
+ uart->UART_CR = UART_CR_TXEN | UART_CR_RXEN;
+
+}
+/**
+ * \brief Enables or disables the transmitter of an UART peripheral.
+ *
+ *
+ * \param uart Pointer to an UART peripheral
+ * \param enabled If true, the transmitter is enabled; otherwise it is
+ * disabled.
+ */
+void UART_SetTransmitterEnabled(Uart *uart, uint8_t enabled)
+{
+ if (enabled)
+ uart->UART_CR = UART_CR_TXEN;
+ else
+ uart->UART_CR = UART_CR_TXDIS;
+}
+
+/**
+ * \brief Enables or disables the receiver of an UART peripheral
+ *
+ *
+ * \param uart Pointer to an UART peripheral
+ * \param enabled If true, the receiver is enabled; otherwise it is disabled.
+ */
+void UART_SetReceiverEnabled(Uart *uart, uint8_t enabled)
+{
+ if (enabled)
+ uart->UART_CR = UART_CR_RXEN;
+ else
+ uart->UART_CR = UART_CR_RXDIS;
+}
+
+/**
+ * \brief Return 1 if a character can be read in UART
+ * \param uart Pointer to an UART peripheral.
+ */
+uint32_t UART_IsRxReady(Uart *uart)
+{
+ return (uart->UART_SR & UART_SR_RXRDY);
+}
+
+/**
+ * \brief Reads and returns a character from the UART.
+ *
+ * \note This function is synchronous (i.e. uses polling).
+ * \param uart Pointer to an UART peripheral.
+ * \return Character received.
+ */
+uint8_t UART_GetChar(Uart *uart)
+{
+ while (!UART_IsRxReady(uart));
+
+ return uart->UART_RHR;
+}
+
+/**
+ * \brief Return 1 if a character can be send to UART
+ * \param uart Pointer to an UART peripheral.
+ */
+uint32_t UART_IsTxReady(Uart *uart)
+{
+ return (uart->UART_SR & UART_SR_TXRDY);
+}
+
+/**
+ * \brief Return 1 if a character can be send to UART
+ * \param uart Pointer to an UART peripheral.
+ */
+static uint32_t UART_IsTxSent(Uart *uart)
+{
+ return (uart->UART_SR & UART_SR_TXEMPTY);
+}
+
+/**
+ * \brief Sends one packet of data through the specified UART peripheral. This
+ * function operates synchronously, so it only returns when the data has been
+ * actually sent.
+ *
+ * \param uart Pointer to an UART peripheral.
+ * \param c Character to send
+ */
+void UART_PutChar(Uart *uart, uint8_t c)
+{
+ /* Wait for the transmitter to be ready*/
+ while (!UART_IsRxReady(uart) && !UART_IsTxSent(uart));
+
+ /* Send character*/
+ uart->UART_THR = c;
+
+ /* Wait for the transfer to complete*/
+ while (!UART_IsTxSent(uart));
+}
+
+/**
+ * \brief Get present status
+ * \param uart Pointer to an UART peripheral.
+ */
+uint32_t UART_GetStatus(Uart *uart)
+{
+ return uart->UART_SR;
+}
+
+/**
+ * \brief Enable interrupt
+ * \param uart Pointer to an UART peripheral.
+ * \param mode Interrupt mode.
+ */
+void UART_EnableIt(Uart *uart, uint32_t mode)
+{
+ uart->UART_IER = mode;
+}
+
+/**
+ * \brief Disable interrupt
+ * \param uart Pointer to an UART peripheral.
+ * \param mode Interrupt mode.
+ */
+void UART_DisableIt(Uart *uart, uint32_t mode)
+{
+ uart->UART_IDR = mode;
+}
+
+/**
+ * \brief Return interrupt mask
+ * \param uart Pointer to an UART peripheral.
+ */
+uint32_t UART_GetItMask(Uart *uart)
+{
+ return uart->UART_IMR;
+}
+
+void UART_SendBuffer(Uart *uart, uint8_t *pBuffer, uint32_t BuffLen)
+{
+ uint8_t *pData = pBuffer;
+ uint32_t Len = 0;
+
+ for (Len = 0; Len < BuffLen; Len++) {
+ UART_PutChar(uart, *pData);
+ pData++;
+ }
+}
+
+void UART_ReceiveBuffer(Uart *uart, uint8_t *pBuffer, uint32_t BuffLen)
+{
+ uint32_t Len = 0;
+
+ for (Len = 0; Len < BuffLen; Len++) {
+ *pBuffer = UART_GetChar(uart);
+ pBuffer++;
+ }
+}
+
+void UART_CompareConfig(Uart *uart, uint8_t Val1, uint8_t Val2)
+{
+ uart->UART_CMPR = (UART_CMPR_VAL1(Val1) | UART_CMPR_VAL2(Val2));
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/uart_dma.c b/bsps/arm/atsam/contrib/libraries/libchip/source/uart_dma.c
new file mode 100644
index 0000000000..606dc83d79
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/uart_dma.c
@@ -0,0 +1,616 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \addtogroup uart_dma_module UART xDMA driver
+ * \ingroup lib_uart
+ * \section Usage
+ *
+ * <ul>
+ * <li> UARTD_Configure() initializes and configures the UART peripheral and
+ * xDMA for data transfer.</li>
+ * <li> Configures the parameters for the device corresponding to the cs value
+ * by UARTD_ConfigureCS(). </li>
+ * <li> Starts a UART master transfer. This is a non blocking function
+ * UARTD_SendData(). It will
+ * return as soon as the transfer is started..</li>
+ * </ul>
+ *
+ */
+
+/**
+ * \file
+ *
+ * Implementation for the UART with xDMA driver.
+ *
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+#include "string.h"
+#include "stdlib.h"
+
+
+/*----------------------------------------------------------------------------
+ * Local functions
+ *----------------------------------------------------------------------------*/
+
+/**
+* \brief UART xDMA Rx callback
+* Invoked on UART DMA reception done.
+* \param channel DMA channel.
+* \param pArg Pointer to callback argument - Pointer to UARTDma instance.
+*/
+static void UARTD_Rx_Cb(uint32_t channel, UartDma *pArg)
+{
+
+ UartChannel *pUartdCh = pArg->pRxChannel;
+
+ if (channel != pUartdCh->ChNum)
+ return;
+
+ /* Release the DMA channels */
+ XDMAD_FreeChannel(pArg->pXdmad, pUartdCh->ChNum);
+ pUartdCh->sempaphore = 1;
+ SCB_InvalidateDCache_by_Addr((uint32_t *)pUartdCh->pBuff, pUartdCh->BuffSize);
+}
+
+/**
+ * \brief USART xDMA Rx callback
+ * Invoked on USART DMA reception done.
+ * \param channel DMA channel.
+ * \param pArg Pointer to callback argument - Pointer to USARTDma instance.
+ */
+static void UARTD_Tx_Cb(uint32_t channel, UartDma *pArg)
+{
+ UartChannel *pUartdCh = pArg->pTxChannel;
+
+ if (channel != pUartdCh->ChNum)
+ return;
+
+ /* Release the DMA channels */
+ XDMAD_FreeChannel(pArg->pXdmad, pUartdCh->ChNum);
+ pUartdCh->sempaphore = 1;
+}
+
+/**
+ * \brief Configure the UART Rx DMA mode.
+ *
+ * \param pUartHw Pointer to UART instance
+ * \param pXdmad Pointer to XDMA instance
+ * \param pUsartRx Pointer to Usart Rx channel
+ * \returns 0 if the dma multibuffer configuration successfully; otherwise
+ * returns USARTD_ERROR_XXX.
+ */
+static uint8_t _configureUartRxDma(UartDma *pUartd , UartChannel *pUartRx)
+{
+ sXdmadCfg xdmadRxCfg;
+ uint32_t xdmaCndc, xdmaInt;
+ uint32_t i, LLI_Size;
+ Uart *pUartHwRx = pUartd->pUartHw;
+ sXdmad *pXdmadRx = pUartd->pXdmad;
+ uint8_t *pBuff = 0;
+
+ /* Setup RX Single block */
+ if (pUartRx->dmaProgrammingMode < XDMAD_LLI) {
+ xdmadRxCfg.mbr_ubc = pUartRx->BuffSize;
+ xdmadRxCfg.mbr_da = (uint32_t)pUartRx->pBuff;
+
+ xdmadRxCfg.mbr_sa = (uint32_t)&pUartHwRx->UART_RHR;
+ xdmadRxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SIXTEEN |
+ XDMAC_CC_DSYNC_PER2MEM |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_FIXED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber
+ (pUartd->uartId, XDMAD_TRANSFER_RX));
+
+ xdmadRxCfg.mbr_bc = 0;
+
+ if (pUartRx->dmaProgrammingMode == XDMAD_MULTI)
+ xdmadRxCfg.mbr_bc = pUartRx->dmaBlockSize;
+
+ xdmadRxCfg.mbr_sus = 0;
+ xdmadRxCfg.mbr_dus = 0;
+ xdmaCndc = 0;
+
+ /* Put all interrupts on for non LLI list setup of DMA */
+ xdmaInt = (XDMAC_CIE_BIE |
+ XDMAC_CIE_DIE |
+ XDMAC_CIE_FIE |
+ XDMAC_CIE_RBIE |
+ XDMAC_CIE_WBIE |
+ XDMAC_CIE_ROIE);
+
+ } else if (pUartRx->dmaProgrammingMode == XDMAD_LLI) {
+ /* Setup RX Link List */
+ LLI_Size = pUartRx->dmaBlockSize;
+ pBuff = pUartRx->pBuff;
+
+ if (pUartRx->pLLIview != NULL) {
+ free(pUartRx->pLLIview);
+ pUartRx->pLLIview = NULL;
+ }
+
+ pUartRx->pLLIview = malloc(sizeof(LinkedListDescriporView1) * LLI_Size);
+
+ if (pUartRx->pLLIview == NULL) {
+ TRACE_ERROR(" Can not allocate memory to Rx LLI");
+ return USARTD_ERROR;
+ }
+
+ xdmadRxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SIXTEEN |
+ XDMAC_CC_DSYNC_PER2MEM |
+ XDMAC_CC_MEMSET_NORMAL_MODE |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_FIXED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(
+ pUartd->uartId, XDMAD_TRANSFER_RX));
+ xdmadRxCfg.mbr_bc = 0;
+
+ for (i = 0; i < LLI_Size; i++) {
+ pUartRx->pLLIview[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1 |
+ XDMA_UBC_NSEN_UNCHANGED |
+ XDMA_UBC_NDEN_UPDATED |
+ ((i == LLI_Size - 1) ? ((pUartRx->dmaRingBuffer) ?
+ XDMA_UBC_NDE_FETCH_EN : 0) :
+ XDMA_UBC_NDE_FETCH_EN) | pUartRx->BuffSize;
+ pUartRx->pLLIview[i].mbr_sa = (uint32_t)&pUartHwRx->UART_RHR;
+ pUartRx->pLLIview[i].mbr_da = (uint32_t)pBuff;
+ pUartRx->pLLIview[i].mbr_nda = (i == (LLI_Size - 1)) ?
+ ((pUartRx->dmaRingBuffer) ? (uint32_t)pUartRx->pLLIview : 0) :
+ (uint32_t)&pUartRx->pLLIview[ i + 1 ];
+ pBuff += pUartRx->BuffSize;
+ }
+
+ SCB_CleanDCache_by_Addr((uint32_t *)(pUartRx->pLLIview),
+ sizeof(LinkedListDescriporView1)*LLI_Size);
+
+ xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1 |
+ XDMAC_CNDC_NDE_DSCR_FETCH_EN |
+ XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED |
+ XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED;
+
+ xdmaInt = ((pUartRx->dmaRingBuffer) ? XDMAC_CIE_BIE : XDMAC_CIE_LIE);
+
+ } else
+ return 1;
+
+ if (XDMAD_ConfigureTransfer(pXdmadRx, pUartRx->ChNum, &xdmadRxCfg,
+ xdmaCndc, (uint32_t)pUartRx->pLLIview, xdmaInt))
+ return USARTD_ERROR;
+
+ return 0;
+}
+
+/**
+ * \brief Configure the UART Tx DMA mode.
+ *
+ * \param pUartHw Pointer to UART instance
+ * \param pXdmad Pointer to XDMA instance
+ * \param pUsartTx Pointer to Usart Tx channel
+ * \returns 0 if the dma multibuffer configuration successfully; otherwise
+ * returns USARTD_ERROR_XXX.
+ */
+static uint8_t _configureUartTxDma(UartDma *pUartd, UartChannel *pUartTx)
+{
+ sXdmadCfg xdmadTxCfg;
+ uint32_t xdmaCndc, xdmaInt, LLI_Size, i;
+ uint8_t *pBuff = 0;
+ Uart *pUartHwTx = pUartd->pUartHw;
+ sXdmad *pXdmadTx = pUartd->pXdmad;
+
+
+ /* Setup TX */
+ if (pUartTx->dmaProgrammingMode < XDMAD_LLI) {
+ xdmadTxCfg.mbr_ubc = pUartTx->BuffSize;
+
+ xdmadTxCfg.mbr_sa = (uint32_t)pUartTx->pBuff;
+ xdmadTxCfg.mbr_da = (uint32_t)&pUartHwTx->UART_THR;
+ xdmadTxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SIXTEEN |
+ XDMAC_CC_DSYNC_MEM2PER |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_INCREMENTED_AM |
+ XDMAC_CC_DAM_FIXED_AM |
+ XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(
+ pUartd->uartId, XDMAD_TRANSFER_TX));
+
+ xdmadTxCfg.mbr_bc = 0;
+
+ if (pUartTx->dmaProgrammingMode == XDMAD_MULTI)
+ xdmadTxCfg.mbr_bc = pUartTx->dmaBlockSize;
+
+ xdmadTxCfg.mbr_sus = 0;
+ xdmadTxCfg.mbr_dus = 0;
+ xdmadTxCfg.mbr_ds = 0;
+ xdmaCndc = 0;
+ /* Enable End of Block; Read Bus error; Write Bus Error;
+ Overflow Error interrupt */
+ xdmaInt = (XDMAC_CIE_BIE |
+ XDMAC_CIE_RBIE |
+ XDMAC_CIE_WBIE |
+ XDMAC_CIE_ROIE);
+
+ } else if (pUartTx->dmaProgrammingMode == XDMAD_LLI) {
+ LLI_Size = pUartTx->dmaBlockSize;
+ pBuff = pUartTx->pBuff;
+
+ if (pUartTx->pLLIview != NULL) {
+ free(pUartTx->pLLIview);
+ pUartTx->pLLIview = NULL;
+ }
+
+ pUartTx->pLLIview = malloc(sizeof(LinkedListDescriporView1) * LLI_Size);
+
+ if (pUartTx->pLLIview == NULL) {
+ TRACE_ERROR(" Can not allocate memory to Tx LLI");
+ return USARTD_ERROR;
+ }
+
+ xdmadTxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SIXTEEN |
+ XDMAC_CC_DSYNC_MEM2PER |
+ XDMAC_CC_MEMSET_NORMAL_MODE |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_INCREMENTED_AM |
+ XDMAC_CC_DAM_FIXED_AM |
+ XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(
+ pUartd->uartId, XDMAD_TRANSFER_TX));
+ xdmadTxCfg.mbr_bc = 0;
+
+ for (i = 0; i < LLI_Size; i++) {
+ pUartTx->pLLIview[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1 |
+ XDMA_UBC_NSEN_UPDATED |
+ XDMA_UBC_NDEN_UNCHANGED |
+ ((i == LLI_Size - 1) ? ((pUartTx->dmaRingBuffer) ?
+ XDMA_UBC_NDE_FETCH_EN : 0) :
+ XDMA_UBC_NDE_FETCH_EN) | pUartTx->BuffSize;
+ pUartTx->pLLIview[i].mbr_da = (uint32_t)&pUartHwTx->UART_THR;
+ pUartTx->pLLIview[i].mbr_sa = (uint32_t)pBuff;
+ pUartTx->pLLIview[i].mbr_nda = (i == (LLI_Size - 1)) ?
+ ((pUartTx->dmaRingBuffer) ? (uint32_t)pUartTx->pLLIview : 0) :
+ (uint32_t)&pUartTx->pLLIview[ i + 1 ];
+ pBuff += pUartTx->BuffSize;
+ }
+
+ SCB_CleanDCache_by_Addr((uint32_t *)(pUartTx->pLLIview),
+ sizeof(LinkedListDescriporView1)*LLI_Size);
+
+ xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1 |
+ XDMAC_CNDC_NDE_DSCR_FETCH_EN |
+ XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED |
+ XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED;
+ xdmaInt = ((pUartTx->dmaRingBuffer) ? XDMAC_CIE_BIE : XDMAC_CIE_LIE);
+
+ } else {
+ TRACE_ERROR("DmaProgState is incorrect \n\r");
+ return 1;
+ }
+
+ if (XDMAD_ConfigureTransfer(pXdmadTx, pUartTx->ChNum, &xdmadTxCfg, xdmaCndc,
+ (uint32_t)pUartTx->pLLIview, xdmaInt))
+ return USARTD_ERROR;
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+/**
+ * \brief Initializes the UartDma structure and the corresponding UART & DMA .
+ * hardware select value.
+ * The driver will uses DMA channel 0 for RX and DMA channel 1 for TX.
+ * The DMA channels are freed automatically when no UART command processing.
+ *
+ * \param pUartd Pointer to a UartDma instance.
+ * \param pUartHw Associated UART peripheral.
+ * \param uartId UART peripheral identifier.
+ * \param uartMode UART peripheral identifier.*
+ * \param baud UART baud rate
+ * \param clk UART ref clock
+ * \param pXdmad Pointer to a Dmad instance.
+ */
+uint32_t UARTD_Configure(UartDma *pUartd ,
+ uint8_t uartId,
+ uint32_t uartMode,
+ uint32_t baud,
+ uint32_t clk)
+{
+ /* Enable the peripheral clock in the PMC*/
+ PMC_EnablePeripheral(uartId);
+
+ /* Initialize the UART structure */
+ pUartd->uartId = uartId;
+
+ if (uartId == ID_UART0)
+ pUartd->pUartHw = UART0;
+
+ if (uartId == ID_UART1)
+ pUartd->pUartHw = UART1;
+
+ if (uartId == ID_UART2)
+ pUartd->pUartHw = UART2;
+
+ if (uartId == ID_UART3)
+ pUartd->pUartHw = UART3;
+
+ if (uartId == ID_UART4)
+ pUartd->pUartHw = UART4;
+
+ pUartd->pXdmad->pXdmacs = XDMAC;
+
+ /* Enable the UART Peripheral ,Execute a software reset of the UART,
+ Configure UART in Master Mode*/
+ UART_Configure (pUartd->pUartHw, uartMode, baud, clk);
+
+ /* Check if DMA IRQ is enable; if not clear pending IRQs in init it */
+ if (!(NVIC_GetActive(XDMAC_IRQn)))
+ NVIC_ClearPendingIRQ(XDMAC_IRQn);
+
+ return 0;
+}
+
+/**
+ * \brief This function initialize the appropriate DMA channel for Rx channel of
+ * UART
+ * \param pUartd Pointer to a UartDma instance.
+ * \param pRxCh Pointer to TxChannel configuration
+ * \returns 0 if the transfer has been started successfully;
+ * otherwise returns UARTD_ERROR_LOCK is the driver is in use, or UARTD_ERROR
+ * if the command is not valid.
+ */
+uint32_t UARTD_EnableRxChannels(UartDma *pUartd, UartChannel *pRxCh)
+{
+ Uart *pUartHw = pUartd->pUartHw;
+ uint32_t Channel;
+
+ assert(pRxCh);
+ /* Init USART Rx Channel. */
+ pUartd->pRxChannel = pRxCh;
+
+ /* Enables the USART to receive data. */
+ UART_SetReceiverEnabled (pUartHw , ENABLE);
+
+
+ /* Allocate a DMA channel for UART RX. */
+ Channel = XDMAD_AllocateChannel(pUartd->pXdmad, pUartd->uartId,
+ XDMAD_TRANSFER_MEMORY);
+
+ if (Channel == XDMAD_ALLOC_FAILED)
+ return UARTD_ERROR;
+
+ pRxCh->ChNum = Channel;
+
+ /* Setup callbacks for UART RX */
+ if (pRxCh->callback) {
+ XDMAD_SetCallback(pUartd->pXdmad, pRxCh->ChNum,
+ (XdmadTransferCallback)pRxCh->callback, pRxCh->pArgument);
+ } else {
+ XDMAD_SetCallback(pUartd->pXdmad, pRxCh->ChNum,
+ (XdmadTransferCallback)UARTD_Rx_Cb, pUartd);
+ }
+
+ if (XDMAD_PrepareChannel(pUartd->pXdmad, pRxCh->ChNum))
+ return UARTD_ERROR;
+
+ if (_configureUartRxDma(pUartd, pRxCh))
+ return UARTD_ERROR_LOCK;
+
+ /* Check if DMA IRQ is enable; if not Enable it */
+ if (!(NVIC_GetActive(XDMAC_IRQn))) {
+ /* Enable interrupt */
+ NVIC_EnableIRQ(XDMAC_IRQn);
+ }
+
+ return 0;
+}
+
+/**
+ * \brief This function initialize the appropriate DMA channel for Tx channel of
+ * UART
+ * \param pUartd Pointer to a UartDma instance.
+ * \param pTxCh Pointer to RxChannel configuration
+ * \returns 0 if the transfer has been started successfully;
+ * otherwise returns UARTD_ERROR_LOCK is the driver is in use, or UARTD_ERROR
+ * if the command is not valid.
+ */
+uint32_t UARTD_EnableTxChannels(UartDma *pUartd, UartChannel *pTxCh)
+{
+ Uart *pUartHw = pUartd->pUartHw;
+ uint32_t Channel;
+
+ /* Init USART Tx Channel. */
+ pUartd->pTxChannel = pTxCh;
+
+ /* Enables the USART to transfer data. */
+ UART_SetTransmitterEnabled (pUartHw , ENABLE);
+
+ /* Allocate a DMA channel for UART TX. */
+ Channel = XDMAD_AllocateChannel(pUartd->pXdmad,
+ XDMAD_TRANSFER_MEMORY, pUartd->uartId);
+
+ if (pTxCh->ChNum == XDMAD_ALLOC_FAILED)
+ return USARTD_ERROR;
+
+ pTxCh->ChNum = Channel;
+
+ /* Setup callbacks for UART TX */
+ if (pUartd->pTxChannel->callback) {
+ XDMAD_SetCallback(pUartd->pXdmad, pTxCh->ChNum,
+ (XdmadTransferCallback)pTxCh->callback, pTxCh->pArgument);
+ } else
+ XDMAD_SetCallback(pUartd->pXdmad, pTxCh->ChNum,
+ (XdmadTransferCallback)UARTD_Tx_Cb, pUartd);
+
+ if (XDMAD_PrepareChannel(pUartd->pXdmad, pTxCh->ChNum))
+ return USARTD_ERROR;
+
+ if (_configureUartTxDma(pUartd, pTxCh))
+ return USARTD_ERROR_LOCK;
+
+ /* Check if DMA IRQ is enable; if not Enable it */
+ if (!(NVIC_GetActive(XDMAC_IRQn))) {
+ /* Enable interrupt */
+ NVIC_EnableIRQ(XDMAC_IRQn);
+ }
+
+ return 0;
+}
+
+/**
+ * \brief This function disables the appropriate DMA channel for Rx channel of
+ * USART
+ * \param pUsartd Pointer to a UsartDma instance.
+ * \param pRxCh Pointer to TxChannel configuration
+ * \returns 0 if the transfer has been started successfully;
+ * otherwise returns USARTD_ERROR_LOCK is the driver is in use, or USARTD_ERROR
+ * if the command is not valid.
+ */
+
+uint32_t UARTD_DisableRxChannels(UartDma *pUartd, UartChannel *pRxCh)
+{
+ assert(pRxCh);
+
+ /* Enables the USART to transfer data. */
+ UART_SetReceiverEnabled (pUartd->pUartHw , DISABLE);
+
+ XDMAD_StopTransfer(pUartd->pXdmad, pRxCh->ChNum);
+
+ XDMAD_SetCallback(pUartd->pXdmad, pRxCh->ChNum, NULL, NULL);
+
+ /* Free allocated DMA channel for USART TX. */
+ if (XDMAD_FreeChannel(pUartd->pXdmad, pRxCh->ChNum) != XDMAD_OK)
+ return USARTD_ERROR;
+
+ if (pRxCh->dmaProgrammingMode == XDMAD_LLI) {
+ free(pRxCh->pLLIview);
+ pRxCh->pLLIview = NULL;
+ }
+
+ pRxCh->sempaphore = 1;
+ return 0;
+}
+
+
+/**
+ * \brief This function disables the appropriate DMA channel for Tx channel of
+ * USART
+ * \param pUsartd Pointer to a USARTDma instance.
+ * \param pTxCh Pointer to TxChannel configuration
+ * \returns 0 if the transfer has been started successfully;
+ * otherwise returns USARTD_ERROR_LOCK is the driver is in use, or USARTD_ERROR
+ * if the command is not valid.
+ */
+
+uint32_t UARTD_DisableTxChannels(UartDma *pUartd, UartChannel *pTxCh)
+{
+ assert(pTxCh);
+
+ /* Enables the USART to transfer data. */
+ UART_SetTransmitterEnabled (pUartd->pUartHw , DISABLE);
+
+ XDMAD_StopTransfer(pUartd->pXdmad, pTxCh->ChNum);
+
+ XDMAD_SetCallback(pUartd->pXdmad, pTxCh->ChNum, NULL, NULL);
+
+ /* Free allocated DMA channel for USART TX. */
+ if (XDMAD_FreeChannel(pUartd->pXdmad, pTxCh->ChNum) != XDMAD_OK)
+ return USARTD_ERROR;
+
+ if (pTxCh->dmaProgrammingMode == XDMAD_LLI) {
+ free(pTxCh->pLLIview);
+ pTxCh->pLLIview = NULL;
+ }
+
+ pTxCh->sempaphore = 1;
+ return 0;
+}
+
+/**
+ * \brief Starts a UART master transfer. This is a non blocking function. It
+ * will return as soon as the transfer is started.
+ *
+ * \param pUartd Pointer to a UartDma instance.
+ * \returns 0 if the transfer has been started successfully; otherwise returns
+ * UARTD_ERROR_LOCK is the driver is in use, or UARTD_ERROR if the command is
+ * not valid.
+ */
+uint32_t UARTD_SendData(UartDma *pUartd)
+{
+ /* Start DMA 0(RX) && 1(TX) */
+ SCB_CleanDCache_by_Addr((uint32_t *)pUartd->pTxChannel->pBuff,
+ pUartd->pTxChannel->BuffSize);
+ pUartd->pTxChannel->sempaphore = 0;
+
+ if (XDMAD_StartTransfer(pUartd->pXdmad, pUartd->pTxChannel->ChNum))
+ return USARTD_ERROR_LOCK;
+
+ return 0;
+}
+
+/**
+ * \brief Starts a UART master transfer. This is a non blocking function. It
+ * will return as soon as the transfer is started.
+ *
+ * \param pUartd Pointer to a UartDma instance.
+ * \returns 0 if the transfer has been started successfully; otherwise returns
+ * UARTD_ERROR_LOCK is the driver is in use, or UARTD_ERROR if the command is
+ * not valid.
+ */
+uint32_t UARTD_RcvData(UartDma *pUartd)
+{
+ pUartd->pRxChannel->sempaphore = 0;
+
+ /* Start DMA 0(RX) && 1(TX) */
+ if (XDMAD_StartTransfer(pUartd->pXdmad, pUartd->pRxChannel->ChNum))
+ return USARTD_ERROR_LOCK;
+
+ return 0;
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/usart.c b/bsps/arm/atsam/contrib/libraries/libchip/source/usart.c
new file mode 100644
index 0000000000..f438d311b1
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/usart.c
@@ -0,0 +1,466 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Implementation of USART (Universal Synchronous Asynchronous Receiver
+ * Transmitter) controller.
+ *
+ */
+/*------------------------------------------------------------------------------
+ * Headers
+ *-----------------------------------------------------------------------------*/
+#include "chip.h"
+
+#include <assert.h>
+#include <string.h>
+
+/*----------------------------------------------------------------------------
+ * Local definitions
+ *----------------------------------------------------------------------------*/
+
+
+/*------------------------------------------------------------------------------
+ * Exported functions
+ *-----------------------------------------------------------------------------*/
+
+/**
+ * \brief Configures an USART baudrate.
+ *
+ *
+ * \param pUsart Pointer to the USART peripheral to configure.
+ * \param baudrate Baudrate at which the USART should operate (in Hz).
+ * \param masterClock Frequency of the system master clock (in Hz).
+ */
+void USART_SetBaudrate(Usart *pUsart,
+ uint8_t OverSamp,
+ uint32_t baudrate,
+ uint32_t masterClock)
+{
+ unsigned int CD, FP, BaudError, ActualBaudRate;
+ /* Configure baudrate*/
+ BaudError = 10;
+ OverSamp = 0;
+#ifdef __rtems__
+ CD = 0;
+ FP = 0;
+#endif /* __rtems__ */
+
+ /*Asynchronous*/
+ if ((pUsart->US_MR & US_MR_SYNC) == 0) {
+ /* 7816 mode */
+ if (((pUsart->US_MR & US_MR_USART_MODE_IS07816_T_0)
+ == US_MR_USART_MODE_IS07816_T_0)
+ || ((pUsart->US_MR & US_MR_USART_MODE_IS07816_T_1)
+ == US_MR_USART_MODE_IS07816_T_1)) {
+ /* Define the baud rate divisor register */
+ /* CD = MCK / SCK */
+ /* SCK = FIDI x BAUD = 372 x 9600 */
+ /* BOARD_MCK */
+ /* CD = MCK/(FIDI x BAUD) = 150000000 / (372x9600) = 42 */
+ CD = masterClock / (pUsart->US_FIDI * baudrate);
+ FP = 0;
+ } else {
+ while (BaudError > 5) {
+ CD = (masterClock / (baudrate * 8 * (2 - OverSamp)));
+ FP = ((masterClock / (baudrate * (2 - OverSamp))) - CD * 8);
+ ActualBaudRate = (masterClock / (CD * 8 + FP)) / (2 - OverSamp);
+ BaudError = (100 - ((baudrate * 100 / ActualBaudRate)));
+
+ if (BaudError > 5) {
+ OverSamp++;
+
+ if (OverSamp >= 2) {
+ TRACE_ERROR("Canont set this baudrate \n\r");
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /*Synchronous SPI */
+ if ((pUsart->US_MR & US_MR_USART_MODE_SPI_MASTER)
+ == US_MR_USART_MODE_SPI_MASTER
+ || ((pUsart->US_MR & US_MR_SYNC) == US_MR_SYNC)) {
+ if ((pUsart->US_MR & US_MR_USCLKS_Msk) == US_MR_USCLKS_MCK) {
+ CD = masterClock / baudrate;
+ FP = ((masterClock / baudrate) - CD);
+ }
+ }
+
+ pUsart->US_BRGR = (US_BRGR_CD(CD) | US_BRGR_FP(FP));
+
+ /* Configure OverSamp*/
+ pUsart->US_MR |= (OverSamp << 19);
+}
+
+/**
+ * \brief Configures an USART peripheral with the specified parameters.
+ *
+ *
+ * \param pUsart Pointer to the USART peripheral to configure.
+ * \param mode Desired value for the USART mode register (see the datasheet).
+ * \param baudrate Baudrate at which the USART should operate (in Hz).
+ * \param masterClock Frequency of the system master clock (in Hz).
+ */
+void USART_Configure(Usart *pUsart,
+ uint32_t mode,
+ uint32_t baudrate,
+ uint32_t masterClock)
+{
+
+ /* Reset and disable receiver & transmitter*/
+ pUsart->US_CR = US_CR_RSTRX | US_CR_RSTTX
+ | US_CR_RXDIS | US_CR_TXDIS | US_CR_RSTSTA;
+ pUsart->US_IDR = 0xFFFFFFFF;
+
+ pUsart->US_MR = mode;
+ /* Configure baudrate*/
+ USART_SetBaudrate(pUsart, 0, baudrate, masterClock);
+
+ /* Enable receiver and transmitter */
+ pUsart->US_CR = US_CR_RXEN | US_CR_TXEN;
+
+ /* Disable buffering for printf(). */
+#if (defined (__GNUC__) && !defined (__SAMBA__))
+ setvbuf(stdout, (char *)NULL, _IONBF, 0);
+#endif
+
+}
+/**
+ * \brief Enables or disables the transmitter of an USART peripheral.
+ *
+ *
+ * \param pUsart Pointer to an USART peripheral
+ * \param enabled If true, the transmitter is enabled; otherwise it is
+ * disabled.
+ */
+void USART_SetTransmitterEnabled(Usart *pUsart, uint8_t enabled)
+{
+ if (enabled)
+ pUsart->US_CR = US_CR_TXEN;
+ else
+ pUsart->US_CR = US_CR_TXDIS;
+}
+
+/**
+ * \brief Disables the Receiver of an USART peripheral.
+ *
+ * \param pUsart Pointer to an USART peripheral
+ */
+void USART_DisableRx(Usart *pUsart)
+{
+
+ pUsart->US_CR = US_CR_RXDIS;
+}
+
+/**
+ * \brief Disables the transmitter of an USART peripheral.
+ *
+ * \param pUsart Pointer to an USART peripheral
+ */
+void USART_DisableTx(Usart *pUsart)
+{
+ pUsart->US_CR = US_CR_TXDIS;
+}
+
+/**
+ * \brief Enables the Receiver of an USART peripheral.
+ *
+ * \param pUsart Pointer to an USART peripheral
+ */
+void USART_EnableRx(Usart *pUsart)
+{
+
+ pUsart->US_CR = US_CR_RXEN;
+}
+
+/**
+ * \brief Enables the transmitter of an USART peripheral
+ *
+ * \param pUsart Pointer to an USART peripheral
+ */
+void USART_EnableTx(Usart *pUsart)
+{
+ pUsart->US_CR = US_CR_TXEN;
+}
+/**
+ * \brief Resets or disables the Receiver of an USART peripheral.
+ *
+ *
+ * \param pUsart Pointer to an USART peripheral
+ */
+void USART_ResetRx(Usart *pUsart)
+{
+
+ pUsart->US_CR = US_CR_RSTRX | US_CR_RXDIS;
+}
+
+/**
+ * \brief resets and disables the transmitter of an USART peripheral.
+ *
+ *
+ * \param pUsart Pointer to an USART peripheral
+ */
+void USART_ResetTx(Usart *pUsart)
+{
+ pUsart->US_CR = US_CR_RSTTX | US_CR_TXDIS;
+}
+/**
+ * \brief Enables or disables the receiver of an USART peripheral
+ *
+ *
+ * \param pUsart Pointer to an USART peripheral
+ * \param enabled If true, the receiver is enabled; otherwise it is disabled.
+ */
+void USART_SetReceiverEnabled(Usart *pUsart, uint8_t enabled)
+{
+ if (enabled)
+ pUsart->US_CR = US_CR_RXEN;
+ else
+ pUsart->US_CR = US_CR_RXDIS;
+}
+
+/**
+ * \brief Enables or disables the Request To Send (RTS) of an USART peripheral
+ *
+ *
+ * \param pUsart Pointer to an USART peripheral
+ * \param enabled If true, the RTS is enabled (0); otherwise it is disabled.
+ */
+void USART_SetRTSEnabled(Usart *pUsart, uint8_t enabled)
+{
+ if (enabled)
+ pUsart->US_CR = US_CR_RTSEN;
+ else
+ pUsart->US_CR = US_CR_RTSDIS;
+}
+
+/**
+ * \brief Sends one packet of data through the specified USART peripheral. This
+ * function operates synchronously, so it only returns when the data has been
+ * actually sent.
+ *
+ *
+ * \param pUsart Pointer to an USART peripheral.
+ * \param data Data to send including 9nth bit and sync field if necessary (in
+ * the same format as the US_THR register in the datasheet).
+ * \param timeOut Time out value (0 = no timeout).
+ */
+void USART_Write(Usart *pUsart, uint16_t data, volatile uint32_t timeOut)
+{
+ if (timeOut == 0) {
+ while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0);
+ } else {
+ while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0) {
+ if (timeOut == 0) {
+ TRACE_ERROR("USART_Write: Timed out.\n\r");
+ return;
+ }
+
+ timeOut--;
+ }
+ }
+
+ pUsart->US_THR = data;
+}
+
+/**
+ * \brief Reads and return a packet of data on the specified USART peripheral.
+ * This function operates asynchronously, so it waits until some data has been
+ * received.
+ *
+ * \param pUsart Pointer to an USART peripheral.
+ * \param timeOut Time out value (0 -> no timeout).
+ */
+uint16_t USART_Read(Usart *pUsart, volatile uint32_t timeOut)
+{
+ if (timeOut == 0) {
+ while ((pUsart->US_CSR & US_CSR_RXRDY) == 0);
+ } else {
+ while ((pUsart->US_CSR & US_CSR_RXRDY) == 0) {
+ if (timeOut == 0) {
+ TRACE_ERROR("USART_Read: Timed out.\n\r");
+ return 0;
+ }
+
+ timeOut--;
+ }
+ }
+
+ return pUsart->US_RHR;
+}
+
+/**
+ * \brief Returns 1 if some data has been received and can be read from an
+ * USART; otherwise returns 0.
+ *
+ * \param pUsart Pointer to an USART instance.
+ */
+uint8_t USART_IsDataAvailable(Usart *pUsart)
+{
+ if ((pUsart->US_CSR & US_CSR_RXRDY) != 0)
+ return 1;
+ else
+ return 0;
+}
+
+/**
+ * \brief Sends one packet of data through the specified USART peripheral. This
+ * function operates synchronously, so it only returns when the data has been
+ * actually sent.
+ *
+ * \param pUsart Pointer to an USART peripheral.
+ * \param c Character to send
+ */
+void USART_PutChar(Usart *pUsart, uint8_t c)
+{
+ /* Wait for the transmitter to be ready*/
+ while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0);
+
+ /* Send character*/
+ pUsart->US_THR = c;
+
+ /* Wait for the transfer to complete*/
+ while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0);
+}
+
+/**
+ * \brief Return 1 if a character can be read in USART
+ * \param pUsart Pointer to an USART peripheral.
+ */
+uint32_t USART_IsRxReady(Usart *pUsart)
+{
+ return (pUsart->US_CSR & US_CSR_RXRDY);
+}
+
+/**
+ * \brief Get present status
+ * \param pUsart Pointer to an USART peripheral.
+ */
+uint32_t USART_GetStatus(Usart *pUsart)
+{
+ return pUsart->US_CSR;
+}
+
+/**
+ * \brief Enable interrupt
+ * \param pUsart Pointer to an USART peripheral.
+ * \param mode Interrupt mode.
+ */
+void USART_EnableIt(Usart *pUsart, uint32_t mode)
+{
+ pUsart->US_IER = mode;
+}
+
+/**
+ * \brief Disable interrupt
+ * \param pUsart Pointer to an USART peripheral.
+ * \param mode Interrupt mode.
+ */
+void USART_DisableIt(Usart *pUsart, uint32_t mode)
+{
+ pUsart->US_IDR = mode;
+}
+
+/**
+ * \brief Return interrupt mask
+ * \param pUsart Pointer to an USART peripheral.
+ */
+uint32_t USART_GetItMask(Usart *pUsart)
+{
+ return pUsart->US_IMR;
+}
+
+/**
+ * \brief Reads and returns a character from the USART.
+ *
+ * \note This function is synchronous (i.e. uses polling).
+ * \param pUsart Pointer to an USART peripheral.
+ * \return Character received.
+ */
+uint8_t USART_GetChar(Usart *pUsart)
+{
+ while ((pUsart->US_CSR & US_CSR_RXRDY) == 0);
+
+ return pUsart->US_RHR;
+}
+
+/**
+ * \brief Enable Rx Timeout for USART.
+ *
+ * \param pUsart Pointer to an USART peripheral.
+ * \param Timeout Timeout value
+ * \return None
+ */
+void USART_EnableRecvTimeOut(Usart *pUsart, uint32_t Timeout)
+{
+ if (Timeout <= MAX_RX_TIMEOUT)
+ pUsart->US_RTOR = Timeout;
+ else if (Timeout == 0) {
+ TRACE_DEBUG("Timeout is disabled\n\r");
+ } else {
+ TRACE_INFO_WP("\n\r");
+ TRACE_FATAL("Timeout value is out of range\n\r");
+ }
+}
+
+/**
+ * \brief Enable Tx Timeout for USART.
+ *
+ * \param pUsart Pointer to an USART peripheral.
+ * \param TimeGaurd TimeGaurd value
+ * \return None
+ */
+void USART_EnableTxTimeGaurd(Usart *pUsart, uint32_t TimeGaurd)
+{
+ if (((pUsart->US_MR & US_MR_USART_MODE_LON) && TimeGaurd <= 16777215) ||
+ ((pUsart->US_MR & US_MR_USART_MODE_LON) && TimeGaurd <= 255))
+ pUsart->US_TTGR = TimeGaurd;
+ else
+ TRACE_ERROR(" TimeGaurd Value is too big for mode");
+}
+/**
+ * \brief Acknowledge Rx timeout and sets to Idle or periodic repetitive state.
+ *
+ * \param pUsart Pointer to an USART peripheral.
+ * \param Periodic If timeout is periodic or should wait for new char
+ * \return None
+ */
+void USART_AcknowledgeRxTimeOut(Usart *pUsart, uint8_t Periodic)
+{
+ if (Periodic) {
+ pUsart->US_CR = US_CR_RETTO; // Restart timeout timer
+ } else {
+ // Puts USARt in Idle mode and waits for a char after timeout
+ pUsart->US_CR = US_CR_STTTO;
+ }
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/usart_dma.c b/bsps/arm/atsam/contrib/libraries/libchip/source/usart_dma.c
new file mode 100644
index 0000000000..51488e6bce
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/usart_dma.c
@@ -0,0 +1,600 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+* \addtogroup usart_dma_module USART xDMA driver
+* \section Usage
+*
+* <ul>
+* <li> USARTD_Configure() initializes and configures the USART peripheral
+* and xDMA for data transfer.</li>
+* <li> Configures the parameters for the device corresponding to the cs
+* value by USARTD_ConfigureCS(). </li>
+* </ul>
+*
+*/
+
+/**
+ * \file
+ *
+ * Implementation for the USART with xDMA driver.
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+#include "string.h"
+#include "stdlib.h"
+
+/*----------------------------------------------------------------------------
+ * Local functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief USART xDMA Rx callback
+ * Invoked on USART DMA reception done.
+ * \param channel DMA channel.
+ * \param pArg Pointer to callback argument - Pointer to USARTDma instance.
+ */
+static void USARTD_Rx_Cb(uint32_t channel, UsartDma *pArg)
+{
+
+ UsartChannel *pUsartdCh = pArg->pRxChannel;
+
+ if (channel != pUsartdCh->ChNum)
+ return;
+
+ /* Release the DMA channels */
+ XDMAD_FreeChannel(pArg->pXdmad, pUsartdCh->ChNum);
+ pUsartdCh->dmaProgress = 1;
+ SCB_InvalidateDCache_by_Addr((uint32_t *)pUsartdCh->pBuff, pUsartdCh->BuffSize);
+
+}
+
+/**
+ * \brief USART xDMA Rx callback
+ * Invoked on USART DMA reception done.
+ * \param channel DMA channel.
+ * \param pArg Pointer to callback argument - Pointer to USARTDma instance.
+ */
+static void USARTD_Tx_Cb(uint32_t channel, UsartDma *pArg)
+{
+ UsartChannel *pUsartdCh = pArg->pTxChannel;
+
+ if (channel != pUsartdCh->ChNum)
+ return;
+
+ /* Release the DMA channels */
+ XDMAD_FreeChannel(pArg->pXdmad, pUsartdCh->ChNum);
+
+ pUsartdCh->dmaProgress = 1;
+}
+
+/**
+ * \brief Configure the USART Rx DMA Destination with Linker List mode.
+ *
+ * \param UsartChannel Pointer to USART dma channel
+ * \returns 0 if the dma multibuffer configuration successfully; otherwise
+ * returnsUSARTD_ERROR_XXX.
+ */
+static uint8_t _configureRxDma(UsartDma *pUsart, UsartChannel *pUsartRx)
+{
+ sXdmadCfg xdmadRxCfg;
+ uint32_t xdmaCndc, xdmaInt;
+ uint32_t i, LLI_Size;
+ Usart *pUsartHwRx = pUsart->pUsartHw;
+ sXdmad *pXdmadRx = pUsart->pXdmad;
+ uint8_t *pBuff = 0;
+
+
+ /* Setup RX Single block */
+ if (pUsartRx->dmaProgrammingMode < XDMAD_LLI) {
+ xdmadRxCfg.mbr_ubc = pUsartRx->BuffSize;
+ xdmadRxCfg.mbr_da = (uint32_t)pUsartRx->pBuff;
+
+ xdmadRxCfg.mbr_sa = (uint32_t)&pUsartHwRx->US_RHR;
+ xdmadRxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SIXTEEN |
+ XDMAC_CC_DSYNC_PER2MEM |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_FIXED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber
+ (pUsart->usartId, XDMAD_TRANSFER_RX));
+
+ xdmadRxCfg.mbr_bc = 0;
+
+ if (pUsartRx->dmaProgrammingMode == XDMAD_MULTI)
+ xdmadRxCfg.mbr_bc = pUsartRx->dmaBlockSize;
+
+ xdmadRxCfg.mbr_sus = 0;
+ xdmadRxCfg.mbr_dus = 0;
+ xdmaCndc = 0;
+ xdmaInt = (XDMAC_CIE_BIE |
+ XDMAC_CIE_DIE |
+ XDMAC_CIE_FIE |
+ XDMAC_CIE_RBIE |
+ XDMAC_CIE_WBIE |
+ XDMAC_CIE_ROIE);
+ } else if (pUsartRx->dmaProgrammingMode == XDMAD_LLI) {
+
+ /* Setup RX Link List */
+ LLI_Size = pUsartRx->dmaBlockSize;
+ pBuff = pUsartRx->pBuff;
+
+ if (pUsartRx->pLLIview != NULL) {
+ free(pUsartRx->pLLIview);
+ pUsartRx->pLLIview = NULL;
+ }
+
+ pUsartRx->pLLIview = malloc(sizeof(LinkedListDescriporView1) * LLI_Size);
+
+ if (pUsartRx->pLLIview == NULL) {
+ TRACE_ERROR(" Can not allocate memory to Rx LLI");
+ return USARTD_ERROR;
+ }
+
+ xdmadRxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SIXTEEN |
+ XDMAC_CC_DSYNC_PER2MEM |
+ XDMAC_CC_MEMSET_NORMAL_MODE |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_FIXED_AM |
+ XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber
+ (pUsart->usartId, XDMAD_TRANSFER_RX));
+ xdmadRxCfg.mbr_bc = 0;
+
+ for (i = 0; i < LLI_Size; i++) {
+ pUsartRx->pLLIview[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1 |
+ XDMA_UBC_NSEN_UNCHANGED |
+ XDMA_UBC_NDEN_UPDATED |
+ ((i == LLI_Size - 1) ? (
+ (pUsartRx->dmaRingBuffer) ?
+ XDMA_UBC_NDE_FETCH_EN : 0) :
+ XDMA_UBC_NDE_FETCH_EN) |
+ pUsartRx->BuffSize;
+ pUsartRx->pLLIview[i].mbr_sa = (uint32_t)&pUsartHwRx->US_RHR;
+ pUsartRx->pLLIview[i].mbr_da = (uint32_t)pBuff;
+ pUsartRx->pLLIview[i].mbr_nda = (i == (LLI_Size - 1)) ?
+ ((pUsartRx->dmaRingBuffer) ? (uint32_t)pUsartRx->pLLIview : 0)
+ : (uint32_t)&pUsartRx->pLLIview[ i + 1 ];
+ pBuff += pUsartRx->BuffSize;
+ }
+
+ SCB_CleanDCache_by_Addr((uint32_t *)(pUsartRx->pLLIview),
+ sizeof(LinkedListDescriporView1)*LLI_Size);
+ xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1 |
+ XDMAC_CNDC_NDE_DSCR_FETCH_EN |
+ XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED |
+ XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED;
+ xdmaInt = ((pUsartRx->dmaRingBuffer) ? XDMAC_CIE_BIE : XDMAC_CIE_LIE);
+ } else
+ return 1;
+
+ if (XDMAD_ConfigureTransfer(
+ pXdmadRx, pUsartRx->ChNum, &xdmadRxCfg, xdmaCndc,
+ (uint32_t)pUsartRx->pLLIview, xdmaInt))
+ return USARTD_ERROR;
+
+ return 0;
+}
+
+/**
+ * \brief Configure the USART tx DMA source with Linker List mode.
+ *
+ * \param UsartChannel Pointer to USART dma channel
+ * \returns 0 if the dma multibuffer configuration successfully; otherwise returns
+ * USARTD_ERROR_XXX.
+ */
+static uint8_t _configureTxDma(UsartDma *pUsart, UsartChannel *pUsartTx)
+{
+ sXdmadCfg xdmadTxCfg;
+ uint32_t xdmaCndc, xdmaInt, LLI_Size, i;
+ uint8_t *pBuff = 0;
+ Usart *pUsartHwTx = pUsart->pUsartHw;
+ sXdmad *pXdmadTx = pUsart->pXdmad;
+
+ /* Setup TX Link List */
+
+ if (pUsartTx->dmaProgrammingMode < XDMAD_LLI) {
+ /* Number of Data */
+ xdmadTxCfg.mbr_ubc = pUsartTx->BuffSize;
+ /* Source and Destination address of DMA */
+ xdmadTxCfg.mbr_sa = (uint32_t)pUsartTx->pBuff;
+ xdmadTxCfg.mbr_da = (uint32_t)&pUsartHwTx->US_THR;
+ /* DMA Channel configuration */
+ xdmadTxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SIXTEEN |
+ XDMAC_CC_DSYNC_MEM2PER |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_INCREMENTED_AM |
+ XDMAC_CC_DAM_FIXED_AM |
+ XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber
+ (pUsart->usartId, XDMAD_TRANSFER_TX));
+
+ xdmadTxCfg.mbr_bc = 0;
+
+ if (pUsartTx->dmaProgrammingMode == XDMAD_MULTI)
+ xdmadTxCfg.mbr_bc = pUsartTx->dmaBlockSize;
+
+ xdmadTxCfg.mbr_sus = 0;
+ xdmadTxCfg.mbr_dus = 0;
+ xdmadTxCfg.mbr_ds = 0;
+ xdmaCndc = 0;
+ /* Enable End of Block; Read Bus error; Write Bus Error;
+ Overflow Error interrupt */
+ xdmaInt = (XDMAC_CIE_BIE |
+ XDMAC_CIE_RBIE |
+ XDMAC_CIE_WBIE |
+ XDMAC_CIE_ROIE);
+ } else if (pUsartTx->dmaProgrammingMode == XDMAD_LLI) {
+ LLI_Size = pUsartTx->dmaBlockSize;
+ pBuff = pUsartTx->pBuff;
+
+ /* If channel's LLI is already configured and application
+ want to reconfigured it, free before re-allocating memory */
+ if (pUsartTx->pLLIview != NULL) {
+ free(pUsartTx->pLLIview);
+ pUsartTx->pLLIview = NULL;
+ }
+
+ pUsartTx->pLLIview = malloc(sizeof(LinkedListDescriporView1) * LLI_Size);
+
+ if (pUsartTx->pLLIview == NULL) {
+ TRACE_ERROR(" Can not allocate memory to Tx LLI");
+ return USARTD_ERROR;
+ }
+
+ xdmadTxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
+ XDMAC_CC_MBSIZE_SIXTEEN |
+ XDMAC_CC_DSYNC_MEM2PER |
+ XDMAC_CC_MEMSET_NORMAL_MODE |
+ XDMAC_CC_CSIZE_CHK_1 |
+ XDMAC_CC_DWIDTH_BYTE |
+ XDMAC_CC_SIF_AHB_IF1 |
+ XDMAC_CC_DIF_AHB_IF1 |
+ XDMAC_CC_SAM_INCREMENTED_AM |
+ XDMAC_CC_DAM_FIXED_AM |
+ XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber
+ (pUsart->usartId, XDMAD_TRANSFER_TX));
+ xdmadTxCfg.mbr_bc = 0;
+
+ for (i = 0; i < LLI_Size; i++) {
+ pUsartTx->pLLIview[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1 |
+ XDMA_UBC_NSEN_UPDATED |
+ XDMA_UBC_NDEN_UNCHANGED |
+ ((i == LLI_Size - 1) ? ((pUsartTx->dmaRingBuffer)
+ ? XDMA_UBC_NDE_FETCH_EN : 0) :
+ XDMA_UBC_NDE_FETCH_EN) | pUsartTx->BuffSize;
+ pUsartTx->pLLIview[i].mbr_sa = (uint32_t)pBuff;
+ pUsartTx->pLLIview[i].mbr_da = (uint32_t)&pUsartHwTx->US_THR;
+ pUsartTx->pLLIview[i].mbr_nda = (i == (LLI_Size - 1)) ?
+ ((pUsartTx->dmaRingBuffer) ? (uint32_t)pUsartTx->pLLIview : 0)
+ : (uint32_t)&pUsartTx->pLLIview[ i + 1 ];
+ pBuff += pUsartTx->BuffSize;
+ }
+
+ SCB_CleanDCache_by_Addr((uint32_t *)(pUsartTx->pLLIview),
+ sizeof(LinkedListDescriporView1)*LLI_Size);
+ xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1 |
+ XDMAC_CNDC_NDE_DSCR_FETCH_EN |
+ XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED |
+ XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED;
+ xdmaInt = ((pUsartTx->dmaRingBuffer) ? XDMAC_CIE_BIE : XDMAC_CIE_LIE);
+ } else {
+ TRACE_ERROR("DmaProgState is incorrect \n\r");
+ return 1;
+ }
+
+ if (XDMAD_ConfigureTransfer(pXdmadTx, pUsartTx->ChNum,
+ &xdmadTxCfg, xdmaCndc, (uint32_t)pUsartTx->pLLIview, xdmaInt))
+ return USARTD_ERROR;
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+/**
+ * \brief Initializes the USARTDma structure and the corresponding USART & DMA .
+ * hardware select value.
+ * The driver will uses DMA channel 0 for RX and DMA channel 1 for TX.
+ * The DMA channels are freed automatically when no USART command processing.
+ *
+ * \param pUSARTD Pointer to a UsartDma instance.
+ * \param pUsartHw Associated USART peripheral.
+ * \param usartId USART peripheral identifier.
+ * \param UsartClk USART clock.
+ * \param pXdmad Pointer to a Dmad instance.
+ */
+uint32_t USARTD_Configure(UsartDma *pUsartd ,
+ uint8_t usartId,
+ uint32_t UsartMode,
+ uint32_t BaudRate,
+ uint32_t UsartClk)
+{
+ /* Enable the peripheral clock in the PMC*/
+ PMC_EnablePeripheral(usartId);
+
+ /* Initialize the USART structure */
+ pUsartd->usartId = usartId;
+
+ if (usartId == ID_USART0)
+ pUsartd->pUsartHw = USART0;
+
+ if (usartId == ID_USART1)
+ pUsartd->pUsartHw = USART1;
+
+ if (usartId == ID_USART2)
+ pUsartd->pUsartHw = USART2;
+
+
+ /* Enable the USART Peripheral ,Execute a software reset of the USART,
+ Configure USART in Master Mode*/
+ USART_Configure (pUsartd->pUsartHw, UsartMode, BaudRate, UsartClk);
+
+ /* Check if DMA IRQ is enable; if not clear pending IRQs in init it */
+ if (!(NVIC_GetActive(XDMAC_IRQn)))
+ NVIC_ClearPendingIRQ(XDMAC_IRQn);
+
+ return 0;
+}
+
+/**
+ * \brief This function initialize the appropriate DMA channel for Rx channel
+ * of USART
+ * \param pUsartd Pointer to a UsartDma instance.
+ * \param pRxCh Pointer to TxChannel configuration
+ * \returns 0 if the transfer has been started successfully;
+ * otherwise returns USARTD_ERROR_LOCK is the driver is in use, or
+ * USARTD_ERROR if the command is not valid.
+ */
+uint32_t USARTD_EnableRxChannels(UsartDma *pUsartd, UsartChannel *pRxCh)
+{
+ uint32_t Channel;
+
+ assert(pRxCh);
+ /* Init USART Rx Channel. */
+ pUsartd->pRxChannel = pRxCh;
+
+ /* Enables the USART to receive data. */
+ USART_SetReceiverEnabled (pUsartd->pUsartHw , ENABLE);
+
+
+ /* Allocate a DMA channel for USART0/1 RX. */
+ Channel = XDMAD_AllocateChannel(pUsartd->pXdmad, pUsartd->usartId,
+ XDMAD_TRANSFER_MEMORY);
+
+ if (Channel == XDMAD_ALLOC_FAILED)
+ return USARTD_ERROR;
+
+ pRxCh->ChNum = Channel;
+
+ /* Setup callbacks for USART RX */
+ if (pUsartd->pRxChannel->callback) {
+ XDMAD_SetCallback(pUsartd->pXdmad, pRxCh->ChNum,
+ (XdmadTransferCallback)pRxCh->callback, pRxCh->pArgument);
+ } else {
+ XDMAD_SetCallback(pUsartd->pXdmad, pRxCh->ChNum,
+ (XdmadTransferCallback)USARTD_Rx_Cb, pUsartd);
+ }
+
+
+ if (XDMAD_PrepareChannel(pUsartd->pXdmad, pRxCh->ChNum))
+ return USARTD_ERROR;
+
+ if (_configureRxDma(pUsartd , pUsartd->pRxChannel))
+ return USARTD_ERROR_LOCK;
+
+ /* Check if DMA IRQ is enable; if not Enable it */
+ if (!(NVIC_GetActive(XDMAC_IRQn))) {
+ /* Enable interrupt */
+ NVIC_EnableIRQ(XDMAC_IRQn);
+ }
+
+ return 0;
+}
+
+/**
+ * \brief This function initialize the appropriate DMA channel for Tx channel
+ * of USART
+ * \param pUsartd Pointer to a USARTDma instance.
+ * \param pTxCh Pointer to TxChannel configuration
+ * \returns 0 if the transfer has been started successfully;
+ * otherwise returns USARTD_ERROR_LOCK is the driver is in use, or
+ * USARTD_ERROR if the command is not valid.
+ */
+uint32_t USARTD_EnableTxChannels(UsartDma *pUsartd, UsartChannel *pTxCh)
+{
+
+ uint32_t Channel;
+
+ assert(pTxCh);
+
+ /* Init USART Tx Channel. */
+ pUsartd->pTxChannel = pTxCh;
+
+ /* Enables the USART to transfer data. */
+ USART_SetTransmitterEnabled (pUsartd->pUsartHw , ENABLE);
+
+ /* Allocate a DMA channel for USART0/1 TX. */
+ Channel = XDMAD_AllocateChannel(pUsartd->pXdmad, XDMAD_TRANSFER_MEMORY,
+ pUsartd->usartId);
+
+ if (Channel == XDMAD_ALLOC_FAILED)
+ return USARTD_ERROR;
+
+ pTxCh->ChNum = Channel;
+
+ /* Setup callbacks for USART0/1 TX */
+ if (pUsartd->pTxChannel->callback) {
+ XDMAD_SetCallback(pUsartd->pXdmad, pTxCh->ChNum,
+ (XdmadTransferCallback)pTxCh->callback, pTxCh->pArgument);
+ } else
+ XDMAD_SetCallback(pUsartd->pXdmad, pTxCh->ChNum,
+ (XdmadTransferCallback)USARTD_Tx_Cb, pUsartd);
+
+ if (XDMAD_PrepareChannel(pUsartd->pXdmad, pTxCh->ChNum))
+ return USARTD_ERROR;
+
+ if (_configureTxDma(pUsartd , pUsartd->pTxChannel))
+ return USARTD_ERROR_LOCK;
+
+ /* Check if DMA IRQ is enable; if not Enable it */
+ if (!(NVIC_GetActive(XDMAC_IRQn))) {
+ /* Enable interrupt */
+ NVIC_EnableIRQ(XDMAC_IRQn);
+ }
+
+ return 0;
+}
+
+/**
+ * \brief This function disables the appropriate DMA channel for Rx channel of
+ * USART
+ * \param pUsartd Pointer to a UsartDma instance.
+ * \param pRxCh Pointer to TxChannel configuration
+ * \returns 0 if the transfer has been started successfully;
+ * otherwise returns USARTD_ERROR_LOCK is the driver is in use, or
+ * USARTD_ERROR if the command is not valid.
+ */
+uint32_t USARTD_DisableRxChannels(UsartDma *pUsartd, UsartChannel *pRxCh)
+{
+ assert(pRxCh);
+
+ /* Enables the USART to transfer data. */
+ USART_SetReceiverEnabled (pUsartd->pUsartHw , DISABLE);
+
+ XDMAD_StopTransfer(pUsartd->pXdmad, pRxCh->ChNum);
+
+ XDMAD_SetCallback(pUsartd->pXdmad, pRxCh->ChNum, NULL, NULL);
+
+ /* Free allocated DMA channel for USART TX. */
+ if (XDMAD_FreeChannel(pUsartd->pXdmad, pRxCh->ChNum) != XDMAD_OK)
+ return USARTD_ERROR;
+
+ if (pRxCh->dmaProgrammingMode == XDMAD_LLI) {
+ free(pRxCh->pLLIview);
+ pRxCh->pLLIview = NULL;
+ }
+
+ pRxCh->dmaProgress = 1;
+ return 0;
+}
+
+/**
+ * \brief This function disables the appropriate DMA channel for Tx channel of
+ * USART
+ * \param pUsartd Pointer to a USARTDma instance.
+ * \param pTxCh Pointer to TxChannel configuration
+ * \returns 0 if the transfer has been started successfully;
+ * otherwise returns USARTD_ERROR_LOCK is the driver is in use, or
+ * USARTD_ERROR if the command is not valid.
+ */
+
+uint32_t USARTD_DisableTxChannels(UsartDma *pUsartd, UsartChannel *pTxCh)
+{
+ assert(pTxCh);
+
+ /* Enables the USART to transfer data. */
+ USART_SetTransmitterEnabled (pUsartd->pUsartHw , DISABLE);
+
+ XDMAD_StopTransfer(pUsartd->pXdmad, pTxCh->ChNum);
+
+ XDMAD_SetCallback(pUsartd->pXdmad, pTxCh->ChNum, NULL, NULL);
+
+ /* Free allocated DMA channel for USART TX. */
+ if (XDMAD_FreeChannel(pUsartd->pXdmad, pTxCh->ChNum) != XDMAD_OK)
+ return USARTD_ERROR;
+
+ if (pTxCh->dmaProgrammingMode == XDMAD_LLI) {
+ free(pTxCh->pLLIview);
+ pTxCh->pLLIview = NULL;
+ }
+
+ pTxCh->dmaProgress = 1;
+ return 0;
+}
+
+/**
+ * \brief Starts a USART master transfer. This is a non blocking function. It
+ * will return as soon as the transfer is started.
+ *
+ * \param pUSARTD Pointer to a USARTDma instance.
+ * \returns 0 if the transfer has been started successfully; otherwise returns
+ * USARTD_ERROR_LOCK is the driver is in use, or USARTD_ERROR if the command is
+ * not valid.
+ */
+uint32_t USARTD_SendData(UsartDma *pUsartd)
+{
+ /* Start DMA 0(RX) && 1(TX) */
+ pUsartd->pTxChannel->dmaProgress = 0;
+ SCB_CleanDCache_by_Addr((uint32_t *)pUsartd->pTxChannel->pBuff,
+ pUsartd->pTxChannel->BuffSize);
+
+ if (XDMAD_StartTransfer(pUsartd->pXdmad, pUsartd->pTxChannel->ChNum))
+ return USARTD_ERROR_LOCK;
+
+ return 0;
+}
+
+/**
+ * \brief Starts a USART master transfer. This is a non blocking function. It will
+ * return as soon as the transfer is started.
+ *
+ * \param pUSARTD Pointer to a USARTDma instance.
+ * \returns 0 if the transfer has been started successfully; otherwise returns
+ * USARTD_ERROR_LOCK is the driver is in use, or USARTD_ERROR if the command is not
+ * valid.
+ */
+uint32_t USARTD_RcvData(UsartDma *pUsartd)
+{
+ /* Start DMA 0(RX) && 1(TX) */
+ pUsartd->pRxChannel->dmaProgress = 0;
+
+ if (XDMAD_StartTransfer(pUsartd->pXdmad, pUsartd->pRxChannel->ChNum))
+ return USARTD_ERROR_LOCK;
+
+ return 0;
+}
+
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/wdt.c b/bsps/arm/atsam/contrib/libraries/libchip/source/wdt.c
new file mode 100644
index 0000000000..e0ced522e2
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/wdt.c
@@ -0,0 +1,133 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/**
+ * \file
+ *
+ * Implementation of Watchdog Timer (WDT) controller.
+ *
+ */
+
+/** \addtogroup wdt_module Working with WDT
+ * \ingroup peripherals_module
+ * The WDT driver provides the interface to configure and use the WDT
+ * peripheral.
+ *
+ * The WDT can be used to prevent system lock-up if the software becomes
+ * trapped in a deadlock. It can generate a general reset or a processor
+ * reset only. It is clocked by slow clock divided by 128.
+ *
+ * The WDT is running at reset with 16 seconds watchdog period (slow clock at
+ * 32.768 kHz)
+ * and external reset generation enabled. The user must either disable it or
+ * reprogram it to meet the application requires.
+ *
+ * To use the WDT, the user could follow these few steps:
+ * <ul>
+ * <li>Enable watchdog with given mode using \ref WDT_Enable().
+ * <li>Restart the watchdog using \ref WDT_Restart() within the watchdog period.
+ * </ul>
+ *
+ * For more accurate information, please look at the WDT section of the
+ * Datasheet.
+ *
+ * \note
+ * The Watchdog Mode Register (WDT_MR) can be written only once.\n
+ *
+ * Related files :\n
+ * \ref wdt.c\n
+ * \ref wdt.h.\n
+ */
+/*@{*/
+/*@}*/
+
+/*---------------------------------------------------------------------------
+ * Headers
+ *---------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Enable watchdog with given mode.
+ *
+ * \note The Watchdog Mode Register (WDT_MR) can be written only once.
+ * Only a processor reset resets it.
+ *
+ * \param dwMode WDT mode to be set
+ */
+extern void WDT_Enable(Wdt *pWDT, uint32_t dwMode)
+{
+ pWDT->WDT_MR = dwMode;
+}
+
+/**
+ * \brief Disable watchdog.
+ *
+ * \note The Watchdog Mode Register (WDT_MR) can be written only once.
+ * Only a processor reset resets it.
+ */
+extern void WDT_Disable(Wdt *pWDT)
+{
+ pWDT->WDT_MR = WDT_MR_WDDIS;
+}
+
+/**
+ * \brief Watchdog restart.
+ */
+extern void WDT_Restart(Wdt *pWDT)
+{
+ pWDT->WDT_CR = 0xA5000001;
+}
+
+/**
+ * \brief Watchdog get status.
+ */
+extern uint32_t WDT_GetStatus(Wdt *pWDT)
+{
+ return (pWDT->WDT_SR & 0x3);
+}
+
+/**
+ * \brief Watchdog get period.
+ *
+ * \param dwMs desired watchdog period in millisecond.
+ */
+extern uint32_t WDT_GetPeriod(uint32_t dwMs)
+{
+ if ((dwMs < 4) || (dwMs > 16000))
+ return 0;
+
+ return ((dwMs << 8) / 1000);
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/xdma_hardware_interface.c b/bsps/arm/atsam/contrib/libraries/libchip/source/xdma_hardware_interface.c
new file mode 100644
index 0000000000..f1e5b114af
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/xdma_hardware_interface.c
@@ -0,0 +1,158 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup dmad_module
+ *
+ * \section DmaHw Dma Hardware Interface Usage
+ * <ul>
+ * <li> The DMA controller can handle the transfer between peripherals and memory
+ * and so receives the triggers from the peripherals. The hardware interface
+ * number are getting from DMAIF_Get_ChannelNumber().</li>
+
+ * <li> DMAIF_IsValidatedPeripherOnDma() helps to check if the given DMAC has
+ * associated peripheral identifier coded by the given peripheral.</li>
+ *
+ * </ul>
+ */
+/*@{*/
+/*@}*/
+
+/** \file */
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+#include "chip.h"
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ *----------------------------------------------------------------------------*/
+/** Array of DMA Channel definition for SAMv7 chip*/
+static const XdmaHardwareInterface xdmaHwIf[] = {
+ /* xdmac, peripheral, T/R, HW interface number*/
+ {0, ID_HSMCI, 0, 0},
+ {0, ID_HSMCI, 1, 0},
+ {0, ID_SPI0, 0, 1},
+ {0, ID_SPI0, 1, 2},
+ {0, ID_SPI1, 0, 3},
+ {0, ID_SPI1, 1, 4},
+ {0, ID_QSPI, 0, 5},
+ {0, ID_QSPI, 1, 6},
+ {0, ID_USART0, 0, 7},
+ {0, ID_USART0, 1, 8},
+ {0, ID_USART1, 0, 9},
+ {0, ID_USART1, 1, 10},
+ {0, ID_USART2, 0, 11},
+ {0, ID_USART2, 1, 12},
+ {0, ID_PWM0, 0, 13},
+ {0, ID_TWIHS0, 0, 14},
+ {0, ID_TWIHS0, 1, 15},
+ {0, ID_TWIHS1, 0, 16},
+ {0, ID_TWIHS1, 1, 17},
+ {0, ID_TWIHS2, 0, 18},
+ {0, ID_TWIHS2, 1, 19},
+ {0, ID_UART0, 0, 20},
+ {0, ID_UART0, 1, 21},
+ {0, ID_UART1, 0, 22},
+ {0, ID_UART1, 1, 23},
+ {0, ID_UART2, 0, 24},
+ {0, ID_UART2, 1, 25},
+ {0, ID_UART3, 0, 26},
+ {0, ID_UART3, 1, 27},
+ {0, ID_UART4, 0, 28},
+ {0, ID_UART4, 1, 29},
+ {0, ID_DACC, 0, 30},
+ {0, ID_DACC, 0, 31},
+ {0, ID_SSC, 0, 32},
+ {0, ID_SSC, 1, 33},
+ {0, ID_PIOA, 1, 34},
+ {0, ID_AFEC0, 1, 35},
+ {0, ID_AFEC1, 1, 36},
+ {0, ID_AES, 0, 37},
+ {0, ID_AES, 1, 38},
+ {0, ID_PWM1, 0, 39},
+ {0, ID_TC0, 1, 40},
+ {0, ID_TC1, 1, 41},
+ {0, ID_TC2, 1, 42},
+ {0, ID_TC3, 1, 43},
+};
+
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Get peripheral identifier coded for hardware handshaking interface
+ *
+ * \param bDmac DMA Controller number.
+ * \param bPeriphID Peripheral ID.
+ * \param bTransfer Transfer type 0: Tx, 1 :Rx.
+ * \return 0-15 peripheral identifier coded.
+ * 0xff : no associated peripheral identifier coded.
+ */
+uint8_t XDMAIF_Get_ChannelNumber (uint8_t bPeriphID,
+ uint8_t bTransfer)
+{
+ uint8_t i;
+ uint8_t NumOfPeripheral = ((XDMAC_GetType(XDMAC) & 0x00FF0000) >> 16);
+
+ for (i = 0; i <= NumOfPeripheral; i++) {
+ if ((xdmaHwIf[i].bPeriphID == bPeriphID) &&
+ (xdmaHwIf[i].bTransfer == bTransfer))
+ return xdmaHwIf[i].bIfID;
+ }
+
+ return 0xff;
+}
+
+/**
+ * \brief Check if the given DMAC has associated peripheral identifier coded by
+ * the given peripheral.
+ *
+ * \param bDmac DMA Controller number.
+ * \param bPeriphID Peripheral ID (0xff : memory only).
+ * \return 1: Is a validated peripheral. 0: no associated peripheral identifier
+ * coded.
+ */
+uint8_t XDMAIF_IsValidatedPeripherOnDma(uint8_t bPeriphID)
+{
+ uint8_t i;
+ uint8_t NumOfPeripheral = ((XDMAC_GetType(XDMAC) & 0x00FF0000) >> 16);
+
+ /* It is always validated when transfer to memory */
+ if (bPeriphID == 0xFF)
+ return 1;
+
+ for (i = 0; i <= NumOfPeripheral; i++) {
+ if ((xdmaHwIf[i].bPeriphID == bPeriphID))
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/xdmad.c b/bsps/arm/atsam/contrib/libraries/libchip/source/xdmad.c
new file mode 100644
index 0000000000..0be891d2e9
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/xdmad.c
@@ -0,0 +1,495 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: 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 */
+/* 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. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup xdmad_module
+ *
+ * \section Xdma xDma Configuration Usage
+ *
+ * To configure a XDMA channel, the user has to follow these few steps :
+ * <ul>
+ * <li> Initialize a XDMA driver instance by XDMAD_Initialize().</li>
+ * <li> choose an available (disabled) channel using XDMAD_AllocateChannel().</li>
+ * <li> After the XDMAC selected channel has been programmed,
+ * XDMAD_PrepareChannel() is to enable clock and dma peripheral of the DMA, and
+ * set Configuration register to set up the transfer type (memory or non-memory
+ * peripheral for source and destination) and flow control device.</li>
+ * <li> Invoke XDMAD_StartTransfer() to start DMA transfer or
+ * XDMAD_StopTransfer() to force stop DMA transfer.</li>
+ * <li> Once the buffer of data is transferred, XDMAD_IsTransferDone()
+ * checks if DMA transfer is finished.</li>
+ * <li> XDMAD_Handler() handles XDMA interrupt, and invoking XDMAD_SetCallback()
+ * if provided.</li>
+ * </ul>
+ *
+ * Related files:\n
+ * \ref xdmad.h\n
+ * \ref xdmad.c.\n
+ */
+
+/** \file */
+
+/** \addtogroup dmad_functions
+ @{*/
+
+/*----------------------------------------------------------------------------
+ * Includes
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+#ifdef __rtems__
+#include "../../../utils/utility.h"
+#include <rtems/irq-extension.h>
+#include <rtems/sysinit.h>
+#include <bsp/fatal.h>
+#endif /* __rtems__ */
+#include <assert.h>
+
+/*----------------------------------------------------------------------------
+ * Local functions
+ *----------------------------------------------------------------------------*/
+static void XDMAD_Handler(void *arg);
+/**
+ * \brief Try to allocate a DMA channel for on given controller.
+ * \param pDmad Pointer to DMA driver instance.
+ * \param bSrcID Source peripheral ID, 0xFF for memory.
+ * \param bDstID Destination peripheral ID, 0xFF for memory.
+ * \return Channel number if allocation successful, return
+ * DMAD_ALLOC_FAILED if allocation failed.
+ */
+static uint32_t XDMAD_AllocateXdmacChannel(sXdmad *pXdmad,
+ uint8_t bSrcID,
+ uint8_t bDstID)
+{
+ uint32_t i;
+
+ /* Can't support peripheral to peripheral */
+ if (((bSrcID != XDMAD_TRANSFER_MEMORY)
+ && (bDstID != XDMAD_TRANSFER_MEMORY)))
+ return XDMAD_ALLOC_FAILED;
+
+ /* dma transfer from peripheral to memory */
+ if (bDstID == XDMAD_TRANSFER_MEMORY) {
+ if ((!XDMAIF_IsValidatedPeripherOnDma(bSrcID))) {
+ TRACE_ERROR("%s:: Allocation failed", __FUNCTION__);
+ return XDMAD_ALLOC_FAILED;
+ }
+ }
+
+ /* dma transfer from memory to peripheral */
+ if (bSrcID == XDMAD_TRANSFER_MEMORY) {
+ if ((!XDMAIF_IsValidatedPeripherOnDma(bDstID))) {
+ TRACE_ERROR("%s:: Allocation failed", __FUNCTION__);
+ return XDMAD_ALLOC_FAILED;
+ }
+ }
+
+ for (i = 0; i < pXdmad->numChannels; i ++) {
+ if (pXdmad->XdmaChannels[i].state == XDMAD_STATE_FREE) {
+ /* Allocate the channel */
+ pXdmad->XdmaChannels[i].state = XDMAD_STATE_ALLOCATED;
+ /* Get general informations */
+ pXdmad->XdmaChannels[i].bSrcPeriphID = bSrcID;
+ pXdmad->XdmaChannels[i].bDstPeriphID = bDstID;
+ pXdmad->XdmaChannels[i].bSrcTxIfID =
+ XDMAIF_Get_ChannelNumber(bSrcID, 0);
+ pXdmad->XdmaChannels[i].bSrcRxIfID =
+ XDMAIF_Get_ChannelNumber(bSrcID, 1);
+ pXdmad->XdmaChannels[i].bDstTxIfID =
+ XDMAIF_Get_ChannelNumber(bDstID, 0);
+ pXdmad->XdmaChannels[i].bDstRxIfID =
+ XDMAIF_Get_ChannelNumber(bDstID, 1);
+ return ((i) & 0xFF);
+ }
+ }
+
+ TRACE_ERROR("%s:: Allocation failed, all channels are occupied", __FUNCTION__);
+ return XDMAD_ALLOC_FAILED;
+}
+
+void XDMAD_DoNothingCallback(uint32_t Channel, void *pArg)
+{
+ /* Do nothing */
+}
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+
+sXdmad XDMAD_Instance;
+
+static void XDMAD_SysInitialize(void)
+{
+ sXdmad *pXdmad;
+ uint32_t j;
+ rtems_status_code sc;
+
+ pXdmad = &XDMAD_Instance;
+
+ pXdmad->pXdmacs = XDMAC;
+ pXdmad->numControllers = XDMAC_CONTROLLER_NUM;
+ pXdmad->numChannels = (XDMAC_GTYPE_NB_CH(XDMAC_GetType(XDMAC)) + 1);
+
+ for (j = 0; j < pXdmad->numChannels; j ++) {
+ pXdmad->XdmaChannels[j].fCallback = XDMAD_DoNothingCallback;
+ }
+
+ sc = rtems_interrupt_handler_install(
+ ID_XDMAC,
+ "XDMA",
+ RTEMS_INTERRUPT_UNIQUE,
+ XDMAD_Handler,
+ pXdmad
+ );
+ if (sc != RTEMS_SUCCESSFUL) {
+ bsp_fatal(ATSAM_FATAL_XDMA_IRQ_INSTALL);
+ }
+}
+
+RTEMS_SYSINIT_ITEM(XDMAD_SysInitialize, RTEMS_SYSINIT_BSP_START,
+ RTEMS_SYSINIT_ORDER_LAST);
+
+
+/**
+ * \brief Allocate a XDMA channel for upper layer.
+ * \param pXdmad Pointer to xDMA driver instance.
+ * \param bSrcID Source peripheral ID, 0xFF for memory.
+ * \param bDstID Destination peripheral ID, 0xFF for memory.
+ * \return Channel number if allocation successful, return
+ * XDMAD_ALLOC_FAILED if allocation failed.
+ */
+uint32_t XDMAD_AllocateChannel(sXdmad *pXdmad,
+ uint8_t bSrcID,
+ uint8_t bDstID)
+{
+ uint32_t dwChannel = XDMAD_ALLOC_FAILED;
+ uint32_t volatile timer = 0x7FF;
+
+ LockMutex(pXdmad->xdmaMutex, timer);
+ dwChannel = XDMAD_AllocateXdmacChannel(pXdmad, bSrcID, bDstID);
+ ReleaseMutex(pXdmad->xdmaMutex);
+
+ return dwChannel;
+}
+
+/**
+ * \brief Free the specified xDMA channel.
+ * \param pXdmad Pointer to xDMA driver instance.
+ * \param dwChannel ControllerNumber << 8 | ChannelNumber.
+ */
+eXdmadRC XDMAD_FreeChannel(sXdmad *pXdmad,
+ uint32_t dwChannel)
+{
+ uint8_t iChannel = (dwChannel) & 0xFF;
+ assert(pXdmad != NULL);
+
+ if (iChannel >= pXdmad->numChannels) return XDMAD_ERROR;
+
+ switch (pXdmad->XdmaChannels[iChannel].state) {
+ case XDMAD_STATE_ALLOCATED:
+ case XDMAD_STATE_START:
+ case XDMAD_STATE_IN_XFR:
+ return XDMAD_BUSY;
+
+ case XDMAD_STATE_DONE:
+ case XDMAD_STATE_HALTED:
+ pXdmad->XdmaChannels[iChannel].state = XDMAD_STATE_FREE;
+ break;
+ }
+
+ return XDMAD_OK;
+}
+
+/**
+ * \brief Set the callback function for xDMA channel transfer.
+ * \param pXdmad Pointer to xDMA driver instance.
+ * \param dwChannel ControllerNumber << 8 | ChannelNumber.
+ * \param fCallback Pointer to callback function.
+ * \param pArg Pointer to optional argument for callback.
+ */
+eXdmadRC XDMAD_SetCallback(sXdmad *pXdmad,
+ uint32_t dwChannel,
+ XdmadTransferCallback fCallback,
+ void *pArg)
+{
+
+ uint8_t iChannel = (dwChannel) & 0xFF;
+ assert(pXdmad != NULL);
+
+ if (iChannel >= pXdmad->numChannels) return XDMAD_ERROR;
+
+ if (pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_FREE)
+ return XDMAD_ERROR;
+ else if (pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_START)
+ return XDMAD_BUSY;
+
+ pXdmad->XdmaChannels[iChannel].fCallback = fCallback;
+ pXdmad->XdmaChannels[iChannel].pArg = pArg;
+
+ return XDMAD_OK;
+}
+
+
+/**
+ * \brief Enable clock of the xDMA peripheral, Enable the dma peripheral,
+ * configure configuration register for xDMA transfer.
+ * \param pXdmad Pointer to xDMA driver instance.
+ * \param dwChannel ControllerNumber << 8 | ChannelNumber.
+ * \param dwCfg Configuration value.
+ */
+eXdmadRC XDMAD_PrepareChannel(sXdmad *pXdmad, uint32_t dwChannel)
+{
+
+ uint8_t iChannel = (dwChannel) & 0xFF;
+ Xdmac *pXdmac = pXdmad->pXdmacs;
+
+ assert(pXdmad != NULL);
+
+ if (iChannel >= pXdmad->numChannels) return XDMAD_ERROR;
+
+ if (pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_FREE)
+ return XDMAD_ERROR;
+ else if ((pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_START)
+ || (pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_IN_XFR))
+ return XDMAD_BUSY;
+
+
+ /* Enable clock of the DMA peripheral */
+ if (!PMC_IsPeriphEnabled(ID_XDMAC))
+ PMC_EnablePeripheral(ID_XDMAC);
+
+ /* Clear dummy status */
+ XDMAC_GetChannelIsr(pXdmac, iChannel);
+ /* Disables XDMAC interrupt for the given channel. */
+ XDMAC_DisableGIt (pXdmac, iChannel);
+ XDMAC_DisableChannelIt (pXdmac, iChannel, 0xFF);
+ /* Disable the given dma channel. */
+ XDMAC_DisableChannel(pXdmac, iChannel);
+ XDMAC_SetSourceAddr(pXdmac, iChannel, 0);
+ XDMAC_SetDestinationAddr(pXdmac, iChannel, 0);
+ XDMAC_SetBlockControl(pXdmac, iChannel, 0);
+ XDMAC_SetChannelConfig(pXdmac, iChannel, 0x20);
+ XDMAC_SetDescriptorAddr(pXdmac, iChannel, 0, 0);
+ XDMAC_SetDescriptorControl(pXdmac, iChannel, 0);
+ return XDMAD_OK;
+}
+
+/**
+ * \brief xDMA interrupt handler
+ * \param arg Pointer to DMA driver instance.
+ */
+static void XDMAD_Handler(void *arg)
+{
+ sXdmad *pDmad;
+ Xdmac *pXdmac;
+ sXdmadChannel *pCh;
+ uint32_t xdmaChannelIntStatus, xdmaGlobaIntStatus, xdmaGlobalChStatus;
+ uint8_t bExec;
+ uint8_t _iChannel;
+
+ pDmad = arg;
+ pXdmac = pDmad->pXdmacs;
+ xdmaGlobaIntStatus = XDMAC_GetGIsr(pXdmac) & 0xFFFFFF;
+ xdmaGlobalChStatus = XDMAC_GetGlobalChStatus(pXdmac);
+
+ while (xdmaGlobaIntStatus != 0) {
+ _iChannel = 31 - __builtin_clz(xdmaGlobaIntStatus);
+ xdmaGlobaIntStatus &= ~(UINT32_C(1) << _iChannel);
+
+ pCh = &pDmad->XdmaChannels[_iChannel];
+ bExec = 0;
+
+ if ((xdmaGlobalChStatus & (XDMAC_GS_ST0 << _iChannel)) == 0) {
+ xdmaChannelIntStatus = XDMAC_GetMaskChannelIsr(pXdmac, _iChannel);
+
+ if (xdmaChannelIntStatus & XDMAC_CIS_BIS) {
+ if ((XDMAC_GetChannelItMask(pXdmac, _iChannel) & XDMAC_CIM_LIM) == 0) {
+ pCh->state = XDMAD_STATE_DONE;
+ bExec = 1;
+ }
+
+ TRACE_DEBUG("XDMAC_CIS_BIS\n\r");
+ }
+
+ if (xdmaChannelIntStatus & XDMAC_CIS_FIS)
+ TRACE_DEBUG("XDMAC_CIS_FIS\n\r");
+
+ if (xdmaChannelIntStatus & XDMAC_CIS_RBEIS)
+ TRACE_DEBUG("XDMAC_CIS_RBEIS\n\r");
+
+ if (xdmaChannelIntStatus & XDMAC_CIS_WBEIS)
+ TRACE_DEBUG("XDMAC_CIS_WBEIS\n\r");
+
+ if (xdmaChannelIntStatus & XDMAC_CIS_ROIS)
+ TRACE_DEBUG("XDMAC_CIS_ROIS\n\r");
+
+ if (xdmaChannelIntStatus & XDMAC_CIS_LIS) {
+ TRACE_DEBUG("XDMAC_CIS_LIS\n\r");
+ pCh->state = XDMAD_STATE_DONE;
+ bExec = 1;
+ }
+
+ if (xdmaChannelIntStatus & XDMAC_CIS_DIS) {
+ pCh->state = XDMAD_STATE_DONE;
+ bExec = 1;
+ }
+
+ } else {
+ /* Block end interrupt for LLI dma mode */
+ if (XDMAC_GetChannelIsr(pXdmac, _iChannel) & XDMAC_CIS_BIS) {
+ bExec = 1;
+ }
+ }
+
+ /* Execute callback */
+ if (bExec)
+ pCh->fCallback(_iChannel, pCh->pArg);
+ }
+}
+
+
+/**
+ * \brief Configure DMA for a single transfer.
+ * \param pXdmad Pointer to xDMA driver instance.
+ * \param dwChannel ControllerNumber << 8 | ChannelNumber.
+ */
+eXdmadRC XDMAD_ConfigureTransfer(sXdmad *pXdmad,
+ uint32_t dwChannel,
+ sXdmadCfg *pXdmaParam,
+ uint32_t dwXdmaDescCfg,
+ uint32_t dwXdmaDescAddr,
+ uint32_t dwXdmaIntEn)
+{
+ uint8_t iChannel = (dwChannel) & 0xFF;
+
+ assert(pXdmad != NULL);
+
+ if (iChannel >= pXdmad->numChannels)
+ return XDMAD_ERROR;
+
+ Xdmac *pXdmac = pXdmad->pXdmacs;
+ XDMAC_GetChannelIsr(pXdmac, iChannel);
+
+ if (pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_FREE)
+ return XDMAD_ERROR;
+
+ if (pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_START)
+ return XDMAD_BUSY;
+
+ /* Linked List is enabled */
+ if ((dwXdmaDescCfg & XDMAC_CNDC_NDE) == XDMAC_CNDC_NDE_DSCR_FETCH_EN) {
+ if ((dwXdmaDescCfg & XDMAC_CNDC_NDVIEW_Msk) == XDMAC_CNDC_NDVIEW_NDV0) {
+ XDMAC_SetChannelConfig(pXdmac, iChannel, pXdmaParam->mbr_cfg);
+ XDMAC_SetSourceAddr(pXdmac, iChannel, pXdmaParam->mbr_sa);
+ XDMAC_SetDestinationAddr(pXdmac, iChannel, pXdmaParam->mbr_da);
+ }
+
+ if ((dwXdmaDescCfg & XDMAC_CNDC_NDVIEW_Msk) == XDMAC_CNDC_NDVIEW_NDV1)
+ XDMAC_SetChannelConfig(pXdmac, iChannel, pXdmaParam->mbr_cfg);
+
+ XDMAC_SetDescriptorAddr(pXdmac, iChannel, dwXdmaDescAddr, 0);
+ XDMAC_SetDescriptorControl(pXdmac, iChannel, dwXdmaDescCfg);
+ XDMAC_DisableChannelIt (pXdmac, iChannel, 0xFF);
+ XDMAC_EnableChannelIt (pXdmac, iChannel, dwXdmaIntEn);
+ } else {
+ /* LLI is disabled. */
+ XDMAC_SetSourceAddr(pXdmac, iChannel, pXdmaParam->mbr_sa);
+ XDMAC_SetDestinationAddr(pXdmac, iChannel, pXdmaParam->mbr_da);
+ XDMAC_SetMicroblockControl(pXdmac, iChannel, pXdmaParam->mbr_ubc);
+ XDMAC_SetBlockControl(pXdmac, iChannel, pXdmaParam->mbr_bc);
+ XDMAC_SetDataStride_MemPattern(pXdmac, iChannel, pXdmaParam->mbr_ds);
+ XDMAC_SetSourceMicroBlockStride(pXdmac, iChannel, pXdmaParam->mbr_sus);
+ XDMAC_SetDestinationMicroBlockStride(pXdmac, iChannel, pXdmaParam->mbr_dus);
+ XDMAC_SetChannelConfig(pXdmac, iChannel, pXdmaParam->mbr_cfg);
+ XDMAC_SetDescriptorAddr(pXdmac, iChannel, 0, 0);
+ XDMAC_SetDescriptorControl(pXdmac, iChannel, 0);
+ XDMAC_EnableChannelIt (pXdmac, iChannel, dwXdmaIntEn);
+ }
+
+ return XDMAD_OK;
+}
+
+/**
+ * \brief Start xDMA transfer.
+ * \param pXdmad Pointer to XDMA driver instance.
+ * \param dwChannel ControllerNumber << 8 | ChannelNumber.
+ */
+eXdmadRC XDMAD_StartTransfer(sXdmad *pXdmad, uint32_t dwChannel)
+{
+ uint8_t iChannel = (dwChannel) & 0xFF;
+
+ assert(pXdmad != NULL);
+
+ if (iChannel >= pXdmad->numChannels) return XDMAD_ERROR;
+
+ Xdmac *pXdmac = pXdmad->pXdmacs;
+
+ if (pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_FREE) {
+ TRACE_ERROR("%s:: XDMAD_STATE_FREE \n\r", __FUNCTION__);
+ return XDMAD_ERROR;
+ } else if (pXdmad->XdmaChannels[iChannel].state == XDMAD_STATE_START) {
+ TRACE_ERROR("%s:: XDMAD_STATE_START \n\r", __FUNCTION__)
+ return XDMAD_BUSY;
+ }
+
+ /* Change state to transferring */
+ pXdmad->XdmaChannels[iChannel].state = XDMAD_STATE_START;
+ XDMAC_EnableChannel(pXdmac, iChannel);
+ XDMAC_EnableGIt(pXdmac, iChannel);
+
+ return XDMAD_OK;
+}
+
+
+/**
+ * \brief Stop DMA transfer.
+ * \param pDmad Pointer to DMA driver instance.
+ * \param dwChannel ControllerNumber << 8 | ChannelNumber.
+ */
+eXdmadRC XDMAD_StopTransfer(sXdmad *pXdmad, uint32_t dwChannel)
+{
+ uint8_t _iChannel = (dwChannel) & 0xFF;
+ assert(pXdmad != NULL);
+
+ if (_iChannel >= pXdmad->numChannels) return XDMAD_ERROR;
+
+ Xdmac *pXdmac = pXdmad->pXdmacs;
+
+ pXdmad->XdmaChannels[_iChannel].state = XDMAD_STATE_HALTED;
+ /* Disable channel */
+ XDMAC_DisableChannel(pXdmac, _iChannel);
+ /* Disable interrupts */
+ XDMAC_DisableChannelIt(pXdmac, _iChannel, 0xFF);
+ /* Clear pending status */
+ XDMAC_GetChannelIsr(pXdmac, _iChannel);
+ XDMAC_GetGlobalChStatus(pXdmac);
+ return XDMAD_OK;
+}
+
+/**@}*/
+
diff --git a/bsps/arm/atsam/contrib/utils/utility.h b/bsps/arm/atsam/contrib/utils/utility.h
new file mode 100644
index 0000000000..e695376ad3
--- /dev/null
+++ b/bsps/arm/atsam/contrib/utils/utility.h
@@ -0,0 +1,111 @@
+/* ----------------------------------------------------------------------------
+ * SAM Software Package License
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2014, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: 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
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#ifndef UTILITY_H
+#define UTILITY_H
+
+#include "chip.h"
+
+
+
+#define RESET_CYCLE_COUNTER() do { \
+ CoreDebug->DEMCR = CoreDebug_DEMCR_TRCENA_Msk; \
+ __DSB(); DWT->LAR = 0xC5ACCE55; __DSB(); \
+ DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk; \
+ DWT->CYCCNT = 0; \
+ DWT->CTRL = DWT_CTRL_CYCCNTENA_Msk; \
+ }while(0)
+
+#define GET_CYCLE_COUNTER(x) x=DWT->CYCCNT;
+
+#define LockMutex(mut, timeout) get_lock(&mut, 1, &timeout)
+
+#define ReleaseMutex(mut) free_lock(&mut)
+
+#define GetResource(mut, max, timeout) get_lock(&mut, max, &timeout)
+
+#define FreeResource(mut) free_lock(&mut)
+
+
+__STATIC_INLINE uint8_t Is_LockFree(volatile uint8_t *Lock_Variable)
+{
+ /* return Variable value*/
+ return __LDREXB(Lock_Variable);
+
+}
+
+__STATIC_INLINE uint8_t get_lock(volatile uint8_t *Lock_Variable, const uint8_t maxValue, volatile uint32_t *pTimeout)
+{
+ while (*pTimeout)
+ {
+ if(__LDREXB(Lock_Variable) < maxValue)
+ {
+ /* Set the Variable */
+ while( __STREXB(((*Lock_Variable) + 1), Lock_Variable) )
+ {
+ if(!(*pTimeout)--)
+ {
+ return 1; // quit if timeout
+ }
+ }
+ /* Memory access barrier */
+ __DMB();
+ TRACE_DEBUG("Mutex locked ");
+ return 0;
+ }
+
+ ((*pTimeout)--);
+ }
+ return 1;
+}
+
+
+
+__STATIC_INLINE uint8_t free_lock(volatile uint8_t *Lock_Variable)
+{
+ /* Memory access barrier Ensure memory operations completed before releasing lock */
+ __DSB();
+ if(__LDREXB(Lock_Variable))
+ {
+ __STREXB( ((*Lock_Variable) - 1), Lock_Variable);
+ TRACE_DEBUG("Mutex freed ");
+ __DSB();
+ __DMB(); // Ensure memory operations completed before
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+
+
+}
+
+
+#endif /* UTILITY_H */
diff --git a/bsps/arm/atsam/start/iocopy.c b/bsps/arm/atsam/start/iocopy.c
new file mode 100644
index 0000000000..b91282dac6
--- /dev/null
+++ b/bsps/arm/atsam/start/iocopy.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp/iocopy.h>
+
+static void atsam_do_copy(
+ uint8_t *dst,
+ const uint8_t *src,
+ size_t n,
+ bool aligned
+)
+{
+ if (aligned) {
+ while (n > 3) {
+ *(uint32_t *)dst = *(uint32_t *)src;
+ dst += 4;
+ src += 4;
+ n -= 4;
+ }
+ }
+
+ while (n > 0) {
+ *dst = *src;
+ ++dst;
+ ++src;
+ --n;
+ }
+}
+
+void atsam_copy_to_io(void *dst, const void *src, size_t n)
+{
+ atsam_do_copy(dst, src, n, ((uintptr_t)dst) % 4 == 0);
+}
+
+void atsam_copy_from_io(void *dst, const void *src, size_t n)
+{
+ atsam_do_copy(dst, src, n, ((uintptr_t)src) % 4 == 0);
+}