From e85ec3fc1190cdfd7866abe8c8ce02aaa4aeba66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Fito=C5=A1?= Date: Sat, 20 May 2023 13:10:01 +0200 Subject: [PATCH] Improved HFCLK management for nRF5x --- CONTRIBUTORS.rst | 5 + src/portable/nordic/nrf5x/dcd_nrf5x.c | 185 ++++++++++++----------- src/portable/nordic/nrf5x/dcd_nrf5x_cb.c | 43 ++++++ src/portable/nordic/nrf5x/dcd_nrf5x_cb.h | 40 +++++ 4 files changed, 188 insertions(+), 85 deletions(-) create mode 100644 src/portable/nordic/nrf5x/dcd_nrf5x_cb.c create mode 100644 src/portable/nordic/nrf5x/dcd_nrf5x_cb.h diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index 50a33ae337..3b07fa74c1 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -93,6 +93,11 @@ Notable contributors - Add new DCD and HCD port for Mentor musb with MSP432E4 - Add new class driver for USB Video Class (UVC 1.5) +`Matej Fitos `__ +----------------------------------------------- + +- Improved HFCLK management for nRF5x + `Nathan Conrad `__ --------------------------------------------- diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index eee5686f41..59ef6ef9d1 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -2,6 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2023 Matej Fitos * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,6 +35,7 @@ #include "nrf_power.h" #include "nrfx_usbd_errata.h" #include "device/dcd.h" +#include "dcd_nrf5x_cb.h" // TODO remove later #include "device/usbd.h" @@ -92,6 +94,91 @@ static struct atomic_bool dma_running; }_dcd; +//--------------------------------------------------------------------+ +// HFCLK helper +//--------------------------------------------------------------------+ +#ifdef SOFTDEVICE_PRESENT + +// For enable/disable hfclk with SoftDevice +#include "nrf_mbr.h" +#include "nrf_sdm.h" +#include "nrf_soc.h" + +#ifndef SD_MAGIC_NUMBER + #define SD_MAGIC_NUMBER 0x51B1E5DB +#endif + +static inline bool is_sd_existed(void) +{ + return *((uint32_t*)(SOFTDEVICE_INFO_STRUCT_ADDRESS+4)) == SD_MAGIC_NUMBER; +} + +// check if SD is existed and enabled +static inline bool is_sd_enabled(void) +{ + if ( !is_sd_existed() ) return false; + + uint8_t sd_en = false; + (void) sd_softdevice_is_enabled(&sd_en); + return sd_en; +} +#endif + +static bool hfclk_running(void) +{ +#ifdef SOFTDEVICE_PRESENT + if ( is_sd_enabled() ) + { + uint32_t is_running = 0; + (void) sd_clock_hfclk_is_running(&is_running); + return (is_running ? true : false); + } +#endif + + return nrf_clock_hf_is_running(NRF_CLOCK, NRF_CLOCK_HFCLK_HIGH_ACCURACY); +} + +static void hfclk_enable(void) +{ +#if CFG_TUSB_OS == OPT_OS_MYNEWT + usb_clock_request(); + return; +#else + + // already running, nothing to do + if ( hfclk_running() ) return; + +#ifdef SOFTDEVICE_PRESENT + if ( is_sd_enabled() ) + { + (void)sd_clock_hfclk_request(); + return; + } +#endif + + dcd_enable_hfclk(); +#endif +} + +static void hfclk_disable(void) +{ +#if CFG_TUSB_OS == OPT_OS_MYNEWT + usb_clock_release(); + return; +#else + +#ifdef SOFTDEVICE_PRESENT + if ( is_sd_enabled() ) + { + (void)sd_clock_hfclk_release(); + return; + } +#endif + + dcd_disable_hfclk(); +#endif +} + /*------------------------------------------------------------------*/ /* Control / Bulk / Interrupt (CBI) Transfer *------------------------------------------------------------------*/ @@ -233,6 +320,18 @@ static void xact_in_dma(uint8_t epnum) void dcd_init (uint8_t rhport) { TU_LOG1("dcd init\r\n"); + +#ifdef SOFTDEVICE_PRESENT + if(!is_sd_enabled()){ +#endif + if(NRF_POWER->USBREGSTATUS & POWER_USBREGSTATUS_VBUSDETECT_Msk){ + //Bootloader already initialized USB + dcd_enable_hfclk(); //Just reserving HFCLK + } +#ifdef SOFTDEVICE_PRESENT + } +#endif + (void) rhport; } @@ -859,92 +958,8 @@ void dcd_int_handler(uint8_t rhport) } //--------------------------------------------------------------------+ -// HFCLK helper -//--------------------------------------------------------------------+ -#ifdef SOFTDEVICE_PRESENT - -// For enable/disable hfclk with SoftDevice -#include "nrf_mbr.h" -#include "nrf_sdm.h" -#include "nrf_soc.h" - -#ifndef SD_MAGIC_NUMBER - #define SD_MAGIC_NUMBER 0x51B1E5DB -#endif - -static inline bool is_sd_existed(void) -{ - return *((uint32_t*)(SOFTDEVICE_INFO_STRUCT_ADDRESS+4)) == SD_MAGIC_NUMBER; -} - -// check if SD is existed and enabled -static inline bool is_sd_enabled(void) -{ - if ( !is_sd_existed() ) return false; - - uint8_t sd_en = false; - (void) sd_softdevice_is_enabled(&sd_en); - return sd_en; -} -#endif - -static bool hfclk_running(void) -{ -#ifdef SOFTDEVICE_PRESENT - if ( is_sd_enabled() ) - { - uint32_t is_running = 0; - (void) sd_clock_hfclk_is_running(&is_running); - return (is_running ? true : false); - } -#endif - - return nrf_clock_hf_is_running(NRF_CLOCK, NRF_CLOCK_HFCLK_HIGH_ACCURACY); -} - -static void hfclk_enable(void) -{ -#if CFG_TUSB_OS == OPT_OS_MYNEWT - usb_clock_request(); - return; -#else - - // already running, nothing to do - if ( hfclk_running() ) return; - -#ifdef SOFTDEVICE_PRESENT - if ( is_sd_enabled() ) - { - (void)sd_clock_hfclk_request(); - return; - } -#endif - - nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLKSTARTED); - nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTART); -#endif -} - -static void hfclk_disable(void) -{ -#if CFG_TUSB_OS == OPT_OS_MYNEWT - usb_clock_release(); - return; -#else - -#ifdef SOFTDEVICE_PRESENT - if ( is_sd_enabled() ) - { - (void)sd_clock_hfclk_release(); - return; - } -#endif - - nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTOP); -#endif -} - // Power & Clock Peripheral on nRF5x to manage USB +//--------------------------------------------------------------------+ // // USB Bus power is managed by Power module, there are 3 VBUS power events: // Detected, Ready, Removed. Upon these power events, This function will diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x_cb.c b/src/portable/nordic/nrf5x/dcd_nrf5x_cb.c new file mode 100644 index 0000000000..4b4842d0c5 --- /dev/null +++ b/src/portable/nordic/nrf5x/dcd_nrf5x_cb.c @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 Matej Fitoš + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "dcd_nrf5x_cb.h" +#include "nrf.h" +#include "nrf_clock.h" + +//Do not forget to include dcd_nrf5x_cb.h file in the code file, where funtion will be overridden + +//Override this function, to manage HFCLK activation by your own code +//This function is called only when SoftDevice is not present +__WEAK void dcd_enable_hfclk(void){ + nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLKSTARTED); + nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTART); +} + +//Override this function, to manage HFCLK deactivation by your own code +//This function is called only when SoftDevice is not present +__WEAK void dcd_disable_hfclk(void){ + nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTOP); +} \ No newline at end of file diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x_cb.h b/src/portable/nordic/nrf5x/dcd_nrf5x_cb.h new file mode 100644 index 0000000000..034d0d183d --- /dev/null +++ b/src/portable/nordic/nrf5x/dcd_nrf5x_cb.h @@ -0,0 +1,40 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023, Matej Fitoš + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef DCD_NRF5X_H_ +#define DCD_NRF5X_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +void dcd_enable_hfclk(void); + +void dcd_disable_hfclk(void); + +#ifdef __cplusplus + } +#endif + +#endif /* DCD_NRF5X_H_ */