at32f413_usb.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. /**
  2. **************************************************************************
  3. * @file at32f413_usb.c
  4. * @brief contains the functions for the usb firmware library
  5. **************************************************************************
  6. * Copyright notice & Disclaimer
  7. *
  8. * The software Board Support Package (BSP) that is made available to
  9. * download from Artery official website is the copyrighted work of Artery.
  10. * Artery authorizes customers to use, copy, and distribute the BSP
  11. * software and its related documentation for the purpose of design and
  12. * development in conjunction with Artery microcontrollers. Use of the
  13. * software is governed by this copyright notice and the following disclaimer.
  14. *
  15. * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
  16. * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
  17. * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
  18. * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
  19. * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
  21. *
  22. **************************************************************************
  23. */
  24. /** @addtogroup AT32F413_periph_driver
  25. * @{
  26. */
  27. /** @defgroup USB
  28. * @brief USB driver modules
  29. * @{
  30. */
  31. #include "at32f413_conf.h"
  32. #ifdef USB_MODULE_ENABLED
  33. /** @defgroup USB_private_functions
  34. * @{
  35. */
  36. /**
  37. * @brief usb packet buffer start address
  38. */
  39. #define USB_ENDP_DESC_TABLE_OFFSET 0x40
  40. uint32_t g_usb_packet_address = USB_PACKET_BUFFER_ADDRESS;
  41. static uint16_t g_usb_offset_addr = USB_ENDP_DESC_TABLE_OFFSET;
  42. /**
  43. * @brief initialize usb peripheral controller register
  44. * @param usbx: to select the usb peripheral.
  45. * parameter as following values: USB
  46. * @retval none
  47. */
  48. void usb_dev_init(usbd_type *usbx)
  49. {
  50. /* clear usb core reset */
  51. usbx->ctrl_bit.csrst = 0;
  52. /* clear usb interrupt status */
  53. usbx->intsts = 0;
  54. /* set usb packet buffer descirption table address */
  55. usbx->buftbl = USB_BUFFER_TABLE_ADDRESS;
  56. /* enable usb core and set device address to 0 */
  57. usbx->devaddr = 0x80;
  58. usb_interrupt_enable(usbx, USB_SOF_INT | USB_RST_INT | USB_SP_INT | USB_WK_INT | USB_TC_INT, TRUE);
  59. }
  60. /**
  61. * @brief connect usb device
  62. * @param usbx: to select the usb peripheral.
  63. * parameter as following values: USB
  64. * @retval none
  65. */
  66. void usb_connect(usbd_type *usbx)
  67. {
  68. /* enable usb phy */
  69. usbx->ctrl_bit.disusb = 0;
  70. }
  71. /**
  72. * @brief disconnect usb device
  73. * @param usbx: to select the usb peripheral.
  74. * parameter as following values: USB
  75. * @retval none
  76. */
  77. void usb_disconnect(usbd_type *usbx)
  78. {
  79. /* disable usb phy */
  80. usbx->ctrl_bit.disusb = TRUE;
  81. }
  82. /**
  83. * @brief mapping usb packet buffer area
  84. * two mapping intervals are available for packet buffer area,
  85. * and are select by the usbbufs in the crm misc1 register.
  86. * when usbbufs is 0,sram size is 512 bytes, packet buffer start
  87. * address is 0x40006000.when usbbufs is 1, sram size is fixed to
  88. * 768~1280 bytes, and the packet buffer start address is fixed to
  89. * 0x40007800,packet buffer size decided by whether can1 and can2 are
  90. * enabled;when both can1 and can2 are disabled, usb packet buffer can be set to the
  91. * maximum of 1280 bytes; when either can1 or can2 is enabled, usb packet buffer can be set to the
  92. * maximum of 1024 bytes; when both CAN1 and CAN2 are enabled, usb packet buffer can be set to the
  93. * maximum of 768 bytes.
  94. * @param usbx: to select the usb peripheral.
  95. * parameter as following values: USB
  96. * @retval none
  97. */
  98. void usb_usbbufs_enable(usbd_type *usbx, confirm_state state)
  99. {
  100. if(state == TRUE)
  101. {
  102. /* enable usbbufs */
  103. g_usb_packet_address = USB_PACKET_BUFFER_ADDRESS_EX;
  104. CRM->misc1_bit.usbbufs = TRUE;
  105. }
  106. else
  107. {
  108. /* disable usbbufs */
  109. g_usb_packet_address = USB_PACKET_BUFFER_ADDRESS;
  110. CRM->misc1_bit.usbbufs = FALSE;
  111. }
  112. }
  113. /**
  114. * @brief open usb endpoint
  115. * @param usbx: to select the usb peripheral.
  116. * parameter as following values: USB
  117. * @param ept_info: endpoint information structure
  118. * @retval none
  119. */
  120. void usb_ept_open(usbd_type *usbx, usb_ept_info *ept_info)
  121. {
  122. uint16_t type = 0;
  123. /* set endpoint address */
  124. USB_SET_EPT_ADDRESS(ept_info->eptn, ept_info->ept_address);
  125. /* select endpoint transfer type */
  126. if(ept_info->trans_type == EPT_CONTROL_TYPE)
  127. {
  128. type = USB_EPT_CONTROL;
  129. }
  130. else if(ept_info->trans_type == EPT_BULK_TYPE)
  131. {
  132. type = USB_EPT_BULK;
  133. }
  134. else if(ept_info->trans_type == EPT_INT_TYPE)
  135. {
  136. type = USB_EPT_INT;
  137. }
  138. else if(ept_info->trans_type == EPT_ISO_TYPE)
  139. {
  140. type = USB_EPT_ISO;
  141. ept_info->is_double_buffer = TRUE;
  142. }
  143. /* configure endpoint transfer type (control, bulk, interrupt, isochronous) */
  144. USB_SET_TRANS_TYPE(ept_info->eptn, type);
  145. /* endpoint is in transfer */
  146. if(ept_info->inout == DATA_TRANS_IN)
  147. {
  148. if(ept_info->is_double_buffer == 0)
  149. {
  150. /* set in endpoint tx offset address */
  151. USB_SET_TX_ADDRESS(ept_info->eptn, ept_info->tx_addr);
  152. /* clear in endpoint data toggle */
  153. USB_CLEAR_TXDTS(ept_info->eptn);
  154. /* set endpoint transmission status: nak */
  155. USB_SET_TXSTS(ept_info->eptn, USB_TX_NAK);
  156. }
  157. else
  158. {
  159. /* set double buffer endpoint*/
  160. USB_SET_EPT_DOUBLE_BUFFER(ept_info->eptn);
  161. /* set in endpoint offset address0 and address1 */
  162. USB_SET_DOUBLE_BUFF0_ADDRESS(ept_info->eptn, ept_info->tx_addr);
  163. USB_SET_DOUBLE_BUFF1_ADDRESS(ept_info->eptn, ept_info->rx_addr);
  164. /* clear in and out data toggle */
  165. USB_CLEAR_TXDTS(ept_info->eptn);
  166. USB_CLEAR_RXDTS(ept_info->eptn);
  167. /* toggle rx data toggle flag */
  168. USB_TOGGLE_RXDTS(ept_info->eptn);
  169. /* set endpoint reception status: disable */
  170. USB_SET_RXSTS(ept_info->eptn, USB_RX_DISABLE);
  171. /* set endpoint transmision status: nak */
  172. USB_SET_TXSTS(ept_info->eptn, USB_TX_NAK);
  173. }
  174. }
  175. else
  176. {
  177. if(ept_info->is_double_buffer == 0)
  178. {
  179. /* set out endpoint rx offset address */
  180. USB_SET_RX_ADDRESS(ept_info->eptn, ept_info->rx_addr);
  181. /* clear out endpoint data toggle */
  182. USB_CLEAR_RXDTS(ept_info->eptn);
  183. /* set out endpoint max reception buffer size */
  184. USB_SET_RXLEN(ept_info->eptn, ept_info->maxpacket);
  185. /* set endpoint reception status: valid */
  186. USB_SET_RXSTS(ept_info->eptn, USB_RX_VALID);
  187. }
  188. else
  189. {
  190. /* set double buffer endpoint */
  191. USB_SET_EPT_DOUBLE_BUFFER(ept_info->eptn);
  192. /* set out endpoint offset address0 and address1 */
  193. USB_SET_DOUBLE_BUFF0_ADDRESS(ept_info->eptn, ept_info->tx_addr);
  194. USB_SET_DOUBLE_BUFF1_ADDRESS(ept_info->eptn, ept_info->rx_addr);
  195. /* set out endpoint max reception buffer size */
  196. USB_SET_EPT_DOUBLE_BUF0_LEN(ept_info->eptn, ept_info->maxpacket, DATA_TRANS_OUT);
  197. USB_SET_EPT_DOUBLE_BUF1_LEN(ept_info->eptn, ept_info->maxpacket, DATA_TRANS_OUT);
  198. /* clear in and out data toggle */
  199. USB_CLEAR_TXDTS(ept_info->eptn);
  200. USB_CLEAR_RXDTS(ept_info->eptn);
  201. /* toggle tx data toggle flag */
  202. USB_TOGGLE_TXDTS(ept_info->eptn);
  203. /* set endpoint reception status: valid */
  204. USB_SET_RXSTS(ept_info->eptn, USB_RX_VALID);
  205. /* set endpoint transmision status: disable */
  206. USB_SET_TXSTS(ept_info->eptn, USB_TX_DISABLE);
  207. }
  208. }
  209. }
  210. /**
  211. * @brief close usb endpoint
  212. * @param usbx: to select the usb peripheral.
  213. * parameter as following values: USB
  214. * @param ept_info: endpoint information structure
  215. * @retval none
  216. */
  217. void usb_ept_close(usbd_type *usbx, usb_ept_info *ept_info)
  218. {
  219. if(ept_info->is_double_buffer == 0)
  220. {
  221. if(ept_info->inout == DATA_TRANS_IN)
  222. {
  223. /*clear tx data toggle */
  224. USB_CLEAR_TXDTS(ept_info->eptn);
  225. /* set tx status: disable */
  226. USB_SET_TXSTS(ept_info->eptn, USB_TX_DISABLE);
  227. }
  228. else
  229. {
  230. /*clear rx data toggle */
  231. USB_CLEAR_RXDTS(ept_info->eptn);
  232. /* set rx status: disable */
  233. USB_SET_RXSTS(ept_info->eptn, USB_RX_DISABLE);
  234. }
  235. }
  236. else
  237. {
  238. /* double buffer */
  239. /*clear rx and tx data toggle */
  240. USB_CLEAR_TXDTS(ept_info->eptn);
  241. USB_CLEAR_RXDTS(ept_info->eptn);
  242. if(ept_info->inout == DATA_TRANS_IN)
  243. {
  244. /* toggle tx */
  245. USB_TOGGLE_TXDTS(ept_info->eptn);
  246. /* set tx and rx status: disable */
  247. USB_SET_TXSTS(ept_info->eptn, USB_TX_DISABLE);
  248. USB_SET_RXSTS(ept_info->eptn, USB_RX_DISABLE);
  249. }
  250. else
  251. {
  252. /* toggle rx */
  253. USB_TOGGLE_RXDTS(ept_info->eptn);
  254. /* set tx and rx status: disable */
  255. USB_SET_TXSTS(ept_info->eptn, USB_TX_DISABLE);
  256. USB_SET_RXSTS(ept_info->eptn, USB_RX_DISABLE);
  257. }
  258. }
  259. }
  260. /**
  261. * @brief write data from user memory to usb buffer
  262. * @param pusr_buf: point to user buffer
  263. * @param offset_addr: endpoint tx offset address
  264. * @param nbytes: number of bytes data write to usb buffer
  265. * @retval none
  266. */
  267. void usb_write_packet(uint8_t *pusr_buf, uint16_t offset_addr, uint16_t nbytes)
  268. {
  269. /* endpoint tx buffer address */
  270. __IO uint16_t *d_addr = (__IO uint16_t *)(offset_addr * 2 + g_usb_packet_address);
  271. uint32_t nhbytes = (nbytes + 1) >> 1;
  272. uint32_t n_index;
  273. uint16_t *pbuf = (uint16_t *)pusr_buf;
  274. for(n_index = 0; n_index < nhbytes; n_index ++)
  275. {
  276. #if defined (__ICCARM__) && (__VER__ < 7000000)
  277. *d_addr++ = *(__packed uint16_t *)pbuf;
  278. #else
  279. *d_addr++ = __UNALIGNED_UINT16_READ(pbuf);
  280. #endif
  281. d_addr ++;
  282. pbuf ++;
  283. }
  284. }
  285. /**
  286. * @brief read data from usb buffer to user buffer
  287. * @param pusr_buf: point to user buffer
  288. * @param offset_addr: endpoint rx offset address
  289. * @param nbytes: number of bytes data write to usb buffer
  290. * @retval none
  291. */
  292. void usb_read_packet(uint8_t *pusr_buf, uint16_t offset_addr, uint16_t nbytes)
  293. {
  294. __IO uint16_t *s_addr = (__IO uint16_t *)(offset_addr * 2 + g_usb_packet_address);
  295. uint32_t nhbytes = (nbytes + 1) >> 1;
  296. uint32_t n_index;
  297. uint16_t *pbuf = (uint16_t *)pusr_buf;
  298. for(n_index = 0; n_index < nhbytes; n_index ++)
  299. {
  300. #if defined (__ICCARM__) && (__VER__ < 7000000)
  301. *(__packed uint16_t *)pbuf = *(__IO uint16_t *)s_addr ++;
  302. #else
  303. __UNALIGNED_UINT16_WRITE(pbuf, *(__IO uint16_t *)s_addr ++);
  304. #endif
  305. s_addr ++;
  306. pbuf ++;
  307. }
  308. }
  309. /**
  310. * @brief usb interrupt enable
  311. * @param usbx: to select the usb peripheral.
  312. * parameter as following values: USB
  313. * @param interrupt:
  314. * this parameter can be any combination of the following values:
  315. * - USB_LSOF_INT
  316. * - USB_SOF_INT
  317. * - USB_RST_INT
  318. * - USB_SP_INT
  319. * - USB_WK_INT
  320. * - USB_BE_INT
  321. * - USB_UCFOR_INT
  322. * - USB_TC_INT
  323. * @param new_state (TRUE or FALSE)
  324. * @retval none
  325. */
  326. void usb_interrupt_enable(usbd_type *usbx, uint16_t interrupt, confirm_state new_state)
  327. {
  328. if(new_state == TRUE)
  329. {
  330. usbx->ctrl |= interrupt;
  331. }
  332. else
  333. {
  334. usbx->ctrl &= ~interrupt;
  335. }
  336. }
  337. /**
  338. * @brief set the host assignment address
  339. * @param usbx: to select the usb peripheral.
  340. * parameter as following values: USB
  341. * @param address: host assignment address
  342. * @retval none
  343. */
  344. void usb_set_address(usbd_type *usbx, uint8_t address)
  345. {
  346. usbx->devaddr_bit.addr = address;
  347. usbx->devaddr_bit.cen = TRUE;
  348. }
  349. /**
  350. * @brief set endpoint tx or rx status to stall
  351. * @param usbx: to select the usb peripheral.
  352. * parameter as following values: USB
  353. * @param ept_info: endpoint information structure
  354. * @retval none
  355. */
  356. void usb_ept_stall(usbd_type *usbx, usb_ept_info *ept_info)
  357. {
  358. if(ept_info->inout == DATA_TRANS_IN)
  359. {
  360. USB_SET_TXSTS(ept_info->eptn, USB_TX_STALL)
  361. }
  362. else
  363. {
  364. USB_SET_RXSTS(ept_info->eptn, USB_RX_STALL)
  365. }
  366. }
  367. /**
  368. * @brief usb device enter suspend mode
  369. * @param usbx: to select the usb peripheral.
  370. * parameter as following values: USB
  371. * @retval none
  372. */
  373. void usb_enter_suspend(usbd_type *usbx)
  374. {
  375. usbx->ctrl_bit.ssp = TRUE;
  376. usbx->ctrl_bit.lpm = TRUE;
  377. }
  378. /**
  379. * @brief usb device exit suspend mode
  380. * @param usbx: to select the usb peripheral.
  381. * parameter as following values: USB
  382. * @retval none
  383. */
  384. void usb_exit_suspend(usbd_type *usbx)
  385. {
  386. usbx->ctrl_bit.ssp = FALSE;
  387. usbx->ctrl_bit.lpm = FALSE;
  388. }
  389. /**
  390. * @brief usb remote wakeup set
  391. * @param usbx: to select the usb peripheral.
  392. * parameter as following values: USB
  393. * @retval none
  394. */
  395. void usb_remote_wkup_set(usbd_type *usbx)
  396. {
  397. usbx->ctrl_bit.gresume = TRUE;
  398. }
  399. /**
  400. * @brief usb remote wakeup clear
  401. * @param usbx: to select the usb peripheral.
  402. * parameter as following values: USB
  403. * @retval none
  404. */
  405. void usb_remote_wkup_clear(usbd_type *usbx)
  406. {
  407. usbx->ctrl_bit.gresume = FALSE;
  408. }
  409. /**
  410. * @brief usb auto malloc endpoint buffer
  411. * @param mapacket: endpoint support max packet size
  412. * @retval none
  413. */
  414. uint16_t usb_buffer_malloc(uint16_t maxpacket)
  415. {
  416. uint16_t offset = g_usb_offset_addr;
  417. g_usb_offset_addr += maxpacket;
  418. return offset;
  419. }
  420. /**
  421. * @brief free usb endpoint buffer
  422. * @param none
  423. * @retval none
  424. */
  425. void usb_buffer_free(void)
  426. {
  427. g_usb_offset_addr = USB_ENDP_DESC_TABLE_OFFSET;
  428. }
  429. /**
  430. * @brief get flag of usb.
  431. * @param usbx: select the usb peripheral
  432. * @param flag: select the usb flag
  433. * this parameter can be one of the following values:
  434. * - USB_INOUT_FLAG
  435. * - USB_LSOF_FLAG
  436. * - USB_SOF_FLAG
  437. * - USB_RST_FLAG
  438. * - USB_SP_FLAG
  439. * - USB_WK_FLAG
  440. * - USB_BE_FLAG
  441. * - USB_UCFOR_FLAG
  442. * - USB_TC_FLAG
  443. * @retval none
  444. */
  445. flag_status usb_flag_get(usbd_type *usbx, uint16_t flag)
  446. {
  447. flag_status status = RESET;
  448. if((usbx->intsts & flag) == RESET)
  449. {
  450. status = RESET;
  451. }
  452. else
  453. {
  454. status = SET;
  455. }
  456. return status;
  457. }
  458. /**
  459. * @brief clear flag of usb.
  460. * @param usbx: select the usb peripheral
  461. * @param flag: select the usb flag
  462. * this parameter can be one of the following values:
  463. * - USB_INOUT_FLAG
  464. * - USB_LSOF_FLAG
  465. * - USB_SOF_FLAG
  466. * - USB_RST_FLAG
  467. * - USB_SP_FLAG
  468. * - USB_WK_FLAG
  469. * - USB_BE_FLAG
  470. * - USB_UCFOR_FLAG
  471. * - USB_TC_FLAG
  472. * @retval none
  473. */
  474. void usb_flag_clear(usbd_type *usbx, uint16_t flag)
  475. {
  476. usbx->intsts = ~flag;
  477. }
  478. /**
  479. * @}
  480. */
  481. #endif
  482. /**
  483. * @}
  484. */
  485. /**
  486. * @}
  487. */