diff --git a/boards/common/kw41z/Makefile.features b/boards/common/kw41z/Makefile.features index 2967530f7d..bebaefb163 100644 --- a/boards/common/kw41z/Makefile.features +++ b/boards/common/kw41z/Makefile.features @@ -3,8 +3,8 @@ CPU_MODEL = mkw41z512vht4 # Put defined MCU peripherals here (in alphabetical order) FEATURES_PROVIDED += periph_adc -FEATURES_PROVIDED += periph_rtc FEATURES_PROVIDED += periph_rtt +FEATURES_PROVIDED += periph_rtc FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart diff --git a/boards/frdm-kl43z/include/board.h b/boards/frdm-kl43z/include/board.h index 7baf7a6e48..fb714d871a 100644 --- a/boards/frdm-kl43z/include/board.h +++ b/boards/frdm-kl43z/include/board.h @@ -60,7 +60,7 @@ extern "C" * @name xtimer configuration * @{ */ -#if KINETIS_XTIMER_SOURCE_PIT +#if IS_ACTIVE(KINETIS_XTIMER_SOURCE_PIT) /* PIT xtimer configuration */ #define XTIMER_DEV (TIMER_PIT_DEV(0)) #define XTIMER_CHAN (0) diff --git a/boards/frdm-kw41z/include/board.h b/boards/frdm-kw41z/include/board.h index b844b4d82c..414c26f86a 100644 --- a/boards/frdm-kw41z/include/board.h +++ b/boards/frdm-kw41z/include/board.h @@ -72,7 +72,7 @@ extern "C" * @name xtimer configuration * @{ */ -#if KINETIS_XTIMER_SOURCE_PIT +#if IS_ACTIVE(KINETIS_XTIMER_SOURCE_PIT) /* PIT xtimer configuration */ #define XTIMER_DEV (TIMER_PIT_DEV(0)) #define XTIMER_CHAN (0) diff --git a/boards/openlabs-kw41z-mini/include/board.h b/boards/openlabs-kw41z-mini/include/board.h index 5cd4a97940..c1b42768c5 100644 --- a/boards/openlabs-kw41z-mini/include/board.h +++ b/boards/openlabs-kw41z-mini/include/board.h @@ -50,7 +50,7 @@ extern "C" * @name xtimer configuration * @{ */ -#if KINETIS_XTIMER_SOURCE_PIT +#if IS_ACTIVE(KINETIS_XTIMER_SOURCE_PIT) /* PIT xtimer configuration */ #define XTIMER_DEV (TIMER_PIT_DEV(0)) #define XTIMER_CHAN (0) diff --git a/boards/pba-d-01-kw2x/Kconfig b/boards/pba-d-01-kw2x/Kconfig index 366726b6a1..1190752761 100644 --- a/boards/pba-d-01-kw2x/Kconfig +++ b/boards/pba-d-01-kw2x/Kconfig @@ -15,7 +15,6 @@ config BOARD_PBA_D_01_KW2X select HAS_PERIPH_I2C select HAS_PERIPH_PWM select HAS_PERIPH_RTC - select HAS_PERIPH_RTT select HAS_PERIPH_SPI select HAS_PERIPH_TIMER select HAS_PERIPH_UART diff --git a/boards/pba-d-01-kw2x/Makefile.features b/boards/pba-d-01-kw2x/Makefile.features index 6e457f3120..71754e01ec 100644 --- a/boards/pba-d-01-kw2x/Makefile.features +++ b/boards/pba-d-01-kw2x/Makefile.features @@ -9,7 +9,6 @@ FEATURES_PROVIDED += periph_adc FEATURES_PROVIDED += periph_i2c FEATURES_PROVIDED += periph_pwm FEATURES_PROVIDED += periph_rtc -FEATURES_PROVIDED += periph_rtt FEATURES_PROVIDED += periph_spi FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart diff --git a/boards/phynode-kw41z/include/board.h b/boards/phynode-kw41z/include/board.h index ae9932a784..54d9e93459 100644 --- a/boards/phynode-kw41z/include/board.h +++ b/boards/phynode-kw41z/include/board.h @@ -87,7 +87,7 @@ extern "C" * @name xtimer configuration * @{ */ -#if KINETIS_XTIMER_SOURCE_PIT +#if IS_ACTIVE(KINETIS_XTIMER_SOURCE_PIT) /* PIT xtimer configuration */ #define XTIMER_DEV (TIMER_PIT_DEV(0)) #define XTIMER_CHAN (0) diff --git a/boards/usb-kw41z/include/board.h b/boards/usb-kw41z/include/board.h index e08553dd92..0b334c6c43 100644 --- a/boards/usb-kw41z/include/board.h +++ b/boards/usb-kw41z/include/board.h @@ -83,7 +83,7 @@ extern "C" * @name xtimer configuration * @{ */ -#if KINETIS_XTIMER_SOURCE_PIT +#if IS_ACTIVE(KINETIS_XTIMER_SOURCE_PIT) /* PIT xtimer configuration */ #define XTIMER_DEV (TIMER_PIT_DEV(0)) #define XTIMER_CHAN (0) diff --git a/cpu/kinetis/Kconfig b/cpu/kinetis/Kconfig index 40dba05140..85cfac3622 100644 --- a/cpu/kinetis/Kconfig +++ b/cpu/kinetis/Kconfig @@ -11,8 +11,6 @@ config CPU_COMMON_KINETIS select HAS_PERIPH_GPIO select HAS_PERIPH_GPIO_IRQ select HAS_PERIPH_PM - select HAS_PERIPH_RTT_SET_COUNTER - select HAS_PERIPH_RTT_OVERFLOW config CPU_FAM_EA bool diff --git a/cpu/kinetis/Makefile.dep b/cpu/kinetis/Makefile.dep index b16b5c78f7..e5297bd6dc 100644 --- a/cpu/kinetis/Makefile.dep +++ b/cpu/kinetis/Makefile.dep @@ -1,3 +1,6 @@ +ifneq (,$(filter periph_rtt,$(USEMODULE))) + USEMODULE += periph_timer +endif ifneq (,$(filter periph_i2c,$(USEMODULE))) USEMODULE += core_thread_flags endif diff --git a/cpu/kinetis/Makefile.features b/cpu/kinetis/Makefile.features index 70fb8b87ea..33484b682f 100644 --- a/cpu/kinetis/Makefile.features +++ b/cpu/kinetis/Makefile.features @@ -14,8 +14,6 @@ endif FEATURES_PROVIDED += periph_gpio FEATURES_PROVIDED += periph_gpio_irq -FEATURES_PROVIDED += periph_rtt_set_counter -FEATURES_PROVIDED += periph_rtt_overflow # Parse parameters from CPU_MODEL using the kinetis-info.mk script in the same # directory as this Makefile. diff --git a/cpu/kinetis/include/periph_cpu.h b/cpu/kinetis/include/periph_cpu.h index 200ce22d2c..02ac59b0ca 100644 --- a/cpu/kinetis/include/periph_cpu.h +++ b/cpu/kinetis/include/periph_cpu.h @@ -157,18 +157,6 @@ enum { #endif /** @} */ -#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_FREQUENCY (1) -#define RTT_MAX_VALUE (0xffffffff) -/** @} */ -#endif - #ifndef DOXYGEN /** * @name GPIO pin modes @@ -500,6 +488,30 @@ enum { #endif /* KINETIS_HAVE_LPTMR */ /** @} */ +/** + * @name RTT configuration + * @{ + */ +#define RTT_DEV (TIMER_LPTMR_DEV(0)) +#define RTT_MAX_VALUE (0x0000ffff) +#define RTT_CLOCK_FREQUENCY (32768U) /* in Hz */ +#define RTT_MAX_FREQUENCY (32768U) /* in Hz */ +#define RTT_MIN_FREQUENCY (1U) /* in Hz */ +#ifndef RTT_FREQUENCY +#define RTT_FREQUENCY RTT_MAX_FREQUENCY +#endif +#if IS_USED(PERIPH_RTT) +/* On kinetis periph_rtt is built on top on an LPTIMER so if used it + will conflict with xtimer, if a LPTIMER backend and RTT are needed + consider using ztimer */ +#define KINETIS_XTIMER_SOURCE_PIT 1 +#endif +/* When setting a new compare value, the value must be at least 5 more + than the current sleep timer value. Otherwise, the timer compare + event may be lost. */ +/** @} */ + + /** * @brief UART hardware module types */ diff --git a/cpu/kinetis/periph/rtt.c b/cpu/kinetis/periph/rtt.c index c5048d49db..59079f2a38 100644 --- a/cpu/kinetis/periph/rtt.c +++ b/cpu/kinetis/periph/rtt.c @@ -14,13 +14,6 @@ * @{ * * @file - * @brief Low-level RTT interface implementation for Freescale Kinetis - * 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 - * RTT as a system real time clock. - * * @author Johann Fischer * @author Joakim NohlgÄrd * @@ -31,154 +24,62 @@ #include "cpu.h" #include "bit.h" #include "periph/rtt.h" +#include "periph/timer.h" #include "periph_conf.h" #define ENABLE_DEBUG 0 #include "debug.h" -typedef struct { - rtt_cb_t alarm_cb; /**< callback called from RTC alarm */ - void *alarm_arg; /**< argument passed to the callback */ - rtt_cb_t overflow_cb; /**< callback called when RTC overflows */ - void *overflow_arg; /**< argument passed to the callback */ -} rtt_state_t; +static rtt_cb_t alarm_cb = NULL; /**< callback called from RTC alarm */ +static void *alarm_arg; /**< argument passed to the callback */ +static uint32_t alarm_value = 0; -static rtt_state_t rtt_callback; +static void _rtt_cb(void *arg, int channel) +{ + (void) arg; + (void) channel; + if (alarm_cb != NULL) { + alarm_cb(alarm_arg); + } +} void rtt_init(void) { - /* Enable module clock gate */ - RTC_CLKEN(); - - /* 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 */ - - /* Enable user mode access */ - bit_set32(&RTC->CR, RTC_CR_SUP_SHIFT); - - /* Disable all RTC interrupts. */ - 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) -{ - rtt_callback.overflow_cb = cb; - rtt_callback.overflow_arg = arg; - bit_set32(&RTC->IER, RTC_IER_TOIE_SHIFT); -} - -void rtt_clear_overflow_cb(void) -{ - bit_clear32(&RTC->IER, RTC_IER_TOIE_SHIFT); + timer_init(RTT_DEV, RTT_FREQUENCY, _rtt_cb, NULL); + alarm_value = 0; } uint32_t rtt_get_counter(void) { - uint32_t t; - for (int i = 0; i < 3; i++) { - /* Read twice to make sure we get a stable reading */ - t = RTC->TSR; - - if (t == RTC->TSR) { - return t; - } - } - /* Fallback if we are not getting stable readings */ - return t; + return timer_read(RTT_DEV); } -void rtt_set_counter(uint32_t counter) -{ - /* Disable time counter before writing to the timestamp register */ - bit_clear32(&RTC->SR, RTC_SR_TCE_SHIFT); - RTC->TPR = 0; - /* write TSR after TPR, as clearing TPR bit 14 will increment TSR */ - RTC->TSR = counter; - /* Enable when done */ - bit_set32(&RTC->SR, RTC_SR_TCE_SHIFT); -} - - 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. - * - * Workaround: Set TAF to alarm - 1 - */ - - /* Disable Timer Alarm Interrupt */ - bit_clear32(&RTC->IER, RTC_IER_TAIE_SHIFT); - - RTC->TAR = alarm - 1; - - rtt_callback.alarm_cb = cb; - rtt_callback.alarm_arg = arg; - - /* Enable Timer Alarm Interrupt */ - bit_set32(&RTC->IER, RTC_IER_TAIE_SHIFT); + unsigned state = irq_disable(); + alarm_arg = arg; + alarm_cb = cb; + alarm_value = alarm; + timer_set_absolute(RTT_DEV, 0, alarm % RTT_MAX_VALUE); + irq_restore(state); } uint32_t rtt_get_alarm(void) { - return RTC->TAR + 1; + return alarm_value; } void rtt_clear_alarm(void) { - /* Disable Timer Alarm Interrupt */ - bit_clear32(&RTC->IER, RTC_IER_TAIE_SHIFT); + timer_clear(RTT_DEV, 0); } -/* RTC module has independent power suply. We can not really turn it on/off. */ - void rtt_poweron(void) { - /* Enable Time Counter */ - bit_set32(&RTC->SR, RTC_SR_TCE_SHIFT); + timer_start(RTT_DEV); } void rtt_poweroff(void) { - /* Disable Time Counter */ - bit_clear32(&RTC->SR, RTC_SR_TCE_SHIFT); -} - -void isr_rtc(void) -{ - if (RTC->SR & RTC_SR_TAF_MASK) { - if (rtt_callback.alarm_cb != NULL) { - /* Disable Timer Alarm Interrupt */ - bit_clear32(&RTC->IER, RTC_IER_TAIE_SHIFT); - rtt_callback.alarm_cb(rtt_callback.alarm_arg); - } - } - - if (RTC->SR & RTC_SR_TOF_MASK) { - if (rtt_callback.overflow_cb != NULL) { - rtt_callback.overflow_cb(rtt_callback.overflow_arg); - } - } - - cortexm_isr_end(); + timer_stop(RTT_DEV); } diff --git a/tests/periph_rtt/Makefile b/tests/periph_rtt/Makefile index 72bb287f2b..5c70de4683 100644 --- a/tests/periph_rtt/Makefile +++ b/tests/periph_rtt/Makefile @@ -9,7 +9,7 @@ DISABLE_MODULE += periph_init_rtt include $(RIOTBASE)/Makefile.include # Put board specific dependencies here -ifeq (stm32,$(CPU)) +ifneq (,$(filter stm32 kinetis,$(CPU))) ifneq (f1,$(CPU_FAM)) # all stm32% but stm32f1 RTT are based on a 16 bit LPTIM, if using the default # 32768KHz configuration TICKS_TO_WAIT will overflow