mbed library sources
Dependents: Freedman_v2 Nucleo_i2c_OLED_BME280_copy
Fork of mbed-src by
Diff: targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/system_nrf51.c
- Revision:
- 603:3c75ef011213
- Parent:
- 598:2d5fc5624619
--- a/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/system_nrf51.c Wed Aug 05 14:30:08 2015 +0100 +++ b/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/system_nrf51.c Thu Aug 13 10:30:09 2015 +0100 @@ -34,6 +34,7 @@ #include <stdint.h> #include <stdbool.h> #include "nrf.h" +#include "nrf_delay.h" #include "system_nrf51.h" /*lint ++flb "Enter library region" */ @@ -42,6 +43,7 @@ static bool is_manual_peripheral_setup_needed(void); static bool is_disabled_in_debug_needed(void); +static void init_clock(void); #if defined ( __CC_ARM ) @@ -82,8 +84,18 @@ } // Start the external 32khz crystal oscillator. + init_clock(); +} - /* for Nordic devices without an external LF crystal */ +void init_clock(void) +{ + /* For compatibility purpose, the default behaviour is to first attempt to initialise an + external clock, and after a timeout, use the internal RC one. To avoid this wait, boards that + don't have an external oscillator can set TARGET_NRF_LFCLK_RC directly. */ + int i = 0; + const uint32_t polling_period = 200; + const uint32_t timeout = 1000000; + #if defined(TARGET_NRF_LFCLK_RC) NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_RC << CLOCK_LFCLKSRC_SRC_Pos); #else @@ -92,7 +104,26 @@ NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; NRF_CLOCK->TASKS_LFCLKSTART = 1; - // Wait for the external oscillator to start up. + /* Wait for the external oscillator to start up. + nRF51822 product specification (8.1.5) gives a typical value of 300ms for external clock + startup duration, and a maximum value of 1s. When using the internal RC source, typical delay + will be 390µs, so we use a polling period of 200µs. + + We can't use us_ticker at this point, so we have to rely on a less precise method for + measuring our timeout. Because of this, the actual timeout will be slightly longer than 1 + second, which isn't an issue at all, since this fallback should only be used as a safety net. + */ + for (i = 0; i < (timeout / polling_period); i++) { + if (NRF_CLOCK->EVENTS_LFCLKSTARTED != 0) + return; + nrf_delay_us(polling_period); + } + + /* Fallback to internal clock. Belt and braces, since the internal clock is used by default + whilst no external source is running. This is not only a sanity check, but it also allows + code down the road (e.g. ble initialisation) to directly know which clock is used. */ + NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_RC << CLOCK_LFCLKSRC_SRC_Pos); + NRF_CLOCK->TASKS_LFCLKSTART = 1; while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) { // Do nothing. }