29#if CFG_TUD_ENABLED && CFG_TUSB_MCU == OPT_MCU_NRF5X
35#pragma GCC diagnostic push
36#pragma GCC diagnostic ignored "-Wcast-qual"
37#pragma GCC diagnostic ignored "-Wcast-align"
38#pragma GCC diagnostic ignored "-Wunused-parameter"
43#include "nrfx_usbd_errata.h"
46#pragma GCC diagnostic pop
55#if CFG_TUSB_OS == OPT_OS_MYNEWT
69#ifndef CFG_TUD_NRF_NRFX_VERSION
70 #define _MDK_VERSION (10000*MDK_MAJOR_VERSION + 100*MDK_MINOR_VERSION + MDK_MICRO_VERSION)
72 #if _MDK_VERSION < 82900 || _MDK_VERSION == 83203 || _MDK_VERSION == 84003
74 #define CFG_TUD_NRF_NRFX_VERSION 1
76 #define CFG_TUD_NRF_NRFX_VERSION 2
88 EDPT_END_ALL_MASK = (0xff << USBD_INTEN_ENDEPIN0_Pos) | (0xff << USBD_INTEN_ENDEPOUT0_Pos) |
89 USBD_INTENCLR_ENDISOIN_Msk | USBD_INTEN_ENDISOOUT_Msk
133TU_ATTR_ALWAYS_INLINE
static inline bool is_in_isr(
void) {
134 return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) ? true :
false;
146 if ((reg_startep == &NRF_USBD->TASKS_EP0STATUS) || (reg_startep == &NRF_USBD->TASKS_EP0RCVOUT)) {
147 atomic_flag_clear(&
_dcd.dma_running);
152 if (atomic_flag_test_and_set(&
_dcd.dma_running)) {
161 atomic_flag_clear(&
_dcd.dma_running);
166 return &
_dcd.xfer[epnum][dir];
183 if (atomic_flag_test_and_set(&
_dcd.dma_running)) {
188 xact_len = NRF_USBD->SIZE.ISOOUT;
190 if (xact_len & USBD_SIZE_ISOOUT_ZERO_Msk) {
192 atomic_flag_clear(&
_dcd.dma_running);
196 NRF_USBD->ISOOUT.PTR = (uint32_t)
xfer->
buffer;
197 NRF_USBD->ISOOUT.MAXCNT = xact_len;
201 atomic_flag_clear(&
_dcd.dma_running);
209 NRF_USBD->EPOUT[epnum].PTR = (uint32_t)
xfer->
buffer;
210 NRF_USBD->EPOUT[epnum].MAXCNT = xact_len;
212 start_dma(&NRF_USBD->TASKS_STARTEPOUT[epnum]);
224 NRF_USBD->EPIN[epnum].PTR = (uint32_t)
xfer->
buffer;
225 NRF_USBD->EPIN[epnum].MAXCNT = xact_len;
236 TU_LOG2(
"dcd init\r\n");
242 NVIC_EnableIRQ(USBD_IRQn);
247 NVIC_DisableIRQ(USBD_IRQn);
259 NRF_USBD->EVENTCAUSE |= NRF_USBD->EVENTCAUSE;
260 NRF_USBD->EVENTS_USBEVENT = 0;
262 NRF_USBD->INTENSET = USBD_INTEN_USBEVENT_Msk;
270 NRF_USBD->LOWPOWER = 0;
276 NRF_USBD->USBPULLUP = 0;
286 NRF_USBD->USBPULLUP = 1;
292 _dcd.sof_enabled =
true;
293 NRF_USBD->INTENSET = USBD_INTENSET_SOF_Msk;
295 _dcd.sof_enabled =
false;
296 NRF_USBD->INTENCLR = USBD_INTENCLR_SOF_Msk;
314 NRF_USBD->INTENSET = TU_BIT(USBD_INTEN_ENDEPOUT0_Pos + epnum);
315 NRF_USBD->EPOUTEN |= TU_BIT(epnum);
318 NRF_USBD->SIZE.EPOUT[epnum] = 0;
320 NRF_USBD->INTENSET = TU_BIT(USBD_INTEN_ENDEPIN0_Pos + epnum);
321 NRF_USBD->EPINEN |= TU_BIT(epnum);
324 NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep_addr;
325 NRF_USBD->DTOGGLE = (USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos) | ep_addr;
333 NRF_USBD->EVENTS_ENDISOOUT = 0;
336 if ((NRF_USBD->INTEN & USBD_INTEN_SOF_Msk) == 0) NRF_USBD->EVENTS_SOF = 0;
339 NRF_USBD->INTENSET = USBD_INTENSET_ENDISOOUT_Msk | USBD_INTENSET_SOF_Msk;
340 NRF_USBD->EPOUTEN |= USBD_EPOUTEN_ISOOUT_Msk;
342 NRF_USBD->EVENTS_ENDISOIN = 0;
348 if ((NRF_USBD->INTEN & USBD_INTEN_SOF_Msk) == 0) NRF_USBD->EVENTS_SOF = 0;
351 NRF_USBD->INTENSET = USBD_INTENSET_ENDISOIN_Msk | USBD_INTENSET_SOF_Msk;
352 NRF_USBD->EPINEN |= USBD_EPINEN_ISOIN_Msk;
368 NRF_USBD->INTENCLR = TU_BIT(USBD_INTEN_ENDEPOUT0_Pos + ep) | TU_BIT(USBD_INTEN_ENDEPIN0_Pos + ep);
370 NRF_USBD->TASKS_STARTEPIN[ep] = 0;
371 NRF_USBD->TASKS_STARTEPOUT[ep] = 0;
377 NRF_USBD->INTENCLR = USBD_INTENCLR_SOF_Msk | USBD_INTENCLR_ENDISOOUT_Msk | USBD_INTENCLR_ENDISOIN_Msk;
378 NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_OneDir;
380 NRF_USBD->TASKS_STARTISOIN = 0;
381 NRF_USBD->TASKS_STARTISOOUT = 0;
386 NRF_USBD->EPOUTEN = 1UL;
387 NRF_USBD->EPINEN = 1UL;
401 NRF_USBD->INTENCLR = TU_BIT(USBD_INTEN_ENDEPOUT0_Pos + epnum);
402 NRF_USBD->EPOUTEN &= ~TU_BIT(epnum);
404 NRF_USBD->INTENCLR = TU_BIT(USBD_INTEN_ENDEPIN0_Pos + epnum);
405 NRF_USBD->EPINEN &= ~TU_BIT(epnum);
411 NRF_USBD->INTENCLR = USBD_INTENCLR_ENDISOOUT_Msk;
412 NRF_USBD->EPOUTEN &= ~USBD_EPOUTEN_ISOOUT_Msk;
413 NRF_USBD->EVENTS_ENDISOOUT = 0;
415 NRF_USBD->INTENCLR = USBD_INTENCLR_ENDISOIN_Msk;
416 NRF_USBD->EPINEN &= ~USBD_EPINEN_ISOIN_Msk;
419 NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_OneDir;
422 NRF_USBD->INTENCLR = USBD_INTENCLR_SOF_Msk;
424 _dcd.xfer[epnum][dir].started =
false;
443 bool const control_status = (epnum == 0 &&
total_bytes == 0 && dir !=
tu_edpt_dir(NRF_USBD->BMREQUESTTYPE));
445 if (control_status) {
491 NRF_USBD->TASKS_EP0STALL = 1;
493 NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_Stall << USBD_EPSTALL_STALL_Pos) | ep_addr;
516 NRF_USBD->DTOGGLE = ep_addr;
517 NRF_USBD->DTOGGLE = (USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos) | ep_addr;
520 NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep_addr;
523 if (dir ==
TUSB_DIR_OUT) NRF_USBD->SIZE.EPOUT[epnum] = 0;
535 NRF_USBD->EPOUTEN = 1UL;
536 NRF_USBD->EPINEN = 1UL;
538 for (
int i = 0; i < 8; i++) {
539 NRF_USBD->TASKS_STARTEPIN[i] = 0;
540 NRF_USBD->TASKS_STARTEPOUT[i] = 0;
543 NRF_USBD->TASKS_STARTISOIN = 0;
544 NRF_USBD->TASKS_STARTISOOUT = 0;
547 NRF_USBD->EVENTS_USBEVENT = 0;
548 NRF_USBD->EVENTCAUSE |= NRF_USBD->EVENTCAUSE;
551 NRF_USBD->INTENCLR = NRF_USBD->INTEN;
552 NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_EPDATA_Msk |
553 USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk |
554 USBD_INTEN_ENDEPOUT0_Msk;
564 uint32_t
const inten = NRF_USBD->INTEN;
565 uint32_t int_status = 0;
567 volatile uint32_t* regevt = &NRF_USBD->EVENTS_USBRESET;
569 for (uint8_t i = 0; i < USBD_INTEN_EPDATA_Pos + 1; i++) {
571 int_status |= TU_BIT(i);
580 if (int_status & USBD_INTEN_USBRESET_Msk) {
586 if (int_status & USBD_INTEN_ENDISOIN_Msk) {
595 if (int_status & USBD_INTEN_SOF_Msk) {
596 bool iso_enabled =
false;
599 if (NRF_USBD->EPOUTEN & USBD_EPOUTEN_ISOOUT_Msk) {
602 if ((int_status & USBD_INTEN_USBEVENT_Msk) == 0 ||
603 (NRF_USBD->EVENTCAUSE & USBD_EVENTCAUSE_ISOOUTCRC_Msk) == 0) {
609 if (NRF_USBD->EPINEN & USBD_EPINEN_ISOIN_Msk) {
619 if (!iso_enabled && !
_dcd.sof_enabled) {
623 NRF_USBD->INTENCLR = USBD_INTENCLR_SOF_Msk;
626 const uint32_t frame = NRF_USBD->FRAMECNTR;
631 if (int_status & USBD_INTEN_USBEVENT_Msk) {
632 TU_LOG(3,
"EVENTCAUSE = 0x%04" PRIX32
"\r\n", NRF_USBD->EVENTCAUSE);
635 EVT_CAUSE_MASK = USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk | USBD_EVENTCAUSE_USBWUALLOWED_Msk |
636 USBD_EVENTCAUSE_ISOOUTCRC_Msk
638 uint32_t
const evt_cause = NRF_USBD->EVENTCAUSE & EVT_CAUSE_MASK;
639 NRF_USBD->EVENTCAUSE = evt_cause;
641 if (evt_cause & USBD_EVENTCAUSE_SUSPEND_Msk) {
644 NRF_USBD->LOWPOWER = 1;
649 if (evt_cause & USBD_EVENTCAUSE_USBWUALLOWED_Msk) {
652 NRF_USBD->DPDMVALUE = USBD_DPDMVALUE_STATE_Resume;
653 NRF_USBD->TASKS_DPDMDRIVE = 1;
657 if ((NRF_USBD->INTEN & USBD_INTEN_SOF_Msk) == 0) NRF_USBD->EVENTS_SOF = 0;
658 NRF_USBD->INTENSET = USBD_INTENSET_SOF_Msk;
661 if (evt_cause & USBD_EVENTCAUSE_RESUME_Msk) {
667 if (int_status & USBD_INTEN_EP0SETUP_Msk) {
668 uint8_t
const setup[8] = {
669 NRF_USBD->BMREQUESTTYPE, NRF_USBD->BREQUEST, NRF_USBD->WVALUEL, NRF_USBD->WVALUEH,
670 NRF_USBD->WINDEXL, NRF_USBD->WINDEXH, NRF_USBD->WLENGTHL, NRF_USBD->WLENGTHH
725 for (uint8_t epnum = 0; epnum <
EP_CBI_COUNT + 1; epnum++) {
726 if (
tu_bit_test(int_status, USBD_INTEN_ENDEPOUT0_Pos + epnum)) {
728 uint16_t
const xact_len = NRF_USBD->EPOUT[epnum].AMOUNT;
756 if (int_status & (USBD_INTEN_EPDATA_Msk | USBD_INTEN_EP0DATADONE_Msk)) {
757 uint32_t data_status = NRF_USBD->EPDATASTATUS;
758 NRF_USBD->EPDATASTATUS = data_status;
765 bool const is_control_in = (int_status & USBD_INTEN_EP0DATADONE_Msk) && (NRF_USBD->BMREQUESTTYPE &
TUSB_DIR_IN_MASK);
766 bool const is_control_out = (int_status & USBD_INTEN_EP0DATADONE_Msk) && !(NRF_USBD->BMREQUESTTYPE &
TUSB_DIR_IN_MASK);
769 for (uint8_t epnum = 0; epnum <
EP_CBI_COUNT; epnum++) {
770 if (
tu_bit_test(data_status, epnum) || (epnum == 0 && is_control_in)) {
772 uint8_t
const xact_len = NRF_USBD->EPIN[epnum].AMOUNT;
788 for (uint8_t epnum = 0; epnum <
EP_CBI_COUNT; epnum++) {
789 if (
tu_bit_test(data_status, 16 + epnum) || (epnum == 0 && is_control_out)) {
807#ifdef SOFTDEVICE_PRESENT
814#ifndef SD_MAGIC_NUMBER
815 #define SD_MAGIC_NUMBER 0x51B1E5DB
819 return *((uint32_t*)(SOFTDEVICE_INFO_STRUCT_ADDRESS+4)) == SD_MAGIC_NUMBER;
825 uint8_t sd_en =
false;
826 (void) sd_softdevice_is_enabled(&sd_en);
832#ifdef SOFTDEVICE_PRESENT
834 uint32_t is_running = 0;
835 (void) sd_clock_hfclk_is_running(&is_running);
836 return (is_running ?
true :
false);
840#if CFG_TUD_NRF_NRFX_VERSION == 1
841 return nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY);
843 return nrf_clock_hf_is_running(NRF_CLOCK, NRF_CLOCK_HFCLK_HIGH_ACCURACY);
848#if CFG_TUSB_OS == OPT_OS_MYNEWT
856#ifdef SOFTDEVICE_PRESENT
858 (void)sd_clock_hfclk_request();
863#if CFG_TUD_NRF_NRFX_VERSION == 1
864 nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED);
865 nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTART);
867 nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLKSTARTED);
868 nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTART);
874#if CFG_TUSB_OS == OPT_OS_MYNEWT
879#ifdef SOFTDEVICE_PRESENT
881 (void)sd_clock_hfclk_release();
886#if CFG_TUD_NRF_NRFX_VERSION == 1
887 nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTOP);
889 nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTOP);
907 USB_EVT_DETECTED = 0,
912#if CFG_TUSB_DEBUG >= 3
913 const char*
const power_evt_str[] = {
"Detected",
"Removed",
"Ready"};
914 TU_LOG(3,
"Power USB event: %s\r\n", power_evt_str[event]);
918 case USB_EVT_DETECTED:
919 if (!NRF_USBD->ENABLE) {
921 NRF_USBD->INTENCLR = USBD_INTEN_USBEVENT_Msk;
922 NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk;
928 if (nrfx_usbd_errata_187()) {
930 if (*((
volatile uint32_t*) (0x4006EC00)) == 0x00000000) {
931 *((
volatile uint32_t*) (0x4006EC00)) = 0x00009375;
932 *((
volatile uint32_t*) (0x4006ED14)) = 0x00000003;
933 *((
volatile uint32_t*) (0x4006EC00)) = 0x00009375;
935 *((
volatile uint32_t*) (0x4006ED14)) = 0x00000003;
940 if (nrfx_usbd_errata_171()) {
942 if (*((
volatile uint32_t*) (0x4006EC00)) == 0x00000000) {
943 *((
volatile uint32_t*) (0x4006EC00)) = 0x00009375;
944 *((
volatile uint32_t*) (0x4006EC14)) = 0x000000C0;
945 *((
volatile uint32_t*) (0x4006EC00)) = 0x00009375;
947 *((
volatile uint32_t*) (0x4006EC14)) = 0x000000C0;
954 NRF_USBD->ENABLE = 1;
969 while (!(USBD_EVENTCAUSE_READY_Msk & NRF_USBD->EVENTCAUSE)) {}
971 NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk;
976 if (nrfx_usbd_errata_171()) {
978 if (*((
volatile uint32_t*) (0x4006EC00)) == 0x00000000) {
979 *((
volatile uint32_t*) (0x4006EC00)) = 0x00009375;
980 *((
volatile uint32_t*) (0x4006EC14)) = 0x00000000;
981 *((
volatile uint32_t*) (0x4006EC00)) = 0x00009375;
983 *((
volatile uint32_t*) (0x4006EC14)) = 0x00000000;
989 if (nrfx_usbd_errata_187()) {
991 if (*((
volatile uint32_t*) (0x4006EC00)) == 0x00000000) {
992 *((
volatile uint32_t*) (0x4006EC00)) = 0x00009375;
993 *((
volatile uint32_t*) (0x4006ED14)) = 0x00000000;
994 *((
volatile uint32_t*) (0x4006EC00)) = 0x00009375;
996 *((
volatile uint32_t*) (0x4006ED14)) = 0x00000000;
1001 if (nrfx_usbd_errata_166()) {
1002 *((
volatile uint32_t*) (NRF_USBD_BASE + 0x800)) = 0x7E3;
1003 *((
volatile uint32_t*) (NRF_USBD_BASE + 0x804)) = 0x40;
1011 NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN;
1014 NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk;
1017 NVIC_ClearPendingIRQ(USBD_IRQn);
1023 NVIC_EnableIRQ(USBD_IRQn);
1030 NRF_USBD->USBPULLUP = 1;
1035 case USB_EVT_REMOVED:
1036 if (NRF_USBD->ENABLE) {
1040 NRF_USBD->USBPULLUP = 0;
1045 NVIC_DisableIRQ(USBD_IRQn);
1048 NRF_USBD->INTENCLR = NRF_USBD->INTEN;
1050 NRF_USBD->ENABLE = 0;
static TU_ATTR_ALWAYS_INLINE void dcd_event_bus_signal(uint8_t rhport, dcd_eventid_t eid, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void dcd_event_xfer_complete(uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void dcd_event_sof(uint8_t rhport, uint32_t frame_count, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void dcd_event_setup_received(uint8_t rhport, uint8_t const *setup, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void dcd_event_bus_reset(uint8_t rhport, tusb_speed_t speed, bool in_isr)
static void hfclk_enable(void)
static bool hfclk_running(void)
static void hfclk_disable(void)
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
static void edpt_dma_start(volatile uint32_t *reg_startep)
static void edpt_dma_end(void)
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
void dcd_int_handler(uint8_t rhport)
void dcd_disconnect(uint8_t rhport)
xfer_td_t xfer[EP_CBI_COUNT+1][2]
void dcd_edpt_close_all(uint8_t rhport)
static TU_ATTR_ALWAYS_INLINE bool is_in_isr(void)
void dcd_int_disable(uint8_t rhport)
static TU_ATTR_ALWAYS_INLINE bool is_sd_existed(void)
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
void tusb_hal_nrf_power_event(uint32_t event)
static void xact_in_dma(uint8_t epnum)
void dcd_connect(uint8_t rhport)
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt)
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
static void start_dma(volatile uint32_t *reg_startep)
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
static TU_ATTR_ALWAYS_INLINE bool is_sd_enabled(void)
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init)
static void xact_out_dma_wrapper(void *epnum)
static void xact_out_dma(uint8_t epnum)
static xfer_td_t * get_td(uint8_t epnum, uint8_t dir)
void dcd_int_enable(uint8_t rhport)
void dcd_remote_wakeup(uint8_t rhport)
void dcd_sof_enable(uint8_t rhport, bool en)
AUDIO Channel Cluster Descriptor (4.1)
struct TU_ATTR_PACKED::@16::TU_ATTR_PACKED bmRequestType_bit
uint8_t bmAttributes
See: audio_clock_source_attribute_t.
uint8_t bRequest
Request type audio_cs_req_t.
volatile uint16_t actual_len
bool iso_in_transfer_ready
volatile bool data_received
static TU_ATTR_ALWAYS_INLINE uint16_t tu_min16(uint16_t x, uint16_t y)
static TU_ATTR_ALWAYS_INLINE bool tu_bit_test(uint32_t value, uint8_t pos)
static TU_ATTR_ALWAYS_INLINE uint8_t tu_edpt_number(uint8_t addr)
static TU_ATTR_ALWAYS_INLINE uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const *desc_ep)
TU_ATTR_PACKED_END TU_ATTR_BIT_FIELD_ORDER_END static TU_ATTR_ALWAYS_INLINE tusb_dir_t tu_edpt_dir(uint8_t addr)
void usbd_defer_func(osal_task_func_t func, void *param, bool in_isr)
CFG_TUH_MEM_ALIGN tusb_control_request_t request