From 54aabb70eb9ad64d3bcb9f95968de6a4473ebe3b Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Sun, 22 Apr 2018 15:11:43 +0200 Subject: bsp/atsam: Move libraries to bsps This patch is a part of the BSP source reorganization. Update #3285. --- bsps/arm/atsam/contrib/libraries/libboard/board.h | 45 + .../contrib/libraries/libboard/board_v71_xult.h | 778 +++++++++++++ .../atsam/contrib/libraries/libboard/include/bmp.h | 119 ++ .../libraries/libboard/include/board_lowlevel.h | 47 + .../libraries/libboard/include/board_memories.h | 52 + .../contrib/libraries/libboard/include/cs2100.h | 93 ++ .../libraries/libboard/include/dbg_console.h | 55 + .../libraries/libboard/include/frame_buffer.h | 83 ++ .../contrib/libraries/libboard/include/gmacb_phy.h | 114 ++ .../contrib/libraries/libboard/include/gmii.h | 116 ++ .../contrib/libraries/libboard/include/ili9488.h | 106 ++ .../libraries/libboard/include/ili9488_dma.h | 92 ++ .../libraries/libboard/include/ili9488_ebi.h | 63 ++ .../libraries/libboard/include/ili9488_ebi_dma.h | 55 + .../libraries/libboard/include/ili9488_reg.h | 131 +++ .../libraries/libboard/include/ili9488_spi.h | 69 ++ .../libraries/libboard/include/ili9488_spi_dma.h | 56 + .../libraries/libboard/include/image_sensor_inf.h | 136 +++ .../contrib/libraries/libboard/include/lcd_color.h | 109 ++ .../contrib/libraries/libboard/include/lcd_draw.h | 186 ++++ .../contrib/libraries/libboard/include/lcd_font.h | 108 ++ .../libraries/libboard/include/lcd_font10x14.h | 45 + .../libraries/libboard/include/lcd_gimp_image.h | 42 + .../contrib/libraries/libboard/include/lcdd.h | 52 + .../atsam/contrib/libraries/libboard/include/led.h | 72 ++ .../contrib/libraries/libboard/include/math.h | 42 + .../libraries/libboard/include/mcan_config.h | 126 +++ .../contrib/libraries/libboard/include/rtc_calib.h | 49 + .../contrib/libraries/libboard/include/s25fl1.h | 255 +++++ .../contrib/libraries/libboard/include/wm8904.h | 160 +++ .../libboard/resources_v71/system_samv71.c | 318 ++++++ .../libraries/libboard/source/board_lowlevel.c | 434 ++++++++ .../libraries/libboard/source/board_memories.c | 293 +++++ .../libraries/libboard/source/dbg_console.c | 564 ++++++++++ .../atsam/contrib/libraries/libchip/source/acc.c | 159 +++ .../atsam/contrib/libraries/libchip/source/aes.c | 286 +++++ .../contrib/libraries/libchip/source/afe_dma.c | 256 +++++ .../atsam/contrib/libraries/libchip/source/afec.c | 458 ++++++++ .../contrib/libraries/libchip/source/dac_dma.c | 238 ++++ .../atsam/contrib/libraries/libchip/source/efc.c | 280 +++++ .../contrib/libraries/libchip/source/exceptions.c | 214 ++++ .../contrib/libraries/libchip/source/flashd.c | 595 ++++++++++ .../atsam/contrib/libraries/libchip/source/gmac.c | 685 ++++++++++++ .../atsam/contrib/libraries/libchip/source/gmacd.c | 1054 ++++++++++++++++++ .../atsam/contrib/libraries/libchip/source/hsmci.c | 569 ++++++++++ .../atsam/contrib/libraries/libchip/source/icm.c | 234 ++++ .../atsam/contrib/libraries/libchip/source/isi.c | 385 +++++++ .../atsam/contrib/libraries/libchip/source/mcan.c | 1175 ++++++++++++++++++++ .../contrib/libraries/libchip/source/mediaLB.c | 58 + .../atsam/contrib/libraries/libchip/source/mpu.c | 168 +++ .../atsam/contrib/libraries/libchip/source/pio.c | 499 +++++++++ .../contrib/libraries/libchip/source/pio_capture.c | 255 +++++ .../contrib/libraries/libchip/source/pio_it.c | 283 +++++ .../atsam/contrib/libraries/libchip/source/pmc.c | 597 ++++++++++ .../atsam/contrib/libraries/libchip/source/pwmc.c | 579 ++++++++++ .../atsam/contrib/libraries/libchip/source/qspi.c | 757 +++++++++++++ .../contrib/libraries/libchip/source/qspi_dma.c | 619 +++++++++++ .../atsam/contrib/libraries/libchip/source/rstc.c | 167 +++ .../atsam/contrib/libraries/libchip/source/rtc.c | 452 ++++++++ .../atsam/contrib/libraries/libchip/source/rtt.c | 134 +++ .../contrib/libraries/libchip/source/sdramc.c | 212 ++++ .../atsam/contrib/libraries/libchip/source/spi.c | 282 +++++ .../contrib/libraries/libchip/source/spi_dma.c | 392 +++++++ .../atsam/contrib/libraries/libchip/source/ssc.c | 219 ++++ .../atsam/contrib/libraries/libchip/source/supc.c | 193 ++++ .../atsam/contrib/libraries/libchip/source/tc.c | 213 ++++ .../atsam/contrib/libraries/libchip/source/trng.c | 122 ++ .../atsam/contrib/libraries/libchip/source/twi.c | 382 +++++++ .../atsam/contrib/libraries/libchip/source/twid.c | 752 +++++++++++++ .../atsam/contrib/libraries/libchip/source/uart.c | 232 ++++ .../contrib/libraries/libchip/source/uart_dma.c | 616 ++++++++++ .../atsam/contrib/libraries/libchip/source/usart.c | 466 ++++++++ .../contrib/libraries/libchip/source/usart_dma.c | 600 ++++++++++ .../atsam/contrib/libraries/libchip/source/wdt.c | 133 +++ .../libchip/source/xdma_hardware_interface.c | 158 +++ .../atsam/contrib/libraries/libchip/source/xdmad.c | 495 +++++++++ bsps/arm/atsam/contrib/utils/utility.h | 111 ++ bsps/arm/atsam/start/iocopy.c | 49 + 78 files changed, 21848 insertions(+) create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/board.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/board_v71_xult.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/bmp.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/board_lowlevel.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/board_memories.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/cs2100.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/dbg_console.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/frame_buffer.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/gmacb_phy.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/gmii.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/ili9488.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_dma.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_ebi.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_ebi_dma.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_reg.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_spi.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/ili9488_spi_dma.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/image_sensor_inf.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/lcd_color.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/lcd_draw.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/lcd_font.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/lcd_font10x14.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/lcd_gimp_image.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/lcdd.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/led.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/math.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/mcan_config.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/rtc_calib.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/s25fl1.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/include/wm8904.h create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/resources_v71/system_samv71.c create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/source/board_lowlevel.c create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/source/board_memories.c create mode 100644 bsps/arm/atsam/contrib/libraries/libboard/source/dbg_console.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/acc.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/aes.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/afe_dma.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/afec.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/dac_dma.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/efc.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/exceptions.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/flashd.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/gmac.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/gmacd.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/hsmci.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/icm.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/isi.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/mcan.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/mediaLB.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/mpu.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/pio.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/pio_capture.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/pio_it.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/pmc.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/pwmc.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/qspi.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/qspi_dma.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/rstc.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/rtc.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/rtt.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/sdramc.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/spi.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/spi_dma.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/ssc.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/supc.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/tc.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/trng.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/twi.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/twid.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/uart.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/uart_dma.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/usart.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/usart_dma.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/wdt.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/xdma_hardware_interface.c create mode 100644 bsps/arm/atsam/contrib/libraries/libchip/source/xdmad.c create mode 100644 bsps/arm/atsam/contrib/utils/utility.h create mode 100644 bsps/arm/atsam/start/iocopy.c (limited to 'bsps') 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 +#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 +#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 + +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 + + +/*---------------------------------------------------------------------------- + * 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 + +/*------------------------------------------------------------------------------ + * 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 + +/*---------------------------------------------------------------------------- + * 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 + +/*---------------------------------------------------------------------------- + * 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 + +/*---------------------------------------------------------------------------- + * 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 +#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 + +/*---------------------------------------------------------------------------- + * 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 + +/** 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 + +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 + +/*---------------------------------------------------------------------------- + * 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 +#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 +#include +#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 +#include +#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 +#include +#endif /* __rtems__ */ + +#include +#include + +/*---------------------------------------------------------------------------- + * 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: + *
    + *
  • Enable ACC peripheral clock by setting the corresponding bit in + * PMC_PCER1 (PMC Peripheral Clock Enable Register 1) + *
  • + *
  • Reset the controller by asserting ACC_CR_SWRST in ACC_CR(ACC Control + * Register)
  • + *
  • Configure the mode as following steps:
  • + * -# 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. + * + *
  • Wait until the automatic mask period expires by polling MASK bit in + * ACC_ISR. + *
