Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.
Upstream: https://github.com/ARMmbed/DAPLink
Diff: source/hic_hal/freescale/usbd_kinetis.c
- Revision:
- 0:01f31e923fe2
diff -r 000000000000 -r 01f31e923fe2 source/hic_hal/freescale/usbd_kinetis.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/hic_hal/freescale/usbd_kinetis.c Tue Apr 07 12:55:42 2020 +0200 @@ -0,0 +1,819 @@ +/** + * @file usbd_kinetis.c + * @brief + * + * DAPLink Interface Firmware + * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "rl_usb.h" +#include "fsl_device_registers.h" +#include "cortex_m.h" +#include "util.h" +#include "string.h" + +#define __NO_USB_LIB_C +#include "usb_config.c" + +typedef struct __BUF_DESC { + uint8_t stat; + uint8_t reserved; + uint16_t bc; + uint32_t buf_addr; +} BUF_DESC; + +BUF_DESC __align(512) BD[(USBD_EP_NUM + 1) * 2 * 2]; +uint8_t EPBuf[(USBD_EP_NUM + 1) * 2 * 2][64]; +uint8_t OutEpSize[USBD_EP_NUM + 1]; +uint8_t StatQueue[(USBD_EP_NUM + 1) * 2 * 2 + 1]; +uint32_t StatQueueHead = 0; +uint32_t StatQueueTail = 0; +uint32_t LastIstat = 0; +uint8_t UsbSuspended = 0; +uint8_t Ep0ZlpOut = 0; + +uint32_t Data1 = 0x55555555; + +#define BD_OWN_MASK 0x80 +#define BD_DATA01_MASK 0x40 +#define BD_KEEP_MASK 0x20 +#define BD_NINC_MASK 0x10 +#define BD_DTS_MASK 0x08 +#define BD_STALL_MASK 0x04 + +#define TX 1 +#define RX 0 +#define ODD 0 +#define EVEN 1 +#define IDX(Ep, dir, Ev_Odd) ((((Ep & 0x0F) * 4) + (2 * dir) + (1 * Ev_Odd))) + +#define SETUP_TOKEN 0x0D +#define IN_TOKEN 0x09 +#define OUT_TOKEN 0x01 +#define TOK_PID(idx) ((BD[idx].stat >> 2) & 0x0F) + +inline static void protected_and(uint32_t *addr, uint32_t val) +{ + cortex_int_state_t state; + state = cortex_int_get_and_disable(); + *addr = *addr & val; + cortex_int_restore(state); +} +inline static void protected_or(uint32_t *addr, uint32_t val) +{ + cortex_int_state_t state; + state = cortex_int_get_and_disable(); + *addr = *addr | val; + cortex_int_restore(state); +} +inline static void protected_xor(uint32_t *addr, uint32_t val) +{ + cortex_int_state_t state; + state = cortex_int_get_and_disable(); + *addr = *addr ^ val; + cortex_int_restore(state); +} + +inline static void stat_enque(uint32_t stat) +{ + cortex_int_state_t state; + state = cortex_int_get_and_disable(); + StatQueue[StatQueueTail] = stat; + StatQueueTail = (StatQueueTail + 1) % sizeof(StatQueue); + cortex_int_restore(state); +} + +inline static uint32_t stat_deque() +{ + cortex_int_state_t state; + uint32_t stat; + state = cortex_int_get_and_disable(); + stat = StatQueue[StatQueueHead]; + StatQueueHead = (StatQueueHead + 1) % sizeof(StatQueue); + cortex_int_restore(state); + + return stat; +} + +inline static uint32_t stat_is_empty() +{ + cortex_int_state_t state; + uint32_t empty; + state = cortex_int_get_and_disable(); + empty = StatQueueHead == StatQueueTail; + cortex_int_restore(state); + return empty; +} + +/* + * USB Device Interrupt enable + * Called by USBD_Init to enable the USB Interrupt + * Return Value: None + */ + +void USBD_IntrEna(void) +{ + NVIC_EnableIRQ(USB0_IRQn); /* Enable OTG interrupt */ +} + + +/* + * USB Device Initialize Function + * Called by the User to initialize USB + * Return Value: None + */ + +void USBD_Init(void) +{ + OutEpSize[0] = USBD_MAX_PACKET0; + /* Enable all clocks needed for USB to function */ + /* Set USB clock to 48 MHz */ + SIM->SOPT2 |= SIM_SOPT2_USBSRC_MASK | /* MCGPLLCLK used as src */ + SIM_SOPT2_PLLFLLSEL_MASK ; /* Select MCGPLLCLK as clock */ +#if defined(TARGET_MK20D5) + SIM->CLKDIV2 &= ~(SIM_CLKDIV2_USBFRAC_MASK | /* Clear CLKDIV2 FS values */ + SIM_CLKDIV2_USBDIV_MASK); + SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(0) ; /* USB clk = (PLL*1/2) */ + /* = ( 48*1/1)=48 */ +#endif // TARGET_MK20D5 + SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK; /* Enable USBOTG clock */ + USBD_IntrEna(); + USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK; + + while (USB0->USBTRC0 & USB_USBTRC0_USBRESET_MASK); + + USB0->BDTPAGE1 = (uint8_t)((uint32_t) BD >> 8); + USB0->BDTPAGE2 = (uint8_t)((uint32_t) BD >> 16); + USB0->BDTPAGE3 = (uint8_t)((uint32_t) BD >> 24); + USB0->ISTAT = 0xFF; /* clear interrupt flags */ + /* enable interrupts */ + USB0->INTEN = USB_INTEN_USBRSTEN_MASK | + USB_INTEN_TOKDNEEN_MASK | + USB_INTEN_SLEEPEN_MASK | +#ifdef __RTX + ((USBD_RTX_DevTask != 0) ? USB_INTEN_SOFTOKEN_MASK : 0) | + ((USBD_RTX_DevTask != 0) ? USB_INTEN_ERROREN_MASK : 0) ; +#else + ((USBD_P_SOF_Event != 0) ? USB_INTEN_SOFTOKEN_MASK : 0) | + ((USBD_P_Error_Event != 0) ? USB_INTEN_ERROREN_MASK : 0) ; +#endif + USB0->USBCTRL = USB_USBCTRL_PDE_MASK;/* pull dawn on D+ and D- */ + USB0->USBTRC0 |= (1 << 6); /* bit 6 must be set to 1 */ +} + + +/* + * USB Device Connect Function + * Called by the User to Connect/Disconnect USB Device + * Parameters: con: Connect/Disconnect + * Return Value: None + */ + +void USBD_Connect(uint32_t con) +{ + if (con) { + USB0->CTL |= USB_CTL_USBENSOFEN_MASK; /* enable USB */ + USB0->CONTROL = USB_CONTROL_DPPULLUPNONOTG_MASK; /* pull up on D+ */ + } else { + USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK; /* disable USB */ + USB0->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK;/* pull down on D+ */ + } +} + + +/* + * USB Device Reset Function + * Called automatically on USB Device Reset + * Return Value: None + */ + +void USBD_Reset(void) +{ + uint32_t i; + + NVIC_DisableIRQ(USB0_IRQn); + + for (i = 1; i < 16; i++) { + USB0->ENDPOINT[i].ENDPT = 0x00; + } + + memset(StatQueue, 0, sizeof(StatQueue)); + StatQueueHead = 0; + StatQueueTail = 0; + LastIstat = 0; + UsbSuspended = 0; + Ep0ZlpOut = 0; + + /* EP0 control endpoint */ + BD[IDX(0, RX, ODD)].bc = USBD_MAX_PACKET0; + BD[IDX(0, RX, ODD)].buf_addr = (uint32_t) & (EPBuf[IDX(0, RX, ODD)][0]); + BD[IDX(0, RX, ODD)].stat = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK; + BD[IDX(0, RX, EVEN)].stat = 0; + BD[IDX(0, TX, ODD)].buf_addr = (uint32_t) & (EPBuf[IDX(0, TX, ODD)][0]); + BD[IDX(0, TX, EVEN)].buf_addr = 0; + USB0->ENDPOINT[0].ENDPT = USB_ENDPT_EPHSHK_MASK | /* enable ep handshaking */ + USB_ENDPT_EPTXEN_MASK | /* enable TX (IN) tran. */ + USB_ENDPT_EPRXEN_MASK; /* enable RX (OUT) tran. */ + Data1 = 0x55555555; + USB0->CTL |= USB_CTL_ODDRST_MASK; + USB0->ISTAT = 0xFF; /* clear all interrupt status flags */ + USB0->ERRSTAT = 0xFF; /* clear all error flags */ + USB0->ERREN = 0xFF; /* enable error interrupt sources */ + USB0->ADDR = 0x00; /* set default address */ + + NVIC_EnableIRQ(USB0_IRQn); +} + + +/* + * USB Device Suspend Function + * Called automatically on USB Device Suspend + * Return Value: None + */ + +void USBD_Suspend(void) +{ + USB0->INTEN |= USB_INTEN_RESUMEEN_MASK; +} + + +/* + * USB Device Resume Function + * Called automatically on USB Device Resume + * Return Value: None + */ + +void USBD_Resume(void) +{ + USB0->INTEN &= ~USB_INTEN_RESUMEEN_MASK; +} + + +/* + * USB Device Remote Wakeup Function + * Called automatically on USB Device Remote Wakeup + * Return Value: None + */ + +void USBD_WakeUp(void) +{ + uint32_t i = 50000; + + if (USBD_DeviceStatus & USB_GETSTATUS_REMOTE_WAKEUP) { + USB0->CTL |= USB_CTL_RESUME_MASK; + + while (i--) { + __nop(); + } + + USB0->CTL &= ~USB_CTL_RESUME_MASK; + } +} + + +/* + * USB Device Remote Wakeup Configuration Function + * Parameters: cfg: Device Enable/Disable + * Return Value: None + */ + +void USBD_WakeUpCfg(uint32_t cfg) +{ + /* Not needed */ +} + + +/* + * USB Device Set Address Function + * Parameters: adr: USB Device Address + * Return Value: None + */ + +void USBD_SetAddress(uint32_t adr, uint32_t setup) +{ + if (!setup) { + USB0->ADDR = adr & 0x7F; + } +} + + +/* + * USB Device Configure Function + * Parameters: cfg: Device Configure/Deconfigure + * Return Value: None + */ + +void USBD_Configure(uint32_t cfg) +{ +} + + +/* + * Configure USB Device Endpoint according to Descriptor + * Parameters: pEPD: Pointer to Device Endpoint Descriptor + * Return Value: None + */ + +void USBD_ConfigEP(USB_ENDPOINT_DESCRIPTOR *pEPD) +{ + uint32_t num, val; + num = pEPD->bEndpointAddress; + val = pEPD->wMaxPacketSize; + + if (!(pEPD->bEndpointAddress & 0x80)) { + OutEpSize[num] = val; + } + + USBD_ResetEP(num); +} + + +/* + * Set Direction for USB Device Control Endpoint + * Parameters: dir: Out (dir == 0), In (dir <> 0) + * Return Value: None + */ + +void USBD_DirCtrlEP(uint32_t dir) +{ + /* Not needed */ +} + + +/* + * Enable USB Device Endpoint + * Parameters: EPNum: Device Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: None + */ + +void USBD_EnableEP(uint32_t EPNum) +{ + if (EPNum & 0x80) { + EPNum &= 0x0F; + USB0->ENDPOINT[EPNum].ENDPT |= USB_ENDPT_EPHSHK_MASK | /*en ep handshaking*/ + USB_ENDPT_EPTXEN_MASK; /*en TX (IN) tran */ + } else { + USB0->ENDPOINT[EPNum].ENDPT |= USB_ENDPT_EPHSHK_MASK | /*en ep handshaking*/ + USB_ENDPT_EPRXEN_MASK; /*en RX (OUT) tran.*/ + } +} + + +/* + * Disable USB Endpoint + * Parameters: EPNum: Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: None + */ + +void USBD_DisableEP(uint32_t EPNum) +{ + if (EPNum & 0x80) { + EPNum &= 0x0F; + USB0->ENDPOINT[EPNum].ENDPT &= ~(USB_ENDPT_EPHSHK_MASK |/*dis handshaking */ + USB_ENDPT_EPTXEN_MASK);/*dis TX(IN) tran */ + } else { + USB0->ENDPOINT[EPNum].ENDPT &= ~(USB_ENDPT_EPHSHK_MASK |/*dis handshaking */ + USB_ENDPT_EPRXEN_MASK);/*dis RX(OUT) tran*/ + } +} + + +/* + * Reset USB Device Endpoint + * Parameters: EPNum: Device Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: None + */ + +void USBD_ResetEP(uint32_t EPNum) +{ + if (EPNum & 0x80) { + EPNum &= 0x0F; + protected_or(&Data1, (1 << ((EPNum * 2) + 1))); + BD[IDX(EPNum, TX, ODD)].buf_addr = (uint32_t) & (EPBuf[IDX(EPNum, TX, ODD)][0]); + BD[IDX(EPNum, TX, EVEN)].buf_addr = 0; + } else { + protected_and(&Data1, ~(1 << (EPNum * 2))); + BD[IDX(EPNum, RX, ODD)].bc = OutEpSize[EPNum]; + BD[IDX(EPNum, RX, ODD)].buf_addr = (uint32_t) & (EPBuf[IDX(EPNum, RX, ODD)][0]); + BD[IDX(EPNum, RX, ODD)].stat = BD_OWN_MASK | BD_DTS_MASK; + BD[IDX(EPNum, RX, EVEN)].stat = 0; + } +} + +/* + * Set Stall for USB Device Endpoint + * Parameters: EPNum: Device Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: None + */ + +void USBD_SetStallEP(uint32_t EPNum) +{ + EPNum &= 0x0F; + USB0->ENDPOINT[EPNum].ENDPT |= USB_ENDPT_EPSTALL_MASK; +} + + +/* + * Clear Stall for USB Device Endpoint + * Parameters: EPNum: Device Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: None + */ + +void USBD_ClrStallEP(uint32_t EPNum) +{ + USB0->ENDPOINT[EPNum & 0x0F].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; + USBD_ResetEP(EPNum); +} + + +/* + * Clear USB Device Endpoint Buffer + * Parameters: EPNum: Device Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * Return Value: None + */ + +void USBD_ClearEPBuf(uint32_t EPNum) +{ +} + + +/* + * Read USB Device Endpoint Data + * Parameters: EPNum: Device Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * pData: Pointer to Data Buffer + * Return Value: Number of bytes read + */ + +uint32_t USBD_ReadEP(uint32_t EPNum, uint8_t *pData, uint32_t size) +{ + uint32_t n, sz, idx, setup = 0; + idx = IDX(EPNum, RX, 0); + sz = BD[idx].bc; + + if ((EPNum == 0) && Ep0ZlpOut) { + // This packet was a zero length data out packet. It has already + // been processed by USB0_IRQHandler. Only toggle the DATAx bit + // and return a size of 0. + protected_xor(&Data1, (1 << (idx / 2))); + return 0; + } + + if ((EPNum == 0) && (TOK_PID(idx) == SETUP_TOKEN)) { + setup = 1; + } + + if (size < sz) { + util_assert(0); + sz = size; + } + + for (n = 0; n < sz; n++) { + pData[n] = EPBuf[idx][n]; + } + + BD[idx].bc = OutEpSize[EPNum]; + + if ((Data1 >> (idx / 2) & 1) == ((BD[idx].stat >> 6) & 1)) { + uint32_t xfer_size = (pData[7] << 8) | (pData[6] << 0); + if (setup && (0 == xfer_size)) { /* if no setup data stage, */ + protected_and(&Data1, ~1); /* set DATA0 */ + } else { + protected_xor(&Data1, (1 << (idx / 2))); + } + } + + if ((Data1 >> (idx / 2)) & 1) { + BD[idx].stat = BD_DTS_MASK | BD_DATA01_MASK; + BD[idx].stat |= BD_OWN_MASK; + } else { + BD[idx].stat = BD_DTS_MASK; + BD[idx].stat |= BD_OWN_MASK; + } + + return (sz); +} + + +/* + * Write USB Device Endpoint Data + * Parameters: EPNum: Device Endpoint Number + * EPNum.0..3: Address + * EPNum.7: Dir + * pData: Pointer to Data Buffer + * cnt: Number of bytes to write + * Return Value: Number of bytes written + */ + +uint32_t USBD_WriteEP(uint32_t EPNum, uint8_t *pData, uint32_t cnt) +{ + uint32_t idx, n; + EPNum &= 0x0F; + idx = IDX(EPNum, TX, 0); + BD[idx].bc = cnt; + + for (n = 0; n < cnt; n++) { + EPBuf[idx][n] = pData[n]; + } + + if ((Data1 >> (idx / 2)) & 1) { + BD[idx].stat = BD_OWN_MASK | BD_DTS_MASK; + } else { + BD[idx].stat = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK; + } + + protected_xor(&Data1, (1 << (idx / 2))); + return (cnt); +} + +/* + * Get USB Device Last Frame Number + * Parameters: None + * Return Value: Frame Number + */ + +uint32_t USBD_GetFrame(void) +{ + return ((USB0->FRMNUML | (USB0->FRMNUMH << 8) & 0x07FF)); +} + +#ifdef __RTX +U32 LastError; /* Last Error */ + +/* + * Get USB Device Last Error Code + * Parameters: None + * Return Value: Error Code + */ + +U32 USBD_GetError(void) +{ + return (LastError); +} +#endif + + +/* + * USB Device Interrupt Service Routine + */ +void USB0_IRQHandler(void) +{ + uint32_t istat, num, dir, ev_odd; + uint32_t new_istat; + uint8_t suspended = 0; + + new_istat = istat = USB0->ISTAT; + + // Read all tokens + if (istat & USB_ISTAT_TOKDNE_MASK) { + while (istat & USB_ISTAT_TOKDNE_MASK) { + uint8_t stat = USB0->STAT; + num = (stat >> 4) & 0x0F; + dir = (stat >> 3) & 0x01; + ev_odd = (stat >> 2) & 0x01; + + // Consume all zero length OUT packets on endpoint 0 to prevent + // a subsequent SETUP packet from being dropped + if ((0 == num) && (RX == dir)) { + uint32_t idx; + idx = IDX(num, dir, ev_odd); + if ((TOK_PID(idx) == OUT_TOKEN) && (BD[idx].bc == 0)) { + BD[idx].bc = OutEpSize[num]; + if (BD[idx].stat & BD_DATA01_MASK) { + BD[idx].stat = BD_OWN_MASK | BD_DTS_MASK; + } else { + BD[idx].stat = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK; + } + stat |= 1 << 0; + } + } + + stat_enque(stat); + USB0->ISTAT = USB_ISTAT_TOKDNE_MASK; + + // Check if USB is suspending before checking istat + suspended = suspended || USB0->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK; + istat = USB0->ISTAT; + } + } + + // Set global istat and suspended flags + new_istat |= istat; + protected_or(&LastIstat, new_istat); + UsbSuspended |= suspended ? 1 : 0; + USB0->ISTAT = istat; + + USBD_SignalHandler(); +} + +/* + * USB Device Service Routine + */ + +void USBD_Handler(void) +{ + uint32_t istr, num, dir, ev_odd; + cortex_int_state_t state; + uint8_t suspended = 0; + + // Get ISTAT + state = cortex_int_get_and_disable(); + istr = LastIstat; + LastIstat = 0; + suspended = UsbSuspended; + UsbSuspended = 0; + cortex_int_restore(state); + + + /* reset interrupt */ + if (istr & USB_ISTAT_USBRST_MASK) { + USBD_Reset(); + usbd_reset_core(); +#ifdef __RTX + + if (USBD_RTX_DevTask) { + isr_evt_set(USBD_EVT_RESET, USBD_RTX_DevTask); + } + +#else + + if (USBD_P_Reset_Event) { + USBD_P_Reset_Event(); + } + +#endif + } + + /* suspend interrupt */ + if (istr & USB_ISTAT_SLEEP_MASK) { + USBD_Suspend(); +#ifdef __RTX + + if (USBD_RTX_DevTask) { + isr_evt_set(USBD_EVT_SUSPEND, USBD_RTX_DevTask); + } + +#else + + if (USBD_P_Suspend_Event) { + USBD_P_Suspend_Event(); + } + +#endif + } + + /* resume interrupt */ + if (istr & USB_ISTAT_RESUME_MASK) { + USBD_Resume(); +#ifdef __RTX + + if (USBD_RTX_DevTask) { + isr_evt_set(USBD_EVT_RESUME, USBD_RTX_DevTask); + } + +#else + + if (USBD_P_Resume_Event) { + USBD_P_Resume_Event(); + } + +#endif + } + + /* Start Of Frame */ + if (istr & USB_ISTAT_SOFTOK_MASK) { +#ifdef __RTX + + if (USBD_RTX_DevTask) { + isr_evt_set(USBD_EVT_SOF, USBD_RTX_DevTask); + } + +#else + + if (USBD_P_SOF_Event) { + USBD_P_SOF_Event(); + } + +#endif + } + + /* Error interrupt */ + if (istr == USB_ISTAT_ERROR_MASK) { +#ifdef __RTX + LastError = USB0->ERRSTAT; + + if (USBD_RTX_DevTask) { + isr_evt_set(USBD_EVT_ERROR, USBD_RTX_DevTask); + } + +#else + + if (USBD_P_Error_Event) { + USBD_P_Error_Event(USB0->ERRSTAT); + } + +#endif + USB0->ERRSTAT = 0xFF; + } + + /* token interrupt */ + if (istr & USB_ISTAT_TOKDNE_MASK) { + while (!stat_is_empty()) { + uint32_t stat; + + stat = stat_deque(); + num = (stat >> 4) & 0x0F; + dir = (stat >> 3) & 0x01; + ev_odd = (stat >> 2) & 0x01; + + /* setup packet */ + if ((num == 0) && (TOK_PID((IDX(num, dir, ev_odd))) == SETUP_TOKEN)) { + Data1 &= ~0x02; + BD[IDX(0, TX, EVEN)].stat &= ~BD_OWN_MASK; + BD[IDX(0, TX, ODD)].stat &= ~BD_OWN_MASK; + Ep0ZlpOut = 0; +#ifdef __RTX + + if (USBD_RTX_EPTask[num]) { + isr_evt_set(USBD_EVT_SETUP, USBD_RTX_EPTask[num]); + } + +#else + + if (USBD_P_EP[num]) { + USBD_P_EP[num](USBD_EVT_SETUP); + } + +#endif + + } else { + /* OUT packet */ + if (TOK_PID((IDX(num, dir, ev_odd))) == OUT_TOKEN) { + if (0 == num) { + Ep0ZlpOut = stat & (1 << 0); + } +#ifdef __RTX + + if (USBD_RTX_EPTask[num]) { + isr_evt_set(USBD_EVT_OUT, USBD_RTX_EPTask[num]); + } + +#else + + if (USBD_P_EP[num]) { + USBD_P_EP[num](USBD_EVT_OUT); + } + +#endif + } + + /* IN packet */ + if (TOK_PID((IDX(num, dir, ev_odd))) == IN_TOKEN) { +#ifdef __RTX + + if (USBD_RTX_EPTask[num]) { + isr_evt_set(USBD_EVT_IN, USBD_RTX_EPTask[num]); + } + +#else + + if (USBD_P_EP[num]) { + USBD_P_EP[num](USBD_EVT_IN); + } + +#endif + } + } + } + } + + if (suspended) { + USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; + } +}