diff --git a/tinyusb/portable/nordic/nrf5x/dcd_nrf5x.c b/tinyusb/portable/nordic/nrf5x/dcd_nrf5x.c index 454db01b..c8e2ec4f 100644 --- a/tinyusb/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/tinyusb/portable/nordic/nrf5x/dcd_nrf5x.c @@ -42,7 +42,6 @@ #include "nrf_usbd.h" #include "nrf_clock.h" -#include "nrf_drv_power.h" #include "nrf_drv_usbd_errata.h" #include "device/dcd.h" @@ -91,146 +90,6 @@ typedef struct volatile bool dma_running; }_dcd; -/*------------------------------------------------------------------*/ -/* Controller Start up Sequence - *------------------------------------------------------------------*/ - -static bool is_sd_enabled(void) -{ -#ifdef SOFTDEVICE_PRESENT - uint8_t sd_en = 0; - (void) sd_softdevice_is_enabled(&sd_en); - - return sd_en; -#else - return false; -#endif -} - -static bool hfclk_running(void) -{ -#ifdef SOFTDEVICE_PRESENT - if ( is_sd_enabled() ) - { - uint32_t is_running; - (void) sd_clock_hfclk_is_running(&is_running); - return (is_running ? true : false); - } -#endif - - return nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY); -} - -static void hfclk_enable(void) -{ - // 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_EVENT_HFCLKSTARTED); - nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTART); -} - -static void hfclk_disable(void) -{ -#ifdef SOFTDEVICE_PRESENT - if ( is_sd_enabled() ) - { - (void)sd_clock_hfclk_release(); - return; - } -#endif // SOFTDEVICE_PRESENT - - nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTOP); -} - -static void power_usb_event_handler(nrf_drv_power_usb_evt_t event) -{ - // 51.4 specs USBD start-up sequene - switch ( event ) - { - case NRF_DRV_POWER_USB_EVT_DETECTED: - if ( !NRF_USBD->ENABLE ) - { - /* Prepare for READY event receiving */ - nrf_usbd_eventcause_clear(NRF_USBD_EVENTCAUSE_READY_MASK); - - /* Enable the peripheral */ - nrf_usbd_enable(); - - // Enable HFCLK - hfclk_enable(); - - /* Waiting for peripheral to enable, this should take a few us */ - while ( !(NRF_USBD_EVENTCAUSE_READY_MASK & NRF_USBD->EVENTCAUSE) ) { } - nrf_usbd_eventcause_clear(NRF_USBD_EVENTCAUSE_READY_MASK); - nrf_usbd_event_clear(NRF_USBD_EVENT_USBEVENT); - } - break; - - case NRF_DRV_POWER_USB_EVT_READY: - // Wait for HFCLK - while ( !hfclk_running() ) {} - - if ( nrf_drv_usbd_errata_166() ) - { - *((volatile uint32_t *) (NRF_USBD_BASE + 0x800)) = 0x7E3; - *((volatile uint32_t *) (NRF_USBD_BASE + 0x804)) = 0x40; - - __ISB(); __DSB(); - } - - nrf_usbd_isosplit_set(NRF_USBD_ISOSPLIT_Half); - - // Enable interrupt. SOF is used as CDC auto flush - NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_ACCESSFAULT_Msk | - USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk | - USBD_INTEN_EPDATA_Msk | USBD_INTEN_SOF_Msk; - - // if (enable_sof || nrf_drv_usbd_errata_104()) - // { - // ints_to_enable |= NRF_USBD_INT_SOF_MASK; - // } - - // Enable interrupt, Priorities 0,1,4,5 (nRF52) are reserved for SoftDevice - NVIC_SetPriority(USBD_IRQn, 7); - NVIC_ClearPendingIRQ(USBD_IRQn); - NVIC_EnableIRQ(USBD_IRQn); - - // Enable pull up - nrf_usbd_pullup_enable(); - break; - - case NRF_DRV_POWER_USB_EVT_REMOVED: - if ( NRF_USBD->ENABLE ) - { - // Abort all transfers - - // Disable pull up - nrf_usbd_pullup_disable(); - - // Disable Interrupt - NVIC_DisableIRQ(USBD_IRQn); - - // disable all interrupt - NRF_USBD->INTENCLR = NRF_USBD->INTEN; - - nrf_usbd_disable(); - hfclk_disable(); - } - break; - - default: break; - } -} - void bus_reset(void) { for(int i=0; i<8; i++) @@ -250,12 +109,7 @@ void bus_reset(void) *------------------------------------------------------------------*/ bool dcd_init (uint8_t rhport) { - // USB Power detection - const nrf_drv_power_usbevt_config_t config = - { - .handler = power_usb_event_handler - }; - return ( NRF_SUCCESS == nrf_drv_power_usbevt_init(&config) ); + (void) rhport; } void dcd_connect (uint8_t rhport) diff --git a/tinyusb/portable/nordic/nrf5x/hal_nrf5x.c b/tinyusb/portable/nordic/nrf5x/hal_nrf5x.c index e3d27e55..4d147e3c 100644 --- a/tinyusb/portable/nordic/nrf5x/hal_nrf5x.c +++ b/tinyusb/portable/nordic/nrf5x/hal_nrf5x.c @@ -40,6 +40,9 @@ #include "nrf.h" #include "nrf_gpio.h" #include "nrf_clock.h" +#include "nrf_drv_power.h" +#include "nrf_usbd.h" +#include "nrf_drv_usbd_errata.h" #include "tusb_hal.h" @@ -47,19 +50,26 @@ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ - /*------------------------------------------------------------------*/ /* VARIABLE DECLARATION *------------------------------------------------------------------*/ +static void power_usb_event_handler(uint32_t event); /*------------------------------------------------------------------*/ /* FUNCTION DECLARATION *------------------------------------------------------------------*/ - - bool tusb_hal_init(void) { - return true; +#ifndef SOFTDEVICE_PRESENT + // USB Power detection + const nrf_drv_power_usbevt_config_t config = + { + .handler = power_usb_event_handler + }; + return ( NRF_SUCCESS == nrf_drv_power_usbevt_init(&config) ); +#else + +#endif } void tusb_hal_int_enable(uint8_t rhport) @@ -74,4 +84,145 @@ void tusb_hal_int_disable(uint8_t rhport) NVIC_DisableIRQ(USBD_IRQn); } +/*------------------------------------------------------------------*/ +/* Controller Start up Sequence + *------------------------------------------------------------------*/ + +/*------------- HFCLK helper -------------*/ +static bool is_sd_enabled(void) +{ +#ifdef SOFTDEVICE_PRESENT + uint8_t sd_en = 0; + (void) sd_softdevice_is_enabled(&sd_en); + + return sd_en; +#else + return false; +#endif +} + +static bool hfclk_running(void) +{ +#ifdef SOFTDEVICE_PRESENT + if ( is_sd_enabled() ) + { + uint32_t is_running; + (void) sd_clock_hfclk_is_running(&is_running); + return (is_running ? true : false); + } +#endif + + return nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY); +} + +static void hfclk_enable(void) +{ + // 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_EVENT_HFCLKSTARTED); + nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTART); +} + +static void hfclk_disable(void) +{ +#ifdef SOFTDEVICE_PRESENT + if ( is_sd_enabled() ) + { + (void)sd_clock_hfclk_release(); + return; + } +#endif + + nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTOP); +} + +/*------------- 51.4 specs USBD start-up sequene -------------*/ +static void power_usb_event_handler(uint32_t event) +{ + switch ( event ) + { + case NRF_DRV_POWER_USB_EVT_DETECTED: + if ( !NRF_USBD->ENABLE ) + { + /* Prepare for READY event receiving */ + nrf_usbd_eventcause_clear(NRF_USBD_EVENTCAUSE_READY_MASK); + + /* Enable the peripheral */ + nrf_usbd_enable(); + + // Enable HFCLK + hfclk_enable(); + + /* Waiting for peripheral to enable, this should take a few us */ + while ( !(NRF_USBD_EVENTCAUSE_READY_MASK & NRF_USBD->EVENTCAUSE) ) { } + nrf_usbd_eventcause_clear(NRF_USBD_EVENTCAUSE_READY_MASK); + nrf_usbd_event_clear(NRF_USBD_EVENT_USBEVENT); + } + break; + + case NRF_DRV_POWER_USB_EVT_READY: + // Wait for HFCLK + while ( !hfclk_running() ) {} + + if ( nrf_drv_usbd_errata_166() ) + { + *((volatile uint32_t *) (NRF_USBD_BASE + 0x800)) = 0x7E3; + *((volatile uint32_t *) (NRF_USBD_BASE + 0x804)) = 0x40; + + __ISB(); __DSB(); + } + + nrf_usbd_isosplit_set(NRF_USBD_ISOSPLIT_Half); + + // Enable interrupt. SOF is used as CDC auto flush + NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_ACCESSFAULT_Msk | + USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk | + USBD_INTEN_EPDATA_Msk | USBD_INTEN_SOF_Msk; + + // if (enable_sof || nrf_drv_usbd_errata_104()) + // { + // ints_to_enable |= NRF_USBD_INT_SOF_MASK; + // } + + // Enable interrupt, Priorities 0,1,4,5 (nRF52) are reserved for SoftDevice + NVIC_SetPriority(USBD_IRQn, 7); + NVIC_ClearPendingIRQ(USBD_IRQn); + NVIC_EnableIRQ(USBD_IRQn); + + // Enable pull up + nrf_usbd_pullup_enable(); + break; + + case NRF_DRV_POWER_USB_EVT_REMOVED: + if ( NRF_USBD->ENABLE ) + { + // Abort all transfers + + // Disable pull up + nrf_usbd_pullup_disable(); + + // Disable Interrupt + NVIC_DisableIRQ(USBD_IRQn); + + // disable all interrupt + NRF_USBD->INTENCLR = NRF_USBD->INTEN; + + nrf_usbd_disable(); + hfclk_disable(); + } + break; + + default: break; + } +} + #endif