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(a)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
--
To view, visit
https://gerrit.osmocom.org/c/osmo-asf4-dfu/+/39434?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: osmo-asf4-dfu
Gerrit-Branch: master
Gerrit-Change-Id: I1403d35497cdea41ea5bed2c94b9e729ca352772
Gerrit-Change-Number: 39434
Gerrit-PatchSet: 1
Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de>