From a3a0be11dc5a81a36fb2b36b37780ea5d733d9fe Mon Sep 17 00:00:00 2001 From: Stephane D'Alu Date: Fri, 5 Feb 2016 18:58:31 +0100 Subject: [PATCH 01/12] moved from HFCLK TIMER to RTC LFCLK --- os/hal/boards/NRF51-DK/board.h | 2 +- os/hal/boards/WVSHARE_BLE400/board.h | 2 +- os/hal/ports/NRF51/NRF51822/hal_lld.c | 29 ++++++++++++++++++++ os/hal/ports/NRF51/NRF51822/hal_lld.h | 4 ++- os/hal/ports/NRF51/NRF51822/st_lld.c | 38 +++++++++------------------ 5 files changed, 47 insertions(+), 28 deletions(-) diff --git a/os/hal/boards/NRF51-DK/board.h b/os/hal/boards/NRF51-DK/board.h index 5e0c7385..abd8f7a2 100644 --- a/os/hal/boards/NRF51-DK/board.h +++ b/os/hal/boards/NRF51-DK/board.h @@ -22,7 +22,7 @@ #define BOARD_NAME "nRF51 DK" /* Board oscillators-related settings. */ -#define XTAL_VALUE 16000000 +#define NRF51_XTAL_VALUE 16000000 /* GPIO pins. */ #define BTN1 17 diff --git a/os/hal/boards/WVSHARE_BLE400/board.h b/os/hal/boards/WVSHARE_BLE400/board.h index 57578b5d..536b7f68 100644 --- a/os/hal/boards/WVSHARE_BLE400/board.h +++ b/os/hal/boards/WVSHARE_BLE400/board.h @@ -22,7 +22,7 @@ #define BOARD_NAME "WvShare BLE400" /* Board oscillators-related settings. */ -#define XTAL_VALUE 16000000 +#define NRF51_XTAL_VALUE 16000000 /* GPIO pins. */ #define KEY1 16 diff --git a/os/hal/ports/NRF51/NRF51822/hal_lld.c b/os/hal/ports/NRF51/NRF51822/hal_lld.c index e1d2ed54..3e74068b 100644 --- a/os/hal/ports/NRF51/NRF51822/hal_lld.c +++ b/os/hal/ports/NRF51/NRF51822/hal_lld.c @@ -55,6 +55,35 @@ */ void hal_lld_init(void) { + /* High frequency clock initialisation + * (If NRF51_XTAL_VALUE is not defined assume its an RC oscillator) + */ +#if defined(NRF51_XTAL_VALUE) +#if NRF51_XTAL_VALUE == 16000000 + NRF_CLOCK->XTALFREQ = 0xFF; +#elif NRF51_XTAL_VALUE == 32000000 + NRF_CLOCK->XTALFREQ = 0x00; +#endif +#endif + NRF_CLOCK->TASKS_HFCLKSTOP = 1; + + /* Low frequency clock initialisation + * If source not specified, use the internal RC (0) which is prefered + * over synthetized clock from the high frequency clock (2) + */ +#if defined(NRF51_LFCLK_SOURCE) +#if (NRF51_LFCLK_SOURCE >=0) && (NRF51_LFCLK_SOURCE <= 2) + NRF_CLOCK->LFCLKSRC = NRF51_LFCLK_SOURCE; +#else +#error "Possible value for NRF51_LFCLK_SOURCE are 0=RC, 1=XTAL, 2=Synth" +#endif +#else + NRF_CLOCK->LFCLKSRC = 0; +#endif + +#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) + NRF_CLOCK->TASKS_LFCLKSTART = 1; +#endif } /** diff --git a/os/hal/ports/NRF51/NRF51822/hal_lld.h b/os/hal/ports/NRF51/NRF51822/hal_lld.h index 1cc9057c..b6856673 100644 --- a/os/hal/ports/NRF51/NRF51822/hal_lld.h +++ b/os/hal/ports/NRF51/NRF51822/hal_lld.h @@ -44,9 +44,11 @@ /*===========================================================================*/ /*===========================================================================*/ -/* Derived constants and error checks. */ +/* Driver constants and error checks. */ /*===========================================================================*/ +#define NRF51_LFCLK_FREQUENCY 32768 + /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ diff --git a/os/hal/ports/NRF51/NRF51822/st_lld.c b/os/hal/ports/NRF51/NRF51822/st_lld.c index 526db35e..d8c7b6c1 100644 --- a/os/hal/ports/NRF51/NRF51822/st_lld.c +++ b/os/hal/ports/NRF51/NRF51822/st_lld.c @@ -52,19 +52,17 @@ #if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__) /** - * @brief System Timer vector. + * @brief System Timer vector (RTC0) * @details This interrupt is used for system tick in periodic mode. * * @isr */ -OSAL_IRQ_HANDLER(Vector60) { +OSAL_IRQ_HANDLER(Vector6C) { OSAL_IRQ_PROLOGUE(); - /* Clear timer compare event */ - if (NRF_TIMER0->EVENTS_COMPARE[0] != 0) - NRF_TIMER0->EVENTS_COMPARE[0] = 0; - + NRF_RTC0->EVENTS_TICK = 0; + osalSysLockFromISR(); osalOsTimerHandlerI(); osalSysUnlockFromISR(); @@ -83,29 +81,19 @@ OSAL_IRQ_HANDLER(Vector60) { * @notapi */ void st_lld_init(void) { +#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) + +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ #if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC - 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 0 to generate interrupt - * and clear timer value when event is generated. - */ - NRF_TIMER0->CC[0] = (1000000 / OSAL_ST_FREQUENCY) - 1; - NRF_TIMER0->SHORTS = 1; - NRF_TIMER0->INTENSET = 0x10000; - - nvicEnableVector(TIMER0_IRQn, 8); + /* Using RTC with prescaler */ + NRF_RTC0->TASKS_STOP = 1; + NRF_RTC0->PRESCALER = (NRF51_LFCLK_FREQUENCY / OSAL_ST_FREQUENCY) - 1; + NRF_RTC0->INTENSET = RTC_INTENSET_TICK_Msk; /* Start timer */ - NRF_TIMER0->TASKS_START = 1; + nvicEnableVector(RTC0_IRQn, 8); + NRF_RTC0->TASKS_START = 1; #endif } From ff98f192c2698f40d84d14bb6a538e79323b72ef Mon Sep 17 00:00:00 2001 From: Stephane D'Alu Date: Fri, 5 Feb 2016 19:00:57 +0100 Subject: [PATCH 02/12] nrf51 has a cristal --- os/hal/boards/NRF51-DK/board.h | 1 + 1 file changed, 1 insertion(+) diff --git a/os/hal/boards/NRF51-DK/board.h b/os/hal/boards/NRF51-DK/board.h index abd8f7a2..04c8dafa 100644 --- a/os/hal/boards/NRF51-DK/board.h +++ b/os/hal/boards/NRF51-DK/board.h @@ -23,6 +23,7 @@ /* Board oscillators-related settings. */ #define NRF51_XTAL_VALUE 16000000 +#define NRF51_LFCLK_SOURCE 1 /* GPIO pins. */ #define BTN1 17 From 80af295f27f0fc5daaaea04cb249d3ad3704d338 Mon Sep 17 00:00:00 2001 From: Stephane D'Alu Date: Fri, 5 Feb 2016 19:03:47 +0100 Subject: [PATCH 03/12] start by a stop --- os/hal/ports/NRF51/NRF51822/hal_lld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/os/hal/ports/NRF51/NRF51822/hal_lld.c b/os/hal/ports/NRF51/NRF51822/hal_lld.c index 3e74068b..30fe6c09 100644 --- a/os/hal/ports/NRF51/NRF51822/hal_lld.c +++ b/os/hal/ports/NRF51/NRF51822/hal_lld.c @@ -58,6 +58,7 @@ void hal_lld_init(void) /* High frequency clock initialisation * (If NRF51_XTAL_VALUE is not defined assume its an RC oscillator) */ + NRF_CLOCK->TASKS_HFCLKSTOP = 1; #if defined(NRF51_XTAL_VALUE) #if NRF51_XTAL_VALUE == 16000000 NRF_CLOCK->XTALFREQ = 0xFF; @@ -65,7 +66,6 @@ void hal_lld_init(void) NRF_CLOCK->XTALFREQ = 0x00; #endif #endif - NRF_CLOCK->TASKS_HFCLKSTOP = 1; /* Low frequency clock initialisation * If source not specified, use the internal RC (0) which is prefered From 8fe62a0f907639db23f14d17a45a7970854f1d22 Mon Sep 17 00:00:00 2001 From: Stephane D'Alu Date: Fri, 5 Feb 2016 23:54:23 +0100 Subject: [PATCH 04/12] use mcuconf.h with NRF51_SYSTEM_TICKS to select the timer source (TIMER or RTC) --- os/hal/ports/NRF51/NRF51822/hal_lld.c | 16 +++----- os/hal/ports/NRF51/NRF51822/hal_lld.h | 24 ++++++++++- os/hal/ports/NRF51/NRF51822/st_lld.c | 58 ++++++++++++++++++++++++++- os/hal/ports/NRF51/NRF51822/st_lld.h | 25 ++++++++++++ 4 files changed, 109 insertions(+), 14 deletions(-) diff --git a/os/hal/ports/NRF51/NRF51822/hal_lld.c b/os/hal/ports/NRF51/NRF51822/hal_lld.c index 30fe6c09..af5e377e 100644 --- a/os/hal/ports/NRF51/NRF51822/hal_lld.c +++ b/os/hal/ports/NRF51/NRF51822/hal_lld.c @@ -66,22 +66,16 @@ void hal_lld_init(void) NRF_CLOCK->XTALFREQ = 0x00; #endif #endif + /* Low frequency clock initialisation - * If source not specified, use the internal RC (0) which is prefered - * over synthetized clock from the high frequency clock (2) + * Clock is only started if st driver requires it */ -#if defined(NRF51_LFCLK_SOURCE) -#if (NRF51_LFCLK_SOURCE >=0) && (NRF51_LFCLK_SOURCE <= 2) + NRF_CLOCK->TASKS_LFCLKSTOP = 1; NRF_CLOCK->LFCLKSRC = NRF51_LFCLK_SOURCE; -#else -#error "Possible value for NRF51_LFCLK_SOURCE are 0=RC, 1=XTAL, 2=Synth" -#endif -#else - NRF_CLOCK->LFCLKSRC = 0; -#endif -#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) +#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) && \ + (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC) NRF_CLOCK->TASKS_LFCLKSTART = 1; #endif } diff --git a/os/hal/ports/NRF51/NRF51822/hal_lld.h b/os/hal/ports/NRF51/NRF51822/hal_lld.h index b6856673..24eff214 100644 --- a/os/hal/ports/NRF51/NRF51822/hal_lld.h +++ b/os/hal/ports/NRF51/NRF51822/hal_lld.h @@ -39,15 +39,35 @@ * @} */ +/** + * @brief Frequency valuefor the Low Frequency Clock + */ +#define NRF51_LFCLK_FREQUENCY 32768 + /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ +/** + * @brief Select source of Low Frequency Clock (LFCLK) + * @details Possible values for source are: + * 0 : RC oscillator + * 1 : External cristal + * 2 : Synthetized clock from High Frequency Clock (HFCLK) + * When cristal is not available it's preferable to use the + * internal RC oscillator that synthezing the clock. + */ +#if !defined(NRF51_LFCLK_SOURCE) || defined(__DOXYGEN__) +#define NRF51_LFCLK_SOURCE 0 +#endif + /*===========================================================================*/ -/* Driver constants and error checks. */ +/* Derived constants and error checks. */ /*===========================================================================*/ -#define NRF51_LFCLK_FREQUENCY 32768 +#if (NRF51_LFCLK_SOURCE < 0) || (NRF51_LFCLK_SOURCE > 2) +#error "Possible value for NRF51_LFCLK_SOURCE are 0=RC, 1=XTAL, 2=Synth" +#endif /*===========================================================================*/ /* Driver data structures and types. */ diff --git a/os/hal/ports/NRF51/NRF51822/st_lld.c b/os/hal/ports/NRF51/NRF51822/st_lld.c index d8c7b6c1..a43a679d 100644 --- a/os/hal/ports/NRF51/NRF51822/st_lld.c +++ b/os/hal/ports/NRF51/NRF51822/st_lld.c @@ -1,5 +1,6 @@ /* ChibiOS - Copyright (C) 2015 Fabio Utzig + 2016 Stephane D'Alu Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -51,9 +52,12 @@ /*===========================================================================*/ #if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__) + +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC) /** * @brief System Timer vector (RTC0) - * @details This interrupt is used for system tick in periodic mode. + * @details This interrupt is used for system tick in periodic mode + * if selected with NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC * * @isr */ @@ -69,6 +73,32 @@ OSAL_IRQ_HANDLER(Vector6C) { OSAL_IRQ_EPILOGUE(); } +#endif + +#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER) +/** + * @brief System Timer vector. (TIMER0) + * @details This interrupt is used for system tick in periodic mode + * 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 /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ /*===========================================================================*/ @@ -86,6 +116,8 @@ void st_lld_init(void) { #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; NRF_RTC0->PRESCALER = (NRF51_LFCLK_FREQUENCY / OSAL_ST_FREQUENCY) - 1; @@ -96,6 +128,30 @@ void st_lld_init(void) { 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 0 to generate interrupt + * and clear timer value when event is generated. + */ + 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 } #endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */ diff --git a/os/hal/ports/NRF51/NRF51822/st_lld.h b/os/hal/ports/NRF51/NRF51822/st_lld.h index 2e0672ef..c62ff2ca 100644 --- a/os/hal/ports/NRF51/NRF51822/st_lld.h +++ b/os/hal/ports/NRF51/NRF51822/st_lld.h @@ -31,14 +31,39 @@ /* Driver constants. */ /*===========================================================================*/ +/** + * @brief SPI0 interrupt priority level setting. + */ +#define NRF51_SYSTEM_TICKS_AS_TIMER 1 + +/** + * @brief SPI0 interrupt priority level setting. + */ +#define NRF51_SYSTEM_TICKS_AS_RTC 2 + /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ +/** + * @brief Select the method to generates system ticks + * @details Possibles values are: + * NRF51_SYSTEM_TICKS_AS_TIMER for TIMER0 + * NRF51_SYSTEM_TICKS_AS_RTC for RTC0 + */ +#if !defined(NRF51_SYSTEM_TICKS) || defined(__DOXYGEN__) +#define NRF51_SYSTEM_TICKS NRF51_SYSTEM_TICKS_AS_RTC +#endif + /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ +#if ((NRF51_SYSTEM_TICKS != NRF51_SYSTEM_TICKS_AS_RTC) && \ + (NRF51_SYSTEM_TICKS != NRF51_SYSTEM_TICKS_AS_TIMER)) +#error "NRF51_SYSTEM_TICKS illegal value" +#endif + /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ From 3c6756556d46ba9349e0b9526c9f5f83e111a080 Mon Sep 17 00:00:00 2001 From: Stephane D'Alu Date: Sat, 6 Feb 2016 02:02:09 +0100 Subject: [PATCH 05/12] 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(-) diff --git a/os/hal/ports/NRF51/NRF51822/st_lld.c b/os/hal/ports/NRF51/NRF51822/st_lld.c index a43a679d..51f942bb 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 c62ff2ca..3f47a115 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_ */ From 90800edb90ad0fcf8e7f53e5d32a4df9a0c62c6c Mon Sep 17 00:00:00 2001 From: Stephane D'Alu Date: Sat, 6 Feb 2016 02:15:26 +0100 Subject: [PATCH 06/12] fixed tickless for RTC, removed it for TIMER --- os/hal/ports/NRF51/NRF51822/st_lld.c | 48 +--------------------------- os/hal/ports/NRF51/NRF51822/st_lld.h | 45 ++++---------------------- 2 files changed, 7 insertions(+), 86 deletions(-) diff --git a/os/hal/ports/NRF51/NRF51822/st_lld.c b/os/hal/ports/NRF51/NRF51822/st_lld.c index 51f942bb..e3ae3f24 100644 --- a/os/hal/ports/NRF51/NRF51822/st_lld.c +++ b/os/hal/ports/NRF51/NRF51822/st_lld.c @@ -129,30 +129,6 @@ OSAL_IRQ_HANDLER(Vector6C) { 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 /*===========================================================================*/ @@ -172,34 +148,12 @@ void st_lld_init(void) { NRF_RTC0->PRESCALER = (NRF51_LFCLK_FREQUENCY / OSAL_ST_FREQUENCY) - 1; NRF_RTC0->EVTENCLR = RTC_EVTEN_COMPARE0_Msk; NRF_RTC0->EVENTS_COMPARE[0] = 0; + NRF_RTC0->INTENSET = RTC_INTENSET_COMPARE0_Msk; /* 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 diff --git a/os/hal/ports/NRF51/NRF51822/st_lld.h b/os/hal/ports/NRF51/NRF51822/st_lld.h index 3f47a115..412f4fd2 100644 --- a/os/hal/ports/NRF51/NRF51822/st_lld.h +++ b/os/hal/ports/NRF51/NRF51822/st_lld.h @@ -70,8 +70,9 @@ #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" +#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) && \ + (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER) +#error "Freeruning (tick-less) mode not supported with TIMER, use RTC" #endif /*===========================================================================*/ @@ -106,13 +107,7 @@ extern "C" { * @notapi */ static inline systime_t st_lld_get_counter(void) { -#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 } /** @@ -125,16 +120,9 @@ static inline systime_t st_lld_get_counter(void) { * @notapi */ static inline void st_lld_start_alarm(systime_t 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 + NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; } /** @@ -143,14 +131,8 @@ 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->EVTENCLR = RTC_EVTENCLR_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 } /** @@ -161,12 +143,7 @@ static inline void st_lld_stop_alarm(void) { * @notapi */ static inline void st_lld_set_alarm(systime_t 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 } /** @@ -177,12 +154,7 @@ static inline void st_lld_set_alarm(systime_t abstime) { * @notapi */ static inline systime_t st_lld_get_alarm(void) { -#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 } /** @@ -195,12 +167,7 @@ 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 + return NRF_RTC0->EVTEN & RTC_EVTEN_COMPARE0_Msk; } #endif /* _ST_LLD_H_ */ From f35c8058efe554ea6adb243baf0737220b65759e Mon Sep 17 00:00:00 2001 From: Stephane D'Alu Date: Sat, 6 Feb 2016 02:41:50 +0100 Subject: [PATCH 07/12] deal with 16bits systime_t --- os/hal/ports/NRF51/NRF51822/st_lld.c | 38 +++++++++++++++++----------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/os/hal/ports/NRF51/NRF51822/st_lld.c b/os/hal/ports/NRF51/NRF51822/st_lld.c index e3ae3f24..e144a11f 100644 --- a/os/hal/ports/NRF51/NRF51822/st_lld.c +++ b/os/hal/ports/NRF51/NRF51822/st_lld.c @@ -31,14 +31,6 @@ /* 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. */ /*===========================================================================*/ @@ -120,12 +112,21 @@ OSAL_IRQ_HANDLER(Vector6C) { OSAL_IRQ_PROLOGUE(); - NRF_RTC0->EVENTS_COMPARE[0] = 0; + if (NRF_RTC0->EVENTS_COMPARE[0]) { + NRF_RTC0->EVENTS_COMPARE[0] = 0; - osalSysLockFromISR(); - osalOsTimerHandlerI(); - osalSysUnlockFromISR(); + osalSysLockFromISR(); + osalOsTimerHandlerI(); + osalSysUnlockFromISR(); + } +#if OSAL_ST_RESOLUTION == 16 + if (NRF_RTC0->EVENTS_COMPARE[1]) { + NRF_RTC0->EVENTS_COMPARE[1] = 0; + NRF_RTC0->TASKS_CLEAR = 1; + } +#endif + OSAL_IRQ_EPILOGUE(); } #endif @@ -146,11 +147,18 @@ void st_lld_init(void) { /* 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->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk; NRF_RTC0->EVENTS_COMPARE[0] = 0; NRF_RTC0->INTENSET = RTC_INTENSET_COMPARE0_Msk; - - /* Start timer */ +#if OSAL_ST_RESOLUTION == 16 + NRF_RTC0->CC[1] = 0x10000; /* 2^16 */ + NRF_RTC0->EVENTS_COMPARE[1] = 0; + NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; + NRF_RTC0->INTENSET = RTC_INTENSET_COMPARE1_Msk; +#endif + NRF_RTC0->TASKS_CLEAR = 1; + + /* Start timer */ nvicEnableVector(RTC0_IRQn, 8); NRF_RTC0->TASKS_START = 1; #endif From 3679d705391bf29fa4d4d6b140cf2bf64d84456c Mon Sep 17 00:00:00 2001 From: Stephane D'Alu Date: Sat, 6 Feb 2016 02:44:52 +0100 Subject: [PATCH 08/12] fixed compile time error detection for deltatime --- os/hal/ports/NRF51/NRF51822/st_lld.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/os/hal/ports/NRF51/NRF51822/st_lld.h b/os/hal/ports/NRF51/NRF51822/st_lld.h index 412f4fd2..54f7aae8 100644 --- a/os/hal/ports/NRF51/NRF51822/st_lld.h +++ b/os/hal/ports/NRF51/NRF51822/st_lld.h @@ -66,14 +66,14 @@ #error "NRF51_SYSTEM_TICKS illegal value" #endif -#if defined(CH_CFG_ST_TIMEDELTA) && CH_CFG_ST_TIMEDELTA < 5 +#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING +#if CH_CFG_ST_TIMEDELTA < 5 #error "CH_CFG_ST_TIMEDELTA is too low" #endif - -#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) && \ - (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER) +#if NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER #error "Freeruning (tick-less) mode not supported with TIMER, use RTC" #endif +#endif /*===========================================================================*/ /* Driver data structures and types. */ From bc3392813c17492dc848fff798283a677cf5b495 Mon Sep 17 00:00:00 2001 From: Stephane D'Alu Date: Sat, 6 Feb 2016 13:32:45 +0100 Subject: [PATCH 09/12] protect ChibiOS specific sanity check --- os/hal/ports/NRF51/NRF51822/st_lld.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/os/hal/ports/NRF51/NRF51822/st_lld.h b/os/hal/ports/NRF51/NRF51822/st_lld.h index 54f7aae8..c6cf201e 100644 --- a/os/hal/ports/NRF51/NRF51822/st_lld.h +++ b/os/hal/ports/NRF51/NRF51822/st_lld.h @@ -67,7 +67,7 @@ #endif #if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING -#if CH_CFG_ST_TIMEDELTA < 5 +#if defined(CH_CFG_ST_TIMEDELTA) && (CH_CFG_ST_TIMEDELTA < 5) #error "CH_CFG_ST_TIMEDELTA is too low" #endif #if NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER From ed35ba38183776a0864e094c78660414c26c93a9 Mon Sep 17 00:00:00 2001 From: Stephane D'Alu Date: Sat, 6 Feb 2016 15:16:48 +0100 Subject: [PATCH 10/12] exclude TIMER0 from GPT if already used for system ticks --- os/hal/ports/NRF51/NRF51822/gpt_lld.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/os/hal/ports/NRF51/NRF51822/gpt_lld.h b/os/hal/ports/NRF51/NRF51822/gpt_lld.h index d707cda8..0e3b5444 100644 --- a/os/hal/ports/NRF51/NRF51822/gpt_lld.h +++ b/os/hal/ports/NRF51/NRF51822/gpt_lld.h @@ -94,7 +94,12 @@ #if !NRF51_GPT_USE_TIMER0 && !NRF51_GPT_USE_TIMER1 && \ !NRF51_GPT_USE_TIMER2 -#error "GPT driver activated but no TIM peripheral assigned" +#error "GPT driver activated but no TIMER peripheral assigned" +#endif + +#if (NRF51_GPT_USE_TIMER0 == TRUE) && \ + (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER) +#error "GPT driver can't use TIMER0 as currently used by ST driver" #endif #if 0 From a1c71cd5a081de9573a184e2a9379d6b47f4fde8 Mon Sep 17 00:00:00 2001 From: Stephane D'Alu Date: Sun, 14 Feb 2016 16:09:37 +0100 Subject: [PATCH 11/12] st handle compile-tie error checking instead of gpt, as gpt is included first --- os/hal/ports/NRF51/NRF51822/gpt_lld.h | 5 ----- os/hal/ports/NRF51/NRF51822/st_lld.h | 9 ++++++++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/os/hal/ports/NRF51/NRF51822/gpt_lld.h b/os/hal/ports/NRF51/NRF51822/gpt_lld.h index 0e3b5444..2c84d6cf 100644 --- a/os/hal/ports/NRF51/NRF51822/gpt_lld.h +++ b/os/hal/ports/NRF51/NRF51822/gpt_lld.h @@ -97,11 +97,6 @@ #error "GPT driver activated but no TIMER peripheral assigned" #endif -#if (NRF51_GPT_USE_TIMER0 == TRUE) && \ - (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER) -#error "GPT driver can't use TIMER0 as currently used by ST driver" -#endif - #if 0 #if NRF51_GPT_USE_TIMER0 && \ !OSAL_IRQ_IS_VALID_PRIORITY(NRF51_GPT_TIMER0_IRQ_PRIORITY) diff --git a/os/hal/ports/NRF51/NRF51822/st_lld.h b/os/hal/ports/NRF51/NRF51822/st_lld.h index c6cf201e..54dabda0 100644 --- a/os/hal/ports/NRF51/NRF51822/st_lld.h +++ b/os/hal/ports/NRF51/NRF51822/st_lld.h @@ -61,7 +61,14 @@ /* Derived constants and error checks. */ /*===========================================================================*/ -#if ((NRF51_SYSTEM_TICKS != NRF51_SYSTEM_TICKS_AS_RTC) && \ +#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) +#if (NRF51_GPT_USE_TIMER0 == TRUE) && \ + (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER) +#error "TIMER0 already used by GPT driver" +#endif +#endif + +#if ((NRF51_SYSTEM_TICKS != NRF51_SYSTEM_TICKS_AS_RTC) && \ (NRF51_SYSTEM_TICKS != NRF51_SYSTEM_TICKS_AS_TIMER)) #error "NRF51_SYSTEM_TICKS illegal value" #endif From 5ef170def22f5327f3c8252799e9f499eb50e5a6 Mon Sep 17 00:00:00 2001 From: Stephane D'Alu Date: Sun, 14 Feb 2016 17:53:22 +0100 Subject: [PATCH 12/12] Now ST can also use RTC1. Added NRF51_ST_PRIORITY for interrupts. Default values are changed if SOFTDEVICE_PRESENT is defined --- os/hal/ports/NRF51/NRF51822/st_lld.c | 120 ++++++++++++++++++++++---- os/hal/ports/NRF51/NRF51822/st_lld.h | 124 +++++++++++++++++++++------ 2 files changed, 203 insertions(+), 41 deletions(-) diff --git a/os/hal/ports/NRF51/NRF51822/st_lld.c b/os/hal/ports/NRF51/NRF51822/st_lld.c index e144a11f..f65117b2 100644 --- a/os/hal/ports/NRF51/NRF51822/st_lld.c +++ b/os/hal/ports/NRF51/NRF51822/st_lld.c @@ -52,11 +52,11 @@ /*===========================================================================*/ #if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__) -#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC) +#if NRF51_ST_USE_RTC0 == TRUE /** * @brief System Timer vector (RTC0) * @details This interrupt is used for system tick in periodic mode - * if selected with NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC + * if selected with NRF51_ST_USE_RTC0 * * @isr */ @@ -74,11 +74,33 @@ OSAL_IRQ_HANDLER(Vector6C) { } #endif -#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER) +#if NRF51_ST_USE_RTC1 == TRUE +/** + * @brief System Timer vector (RTC1) + * @details This interrupt is used for system tick in periodic mode + * if selected with NRF51_ST_USE_RTC1 + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector84) { + + OSAL_IRQ_PROLOGUE(); + + NRF_RTC1->EVENTS_TICK = 0; + + osalSysLockFromISR(); + osalOsTimerHandlerI(); + osalSysUnlockFromISR(); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if NRF51_ST_USE_TIMER0 == TRUE /** * @brief System Timer vector. (TIMER0) * @details This interrupt is used for system tick in periodic mode - * if selected with NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER + * if selected with NRF51_ST_USE_TIMER0 * * @isr */ @@ -100,11 +122,11 @@ OSAL_IRQ_HANDLER(Vector60) { #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) +#if NRF51_ST_USE_RTC0 == TRUE /** * @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 + * if selected with NRF51_ST_USE_RTC0 * * @isr */ @@ -130,7 +152,38 @@ OSAL_IRQ_HANDLER(Vector6C) { OSAL_IRQ_EPILOGUE(); } #endif + +#if NRF51_ST_USE_RTC1 == TRUE +/** + * @brief System Timer vector (RTC1) + * @details This interrupt is used for freerunning mode (tick-less) + * if selected with NRF51_ST_USE_RTC1 + * + * @isr + */ +OSAL_IRQ_HANDLER(Vector84) { + + OSAL_IRQ_PROLOGUE(); + + if (NRF_RTC1->EVENTS_COMPARE[0]) { + NRF_RTC1->EVENTS_COMPARE[0] = 0; + + osalSysLockFromISR(); + osalOsTimerHandlerI(); + osalSysUnlockFromISR(); + } + +#if OSAL_ST_RESOLUTION == 16 + if (NRF_RTC1->EVENTS_COMPARE[1]) { + NRF_RTC1->EVENTS_COMPARE[1] = 0; + NRF_RTC1->TASKS_CLEAR = 1; + } #endif + + OSAL_IRQ_EPILOGUE(); +} +#endif +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ /*===========================================================================*/ /* Driver exported functions. */ @@ -142,8 +195,9 @@ OSAL_IRQ_HANDLER(Vector6C) { * @notapi */ void st_lld_init(void) { -#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) -#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_RTC) +#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING + +#if NRF51_ST_USE_RTC0 == TRUE /* Using RTC with prescaler */ NRF_RTC0->TASKS_STOP = 1; NRF_RTC0->PRESCALER = (NRF51_LFCLK_FREQUENCY / OSAL_ST_FREQUENCY) - 1; @@ -159,24 +213,57 @@ void st_lld_init(void) { NRF_RTC0->TASKS_CLEAR = 1; /* Start timer */ - nvicEnableVector(RTC0_IRQn, 8); + nvicEnableVector(RTC0_IRQn, NRF51_ST_PRIORITY); NRF_RTC0->TASKS_START = 1; +#endif /* NRF51_ST_USE_RTC0 == TRUE */ + +#if NRF51_ST_USE_RTC1 == TRUE + /* Using RTC with prescaler */ + NRF_RTC1->TASKS_STOP = 1; + NRF_RTC1->PRESCALER = (NRF51_LFCLK_FREQUENCY / OSAL_ST_FREQUENCY) - 1; + NRF_RTC1->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk; + NRF_RTC1->EVENTS_COMPARE[0] = 0; + NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk; +#if OSAL_ST_RESOLUTION == 16 + NRF_RTC1->CC[1] = 0x10000; /* 2^16 */ + NRF_RTC1->EVENTS_COMPARE[1] = 0; + NRF_RTC1->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; + NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE1_Msk; #endif + NRF_RTC1->TASKS_CLEAR = 1; + + /* Start timer */ + nvicEnableVector(RTC1_IRQn, NRF51_ST_PRIORITY); + NRF_RTC1->TASKS_START = 1; +#endif /* NRF51_ST_USE_RTC1 == TRUE */ + #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) + +#if NRF51_ST_USE_RTC0 == TRUE /* Using RTC with prescaler */ NRF_RTC0->TASKS_STOP = 1; NRF_RTC0->PRESCALER = (NRF51_LFCLK_FREQUENCY / OSAL_ST_FREQUENCY) - 1; NRF_RTC0->INTENSET = RTC_INTENSET_TICK_Msk; /* Start timer */ - nvicEnableVector(RTC0_IRQn, 8); + nvicEnableVector(RTC0_IRQn, NRF51_ST_PRIORITY); NRF_RTC0->TASKS_START = 1; -#endif +#endif /* NRF51_ST_USE_RTC0 == TRUE */ -#if (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER) +#if NRF51_ST_USE_RTC1 == TRUE + /* Using RTC with prescaler */ + NRF_RTC1->TASKS_STOP = 1; + NRF_RTC1->PRESCALER = (NRF51_LFCLK_FREQUENCY / OSAL_ST_FREQUENCY) - 1; + NRF_RTC1->INTENSET = RTC_INTENSET_TICK_Msk; + + /* Start timer */ + nvicEnableVector(RTC1_IRQn, NRF51_ST_PRIORITY); + NRF_RTC1->TASKS_START = 1; +#endif /* NRF51_ST_USE_RTC1 == TRUE */ + +#if NRF51_ST_USE_TIMER0 == TRUE NRF_TIMER0->TASKS_CLEAR = 1; /* @@ -195,10 +282,11 @@ void st_lld_init(void) { NRF_TIMER0->INTENSET = 0x10000; /* Start timer */ - nvicEnableVector(TIMER0_IRQn, 8); + nvicEnableVector(TIMER0_IRQn, NRF51_ST_PRIORITY); NRF_TIMER0->TASKS_START = 1; -#endif -#endif +#endif /* NRF51_ST_USE_TIMER0 == TRUE */ + +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ } #endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */ diff --git a/os/hal/ports/NRF51/NRF51822/st_lld.h b/os/hal/ports/NRF51/NRF51822/st_lld.h index 54dabda0..ab25dbb4 100644 --- a/os/hal/ports/NRF51/NRF51822/st_lld.h +++ b/os/hal/ports/NRF51/NRF51822/st_lld.h @@ -33,54 +33,95 @@ /* Driver constants. */ /*===========================================================================*/ -/** - * @brief System ticks implementer as a timer. - */ -#define NRF51_SYSTEM_TICKS_AS_TIMER 1 - -/** - * @brief System ticks implementer as an rtc. - */ -#define NRF51_SYSTEM_TICKS_AS_RTC 2 - /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ /** - * @brief Select the method to generates system ticks - * @details Possibles values are: - * NRF51_SYSTEM_TICKS_AS_TIMER for TIMER0 - * NRF51_SYSTEM_TICKS_AS_RTC for RTC0 + * @brief Use RTC0 to generates system ticks */ -#if !defined(NRF51_SYSTEM_TICKS) || defined(__DOXYGEN__) -#define NRF51_SYSTEM_TICKS NRF51_SYSTEM_TICKS_AS_RTC +#if !defined(NRF51_ST_USE_RTC0) || defined(__DOXYGEN__) +#if !defined(SOFTDEVICE_PRESENT) +#define NRF51_ST_USE_RTC0 TRUE +#else +#define NRF51_ST_USE_RTC0 FALSE +#endif +#endif + +/** + * @brief Use RTC1 to generates system ticks + */ +#if !defined(NRF51_ST_USE_RTC1) || defined(__DOXYGEN__) +#if !defined(SOFTDEVICE_PRESENT) +#define NRF51_ST_USE_RTC1 FALSE +#else +#define NRF51_ST_USE_RTC1 TRUE +#endif +#endif + +/** + * @brief Use TIMER0 to generates system ticks + */ +#if !defined(NRF51_ST_USE_TIMER0) || defined(__DOXYGEN__) +#define NRF51_ST_USE_TIMER0 FALSE +#endif + +/** + * @brief ST interrupt priority level setting. + */ +#if !defined(NRF51_ST_PRIORITY) || defined(__DOXYGEN__) +#if !defined(SOFTDEVICE_PRESENT) +#define NRF51_ST_PRIORITY 8 +#else +#define NRF51_ST_PRIORITY 1 +#endif #endif /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ -#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) -#if (NRF51_GPT_USE_TIMER0 == TRUE) && \ - (NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER) +#if OSAL_ST_MODE != OSAL_ST_MODE_NONE +#if (NRF51_ST_USE_TIMER0 == TRUE) && (NRF51_GPT_USE_TIMER0 == TRUE) #error "TIMER0 already used by GPT driver" #endif + +#if (NRF51_ST_USE_RTC0 == FALSE) && \ + (NRF51_ST_USE_RTC1 == FALSE) && \ + (NRF51_ST_USE_TIMER0 == FALSE) +#error "One clock source is needed, enable one (RTC0, RTC1, or TIMER0)" #endif -#if ((NRF51_SYSTEM_TICKS != NRF51_SYSTEM_TICKS_AS_RTC) && \ - (NRF51_SYSTEM_TICKS != NRF51_SYSTEM_TICKS_AS_TIMER)) -#error "NRF51_SYSTEM_TICKS illegal value" +#if ((NRF51_ST_USE_RTC0 == TRUE ? 1 : 0) + \ + (NRF51_ST_USE_RTC1 == TRUE ? 1 : 0) + \ + (NRF51_ST_USE_TIMER0 == TRUE ? 1 : 0)) > 1 +#error "Only one clock source can be used (RTC0, RTC1, or TIMER0)" #endif +#if defined(SOFTDEVICE_PRESENT) +#if NRF51_ST_USE_RTC0 == TRUE +#error "RTC0 cannot be used for system ticks when SOFTDEVICE present" +#endif + +#if NRF51_ST_USE_TIMER0 == TRUE +#error "TIMER0 cannot be used for system ticks when SOFTDEVICE present" +#endif + +#if NRF51_ST_PRIORITY != 1 +#error "ST priority must be 1 when SOFTDEVICE present" +#endif + +#endif /* defined(SOFTDEVICE_PRESENT) */ +#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */ + #if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING #if defined(CH_CFG_ST_TIMEDELTA) && (CH_CFG_ST_TIMEDELTA < 5) #error "CH_CFG_ST_TIMEDELTA is too low" #endif -#if NRF51_SYSTEM_TICKS == NRF51_SYSTEM_TICKS_AS_TIMER +#if NRF51_ST_USE_TIMER0 == TRUE #error "Freeruning (tick-less) mode not supported with TIMER, use RTC" #endif -#endif +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ /*===========================================================================*/ /* Driver data structures and types. */ @@ -114,7 +155,12 @@ extern "C" { * @notapi */ static inline systime_t st_lld_get_counter(void) { - return (systime_t)NRF_RTC0->COUNTER; +#if NRF51_ST_USE_RTC0 == TRUE + return (systime_t)NRF_RTC0->COUNTER; +#endif +#if NRF51_ST_USE_RTC1 == TRUE + return (systime_t)NRF_RTC1->COUNTER; +#endif } /** @@ -127,9 +173,16 @@ static inline systime_t st_lld_get_counter(void) { * @notapi */ static inline void st_lld_start_alarm(systime_t abstime) { +#if NRF51_ST_USE_RTC0 == TRUE NRF_RTC0->CC[0] = abstime; NRF_RTC0->EVENTS_COMPARE[0] = 0; NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; +#endif +#if NRF51_ST_USE_RTC1 == TRUE + NRF_RTC1->CC[0] = abstime; + NRF_RTC1->EVENTS_COMPARE[0] = 0; + NRF_RTC1->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; +#endif } /** @@ -138,8 +191,14 @@ static inline void st_lld_start_alarm(systime_t abstime) { * @notapi */ static inline void st_lld_stop_alarm(void) { +#if NRF51_ST_USE_RTC0 == TRUE NRF_RTC0->EVTENCLR = RTC_EVTENCLR_COMPARE0_Msk; NRF_RTC0->EVENTS_COMPARE[0] = 0; +#endif +#if NRF51_ST_USE_RTC1 == TRUE + NRF_RTC1->EVTENCLR = RTC_EVTENCLR_COMPARE0_Msk; + NRF_RTC1->EVENTS_COMPARE[0] = 0; +#endif } /** @@ -150,7 +209,12 @@ static inline void st_lld_stop_alarm(void) { * @notapi */ static inline void st_lld_set_alarm(systime_t abstime) { +#if NRF51_ST_USE_RTC0 == TRUE NRF_RTC0->CC[0] = abstime; +#endif +#if NRF51_ST_USE_RTC1 == TRUE + NRF_RTC1->CC[0] = abstime; +#endif } /** @@ -161,7 +225,12 @@ static inline void st_lld_set_alarm(systime_t abstime) { * @notapi */ static inline systime_t st_lld_get_alarm(void) { +#if NRF51_ST_USE_RTC0 == TRUE return (systime_t)NRF_RTC0->CC[0]; +#endif +#if NRF51_ST_USE_RTC1 == TRUE + return (systime_t)NRF_RTC1->CC[0]; +#endif } /** @@ -174,7 +243,12 @@ static inline systime_t st_lld_get_alarm(void) { * @notapi */ static inline bool st_lld_is_alarm_active(void) { +#if NRF51_ST_USE_RTC0 == TRUE return NRF_RTC0->EVTEN & RTC_EVTEN_COMPARE0_Msk; +#endif +#if NRF51_ST_USE_RTC1 == TRUE + return NRF_RTC1->EVTEN & RTC_EVTEN_COMPARE0_Msk; +#endif } #endif /* _ST_LLD_H_ */