2 * The Clear BSD License
3 * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
4 * Copyright 2016 - 2018 NXP
7 * Redistribution and use in source and binary forms, with or without modification,
8 * are permitted (subject to the limitations in the disclaimer below) provided
9 * that the following conditions are met:
11 * o Redistributions of source code must retain the above copyright notice, this list
12 * of conditions and the following disclaimer.
14 * o Redistributions in binary form must reproduce the above copyright notice, this
15 * list of conditions and the following disclaimer in the documentation and/or
16 * other materials provided with the distribution.
18 * o Neither the name of the copyright holder nor the names of its
19 * contributors may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
22 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
27 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include "usb_device_config.h"
38 #include "usb_device.h"
40 #include "fsl_device_registers.h"
42 #if ((defined(USB_DEVICE_CONFIG_KHCI)) && (USB_DEVICE_CONFIG_KHCI > 0U))
45 #include "usb_device_dci.h"
47 #include "usb_device_khci.h"
49 /*******************************************************************************
51 ******************************************************************************/
52 #if defined(USB_STACK_USE_DEDICATED_RAM) && (USB_STACK_USE_DEDICATED_RAM > 0U)
54 /* USB_STACK_USE_DEDICATED_RAM */
55 #if defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
57 #if (USB_STACK_USE_DEDICATED_RAM == USB_STACK_DEDICATED_RAM_TYPE_BDT_GLOBAL)
58 #if (FSL_FEATURE_USB_KHCI_USB_RAM > 512U)
60 #error The dedicated RAM length is not more than 512 Bytes, the SOC does not support this case.
62 #endif /* USB_STACK_USE_DEDICATED_RAM */
65 #error The SOC does not suppoort dedicated RAM case.
66 #endif /* USB_STACK_USE_DEDICATED_RAM */
70 /*******************************************************************************
72 ******************************************************************************/
73 static usb_status_t USB_DeviceKhciEndpointTransfer(
74 usb_device_khci_state_struct_t *khciState, uint8_t endpoint, uint8_t direction, uint8_t *buffer, uint32_t length);
75 static void USB_DeviceKhciPrimeNextSetup(usb_device_khci_state_struct_t *khciState);
76 static void USB_DeviceKhciSetDefaultState(usb_device_khci_state_struct_t *khciState);
77 static usb_status_t USB_DeviceKhciEndpointInit(usb_device_khci_state_struct_t *khciState,
78 usb_device_endpoint_init_struct_t *epInit);
79 static usb_status_t USB_DeviceKhciEndpointDeinit(usb_device_khci_state_struct_t *khciState, uint8_t ep);
80 static usb_status_t USB_DeviceKhciEndpointStall(usb_device_khci_state_struct_t *khciState, uint8_t ep);
81 static usb_status_t USB_DeviceKhciEndpointUnstall(usb_device_khci_state_struct_t *khciState, uint8_t ep);
82 static void USB_DeviceKhciInterruptTokenDone(usb_device_khci_state_struct_t *khciState);
83 static void USB_DeviceKhciInterruptReset(usb_device_khci_state_struct_t *khciState);
84 #if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
85 static void USB_DeviceKhciInterruptSleep(usb_device_khci_state_struct_t *khciState);
86 static void USB_DeviceKhciInterruptResume(usb_device_khci_state_struct_t *khciState);
87 #endif /* USB_DEVICE_CONFIG_LOW_POWER_MODE */
88 static void USB_DeviceKhciInterruptStall(usb_device_khci_state_struct_t *khciState);
89 #if defined(USB_DEVICE_CONFIG_ERROR_HANDLING) && (USB_DEVICE_CONFIG_ERROR_HANDLING > 0U)
90 static void USB_DeviceKhciInterruptError(usb_device_khci_state_struct_t *khciState);
91 #endif /* USB_DEVICE_CONFIG_ERROR_HANDLING */
93 extern usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg);
95 /*******************************************************************************
97 ******************************************************************************/
99 /* Apply for BDT buffer, 512-byte alignment */
100 USB_BDT USB_RAM_ADDRESS_ALIGNMENT(512) static uint8_t s_UsbDeviceKhciBdtBuffer[USB_DEVICE_CONFIG_KHCI][512U];
102 /* Apply for khci device state structure */
103 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_khci_state_struct_t
104 s_UsbDeviceKhciState[USB_DEVICE_CONFIG_KHCI];
106 #if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
107 (defined(FSL_FEATURE_SOC_USBDCD_COUNT) && (FSL_FEATURE_SOC_USBDCD_COUNT > 0U))
108 /* Apply for device dcd state structure */
109 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_dcd_state_struct_t
110 s_UsbDeviceDcdState[USB_DEVICE_CONFIG_KHCI];
113 /* Apply for KHCI DMA aligned buffer when marco USB_DEVICE_CONFIG_KHCI_DMA_ALIGN enabled */
114 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static uint32_t s_UsbDeviceKhciDmaAlignBuffer
115 [USB_DEVICE_CONFIG_KHCI][((USB_DEVICE_CONFIG_KHCI_DMA_ALIGN_BUFFER_LENGTH - 1U) >> 2U) + 1U];
117 /*******************************************************************************
119 ******************************************************************************/
122 * @brief Write the BDT to start a transfer.
124 * The function is used to start a transfer by writing the BDT.
126 * @param khciState Pointer of the device KHCI state structure.
127 * @param endpoint Endpoint number.
128 * @param direction The direction of the endpoint, 0U - USB_OUT, 1U - USB_IN.
129 * @param buffer The memory address to save the received data, or the memory address to hold the data need to
131 * @param length The length of the data.
133 * @return A USB error code or kStatus_USB_Success.
135 static usb_status_t USB_DeviceKhciEndpointTransfer(
136 usb_device_khci_state_struct_t *khciState, uint8_t endpoint, uint8_t direction, uint8_t *buffer, uint32_t length)
138 uint32_t index = ((uint32_t)endpoint << 1U) | (uint32_t)direction;
142 USB_OSA_ENTER_CRITICAL();
144 /* Flag the endpoint is busy. */
145 khciState->endpointState[index].stateUnion.stateBitField.transferring = 1U;
147 /* Add the data buffer address to the BDT. */
148 USB_KHCI_BDT_SET_ADDRESS((uint32_t)khciState->bdt, endpoint, direction,
149 khciState->endpointState[index].stateUnion.stateBitField.bdtOdd, (uint32_t)buffer);
151 /* Change the BDT control field to start the transfer. */
152 USB_KHCI_BDT_SET_CONTROL(
153 (uint32_t)khciState->bdt, endpoint, direction, khciState->endpointState[index].stateUnion.stateBitField.bdtOdd,
154 USB_LONG_TO_LITTLE_ENDIAN(USB_KHCI_BDT_BC(length) | USB_KHCI_BDT_OWN | USB_KHCI_BDT_DTS |
155 USB_KHCI_BDT_DATA01(khciState->endpointState[index].stateUnion.stateBitField.data0)));
158 USB_OSA_EXIT_CRITICAL();
160 /* Clear the token busy state */
161 khciState->registerBase->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
162 return kStatus_USB_Success;
166 * @brief Prime a next setup transfer.
168 * The function is used to prime a buffer in control out pipe to wait for receiving the host's setup packet.
170 * @param khciState Pointer of the device KHCI state structure.
173 static void USB_DeviceKhciPrimeNextSetup(usb_device_khci_state_struct_t *khciState)
175 /* Update the endpoint state */
176 /* Save the buffer address used to receive the setup packet. */
177 #if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
178 defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \
179 defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
180 /* In case of lowpower mode enabled, it requires to put the setup packet buffer(16 bytes) into the USB RAM so
181 * that the setup packet would wake up the USB.
183 khciState->endpointState[(USB_CONTROL_ENDPOINT << 1U) | USB_OUT].transferBuffer =
184 (uint8_t *)(khciState->bdt + 0x200U - 0x10U) +
185 khciState->endpointState[(USB_CONTROL_ENDPOINT << 1U) | USB_OUT].stateUnion.stateBitField.bdtOdd *
186 USB_SETUP_PACKET_SIZE;
188 khciState->endpointState[(USB_CONTROL_ENDPOINT << 1U) | USB_OUT].transferBuffer =
189 (uint8_t *)&khciState->setupPacketBuffer[0] +
190 khciState->endpointState[(USB_CONTROL_ENDPOINT << 1U) | USB_OUT].stateUnion.stateBitField.bdtOdd *
191 USB_SETUP_PACKET_SIZE;
193 /* Clear the transferred length. */
194 khciState->endpointState[(USB_CONTROL_ENDPOINT << 1U) | USB_OUT].transferDone = 0U;
195 /* Save the data length expected to get from a host. */
196 khciState->endpointState[(USB_CONTROL_ENDPOINT << 1U) | USB_OUT].transferLength = USB_SETUP_PACKET_SIZE;
197 /* Save the data buffer DMA align flag. */
198 khciState->endpointState[(USB_CONTROL_ENDPOINT << 1U) | USB_OUT].stateUnion.stateBitField.dmaAlign = 1U;
199 /* Set the DATA0/1 to DATA0. */
200 khciState->endpointState[(USB_CONTROL_ENDPOINT << 1U) | USB_OUT].stateUnion.stateBitField.data0 = 0U;
202 USB_DeviceKhciEndpointTransfer(khciState, USB_CONTROL_ENDPOINT, USB_OUT,
203 khciState->endpointState[(USB_CONTROL_ENDPOINT << 1U) | USB_OUT].transferBuffer,
204 USB_SETUP_PACKET_SIZE);
208 * @brief Set device controller state to default state.
210 * The function is used to set device controller state to default state.
211 * The function will be called when USB_DeviceKhciInit called or the control type kUSB_DeviceControlGetEndpointStatus
212 * received in USB_DeviceKhciControl.
214 * @param khciState Pointer of the device KHCI state structure.
217 static void USB_DeviceKhciSetDefaultState(usb_device_khci_state_struct_t *khciState)
219 uint8_t interruptFlag;
221 /* Clear the error state register */
222 khciState->registerBase->ERRSTAT = 0xFFU;
224 /* Setting this bit to 1U resets all the BDT ODD ping/pong fields to 0U, which then specifies the EVEN BDT bank. */
225 khciState->registerBase->CTL |= USB_CTL_ODDRST_MASK;
227 /* Clear the device address */
228 khciState->registerBase->ADDR = 0U;
230 /* Clear the endpoint state and disable the endpoint */
231 for (uint8_t count = 0U; count < USB_DEVICE_CONFIG_ENDPOINTS; count++)
233 USB_KHCI_BDT_SET_CONTROL((uint32_t)khciState->bdt, count, USB_OUT, 0U, 0U);
234 USB_KHCI_BDT_SET_CONTROL((uint32_t)khciState->bdt, count, USB_OUT, 1U, 0U);
235 USB_KHCI_BDT_SET_CONTROL((uint32_t)khciState->bdt, count, USB_IN, 0U, 0U);
236 USB_KHCI_BDT_SET_CONTROL((uint32_t)khciState->bdt, count, USB_IN, 1U, 0U);
238 khciState->endpointState[((uint32_t)count << 1U) | USB_OUT].stateUnion.state = 0U;
239 khciState->endpointState[((uint32_t)count << 1U) | USB_IN].stateUnion.state = 0U;
240 khciState->registerBase->ENDPOINT[count].ENDPT = 0x00U;
242 khciState->isDmaAlignBufferInusing = 0U;
244 /* Clear the BDT odd reset flag */
245 khciState->registerBase->CTL &= ~USB_CTL_ODDRST_MASK;
247 /* Enable all error */
248 khciState->registerBase->ERREN = 0xFFU;
250 /* Enable reset, sof, token, stall interrupt */
251 interruptFlag = kUSB_KhciInterruptReset
253 | kUSB_KhciInterruptSofToken
255 | kUSB_KhciInterruptTokenDone | kUSB_KhciInterruptStall;
257 #if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
258 /* Enable suspend interruprt */
259 interruptFlag |= kUSB_KhciInterruptSleep;
260 #endif /* USB_DEVICE_CONFIG_LOW_POWER_MODE */
262 #if defined(USB_DEVICE_CONFIG_ERROR_HANDLING) && (USB_DEVICE_CONFIG_ERROR_HANDLING > 0U)
263 /* Enable error interruprt */
264 interruptFlag |= kUSB_KhciInterruptError;
265 #endif /* USB_DEVICE_CONFIG_ERROR_HANDLING */
266 /* Write the interrupt enable register */
267 khciState->registerBase->INTEN = interruptFlag;
269 /* Clear reset flag */
270 khciState->isResetting = 0U;
272 khciState->registerBase->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
276 * @brief Initialize a specified endpoint.
278 * The function is used to initialize a specified endpoint.
280 * @param khciState Pointer of the device KHCI state structure.
281 * @param epInit The endpoint initialization structure pointer.
283 * @return A USB error code or kStatus_USB_Success.
285 static usb_status_t USB_DeviceKhciEndpointInit(usb_device_khci_state_struct_t *khciState,
286 usb_device_endpoint_init_struct_t *epInit)
288 uint16_t maxPacketSize = epInit->maxPacketSize;
289 uint8_t endpoint = (epInit->endpointAddress & USB_ENDPOINT_NUMBER_MASK);
290 uint8_t direction = (epInit->endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
291 USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
292 uint8_t index = ((uint8_t)((uint32_t)endpoint << 1U)) | (uint8_t)direction;
294 /* Make the endpoint max packet size align with USB Specification 2.0. */
295 if (USB_ENDPOINT_ISOCHRONOUS == epInit->transferType)
297 if (maxPacketSize > USB_DEVICE_MAX_FS_ISO_MAX_PACKET_SIZE)
299 maxPacketSize = USB_DEVICE_MAX_FS_ISO_MAX_PACKET_SIZE;
304 if (maxPacketSize > USB_DEVICE_MAX_FS_NONE_ISO_MAX_PACKET_SIZE)
306 maxPacketSize = USB_DEVICE_MAX_FS_NONE_ISO_MAX_PACKET_SIZE;
308 /* Enable an endpoint to perform handshaking during a transaction to this endpoint. */
309 khciState->registerBase->ENDPOINT[endpoint].ENDPT |= USB_ENDPT_EPHSHK_MASK;
311 /* Set the endpoint idle */
312 khciState->endpointState[index].stateUnion.stateBitField.transferring = 0U;
313 /* Save the max packet size of the endpoint */
314 khciState->endpointState[index].stateUnion.stateBitField.maxPacketSize = maxPacketSize;
315 /* Set the data toggle to DATA0 */
316 khciState->endpointState[index].stateUnion.stateBitField.data0 = 0U;
317 /* Clear the endpoint stalled state */
318 khciState->endpointState[index].stateUnion.stateBitField.stalled = 0U;
319 /* Set the ZLT field */
320 khciState->endpointState[index].stateUnion.stateBitField.zlt = epInit->zlt;
321 /* Enable the endpoint. */
322 khciState->registerBase->ENDPOINT[endpoint].ENDPT |=
323 (USB_IN == direction) ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK;
324 #if defined(FSL_FEATURE_USB_KHCI_HAS_STALL_LOW) && (FSL_FEATURE_USB_KHCI_HAS_STALL_LOW > 0U)
325 /*control endpoint bidirection stall default state shoule be enable, iso doesn't support stall*/
326 if ((USB_ENDPOINT_BULK == epInit->transferType) || (USB_ENDPOINT_INTERRUPT == epInit->transferType))
328 if(USB_IN == direction)
332 khciState->registerBase->STALL_IL_DIS |= (1<<endpoint);
334 #if defined(FSL_FEATURE_USB_KHCI_HAS_STALL_HIGH) && (FSL_FEATURE_USB_KHCI_HAS_STALL_HIGH > 0U)
335 else if ((endpoint >= 8) && (endpoint < 16))
337 khciState->registerBase->STALL_IH_DIS |= (1<<(endpoint-8));
345 khciState->registerBase->STALL_OL_DIS |= (1<<endpoint);
347 #if defined(FSL_FEATURE_USB_KHCI_HAS_STALL_HIGH) && (FSL_FEATURE_USB_KHCI_HAS_STALL_HIGH > 0U)
348 else if ((endpoint >= 8) && (endpoint < 16))
350 khciState->registerBase->STALL_OH_DIS |= (1<<(endpoint-8));
355 else if ((USB_ENDPOINT_CONTROL == epInit->transferType))
357 khciState->registerBase->STALL_IL_DIS &= ~(1<<endpoint);
358 khciState->registerBase->STALL_OL_DIS &= ~(1<<endpoint);
365 /* Prime a transfer to receive next setup packet when the endpoint is control out endpoint. */
366 if ((USB_CONTROL_ENDPOINT == endpoint) && (USB_OUT == direction))
368 USB_DeviceKhciPrimeNextSetup(khciState);
371 return kStatus_USB_Success;
375 * @brief De-initialize a specified endpoint.
377 * The function is used to de-initialize a specified endpoint.
378 * Current transfer of the endpoint will be canceled and the specified endpoint will be disabled.
380 * @param khciState Pointer of the device KHCI state structure.
381 * @param ep The endpoint address, Bit7, 0U - USB_OUT, 1U - USB_IN.
383 * @return A USB error code or kStatus_USB_Success.
385 static usb_status_t USB_DeviceKhciEndpointDeinit(usb_device_khci_state_struct_t *khciState, uint8_t ep)
387 uint8_t endpoint = (ep & USB_ENDPOINT_NUMBER_MASK);
389 (ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
390 uint8_t index = ((uint8_t)((uint32_t)endpoint << 1U)) | (uint8_t)direction;
392 /* Cancel the transfer of the endpoint */
393 USB_DeviceKhciCancel(khciState, ep);
395 /* Disable the endpoint */
396 khciState->registerBase->ENDPOINT[endpoint].ENDPT = 0x00U;
397 /* Clear the max packet size */
398 khciState->endpointState[index].stateUnion.stateBitField.maxPacketSize = 0U;
400 return kStatus_USB_Success;
404 * @brief Stall a specified endpoint.
406 * The function is used to stall a specified endpoint.
407 * Current transfer of the endpoint will be canceled and the specified endpoint will be stalled.
409 * @param khciState Pointer of the device KHCI state structure.
410 * @param ep The endpoint address, Bit7, 0U - USB_OUT, 1U - USB_IN.
412 * @return A USB error code or kStatus_USB_Success.
414 static usb_status_t USB_DeviceKhciEndpointStall(usb_device_khci_state_struct_t *khciState, uint8_t ep)
416 uint8_t endpoint = ep & USB_ENDPOINT_NUMBER_MASK;
418 (ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
419 uint8_t index = ((uint8_t)((uint32_t)endpoint << 1U)) | (uint8_t)direction;
421 /* Cancel the transfer of the endpoint */
422 USB_DeviceKhciCancel(khciState, ep);
424 /* Set endpoint stall flag. */
425 khciState->endpointState[index].stateUnion.stateBitField.stalled = 1U;
426 #if defined(FSL_FEATURE_USB_KHCI_HAS_STALL_LOW) && (FSL_FEATURE_USB_KHCI_HAS_STALL_LOW > 0U)
427 if (USB_CONTROL_ENDPOINT != endpoint)
429 if(USB_IN == direction)
433 khciState->registerBase->STALL_IL_DIS &= ~(1<<endpoint);
435 #if defined(FSL_FEATURE_USB_KHCI_HAS_STALL_HIGH) && (FSL_FEATURE_USB_KHCI_HAS_STALL_HIGH > 0U)
436 else if ((endpoint >= 8) && (endpoint < 16))
438 khciState->registerBase->STALL_IH_DIS &= ~(1<<(endpoint-8));
446 khciState->registerBase->STALL_OL_DIS &= ~(1<<endpoint);
448 #if defined(FSL_FEATURE_USB_KHCI_HAS_STALL_HIGH) && (FSL_FEATURE_USB_KHCI_HAS_STALL_HIGH > 0U)
449 else if ((endpoint >= 8) && (endpoint < 16))
451 khciState->registerBase->STALL_OH_DIS &= ~(1<<(endpoint-8));
457 /* Set endpoint stall in BDT. And then if the host send a IN/OUT tanscation, the device will response a STALL state.
459 USB_KHCI_BDT_SET_CONTROL(
460 (uint32_t)khciState->bdt, endpoint, direction, khciState->endpointState[index].stateUnion.stateBitField.bdtOdd,
461 USB_LONG_TO_LITTLE_ENDIAN(
462 (uint32_t)(USB_KHCI_BDT_BC(khciState->endpointState[index].stateUnion.stateBitField.maxPacketSize) |
463 USB_KHCI_BDT_DTS | USB_KHCI_BDT_STALL | USB_KHCI_BDT_OWN)));
465 khciState->registerBase->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
467 return kStatus_USB_Success;
471 * @brief Un-stall a specified endpoint.
473 * The function is used to un-stall a specified endpoint.
474 * Current transfer of the endpoint will be canceled and the specified endpoint will be un-stalled.
476 * @param khciState Pointer of the device KHCI state structure.
477 * @param ep The endpoint address, Bit7, 0U - USB_OUT, 1U - USB_IN.
479 * @return A USB error code or kStatus_USB_Success.
481 static usb_status_t USB_DeviceKhciEndpointUnstall(usb_device_khci_state_struct_t *khciState, uint8_t ep)
483 uint8_t endpoint = ep & USB_ENDPOINT_NUMBER_MASK;
485 (ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
486 uint8_t index = ((uint8_t)((uint32_t)endpoint << 1U)) | (uint8_t)direction;
488 /* Clear the endpoint stall state */
489 khciState->endpointState[index].stateUnion.stateBitField.stalled = 0U;
490 /* Reset the endpoint data toggle to DATA0 */
491 khciState->endpointState[index].stateUnion.stateBitField.data0 = 0U;
493 /* Clear stall state in BDT */
494 for (uint8_t i = 0U; i < 2U; i++)
496 USB_KHCI_BDT_SET_CONTROL(
497 (uint32_t)khciState->bdt, endpoint, direction, i,
498 USB_LONG_TO_LITTLE_ENDIAN(
499 (uint32_t)(USB_KHCI_BDT_BC(khciState->endpointState[index].stateUnion.stateBitField.maxPacketSize) |
500 USB_KHCI_BDT_DTS | USB_KHCI_BDT_DATA01(0U))));
503 /* Clear stall state in endpoint control register */
504 khciState->registerBase->ENDPOINT[endpoint].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
505 #if defined(FSL_FEATURE_USB_KHCI_HAS_STALL_LOW) && (FSL_FEATURE_USB_KHCI_HAS_STALL_LOW > 0U)
506 if (USB_CONTROL_ENDPOINT != endpoint)
508 if(USB_IN == direction)
512 khciState->registerBase->STALL_IL_DIS |= (1<<endpoint);
514 #if defined(FSL_FEATURE_USB_KHCI_HAS_STALL_HIGH) && (FSL_FEATURE_USB_KHCI_HAS_STALL_HIGH > 0U)
515 else if ((endpoint >= 8) && (endpoint < 16))
517 khciState->registerBase->STALL_IH_DIS |= (1<<(endpoint-8));
525 khciState->registerBase->STALL_OL_DIS |= (1<<endpoint);
527 #if defined(FSL_FEATURE_USB_KHCI_HAS_STALL_HIGH) && (FSL_FEATURE_USB_KHCI_HAS_STALL_HIGH > 0U)
528 else if ((endpoint >= 8) && (endpoint < 16))
530 khciState->registerBase->STALL_OH_DIS |= (1<<(endpoint-8));
536 if ((USB_CONTROL_ENDPOINT != endpoint))
538 /* Cancel the transfer of the endpoint */
539 USB_DeviceKhciCancel(khciState, ep);
542 /* Prime a transfer to receive next setup packet when the endpoint is a control out endpoint. */
543 if ((USB_CONTROL_ENDPOINT == endpoint) && (USB_OUT == direction))
545 USB_DeviceKhciPrimeNextSetup(khciState);
548 khciState->registerBase->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
550 return kStatus_USB_Success;
554 * @brief Handle the token done interrupt.
556 * The function is used to handle the token done interrupt.
558 * @param khciState Pointer of the device KHCI state structure.
561 static void USB_DeviceKhciInterruptTokenDone(usb_device_khci_state_struct_t *khciState)
565 uint32_t remainingLength;
567 usb_device_callback_message_struct_t message;
573 uint8_t stateRegister = khciState->registerBase->STAT;
575 /* Get the endpoint number to identify which one triggers the token done interrupt. */
576 endpoint = (stateRegister & USB_STAT_ENDP_MASK) >> USB_STAT_ENDP_SHIFT;
578 /* Get the direction of the endpoint number. */
579 direction = (stateRegister & USB_STAT_TX_MASK) >> USB_STAT_TX_SHIFT;
581 /* Get the finished BDT ODD. */
582 bdtOdd = (stateRegister & USB_STAT_ODD_MASK) >> USB_STAT_ODD_SHIFT;
584 /* Clear token done interrupt flag. */
585 khciState->registerBase->ISTAT = kUSB_KhciInterruptTokenDone;
587 /* Get the Control field of the BDT element according to the endpoint number, the direction and finished BDT ODD. */
588 control = USB_KHCI_BDT_GET_CONTROL((uint32_t)khciState->bdt, endpoint, direction, bdtOdd);
590 /* Get the buffer field of the BDT element according to the endpoint number, the direction and finished BDT ODD. */
591 bdtBuffer = (uint8_t *)USB_KHCI_BDT_GET_ADDRESS((uint32_t)khciState->bdt, endpoint, direction, bdtOdd);
593 /* Get the transferred length. */
594 length = ((USB_LONG_FROM_LITTLE_ENDIAN(control)) >> 16U) & 0x3FFU;
596 /* Get the transferred length. */
597 isSetup = (USB_KHCI_BDT_DEVICE_SETUP_TOKEN == ((uint8_t)(((USB_LONG_FROM_LITTLE_ENDIAN(control)) >> 2U) & 0x0FU))) ?
601 index = ((uint8_t)((uint32_t)endpoint << 1U)) | (uint8_t)direction;
603 if (0U == khciState->endpointState[index].stateUnion.stateBitField.transferring)
610 khciState->setupBufferIndex = bdtOdd;
613 /* USB_IN, Send completed */
614 if (direction == USB_IN)
616 /* The transferred length */
617 khciState->endpointState[index].transferDone += length;
619 /* Remaining length */
620 remainingLength = khciState->endpointState[index].transferLength - khciState->endpointState[index].transferDone;
622 /* Change the data toggle flag */
623 khciState->endpointState[index].stateUnion.stateBitField.data0 ^= 1U;
624 /* Change the BDT odd toggle flag */
625 khciState->endpointState[index].stateUnion.stateBitField.bdtOdd ^= 1U;
627 /* Whether the transfer is completed or not. */
629 * The transfer is completed when one of the following conditions meet:
630 * 1. The remaining length is zero.
631 * 2. The length of current transcation is less than the max packet size of the current pipe.
633 if ((0U == remainingLength) ||
634 (khciState->endpointState[index].stateUnion.stateBitField.maxPacketSize > length))
636 message.length = khciState->endpointState[index].transferDone;
637 message.buffer = khciState->endpointState[index].transferBuffer;
638 khciState->endpointState[index].stateUnion.stateBitField.transferring = 0U;
641 * Whether need to send ZLT when the pipe is control in pipe and the transferred length of current
642 * transaction equals to max packet size.
644 if ((length) && (!(length % khciState->endpointState[index].stateUnion.stateBitField.maxPacketSize)))
646 if (USB_CONTROL_ENDPOINT == endpoint)
648 usb_setup_struct_t *setup_packet =
650 *)(&khciState->setupPacketBuffer[(USB_SETUP_PACKET_SIZE * khciState->setupBufferIndex)]);
652 * Send the ZLT and terminate the token done interrupt service when the tranferred length in data
654 * is less than the host request.
656 if (USB_SHORT_FROM_LITTLE_ENDIAN(setup_packet->wLength) >
657 khciState->endpointState[index].transferLength)
659 (void)USB_DeviceKhciEndpointTransfer(khciState, endpoint, USB_IN, (uint8_t *)NULL, 0U);
663 else if (khciState->endpointState[index].stateUnion.stateBitField.zlt)
665 (void)USB_DeviceKhciEndpointTransfer(khciState, endpoint, USB_IN, (uint8_t *)NULL, 0U);
675 /* Send remaining data and terminate the token done interrupt service. */
676 (void)USB_DeviceKhciSend(khciState, endpoint | (USB_IN << 0x07U),
677 khciState->endpointState[index].transferBuffer, remainingLength);
683 if ((USB_CONTROL_ENDPOINT == endpoint) && (0U == length))
686 message.buffer = (uint8_t *)NULL;
690 if (0U == khciState->endpointState[index].stateUnion.stateBitField.dmaAlign)
692 uint8_t *buffer = (uint8_t *)USB_LONG_FROM_LITTLE_ENDIAN(
693 USB_KHCI_BDT_GET_ADDRESS((uint32_t)khciState->bdt, endpoint, USB_OUT,
694 khciState->endpointState[index].stateUnion.stateBitField.bdtOdd));
695 uint8_t *transferBuffer =
696 khciState->endpointState[index].transferBuffer + khciState->endpointState[index].transferDone;
697 if (buffer != transferBuffer)
699 for (uint32_t i = 0U; i < length; i++)
701 transferBuffer[i] = buffer[i];
704 khciState->isDmaAlignBufferInusing = 0U;
706 /* The transferred length */
707 khciState->endpointState[index].transferDone += length;
708 /* Remaining length */
710 khciState->endpointState[index].transferLength - khciState->endpointState[index].transferDone;
712 if ((USB_CONTROL_ENDPOINT == endpoint) && isSetup)
714 khciState->endpointState[(USB_CONTROL_ENDPOINT << 1U) | USB_OUT].stateUnion.stateBitField.data0 = 1U;
715 khciState->endpointState[(USB_CONTROL_ENDPOINT << 1U) | USB_IN].stateUnion.stateBitField.data0 = 1U;
719 khciState->endpointState[index].stateUnion.stateBitField.data0 ^= 1U;
721 khciState->endpointState[index].stateUnion.stateBitField.bdtOdd ^= 1U;
722 if ((!khciState->endpointState[index].transferLength) || (!remainingLength) ||
723 (khciState->endpointState[index].stateUnion.stateBitField.maxPacketSize > length))
725 message.length = khciState->endpointState[index].transferDone;
728 message.buffer = bdtBuffer;
732 message.buffer = khciState->endpointState[index].transferBuffer;
734 khciState->endpointState[index].stateUnion.stateBitField.transferring = 0U;
738 /* Receive remaining data and terminate the token done interrupt service. */
739 USB_DeviceKhciRecv(khciState, (endpoint) | (USB_OUT << 0x07U),
740 khciState->endpointState[index].transferBuffer, remainingLength);
746 message.isSetup = isSetup;
747 message.code = (endpoint) | (uint8_t)(((uint32_t)direction << 0x07U));
749 /* Notify the up layer the KHCI status changed. */
750 USB_DeviceNotificationTrigger(khciState->deviceHandle, &message);
752 khciState->registerBase->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
756 * @brief Handle the USB bus reset interrupt.
758 * The function is used to handle the USB bus reset interrupt.
760 * @param khciState Pointer of the device KHCI state structure.
763 static void USB_DeviceKhciInterruptReset(usb_device_khci_state_struct_t *khciState)
765 usb_device_callback_message_struct_t message;
767 /* Set KHCI reset flag */
768 khciState->isResetting = 1U;
770 /* Clear the reset interrupt */
771 khciState->registerBase->ISTAT = (kUSB_KhciInterruptReset);
772 #if ((defined(USB_DEVICE_CONFIG_LOW_POWER_MODE)) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
773 /* Clear the suspend interrupt */
774 khciState->registerBase->ISTAT = (kUSB_KhciInterruptSleep);
775 khciState->registerBase->USBCTRL &= ~USB_USBCTRL_SUSP_MASK;
778 message.buffer = (uint8_t *)NULL;
779 message.code = kUSB_DeviceNotifyBusReset;
781 message.isSetup = 0U;
782 /* Notify up layer the USB bus reset signal detected. */
783 USB_DeviceNotificationTrigger(khciState->deviceHandle, &message);
786 /* The USB suspend and resume signals need to be detected and handled when the low power or remote wakeup function
788 #if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
791 * @brief Handle the suspend interrupt.
793 * The function is used to handle the suspend interrupt when the suspend signal detected.
795 * @param khciState Pointer of the device KHCI state structure.
798 static void USB_DeviceKhciInterruptSleep(usb_device_khci_state_struct_t *khciState)
800 usb_device_callback_message_struct_t message;
802 /* Enable the resume interrupt */
803 khciState->registerBase->INTEN |= kUSB_KhciInterruptResume;
804 khciState->registerBase->USBTRC0 |= USB_USBTRC0_USBRESMEN_MASK;
805 khciState->registerBase->USBCTRL |= USB_USBCTRL_SUSP_MASK;
806 /* Disable the suspend interrupt */
807 khciState->registerBase->INTEN &= ~((uint32_t)kUSB_KhciInterruptSleep);
809 /* Clear the suspend interrupt */
810 khciState->registerBase->ISTAT = (kUSB_KhciInterruptSleep);
811 /* Clear the resume interrupt */
812 khciState->registerBase->ISTAT = (kUSB_KhciInterruptResume);
814 message.buffer = (uint8_t *)NULL;
815 message.code = kUSB_DeviceNotifySuspend;
817 message.isSetup = 0U;
819 /* Notify up layer the USB suspend signal detected. */
820 USB_DeviceNotificationTrigger(khciState->deviceHandle, &message);
824 * @brief Handle the resume interrupt.
826 * The function is used to handle the resume interrupt when the resume signal detected.
828 * @param khciState Pointer of the device KHCI state structure.
831 static void USB_DeviceKhciInterruptResume(usb_device_khci_state_struct_t *khciState)
833 usb_device_callback_message_struct_t message;
835 khciState->registerBase->USBCTRL &= ~USB_USBCTRL_SUSP_MASK;
836 /* Enable the suspend interrupt */
837 khciState->registerBase->INTEN |= kUSB_KhciInterruptSleep;
838 /* Disable the resume interrupt */
839 khciState->registerBase->INTEN &= ~((uint32_t)kUSB_KhciInterruptResume);
840 khciState->registerBase->USBTRC0 &= ~USB_USBTRC0_USBRESMEN_MASK;
842 /* Clear the resume interrupt */
843 khciState->registerBase->ISTAT = (kUSB_KhciInterruptResume);
844 /* Clear the suspend interrupt */
845 khciState->registerBase->ISTAT = (kUSB_KhciInterruptSleep);
847 message.buffer = (uint8_t *)NULL;
848 message.code = kUSB_DeviceNotifyResume;
850 message.isSetup = 0U;
852 /* Notify up layer the USB resume signal detected. */
853 USB_DeviceNotificationTrigger(khciState->deviceHandle, &message);
855 #endif /* USB_DEVICE_CONFIG_LOW_POWER_MODE */
857 #if (defined(USB_DEVICE_CONFIG_DETACH_ENABLE) && (USB_DEVICE_CONFIG_DETACH_ENABLE > 0U)) && \
858 (defined(FSL_FEATURE_USB_KHCI_VBUS_DETECT_ENABLED) && (FSL_FEATURE_USB_KHCI_VBUS_DETECT_ENABLED > 0U))
860 * @brief Handle the VBUS rising interrupt.
862 * The function is used to handle the VBUS rising interrupt when the VBUS rising signal detected.
864 * @param khciState Pointer of the device KHCI state structure.
867 static void USB_DeviceKhciInterruptVbusRising(usb_device_khci_state_struct_t *khciState)
869 usb_device_callback_message_struct_t message;
871 /* Disable the VBUS rising interrupt */
872 khciState->registerBase->MISCCTRL &= ~USB_MISCCTRL_VREDG_EN_MASK;
873 /* Enable the VBUS rising interrupt */
874 khciState->registerBase->MISCCTRL |= USB_MISCCTRL_VREDG_EN_MASK;
876 message.buffer = (uint8_t *)NULL;
877 message.code = kUSB_DeviceNotifyAttach;
879 message.isSetup = 0U;
881 /* Notify up layer the USB VBUS rising signal detected. */
882 USB_DeviceNotificationTrigger(khciState->deviceHandle, &message);
886 * @brief Handle the VBUS falling interrupt.
888 * The function is used to handle the VBUS falling interrupt when the VBUS falling signal detected.
890 * @param khciState Pointer of the device KHCI state structure.
893 static void USB_DeviceKhciInterruptVbusFalling(usb_device_khci_state_struct_t *khciState)
895 usb_device_callback_message_struct_t message;
897 /* Disable the VBUS rising interrupt */
898 khciState->registerBase->MISCCTRL &= ~USB_MISCCTRL_VFEDG_EN_MASK;
899 /* Enable the VBUS rising interrupt */
900 khciState->registerBase->MISCCTRL |= USB_MISCCTRL_VFEDG_EN_MASK;
902 message.buffer = (uint8_t *)NULL;
903 message.code = kUSB_DeviceNotifyDetach;
905 message.isSetup = 0U;
907 /* Notify up layer the USB VBUS falling signal detected. */
908 USB_DeviceNotificationTrigger(khciState->deviceHandle, &message);
910 #endif /* USB_DEVICE_CONFIG_DETACH_ENABLE || FSL_FEATURE_USB_KHCI_VBUS_DETECT_ENABLED */
914 * @brief Handle the sof interrupt.
916 * The function is used to handle the sof interrupt.
918 * @param khciState Pointer of the device KHCI state structure.
921 void USB_DeviceKhciInterruptSof(usb_device_khci_state_struct_t *khciState)
923 khciState->registerBase->ISTAT = (kUSB_KhciInterruptSofToken);
925 khciState->registerBase->ISTAT = (kUSB_KhciInterruptResume);
930 * @brief Handle endpoint stalled interrupt.
932 * The function is used to handle endpoint stalled interrupt.
934 * @param khciState Pointer of the device KHCI state structure.
937 static void USB_DeviceKhciInterruptStall(usb_device_khci_state_struct_t *khciState)
939 /* Clear the endpoint stalled interrupt flag */
940 while (khciState->registerBase->ISTAT & (kUSB_KhciInterruptStall))
942 khciState->registerBase->ISTAT = (kUSB_KhciInterruptStall);
945 /* Un-stall the control in and out pipe when the control in or out pipe stalled. */
946 if ((khciState->endpointState[(USB_CONTROL_ENDPOINT << 1U) | USB_IN].stateUnion.stateBitField.stalled) ||
947 (khciState->endpointState[(USB_CONTROL_ENDPOINT << 1U) | USB_OUT].stateUnion.stateBitField.stalled))
949 USB_DeviceKhciEndpointUnstall(
950 khciState, (USB_CONTROL_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)));
951 USB_DeviceKhciEndpointUnstall(
952 khciState, (USB_CONTROL_ENDPOINT | (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)));
956 #if defined(USB_DEVICE_CONFIG_ERROR_HANDLING) && (USB_DEVICE_CONFIG_ERROR_HANDLING > 0U)
957 static void USB_DeviceKhciInterruptError(usb_device_khci_state_struct_t *khciState)
959 usb_device_callback_message_struct_t message;
961 khciState->registerBase->ISTAT = (kUSB_KhciInterruptError);
963 message.buffer = (uint8_t *)NULL;
964 message.code = kUSB_DeviceNotifyError;
966 message.isSetup = 0U;
968 /* Notify up layer the USB error detected. */
969 USB_DeviceNotificationTrigger(khciState->deviceHandle, &message);
971 #endif /* USB_DEVICE_CONFIG_ERROR_HANDLING */
974 * @brief Initialize the USB device KHCI instance.
976 * This function initizlizes the USB device KHCI module specified by the controllerId.
978 * @param controllerId The controller id of the USB IP. Please refer to enumeration type usb_controller_index_t.
979 * @param handle Pointer of the device handle, used to identify the device object is belonged to.
980 * @param khciHandle It is out parameter, is used to return pointer of the device KHCI handle to the caller.
982 * @return A USB error code or kStatus_USB_Success.
984 usb_status_t USB_DeviceKhciInit(uint8_t controllerId,
985 usb_device_handle handle,
986 usb_device_controller_handle *khciHandle)
988 usb_device_khci_state_struct_t *khciState;
989 uint32_t khci_base[] = USB_BASE_ADDRS;
990 #if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
991 (defined(FSL_FEATURE_SOC_USBDCD_COUNT) && (FSL_FEATURE_SOC_USBDCD_COUNT > 0U))
992 usb_device_dcd_state_struct_t *dcdState;
993 uint32_t dcd_base[] = USBDCD_BASE_ADDRS;
996 if (((controllerId - kUSB_ControllerKhci0) >= (uint8_t)USB_DEVICE_CONFIG_KHCI) ||
997 ((controllerId - kUSB_ControllerKhci0) >= (sizeof(khci_base) / sizeof(uint32_t))))
999 return kStatus_USB_ControllerNotFound;
1001 khciState = &s_UsbDeviceKhciState[controllerId - kUSB_ControllerKhci0];
1003 khciState->controllerId = controllerId;
1005 khciState->registerBase = (USB_Type *)khci_base[controllerId - kUSB_ControllerKhci0];
1007 khciState->dmaAlignBuffer = (uint8_t *)&s_UsbDeviceKhciDmaAlignBuffer[controllerId - kUSB_ControllerKhci0][0];
1009 /* Clear all interrupt flags. */
1010 khciState->registerBase->ISTAT = 0xFFU;
1012 #if (defined(USB_DEVICE_CONFIG_OTG) && (USB_DEVICE_CONFIG_OTG))
1013 khciState->otgStatus = 0U;
1015 /* Disable the device functionality. */
1016 USB_DeviceKhciControl(khciState, kUSB_DeviceControlStop, NULL);
1019 khciState->bdt = s_UsbDeviceKhciBdtBuffer[controllerId - kUSB_ControllerKhci0];
1021 /* Set BDT buffer address */
1022 khciState->registerBase->BDTPAGE1 = (uint8_t)((((uint32_t)khciState->bdt) >> 8U) & 0xFFU);
1023 khciState->registerBase->BDTPAGE2 = (uint8_t)((((uint32_t)khciState->bdt) >> 16U) & 0xFFU);
1024 khciState->registerBase->BDTPAGE3 = (uint8_t)((((uint32_t)khciState->bdt) >> 24U) & 0xFFU);
1026 #if (defined(USB_DEVICE_CONFIG_DETACH_ENABLE) && (USB_DEVICE_CONFIG_DETACH_ENABLE > 0U)) && \
1027 (defined(FSL_FEATURE_USB_KHCI_VBUS_DETECT_ENABLED) && (FSL_FEATURE_USB_KHCI_VBUS_DETECT_ENABLED > 0U))
1028 khciState->registerBase->MISCCTRL |= USB_MISCCTRL_VREDG_EN_MASK | USB_MISCCTRL_VFEDG_EN_MASK;
1031 #if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
1032 defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \
1033 defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
1034 khciState->registerBase->CLK_RECOVER_CTRL |= USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN_MASK;
1035 khciState->registerBase->KEEP_ALIVE_CTRL =
1036 USB_KEEP_ALIVE_CTRL_KEEP_ALIVE_EN_MASK | USB_KEEP_ALIVE_CTRL_OWN_OVERRD_EN_MASK |
1037 USB_KEEP_ALIVE_CTRL_WAKE_INT_EN_MASK | FSL_FEATURE_USB_KHCI_KEEP_ALIVE_MODE_CONTROL;
1038 /* wake on out and setup transaction */
1039 khciState->registerBase->KEEP_ALIVE_WKCTRL = 0x1U;
1040 #if defined(FSL_FEATURE_SOC_MCGLITE_COUNT) && (FSL_FEATURE_SOC_MCGLITE_COUNT > 0U)
1041 MCG->MC |= MCG_MC_HIRCLPEN_MASK;
1045 #if defined(FSL_FEATURE_USB_KHCI_HAS_STALL_LOW) && (FSL_FEATURE_USB_KHCI_HAS_STALL_LOW > 0U)
1046 khciState->registerBase->MISCCTRL |= USB_MISCCTRL_STL_ADJ_EN_MASK;
1049 /* Set KHCI device state to default value. */
1050 USB_DeviceKhciSetDefaultState(khciState);
1052 *khciHandle = khciState;
1053 khciState->deviceHandle = (usb_device_struct_t *)handle;
1054 #if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
1055 (defined(FSL_FEATURE_SOC_USBDCD_COUNT) && (FSL_FEATURE_SOC_USBDCD_COUNT > 0U))
1056 dcdState = &s_UsbDeviceDcdState[controllerId - kUSB_ControllerKhci0];
1058 dcdState->controllerId = controllerId;
1060 dcdState->dcdRegisterBase = (USBDCD_Type *)dcd_base[controllerId - kUSB_ControllerKhci0];
1062 dcdState->deviceHandle = (usb_device_struct_t *)handle;
1065 return kStatus_USB_Success;
1069 * @brief De-initialize the USB device KHCI instance.
1071 * This function de-initizlizes the USB device KHCI module.
1073 * @param khciHandle Pointer of the device KHCI handle.
1075 * @return A USB error code or kStatus_USB_Success.
1077 usb_status_t USB_DeviceKhciDeinit(usb_device_controller_handle khciHandle)
1079 usb_device_khci_state_struct_t *khciState = (usb_device_khci_state_struct_t *)khciHandle;
1083 return kStatus_USB_InvalidHandle;
1085 /* Clear all interrupt flags. */
1086 khciState->registerBase->ISTAT = 0xFFU;
1087 /* Disable all interrupts. */
1088 khciState->registerBase->INTEN &= ~(0xFFU);
1089 /* Clear device address. */
1090 khciState->registerBase->ADDR = (0U);
1092 /* Clear USB_CTL register */
1093 khciState->registerBase->CTL = 0x00U;
1094 khciState->registerBase->USBCTRL |= USB_USBCTRL_PDE_MASK | USB_USBCTRL_SUSP_MASK;
1096 return kStatus_USB_Success;
1100 * @brief Send data through a specified endpoint.
1102 * This function sends data through a specified endpoint.
1104 * @param khciHandle Pointer of the device KHCI handle.
1105 * @param endpointAddress Endpoint index.
1106 * @param buffer The memory address to hold the data need to be sent.
1107 * @param length The data length need to be sent.
1109 * @return A USB error code or kStatus_USB_Success.
1111 * @note The return value just means if the sending request is successful or not; the transfer done is notified by the
1112 * corresponding callback function.
1113 * Currently, only one transfer request can be supported for one specific endpoint.
1114 * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
1115 * should implement a queue in the application level.
1116 * The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint
1119 usb_status_t USB_DeviceKhciSend(usb_device_controller_handle khciHandle,
1120 uint8_t endpointAddress,
1124 usb_device_khci_state_struct_t *khciState = (usb_device_khci_state_struct_t *)khciHandle;
1125 uint32_t index = ((endpointAddress & USB_ENDPOINT_NUMBER_MASK) << 1U) | USB_IN;
1126 usb_status_t error = kStatus_USB_Error;
1128 /* Save the tansfer information */
1129 if (0U == khciState->endpointState[index].stateUnion.stateBitField.transferring)
1131 khciState->endpointState[index].transferDone = 0U;
1132 khciState->endpointState[index].transferBuffer = buffer;
1133 khciState->endpointState[index].transferLength = length;
1134 khciState->endpointState[index].stateUnion.stateBitField.dmaAlign = 1U;
1137 /* Data length needs to less than max packet size in each call. */
1138 if (length > khciState->endpointState[index].stateUnion.stateBitField.maxPacketSize)
1140 length = khciState->endpointState[index].stateUnion.stateBitField.maxPacketSize;
1143 /* Send data when the device is not resetting. */
1144 if (0U == khciState->isResetting)
1146 error = USB_DeviceKhciEndpointTransfer(khciState, endpointAddress & USB_ENDPOINT_NUMBER_MASK, USB_IN,
1147 (uint8_t *)((uint32_t)khciState->endpointState[index].transferBuffer +
1148 (uint32_t)khciState->endpointState[index].transferDone),
1152 /* Prime a transfer to receive next setup packet if the dat length is zero in a control in endpoint. */
1153 if ((0U == khciState->endpointState[index].transferDone) && (0U == length) &&
1154 (USB_CONTROL_ENDPOINT == (endpointAddress & USB_ENDPOINT_NUMBER_MASK)))
1156 USB_DeviceKhciPrimeNextSetup(khciState);
1162 * @brief Receive data through a specified endpoint.
1164 * This function Receives data through a specified endpoint.
1166 * @param khciHandle Pointer of the device KHCI handle.
1167 * @param endpointAddress Endpoint index.
1168 * @param buffer The memory address to save the received data.
1169 * @param length The data length want to be received.
1171 * @return A USB error code or kStatus_USB_Success.
1173 * @note The return value just means if the receiving request is successful or not; the transfer done is notified by the
1174 * corresponding callback function.
1175 * Currently, only one transfer request can be supported for one specific endpoint.
1176 * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
1177 * should implement a queue in the application level.
1178 * The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint
1181 usb_status_t USB_DeviceKhciRecv(usb_device_controller_handle khciHandle,
1182 uint8_t endpointAddress,
1186 usb_device_khci_state_struct_t *khciState = (usb_device_khci_state_struct_t *)khciHandle;
1187 uint32_t index = ((endpointAddress & USB_ENDPOINT_NUMBER_MASK) << 1U) | USB_OUT;
1188 usb_status_t error = kStatus_USB_Error;
1190 if ((0U == length) && (USB_CONTROL_ENDPOINT == (endpointAddress & USB_ENDPOINT_NUMBER_MASK)))
1192 khciState->endpointState[index].stateUnion.stateBitField.transferring = 0U;
1193 USB_DeviceKhciPrimeNextSetup(khciState);
1197 /* Save the tansfer information */
1198 if (0U == khciState->endpointState[index].stateUnion.stateBitField.transferring)
1200 khciState->endpointState[index].transferDone = 0U;
1201 khciState->endpointState[index].transferBuffer = buffer;
1202 khciState->endpointState[index].transferLength = length;
1204 khciState->endpointState[index].stateUnion.stateBitField.dmaAlign = 1U;
1206 /* Data length needs to less than max packet size in each call. */
1207 if (length > khciState->endpointState[index].stateUnion.stateBitField.maxPacketSize)
1209 length = khciState->endpointState[index].stateUnion.stateBitField.maxPacketSize;
1212 buffer = (uint8_t *)((uint32_t)buffer + (uint32_t)khciState->endpointState[index].transferDone);
1214 if ((khciState->dmaAlignBuffer) && (0U == khciState->isDmaAlignBufferInusing) &&
1215 (USB_DEVICE_CONFIG_KHCI_DMA_ALIGN_BUFFER_LENGTH >= length) &&
1216 ((length & 0x03U) || (((uint32_t)buffer) & 0x03U)))
1218 khciState->endpointState[index].stateUnion.stateBitField.dmaAlign = 0U;
1219 buffer = khciState->dmaAlignBuffer;
1220 khciState->isDmaAlignBufferInusing = 1U;
1223 /* Receive data when the device is not resetting. */
1224 if (0U == khciState->isResetting)
1226 error = USB_DeviceKhciEndpointTransfer(khciState, endpointAddress & USB_ENDPOINT_NUMBER_MASK, USB_OUT,
1234 * @brief Cancel the pending transfer in a specified endpoint.
1236 * The function is used to cancel the pending transfer in a specified endpoint.
1238 * @param khciHandle Pointer of the device KHCI handle.
1239 * @param ep Endpoint address, bit7 is the direction of endpoint, 1U - IN, abd 0U - OUT.
1241 * @return A USB error code or kStatus_USB_Success.
1243 usb_status_t USB_DeviceKhciCancel(usb_device_controller_handle khciHandle, uint8_t ep)
1245 usb_device_khci_state_struct_t *khciState = (usb_device_khci_state_struct_t *)khciHandle;
1246 usb_device_callback_message_struct_t message;
1247 uint8_t index = ((ep & USB_ENDPOINT_NUMBER_MASK) << 1U) | ((ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
1248 USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
1250 /* Cancel the transfer and notify the up layer when the endpoint is busy. */
1251 if (khciState->endpointState[index].stateUnion.stateBitField.transferring)
1253 message.length = USB_UNINITIALIZED_VAL_32;
1254 message.buffer = khciState->endpointState[index].transferBuffer;
1256 message.isSetup = 0U;
1257 khciState->endpointState[index].stateUnion.stateBitField.transferring = 0U;
1258 USB_DeviceNotificationTrigger(khciState->deviceHandle, &message);
1260 return kStatus_USB_Success;
1264 * @brief Control the status of the selected item.
1266 * The function is used to control the status of the selected item.
1268 * @param khciHandle Pointer of the device KHCI handle.
1269 * @param type The selected item. Please refer to enumeration type usb_device_control_type_t.
1270 * @param param The param type is determined by the selected item.
1272 * @return A USB error code or kStatus_USB_Success.
1274 usb_status_t USB_DeviceKhciControl(usb_device_controller_handle khciHandle, usb_device_control_type_t type, void *param)
1276 usb_device_khci_state_struct_t *khciState = (usb_device_khci_state_struct_t *)khciHandle;
1279 #if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
1280 (defined(FSL_FEATURE_SOC_USBDCD_COUNT) && (FSL_FEATURE_SOC_USBDCD_COUNT > 0U))
1281 usb_device_dcd_state_struct_t *dcdState;
1282 dcdState = &s_UsbDeviceDcdState[khciState->controllerId - kUSB_ControllerKhci0];
1283 usb_device_dcd_charging_time_t *deviceDcdTimingConfig = (usb_device_dcd_charging_time_t *)param;
1285 #if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
1286 usb_device_struct_t *deviceHandle;
1289 usb_status_t error = kStatus_USB_Error;
1293 return kStatus_USB_InvalidHandle;
1296 #if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
1297 deviceHandle = (usb_device_struct_t *)khciState->deviceHandle;
1302 case kUSB_DeviceControlRun:
1303 khciState->registerBase->USBCTRL = 0U;
1304 #if defined(FSL_FEATURE_USB_KHCI_OTG_ENABLED) && (FSL_FEATURE_USB_KHCI_OTG_ENABLED > 0U)
1305 if (khciState->registerBase->OTGCTL & USB_OTGCTL_OTGEN_MASK)
1307 khciState->registerBase->OTGCTL |= USB_OTGCTL_DPHIGH_MASK;
1309 #endif /* FSL_FEATURE_USB_KHCI_OTG_ENABLED */
1310 khciState->registerBase->CONTROL |= USB_CONTROL_DPPULLUPNONOTG_MASK;
1311 khciState->registerBase->CTL |= USB_CTL_USBENSOFEN_MASK;
1313 error = kStatus_USB_Success;
1315 case kUSB_DeviceControlStop:
1316 #if defined(FSL_FEATURE_USB_KHCI_OTG_ENABLED) && (FSL_FEATURE_USB_KHCI_OTG_ENABLED > 0U)
1317 if (khciState->registerBase->OTGCTL & USB_OTGCTL_OTGEN_MASK)
1319 khciState->registerBase->OTGCTL &= ~USB_OTGCTL_DPHIGH_MASK;
1321 #endif /* FSL_FEATURE_USB_KHCI_OTG_ENABLED */
1322 khciState->registerBase->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK;
1323 error = kStatus_USB_Success;
1325 case kUSB_DeviceControlEndpointInit:
1328 error = USB_DeviceKhciEndpointInit(khciState, (usb_device_endpoint_init_struct_t *)param);
1331 case kUSB_DeviceControlEndpointDeinit:
1334 temp8 = (uint8_t *)param;
1335 error = USB_DeviceKhciEndpointDeinit(khciState, *temp8);
1338 case kUSB_DeviceControlEndpointStall:
1341 temp8 = (uint8_t *)param;
1342 error = USB_DeviceKhciEndpointStall(khciState, *temp8);
1345 case kUSB_DeviceControlEndpointUnstall:
1348 temp8 = (uint8_t *)param;
1349 error = USB_DeviceKhciEndpointUnstall(khciState, *temp8);
1352 case kUSB_DeviceControlGetDeviceStatus:
1355 temp16 = (uint16_t *)param;
1356 *temp16 = (USB_DEVICE_CONFIG_SELF_POWER << (USB_REQUEST_STANDARD_GET_STATUS_DEVICE_SELF_POWERED_SHIFT))
1357 #if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
1358 | ((uint16_t)(((uint32_t)deviceHandle->remotewakeup)
1359 << (USB_REQUEST_STANDARD_GET_STATUS_DEVICE_REMOTE_WARKUP_SHIFT)))
1362 error = kStatus_USB_Success;
1365 case kUSB_DeviceControlGetEndpointStatus:
1368 usb_device_endpoint_status_struct_t *endpointStatus = (usb_device_endpoint_status_struct_t *)param;
1370 if (((endpointStatus->endpointAddress) & USB_ENDPOINT_NUMBER_MASK) < USB_DEVICE_CONFIG_ENDPOINTS)
1372 endpointStatus->endpointStatus =
1375 ->endpointState[(((endpointStatus->endpointAddress) & USB_ENDPOINT_NUMBER_MASK) << 1U) |
1376 (((endpointStatus->endpointAddress) &
1377 USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
1378 USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)]
1379 .stateUnion.stateBitField.stalled == 1U) ?
1380 kUSB_DeviceEndpointStateStalled :
1381 kUSB_DeviceEndpointStateIdle;
1382 error = kStatus_USB_Success;
1386 case kUSB_DeviceControlSetDeviceAddress:
1389 temp8 = (uint8_t *)param;
1390 khciState->registerBase->ADDR = (*temp8);
1391 error = kStatus_USB_Success;
1394 case kUSB_DeviceControlGetSynchFrame:
1396 #if ((defined(USB_DEVICE_CONFIG_LOW_POWER_MODE)) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
1397 #if defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U)
1398 case kUSB_DeviceControlResume:
1399 khciState->registerBase->CTL |= USB_CTL_RESUME_MASK;
1400 startTick = deviceHandle->hwTick;
1401 while ((deviceHandle->hwTick - startTick) < 10)
1405 khciState->registerBase->CTL &= ~USB_CTL_RESUME_MASK;
1406 error = kStatus_USB_Success;
1408 #endif /* USB_DEVICE_CONFIG_REMOTE_WAKEUP */
1409 case kUSB_DeviceControlSuspend:
1410 error = kStatus_USB_Success;
1412 #endif /* USB_DEVICE_CONFIG_LOW_POWER_MODE */
1413 case kUSB_DeviceControlSetDefaultStatus:
1414 for (uint8_t count = 0U; count < USB_DEVICE_CONFIG_ENDPOINTS; count++)
1416 USB_DeviceKhciEndpointDeinit(khciState, (count | (USB_IN << 0x07U)));
1417 USB_DeviceKhciEndpointDeinit(khciState, (count | (USB_OUT << 0x07U)));
1419 USB_DeviceKhciSetDefaultState(khciState);
1420 error = kStatus_USB_Success;
1422 case kUSB_DeviceControlGetSpeed:
1425 temp8 = (uint8_t *)param;
1426 *temp8 = USB_SPEED_FULL;
1427 error = kStatus_USB_Success;
1430 #if (defined(USB_DEVICE_CONFIG_OTG) && (USB_DEVICE_CONFIG_OTG))
1431 case kUSB_DeviceControlGetOtgStatus:
1432 *((uint8_t *)param) = khciState->otgStatus;
1434 case kUSB_DeviceControlSetOtgStatus:
1435 khciState->otgStatus = *((uint8_t *)param);
1438 case kUSB_DeviceControlSetTestMode:
1440 #if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
1441 (defined(FSL_FEATURE_SOC_USBDCD_COUNT) && (FSL_FEATURE_SOC_USBDCD_COUNT > 0U))
1442 case kUSB_DeviceControlDcdInitModule:
1443 dcdState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_SR_MASK;
1444 dcdState->dcdRegisterBase->TIMER0 = USBDCD_TIMER0_TSEQ_INIT(deviceDcdTimingConfig->dcdSeqInitTime);
1445 dcdState->dcdRegisterBase->TIMER1 = USBDCD_TIMER1_TDCD_DBNC(deviceDcdTimingConfig->dcdDbncTime);
1446 dcdState->dcdRegisterBase->TIMER1 |= USBDCD_TIMER1_TVDPSRC_ON(deviceDcdTimingConfig->dcdDpSrcOnTime);
1447 dcdState->dcdRegisterBase->TIMER2_BC12 =
1448 USBDCD_TIMER2_BC12_TWAIT_AFTER_PRD(deviceDcdTimingConfig->dcdTimeWaitAfterPrD);
1449 dcdState->dcdRegisterBase->TIMER2_BC12 |=
1450 USBDCD_TIMER2_BC12_TVDMSRC_ON(deviceDcdTimingConfig->dcdTimeDMSrcOn);
1451 dcdState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_IE_MASK;
1452 dcdState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_BC12_MASK;
1453 dcdState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_START_MASK;
1455 case kUSB_DeviceControlDcdDeinitModule:
1456 dcdState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_SR_MASK;
1468 * @brief Handle the KHCI device interrupt.
1470 * The function is used to handle the KHCI device interrupt.
1472 * @param deviceHandle The device handle got from USB_DeviceInit.
1475 void USB_DeviceKhciIsrFunction(void *deviceHandle)
1477 usb_device_struct_t *handle = (usb_device_struct_t *)deviceHandle;
1478 usb_device_khci_state_struct_t *khciState;
1481 if (NULL == deviceHandle)
1486 khciState = (usb_device_khci_state_struct_t *)(handle->controllerHandle);
1488 status = khciState->registerBase->ISTAT;
1489 #if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
1490 defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \
1491 defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
1492 /* Clear EEP_ALIVE_CTRL_WAKE_INT interrupt state */
1493 if (khciState->registerBase->KEEP_ALIVE_CTRL & USB_KEEP_ALIVE_CTRL_WAKE_INT_STS_MASK)
1495 khciState->registerBase->KEEP_ALIVE_CTRL |= USB_KEEP_ALIVE_CTRL_WAKE_INT_STS_MASK;
1497 /* Clear SOFTOK interrupt state */
1498 if (khciState->registerBase->ISTAT & USB_ISTAT_SOFTOK_MASK)
1500 khciState->registerBase->ISTAT = USB_ISTAT_SOFTOK_MASK;
1503 #if defined(USB_DEVICE_CONFIG_ERROR_HANDLING) && (USB_DEVICE_CONFIG_ERROR_HANDLING > 0U)
1504 /* Error interrupt */
1505 if (status & kUSB_KhciInterruptError)
1507 USB_DeviceKhciInterruptError(khciState);
1509 #endif /* USB_DEVICE_CONFIG_ERROR_HANDLING */
1510 /* Token done interrupt */
1511 if (status & kUSB_KhciInterruptTokenDone)
1513 USB_DeviceKhciInterruptTokenDone(khciState);
1516 /* Reset interrupt */
1517 if (status & kUSB_KhciInterruptReset)
1519 USB_DeviceKhciInterruptReset(khciState);
1522 #if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
1523 /* Suspend interrupt */
1524 if (status & kUSB_KhciInterruptSleep)
1526 USB_DeviceKhciInterruptSleep(khciState);
1529 /* Resume interrupt */
1530 if (status & kUSB_KhciInterruptResume)
1532 USB_DeviceKhciInterruptResume(khciState);
1535 if (khciState->registerBase->USBTRC0 & USB_USBTRC0_USB_RESUME_INT_MASK)
1537 USB_DeviceKhciInterruptResume(khciState);
1539 #endif /* USB_DEVICE_CONFIG_LOW_POWER_MODE */
1541 /* Endpoint stalled interrupt */
1542 if (status & kUSB_KhciInterruptStall)
1544 USB_DeviceKhciInterruptStall(khciState);
1547 #if (defined(USB_DEVICE_CONFIG_DETACH_ENABLE) && (USB_DEVICE_CONFIG_DETACH_ENABLE > 0U)) && \
1548 (defined(FSL_FEATURE_USB_KHCI_VBUS_DETECT_ENABLED) && (FSL_FEATURE_USB_KHCI_VBUS_DETECT_ENABLED > 0U))
1549 if (khciState->registerBase->USBTRC0 & USB_USBTRC0_VREDG_DET_MASK)
1551 USB_DeviceKhciInterruptVbusRising(khciState);
1554 if (khciState->registerBase->USBTRC0 & USB_USBTRC0_VFEDG_DET_MASK)
1556 USB_DeviceKhciInterruptVbusFalling(khciState);
1558 #endif /* USB_DEVICE_CONFIG_DETACH_ENABLE && FSL_FEATURE_USB_KHCI_VBUS_DETECT_ENABLED */
1561 /* Sof token interrupt */
1562 if (status & kUSB_KhciInterruptSofToken)
1564 USB_DeviceKhciInterruptSof(khciState);
1568 #if ((defined FSL_FEATURE_USB_KHCI_IRC48M_MODULE_CLOCK_ENABLED) && \
1569 (FSL_FEATURE_USB_KHCI_IRC48M_MODULE_CLOCK_ENABLED > 0U))
1570 status = khciState->registerBase->CLK_RECOVER_INT_STATUS;
1573 /* USB RECOVER interrupt is happenned */
1574 if (USB_CLK_RECOVER_INT_STATUS_OVF_ERROR_MASK & status)
1576 /* Indicates that the USB clock recovery algorithm has detected that the frequency trim adjustment needed
1577 * for the IRC48M output clock is outside the available TRIM_FINE adjustment range for the IRC48M
1581 khciState->registerBase->CLK_RECOVER_INT_STATUS = status;
1586 #if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
1587 (defined(FSL_FEATURE_SOC_USBDCD_COUNT) && (FSL_FEATURE_SOC_USBDCD_COUNT > 0U))
1589 * @brief Handle the device DCD module interrupt.
1591 * The function is used to handle the device DCD module interrupt.
1593 * @param deviceHandle The device handle got from USB_DeviceInit.
1596 void USB_DeviceDcdIsrFunction(void *deviceHandle)
1598 usb_device_struct_t *handle = (usb_device_struct_t *)deviceHandle;
1599 usb_device_khci_state_struct_t *khciState;
1600 usb_device_dcd_state_struct_t *dcdState;
1602 uint32_t chargerType;
1603 usb_device_callback_message_struct_t message;
1605 if (NULL == deviceHandle)
1610 khciState = (usb_device_khci_state_struct_t *)(handle->controllerHandle);
1612 dcdState = &s_UsbDeviceDcdState[khciState->controllerId - kUSB_ControllerKhci0];
1614 /* Read the STATUS register in the interrupt routine. */
1615 status = dcdState->dcdRegisterBase->STATUS;
1617 /* Clear the interrupt flag bit. */
1618 dcdState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_IACK_MASK;
1620 message.buffer = (uint8_t *)NULL;
1621 message.length = 0U;
1622 message.isSetup = 0U;
1624 if (status & USBDCD_STATUS_ERR_MASK)
1626 if (status & USBDCD_STATUS_TO_MASK)
1628 dcdState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_SR_MASK;
1629 message.code = kUSB_DeviceNotifyDcdTimeOut;
1630 USB_DeviceNotificationTrigger(dcdState->deviceHandle, &message);
1634 dcdState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_SR_MASK;
1635 message.code = kUSB_DeviceNotifyDcdUnknownPortType;
1636 USB_DeviceNotificationTrigger(dcdState->deviceHandle, &message);
1641 switch (status & USBDCD_STATUS_SEQ_STAT_MASK)
1643 case USBDCD_STATUS_SEQ_STAT(kUSB_DcdChargingPortDetectionCompleted):
1644 chargerType = status & USBDCD_STATUS_SEQ_RES_MASK;
1645 if (chargerType == USBDCD_STATUS_SEQ_RES(kUSB_DcdDetectionStandardHost))
1647 dcdState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_SR_MASK;
1648 message.code = kUSB_DeviceNotifySDPDetected;
1649 USB_DeviceNotificationTrigger(dcdState->deviceHandle, &message);
1651 else if (chargerType == USBDCD_STATUS_SEQ_RES(kUSB_DcdDetectionChargingPort))
1653 message.code = kUSB_DeviceNotifyChargingPortDetected;
1654 USB_DeviceNotificationTrigger(dcdState->deviceHandle, &message);
1657 case USBDCD_STATUS_SEQ_STAT(kUSB_DcdChargerTypeDetectionCompleted):
1658 chargerType = status & USBDCD_STATUS_SEQ_RES_MASK;
1659 if (chargerType == USBDCD_STATUS_SEQ_RES(kUSB_DcdDetectionChargingPort))
1661 dcdState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_SR_MASK;
1662 message.code = kUSB_DeviceNotifyChargingHostDetected;
1663 USB_DeviceNotificationTrigger(dcdState->deviceHandle, &message);
1665 else if (chargerType == USBDCD_STATUS_SEQ_RES(kUSB_DcdDetectionDedicatedCharger))
1667 dcdState->dcdRegisterBase->CONTROL |= USBDCD_CONTROL_SR_MASK;
1668 message.code = kUSB_DeviceNotifyDedicatedChargerDetected;
1669 USB_DeviceNotificationTrigger(dcdState->deviceHandle, &message);
1679 #endif /* USB_DEVICE_CONFIG_KHCI */