From 3060d96bfd97315ca8d148c15485db317f87de4d Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Mon, 3 Apr 2017 15:26:10 +0200 Subject: [PATCH] cpu/nrf5x: unified clock initialization code --- boards/airfy-beacon/include/periph_conf.h | 11 ++- boards/calliope-mini/include/periph_conf.h | 7 +- boards/microbit/include/periph_conf.h | 7 +- boards/nrf51dongle/include/periph_conf.h | 11 ++- boards/nrf52840dk/include/periph_conf.h | 9 ++- boards/nrf52dk/include/periph_conf.h | 9 ++- boards/nrf6310/include/periph_conf.h | 11 ++- boards/pca10000/include/periph_conf.h | 11 ++- boards/pca10005/include/periph_conf.h | 11 ++- boards/yunjia-nrf51822/include/periph_conf.h | 11 ++- cpu/nrf51/cpu.c | 15 +--- cpu/nrf52/cpu.c | 12 +-- cpu/nrf5x_common/Makefile | 1 + cpu/nrf5x_common/Makefile.include | 3 + cpu/nrf5x_common/clock.c | 83 ++++++++++++++++++++ cpu/nrf5x_common/include/nrf_clock.h | 52 ++++++++++++ 16 files changed, 209 insertions(+), 55 deletions(-) create mode 100644 cpu/nrf5x_common/clock.c create mode 100644 cpu/nrf5x_common/include/nrf_clock.h diff --git a/boards/airfy-beacon/include/periph_conf.h b/boards/airfy-beacon/include/periph_conf.h index 742d7e8900..a58349f7b6 100644 --- a/boards/airfy-beacon/include/periph_conf.h +++ b/boards/airfy-beacon/include/periph_conf.h @@ -27,16 +27,19 @@ #endif /** - * @name Clock configuration + * @name Clock configuration * - * @note: the radio will not work with the internal RC oscillator! + * @note The radio will not work with the internal RC oscillator! * * @{ */ -#define CLOCK_CORECLOCK (16000000U) /* fixed for all NRF51822 */ -#define CLOCK_CRYSTAL (16U) /* set to 0: internal RC oscillator +#define CLOCK_CORECLOCK (16000000U) /* fixed for all nRF51822 */ +#define CLOCK_HFCLK (16U) /* set to 0: internal RC oscillator 16: 16MHz crystal 32: 32MHz crystal */ +#define CLOCK_LFCLK (1) /* set to 0: internal RC oscillator + * 1: 32.768 kHz crystal + * 2: derived from HFCLK */ /** @} */ /** diff --git a/boards/calliope-mini/include/periph_conf.h b/boards/calliope-mini/include/periph_conf.h index 4fc702576b..4d42c4f802 100644 --- a/boards/calliope-mini/include/periph_conf.h +++ b/boards/calliope-mini/include/periph_conf.h @@ -32,10 +32,13 @@ extern "C" { * * @{ */ -#define CLOCK_CORECLOCK (16000000U) /* fixed for all NRF51822 */ -#define CLOCK_CRYSTAL (16U) /* set to 0: internal RC oscillator +#define CLOCK_CORECLOCK (16000000U) /* fixed for all nRF51822 */ +#define CLOCK_HFCLK (16U) /* set to 0: internal RC oscillator 16: 16MHz crystal 32: 32MHz crystal */ +#define CLOCK_LFCLK (0) /* set to 0: internal RC oscillator + * 1: 32.768 kHz crystal + * 2: derived from HFCLK */ /** @} */ /** diff --git a/boards/microbit/include/periph_conf.h b/boards/microbit/include/periph_conf.h index d86772fd22..f957f0bf92 100644 --- a/boards/microbit/include/periph_conf.h +++ b/boards/microbit/include/periph_conf.h @@ -32,10 +32,13 @@ extern "C" { * * @{ */ -#define CLOCK_CORECLOCK (16000000U) /* fixed for all NRF51822 */ -#define CLOCK_CRYSTAL (16U) /* set to 0: internal RC oscillator +#define CLOCK_CORECLOCK (16000000U) /* fixed for all nRF51822 */ +#define CLOCK_HFCLK (16U) /* set to 0: internal RC oscillator 16: 16MHz crystal 32: 32MHz crystal */ +#define CLOCK_LFCLK (0) /* set to 0: internal RC oscillator + * 1: 32.768 kHz crystal + * 2: derived from HFCLK */ /** @} */ /** diff --git a/boards/nrf51dongle/include/periph_conf.h b/boards/nrf51dongle/include/periph_conf.h index 4f43980a6b..3ffda30d59 100644 --- a/boards/nrf51dongle/include/periph_conf.h +++ b/boards/nrf51dongle/include/periph_conf.h @@ -26,16 +26,19 @@ extern "C" { #endif /** - * @name Clock configuration + * @name Clock configuration * - * @note: the radio will not work with the internal RC oscillator! + * @note The radio will not work with the internal RC oscillator! * * @{ */ -#define CLOCK_CORECLOCK (16000000U) /* fixed for all NRF51822 */ -#define CLOCK_CRYSTAL (16U) /* set to 0: internal RC oscillator +#define CLOCK_CORECLOCK (16000000U) /* fixed for all nRF51822 */ +#define CLOCK_HFCLK (16U) /* set to 0: internal RC oscillator 16: 16MHz crystal 32: 32MHz crystal */ +#define CLOCK_LFCLK (1) /* set to 0: internal RC oscillator + * 1: 32.768 kHz crystal + * 2: derived from HFCLK */ /** @} */ /** diff --git a/boards/nrf52840dk/include/periph_conf.h b/boards/nrf52840dk/include/periph_conf.h index d8951d0d19..c03badb5c7 100644 --- a/boards/nrf52840dk/include/periph_conf.h +++ b/boards/nrf52840dk/include/periph_conf.h @@ -33,9 +33,12 @@ extern "C" { * * @{ */ -#define CLOCK_CORECLOCK (64000000U) /* fixed for all NRF52832 */ -#define CLOCK_CRYSTAL (32U) /* set to 0: internal RC oscillator - 32: 32MHz crystal */ +#define CLOCK_CORECLOCK (64000000U) /* fixed for all nRF52832 */ +#define CLOCK_HFCLK (32U) /* set to 0: internal RC oscillator + * 32: 32MHz crystal */ +#define CLOCK_LFCLK (1) /* set to 0: internal RC oscillator + * 1: 32.768 kHz crystal + * 2: derived from HFCLK */ /** @} */ /** diff --git a/boards/nrf52dk/include/periph_conf.h b/boards/nrf52dk/include/periph_conf.h index 9ecc98d691..fb27fa253b 100644 --- a/boards/nrf52dk/include/periph_conf.h +++ b/boards/nrf52dk/include/periph_conf.h @@ -33,9 +33,12 @@ extern "C" { * * @{ */ -#define CLOCK_CORECLOCK (64000000U) /* fixed for all NRF52832 */ -#define CLOCK_CRYSTAL (32U) /* set to 0: internal RC oscillator - 32: 32MHz crystal */ +#define CLOCK_CORECLOCK (64000000U) /* fixed for all nRF52832 */ +#define CLOCK_HFCLK (32U) /* set to 0: internal RC oscillator + * 32: 32MHz crystal */ +#define CLOCK_LFCLK (1) /* set to 0: internal RC oscillator + * 1: 32.768 kHz crystal + * 2: derived from HFCLK */ /** @} */ /** diff --git a/boards/nrf6310/include/periph_conf.h b/boards/nrf6310/include/periph_conf.h index 3c217504e7..c182328750 100644 --- a/boards/nrf6310/include/periph_conf.h +++ b/boards/nrf6310/include/periph_conf.h @@ -29,16 +29,19 @@ extern "C" { #endif /** - * @name Clock configuration + * @name Clock configuration * - * @note: the radio will not work with the internal RC oscillator! + * @note The radio will not work with the internal RC oscillator! * * @{ */ -#define CLOCK_CORECLOCK (16000000U) /* fixed for all NRF51822 */ -#define CLOCK_CRYSTAL (16U) /* set to 0: internal RC oscillator +#define CLOCK_CORECLOCK (16000000U) /* fixed for all nRF51822 */ +#define CLOCK_HFCLK (16U) /* set to 0: internal RC oscillator 16: 16MHz crystal 32: 32MHz crystal */ +#define CLOCK_LFCLK (1) /* set to 0: internal RC oscillator + * 1: 32.768 kHz crystal + * 2: derived from HFCLK */ /** @} */ /** diff --git a/boards/pca10000/include/periph_conf.h b/boards/pca10000/include/periph_conf.h index bccca1e941..020ab8d751 100644 --- a/boards/pca10000/include/periph_conf.h +++ b/boards/pca10000/include/periph_conf.h @@ -28,16 +28,19 @@ extern "C" { #endif /** - * @name Clock configuration + * @name Clock configuration * - * @note: the radio will not work with the internal RC oscillator! + * @note The radio will not work with the internal RC oscillator! * * @{ */ -#define CLOCK_CORECLOCK (16000000U) /* fixed for all NRF51822 */ -#define CLOCK_CRYSTAL (16U) /* set to 0: internal RC oscillator +#define CLOCK_CORECLOCK (16000000U) /* fixed for all nRF51822 */ +#define CLOCK_HFCLK (16U) /* set to 0: internal RC oscillator 16: 16MHz crystal 32: 32MHz crystal */ +#define CLOCK_LFCLK (0) /* set to 0: internal RC oscillator + * 1: 32.768 kHz crystal + * 2: derived from HFCLK */ /** @} */ /** diff --git a/boards/pca10005/include/periph_conf.h b/boards/pca10005/include/periph_conf.h index a9704bd116..c505a1bd01 100644 --- a/boards/pca10005/include/periph_conf.h +++ b/boards/pca10005/include/periph_conf.h @@ -28,16 +28,19 @@ extern "C" { #endif /** - * @name Clock configuration + * @name Clock configuration * - * @note: the radio will not work with the internal RC oscillator! + * @note The radio will not work with the internal RC oscillator! * * @{ */ -#define CLOCK_CORECLOCK (16000000U) /* fixed for all NRF51822 */ -#define CLOCK_CRYSTAL (16U) /* set to 0: internal RC oscillator +#define CLOCK_CORECLOCK (16000000U) /* fixed for all nRF51822 */ +#define CLOCK_HFCLK (16U) /* set to 0: internal RC oscillator 16: 16MHz crystal 32: 32MHz crystal */ +#define CLOCK_LFCLK (0) /* set to 0: internal RC oscillator + * 1: 32.768 kHz crystal + * 2: derived from HFCLK */ /** @} */ /** diff --git a/boards/yunjia-nrf51822/include/periph_conf.h b/boards/yunjia-nrf51822/include/periph_conf.h index 21b39df6dd..8ccc93240d 100644 --- a/boards/yunjia-nrf51822/include/periph_conf.h +++ b/boards/yunjia-nrf51822/include/periph_conf.h @@ -26,16 +26,19 @@ extern "C" { #endif /** - * @name Clock configuration + * @name Clock configuration * - * @note: the radio will not work with the internal RC oscillator! + * @note The radio will not work with the internal RC oscillator! * * @{ */ -#define CLOCK_CORECLOCK (16000000U) /* fixed for all NRF51822 */ -#define CLOCK_CRYSTAL (16U) /* set to 0: internal RC oscillator +#define CLOCK_CORECLOCK (16000000U) /* fixed for all nRF51822 */ +#define CLOCK_HFCLK (16U) /* set to 0: internal RC oscillator 16: 16MHz crystal 32: 32MHz crystal */ +#define CLOCK_LFCLK (0) /* set to 0: internal RC oscillator + * 1: 32.768 kHz crystal + * 2: derived from HFCLK */ /** @} */ /** diff --git a/cpu/nrf51/cpu.c b/cpu/nrf51/cpu.c index db19c2681a..76316c845d 100644 --- a/cpu/nrf51/cpu.c +++ b/cpu/nrf51/cpu.c @@ -18,6 +18,7 @@ */ #include "cpu.h" +#include "nrf_clock.h" #include "periph_conf.h" #include "periph/init.h" @@ -28,18 +29,8 @@ void cpu_init(void) { /* initialize the Cortex-M core */ cortexm_init(); - /* set the correct clock source for HFCLK */ -#if CLOCK_CRYSTAL == 32 - NRF_CLOCK->XTALFREQ = CLOCK_XTALFREQ_XTALFREQ_32MHz; - NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; - NRF_CLOCK->TASKS_HFCLKSTART = 1; - while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) {} -#elif CLOCK_CRYSTAL == 16 - NRF_CLOCK->XTALFREQ = CLOCK_XTALFREQ_XTALFREQ_16MHz; - NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; - NRF_CLOCK->TASKS_HFCLKSTART = 1; - while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) {} -#endif + /* setup the HF clock */ + clock_init_hf(); /* trigger static peripheral initialization */ periph_init(); } diff --git a/cpu/nrf52/cpu.c b/cpu/nrf52/cpu.c index 85687fb9d8..1a0d6672d4 100644 --- a/cpu/nrf52/cpu.c +++ b/cpu/nrf52/cpu.c @@ -23,6 +23,7 @@ #define DONT_OVERRIDE_NVIC #include "cpu.h" +#include "nrf_clock.h" #include "periph_conf.h" #include "periph/init.h" @@ -60,15 +61,8 @@ void cpu_init(void) NRF_CLOCK->EVENTS_CTTO = 0; } - /* set the correct clock source for HFCLK */ -#if (CLOCK_CRYSTAL == 32) - NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos); - - NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; - NRF_CLOCK->TASKS_HFCLKSTART = 1; - - while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0); -#endif + /* initialize hf clock */ + clock_init_hf(); /* softdevice needs to be enabled from ISR context */ #ifdef SOFTDEVICE_PRESENT diff --git a/cpu/nrf5x_common/Makefile b/cpu/nrf5x_common/Makefile index 3b0970ca13..6f68314295 100644 --- a/cpu/nrf5x_common/Makefile +++ b/cpu/nrf5x_common/Makefile @@ -1,3 +1,4 @@ +MODULE = cpu_common DIRS = periph # build one of the radio drivers, if enabled diff --git a/cpu/nrf5x_common/Makefile.include b/cpu/nrf5x_common/Makefile.include index d1f1178256..3bb12bc975 100644 --- a/cpu/nrf5x_common/Makefile.include +++ b/cpu/nrf5x_common/Makefile.include @@ -8,5 +8,8 @@ USEMODULE += periph_common # include nrf5x common periph drivers USEMODULE += nrf5x_common_periph +# link common cpu code +USEMODULE += cpu_common + # export the common include directory export INCLUDES += -I$(RIOTCPU)/nrf5x_common/include diff --git a/cpu/nrf5x_common/clock.c b/cpu/nrf5x_common/clock.c new file mode 100644 index 0000000000..6fb89472ed --- /dev/null +++ b/cpu/nrf5x_common/clock.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2017 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_nrf5x_common + * @{ + * + * @file + * @brief Clock initialization code + * + * @author Hauke Petersen + * @} + */ + +#include "cpu.h" +#include "periph_conf.h" + +/* make sure both clocks are configured */ +#ifndef CLOCK_HFCLK +#error "Clock init: CLOCK_HFCLK is not defined by your board!" +#endif +#ifndef CLOCK_LFCLK +#error "Clock init: CLOCK_LFCLK is not defined by your board!" +#endif + +void clock_init_hf(void) +{ + /* for the nRF51 we can chose the XTAL frequency */ +#ifdef CPU_FAM_NRF51 +#if (CLOCK_HFCLK == 32) + NRF_CLOCK->XTALFREQ = CLOCK_XTALFREQ_XTALFREQ_32MHz; +#elif (CLOCK_HFCLK == 16) + NRF_CLOCK->XTALFREQ = CLOCK_XTALFREQ_XTALFREQ_16MHz; +#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) {} +#endif +} + +void clock_start_lf(void) +{ + /* abort if LF clock is already running */ + if (NRF_CLOCK->LFCLKSTAT & CLOCK_LFCLKSTAT_STATE_Msk) { + return; + } + +#if (CLOCK_LFCLK == 0) + NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_RC); +#elif (CLOCK_LFCLK == 1) + NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_Xtal); +#elif (CLOCK_LFCLK == 2) + NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_Synth); +#else +#error "LFCLK init: CLOCK_LFCLK has invalid value" +#endif + /* enable LF clock */ + NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; + NRF_CLOCK->TASKS_LFCLKSTART = 1; + while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) {} + + /* calibrate the RC LF clock if applicable */ +#if (CLOCK_HFCLK && (CLOCK_LFCLK == 0)) + NRF_CLOCK->EVENTS_DONE = 0; + NRF_CLOCK->TASKS_CAL = 1; + while (NRF_CLOCK->EVENTS_DONE == 0) {} +#endif +} + +void clock_stop_lf(void) +{ + NRF_CLOCK->TASKS_LFCLKSTOP = 1; + while (NRF_CLOCK->LFCLKSTAT & CLOCK_LFCLKSTAT_STATE_Msk) {} +} diff --git a/cpu/nrf5x_common/include/nrf_clock.h b/cpu/nrf5x_common/include/nrf_clock.h new file mode 100644 index 0000000000..39f8a45eeb --- /dev/null +++ b/cpu/nrf5x_common/include/nrf_clock.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2017 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_nrf5x_common + * @{ + * + * @file + * @brief nRF5x shared functions for configuration the system clocks + * + * @author Hauke Petersen + */ + +#ifndef NRF_CLOCK_H +#define NRF_CLOCK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize the high frequency clock (HFCLK) as configured in the + * board's periph_conf.h + */ +void clock_init_hf(void); + +/** + * @brief Start the low frequency clock (LFCLK) as configured in the board's + * periph_conf. + * + * Calling this function while the LFCLK is already running will have no effect. + */ +void clock_start_lf(void); + +/** + * @brief Stop the low frequency clock (LFCLK) + * + * @note Be sure that no module is using the LFCLK before you shut it down! + */ +void clock_stop_lf(void); + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_CLOCK_H */ +/** @} */