1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321 |
- #include <stddef.h>
- #include <mdk/nrf52840_bitfields.h>
- #include "nrf52840.h"
- #include "usb_def.h"
- #include "usb_dc.h"
- #include "usbd_core.h"
- #ifndef USBD_IRQHandler
- #define USBD_IRQHandler USBD_IRQHandler /*!< Use actual usb irq name instead */
- #endif
- #ifndef USBD_CONFIG_ISO_IN_ZLP
- #define USBD_CONFIG_ISO_IN_ZLP 0
- #endif
- /*!< The default platform is NRF52840 */
- #define NRF52_SERIES
- /*!< Ep nums */
- #define EP_NUMS 9
- /*!< Ep mps */
- #define EP_MPS 64
- /*!< Nrf5x special */
- #define EP_ISO_NUM 8
- /*!< USBD peripheral address base */
- #define NRF_USBD_BASE 0x40027000UL
- /*!< Clock peripheral address base */
- #define NRF_CLOCK_BASE 0x40000000UL
- #define USBD_IRQn 39
- #ifndef EP_ISO_MPS
- #define EP_ISO_MPS 64
- #endif
- #define CHECK_ADD_IS_RAM(address) ((((uint32_t)address) & 0xE0000000u) == 0x20000000u) ? 1 : 0
- /**
- * @brief Endpoint information structure
- */
- typedef struct _usbd_ep_info
- {
- uint16_t mps; /*!< Maximum packet length of endpoint */
- uint8_t eptype; /*!< Endpoint Type */
- uint8_t ep_stalled; /* Endpoint stall flag */
- uint8_t ep_enable; /* Endpoint enable */
- uint8_t *xfer_buf;
- uint32_t xfer_len;
- uint32_t actual_xfer_len;
- uint8_t ep_buffer[EP_MPS];
- /*!< Other endpoint parameters that may be used */
- volatile uint8_t is_using_dma;
- volatile uint8_t add_flag;
- } usbd_ep_info;
- /*!< nrf52840 usb */
- struct _nrf52840_core_prvi
- {
- uint8_t address; /*!< address */
- usbd_ep_info ep_in[EP_NUMS]; /*!< ep in */
- usbd_ep_info ep_out[EP_NUMS]; /*!< ep out */
- struct usb_setup_packet setup; /*!< Setup package that may be used in interrupt processing (outside the protocol stack) */
- volatile uint8_t dma_running;
- int8_t in_count;
- volatile uint8_t iso_turn;
- volatile uint8_t iso_tx_is_ready;
- /**
- * For nrf5x, easydma will not move the setup packet into RAM.
- * We use a flag bit to judge whether the host sends setup,
- * and then notify usbd_ep_read to and from the register to read the setup package
- */
- volatile uint8_t is_setup_packet;
- } usb_dc_cfg;
- __WEAK void usb_dc_low_level_pre_init(void)
- {
- }
- __WEAK void usb_dc_low_level_post_init(void)
- {
- }
- __WEAK void usb_dc_low_level_deinit(void)
- {
- }
- /**@brief Usbds the set remote wakeup.
- *
- * @param[in] busid do not used
- *
- * @retval
- */
- int usbd_set_remote_wakeup (uint8_t busid)
- {
- //TOGGLE_GPIOA9();
- //#TASK 1.唤醒使能+挂起标志+休眠标志
- // USB->CNTR |= (uint16_t)USB_CNTR_RESUME;
- return -1;
- }
- /**
- * @brief Get setup package
- * @pre None
- * @param[in] setup Pointer to the address where the setup package is stored
- * @retval None
- */
- static inline void get_setup_packet(struct usb_setup_packet *setup)
- {
- setup->bmRequestType = (uint8_t)(NRF_USBD->BMREQUESTTYPE);
- setup->bRequest = (uint8_t)(NRF_USBD->BREQUEST);
- setup->wIndex = (uint16_t)(NRF_USBD->WINDEXL | ((NRF_USBD->WINDEXH) << 8));
- setup->wLength = (uint16_t)(NRF_USBD->WLENGTHL | ((NRF_USBD->WLENGTHH) << 8));
- setup->wValue = (uint16_t)(NRF_USBD->WVALUEL | ((NRF_USBD->WVALUEH) << 8));
- }
- /**
- * @brief Set tx easydma
- * @pre None
- * @param[in] ep End point address
- * @param[in] ptr Data ram ptr
- * @param[in] maxcnt Max length
- * @retval None
- */
- static void nrf_usbd_ep_easydma_set_tx(uint8_t ep, uint32_t ptr, uint32_t maxcnt)
- {
- uint8_t epid = USB_EP_GET_IDX(ep);
- if (epid == EP_ISO_NUM)
- {
- NRF_USBD->ISOIN.PTR = ptr;
- NRF_USBD->ISOIN.MAXCNT = maxcnt;
- return;
- }
- NRF_USBD->EPIN[epid].PTR = ptr;
- NRF_USBD->EPIN[epid].MAXCNT = maxcnt;
- }
- /**
- * @brief Set rx easydma
- * @pre None
- * @param[in] ep End point address
- * @param[in] ptr Data ram ptr
- * @param[in] maxcnt Max length
- * @retval None
- */
- static void nrf_usbd_ep_easydma_set_rx(uint8_t ep, uint32_t ptr, uint32_t maxcnt)
- {
- uint8_t epid = USB_EP_GET_IDX(ep);
- if (epid == EP_ISO_NUM)
- {
- NRF_USBD->ISOOUT.PTR = ptr;
- NRF_USBD->ISOOUT.MAXCNT = maxcnt;
- return;
- }
- NRF_USBD->EPOUT[epid].PTR = ptr;
- NRF_USBD->EPOUT[epid].MAXCNT = maxcnt;
- }
- /**@brief Usbds the set address.
- *
- * @param[in] usbid do not used
- * @param[in] address 8-bit valid address
- *
- * @retval >=0 success otherwise failureSet addressNone
- */
- int usbd_set_address(uint8_t usbid, const uint8_t address)
- {
- if (address == 0)
- {
- /*!< init 0 address */
- }
- else
- {
- /*!< For non-0 addresses, write the address to the register in the state phase of setting the address */
- }
- NRF_USBD->EVENTCAUSE |= NRF_USBD->EVENTCAUSE;
- NRF_USBD->EVENTS_USBEVENT = 0;
- NRF_USBD->INTENSET = USBD_INTEN_USBEVENT_Msk;
- /*!< nothing to do, handled by hardware; but don't STALL */
- usb_dc_cfg.address = address;
- return 0;
- }
- uint8_t usbd_get_port_speed(const uint8_t port)
- {
- return USB_SPEED_FULL;
- }
- /**@brief Usbds the ep open.
- *
- * @param[in] busid do not used
- * @param[in] ep_cfg Endpoint configuration structure pointer
- *
- * @retval >=0 success otherwise failureOpen endpointNone
- */
- int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep_cfg)
- {
- /*!< ep id */
- uint8_t epid = USB_EP_GET_IDX(ep_cfg->bEndpointAddress);
- /*!< ep max packet length */
- uint16_t mps = ep_cfg->wMaxPacketSize;
- if (USB_EP_DIR_IS_IN(ep_cfg->bEndpointAddress))
- {
- /*!< In */
- usb_dc_cfg.ep_in[epid].mps = mps;
- usb_dc_cfg.ep_in[epid].eptype = ep_cfg->bmAttributes;
- usb_dc_cfg.ep_in[epid].ep_enable = true;
- /*!< Open ep */
- if (ep_cfg->bmAttributes != USB_ENDPOINT_TYPE_ISOCHRONOUS)
- {
- /*!< Enable endpoint interrupt */
- NRF_USBD->INTENSET = (1 << (USBD_INTEN_ENDEPIN0_Pos + epid));
- /*!< Enable the in endpoint host to respond when sending in token */
- NRF_USBD->EPINEN |= (1 << (epid));
- __ISB();
- __DSB();
- }
- else
- {
- NRF_USBD->EVENTS_ENDISOIN = 0;
- /*!< SPLIT ISO buffer when ISO OUT endpoint is already opened. */
- if (usb_dc_cfg.ep_out[EP_ISO_NUM].mps)
- NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN;
- /*!< Clear SOF event in case interrupt was not enabled yet. */
- if ((NRF_USBD->INTEN & USBD_INTEN_SOF_Msk) == 0)
- NRF_USBD->EVENTS_SOF = 0;
- /*!< Enable SOF and ISOIN interrupts, and ISOIN endpoint. */
- NRF_USBD->INTENSET = USBD_INTENSET_ENDISOIN_Msk | USBD_INTENSET_SOF_Msk;
- NRF_USBD->EPINEN |= USBD_EPINEN_ISOIN_Msk;
- }
- }
- else if (USB_EP_DIR_IS_OUT(ep_cfg->bEndpointAddress))
- {
- /*!< Out */
- usb_dc_cfg.ep_out[epid].mps = mps;
- usb_dc_cfg.ep_out[epid].eptype = ep_cfg->bmAttributes;
- usb_dc_cfg.ep_out[epid].ep_enable = true;
- /*!< Open ep */
- if (ep_cfg->bmAttributes != USB_ENDPOINT_TYPE_ISOCHRONOUS)
- {
- NRF_USBD->INTENSET = (1 << (USBD_INTEN_ENDEPOUT0_Pos + epid));
- NRF_USBD->EPOUTEN |= (1 << (epid));
- __ISB();
- __DSB();
- /*!< Write any value to SIZE register will allow nRF to ACK/accept data */
- NRF_USBD->SIZE.EPOUT[epid] = 0;
- }
- else
- {
- /*!< SPLIT ISO buffer when ISO IN endpoint is already opened. */
- if (usb_dc_cfg.ep_in[EP_ISO_NUM].mps)
- NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN;
- /*!< Clear old events */
- NRF_USBD->EVENTS_ENDISOOUT = 0;
- /*!< Clear SOF event in case interrupt was not enabled yet. */
- if ((NRF_USBD->INTEN & USBD_INTEN_SOF_Msk) == 0)
- NRF_USBD->EVENTS_SOF = 0;
- /*!< Enable SOF and ISOOUT interrupts, and ISOOUT endpoint. */
- NRF_USBD->INTENSET = USBD_INTENSET_ENDISOOUT_Msk | USBD_INTENSET_SOF_Msk;
- NRF_USBD->EPOUTEN |= USBD_EPOUTEN_ISOOUT_Msk;
- }
- }
- /*!< Clear stall and reset DataToggle */
- NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | (ep_cfg->bEndpointAddress);
- NRF_USBD->DTOGGLE = (USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos) | (ep_cfg->bEndpointAddress);
- __ISB();
- __DSB();
- return 0;
- }
- /**@brief Usbds the ep close.
- *
- * @param[in] busid do not used
- * @param[in] ep ep : Endpoint address
- *
- * @retval >=0 success otherwise failureClose endpointNone
- */
- int usbd_ep_close(uint8_t busid, const uint8_t ep)
- {
- /*!< ep id */
- uint8_t epid = USB_EP_GET_IDX(ep);
- if (epid != EP_ISO_NUM)
- {
- if (USB_EP_DIR_IS_OUT(ep))
- {
- usb_dc_cfg.ep_out[epid].ep_enable = false;
- NRF_USBD->INTENCLR = (1 << (USBD_INTEN_ENDEPOUT0_Pos + epid));
- NRF_USBD->EPOUTEN &= ~(1 << (epid));
- }
- else
- {
- usb_dc_cfg.ep_in[epid].ep_enable = false;
- NRF_USBD->INTENCLR = (1 << (USBD_INTEN_ENDEPIN0_Pos + epid));
- NRF_USBD->EPINEN &= ~(1 << (epid));
- }
- }
- else
- {
- /*!< ISO EP */
- if (USB_EP_DIR_IS_OUT(ep))
- {
- usb_dc_cfg.ep_out[epid].ep_enable = false;
- usb_dc_cfg.ep_out[EP_ISO_NUM].mps = 0;
- NRF_USBD->INTENCLR = USBD_INTENCLR_ENDISOOUT_Msk;
- NRF_USBD->EPOUTEN &= ~USBD_EPOUTEN_ISOOUT_Msk;
- NRF_USBD->EVENTS_ENDISOOUT = 0;
- }
- else
- {
- usb_dc_cfg.ep_in[epid].ep_enable = false;
- usb_dc_cfg.ep_in[EP_ISO_NUM].mps = 0;
- NRF_USBD->INTENCLR = USBD_INTENCLR_ENDISOIN_Msk;
- NRF_USBD->EPINEN &= ~USBD_EPINEN_ISOIN_Msk;
- }
- /*!< One of the ISO endpoints closed, no need to split buffers any more. */
- NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_OneDir;
- /*!< When both ISO endpoint are close there is no need for SOF any more. */
- if (usb_dc_cfg.ep_in[EP_ISO_NUM].mps + usb_dc_cfg.ep_out[EP_ISO_NUM].mps == 0)
- {
- NRF_USBD->INTENCLR = USBD_INTENCLR_SOF_Msk;
- }
- }
- __ISB();
- __DSB();
- return 0;
- }
- /**
- * @brief Setup in ep transfer setting and start transfer.
- *
- * This function is asynchronous.
- * This function is similar to uart with tx dma.
- *
- * This function is called to write data to the specified endpoint. The
- * supplied usbd_endpoint_callback function will be called when data is transmitted
- * out.
- *
- * @param[in] busid do not used
- * @param[in] ep Endpoint address corresponding to the one
- * listed in the device configuration table
- * @param[in] data Pointer to data to write
- * @param[in] data_len Length of the data requested to write. This may
- * be zero for a zero length status packet.
- * @return 0 on success, negative errno code on fail.
- */
- int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
- {
- uint8_t ep_idx = USB_EP_GET_IDX(ep);
- if (!data && data_len)
- {
- return -1;
- }
- if (!usb_dc_cfg.ep_in[ep_idx].ep_enable)
- {
- return -2;
- }
- if ((uint32_t)data & 0x03)
- {
- return -3;
- }
- usb_dc_cfg.ep_in[ep_idx].xfer_buf = (uint8_t *)data;
- usb_dc_cfg.ep_in[ep_idx].xfer_len = data_len;
- usb_dc_cfg.ep_in[ep_idx].actual_xfer_len = 0;
- if (data_len == 0)
- {
- /*!< write 0 len data */
- nrf_usbd_ep_easydma_set_tx(ep_idx, (uint32_t)NULL, 0);
- NRF_USBD->TASKS_STARTEPIN[ep_idx] = 1;
- }
- else
- {
- /*!< Not zlp */
- data_len = MIN(data_len, usb_dc_cfg.ep_in[ep_idx].mps);
- if (!CHECK_ADD_IS_RAM(data))
- {
- /*!< Data is not in ram */
- /*!< Memcpy data to ram */
- memcpy(usb_dc_cfg.ep_in[ep_idx].ep_buffer, data, data_len);
- nrf_usbd_ep_easydma_set_tx(ep_idx, (uint32_t)usb_dc_cfg.ep_in[ep_idx].ep_buffer, data_len);
- }
- else
- {
- nrf_usbd_ep_easydma_set_tx(ep_idx, (uint32_t)data, data_len);
- }
- /**
- * Note that starting DMA transmission is to transmit data to USB peripherals,
- * and then wait for the host to get it
- */
- /*!< Start dma transfer */
- if (ep_idx != EP_ISO_NUM)
- {
- NRF_USBD->TASKS_STARTEPIN[ep_idx] = 1;
- }
- else
- {
- // NRF_USBD->TASKS_STARTISOIN = 1;
- usb_dc_cfg.iso_tx_is_ready = 1;
- }
- }
- return 0;
- }
- /**
- * @brief Setup out ep transfer setting and start transfer.
- *
- * This function is asynchronous.
- * This function is similar to uart with rx dma.
- *
- * This function is called to read data to the specified endpoint. The
- * supplied usbd_endpoint_callback function will be called when data is received
- * in.
- *
- * @param[in] busid do not used
- * @param[in] ep Endpoint address corresponding to the one
- * listed in the device configuration table
- * @param[in] data Pointer to data to read
- * @param[in] data_len Max length of the data requested to read.
- *
- * @return 0 on success, negative errno code on fail.
- */
- int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
- {
- uint8_t ep_idx = USB_EP_GET_IDX(ep);
- if (!data && data_len)
- {
- return -1;
- }
- if (!usb_dc_cfg.ep_out[ep_idx].ep_enable)
- {
- return -2;
- }
- if ((uint32_t)data & 0x03)
- {
- return -3;
- }
- usb_dc_cfg.ep_out[ep_idx].xfer_buf = (uint8_t *)data;
- usb_dc_cfg.ep_out[ep_idx].xfer_len = data_len;
- usb_dc_cfg.ep_out[ep_idx].actual_xfer_len = 0;
- if (data_len == 0)
- {
- return 0;
- }
- else
- {
- data_len = MIN(data_len, usb_dc_cfg.ep_out[ep_idx].mps);
- if (!CHECK_ADD_IS_RAM(data))
- {
- /*!< Data address is not in ram */
- // TODO:
- }
- else
- {
- if (ep_idx == 0)
- {
- NRF_USBD->TASKS_EP0RCVOUT = 1;
- }
- nrf_usbd_ep_easydma_set_rx(ep_idx, (uint32_t)data, data_len);
- }
- }
- return 0;
- }
- /**
- * @brief Endpoint setting pause
- * @pre None
- * @param[in] busid do not used
- * @param[in] ep : Endpoint address
- * @retval >=0 success otherwise failure
- */
- int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
- {
- /*!< ep id */
- uint8_t epid = USB_EP_GET_IDX(ep);
- if (epid == 0)
- {
- NRF_USBD->TASKS_EP0STALL = 1;
- }
- else if (epid != EP_ISO_NUM)
- {
- NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_Stall << USBD_EPSTALL_STALL_Pos) | (ep);
- }
- __ISB();
- __DSB();
- return 0;
- }
- /**
- * @brief Endpoint clear pause
- * @pre None
- * @param[in] busid do not used
- * @param[in] ep : Endpoint address
- * @retval >=0 success otherwise failure
- */
- int usbd_ep_clear_stall(uint8_t usbid, const uint8_t ep)
- {
- /*!< ep id */
- uint8_t epid = USB_EP_GET_IDX(ep);
- if (epid != 0 && epid != EP_ISO_NUM)
- {
- /**
- * reset data toggle to DATA0
- * First write this register with VALUE=Nop to select the endpoint, then either read it to get the status from
- * VALUE, or write it again with VALUE=Data0 or Data1
- */
- NRF_USBD->DTOGGLE = ep;
- NRF_USBD->DTOGGLE = (USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos) | ep;
- /*!< Clear stall */
- NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep;
- /*!< Write any value to SIZE register will allow nRF to ACK/accept data */
- if (USB_EP_DIR_IS_OUT(ep))
- NRF_USBD->SIZE.EPOUT[epid] = 0;
- __ISB();
- __DSB();
- }
- return 0;
- }
- /**
- * @brief Check endpoint status
- * @pre None
- * @param[in] busid do not used
- * @param[in] ep : Endpoint address
- * @param[out] stalled : Outgoing endpoint status
- * @retval >=0 success otherwise failure
- */
- int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
- {
- return 0;
- }
- /**
- * @brief USB initialization
- * @pre None
- * @param[in] busid do not used
- * @retval >=0 success otherwise failure
- */
- int usb_dc_init(uint8_t busid)
- {
- /*!< dc init */
- usb_dc_low_level_pre_init();
- memset(&usb_dc_cfg, 0, sizeof(usb_dc_cfg));
- /*!< Clear USB Event Interrupt */
- NRF_USBD->EVENTS_USBEVENT = 0;
- NRF_USBD->EVENTCAUSE |= NRF_USBD->EVENTCAUSE;
- /*!< Reset interrupt */
- NRF_USBD->INTENCLR = NRF_USBD->INTEN;
- NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_EPDATA_Msk |
- USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk | USBD_INTEN_STARTED_Msk;
- usb_dc_low_level_post_init();
- return 0;
- }
- /**
- * @brief USB deinit
- * @pre None
- * @param[in] busid do not used
- * @retval >=0 success otherwise failure
- */
- int usb_dc_deinit(uint8_t busid)
- {
- /*!< dc deinit */
- return 0;
- }
- /**
- * @brief USB interrupt processing function
- * @pre None
- * @param[in] None
- * @retval None
- */
- void USBD_IRQHandler(void)
- {
- uint32_t const inten = NRF_USBD->INTEN;
- uint32_t int_status = 0;
- volatile uint32_t usb_event = 0;
- volatile uint32_t *regevt = &NRF_USBD->EVENTS_USBRESET;
- /*!< Traverse USB events */
- for (uint8_t i = 0; i < USBD_INTEN_EPDATA_Pos + 1; i++)
- {
- if ((inten & (1 << i)) && regevt[i])
- {
- int_status |= (1 << (i));
- /*!< event clear */
- regevt[i] = 0;
- __ISB();
- __DSB();
- }
- }
- /*!< bit 24 */
- if (int_status & USBD_INTEN_EPDATA_Msk)
- {
- /*!< out ep */
- for (uint8_t ep_out_ct = 1; ep_out_ct <= 7; ep_out_ct++)
- {
- if ((NRF_USBD->EPDATASTATUS) & (1 << (16 + ep_out_ct)))
- {
- NRF_USBD->EPDATASTATUS |= (1 << (16 + ep_out_ct));
- /*!< The data arrives at the usb fifo, starts the dma transmission, and transfers it to the user ram */
- NRF_USBD->TASKS_STARTEPOUT[ep_out_ct] = 1;
- }
- }
- /*!< in ep */
- for (uint8_t ep_in_ct = 1; ep_in_ct <= 7; ep_in_ct++)
- {
- if ((NRF_USBD->EPDATASTATUS) & (1 << (0 + ep_in_ct)))
- {
- /*!< in ep tranfer to host successfully */
- NRF_USBD->EPDATASTATUS |= (1 << (0 + ep_in_ct));
- if (usb_dc_cfg.ep_in[ep_in_ct].xfer_len > usb_dc_cfg.ep_in[ep_in_ct].mps)
- {
- /*!< Need start in again */
- usb_dc_cfg.ep_in[ep_in_ct].xfer_buf += usb_dc_cfg.ep_in[ep_in_ct].mps;
- usb_dc_cfg.ep_in[ep_in_ct].xfer_len -= usb_dc_cfg.ep_in[ep_in_ct].mps;
- usb_dc_cfg.ep_in[ep_in_ct].actual_xfer_len += usb_dc_cfg.ep_in[ep_in_ct].mps;
- if (usb_dc_cfg.ep_in[ep_in_ct].xfer_len > usb_dc_cfg.ep_in[ep_in_ct].mps)
- {
- nrf_usbd_ep_easydma_set_tx(ep_in_ct, (uint32_t)usb_dc_cfg.ep_in[ep_in_ct].xfer_buf, usb_dc_cfg.ep_in[ep_in_ct].mps);
- }
- else
- {
- nrf_usbd_ep_easydma_set_tx(ep_in_ct, (uint32_t)usb_dc_cfg.ep_in[ep_in_ct].xfer_buf, usb_dc_cfg.ep_in[ep_in_ct].xfer_len);
- }
- NRF_USBD->TASKS_STARTEPIN[ep_in_ct] = 1;
- }
- else
- {
- usb_dc_cfg.ep_in[ep_in_ct].actual_xfer_len += usb_dc_cfg.ep_in[ep_in_ct].xfer_len;
- usb_dc_cfg.ep_in[ep_in_ct].xfer_len = 0;
- usbd_event_ep_in_complete_handler(0, ep_in_ct | 0x80, usb_dc_cfg.ep_in[ep_in_ct].actual_xfer_len);
- }
- }
- }
- }
- /*!< bit 23 */
- if (int_status & USBD_INTEN_EP0SETUP_Msk)
- {
- /* Setup */
- /*!< Storing this setup package will help the following procedures */
- get_setup_packet(&(usb_dc_cfg.setup));
- /*!< Nrf52840 will set the address automatically by hardware,
- so the protocol stack of the address setting command sent by the host does not need to be processed */
- if (usb_dc_cfg.setup.wLength == 0)
- {
- NRF_USBD->TASKS_EP0STATUS = 1;
- }
- if (usb_dc_cfg.setup.bRequest != USB_REQUEST_SET_ADDRESS)
- {
- usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&(usb_dc_cfg.setup));
- }
- }
- /*!< bit 22 */
- if (int_status & USBD_INTEN_USBEVENT_Msk)
- {
- usb_event = NRF_USBD->EVENTCAUSE;
- NRF_USBD->EVENTCAUSE = usb_event;
- if (usb_event & USBD_EVENTCAUSE_SUSPEND_Msk)
- {
- NRF_USBD->LOWPOWER = 1;
- /*!< */
- }
- if (usb_event & USBD_EVENTCAUSE_RESUME_Msk)
- {
- /*!< */
- }
- if (usb_event & USBD_EVENTCAUSE_USBWUALLOWED_Msk)
- {
- NRF_USBD->DPDMVALUE = USBD_DPDMVALUE_STATE_Resume;
- NRF_USBD->TASKS_DPDMDRIVE = 1;
- /**
- * There is no Resume interrupt for remote wakeup, enable SOF for to report bus ready state
- * Clear SOF event in case interrupt was not enabled yet.
- */
- if ((NRF_USBD->INTEN & USBD_INTEN_SOF_Msk) == 0)
- NRF_USBD->EVENTS_SOF = 0;
- NRF_USBD->INTENSET = USBD_INTENSET_SOF_Msk;
- }
- }
- /*!< bit 21 */
- if (int_status & USBD_INTEN_SOF_Msk)
- {
- bool iso_enabled = false;
- /*!< ISOOUT: Transfer data gathered in previous frame from buffer to RAM */
- if (NRF_USBD->EPOUTEN & USBD_EPOUTEN_ISOOUT_Msk)
- {
- iso_enabled = true;
- /*!< If ZERO bit is set, ignore ISOOUT length */
- if ((NRF_USBD->SIZE.ISOOUT) & USBD_SIZE_ISOOUT_ZERO_Msk)
- {
- }
- else
- {
- /*!< Trigger DMA move data from Endpoint -> SRAM */
- NRF_USBD->TASKS_STARTISOOUT = 1;
- /*!< EP_ISO_NUM out using dma */
- usb_dc_cfg.ep_out[EP_ISO_NUM].is_using_dma = 1;
- }
- }
- /*!< ISOIN: Notify client that data was transferred */
- if (NRF_USBD->EPINEN & USBD_EPINEN_ISOIN_Msk)
- {
- iso_enabled = true;
- if (usb_dc_cfg.iso_tx_is_ready == 1)
- {
- usb_dc_cfg.iso_tx_is_ready = 0;
- NRF_USBD->TASKS_STARTISOIN = 1;
- }
- }
- if (!iso_enabled)
- {
- /**
- * ISO endpoint is not used, SOF is only enabled one-time for remote wakeup
- * so we disable it now
- */
- NRF_USBD->INTENCLR = USBD_INTENSET_SOF_Msk;
- }
- }
- /*!< bit 20 */
- if (int_status & USBD_INTEN_ENDISOOUT_Msk)
- {
- if (usb_dc_cfg.ep_out[EP_ISO_NUM].is_using_dma == 1)
- {
- usb_dc_cfg.ep_out[EP_ISO_NUM].is_using_dma = 0;
- uint32_t read_count = NRF_USBD->SIZE.ISOOUT;
- usb_dc_cfg.ep_out[EP_ISO_NUM].xfer_buf += read_count;
- usb_dc_cfg.ep_out[EP_ISO_NUM].actual_xfer_len += read_count;
- usb_dc_cfg.ep_out[EP_ISO_NUM].xfer_len -= read_count;
- if ((read_count < usb_dc_cfg.ep_out[EP_ISO_NUM].mps) || (usb_dc_cfg.ep_out[EP_ISO_NUM].xfer_len == 0))
- {
- usbd_event_ep_out_complete_handler(0, ((EP_ISO_NUM)&0x7f), usb_dc_cfg.ep_out[EP_ISO_NUM].actual_xfer_len);
- }
- else
- {
- if (usb_dc_cfg.ep_out[EP_ISO_NUM].xfer_len > usb_dc_cfg.ep_out[EP_ISO_NUM].mps)
- {
- nrf_usbd_ep_easydma_set_rx(((EP_ISO_NUM)&0x7f), (uint32_t)usb_dc_cfg.ep_out[EP_ISO_NUM].xfer_buf, usb_dc_cfg.ep_out[EP_ISO_NUM].mps);
- }
- else
- {
- nrf_usbd_ep_easydma_set_rx(((EP_ISO_NUM)&0x7f), (uint32_t)usb_dc_cfg.ep_out[EP_ISO_NUM].xfer_buf, usb_dc_cfg.ep_out[EP_ISO_NUM].xfer_len);
- }
- }
- }
- }
- /**
- * Traverse ordinary out endpoint events, starting from endpoint 1 to endpoint 7,
- * and end 0 for special processing
- */
- for (uint8_t offset = 0; offset < 7; offset++)
- {
- if (int_status & (USBD_INTEN_ENDEPOUT1_Msk << offset))
- {
- /*!< Out 'offset' transfer complete */
- uint32_t read_count = NRF_USBD->SIZE.EPOUT[offset + 1];
- usb_dc_cfg.ep_out[offset + 1].xfer_buf += read_count;
- usb_dc_cfg.ep_out[offset + 1].actual_xfer_len += read_count;
- usb_dc_cfg.ep_out[offset + 1].xfer_len -= read_count;
- if ((read_count < usb_dc_cfg.ep_out[offset + 1].mps) || (usb_dc_cfg.ep_out[offset + 1].xfer_len == 0))
- {
- usbd_event_ep_out_complete_handler(0, ((offset + 1) & 0x7f), usb_dc_cfg.ep_out[offset + 1].actual_xfer_len);
- }
- else
- {
- if (usb_dc_cfg.ep_out[offset + 1].xfer_len > usb_dc_cfg.ep_out[offset + 1].mps)
- {
- nrf_usbd_ep_easydma_set_rx(((offset + 1) & 0x7f), (uint32_t)usb_dc_cfg.ep_out[offset + 1].xfer_buf, usb_dc_cfg.ep_out[offset + 1].mps);
- }
- else
- {
- nrf_usbd_ep_easydma_set_rx(((offset + 1) & 0x7f), (uint32_t)usb_dc_cfg.ep_out[offset + 1].xfer_buf, usb_dc_cfg.ep_out[offset + 1].xfer_len);
- }
- }
- }
- }
- /*!< bit 12 */
- if (int_status & USBD_INTEN_ENDEPOUT0_Msk)
- {
- uint32_t read_count = NRF_USBD->SIZE.EPOUT[0];
- usb_dc_cfg.ep_out[0].actual_xfer_len += read_count;
- usb_dc_cfg.ep_out[0].xfer_len -= read_count;
- if (usb_dc_cfg.ep_out[0].xfer_len == 0)
- {
- /*!< Enable the state phase of endpoint 0 */
- NRF_USBD->TASKS_EP0STATUS = 1;
- }
- usbd_event_ep_out_complete_handler(0, 0x00, usb_dc_cfg.ep_out[0].actual_xfer_len);
- }
- /*!< bit 11 */
- if (int_status & USBD_INTEN_ENDISOIN_Msk)
- {
- }
- /*!< bit 10 */
- if (int_status & USBD_INTEN_EP0DATADONE_Msk)
- {
- switch (usb_dc_cfg.setup.bmRequestType >> USB_REQUEST_DIR_SHIFT)
- {
- case 1:
- /*!< IN */
- if (usb_dc_cfg.ep_in[0].xfer_len > usb_dc_cfg.ep_in[0].mps)
- {
- usb_dc_cfg.ep_in[0].xfer_len -= usb_dc_cfg.ep_in[0].mps;
- usb_dc_cfg.ep_in[0].actual_xfer_len += usb_dc_cfg.ep_in[0].mps;
- usbd_event_ep_in_complete_handler(0, 0 | 0x80, usb_dc_cfg.ep_in[0].actual_xfer_len);
- }
- else
- {
- usb_dc_cfg.ep_in[0].actual_xfer_len += usb_dc_cfg.ep_in[0].xfer_len;
- usb_dc_cfg.ep_in[0].xfer_len = 0;
- /*!< Enable the state phase of endpoint 0 */
- usbd_event_ep_in_complete_handler(0, 0 | 0x80, usb_dc_cfg.ep_in[0].actual_xfer_len);
- NRF_USBD->TASKS_EP0STATUS = 1;
- }
- break;
- case 0:
- if (usb_dc_cfg.setup.bRequest != USB_REQUEST_SET_ADDRESS)
- {
- /*!< The data arrives at the usb fifo, starts the dma transmission, and transfers it to the user ram */
- NRF_USBD->TASKS_STARTEPOUT[0] = 1;
- }
- break;
- }
- }
- /**
- * Traversing ordinary in endpoint events, starting from endpoint 1 to endpoint 7,
- * endpoint 0 special processing
- */
- for (uint8_t offset = 0; offset < 7; offset++)
- {
- if (int_status & (USBD_INTEN_ENDEPIN1_Msk << offset))
- {
- /*!< DMA move data completed */
- }
- }
- /*!< bit 1 */
- if (int_status & USBD_INTEN_STARTED_Msk)
- {
- /*!< Easy dma start transfer data */
- }
- /*!< bit 2 */
- if (int_status & USBD_INTEN_ENDEPIN0_Msk)
- {
- /*!< EP0 IN DMA move data completed */
- }
- /*!< bit 0 */
- if (int_status & USBD_INTEN_USBRESET_Msk)
- {
- NRF_USBD->EPOUTEN = 1UL;
- NRF_USBD->EPINEN = 1UL;
- for (int i = 0; i < 8; i++)
- {
- NRF_USBD->TASKS_STARTEPIN[i] = 0;
- NRF_USBD->TASKS_STARTEPOUT[i] = 0;
- }
- NRF_USBD->TASKS_STARTISOIN = 0;
- NRF_USBD->TASKS_STARTISOOUT = 0;
- /*!< Clear USB Event Interrupt */
- NRF_USBD->EVENTS_USBEVENT = 0;
- NRF_USBD->EVENTCAUSE |= NRF_USBD->EVENTCAUSE;
- /*!< Reset interrupt */
- NRF_USBD->INTENCLR = NRF_USBD->INTEN;
- NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_EPDATA_Msk |
- USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk | USBD_INTEN_STARTED_Msk;
- usbd_event_reset_handler(0);
- }
- }
- /**
- * Errata: USB cannot be enabled.
- */
- static bool chyu_nrf52_errata_187(void)
- {
- #ifndef NRF52_SERIES
- return false;
- #else
- #if defined(NRF52820_XXAA) || defined(DEVELOP_IN_NRF52820) || defined(NRF52833_XXAA) || defined(DEVELOP_IN_NRF52833) || defined(NRF52840_XXAA) || defined(DEVELOP_IN_NRF52840)
- uint32_t var1 = *(uint32_t *)0x10000130ul;
- uint32_t var2 = *(uint32_t *)0x10000134ul;
- #endif
- #if defined(NRF52840_XXAA) || defined(DEVELOP_IN_NRF52840)
- if (var1 == 0x08)
- {
- switch (var2)
- {
- case 0x00ul:
- return false;
- case 0x01ul:
- return true;
- case 0x02ul:
- return true;
- case 0x03ul:
- return true;
- default:
- return true;
- }
- }
- #endif
- #if defined(NRF52833_XXAA) || defined(DEVELOP_IN_NRF52833)
- if (var1 == 0x0D)
- {
- switch (var2)
- {
- case 0x00ul:
- return true;
- case 0x01ul:
- return true;
- default:
- return true;
- }
- }
- #endif
- #if defined(NRF52820_XXAA) || defined(DEVELOP_IN_NRF52820)
- if (var1 == 0x10)
- {
- switch (var2)
- {
- case 0x00ul:
- return true;
- case 0x01ul:
- return true;
- case 0x02ul:
- return true;
- default:
- return true;
- }
- }
- #endif
- return false;
- #endif
- }
- /**
- * Errata: USBD might not reach its active state.
- */
- static bool chyu_nrf52_errata_171(void)
- {
- #ifndef NRF52_SERIES
- return false;
- #else
- #if defined(NRF52840_XXAA) || defined(DEVELOP_IN_NRF52840)
- uint32_t var1 = *(uint32_t *)0x10000130ul;
- uint32_t var2 = *(uint32_t *)0x10000134ul;
- #endif
- #if defined(NRF52840_XXAA) || defined(DEVELOP_IN_NRF52840)
- if (var1 == 0x08)
- {
- switch (var2)
- {
- case 0x00ul:
- return true;
- case 0x01ul:
- return true;
- case 0x02ul:
- return true;
- case 0x03ul:
- return true;
- default:
- return true;
- }
- }
- #endif
- return false;
- #endif
- }
- /**
- * Errata: ISO double buffering not functional.
- */
- static bool chyu_nrf52_errata_166(void)
- {
- #ifndef NRF52_SERIES
- return false;
- #else
- #if defined(NRF52840_XXAA) || defined(DEVELOP_IN_NRF52840)
- uint32_t var1 = *(uint32_t *)0x10000130ul;
- uint32_t var2 = *(uint32_t *)0x10000134ul;
- #endif
- #if defined(NRF52840_XXAA) || defined(DEVELOP_IN_NRF52840)
- if (var1 == 0x08)
- {
- switch (var2)
- {
- case 0x00ul:
- return true;
- case 0x01ul:
- return true;
- case 0x02ul:
- return true;
- case 0x03ul:
- return true;
- default:
- return true;
- }
- }
- #endif
- return false;
- #endif
- }
- #ifdef SOFTDEVICE_PRESENT
- #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
- #if defined(CLOCK_HFCLKSTAT_SRC_Xtal) || defined(__NRFX_DOXYGEN__)
- return (NRF_CLOCK->HFCLKSTAT & (CLOCK_HFCLKSTAT_STATE_Msk | CLOCK_HFCLKSTAT_SRC_Msk)) ==
- (CLOCK_HFCLKSTAT_STATE_Msk | (CLOCK_HFCLKSTAT_SRC_Xtal << CLOCK_HFCLKSTAT_SRC_Pos));
- #else
- return (NRF_CLOCK->HFCLKSTAT & (CLOCK_HFCLKSTAT_STATE_Msk | CLOCK_HFCLKSTAT_SRC_Msk)) ==
- (CLOCK_HFCLKSTAT_STATE_Msk | (CLOCK_HFCLKSTAT_SRC_HFXO << CLOCK_HFCLKSTAT_SRC_Pos));
- #endif
- }
- enum
- {
- NRF_CLOCK_EVENT_HFCLKSTARTED = offsetof(NRF_CLOCK_Type, EVENTS_HFCLKSTARTED), /*!< HFCLK oscillator started. */
- };
- enum
- {
- NRF_CLOCK_TASK_HFCLKSTART = offsetof(NRF_CLOCK_Type, TASKS_HFCLKSTART), /*!< Start HFCLK clock source. */
- NRF_CLOCK_TASK_HFCLKSTOP = offsetof(NRF_CLOCK_Type, TASKS_HFCLKSTOP), /*!< Stop HFCLK clock source. */
- };
- 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
- *((volatile uint32_t *)((uint8_t *)NRF_CLOCK + NRF_CLOCK_EVENT_HFCLKSTARTED)) = 0x0UL;
- volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)NRF_CLOCK + (uint32_t)NRF_CLOCK_EVENT_HFCLKSTARTED));
- (void)dummy;
- *((volatile uint32_t *)((uint8_t *)NRF_CLOCK + NRF_CLOCK_TASK_HFCLKSTART)) = 0x1UL;
- }
- static void hfclk_disable(void)
- {
- #ifdef SOFTDEVICE_PRESENT
- if (is_sd_enabled())
- {
- (void)sd_clock_hfclk_release();
- return;
- }
- #endif
- *((volatile uint32_t *)((uint8_t *)NRF_CLOCK + NRF_CLOCK_TASK_HFCLKSTOP)) = 0x1UL;
- }
- /**
- * 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
- * enable ( or disable ) usb & hfclk peripheral, set the usb pin pull up
- * accordingly to the controller Startup/Standby Sequence in USBD 51.4 specs.
- * Therefore this function must be called to handle USB power event by
- * - nrfx_power_usbevt_init() : if Softdevice is not used or enabled
- * - SoftDevice SOC event : if SD is used and enabled
- */
- void cherry_usb_hal_nrf_power_event(uint32_t event)
- {
- enum
- {
- USB_EVT_DETECTED = 0,
- USB_EVT_REMOVED = 1,
- USB_EVT_READY = 2
- };
- switch (event)
- {
- case USB_EVT_DETECTED:
- if (!NRF_USBD->ENABLE)
- {
- /*!< Prepare for receiving READY event: disable interrupt since we will blocking wait */
- NRF_USBD->INTENCLR = USBD_INTEN_USBEVENT_Msk;
- NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk;
- __ISB();
- __DSB();
- #ifdef NRF52_SERIES /*!< NRF53 does not need this errata */
- /*!< ERRATA 171, 187, 166 */
- if (chyu_nrf52_errata_187())
- {
- if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
- {
- *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
- *((volatile uint32_t *)(0x4006ED14)) = 0x00000003;
- *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
- }
- else
- {
- *((volatile uint32_t *)(0x4006ED14)) = 0x00000003;
- }
- }
- if (chyu_nrf52_errata_171())
- {
- if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
- {
- *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
- *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0;
- *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
- }
- else
- {
- *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0;
- }
- }
- #endif
- /*!< Enable the peripheral (will cause Ready event) */
- NRF_USBD->ENABLE = 1;
- __ISB();
- __DSB();
- /*!< Enable HFCLK */
- hfclk_enable();
- }
- break;
- case USB_EVT_READY:
- /**
- * Skip if pull-up is enabled and HCLK is already running.
- * Application probably call this more than necessary.
- */
- if (NRF_USBD->USBPULLUP && hfclk_running())
- break;
- /*!< Waiting for USBD peripheral enabled */
- while (!(USBD_EVENTCAUSE_READY_Msk & NRF_USBD->EVENTCAUSE))
- {
- }
- NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk;
- __ISB();
- __DSB();
- #ifdef NRF52_SERIES
- if (chyu_nrf52_errata_171())
- {
- if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
- {
- *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
- *((volatile uint32_t *)(0x4006EC14)) = 0x00000000;
- *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
- }
- else
- {
- *((volatile uint32_t *)(0x4006EC14)) = 0x00000000;
- }
- }
- if (chyu_nrf52_errata_187())
- {
- if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
- {
- *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
- *((volatile uint32_t *)(0x4006ED14)) = 0x00000000;
- *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
- }
- else
- {
- *((volatile uint32_t *)(0x4006ED14)) = 0x00000000;
- }
- }
- if (chyu_nrf52_errata_166())
- {
- *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7E3;
- *((volatile uint32_t *)(NRF_USBD_BASE + 0x804)) = 0x40;
- __ISB();
- __DSB();
- }
- #endif
- /*!< ISO buffer Lower half for IN, upper half for OUT */
- NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN;
- /*!< Enable bus-reset interrupt */
- NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk;
- /*!< Enable interrupt, priorities should be set by application */
- /*!< clear pending irq */
- NVIC->ICPR[(((uint32_t)USBD_IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)USBD_IRQn) & 0x1FUL));
- /**
- * Don't enable USBD interrupt yet, if dcd_init() did not finish yet
- * Interrupt will be enabled by tud_init(), when USB stack is ready
- * to handle interrupts.
- */
- /*!< Wait for HFCLK */
- while (!hfclk_running())
- {
- }
- /*!< Enable pull up */
- NRF_USBD->USBPULLUP = 1;
- __ISB();
- __DSB();
- break;
- case USB_EVT_REMOVED:
- if (NRF_USBD->ENABLE)
- {
- /*!< Disable pull up */
- NRF_USBD->USBPULLUP = 0;
- __ISB();
- __DSB();
- /*!< Disable Interrupt */
- NVIC->ICER[(((uint32_t)USBD_IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)USBD_IRQn) & 0x1FUL));
- __DSB();
- __ISB();
- /*!< disable all interrupt */
- NRF_USBD->INTENCLR = NRF_USBD->INTEN;
- NRF_USBD->ENABLE = 0;
- __ISB();
- __DSB();
- hfclk_disable();
- }
- break;
- default:
- break;
- }
- }
|