From 3c6756556d46ba9349e0b9526c9f5f83e111a080 Mon Sep 17 00:00:00 2001 From: Stephane D'Alu Date: Sat, 6 Feb 2016 02:02:09 +0100 Subject: try to implement tick-less mode --- os/hal/ports/NRF51/NRF51822/st_lld.c | 93 ++++++++++++++++++++++++++++++++++-- os/hal/ports/NRF51/NRF51822/st_lld.h | 66 ++++++++++++++++++++----- 2 files changed, 143 insertions(+), 16 deletions(-) (limited to 'os/hal/ports') diff --git a/os/hal/ports/NRF51/NRF51822/st_lld.c b/os/hal/ports/NRF51/NRF51822/st_lld.c index a43a679..51f942b 100644 --- a/os/hal/ports/NRF51/NRF51822/st_lld.c +++ b/os/hal/ports/NRF51/NRF51822/st_lld.c @@ -31,6 +31,14 @@ /* Driver local definitions. */ /*===========================================================================*/ +#if (OSAL_ST_RESOLUTION == 32) +#define ST_OVERFLOW_VALUE 0xFFFFFFFF +#elif (OSAL_ST_RESOLUTION == 24) +#define ST_OVERFLOW_VALUE 0x00FFFFFF +#elif (OSAL_ST_RESOLUTION == 16) +#define ST_OVERFLOW_VALUE 0x0000FFFF +#endif + /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ @@ -52,7 +60,6 @@ /*===========================================================================*/ #if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__) - #if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC) /** * @brief System Timer vector (RTC0) @@ -98,9 +105,56 @@ OSAL_IRQ_HANDLER(Vector60) { OSAL_IRQ_EPILOGUE(); } #endif - #endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ +#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__) +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC) +/** + * @brief System Timer vector (RTC0) + * @details This interrupt is used for freerunning mode (tick-less) + * if selected with NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector6C) { + + OSAL_IRQ_PROLOGUE(); + + NRF_RTC0->EVENTS_COMPARE[0] = 0; + + osalSysLockFromISR(); + osalOsTimerHandlerI(); + osalSysUnlockFromISR(); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER) +/** + * @brief System Timer vector. (TIMER0) + * @details This interrupt is used for freerunning mode (tick-less) + * if selected with NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector60) { + + OSAL_IRQ_PROLOGUE(); + + /* Clear timer compare event */ + if (NRF_TIMER0->EVENTS_COMPARE[0] != 0) + NRF_TIMER0->EVENTS_COMPARE[0] = 0; + + osalSysLockFromISR(); + osalOsTimerHandlerI(); + osalSysUnlockFromISR(); + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif + /*===========================================================================*/ /* Driver exported functions. */ /*===========================================================================*/ @@ -112,11 +166,43 @@ OSAL_IRQ_HANDLER(Vector60) { */ void st_lld_init(void) { #if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC) + /* Using RTC with prescaler */ + NRF_RTC0->TASKS_STOP = 1; + NRF_RTC0->PRESCALER = (NRF51_LFCLK_FREQUENCY / OSAL_ST_FREQUENCY) - 1; + NRF_RTC0->EVTENCLR = RTC_EVTEN_COMPARE0_Msk; + NRF_RTC0->EVENTS_COMPARE[0] = 0; + + /* Start timer */ + nvicEnableVector(RTC0_IRQn, 8); + NRF_RTC0->TASKS_START = 1; +#endif + +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER) + NRF_TIMER0->TASKS_CLEAR = 1; + /* + * Using 32-bit mode with prescaler 16 configures this + * timer with a 1MHz clock. + */ + NRF_TIMER0->BITMODE = 3; + NRF_TIMER0->PRESCALER = 4; + + /* + * Configure timer 0 compare capture 1 to generate interrupt + * for overflow according to ST_OVERFLOW_VALUE + */ + NRF_TIMER0->CC[0] = (1000000 / OSAL_ST_FREQUENCY) - 1; + NRF_TIMER0->SHORTS = 1; + NRF_TIMER0->INTENSET = 0x10000; + + /* Start timer */ + nvicEnableVector(TIMER0_IRQn, 8); + NRF_TIMER0->TASKS_START = 1; +#endif #endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ #if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC - #if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC) /* Using RTC with prescaler */ NRF_RTC0->TASKS_STOP = 1; @@ -150,7 +236,6 @@ void st_lld_init(void) { nvicEnableVector(TIMER0_IRQn, 8); NRF_TIMER0->TASKS_START = 1; #endif - #endif } diff --git a/os/hal/ports/NRF51/NRF51822/st_lld.h b/os/hal/ports/NRF51/NRF51822/st_lld.h index c62ff2c..3f47a11 100644 --- a/os/hal/ports/NRF51/NRF51822/st_lld.h +++ b/os/hal/ports/NRF51/NRF51822/st_lld.h @@ -27,17 +27,19 @@ #ifndef _ST_LLD_H_ #define _ST_LLD_H_ +#include "halconf.h" + /*===========================================================================*/ /* Driver constants. */ /*===========================================================================*/ /** - * @brief SPI0 interrupt priority level setting. + * @brief System ticks implementer as a timer. */ #define NRF51_SYSTEM_TICKS_AS_TIMER 1 /** - * @brief SPI0 interrupt priority level setting. + * @brief System ticks implementer as an rtc. */ #define NRF51_SYSTEM_TICKS_AS_RTC 2 @@ -64,6 +66,14 @@ #error "NRF51_SYSTEM_TICKS illegal value" #endif +#if defined(CH_CFG_ST_TIMEDELTA) && CH_CFG_ST_TIMEDELTA < 5 +#error "CH_CFG_ST_TIMEDELTA is too low" +#endif + +#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) +#error "Freeruning (tick-less) mode currently not working" +#endif + /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ @@ -96,8 +106,13 @@ extern "C" { * @notapi */ static inline systime_t st_lld_get_counter(void) { - - return (systime_t)0; +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC) + return (systime_t)NRF_RTC0->COUNTER; +#endif +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER) + NRF_TIMER0->TASKS_CAPTURE[1] = 1; + return (systime_t)NRF_TIMER0->CC[1]; +#endif } /** @@ -110,8 +125,16 @@ static inline systime_t st_lld_get_counter(void) { * @notapi */ static inline void st_lld_start_alarm(systime_t abstime) { - - (void)abstime; +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC) + NRF_RTC0->CC[0] = abstime; + NRF_RTC0->EVENTS_COMPARE[0] = 0; + NRF_RTC0->EVTENSET = RTC_EVTEN_COMPARE0_Msk; +#endif +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER) + NRF_TIMER0->CC[0] = abstime; + NRF_TIMER0->EVENTS_COMPARE[0] = 0; + NRF_TIMER0->INTENSET = TIMER_INTENSET_COMPARE0_Msk; +#endif } /** @@ -120,7 +143,14 @@ static inline void st_lld_start_alarm(systime_t abstime) { * @notapi */ static inline void st_lld_stop_alarm(void) { - +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC) + NRF_RTC0->EVTENCLR = RTC_EVTEN_COMPARE0_Msk; + NRF_RTC0->EVENTS_COMPARE[0] = 0; +#endif +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER) + NRF_TIMER0->INTENCLR = TIMER_INTENCLR_COMPARE0_Msk; + NRF_TIMER0->EVENTS_COMPARE[0] = 0; +#endif } /** @@ -131,8 +161,12 @@ static inline void st_lld_stop_alarm(void) { * @notapi */ static inline void st_lld_set_alarm(systime_t abstime) { - - (void)abstime; +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC) + NRF_RTC0->CC[0] = abstime; +#endif +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER) + NRF_TIMER0->CC[0] = abstime; +#endif } /** @@ -143,8 +177,12 @@ static inline void st_lld_set_alarm(systime_t abstime) { * @notapi */ static inline systime_t st_lld_get_alarm(void) { - - return (systime_t)0; +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC) + return (systime_t)NRF_RTC0->CC[0]; +#endif +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER) + return (systime_t)NRF_TIMER0->CC[0]; +#endif } /** @@ -157,8 +195,12 @@ static inline systime_t st_lld_get_alarm(void) { * @notapi */ static inline bool st_lld_is_alarm_active(void) { - +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC) + return NRF_RTC0->EVTEN & RTC_INTENSET_COMPARE0_Msk; +#endif +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER) return false; +#endif } #endif /* _ST_LLD_H_ */ -- cgit v1.2.3