From 0ab319927df6efdf8033843c550df37ee5f9381f Mon Sep 17 00:00:00 2001 From: Michal Gorecki <michal.gorecki@codecoup.pl> Date: Thu, 11 May 2023 14:39:18 +0200 Subject: [PATCH 1/4] mcu/nrf5340_net: Add API to switch lpclk in the runtime --- .../include/mcu/nrf5340_net_clock.h | 14 +++++ .../nrf5340_net/src/nrf5340_net_clock.c | 55 +++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/hw/mcu/nordic/nrf5340_net/include/mcu/nrf5340_net_clock.h b/hw/mcu/nordic/nrf5340_net/include/mcu/nrf5340_net_clock.h index a87e41e462..ec73db6914 100644 --- a/hw/mcu/nordic/nrf5340_net/include/mcu/nrf5340_net_clock.h +++ b/hw/mcu/nordic/nrf5340_net/include/mcu/nrf5340_net_clock.h @@ -43,6 +43,20 @@ int nrf5340_net_clock_hfxo_request(void); */ int nrf5340_net_clock_hfxo_release(void); +/** + * Request low frequency clock source change. + * + * @param clksrc Value to determine requested clock source + * This parameter can be one of the following values: + * @arg CLOCK_LFCLKSTAT_SRC_LFRC - 32.768 kHz RC oscillator + * @arg CLOCK_LFCLKSTAT_SRC_LFXO - 32.768 kHz crystal oscillator + * @arg CLOCK_LFCLKSTAT_SRC_LFSYNT - 32.768 kHz synthesized from HFCLK + * + * @return int 0: clock source was already as requested. 1: clock source + * changed. + */ +int nrf5340_net_set_lf_clock_source(uint32_t clksrc); + #ifdef __cplusplus } #endif diff --git a/hw/mcu/nordic/nrf5340_net/src/nrf5340_net_clock.c b/hw/mcu/nordic/nrf5340_net/src/nrf5340_net_clock.c index 8a67ec1add..74c97c1f44 100644 --- a/hw/mcu/nordic/nrf5340_net/src/nrf5340_net_clock.c +++ b/hw/mcu/nordic/nrf5340_net/src/nrf5340_net_clock.c @@ -75,3 +75,58 @@ nrf5340_net_clock_hfxo_release(void) return stopped; } + +/** + * Request low frequency clock source change. + * + * @return int 0: clock source was already as requested. 1: clock source + * changed. + */ +int +nrf5340_net_set_lf_clock_source(uint32_t clksrc) +{ + uint32_t regmsk; + uint32_t regval; + + regmsk = CLOCK_LFCLKSTAT_STATE_Msk | CLOCK_LFCLKSTAT_SRC_Msk; + regval = CLOCK_LFCLKSTAT_STATE_Running << CLOCK_LFCLKSTAT_STATE_Pos; + + regval |= clksrc << CLOCK_LFCLKSTAT_SRC_Pos; + + /* Check if this clock source isn't already running */ + if ((NRF_CLOCK_NS->LFCLKSTAT & regmsk) == regval) { + return 0; + } + + /* + * Request HFXO if LFSYNTH is going to be set as source. If LFSYNTH is going to be + * replaced with other source, release HFXO. + */ + if (clksrc == CLOCK_LFCLKSTAT_SRC_LFSYNT) { + if ((NRF_CLOCK_NS->HFCLKSTAT & CLOCK_HFCLKSTAT_STATE_Msk) != + (CLOCK_HFCLKSTAT_STATE_Running << CLOCK_HFCLKSTAT_STATE_Pos)) { + NRF_CLOCK_NS->EVENTS_HFCLKSTARTED = 0; + nrf5340_net_clock_hfxo_request(); + while (!NRF_CLOCK_NS->EVENTS_HFCLKSTARTED) { + } + } else { + nrf5340_net_clock_hfxo_request(); + } + } else if (NRF_CLOCK_NS->LFCLKSRC == CLOCK_LFCLKSTAT_SRC_LFSYNT) { + nrf5340_net_clock_hfxo_release(); + } + + NRF_CLOCK_NS->LFCLKSRC = clksrc; + NRF_CLOCK_NS->TASKS_LFCLKSTART = 1; + + /* Wait here till started! */ + while (1) { + if (NRF_CLOCK_NS->EVENTS_LFCLKSTARTED) { + if ((NRF_CLOCK_NS->LFCLKSTAT & regmsk) == regval) { + break; + } + } + } + + return 1; +} From f9a2fbfaea6db9fa3e4f0071893857f8bee1f929 Mon Sep 17 00:00:00 2001 From: Michal Gorecki <michal.gorecki@codecoup.pl> Date: Thu, 11 May 2023 15:05:29 +0200 Subject: [PATCH 2/4] mcu/nrf5340_net: Use Low Frequency Clock source setting API in startup Code from function hal_system_clock_start was moved into new API, so now we can call that API with proper argument to avoid code repetition. --- hw/mcu/nordic/nrf5340_net/src/hal_system.c | 47 ++-------------------- 1 file changed, 3 insertions(+), 44 deletions(-) diff --git a/hw/mcu/nordic/nrf5340_net/src/hal_system.c b/hw/mcu/nordic/nrf5340_net/src/hal_system.c index d7d1f3cb51..947d60fb67 100644 --- a/hw/mcu/nordic/nrf5340_net/src/hal_system.c +++ b/hw/mcu/nordic/nrf5340_net/src/hal_system.c @@ -70,57 +70,16 @@ void hal_system_clock_start(void) { #if MYNEWT_VAL(MCU_LFCLK_SOURCE) - uint32_t regmsk; - uint32_t regval; - uint32_t clksrc; - - regmsk = CLOCK_LFCLKSTAT_STATE_Msk | CLOCK_LFCLKSTAT_SRC_Msk; - regval = CLOCK_LFCLKSTAT_STATE_Running << CLOCK_LFCLKSTAT_STATE_Pos; #if MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFXO) - regval |= CLOCK_LFCLKSTAT_SRC_LFXO << CLOCK_LFCLKSTAT_SRC_Pos; - clksrc = CLOCK_LFCLKSTAT_SRC_LFXO; + nrf5340_net_set_lf_clock_source(CLOCK_LFCLKSTAT_SRC_LFXO); #elif MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFSYNTH) - regval |= CLOCK_LFCLKSTAT_SRC_LFSYNT << CLOCK_LFCLKSTAT_SRC_Pos; - clksrc = CLOCK_LFCLKSTAT_SRC_LFSYNT; + nrf5340_net_set_lf_clock_source(CLOCK_LFCLKSTAT_SRC_LFSYNT); #elif MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFRC) - regval |= CLOCK_LFCLKSTAT_SRC_LFRC << CLOCK_LFCLKSTAT_SRC_Pos; - clksrc = CLOCK_LFCLKSTAT_SRC_LFRC; + nrf5340_net_set_lf_clock_source(CLOCK_LFCLKSTAT_SRC_LFRC); #else #error Unknown LFCLK source selected #endif -#if MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFSYNTH) - /* Must turn on HFLCK for synthesized 32768 crystal */ - if ((NRF_CLOCK_NS->HFCLKSTAT & CLOCK_HFCLKSTAT_STATE_Msk) != - (CLOCK_HFCLKSTAT_STATE_Running << CLOCK_HFCLKSTAT_STATE_Pos)) { - NRF_CLOCK_NS->EVENTS_HFCLKSTARTED = 0; - nrf5340_net_clock_hfxo_request(); - while (1) { - if ((NRF_CLOCK_NS->EVENTS_HFCLKSTARTED) != 0) { - break; - } - } - } else { - nrf5340_net_clock_hfxo_request(); - } -#endif - - /* Check if this clock source is already running */ - if ((NRF_CLOCK_NS->LFCLKSTAT & regmsk) != regval) { - NRF_CLOCK_NS->TASKS_LFCLKSTOP = 1; - NRF_CLOCK_NS->EVENTS_LFCLKSTARTED = 0; - NRF_CLOCK_NS->LFCLKSRC = clksrc; - NRF_CLOCK_NS->TASKS_LFCLKSTART = 1; - - /* Wait here till started! */ - while (1) { - if (NRF_CLOCK_NS->EVENTS_LFCLKSTARTED) { - if ((NRF_CLOCK_NS->LFCLKSTAT & regmsk) == regval) { - break; - } - } - } - } #endif } From 942adc6bf50de082cd985dd76640c9109a7ea65b Mon Sep 17 00:00:00 2001 From: Michal Gorecki <michal.gorecki@codecoup.pl> Date: Thu, 11 May 2023 16:20:27 +0200 Subject: [PATCH 3/4] mcu/nrf5340: Add API to switch lpclk in the runtime --- .../nrf5340/include/mcu/nrf5340_clock.h | 14 ++++++ hw/mcu/nordic/nrf5340/src/nrf5340_clock.c | 49 +++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/hw/mcu/nordic/nrf5340/include/mcu/nrf5340_clock.h b/hw/mcu/nordic/nrf5340/include/mcu/nrf5340_clock.h index 0a69dbaee9..9c623a9723 100644 --- a/hw/mcu/nordic/nrf5340/include/mcu/nrf5340_clock.h +++ b/hw/mcu/nordic/nrf5340/include/mcu/nrf5340_clock.h @@ -43,6 +43,20 @@ int nrf5340_clock_hfxo_request(void); */ int nrf5340_clock_hfxo_release(void); +/** + * Request low frequency clock source change. + * + * @param clksrc Value to determine requested clock source + * This parameter can be one of the following values: + * @arg CLOCK_LFCLKSTAT_SRC_LFRC - 32.768 kHz RC oscillator + * @arg CLOCK_LFCLKSTAT_SRC_LFXO - 32.768 kHz crystal oscillator + * @arg CLOCK_LFCLKSTAT_SRC_LFSYNT - 32.768 kHz synthesized from HFCLK + * + * @return int 0: clock source was already as requested. 1: clock source + * changed. + */ +int nrf5340_set_lf_clock_source(uint32_t clksrc); + /** * Request HFCLK192M clock be turned on. Note that each request must have a * corresponding release. diff --git a/hw/mcu/nordic/nrf5340/src/nrf5340_clock.c b/hw/mcu/nordic/nrf5340/src/nrf5340_clock.c index 77b7f0bee3..6ad8b67221 100644 --- a/hw/mcu/nordic/nrf5340/src/nrf5340_clock.c +++ b/hw/mcu/nordic/nrf5340/src/nrf5340_clock.c @@ -100,3 +100,52 @@ nrf5340_clock_hfclk192m_release(void) return stopped; } + +int +nrf5340_set_lf_clock_source(uint32_t clksrc) +{ + uint32_t regmsk; + uint32_t regval; + + regmsk = CLOCK_LFCLKSTAT_STATE_Msk | CLOCK_LFCLKSTAT_SRC_Msk; + regval = CLOCK_LFCLKSTAT_STATE_Running << CLOCK_LFCLKSTAT_STATE_Pos; + + regval |= clksrc << CLOCK_LFCLKSTAT_SRC_Pos; + + /* Check if this clock source isn't already running */ + if ((NRF_CLOCK->LFCLKSTAT & regmsk) == regval) { + return 0; + } + + /* + * Request HFXO if LFSYNTH is going to be set as source. If LFSYNTH is going to be + * replaced with other source, release HFXO. + */ + if (clksrc == CLOCK_LFCLKSTAT_SRC_LFSYNT) { + if ((NRF_CLOCK->HFCLKSTAT & CLOCK_HFCLKSTAT_STATE_Msk) != + (CLOCK_HFCLKSTAT_STATE_Running << CLOCK_HFCLKSTAT_STATE_Pos)) { + NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; + nrf5340_clock_hfxo_request(); + while (!NRF_CLOCK->EVENTS_HFCLKSTARTED) { + } + } else { + nrf5340_clock_hfxo_request(); + } + } else if (NRF_CLOCK->LFCLKSRC == CLOCK_LFCLKSTAT_SRC_LFSYNT) { + nrf5340_clock_hfxo_release(); + } + + NRF_CLOCK->LFCLKSRC = clksrc; + NRF_CLOCK->TASKS_LFCLKSTART = 1; + + /* Wait here till started! */ + while (1) { + if (NRF_CLOCK->EVENTS_LFCLKSTARTED) { + if ((NRF_CLOCK->LFCLKSTAT & regmsk) == regval) { + break; + } + } + } + + return 1; +} \ No newline at end of file From 71d8fad72a30c13293946009ef5cd6ae26865d37 Mon Sep 17 00:00:00 2001 From: Michal Gorecki <michal.gorecki@codecoup.pl> Date: Thu, 11 May 2023 16:22:37 +0200 Subject: [PATCH 4/4] mcu/nrf5340: Use Low Frequency Clock source setting API in startup Code from function hal_system_clock_start was moved into new API, so now we can call that API with proper argument to avoid code repetition. --- hw/mcu/nordic/nrf5340/src/hal_system.c | 47 ++------------------------ 1 file changed, 3 insertions(+), 44 deletions(-) diff --git a/hw/mcu/nordic/nrf5340/src/hal_system.c b/hw/mcu/nordic/nrf5340/src/hal_system.c index 36868c0f90..8f641b7a0f 100644 --- a/hw/mcu/nordic/nrf5340/src/hal_system.c +++ b/hw/mcu/nordic/nrf5340/src/hal_system.c @@ -84,12 +84,6 @@ void hal_system_clock_start(void) { #if MYNEWT_VAL(MCU_LFCLK_SOURCE) - uint32_t regmsk; - uint32_t regval; - uint32_t clksrc; - - regmsk = CLOCK_LFCLKSTAT_STATE_Msk | CLOCK_LFCLKSTAT_SRC_Msk; - regval = CLOCK_LFCLKSTAT_STATE_Running << CLOCK_LFCLKSTAT_STATE_Pos; #if MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFXO) @@ -107,50 +101,15 @@ hal_system_clock_start(void) NRF_P0->PIN_CNF[0] = GPIO_PIN_CNF_MCUSEL_Peripheral << GPIO_PIN_CNF_MCUSEL_Pos; NRF_P0->PIN_CNF[1] = GPIO_PIN_CNF_MCUSEL_Peripheral << GPIO_PIN_CNF_MCUSEL_Pos; #endif - regval |= CLOCK_LFCLKSTAT_SRC_LFXO << CLOCK_LFCLKSTAT_SRC_Pos; - clksrc = CLOCK_LFCLKSTAT_SRC_LFXO; + nrf5340_set_lf_clock_source(CLOCK_LFCLKSTAT_SRC_LFXO); #elif MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFSYNTH) - regval |= CLOCK_LFCLKSTAT_SRC_LFSYNT << CLOCK_LFCLKSTAT_SRC_Pos; - clksrc = CLOCK_LFCLKSTAT_SRC_LFSYNT; + nrf5340_set_lf_clock_source(CLOCK_LFCLKSTAT_SRC_LFSYNT); #elif MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFRC) - regval |= CLOCK_LFCLKSTAT_SRC_LFRC << CLOCK_LFCLKSTAT_SRC_Pos; - clksrc = CLOCK_LFCLKSTAT_SRC_LFRC; + nrf5340_set_lf_clock_source(CLOCK_LFCLKSTAT_SRC_LFRC); #else #error Unknown LFCLK source selected #endif -#if MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFSYNTH) - /* Must turn on HFLCK for synthesized 32768 crystal */ - if ((NRF_CLOCK->HFCLKSTAT & CLOCK_HFCLKSTAT_STATE_Msk) != - (CLOCK_HFCLKSTAT_STATE_Running << CLOCK_HFCLKSTAT_STATE_Pos)) { - NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; - nrf5340_clock_hfxo_request(); - while (1) { - if ((NRF_CLOCK->EVENTS_HFCLKSTARTED) != 0) { - break; - } - } - } else { - nrf5340_clock_hfxo_request(); - } -#endif - - /* Check if this clock source is already running */ - if ((NRF_CLOCK->LFCLKSTAT & regmsk) != regval) { - NRF_CLOCK->TASKS_LFCLKSTOP = 1; - NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; - NRF_CLOCK->LFCLKSRC = clksrc; - NRF_CLOCK->TASKS_LFCLKSTART = 1; - - /* Wait here till started! */ - while (1) { - if (NRF_CLOCK->EVENTS_LFCLKSTARTED) { - if ((NRF_CLOCK->LFCLKSTAT & regmsk) == regval) { - break; - } - } - } - } #endif if (MYNEWT_VAL(MCU_HFCLCK192_DIV) == 1) { NRF_CLOCK->HFCLK192MCTRL = 0;