From 6441607ff7e54e9a939e7e142bd0152196fa6eeb Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Wed, 3 Apr 2019 17:50:43 +0200 Subject: [PATCH] sam0_common: make Timer implementation common across all sam0 MCUs The currently supported SAM0 MCUs (samd21, saml21, saml1x) share the same Timer peripheral, yet each of them carries it's own copy of the Timer driver. This introduces a new timer driver that is common for all sam0 MCUs and uses structs for configuration instead of defines. --- boards/arduino-zero/include/board.h | 2 +- boards/arduino-zero/include/periph_conf.h | 46 ++- .../common/arduino-mkr/include/periph_conf.h | 47 ++- boards/common/saml1x/include/periph_conf.h | 21 +- boards/feather-m0/include/periph_conf.h | 49 ++- boards/hamilton/include/periph_conf.h | 49 ++- boards/samd21-xpro/include/board.h | 2 +- boards/samd21-xpro/include/periph_conf.h | 47 ++- boards/saml21-xpro/include/periph_conf.h | 21 +- boards/samr21-xpro/include/periph_conf.h | 47 ++- boards/samr30-xpro/include/periph_conf.h | 21 +- boards/sensebox_samd21/include/periph_conf.h | 49 ++- boards/sodaq-autonomo/include/periph_conf.h | 47 ++- boards/sodaq-explorer/include/board.h | 7 - boards/sodaq-explorer/include/periph_conf.h | 36 +- boards/sodaq-one/include/periph_conf.h | 49 ++- boards/sodaq-sara-aff/include/periph_conf.h | 49 ++- cpu/sam0_common/include/periph_cpu_common.h | 19 + cpu/sam0_common/periph/timer.c | 269 ++++++++++++++ cpu/samd21/periph/timer.c | 351 ------------------ cpu/saml1x/periph/timer.c | 231 ------------ cpu/saml21/periph/timer.c | 228 ------------ 22 files changed, 710 insertions(+), 977 deletions(-) create mode 100644 cpu/sam0_common/periph/timer.c delete mode 100644 cpu/samd21/periph/timer.c delete mode 100644 cpu/saml1x/periph/timer.c delete mode 100644 cpu/saml21/periph/timer.c diff --git a/boards/arduino-zero/include/board.h b/boards/arduino-zero/include/board.h index d3e209a67872a..c9310a85fedf2 100644 --- a/boards/arduino-zero/include/board.h +++ b/boards/arduino-zero/include/board.h @@ -33,7 +33,7 @@ extern "C" { * @name xtimer configuration * @{ */ -#define XTIMER TIMER_DEV(1) +#define XTIMER_DEV TIMER_DEV(1) #define XTIMER_CHAN (0) /** @} */ diff --git a/boards/arduino-zero/include/periph_conf.h b/boards/arduino-zero/include/periph_conf.h index b3a64798ce701..09eed72b8c459 100644 --- a/boards/arduino-zero/include/periph_conf.h +++ b/boards/arduino-zero/include/periph_conf.h @@ -83,22 +83,44 @@ extern "C" { * @name Timer peripheral configuration * @{ */ -#define TIMER_NUMOF (2U) -#define TIMER_0_EN 1 -#define TIMER_1_EN 1 +static const tc32_conf_t timer_config[] = { + { /* Timer 0 - System Clock */ + .dev = TC3, + .irq = TC3_IRQn, + .pm_mask = PM_APBCMASK_TC3, + .gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT16, + }, + { /* Timer 1 */ + .dev = TC4, + .irq = TC4_IRQn, + .pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5, + .gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT32, + } +}; -/* Timer 0 configuration */ -#define TIMER_0_DEV TC3->COUNT16 -#define TIMER_0_CHANNELS 2 -#define TIMER_0_MAX_VALUE (0xffff) -#define TIMER_0_ISR isr_tc3 +#define TIMER_0_MAX_VALUE 0xffff -/* Timer 1 configuration */ -#define TIMER_1_DEV TC4->COUNT32 -#define TIMER_1_CHANNELS 2 -#define TIMER_1_MAX_VALUE (0xffffffff) +/* interrupt function name mapping */ +#define TIMER_0_ISR isr_tc3 #define TIMER_1_ISR isr_tc4 +#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0])) /** @} */ /** diff --git a/boards/common/arduino-mkr/include/periph_conf.h b/boards/common/arduino-mkr/include/periph_conf.h index 5949d249248bc..7df029386e988 100644 --- a/boards/common/arduino-mkr/include/periph_conf.h +++ b/boards/common/arduino-mkr/include/periph_conf.h @@ -81,21 +81,44 @@ extern "C" { * @name Timer peripheral configuration * @{ */ -#define TIMER_NUMOF (2U) -#define TIMER_0_EN 1 -#define TIMER_1_EN 1 +static const tc32_conf_t timer_config[] = { + { /* Timer 0 - System Clock */ + .dev = TC3, + .irq = TC3_IRQn, + .pm_mask = PM_APBCMASK_TC3, + .gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT16, + }, + { /* Timer 1 */ + .dev = TC4, + .irq = TC4_IRQn, + .pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5, + .gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT32, + } +}; -/* Timer 0 configuration */ -#define TIMER_0_DEV TC3->COUNT16 -#define TIMER_0_CHANNELS 2 -#define TIMER_0_MAX_VALUE (0xffff) -#define TIMER_0_ISR isr_tc3 +#define TIMER_0_MAX_VALUE 0xffff -/* Timer 1 configuration */ -#define TIMER_1_DEV TC4->COUNT32 -#define TIMER_1_CHANNELS 2 -#define TIMER_1_MAX_VALUE (0xffffffff) +/* interrupt function name mapping */ +#define TIMER_0_ISR isr_tc3 #define TIMER_1_ISR isr_tc4 + +#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0])) /** @} */ /** diff --git a/boards/common/saml1x/include/periph_conf.h b/boards/common/saml1x/include/periph_conf.h index b060916b5aa6e..56fbe2e3ebd2e 100644 --- a/boards/common/saml1x/include/periph_conf.h +++ b/boards/common/saml1x/include/periph_conf.h @@ -35,14 +35,23 @@ extern "C" { * @name Timer peripheral configuration * @{ */ -#define TIMER_NUMOF (1U) -#define TIMER_0_EN 1 +static const tc32_conf_t timer_config[] = { + { /* Timer 0 - System Clock */ + .dev = TC0, + .irq = TC0_IRQn, + .mclk = &MCLK->APBCMASK.reg, + .mclk_mask = MCLK_APBCMASK_TC0 | MCLK_APBCMASK_TC1, + .gclk_id = TC0_GCLK_ID, + .gclk_src = GCLK_PCHCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER(4), + .flags = TC_CTRLA_MODE_COUNT32, + } +}; /* Timer 0 configuration */ -#define TIMER_0_DEV TC0->COUNT32 -#define TIMER_0_CHANNELS 1 -#define TIMER_0_MAX_VALUE (0xffffffff) -#define TIMER_0_ISR isr_tc0 +#define TIMER_0_CHANNELS 2 +#define TIMER_0_ISR isr_tc0 +#define TIMER_NUMOF (sizeof(timer_config)/sizeof(timer_config[0])) /** @} */ /** diff --git a/boards/feather-m0/include/periph_conf.h b/boards/feather-m0/include/periph_conf.h index 61bdb06118eec..4fc23a1cd09f9 100644 --- a/boards/feather-m0/include/periph_conf.h +++ b/boards/feather-m0/include/periph_conf.h @@ -78,21 +78,44 @@ extern "C" { * @name Timer peripheral configuration * @{ */ -#define TIMER_NUMOF (2U) -#define TIMER_0_EN 1 -#define TIMER_1_EN 1 - -/* Timer 0 configuration */ -#define TIMER_0_DEV TC3->COUNT16 -#define TIMER_0_CHANNELS 2 -#define TIMER_0_MAX_VALUE (0xffff) -#define TIMER_0_ISR isr_tc3 +static const tc32_conf_t timer_config[] = { + { /* Timer 0 - System Clock */ + .dev = TC3, + .irq = TC3_IRQn, + .pm_mask = PM_APBCMASK_TC3, + .gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT16, + }, + { /* Timer 1 */ + .dev = TC4, + .irq = TC4_IRQn, + .pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5, + .gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT32, + } +}; + +#define TIMER_0_MAX_VALUE 0xffff -/* Timer 1 configuration */ -#define TIMER_1_DEV TC4->COUNT32 -#define TIMER_1_CHANNELS 2 -#define TIMER_1_MAX_VALUE (0xffffffff) +/* interrupt function name mapping */ +#define TIMER_0_ISR isr_tc3 #define TIMER_1_ISR isr_tc4 + +#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0])) /** @} */ /** diff --git a/boards/hamilton/include/periph_conf.h b/boards/hamilton/include/periph_conf.h index f1d2057ec3d4b..c1bf3c6c80573 100644 --- a/boards/hamilton/include/periph_conf.h +++ b/boards/hamilton/include/periph_conf.h @@ -113,21 +113,44 @@ extern "C" { * @name Timer peripheral configuration * @{ */ -#define TIMER_NUMOF (2U) -#define TIMER_0_EN 1 -#define TIMER_1_EN 1 - -/* Timer 0 configuration */ -#define TIMER_0_DEV TC3->COUNT16 -#define TIMER_0_CHANNELS 2 -#define TIMER_0_MAX_VALUE (0xffff) -#define TIMER_0_ISR isr_tc3 +static const tc32_conf_t timer_config[] = { + { /* Timer 0 - System Clock */ + .dev = TC3, + .irq = TC3_IRQn, + .pm_mask = PM_APBCMASK_TC3, + .gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT16, + }, + { /* Timer 1 */ + .dev = TC4, + .irq = TC4_IRQn, + .pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5, + .gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT32, + } +}; + +#define TIMER_0_MAX_VALUE 0xffff -/* Timer 1 configuration */ -#define TIMER_1_DEV TC4->COUNT32 -#define TIMER_1_CHANNELS 2 -#define TIMER_1_MAX_VALUE (0xffffffff) +/* interrupt function name mapping */ +#define TIMER_0_ISR isr_tc3 #define TIMER_1_ISR isr_tc4 + +#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0])) /** @} */ /** diff --git a/boards/samd21-xpro/include/board.h b/boards/samd21-xpro/include/board.h index 368cca7da50be..8b0c4b2395f54 100644 --- a/boards/samd21-xpro/include/board.h +++ b/boards/samd21-xpro/include/board.h @@ -32,7 +32,7 @@ extern "C" { #endif /** - * @name xtimer configuration + * @name xtimer configuration * @{ */ #define XTIMER_DEV TIMER_DEV(1) diff --git a/boards/samd21-xpro/include/periph_conf.h b/boards/samd21-xpro/include/periph_conf.h index b65ee51a2c5e1..ce3231ba4d97c 100644 --- a/boards/samd21-xpro/include/periph_conf.h +++ b/boards/samd21-xpro/include/periph_conf.h @@ -89,21 +89,44 @@ extern "C" { * @name Timer peripheral configuration * @{ */ -#define TIMER_NUMOF (2U) -#define TIMER_0_EN 1 -#define TIMER_1_EN 1 +static const tc32_conf_t timer_config[] = { + { /* Timer 0 - System Clock */ + .dev = TC3, + .irq = TC3_IRQn, + .pm_mask = PM_APBCMASK_TC3, + .gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT16, + }, + { /* Timer 1 */ + .dev = TC4, + .irq = TC4_IRQn, + .pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5, + .gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT32, + } +}; -/* Timer 0 configuration */ -#define TIMER_0_DEV TC3->COUNT16 -#define TIMER_0_CHANNELS 2 -#define TIMER_0_MAX_VALUE (0xffff) -#define TIMER_0_ISR isr_tc3 +#define TIMER_0_MAX_VALUE 0xffff -/* Timer 1 configuration */ -#define TIMER_1_DEV TC4->COUNT32 -#define TIMER_1_CHANNELS 2 -#define TIMER_1_MAX_VALUE (0xffffffff) +/* interrupt function name mapping */ +#define TIMER_0_ISR isr_tc3 #define TIMER_1_ISR isr_tc4 + +#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0])) /** @} */ /** diff --git a/boards/saml21-xpro/include/periph_conf.h b/boards/saml21-xpro/include/periph_conf.h index baeca4aa49362..95c4b8b2ed89d 100644 --- a/boards/saml21-xpro/include/periph_conf.h +++ b/boards/saml21-xpro/include/periph_conf.h @@ -38,14 +38,23 @@ extern "C" { * @name Timer peripheral configuration * @{ */ -#define TIMER_NUMOF (1U) -#define TIMER_0_EN 1 +static const tc32_conf_t timer_config[] = { + { /* Timer 0 - System Clock */ + .dev = TC0, + .irq = TC0_IRQn, + .mclk = &MCLK->APBCMASK.reg, + .mclk_mask = MCLK_APBCMASK_TC0 | MCLK_APBCMASK_TC1, + .gclk_id = TC0_GCLK_ID, + .gclk_src = GCLK_PCHCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER(4), + .flags = TC_CTRLA_MODE_COUNT32, + } +}; /* Timer 0 configuration */ -#define TIMER_0_DEV TC0->COUNT32 -#define TIMER_0_CHANNELS 1 -#define TIMER_0_MAX_VALUE (0xffffffff) -#define TIMER_0_ISR isr_tc0 +#define TIMER_0_CHANNELS 2 +#define TIMER_0_ISR isr_tc0 +#define TIMER_NUMOF (sizeof(timer_config)/sizeof(timer_config[0])) /** @} */ /** diff --git a/boards/samr21-xpro/include/periph_conf.h b/boards/samr21-xpro/include/periph_conf.h index 3f1894b0658c6..c405144baf5f6 100644 --- a/boards/samr21-xpro/include/periph_conf.h +++ b/boards/samr21-xpro/include/periph_conf.h @@ -89,21 +89,44 @@ extern "C" { * @name Timer peripheral configuration * @{ */ -#define TIMER_NUMOF (2U) -#define TIMER_0_EN 1 -#define TIMER_1_EN 1 +static const tc32_conf_t timer_config[] = { + { /* Timer 0 - System Clock */ + .dev = TC3, + .irq = TC3_IRQn, + .pm_mask = PM_APBCMASK_TC3, + .gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT16, + }, + { /* Timer 1 */ + .dev = TC4, + .irq = TC4_IRQn, + .pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5, + .gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT32, + } +}; -/* Timer 0 configuration */ -#define TIMER_0_DEV TC3->COUNT16 -#define TIMER_0_CHANNELS 2 -#define TIMER_0_MAX_VALUE (0xffff) -#define TIMER_0_ISR isr_tc3 +#define TIMER_0_MAX_VALUE 0xffff -/* Timer 1 configuration */ -#define TIMER_1_DEV TC4->COUNT32 -#define TIMER_1_CHANNELS 2 -#define TIMER_1_MAX_VALUE (0xffffffff) +/* interrupt function name mapping */ +#define TIMER_0_ISR isr_tc3 #define TIMER_1_ISR isr_tc4 + +#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0])) /** @} */ /** diff --git a/boards/samr30-xpro/include/periph_conf.h b/boards/samr30-xpro/include/periph_conf.h index 4401c4d320d7a..1ff3d224ef767 100644 --- a/boards/samr30-xpro/include/periph_conf.h +++ b/boards/samr30-xpro/include/periph_conf.h @@ -34,14 +34,23 @@ extern "C" { * @name Timer peripheral configuration * @{ */ -#define TIMER_NUMOF (1U) -#define TIMER_0_EN 1 +static const tc32_conf_t timer_config[] = { + { /* Timer 0 - System Clock */ + .dev = TC0, + .irq = TC0_IRQn, + .mclk = &MCLK->APBCMASK.reg, + .mclk_mask = MCLK_APBCMASK_TC0 | MCLK_APBCMASK_TC1, + .gclk_id = TC0_GCLK_ID, + .gclk_src = GCLK_PCHCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER(4), + .flags = TC_CTRLA_MODE_COUNT32, + } +}; /* Timer 0 configuration */ -#define TIMER_0_DEV TC0->COUNT32 -#define TIMER_0_CHANNELS 1 -#define TIMER_0_MAX_VALUE (0xffffffff) -#define TIMER_0_ISR isr_tc0 +#define TIMER_0_CHANNELS 2 +#define TIMER_0_ISR isr_tc0 +#define TIMER_NUMOF (sizeof(timer_config)/sizeof(timer_config[0])) /** @} */ /** diff --git a/boards/sensebox_samd21/include/periph_conf.h b/boards/sensebox_samd21/include/periph_conf.h index e0c844e1e16d7..e1d21a97af73c 100644 --- a/boards/sensebox_samd21/include/periph_conf.h +++ b/boards/sensebox_samd21/include/periph_conf.h @@ -79,21 +79,44 @@ extern "C" { * @name Timer peripheral configuration * @{ */ -#define TIMER_NUMOF (2U) -#define TIMER_0_EN 1 -#define TIMER_1_EN 1 - -/* Timer 0 configuration */ -#define TIMER_0_DEV TC3->COUNT16 -#define TIMER_0_CHANNELS 2 -#define TIMER_0_MAX_VALUE (0xffff) -#define TIMER_0_ISR isr_tc3 +static const tc32_conf_t timer_config[] = { + { /* Timer 0 - System Clock */ + .dev = TC3, + .irq = TC3_IRQn, + .pm_mask = PM_APBCMASK_TC3, + .gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT16, + }, + { /* Timer 1 */ + .dev = TC4, + .irq = TC4_IRQn, + .pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5, + .gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT32, + } +}; + +#define TIMER_0_MAX_VALUE 0xffff -/* Timer 1 configuration */ -#define TIMER_1_DEV TC4->COUNT32 -#define TIMER_1_CHANNELS 2 -#define TIMER_1_MAX_VALUE (0xffffffff) +/* interrupt function name mapping */ +#define TIMER_0_ISR isr_tc3 #define TIMER_1_ISR isr_tc4 + +#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0])) /** @} */ /** diff --git a/boards/sodaq-autonomo/include/periph_conf.h b/boards/sodaq-autonomo/include/periph_conf.h index ca0a02a9f188d..d713e2508687e 100644 --- a/boards/sodaq-autonomo/include/periph_conf.h +++ b/boards/sodaq-autonomo/include/periph_conf.h @@ -79,21 +79,44 @@ extern "C" { * @name Timer peripheral configuration * @{ */ -#define TIMER_NUMOF (2U) -#define TIMER_0_EN 1 -#define TIMER_1_EN 1 +static const tc32_conf_t timer_config[] = { + { /* Timer 0 - System Clock */ + .dev = TC3, + .irq = TC3_IRQn, + .pm_mask = PM_APBCMASK_TC3, + .gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT16, + }, + { /* Timer 1 */ + .dev = TC4, + .irq = TC4_IRQn, + .pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5, + .gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT32, + } +}; -/* Timer 0 configuration */ -#define TIMER_0_DEV TC3->COUNT16 -#define TIMER_0_CHANNELS 2 -#define TIMER_0_MAX_VALUE (0xffff) -#define TIMER_0_ISR isr_tc3 +#define TIMER_0_MAX_VALUE 0xffff -/* Timer 1 configuration */ -#define TIMER_1_DEV TC4->COUNT32 -#define TIMER_1_CHANNELS 2 -#define TIMER_1_MAX_VALUE (0xffffffff) +/* interrupt function name mapping */ +#define TIMER_0_ISR isr_tc3 #define TIMER_1_ISR isr_tc4 + +#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0])) /** @} */ /** diff --git a/boards/sodaq-explorer/include/board.h b/boards/sodaq-explorer/include/board.h index 437c354d122b6..e727f09fb72ce 100644 --- a/boards/sodaq-explorer/include/board.h +++ b/boards/sodaq-explorer/include/board.h @@ -26,13 +26,6 @@ extern "C" { #endif -/** - * @name xtimer configuration - * @{ - */ -#define XTIMER_WIDTH (16) -/** @} */ - /** * @name LED pin definitions and handlers * @{ diff --git a/boards/sodaq-explorer/include/periph_conf.h b/boards/sodaq-explorer/include/periph_conf.h index 2cbe5761d066a..2415d46d666fd 100644 --- a/boards/sodaq-explorer/include/periph_conf.h +++ b/boards/sodaq-explorer/include/periph_conf.h @@ -76,21 +76,27 @@ extern "C" { * @name Timer peripheral configuration * @{ */ -#define TIMER_NUMOF (2U) -#define TIMER_0_EN 1 -#define TIMER_1_EN 1 - -/* Timer 0 configuration */ -#define TIMER_0_DEV TC3->COUNT16 -#define TIMER_0_CHANNELS 2 -#define TIMER_0_MAX_VALUE (0xffff) -#define TIMER_0_ISR isr_tc3 - -/* Timer 1 configuration */ -#define TIMER_1_DEV TC4->COUNT32 -#define TIMER_1_CHANNELS 2 -#define TIMER_1_MAX_VALUE (0xffffffff) -#define TIMER_1_ISR isr_tc4 +static const tc32_conf_t timer_config[] = { + { /* Timer 0 - System Clock */ + .dev = TC4, + .irq = TC4_IRQn, + .pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5, + .gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT32, + } +}; + +/* interrupt function name mapping */ +#define TIMER_0_ISR isr_tc4 + +#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0])) /** @} */ /** diff --git a/boards/sodaq-one/include/periph_conf.h b/boards/sodaq-one/include/periph_conf.h index 5c4cc4c78a813..fc331aecad68a 100644 --- a/boards/sodaq-one/include/periph_conf.h +++ b/boards/sodaq-one/include/periph_conf.h @@ -79,21 +79,44 @@ extern "C" { * @name Timer peripheral configuration * @{ */ -#define TIMER_NUMOF (2U) -#define TIMER_0_EN 1 -#define TIMER_1_EN 1 - -/* Timer 0 configuration */ -#define TIMER_0_DEV TC3->COUNT16 -#define TIMER_0_CHANNELS 2 -#define TIMER_0_MAX_VALUE (0xffff) -#define TIMER_0_ISR isr_tc3 +static const tc32_conf_t timer_config[] = { + { /* Timer 0 - System Clock */ + .dev = TC3, + .irq = TC3_IRQn, + .pm_mask = PM_APBCMASK_TC3, + .gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT16, + }, + { /* Timer 1 */ + .dev = TC4, + .irq = TC4_IRQn, + .pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5, + .gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT32, + } +}; + +#define TIMER_0_MAX_VALUE 0xffff -/* Timer 1 configuration */ -#define TIMER_1_DEV TC4->COUNT32 -#define TIMER_1_CHANNELS 2 -#define TIMER_1_MAX_VALUE (0xffffffff) +/* interrupt function name mapping */ +#define TIMER_0_ISR isr_tc3 #define TIMER_1_ISR isr_tc4 + +#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0])) /** @} */ /** diff --git a/boards/sodaq-sara-aff/include/periph_conf.h b/boards/sodaq-sara-aff/include/periph_conf.h index 65fe8070c35b8..320275387d549 100644 --- a/boards/sodaq-sara-aff/include/periph_conf.h +++ b/boards/sodaq-sara-aff/include/periph_conf.h @@ -81,21 +81,44 @@ extern "C" { * @name Timer peripheral configuration * @{ */ -#define TIMER_NUMOF (2U) -#define TIMER_0_EN 1 -#define TIMER_1_EN 1 - -/* Timer 0 configuration */ -#define TIMER_0_DEV TC3->COUNT16 -#define TIMER_0_CHANNELS 2 -#define TIMER_0_MAX_VALUE (0xffff) -#define TIMER_0_ISR isr_tc3 +static const tc32_conf_t timer_config[] = { + { /* Timer 0 - System Clock */ + .dev = TC3, + .irq = TC3_IRQn, + .pm_mask = PM_APBCMASK_TC3, + .gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT16, + }, + { /* Timer 1 */ + .dev = TC4, + .irq = TC4_IRQn, + .pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5, + .gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5, +#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL + .gclk_src = GCLK_CLKCTRL_GEN(1), + .prescaler = TC_CTRLA_PRESCALER_DIV1, +#else + .gclk_src = GCLK_CLKCTRL_GEN(0), + .prescaler = TC_CTRLA_PRESCALER_DIV8, +#endif + .flags = TC_CTRLA_MODE_COUNT32, + } +}; + +#define TIMER_0_MAX_VALUE 0xffff -/* Timer 1 configuration */ -#define TIMER_1_DEV TC4->COUNT32 -#define TIMER_1_CHANNELS 2 -#define TIMER_1_MAX_VALUE (0xffffffff) +/* interrupt function name mapping */ +#define TIMER_0_ISR isr_tc3 #define TIMER_1_ISR isr_tc4 + +#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0])) /** @} */ /** diff --git a/cpu/sam0_common/include/periph_cpu_common.h b/cpu/sam0_common/include/periph_cpu_common.h index 2472337e14d09..215ff32e1cb21 100644 --- a/cpu/sam0_common/include/periph_cpu_common.h +++ b/cpu/sam0_common/include/periph_cpu_common.h @@ -289,6 +289,25 @@ typedef struct { uint8_t flags; /**< allow SERCOM to run in standby mode */ } i2c_conf_t; +/** + * @brief Timer device configuration + */ +typedef struct { + Tc *dev; /**< pointer to the used Timer device */ + IRQn_Type irq; /**< IRQ# of Timer Interrupt */ +#ifdef MCLK + volatile uint32_t *mclk;/**< Pointer to MCLK->APBxMASK.reg */ + uint32_t mclk_mask; /**< MCLK_APBxMASK bits to enable Timer */ + uint16_t gclk_id; /**< TCn_GCLK_ID */ +#else + uint32_t pm_mask; /**< PM_APBCMASK bits to enable Timer */ + uint16_t gclk_ctrl; /**< GCLK_CLKCTRL_ID for the Timer */ +#endif + uint16_t gclk_src; /**< GCLK source which supplys Timer */ + uint16_t prescaler; /**< prescaler used by the Timer */ + uint16_t flags; /**< flags for CTRA, e.g. TC_CTRLA_MODE_COUNT32 */ +} tc32_conf_t; + /** * @brief Set up alternate function (PMUX setting) for a PORT pin * diff --git a/cpu/sam0_common/periph/timer.c b/cpu/sam0_common/periph/timer.c new file mode 100644 index 0000000000000..15e6f5d430b3b --- /dev/null +++ b/cpu/sam0_common/periph/timer.c @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2019 ML!PA Consulting GmbH + * + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_sam0_common + * @ingroup drivers_periph_timer + * @{ + * + * @file timer.c + * @brief Low-level timer driver implementation + * + * @author Benjamin Valentin + * + * @} + */ + +#include +#include + +#include "board.h" +#include "cpu.h" + +#include "periph/timer.h" +#include "periph_conf.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/** + * @brief Timer state memory + */ +static timer_isr_ctx_t config[TIMER_NUMOF]; + +static inline TcCount32 *dev(tim_t tim) +{ + return &timer_config[tim].dev->COUNT32; +} + +static inline TcCount16 *dev16(tim_t tim) +{ + return &timer_config[tim].dev->COUNT16; +} + +static inline TcCount8 *dev8(tim_t tim) +{ + return &timer_config[tim].dev->COUNT8; +} + +static inline void wait_synchronization(tim_t tim) +{ +#if defined(TC_SYNCBUSY_MASK) + /* SYNCBUSY is a register */ + while ((dev(tim)->SYNCBUSY.reg & TC_SYNCBUSY_MASK) != 0) {} +#elif defined(TC_STATUS_SYNCBUSY) + /* SYNCBUSY is a bit */ + while ((dev(tim)->STATUS.reg & TC_STATUS_SYNCBUSY) != 0) {} +#else +#error Unsupported device +#endif +} + +/* enable timer interrupts */ +static inline void _irq_enable(tim_t tim) +{ + NVIC_EnableIRQ(timer_config[tim].irq); +} + +/** + * @brief Setup the given timer + */ +int timer_init(tim_t tim, unsigned long freq, timer_cb_t cb, void *arg) +{ + const tc32_conf_t *cfg = &timer_config[tim]; + + /* make sure given device is valid */ + if (tim >= TIMER_NUMOF) { + return -1; + } + + /* at the moment, the timer can only run at 1MHz */ + if (freq != 1000000ul) { + return -1; + } + + /* make sure the timer is not running */ + timer_stop(tim); + +#ifdef MCLK + GCLK->PCHCTRL[cfg->gclk_id].reg = cfg->gclk_src | GCLK_PCHCTRL_CHEN; + *cfg->mclk |= cfg->mclk_mask; +#else + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | cfg->gclk_src | cfg->gclk_ctrl; + PM->APBCMASK.reg |= cfg->pm_mask; +#endif + + /* reset the timer */ + dev(tim)->CTRLA.bit.SWRST = 1; + while (dev(tim)->CTRLA.bit.SWRST) {} + + dev(tim)->CTRLA.reg = cfg->flags +#ifdef TC_CTRLA_WAVEGEN_NFRQ + | TC_CTRLA_WAVEGEN_NFRQ +#endif + | cfg->prescaler + | TC_CTRLA_PRESCSYNC_RESYNC; + +#ifdef TC_WAVE_WAVEGEN_NFRQ + dev(tim)->WAVE.reg = TC_WAVE_WAVEGEN_NFRQ; +#endif + + wait_synchronization(tim); + + dev(tim)->INTENCLR.reg = TC_INTENCLR_MASK; + + /* save callback */ + config[tim].cb = cb; + config[tim].arg = arg; + + timer_start(tim); + + /* enable interrupts for given timer */ + _irq_enable(tim); + + return 0; +} + +static void _set_cc(tim_t tim, int cc, unsigned int value) +{ + const uint16_t flags = timer_config[tim].flags; + + if (flags & TC_CTRLA_MODE_COUNT32) { + dev(tim)->CC[cc].reg = value; + return; + } + + if (flags & TC_CTRLA_MODE_COUNT8) { + dev8(tim)->CC[cc].reg = value; + return; + } + + /* 16 bit is the default */ + dev16(tim)->CC[cc].reg = value; +} + +int timer_set_absolute(tim_t tim, int channel, unsigned int value) +{ + DEBUG("Setting timer %i channel %i to %i\n", tim, channel, value); + + /* set timeout value */ + switch (channel) { + case 0: + dev(tim)->INTFLAG.reg = TC_INTFLAG_MC0; + _set_cc(tim, 0, value); + dev(tim)->INTENSET.bit.MC0 = 1; + break; + case 1: + dev(tim)->INTFLAG.reg = TC_INTFLAG_MC1; + _set_cc(tim, 1, value); + dev(tim)->INTENSET.bit.MC1 = 1; + break; + default: + return -1; + } + + return 1; +} + +int timer_clear(tim_t tim, int channel) +{ + switch (channel) { + case 0: + dev(tim)->INTFLAG.reg = TC_INTFLAG_MC0; + dev(tim)->INTENCLR.bit.MC0 = 1; + break; + case 1: + dev(tim)->INTFLAG.reg = TC_INTFLAG_MC1; + dev(tim)->INTENCLR.bit.MC1 = 1; + break; + default: + return -1; + } + + return 1; +} + +unsigned int timer_read(tim_t tim) +{ + /* WORKAROUND to prevent being stuck there if timer not init */ + if (!dev(tim)->CTRLA.bit.ENABLE) { + return 0; + } + + /* request syncronisation */ +#ifdef TC_CTRLBSET_CMD_READSYNC_Val + dev(tim)->CTRLBSET.bit.CMD = TC_CTRLBSET_CMD_READSYNC_Val; +#else + dev(tim)->READREQ.reg = TC_READREQ_RREQ | TC_READREQ_ADDR(0x10); +#endif + wait_synchronization(tim); + + return dev(tim)->COUNT.reg; +} + +void timer_stop(tim_t tim) +{ + dev(tim)->CTRLA.bit.ENABLE = 0; +} + +void timer_start(tim_t tim) +{ + dev(tim)->CTRLA.bit.ENABLE = 1; +} + +static inline void timer_isr(tim_t tim) +{ + TcCount32 *tc = dev(tim); + uint8_t status = tc->INTFLAG.reg; + + /* Acknowledge all interrupts */ + tc->INTFLAG.reg = status; + + if ((status & TC_INTFLAG_MC0) && tc->INTENSET.bit.MC0) { + tc->INTENCLR.reg = TC_INTENCLR_MC0; + if (config[tim].cb) { + config[tim].cb(config[tim].arg, 0); + } + } + if ((status & TC_INTFLAG_MC1) && tc->INTENSET.bit.MC1) { + tc->INTENCLR.reg = TC_INTENCLR_MC1; + if (config[tim].cb) { + config[tim].cb(config[tim].arg, 1); + } + } +} + +#ifdef TIMER_0_ISR +void TIMER_0_ISR(void) +{ + timer_isr(0); + cortexm_isr_end(); +} +#endif +#ifdef TIMER_1_ISR +void TIMER_1_ISR(void) +{ + timer_isr(1); + cortexm_isr_end(); +} +#endif +#ifdef TIMER_2_ISR +void TIMER_2_ISR(void) +{ + timer_isr(2); + cortexm_isr_end(); +} +#endif +#ifdef TIMER_3_ISR +void TIMER_3_ISR(void) +{ + timer_isr(3); + cortexm_isr_end(); +} +#endif diff --git a/cpu/samd21/periph/timer.c b/cpu/samd21/periph/timer.c deleted file mode 100644 index 689d9bc73387f..0000000000000 --- a/cpu/samd21/periph/timer.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (C) 2014 Freie Universität Berlin - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_samd21 - * @ingroup drivers_periph_timer - * @{ - * - * @file - * @brief Low-level timer driver implementation - * - * @author Thomas Eichinger - * - * @} - */ - -#include -#include - -#include "board.h" -#include "cpu.h" - -#include "periph/timer.h" -#include "periph_conf.h" - -#define ENABLE_DEBUG (0) -#include "debug.h" - -/** - * @brief Timer state memory - */ -static timer_isr_ctx_t config[TIMER_NUMOF]; - -/* enable timer interrupts */ -static inline void _irq_enable(tim_t dev); - -/** - * @brief Setup the given timer - */ -int timer_init(tim_t dev, unsigned long freq, timer_cb_t cb, void *arg) -{ - /* at the moment, the timer can only run at 1MHz */ - if (freq != 1000000ul) { - return -1; - } - -/* select the clock generator depending on the main clock source: - * GCLK0 (1MHz) if we use the internal 8MHz oscillator - * GCLK1 (8MHz) if we use the PLL */ -#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL - /* configure GCLK1 (configured to 1MHz) to feed TC3, TC4 and TC5 */; - /* configure GCLK1 to feed TC3, TC4 and TC5 */; - GCLK->CLKCTRL.reg = (uint16_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK1 | (TC3_GCLK_ID << GCLK_CLKCTRL_ID_Pos))); - while (GCLK->STATUS.bit.SYNCBUSY) {} - /* TC4 and TC5 share the same channel */ - GCLK->CLKCTRL.reg = (uint16_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK1 | (TC4_GCLK_ID << GCLK_CLKCTRL_ID_Pos))); -#else - /* configure GCLK0 to feed TC3, TC4 and TC5 */; - GCLK->CLKCTRL.reg = (uint16_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | (TC3_GCLK_ID << GCLK_CLKCTRL_ID_Pos))); - /* TC4 and TC5 share the same channel */ - GCLK->CLKCTRL.reg = (uint16_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | (TC4_GCLK_ID << GCLK_CLKCTRL_ID_Pos))); -#endif - while (GCLK->STATUS.bit.SYNCBUSY) {} - - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - if (TIMER_0_DEV.CTRLA.bit.ENABLE) { - return 0; - } - PM->APBCMASK.reg |= PM_APBCMASK_TC3; - /* reset timer */ - TIMER_0_DEV.CTRLA.bit.SWRST = 1; - while (TIMER_0_DEV.CTRLA.bit.SWRST) {} - /* choosing 16 bit mode */ - TIMER_0_DEV.CTRLA.bit.MODE = TC_CTRLA_MODE_COUNT16_Val; -#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL - /* PLL/DFLL: sourced by 1MHz and prescaler 1 to reach 1MHz */ - TIMER_0_DEV.CTRLA.bit.PRESCALER = TC_CTRLA_PRESCALER_DIV1_Val; -#else - /* sourced by 8MHz with Presc 8 results in 1MHz clk */ - TIMER_0_DEV.CTRLA.bit.PRESCALER = TC_CTRLA_PRESCALER_DIV8_Val; -#endif - /* choose normal frequency operation */ - TIMER_0_DEV.CTRLA.bit.WAVEGEN = TC_CTRLA_WAVEGEN_NFRQ_Val; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - if (TIMER_1_DEV.CTRLA.bit.ENABLE) { - return 0; - } - PM->APBCMASK.reg |= PM_APBCMASK_TC4; - /* reset timer */ - TIMER_1_DEV.CTRLA.bit.SWRST = 1; - - while (TIMER_1_DEV.CTRLA.bit.SWRST) {} - - - TIMER_1_DEV.CTRLA.bit.MODE = TC_CTRLA_MODE_COUNT32_Val; -#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL - /* PLL/DFLL: sourced by 1MHz and prescaler 1 to reach 1MHz */ - TIMER_1_DEV.CTRLA.bit.PRESCALER = TC_CTRLA_PRESCALER_DIV1_Val; -#else - /* sourced by 8MHz with Presc 8 results in 1Mhz clk */ - TIMER_1_DEV.CTRLA.bit.PRESCALER = TC_CTRLA_PRESCALER_DIV8_Val; -#endif - /* choose normal frequency operation */ - TIMER_1_DEV.CTRLA.bit.WAVEGEN = TC_CTRLA_WAVEGEN_NFRQ_Val; - break; -#endif - case TIMER_UNDEFINED: - default: - return -1; - } - - /* save callback */ - config[dev].cb = cb; - config[dev].arg = arg; - - /* enable interrupts for given timer */ - _irq_enable(dev); - - timer_start(dev); - - return 0; -} - -int timer_set_absolute(tim_t dev, int channel, unsigned int value) -{ - DEBUG("Setting timer %i channel %i to %i\n", dev, channel, value); - - /* get timer base register address */ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - /* set timeout value */ - switch (channel) { - case 0: - TIMER_0_DEV.INTFLAG.reg = TC_INTFLAG_MC0; - TIMER_0_DEV.CC[0].reg = value; - TIMER_0_DEV.INTENSET.reg = TC_INTENSET_MC0; - break; - case 1: - TIMER_0_DEV.INTFLAG.reg = TC_INTFLAG_MC1; - TIMER_0_DEV.CC[1].reg = value; - TIMER_0_DEV.INTENSET.reg = TC_INTENSET_MC1; - break; - default: - return -1; - } - break; -#endif -#if TIMER_1_EN - case TIMER_1: - /* set timeout value */ - switch (channel) { - case 0: - TIMER_1_DEV.INTFLAG.reg = TC_INTFLAG_MC0; - TIMER_1_DEV.CC[0].reg = value; - TIMER_1_DEV.INTENSET.reg = TC_INTENSET_MC0; - break; - case 1: - TIMER_1_DEV.INTFLAG.reg = TC_INTFLAG_MC1; - TIMER_1_DEV.CC[1].reg = value; - TIMER_1_DEV.INTENSET.reg = TC_INTENSET_MC1; - break; - default: - return -1; - } - break; -#endif - case TIMER_UNDEFINED: - default: - return -1; - } - - return 1; -} - -int timer_clear(tim_t dev, int channel) -{ - /* get timer base register address */ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - switch (channel) { - case 0: - TIMER_0_DEV.INTFLAG.reg = TC_INTFLAG_MC0; - TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC0; - break; - case 1: - TIMER_0_DEV.INTFLAG.reg = TC_INTFLAG_MC1; - TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC1; - break; - default: - return -1; - } - break; -#endif -#if TIMER_1_EN - case TIMER_1: - switch (channel) { - case 0: - TIMER_1_DEV.INTFLAG.reg = TC_INTFLAG_MC0; - TIMER_1_DEV.INTENCLR.reg = TC_INTENCLR_MC0; - break; - case 1: - TIMER_1_DEV.INTFLAG.reg = TC_INTFLAG_MC1; - TIMER_1_DEV.INTENCLR.reg = TC_INTENCLR_MC1; - break; - default: - return -1; - } - break; -#endif - case TIMER_UNDEFINED: - default: - return -1; - } - - return 1; -} - -unsigned int timer_read(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - /* request syncronisation */ - TIMER_0_DEV.READREQ.reg = TC_READREQ_RREQ | TC_READREQ_ADDR(0x10); - while (TIMER_0_DEV.STATUS.bit.SYNCBUSY) {} - return TIMER_0_DEV.COUNT.reg; -#endif -#if TIMER_1_EN - case TIMER_1: - /* request syncronisation */ - TIMER_1_DEV.READREQ.reg = TC_READREQ_RREQ | TC_READREQ_ADDR(0x10); - while (TIMER_1_DEV.STATUS.bit.SYNCBUSY) {} - return TIMER_1_DEV.COUNT.reg; -#endif - default: - return 0; - } - - -} - -void timer_stop(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - TIMER_0_DEV.CTRLA.bit.ENABLE = 0; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - TIMER_1_DEV.CTRLA.bit.ENABLE = 0; - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -void timer_start(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - TIMER_0_DEV.CTRLA.bit.ENABLE = 1; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - TIMER_1_DEV.CTRLA.bit.ENABLE = 1; - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -static inline void _irq_enable(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - NVIC_EnableIRQ(TC3_IRQn); - break; -#endif -#if TIMER_1_EN - case TIMER_1: - NVIC_EnableIRQ(TC4_IRQn); - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -#if TIMER_0_EN -void TIMER_0_ISR(void) -{ - if (TIMER_0_DEV.INTFLAG.bit.MC0 && TIMER_0_DEV.INTENSET.bit.MC0) { - TIMER_0_DEV.INTFLAG.reg = TC_INTFLAG_MC0; - TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC0; - if(config[TIMER_0].cb) { - config[TIMER_0].cb(config[TIMER_0].arg, 0); - } - } - if (TIMER_0_DEV.INTFLAG.bit.MC1 && TIMER_0_DEV.INTENSET.bit.MC1) { - TIMER_0_DEV.INTFLAG.reg = TC_INTFLAG_MC1; - TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC1; - if(config[TIMER_0].cb) { - config[TIMER_0].cb(config[TIMER_0].arg, 1); - } - } - - cortexm_isr_end(); -} -#endif /* TIMER_0_EN */ - - -#if TIMER_1_EN -void TIMER_1_ISR(void) -{ - if (TIMER_1_DEV.INTFLAG.bit.MC0 && TIMER_1_DEV.INTENSET.bit.MC0) { - TIMER_1_DEV.INTFLAG.reg = TC_INTFLAG_MC0; - TIMER_1_DEV.INTENCLR.reg = TC_INTENCLR_MC0; - if (config[TIMER_1].cb) { - config[TIMER_1].cb(config[TIMER_1].arg, 0); - } - } - if (TIMER_1_DEV.INTFLAG.bit.MC1 && TIMER_1_DEV.INTENSET.bit.MC1) { - TIMER_1_DEV.INTFLAG.reg = TC_INTFLAG_MC1; - TIMER_1_DEV.INTENCLR.reg = TC_INTENCLR_MC1; - if(config[TIMER_1].cb) { - config[TIMER_1].cb(config[TIMER_1].arg, 1); - } - } - - cortexm_isr_end(); -} -#endif /* TIMER_1_EN */ diff --git a/cpu/saml1x/periph/timer.c b/cpu/saml1x/periph/timer.c deleted file mode 100644 index bf0a13f4b1753..0000000000000 --- a/cpu/saml1x/periph/timer.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (C) 2018 Mesotic SAS - * - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_saml1x - * @ingroup drivers_periph_timer - * @{ - * - * @file timer.c - * @brief Low-level timer driver implementation - * - * @author Dylan Laduranty - * - * @} - */ - -#include -#include - -#include "board.h" -#include "cpu.h" - -#include "periph/timer.h" -#include "periph_conf.h" - -#define ENABLE_DEBUG (0) -#include "debug.h" - -/** - * @brief Timer state memory - */ -static timer_isr_ctx_t config[TIMER_NUMOF]; - -/* enable timer interrupts */ -static inline void _irq_enable(tim_t dev); - - -/** - * @brief Setup the given timer - */ -int timer_init(tim_t dev, unsigned long freq, timer_cb_t cb, void *arg) -{ - /* at the moment, the timer can only run at 1MHz */ - if (freq != 1000000ul) { - return -1; - } - /* configure GCLK0 to feed TC0 & TC1*/ - GCLK->PCHCTRL[TC0_GCLK_ID].reg |= GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK0; - while (!(GCLK->PCHCTRL[TC0_GCLK_ID].reg & GCLK_PCHCTRL_CHEN)) {} - - /* select the timer and enable the timer specific peripheral clocks */ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - if (TIMER_0_DEV.CTRLA.bit.ENABLE) { - return 0; - } - MCLK->APBCMASK.reg |= MCLK_APBCMASK_TC0; - /* reset timer */ - TIMER_0_DEV.CTRLA.bit.SWRST = 1; - while (TIMER_0_DEV.SYNCBUSY.bit.SWRST) {} - TIMER_0_DEV.CTRLA.reg |= TC_CTRLA_MODE_COUNT32 | /* choosing 32 bit mode */ - TC_CTRLA_PRESCALER(4) | /* sourced by 4MHz with Presc 4 results in 1MHz*/ - TC_CTRLA_PRESCSYNC_RESYNC; /* initial prescaler resync */ - break; -#endif - case TIMER_UNDEFINED: - default: - return -1; - } - - /* save callback */ - config[dev].cb = cb; - config[dev].arg = arg; - - /* enable interrupts for given timer */ - _irq_enable(dev); - - timer_start(dev); - - return 0; -} - -int timer_set_absolute(tim_t dev, int channel, unsigned int value) -{ - DEBUG("Setting timer %i channel %i to %i\n", dev, channel, value); - - /* get timer base register address */ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - /* set timeout value */ - switch (channel) { - case 0: - TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC0; - TIMER_0_DEV.CC[0].reg = value; - TIMER_0_DEV.INTENSET.bit.MC0 = 1; - break; - case 1: - TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC1; - TIMER_0_DEV.CC[1].reg = value; - TIMER_0_DEV.INTENSET.bit.MC1 = 1; - break; - default: - return -1; - } - break; -#endif - case TIMER_UNDEFINED: - default: - return -1; - } - - return 1; -} - -int timer_clear(tim_t dev, int channel) -{ - /* get timer base register address */ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - switch (channel) { - case 0: - TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC0; - TIMER_0_DEV.INTENCLR.bit.MC0 = 1; - break; - case 1: - TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC1; - TIMER_0_DEV.INTENCLR.bit.MC1 = 1; - break; - default: - return -1; - } - break; -#endif - case TIMER_UNDEFINED: - default: - return -1; - } - - return 1; -} - -unsigned int timer_read(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - /* request syncronisation */ - TIMER_0_DEV.CTRLBSET.bit.CMD = TC_CTRLBSET_CMD_READSYNC_Val; - while (TIMER_0_DEV.SYNCBUSY.bit.CTRLB) { - /* WORKAROUND to prevent being stuck there if timer not init */ - if(!TIMER_0_DEV.CTRLA.bit.ENABLE) { - return 0; - } - } - return TIMER_0_DEV.COUNT.reg; -#endif - default: - return 0; - } - - -} - -void timer_stop(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - TIMER_0_DEV.CTRLA.bit.ENABLE = 0; - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -void timer_start(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - TIMER_0_DEV.CTRLA.bit.ENABLE = 1; - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -static inline void _irq_enable(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - NVIC_EnableIRQ(TC0_IRQn); - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -#if TIMER_0_EN -void TIMER_0_ISR(void) -{ - if (TIMER_0_DEV.INTFLAG.bit.MC0 && TIMER_0_DEV.INTENSET.bit.MC0) { - if(config[TIMER_0].cb) { - TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC0; - TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC0; - config[TIMER_0].cb(config[TIMER_0].arg, 0); - } - } - else if (TIMER_0_DEV.INTFLAG.bit.MC1 && TIMER_0_DEV.INTENSET.bit.MC1) { - if(config[TIMER_0].cb) { - TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC1; - TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC1; - config[TIMER_0].cb(config[TIMER_0].arg, 1); - } - } - cortexm_isr_end(); -} -#endif /* TIMER_0_EN */ diff --git a/cpu/saml21/periph/timer.c b/cpu/saml21/periph/timer.c deleted file mode 100644 index 71449637f5ee3..0000000000000 --- a/cpu/saml21/periph/timer.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (C) 2015 Kaspar Schleiser - * 2015 FreshTemp, LLC. - * 2014 Freie Universität Berlin - * - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_saml21 - * @ingroup drivers_periph_timer - * @{ - * - * @file timer.c - * @brief Low-level timer driver implementation - * - * @author Thomas Eichinger - * @author Kaspar Schleiser - * - * @} - */ - -#include -#include - -#include "board.h" -#include "cpu.h" - -#include "periph/timer.h" -#include "periph_conf.h" - -#define ENABLE_DEBUG (0) -#include "debug.h" - -/** - * @brief Timer state memory - */ -static timer_isr_ctx_t config[TIMER_NUMOF]; - -/* enable timer interrupts */ -static inline void _irq_enable(tim_t dev); - -/** - * @brief Setup the given timer - */ -int timer_init(tim_t dev, unsigned long freq, timer_cb_t cb, void *arg) -{ - /* at the moment, the timer can only run at 1MHz */ - if (freq != 1000000ul) { - return -1; - } - /* configure GCLK0 to feed TC0 & TC1*/; - GCLK->PCHCTRL[TC0_GCLK_ID].reg |= GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK0; - while (!(GCLK->PCHCTRL[TC0_GCLK_ID].reg & GCLK_PCHCTRL_CHEN)) {} - - /* select the timer and enable the timer specific peripheral clocks */ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - if (TIMER_0_DEV.CTRLA.bit.ENABLE) { - return 0; - } - MCLK->APBCMASK.reg |= MCLK_APBCMASK_TC0; - /* reset timer */ - TIMER_0_DEV.CTRLA.bit.SWRST = 1; - while (TIMER_0_DEV.SYNCBUSY.bit.SWRST) {} - TIMER_0_DEV.CTRLA.reg |= TC_CTRLA_MODE_COUNT32 | /* choosing 32 bit mode */ - TC_CTRLA_PRESCALER(4) | /* sourced by 4MHz with Presc 4 results in 1MHz*/ - TC_CTRLA_PRESCSYNC_RESYNC; /* initial prescaler resync */ - break; -#endif - case TIMER_UNDEFINED: - default: - return -1; - } - - /* save callback */ - config[dev].cb = cb; - config[dev].arg = arg; - - /* enable interrupts for given timer */ - _irq_enable(dev); - - timer_start(dev); - - return 0; -} - -int timer_set_absolute(tim_t dev, int channel, unsigned int value) -{ - DEBUG("Setting timer %i channel %i to %i\n", dev, channel, value); - - /* get timer base register address */ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - /* set timeout value */ - switch (channel) { - case 0: - TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC0; - TIMER_0_DEV.CC[0].reg = value; - TIMER_0_DEV.INTENSET.bit.MC0 = 1; - break; - case 1: - TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC1; - TIMER_0_DEV.CC[1].reg = value; - TIMER_0_DEV.INTENSET.bit.MC1 = 1; - break; - default: - return -1; - } - break; -#endif - case TIMER_UNDEFINED: - default: - return -1; - } - - return 1; -} - -int timer_clear(tim_t dev, int channel) -{ - /* get timer base register address */ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - switch (channel) { - case 0: - TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC0; - TIMER_0_DEV.INTENCLR.bit.MC0 = 1; - break; - case 1: - TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC1; - TIMER_0_DEV.INTENCLR.bit.MC1 = 1; - break; - default: - return -1; - } - break; -#endif - case TIMER_UNDEFINED: - default: - return -1; - } - - return 1; -} - -unsigned int timer_read(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - /* request syncronisation */ - TIMER_0_DEV.CTRLBSET.bit.CMD = TC_CTRLBSET_CMD_READSYNC_Val; - while (TIMER_0_DEV.SYNCBUSY.bit.STATUS) {} - return TIMER_0_DEV.COUNT.reg; -#endif - default: - return 0; - } - - -} - -void timer_stop(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - TIMER_0_DEV.CTRLA.bit.ENABLE = 0; - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -void timer_start(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - TIMER_0_DEV.CTRLA.bit.ENABLE = 1; - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -static inline void _irq_enable(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - NVIC_EnableIRQ(TC0_IRQn); - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -#if TIMER_0_EN -void TIMER_0_ISR(void) -{ - if (TIMER_0_DEV.INTFLAG.bit.MC0 && TIMER_0_DEV.INTENSET.bit.MC0) { - if(config[TIMER_0].cb) { - TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC0; - TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC0; - config[TIMER_0].cb(config[TIMER_0].arg, 0); - } - } - else if (TIMER_0_DEV.INTFLAG.bit.MC1 && TIMER_0_DEV.INTENSET.bit.MC1) { - if(config[TIMER_0].cb) { - TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC1; - TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC1; - config[TIMER_0].cb(config[TIMER_0].arg, 1); - } - } - cortexm_isr_end(); -} -#endif /* TIMER_0_EN */