+ * + * 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: + *
    + *
  • A software triggered hardware reset of the AES interface is performed + * by AES_SoftReset().
  • + *
  • Configure AES algorithm mode, key mode, start mode and operation mode by + * AES_Configure().
  • + *
  • Input AES data for encryption and decryption with function + * AES_SetInput()
  • + *
  • Set AES key with function AES_WriteKey().
  • + *
  • To start the encryption or the decryption process with AES_Start()
  • + *
  • To get the encryption or decryption result by AES_GetOutput()
  • + *
+ * + * + * 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 +#include + +/* 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: + *
    + *
  • Select an appropriate reference voltage on ADVREF
  • + *
  • 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. +
  • + *
  • Start conversion by setting AFEC_CR_START in AFEC_CR.
  • + *
+ * + * 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: + *
    + *
  • Select an appropriate reference voltage on ADVREF
  • + *
  • 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 . +
  • + *
+ * + * 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 +#include + +/* 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: + *
    + *
  • Write a correct key, command and argument in EEFC_FCR.
  • + *
  • 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.
  • + *
  • Once the command is achieved, it can be detected even by polling + * EEFC_FSR or interrupt. + *
+ * + * 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 + + +/*---------------------------------------------------------------------------- + * 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 : + *
    + *
  • Configure flash wait states to initializes the flash.
  • + *
  • Checks whether a region to be programmed is locked.
  • + *
  • Unlocks the user region to be programmed if the region have locked + * before.
  • + *
  • Erases the user page before program (optional).
  • + *
  • Writes the user page from the page buffer.
  • + *
  • Locks the region of programmed area if any.
  • + *
+ * + * 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 +#include + +/*---------------------------------------------------------------------------- + * 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 +#include +#include + + + +/*---------------------------------------------------------------------------- + * 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 + +/** \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 + +/*--------------------------------------------------------------------------- + * 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 + *
    + *
  • Configures a TWI peripheral to operate in master mode, at the given + * frequency (in Hz) using TWI_Configure().
  • + *
  • Sends a STOP condition on the TWI using TWI_Stop().
  • + *
  • 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()).
  • + *
  • 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.
  • + *
  • 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.
  • + *
  • 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().
  • + *
  • Check if the current transmission is complete (the STOP has been sent) + * using TWI_TransferComplete().
  • + *
  • Enables & disable the selected interrupts sources on a TWI peripheral + * using TWI_EnableIt() and TWI_DisableIt().
  • + *
  • 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().
  • + *
+ * 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 +/*--------------------------------------------------------------------------- + * 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 + +/*---------------------------------------------------------------------------- + * 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 + +/*---------------------------------------------------------------------------- + * 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: + *
    + *
  • Enable PIOA peripheral clock
  • + *
  • Configure the PDC
  • + *
  • Configure the PIO Capture interrupt
  • + *
  • Enable the PDC
  • + *
  • Enable the PIO Capture
  • + *
  • Wait for interrupt
  • + *
  • Disable the interrupt
  • + *
  • Read the DATA
  • + *
+ * + * For more accurate information, please look at the PIO Parallel Capture Mode + * section of the Datasheet. + * + * API Usage: + * + * -# 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 + +#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 +#include +#include + +/*---------------------------------------------------------------------------- + * 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 + *
    + *
  • Enables/Disable the clock of a peripheral by using + * PMC_EnablePeripheral() and PMC_DisablePeripheral().
  • + *
  • Enables/Disable the clock of all peripherals by using + * PMC_EnableAllPeripherals() and PMC_DisableAllPeripherals().
  • + *
  • Get status of a peripheral using PMC_IsPeriphEnabled().
  • + *
  • 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().
  • + * + *
+ * 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 + +/*---------------------------------------------------------------------------- + * 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: + *
    + *
  • Configuration of the clock generator.
  • + *
  • Selection of the clock for each channel.
  • + *
  • Configuration of output waveform characteristics, such as period, + * duty-cycle etc.
  • + *
  • Configuration for synchronous channels if needed.
  • + * - 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). + *
+ * + * 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 +#include + +/*---------------------------------------------------------------------------- + * 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 +#include + + +#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 + + +/*--------------------------------------------------------------------------- + * 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 : + *
    + *
  • Set UPDTIM and/or UPDCAL bit(s) in RTC_CR,
  • + *
  • Polling or IRQ on the ACKUPD bit of RTC_CR,
  • + *
  • Clear ACKUPD bit in RTC_SCCR,
  • + *
  • Update Time and/or Calendar values in RTC_TIMR/RTC_CALR (BCD format),
  • + *
  • Clear UPDTIM and/or UPDCAL bit in RTC_CR.
  • + *
+ * 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 +#include + +/*---------------------------------------------------------------------------- + * 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: + *
    + *
  • Programming PTPRES in RTT_MR to feeding the timer with a 1Hz signal.
  • + *
  • Writing the bit RTTRST in RTT_MR to restart the timer with new settings. + *
  • + *
+ * + * 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 + +/*---------------------------------------------------------------------------- + * 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 + *
    + *
  • Configure SDRAM using SDRAMC_Configure().
  • + + *
+ * 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 + +/*---------------------------------------------------------------------------- + * 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 + * + *
    + *
  • SPID_Configure() initializes and configures the SPI peripheral and xDMA + * for data transfer.
  • + *
  • Configures the parameters for the device corresponding to the cs value + * by SPID_ConfigureCS().
  • + *
  • Starts a SPI master transfer. This is a non blocking function + * SPID_SendCommand(). It will + * return as soon as the transfer is started..
  • + *
+ * + */ + +/** + * \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 + +/*---------------------------------------------------------------------------- + * 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 + *
    + *
  • 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().
  • + * + *
+ * 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 +#endif /* __rtems__ */ + +#include + +/*------------------------------------------------------------------------------ + * 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 + *
    + *
  • Configures a TWI peripheral to operate in master mode, at the given + * frequency (in Hz) using TWI_Configure().
  • + *
  • Sends a STOP condition on the TWI using TWI_Stop().
  • + *
  • 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()).
  • + *
  • 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.
  • + *
  • 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.
  • + *
  • 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().
  • + *
  • Check if the current transmission is complete (the STOP has been sent) + * using TWI_TransferComplete().
  • + *
  • Enables & disable the selected interrupts sources on a TWI peripheral + * using TWI_EnableIt() and TWI_DisableIt().
  • + *
  • 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().
  • + *
