drv_usbh_int.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. /*!
  2. \file drv_usbh_int.c
  3. \brief USB host mode interrupt handler file
  4. \version 2023-06-30, V2.1.6, firmware for GD32F30x
  5. */
  6. /*
  7. Copyright (c) 2023, GigaDevice Semiconductor Inc.
  8. Redistribution and use in source and binary forms, with or without modification,
  9. are permitted provided that the following conditions are met:
  10. 1. Redistributions of source code must retain the above copyright notice, this
  11. list of conditions and the following disclaimer.
  12. 2. Redistributions in binary form must reproduce the above copyright notice,
  13. this list of conditions and the following disclaimer in the documentation
  14. and/or other materials provided with the distribution.
  15. 3. Neither the name of the copyright holder nor the names of its contributors
  16. may be used to endorse or promote products derived from this software without
  17. specific prior written permission.
  18. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  19. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  21. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  22. INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  23. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  24. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  25. WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  26. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  27. OF SUCH DAMAGE.
  28. */
  29. #include "drv_usbh_int.h"
  30. #if defined (__CC_ARM) /*!< ARM compiler */
  31. #pragma O0
  32. #elif defined (__GNUC__) /*!< GNU compiler */
  33. #pragma GCC optimize ("O0")
  34. #elif defined (__TASKING__) /*!< TASKING compiler */
  35. #pragma optimize=0
  36. #endif /* __CC_ARM */
  37. /* local function prototypes ('static') */
  38. static uint32_t usbh_int_port (usb_core_driver *pudev);
  39. static uint32_t usbh_int_pipe (usb_core_driver *pudev);
  40. static uint32_t usbh_int_pipe_in (usb_core_driver *pudev, uint32_t pp_num);
  41. static uint32_t usbh_int_pipe_out (usb_core_driver *pudev, uint32_t pp_num);
  42. static uint32_t usbh_int_rxfifonoempty (usb_core_driver *pudev);
  43. static uint32_t usbh_int_txfifoempty (usb_core_driver *pudev, usb_pipe_mode pp_mode);
  44. /*!
  45. \brief handle global host interrupt
  46. \param[in] pudev: pointer to USB core instance
  47. \param[out] none
  48. \retval operation status
  49. */
  50. uint32_t usbh_isr (usb_core_driver *pudev)
  51. {
  52. uint32_t retval = 0U;
  53. __IO uint32_t intr = 0U;
  54. /* check if host mode */
  55. if (HOST_MODE == (pudev->regs.gr->GINTF & GINTF_COPM)) {
  56. intr = usb_coreintr_get(&pudev->regs);
  57. if (!intr) {
  58. return 0U;
  59. }
  60. if (intr & GINTF_SOF) {
  61. usbh_int_fop->SOF(pudev->host.data);
  62. /* clear interrupt */
  63. pudev->regs.gr->GINTF = GINTF_SOF;
  64. }
  65. if (intr & GINTF_RXFNEIF) {
  66. retval |= usbh_int_rxfifonoempty (pudev);
  67. }
  68. if (intr & GINTF_NPTXFEIF) {
  69. retval |= usbh_int_txfifoempty (pudev, PIPE_NON_PERIOD);
  70. }
  71. if (intr & GINTF_PTXFEIF) {
  72. retval |= usbh_int_txfifoempty (pudev, PIPE_PERIOD);
  73. }
  74. if (intr & GINTF_HCIF) {
  75. retval |= usbh_int_pipe (pudev);
  76. }
  77. if (intr & GINTF_HPIF) {
  78. retval |= usbh_int_port (pudev);
  79. }
  80. if (intr & GINTF_DISCIF) {
  81. usbh_int_fop->disconnect(pudev->host.data);
  82. /* clear interrupt */
  83. pudev->regs.gr->GINTF = GINTF_DISCIF;
  84. }
  85. if (intr & GINTF_ISOONCIF) {
  86. pudev->regs.pr[0]->HCHCTL |= HCHCTL_CEN | HCHCTL_CDIS;
  87. /* clear interrupt */
  88. pudev->regs.gr->GINTF = GINTF_ISOONCIF;
  89. }
  90. if (intr & GINTF_SESIF) {
  91. usb_portvbus_switch (pudev, 1U);
  92. pudev->regs.gr->GINTF = GINTF_SESIF;
  93. }
  94. if (intr & GINTF_WKUPIF) {
  95. /* clear interrupt */
  96. pudev->regs.gr->GINTF = GINTF_WKUPIF;
  97. }
  98. }
  99. return retval;
  100. }
  101. /*!
  102. \brief handle USB pipe halt
  103. \param[in] pudev: pointer to USB core instance
  104. \param[in] pp_num: pp_num: host channel number which is in (0..7)
  105. \param[in] pp_int: pipe interrupt
  106. \param[in] pp_status: pipe status
  107. \param[out] none
  108. \retval none
  109. */
  110. static inline void usb_pp_halt (usb_core_driver *pudev,
  111. uint8_t pp_num,
  112. uint32_t pp_int,
  113. usb_pipe_staus pp_status)
  114. {
  115. pudev->regs.pr[pp_num]->HCHINTEN |= HCHINTEN_CHIE;
  116. usb_pipe_halt(pudev, pp_num);
  117. pudev->regs.pr[pp_num]->HCHINTF = pp_int;
  118. pudev->host.pipe[pp_num].pp_status = pp_status;
  119. }
  120. /*!
  121. \brief handle the host port interrupt
  122. \param[in] pudev: pointer to USB device instance
  123. \param[out] none
  124. \retval operation status
  125. */
  126. #if defined (__ICCARM__) /*!< IAR compiler */
  127. #pragma optimize = none
  128. #endif /* __ICCARM */
  129. static uint32_t usbh_int_port (usb_core_driver *pudev)
  130. {
  131. uint32_t retval = 0U;
  132. /* note: when the USB PHY use USB HS PHY, the flag is needed */
  133. uint8_t port_reset = 0U;
  134. __IO uint32_t port_state = *pudev->regs.HPCS;
  135. /* clear the interrupt bits in GINTSTS */
  136. port_state &= ~(HPCS_PE | HPCS_PCD | HPCS_PEDC);
  137. /* port connect detected */
  138. if (*pudev->regs.HPCS & HPCS_PCD) {
  139. port_state |= HPCS_PCD;
  140. usbh_int_fop->connect(pudev->host.data);
  141. retval |= 1U;
  142. }
  143. /* port enable changed */
  144. if (*pudev->regs.HPCS & HPCS_PEDC) {
  145. port_state |= HPCS_PEDC;
  146. if (*pudev->regs.HPCS & HPCS_PE) {
  147. uint32_t port_speed = usb_curspeed_get(pudev);
  148. uint32_t clock_type = pudev->regs.hr->HCTL & HCTL_CLKSEL;
  149. pudev->host.connect_status = 1U;
  150. if (PORT_SPEED_LOW == port_speed) {
  151. pudev->regs.hr->HFT = 6000U;
  152. if (HCTL_6MHZ != clock_type) {
  153. if (USB_EMBEDDED_PHY == pudev->bp.phy_itf) {
  154. usb_phyclock_config (pudev, HCTL_6MHZ);
  155. }
  156. port_reset = 1U;
  157. }
  158. } else if (PORT_SPEED_FULL == port_speed) {
  159. pudev->regs.hr->HFT = 48000U;
  160. if (HCTL_48MHZ != clock_type) {
  161. if (USB_EMBEDDED_PHY == pudev->bp.phy_itf) {
  162. usb_phyclock_config (pudev, HCTL_48MHZ);
  163. }
  164. port_reset = 1U;
  165. }
  166. } else {
  167. /* for high speed device and others */
  168. port_reset = 1U;
  169. }
  170. pudev->host.port_enabled = 1;
  171. pudev->regs.gr->GINTEN |= GINTEN_DISCIE | GINTEN_SOFIE;
  172. } else {
  173. pudev->host.port_enabled = 0;
  174. }
  175. }
  176. if (port_reset) {
  177. usb_port_reset(pudev);
  178. }
  179. /* clear port interrupts */
  180. *pudev->regs.HPCS = port_state;
  181. return retval;
  182. }
  183. /*!
  184. \brief handle all host channels interrupt
  185. \param[in] pudev: pointer to USB device instance
  186. \param[out] none
  187. \retval operation status
  188. */
  189. static uint32_t usbh_int_pipe (usb_core_driver *pudev)
  190. {
  191. uint32_t pp_num = 0U;
  192. uint32_t retval = 0U;
  193. for (pp_num = 0U; pp_num < pudev->bp.num_pipe; pp_num++) {
  194. if ((pudev->regs.hr->HACHINT & HACHINT_HACHINT) & (1UL << pp_num)) {
  195. if (pudev->regs.pr[pp_num]->HCHCTL & HCHCTL_EPDIR) {
  196. retval |= usbh_int_pipe_in (pudev, pp_num);
  197. } else {
  198. retval |= usbh_int_pipe_out (pudev, pp_num);
  199. }
  200. }
  201. }
  202. return retval;
  203. }
  204. /*!
  205. \brief handle the IN channel interrupt
  206. \param[in] pudev: pointer to USB device instance
  207. \param[in] pp_num: host channel number which is in (0..7)
  208. \param[out] none
  209. \retval operation status
  210. */
  211. #if defined (__ICCARM__) /*!< IAR compiler */
  212. #pragma optimize = none
  213. #endif /* __ICCARM */
  214. static uint32_t usbh_int_pipe_in (usb_core_driver *pudev, uint32_t pp_num)
  215. {
  216. usb_pr *pp_reg = pudev->regs.pr[pp_num];
  217. usb_pipe *pp = &pudev->host.pipe[pp_num];
  218. uint32_t intr_pp = pp_reg->HCHINTF;
  219. intr_pp &= pp_reg->HCHINTEN;
  220. uint8_t ep_type = (uint8_t)((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U);
  221. if (intr_pp & HCHINTF_ACK) {
  222. pp_reg->HCHINTF = HCHINTF_ACK;
  223. } else if (intr_pp & HCHINTF_STALL) {
  224. usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL);
  225. pp_reg->HCHINTF = HCHINTF_NAK;
  226. /* note: When there is a 'STALL', reset also NAK,
  227. else, the pudev->host.pp_status = HC_STALL
  228. will be overwritten by 'NAK' in code below */
  229. intr_pp &= ~HCHINTF_NAK;
  230. } else if (intr_pp & HCHINTF_DTER) {
  231. usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR);
  232. pp_reg->HCHINTF = HCHINTF_NAK;
  233. } else {
  234. /* no operation */
  235. }
  236. if (intr_pp & HCHINTF_REQOVR) {
  237. usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR);
  238. } else if (intr_pp & HCHINTF_TF) {
  239. pp->pp_status = PIPE_XF;
  240. pp->err_count = 0U;
  241. pp_reg->HCHINTF = HCHINTF_TF;
  242. switch (ep_type) {
  243. case USB_EPTYPE_CTRL:
  244. case USB_EPTYPE_BULK:
  245. usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_XF);
  246. pp->data_toggle_in ^= 1U;
  247. break;
  248. case USB_EPTYPE_INTR:
  249. case USB_EPTYPE_ISOC:
  250. pp_reg->HCHCTL |= HCHCTL_ODDFRM;
  251. pp->urb_state = URB_DONE;
  252. break;
  253. default:
  254. break;
  255. }
  256. } else if (intr_pp & HCHINTF_CH) {
  257. pp_reg->HCHINTEN &= ~HCHINTEN_CHIE;
  258. switch (pp->pp_status) {
  259. case PIPE_XF:
  260. pp->urb_state = URB_DONE;
  261. break;
  262. case PIPE_STALL:
  263. pp->urb_state = URB_STALL;
  264. break;
  265. case PIPE_TRACERR:
  266. case PIPE_DTGERR:
  267. pp->err_count = 0U;
  268. pp->urb_state = URB_ERROR;
  269. pp->data_toggle_in ^= 1U;
  270. break;
  271. case PIPE_IDLE:
  272. case PIPE_HALTED:
  273. case PIPE_NAK:
  274. case PIPE_NYET:
  275. case PIPE_BBERR:
  276. case PIPE_REQOVR:
  277. default:
  278. if((uint8_t)USB_EPTYPE_INTR == ep_type) {
  279. pp->data_toggle_in ^= 1U;
  280. }
  281. break;
  282. }
  283. pp_reg->HCHINTF = HCHINTF_CH;
  284. } else if (intr_pp & HCHINTF_USBER) {
  285. pp->err_count++;
  286. usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR);
  287. } else if (intr_pp & HCHINTF_NAK) {
  288. switch (ep_type) {
  289. case USB_EPTYPE_CTRL:
  290. case USB_EPTYPE_BULK:
  291. /* re-activate the channel */
  292. pp_reg->HCHCTL = (pp_reg->HCHCTL | HCHCTL_CEN) & ~HCHCTL_CDIS;
  293. break;
  294. case USB_EPTYPE_INTR:
  295. pp_reg->HCHINTEN |= HCHINTEN_CHIE;
  296. (void)usb_pipe_halt(pudev, (uint8_t)pp_num);
  297. break;
  298. default:
  299. break;
  300. }
  301. pp->pp_status = PIPE_NAK;
  302. pp_reg->HCHINTF = HCHINTF_NAK;
  303. } else {
  304. /* no operation */
  305. }
  306. return 1U;
  307. }
  308. /*!
  309. \brief handle the OUT channel interrupt
  310. \param[in] pudev: pointer to USB device instance
  311. \param[in] pp_num: host channel number which is in (0..7)
  312. \param[out] none
  313. \retval operation status
  314. */
  315. #if defined (__ICCARM__) /*!< IAR compiler */
  316. #pragma optimize = none
  317. #endif /* __ICCARM */
  318. static uint32_t usbh_int_pipe_out (usb_core_driver *pudev, uint32_t pp_num)
  319. {
  320. usb_pr *pp_reg = pudev->regs.pr[pp_num];
  321. usb_pipe *pp = &pudev->host.pipe[pp_num];
  322. uint32_t intr_pp = pp_reg->HCHINTF;
  323. intr_pp &= pp_reg->HCHINTEN;
  324. if (intr_pp & HCHINTF_ACK) {
  325. if (URB_PING == pp->urb_state) {
  326. pp->err_count = 0U;
  327. usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF);
  328. }
  329. pp_reg->HCHINTF = HCHINTF_ACK;
  330. } else if (intr_pp & HCHINTF_STALL) {
  331. usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL);
  332. } else if (intr_pp & HCHINTF_DTER) {
  333. usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR);
  334. pp_reg->HCHINTF = HCHINTF_NAK;
  335. } else if (intr_pp & HCHINTF_REQOVR) {
  336. usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR);
  337. } else if (intr_pp & HCHINTF_TF) {
  338. pp->err_count = 0U;
  339. usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF);
  340. } else if (intr_pp & HCHINTF_NAK) {
  341. pp->err_count = 0U;
  342. usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_NAK);
  343. } else if (intr_pp & HCHINTF_USBER) {
  344. pp->err_count++;
  345. usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR);
  346. } else if (intr_pp & HCHINTF_NYET) {
  347. pp->err_count = 0U;
  348. usb_pp_halt (pudev, (uint8_t)pp_num, HCHINTF_NYET, PIPE_NYET);
  349. } else if (intr_pp & HCHINTF_CH) {
  350. pudev->regs.pr[pp_num]->HCHINTEN &= ~HCHINTEN_CHIE;
  351. switch (pp->pp_status) {
  352. case PIPE_XF:
  353. pp->urb_state = URB_DONE;
  354. if ((uint8_t)USB_EPTYPE_BULK == ((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U)) {
  355. pp->data_toggle_out ^= 1U;
  356. }
  357. break;
  358. case PIPE_NAK:
  359. if (URB_PING == pp->urb_state) {
  360. (void)usb_pipe_ping (pudev, (uint8_t)pp_num);
  361. } else {
  362. pp->urb_state = URB_NOTREADY;
  363. }
  364. break;
  365. case PIPE_NYET:
  366. if (1U == pudev->host.pipe[pp_num].ping) {
  367. (void)usb_pipe_ping (pudev, (uint8_t)pp_num);
  368. pp->urb_state = URB_PING;
  369. }
  370. else {
  371. pp->urb_state = URB_NOTREADY;
  372. }
  373. break;
  374. case PIPE_STALL:
  375. pp->urb_state = URB_STALL;
  376. break;
  377. case PIPE_TRACERR:
  378. if (3U == pp->err_count) {
  379. pp->urb_state = URB_ERROR;
  380. pp->err_count = 0U;
  381. }
  382. break;
  383. case PIPE_IDLE:
  384. case PIPE_HALTED:
  385. case PIPE_BBERR:
  386. case PIPE_REQOVR:
  387. case PIPE_DTGERR:
  388. default:
  389. break;
  390. }
  391. pp_reg->HCHINTF = HCHINTF_CH;
  392. } else {
  393. /* no operation */
  394. }
  395. return 1U;
  396. }
  397. /*!
  398. \brief handle the RX FIFO non-empty interrupt
  399. \param[in] pudev: pointer to USB device instance
  400. \param[out] none
  401. \retval operation status
  402. */
  403. #if defined (__ICCARM__) /*!< IAR compiler */
  404. #pragma optimize = none
  405. #endif /* __ICCARM */
  406. static uint32_t usbh_int_rxfifonoempty (usb_core_driver *pudev)
  407. {
  408. uint32_t count = 0U,xfer_count = 0U;
  409. __IO uint8_t pp_num = 0U;
  410. __IO uint32_t rx_stat = 0U;
  411. /* disable the RX status queue level interrupt */
  412. pudev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE;
  413. rx_stat = pudev->regs.gr->GRSTATP;
  414. pp_num = (uint8_t)(rx_stat & GRSTATRP_CNUM);
  415. switch ((rx_stat & GRSTATRP_RPCKST) >> 17U) {
  416. case GRXSTS_PKTSTS_IN:
  417. count = (rx_stat & GRSTATRP_BCOUNT) >> 4U;
  418. /* read the data into the host buffer. */
  419. if ((count > 0U) && (NULL != pudev->host.pipe[pp_num].xfer_buf)) {
  420. (void)usb_rxfifo_read (&pudev->regs, pudev->host.pipe[pp_num].xfer_buf, (uint16_t)count);
  421. /* manage multiple transfer packet */
  422. pudev->host.pipe[pp_num].xfer_buf += count;
  423. pudev->host.pipe[pp_num].xfer_count += count;
  424. xfer_count = pudev->host.pipe[pp_num].xfer_count;
  425. pudev->host.backup_xfercount[pp_num] = xfer_count;
  426. if (pudev->regs.pr[pp_num]->HCHLEN & HCHLEN_PCNT) {
  427. /* re-activate the channel when more packets are expected */
  428. uint32_t pp_ctl = pudev->regs.pr[pp_num]->HCHCTL;
  429. pp_ctl |= HCHCTL_CEN;
  430. pp_ctl &= ~HCHCTL_CDIS;
  431. pudev->regs.pr[pp_num]->HCHCTL = pp_ctl;
  432. }
  433. }
  434. break;
  435. case GRXSTS_PKTSTS_IN_XFER_COMP:
  436. break;
  437. case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
  438. count = (rx_stat & GRSTATRP_BCOUNT) >> 4U;
  439. while (count > 0U) {
  440. rx_stat = pudev->regs.gr->GRSTATP;
  441. count--;
  442. }
  443. break;
  444. case GRXSTS_PKTSTS_CH_HALTED:
  445. break;
  446. default:
  447. break;
  448. }
  449. /* enable the RX status queue level interrupt */
  450. pudev->regs.gr->GINTEN |= GINTEN_RXFNEIE;
  451. return 1U;
  452. }
  453. /*!
  454. \brief handle the TX FIFO empty interrupt
  455. \param[in] pudev: pointer to USB device instance
  456. \param[in] pp_mode: pipe mode
  457. \param[out] none
  458. \retval operation status
  459. */
  460. #if defined (__ICCARM__) /*!< IAR compiler */
  461. #pragma optimize = none
  462. #endif /* __ICCARM */
  463. static uint32_t usbh_int_txfifoempty (usb_core_driver *pudev, usb_pipe_mode pp_mode)
  464. {
  465. uint8_t pp_num = 0U;
  466. uint16_t word_count = 0U, len = 0U;
  467. __IO uint32_t *txfiforeg = 0U, txfifostate = 0U;
  468. if (PIPE_NON_PERIOD == pp_mode) {
  469. txfiforeg = &pudev->regs.gr->HNPTFQSTAT;
  470. } else if (PIPE_PERIOD == pp_mode) {
  471. txfiforeg = &pudev->regs.hr->HPTFQSTAT;
  472. } else {
  473. return 0U;
  474. }
  475. txfifostate = *txfiforeg;
  476. pp_num = (uint8_t)((txfifostate & TFQSTAT_CNUM) >> 27U);
  477. word_count = (uint16_t)(pudev->host.pipe[pp_num].xfer_len + 3U) / 4U;
  478. while (((txfifostate & TFQSTAT_TXFS) >= word_count) && (0U != pudev->host.pipe[pp_num].xfer_len)) {
  479. len = (uint16_t)(txfifostate & TFQSTAT_TXFS) * 4U;
  480. if (len > pudev->host.pipe[pp_num].xfer_len) {
  481. /* last packet */
  482. len = (uint16_t)pudev->host.pipe[pp_num].xfer_len;
  483. if (PIPE_NON_PERIOD == pp_mode) {
  484. pudev->regs.gr->GINTEN &= ~GINTEN_NPTXFEIE;
  485. } else {
  486. pudev->regs.gr->GINTEN &= ~GINTEN_PTXFEIE;
  487. }
  488. }
  489. word_count = (uint16_t)((pudev->host.pipe[pp_num].xfer_len + 3U) / 4U);
  490. usb_txfifo_write (&pudev->regs, pudev->host.pipe[pp_num].xfer_buf, pp_num, len);
  491. pudev->host.pipe[pp_num].xfer_buf += len;
  492. pudev->host.pipe[pp_num].xfer_len -= len;
  493. pudev->host.pipe[pp_num].xfer_count += len;
  494. txfifostate = *txfiforeg;
  495. }
  496. return 1U;
  497. }