Hoernchen has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-asf4-dfu/+/39434?usp=email )
Change subject: bl updater app ......................................................................
bl updater app
This builds a second binary that will be flashed like the main firmware and will then update the bootloader, just like the st2. It additionaly aligns the cmsis + config with the main app, and ensures the hw is mostly completely initalized before the main app starts, which allows skipping the init in the main fw.
Main changes: * bl freq 12/48Mhz -> 120Mhz * ext 32khz disabled * "proper" init time for xosc * no usb init unless DFU mode is actually used * errata 2.13.1 clock init/lock fixups * no guessing according to f++&%! bootprog flags where the main app is
Change-Id: I1403d35497cdea41ea5bed2c94b9e729ca352772 --- A CMSIS/Include/cmsis_version.h M atmel_start.c M atmel_start_pins.h M config/hpl_cmcc_config.h M config/hpl_gclk_config.h M config/hpl_osc32kctrl_config.h M config/hpl_oscctrl_config.h A config/hpl_rtc_config.h A config/hpl_sercom_config.h M config/peripheral_clk_config.h M gcc/Makefile M gcc/system_same54.c M hpl/core/hpl_core_m4.c M hpl/oscctrl/hpl_oscctrl.c A hpl/sercom/hpl_sercom.c A usb_dfu_main.c M usb_flash_main.c M usb_start.c 18 files changed, 6,118 insertions(+), 196 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-asf4-dfu refs/changes/34/39434/1
diff --git a/CMSIS/Include/cmsis_version.h b/CMSIS/Include/cmsis_version.h new file mode 100644 index 0000000..ae3f2e3 --- /dev/null +++ b/CMSIS/Include/cmsis_version.h @@ -0,0 +1,39 @@ +/**************************************************************************//** + * @file cmsis_version.h + * @brief CMSIS Core(M) Version definitions + * @version V5.0.2 + * @date 19. April 2017 + ******************************************************************************/ +/* + * Copyright (c) 2009-2017 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CMSIS_VERSION_H +#define __CMSIS_VERSION_H + +/* CMSIS Version definitions */ +#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ +#define __CM_CMSIS_VERSION_SUB ( 1U) /*!< [15:0] CMSIS Core(M) sub version */ +#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ + __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ +#endif diff --git a/atmel_start.c b/atmel_start.c index 9a5f36c..b788d5a 100644 --- a/atmel_start.c +++ b/atmel_start.c @@ -6,5 +6,5 @@ void atmel_start_init(void) { system_init(); - usb_init(); + // do not init usb here: might not be needed. } diff --git a/atmel_start_pins.h b/atmel_start_pins.h index 220a7b5..e51dd83 100644 --- a/atmel_start_pins.h +++ b/atmel_start_pins.h @@ -45,4 +45,41 @@ #define PA24 GPIO(GPIO_PORTA, 24) #define PA25 GPIO(GPIO_PORTA, 25)
+#define SIM4_INT GPIO(GPIO_PORTA, 2) +#define SIM5_INT GPIO(GPIO_PORTA, 3) +#define SIM0_IO GPIO(GPIO_PORTA, 4) +#define SIM2_IO GPIO(GPIO_PORTA, 9) +#define RMII_CLOCK GPIO(GPIO_PORTA, 10) +#define SIMCLK_20MHZ GPIO(GPIO_PORTA, 11) +#define SIM1_IO GPIO(GPIO_PORTA, 16) +#define VB0 GPIO(GPIO_PORTA, 20) +#define VB1 GPIO(GPIO_PORTA, 21) +#define VB2 GPIO(GPIO_PORTA, 22) +#define VB3 GPIO(GPIO_PORTA, 23) +#define USBUP_D_N GPIO(GPIO_PORTA, 24) +#define USBUP_D_P GPIO(GPIO_PORTA, 25) +#define SCL2 GPIO(GPIO_PORTB, 2) +#define SDA2 GPIO(GPIO_PORTB, 3) +#define SIM6_INT GPIO(GPIO_PORTB, 4) +#define SIM7_INT GPIO(GPIO_PORTB, 5) +#define SCL3 GPIO(GPIO_PORTB, 6) +#define SDA3 GPIO(GPIO_PORTB, 7) +#define SIM4_IO GPIO(GPIO_PORTB, 8) +#define SCL1 GPIO(GPIO_PORTB, 14) +#define SDA1 GPIO(GPIO_PORTB, 15) +#define SIM5_IO GPIO(GPIO_PORTB, 16) +#define SIM3_IO GPIO(GPIO_PORTB, 20) +#define UART_TX GPIO(GPIO_PORTB, 30) +#define UART_RX GPIO(GPIO_PORTB, 31) +#define SIM0_INT GPIO(GPIO_PORTC, 0) +#define SIM1_INT GPIO(GPIO_PORTC, 1) +#define SIM2_INT GPIO(GPIO_PORTC, 2) +#define SIM3_INT GPIO(GPIO_PORTC, 3) +#define SWITCH GPIO(GPIO_PORTC, 14) +#define MUX_STAT GPIO(GPIO_PORTC, 15) +#define SIM6_IO GPIO(GPIO_PORTC, 16) +#define USER_LED GPIO(GPIO_PORTC, 26) +#define SCL4 GPIO(GPIO_PORTC, 27) +#define SDA4 GPIO(GPIO_PORTC, 28) + #endif // ATMEL_START_PINS_H_INCLUDED diff --git a/config/hpl_cmcc_config.h b/config/hpl_cmcc_config.h index 8590736..d69c21a 100644 --- a/config/hpl_cmcc_config.h +++ b/config/hpl_cmcc_config.h @@ -10,7 +10,7 @@ //<i> Defines the cache should be enabled or not. // <id> cmcc_enable #ifndef CONF_CMCC_ENABLE -#define CONF_CMCC_ENABLE 0x0 +#define CONF_CMCC_ENABLE 0x1 #endif
// <o> Cache Size @@ -29,7 +29,7 @@ //<i> Defines the data cache should be disabled or not. // <id> cmcc_data_cache_disable #ifndef CONF_CMCC_DATA_CACHE_DISABLE -#define CONF_CMCC_DATA_CACHE_DISABLE 0x0 +#define CONF_CMCC_DATA_CACHE_DISABLE 0x1 #endif
// <q> Instruction cache disable diff --git a/config/hpl_gclk_config.h b/config/hpl_gclk_config.h index 306d90e..f2b75bf 100644 --- a/config/hpl_gclk_config.h +++ b/config/hpl_gclk_config.h @@ -25,7 +25,7 @@ // <i> This defines the clock source for generic clock generator 0 // <id> gclk_gen_0_oscillator #ifndef CONF_GCLK_GEN_0_SOURCE -#define CONF_GCLK_GEN_0_SOURCE GCLK_GENCTRL_SRC_XOSC1 +#define CONF_GCLK_GEN_0_SOURCE GCLK_GENCTRL_SRC_DPLL0 #endif
// <q> Run in Standby @@ -159,7 +159,7 @@ // <i> Indicates whether generic clock 2 configuration is enabled or not // <id> enable_gclk_gen_2 #ifndef CONF_GCLK_GENERATOR_2_CONFIG -#define CONF_GCLK_GENERATOR_2_CONFIG 0 +#define CONF_GCLK_GENERATOR_2_CONFIG 1 #endif
// <h> Generic Clock Generator Control @@ -176,7 +176,7 @@ // <i> This defines the clock source for generic clock generator 2 // <id> gclk_gen_2_oscillator #ifndef CONF_GCLK_GEN_2_SOURCE -#define CONF_GCLK_GEN_2_SOURCE GCLK_GENCTRL_SRC_XOSC0 +#define CONF_GCLK_GEN_2_SOURCE GCLK_GENCTRL_SRC_DPLL1 #endif
// <q> Run in Standby @@ -190,7 +190,7 @@ // <i> Indicates whether Divide Selection is enabled or not //<id> gclk_gen_2_div_sel #ifndef CONF_GCLK_GEN_2_DIVSEL -#define CONF_GCLK_GEN_2_DIVSEL 1 +#define CONF_GCLK_GEN_2_DIVSEL 0 #endif
// <q> Output Enable @@ -218,7 +218,7 @@ // <i> Indicates whether Generic Clock Generator Enable is enabled or not // <id> gclk_arch_gen_2_enable #ifndef CONF_GCLK_GEN_2_GENEN -#define CONF_GCLK_GEN_2_GENEN 0 +#define CONF_GCLK_GEN_2_GENEN 1 #endif // </h>
@@ -226,7 +226,7 @@ //<o> Generic clock generator 2 division <0x0000-0xFFFF> // <id> gclk_gen_2_div #ifndef CONF_GCLK_GEN_2_DIV -#define CONF_GCLK_GEN_2_DIV 1 +#define CONF_GCLK_GEN_2_DIV 200 #endif // </h> // </e> @@ -252,7 +252,7 @@ // <i> This defines the clock source for generic clock generator 3 // <id> gclk_gen_3_oscillator #ifndef CONF_GCLK_GEN_3_SOURCE -#define CONF_GCLK_GEN_3_SOURCE GCLK_GENCTRL_SRC_XOSC32K +#define CONF_GCLK_GEN_3_SOURCE GCLK_GENCTRL_SRC_OSCULP32K #endif
// <q> Run in Standby @@ -311,7 +311,7 @@ // <i> Indicates whether generic clock 4 configuration is enabled or not // <id> enable_gclk_gen_4 #ifndef CONF_GCLK_GENERATOR_4_CONFIG -#define CONF_GCLK_GENERATOR_4_CONFIG 0 +#define CONF_GCLK_GENERATOR_4_CONFIG 1 #endif
// <h> Generic Clock Generator Control @@ -328,7 +328,7 @@ // <i> This defines the clock source for generic clock generator 4 // <id> gclk_gen_4_oscillator #ifndef CONF_GCLK_GEN_4_SOURCE -#define CONF_GCLK_GEN_4_SOURCE GCLK_GENCTRL_SRC_XOSC0 +#define CONF_GCLK_GEN_4_SOURCE GCLK_GENCTRL_SRC_DPLL1 #endif
// <q> Run in Standby @@ -349,7 +349,7 @@ // <i> Indicates whether Output Enable is enabled or not // <id> gclk_arch_gen_4_oe #ifndef CONF_GCLK_GEN_4_OE -#define CONF_GCLK_GEN_4_OE 0 +#define CONF_GCLK_GEN_4_OE 1 #endif
// <q> Output Off Value @@ -370,7 +370,7 @@ // <i> Indicates whether Generic Clock Generator Enable is enabled or not // <id> gclk_arch_gen_4_enable #ifndef CONF_GCLK_GEN_4_GENEN -#define CONF_GCLK_GEN_4_GENEN 0 +#define CONF_GCLK_GEN_4_GENEN 1 #endif // </h>
@@ -378,7 +378,7 @@ //<o> Generic clock generator 4 division <0x0000-0xFFFF> // <id> gclk_gen_4_div #ifndef CONF_GCLK_GEN_4_DIV -#define CONF_GCLK_GEN_4_DIV 1 +#define CONF_GCLK_GEN_4_DIV 2 #endif // </h> // </e> @@ -387,7 +387,7 @@ // <i> Indicates whether generic clock 5 configuration is enabled or not // <id> enable_gclk_gen_5 #ifndef CONF_GCLK_GENERATOR_5_CONFIG -#define CONF_GCLK_GENERATOR_5_CONFIG 0 +#define CONF_GCLK_GENERATOR_5_CONFIG 1 #endif
// <h> Generic Clock Generator Control @@ -404,7 +404,7 @@ // <i> This defines the clock source for generic clock generator 5 // <id> gclk_gen_5_oscillator #ifndef CONF_GCLK_GEN_5_SOURCE -#define CONF_GCLK_GEN_5_SOURCE GCLK_GENCTRL_SRC_XOSC0 +#define CONF_GCLK_GEN_5_SOURCE GCLK_GENCTRL_SRC_DPLL1 #endif
// <q> Run in Standby @@ -425,7 +425,7 @@ // <i> Indicates whether Output Enable is enabled or not // <id> gclk_arch_gen_5_oe #ifndef CONF_GCLK_GEN_5_OE -#define CONF_GCLK_GEN_5_OE 0 +#define CONF_GCLK_GEN_5_OE 1 #endif
// <q> Output Off Value @@ -446,7 +446,7 @@ // <i> Indicates whether Generic Clock Generator Enable is enabled or not // <id> gclk_arch_gen_5_enable #ifndef CONF_GCLK_GEN_5_GENEN -#define CONF_GCLK_GEN_5_GENEN 0 +#define CONF_GCLK_GEN_5_GENEN 1 #endif // </h>
@@ -454,7 +454,7 @@ //<o> Generic clock generator 5 division <0x0000-0xFFFF> // <id> gclk_gen_5_div #ifndef CONF_GCLK_GEN_5_DIV -#define CONF_GCLK_GEN_5_DIV 1 +#define CONF_GCLK_GEN_5_DIV 5 #endif // </h> // </e> @@ -463,7 +463,7 @@ // <i> Indicates whether generic clock 6 configuration is enabled or not // <id> enable_gclk_gen_6 #ifndef CONF_GCLK_GENERATOR_6_CONFIG -#define CONF_GCLK_GENERATOR_6_CONFIG 0 +#define CONF_GCLK_GENERATOR_6_CONFIG 1 #endif
// <h> Generic Clock Generator Control @@ -480,7 +480,7 @@ // <i> This defines the clock source for generic clock generator 6 // <id> gclk_gen_6_oscillator #ifndef CONF_GCLK_GEN_6_SOURCE -#define CONF_GCLK_GEN_6_SOURCE GCLK_GENCTRL_SRC_XOSC0 +#define CONF_GCLK_GEN_6_SOURCE GCLK_GENCTRL_SRC_DPLL0 #endif
// <q> Run in Standby @@ -522,7 +522,7 @@ // <i> Indicates whether Generic Clock Generator Enable is enabled or not // <id> gclk_arch_gen_6_enable #ifndef CONF_GCLK_GEN_6_GENEN -#define CONF_GCLK_GEN_6_GENEN 0 +#define CONF_GCLK_GEN_6_GENEN 1 #endif // </h>
@@ -530,7 +530,7 @@ //<o> Generic clock generator 6 division <0x0000-0xFFFF> // <id> gclk_gen_6_div #ifndef CONF_GCLK_GEN_6_DIV -#define CONF_GCLK_GEN_6_DIV 1 +#define CONF_GCLK_GEN_6_DIV 17 #endif // </h> // </e> @@ -556,7 +556,7 @@ // <i> This defines the clock source for generic clock generator 7 // <id> gclk_gen_7_oscillator #ifndef CONF_GCLK_GEN_7_SOURCE -#define CONF_GCLK_GEN_7_SOURCE GCLK_GENCTRL_SRC_XOSC0 +#define CONF_GCLK_GEN_7_SOURCE GCLK_GENCTRL_SRC_XOSC1 #endif
// <q> Run in Standby @@ -632,7 +632,7 @@ // <i> This defines the clock source for generic clock generator 8 // <id> gclk_gen_8_oscillator #ifndef CONF_GCLK_GEN_8_SOURCE -#define CONF_GCLK_GEN_8_SOURCE GCLK_GENCTRL_SRC_XOSC0 +#define CONF_GCLK_GEN_8_SOURCE GCLK_GENCTRL_SRC_XOSC1 #endif
// <q> Run in Standby @@ -708,7 +708,7 @@ // <i> This defines the clock source for generic clock generator 9 // <id> gclk_gen_9_oscillator #ifndef CONF_GCLK_GEN_9_SOURCE -#define CONF_GCLK_GEN_9_SOURCE GCLK_GENCTRL_SRC_XOSC0 +#define CONF_GCLK_GEN_9_SOURCE GCLK_GENCTRL_SRC_XOSC1 #endif
// <q> Run in Standby @@ -784,7 +784,7 @@ // <i> This defines the clock source for generic clock generator 10 // <id> gclk_gen_10_oscillator #ifndef CONF_GCLK_GEN_10_SOURCE -#define CONF_GCLK_GEN_10_SOURCE GCLK_GENCTRL_SRC_XOSC0 +#define CONF_GCLK_GEN_10_SOURCE GCLK_GENCTRL_SRC_XOSC1 #endif
// <q> Run in Standby @@ -860,7 +860,7 @@ // <i> This defines the clock source for generic clock generator 11 // <id> gclk_gen_11_oscillator #ifndef CONF_GCLK_GEN_11_SOURCE -#define CONF_GCLK_GEN_11_SOURCE GCLK_GENCTRL_SRC_XOSC0 +#define CONF_GCLK_GEN_11_SOURCE GCLK_GENCTRL_SRC_XOSC1 #endif
// <q> Run in Standby @@ -910,7 +910,7 @@ //<o> Generic clock generator 11 division <0x0000-0xFFFF> // <id> gclk_gen_11_div #ifndef CONF_GCLK_GEN_11_DIV -#define CONF_GCLK_GEN_11_DIV 1 +#define CONF_GCLK_GEN_11_DIV 6 #endif // </h> // </e> diff --git a/config/hpl_osc32kctrl_config.h b/config/hpl_osc32kctrl_config.h index d0b0d34..7bcb41b 100644 --- a/config/hpl_osc32kctrl_config.h +++ b/config/hpl_osc32kctrl_config.h @@ -43,7 +43,7 @@ // <i> Indicates whether configuration for External 32K Osc is enabled or not // <id> enable_xosc32k #ifndef CONF_XOSC32K_CONFIG -#define CONF_XOSC32K_CONFIG 1 +#define CONF_XOSC32K_CONFIG 0 #endif
// <h> 32kHz External Crystal Oscillator Control @@ -51,7 +51,7 @@ // <i> Indicates whether 32kHz External Crystal Oscillator is enabled or not // <id> xosc32k_arch_enable #ifndef CONF_XOSC32K_ENABLE -#define CONF_XOSC32K_ENABLE 1 +#define CONF_XOSC32K_ENABLE 0 #endif
// <o> Start-Up Time @@ -71,21 +71,21 @@ // <i> Indicates whether On Demand Control is enabled or not // <id> xosc32k_arch_ondemand #ifndef CONF_XOSC32K_ONDEMAND -#define CONF_XOSC32K_ONDEMAND 1 +#define CONF_XOSC32K_ONDEMAND 0 #endif
// <q> Run in Standby // <i> Indicates whether Run in Standby is enabled or not // <id> xosc32k_arch_runstdby #ifndef CONF_XOSC32K_RUNSTDBY -#define CONF_XOSC32K_RUNSTDBY 0 +#define CONF_XOSC32K_RUNSTDBY 1 #endif
// <q> 1kHz Output Enable // <i> Indicates whether 1kHz Output is enabled or not // <id> xosc32k_arch_en1k #ifndef CONF_XOSC32K_EN1K -#define CONF_XOSC32K_EN1K 0 +#define CONF_XOSC32K_EN1K 1 #endif
// <q> 32kHz Output Enable diff --git a/config/hpl_oscctrl_config.h b/config/hpl_oscctrl_config.h index 11e4a24..db34009 100644 --- a/config/hpl_oscctrl_config.h +++ b/config/hpl_oscctrl_config.h @@ -158,7 +158,7 @@ // <0xF=>1000000us // <id> xosc1_arch_startup #ifndef CONF_XOSC1_STARTUP -#define CONF_XOSC1_STARTUP 0 +#define CONF_XOSC1_STARTUP 0xE #endif
// <q> Clock Switch Back @@ -179,7 +179,7 @@ // <i> Indicates whether Automatic Loop Control is enabled or not // <id> xosc1_arch_enalc #ifndef CONF_XOSC1_ENALC -#define CONF_XOSC1_ENALC 0 +#define CONF_XOSC1_ENALC 1 #endif
// <q> Low Buffer Gain Enable @@ -296,7 +296,7 @@ // <i> Indicates whether Bypass Coarse Lock is enabled or not // <id> dfll_arch_bplckc #ifndef CONF_DFLL_BPLCKC -#define CONF_DFLL_BPLCKC 0 +#define CONF_DFLL_BPLCKC 1 #endif
// <q> Quick Lock Disable @@ -324,7 +324,7 @@ // <i> Indicates whether Stable DFLL Frequency is enabled or not // <id> dfll_arch_stable #ifndef CONF_DFLL_STABLE -#define CONF_DFLL_STABLE 0 +#define CONF_DFLL_STABLE 1 #endif
// <o> Operating Mode Selection @@ -332,7 +332,7 @@ // <1=>Closed Loop Mode // <id> dfll_mode #ifndef CONF_DFLL_MODE -#define CONF_DFLL_MODE 0x1 +#define CONF_DFLL_MODE 0x0 #endif
// <o> Coarse Maximum Step <0x0-0x1F> @@ -344,7 +344,7 @@ // <o> Fine Maximum Step <0x0-0xFF> // <id> dfll_arch_fstep #ifndef CONF_DFLL_FSTEP -#define CONF_DFLL_FSTEP 0x1 +#define CONF_DFLL_FSTEP 0xa #endif
// <o> DFLL Multiply Factor <0x0-0xFFFF> @@ -382,7 +382,7 @@ // <i> Indicates whether configuration for FDPLL0 is enabled or not // <id> enable_fdpll0 #ifndef CONF_FDPLL0_CONFIG -#define CONF_FDPLL0_CONFIG 0 +#define CONF_FDPLL0_CONFIG 1 #endif
// <y> Reference Clock Source @@ -404,7 +404,7 @@ // <i> Select the clock source. // <id> fdpll0_ref_clock #ifndef CONF_FDPLL0_GCLK -#define CONF_FDPLL0_GCLK GCLK_GENCTRL_SRC_XOSC32K +#define CONF_FDPLL0_GCLK GCLK_GENCTRL_SRC_XOSC1 #endif
// <h> Digital Phase Locked Loop Control @@ -412,7 +412,7 @@ // <i> Indicates whether Digital Phase Locked Loop is enabled or not // <id> fdpll0_arch_enable #ifndef CONF_FDPLL0_ENABLE -#define CONF_FDPLL0_ENABLE 0 +#define CONF_FDPLL0_ENABLE 1 #endif
// <q> On Demand Control @@ -430,21 +430,24 @@ #endif
// <o> Loop Divider Ratio Fractional Part <0x0-0x1F> +// <i> Value of LDRFRAC is calculated using Fclk_dpll=Fckr*(LDR+1+LDRFRAC/32) formula as given in datasheet. This value is directly written in to DPLLRATIO register // <id> fdpll0_ldrfrac #ifndef CONF_FDPLL0_LDRFRAC -#define CONF_FDPLL0_LDRFRAC 0xd +#define CONF_FDPLL0_LDRFRAC 0x0 #endif
// <o> Loop Divider Ratio Integer Part <0x0-0x1FFF> +// <i> Value of LDR is calculated using Fclk_dpll=Fckr*(LDR+1+LDRFRAC/32) formula as given in datasheet. This value is directly written in to DPLLRATIO register // <id> fdpll0_ldr #ifndef CONF_FDPLL0_LDR -#define CONF_FDPLL0_LDR 0x5b7 +#define CONF_FDPLL0_LDR 0x3b #endif
// <o> Clock Divider <0x0-0x7FF> +// <i> This Clock divider is only for XOSC clock input to DPLL // <id> fdpll0_clock_div #ifndef CONF_FDPLL0_DIV -#define CONF_FDPLL0_DIV 0x0 +#define CONF_FDPLL0_DIV 0x2 #endif
// <q> DCO Filter Enable @@ -464,7 +467,7 @@ // <i> Indicates whether Lock Bypass is enabled or not // <id> fdpll0_arch_lbypass #ifndef CONF_FDPLL0_LBYPASS -#define CONF_FDPLL0_LBYPASS 0 +#define CONF_FDPLL0_LBYPASS 1 #endif
// <o> Lock Time @@ -485,14 +488,14 @@ // <0x3=>XOSC1 clock reference // <id> fdpll0_arch_refclk #ifndef CONF_FDPLL0_REFCLK -#define CONF_FDPLL0_REFCLK 0x1 +#define CONF_FDPLL0_REFCLK 0x3 #endif
// <q> Wake Up Fast // <i> Indicates whether Wake Up Fast is enabled or not // <id> fdpll0_arch_wuf #ifndef CONF_FDPLL0_WUF -#define CONF_FDPLL0_WUF 0 +#define CONF_FDPLL0_WUF 1 #endif
// <o> Proportional Integral Filter Selection <0x0-0xF> @@ -507,7 +510,7 @@ // <i> Indicates whether configuration for FDPLL1 is enabled or not // <id> enable_fdpll1 #ifndef CONF_FDPLL1_CONFIG -#define CONF_FDPLL1_CONFIG 0 +#define CONF_FDPLL1_CONFIG 1 #endif
// <y> Reference Clock Source @@ -529,7 +532,7 @@ // <i> Select the clock source. // <id> fdpll1_ref_clock #ifndef CONF_FDPLL1_GCLK -#define CONF_FDPLL1_GCLK GCLK_GENCTRL_SRC_XOSC32K +#define CONF_FDPLL1_GCLK GCLK_GENCTRL_SRC_XOSC1 #endif
// <h> Digital Phase Locked Loop Control @@ -537,7 +540,7 @@ // <i> Indicates whether Digital Phase Locked Loop is enabled or not // <id> fdpll1_arch_enable #ifndef CONF_FDPLL1_ENABLE -#define CONF_FDPLL1_ENABLE 0 +#define CONF_FDPLL1_ENABLE 1 #endif
// <q> On Demand Control @@ -555,21 +558,24 @@ #endif
// <o> Loop Divider Ratio Fractional Part <0x0-0x1F> +// <i> Value of LDRFRAC is calculated using Fclk_dpll=Fckr*(LDR+1+LDRFRAC/32) formula as given in datasheet. This value is directly written in to DPLLRATIO register // <id> fdpll1_ldrfrac #ifndef CONF_FDPLL1_LDRFRAC -#define CONF_FDPLL1_LDRFRAC 0xd +#define CONF_FDPLL1_LDRFRAC 0x0 #endif
// <o> Loop Divider Ratio Integer Part <0x0-0x1FFF> +// <i> Value of LDR is calculated using Fclk_dpll=Fckr*(LDR+1+LDRFRAC/32) formula as given in datasheet. This value is directly written in to DPLLRATIO register // <id> fdpll1_ldr #ifndef CONF_FDPLL1_LDR -#define CONF_FDPLL1_LDR 0x5b7 +#define CONF_FDPLL1_LDR 0x31 #endif
// <o> Clock Divider <0x0-0x7FF> +// <i> This Clock divider is only for XOSC clock input to DPLL // <id> fdpll1_clock_div #ifndef CONF_FDPLL1_DIV -#define CONF_FDPLL1_DIV 0x0 +#define CONF_FDPLL1_DIV 0x2 #endif
// <q> DCO Filter Enable @@ -589,7 +595,7 @@ // <i> Indicates whether Lock Bypass is enabled or not // <id> fdpll1_arch_lbypass #ifndef CONF_FDPLL1_LBYPASS -#define CONF_FDPLL1_LBYPASS 0 +#define CONF_FDPLL1_LBYPASS 1 #endif
// <o> Lock Time @@ -610,14 +616,14 @@ // <0x3=>XOSC1 clock reference // <id> fdpll1_arch_refclk #ifndef CONF_FDPLL1_REFCLK -#define CONF_FDPLL1_REFCLK 0x1 +#define CONF_FDPLL1_REFCLK 0x3 #endif
// <q> Wake Up Fast // <i> Indicates whether Wake Up Fast is enabled or not // <id> fdpll1_arch_wuf #ifndef CONF_FDPLL1_WUF -#define CONF_FDPLL1_WUF 0 +#define CONF_FDPLL1_WUF 1 #endif
// <o> Proportional Integral Filter Selection <0x0-0xF> diff --git a/config/hpl_rtc_config.h b/config/hpl_rtc_config.h new file mode 100644 index 0000000..0e795ba --- /dev/null +++ b/config/hpl_rtc_config.h @@ -0,0 +1,337 @@ +/* Auto-generated config file hpl_rtc_config.h */ +#ifndef HPL_RTC_CONFIG_H +#define HPL_RTC_CONFIG_H + +// <<< Use Configuration Wizard in Context Menu >>> + +// <h> Basic settings + +#ifndef CONF_RTC_ENABLE +#define CONF_RTC_ENABLE 1 +#endif + +// <q> Force reset RTC on initialization +// <i> Force RTC to reset on initialization. +// <i> Note that the previous power down data in RTC is lost if it's enabled. +// <id> rtc_arch_init_reset +#ifndef CONF_RTC_INIT_RESET +#define CONF_RTC_INIT_RESET 1 +#endif + +// <o> Prescaler configuration +// <0x0=>OFF(Peripheral clock divided by 1) +// <0x1=>Peripheral clock divided by 1 +// <0x2=>Peripheral clock divided by 2 +// <0x3=>Peripheral clock divided by 4 +// <0x4=>Peripheral clock divided by 8 +// <0x5=>Peripheral clock divided by 16 +// <0x6=>Peripheral clock divided by 32 +// <0x7=>Peripheral clock divided by 64 +// <0x8=>Peripheral clock divided by 128 +// <0x9=>Peripheral clock divided by 256 +// <0xA=>Peripheral clock divided by 512 +// <0xB=>Peripheral clock divided by 1024 +// <i> These bits define the RTC clock relative to the peripheral clock +// <id> rtc_arch_prescaler +#ifndef CONF_RTC_PRESCALER + +#define CONF_RTC_PRESCALER 0xb + +#endif + +#ifndef CONF_RTC_COMP_VAL + +#define CONF_RTC_COMP_VAL 0 + +#endif + +// <e> RTC Tamper Input 0 settings +// <id> tamper_input_0_settings +#ifndef CONF_TAMPER_INPUT_0_SETTINGS +#define CONF_TAMPER_INPUT_0_SETTINGS 0 +#endif + +// <q> Tamper Level Settings +// <i> Indicates Tamper input 0 level +// <id> tamper_level_0 +#ifndef CONF_RTC_TAMP_LVL_0 +#define CONF_RTC_TAMP_LVL_0 0 +#endif + +// <o> RTC Tamper Input Action +// <0x0=>OFF(Disabled) +// <0x1=>Wake and Set Tamper Flag +// <0x2=>Capture Timestamp and Set Tamper Flag +// <0x3=>Active Layer Mode.IN and OUT pin is used.Timestamp is also captured. +// <i> These bits define the RTC Tamper Input Action to be performed +// <id> rtc_tamper_input_action_0 +#ifndef CONF_RTC_TAMPER_INACT_0 +#define CONF_RTC_TAMPER_INACT_0 0 +#endif + +// <q> Debounce Enable for Tamper Input +// <i> Indicates Debounce should be enabled for Tamper input 0 +// <id> tamper_debounce_enable_0 +#ifndef CONF_RTC_TAMP_DEBNC_0 +#define CONF_RTC_TAMP_DEBNC_0 0 +#endif + +// </e> + +// <e> RTC Tamper Input 1 settings +// <id> tamper_input_1_settings +#ifndef CONF_TAMPER_INPUT_1_SETTINGS +#define CONF_TAMPER_INPUT_1_SETTINGS 0 +#endif + +// <q> Tamper Level Settings +// <i> Indicates Tamper input 1 level +// <id> tamper_level_1 +#ifndef CONF_RTC_TAMP_LVL_1 +#define CONF_RTC_TAMP_LVL_1 0 +#endif + +// <o> RTC Tamper Input Action +// <0x0=>OFF(Disabled) +// <0x1=>Wake and Set Tamper Flag +// <0x2=>Capture Timestamp and Set Tamper Flag +// <0x3=>Active Layer Mode.IN and OUT pin is used.Timestamp is also captured. +// <i> These bits define the RTC Tamper Input Action to be performed +// <id> rtc_tamper_input_action_1 +#ifndef CONF_RTC_TAMPER_INACT_1 +#define CONF_RTC_TAMPER_INACT_1 0 +#endif + +// <q> Debounce Enable for Tamper Input +// <i> Indicates Debounce should be enabled for Tamper input 1 +// <id> tamper_debounce_enable_1 +#ifndef CONF_RTC_TAMP_DEBNC_1 +#define CONF_RTC_TAMP_DEBNC_1 0 +#endif + +// </e> + +// <e> RTC Tamper Input 2 settings +// <id> tamper_input_2_settings +#ifndef CONF_TAMPER_INPUT_2_SETTINGS +#define CONF_TAMPER_INPUT_2_SETTINGS 0 +#endif + +// <q> Tamper Level Settings +// <i> Indicates Tamper input 2 level +// <id> tamper_level_2 +#ifndef CONF_RTC_TAMP_LVL_2 +#define CONF_RTC_TAMP_LVL_2 0 +#endif + +// <o> RTC Tamper Input Action +// <0x0=>OFF(Disabled) +// <0x1=>Wake and Set Tamper Flag +// <0x2=>Capture Timestamp and Set Tamper Flag +// <0x3=>Active Layer Mode.IN and OUT pin is used.Timestamp is also captured. +// <i> These bits define the RTC Tamper Input Action to be performed +// <id> rtc_tamper_input_action_2 +#ifndef CONF_RTC_TAMPER_INACT_2 +#define CONF_RTC_TAMPER_INACT_2 0 +#endif + +// <q> Debounce Enable for Tamper Input +// <i> Indicates Debounce should be enabled for Tamper input 2 +// <id> tamper_debounce_enable_2 +#ifndef CONF_RTC_TAMP_DEBNC_2 +#define CONF_RTC_TAMP_DEBNC_2 0 +#endif + +// </e> + +// <e> RTC Tamper Input 3 settings +// <id> tamper_input_3_settings +#ifndef CONF_TAMPER_INPUT_3_SETTINGS +#define CONF_TAMPER_INPUT_3_SETTINGS 0 +#endif + +// <q> Tamper Level Settings +// <i> Indicates Tamper input 3 level +// <id> tamper_level_3 +#ifndef CONF_RTC_TAMP_LVL_3 +#define CONF_RTC_TAMP_LVL_3 0 +#endif + +// <o> RTC Tamper Input Action +// <0x0=>OFF(Disabled) +// <0x1=>Wake and Set Tamper Flag +// <0x2=>Capture Timestamp and Set Tamper Flag +// <0x3=>Active Layer Mode.IN and OUT pin is used.Timestamp is also captured. +// <i> These bits define the RTC Tamper Input Action to be performed +// <id> rtc_tamper_input_action_3 +#ifndef CONF_RTC_TAMPER_INACT_3 +#define CONF_RTC_TAMPER_INACT_3 0 +#endif + +// <q> Debounce Enable for Tamper Input +// <i> Indicates Debounce should be enabled for Tamper input 3 +// <id> tamper_debounce_enable_3 +#ifndef CONF_RTC_TAMP_DEBNC_3 +#define CONF_RTC_TAMP_DEBNC_3 0 +#endif + +// </e> + +// <e> RTC Tamper Input 4 settings +// <id> tamper_input_4_settings +#ifndef CONF_TAMPER_INPUT_4_SETTINGS +#define CONF_TAMPER_INPUT_4_SETTINGS 0 +#endif + +// <q> Tamper Level Settings +// <i> Indicates Tamper input 4 level +// <id> tamper_level_4 +#ifndef CONF_RTC_TAMP_LVL_4 +#define CONF_RTC_TAMP_LVL_4 0 +#endif + +// <o> RTC Tamper Input Action +// <0x0=>OFF(Disabled) +// <0x1=>Wake and Set Tamper Flag +// <0x2=>Capture Timestamp and Set Tamper Flag +// <0x3=>Active Layer Mode.IN and OUT pin is used.Timestamp is also captured. +// <i> These bits define the RTC Tamper Input Action to be performed +// <id> rtc_tamper_input_action_4 +#ifndef CONF_RTC_TAMPER_INACT_4 +#define CONF_RTC_TAMPER_INACT_4 0 +#endif + +// <q> Debounce Enable for Tamper Input +// <i> Indicates Debounce should be enabled for Tamper input 4 +// <id> tamper_debounce_enable_4 +#ifndef CONF_RTC_TAMP_DEBNC_4 +#define CONF_RTC_TAMP_DEBNC_4 0 +#endif + +// </e> + +// <o> RTC Tamper Active Layer Frequency Prescalar +// <0x0=>DIV2 CLK_RTC_OUT is CLK_RTC /2 +// <0x1=>DIV4 CLK_RTC_OUT is CLK_RTC /4 +// <0x2=>DIV8 CLK_RTC_OUT is CLK_RTC /8 +// <0x3=>DIV16 CLK_RTC_OUT is CLK_RTC /16 +// <0x4=>DIV32 CLK_RTC_OUT is CLK_RTC /32 +// <0x5=>DIV64 CLK_RTC_OUT is CLK_RTC /64 +// <0x6=>DIV128 CLK_RTC_OUT is CLK_RTC /128 +// <0x7=>DIV256 CLK_RTC_OUT is CLK_RTC /256 +// <i> These bits define the RTC Tamper Active Layer Frequecny Prescalar +// <id> rtc_tamper_active_layer_frequency_prescalar +#ifndef CONF_RTC_TAMP_ACT_LAYER_FREQ_PRES +#define CONF_RTC_TAMP_ACT_LAYER_FREQ_PRES 0 +#endif + +// <o> RTC Tamper Debounce Frequency Prescalar +// <0x0=>DIV2 CLK_RTC_DEB is CLK_RTC /2 +// <0x1=>DIV4 CLK_RTC_DEB is CLK_RTC /4 +// <0x2=>DIV8 CLK_RTC_DEB is CLK_RTC /8 +// <0x3=>DIV16 CLK_RTC_DEB is CLK_RTC /16 +// <0x4=>DIV32 CLK_RTC_DEB is CLK_RTC /32 +// <0x5=>DIV64 CLK_RTC_DEB is CLK_RTC /64 +// <0x6=>DIV128 CLK_RTC_DEB is CLK_RTC /128 +// <0x7=>DIV256 CLK_RTC_DEB is CLK_RTC /256 +// <i> These bits define the RTC Debounce Frequency Prescalar +// <id> rtc_tamper_debounce_frequency_prescalar +#ifndef CONF_RTC_TAMP_DEBF_PRES +#define CONF_RTC_TAMP_DEBF_PRES 0 +#endif + +// <e> Event control +// <id> rtc_event_control +#ifndef CONF_RTC_EVENT_CONTROL_ENABLE +#define CONF_RTC_EVENT_CONTROL_ENABLE 0 +#endif + +// <q> Periodic Interval 0 Event Output +// <i> This bit indicates whether Periodic interval 0 event is enabled and will be generated +// <id> rtc_pereo0 +#ifndef CONF_RTC_PEREO0 +#define CONF_RTC_PEREO0 0 +#endif +// <q> Periodic Interval 1 Event Output +// <i> This bit indicates whether Periodic interval 1 event is enabled and will be generated +// <id> rtc_pereo1 +#ifndef CONF_RTC_PEREO1 +#define CONF_RTC_PEREO1 0 +#endif +// <q> Periodic Interval 2 Event Output +// <i> This bit indicates whether Periodic interval 2 event is enabled and will be generated +// <id> rtc_pereo2 +#ifndef CONF_RTC_PEREO2 +#define CONF_RTC_PEREO2 0 +#endif +// <q> Periodic Interval 3 Event Output +// <i> This bit indicates whether Periodic interval 3 event is enabled and will be generated +// <id> rtc_pereo3 +#ifndef CONF_RTC_PEREO3 +#define CONF_RTC_PEREO3 0 +#endif +// <q> Periodic Interval 4 Event Output +// <i> This bit indicates whether Periodic interval 4 event is enabled and will be generated +// <id> rtc_pereo4 +#ifndef CONF_RTC_PEREO4 +#define CONF_RTC_PEREO4 0 +#endif +// <q> Periodic Interval 5 Event Output +// <i> This bit indicates whether Periodic interval 5 event is enabled and will be generated +// <id> rtc_pereo5 +#ifndef CONF_RTC_PEREO5 +#define CONF_RTC_PEREO5 0 +#endif +// <q> Periodic Interval 6 Event Output +// <i> This bit indicates whether Periodic interval 6 event is enabled and will be generated +// <id> rtc_pereo6 +#ifndef CONF_RTC_PEREO6 +#define CONF_RTC_PEREO6 0 +#endif +// <q> Periodic Interval 7 Event Output +// <i> This bit indicates whether Periodic interval 7 event is enabled and will be generated +// <id> rtc_pereo7 +#ifndef CONF_RTC_PEREO7 +#define CONF_RTC_PEREO7 0 +#endif + +// <q> Compare 0 Event Output +// <i> This bit indicates whether Compare O event is enabled and will be generated +// <id> rtc_cmpeo0 +#ifndef CONF_RTC_COMPE0 +#define CONF_RTC_COMPE0 0 +#endif + +// <q> Compare 1 Event Output +// <i> This bit indicates whether Compare 1 event is enabled and will be generated +// <id> rtc_cmpeo1 +#ifndef CONF_RTC_COMPE1 +#define CONF_RTC_COMPE1 0 +#endif +// <q> Overflow Event Output +// <i> This bit indicates whether Overflow event is enabled and will be generated +// <id> rtc_ovfeo +#ifndef CONF_RTC_OVFEO +#define CONF_RTC_OVFEO 0 +#endif + +// <q> Tamper Event Output +// <i> This bit indicates whether Tamper event output is enabled and will be generated +// <id> rtc_tampereo +#ifndef CONF_RTC_TAMPEREO +#define CONF_RTC_TAMPEREO 0 +#endif + +// <q> Tamper Event Input +// <i> This bit indicates whether Tamper event input is enabled and will be generated +// <id> rtc_tampevei +#ifndef CONF_RTC_TAMPEVEI +#define CONF_RTC_TAMPEVEI 0 +#endif +// </e> + +// </h> + +// <<< end of configuration section >>> + +#endif // HPL_RTC_CONFIG_H diff --git a/config/hpl_sercom_config.h b/config/hpl_sercom_config.h new file mode 100644 index 0000000..bb2bbff --- /dev/null +++ b/config/hpl_sercom_config.h @@ -0,0 +1,2182 @@ +/* Auto-generated config file hpl_sercom_config.h */ +#ifndef HPL_SERCOM_CONFIG_H +#define HPL_SERCOM_CONFIG_H + +// <<< Use Configuration Wizard in Context Menu >>> + +#include <peripheral_clk_config.h> + +#ifndef CONF_SERCOM_0_USART_ENABLE +#define CONF_SERCOM_0_USART_ENABLE 1 +#endif + +// <h> Basic Configuration + +// <q> Receive buffer enable +// <i> Enable input buffer in SERCOM module +// <id> usart_rx_enable +#ifndef CONF_SERCOM_0_USART_RXEN +#define CONF_SERCOM_0_USART_RXEN 1 +#endif + +// <q> Transmitt buffer enable +// <i> Enable output buffer in SERCOM module +// <id> usart_tx_enable +#ifndef CONF_SERCOM_0_USART_TXEN +#define CONF_SERCOM_0_USART_TXEN 1 +#endif + +// <o> Frame parity +// <0x1=>Even parity +// <i> Parity bit mode for USART frame +// <id> usart_parity +#ifndef CONF_SERCOM_0_USART_PARITY +#define CONF_SERCOM_0_USART_PARITY 1 +#endif + +// <o> Character Size +// <0x0=>8 bits +// <0x1=>9 bits +// <0x5=>5 bits +// <0x6=>6 bits +// <0x7=>7 bits +// <i> Data character size in USART frame +// <id> usart_character_size +#ifndef CONF_SERCOM_0_USART_CHSIZE +#define CONF_SERCOM_0_USART_CHSIZE 0x0 +#endif + +// <o> Stop Bit +// <0=>One stop bit +// <1=>Two stop bits +// <i> Number of stop bits in USART frame +// <id> usart_stop_bit +#ifndef CONF_SERCOM_0_USART_SBMODE +#define CONF_SERCOM_0_USART_SBMODE 1 +#endif + +// <o> Baud rate <1-3000000> +// <i> USART baud rate setting +// <id> usart_baud_rate +#ifndef CONF_SERCOM_0_USART_BAUD +#define CONF_SERCOM_0_USART_BAUD 6720 +#endif +// </h> + +// <h> ISO7816 configuration +// <o> ISO7816 Protocol Type +// <0x1=> T=0 +// <0x0=> T=1 +// <i> Define ISO7816 protocol type as 0. +// <id> usart_iso7816_type +#ifndef CONF_SERCOM_0_USART_ISO7816_PROTOCOL_T +#define CONF_SERCOM_0_USART_ISO7816_PROTOCOL_T 0x0 +#endif + +// <o> ISO7816 Inhibit Not Acknowledge +// <0x0=> NACK is transmitted when a parity error is received. +// <0x1=> NACK is not transmitted when a parity error is received. +// <i> Define whether a NACK is transmitted when a parity error is received. +// <id> usart_inack +#ifndef CONF_SERCOM_0_USART_INACK +#define CONF_SERCOM_0_USART_INACK 0x0 +#endif + +// <o> ISO7816 Disable Successive Not Acknowledge +// <0x0=> The successive receive NACK is disable. +// <0x1=> The successive receive NACK is enable. +// <i> Define whether NACK will be sent on parity error reception. +// <id> usart_dsnack +#ifndef CONF_SERCOM_0_USART_DSNACK +#define CONF_SERCOM_0_USART_DSNACK 0x0 +#endif + +// <o> ISO7816 Maximum Iterations<0-7> +// <i> Define the maximum number of retransmit iterations. +// <id> usart_maxiter +#ifndef CONF_SERCOM_0_USART_MAXITER +#define CONF_SERCOM_0_USART_MAXITER 0x7 +#endif + +// <o> ISO7816 Guard Time +// <0x2=> 2-bit times +// <0x3=> 3-bit times +// <0x4=> 4-bit times +// <0x5=> 5-bit times +// <0x6=> 6-bit times +// <0x7=> 7-bit times +// <i> Define the guard time. +// <id> usart_gtime +#ifndef CONF_SERCOM_0_USART_GTIME +#define CONF_SERCOM_0_USART_GTIME 0x2 +#endif + +// <q> Inverse transmission and reception enabled +// <i> Define inverse transmission and reception enabled. +// <id> usart_inverse_enabled +#ifndef CONF_SERCOM_0_USART_INVERSE_ENABLED +#define CONF_SERCOM_0_USART_INVERSE_ENABLED 0x0 +#endif + +#if (CONF_SERCOM_0_USART_INVERSE_ENABLED == 1) +#define CONF_SERCOM_0_USART_RXINV 0x1 +#define CONF_SERCOM_0_USART_TXINV 0x1 +#else +#define CONF_SERCOM_0_USART_RXINV 0x0 +#define CONF_SERCOM_0_USART_TXINV 0x0 +#endif + +// </h> + +// <e> Advanced configuration +// <id> usart_advanced +#ifndef CONF_SERCOM_0_USART_ADVANCED_CONFIG +#define CONF_SERCOM_0_USART_ADVANCED_CONFIG 0 +#endif + +// <q> Run in stand-by +// <i> Keep the module running in standby sleep mode +// <id> usart_arch_runstdby +#ifndef CONF_SERCOM_0_USART_RUNSTDBY +#define CONF_SERCOM_0_USART_RUNSTDBY 0 +#endif + +// <q> Immediate Buffer Overflow Notification +// <i> Controls when the BUFOVF status bit is asserted +// <id> usart_arch_ibon +#ifndef CONF_SERCOM_0_USART_IBON +#define CONF_SERCOM_0_USART_IBON 0 +#endif + +// <q> Start of Frame Detection Enable +// <i> Will wake the device from any sleep mode if usart_init and usart_enable was run priort to going to sleep. (receive buffer must be enabled) +// <id> usart_arch_sfde +#ifndef CONF_SERCOM_0_USART_SFDE +#define CONF_SERCOM_0_USART_SFDE 0 +#endif + +// <q> Collision Detection Enable +// <i> Collision detection enable +// <id> usart_arch_cloden +#ifndef CONF_SERCOM_0_USART_CLODEN +#define CONF_SERCOM_0_USART_CLODEN 0 +#endif + +// <o> Operating Mode +// <0x1=>USART with internal clock +// <i> Drive the shift register by an internal clock generated by the baud rate generator. +// <id> usart_arch_clock_mode +#ifndef CONF_SERCOM_0_USART_MODE +#define CONF_SERCOM_0_USART_MODE 0x1 +#endif + +// <o> Data Order +// <0=>MSB is transmitted first +// <1=>LSB is transmitted first +// <i> Data order of the data bits in the frame +// <id> usart_arch_dord +#ifndef CONF_SERCOM_0_USART_DORD +#define CONF_SERCOM_0_USART_DORD 1 +#endif + +// <o> Debug Stop Mode +// <i> Behavior of the baud-rate generator when CPU is halted by external debugger. +// <0=>Keep running +// <1=>Halt +// <id> usart_arch_dbgstop +#ifndef CONF_SERCOM_0_USART_DEBUG_STOP_MODE +#define CONF_SERCOM_0_USART_DEBUG_STOP_MODE 0 +#endif + +// Does not do anything in USRT mode +#define CONF_SERCOM_0_USART_SAMPR 0x0 +#define CONF_SERCOM_0_USART_SAMPA 0x0 +#define CONF_SERCOM_0_USART_FRACTIONAL 0x0 + +// Does not do anything in UART mode +#define CONF_SERCOM_0_USART_CPOL 0 + +// Does not do anything in USRT mode +#define CONF_SERCOM_0_USART_ENC 0 + +// </e> + +#ifndef CONF_SERCOM_0_USART_CMODE +#define CONF_SERCOM_0_USART_CMODE CONF_SERCOM_0_USART_ISO7816_PROTOCOL_T +#endif + +/* RX is on PIN_PA04 */ +#ifndef CONF_SERCOM_0_USART_RXPO +#define CONF_SERCOM_0_USART_RXPO 0 +#endif + +/* TX uses the same pin with RX */ +#ifndef CONF_SERCOM_0_USART_TXPO +#define CONF_SERCOM_0_USART_TXPO 2 +#endif + +/* Set iso7816 mode */ +#define CONF_SERCOM_0_USART_PMODE (CONF_SERCOM_0_USART_PARITY - 1) +#define CONF_SERCOM_0_USART_FORM 7 + +#if CONF_SERCOM_0_USART_CMODE == 0 +// Calculate BAUD register value in UART mode +#if CONF_SERCOM_0_USART_SAMPR == 0 +#ifndef CONF_SERCOM_0_USART_BAUD_RATE +#define CONF_SERCOM_0_USART_BAUD_RATE \ + 65536 - ((65536 * 16.0f * CONF_SERCOM_0_USART_BAUD) / CONF_GCLK_SERCOM0_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_0_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_0_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_0_USART_SAMPR == 1 +#ifndef CONF_SERCOM_0_USART_BAUD_RATE +#define CONF_SERCOM_0_USART_BAUD_RATE \ + ((CONF_GCLK_SERCOM0_CORE_FREQUENCY) / (CONF_SERCOM_0_USART_BAUD * 16)) - (CONF_SERCOM_0_USART_FRACTIONAL / 8) +#endif +#ifndef CONF_SERCOM_0_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_0_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_0_USART_SAMPR == 2 +#ifndef CONF_SERCOM_0_USART_BAUD_RATE +#define CONF_SERCOM_0_USART_BAUD_RATE \ + 65536 - ((65536 * 8.0f * CONF_SERCOM_0_USART_BAUD) / CONF_GCLK_SERCOM0_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_0_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_0_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_0_USART_SAMPR == 3 +#ifndef CONF_SERCOM_0_USART_BAUD_RATE +#define CONF_SERCOM_0_USART_BAUD_RATE \ + ((CONF_GCLK_SERCOM0_CORE_FREQUENCY) / (CONF_SERCOM_0_USART_BAUD * 8)) - (CONF_SERCOM_0_USART_FRACTIONAL / 8) +#endif +#ifndef CONF_SERCOM_0_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_0_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_0_USART_SAMPR == 4 +#ifndef CONF_SERCOM_0_USART_BAUD_RATE +#define CONF_SERCOM_0_USART_BAUD_RATE \ + 65536 - ((65536 * 3.0f * CONF_SERCOM_0_USART_BAUD) / CONF_GCLK_SERCOM0_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_0_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_0_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#endif + +#elif CONF_SERCOM_0_USART_CMODE == 1 +#ifndef CONF_SERCOM_0_USART_BAUD_RATE +// Calculate BAUD register value in USRT mode +#define CONF_SERCOM_0_USART_BAUD_RATE (CONF_GCLK_SERCOM0_CORE_FREQUENCY) / (2 * CONF_SERCOM_0_USART_BAUD) - 1 +#endif + +#ifndef CONF_SERCOM_0_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_0_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#else +#error CMODE value for SERCOM 0 in USART mode not known +#endif + +#include <peripheral_clk_config.h> + +#ifndef CONF_SERCOM_1_USART_ENABLE +#define CONF_SERCOM_1_USART_ENABLE 1 +#endif + +// <h> Basic Configuration + +// <q> Receive buffer enable +// <i> Enable input buffer in SERCOM module +// <id> usart_rx_enable +#ifndef CONF_SERCOM_1_USART_RXEN +#define CONF_SERCOM_1_USART_RXEN 1 +#endif + +// <q> Transmitt buffer enable +// <i> Enable output buffer in SERCOM module +// <id> usart_tx_enable +#ifndef CONF_SERCOM_1_USART_TXEN +#define CONF_SERCOM_1_USART_TXEN 1 +#endif + +// <o> Frame parity +// <0x1=>Even parity +// <i> Parity bit mode for USART frame +// <id> usart_parity +#ifndef CONF_SERCOM_1_USART_PARITY +#define CONF_SERCOM_1_USART_PARITY 1 +#endif + +// <o> Character Size +// <0x0=>8 bits +// <0x1=>9 bits +// <0x5=>5 bits +// <0x6=>6 bits +// <0x7=>7 bits +// <i> Data character size in USART frame +// <id> usart_character_size +#ifndef CONF_SERCOM_1_USART_CHSIZE +#define CONF_SERCOM_1_USART_CHSIZE 0x0 +#endif + +// <o> Stop Bit +// <0=>One stop bit +// <1=>Two stop bits +// <i> Number of stop bits in USART frame +// <id> usart_stop_bit +#ifndef CONF_SERCOM_1_USART_SBMODE +#define CONF_SERCOM_1_USART_SBMODE 1 +#endif + +// <o> Baud rate <1-3000000> +// <i> USART baud rate setting +// <id> usart_baud_rate +#ifndef CONF_SERCOM_1_USART_BAUD +#define CONF_SERCOM_1_USART_BAUD 6720 +#endif +// </h> + +// <h> ISO7816 configuration +// <o> ISO7816 Protocol Type +// <0x1=> T=0 +// <0x0=> T=1 +// <i> Define ISO7816 protocol type as 0. +// <id> usart_iso7816_type +#ifndef CONF_SERCOM_1_USART_ISO7816_PROTOCOL_T +#define CONF_SERCOM_1_USART_ISO7816_PROTOCOL_T 0x0 +#endif + +// <o> ISO7816 Inhibit Not Acknowledge +// <0x0=> NACK is transmitted when a parity error is received. +// <0x1=> NACK is not transmitted when a parity error is received. +// <i> Define whether a NACK is transmitted when a parity error is received. +// <id> usart_inack +#ifndef CONF_SERCOM_1_USART_INACK +#define CONF_SERCOM_1_USART_INACK 0x0 +#endif + +// <o> ISO7816 Disable Successive Not Acknowledge +// <0x0=> The successive receive NACK is disable. +// <0x1=> The successive receive NACK is enable. +// <i> Define whether NACK will be sent on parity error reception. +// <id> usart_dsnack +#ifndef CONF_SERCOM_1_USART_DSNACK +#define CONF_SERCOM_1_USART_DSNACK 0x0 +#endif + +// <o> ISO7816 Maximum Iterations<0-7> +// <i> Define the maximum number of retransmit iterations. +// <id> usart_maxiter +#ifndef CONF_SERCOM_1_USART_MAXITER +#define CONF_SERCOM_1_USART_MAXITER 0x7 +#endif + +// <o> ISO7816 Guard Time +// <0x2=> 2-bit times +// <0x3=> 3-bit times +// <0x4=> 4-bit times +// <0x5=> 5-bit times +// <0x6=> 6-bit times +// <0x7=> 7-bit times +// <i> Define the guard time. +// <id> usart_gtime +#ifndef CONF_SERCOM_1_USART_GTIME +#define CONF_SERCOM_1_USART_GTIME 0x2 +#endif + +// <q> Inverse transmission and reception enabled +// <i> Define inverse transmission and reception enabled. +// <id> usart_inverse_enabled +#ifndef CONF_SERCOM_1_USART_INVERSE_ENABLED +#define CONF_SERCOM_1_USART_INVERSE_ENABLED 0x0 +#endif + +#if (CONF_SERCOM_1_USART_INVERSE_ENABLED == 1) +#define CONF_SERCOM_1_USART_RXINV 0x1 +#define CONF_SERCOM_1_USART_TXINV 0x1 +#else +#define CONF_SERCOM_1_USART_RXINV 0x0 +#define CONF_SERCOM_1_USART_TXINV 0x0 +#endif + +// </h> + +// <e> Advanced configuration +// <id> usart_advanced +#ifndef CONF_SERCOM_1_USART_ADVANCED_CONFIG +#define CONF_SERCOM_1_USART_ADVANCED_CONFIG 0 +#endif + +// <q> Run in stand-by +// <i> Keep the module running in standby sleep mode +// <id> usart_arch_runstdby +#ifndef CONF_SERCOM_1_USART_RUNSTDBY +#define CONF_SERCOM_1_USART_RUNSTDBY 0 +#endif + +// <q> Immediate Buffer Overflow Notification +// <i> Controls when the BUFOVF status bit is asserted +// <id> usart_arch_ibon +#ifndef CONF_SERCOM_1_USART_IBON +#define CONF_SERCOM_1_USART_IBON 0 +#endif + +// <q> Start of Frame Detection Enable +// <i> Will wake the device from any sleep mode if usart_init and usart_enable was run priort to going to sleep. (receive buffer must be enabled) +// <id> usart_arch_sfde +#ifndef CONF_SERCOM_1_USART_SFDE +#define CONF_SERCOM_1_USART_SFDE 0 +#endif + +// <q> Collision Detection Enable +// <i> Collision detection enable +// <id> usart_arch_cloden +#ifndef CONF_SERCOM_1_USART_CLODEN +#define CONF_SERCOM_1_USART_CLODEN 0 +#endif + +// <o> Operating Mode +// <0x1=>USART with internal clock +// <i> Drive the shift register by an internal clock generated by the baud rate generator. +// <id> usart_arch_clock_mode +#ifndef CONF_SERCOM_1_USART_MODE +#define CONF_SERCOM_1_USART_MODE 0x1 +#endif + +// <o> Data Order +// <0=>MSB is transmitted first +// <1=>LSB is transmitted first +// <i> Data order of the data bits in the frame +// <id> usart_arch_dord +#ifndef CONF_SERCOM_1_USART_DORD +#define CONF_SERCOM_1_USART_DORD 1 +#endif + +// <o> Debug Stop Mode +// <i> Behavior of the baud-rate generator when CPU is halted by external debugger. +// <0=>Keep running +// <1=>Halt +// <id> usart_arch_dbgstop +#ifndef CONF_SERCOM_1_USART_DEBUG_STOP_MODE +#define CONF_SERCOM_1_USART_DEBUG_STOP_MODE 0 +#endif + +// Does not do anything in USRT mode +#define CONF_SERCOM_1_USART_SAMPR 0x0 +#define CONF_SERCOM_1_USART_SAMPA 0x0 +#define CONF_SERCOM_1_USART_FRACTIONAL 0x0 + +// Does not do anything in UART mode +#define CONF_SERCOM_1_USART_CPOL 0 + +// Does not do anything in USRT mode +#define CONF_SERCOM_1_USART_ENC 0 + +// </e> + +#ifndef CONF_SERCOM_1_USART_CMODE +#define CONF_SERCOM_1_USART_CMODE CONF_SERCOM_1_USART_ISO7816_PROTOCOL_T +#endif + +/* RX is on PIN_PA16 */ +#ifndef CONF_SERCOM_1_USART_RXPO +#define CONF_SERCOM_1_USART_RXPO 0 +#endif + +/* TX uses the same pin with RX */ +#ifndef CONF_SERCOM_1_USART_TXPO +#define CONF_SERCOM_1_USART_TXPO 2 +#endif + +/* Set iso7816 mode */ +#define CONF_SERCOM_1_USART_PMODE (CONF_SERCOM_1_USART_PARITY - 1) +#define CONF_SERCOM_1_USART_FORM 7 + +#if CONF_SERCOM_1_USART_CMODE == 0 +// Calculate BAUD register value in UART mode +#if CONF_SERCOM_1_USART_SAMPR == 0 +#ifndef CONF_SERCOM_1_USART_BAUD_RATE +#define CONF_SERCOM_1_USART_BAUD_RATE \ + 65536 - ((65536 * 16.0f * CONF_SERCOM_1_USART_BAUD) / CONF_GCLK_SERCOM1_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_1_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_1_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_1_USART_SAMPR == 1 +#ifndef CONF_SERCOM_1_USART_BAUD_RATE +#define CONF_SERCOM_1_USART_BAUD_RATE \ + ((CONF_GCLK_SERCOM1_CORE_FREQUENCY) / (CONF_SERCOM_1_USART_BAUD * 16)) - (CONF_SERCOM_1_USART_FRACTIONAL / 8) +#endif +#ifndef CONF_SERCOM_1_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_1_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_1_USART_SAMPR == 2 +#ifndef CONF_SERCOM_1_USART_BAUD_RATE +#define CONF_SERCOM_1_USART_BAUD_RATE \ + 65536 - ((65536 * 8.0f * CONF_SERCOM_1_USART_BAUD) / CONF_GCLK_SERCOM1_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_1_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_1_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_1_USART_SAMPR == 3 +#ifndef CONF_SERCOM_1_USART_BAUD_RATE +#define CONF_SERCOM_1_USART_BAUD_RATE \ + ((CONF_GCLK_SERCOM1_CORE_FREQUENCY) / (CONF_SERCOM_1_USART_BAUD * 8)) - (CONF_SERCOM_1_USART_FRACTIONAL / 8) +#endif +#ifndef CONF_SERCOM_1_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_1_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_1_USART_SAMPR == 4 +#ifndef CONF_SERCOM_1_USART_BAUD_RATE +#define CONF_SERCOM_1_USART_BAUD_RATE \ + 65536 - ((65536 * 3.0f * CONF_SERCOM_1_USART_BAUD) / CONF_GCLK_SERCOM1_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_1_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_1_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#endif + +#elif CONF_SERCOM_1_USART_CMODE == 1 +#ifndef CONF_SERCOM_1_USART_BAUD_RATE +// Calculate BAUD register value in USRT mode +#define CONF_SERCOM_1_USART_BAUD_RATE (CONF_GCLK_SERCOM1_CORE_FREQUENCY) / (2 * CONF_SERCOM_1_USART_BAUD) - 1 +#endif + +#ifndef CONF_SERCOM_1_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_1_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#else +#error CMODE value for SERCOM 1 in USART mode not known +#endif + +#include <peripheral_clk_config.h> + +#ifndef CONF_SERCOM_2_USART_ENABLE +#define CONF_SERCOM_2_USART_ENABLE 1 +#endif + +// <h> Basic Configuration + +// <q> Receive buffer enable +// <i> Enable input buffer in SERCOM module +// <id> usart_rx_enable +#ifndef CONF_SERCOM_2_USART_RXEN +#define CONF_SERCOM_2_USART_RXEN 1 +#endif + +// <q> Transmitt buffer enable +// <i> Enable output buffer in SERCOM module +// <id> usart_tx_enable +#ifndef CONF_SERCOM_2_USART_TXEN +#define CONF_SERCOM_2_USART_TXEN 1 +#endif + +// <o> Frame parity +// <0x1=>Even parity +// <i> Parity bit mode for USART frame +// <id> usart_parity +#ifndef CONF_SERCOM_2_USART_PARITY +#define CONF_SERCOM_2_USART_PARITY 1 +#endif + +// <o> Character Size +// <0x0=>8 bits +// <0x1=>9 bits +// <0x5=>5 bits +// <0x6=>6 bits +// <0x7=>7 bits +// <i> Data character size in USART frame +// <id> usart_character_size +#ifndef CONF_SERCOM_2_USART_CHSIZE +#define CONF_SERCOM_2_USART_CHSIZE 0x0 +#endif + +// <o> Stop Bit +// <0=>One stop bit +// <1=>Two stop bits +// <i> Number of stop bits in USART frame +// <id> usart_stop_bit +#ifndef CONF_SERCOM_2_USART_SBMODE +#define CONF_SERCOM_2_USART_SBMODE 1 +#endif + +// <o> Baud rate <1-3000000> +// <i> USART baud rate setting +// <id> usart_baud_rate +#ifndef CONF_SERCOM_2_USART_BAUD +#define CONF_SERCOM_2_USART_BAUD 6720 +#endif +// </h> + +// <h> ISO7816 configuration +// <o> ISO7816 Protocol Type +// <0x1=> T=0 +// <0x0=> T=1 +// <i> Define ISO7816 protocol type as 0. +// <id> usart_iso7816_type +#ifndef CONF_SERCOM_2_USART_ISO7816_PROTOCOL_T +#define CONF_SERCOM_2_USART_ISO7816_PROTOCOL_T 0x0 +#endif + +// <o> ISO7816 Inhibit Not Acknowledge +// <0x0=> NACK is transmitted when a parity error is received. +// <0x1=> NACK is not transmitted when a parity error is received. +// <i> Define whether a NACK is transmitted when a parity error is received. +// <id> usart_inack +#ifndef CONF_SERCOM_2_USART_INACK +#define CONF_SERCOM_2_USART_INACK 0x0 +#endif + +// <o> ISO7816 Disable Successive Not Acknowledge +// <0x0=> The successive receive NACK is disable. +// <0x1=> The successive receive NACK is enable. +// <i> Define whether NACK will be sent on parity error reception. +// <id> usart_dsnack +#ifndef CONF_SERCOM_2_USART_DSNACK +#define CONF_SERCOM_2_USART_DSNACK 0x0 +#endif + +// <o> ISO7816 Maximum Iterations<0-7> +// <i> Define the maximum number of retransmit iterations. +// <id> usart_maxiter +#ifndef CONF_SERCOM_2_USART_MAXITER +#define CONF_SERCOM_2_USART_MAXITER 0x7 +#endif + +// <o> ISO7816 Guard Time +// <0x2=> 2-bit times +// <0x3=> 3-bit times +// <0x4=> 4-bit times +// <0x5=> 5-bit times +// <0x6=> 6-bit times +// <0x7=> 7-bit times +// <i> Define the guard time. +// <id> usart_gtime +#ifndef CONF_SERCOM_2_USART_GTIME +#define CONF_SERCOM_2_USART_GTIME 0x2 +#endif + +// <q> Inverse transmission and reception enabled +// <i> Define inverse transmission and reception enabled. +// <id> usart_inverse_enabled +#ifndef CONF_SERCOM_2_USART_INVERSE_ENABLED +#define CONF_SERCOM_2_USART_INVERSE_ENABLED 0x0 +#endif + +#if (CONF_SERCOM_2_USART_INVERSE_ENABLED == 1) +#define CONF_SERCOM_2_USART_RXINV 0x1 +#define CONF_SERCOM_2_USART_TXINV 0x1 +#else +#define CONF_SERCOM_2_USART_RXINV 0x0 +#define CONF_SERCOM_2_USART_TXINV 0x0 +#endif + +// </h> + +// <e> Advanced configuration +// <id> usart_advanced +#ifndef CONF_SERCOM_2_USART_ADVANCED_CONFIG +#define CONF_SERCOM_2_USART_ADVANCED_CONFIG 0 +#endif + +// <q> Run in stand-by +// <i> Keep the module running in standby sleep mode +// <id> usart_arch_runstdby +#ifndef CONF_SERCOM_2_USART_RUNSTDBY +#define CONF_SERCOM_2_USART_RUNSTDBY 0 +#endif + +// <q> Immediate Buffer Overflow Notification +// <i> Controls when the BUFOVF status bit is asserted +// <id> usart_arch_ibon +#ifndef CONF_SERCOM_2_USART_IBON +#define CONF_SERCOM_2_USART_IBON 0 +#endif + +// <q> Start of Frame Detection Enable +// <i> Will wake the device from any sleep mode if usart_init and usart_enable was run priort to going to sleep. (receive buffer must be enabled) +// <id> usart_arch_sfde +#ifndef CONF_SERCOM_2_USART_SFDE +#define CONF_SERCOM_2_USART_SFDE 0 +#endif + +// <q> Collision Detection Enable +// <i> Collision detection enable +// <id> usart_arch_cloden +#ifndef CONF_SERCOM_2_USART_CLODEN +#define CONF_SERCOM_2_USART_CLODEN 0 +#endif + +// <o> Operating Mode +// <0x1=>USART with internal clock +// <i> Drive the shift register by an internal clock generated by the baud rate generator. +// <id> usart_arch_clock_mode +#ifndef CONF_SERCOM_2_USART_MODE +#define CONF_SERCOM_2_USART_MODE 0x1 +#endif + +// <o> Data Order +// <0=>MSB is transmitted first +// <1=>LSB is transmitted first +// <i> Data order of the data bits in the frame +// <id> usart_arch_dord +#ifndef CONF_SERCOM_2_USART_DORD +#define CONF_SERCOM_2_USART_DORD 1 +#endif + +// <o> Debug Stop Mode +// <i> Behavior of the baud-rate generator when CPU is halted by external debugger. +// <0=>Keep running +// <1=>Halt +// <id> usart_arch_dbgstop +#ifndef CONF_SERCOM_2_USART_DEBUG_STOP_MODE +#define CONF_SERCOM_2_USART_DEBUG_STOP_MODE 0 +#endif + +// Does not do anything in USRT mode +#define CONF_SERCOM_2_USART_SAMPR 0x0 +#define CONF_SERCOM_2_USART_SAMPA 0x0 +#define CONF_SERCOM_2_USART_FRACTIONAL 0x0 + +// Does not do anything in UART mode +#define CONF_SERCOM_2_USART_CPOL 0 + +// Does not do anything in USRT mode +#define CONF_SERCOM_2_USART_ENC 0 + +// </e> + +#ifndef CONF_SERCOM_2_USART_CMODE +#define CONF_SERCOM_2_USART_CMODE CONF_SERCOM_2_USART_ISO7816_PROTOCOL_T +#endif + +/* RX is on PIN_PA09 */ +#ifndef CONF_SERCOM_2_USART_RXPO +#define CONF_SERCOM_2_USART_RXPO 0 +#endif + +/* TX uses the same pin with RX */ +#ifndef CONF_SERCOM_2_USART_TXPO +#define CONF_SERCOM_2_USART_TXPO 2 +#endif + +/* Set iso7816 mode */ +#define CONF_SERCOM_2_USART_PMODE (CONF_SERCOM_2_USART_PARITY - 1) +#define CONF_SERCOM_2_USART_FORM 7 + +#if CONF_SERCOM_2_USART_CMODE == 0 +// Calculate BAUD register value in UART mode +#if CONF_SERCOM_2_USART_SAMPR == 0 +#ifndef CONF_SERCOM_2_USART_BAUD_RATE +#define CONF_SERCOM_2_USART_BAUD_RATE \ + 65536 - ((65536 * 16.0f * CONF_SERCOM_2_USART_BAUD) / CONF_GCLK_SERCOM2_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_2_USART_SAMPR == 1 +#ifndef CONF_SERCOM_2_USART_BAUD_RATE +#define CONF_SERCOM_2_USART_BAUD_RATE \ + ((CONF_GCLK_SERCOM2_CORE_FREQUENCY) / (CONF_SERCOM_2_USART_BAUD * 16)) - (CONF_SERCOM_2_USART_FRACTIONAL / 8) +#endif +#ifndef CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_2_USART_SAMPR == 2 +#ifndef CONF_SERCOM_2_USART_BAUD_RATE +#define CONF_SERCOM_2_USART_BAUD_RATE \ + 65536 - ((65536 * 8.0f * CONF_SERCOM_2_USART_BAUD) / CONF_GCLK_SERCOM2_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_2_USART_SAMPR == 3 +#ifndef CONF_SERCOM_2_USART_BAUD_RATE +#define CONF_SERCOM_2_USART_BAUD_RATE \ + ((CONF_GCLK_SERCOM2_CORE_FREQUENCY) / (CONF_SERCOM_2_USART_BAUD * 8)) - (CONF_SERCOM_2_USART_FRACTIONAL / 8) +#endif +#ifndef CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_2_USART_SAMPR == 4 +#ifndef CONF_SERCOM_2_USART_BAUD_RATE +#define CONF_SERCOM_2_USART_BAUD_RATE \ + 65536 - ((65536 * 3.0f * CONF_SERCOM_2_USART_BAUD) / CONF_GCLK_SERCOM2_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#endif + +#elif CONF_SERCOM_2_USART_CMODE == 1 +#ifndef CONF_SERCOM_2_USART_BAUD_RATE +// Calculate BAUD register value in USRT mode +#define CONF_SERCOM_2_USART_BAUD_RATE (CONF_GCLK_SERCOM2_CORE_FREQUENCY) / (2 * CONF_SERCOM_2_USART_BAUD) - 1 +#endif + +#ifndef CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_2_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#else +#error CMODE value for SERCOM 2 in USART mode not known +#endif + +#include <peripheral_clk_config.h> + +#ifndef CONF_SERCOM_3_USART_ENABLE +#define CONF_SERCOM_3_USART_ENABLE 1 +#endif + +// <h> Basic Configuration + +// <q> Receive buffer enable +// <i> Enable input buffer in SERCOM module +// <id> usart_rx_enable +#ifndef CONF_SERCOM_3_USART_RXEN +#define CONF_SERCOM_3_USART_RXEN 1 +#endif + +// <q> Transmitt buffer enable +// <i> Enable output buffer in SERCOM module +// <id> usart_tx_enable +#ifndef CONF_SERCOM_3_USART_TXEN +#define CONF_SERCOM_3_USART_TXEN 1 +#endif + +// <o> Frame parity +// <0x1=>Even parity +// <i> Parity bit mode for USART frame +// <id> usart_parity +#ifndef CONF_SERCOM_3_USART_PARITY +#define CONF_SERCOM_3_USART_PARITY 1 +#endif + +// <o> Character Size +// <0x0=>8 bits +// <0x1=>9 bits +// <0x5=>5 bits +// <0x6=>6 bits +// <0x7=>7 bits +// <i> Data character size in USART frame +// <id> usart_character_size +#ifndef CONF_SERCOM_3_USART_CHSIZE +#define CONF_SERCOM_3_USART_CHSIZE 0x0 +#endif + +// <o> Stop Bit +// <0=>One stop bit +// <1=>Two stop bits +// <i> Number of stop bits in USART frame +// <id> usart_stop_bit +#ifndef CONF_SERCOM_3_USART_SBMODE +#define CONF_SERCOM_3_USART_SBMODE 1 +#endif + +// <o> Baud rate <1-3000000> +// <i> USART baud rate setting +// <id> usart_baud_rate +#ifndef CONF_SERCOM_3_USART_BAUD +#define CONF_SERCOM_3_USART_BAUD 6720 +#endif +// </h> + +// <h> ISO7816 configuration +// <o> ISO7816 Protocol Type +// <0x1=> T=0 +// <0x0=> T=1 +// <i> Define ISO7816 protocol type as 0. +// <id> usart_iso7816_type +#ifndef CONF_SERCOM_3_USART_ISO7816_PROTOCOL_T +#define CONF_SERCOM_3_USART_ISO7816_PROTOCOL_T 0x0 +#endif + +// <o> ISO7816 Inhibit Not Acknowledge +// <0x0=> NACK is transmitted when a parity error is received. +// <0x1=> NACK is not transmitted when a parity error is received. +// <i> Define whether a NACK is transmitted when a parity error is received. +// <id> usart_inack +#ifndef CONF_SERCOM_3_USART_INACK +#define CONF_SERCOM_3_USART_INACK 0x0 +#endif + +// <o> ISO7816 Disable Successive Not Acknowledge +// <0x0=> The successive receive NACK is disable. +// <0x1=> The successive receive NACK is enable. +// <i> Define whether NACK will be sent on parity error reception. +// <id> usart_dsnack +#ifndef CONF_SERCOM_3_USART_DSNACK +#define CONF_SERCOM_3_USART_DSNACK 0x0 +#endif + +// <o> ISO7816 Maximum Iterations<0-7> +// <i> Define the maximum number of retransmit iterations. +// <id> usart_maxiter +#ifndef CONF_SERCOM_3_USART_MAXITER +#define CONF_SERCOM_3_USART_MAXITER 0x7 +#endif + +// <o> ISO7816 Guard Time +// <0x2=> 2-bit times +// <0x3=> 3-bit times +// <0x4=> 4-bit times +// <0x5=> 5-bit times +// <0x6=> 6-bit times +// <0x7=> 7-bit times +// <i> Define the guard time. +// <id> usart_gtime +#ifndef CONF_SERCOM_3_USART_GTIME +#define CONF_SERCOM_3_USART_GTIME 0x2 +#endif + +// <q> Inverse transmission and reception enabled +// <i> Define inverse transmission and reception enabled. +// <id> usart_inverse_enabled +#ifndef CONF_SERCOM_3_USART_INVERSE_ENABLED +#define CONF_SERCOM_3_USART_INVERSE_ENABLED 0x0 +#endif + +#if (CONF_SERCOM_3_USART_INVERSE_ENABLED == 1) +#define CONF_SERCOM_3_USART_RXINV 0x1 +#define CONF_SERCOM_3_USART_TXINV 0x1 +#else +#define CONF_SERCOM_3_USART_RXINV 0x0 +#define CONF_SERCOM_3_USART_TXINV 0x0 +#endif + +// </h> + +// <e> Advanced configuration +// <id> usart_advanced +#ifndef CONF_SERCOM_3_USART_ADVANCED_CONFIG +#define CONF_SERCOM_3_USART_ADVANCED_CONFIG 0 +#endif + +// <q> Run in stand-by +// <i> Keep the module running in standby sleep mode +// <id> usart_arch_runstdby +#ifndef CONF_SERCOM_3_USART_RUNSTDBY +#define CONF_SERCOM_3_USART_RUNSTDBY 0 +#endif + +// <q> Immediate Buffer Overflow Notification +// <i> Controls when the BUFOVF status bit is asserted +// <id> usart_arch_ibon +#ifndef CONF_SERCOM_3_USART_IBON +#define CONF_SERCOM_3_USART_IBON 0 +#endif + +// <q> Start of Frame Detection Enable +// <i> Will wake the device from any sleep mode if usart_init and usart_enable was run priort to going to sleep. (receive buffer must be enabled) +// <id> usart_arch_sfde +#ifndef CONF_SERCOM_3_USART_SFDE +#define CONF_SERCOM_3_USART_SFDE 0 +#endif + +// <q> Collision Detection Enable +// <i> Collision detection enable +// <id> usart_arch_cloden +#ifndef CONF_SERCOM_3_USART_CLODEN +#define CONF_SERCOM_3_USART_CLODEN 0 +#endif + +// <o> Operating Mode +// <0x1=>USART with internal clock +// <i> Drive the shift register by an internal clock generated by the baud rate generator. +// <id> usart_arch_clock_mode +#ifndef CONF_SERCOM_3_USART_MODE +#define CONF_SERCOM_3_USART_MODE 0x1 +#endif + +// <o> Data Order +// <0=>MSB is transmitted first +// <1=>LSB is transmitted first +// <i> Data order of the data bits in the frame +// <id> usart_arch_dord +#ifndef CONF_SERCOM_3_USART_DORD +#define CONF_SERCOM_3_USART_DORD 1 +#endif + +// <o> Debug Stop Mode +// <i> Behavior of the baud-rate generator when CPU is halted by external debugger. +// <0=>Keep running +// <1=>Halt +// <id> usart_arch_dbgstop +#ifndef CONF_SERCOM_3_USART_DEBUG_STOP_MODE +#define CONF_SERCOM_3_USART_DEBUG_STOP_MODE 0 +#endif + +// Does not do anything in USRT mode +#define CONF_SERCOM_3_USART_SAMPR 0x0 +#define CONF_SERCOM_3_USART_SAMPA 0x0 +#define CONF_SERCOM_3_USART_FRACTIONAL 0x0 + +// Does not do anything in UART mode +#define CONF_SERCOM_3_USART_CPOL 0 + +// Does not do anything in USRT mode +#define CONF_SERCOM_3_USART_ENC 0 + +// </e> + +#ifndef CONF_SERCOM_3_USART_CMODE +#define CONF_SERCOM_3_USART_CMODE CONF_SERCOM_3_USART_ISO7816_PROTOCOL_T +#endif + +/* RX is on PIN_PB20 */ +#ifndef CONF_SERCOM_3_USART_RXPO +#define CONF_SERCOM_3_USART_RXPO 0 +#endif + +/* TX uses the same pin with RX */ +#ifndef CONF_SERCOM_3_USART_TXPO +#define CONF_SERCOM_3_USART_TXPO 2 +#endif + +/* Set iso7816 mode */ +#define CONF_SERCOM_3_USART_PMODE (CONF_SERCOM_3_USART_PARITY - 1) +#define CONF_SERCOM_3_USART_FORM 7 + +#if CONF_SERCOM_3_USART_CMODE == 0 +// Calculate BAUD register value in UART mode +#if CONF_SERCOM_3_USART_SAMPR == 0 +#ifndef CONF_SERCOM_3_USART_BAUD_RATE +#define CONF_SERCOM_3_USART_BAUD_RATE \ + 65536 - ((65536 * 16.0f * CONF_SERCOM_3_USART_BAUD) / CONF_GCLK_SERCOM3_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_3_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_3_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_3_USART_SAMPR == 1 +#ifndef CONF_SERCOM_3_USART_BAUD_RATE +#define CONF_SERCOM_3_USART_BAUD_RATE \ + ((CONF_GCLK_SERCOM3_CORE_FREQUENCY) / (CONF_SERCOM_3_USART_BAUD * 16)) - (CONF_SERCOM_3_USART_FRACTIONAL / 8) +#endif +#ifndef CONF_SERCOM_3_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_3_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_3_USART_SAMPR == 2 +#ifndef CONF_SERCOM_3_USART_BAUD_RATE +#define CONF_SERCOM_3_USART_BAUD_RATE \ + 65536 - ((65536 * 8.0f * CONF_SERCOM_3_USART_BAUD) / CONF_GCLK_SERCOM3_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_3_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_3_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_3_USART_SAMPR == 3 +#ifndef CONF_SERCOM_3_USART_BAUD_RATE +#define CONF_SERCOM_3_USART_BAUD_RATE \ + ((CONF_GCLK_SERCOM3_CORE_FREQUENCY) / (CONF_SERCOM_3_USART_BAUD * 8)) - (CONF_SERCOM_3_USART_FRACTIONAL / 8) +#endif +#ifndef CONF_SERCOM_3_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_3_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_3_USART_SAMPR == 4 +#ifndef CONF_SERCOM_3_USART_BAUD_RATE +#define CONF_SERCOM_3_USART_BAUD_RATE \ + 65536 - ((65536 * 3.0f * CONF_SERCOM_3_USART_BAUD) / CONF_GCLK_SERCOM3_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_3_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_3_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#endif + +#elif CONF_SERCOM_3_USART_CMODE == 1 +#ifndef CONF_SERCOM_3_USART_BAUD_RATE +// Calculate BAUD register value in USRT mode +#define CONF_SERCOM_3_USART_BAUD_RATE (CONF_GCLK_SERCOM3_CORE_FREQUENCY) / (2 * CONF_SERCOM_3_USART_BAUD) - 1 +#endif + +#ifndef CONF_SERCOM_3_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_3_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#else +#error CMODE value for SERCOM 3 in USART mode not known +#endif + +#include <peripheral_clk_config.h> + +#ifndef CONF_SERCOM_4_USART_ENABLE +#define CONF_SERCOM_4_USART_ENABLE 1 +#endif + +// <h> Basic Configuration + +// <q> Receive buffer enable +// <i> Enable input buffer in SERCOM module +// <id> usart_rx_enable +#ifndef CONF_SERCOM_4_USART_RXEN +#define CONF_SERCOM_4_USART_RXEN 1 +#endif + +// <q> Transmitt buffer enable +// <i> Enable output buffer in SERCOM module +// <id> usart_tx_enable +#ifndef CONF_SERCOM_4_USART_TXEN +#define CONF_SERCOM_4_USART_TXEN 1 +#endif + +// <o> Frame parity +// <0x1=>Even parity +// <i> Parity bit mode for USART frame +// <id> usart_parity +#ifndef CONF_SERCOM_4_USART_PARITY +#define CONF_SERCOM_4_USART_PARITY 1 +#endif + +// <o> Character Size +// <0x0=>8 bits +// <0x1=>9 bits +// <0x5=>5 bits +// <0x6=>6 bits +// <0x7=>7 bits +// <i> Data character size in USART frame +// <id> usart_character_size +#ifndef CONF_SERCOM_4_USART_CHSIZE +#define CONF_SERCOM_4_USART_CHSIZE 0x0 +#endif + +// <o> Stop Bit +// <0=>One stop bit +// <1=>Two stop bits +// <i> Number of stop bits in USART frame +// <id> usart_stop_bit +#ifndef CONF_SERCOM_4_USART_SBMODE +#define CONF_SERCOM_4_USART_SBMODE 1 +#endif + +// <o> Baud rate <1-3000000> +// <i> USART baud rate setting +// <id> usart_baud_rate +#ifndef CONF_SERCOM_4_USART_BAUD +#define CONF_SERCOM_4_USART_BAUD 6720 +#endif +// </h> + +// <h> ISO7816 configuration +// <o> ISO7816 Protocol Type +// <0x1=> T=0 +// <0x0=> T=1 +// <i> Define ISO7816 protocol type as 0. +// <id> usart_iso7816_type +#ifndef CONF_SERCOM_4_USART_ISO7816_PROTOCOL_T +#define CONF_SERCOM_4_USART_ISO7816_PROTOCOL_T 0x0 +#endif + +// <o> ISO7816 Inhibit Not Acknowledge +// <0x0=> NACK is transmitted when a parity error is received. +// <0x1=> NACK is not transmitted when a parity error is received. +// <i> Define whether a NACK is transmitted when a parity error is received. +// <id> usart_inack +#ifndef CONF_SERCOM_4_USART_INACK +#define CONF_SERCOM_4_USART_INACK 0x0 +#endif + +// <o> ISO7816 Disable Successive Not Acknowledge +// <0x0=> The successive receive NACK is disable. +// <0x1=> The successive receive NACK is enable. +// <i> Define whether NACK will be sent on parity error reception. +// <id> usart_dsnack +#ifndef CONF_SERCOM_4_USART_DSNACK +#define CONF_SERCOM_4_USART_DSNACK 0x0 +#endif + +// <o> ISO7816 Maximum Iterations<0-7> +// <i> Define the maximum number of retransmit iterations. +// <id> usart_maxiter +#ifndef CONF_SERCOM_4_USART_MAXITER +#define CONF_SERCOM_4_USART_MAXITER 0x7 +#endif + +// <o> ISO7816 Guard Time +// <0x2=> 2-bit times +// <0x3=> 3-bit times +// <0x4=> 4-bit times +// <0x5=> 5-bit times +// <0x6=> 6-bit times +// <0x7=> 7-bit times +// <i> Define the guard time. +// <id> usart_gtime +#ifndef CONF_SERCOM_4_USART_GTIME +#define CONF_SERCOM_4_USART_GTIME 0x2 +#endif + +// <q> Inverse transmission and reception enabled +// <i> Define inverse transmission and reception enabled. +// <id> usart_inverse_enabled +#ifndef CONF_SERCOM_4_USART_INVERSE_ENABLED +#define CONF_SERCOM_4_USART_INVERSE_ENABLED 0x0 +#endif + +#if (CONF_SERCOM_4_USART_INVERSE_ENABLED == 1) +#define CONF_SERCOM_4_USART_RXINV 0x1 +#define CONF_SERCOM_4_USART_TXINV 0x1 +#else +#define CONF_SERCOM_4_USART_RXINV 0x0 +#define CONF_SERCOM_4_USART_TXINV 0x0 +#endif + +// </h> + +// <e> Advanced configuration +// <id> usart_advanced +#ifndef CONF_SERCOM_4_USART_ADVANCED_CONFIG +#define CONF_SERCOM_4_USART_ADVANCED_CONFIG 0 +#endif + +// <q> Run in stand-by +// <i> Keep the module running in standby sleep mode +// <id> usart_arch_runstdby +#ifndef CONF_SERCOM_4_USART_RUNSTDBY +#define CONF_SERCOM_4_USART_RUNSTDBY 0 +#endif + +// <q> Immediate Buffer Overflow Notification +// <i> Controls when the BUFOVF status bit is asserted +// <id> usart_arch_ibon +#ifndef CONF_SERCOM_4_USART_IBON +#define CONF_SERCOM_4_USART_IBON 0 +#endif + +// <q> Start of Frame Detection Enable +// <i> Will wake the device from any sleep mode if usart_init and usart_enable was run priort to going to sleep. (receive buffer must be enabled) +// <id> usart_arch_sfde +#ifndef CONF_SERCOM_4_USART_SFDE +#define CONF_SERCOM_4_USART_SFDE 0 +#endif + +// <q> Collision Detection Enable +// <i> Collision detection enable +// <id> usart_arch_cloden +#ifndef CONF_SERCOM_4_USART_CLODEN +#define CONF_SERCOM_4_USART_CLODEN 0 +#endif + +// <o> Operating Mode +// <0x1=>USART with internal clock +// <i> Drive the shift register by an internal clock generated by the baud rate generator. +// <id> usart_arch_clock_mode +#ifndef CONF_SERCOM_4_USART_MODE +#define CONF_SERCOM_4_USART_MODE 0x1 +#endif + +// <o> Data Order +// <0=>MSB is transmitted first +// <1=>LSB is transmitted first +// <i> Data order of the data bits in the frame +// <id> usart_arch_dord +#ifndef CONF_SERCOM_4_USART_DORD +#define CONF_SERCOM_4_USART_DORD 1 +#endif + +// <o> Debug Stop Mode +// <i> Behavior of the baud-rate generator when CPU is halted by external debugger. +// <0=>Keep running +// <1=>Halt +// <id> usart_arch_dbgstop +#ifndef CONF_SERCOM_4_USART_DEBUG_STOP_MODE +#define CONF_SERCOM_4_USART_DEBUG_STOP_MODE 0 +#endif + +// Does not do anything in USRT mode +#define CONF_SERCOM_4_USART_SAMPR 0x0 +#define CONF_SERCOM_4_USART_SAMPA 0x0 +#define CONF_SERCOM_4_USART_FRACTIONAL 0x0 + +// Does not do anything in UART mode +#define CONF_SERCOM_4_USART_CPOL 0 + +// Does not do anything in USRT mode +#define CONF_SERCOM_4_USART_ENC 0 + +// </e> + +#ifndef CONF_SERCOM_4_USART_CMODE +#define CONF_SERCOM_4_USART_CMODE CONF_SERCOM_4_USART_ISO7816_PROTOCOL_T +#endif + +/* RX is on PIN_PB08 */ +#ifndef CONF_SERCOM_4_USART_RXPO +#define CONF_SERCOM_4_USART_RXPO 0 +#endif + +/* TX uses the same pin with RX */ +#ifndef CONF_SERCOM_4_USART_TXPO +#define CONF_SERCOM_4_USART_TXPO 2 +#endif + +/* Set iso7816 mode */ +#define CONF_SERCOM_4_USART_PMODE (CONF_SERCOM_4_USART_PARITY - 1) +#define CONF_SERCOM_4_USART_FORM 7 + +#if CONF_SERCOM_4_USART_CMODE == 0 +// Calculate BAUD register value in UART mode +#if CONF_SERCOM_4_USART_SAMPR == 0 +#ifndef CONF_SERCOM_4_USART_BAUD_RATE +#define CONF_SERCOM_4_USART_BAUD_RATE \ + 65536 - ((65536 * 16.0f * CONF_SERCOM_4_USART_BAUD) / CONF_GCLK_SERCOM4_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_4_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_4_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_4_USART_SAMPR == 1 +#ifndef CONF_SERCOM_4_USART_BAUD_RATE +#define CONF_SERCOM_4_USART_BAUD_RATE \ + ((CONF_GCLK_SERCOM4_CORE_FREQUENCY) / (CONF_SERCOM_4_USART_BAUD * 16)) - (CONF_SERCOM_4_USART_FRACTIONAL / 8) +#endif +#ifndef CONF_SERCOM_4_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_4_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_4_USART_SAMPR == 2 +#ifndef CONF_SERCOM_4_USART_BAUD_RATE +#define CONF_SERCOM_4_USART_BAUD_RATE \ + 65536 - ((65536 * 8.0f * CONF_SERCOM_4_USART_BAUD) / CONF_GCLK_SERCOM4_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_4_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_4_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_4_USART_SAMPR == 3 +#ifndef CONF_SERCOM_4_USART_BAUD_RATE +#define CONF_SERCOM_4_USART_BAUD_RATE \ + ((CONF_GCLK_SERCOM4_CORE_FREQUENCY) / (CONF_SERCOM_4_USART_BAUD * 8)) - (CONF_SERCOM_4_USART_FRACTIONAL / 8) +#endif +#ifndef CONF_SERCOM_4_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_4_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_4_USART_SAMPR == 4 +#ifndef CONF_SERCOM_4_USART_BAUD_RATE +#define CONF_SERCOM_4_USART_BAUD_RATE \ + 65536 - ((65536 * 3.0f * CONF_SERCOM_4_USART_BAUD) / CONF_GCLK_SERCOM4_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_4_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_4_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#endif + +#elif CONF_SERCOM_4_USART_CMODE == 1 +#ifndef CONF_SERCOM_4_USART_BAUD_RATE +// Calculate BAUD register value in USRT mode +#define CONF_SERCOM_4_USART_BAUD_RATE (CONF_GCLK_SERCOM4_CORE_FREQUENCY) / (2 * CONF_SERCOM_4_USART_BAUD) - 1 +#endif + +#ifndef CONF_SERCOM_4_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_4_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#else +#error CMODE value for SERCOM 4 in USART mode not known +#endif + +#include <peripheral_clk_config.h> + +#ifndef CONF_SERCOM_5_USART_ENABLE +#define CONF_SERCOM_5_USART_ENABLE 1 +#endif + +// <h> Basic Configuration + +// <q> Receive buffer enable +// <i> Enable input buffer in SERCOM module +// <id> usart_rx_enable +#ifndef CONF_SERCOM_5_USART_RXEN +#define CONF_SERCOM_5_USART_RXEN 1 +#endif + +// <q> Transmitt buffer enable +// <i> Enable output buffer in SERCOM module +// <id> usart_tx_enable +#ifndef CONF_SERCOM_5_USART_TXEN +#define CONF_SERCOM_5_USART_TXEN 1 +#endif + +// <o> Frame parity +// <0x1=>Even parity +// <i> Parity bit mode for USART frame +// <id> usart_parity +#ifndef CONF_SERCOM_5_USART_PARITY +#define CONF_SERCOM_5_USART_PARITY 1 +#endif + +// <o> Character Size +// <0x0=>8 bits +// <0x1=>9 bits +// <0x5=>5 bits +// <0x6=>6 bits +// <0x7=>7 bits +// <i> Data character size in USART frame +// <id> usart_character_size +#ifndef CONF_SERCOM_5_USART_CHSIZE +#define CONF_SERCOM_5_USART_CHSIZE 0x0 +#endif + +// <o> Stop Bit +// <0=>One stop bit +// <1=>Two stop bits +// <i> Number of stop bits in USART frame +// <id> usart_stop_bit +#ifndef CONF_SERCOM_5_USART_SBMODE +#define CONF_SERCOM_5_USART_SBMODE 1 +#endif + +// <o> Baud rate <1-3000000> +// <i> USART baud rate setting +// <id> usart_baud_rate +#ifndef CONF_SERCOM_5_USART_BAUD +#define CONF_SERCOM_5_USART_BAUD 6720 +#endif +// </h> + +// <h> ISO7816 configuration +// <o> ISO7816 Protocol Type +// <0x1=> T=0 +// <0x0=> T=1 +// <i> Define ISO7816 protocol type as 0. +// <id> usart_iso7816_type +#ifndef CONF_SERCOM_5_USART_ISO7816_PROTOCOL_T +#define CONF_SERCOM_5_USART_ISO7816_PROTOCOL_T 0x0 +#endif + +// <o> ISO7816 Inhibit Not Acknowledge +// <0x0=> NACK is transmitted when a parity error is received. +// <0x1=> NACK is not transmitted when a parity error is received. +// <i> Define whether a NACK is transmitted when a parity error is received. +// <id> usart_inack +#ifndef CONF_SERCOM_5_USART_INACK +#define CONF_SERCOM_5_USART_INACK 0x0 +#endif + +// <o> ISO7816 Disable Successive Not Acknowledge +// <0x0=> The successive receive NACK is disable. +// <0x1=> The successive receive NACK is enable. +// <i> Define whether NACK will be sent on parity error reception. +// <id> usart_dsnack +#ifndef CONF_SERCOM_5_USART_DSNACK +#define CONF_SERCOM_5_USART_DSNACK 0x0 +#endif + +// <o> ISO7816 Maximum Iterations<0-7> +// <i> Define the maximum number of retransmit iterations. +// <id> usart_maxiter +#ifndef CONF_SERCOM_5_USART_MAXITER +#define CONF_SERCOM_5_USART_MAXITER 0x7 +#endif + +// <o> ISO7816 Guard Time +// <0x2=> 2-bit times +// <0x3=> 3-bit times +// <0x4=> 4-bit times +// <0x5=> 5-bit times +// <0x6=> 6-bit times +// <0x7=> 7-bit times +// <i> Define the guard time. +// <id> usart_gtime +#ifndef CONF_SERCOM_5_USART_GTIME +#define CONF_SERCOM_5_USART_GTIME 0x2 +#endif + +// <q> Inverse transmission and reception enabled +// <i> Define inverse transmission and reception enabled. +// <id> usart_inverse_enabled +#ifndef CONF_SERCOM_5_USART_INVERSE_ENABLED +#define CONF_SERCOM_5_USART_INVERSE_ENABLED 0x0 +#endif + +#if (CONF_SERCOM_5_USART_INVERSE_ENABLED == 1) +#define CONF_SERCOM_5_USART_RXINV 0x1 +#define CONF_SERCOM_5_USART_TXINV 0x1 +#else +#define CONF_SERCOM_5_USART_RXINV 0x0 +#define CONF_SERCOM_5_USART_TXINV 0x0 +#endif + +// </h> + +// <e> Advanced configuration +// <id> usart_advanced +#ifndef CONF_SERCOM_5_USART_ADVANCED_CONFIG +#define CONF_SERCOM_5_USART_ADVANCED_CONFIG 0 +#endif + +// <q> Run in stand-by +// <i> Keep the module running in standby sleep mode +// <id> usart_arch_runstdby +#ifndef CONF_SERCOM_5_USART_RUNSTDBY +#define CONF_SERCOM_5_USART_RUNSTDBY 0 +#endif + +// <q> Immediate Buffer Overflow Notification +// <i> Controls when the BUFOVF status bit is asserted +// <id> usart_arch_ibon +#ifndef CONF_SERCOM_5_USART_IBON +#define CONF_SERCOM_5_USART_IBON 0 +#endif + +// <q> Start of Frame Detection Enable +// <i> Will wake the device from any sleep mode if usart_init and usart_enable was run priort to going to sleep. (receive buffer must be enabled) +// <id> usart_arch_sfde +#ifndef CONF_SERCOM_5_USART_SFDE +#define CONF_SERCOM_5_USART_SFDE 0 +#endif + +// <q> Collision Detection Enable +// <i> Collision detection enable +// <id> usart_arch_cloden +#ifndef CONF_SERCOM_5_USART_CLODEN +#define CONF_SERCOM_5_USART_CLODEN 0 +#endif + +// <o> Operating Mode +// <0x1=>USART with internal clock +// <i> Drive the shift register by an internal clock generated by the baud rate generator. +// <id> usart_arch_clock_mode +#ifndef CONF_SERCOM_5_USART_MODE +#define CONF_SERCOM_5_USART_MODE 0x1 +#endif + +// <o> Data Order +// <0=>MSB is transmitted first +// <1=>LSB is transmitted first +// <i> Data order of the data bits in the frame +// <id> usart_arch_dord +#ifndef CONF_SERCOM_5_USART_DORD +#define CONF_SERCOM_5_USART_DORD 1 +#endif + +// <o> Debug Stop Mode +// <i> Behavior of the baud-rate generator when CPU is halted by external debugger. +// <0=>Keep running +// <1=>Halt +// <id> usart_arch_dbgstop +#ifndef CONF_SERCOM_5_USART_DEBUG_STOP_MODE +#define CONF_SERCOM_5_USART_DEBUG_STOP_MODE 0 +#endif + +// Does not do anything in USRT mode +#define CONF_SERCOM_5_USART_SAMPR 0x0 +#define CONF_SERCOM_5_USART_SAMPA 0x0 +#define CONF_SERCOM_5_USART_FRACTIONAL 0x0 + +// Does not do anything in UART mode +#define CONF_SERCOM_5_USART_CPOL 0 + +// Does not do anything in USRT mode +#define CONF_SERCOM_5_USART_ENC 0 + +// </e> + +#ifndef CONF_SERCOM_5_USART_CMODE +#define CONF_SERCOM_5_USART_CMODE CONF_SERCOM_5_USART_ISO7816_PROTOCOL_T +#endif + +/* RX is on PIN_PB16 */ +#ifndef CONF_SERCOM_5_USART_RXPO +#define CONF_SERCOM_5_USART_RXPO 0 +#endif + +/* TX uses the same pin with RX */ +#ifndef CONF_SERCOM_5_USART_TXPO +#define CONF_SERCOM_5_USART_TXPO 2 +#endif + +/* Set iso7816 mode */ +#define CONF_SERCOM_5_USART_PMODE (CONF_SERCOM_5_USART_PARITY - 1) +#define CONF_SERCOM_5_USART_FORM 7 + +#if CONF_SERCOM_5_USART_CMODE == 0 +// Calculate BAUD register value in UART mode +#if CONF_SERCOM_5_USART_SAMPR == 0 +#ifndef CONF_SERCOM_5_USART_BAUD_RATE +#define CONF_SERCOM_5_USART_BAUD_RATE \ + 65536 - ((65536 * 16.0f * CONF_SERCOM_5_USART_BAUD) / CONF_GCLK_SERCOM5_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_5_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_5_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_5_USART_SAMPR == 1 +#ifndef CONF_SERCOM_5_USART_BAUD_RATE +#define CONF_SERCOM_5_USART_BAUD_RATE \ + ((CONF_GCLK_SERCOM5_CORE_FREQUENCY) / (CONF_SERCOM_5_USART_BAUD * 16)) - (CONF_SERCOM_5_USART_FRACTIONAL / 8) +#endif +#ifndef CONF_SERCOM_5_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_5_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_5_USART_SAMPR == 2 +#ifndef CONF_SERCOM_5_USART_BAUD_RATE +#define CONF_SERCOM_5_USART_BAUD_RATE \ + 65536 - ((65536 * 8.0f * CONF_SERCOM_5_USART_BAUD) / CONF_GCLK_SERCOM5_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_5_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_5_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_5_USART_SAMPR == 3 +#ifndef CONF_SERCOM_5_USART_BAUD_RATE +#define CONF_SERCOM_5_USART_BAUD_RATE \ + ((CONF_GCLK_SERCOM5_CORE_FREQUENCY) / (CONF_SERCOM_5_USART_BAUD * 8)) - (CONF_SERCOM_5_USART_FRACTIONAL / 8) +#endif +#ifndef CONF_SERCOM_5_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_5_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_5_USART_SAMPR == 4 +#ifndef CONF_SERCOM_5_USART_BAUD_RATE +#define CONF_SERCOM_5_USART_BAUD_RATE \ + 65536 - ((65536 * 3.0f * CONF_SERCOM_5_USART_BAUD) / CONF_GCLK_SERCOM5_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_5_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_5_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#endif + +#elif CONF_SERCOM_5_USART_CMODE == 1 +#ifndef CONF_SERCOM_5_USART_BAUD_RATE +// Calculate BAUD register value in USRT mode +#define CONF_SERCOM_5_USART_BAUD_RATE (CONF_GCLK_SERCOM5_CORE_FREQUENCY) / (2 * CONF_SERCOM_5_USART_BAUD) - 1 +#endif + +#ifndef CONF_SERCOM_5_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_5_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#else +#error CMODE value for SERCOM 5 in USART mode not known +#endif + +#include <peripheral_clk_config.h> + +#ifndef CONF_SERCOM_6_USART_ENABLE +#define CONF_SERCOM_6_USART_ENABLE 1 +#endif + +// <h> Basic Configuration + +// <q> Receive buffer enable +// <i> Enable input buffer in SERCOM module +// <id> usart_rx_enable +#ifndef CONF_SERCOM_6_USART_RXEN +#define CONF_SERCOM_6_USART_RXEN 1 +#endif + +// <q> Transmitt buffer enable +// <i> Enable output buffer in SERCOM module +// <id> usart_tx_enable +#ifndef CONF_SERCOM_6_USART_TXEN +#define CONF_SERCOM_6_USART_TXEN 1 +#endif + +// <o> Frame parity +// <0x1=>Even parity +// <i> Parity bit mode for USART frame +// <id> usart_parity +#ifndef CONF_SERCOM_6_USART_PARITY +#define CONF_SERCOM_6_USART_PARITY 1 +#endif + +// <o> Character Size +// <0x0=>8 bits +// <0x1=>9 bits +// <0x5=>5 bits +// <0x6=>6 bits +// <0x7=>7 bits +// <i> Data character size in USART frame +// <id> usart_character_size +#ifndef CONF_SERCOM_6_USART_CHSIZE +#define CONF_SERCOM_6_USART_CHSIZE 0x0 +#endif + +// <o> Stop Bit +// <0=>One stop bit +// <1=>Two stop bits +// <i> Number of stop bits in USART frame +// <id> usart_stop_bit +#ifndef CONF_SERCOM_6_USART_SBMODE +#define CONF_SERCOM_6_USART_SBMODE 1 +#endif + +// <o> Baud rate <1-3000000> +// <i> USART baud rate setting +// <id> usart_baud_rate +#ifndef CONF_SERCOM_6_USART_BAUD +#define CONF_SERCOM_6_USART_BAUD 6720 +#endif +// </h> + +// <h> ISO7816 configuration +// <o> ISO7816 Protocol Type +// <0x1=> T=0 +// <0x0=> T=1 +// <i> Define ISO7816 protocol type as 0. +// <id> usart_iso7816_type +#ifndef CONF_SERCOM_6_USART_ISO7816_PROTOCOL_T +#define CONF_SERCOM_6_USART_ISO7816_PROTOCOL_T 0x0 +#endif + +// <o> ISO7816 Inhibit Not Acknowledge +// <0x0=> NACK is transmitted when a parity error is received. +// <0x1=> NACK is not transmitted when a parity error is received. +// <i> Define whether a NACK is transmitted when a parity error is received. +// <id> usart_inack +#ifndef CONF_SERCOM_6_USART_INACK +#define CONF_SERCOM_6_USART_INACK 0x0 +#endif + +// <o> ISO7816 Disable Successive Not Acknowledge +// <0x0=> The successive receive NACK is disable. +// <0x1=> The successive receive NACK is enable. +// <i> Define whether NACK will be sent on parity error reception. +// <id> usart_dsnack +#ifndef CONF_SERCOM_6_USART_DSNACK +#define CONF_SERCOM_6_USART_DSNACK 0x0 +#endif + +// <o> ISO7816 Maximum Iterations<0-7> +// <i> Define the maximum number of retransmit iterations. +// <id> usart_maxiter +#ifndef CONF_SERCOM_6_USART_MAXITER +#define CONF_SERCOM_6_USART_MAXITER 0x7 +#endif + +// <o> ISO7816 Guard Time +// <0x2=> 2-bit times +// <0x3=> 3-bit times +// <0x4=> 4-bit times +// <0x5=> 5-bit times +// <0x6=> 6-bit times +// <0x7=> 7-bit times +// <i> Define the guard time. +// <id> usart_gtime +#ifndef CONF_SERCOM_6_USART_GTIME +#define CONF_SERCOM_6_USART_GTIME 0x2 +#endif + +// <q> Inverse transmission and reception enabled +// <i> Define inverse transmission and reception enabled. +// <id> usart_inverse_enabled +#ifndef CONF_SERCOM_6_USART_INVERSE_ENABLED +#define CONF_SERCOM_6_USART_INVERSE_ENABLED 0x0 +#endif + +#if (CONF_SERCOM_6_USART_INVERSE_ENABLED == 1) +#define CONF_SERCOM_6_USART_RXINV 0x1 +#define CONF_SERCOM_6_USART_TXINV 0x1 +#else +#define CONF_SERCOM_6_USART_RXINV 0x0 +#define CONF_SERCOM_6_USART_TXINV 0x0 +#endif + +// </h> + +// <e> Advanced configuration +// <id> usart_advanced +#ifndef CONF_SERCOM_6_USART_ADVANCED_CONFIG +#define CONF_SERCOM_6_USART_ADVANCED_CONFIG 0 +#endif + +// <q> Run in stand-by +// <i> Keep the module running in standby sleep mode +// <id> usart_arch_runstdby +#ifndef CONF_SERCOM_6_USART_RUNSTDBY +#define CONF_SERCOM_6_USART_RUNSTDBY 0 +#endif + +// <q> Immediate Buffer Overflow Notification +// <i> Controls when the BUFOVF status bit is asserted +// <id> usart_arch_ibon +#ifndef CONF_SERCOM_6_USART_IBON +#define CONF_SERCOM_6_USART_IBON 0 +#endif + +// <q> Start of Frame Detection Enable +// <i> Will wake the device from any sleep mode if usart_init and usart_enable was run priort to going to sleep. (receive buffer must be enabled) +// <id> usart_arch_sfde +#ifndef CONF_SERCOM_6_USART_SFDE +#define CONF_SERCOM_6_USART_SFDE 0 +#endif + +// <q> Collision Detection Enable +// <i> Collision detection enable +// <id> usart_arch_cloden +#ifndef CONF_SERCOM_6_USART_CLODEN +#define CONF_SERCOM_6_USART_CLODEN 0 +#endif + +// <o> Operating Mode +// <0x1=>USART with internal clock +// <i> Drive the shift register by an internal clock generated by the baud rate generator. +// <id> usart_arch_clock_mode +#ifndef CONF_SERCOM_6_USART_MODE +#define CONF_SERCOM_6_USART_MODE 0x1 +#endif + +// <o> Data Order +// <0=>MSB is transmitted first +// <1=>LSB is transmitted first +// <i> Data order of the data bits in the frame +// <id> usart_arch_dord +#ifndef CONF_SERCOM_6_USART_DORD +#define CONF_SERCOM_6_USART_DORD 1 +#endif + +// <o> Debug Stop Mode +// <i> Behavior of the baud-rate generator when CPU is halted by external debugger. +// <0=>Keep running +// <1=>Halt +// <id> usart_arch_dbgstop +#ifndef CONF_SERCOM_6_USART_DEBUG_STOP_MODE +#define CONF_SERCOM_6_USART_DEBUG_STOP_MODE 0 +#endif + +// Does not do anything in USRT mode +#define CONF_SERCOM_6_USART_SAMPR 0x0 +#define CONF_SERCOM_6_USART_SAMPA 0x0 +#define CONF_SERCOM_6_USART_FRACTIONAL 0x0 + +// Does not do anything in UART mode +#define CONF_SERCOM_6_USART_CPOL 0 + +// Does not do anything in USRT mode +#define CONF_SERCOM_6_USART_ENC 0 + +// </e> + +#ifndef CONF_SERCOM_6_USART_CMODE +#define CONF_SERCOM_6_USART_CMODE CONF_SERCOM_6_USART_ISO7816_PROTOCOL_T +#endif + +/* RX is on PIN_PC16 */ +#ifndef CONF_SERCOM_6_USART_RXPO +#define CONF_SERCOM_6_USART_RXPO 0 +#endif + +/* TX uses the same pin with RX */ +#ifndef CONF_SERCOM_6_USART_TXPO +#define CONF_SERCOM_6_USART_TXPO 2 +#endif + +/* Set iso7816 mode */ +#define CONF_SERCOM_6_USART_PMODE (CONF_SERCOM_6_USART_PARITY - 1) +#define CONF_SERCOM_6_USART_FORM 7 + +#if CONF_SERCOM_6_USART_CMODE == 0 +// Calculate BAUD register value in UART mode +#if CONF_SERCOM_6_USART_SAMPR == 0 +#ifndef CONF_SERCOM_6_USART_BAUD_RATE +#define CONF_SERCOM_6_USART_BAUD_RATE \ + 65536 - ((65536 * 16.0f * CONF_SERCOM_6_USART_BAUD) / CONF_GCLK_SERCOM6_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_6_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_6_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_6_USART_SAMPR == 1 +#ifndef CONF_SERCOM_6_USART_BAUD_RATE +#define CONF_SERCOM_6_USART_BAUD_RATE \ + ((CONF_GCLK_SERCOM6_CORE_FREQUENCY) / (CONF_SERCOM_6_USART_BAUD * 16)) - (CONF_SERCOM_6_USART_FRACTIONAL / 8) +#endif +#ifndef CONF_SERCOM_6_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_6_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_6_USART_SAMPR == 2 +#ifndef CONF_SERCOM_6_USART_BAUD_RATE +#define CONF_SERCOM_6_USART_BAUD_RATE \ + 65536 - ((65536 * 8.0f * CONF_SERCOM_6_USART_BAUD) / CONF_GCLK_SERCOM6_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_6_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_6_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_6_USART_SAMPR == 3 +#ifndef CONF_SERCOM_6_USART_BAUD_RATE +#define CONF_SERCOM_6_USART_BAUD_RATE \ + ((CONF_GCLK_SERCOM6_CORE_FREQUENCY) / (CONF_SERCOM_6_USART_BAUD * 8)) - (CONF_SERCOM_6_USART_FRACTIONAL / 8) +#endif +#ifndef CONF_SERCOM_6_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_6_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_6_USART_SAMPR == 4 +#ifndef CONF_SERCOM_6_USART_BAUD_RATE +#define CONF_SERCOM_6_USART_BAUD_RATE \ + 65536 - ((65536 * 3.0f * CONF_SERCOM_6_USART_BAUD) / CONF_GCLK_SERCOM6_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_6_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_6_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#endif + +#elif CONF_SERCOM_6_USART_CMODE == 1 +#ifndef CONF_SERCOM_6_USART_BAUD_RATE +// Calculate BAUD register value in USRT mode +#define CONF_SERCOM_6_USART_BAUD_RATE (CONF_GCLK_SERCOM6_CORE_FREQUENCY) / (2 * CONF_SERCOM_6_USART_BAUD) - 1 +#endif + +#ifndef CONF_SERCOM_6_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_6_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#else +#error CMODE value for SERCOM 6 in USART mode not known +#endif + +#include <peripheral_clk_config.h> + +#ifndef CONF_SERCOM_7_USART_ENABLE +#define CONF_SERCOM_7_USART_ENABLE 1 +#endif + +// <h> Basic Configuration + +// <q> Receive buffer enable +// <i> Enable input buffer in SERCOM module +// <id> usart_rx_enable +#ifndef CONF_SERCOM_7_USART_RXEN +#define CONF_SERCOM_7_USART_RXEN 1 +#endif + +// <q> Transmitt buffer enable +// <i> Enable output buffer in SERCOM module +// <id> usart_tx_enable +#ifndef CONF_SERCOM_7_USART_TXEN +#define CONF_SERCOM_7_USART_TXEN 1 +#endif + +// <o> Frame parity +// <0x0=>No parity +// <0x1=>Even parity +// <0x2=>Odd parity +// <i> Parity bit mode for USART frame +// <id> usart_parity +#ifndef CONF_SERCOM_7_USART_PARITY +#define CONF_SERCOM_7_USART_PARITY 0x0 +#endif + +// <o> Character Size +// <0x0=>8 bits +// <0x1=>9 bits +// <0x5=>5 bits +// <0x6=>6 bits +// <0x7=>7 bits +// <i> Data character size in USART frame +// <id> usart_character_size +#ifndef CONF_SERCOM_7_USART_CHSIZE +#define CONF_SERCOM_7_USART_CHSIZE 0x0 +#endif + +// <o> Stop Bit +// <0=>One stop bit +// <1=>Two stop bits +// <i> Number of stop bits in USART frame +// <id> usart_stop_bit +#ifndef CONF_SERCOM_7_USART_SBMODE +#define CONF_SERCOM_7_USART_SBMODE 0 +#endif + +// <o> Baud rate <1-6250000> +// <i> USART baud rate setting +// <id> usart_baud_rate +#ifndef CONF_SERCOM_7_USART_BAUD +#define CONF_SERCOM_7_USART_BAUD 921600 +#endif + +// </h> + +// <e> Advanced configuration +// <id> usart_advanced +#ifndef CONF_SERCOM_7_USART_ADVANCED_CONFIG +#define CONF_SERCOM_7_USART_ADVANCED_CONFIG 0 +#endif + +// <q> Run in stand-by +// <i> Keep the module running in standby sleep mode +// <id> usart_arch_runstdby +#ifndef CONF_SERCOM_7_USART_RUNSTDBY +#define CONF_SERCOM_7_USART_RUNSTDBY 0 +#endif + +// <q> Immediate Buffer Overflow Notification +// <i> Controls when the BUFOVF status bit is asserted +// <id> usart_arch_ibon +#ifndef CONF_SERCOM_7_USART_IBON +#define CONF_SERCOM_7_USART_IBON 0 +#endif + +// <q> Start of Frame Detection Enable +// <i> Will wake the device from any sleep mode if usart_init and usart_enable was run priort to going to sleep. (receive buffer must be enabled) +// <id> usart_arch_sfde +#ifndef CONF_SERCOM_7_USART_SFDE +#define CONF_SERCOM_7_USART_SFDE 0 +#endif + +// <q> Collision Detection Enable +// <i> Collision detection enable +// <id> usart_arch_cloden +#ifndef CONF_SERCOM_7_USART_CLODEN +#define CONF_SERCOM_7_USART_CLODEN 0 +#endif + +// <o> Operating Mode +// <0x0=>USART with external clock +// <0x1=>USART with internal clock +// <i> Drive the shift register by an internal clock generated by the baud rate generator or an external clock supplied on the XCK pin. +// <id> usart_arch_clock_mode +#ifndef CONF_SERCOM_7_USART_MODE +#define CONF_SERCOM_7_USART_MODE 0x1 +#endif + +// <o> Sample Rate +// <0x0=>16x arithmetic +// <0x1=>16x fractional +// <0x2=>8x arithmetic +// <0x3=>8x fractional +// <0x4=>3x arithmetic +// <i> How many over-sampling bits used when sampling data state +// <id> usart_arch_sampr +#ifndef CONF_SERCOM_7_USART_SAMPR +#define CONF_SERCOM_7_USART_SAMPR 0x0 +#endif + +// <o> Sample Adjustment +// <0x0=>7-8-9 (3-4-5 8-bit over-sampling) +// <0x1=>9-10-11 (4-5-6 8-bit over-sampling) +// <0x2=>11-12-13 (5-6-7 8-bit over-sampling) +// <0x3=>13-14-15 (6-7-8 8-bit over-sampling) +// <i> Adjust which samples to use for data sampling in asynchronous mode +// <id> usart_arch_sampa +#ifndef CONF_SERCOM_7_USART_SAMPA +#define CONF_SERCOM_7_USART_SAMPA 0x0 +#endif + +// <o> Fractional Part <0-7> +// <i> Fractional part of the baud rate if baud rate generator is in fractional mode +// <id> usart_arch_fractional +#ifndef CONF_SERCOM_7_USART_FRACTIONAL +#define CONF_SERCOM_7_USART_FRACTIONAL 0x0 +#endif + +// <o> Data Order +// <0=>MSB is transmitted first +// <1=>LSB is transmitted first +// <i> Data order of the data bits in the frame +// <id> usart_arch_dord +#ifndef CONF_SERCOM_7_USART_DORD +#define CONF_SERCOM_7_USART_DORD 1 +#endif + +// Does not do anything in UART mode +#define CONF_SERCOM_7_USART_CPOL 0 + +// <o> Encoding Format +// <0=>No encoding +// <1=>IrDA encoded +// <id> usart_arch_enc +#ifndef CONF_SERCOM_7_USART_ENC +#define CONF_SERCOM_7_USART_ENC 0 +#endif + +// <o> LIN Slave Enable +// <i> Break Character Detection and Auto-Baud/LIN Slave Enable. +// <i> Additional setting needed: 16x sample rate using fractional baud rate generation (CTRLA.SAMPR = 1). +// <0=>Disable +// <1=>Enable +// <id> usart_arch_lin_slave_enable +#ifndef CONF_SERCOM_7_USART_LIN_SLAVE_ENABLE +#define CONF_SERCOM_7_USART_LIN_SLAVE_ENABLE 0 +#endif + +// <o> Debug Stop Mode +// <i> Behavior of the baud-rate generator when CPU is halted by external debugger. +// <0=>Keep running +// <1=>Halt +// <id> usart_arch_dbgstop +#ifndef CONF_SERCOM_7_USART_DEBUG_STOP_MODE +#define CONF_SERCOM_7_USART_DEBUG_STOP_MODE 0 +#endif + +// </e> + +#ifndef CONF_SERCOM_7_USART_INACK +#define CONF_SERCOM_7_USART_INACK 0x0 +#endif + +#ifndef CONF_SERCOM_7_USART_DSNACK +#define CONF_SERCOM_7_USART_DSNACK 0x0 +#endif + +#ifndef CONF_SERCOM_7_USART_MAXITER +#define CONF_SERCOM_7_USART_MAXITER 0x7 +#endif + +#ifndef CONF_SERCOM_7_USART_GTIME +#define CONF_SERCOM_7_USART_GTIME 0x2 +#endif + +#define CONF_SERCOM_7_USART_RXINV 0x0 +#define CONF_SERCOM_7_USART_TXINV 0x0 + +#ifndef CONF_SERCOM_7_USART_CMODE +#define CONF_SERCOM_7_USART_CMODE 0 +#endif + +#ifndef CONF_SERCOM_7_USART_RXPO +#define CONF_SERCOM_7_USART_RXPO 1 /* RX is on PIN_PB31 */ +#endif + +#ifndef CONF_SERCOM_7_USART_TXPO +#define CONF_SERCOM_7_USART_TXPO 0 /* TX is on PIN_PB30 */ +#endif + +/* Set correct parity settings in register interface based on PARITY setting */ +#if CONF_SERCOM_7_USART_LIN_SLAVE_ENABLE == 1 +#if CONF_SERCOM_7_USART_PARITY == 0 +#define CONF_SERCOM_7_USART_PMODE 0 +#define CONF_SERCOM_7_USART_FORM 4 +#else +#define CONF_SERCOM_7_USART_PMODE CONF_SERCOM_7_USART_PARITY - 1 +#define CONF_SERCOM_7_USART_FORM 5 +#endif +#else /* #if CONF_SERCOM_7_USART_LIN_SLAVE_ENABLE == 0 */ +#if CONF_SERCOM_7_USART_PARITY == 0 +#define CONF_SERCOM_7_USART_PMODE 0 +#define CONF_SERCOM_7_USART_FORM 0 +#else +#define CONF_SERCOM_7_USART_PMODE CONF_SERCOM_7_USART_PARITY - 1 +#define CONF_SERCOM_7_USART_FORM 1 +#endif +#endif + +// Calculate BAUD register value in UART mode +#if CONF_SERCOM_7_USART_SAMPR == 0 +#ifndef CONF_SERCOM_7_USART_BAUD_RATE +#define CONF_SERCOM_7_USART_BAUD_RATE \ + 65536 - ((65536 * 16.0f * CONF_SERCOM_7_USART_BAUD) / CONF_GCLK_SERCOM7_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_7_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_7_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_7_USART_SAMPR == 1 +#ifndef CONF_SERCOM_7_USART_BAUD_RATE +#define CONF_SERCOM_7_USART_BAUD_RATE \ + ((CONF_GCLK_SERCOM7_CORE_FREQUENCY) / (CONF_SERCOM_7_USART_BAUD * 16)) - (CONF_SERCOM_7_USART_FRACTIONAL / 8) +#endif +#ifndef CONF_SERCOM_7_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_7_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_7_USART_SAMPR == 2 +#ifndef CONF_SERCOM_7_USART_BAUD_RATE +#define CONF_SERCOM_7_USART_BAUD_RATE \ + 65536 - ((65536 * 8.0f * CONF_SERCOM_7_USART_BAUD) / CONF_GCLK_SERCOM7_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_7_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_7_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_7_USART_SAMPR == 3 +#ifndef CONF_SERCOM_7_USART_BAUD_RATE +#define CONF_SERCOM_7_USART_BAUD_RATE \ + ((CONF_GCLK_SERCOM7_CORE_FREQUENCY) / (CONF_SERCOM_7_USART_BAUD * 8)) - (CONF_SERCOM_7_USART_FRACTIONAL / 8) +#endif +#ifndef CONF_SERCOM_7_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_7_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#elif CONF_SERCOM_7_USART_SAMPR == 4 +#ifndef CONF_SERCOM_7_USART_BAUD_RATE +#define CONF_SERCOM_7_USART_BAUD_RATE \ + 65536 - ((65536 * 3.0f * CONF_SERCOM_7_USART_BAUD) / CONF_GCLK_SERCOM7_CORE_FREQUENCY) +#endif +#ifndef CONF_SERCOM_7_USART_RECEIVE_PULSE_LENGTH +#define CONF_SERCOM_7_USART_RECEIVE_PULSE_LENGTH 0 +#endif +#endif + +// <<< end of configuration section >>> + +#endif // HPL_SERCOM_CONFIG_H diff --git a/config/peripheral_clk_config.h b/config/peripheral_clk_config.h index 9a9c30f..8078e4b 100644 --- a/config/peripheral_clk_config.h +++ b/config/peripheral_clk_config.h @@ -9,7 +9,7 @@ * \brief CPU's Clock frequency */ #ifndef CONF_CPU_FREQUENCY -#define CONF_CPU_FREQUENCY 12000000 +#define CONF_CPU_FREQUENCY 120000000 #endif
// <y> USB Clock Source diff --git a/gcc/Makefile b/gcc/Makefile index 3493102..2df931e 100644 --- a/gcc/Makefile +++ b/gcc/Makefile @@ -5,7 +5,7 @@ # Set for which board the bootloader should be compiled # run `make clean` for the change to be effective # possible values: SAME54_XPLAINED_PRO, SYSMOOCTSIM -BOARD ?= SAME54_XPLAINED_PRO +BOARD ?= SYSMOOCTSIM
GIT_VERSION=$(shell ../git-version-gen $(TOP)/.tarvers)
@@ -89,124 +89,64 @@ hal/src/hal_cache.o \ hpl/cmcc/hpl_cmcc.o \ atmel_start.o \ -usb_dfu_main.o \ usb/device/usbdc.o \ hal/src/hal_atomic.o
- -OBJS_AS_ARGS += \ -"hal/src/hal_io.o" \ -"hpl/core/hpl_core_m4.o" \ -"usb/class/dfu/device/dfudf.o" \ -"hal/utils/src/utils_syscalls.o" \ -"hpl/dmac/hpl_dmac.o" \ -"hpl/nvmctrl/hpl_nvmctrl.o" \ -"gcc/system_same54.o" \ -"hpl/usb/hpl_usb.o" \ -"hal/src/hal_delay.o" \ -"hpl/pm/hpl_pm.o" \ -"hpl/core/hpl_init.o" \ -"hpl/gclk/hpl_gclk.o" \ -"hal/utils/src/utils_list.o" \ -"hal/utils/src/utils_assert.o" \ -"usb_start.o" \ -"hpl/oscctrl/hpl_oscctrl.o" \ -"hpl/mclk/hpl_mclk.o" \ -"hpl/ramecc/hpl_ramecc.o" \ -"usb/usb_protocol.o" \ -"hal/src/hal_flash.o" \ -"hal/src/hal_init.o" \ -"gcc/gcc/startup_same54.o" \ -"hal/src/hal_usb_device.o" \ -"hpl/osc32kctrl/hpl_osc32kctrl.o" \ -"driver_init.o" \ -"hal/src/hal_gpio.o" \ -"hal/utils/src/utils_event.o" \ -"hal/src/hal_sleep.o" \ -"hal/src/hal_cache.o" \ -"hpl/cmcc/hpl_cmcc.o" \ -"atmel_start.o" \ -"usb_dfu_main.o" \ -"usb/device/usbdc.o" \ -"hal/src/hal_atomic.o" - -# List the dependency files DEPS := $(OBJS:%.o=%.d) - -DEPS_AS_ARGS += \ -"hal/utils/src/utils_event.d" \ -"hal/src/hal_io.d" \ -"hpl/ramecc/hpl_ramecc.d" \ -"hpl/core/hpl_core_m4.d" \ -"hal/utils/src/utils_syscalls.d" \ -"hpl/nvmctrl/hpl_nvmctrl.d" \ -"usb/class/dfu/device/dfudf.d" \ -"gcc/gcc/startup_same54.d" \ -"hpl/usb/hpl_usb.d" \ -"hal/utils/src/utils_list.d" \ -"hpl/cmcc/hpl_cmcc.d" \ -"usb_start.d" \ -"hal/utils/src/utils_assert.d" \ -"hal/src/hal_delay.d" \ -"hpl/core/hpl_init.d" \ -"hpl/pm/hpl_pm.d" \ -"usb/usb_protocol.d" \ -"hal/src/hal_flash.d" \ -"hpl/gclk/hpl_gclk.d" \ -"hal/src/hal_usb_device.d" \ -"hpl/dmac/hpl_dmac.d" \ -"hal/src/hal_init.d" \ -"usb_dfu_main.d" \ -"hpl/mclk/hpl_mclk.d" \ -"driver_init.d" \ -"hpl/osc32kctrl/hpl_osc32kctrl.d" \ -"hal/src/hal_cache.d" \ -"hal/src/hal_sleep.d" \ -"hal/src/hal_gpio.d" \ -"hal/src/hal_atomic.d" \ -"usb/device/usbdc.d" \ -"hpl/oscctrl/hpl_oscctrl.d" \ -"gcc/system_same54.d" \ -"atmel_start.d" +OBJS_AS_ARGS = $(patsubst %,"%",$(OBJS)) +DEPS_AS_ARGS = $(patsubst %,"%",$(DEPS))
BOARD_LC := $(shell echo $(BOARD) | tr A-Z a-z) OUTPUT_FILE_NAME := bootloader-$(BOARD_LC)-$(GIT_VERSION) QUOTE := " -OUTPUT_FILE_PATH +=$(OUTPUT_FILE_NAME).elf -OUTPUT_FILE_PATH_AS_ARGS +=$(OUTPUT_FILE_NAME).elf +# OUTPUT_FILE_PATH +=$(OUTPUT_FILE_NAME).elf +#OUTPUT_FILE_PATH_AS_ARGS +=$(OUTPUT_FILE_NAME).elf +BLSIZE_DEF := -D$(QUOTE)$(shell sed 's/;//g' gcc/blsize.ld | tr -d ' ')$(QUOTE) + +# .PHONY MAIN_dfu MAIN_flash +# MAIN_%: +# = usb_dfu_main.o
vpath %.c ../ vpath %.s ../ vpath %.S ../
-# All Target -all: $(SUB_DIRS) $(OUTPUT_FILE_PATH) symlink +.PHONY: clean-dfu clean-flash + +all: $(SUB_DIRS) dfu-merge + +dfu-merge: $(OUTPUT_FILE_NAME)-dfu + +$(OUTPUT_FILE_NAME)-dfu: $(OUTPUT_FILE_NAME)-flash
# Linker target
-$(OUTPUT_FILE_PATH): $(OBJS) +$(OUTPUT_FILE_NAME)-%: $(OBJS) usb_%_main.o @echo Building target: $@ @echo Invoking: ARM/GNU Linker - $(QUOTE)arm-none-eabi-gcc$(QUOTE) -o $(OUTPUT_FILE_NAME).elf $(OBJS_AS_ARGS) -Wl,--start-group -lm -Wl,--end-group -mthumb \ --Wl,-Map="$(OUTPUT_FILE_NAME).map" --specs=nano.specs -Wl,--gc-sections -mcpu=cortex-m4 \ - \ --T"../gcc/gcc/same54p20a_flash.ld" \ --L"../gcc/gcc" + $(QUOTE)arm-none-eabi-gcc$(QUOTE) -o $(OUTPUT_FILE_NAME)-$*.elf $(OBJS_AS_ARGS) "usb_$*_main.o" \ + -Wl,--no-undefined -Wl,--print-memory-usage -Wl,--strip-discarded -Wl,--start-group -lm -Wl,--end-group -mthumb \ + -Wl,-Map="$(OUTPUT_FILE_NAME)-$*.map" --specs=nano.specs -Wl,--gc-sections -mcpu=cortex-m4 \ + -T"../gcc/gcc/same54p20a_$*.ld" \ + -L"../gcc/gcc" @echo Finished building target: $@
- "arm-none-eabi-objcopy" -O binary "$(OUTPUT_FILE_NAME).elf" "$(OUTPUT_FILE_NAME).bin" - "arm-none-eabi-objcopy" -O ihex -R .eeprom -R .fuse -R .lock -R .signature \ - "$(OUTPUT_FILE_NAME).elf" "$(OUTPUT_FILE_NAME).hex" - "arm-none-eabi-objcopy" -j .eeprom --set-section-flags=.eeprom=alloc,load --change-section-lma \ - .eeprom=0 --no-change-warnings -O binary "$(OUTPUT_FILE_NAME).elf" \ - "$(OUTPUT_FILE_NAME).eep" || exit 0 - "arm-none-eabi-objdump" -h -S "$(OUTPUT_FILE_NAME).elf" > "$(OUTPUT_FILE_NAME).lss" - "arm-none-eabi-size" "$(OUTPUT_FILE_NAME).elf" + "arm-none-eabi-objcopy" -O binary "$(OUTPUT_FILE_NAME)-$*.elf" "$(OUTPUT_FILE_NAME)-$*.bin" +# "arm-none-eabi-objcopy" -O ihex -R .eeprom -R .fuse -R .lock -R .signature "$(OUTPUT_FILE_NAME)-$*.elf" "$(OUTPUT_FILE_NAME)-$*.hex" +# "arm-none-eabi-objcopy" -j .eeprom --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0 --no-change-warnings -O binary "$(OUTPUT_FILE_NAME)-$*.elf" "$(OUTPUT_FILE_NAME)-$*.eep" || exit 0 + "arm-none-eabi-objdump" -h -S "$(OUTPUT_FILE_NAME)-$*.elf" > "$(OUTPUT_FILE_NAME)-$*.lss" + "arm-none-eabi-size" "$(OUTPUT_FILE_NAME)-$*.elf" + ln -sf $(OUTPUT_FILE_NAME)-$*.bin bootloader-$(BOARD_LC)-$*.bin + ln -sf $(OUTPUT_FILE_NAME)-$*.elf bootloader-$(BOARD_LC)-$*.elf
-.PHONY: symlink -symlink: $(OUTPUT_FILE_PATH) - ln -sf $(OUTPUT_FILE_NAME).bin bootloader-$(BOARD_LC).bin - ln -sf $(OUTPUT_FILE_NAME).elf bootloader-$(BOARD_LC).elf +.PHONY: dfu-merge +dfu-merge: + $(info updating updater section with padded bootloader file..) + $(SILENT)dd if=/dev/zero bs=16384 count=1 of=dfu-flash-padded.bin + $(SILENT)dd if=$(OUTPUT_FILE_NAME)-flash.bin conv=notrunc of=dfu-flash-padded.bin + $(SILENT)"arm-none-eabi-objcopy" --update-section .blupdate=dfu-flash-padded.bin $(OUTPUT_FILE_NAME)-dfu.elf + $(SILENT)"arm-none-eabi-objcopy" -O binary $(OUTPUT_FILE_NAME)-dfu.elf $(OUTPUT_FILE_NAME)-dfu.bin + rm dfu-flash-padded.bin
# Compiler targets
@@ -217,7 +157,7 @@ @echo Building file: $< @echo ARM/GNU C Compiler $(QUOTE)arm-none-eabi-gcc$(QUOTE) -x c -mthumb -DDEBUG -Os -ffunction-sections -mlong-calls -g3 -Wall -c -std=gnu99 \ --D__SAME54P20A__ -D$(BOARD) -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \ +$(BLSIZE_DEF) -D__SAME54P19A__ -D$(BOARD) -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \ -I"../" -I"../config" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/nvmctrl" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/dfu" -I"../usb/class/dfu/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include" \ -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -o "$@" "$<" @echo Finished building: $< @@ -226,7 +166,7 @@ @echo Building file: $< @echo ARM/GNU Assembler $(QUOTE)arm-none-eabi-as$(QUOTE) -x c -mthumb -DDEBUG -Os -ffunction-sections -mlong-calls -g3 -Wall -c -std=gnu99 \ --D__SAME54P20A__ -D$(BOARD) -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \ +$(BLSIZE_DEF) -D__SAME54P19A__ -D$(BOARD) -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \ -I"../" -I"../config" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/nvmctrl" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/dfu" -I"../usb/class/dfu/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include" \ -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -o "$@" "$<" @echo Finished building: $< @@ -235,7 +175,7 @@ @echo Building file: $< @echo ARM/GNU Preprocessing Assembler $(QUOTE)arm-none-eabi-gcc$(QUOTE) -x c -mthumb -DDEBUG -Os -ffunction-sections -mlong-calls -g3 -Wall -c -std=gnu99 \ --D__SAME54P20A__ -D$(BOARD) -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \ +$(BLSIZE_DEF) -D__SAME54P19A__ -D$(BOARD) -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \ -I"../" -I"../config" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/nvmctrl" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/dfu" -I"../usb/class/dfu/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include" \ -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -o "$@" "$<" @echo Finished building: $< @@ -244,19 +184,28 @@ ifneq ($(MAKECMDGOALS),clean) ifneq ($(strip $(DEPS)),) -include $(DEPS) +-include usb_flash_main.d usb_dfu_main.d endif endif
$(SUB_DIRS): $(MK_DIR) "$@"
-clean: +clean-%: rm -f $(OBJS_AS_ARGS) - rm -f $(OUTPUT_FILE_PATH) + # rm -f $(OUTPUT_FILE_PATH) rm -f $(DEPS_AS_ARGS) - rm -f $(OUTPUT_FILE_NAME).a $(OUTPUT_FILE_NAME).hex $(OUTPUT_FILE_NAME).bin \ - $(OUTPUT_FILE_NAME).lss $(OUTPUT_FILE_NAME).eep $(OUTPUT_FILE_NAME).map \ - $(OUTPUT_FILE_NAME).srec bootloader-$(BOARD_LC).bin bootloader-$(BOARD_LC).elf + rm -f $(OUTPUT_FILE_NAME)-$*.a $(OUTPUT_FILE_NAME)-$*.hex $(OUTPUT_FILE_NAME)-$*.bin \ + $(OUTPUT_FILE_NAME)-$*.lss $(OUTPUT_FILE_NAME)-$*.eep $(OUTPUT_FILE_NAME)-$*.map \ + $(OUTPUT_FILE_NAME)-$*.srec bootloader-$(BOARD_LC)-$*.bin bootloader-$(BOARD_LC)-$*.elf + +clean: clean-dfu clean-flash + rm -f $(OBJS_AS_ARGS) + # rm -f $(OUTPUT_FILE_PATH) + rm -f $(DEPS_AS_ARGS) + # rm -f $(OUTPUT_FILE_NAME).a $(OUTPUT_FILE_NAME).hex $(OUTPUT_FILE_NAME).bin \ + # $(OUTPUT_FILE_NAME).lss $(OUTPUT_FILE_NAME).eep $(OUTPUT_FILE_NAME).map \ + # $(OUTPUT_FILE_NAME).srec bootloader-$(BOARD_LC).bin bootloader-$(BOARD_LC).elf
mrproper: clean - rm -f *.o *.d *.a *.elf *.bin *.ihex *.eep *.lss *.map *.srec + rm -f *.o *.d *.a *.elf *.bin *.hex *.ihex *.eep *.lss *.map *.srec diff --git a/gcc/system_same54.c b/gcc/system_same54.c index 55a5fd2..9d17c8d 100644 --- a/gcc/system_same54.c +++ b/gcc/system_same54.c @@ -28,12 +28,13 @@ */
#include "same54.h" +#include "peripheral_clk_config.h"
/** * Initial system clock frequency. The System RC Oscillator (RCSYS) provides * the source for the main clock at chip startup. */ -#define __SYSTEM_CLOCK (48000000) +#define __SYSTEM_CLOCK CONF_CPU_FREQUENCY
uint32_t SystemCoreClock = __SYSTEM_CLOCK; /*!< System Clock Frequency (Core Clock)*/
diff --git a/hpl/core/hpl_core_m4.c b/hpl/core/hpl_core_m4.c index acb75bc..4680ec3 100644 --- a/hpl/core/hpl_core_m4.c +++ b/hpl/core/hpl_core_m4.c @@ -216,8 +216,14 @@ #ifndef _UNIT_TEST_ (void)hw; (void)cycles; -#if defined __GNUC__ +#if defined(__GNUC__) && (__ARMCOMPILER_VERSION > 6000000) /* Keil MDK with ARM Compiler 6 */ + __asm(".align 3 \n" + "__delay:\n" + "subs r1, r1, #1\n" + "bhi __delay\n"); +#elif defined __GNUC__ __asm(".syntax unified\n" + ".align 3 \n" "__delay:\n" "subs r1, r1, #1\n" "bhi __delay\n" diff --git a/hpl/oscctrl/hpl_oscctrl.c b/hpl/oscctrl/hpl_oscctrl.c index 9f55076..1fc04bd 100644 --- a/hpl/oscctrl/hpl_oscctrl.c +++ b/hpl/oscctrl/hpl_oscctrl.c @@ -35,6 +35,7 @@ #include <hpl_init.h> #include <hpl_oscctrl_config.h> #include <hpl_gclk_config.h> +#include <hpl_delay.h>
/** * \brief Initialize clock sources @@ -219,6 +220,11 @@ #endif #endif
+ // startup default is internal osck32k -> pll @48M -> gclk0 -> cpu + // but this code sets it to osc32k while being reconfigured + // errata 2.13.1 delay + _delay_cycles(0, (32768U/1000) * 10 /* 10 ms*/); + #if CONF_DFLL_CONFIG == 1 while (hri_gclk_read_SYNCBUSY_reg(GCLK)) ; diff --git a/hpl/sercom/hpl_sercom.c b/hpl/sercom/hpl_sercom.c new file mode 100644 index 0000000..bda6655 --- /dev/null +++ b/hpl/sercom/hpl_sercom.c @@ -0,0 +1,3238 @@ + +/** + * \file + * + * \brief SAM Serial Communication Interface + * + * Copyright (c) 2014-2019 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ +#include <hpl_dma.h> +#include <hpl_i2c_m_async.h> +#include <hpl_i2c_m_sync.h> +#include <hpl_i2c_s_async.h> +#include <hpl_sercom_config.h> +#include <hpl_spi_m_async.h> +#include <hpl_spi_m_sync.h> +#include <hpl_spi_s_async.h> +#include <hpl_spi_s_sync.h> +#include <hpl_usart_async.h> +#include <hpl_usart_sync.h> +#include <utils.h> +#include <utils_assert.h> + +#ifndef CONF_SERCOM_0_USART_ENABLE +#define CONF_SERCOM_0_USART_ENABLE 0 +#endif +#ifndef CONF_SERCOM_1_USART_ENABLE +#define CONF_SERCOM_1_USART_ENABLE 0 +#endif +#ifndef CONF_SERCOM_2_USART_ENABLE +#define CONF_SERCOM_2_USART_ENABLE 0 +#endif +#ifndef CONF_SERCOM_3_USART_ENABLE +#define CONF_SERCOM_3_USART_ENABLE 0 +#endif +#ifndef CONF_SERCOM_4_USART_ENABLE +#define CONF_SERCOM_4_USART_ENABLE 0 +#endif +#ifndef CONF_SERCOM_5_USART_ENABLE +#define CONF_SERCOM_5_USART_ENABLE 0 +#endif +#ifndef CONF_SERCOM_6_USART_ENABLE +#define CONF_SERCOM_6_USART_ENABLE 0 +#endif +#ifndef CONF_SERCOM_7_USART_ENABLE +#define CONF_SERCOM_7_USART_ENABLE 0 +#endif + +/** Amount of SERCOM that is used as USART. */ +#define SERCOM_USART_AMOUNT \ + (CONF_SERCOM_0_USART_ENABLE + CONF_SERCOM_1_USART_ENABLE + CONF_SERCOM_2_USART_ENABLE + CONF_SERCOM_3_USART_ENABLE \ + + CONF_SERCOM_4_USART_ENABLE + CONF_SERCOM_5_USART_ENABLE + CONF_SERCOM_6_USART_ENABLE \ + + CONF_SERCOM_7_USART_ENABLE) + +/** + * \brief Macro is used to fill usart configuration structure based on + * its number + * + * \param[in] n The number of structures + */ +#define SERCOM_CONFIGURATION(n) \ + { \ + n, \ + SERCOM_USART_CTRLA_MODE(CONF_SERCOM_##n##_USART_MODE) \ + | (CONF_SERCOM_##n##_USART_RUNSTDBY << SERCOM_USART_CTRLA_RUNSTDBY_Pos) \ + | (CONF_SERCOM_##n##_USART_IBON << SERCOM_USART_CTRLA_IBON_Pos) \ + | (CONF_SERCOM_##n##_USART_TXINV << SERCOM_USART_CTRLA_TXINV_Pos) \ + | (CONF_SERCOM_##n##_USART_RXINV << SERCOM_USART_CTRLA_RXINV_Pos) \ + | SERCOM_USART_CTRLA_SAMPR(CONF_SERCOM_##n##_USART_SAMPR) \ + | SERCOM_USART_CTRLA_TXPO(CONF_SERCOM_##n##_USART_TXPO) \ + | SERCOM_USART_CTRLA_RXPO(CONF_SERCOM_##n##_USART_RXPO) \ + | SERCOM_USART_CTRLA_SAMPA(CONF_SERCOM_##n##_USART_SAMPA) \ + | SERCOM_USART_CTRLA_FORM(CONF_SERCOM_##n##_USART_FORM) \ + | (CONF_SERCOM_##n##_USART_CMODE << SERCOM_USART_CTRLA_CMODE_Pos) \ + | (CONF_SERCOM_##n##_USART_CPOL << SERCOM_USART_CTRLA_CPOL_Pos) \ + | (CONF_SERCOM_##n##_USART_DORD << SERCOM_USART_CTRLA_DORD_Pos), \ + SERCOM_USART_CTRLB_CHSIZE(CONF_SERCOM_##n##_USART_CHSIZE) \ + | (CONF_SERCOM_##n##_USART_SBMODE << SERCOM_USART_CTRLB_SBMODE_Pos) \ + | (CONF_SERCOM_##n##_USART_CLODEN << SERCOM_USART_CTRLB_COLDEN_Pos) \ + | (CONF_SERCOM_##n##_USART_SFDE << SERCOM_USART_CTRLB_SFDE_Pos) \ + | (CONF_SERCOM_##n##_USART_ENC << SERCOM_USART_CTRLB_ENC_Pos) \ + | (CONF_SERCOM_##n##_USART_PMODE << SERCOM_USART_CTRLB_PMODE_Pos) \ + | (CONF_SERCOM_##n##_USART_TXEN << SERCOM_USART_CTRLB_TXEN_Pos) \ + | (CONF_SERCOM_##n##_USART_RXEN << SERCOM_USART_CTRLB_RXEN_Pos), \ + SERCOM_USART_CTRLC_GTIME(CONF_SERCOM_##n##_USART_GTIME) \ + | (CONF_SERCOM_##n##_USART_DSNACK << SERCOM_USART_CTRLC_DSNACK_Pos) \ + | (CONF_SERCOM_##n##_USART_INACK << SERCOM_USART_CTRLC_INACK_Pos) \ + | SERCOM_USART_CTRLC_MAXITER(CONF_SERCOM_##n##_USART_MAXITER), \ + (uint16_t)(CONF_SERCOM_##n##_USART_BAUD_RATE), CONF_SERCOM_##n##_USART_FRACTIONAL, \ + CONF_SERCOM_##n##_USART_RECEIVE_PULSE_LENGTH, CONF_SERCOM_##n##_USART_DEBUG_STOP_MODE, \ + } + +/** + * \brief SERCOM USART configuration type + */ +struct usart_configuration { + uint8_t number; + hri_sercomusart_ctrla_reg_t ctrl_a; + hri_sercomusart_ctrlb_reg_t ctrl_b; + hri_sercomusart_ctrlc_reg_t ctrl_c; + hri_sercomusart_baud_reg_t baud; + uint8_t fractional; + hri_sercomusart_rxpl_reg_t rxpl; + hri_sercomusart_dbgctrl_reg_t debug_ctrl; +}; + +#if SERCOM_USART_AMOUNT < 1 +/** Dummy array to pass compiling. */ +static struct usart_configuration _usarts[1] = {{0}}; +#else +/** + * \brief Array of SERCOM USART configurations + */ +static struct usart_configuration _usarts[] = { +#if CONF_SERCOM_0_USART_ENABLE == 1 + SERCOM_CONFIGURATION(0), +#endif +#if CONF_SERCOM_1_USART_ENABLE == 1 + SERCOM_CONFIGURATION(1), +#endif +#if CONF_SERCOM_2_USART_ENABLE == 1 + SERCOM_CONFIGURATION(2), +#endif +#if CONF_SERCOM_3_USART_ENABLE == 1 + SERCOM_CONFIGURATION(3), +#endif +#if CONF_SERCOM_4_USART_ENABLE == 1 + SERCOM_CONFIGURATION(4), +#endif +#if CONF_SERCOM_5_USART_ENABLE == 1 + SERCOM_CONFIGURATION(5), +#endif +#if CONF_SERCOM_6_USART_ENABLE == 1 + SERCOM_CONFIGURATION(6), +#endif +#if CONF_SERCOM_7_USART_ENABLE == 1 + SERCOM_CONFIGURATION(7), +#endif +}; +#endif + +static struct _usart_async_device *_sercom0_dev = NULL; + +static struct _usart_async_device *_sercom1_dev = NULL; + +static struct _usart_async_device *_sercom2_dev = NULL; + +static struct _usart_async_device *_sercom3_dev = NULL; + +static struct _usart_async_device *_sercom4_dev = NULL; + +static struct _usart_async_device *_sercom5_dev = NULL; + +static struct _usart_async_device *_sercom6_dev = NULL; + +static uint8_t _get_sercom_index(const void *const hw); +static uint8_t _sercom_get_irq_num(const void *const hw); +static void _sercom_init_irq_param(const void *const hw, void *dev); +static uint8_t _sercom_get_hardware_index(const void *const hw); + +static int32_t _usart_init(void *const hw); +static inline void _usart_deinit(void *const hw); +static uint16_t _usart_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples, + const enum usart_baud_rate_mode mode, const uint8_t fraction); +static void _usart_set_baud_rate(void *const hw, const uint32_t baud_rate); +static void _usart_set_data_order(void *const hw, const enum usart_data_order order); +static void _usart_set_mode(void *const hw, const enum usart_mode mode); +static void _usart_set_parity(void *const hw, const enum usart_parity parity); +static void _usart_set_stop_bits(void *const hw, const enum usart_stop_bits stop_bits); +static void _usart_set_character_size(void *const hw, const enum usart_character_size size); + +/** + * \brief Initialize synchronous SERCOM USART + */ +int32_t _usart_sync_init(struct _usart_sync_device *const device, void *const hw) +{ + ASSERT(device); + + device->hw = hw; + + return _usart_init(hw); +} + +/** + * \brief Initialize asynchronous SERCOM USART + */ +int32_t _usart_async_init(struct _usart_async_device *const device, void *const hw) +{ + int32_t init_status; + + ASSERT(device); + + init_status = _usart_init(hw); + if (init_status) { + return init_status; + } + device->hw = hw; + _sercom_init_irq_param(hw, (void *)device); + uint8_t irq = _sercom_get_irq_num(hw); + for (uint32_t i = 0; i < 4; i++) { + NVIC_DisableIRQ((IRQn_Type)irq); + NVIC_ClearPendingIRQ((IRQn_Type)irq); + NVIC_EnableIRQ((IRQn_Type)irq); + irq++; + } + return ERR_NONE; +} + +/** + * \brief De-initialize SERCOM USART + */ +void _usart_sync_deinit(struct _usart_sync_device *const device) +{ + _usart_deinit(device->hw); +} + +/** + * \brief De-initialize SERCOM USART + */ +void _usart_async_deinit(struct _usart_async_device *const device) +{ + NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(device->hw)); + _usart_deinit(device->hw); +} + +/** + * \brief Calculate baud rate register value + */ +uint16_t _usart_sync_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples, + const enum usart_baud_rate_mode mode, const uint8_t fraction) +{ + return _usart_calculate_baud_rate(baud, clock_rate, samples, mode, fraction); +} + +/** + * \brief Calculate baud rate register value + */ +uint16_t _usart_async_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples, + const enum usart_baud_rate_mode mode, const uint8_t fraction) +{ + return _usart_calculate_baud_rate(baud, clock_rate, samples, mode, fraction); +} + +/** + * \brief Enable SERCOM module + */ +void _usart_sync_enable(struct _usart_sync_device *const device) +{ + hri_sercomusart_set_CTRLA_ENABLE_bit(device->hw); +} + +/** + * \brief Enable SERCOM module + */ +void _usart_async_enable(struct _usart_async_device *const device) +{ + hri_sercomusart_set_CTRLA_ENABLE_bit(device->hw); +} + +/** + * \brief Disable SERCOM module + */ +void _usart_sync_disable(struct _usart_sync_device *const device) +{ + hri_sercomusart_clear_CTRLA_ENABLE_bit(device->hw); +} + +/** + * \brief Disable SERCOM module + */ +void _usart_async_disable(struct _usart_async_device *const device) +{ + hri_sercomusart_clear_CTRLA_ENABLE_bit(device->hw); +} + +/** + * \brief Set baud rate + */ +void _usart_sync_set_baud_rate(struct _usart_sync_device *const device, const uint32_t baud_rate) +{ + _usart_set_baud_rate(device->hw, baud_rate); +} + +/** + * \brief Set baud rate + */ +void _usart_async_set_baud_rate(struct _usart_async_device *const device, const uint32_t baud_rate) +{ + _usart_set_baud_rate(device->hw, baud_rate); +} + +/** + * \brief Set data order + */ +void _usart_sync_set_data_order(struct _usart_sync_device *const device, const enum usart_data_order order) +{ + _usart_set_data_order(device->hw, order); +} + +/** + * \brief Set data order + */ +void _usart_async_set_data_order(struct _usart_async_device *const device, const enum usart_data_order order) +{ + _usart_set_data_order(device->hw, order); +} + +/** + * \brief Set mode + */ +void _usart_sync_set_mode(struct _usart_sync_device *const device, const enum usart_mode mode) +{ + _usart_set_mode(device->hw, mode); +} + +/** + * \brief Set mode + */ +void _usart_async_set_mode(struct _usart_async_device *const device, const enum usart_mode mode) +{ + _usart_set_mode(device->hw, mode); +} + +/** + * \brief Set parity + */ +void _usart_sync_set_parity(struct _usart_sync_device *const device, const enum usart_parity parity) +{ + _usart_set_parity(device->hw, parity); +} + +/** + * \brief Set parity + */ +void _usart_async_set_parity(struct _usart_async_device *const device, const enum usart_parity parity) +{ + _usart_set_parity(device->hw, parity); +} + +/** + * \brief Set stop bits mode + */ +void _usart_sync_set_stop_bits(struct _usart_sync_device *const device, const enum usart_stop_bits stop_bits) +{ + _usart_set_stop_bits(device->hw, stop_bits); +} + +/** + * \brief Set stop bits mode + */ +void _usart_async_set_stop_bits(struct _usart_async_device *const device, const enum usart_stop_bits stop_bits) +{ + _usart_set_stop_bits(device->hw, stop_bits); +} + +/** + * \brief Set character size + */ +void _usart_sync_set_character_size(struct _usart_sync_device *const device, const enum usart_character_size size) +{ + _usart_set_character_size(device->hw, size); +} + +/** + * \brief Set character size + */ +void _usart_async_set_character_size(struct _usart_async_device *const device, const enum usart_character_size size) +{ + _usart_set_character_size(device->hw, size); +} + +/** + * \brief Retrieve SERCOM usart status + */ +uint32_t _usart_sync_get_status(const struct _usart_sync_device *const device) +{ + return hri_sercomusart_read_STATUS_reg(device->hw); +} + +/** + * \brief Retrieve SERCOM usart status + */ +uint32_t _usart_async_get_status(const struct _usart_async_device *const device) +{ + return hri_sercomusart_read_STATUS_reg(device->hw); +} + +/** + * \brief Write a byte to the given SERCOM USART instance + */ +void _usart_sync_write_byte(struct _usart_sync_device *const device, uint8_t data) +{ + hri_sercomusart_write_DATA_reg(device->hw, data); +} + +/** + * \brief Write a byte to the given SERCOM USART instance + */ +void _usart_async_write_byte(struct _usart_async_device *const device, uint8_t data) +{ + hri_sercomusart_write_DATA_reg(device->hw, data); +} + +/** + * \brief Read a byte from the given SERCOM USART instance + */ +uint8_t _usart_sync_read_byte(const struct _usart_sync_device *const device) +{ + return hri_sercomusart_read_DATA_reg(device->hw); +} + +/** + * \brief Check if USART is ready to send next byte + */ +bool _usart_sync_is_ready_to_send(const struct _usart_sync_device *const device) +{ + return hri_sercomusart_get_interrupt_DRE_bit(device->hw); +} + +/** + * \brief Check if USART transmission complete + */ +bool _usart_sync_is_transmit_done(const struct _usart_sync_device *const device) +{ + return hri_sercomusart_get_interrupt_TXC_bit(device->hw); +} + +/** + * \brief Check if USART is ready to send next byte + */ +bool _usart_async_is_byte_sent(const struct _usart_async_device *const device) +{ + return hri_sercomusart_get_interrupt_DRE_bit(device->hw); +} + +/** + * \brief Check if there is data received by USART + */ +bool _usart_sync_is_byte_received(const struct _usart_sync_device *const device) +{ + return hri_sercomusart_get_interrupt_RXC_bit(device->hw); +} + +/** + * \brief Set the state of flow control pins + */ +void _usart_sync_set_flow_control_state(struct _usart_sync_device *const device, + const union usart_flow_control_state state) +{ + (void)device; + (void)state; +} + +/** + * \brief Set the state of flow control pins + */ +void _usart_async_set_flow_control_state(struct _usart_async_device *const device, + const union usart_flow_control_state state) +{ + (void)device; + (void)state; +} + +/** + * \brief Retrieve the state of flow control pins + */ +union usart_flow_control_state _usart_sync_get_flow_control_state(const struct _usart_sync_device *const device) +{ + (void)device; + union usart_flow_control_state state; + + state.value = 0; + state.bit.unavailable = 1; + return state; +} + +/** + * \brief Retrieve the state of flow control pins + */ +union usart_flow_control_state _usart_async_get_flow_control_state(const struct _usart_async_device *const device) +{ + (void)device; + union usart_flow_control_state state; + + state.value = 0; + state.bit.unavailable = 1; + return state; +} + +/** + * \brief Enable data register empty interrupt + */ +void _usart_async_enable_byte_sent_irq(struct _usart_async_device *const device) +{ + hri_sercomusart_set_INTEN_DRE_bit(device->hw); +} + +/** + * \brief Enable transmission complete interrupt + */ +void _usart_async_enable_tx_done_irq(struct _usart_async_device *const device) +{ + hri_sercomusart_set_INTEN_TXC_bit(device->hw); +} + +/** + * \brief Retrieve ordinal number of the given sercom hardware instance + */ +static uint8_t _sercom_get_hardware_index(const void *const hw) +{ + Sercom *const sercom_modules[] = SERCOM_INSTS; + /* Find index for SERCOM instance. */ + for (uint32_t i = 0; i < SERCOM_INST_NUM; i++) { + if ((uint32_t)hw == (uint32_t)sercom_modules[i]) { + return i; + } + } + return 0; +} + +/** + * \brief Retrieve ordinal number of the given SERCOM USART hardware instance + */ +uint8_t _usart_sync_get_hardware_index(const struct _usart_sync_device *const device) +{ + return _sercom_get_hardware_index(device->hw); +} + +/** + * \brief Retrieve ordinal number of the given SERCOM USART hardware instance + */ +uint8_t _usart_async_get_hardware_index(const struct _usart_async_device *const device) +{ + return _sercom_get_hardware_index(device->hw); +} + +/** + * \brief Enable/disable USART interrupt + */ +void _usart_async_set_irq_state(struct _usart_async_device *const device, const enum _usart_async_callback_type type, + const bool state) +{ + ASSERT(device); + + if (USART_ASYNC_BYTE_SENT == type || USART_ASYNC_TX_DONE == type) { + hri_sercomusart_write_INTEN_DRE_bit(device->hw, state); + hri_sercomusart_write_INTEN_TXC_bit(device->hw, state); + } else if (USART_ASYNC_RX_DONE == type) { + hri_sercomusart_write_INTEN_RXC_bit(device->hw, state); + } else if (USART_ASYNC_ERROR == type) { + hri_sercomusart_write_INTEN_ERROR_bit(device->hw, state); + } +} + +/** + * \internal Sercom interrupt handler + * + * \param[in] p The pointer to interrupt parameter + */ +static void _sercom_usart_interrupt_handler(struct _usart_async_device *device) +{ + void *hw = device->hw; + + if (hri_sercomusart_get_interrupt_DRE_bit(hw) && hri_sercomusart_get_INTEN_DRE_bit(hw)) { + hri_sercomusart_clear_INTEN_DRE_bit(hw); + device->usart_cb.tx_byte_sent(device); + } else if (hri_sercomusart_get_interrupt_TXC_bit(hw) && hri_sercomusart_get_INTEN_TXC_bit(hw)) { + hri_sercomusart_clear_INTEN_TXC_bit(hw); + device->usart_cb.tx_done_cb(device); + } else if (hri_sercomusart_get_interrupt_RXC_bit(hw)) { + if (hri_sercomusart_read_STATUS_reg(hw) + & (SERCOM_USART_STATUS_PERR | SERCOM_USART_STATUS_FERR | SERCOM_USART_STATUS_BUFOVF + | SERCOM_USART_STATUS_ISF | SERCOM_USART_STATUS_COLL)) { + hri_sercomusart_clear_STATUS_reg(hw, SERCOM_USART_STATUS_MASK); + return; + } + + device->usart_cb.rx_done_cb(device, hri_sercomusart_read_DATA_reg(hw)); + } else if (hri_sercomusart_get_interrupt_ERROR_bit(hw)) { + uint32_t status; + + hri_sercomusart_clear_interrupt_ERROR_bit(hw); + device->usart_cb.error_cb(device); + status = hri_sercomusart_read_STATUS_reg(hw); + hri_sercomusart_clear_STATUS_reg(hw, status); + } +} + +/** + * \internal Retrieve ordinal number of the given sercom hardware instance + * + * \param[in] hw The pointer to hardware instance + + * \return The ordinal number of the given sercom hardware instance + */ +static uint8_t _get_sercom_index(const void *const hw) +{ + uint8_t sercom_offset = _sercom_get_hardware_index(hw); + uint8_t i; + + for (i = 0; i < ARRAY_SIZE(_usarts); i++) { + if (_usarts[i].number == sercom_offset) { + return i; + } + } + + ASSERT(false); + return 0; +} + +/** + * \brief Init irq param with the given sercom hardware instance + */ +static void _sercom_init_irq_param(const void *const hw, void *dev) +{ + + if (hw == SERCOM0) { + _sercom0_dev = (struct _usart_async_device *)dev; + } + + if (hw == SERCOM1) { + _sercom1_dev = (struct _usart_async_device *)dev; + } + + if (hw == SERCOM2) { + _sercom2_dev = (struct _usart_async_device *)dev; + } + + if (hw == SERCOM3) { + _sercom3_dev = (struct _usart_async_device *)dev; + } + + if (hw == SERCOM4) { + _sercom4_dev = (struct _usart_async_device *)dev; + } + + if (hw == SERCOM5) { + _sercom5_dev = (struct _usart_async_device *)dev; + } + + if (hw == SERCOM6) { + _sercom6_dev = (struct _usart_async_device *)dev; + } +} + +/** + * \internal Initialize SERCOM USART + * + * \param[in] hw The pointer to hardware instance + * + * \return The status of initialization + */ +static int32_t _usart_init(void *const hw) +{ + uint8_t i = _get_sercom_index(hw); + + if (!hri_sercomusart_is_syncing(hw, SERCOM_USART_SYNCBUSY_SWRST)) { + uint32_t mode = _usarts[i].ctrl_a & SERCOM_USART_CTRLA_MODE_Msk; + if (hri_sercomusart_get_CTRLA_reg(hw, SERCOM_USART_CTRLA_ENABLE)) { + hri_sercomusart_clear_CTRLA_ENABLE_bit(hw); + hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE); + } + hri_sercomusart_write_CTRLA_reg(hw, SERCOM_USART_CTRLA_SWRST | mode); + } + hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_SWRST); + + hri_sercomusart_write_CTRLA_reg(hw, _usarts[i].ctrl_a); + hri_sercomusart_write_CTRLB_reg(hw, _usarts[i].ctrl_b); + hri_sercomusart_write_CTRLC_reg(hw, _usarts[i].ctrl_c); + if ((_usarts[i].ctrl_a & SERCOM_USART_CTRLA_SAMPR(0x1)) || (_usarts[i].ctrl_a & SERCOM_USART_CTRLA_SAMPR(0x3))) { + ((Sercom *)hw)->USART.BAUD.FRAC.BAUD = _usarts[i].baud; + ((Sercom *)hw)->USART.BAUD.FRAC.FP = _usarts[i].fractional; + } else { + hri_sercomusart_write_BAUD_reg(hw, _usarts[i].baud); + } + + hri_sercomusart_write_RXPL_reg(hw, _usarts[i].rxpl); + hri_sercomusart_write_DBGCTRL_reg(hw, _usarts[i].debug_ctrl); + + return ERR_NONE; +} + +/** + * \internal De-initialize SERCOM USART + * + * \param[in] hw The pointer to hardware instance + */ +static inline void _usart_deinit(void *const hw) +{ + hri_sercomusart_clear_CTRLA_ENABLE_bit(hw); + hri_sercomusart_set_CTRLA_SWRST_bit(hw); +} + +/** + * \internal Calculate baud rate register value + * + * \param[in] baud Required baud rate + * \param[in] clock_rate SERCOM clock frequency + * \param[in] samples The number of samples + * \param[in] mode USART mode + * \param[in] fraction A fraction value + * + * \return Calculated baud rate register value + */ +static uint16_t _usart_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples, + const enum usart_baud_rate_mode mode, const uint8_t fraction) +{ + if (USART_BAUDRATE_ASYNCH_ARITHMETIC == mode) { + return 65536 - ((uint64_t)65536 * samples * baud) / clock_rate; + } + + if (USART_BAUDRATE_ASYNCH_FRACTIONAL == mode) { + return clock_rate / baud / samples + SERCOM_USART_BAUD_FRACFP_FP(fraction); + } + + if (USART_BAUDRATE_SYNCH == mode) { + return clock_rate / baud / 2 - 1; + } + + return 0; +} + +/** + * \internal Set baud rate + * + * \param[in] device The pointer to USART device instance + * \param[in] baud_rate A baud rate to set + */ +static void _usart_set_baud_rate(void *const hw, const uint32_t baud_rate) +{ + bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw); + + hri_sercomusart_clear_CTRLA_ENABLE_bit(hw); + + CRITICAL_SECTION_ENTER() + hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE); + hri_sercomusart_write_BAUD_reg(hw, baud_rate); + CRITICAL_SECTION_LEAVE() + + hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled); +} + +/** + * \internal Set data order + * + * \param[in] device The pointer to USART device instance + * \param[in] order A data order to set + */ +static void _usart_set_data_order(void *const hw, const enum usart_data_order order) +{ + bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw); + + hri_sercomusart_clear_CTRLA_ENABLE_bit(hw); + + CRITICAL_SECTION_ENTER() + hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE); + hri_sercomusart_write_CTRLA_DORD_bit(hw, order); + CRITICAL_SECTION_LEAVE() + + hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled); +} + +/** + * \internal Set mode + * + * \param[in] device The pointer to USART device instance + * \param[in] mode A mode to set + */ +static void _usart_set_mode(void *const hw, const enum usart_mode mode) +{ + bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw); + + hri_sercomusart_clear_CTRLA_ENABLE_bit(hw); + + CRITICAL_SECTION_ENTER() + hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE); + hri_sercomusart_write_CTRLA_CMODE_bit(hw, mode); + CRITICAL_SECTION_LEAVE() + + hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled); +} + +/** + * \internal Set parity + * + * \param[in] device The pointer to USART device instance + * \param[in] parity A parity to set + */ +static void _usart_set_parity(void *const hw, const enum usart_parity parity) +{ + bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw); + + hri_sercomusart_clear_CTRLA_ENABLE_bit(hw); + + CRITICAL_SECTION_ENTER() + hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE); + + if (USART_PARITY_NONE != parity) { + hri_sercomusart_set_CTRLA_FORM_bf(hw, 1); + } else { + hri_sercomusart_clear_CTRLA_FORM_bf(hw, 1); + } + + hri_sercomusart_write_CTRLB_PMODE_bit(hw, parity); + CRITICAL_SECTION_LEAVE() + + hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled); +} + +/** + * \internal Set stop bits mode + * + * \param[in] device The pointer to USART device instance + * \param[in] stop_bits A stop bits mode to set + */ +static void _usart_set_stop_bits(void *const hw, const enum usart_stop_bits stop_bits) +{ + bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw); + + hri_sercomusart_clear_CTRLA_ENABLE_bit(hw); + + CRITICAL_SECTION_ENTER() + hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE); + hri_sercomusart_write_CTRLB_SBMODE_bit(hw, stop_bits); + CRITICAL_SECTION_LEAVE() + + hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled); +} + +/** + * \internal Set character size + * + * \param[in] device The pointer to USART device instance + * \param[in] size A character size to set + */ +static void _usart_set_character_size(void *const hw, const enum usart_character_size size) +{ + bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw); + + hri_sercomusart_clear_CTRLA_ENABLE_bit(hw); + + CRITICAL_SECTION_ENTER() + hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE); + hri_sercomusart_write_CTRLB_CHSIZE_bf(hw, size); + CRITICAL_SECTION_LEAVE() + + if (enabled) { + hri_sercomusart_set_CTRLA_ENABLE_bit(hw); + } +} + + /* Sercom I2C implementation */ + +#ifndef CONF_SERCOM_0_I2CM_ENABLE +#define CONF_SERCOM_0_I2CM_ENABLE 0 +#endif +#ifndef CONF_SERCOM_1_I2CM_ENABLE +#define CONF_SERCOM_1_I2CM_ENABLE 0 +#endif +#ifndef CONF_SERCOM_2_I2CM_ENABLE +#define CONF_SERCOM_2_I2CM_ENABLE 0 +#endif +#ifndef CONF_SERCOM_3_I2CM_ENABLE +#define CONF_SERCOM_3_I2CM_ENABLE 0 +#endif +#ifndef CONF_SERCOM_4_I2CM_ENABLE +#define CONF_SERCOM_4_I2CM_ENABLE 0 +#endif +#ifndef CONF_SERCOM_5_I2CM_ENABLE +#define CONF_SERCOM_5_I2CM_ENABLE 0 +#endif +#ifndef CONF_SERCOM_6_I2CM_ENABLE +#define CONF_SERCOM_6_I2CM_ENABLE 0 +#endif +#ifndef CONF_SERCOM_7_I2CM_ENABLE +#define CONF_SERCOM_7_I2CM_ENABLE 0 +#endif + +/** Amount of SERCOM that is used as I2C Master. */ +#define SERCOM_I2CM_AMOUNT \ + (CONF_SERCOM_0_I2CM_ENABLE + CONF_SERCOM_1_I2CM_ENABLE + CONF_SERCOM_2_I2CM_ENABLE + CONF_SERCOM_3_I2CM_ENABLE \ + + CONF_SERCOM_4_I2CM_ENABLE + CONF_SERCOM_5_I2CM_ENABLE + CONF_SERCOM_6_I2CM_ENABLE + CONF_SERCOM_7_I2CM_ENABLE) + +/** + * \brief Macro is used to fill i2cm configuration structure based on + * its number + * + * \param[in] n The number of structures + */ +#define I2CM_CONFIGURATION(n) \ + { \ + (n), \ + (SERCOM_I2CM_CTRLA_MODE_I2C_MASTER) | (CONF_SERCOM_##n##_I2CM_RUNSTDBY << SERCOM_I2CM_CTRLA_RUNSTDBY_Pos) \ + | (CONF_SERCOM_##n##_I2CM_SPEED << SERCOM_I2CM_CTRLA_SPEED_Pos) \ + | (CONF_SERCOM_##n##_I2CM_MEXTTOEN << SERCOM_I2CM_CTRLA_MEXTTOEN_Pos) \ + | (CONF_SERCOM_##n##_I2CM_SEXTTOEN << SERCOM_I2CM_CTRLA_SEXTTOEN_Pos) \ + | (CONF_SERCOM_##n##_I2CM_INACTOUT << SERCOM_I2CM_CTRLA_INACTOUT_Pos) \ + | (CONF_SERCOM_##n##_I2CM_LOWTOUT << SERCOM_I2CM_CTRLA_LOWTOUTEN_Pos) \ + | (CONF_SERCOM_##n##_I2CM_SDAHOLD << SERCOM_I2CM_CTRLA_SDAHOLD_Pos), \ + SERCOM_I2CM_CTRLB_SMEN, (uint32_t)(CONF_SERCOM_##n##_I2CM_BAUD_RATE), \ + CONF_SERCOM_##n##_I2CM_DEBUG_STOP_MODE, CONF_SERCOM_##n##_I2CM_TRISE, CONF_GCLK_SERCOM##n##_CORE_FREQUENCY \ + } + +#define ERROR_FLAG (1 << 7) +#define SB_FLAG (1 << 1) +#define MB_FLAG (1 << 0) + +#define CMD_STOP 0x3 +#define I2C_IDLE 0x1 +#define I2C_SM 0x0 +#define I2C_FM 0x1 +#define I2C_HS 0x2 +#define TEN_ADDR_FRAME 0x78 +#define TEN_ADDR_MASK 0x3ff +#define SEVEN_ADDR_MASK 0x7f + +/** + * \brief SERCOM I2CM configuration type + */ +struct i2cm_configuration { + uint8_t number; + hri_sercomi2cm_ctrla_reg_t ctrl_a; + hri_sercomi2cm_ctrlb_reg_t ctrl_b; + hri_sercomi2cm_baud_reg_t baud; + hri_sercomi2cm_dbgctrl_reg_t dbgctrl; + uint16_t trise; + uint32_t clk; /* SERCOM peripheral clock frequency */ +}; + +static inline int32_t _i2c_m_enable_implementation(void *hw); +static int32_t _i2c_m_sync_init_impl(struct _i2c_m_service *const service, void *const hw); + +#if SERCOM_I2CM_AMOUNT < 1 +/** Dummy array to pass compiling. */ +static struct i2cm_configuration _i2cms[1] = {{0}}; +#else +/** + * \brief Array of SERCOM I2CM configurations + */ +static struct i2cm_configuration _i2cms[] = { +#if CONF_SERCOM_0_I2CM_ENABLE == 1 + I2CM_CONFIGURATION(0), +#endif +#if CONF_SERCOM_1_I2CM_ENABLE == 1 + I2CM_CONFIGURATION(1), +#endif +#if CONF_SERCOM_2_I2CM_ENABLE == 1 + I2CM_CONFIGURATION(2), +#endif +#if CONF_SERCOM_3_I2CM_ENABLE == 1 + I2CM_CONFIGURATION(3), +#endif +#if CONF_SERCOM_4_I2CM_ENABLE == 1 + I2CM_CONFIGURATION(4), +#endif +#if CONF_SERCOM_5_I2CM_ENABLE == 1 + I2CM_CONFIGURATION(5), +#endif +#if CONF_SERCOM_6_I2CM_ENABLE == 1 + I2CM_CONFIGURATION(6), +#endif +#if CONF_SERCOM_7_I2CM_ENABLE == 1 + I2CM_CONFIGURATION(7), +#endif +}; +#endif + +/** + * \internal Retrieve ordinal number of the given sercom hardware instance + * + * \param[in] hw The pointer to hardware instance + + * \return The ordinal number of the given sercom hardware instance + */ +static int8_t _get_i2cm_index(const void *const hw) +{ + uint8_t sercom_offset = _sercom_get_hardware_index(hw); + uint8_t i; + + for (i = 0; i < ARRAY_SIZE(_i2cms); i++) { + if (_i2cms[i].number == sercom_offset) { + return i; + } + } + + ASSERT(false); + return -1; +} + +static inline void _sercom_i2c_send_stop(void *const hw) +{ + hri_sercomi2cm_set_CTRLB_CMD_bf(hw, CMD_STOP); +} + +/** + * \brief SERCOM I2CM analyze hardware status and transfer next byte + */ +static inline int32_t _sercom_i2c_sync_analyse_flags(void *const hw, uint32_t flags, struct _i2c_m_msg *const msg) +{ + int sclsm = hri_sercomi2cm_get_CTRLA_SCLSM_bit(hw); + uint16_t status = hri_sercomi2cm_read_STATUS_reg(hw); + + if (flags & MB_FLAG) { + /* tx error */ + if (status & SERCOM_I2CM_STATUS_ARBLOST) { + hri_sercomi2cm_clear_interrupt_MB_bit(hw); + msg->flags |= I2C_M_FAIL; + msg->flags &= ~I2C_M_BUSY; + + if (status & SERCOM_I2CM_STATUS_BUSERR) { + return I2C_ERR_BUS; + } + + return I2C_ERR_BAD_ADDRESS; + } else { + if (status & SERCOM_I2CM_STATUS_RXNACK) { + + /* Slave rejects to receive more data */ + if (msg->len > 0) { + msg->flags |= I2C_M_FAIL; + } + + if (msg->flags & I2C_M_STOP) { + _sercom_i2c_send_stop(hw); + } + + msg->flags &= ~I2C_M_BUSY; + + return I2C_NACK; + } + + if (msg->flags & I2C_M_TEN) { + hri_sercomi2cm_write_ADDR_reg(hw, + ((((msg->addr & TEN_ADDR_MASK) >> 8) | TEN_ADDR_FRAME) << 1) | I2C_M_RD + | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS)); + msg->flags &= ~I2C_M_TEN; + + return I2C_OK; + } + + if (msg->len == 0) { + if (msg->flags & I2C_M_STOP) { + _sercom_i2c_send_stop(hw); + } + + msg->flags &= ~I2C_M_BUSY; + } else { + hri_sercomi2cm_write_DATA_reg(hw, *msg->buffer); + msg->buffer++; + msg->len--; + } + + return I2C_OK; + } + } else if (flags & SB_FLAG) { + if ((msg->len) && !(status & SERCOM_I2CM_STATUS_RXNACK)) { + msg->len--; + + /* last byte, send nack */ + if ((msg->len == 0 && !sclsm) || (msg->len == 1 && sclsm)) { + hri_sercomi2cm_set_CTRLB_ACKACT_bit(hw); + } + + if (msg->len == 0) { + if (msg->flags & I2C_M_STOP) { + hri_sercomi2cm_clear_CTRLB_SMEN_bit(hw); + _sercom_i2c_send_stop(hw); + } + + msg->flags &= ~I2C_M_BUSY; + } + + /* Accessing DATA.DATA auto-triggers I2C bus operations. + * The operation performed depends on the state of + * CTRLB.ACKACT, CTRLB.SMEN + **/ + *msg->buffer++ = hri_sercomi2cm_read_DATA_reg(hw); + } else { + hri_sercomi2cm_clear_interrupt_SB_bit(hw); + return I2C_NACK; + } + + hri_sercomi2cm_clear_interrupt_SB_bit(hw); + } + + return I2C_OK; +} + +/** + * \brief Enable the i2c master module + * + * \param[in] i2c_dev The pointer to i2c device + */ +int32_t _i2c_m_async_enable(struct _i2c_m_async_device *const i2c_dev) +{ + ASSERT(i2c_dev); + + return _i2c_m_enable_implementation(i2c_dev->hw); +} + +/** + * \brief Disable the i2c master module + * + * \param[in] i2c_dev The pointer to i2c device + */ +int32_t _i2c_m_async_disable(struct _i2c_m_async_device *const i2c_dev) +{ + void *hw = i2c_dev->hw; + + ASSERT(i2c_dev); + ASSERT(i2c_dev->hw); + + NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(hw)); + hri_sercomi2cm_clear_CTRLA_ENABLE_bit(hw); + + return ERR_NONE; +} + +/** + * \brief Set baudrate of master + * + * \param[in] i2c_dev The pointer to i2c device + * \param[in] clkrate The clock rate of i2c master, in KHz + * \param[in] baudrate The baud rate desired for i2c master, in KHz + */ +int32_t _i2c_m_async_set_baudrate(struct _i2c_m_async_device *const i2c_dev, uint32_t clkrate, uint32_t baudrate) +{ + uint32_t tmp; + void * hw = i2c_dev->hw; + + if (hri_sercomi2cm_get_CTRLA_ENABLE_bit(hw)) { + return ERR_DENIED; + } + + tmp = _get_i2cm_index(hw); + clkrate = _i2cms[tmp].clk / 1000; + + if (i2c_dev->service.mode == I2C_STANDARD_MODE) { + tmp = (uint32_t)((clkrate - 10 * baudrate - baudrate * clkrate * (i2c_dev->service.trise * 0.000000001)) + / (2 * baudrate)); + hri_sercomi2cm_write_BAUD_BAUD_bf(hw, tmp); + } else if (i2c_dev->service.mode == I2C_FASTMODE) { + tmp = (uint32_t)((clkrate - 10 * baudrate - baudrate * clkrate * (i2c_dev->service.trise * 0.000000001)) + / (2 * baudrate)); + hri_sercomi2cm_write_BAUD_BAUD_bf(hw, tmp); + } else if (i2c_dev->service.mode == I2C_HIGHSPEED_MODE) { + tmp = (clkrate - 2 * baudrate) / (2 * baudrate); + hri_sercomi2cm_write_BAUD_HSBAUD_bf(hw, tmp); + } else { + /* error baudrate */ + return ERR_INVALID_ARG; + } + + return ERR_NONE; +} + +/** + * \brief Retrieve IRQ number for the given hardware instance + */ +static uint8_t _sercom_get_irq_num(const void *const hw) +{ + return SERCOM0_0_IRQn + (_sercom_get_hardware_index(hw) << 2); +} + +/** + * \brief Initialize sercom i2c module to use in async mode + * + * \param[in] i2c_dev The pointer to i2c device + */ +int32_t _i2c_m_async_init(struct _i2c_m_async_device *const i2c_dev, void *const hw) +{ + int32_t init_status; + + ASSERT(i2c_dev); + + i2c_dev->hw = hw; + + init_status = _i2c_m_sync_init_impl(&i2c_dev->service, hw); + if (init_status) { + return init_status; + } + + _sercom_init_irq_param(hw, (void *)i2c_dev); + uint8_t irq = _sercom_get_irq_num(hw); + for (uint32_t i = 0; i < 4; i++) { + NVIC_DisableIRQ((IRQn_Type)irq); + NVIC_ClearPendingIRQ((IRQn_Type)irq); + NVIC_EnableIRQ((IRQn_Type)irq); + irq++; + } + return ERR_NONE; +} + +/** + * \brief Deinitialize sercom i2c module + * + * \param[in] i2c_dev The pointer to i2c device + */ +int32_t _i2c_m_async_deinit(struct _i2c_m_async_device *const i2c_dev) +{ + ASSERT(i2c_dev); + + hri_sercomi2cm_clear_CTRLA_ENABLE_bit(i2c_dev->hw); + hri_sercomi2cm_set_CTRLA_SWRST_bit(i2c_dev->hw); + + return ERR_NONE; +} + +/** + * \brief Transfer the slave address to bus, which will start the transfer + * + * \param[in] i2c_dev The pointer to i2c device + */ +static int32_t _sercom_i2c_send_address(struct _i2c_m_async_device *const i2c_dev) +{ + void * hw = i2c_dev->hw; + struct _i2c_m_msg *msg = &i2c_dev->service.msg; + int sclsm = hri_sercomi2cm_get_CTRLA_SCLSM_bit(hw); + + ASSERT(i2c_dev); + + if (msg->len == 1 && sclsm) { + hri_sercomi2cm_set_CTRLB_ACKACT_bit(hw); + } else { + hri_sercomi2cm_clear_CTRLB_ACKACT_bit(hw); + } + + /* ten bit address */ + if (msg->addr & I2C_M_TEN) { + if (msg->flags & I2C_M_RD) { + msg->flags |= I2C_M_TEN; + } + + hri_sercomi2cm_write_ADDR_reg(hw, + ((msg->addr & TEN_ADDR_MASK) << 1) | SERCOM_I2CM_ADDR_TENBITEN + | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS)); + } else { + hri_sercomi2cm_write_ADDR_reg(hw, + ((msg->addr & SEVEN_ADDR_MASK) << 1) | (msg->flags & I2C_M_RD ? I2C_M_RD : 0x0) + | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS)); + } + + return ERR_NONE; +} + +/** + * \brief Transfer data specified by msg + * + * \param[in] i2c_dev The pointer to i2c device + * \param[in] msg The pointer to i2c message + * + * \return Transfer status. + * \retval 0 Transfer success + * \retval <0 Transfer fail, return the error code + */ +int32_t _i2c_m_async_transfer(struct _i2c_m_async_device *i2c_dev, struct _i2c_m_msg *msg) +{ + int ret; + + ASSERT(i2c_dev); + ASSERT(i2c_dev->hw); + ASSERT(msg); + + if (msg->len == 0) { + return ERR_NONE; + } + + if (i2c_dev->service.msg.flags & I2C_M_BUSY) { + return ERR_BUSY; + } + + msg->flags |= I2C_M_BUSY; + i2c_dev->service.msg = *msg; + hri_sercomi2cm_set_CTRLB_SMEN_bit(i2c_dev->hw); + + ret = _sercom_i2c_send_address(i2c_dev); + + if (ret) { + i2c_dev->service.msg.flags &= ~I2C_M_BUSY; + + return ret; + } + + return ERR_NONE; +} + +/** + * \brief Set callback to be called in interrupt handler + * + * \param[in] i2c_dev The pointer to master i2c device + * \param[in] type The callback type + * \param[in] func The callback function pointer + */ +int32_t _i2c_m_async_register_callback(struct _i2c_m_async_device *const i2c_dev, enum _i2c_m_async_callback_type type, + FUNC_PTR func) +{ + switch (type) { + case I2C_M_ASYNC_DEVICE_ERROR: + i2c_dev->cb.error = (_i2c_error_cb_t)func; + break; + case I2C_M_ASYNC_DEVICE_TX_COMPLETE: + i2c_dev->cb.tx_complete = (_i2c_complete_cb_t)func; + break; + case I2C_M_ASYNC_DEVICE_RX_COMPLETE: + i2c_dev->cb.rx_complete = (_i2c_complete_cb_t)func; + break; + default: + /* error */ + break; + } + + return ERR_NONE; +} + +/** + * \brief Set stop condition on I2C + * + * \param i2c_dev Pointer to master i2c device + * + * \return Operation status + * \retval I2C_OK Operation was successfull + */ +int32_t _i2c_m_async_send_stop(struct _i2c_m_async_device *const i2c_dev) +{ + void *hw = i2c_dev->hw; + + _sercom_i2c_send_stop(hw); + + return I2C_OK; +} + +/** + * \brief Get number of bytes left in transfer buffer + * + * \param i2c_dev Pointer to i2c master device + * + * \return Bytes left in buffer + * \retval =>0 Bytes left in buffer + */ +int32_t _i2c_m_async_get_bytes_left(struct _i2c_m_async_device *const i2c_dev) +{ + if (i2c_dev->service.msg.flags & I2C_M_BUSY) { + return i2c_dev->service.msg.len; + } + + return 0; +} + +/** + * \brief Initialize sercom i2c module to use in sync mode + * + * \param[in] i2c_dev The pointer to i2c device + */ +int32_t _i2c_m_sync_init(struct _i2c_m_sync_device *const i2c_dev, void *const hw) +{ + ASSERT(i2c_dev); + + i2c_dev->hw = hw; + + return _i2c_m_sync_init_impl(&i2c_dev->service, hw); +} + +/** + * \brief Deinitialize sercom i2c module + * + * \param[in] i2c_dev The pointer to i2c device + */ +int32_t _i2c_m_sync_deinit(struct _i2c_m_sync_device *const i2c_dev) +{ + ASSERT(i2c_dev); + + hri_sercomi2cm_clear_CTRLA_ENABLE_bit(i2c_dev->hw); + hri_sercomi2cm_set_CTRLA_SWRST_bit(i2c_dev->hw); + + return ERR_NONE; +} + +/** + * \brief Enable the i2c master module + * + * \param[in] i2c_dev The pointer to i2c device + */ +int32_t _i2c_m_sync_enable(struct _i2c_m_sync_device *const i2c_dev) +{ + ASSERT(i2c_dev); + + return _i2c_m_enable_implementation(i2c_dev->hw); +} + +/** + * \brief Disable the i2c master module + * + * \param[in] i2c_dev The pointer to i2c device + */ +int32_t _i2c_m_sync_disable(struct _i2c_m_sync_device *const i2c_dev) +{ + void *hw = i2c_dev->hw; + + ASSERT(i2c_dev); + ASSERT(i2c_dev->hw); + + hri_sercomi2cm_clear_CTRLA_ENABLE_bit(hw); + + return ERR_NONE; +} + +/** + * \brief Set baudrate of master + * + * \param[in] i2c_dev The pointer to i2c device + * \param[in] clkrate The clock rate of i2c master, in KHz + * \param[in] baudrate The baud rate desired for i2c master, in KHz + */ +int32_t _i2c_m_sync_set_baudrate(struct _i2c_m_sync_device *const i2c_dev, uint32_t clkrate, uint32_t baudrate) +{ + uint32_t tmp; + void * hw = i2c_dev->hw; + + if (hri_sercomi2cm_get_CTRLA_ENABLE_bit(hw)) { + return ERR_DENIED; + } + + tmp = _get_i2cm_index(hw); + clkrate = _i2cms[tmp].clk / 1000; + + if (i2c_dev->service.mode == I2C_STANDARD_MODE) { + tmp = (uint32_t)((clkrate - 10 * baudrate - baudrate * clkrate * (i2c_dev->service.trise * 0.000000001)) + / (2 * baudrate)); + hri_sercomi2cm_write_BAUD_BAUD_bf(hw, tmp); + } else if (i2c_dev->service.mode == I2C_FASTMODE) { + tmp = (uint32_t)((clkrate - 10 * baudrate - baudrate * clkrate * (i2c_dev->service.trise * 0.000000001)) + / (2 * baudrate)); + hri_sercomi2cm_write_BAUD_BAUD_bf(hw, tmp); + } else if (i2c_dev->service.mode == I2C_HIGHSPEED_MODE) { + tmp = (clkrate - 2 * baudrate) / (2 * baudrate); + hri_sercomi2cm_write_BAUD_HSBAUD_bf(hw, tmp); + } else { + /* error baudrate */ + return ERR_INVALID_ARG; + } + + return ERR_NONE; +} + +/** + * \brief Enable/disable I2C master interrupt + */ +void _i2c_m_async_set_irq_state(struct _i2c_m_async_device *const device, const enum _i2c_m_async_callback_type type, + const bool state) +{ + if (I2C_M_ASYNC_DEVICE_TX_COMPLETE == type || I2C_M_ASYNC_DEVICE_RX_COMPLETE == type) { + hri_sercomi2cm_write_INTEN_SB_bit(device->hw, state); + hri_sercomi2cm_write_INTEN_MB_bit(device->hw, state); + } else if (I2C_M_ASYNC_DEVICE_ERROR == type) { + hri_sercomi2cm_write_INTEN_ERROR_bit(device->hw, state); + } +} + +/** + * \brief Wait for bus response + * + * \param[in] i2c_dev The pointer to i2c device + * \param[in] flags Store the hardware response + * + * \return Bus response status. + * \retval 0 Bus response status OK + * \retval <0 Bus response fail + */ +inline static int32_t _sercom_i2c_sync_wait_bus(struct _i2c_m_sync_device *const i2c_dev, uint32_t *flags) +{ + uint32_t timeout = 65535; + void * hw = i2c_dev->hw; + + do { + *flags = hri_sercomi2cm_read_INTFLAG_reg(hw); + + if (timeout-- == 0) { + return I2C_ERR_BUS; + } + } while (!(*flags & MB_FLAG) && !(*flags & SB_FLAG)); + + return I2C_OK; +} + +/** + * \brief Send the slave address to bus, which will start the transfer + * + * \param[in] i2c_dev The pointer to i2c device + */ +static int32_t _sercom_i2c_sync_send_address(struct _i2c_m_sync_device *const i2c_dev) +{ + void * hw = i2c_dev->hw; + struct _i2c_m_msg *msg = &i2c_dev->service.msg; + int sclsm = hri_sercomi2cm_get_CTRLA_SCLSM_bit(hw); + uint32_t flags; + + ASSERT(i2c_dev); + + if (msg->len == 1 && sclsm) { + hri_sercomi2cm_set_CTRLB_ACKACT_bit(hw); + } else { + hri_sercomi2cm_clear_CTRLB_ACKACT_bit(hw); + } + + /* ten bit address */ + if (msg->addr & I2C_M_TEN) { + if (msg->flags & I2C_M_RD) { + msg->flags |= I2C_M_TEN; + } + + hri_sercomi2cm_write_ADDR_reg(hw, + ((msg->addr & TEN_ADDR_MASK) << 1) | SERCOM_I2CM_ADDR_TENBITEN + | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS)); + } else { + hri_sercomi2cm_write_ADDR_reg(hw, + ((msg->addr & SEVEN_ADDR_MASK) << 1) | (msg->flags & I2C_M_RD ? I2C_M_RD : 0x0) + | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS)); + } + + _sercom_i2c_sync_wait_bus(i2c_dev, &flags); + return _sercom_i2c_sync_analyse_flags(hw, flags, msg); +} + +/** + * \brief Transfer data specified by msg + * + * \param[in] i2c_dev The pointer to i2c device + * \param[in] msg The pointer to i2c message + * + * \return Transfer status. + * \retval 0 Transfer success + * \retval <0 Transfer fail or partial fail, return the error code + */ +int32_t _i2c_m_sync_transfer(struct _i2c_m_sync_device *const i2c_dev, struct _i2c_m_msg *msg) +{ + uint32_t flags; + int ret; + void * hw = i2c_dev->hw; + + ASSERT(i2c_dev); + ASSERT(i2c_dev->hw); + ASSERT(msg); + + if (i2c_dev->service.msg.flags & I2C_M_BUSY) { + return I2C_ERR_BUSY; + } + + msg->flags |= I2C_M_BUSY; + i2c_dev->service.msg = *msg; + hri_sercomi2cm_set_CTRLB_SMEN_bit(hw); + + ret = _sercom_i2c_sync_send_address(i2c_dev); + + if (ret) { + i2c_dev->service.msg.flags &= ~I2C_M_BUSY; + + return ret; + } + + while (i2c_dev->service.msg.flags & I2C_M_BUSY) { + ret = _sercom_i2c_sync_wait_bus(i2c_dev, &flags); + + if (ret) { + if (msg->flags & I2C_M_STOP) { + _sercom_i2c_send_stop(hw); + } + + i2c_dev->service.msg.flags &= ~I2C_M_BUSY; + + return ret; + } + + ret = _sercom_i2c_sync_analyse_flags(hw, flags, &i2c_dev->service.msg); + } + + return ret; +} + +int32_t _i2c_m_sync_send_stop(struct _i2c_m_sync_device *const i2c_dev) +{ + void *hw = i2c_dev->hw; + + _sercom_i2c_send_stop(hw); + + return I2C_OK; +} + +static inline int32_t _i2c_m_enable_implementation(void *const hw) +{ + int timeout = 65535; + int timeout_attempt = 4; + + ASSERT(hw); + + /* Enable interrupts */ + hri_sercomi2cm_set_CTRLA_ENABLE_bit(hw); + + while (hri_sercomi2cm_read_STATUS_BUSSTATE_bf(hw) != I2C_IDLE) { + timeout--; + + if (timeout <= 0) { + if (--timeout_attempt) + timeout = 65535; + else + return I2C_ERR_BUSY; + hri_sercomi2cm_clear_STATUS_reg(hw, SERCOM_I2CM_STATUS_BUSSTATE(I2C_IDLE)); + } + } + return ERR_NONE; +} + +static int32_t _i2c_m_sync_init_impl(struct _i2c_m_service *const service, void *const hw) +{ + uint8_t i = _get_i2cm_index(hw); + + if (!hri_sercomi2cm_is_syncing(hw, SERCOM_I2CM_SYNCBUSY_SWRST)) { + uint32_t mode = _i2cms[i].ctrl_a & SERCOM_I2CM_CTRLA_MODE_Msk; + if (hri_sercomi2cm_get_CTRLA_reg(hw, SERCOM_I2CM_CTRLA_ENABLE)) { + hri_sercomi2cm_clear_CTRLA_ENABLE_bit(hw); + hri_sercomi2cm_wait_for_sync(hw, SERCOM_I2CM_SYNCBUSY_ENABLE); + } + hri_sercomi2cm_write_CTRLA_reg(hw, SERCOM_I2CM_CTRLA_SWRST | mode); + } + hri_sercomi2cm_wait_for_sync(hw, SERCOM_I2CM_SYNCBUSY_SWRST); + + hri_sercomi2cm_write_CTRLA_reg(hw, _i2cms[i].ctrl_a); + hri_sercomi2cm_write_CTRLB_reg(hw, _i2cms[i].ctrl_b); + hri_sercomi2cm_write_BAUD_reg(hw, _i2cms[i].baud); + + service->mode = (_i2cms[i].ctrl_a & SERCOM_I2CM_CTRLA_SPEED_Msk) >> SERCOM_I2CM_CTRLA_SPEED_Pos; + hri_sercomi2cm_write_ADDR_HS_bit(hw, service->mode < I2C_HS ? 0 : 1); + + service->trise = _i2cms[i].trise; + + return ERR_NONE; +} + + /* SERCOM I2C slave */ + +#ifndef CONF_SERCOM_0_I2CS_ENABLE +#define CONF_SERCOM_0_I2CS_ENABLE 0 +#endif +#ifndef CONF_SERCOM_1_I2CS_ENABLE +#define CONF_SERCOM_1_I2CS_ENABLE 0 +#endif +#ifndef CONF_SERCOM_2_I2CS_ENABLE +#define CONF_SERCOM_2_I2CS_ENABLE 0 +#endif +#ifndef CONF_SERCOM_3_I2CS_ENABLE +#define CONF_SERCOM_3_I2CS_ENABLE 0 +#endif +#ifndef CONF_SERCOM_4_I2CS_ENABLE +#define CONF_SERCOM_4_I2CS_ENABLE 0 +#endif +#ifndef CONF_SERCOM_5_I2CS_ENABLE +#define CONF_SERCOM_5_I2CS_ENABLE 0 +#endif +#ifndef CONF_SERCOM_6_I2CS_ENABLE +#define CONF_SERCOM_6_I2CS_ENABLE 0 +#endif +#ifndef CONF_SERCOM_7_I2CS_ENABLE +#define CONF_SERCOM_7_I2CS_ENABLE 0 +#endif + +/** Amount of SERCOM that is used as I2C Slave. */ +#define SERCOM_I2CS_AMOUNT \ + (CONF_SERCOM_0_I2CS_ENABLE + CONF_SERCOM_1_I2CS_ENABLE + CONF_SERCOM_2_I2CS_ENABLE + CONF_SERCOM_3_I2CS_ENABLE \ + + CONF_SERCOM_4_I2CS_ENABLE + CONF_SERCOM_5_I2CS_ENABLE + CONF_SERCOM_6_I2CS_ENABLE + CONF_SERCOM_7_I2CS_ENABLE) + +/** + * \brief Macro is used to fill I2C slave configuration structure based on + * its number + * + * \param[in] n The number of structures + */ +#define I2CS_CONFIGURATION(n) \ + { \ + n, \ + SERCOM_I2CM_CTRLA_MODE_I2C_SLAVE | (CONF_SERCOM_##n##_I2CS_RUNSTDBY << SERCOM_I2CS_CTRLA_RUNSTDBY_Pos) \ + | SERCOM_I2CS_CTRLA_SDAHOLD(CONF_SERCOM_##n##_I2CS_SDAHOLD) \ + | (CONF_SERCOM_##n##_I2CS_SEXTTOEN << SERCOM_I2CS_CTRLA_SEXTTOEN_Pos) \ + | (CONF_SERCOM_##n##_I2CS_SPEED << SERCOM_I2CS_CTRLA_SPEED_Pos) \ + | (CONF_SERCOM_##n##_I2CS_SCLSM << SERCOM_I2CS_CTRLA_SCLSM_Pos) \ + | (CONF_SERCOM_##n##_I2CS_LOWTOUT << SERCOM_I2CS_CTRLA_LOWTOUTEN_Pos), \ + SERCOM_I2CS_CTRLB_SMEN | SERCOM_I2CS_CTRLB_AACKEN | SERCOM_I2CS_CTRLB_AMODE(CONF_SERCOM_##n##_I2CS_AMODE), \ + (CONF_SERCOM_##n##_I2CS_GENCEN << SERCOM_I2CS_ADDR_GENCEN_Pos) \ + | SERCOM_I2CS_ADDR_ADDR(CONF_SERCOM_##n##_I2CS_ADDRESS) \ + | (CONF_SERCOM_##n##_I2CS_TENBITEN << SERCOM_I2CS_ADDR_TENBITEN_Pos) \ + | SERCOM_I2CS_ADDR_ADDRMASK(CONF_SERCOM_##n##_I2CS_ADDRESS_MASK) \ + } + +/** + * \brief Macro to check 10-bit addressing + */ +#define I2CS_7BIT_ADDRESSING_MASK 0x7F + +static int32_t _i2c_s_init(void *const hw); +static int8_t _get_i2c_s_index(const void *const hw); +static inline void _i2c_s_deinit(void *const hw); +static int32_t _i2c_s_set_address(void *const hw, const uint16_t address); + +/** + * \brief SERCOM I2C slave configuration type + */ +struct i2cs_configuration { + uint8_t number; + hri_sercomi2cs_ctrla_reg_t ctrl_a; + hri_sercomi2cs_ctrlb_reg_t ctrl_b; + hri_sercomi2cs_addr_reg_t address; +}; + +#if SERCOM_I2CS_AMOUNT < 1 +/** Dummy array for compiling. */ +static struct i2cs_configuration _i2css[1] = {{0}}; +#else +/** + * \brief Array of SERCOM I2C slave configurations + */ +static struct i2cs_configuration _i2css[] = { +#if CONF_SERCOM_0_I2CS_ENABLE == 1 + I2CS_CONFIGURATION(0), +#endif +#if CONF_SERCOM_1_I2CS_ENABLE == 1 + I2CS_CONFIGURATION(1), +#endif +#if CONF_SERCOM_2_I2CS_ENABLE == 1 + I2CS_CONFIGURATION(2), +#endif +#if CONF_SERCOM_3_I2CS_ENABLE == 1 + I2CS_CONFIGURATION(3), +#endif +#if CONF_SERCOM_4_I2CS_ENABLE == 1 + I2CS_CONFIGURATION(4), +#endif +#if CONF_SERCOM_5_I2CS_ENABLE == 1 + I2CS_CONFIGURATION(5), +#endif +#if CONF_SERCOM_6_I2CS_ENABLE == 1 + I2CS_CONFIGURATION(6), +#endif +#if CONF_SERCOM_7_I2CS_ENABLE == 1 + I2CS_CONFIGURATION(7), +#endif +}; +#endif + +/** + * \brief Initialize synchronous I2C slave + */ +int32_t _i2c_s_sync_init(struct _i2c_s_sync_device *const device, void *const hw) +{ + int32_t status; + + ASSERT(device); + + status = _i2c_s_init(hw); + if (status) { + return status; + } + device->hw = hw; + + return ERR_NONE; +} + +/** + * \brief Initialize asynchronous I2C slave + */ +int32_t _i2c_s_async_init(struct _i2c_s_async_device *const device, void *const hw) +{ + int32_t init_status; + + ASSERT(device); + + init_status = _i2c_s_init(hw); + if (init_status) { + return init_status; + } + + device->hw = hw; + _sercom_init_irq_param(hw, (void *)device); + uint8_t irq = _sercom_get_irq_num(hw); + for (uint32_t i = 0; i < 4; i++) { + NVIC_DisableIRQ((IRQn_Type)irq); + NVIC_ClearPendingIRQ((IRQn_Type)irq); + NVIC_EnableIRQ((IRQn_Type)irq); + irq++; + } + // Enable Address Match and PREC interrupt by default. + hri_sercomi2cs_set_INTEN_AMATCH_bit(hw); + hri_sercomi2cs_set_INTEN_PREC_bit(hw); + + return ERR_NONE; +} + +/** + * \brief Deinitialize synchronous I2C + */ +int32_t _i2c_s_sync_deinit(struct _i2c_s_sync_device *const device) +{ + _i2c_s_deinit(device->hw); + + return ERR_NONE; +} + +/** + * \brief Deinitialize asynchronous I2C + */ +int32_t _i2c_s_async_deinit(struct _i2c_s_async_device *const device) +{ + NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(device->hw)); + _i2c_s_deinit(device->hw); + + return ERR_NONE; +} + +/** + * \brief Enable I2C module + */ +int32_t _i2c_s_sync_enable(struct _i2c_s_sync_device *const device) +{ + hri_sercomi2cs_set_CTRLA_ENABLE_bit(device->hw); + + return ERR_NONE; +} + +/** + * \brief Enable I2C module + */ +int32_t _i2c_s_async_enable(struct _i2c_s_async_device *const device) +{ + hri_sercomi2cs_set_CTRLA_ENABLE_bit(device->hw); + + return ERR_NONE; +} + +/** + * \brief Disable I2C module + */ +int32_t _i2c_s_sync_disable(struct _i2c_s_sync_device *const device) +{ + hri_sercomi2cs_clear_CTRLA_ENABLE_bit(device->hw); + + return ERR_NONE; +} + +/** + * \brief Disable I2C module + */ +int32_t _i2c_s_async_disable(struct _i2c_s_async_device *const device) +{ + hri_sercomi2cs_clear_CTRLA_ENABLE_bit(device->hw); + + return ERR_NONE; +} + +/** + * \brief Check if 10-bit addressing mode is on + */ +int32_t _i2c_s_sync_is_10bit_addressing_on(const struct _i2c_s_sync_device *const device) +{ + return hri_sercomi2cs_get_ADDR_TENBITEN_bit(device->hw); +} + +/** + * \brief Check if 10-bit addressing mode is on + */ +int32_t _i2c_s_async_is_10bit_addressing_on(const struct _i2c_s_async_device *const device) +{ + return hri_sercomi2cs_get_ADDR_TENBITEN_bit(device->hw); +} + +/** + * \brief Set I2C slave address + */ +int32_t _i2c_s_sync_set_address(struct _i2c_s_sync_device *const device, const uint16_t address) +{ + return _i2c_s_set_address(device->hw, address); +} + +/** + * \brief Set I2C slave address + */ +int32_t _i2c_s_async_set_address(struct _i2c_s_async_device *const device, const uint16_t address) +{ + return _i2c_s_set_address(device->hw, address); +} + +/** + * \brief Write a byte to the given I2C instance + */ +void _i2c_s_sync_write_byte(struct _i2c_s_sync_device *const device, const uint8_t data) +{ + hri_sercomi2cs_write_DATA_reg(device->hw, data); +} + +/** + * \brief Write a byte to the given I2C instance + */ +void _i2c_s_async_write_byte(struct _i2c_s_async_device *const device, const uint8_t data) +{ + hri_sercomi2cs_write_DATA_reg(device->hw, data); +} + +/** + * \brief Read a byte from the given I2C instance + */ +uint8_t _i2c_s_sync_read_byte(const struct _i2c_s_sync_device *const device) +{ + return hri_sercomi2cs_read_DATA_reg(device->hw); +} + +/** + * \brief Check if I2C is ready to send next byt + */ +bool _i2c_s_sync_is_byte_sent(const struct _i2c_s_sync_device *const device) +{ + return hri_sercomi2cs_get_interrupt_DRDY_bit(device->hw); +} + +/** + * \brief Check if there is data received by I2C + */ +bool _i2c_s_sync_is_byte_received(const struct _i2c_s_sync_device *const device) +{ + return hri_sercomi2cs_get_interrupt_DRDY_bit(device->hw); +} + +/** + * \brief Retrieve I2C slave status + */ +i2c_s_status_t _i2c_s_sync_get_status(const struct _i2c_s_sync_device *const device) +{ + return hri_sercomi2cs_read_STATUS_reg(device->hw); +} + +/** + * \brief Clear the Data Ready interrupt flag + */ +int32_t _i2c_s_sync_clear_data_ready_flag(const struct _i2c_s_sync_device *const device) +{ + hri_sercomi2cs_clear_INTFLAG_DRDY_bit(device->hw); + + return ERR_NONE; +} + +/** + * \brief Retrieve I2C slave status + */ +i2c_s_status_t _i2c_s_async_get_status(const struct _i2c_s_async_device *const device) +{ + return hri_sercomi2cs_read_STATUS_reg(device->hw); +} + +/** + * \brief Abort data transmission + */ +int32_t _i2c_s_async_abort_transmission(const struct _i2c_s_async_device *const device) +{ + hri_sercomi2cs_clear_INTEN_DRDY_bit(device->hw); + + return ERR_NONE; +} + +/** + * \brief Enable/disable I2C slave interrupt + */ +int32_t _i2c_s_async_set_irq_state(struct _i2c_s_async_device *const device, const enum _i2c_s_async_callback_type type, + const bool state) +{ + ASSERT(device); + + if (I2C_S_DEVICE_TX == type || I2C_S_DEVICE_RX_COMPLETE == type) { + hri_sercomi2cs_write_INTEN_DRDY_bit(device->hw, state); + } else if (I2C_S_DEVICE_ERROR == type) { + hri_sercomi2cs_write_INTEN_ERROR_bit(device->hw, state); + } + + return ERR_NONE; +} + +/** + * \internal Initalize i2c slave hardware + * + * \param[in] p The pointer to hardware instance + * + *\ return status of initialization + */ +static int32_t _i2c_s_init(void *const hw) +{ + int8_t i = _get_i2c_s_index(hw); + if (i == -1) { + return ERR_INVALID_ARG; + } + + if (!hri_sercomi2cs_is_syncing(hw, SERCOM_I2CS_CTRLA_SWRST)) { + uint32_t mode = _i2css[i].ctrl_a & SERCOM_I2CS_CTRLA_MODE_Msk; + if (hri_sercomi2cs_get_CTRLA_reg(hw, SERCOM_I2CS_CTRLA_ENABLE)) { + hri_sercomi2cs_clear_CTRLA_ENABLE_bit(hw); + hri_sercomi2cs_wait_for_sync(hw, SERCOM_I2CS_SYNCBUSY_ENABLE); + } + hri_sercomi2cs_write_CTRLA_reg(hw, SERCOM_I2CS_CTRLA_SWRST | mode); + } + hri_sercomi2cs_wait_for_sync(hw, SERCOM_I2CS_SYNCBUSY_SWRST); + + hri_sercomi2cs_write_CTRLA_reg(hw, _i2css[i].ctrl_a); + hri_sercomi2cs_write_CTRLB_reg(hw, _i2css[i].ctrl_b); + hri_sercomi2cs_write_ADDR_reg(hw, _i2css[i].address); + + return ERR_NONE; +} + +/** + * \internal Retrieve ordinal number of the given sercom hardware instance + * + * \param[in] hw The pointer to hardware instance + * + * \return The ordinal number of the given sercom hardware instance + */ +static int8_t _get_i2c_s_index(const void *const hw) +{ + uint8_t sercom_offset = _sercom_get_hardware_index(hw); + uint8_t i; + + for (i = 0; i < ARRAY_SIZE(_i2css); i++) { + if (_i2css[i].number == sercom_offset) { + return i; + } + } + + ASSERT(false); + return -1; +} + +/** + * \internal De-initialize i2c slave + * + * \param[in] hw The pointer to hardware instance + */ +static inline void _i2c_s_deinit(void *const hw) +{ + hri_sercomi2cs_clear_CTRLA_ENABLE_bit(hw); + hri_sercomi2cs_set_CTRLA_SWRST_bit(hw); +} + +/** + * \internal De-initialize i2c slave + * + * \param[in] hw The pointer to hardware instance + * \param[in] address Address to set + */ +static int32_t _i2c_s_set_address(void *const hw, const uint16_t address) +{ + bool enabled; + + enabled = hri_sercomi2cs_get_CTRLA_ENABLE_bit(hw); + + CRITICAL_SECTION_ENTER() + hri_sercomi2cs_clear_CTRLA_ENABLE_bit(hw); + hri_sercomi2cs_write_ADDR_ADDR_bf(hw, address); + CRITICAL_SECTION_LEAVE() + + if (enabled) { + hri_sercomi2cs_set_CTRLA_ENABLE_bit(hw); + } + + return ERR_NONE; +} + + /* Sercom SPI implementation */ + +#ifndef SERCOM_USART_CTRLA_MODE_SPI_SLAVE +#define SERCOM_USART_CTRLA_MODE_SPI_SLAVE (2 << 2) +#endif + +#define SPI_DEV_IRQ_MODE 0x8000 + +#define _SPI_CS_PORT_EXTRACT(cs) (((cs) >> 0) & 0xFF) +#define _SPI_CS_PIN_EXTRACT(cs) (((cs) >> 8) & 0xFF) + +COMPILER_PACK_SET(1) +/** Initialization configuration of registers. */ +struct sercomspi_regs_cfg { + uint32_t ctrla; + uint32_t ctrlb; + uint32_t addr; + uint8_t baud; + uint8_t dbgctrl; + uint16_t dummy_byte; + uint8_t n; +}; +COMPILER_PACK_RESET() + +/** Build configuration from header macros. */ +#define SERCOMSPI_REGS(n) \ + { \ + (((CONF_SERCOM_##n##_SPI_DORD) << SERCOM_SPI_CTRLA_DORD_Pos) \ + | (CONF_SERCOM_##n##_SPI_CPOL << SERCOM_SPI_CTRLA_CPOL_Pos) \ + | (CONF_SERCOM_##n##_SPI_CPHA << SERCOM_SPI_CTRLA_CPHA_Pos) \ + | (CONF_SERCOM_##n##_SPI_AMODE_EN ? SERCOM_SPI_CTRLA_FORM(2) : SERCOM_SPI_CTRLA_FORM(0)) \ + | SERCOM_SPI_CTRLA_DOPO(CONF_SERCOM_##n##_SPI_TXPO) | SERCOM_SPI_CTRLA_DIPO(CONF_SERCOM_##n##_SPI_RXPO) \ + | (CONF_SERCOM_##n##_SPI_IBON << SERCOM_SPI_CTRLA_IBON_Pos) \ + | (CONF_SERCOM_##n##_SPI_RUNSTDBY << SERCOM_SPI_CTRLA_RUNSTDBY_Pos) \ + | SERCOM_SPI_CTRLA_MODE(CONF_SERCOM_##n##_SPI_MODE)), /* ctrla */ \ + ((CONF_SERCOM_##n##_SPI_RXEN << SERCOM_SPI_CTRLB_RXEN_Pos) \ + | (CONF_SERCOM_##n##_SPI_MSSEN << SERCOM_SPI_CTRLB_MSSEN_Pos) \ + | (CONF_SERCOM_##n##_SPI_SSDE << SERCOM_SPI_CTRLB_SSDE_Pos) \ + | (CONF_SERCOM_##n##_SPI_PLOADEN << SERCOM_SPI_CTRLB_PLOADEN_Pos) \ + | SERCOM_SPI_CTRLB_AMODE(CONF_SERCOM_##n##_SPI_AMODE) \ + | SERCOM_SPI_CTRLB_CHSIZE(CONF_SERCOM_##n##_SPI_CHSIZE)), /* ctrlb */ \ + (SERCOM_SPI_ADDR_ADDR(CONF_SERCOM_##n##_SPI_ADDR) \ + | SERCOM_SPI_ADDR_ADDRMASK(CONF_SERCOM_##n##_SPI_ADDRMASK)), /* addr */ \ + ((uint8_t)CONF_SERCOM_##n##_SPI_BAUD_RATE), /* baud */ \ + (CONF_SERCOM_##n##_SPI_DBGSTOP << SERCOM_SPI_DBGCTRL_DBGSTOP_Pos), /* dbgctrl */ \ + CONF_SERCOM_##n##_SPI_DUMMYBYTE, /* Dummy byte for SPI master mode */ \ + n /* sercom number */ \ + } + +#ifndef CONF_SERCOM_0_SPI_ENABLE +#define CONF_SERCOM_0_SPI_ENABLE 0 +#endif +#ifndef CONF_SERCOM_1_SPI_ENABLE +#define CONF_SERCOM_1_SPI_ENABLE 0 +#endif +#ifndef CONF_SERCOM_2_SPI_ENABLE +#define CONF_SERCOM_2_SPI_ENABLE 0 +#endif +#ifndef CONF_SERCOM_3_SPI_ENABLE +#define CONF_SERCOM_3_SPI_ENABLE 0 +#endif +#ifndef CONF_SERCOM_4_SPI_ENABLE +#define CONF_SERCOM_4_SPI_ENABLE 0 +#endif +#ifndef CONF_SERCOM_5_SPI_ENABLE +#define CONF_SERCOM_5_SPI_ENABLE 0 +#endif +#ifndef CONF_SERCOM_6_SPI_ENABLE +#define CONF_SERCOM_6_SPI_ENABLE 0 +#endif +#ifndef CONF_SERCOM_7_SPI_ENABLE +#define CONF_SERCOM_7_SPI_ENABLE 0 +#endif + +/** Amount of SERCOM that is used as SPI */ +#define SERCOM_SPI_AMOUNT \ + (CONF_SERCOM_0_SPI_ENABLE + CONF_SERCOM_1_SPI_ENABLE + CONF_SERCOM_2_SPI_ENABLE + CONF_SERCOM_3_SPI_ENABLE \ + + CONF_SERCOM_4_SPI_ENABLE + CONF_SERCOM_5_SPI_ENABLE + CONF_SERCOM_6_SPI_ENABLE + CONF_SERCOM_7_SPI_ENABLE) + +#if SERCOM_SPI_AMOUNT < 1 +/** Dummy array for compiling. */ +static const struct sercomspi_regs_cfg sercomspi_regs[1] = {{0}}; +#else +/** The SERCOM SPI configurations of SERCOM that is used as SPI. */ +static const struct sercomspi_regs_cfg sercomspi_regs[] = { +#if CONF_SERCOM_0_SPI_ENABLE + SERCOMSPI_REGS(0), +#endif +#if CONF_SERCOM_1_SPI_ENABLE + SERCOMSPI_REGS(1), +#endif +#if CONF_SERCOM_2_SPI_ENABLE + SERCOMSPI_REGS(2), +#endif +#if CONF_SERCOM_3_SPI_ENABLE + SERCOMSPI_REGS(3), +#endif +#if CONF_SERCOM_4_SPI_ENABLE + SERCOMSPI_REGS(4), +#endif +#if CONF_SERCOM_5_SPI_ENABLE + SERCOMSPI_REGS(5), +#endif +#if CONF_SERCOM_6_SPI_ENABLE + SERCOMSPI_REGS(6), +#endif +#if CONF_SERCOM_7_SPI_ENABLE + SERCOMSPI_REGS(7), +#endif +}; +#endif + +/** \internal De-initialize SERCOM SPI + * + * \param[in] hw Pointer to the hardware register base. + * + * \return De-initialization status + */ +static int32_t _spi_deinit(void *const hw) +{ + hri_sercomspi_clear_CTRLA_ENABLE_bit(hw); + hri_sercomspi_set_CTRLA_SWRST_bit(hw); + + return ERR_NONE; +} + +/** \internal Enable SERCOM SPI + * + * \param[in] hw Pointer to the hardware register base. + * + * \return Enabling status + */ +static int32_t _spi_sync_enable(void *const hw) +{ + if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) { + return ERR_BUSY; + } + + hri_sercomspi_set_CTRLA_ENABLE_bit(hw); + + return ERR_NONE; +} + +/** \internal Enable SERCOM SPI + * + * \param[in] hw Pointer to the hardware register base. + * + * \return Enabling status + */ +static int32_t _spi_async_enable(void *const hw) +{ + _spi_sync_enable(hw); + uint8_t irq = _sercom_get_irq_num(hw); + for (uint32_t i = 0; i < 4; i++) { + NVIC_EnableIRQ((IRQn_Type)irq++); + } + + return ERR_NONE; +} + +/** \internal Disable SERCOM SPI + * + * \param[in] hw Pointer to the hardware register base. + * + * \return Disabling status + */ +static int32_t _spi_sync_disable(void *const hw) +{ + if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) { + return ERR_BUSY; + } + hri_sercomspi_clear_CTRLA_ENABLE_bit(hw); + + return ERR_NONE; +} + +/** \internal Disable SERCOM SPI + * + * \param[in] hw Pointer to the hardware register base. + * + * \return Disabling status + */ +static int32_t _spi_async_disable(void *const hw) +{ + _spi_sync_disable(hw); + hri_sercomspi_clear_INTEN_reg( + hw, SERCOM_SPI_INTFLAG_ERROR | SERCOM_SPI_INTFLAG_RXC | SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE); + uint8_t irq = _sercom_get_irq_num(hw); + for (uint32_t i = 0; i < 4; i++) { + NVIC_DisableIRQ((IRQn_Type)irq++); + } + + return ERR_NONE; +} + +/** \internal Set SERCOM SPI mode + * + * \param[in] hw Pointer to the hardware register base. + * \param[in] mode The mode to set + * + * \return Setting mode status + */ +static int32_t _spi_set_mode(void *const hw, const enum spi_transfer_mode mode) +{ + uint32_t ctrla; + + if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST | SERCOM_SPI_SYNCBUSY_ENABLE)) { + return ERR_BUSY; + } + + ctrla = hri_sercomspi_read_CTRLA_reg(hw); + ctrla &= ~(SERCOM_SPI_CTRLA_CPOL | SERCOM_SPI_CTRLA_CPHA); + ctrla |= (mode & 0x3u) << SERCOM_SPI_CTRLA_CPHA_Pos; + hri_sercomspi_write_CTRLA_reg(hw, ctrla); + + return ERR_NONE; +} + +/** \internal Set SERCOM SPI baudrate + * + * \param[in] hw Pointer to the hardware register base. + * \param[in] baud_val The baudrate to set + * + * \return Setting baudrate status + */ +static int32_t _spi_set_baudrate(void *const hw, const uint32_t baud_val) +{ + if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) { + return ERR_BUSY; + } + + hri_sercomspi_write_BAUD_reg(hw, baud_val); + + return ERR_NONE; +} + +/** \internal Set SERCOM SPI char size + * + * \param[in] hw Pointer to the hardware register base. + * \param[in] baud_val The baudrate to set + * \param[out] size Stored char size + * + * \return Setting char size status + */ +static int32_t _spi_set_char_size(void *const hw, const enum spi_char_size char_size, uint8_t *const size) +{ + /* Only 8-bit or 9-bit accepted */ + if (!(char_size == SPI_CHAR_SIZE_8 || char_size == SPI_CHAR_SIZE_9)) { + return ERR_INVALID_ARG; + } + + if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST | SERCOM_SPI_SYNCBUSY_CTRLB)) { + return ERR_BUSY; + } + + hri_sercomspi_write_CTRLB_CHSIZE_bf(hw, char_size); + *size = (char_size == SPI_CHAR_SIZE_8) ? 1 : 2; + + return ERR_NONE; +} + +/** \internal Set SERCOM SPI data order + * + * \param[in] hw Pointer to the hardware register base. + * \param[in] baud_val The baudrate to set + * + * \return Setting data order status + */ +static int32_t _spi_set_data_order(void *const hw, const enum spi_data_order dord) +{ + uint32_t ctrla; + + if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) { + return ERR_BUSY; + } + + ctrla = hri_sercomspi_read_CTRLA_reg(hw); + + if (dord == SPI_DATA_ORDER_LSB_1ST) { + ctrla |= SERCOM_SPI_CTRLA_DORD; + } else { + ctrla &= ~SERCOM_SPI_CTRLA_DORD; + } + hri_sercomspi_write_CTRLA_reg(hw, ctrla); + + return ERR_NONE; +} + +/** \brief Load SERCOM registers to init for SPI master mode + * The settings will be applied with default master mode, unsupported things + * are ignored. + * \param[in, out] hw Pointer to the hardware register base. + * \param[in] regs Pointer to register configuration values. + */ +static inline void _spi_load_regs_master(void *const hw, const struct sercomspi_regs_cfg *regs) +{ + ASSERT(hw && regs); + hri_sercomspi_write_CTRLA_reg( + hw, regs->ctrla & ~(SERCOM_SPI_CTRLA_IBON | SERCOM_SPI_CTRLA_ENABLE | SERCOM_SPI_CTRLA_SWRST)); + hri_sercomspi_write_CTRLB_reg( + hw, + (regs->ctrlb + & ~(SERCOM_SPI_CTRLB_MSSEN | SERCOM_SPI_CTRLB_AMODE_Msk | SERCOM_SPI_CTRLB_SSDE | SERCOM_SPI_CTRLB_PLOADEN)) + | (SERCOM_SPI_CTRLB_RXEN)); + hri_sercomspi_write_BAUD_reg(hw, regs->baud); + hri_sercomspi_write_DBGCTRL_reg(hw, regs->dbgctrl); +} + +/** \brief Load SERCOM registers to init for SPI slave mode + * The settings will be applied with default slave mode, unsupported things + * are ignored. + * \param[in, out] hw Pointer to the hardware register base. + * \param[in] regs Pointer to register configuration values. + */ +static inline void _spi_load_regs_slave(void *const hw, const struct sercomspi_regs_cfg *regs) +{ + ASSERT(hw && regs); + hri_sercomspi_write_CTRLA_reg( + hw, regs->ctrla & ~(SERCOM_SPI_CTRLA_IBON | SERCOM_SPI_CTRLA_ENABLE | SERCOM_SPI_CTRLA_SWRST)); + hri_sercomspi_write_CTRLB_reg(hw, + (regs->ctrlb & ~(SERCOM_SPI_CTRLB_MSSEN)) + | (SERCOM_SPI_CTRLB_RXEN | SERCOM_SPI_CTRLB_SSDE | SERCOM_SPI_CTRLB_PLOADEN)); + hri_sercomspi_write_ADDR_reg(hw, regs->addr); + hri_sercomspi_write_DBGCTRL_reg(hw, regs->dbgctrl); + while (hri_sercomspi_is_syncing(hw, 0xFFFFFFFF)) + ; +} + +/** \brief Return the pointer to register settings of specific SERCOM + * \param[in] hw_addr The hardware register base address. + * \return Pointer to register settings of specific SERCOM. + */ +static inline const struct sercomspi_regs_cfg *_spi_get_regs(const uint32_t hw_addr) +{ + uint8_t n = _sercom_get_hardware_index((const void *)hw_addr); + uint8_t i; + + for (i = 0; i < sizeof(sercomspi_regs) / sizeof(struct sercomspi_regs_cfg); i++) { + if (sercomspi_regs[i].n == n) { + return &sercomspi_regs[i]; + } + } + + return NULL; +} + +/** + * \internal Sercom interrupt handler + */ +void SERCOM0_0_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom0_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM0_1_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom0_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM0_2_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom0_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM0_3_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom0_dev); +} + +/** + * \internal Sercom interrupt handler + */ +void SERCOM1_0_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom1_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM1_1_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom1_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM1_2_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom1_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM1_3_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom1_dev); +} + +/** + * \internal Sercom interrupt handler + */ +void SERCOM2_0_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom2_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM2_1_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom2_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM2_2_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom2_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM2_3_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom2_dev); +} + +/** + * \internal Sercom interrupt handler + */ +void SERCOM3_0_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom3_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM3_1_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom3_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM3_2_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom3_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM3_3_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom3_dev); +} + +/** + * \internal Sercom interrupt handler + */ +void SERCOM4_0_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom4_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM4_1_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom4_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM4_2_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom4_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM4_3_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom4_dev); +} + +/** + * \internal Sercom interrupt handler + */ +void SERCOM5_0_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom5_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM5_1_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom5_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM5_2_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom5_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM5_3_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom5_dev); +} + +/** + * \internal Sercom interrupt handler + */ +void SERCOM6_0_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom6_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM6_1_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom6_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM6_2_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom6_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM6_3_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom6_dev); +} + +int32_t _spi_m_sync_init(struct _spi_m_sync_dev *dev, void *const hw) +{ + const struct sercomspi_regs_cfg *regs = _spi_get_regs((uint32_t)hw); + + ASSERT(dev && hw); + + if (regs == NULL) { + return ERR_INVALID_ARG; + } + + if (!hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) { + uint32_t mode = regs->ctrla & SERCOM_SPI_CTRLA_MODE_Msk; + if (hri_sercomspi_get_CTRLA_reg(hw, SERCOM_SPI_CTRLA_ENABLE)) { + hri_sercomspi_clear_CTRLA_ENABLE_bit(hw); + hri_sercomspi_wait_for_sync(hw, SERCOM_SPI_SYNCBUSY_ENABLE); + } + hri_sercomspi_write_CTRLA_reg(hw, SERCOM_SPI_CTRLA_SWRST | mode); + } + hri_sercomspi_wait_for_sync(hw, SERCOM_SPI_SYNCBUSY_SWRST); + + dev->prvt = hw; + + if ((regs->ctrla & SERCOM_SPI_CTRLA_MODE_Msk) == SERCOM_USART_CTRLA_MODE_SPI_SLAVE) { + _spi_load_regs_slave(hw, regs); + } else { + _spi_load_regs_master(hw, regs); + } + + /* Load character size from default hardware configuration */ + dev->char_size = ((regs->ctrlb & SERCOM_SPI_CTRLB_CHSIZE_Msk) == 0) ? 1 : 2; + + dev->dummy_byte = regs->dummy_byte; + + return ERR_NONE; +} + +int32_t _spi_s_sync_init(struct _spi_s_sync_dev *dev, void *const hw) +{ + return _spi_m_sync_init(dev, hw); +} + +int32_t _spi_m_async_init(struct _spi_async_dev *dev, void *const hw) +{ + struct _spi_async_dev *spid = dev; + /* Do hardware initialize. */ + int32_t rc = _spi_m_sync_init((struct _spi_m_sync_dev *)dev, hw); + + if (rc < 0) { + return rc; + } + + _sercom_init_irq_param(hw, (void *)dev); + /* Initialize callbacks: must use them */ + spid->callbacks.complete = NULL; + spid->callbacks.rx = NULL; + spid->callbacks.tx = NULL; + uint8_t irq = _sercom_get_irq_num(hw); + for (uint32_t i = 0; i < 4; i++) { + NVIC_DisableIRQ((IRQn_Type)irq); + NVIC_ClearPendingIRQ((IRQn_Type)irq); + irq++; + } + + return ERR_NONE; +} + +int32_t _spi_s_async_init(struct _spi_s_async_dev *dev, void *const hw) +{ + return _spi_m_async_init(dev, hw); +} + +int32_t _spi_m_async_deinit(struct _spi_async_dev *dev) +{ + NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(dev->prvt)); + NVIC_ClearPendingIRQ((IRQn_Type)_sercom_get_irq_num(dev->prvt)); + + return _spi_deinit(dev->prvt); +} + +int32_t _spi_s_async_deinit(struct _spi_s_async_dev *dev) +{ + NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(dev->prvt)); + NVIC_ClearPendingIRQ((IRQn_Type)_sercom_get_irq_num(dev->prvt)); + + return _spi_deinit(dev->prvt); +} + +int32_t _spi_m_sync_deinit(struct _spi_m_sync_dev *dev) +{ + return _spi_deinit(dev->prvt); +} + +int32_t _spi_s_sync_deinit(struct _spi_s_sync_dev *dev) +{ + return _spi_deinit(dev->prvt); +} + +int32_t _spi_m_sync_enable(struct _spi_m_sync_dev *dev) +{ + ASSERT(dev && dev->prvt); + + return _spi_sync_enable(dev->prvt); +} + +int32_t _spi_s_sync_enable(struct _spi_s_sync_dev *dev) +{ + ASSERT(dev && dev->prvt); + + return _spi_sync_enable(dev->prvt); +} + +int32_t _spi_m_async_enable(struct _spi_async_dev *dev) +{ + ASSERT(dev && dev->prvt); + + return _spi_async_enable(dev->prvt); +} + +int32_t _spi_s_async_enable(struct _spi_s_async_dev *dev) +{ + ASSERT(dev && dev->prvt); + + return _spi_async_enable(dev->prvt); +} + +int32_t _spi_m_sync_disable(struct _spi_m_sync_dev *dev) +{ + ASSERT(dev && dev->prvt); + + return _spi_sync_disable(dev->prvt); +} + +int32_t _spi_s_sync_disable(struct _spi_s_sync_dev *dev) +{ + ASSERT(dev && dev->prvt); + + return _spi_sync_disable(dev->prvt); +} + +int32_t _spi_m_async_disable(struct _spi_async_dev *dev) +{ + ASSERT(dev && dev->prvt); + + return _spi_async_disable(dev->prvt); +} + +int32_t _spi_s_async_disable(struct _spi_s_async_dev *dev) +{ + ASSERT(dev && dev->prvt); + + return _spi_async_disable(dev->prvt); +} + +int32_t _spi_m_sync_set_mode(struct _spi_m_sync_dev *dev, const enum spi_transfer_mode mode) +{ + ASSERT(dev && dev->prvt); + + return _spi_set_mode(dev->prvt, mode); +} + +int32_t _spi_m_async_set_mode(struct _spi_async_dev *dev, const enum spi_transfer_mode mode) +{ + ASSERT(dev && dev->prvt); + + return _spi_set_mode(dev->prvt, mode); +} + +int32_t _spi_s_async_set_mode(struct _spi_s_async_dev *dev, const enum spi_transfer_mode mode) +{ + ASSERT(dev && dev->prvt); + + return _spi_set_mode(dev->prvt, mode); +} + +int32_t _spi_s_sync_set_mode(struct _spi_s_sync_dev *dev, const enum spi_transfer_mode mode) +{ + ASSERT(dev && dev->prvt); + + return _spi_set_mode(dev->prvt, mode); +} + +int32_t _spi_calc_baud_val(struct spi_dev *dev, const uint32_t clk, const uint32_t baud) +{ + int32_t rc; + ASSERT(dev); + + /* Not accept 0es */ + if (clk == 0 || baud == 0) { + return ERR_INVALID_ARG; + } + + /* Check baudrate range of current assigned clock */ + if (!(baud <= (clk >> 1) && baud >= (clk >> 8))) { + return ERR_INVALID_ARG; + } + + rc = ((clk >> 1) / baud) - 1; + return rc; +} + +int32_t _spi_m_sync_set_baudrate(struct _spi_m_sync_dev *dev, const uint32_t baud_val) +{ + ASSERT(dev && dev->prvt); + + return _spi_set_baudrate(dev->prvt, baud_val); +} + +int32_t _spi_m_async_set_baudrate(struct _spi_async_dev *dev, const uint32_t baud_val) +{ + ASSERT(dev && dev->prvt); + + return _spi_set_baudrate(dev->prvt, baud_val); +} + +int32_t _spi_m_sync_set_char_size(struct _spi_m_sync_dev *dev, const enum spi_char_size char_size) +{ + ASSERT(dev && dev->prvt); + + return _spi_set_char_size(dev->prvt, char_size, &dev->char_size); +} + +int32_t _spi_m_async_set_char_size(struct _spi_async_dev *dev, const enum spi_char_size char_size) +{ + ASSERT(dev && dev->prvt); + + return _spi_set_char_size(dev->prvt, char_size, &dev->char_size); +} + +int32_t _spi_s_async_set_char_size(struct _spi_s_async_dev *dev, const enum spi_char_size char_size) +{ + ASSERT(dev && dev->prvt); + + return _spi_set_char_size(dev->prvt, char_size, &dev->char_size); +} + +int32_t _spi_s_sync_set_char_size(struct _spi_s_sync_dev *dev, const enum spi_char_size char_size) +{ + ASSERT(dev && dev->prvt); + + return _spi_set_char_size(dev->prvt, char_size, &dev->char_size); +} + +int32_t _spi_m_sync_set_data_order(struct _spi_m_sync_dev *dev, const enum spi_data_order dord) +{ + ASSERT(dev && dev->prvt); + + return _spi_set_data_order(dev->prvt, dord); +} + +int32_t _spi_m_async_set_data_order(struct _spi_async_dev *dev, const enum spi_data_order dord) +{ + ASSERT(dev && dev->prvt); + + return _spi_set_data_order(dev->prvt, dord); +} + +int32_t _spi_s_async_set_data_order(struct _spi_s_async_dev *dev, const enum spi_data_order dord) +{ + ASSERT(dev && dev->prvt); + + return _spi_set_data_order(dev->prvt, dord); +} + +int32_t _spi_s_sync_set_data_order(struct _spi_s_sync_dev *dev, const enum spi_data_order dord) +{ + ASSERT(dev && dev->prvt); + + return _spi_set_data_order(dev->prvt, dord); +} + +/** Wait until SPI bus idle. */ +static inline void _spi_wait_bus_idle(void *const hw) +{ + while (!(hri_sercomspi_get_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE))) { + ; + } + hri_sercomspi_clear_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE); +} + +/** Holds run time information for message sync transaction. */ +struct _spi_trans_ctrl { + /** Pointer to transmitting data buffer. */ + uint8_t *txbuf; + /** Pointer to receiving data buffer. */ + uint8_t *rxbuf; + /** Count number of data transmitted. */ + uint32_t txcnt; + /** Count number of data received. */ + uint32_t rxcnt; + /** Data character size. */ + uint8_t char_size; +}; + +/** Check interrupt flag of RXC and update transaction runtime information. */ +static inline bool _spi_rx_check_and_receive(void *const hw, const uint32_t iflag, struct _spi_trans_ctrl *ctrl) +{ + uint32_t data; + + if (!(iflag & SERCOM_SPI_INTFLAG_RXC)) { + return false; + } + + data = hri_sercomspi_read_DATA_reg(hw); + + if (ctrl->rxbuf) { + *ctrl->rxbuf++ = (uint8_t)data; + + if (ctrl->char_size > 1) { + *ctrl->rxbuf++ = (uint8_t)(data >> 8); + } + } + + ctrl->rxcnt++; + + return true; +} + +/** Check interrupt flag of DRE and update transaction runtime information. */ +static inline void _spi_tx_check_and_send(void *const hw, const uint32_t iflag, struct _spi_trans_ctrl *ctrl, + uint16_t dummy) +{ + uint32_t data; + + if (!(SERCOM_SPI_INTFLAG_DRE & iflag)) { + return; + } + + if (ctrl->txbuf) { + data = *ctrl->txbuf++; + + if (ctrl->char_size > 1) { + data |= (*ctrl->txbuf) << 8; + ctrl->txbuf++; + } + } else { + data = dummy; + } + + ctrl->txcnt++; + hri_sercomspi_write_DATA_reg(hw, data); +} + +/** Check interrupt flag of ERROR and update transaction runtime information. */ +static inline int32_t _spi_err_check(const uint32_t iflag, void *const hw) +{ + if (SERCOM_SPI_INTFLAG_ERROR & iflag) { + hri_sercomspi_clear_STATUS_reg(hw, ~0); + hri_sercomspi_clear_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_ERROR); + return ERR_OVERFLOW; + } + + return ERR_NONE; +} + +int32_t _spi_m_sync_trans(struct _spi_m_sync_dev *dev, const struct spi_msg *msg) +{ + void * hw = dev->prvt; + int32_t rc = 0; + struct _spi_trans_ctrl ctrl = {msg->txbuf, msg->rxbuf, 0, 0, dev->char_size}; + + ASSERT(dev && hw); + + /* If settings are not applied (pending), we can not go on */ + if (hri_sercomspi_is_syncing( + hw, (SERCOM_SPI_SYNCBUSY_SWRST | SERCOM_SPI_SYNCBUSY_ENABLE | SERCOM_SPI_SYNCBUSY_CTRLB))) { + return ERR_BUSY; + } + + /* SPI must be enabled to start synchronous transfer */ + if (!hri_sercomspi_get_CTRLA_ENABLE_bit(hw)) { + return ERR_NOT_INITIALIZED; + } + + for (;;) { + uint32_t iflag = hri_sercomspi_read_INTFLAG_reg(hw); + + if (!_spi_rx_check_and_receive(hw, iflag, &ctrl)) { + /* In master mode, do not start next byte before previous byte received + * to make better output waveform */ + if (ctrl.rxcnt >= ctrl.txcnt) { + _spi_tx_check_and_send(hw, iflag, &ctrl, dev->dummy_byte); + } + } + + rc = _spi_err_check(iflag, hw); + + if (rc < 0) { + break; + } + if (ctrl.txcnt >= msg->size && ctrl.rxcnt >= msg->size) { + rc = ctrl.txcnt; + break; + } + } + /* Wait until SPI bus idle */ + _spi_wait_bus_idle(hw); + + return rc; +} + +int32_t _spi_m_async_enable_tx(struct _spi_async_dev *dev, bool state) +{ + void *hw = dev->prvt; + + ASSERT(dev && hw); + + if (state) { + hri_sercomspi_set_INTEN_DRE_bit(hw); + } else { + hri_sercomspi_clear_INTEN_DRE_bit(hw); + } + + return ERR_NONE; +} + +int32_t _spi_s_async_enable_tx(struct _spi_s_async_dev *dev, bool state) +{ + return _spi_m_async_enable_tx(dev, state); +} + +int32_t _spi_m_async_enable_rx(struct _spi_async_dev *dev, bool state) +{ + void *hw = dev->prvt; + + ASSERT(dev); + ASSERT(hw); + + if (state) { + hri_sercomspi_set_INTEN_RXC_bit(hw); + } else { + hri_sercomspi_clear_INTEN_RXC_bit(hw); + } + + return ERR_NONE; +} + +int32_t _spi_s_async_enable_rx(struct _spi_s_async_dev *dev, bool state) +{ + return _spi_m_async_enable_rx(dev, state); +} + +int32_t _spi_m_async_enable_tx_complete(struct _spi_async_dev *dev, bool state) +{ + ASSERT(dev && dev->prvt); + + if (state) { + hri_sercomspi_set_INTEN_TXC_bit(dev->prvt); + } else { + hri_sercomspi_clear_INTEN_TXC_bit(dev->prvt); + } + + return ERR_NONE; +} + +int32_t _spi_s_async_enable_ss_detect(struct _spi_s_async_dev *dev, bool state) +{ + return _spi_m_async_enable_tx_complete(dev, state); +} + +int32_t _spi_m_async_write_one(struct _spi_async_dev *dev, uint16_t data) +{ + ASSERT(dev && dev->prvt); + + hri_sercomspi_write_DATA_reg(dev->prvt, data); + + return ERR_NONE; +} + +int32_t _spi_s_async_write_one(struct _spi_s_async_dev *dev, uint16_t data) +{ + ASSERT(dev && dev->prvt); + + hri_sercomspi_write_DATA_reg(dev->prvt, data); + + return ERR_NONE; +} + +int32_t _spi_s_sync_write_one(struct _spi_s_sync_dev *dev, uint16_t data) +{ + ASSERT(dev && dev->prvt); + + hri_sercomspi_write_DATA_reg(dev->prvt, data); + + return ERR_NONE; +} + +uint16_t _spi_m_async_read_one(struct _spi_async_dev *dev) +{ + ASSERT(dev && dev->prvt); + + return hri_sercomspi_read_DATA_reg(dev->prvt); +} + +uint16_t _spi_s_async_read_one(struct _spi_s_async_dev *dev) +{ + ASSERT(dev && dev->prvt); + + return hri_sercomspi_read_DATA_reg(dev->prvt); +} + +uint16_t _spi_s_sync_read_one(struct _spi_s_sync_dev *dev) +{ + ASSERT(dev && dev->prvt); + + return hri_sercomspi_read_DATA_reg(dev->prvt); +} + +int32_t _spi_m_async_register_callback(struct _spi_async_dev *dev, const enum _spi_async_dev_cb_type cb_type, + const FUNC_PTR func) +{ + typedef void (*func_t)(void); + struct _spi_async_dev *spid = dev; + + ASSERT(dev && (cb_type < SPI_DEV_CB_N)); + + func_t *p_ls = (func_t *)&spid->callbacks; + p_ls[cb_type] = (func_t)func; + + return ERR_NONE; +} + +int32_t _spi_s_async_register_callback(struct _spi_s_async_dev *dev, const enum _spi_s_async_dev_cb_type cb_type, + const FUNC_PTR func) +{ + return _spi_m_async_register_callback(dev, cb_type, func); +} + +bool _spi_s_sync_is_tx_ready(struct _spi_s_sync_dev *dev) +{ + ASSERT(dev && dev->prvt); + + return hri_sercomi2cm_get_INTFLAG_reg(dev->prvt, SERCOM_SPI_INTFLAG_DRE); +} + +bool _spi_s_sync_is_rx_ready(struct _spi_s_sync_dev *dev) +{ + ASSERT(dev && dev->prvt); + + return hri_sercomi2cm_get_INTFLAG_reg(dev->prvt, SERCOM_SPI_INTFLAG_RXC); +} + +bool _spi_s_sync_is_ss_deactivated(struct _spi_s_sync_dev *dev) +{ + void *hw = dev->prvt; + + ASSERT(dev && hw); + + if (hri_sercomi2cm_get_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_TXC)) { + hri_sercomspi_clear_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_TXC); + return true; + } + return false; +} + +bool _spi_s_sync_is_error(struct _spi_s_sync_dev *dev) +{ + void *hw = dev->prvt; + + ASSERT(dev && hw); + + if (hri_sercomi2cm_get_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_ERROR)) { + hri_sercomspi_clear_STATUS_reg(hw, SERCOM_SPI_STATUS_BUFOVF); + hri_sercomspi_clear_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_ERROR); + return true; + } + return false; +} + +/** + * \brief Enable/disable SPI master interrupt + * + * param[in] device The pointer to SPI master device instance + * param[in] type The type of interrupt to disable/enable if applicable + * param[in] state Enable or disable + */ +void _spi_m_async_set_irq_state(struct _spi_async_dev *const device, const enum _spi_async_dev_cb_type type, + const bool state) +{ + ASSERT(device); + + if (SPI_DEV_CB_ERROR == type) { + hri_sercomspi_write_INTEN_ERROR_bit(device->prvt, state); + } +} + +/** + * \brief Enable/disable SPI slave interrupt + * + * param[in] device The pointer to SPI slave device instance + * param[in] type The type of interrupt to disable/enable if applicable + * param[in] state Enable or disable + */ +void _spi_s_async_set_irq_state(struct _spi_async_dev *const device, const enum _spi_async_dev_cb_type type, + const bool state) +{ + _spi_m_async_set_irq_state(device, type, state); +} diff --git a/usb_dfu_main.c b/usb_dfu_main.c new file mode 100644 index 0000000..ebecba9 --- /dev/null +++ b/usb_dfu_main.c @@ -0,0 +1,133 @@ +/** + * \file + * \brief USB DFU bootloader implementation (DFU mode) + * + * Copyright (c) 2018-2019 sysmocom -s.f.m.c. GmbH, Author: Kevin Redon kredon@sysmocom.de + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <errno.h> +#include <stdint.h> +#include "atmel_start.h" +#include "atmel_start_pins.h" +#include "component/nvmctrl.h" + + +#ifdef __clang__ +#define OPTNONE optnone +#else +#define OPTNONE optimize(0) +#endif + +#define BLSZ_BYTE (BL_SIZE_BYTE) +static volatile const uint32_t bl_update_data[BLSZ_BYTE / sizeof(uint32_t)] __attribute__((section(".fwupdate"),used,retain)) = { 0xFF }; + +_Static_assert (BLSZ_BYTE % NVMCTRL_PAGE_SIZE == 0, "invalid bl size"); + + +__attribute__((section(".ramfunc"), OPTNONE)) +void same54_flash_write_page(uint32_t address, uint8_t *data) { + // address &= ~(NVMCTRL_PAGE_SIZE - 1); + while (!NVMCTRL->STATUS.bit.READY) {} + + hri_nvmctrl_write_CTRLB_reg(NVMCTRL, NVMCTRL_CTRLB_CMD_PBC | NVMCTRL_CTRLB_CMDEX_KEY); + + while (!NVMCTRL->STATUS.bit.READY) {} + + volatile uint32_t *dst = (uint32_t *)address; + volatile uint32_t *src = (uint32_t *)data; + + for (uint32_t i = 0; i < (NVMCTRL_PAGE_SIZE / sizeof(uint32_t)); i++) { + dst[i] = src[i]; + } + + NVMCTRL->ADDR.reg = address; + NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMD_WP | NVMCTRL_CTRLB_CMDEX_KEY; + while (!NVMCTRL->INTFLAG.bit.DONE) {} + while (!NVMCTRL->STATUS.bit.READY) {} +} + +__attribute__((section(".ramfunc"),OPTNONE)) +void do_update() { + uint16_t mask = NVMCTRL_CTRLA_AHBNS0 |NVMCTRL_CTRLA_AHBNS1|NVMCTRL_CTRLA_RWS_Msk; + uint16_t _nvm = (NVMCTRL_CTRLA_CACHEDIS0 | NVMCTRL_CTRLA_CACHEDIS1 | NVMCTRL_CTRLA_PRM(3) | NVMCTRL_CTRLA_RWS(0x7) | NVMCTRL_CTRLA_WMODE(0) |NVMCTRL_CTRLA_AUTOWS ); + uint32_t ctrla = NVMCTRL->CTRLA.reg; + ctrla &= ~(mask); + ctrla |= _nvm; + NVMCTRL->CTRLA.reg = ctrla; + + NVIC_DisableIRQ(NVMCTRL_0_IRQn); + NVIC_DisableIRQ(NVMCTRL_1_IRQn); + NVIC_ClearPendingIRQ(NVMCTRL_0_IRQn); + NVIC_ClearPendingIRQ(NVMCTRL_1_IRQn); + + #define NVMCTRL_REGIONS_NUM 32 + #define REGION_SZ (FLASH_SIZE/NVMCTRL_REGIONS_NUM) + #define BL_IN_PAGESZ (BLSZ_BYTE/NVMCTRL_PAGE_SIZE) + #define BL_IN_REGIONS (BLSZ_BYTE / REGION_SZ) + const uint32_t bootloader_regions = BLSZ_BYTE / NVMCTRL_BLOCK_SIZE; + + _Static_assert (BL_IN_REGIONS > 0, "bootprot regions must be at least 1"); + + // unlock everything + for(int i = 0; i< NVMCTRL_REGIONS_NUM; i++){ + while (!hri_nvmctrl_get_STATUS_READY_bit(NVMCTRL)) {} + hri_nvmctrl_write_ADDR_reg(NVMCTRL, REGION_SZ* i); + hri_nvmctrl_write_CTRLB_reg(NVMCTRL, NVMCTRL_CTRLB_CMD_UR | NVMCTRL_CTRLB_CMDEX_KEY); + } + + // disable bl protection + hri_nvmctrl_write_CTRLB_reg(NVMCTRL, NVMCTRL_CTRLB_CMD_SBPDIS | NVMCTRL_CTRLB_CMDEX_KEY); + while (!hri_nvmctrl_get_STATUS_READY_bit(NVMCTRL)) {} + + for(int i = 0; i< bootloader_regions; i++){ + while (!hri_nvmctrl_get_STATUS_READY_bit(NVMCTRL)) {} + hri_nvmctrl_write_ADDR_reg(NVMCTRL, NVMCTRL_BLOCK_SIZE * i); + hri_nvmctrl_write_CTRLB_reg(NVMCTRL, NVMCTRL_CTRLB_CMD_EB | NVMCTRL_CTRLB_CMDEX_KEY); + } + + while (!hri_nvmctrl_get_STATUS_READY_bit(NVMCTRL)) {} + + // Write firmware data to flash + uint32_t address = 0; + uint8_t *data_ptr = (uint8_t *)bl_update_data; + uint32_t remaining = BLSZ_BYTE; + + while (remaining >= NVMCTRL_PAGE_SIZE) { + same54_flash_write_page(address, data_ptr); + address += NVMCTRL_PAGE_SIZE; + data_ptr += NVMCTRL_PAGE_SIZE; + remaining -= NVMCTRL_PAGE_SIZE; + } + + //erases itself, fns likely not inlined @ -Os. + for(int i = bootloader_regions; i < bootloader_regions+1; i++){ + while (!(((Nvmctrl *)NVMCTRL)->STATUS.reg & NVMCTRL_STATUS_READY) >> NVMCTRL_STATUS_READY_Pos) {} + ((Nvmctrl *)NVMCTRL)->ADDR.reg = NVMCTRL_BLOCK_SIZE * i; + ((Nvmctrl *)NVMCTRL)->CTRLB.reg = NVMCTRL_CTRLB_CMD_EB | NVMCTRL_CTRLB_CMDEX_KEY; + } + while (!(((Nvmctrl *)NVMCTRL)->STATUS.reg & NVMCTRL_STATUS_READY) >> NVMCTRL_STATUS_READY_Pos) {} + + __DSB(); + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |(SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |SCB_AIRCR_SYSRESETREQ_Msk ); + __DSB(); +} +int main(void) +{ + __disable_irq(); + MCLK->AHBMASK.reg |= MCLK_AHBMASK_NVMCTRL; + do_update(); +} diff --git a/usb_flash_main.c b/usb_flash_main.c index 9115bf7..518cf2d 100644 --- a/usb_flash_main.c +++ b/usb_flash_main.c @@ -22,31 +22,16 @@ #include <errno.h> #include "atmel_start.h" #include "atmel_start_pins.h" +#include "hpl_user_area.h"
/** Start address of the application in flash * \remark must be initialized by check_bootloader */ -static uint32_t* application_start_address; +static uint32_t* application_start_address = (uint32_t*)(BL_SIZE_BYTE);
/** Location of the DFU magic value to force starting DFU */ static volatile uint32_t* dfu_magic = (uint32_t*)HSRAM_ADDR; // magic value should be written at start of RAM
-/** Check if the bootloader is valid - * \return true if the bootloader is valid and can be run - * \remark initializes application_start_address - */ -static bool check_bootloader(void) -{ - if (hri_nvmctrl_read_STATUS_BOOTPROT_bf(FLASH_0.dev.hw) > 15) { // ensure BOOTPROT setting is valid - return false; - } - application_start_address = (uint32_t*)((15 - hri_nvmctrl_read_STATUS_BOOTPROT_bf(FLASH_0.dev.hw)) * 8192); // calculate bootloader size to know start address of the application (e.g. after the bootloader) - if (0 == application_start_address) { // no space has been reserved for the bootloader - return false; - } - return true; -} - /** Check if starting the bootloader is forced * \return true of the DFU bootloader should be started */ @@ -84,6 +69,8 @@ { __set_MSP(*application_start_address); // re-base the Stack Pointer SCB->VTOR = ((uint32_t) application_start_address & SCB_VTOR_TBLOFF_Msk); // re-base the vector table base address + __DSB(); + __ISB(); asm("bx %0"::"r"(*(application_start_address + 1))); // jump to application Reset Handler in the application */ } #if defined(SYSMOOCTSIM) @@ -143,21 +130,23 @@ get_chip_unique_serial_str(sernr_buf, sizeof(sernr_buf)); str_to_usb_desc(sernr_buf, sizeof(sernr_buf), sernr_buf_descr, sizeof(sernr_buf_descr)); #endif - if (!check_bootloader()) { // check bootloader - // blink the LED to tell the user we don't know where the application starts - while (true) { - gpio_set_pin_level(LED_SYSTEM, false); - delay_ms(500); - gpio_set_pin_level(LED_SYSTEM, true); - delay_ms(500); - } + + + // set bootprot bits for (15-13)=2 x8192 byte + // hri_nvmctrl_write_CTRLB_reg(NVMCTRL, NVMCTRL_CTRLB_CMD_SBPDIS | NVMCTRL_CTRLB_CMDEX_KEY); + while (!hri_nvmctrl_get_STATUS_READY_bit(NVMCTRL)) {} + if (hri_nvmctrl_read_STATUS_BOOTPROT_bf(FLASH_0.dev.hw) != 13) { + _user_area_write_bits((void*)NVMCTRL_FUSES_BOOTPROT_ADDR, NVMCTRL_FUSES_BOOTPROT_Pos, 13, 4); } + + if (!check_force_dfu() && check_application()) { // application is valid start_application(); // start application } else { if (!check_application()) { // if the application is corrupted the start DFU start should be dfuERROR dfu_state = USB_DFU_STATE_DFU_ERROR; } + usb_init(); usb_dfu(); // start DFU bootloader } } diff --git a/usb_start.c b/usb_start.c index 24cde4f..dacd325 100644 --- a/usb_start.c +++ b/usb_start.c @@ -151,8 +151,7 @@ while (!dfudf_is_enabled()); // wait for DFU to be installed LED_SYSTEM_on(); // switch LED on to indicate USB DFU stack is ready
- ASSERT(hri_nvmctrl_read_STATUS_BOOTPROT_bf(FLASH_0.dev.hw) <= 15); - uint32_t application_start_address = (15 - hri_nvmctrl_read_STATUS_BOOTPROT_bf(FLASH_0.dev.hw)) * 8192; // calculate bootloader size to know where we should write the application firmware + uint32_t application_start_address = BL_SIZE_BYTE; // calculate bootloader size to know where we should write the application firmware ASSERT(application_start_address > 0);
while (true) { // main DFU infinite loop