usb_dwc_hal.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. /*
  2. * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stddef.h>
  7. #include <stdint.h>
  8. #include <string.h>
  9. #include "sdkconfig.h"
  10. #include "soc/chip_revision.h"
  11. #include "hal/efuse_hal.h"
  12. #include "hal/usb_dwc_hal.h"
  13. #include "hal/usb_dwc_ll.h"
  14. #include "hal/assert.h"
  15. // ------------------------------------------------ Macros and Types ---------------------------------------------------
  16. // ---------------------- Constants ------------------------
  17. #define BENDPOINTADDRESS_NUM_MSK 0x0F //Endpoint number mask of the bEndpointAddress field of an endpoint descriptor
  18. #define BENDPOINTADDRESS_DIR_MSK 0x80 //Endpoint direction mask of the bEndpointAddress field of an endpoint descriptor
  19. #define CORE_REG_GSNPSID 0x4F54400A
  20. #define CORE_REG_GHWCFG1 0x00000000
  21. #define CORE_REG_GHWCFG2 0x224DD930
  22. #define CORE_REG_GHWCFG3 0x00C804B5
  23. #define CORE_REG_GHWCFG4 0xD3F0A030
  24. // -------------------- Configurable -----------------------
  25. /**
  26. * The following core interrupts will be enabled (listed LSB to MSB). Some of these
  27. * interrupts are enabled later than others.
  28. * - USB_DWC_LL_INTR_CORE_PRTINT
  29. * - USB_DWC_LL_INTR_CORE_HCHINT
  30. * - USB_DWC_LL_INTR_CORE_DISCONNINT
  31. * The following PORT interrupts cannot be masked, listed LSB to MSB
  32. * - USB_DWC_LL_INTR_HPRT_PRTCONNDET
  33. * - USB_DWC_LL_INTR_HPRT_PRTENCHNG
  34. * - USB_DWC_LL_INTR_HPRT_PRTOVRCURRCHNG
  35. */
  36. #define CORE_INTRS_EN_MSK (USB_DWC_LL_INTR_CORE_DISCONNINT)
  37. //Interrupts that pertain to core events
  38. #define CORE_EVENTS_INTRS_MSK (USB_DWC_LL_INTR_CORE_DISCONNINT | \
  39. USB_DWC_LL_INTR_CORE_HCHINT)
  40. //Interrupt that pertain to host port events
  41. #define PORT_EVENTS_INTRS_MSK (USB_DWC_LL_INTR_HPRT_PRTCONNDET | \
  42. USB_DWC_LL_INTR_HPRT_PRTENCHNG | \
  43. USB_DWC_LL_INTR_HPRT_PRTOVRCURRCHNG)
  44. /**
  45. * The following channel interrupt bits are currently checked (in order LSB to MSB)
  46. * - USB_DWC_LL_INTR_CHAN_XFERCOMPL
  47. * - USB_DWC_LL_INTR_CHAN_CHHLTD
  48. * - USB_DWC_LL_INTR_CHAN_STALL
  49. * - USB_DWC_LL_INTR_CHAN_BBLEER
  50. * - USB_DWC_LL_INTR_CHAN_BNAINTR
  51. * - USB_DWC_LL_INTR_CHAN_XCS_XACT_ERR
  52. *
  53. * Note the following points about channel interrupts:
  54. * - Not all bits are unmaskable under scatter/gather
  55. * - Those bits proxy their interrupt through the USB_DWC_LL_INTR_CHAN_CHHLTD bit
  56. * - USB_DWC_LL_INTR_CHAN_XCS_XACT_ERR is always unmasked
  57. * - When USB_DWC_LL_INTR_CHAN_BNAINTR occurs, USB_DWC_LL_INTR_CHAN_CHHLTD will NOT.
  58. * - USB_DWC_LL_INTR_CHAN_AHBERR doesn't actually ever happen on our system (i.e., ESP32-S2, ESP32-S3):
  59. * - If the QTD list's starting address is an invalid address (e.g., NULL), the core will attempt to fetch that
  60. * address for a transfer descriptor and probably gets all zeroes. It will interpret the zero as a bad QTD and
  61. * return a USB_DWC_LL_INTR_CHAN_BNAINTR instead.
  62. * - If the QTD's buffer pointer is an invalid address, the core will attempt to read/write data to/from that
  63. * invalid buffer address with NO INDICATION OF ERROR. The transfer will be acknowledged and treated as
  64. * successful. Bad buffer pointers MUST BE CHECKED FROM HIGHER LAYERS INSTEAD.
  65. */
  66. #define CHAN_INTRS_EN_MSK (USB_DWC_LL_INTR_CHAN_XFERCOMPL | \
  67. USB_DWC_LL_INTR_CHAN_CHHLTD | \
  68. USB_DWC_LL_INTR_CHAN_BNAINTR)
  69. #define CHAN_INTRS_ERROR_MSK (USB_DWC_LL_INTR_CHAN_STALL | \
  70. USB_DWC_LL_INTR_CHAN_BBLEER | \
  71. USB_DWC_LL_INTR_CHAN_BNAINTR | \
  72. USB_DWC_LL_INTR_CHAN_XCS_XACT_ERR)
  73. // -------------------------------------------------- Core (Global) ----------------------------------------------------
  74. static void set_defaults(usb_dwc_hal_context_t *hal)
  75. {
  76. //GAHBCFG register
  77. usb_dwc_ll_gahbcfg_en_dma_mode(hal->dev);
  78. int hbstlen = 0; //Use AHB burst SINGLE by default
  79. #if CONFIG_IDF_TARGET_ESP32S2 && CONFIG_ESP32S2_REV_MIN_FULL < 100
  80. /*
  81. Hardware errata workaround for the ESP32-S2 ECO0 (see ESP32-S2 Errata Document section 4.0 for full details).
  82. ESP32-S2 ECO0 has a hardware errata where the AHB bus arbiter may generate incorrect arbitration signals leading to
  83. the DWC_OTG corrupting the DMA transfers of other peripherals (or vice versa) on the same bus. The peripherals that
  84. share the same bus with DWC_OTG include I2C and SPI (see ESP32-S2 Errata Document for more details). To workaround
  85. this, the DWC_OTG's AHB should use INCR mode to prevent change of arbitration during a burst operation, thus
  86. avoiding this errata.
  87. Note: Setting AHB burst to INCR increases the likeliness of DMA underruns on other peripherals sharing the same bus
  88. arbiter as the DWC_OTG (e.g., I2C and SPI) as change of arbitration during the burst operation is not permitted.
  89. Users should keep this limitation in mind when the DWC_OTG transfers large data payloads (e.g., 512 MPS transfers)
  90. while this workaround is enabled.
  91. */
  92. if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 100)) {
  93. hbstlen = 1; //Set AHB burst to INCR to workaround hardware errata
  94. }
  95. #endif //CONFIG_IDF_TARGET_ESP32S2 && CONFIG_ESP32S2_REV_MIN_FULL < 100
  96. usb_dwc_ll_gahbcfg_set_hbstlen(hal->dev, hbstlen); //Set AHB burst mode
  97. //GUSBCFG register
  98. usb_dwc_ll_gusbcfg_dis_hnp_cap(hal->dev); //Disable HNP
  99. usb_dwc_ll_gusbcfg_dis_srp_cap(hal->dev); //Disable SRP
  100. //Enable interruts
  101. usb_dwc_ll_gintmsk_dis_intrs(hal->dev, 0xFFFFFFFF); //Mask all interrupts first
  102. usb_dwc_ll_gintmsk_en_intrs(hal->dev, CORE_INTRS_EN_MSK); //Unmask global interrupts
  103. usb_dwc_ll_gintsts_read_and_clear_intrs(hal->dev); //Clear interrupts
  104. usb_dwc_ll_gahbcfg_en_global_intr(hal->dev); //Enable interrupt signal
  105. //Enable host mode
  106. usb_dwc_ll_gusbcfg_force_host_mode(hal->dev);
  107. }
  108. void usb_dwc_hal_init(usb_dwc_hal_context_t *hal)
  109. {
  110. //Check if a peripheral is alive by reading the core ID registers
  111. usb_dwc_dev_t *dev = &USB_DWC;
  112. uint32_t core_id = usb_dwc_ll_gsnpsid_get_id(dev);
  113. HAL_ASSERT(core_id == CORE_REG_GSNPSID);
  114. (void) core_id; //Suppress unused variable warning if asserts are disabled
  115. //Initialize HAL context
  116. memset(hal, 0, sizeof(usb_dwc_hal_context_t));
  117. hal->dev = dev;
  118. set_defaults(hal);
  119. }
  120. void usb_dwc_hal_deinit(usb_dwc_hal_context_t *hal)
  121. {
  122. //Disable and clear global interrupt
  123. usb_dwc_ll_gintmsk_dis_intrs(hal->dev, 0xFFFFFFFF); //Disable all interrupts
  124. usb_dwc_ll_gintsts_read_and_clear_intrs(hal->dev); //Clear interrupts
  125. usb_dwc_ll_gahbcfg_dis_global_intr(hal->dev); //Disable interrupt signal
  126. hal->dev = NULL;
  127. }
  128. void usb_dwc_hal_core_soft_reset(usb_dwc_hal_context_t *hal)
  129. {
  130. usb_dwc_ll_grstctl_core_soft_reset(hal->dev);
  131. while (usb_dwc_ll_grstctl_is_core_soft_reset_in_progress(hal->dev)) {
  132. ; //Wait until core reset is done
  133. }
  134. while (!usb_dwc_ll_grstctl_is_ahb_idle(hal->dev)) {
  135. ; //Wait until AHB Master bus is idle before doing any other operations
  136. }
  137. //Set the default bits
  138. set_defaults(hal);
  139. //Clear all the flags and channels
  140. hal->periodic_frame_list = NULL;
  141. hal->flags.val = 0;
  142. hal->channels.num_allocd = 0;
  143. hal->channels.chan_pend_intrs_msk = 0;
  144. memset(hal->channels.hdls, 0, sizeof(usb_dwc_hal_chan_t *) * USB_DWC_NUM_HOST_CHAN);
  145. }
  146. void usb_dwc_hal_set_fifo_size(usb_dwc_hal_context_t *hal, const usb_dwc_hal_fifo_config_t *fifo_config)
  147. {
  148. HAL_ASSERT((fifo_config->rx_fifo_lines + fifo_config->nptx_fifo_lines + fifo_config->ptx_fifo_lines) <= USB_DWC_FIFO_TOTAL_USABLE_LINES);
  149. //Check that none of the channels are active
  150. for (int i = 0; i < USB_DWC_NUM_HOST_CHAN; i++) {
  151. if (hal->channels.hdls[i] != NULL) {
  152. HAL_ASSERT(!hal->channels.hdls[i]->flags.active);
  153. }
  154. }
  155. //Set the new FIFO lengths
  156. usb_dwc_ll_grxfsiz_set_fifo_size(hal->dev, fifo_config->rx_fifo_lines);
  157. usb_dwc_ll_gnptxfsiz_set_fifo_size(hal->dev, fifo_config->rx_fifo_lines, fifo_config->nptx_fifo_lines);
  158. usb_dwc_ll_hptxfsiz_set_ptx_fifo_size(hal->dev, fifo_config->rx_fifo_lines + fifo_config->nptx_fifo_lines, fifo_config->ptx_fifo_lines);
  159. //Flush the FIFOs
  160. usb_dwc_ll_grstctl_flush_nptx_fifo(hal->dev);
  161. usb_dwc_ll_grstctl_flush_ptx_fifo(hal->dev);
  162. usb_dwc_ll_grstctl_flush_rx_fifo(hal->dev);
  163. hal->flags.fifo_sizes_set = 1;
  164. }
  165. // ---------------------------------------------------- Host Port ------------------------------------------------------
  166. static inline void debounce_lock_enable(usb_dwc_hal_context_t *hal)
  167. {
  168. //Disable the hprt (connection) and disconnection interrupts to prevent repeated triggerings
  169. usb_dwc_ll_gintmsk_dis_intrs(hal->dev, USB_DWC_LL_INTR_CORE_PRTINT | USB_DWC_LL_INTR_CORE_DISCONNINT);
  170. hal->flags.dbnc_lock_enabled = 1;
  171. }
  172. void usb_dwc_hal_port_enable(usb_dwc_hal_context_t *hal)
  173. {
  174. usb_priv_speed_t speed = usb_dwc_ll_hprt_get_speed(hal->dev);
  175. //Host Configuration
  176. usb_dwc_ll_hcfg_set_defaults(hal->dev, speed);
  177. //Configure HFIR
  178. usb_dwc_ll_hfir_set_defaults(hal->dev, speed);
  179. }
  180. // ----------------------------------------------------- Channel -------------------------------------------------------
  181. // ----------------- Channel Allocation --------------------
  182. bool usb_dwc_hal_chan_alloc(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t *chan_obj, void *chan_ctx)
  183. {
  184. HAL_ASSERT(hal->flags.fifo_sizes_set); //FIFO sizes should be set befor attempting to allocate a channel
  185. //Attempt to allocate channel
  186. if (hal->channels.num_allocd == USB_DWC_NUM_HOST_CHAN) {
  187. return false; //Out of free channels
  188. }
  189. int chan_idx = -1;
  190. for (int i = 0; i < USB_DWC_NUM_HOST_CHAN; i++) {
  191. if (hal->channels.hdls[i] == NULL) {
  192. hal->channels.hdls[i] = chan_obj;
  193. chan_idx = i;
  194. hal->channels.num_allocd++;
  195. break;
  196. }
  197. }
  198. HAL_ASSERT(chan_idx != -1);
  199. //Initialize channel object
  200. memset(chan_obj, 0, sizeof(usb_dwc_hal_chan_t));
  201. chan_obj->flags.chan_idx = chan_idx;
  202. chan_obj->regs = usb_dwc_ll_chan_get_regs(hal->dev, chan_idx);
  203. chan_obj->chan_ctx = chan_ctx;
  204. //Note: EP characteristics configured separately
  205. //Clean and unmask the channel's interrupt
  206. usb_dwc_ll_hcint_read_and_clear_intrs(chan_obj->regs); //Clear the interrupt bits for that channel
  207. usb_dwc_ll_haintmsk_en_chan_intr(hal->dev, 1 << chan_obj->flags.chan_idx);
  208. usb_dwc_ll_hcintmsk_set_intr_mask(chan_obj->regs, CHAN_INTRS_EN_MSK); //Unmask interrupts for this channel
  209. usb_dwc_ll_hctsiz_set_pid(chan_obj->regs, 0); //Set the initial PID to zero
  210. usb_dwc_ll_hctsiz_init(chan_obj->regs); //Set the non changing parts of the HCTSIZ registers (e.g., do_ping and sched info)
  211. return true;
  212. }
  213. void usb_dwc_hal_chan_free(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t *chan_obj)
  214. {
  215. if (chan_obj->type == USB_PRIV_XFER_TYPE_INTR || chan_obj->type == USB_PRIV_XFER_TYPE_ISOCHRONOUS) {
  216. //Unschedule this channel
  217. for (int i = 0; i < hal->frame_list_len; i++) {
  218. hal->periodic_frame_list[i] &= ~(1 << chan_obj->flags.chan_idx);
  219. }
  220. }
  221. //Can only free a channel when in the disabled state and descriptor list released
  222. HAL_ASSERT(!chan_obj->flags.active);
  223. //Disable channel's interrupt
  224. usb_dwc_ll_haintmsk_dis_chan_intr(hal->dev, 1 << chan_obj->flags.chan_idx);
  225. //Deallocate channel
  226. hal->channels.hdls[chan_obj->flags.chan_idx] = NULL;
  227. hal->channels.num_allocd--;
  228. HAL_ASSERT(hal->channels.num_allocd >= 0);
  229. }
  230. // ---------------- Channel Configuration ------------------
  231. void usb_dwc_hal_chan_set_ep_char(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t *chan_obj, usb_dwc_hal_ep_char_t *ep_char)
  232. {
  233. //Cannot change ep_char whilst channel is still active or in error
  234. HAL_ASSERT(!chan_obj->flags.active);
  235. //Set the endpoint characteristics of the pipe
  236. usb_dwc_ll_hcchar_init(chan_obj->regs,
  237. ep_char->dev_addr,
  238. ep_char->bEndpointAddress & BENDPOINTADDRESS_NUM_MSK,
  239. ep_char->mps,
  240. ep_char->type,
  241. ep_char->bEndpointAddress & BENDPOINTADDRESS_DIR_MSK,
  242. ep_char->ls_via_fs_hub);
  243. //Save channel type
  244. chan_obj->type = ep_char->type;
  245. //If this is a periodic endpoint/channel, set its schedule in the frame list
  246. if (ep_char->type == USB_PRIV_XFER_TYPE_ISOCHRONOUS || ep_char->type == USB_PRIV_XFER_TYPE_INTR) {
  247. HAL_ASSERT((int)ep_char->periodic.interval <= (int)hal->frame_list_len); //Interval cannot exceed the length of the frame list
  248. //Find the effective offset in the frame list (in case the phase_offset_frames > interval)
  249. int offset = ep_char->periodic.phase_offset_frames % ep_char->periodic.interval;
  250. //Schedule the channel in the frame list
  251. for (int i = offset; i < hal->frame_list_len; i+= ep_char->periodic.interval) {
  252. hal->periodic_frame_list[i] |= 1 << chan_obj->flags.chan_idx;
  253. }
  254. }
  255. }
  256. // ------------------- Channel Control ---------------------
  257. void usb_dwc_hal_chan_activate(usb_dwc_hal_chan_t *chan_obj, void *xfer_desc_list, int desc_list_len, int start_idx)
  258. {
  259. //Cannot activate a channel that has already been enabled or is pending error handling
  260. HAL_ASSERT(!chan_obj->flags.active);
  261. //Set start address of the QTD list and starting QTD index
  262. usb_dwc_ll_hcdma_set_qtd_list_addr(chan_obj->regs, xfer_desc_list, start_idx);
  263. usb_dwc_ll_hctsiz_set_qtd_list_len(chan_obj->regs, desc_list_len);
  264. usb_dwc_ll_hcchar_enable_chan(chan_obj->regs); //Start the channel
  265. chan_obj->flags.active = 1;
  266. }
  267. bool usb_dwc_hal_chan_request_halt(usb_dwc_hal_chan_t *chan_obj)
  268. {
  269. if (chan_obj->flags.active) {
  270. /*
  271. Request a halt so long as the channel's active flag is set.
  272. - If the underlying hardware channel is already halted but the channel is pending interrupt handling,
  273. disabling the channel will have no effect (i.e., no channel interrupt is generated).
  274. - If the underlying channel is currently active, disabling the channel will trigger a channel interrupt.
  275. Regardless, setting the "halt_requested" should cause "usb_dwc_hal_chan_decode_intr()" to report the
  276. USB_DWC_HAL_CHAN_EVENT_HALT_REQ event when channel interrupt is handled (pending or triggered).
  277. */
  278. usb_dwc_ll_hcchar_disable_chan(chan_obj->regs);
  279. chan_obj->flags.halt_requested = 1;
  280. return false;
  281. } else {
  282. //Channel was never active to begin with, simply return true
  283. return true;
  284. }
  285. }
  286. // ------------------------------------------------- Event Handling ----------------------------------------------------
  287. usb_dwc_hal_port_event_t usb_dwc_hal_decode_intr(usb_dwc_hal_context_t *hal)
  288. {
  289. uint32_t intrs_core = usb_dwc_ll_gintsts_read_and_clear_intrs(hal->dev); //Read and clear core interrupts
  290. uint32_t intrs_port = 0;
  291. if (intrs_core & USB_DWC_LL_INTR_CORE_PRTINT) {
  292. //There are host port interrupts. Read and clear those as well.
  293. intrs_port = usb_dwc_ll_hprt_intr_read_and_clear(hal->dev);
  294. }
  295. //Note: Do not change order of checks. Regressing events (e.g. enable -> disabled, connected -> connected)
  296. //always take precedence. ENABLED < DISABLED < CONN < DISCONN < OVRCUR
  297. usb_dwc_hal_port_event_t event = USB_DWC_HAL_PORT_EVENT_NONE;
  298. //Check if this is a core or port event
  299. if ((intrs_core & CORE_EVENTS_INTRS_MSK) || (intrs_port & PORT_EVENTS_INTRS_MSK)) {
  300. //Do not change the order of the following checks. Some events/interrupts take precedence over others
  301. if (intrs_core & USB_DWC_LL_INTR_CORE_DISCONNINT) {
  302. event = USB_DWC_HAL_PORT_EVENT_DISCONN;
  303. debounce_lock_enable(hal);
  304. //Mask the port connection and disconnection interrupts to prevent repeated triggering
  305. } else if (intrs_port & USB_DWC_LL_INTR_HPRT_PRTOVRCURRCHNG) {
  306. //Check if this is an overcurrent or an overcurrent cleared
  307. if (usb_dwc_ll_hprt_get_port_overcur(hal->dev)) {
  308. event = USB_DWC_HAL_PORT_EVENT_OVRCUR;
  309. } else {
  310. event = USB_DWC_HAL_PORT_EVENT_OVRCUR_CLR;
  311. }
  312. } else if (intrs_port & USB_DWC_LL_INTR_HPRT_PRTENCHNG) {
  313. if (usb_dwc_ll_hprt_get_port_en(hal->dev)) { //Host port was enabled
  314. event = USB_DWC_HAL_PORT_EVENT_ENABLED;
  315. } else { //Host port has been disabled
  316. event = USB_DWC_HAL_PORT_EVENT_DISABLED;
  317. }
  318. } else if (intrs_port & USB_DWC_LL_INTR_HPRT_PRTCONNDET && !hal->flags.dbnc_lock_enabled) {
  319. event = USB_DWC_HAL_PORT_EVENT_CONN;
  320. debounce_lock_enable(hal);
  321. }
  322. }
  323. //Port events always take precedence over channel events
  324. if (event == USB_DWC_HAL_PORT_EVENT_NONE && (intrs_core & USB_DWC_LL_INTR_CORE_HCHINT)) {
  325. //One or more channels have pending interrupts. Store the mask of those channels
  326. hal->channels.chan_pend_intrs_msk = usb_dwc_ll_haint_get_chan_intrs(hal->dev);
  327. event = USB_DWC_HAL_PORT_EVENT_CHAN;
  328. }
  329. return event;
  330. }
  331. usb_dwc_hal_chan_t *usb_dwc_hal_get_chan_pending_intr(usb_dwc_hal_context_t *hal)
  332. {
  333. int chan_num = __builtin_ffs(hal->channels.chan_pend_intrs_msk);
  334. if (chan_num) {
  335. hal->channels.chan_pend_intrs_msk &= ~(1 << (chan_num - 1)); //Clear the pending bit for that channel
  336. return hal->channels.hdls[chan_num - 1];
  337. } else {
  338. return NULL;
  339. }
  340. }
  341. usb_dwc_hal_chan_event_t usb_dwc_hal_chan_decode_intr(usb_dwc_hal_chan_t *chan_obj)
  342. {
  343. uint32_t chan_intrs = usb_dwc_ll_hcint_read_and_clear_intrs(chan_obj->regs);
  344. usb_dwc_hal_chan_event_t chan_event;
  345. //Note: We don't assert on (chan_obj->flags.active) here as it could have been already cleared by usb_dwc_hal_chan_request_halt()
  346. /*
  347. Note: Do not change order of checks as some events take precedence over others.
  348. Errors > Channel Halt Request > Transfer completed
  349. */
  350. if (chan_intrs & CHAN_INTRS_ERROR_MSK) { //Note: Errors are uncommon, so we check against the entire interrupt mask to reduce frequency of entering this call path
  351. HAL_ASSERT(chan_intrs & USB_DWC_LL_INTR_CHAN_CHHLTD); //An error should have halted the channel
  352. //Store the error in hal context
  353. usb_dwc_hal_chan_error_t error;
  354. if (chan_intrs & USB_DWC_LL_INTR_CHAN_STALL) {
  355. error = USB_DWC_HAL_CHAN_ERROR_STALL;
  356. } else if (chan_intrs & USB_DWC_LL_INTR_CHAN_BBLEER) {
  357. error = USB_DWC_HAL_CHAN_ERROR_PKT_BBL;
  358. } else if (chan_intrs & USB_DWC_LL_INTR_CHAN_BNAINTR) {
  359. error = USB_DWC_HAL_CHAN_ERROR_BNA;
  360. } else { //USB_DWC_LL_INTR_CHAN_XCS_XACT_ERR
  361. error = USB_DWC_HAL_CHAN_ERROR_XCS_XACT;
  362. }
  363. //Update flags
  364. chan_obj->error = error;
  365. chan_obj->flags.active = 0;
  366. //Save the error to be handled later
  367. chan_event = USB_DWC_HAL_CHAN_EVENT_ERROR;
  368. } else if (chan_intrs & USB_DWC_LL_INTR_CHAN_CHHLTD) {
  369. if (chan_obj->flags.halt_requested) {
  370. chan_obj->flags.halt_requested = 0;
  371. chan_event = USB_DWC_HAL_CHAN_EVENT_HALT_REQ;
  372. } else {
  373. //Must have been halted due to QTD HOC
  374. chan_event = USB_DWC_HAL_CHAN_EVENT_CPLT;
  375. }
  376. chan_obj->flags.active = 0;
  377. } else if (chan_intrs & USB_DWC_LL_INTR_CHAN_XFERCOMPL) {
  378. /*
  379. A transfer complete interrupt WITHOUT the channel halting only occurs when receiving a short interrupt IN packet
  380. and the underlying QTD does not have the HOC bit set. This signifies the last packet of the Interrupt transfer
  381. as all interrupt packets must MPS sized except the last.
  382. */
  383. //The channel isn't halted yet, so we need to halt it manually to stop the execution of the next QTD/packet
  384. usb_dwc_ll_hcchar_disable_chan(chan_obj->regs);
  385. /*
  386. After setting the halt bit, this will generate another channel halted interrupt. We treat this interrupt as
  387. a NONE event, then cycle back with the channel halted interrupt to handle the CPLT event.
  388. */
  389. chan_event = USB_DWC_HAL_CHAN_EVENT_NONE;
  390. } else {
  391. abort(); //Should never reach this point
  392. }
  393. return chan_event;
  394. }