From c7801e466d8a66e0c20773b129f42041f1a85cab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Fri, 16 Mar 2018 09:00:31 +0100 Subject: [PATCH 1/3] kinetis: Refactor RTT driver - Keep counter value between resets - Let kinetis_mcg_init manage the RTC oscillator, to avoid disrupting the core clock in certain configurations - Remove some unnecessary macros for hardware abstraction; all Kinetis CPUs which have an RTC only have a single RTC instance, and the ISRs and hardware registers are named the same way in all Kinetis CPU headers. --- cpu/kinetis/periph/rtt.c | 113 +++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 65 deletions(-) diff --git a/cpu/kinetis/periph/rtt.c b/cpu/kinetis/periph/rtt.c index b7b537062a..4bbf3240d0 100644 --- a/cpu/kinetis/periph/rtt.c +++ b/cpu/kinetis/periph/rtt.c @@ -15,7 +15,7 @@ * * @file * @brief Low-level RTT interface implementation for Freescale Kinetis - * MCUs. Freescale's RTC module is what RIOT calls a Real-Time + * MCUs. NXP's RTC module is what RIOT calls a Real-Time * Timer (RTT), a simple counter which counts seconds; RIOT Real- * Time Clocks (RTC) counts seconds, minutes, hours etc. We provide * an RTT->RTC wrapper layer in a separate file to allow using the @@ -29,16 +29,13 @@ #include #include "cpu.h" +#include "bit.h" #include "periph/rtt.h" #include "periph_conf.h" #define ENABLE_DEBUG (0) #include "debug.h" -#ifndef RTC_LOAD_CAP_BITS -#define RTC_LOAD_CAP_BITS 0 -#endif - typedef struct { rtt_cb_t alarm_cb; /**< callback called from RTC alarm */ void *alarm_arg; /**< argument passed to the callback */ @@ -50,58 +47,58 @@ static rtt_state_t rtt_callback; void rtt_init(void) { - RTC_Type *rtt = RTT_DEV; + /* Enable module clock gate */ + RTC_CLKEN(); - RTT_UNLOCK(); - /* Reset RTC */ - rtt->CR = RTC_CR_SWR_MASK; - /* cppcheck-suppress redundantAssignment - * reset routine */ - rtt->CR = 0; + /* At this point, the CPU core may be clocked by a clock derived from the + * RTC oscillator, avoid touching the oscillator enable bit (OSCE) in RTC_CR */ - if (rtt->SR & RTC_SR_TIF_MASK) { - /* Clear TIF by writing TSR. */ - rtt->TSR = 0; - } - - /* Enable RTC oscillator and non-supervisor mode accesses. */ - /* Enable load capacitance as configured by periph_conf.h */ - rtt->CR = RTC_CR_OSCE_MASK | RTC_CR_SUP_MASK | RTC_LOAD_CAP_BITS; - - /* Clear TAF by writing TAR. */ - rtt->TAR = 0xffffff42; + /* Enable user mode access */ + bit_set32(&RTC->CR, RTC_CR_SUP_SHIFT); /* Disable all RTC interrupts. */ - rtt->IER = 0; + RTC->IER = 0; + + /* The RTC module is only reset on VBAT power on reset, we try to preserve + * the seconds counter between reboots */ + if (RTC->SR & RTC_SR_TIF_MASK) { + /* Time Invalid Flag is set, clear TIF by writing TSR */ + + /* Stop counter to make TSR writable */ + bit_clear32(&RTC->SR, RTC_SR_TCE_SHIFT); + + RTC->TSR = 0; + } + + /* Clear the alarm flag TAF by writing a new alarm target to TAR */ + RTC->TAR = 0xffffffff; + + /* Enable RTC interrupts */ + NVIC_EnableIRQ(RTC_IRQn); rtt_poweron(); } void rtt_set_overflow_cb(rtt_cb_t cb, void *arg) { - RTC_Type *rtt = RTT_DEV; rtt_callback.overflow_cb = cb; rtt_callback.overflow_arg = arg; - rtt->IER |= RTC_IER_TOIE_MASK; + bit_set32(&RTC->IER, RTC_IER_TOIE_SHIFT); } void rtt_clear_overflow_cb(void) { - RTC_Type *rtt = RTT_DEV; - rtt_callback.overflow_cb = NULL; - rtt_callback.overflow_arg = NULL; - rtt->IER &= ~(RTC_IER_TOIE_MASK); + bit_clear32(&RTC->IER, RTC_IER_TOIE_SHIFT); } uint32_t rtt_get_counter(void) { - RTC_Type *rtt = RTT_DEV; uint32_t t; for (int i = 0; i < 3; i++) { /* Read twice to make sure we get a stable reading */ - t = rtt->TSR; + t = RTC->TSR; - if (t == rtt->TSR) { + if (t == RTC->TSR) { return t; } } @@ -111,13 +108,11 @@ uint32_t rtt_get_counter(void) void rtt_set_counter(uint32_t counter) { - RTC_Type *rtt = RTT_DEV; - /* Disable time counter before writing to the timestamp register */ - rtt->SR &= ~RTC_SR_TCE_MASK; - rtt->TSR = counter; + bit_clear32(&RTC->SR, RTC_SR_TCE_SHIFT); + RTC->TSR = counter; /* Enable when done */ - rtt->SR |= RTC_SR_TCE_MASK; + bit_set32(&RTC->SR, RTC_SR_TCE_SHIFT); } @@ -125,71 +120,59 @@ void rtt_set_alarm(uint32_t alarm, rtt_cb_t cb, void *arg) { /* The alarm is triggered when TSR matches TAR, and TSR increments. This * seem counterintuitive as most users expect the alarm to trigger - * immediately when the counter becomes equal to the alarm time. */ - RTC_Type *rtt = RTT_DEV; + * immediately when the counter becomes equal to the alarm time. + * + * Workaround: Set TAF to alarm - 1 + */ /* Disable Timer Alarm Interrupt */ - rtt->IER &= ~(RTC_IER_TAIE_MASK); + bit_clear32(&RTC->IER, RTC_IER_TAIE_SHIFT); - rtt->TAR = alarm - 1; + RTC->TAR = alarm - 1; rtt_callback.alarm_cb = cb; rtt_callback.alarm_arg = arg; /* Enable Timer Alarm Interrupt */ - rtt->IER |= RTC_IER_TAIE_MASK; - - /* Enable RTC interrupts */ - NVIC_SetPriority(RTT_IRQ, RTT_IRQ_PRIO); - NVIC_EnableIRQ(RTT_IRQ); + bit_set32(&RTC->IER, RTC_IER_TAIE_SHIFT); } uint32_t rtt_get_alarm(void) { - RTC_Type *rtt = RTT_DEV; - return rtt->TAR + 1; + return RTC->TAR + 1; } void rtt_clear_alarm(void) { - RTC_Type *rtt = RTT_DEV; - /* Disable Timer Alarm Interrupt */ - rtt->IER &= ~RTC_IER_TAIE_MASK; - rtt->TAR = 0; - rtt_callback.alarm_cb = NULL; - rtt_callback.alarm_arg = NULL; + bit_clear32(&RTC->IER, RTC_IER_TAIE_SHIFT); } /* RTC module has independent power suply. We can not really turn it on/off. */ void rtt_poweron(void) { - RTC_Type *rtt = RTT_DEV; /* Enable Time Counter */ - rtt->SR |= RTC_SR_TCE_MASK; + bit_set32(&RTC->SR, RTC_SR_TCE_SHIFT); } void rtt_poweroff(void) { - RTC_Type *rtt = RTT_DEV; /* Disable Time Counter */ - rtt->SR &= ~RTC_SR_TCE_MASK; + bit_clear32(&RTC->SR, RTC_SR_TCE_SHIFT); } -void RTT_ISR(void) +void isr_rtc(void) { - RTC_Type *rtt = RTT_DEV; - - if (rtt->SR & RTC_SR_TAF_MASK) { + if (RTC->SR & RTC_SR_TAF_MASK) { if (rtt_callback.alarm_cb != NULL) { /* Disable Timer Alarm Interrupt */ - rtt->IER &= ~RTC_IER_TAIE_MASK; + bit_clear32(&RTC->IER, RTC_IER_TAIE_SHIFT); rtt_callback.alarm_cb(rtt_callback.alarm_arg); } } - if (rtt->SR & RTC_SR_TOF_MASK) { + if (RTC->SR & RTC_SR_TOF_MASK) { if (rtt_callback.overflow_cb != NULL) { rtt_callback.overflow_cb(rtt_callback.overflow_arg); } From a6c30ab61d82e8a526881433d181d15a330f39f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Wed, 11 Apr 2018 18:53:24 +0200 Subject: [PATCH 2/3] kinetis: Move RTT config to periph_cpu.h --- boards/frdm-k22f/include/periph_conf.h | 15 -------------- boards/frdm-k64f/include/periph_conf.h | 15 -------------- boards/frdm-kw41z/include/periph_conf.h | 15 -------------- boards/mulle/include/periph_conf.h | 23 +--------------------- boards/pba-d-01-kw2x/include/periph_conf.h | 15 -------------- cpu/kinetis/include/periph_cpu.h | 14 +++++++++++++ 6 files changed, 15 insertions(+), 82 deletions(-) diff --git a/boards/frdm-k22f/include/periph_conf.h b/boards/frdm-k22f/include/periph_conf.h index d028cb307b..ed898ba0dd 100644 --- a/boards/frdm-k22f/include/periph_conf.h +++ b/boards/frdm-k22f/include/periph_conf.h @@ -265,21 +265,6 @@ static const spi_conf_t spi_config[] = { #define I2C_0_PORT_CFG (PORT_PCR_MUX(I2C_0_PIN_AF) | PORT_PCR_ODE_MASK) /** @} */ -/** -* @name RTT and RTC configuration -* @{ -*/ -#define RTT_NUMOF (1U) -#define RTC_NUMOF (1U) -#define RTT_DEV RTC -#define RTT_IRQ RTC_IRQn -#define RTT_IRQ_PRIO 10 -#define RTT_UNLOCK() (SIM->SCGC6 |= (SIM_SCGC6_RTC_MASK)) -#define RTT_ISR isr_rtc -#define RTT_FREQUENCY (1) -#define RTT_MAX_VALUE (0xffffffff) -/** @} */ - #ifdef __cplusplus } #endif diff --git a/boards/frdm-k64f/include/periph_conf.h b/boards/frdm-k64f/include/periph_conf.h index 1f36c6427c..649a37572c 100644 --- a/boards/frdm-k64f/include/periph_conf.h +++ b/boards/frdm-k64f/include/periph_conf.h @@ -259,21 +259,6 @@ static const spi_conf_t spi_config[] = { #define I2C_0_PORT_CFG (PORT_PCR_MUX(I2C_0_PIN_AF) | PORT_PCR_ODE_MASK) /** @} */ -/** -* @name RTT and RTC configuration -* @{ -*/ -#define RTT_NUMOF (1U) -#define RTC_NUMOF (1U) -#define RTT_DEV RTC -#define RTT_IRQ RTC_IRQn -#define RTT_IRQ_PRIO 10 -#define RTT_UNLOCK() (SIM->SCGC6 |= (SIM_SCGC6_RTC_MASK)) -#define RTT_ISR isr_rtc -#define RTT_FREQUENCY (1) -#define RTT_MAX_VALUE (0xffffffff) -/** @} */ - #ifdef __cplusplus } #endif diff --git a/boards/frdm-kw41z/include/periph_conf.h b/boards/frdm-kw41z/include/periph_conf.h index 05feabb1cd..50a93eb138 100644 --- a/boards/frdm-kw41z/include/periph_conf.h +++ b/boards/frdm-kw41z/include/periph_conf.h @@ -286,21 +286,6 @@ static const spi_conf_t spi_config[] = { #define I2C_1_PORT_CFG (PORT_PCR_MUX(I2C_0_PIN_AF)) /** @} */ -/** -* @name RTT and RTC configuration -* @{ -*/ -#define RTT_NUMOF (1U) -#define RTC_NUMOF (1U) -#define RTT_DEV RTC -#define RTT_IRQ RTC_IRQn -#define RTT_IRQ_PRIO 10 -#define RTT_UNLOCK() (bit_set32(&SIM->SCGC6, SIM_SCGC6_RTC_SHIFT)) -#define RTT_ISR isr_rtc -#define RTT_FREQUENCY (1) -#define RTT_MAX_VALUE (0xffffffff) -/** @} */ - /** * @name Random Number Generator configuration * @{ diff --git a/boards/mulle/include/periph_conf.h b/boards/mulle/include/periph_conf.h index 67b98614f8..7a688da8da 100644 --- a/boards/mulle/include/periph_conf.h +++ b/boards/mulle/include/periph_conf.h @@ -115,6 +115,7 @@ static const clock_config_t clock_config = { #define PIT_ISR_0 isr_pit1 #define PIT_ISR_1 isr_pit3 #define LPTMR_ISR_0 isr_lptmr0 + /** @} */ /** @@ -374,28 +375,6 @@ static const spi_conf_t spi_config[] = { #define KINETIS_I2C_F_MULT_FAST_PLUS (0) /** @} */ -/** - * @name RTC configuration - * @{ - */ -/* RIOT RTC implementation uses RTT for underlying timekeeper */ -#define RTC_NUMOF (1U) -/** @} */ - -/** - * @name RTT configuration - * @{ - */ -#define RTT_NUMOF (1U) -#define RTT_IRQ RTC_IRQn -#define RTT_IRQ_PRIO 10 -#define RTT_ISR isr_rtc -#define RTT_DEV RTC -#define RTT_UNLOCK() (BITBAND_REG32(SIM->SCGC6, SIM_SCGC6_RTC_SHIFT) = 1) -#define RTT_MAX_VALUE (0xffffffff) -#define RTT_FREQUENCY (1) /* in Hz */ -/** @} */ - #ifdef __cplusplus } #endif diff --git a/boards/pba-d-01-kw2x/include/periph_conf.h b/boards/pba-d-01-kw2x/include/periph_conf.h index bfb467923e..043f93f024 100644 --- a/boards/pba-d-01-kw2x/include/periph_conf.h +++ b/boards/pba-d-01-kw2x/include/periph_conf.h @@ -289,21 +289,6 @@ static const spi_conf_t spi_config[] = { /** @} */ -/** -* @name RTT and RTC configuration -* @{ -*/ -#define RTT_NUMOF (1U) -#define RTC_NUMOF (1U) -#define RTT_DEV RTC -#define RTT_IRQ RTC_IRQn -#define RTT_IRQ_PRIO 10 -#define RTT_UNLOCK() (SIM->SCGC6 |= (SIM_SCGC6_RTC_MASK)) -#define RTT_ISR isr_rtc -#define RTT_FREQUENCY (1) -#define RTT_MAX_VALUE (0xffffffff) -/** @} */ - #ifdef __cplusplus } #endif diff --git a/cpu/kinetis/include/periph_cpu.h b/cpu/kinetis/include/periph_cpu.h index e7645edcaa..703f82d335 100644 --- a/cpu/kinetis/include/periph_cpu.h +++ b/cpu/kinetis/include/periph_cpu.h @@ -114,6 +114,20 @@ typedef uint16_t gpio_t; */ #define PM_NUM_MODES (1U) +#ifdef RTC +/* All Kinetis CPUs have exactly one RTC hardware module, except for the KL02 + * family which don't have an RTC at all */ +/** + * @name RTT and RTC configuration + * @{ + */ +#define RTT_NUMOF (1U) +#define RTC_NUMOF (1U) +#define RTT_FREQUENCY (1) +#define RTT_MAX_VALUE (0xffffffff) +/** @} */ +#endif + #ifndef DOXYGEN /** * @name GPIO pin modes From 31cf342eac67a637b5515198cc20eedd55a7efb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Wed, 11 Apr 2018 20:37:40 +0200 Subject: [PATCH 3/3] teensy31: Clean up Makefile.features --- boards/teensy31/Makefile.features | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/boards/teensy31/Makefile.features b/boards/teensy31/Makefile.features index acfddffc97..8e732a00a6 100644 --- a/boards/teensy31/Makefile.features +++ b/boards/teensy31/Makefile.features @@ -1,11 +1,13 @@ # Put defined MCU peripherals here (in alphabetical order) -FEATURES_PROVIDED += periph_cpuid -FEATURES_PROVIDED += periph_gpio FEATURES_PROVIDED += periph_pwm +FEATURES_PROVIDED += periph_rtc +FEATURES_PROVIDED += periph_rtt FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart # The board MPU family (used for grouping by the CI system) FEATURES_MCU_GROUP = cortex_m4_2 -include $(RIOTCPU)/cortexm_common/Makefile.features +include $(RIOTCPU)/kinetis/Makefile.features +# No HWRNG in MK20D7 devices +FEATURES_PROVIDED := $(filter-out periph_hwrng,$(FEATURES_PROVIDED))