+ * 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 + +#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 + +/*---------------------------------------------------------------------------- + * 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 +#include + +/*------------------------------------------------------------------------------ + * 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 + * + *
    + *
  • UARTD_Configure() initializes and configures the UART peripheral and + * xDMA for data transfer.
  • + *
  • Configures the parameters for the device corresponding to the cs value + * by UARTD_ConfigureCS().
  • + *
  • Starts a UART master transfer. This is a non blocking function + * UARTD_SendData(). It will + * return as soon as the transfer is started..
  • + *
+ * + */ + +/** + * \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 +#include + +/*---------------------------------------------------------------------------- + * 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 +* +*
    +*
  • USARTD_Configure() initializes and configures the USART peripheral +* and xDMA for data transfer.
  • +*
  • Configures the parameters for the device corresponding to the cs +* value by USARTD_ConfigureCS().
  • +*
+* +*/ + +/** + * \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: + *
    + *
  • Enable watchdog with given mode using \ref WDT_Enable(). + *
  • Restart the watchdog using \ref WDT_Restart() within the watchdog period. + *
+ * + * 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 + +/*---------------------------------------------------------------------------- + * 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 + *
    + *
  • 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().
  • + + *
  • DMAIF_IsValidatedPeripherOnDma() helps to check if the given DMAC has + * associated peripheral identifier coded by the given peripheral.
  • + * + *
+ */ +/*@{*/ +/*@}*/ + +/** \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 : + *
    + *
  • Initialize a XDMA driver instance by XDMAD_Initialize().
  • + *
  • choose an available (disabled) channel using XDMAD_AllocateChannel().
  • + *
  • 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.
  • + *
  • Invoke XDMAD_StartTransfer() to start DMA transfer or + * XDMAD_StopTransfer() to force stop DMA transfer.
  • + *
  • Once the buffer of data is transferred, XDMAD_IsTransferDone() + * checks if DMA transfer is finished.
  • + *
  • XDMAD_Handler() handles XDMA interrupt, and invoking XDMAD_SetCallback() + * if provided.
  • + *
+ * + * 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 +#include +#include +#endif /* __rtems__ */ +#include + +/*---------------------------------------------------------------------------- + * 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 + * + * + * 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 + +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); +} -- cgit v1.2.3