diff --git a/cpu/nrf5x_common/clock.c b/cpu/nrf5x_common/clock.c index 6fb89472ed..4eef401553 100644 --- a/cpu/nrf5x_common/clock.c +++ b/cpu/nrf5x_common/clock.c @@ -18,6 +18,9 @@ */ #include "cpu.h" +#include "irq.h" +#include "assert.h" +#include "nrf_clock.h" #include "periph_conf.h" /* make sure both clocks are configured */ @@ -28,6 +31,8 @@ #error "Clock init: CLOCK_LFCLK is not defined by your board!" #endif +static unsigned _hfxo_requests = 0; + void clock_init_hf(void) { /* for the nRF51 we can chose the XTAL frequency */ @@ -39,14 +44,38 @@ void clock_init_hf(void) #endif #endif -#if CLOCK_HFCLK - /* start the HF clock */ - NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; - NRF_CLOCK->TASKS_HFCLKSTART = 1; - while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) {} + /* allow to always enable the HFXO as non-default option */ +#if CLOCK_HFXO_ONBOOT + clock_hfxo_request(); #endif } +void clock_hfxo_request(void) +{ + unsigned state = irq_disable(); + ++_hfxo_requests; + if (_hfxo_requests == 1) { + NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; + NRF_CLOCK->TASKS_HFCLKSTART = 1; + while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) {} + } + irq_restore(state); +} + +void clock_hfxo_release(void) +{ + /* if this function is called while the counter is zero the state in a + * driver requesting the HFXO is broken! */ + assert(_hfxo_requests); + + unsigned state = irq_disable(); + --_hfxo_requests; + if (_hfxo_requests == 0) { + NRF_CLOCK->TASKS_HFCLKSTOP = 1; + } + irq_restore(state); +} + void clock_start_lf(void) { /* abort if LF clock is already running */ diff --git a/cpu/nrf5x_common/include/nrf_clock.h b/cpu/nrf5x_common/include/nrf_clock.h index 39f8a45eeb..a2a3fd3ff9 100644 --- a/cpu/nrf5x_common/include/nrf_clock.h +++ b/cpu/nrf5x_common/include/nrf_clock.h @@ -23,12 +23,33 @@ extern "C" { #endif +/** + * @brief The high frequency clock (HFCLK) uses the internal oscillator per + * default. Setting this define to 1 will enable the HFXO clock source + * on boot so it will always be active. + */ +#ifndef CLOCK_HFXO_ONBOOT +#define CLOCK_HFXO_ONBOOT 0 +#endif + /** * @brief Initialize the high frequency clock (HFCLK) as configured in the * board's periph_conf.h */ void clock_init_hf(void); +/** + * @brief Request the external high frequency crystal (HFXO) as HF clock + * source. If this is the first request, the HFXO will be enabled. + */ +void clock_hfxo_request(void); + +/** + * @brief Release the use of the HFXO. If this was the last active request, + * the HFXO will be disabled + */ +void clock_hfxo_release(void); + /** * @brief Start the low frequency clock (LFCLK) as configured in the board's * periph_conf.