Merge pull request #15804 from haukepetersen/opt_nrf5x_hfxo
cpu/nrf5x: enhance external HF clock source handling to allow for substantial energy savings
This commit is contained in:
commit
42ff2ab778
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "mutex.h"
|
#include "mutex.h"
|
||||||
|
#include "nrf_clock.h"
|
||||||
|
|
||||||
#include "net/ieee802154.h"
|
#include "net/ieee802154.h"
|
||||||
#include "periph/timer.h"
|
#include "periph/timer.h"
|
||||||
@ -247,6 +248,11 @@ static int _init(netdev_t *dev)
|
|||||||
txbuf[0] = 0;
|
txbuf[0] = 0;
|
||||||
_state = 0;
|
_state = 0;
|
||||||
|
|
||||||
|
/* the radio need the external HF clock source to be enabled */
|
||||||
|
/* @todo add proper handling to release the clock whenever the radio is
|
||||||
|
* idle */
|
||||||
|
clock_hfxo_request();
|
||||||
|
|
||||||
/* power on peripheral */
|
/* power on peripheral */
|
||||||
NRF_RADIO->POWER = 1;
|
NRF_RADIO->POWER = 1;
|
||||||
|
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "luid.h"
|
#include "luid.h"
|
||||||
|
#include "nrf_clock.h"
|
||||||
|
|
||||||
#include "net/ieee802154.h"
|
#include "net/ieee802154.h"
|
||||||
#include "periph/timer.h"
|
#include "periph/timer.h"
|
||||||
@ -101,6 +102,22 @@ ieee802154_dev_t nrf802154_hal_dev = {
|
|||||||
.driver = &nrf802154_ops,
|
.driver = &nrf802154_ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void _power_on(void)
|
||||||
|
{
|
||||||
|
if (NRF_RADIO->POWER == 0) {
|
||||||
|
clock_hfxo_request();
|
||||||
|
NRF_RADIO->POWER = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _power_off(void)
|
||||||
|
{
|
||||||
|
if (NRF_RADIO->POWER == 1) {
|
||||||
|
NRF_RADIO->POWER = 0;
|
||||||
|
clock_hfxo_release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool _l2filter(uint8_t *mhr)
|
static bool _l2filter(uint8_t *mhr)
|
||||||
{
|
{
|
||||||
uint8_t dst_addr[IEEE802154_LONG_ADDRESS_LEN];
|
uint8_t dst_addr[IEEE802154_LONG_ADDRESS_LEN];
|
||||||
@ -445,7 +462,8 @@ int nrf802154_init(void)
|
|||||||
(void)result;
|
(void)result;
|
||||||
timer_stop(NRF802154_TIMER);
|
timer_stop(NRF802154_TIMER);
|
||||||
|
|
||||||
/* power off peripheral */
|
/* power off peripheral (but do not release the HFXO as we never requested
|
||||||
|
* it so far) */
|
||||||
NRF_RADIO->POWER = 0;
|
NRF_RADIO->POWER = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -574,7 +592,7 @@ static int _request_on(ieee802154_dev_t *dev)
|
|||||||
(void) dev;
|
(void) dev;
|
||||||
_state = STATE_IDLE;
|
_state = STATE_IDLE;
|
||||||
DEBUG("[nrf802154]: Request to turn on\n");
|
DEBUG("[nrf802154]: Request to turn on\n");
|
||||||
NRF_RADIO->POWER = 1;
|
_power_on();
|
||||||
/* make sure the radio is disabled/stopped */
|
/* make sure the radio is disabled/stopped */
|
||||||
_disable();
|
_disable();
|
||||||
/* we configure it to run in IEEE802.15.4 mode */
|
/* we configure it to run in IEEE802.15.4 mode */
|
||||||
@ -639,7 +657,7 @@ static int _off(ieee802154_dev_t *dev)
|
|||||||
{
|
{
|
||||||
(void) dev;
|
(void) dev;
|
||||||
DEBUG("[nrf802154] Turning off the radio\n");
|
DEBUG("[nrf802154] Turning off the radio\n");
|
||||||
NRF_RADIO->POWER = 0;
|
_power_off();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "irq.h"
|
||||||
|
#include "assert.h"
|
||||||
|
#include "nrf_clock.h"
|
||||||
#include "periph_conf.h"
|
#include "periph_conf.h"
|
||||||
|
|
||||||
/* make sure both clocks are configured */
|
/* make sure both clocks are configured */
|
||||||
@ -28,6 +31,8 @@
|
|||||||
#error "Clock init: CLOCK_LFCLK is not defined by your board!"
|
#error "Clock init: CLOCK_LFCLK is not defined by your board!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static unsigned _hfxo_requests = 0;
|
||||||
|
|
||||||
void clock_init_hf(void)
|
void clock_init_hf(void)
|
||||||
{
|
{
|
||||||
/* for the nRF51 we can chose the XTAL frequency */
|
/* for the nRF51 we can chose the XTAL frequency */
|
||||||
@ -39,12 +44,36 @@ void clock_init_hf(void)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CLOCK_HFCLK
|
/* allow to always enable the HFXO as non-default option */
|
||||||
/* start the HF clock */
|
#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->EVENTS_HFCLKSTARTED = 0;
|
||||||
NRF_CLOCK->TASKS_HFCLKSTART = 1;
|
NRF_CLOCK->TASKS_HFCLKSTART = 1;
|
||||||
while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) {}
|
while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) {}
|
||||||
#endif
|
}
|
||||||
|
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)
|
void clock_start_lf(void)
|
||||||
|
|||||||
@ -23,12 +23,33 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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
|
* @brief Initialize the high frequency clock (HFCLK) as configured in the
|
||||||
* board's periph_conf.h
|
* board's periph_conf.h
|
||||||
*/
|
*/
|
||||||
void clock_init_hf(void);
|
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
|
* @brief Start the low frequency clock (LFCLK) as configured in the board's
|
||||||
* periph_conf.
|
* periph_conf.
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
|
#include "nrf_clock.h"
|
||||||
|
|
||||||
#include "nrfble.h"
|
#include "nrfble.h"
|
||||||
#include "net/netdev/ble.h"
|
#include "net/netdev/ble.h"
|
||||||
@ -238,6 +239,11 @@ static int _nrfble_init(netdev_t *dev)
|
|||||||
(void)dev;
|
(void)dev;
|
||||||
assert(_nrfble_dev.driver && _nrfble_dev.event_callback);
|
assert(_nrfble_dev.driver && _nrfble_dev.event_callback);
|
||||||
|
|
||||||
|
/* the radio need the external HF clock source to be enabled */
|
||||||
|
/* @todo add proper handling to release the clock whenever the radio is
|
||||||
|
* idle */
|
||||||
|
clock_hfxo_request();
|
||||||
|
|
||||||
/* power on the NRFs radio */
|
/* power on the NRFs radio */
|
||||||
NRF_RADIO->POWER = 1;
|
NRF_RADIO->POWER = 1;
|
||||||
/* configure variable parameters to default values */
|
/* configure variable parameters to default values */
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "mutex.h"
|
#include "mutex.h"
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
|
#include "nrf_clock.h"
|
||||||
|
|
||||||
#include "periph_conf.h"
|
#include "periph_conf.h"
|
||||||
#include "periph/cpuid.h"
|
#include "periph/cpuid.h"
|
||||||
@ -401,6 +402,11 @@ static int nrfmin_init(netdev_t *dev)
|
|||||||
my_addr ^= cpuid[i] << (8 * (i & 0x01));
|
my_addr ^= cpuid[i] << (8 * (i & 0x01));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* the radio need the external HF clock source to be enabled */
|
||||||
|
/* @todo add proper handling to release the clock whenever the radio is
|
||||||
|
* idle */
|
||||||
|
clock_hfxo_request();
|
||||||
|
|
||||||
/* power on the NRFs radio */
|
/* power on the NRFs radio */
|
||||||
NRF_RADIO->POWER = 1;
|
NRF_RADIO->POWER = 1;
|
||||||
/* load driver specific configuration */
|
/* load driver specific configuration */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user