usb.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. /*
  2. * Copyright (c) 2020, Alex Taradov <alex@taradov.com>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice,
  9. * this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. The name of the author may not be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  20. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  22. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  23. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  24. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  25. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  26. * POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. /*- Includes ----------------------------------------------------------------*/
  29. #include <string.h>
  30. #include <stdbool.h>
  31. #include <stdalign.h>
  32. #include "same70.h"
  33. #include "hal_gpio.h"
  34. #include "utils.h"
  35. #include "usb.h"
  36. #include "usb_std.h"
  37. #include "usb_descriptors.h"
  38. /*- Definitions -------------------------------------------------------------*/
  39. #define USBHS_RAM(ep) ((volatile uint8_t *)(0xa0100000 + 0x8000 * (ep)))
  40. /*- Constants ---------------------------------------------------------------*/
  41. static const int usb_ep_banks[USB_EP_NUM] = USB_EP_BANKS;
  42. /*- Variables ---------------------------------------------------------------*/
  43. static uint8_t usb_ctrl_out_buf[64];
  44. static void (*usb_control_recv_callback)(uint8_t *data, int size);
  45. static uint8_t *usb_ep_data[USB_EP_NUM];
  46. static int usb_ep_size[USB_EP_NUM];
  47. /*- Implementations ---------------------------------------------------------*/
  48. //-----------------------------------------------------------------------------
  49. void usb_hw_init(void)
  50. {
  51. PMC->PMC_PCER1 = PMC_PCER1_PID34/*ID_USBHS*/;
  52. PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(3);
  53. while (0 == (PMC->PMC_SR & PMC_SR_LOCKU));
  54. PMC->PMC_USB = PMC_USB_USBS;
  55. USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD_DEVICE | USBHS_CTRL_USBE;
  56. while (0 == (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE));
  57. for (int i = 0; i < USB_EP_NUM; i++)
  58. usb_reset_endpoint(i, 0);
  59. usb_detach();
  60. usb_attach();
  61. #ifdef USB_ASYNC
  62. NVIC_EnableIRQ(USBHS_IRQn);
  63. #endif
  64. }
  65. //-----------------------------------------------------------------------------
  66. void usb_attach(void)
  67. {
  68. while (0 == (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE));
  69. USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC | USBHS_DEVICR_MSOFC |
  70. USBHS_DEVICR_SOFC | USBHS_DEVICR_EORSTC | USBHS_DEVICR_WAKEUPC |
  71. USBHS_DEVICR_EORSMC | USBHS_DEVICR_UPRSMC;
  72. USBHS->USBHS_DEVIER = USBHS_DEVIER_EORSTES;
  73. USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH;
  74. }
  75. //-----------------------------------------------------------------------------
  76. void usb_detach(void)
  77. {
  78. USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_DETACH;
  79. }
  80. //-----------------------------------------------------------------------------
  81. void usb_reset_endpoint(int ep, int dir)
  82. {
  83. USBHS->USBHS_DEVEPT |= (USBHS_DEVEPT_EPRST0 << ep);
  84. USBHS->USBHS_DEVEPT &= ~(USBHS_DEVEPT_EPRST0 << ep);
  85. USBHS->USBHS_DEVEPTIER[ep] = USBHS_DEVEPTIER_RSTDTS;
  86. USBHS->USBHS_DEVEPTIDR[ep] = USBHS_DEVEPTIDR_RXOUTEC | USBHS_DEVEPTIDR_TXINEC;
  87. usb_ep_size[ep] = 0;
  88. usb_ep_data[ep] = NULL;
  89. (void)dir;
  90. }
  91. //-----------------------------------------------------------------------------
  92. void usb_configure_endpoint(usb_endpoint_descriptor_t *desc)
  93. {
  94. int ep, dir, type, size, banks;
  95. ep = desc->bEndpointAddress & USB_INDEX_MASK;
  96. dir = desc->bEndpointAddress & USB_DIRECTION_MASK;
  97. type = desc->bmAttributes & 0x03;
  98. size = desc->wMaxPacketSize;
  99. usb_reset_endpoint(desc->bEndpointAddress, dir);
  100. if (USB_ISOCHRONOUS_ENDPOINT != type)
  101. USBHS->USBHS_DEVEPTIER[ep] = USBHS_DEVEPTIER_RSTDTS;
  102. if (size <= 8)
  103. size = USBHS_DEVEPTCFG_EPSIZE_8_BYTE;
  104. else if (size <= 16)
  105. size = USBHS_DEVEPTCFG_EPSIZE_16_BYTE;
  106. else if (size <= 32)
  107. size = USBHS_DEVEPTCFG_EPSIZE_32_BYTE;
  108. else if (size <= 64)
  109. size = USBHS_DEVEPTCFG_EPSIZE_64_BYTE;
  110. else if (size <= 128)
  111. size = USBHS_DEVEPTCFG_EPSIZE_128_BYTE;
  112. else if (size <= 256)
  113. size = USBHS_DEVEPTCFG_EPSIZE_256_BYTE;
  114. else if (size <= 512)
  115. size = USBHS_DEVEPTCFG_EPSIZE_512_BYTE;
  116. else if (size <= 1024)
  117. size = USBHS_DEVEPTCFG_EPSIZE_1024_BYTE;
  118. else
  119. while (1);
  120. if (USB_CONTROL_ENDPOINT == type)
  121. type = USBHS_DEVEPTCFG_EPTYPE_CTRL;
  122. else if (USB_ISOCHRONOUS_ENDPOINT == type)
  123. type = USBHS_DEVEPTCFG_EPTYPE_ISO;
  124. else if (USB_BULK_ENDPOINT == type)
  125. type = USBHS_DEVEPTCFG_EPTYPE_BLK;
  126. else
  127. type = USBHS_DEVEPTCFG_EPTYPE_INTRPT;
  128. if (USB_IN_ENDPOINT == dir)
  129. dir = USBHS_DEVEPTCFG_EPDIR_IN;
  130. else
  131. dir = USBHS_DEVEPTCFG_EPDIR_OUT;
  132. if (1 == usb_ep_banks[ep])
  133. banks = USBHS_DEVEPTCFG_EPBK_1_BANK;
  134. else if (2 == usb_ep_banks[ep])
  135. banks = USBHS_DEVEPTCFG_EPBK_2_BANK;
  136. else if (3 == usb_ep_banks[ep])
  137. banks = USBHS_DEVEPTCFG_EPBK_3_BANK;
  138. else
  139. while (1);
  140. USBHS->USBHS_DEVEPTCFG[ep] = type | size | dir | banks |
  141. USBHS_DEVEPTCFG_NBTRANS_1_TRANS | USBHS_DEVEPTCFG_ALLOC;
  142. while (0 == (USBHS->USBHS_DEVEPTISR[ep] & USBHS_DEVEPTISR_CFGOK));
  143. USBHS->USBHS_DEVEPT |= (USBHS_DEVEPT_EPEN0 << ep);
  144. USBHS->USBHS_DEVIER = (USBHS_DEVIER_PEP_0 << ep);
  145. }
  146. //-----------------------------------------------------------------------------
  147. bool usb_endpoint_configured(int ep, int dir)
  148. {
  149. (void)dir;
  150. return (0 != (USBHS->USBHS_DEVEPT & (USBHS_DEVEPT_EPEN0 << ep)));
  151. }
  152. //-----------------------------------------------------------------------------
  153. int usb_endpoint_get_status(int ep, int dir)
  154. {
  155. (void)dir;
  156. return (0 != (USBHS->USBHS_DEVEPTIMR[ep] & USBHS_DEVEPTIMR_STALLRQ));
  157. }
  158. //-----------------------------------------------------------------------------
  159. void usb_endpoint_set_feature(int ep, int dir)
  160. {
  161. USBHS->USBHS_DEVEPTICR[ep] = USBHS_DEVEPTICR_STALLEDIC;
  162. USBHS->USBHS_DEVEPTIER[ep] = USBHS_DEVEPTIER_STALLRQS;
  163. (void)dir;
  164. }
  165. //-----------------------------------------------------------------------------
  166. void usb_endpoint_clear_feature(int ep, int dir)
  167. {
  168. if (USBHS->USBHS_DEVEPTIMR[ep] & USBHS_DEVEPTIMR_STALLRQ)
  169. {
  170. if (USBHS->USBHS_DEVEPTISR[ep] & USBHS_DEVEPTISR_STALLEDI)
  171. USBHS->USBHS_DEVEPTICR[ep] = USBHS_DEVEPTICR_STALLEDIC;
  172. USBHS->USBHS_DEVEPTIDR[ep] = USBHS_DEVEPTIDR_STALLRQC;
  173. }
  174. USBHS->USBHS_DEVEPTIER[ep] = USBHS_DEVEPTIER_RSTDTS;
  175. (void)dir;
  176. }
  177. //-----------------------------------------------------------------------------
  178. void usb_set_address(int address)
  179. {
  180. USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_ADDEN;
  181. USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_UADD_Msk;
  182. USBHS->USBHS_DEVCTRL |= address;
  183. USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_ADDEN;
  184. }
  185. //-----------------------------------------------------------------------------
  186. static bool endpoint_busy(int ep)
  187. {
  188. int busy = ((USBHS->USBHS_DEVEPTISR[ep] & USBHS_DEVEPTISR_NBUSYBK_Msk) >> USBHS_DEVEPTISR_NBUSYBK_Pos);
  189. return (busy == usb_ep_banks[ep]);
  190. }
  191. //-----------------------------------------------------------------------------
  192. static void dma_transfer(int ep, uint8_t *data, int size)
  193. {
  194. int ch = ep-1;
  195. USBHS->USBHS_DEVDMA[ch].USBHS_DEVDMANXTDSC = 0;
  196. USBHS->USBHS_DEVDMA[ch].USBHS_DEVDMAADDRESS = (uint32_t)data;
  197. USBHS->USBHS_DEVDMA[ch].USBHS_DEVDMACONTROL = USBHS_DEVDMACONTROL_CHANN_ENB |
  198. USBHS_DEVDMACONTROL_BUFF_LENGTH(size);
  199. while (0 == (USBHS->USBHS_DEVDMA[ch].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_BF_ST));
  200. }
  201. //-----------------------------------------------------------------------------
  202. void usb_send(int ep, uint8_t *data, int size)
  203. {
  204. while (endpoint_busy(ep));
  205. dma_transfer(ep, data, size);
  206. USBHS->USBHS_DEVEPTICR[ep] = USBHS_DEVEPTICR_TXINIC;
  207. USBHS->USBHS_DEVEPTIER[ep] = USBHS_DEVEPTIER_TXINES;
  208. USBHS->USBHS_DEVEPTIDR[ep] = USBHS_DEVEPTIDR_FIFOCONC;
  209. }
  210. //-----------------------------------------------------------------------------
  211. void usb_recv(int ep, uint8_t *data, int size)
  212. {
  213. usb_ep_size[ep] = size;
  214. usb_ep_data[ep] = data;
  215. USBHS->USBHS_DEVEPTICR[ep] = USBHS_DEVEPTICR_RXOUTIC;
  216. USBHS->USBHS_DEVEPTIER[ep] = USBHS_DEVEPTIER_RXOUTES;
  217. USBHS->USBHS_DEVEPTIDR[ep] = USBHS_DEVEPTIDR_FIFOCONC;
  218. }
  219. //-----------------------------------------------------------------------------
  220. void usb_control_send_zlp(void)
  221. {
  222. USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC;
  223. while (0 == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_TXINI));
  224. }
  225. //-----------------------------------------------------------------------------
  226. void usb_control_stall(void)
  227. {
  228. USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_STALLRQS;
  229. }
  230. //-----------------------------------------------------------------------------
  231. void usb_control_send(uint8_t *data, int size)
  232. {
  233. volatile uint8_t *usb_ram = USBHS_RAM(0);
  234. while (size)
  235. {
  236. int transfer_size = LIMIT(size, usb_device_descriptor.bMaxPacketSize0);
  237. for (int i = 0; i < transfer_size; i++)
  238. {
  239. usb_ram[i] = data[i];
  240. __DSB();
  241. }
  242. USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC;
  243. while (0 == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_TXINI));
  244. size -= transfer_size;
  245. data += transfer_size;
  246. }
  247. }
  248. //-----------------------------------------------------------------------------
  249. void usb_control_recv(void (*callback)(uint8_t *data, int size))
  250. {
  251. usb_control_recv_callback = callback;
  252. }
  253. //-----------------------------------------------------------------------------
  254. static int get_ep_byte_count(int ep)
  255. {
  256. return ((USBHS->USBHS_DEVEPTISR[ep] & USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos);
  257. }
  258. //-----------------------------------------------------------------------------
  259. static void usb_handler(void)
  260. {
  261. if (USBHS->USBHS_DEVISR & USBHS_DEVISR_EORST)
  262. {
  263. for (int i = 0; i < USB_EP_NUM; i++)
  264. usb_reset_endpoint(i, 0);
  265. usb_set_address(0);
  266. USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS;
  267. USBHS->USBHS_DEVEPTCFG[0] = USBHS_DEVEPTCFG_EPTYPE_CTRL |
  268. USBHS_DEVEPTCFG_ALLOC | USBHS_DEVEPTCFG_EPSIZE_64_BYTE |
  269. USBHS_DEVEPTCFG_EPBK_1_BANK | USBHS_DEVEPTCFG_NBTRANS_1_TRANS;
  270. while (0 == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK));
  271. USBHS->USBHS_DEVEPT = USBHS_DEVEPT_EPEN0;
  272. USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0;
  273. USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXSTPIC;
  274. USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RXSTPES;
  275. USBHS->USBHS_DEVICR = USBHS_DEVICR_EORSTC;
  276. }
  277. if (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_RXSTPI)
  278. {
  279. volatile uint8_t *data = USBHS_RAM(0);
  280. int size = get_ep_byte_count(0);
  281. for (int i = 0; i < (int)sizeof(usb_request_t); i++)
  282. usb_ctrl_out_buf[i] = data[i];
  283. USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXSTPIC;
  284. if (size == sizeof(usb_request_t))
  285. {
  286. if (!usb_handle_standard_request((usb_request_t *)usb_ctrl_out_buf))
  287. usb_control_stall();
  288. }
  289. else
  290. {
  291. usb_control_stall();
  292. }
  293. }
  294. else if (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_RXOUTI)
  295. {
  296. USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXOUTIC;
  297. // NOTE: This was not tested
  298. if (usb_control_recv_callback)
  299. {
  300. volatile uint8_t *data = USBHS_RAM(0);
  301. int size = LIMIT(get_ep_byte_count(0), usb_device_descriptor.bMaxPacketSize0);
  302. for (int i = 0; i < size; i++)
  303. usb_ctrl_out_buf[i] = data[i];
  304. usb_control_recv_callback(usb_ctrl_out_buf, size);
  305. usb_control_recv_callback = NULL;
  306. usb_control_send_zlp();
  307. }
  308. }
  309. for (int ep = 1; ep < USB_EP_NUM; ep++)
  310. {
  311. int sr = USBHS->USBHS_DEVEPTISR[ep] & USBHS->USBHS_DEVEPTIMR[ep];
  312. if (sr & USBHS_DEVEPTISR_RXOUTI)
  313. {
  314. int size = LIMIT(get_ep_byte_count(ep), usb_ep_size[ep]);
  315. dma_transfer(ep, usb_ep_data[ep], size);
  316. USBHS->USBHS_DEVEPTICR[ep] = USBHS_DEVEPTICR_RXOUTIC;
  317. USBHS->USBHS_DEVEPTIDR[ep] = USBHS_DEVEPTIDR_RXOUTEC;
  318. usb_recv_callback(ep, size);
  319. }
  320. if (sr & USBHS_DEVEPTISR_TXINI)
  321. {
  322. USBHS->USBHS_DEVEPTICR[ep] = USBHS_DEVEPTICR_TXINIC;
  323. USBHS->USBHS_DEVEPTIDR[ep] = USBHS_DEVEPTIDR_TXINEC;
  324. usb_send_callback(ep);
  325. }
  326. }
  327. }
  328. //-----------------------------------------------------------------------------
  329. void irq_handler_usbhs(void)
  330. {
  331. #ifdef USB_ASYNC
  332. usb_handler();
  333. #endif
  334. }
  335. //-----------------------------------------------------------------------------
  336. void usb_task(void)
  337. {
  338. #ifndef USB_ASYNC
  339. usb_handler();
  340. #endif
  341. }