You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

436 lines
11 KiB

  1. /** @addtogroup usb_file USB peripheral API
  2. * @ingroup peripheral_apis
  3. *
  4. * @sa usb_defines
  5. * @copyright See @ref lgpl_license
  6. */
  7. /*
  8. * This file is part of the libopencm3 project.
  9. *
  10. * Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
  11. * Copyright (C) 2015 Kuldeep Singh Dhaka <kuldeepdhaka9@gmail.com>
  12. *
  13. * This library is free software: you can redistribute it and/or modify
  14. * it under the terms of the GNU Lesser General Public License as published by
  15. * the Free Software Foundation, either version 3 of the License, or
  16. * (at your option) any later version.
  17. *
  18. * This library is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU Lesser General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU Lesser General Public License
  24. * along with this library. If not, see <http://www.gnu.org/licenses/>.
  25. */
  26. #include <string.h>
  27. #include <libopencm3/cm3/common.h>
  28. #include <libopencm3/efm32/memorymap.h>
  29. #include <libopencm3/efm32/cmu.h>
  30. #include <libopencm3/efm32/usb.h>
  31. #include <libopencm3/usb/usbd.h>
  32. #include "usb_private.h"
  33. /**@{*/
  34. /* Receive FIFO size in 32-bit words. */
  35. #define RX_FIFO_SIZE 256
  36. /* FIME: EFM32LG have 6 bidirectonal-endpoint
  37. * problem is "uint32_t doeptsiz[4];" in usb_private.h
  38. * doeptsiz is fixed size of length 4,
  39. * if we it to be of length 6
  40. * possibly, same with "uint8_t force_nak[4];"
  41. *
  42. * solution: remove everything driver specific from usb_private.h
  43. * and move that to there specific driver files.
  44. * maybe a pointer to driver specific data will do the task. */
  45. #define ENDPOINT_COUNT 4
  46. static struct _usbd_device _usbd_dev;
  47. /** Initialize the USB_FS device controller hardware of the STM32. */
  48. static usbd_device *efm32lg_usbd_init(void)
  49. {
  50. /* Enable clock */
  51. CMU_HFCORECLKEN0 |= CMU_HFCORECLKEN0_USB | CMU_HFCORECLKEN0_USBC;
  52. CMU_CMD = CMU_CMD_USBCCLKSEL_HFCLKNODIV;
  53. /* wait till clock not selected */
  54. while (!(CMU_STATUS & CMU_STATUS_USBCHFCLKSEL));
  55. USB_GINTSTS = USB_GINTSTS_MMIS;
  56. USB_CTRL &= ~USB_CTRL_DMPUAP;
  57. USB_ROUTE = USB_ROUTE_DMPUPEN | USB_ROUTE_PHYPEN;
  58. /* Wait for AHB idle. */
  59. while (!(USB_GRSTCTL & USB_GRSTCTL_AHBIDL));
  60. /* Do core soft reset. */
  61. USB_GRSTCTL |= USB_GRSTCTL_CSRST;
  62. while (USB_GRSTCTL & USB_GRSTCTL_CSRST);
  63. /* Force peripheral only mode. */
  64. USB_GUSBCFG |= USB_GUSBCFG_FDMOD | USB_GUSBCFG_TRDT_16BIT;
  65. /* Full speed device. */
  66. USB_DCFG |= USB_DCFG_DSPD;
  67. /* Restart the PHY clock. */
  68. USB_PCGCCTL = 0;
  69. USB_GRXFSIZ = efm32lg_usb_driver.rx_fifo_size;
  70. _usbd_dev.fifo_mem_top = efm32lg_usb_driver.rx_fifo_size;
  71. /* Unmask interrupts for TX and RX. */
  72. USB_GAHBCFG |= USB_GAHBCFG_GLBLINTRMSK;
  73. USB_GINTMSK = USB_GINTMSK_ENUMDNEM |
  74. USB_GINTMSK_RXFLVLM |
  75. USB_GINTMSK_IEPINT |
  76. USB_GINTMSK_USBSUSPM |
  77. USB_GINTMSK_WUIM;
  78. USB_DAINTMSK = 0xF;
  79. USB_DIEPMSK = USB_DIEPMSK_XFRCM;
  80. return &_usbd_dev;
  81. }
  82. static void efm32lg_set_address(usbd_device *usbd_dev, uint8_t addr)
  83. {
  84. (void)usbd_dev;
  85. USB_DCFG = (USB_DCFG & ~USB_DCFG_DAD) | (addr << 4);
  86. }
  87. static void efm32lg_ep_setup(usbd_device *usbd_dev, uint8_t addr, uint8_t type,
  88. uint16_t max_size,
  89. void (*callback) (usbd_device *usbd_dev, uint8_t ep))
  90. {
  91. /*
  92. * Configure endpoint address and type. Allocate FIFO memory for
  93. * endpoint. Install callback function.
  94. */
  95. uint8_t dir = addr & 0x80;
  96. addr &= 0x7f;
  97. if (addr == 0) { /* For the default control endpoint */
  98. /* Configure IN part. */
  99. if (max_size >= 64) {
  100. USB_DIEP0CTL = USB_DIEP0CTL_MPSIZ_64;
  101. } else if (max_size >= 32) {
  102. USB_DIEP0CTL = USB_DIEP0CTL_MPSIZ_32;
  103. } else if (max_size >= 16) {
  104. USB_DIEP0CTL = USB_DIEP0CTL_MPSIZ_16;
  105. } else {
  106. USB_DIEP0CTL = USB_DIEP0CTL_MPSIZ_8;
  107. }
  108. USB_DIEP0TSIZ =
  109. (max_size & USB_DIEP0TSIZ_XFRSIZ_MASK);
  110. USB_DIEP0CTL |=
  111. USB_DIEP0CTL_EPENA | USB_DIEP0CTL_SNAK;
  112. /* Configure OUT part. */
  113. usbd_dev->doeptsiz[0] = USB_DIEP0TSIZ_STUPCNT_1 |
  114. USB_DIEP0TSIZ_PKTCNT |
  115. (max_size & USB_DIEP0TSIZ_XFRSIZ_MASK);
  116. USB_DOEPx_TSIZ(0) = usbd_dev->doeptsiz[0];
  117. USB_DOEPx_CTL(0) |=
  118. USB_DOEP0CTL_EPENA | USB_DIEP0CTL_SNAK;
  119. USB_GNPTXFSIZ = ((max_size / 4) << 16) |
  120. usbd_dev->driver->rx_fifo_size;
  121. usbd_dev->fifo_mem_top += max_size / 4;
  122. usbd_dev->fifo_mem_top_ep0 = usbd_dev->fifo_mem_top;
  123. return;
  124. }
  125. if (dir) {
  126. USB_DIEPTXF(addr) = ((max_size / 4) << 16) |
  127. usbd_dev->fifo_mem_top;
  128. usbd_dev->fifo_mem_top += max_size / 4;
  129. USB_DIEPx_TSIZ(addr) =
  130. (max_size & USB_DIEP0TSIZ_XFRSIZ_MASK);
  131. USB_DIEPx_CTL(addr) |=
  132. USB_DIEP0CTL_EPENA | USB_DIEP0CTL_SNAK | (type << 18)
  133. | USB_DIEP0CTL_USBAEP | USB_DIEP0CTL_SD0PID
  134. | (addr << 22) | max_size;
  135. if (callback) {
  136. usbd_dev->user_callback_ctr[addr][USB_TRANSACTION_IN] =
  137. (void *)callback;
  138. }
  139. }
  140. if (!dir) {
  141. usbd_dev->doeptsiz[addr] = USB_DIEP0TSIZ_PKTCNT |
  142. (max_size & USB_DIEP0TSIZ_XFRSIZ_MASK);
  143. USB_DOEPx_TSIZ(addr) = usbd_dev->doeptsiz[addr];
  144. USB_DOEPx_CTL(addr) |= USB_DOEP0CTL_EPENA |
  145. USB_DOEP0CTL_USBAEP | USB_DIEP0CTL_CNAK |
  146. USB_DOEP0CTL_SD0PID | (type << 18) | max_size;
  147. if (callback) {
  148. usbd_dev->user_callback_ctr[addr][USB_TRANSACTION_OUT] =
  149. (void *)callback;
  150. }
  151. }
  152. }
  153. static void efm32lg_endpoints_reset(usbd_device *usbd_dev)
  154. {
  155. /* The core resets the endpoints automatically on reset. */
  156. usbd_dev->fifo_mem_top = usbd_dev->fifo_mem_top_ep0;
  157. }
  158. static void efm32lg_ep_stall_set(usbd_device *usbd_dev, uint8_t addr,
  159. uint8_t stall)
  160. {
  161. (void)usbd_dev;
  162. if (addr == 0) {
  163. if (stall) {
  164. USB_DIEPx_CTL(addr) |= USB_DIEP0CTL_STALL;
  165. } else {
  166. USB_DIEPx_CTL(addr) &= ~USB_DIEP0CTL_STALL;
  167. }
  168. }
  169. if (addr & 0x80) {
  170. addr &= 0x7F;
  171. if (stall) {
  172. USB_DIEPx_CTL(addr) |= USB_DIEP0CTL_STALL;
  173. } else {
  174. USB_DIEPx_CTL(addr) &= ~USB_DIEP0CTL_STALL;
  175. USB_DIEPx_CTL(addr) |= USB_DIEP0CTL_SD0PID;
  176. }
  177. } else {
  178. if (stall) {
  179. USB_DOEPx_CTL(addr) |= USB_DOEP0CTL_STALL;
  180. } else {
  181. USB_DOEPx_CTL(addr) &= ~USB_DOEP0CTL_STALL;
  182. USB_DOEPx_CTL(addr) |= USB_DOEP0CTL_SD0PID;
  183. }
  184. }
  185. }
  186. static uint8_t efm32lg_ep_stall_get(usbd_device *usbd_dev, uint8_t addr)
  187. {
  188. (void)usbd_dev;
  189. /* Return non-zero if STALL set. */
  190. if (addr & 0x80) {
  191. return (USB_DIEPx_CTL(addr & 0x7f) &
  192. USB_DIEP0CTL_STALL) ? 1 : 0;
  193. } else {
  194. return (USB_DOEPx_CTL(addr) &
  195. USB_DOEP0CTL_STALL) ? 1 : 0;
  196. }
  197. }
  198. static void efm32lg_ep_nak_set(usbd_device *usbd_dev, uint8_t addr, uint8_t nak)
  199. {
  200. /* It does not make sence to force NAK on IN endpoints. */
  201. if (addr & 0x80) {
  202. return;
  203. }
  204. usbd_dev->force_nak[addr] = nak;
  205. if (nak) {
  206. USB_DOEPx_CTL(addr) |= USB_DOEP0CTL_SNAK;
  207. } else {
  208. USB_DOEPx_CTL(addr) |= USB_DOEP0CTL_CNAK;
  209. }
  210. }
  211. static uint16_t efm32lg_ep_write_packet(usbd_device *usbd_dev, uint8_t addr,
  212. const void *buf, uint16_t len)
  213. {
  214. (void)usbd_dev;
  215. const uint32_t *buf32 = buf;
  216. int i;
  217. addr &= 0x7F;
  218. /* Return if endpoint is already enabled. */
  219. if (USB_DIEPx_TSIZ(addr) & USB_DIEP0TSIZ_PKTCNT) {
  220. return 0;
  221. }
  222. /* Enable endpoint for transmission. */
  223. USB_DIEPx_TSIZ(addr) = USB_DIEP0TSIZ_PKTCNT | len;
  224. USB_DIEPx_CTL(addr) |= USB_DIEP0CTL_EPENA |
  225. USB_DIEP0CTL_CNAK;
  226. volatile uint32_t *fifo = USB_FIFOxD(addr);
  227. /* Copy buffer to endpoint FIFO, note - memcpy does not work */
  228. for (i = len; i > 0; i -= 4) {
  229. *fifo++ = *buf32++;
  230. }
  231. return len;
  232. }
  233. static uint16_t efm32lg_ep_read_packet(usbd_device *usbd_dev, uint8_t addr,
  234. void *buf, uint16_t len)
  235. {
  236. int i;
  237. uint32_t *buf32 = buf;
  238. uint32_t extra;
  239. len = MIN(len, usbd_dev->rxbcnt);
  240. usbd_dev->rxbcnt -= len;
  241. volatile uint32_t *fifo = USB_FIFOxD(addr);
  242. for (i = len; i >= 4; i -= 4) {
  243. *buf32++ = *fifo++;
  244. }
  245. if (i) {
  246. extra = *fifo++;
  247. memcpy(buf32, &extra, i);
  248. }
  249. USB_DOEPx_TSIZ(addr) = usbd_dev->doeptsiz[addr];
  250. USB_DOEPx_CTL(addr) |= USB_DOEP0CTL_EPENA |
  251. (usbd_dev->force_nak[addr] ?
  252. USB_DOEP0CTL_SNAK : USB_DOEP0CTL_CNAK);
  253. return len;
  254. }
  255. static void efm32lg_poll(usbd_device *usbd_dev)
  256. {
  257. /* Read interrupt status register. */
  258. uint32_t intsts = USB_GINTSTS;
  259. int i;
  260. if (intsts & USB_GINTSTS_ENUMDNE) {
  261. /* Handle USB RESET condition. */
  262. USB_GINTSTS = USB_GINTSTS_ENUMDNE;
  263. usbd_dev->fifo_mem_top = usbd_dev->driver->rx_fifo_size;
  264. _usbd_reset(usbd_dev);
  265. return;
  266. }
  267. /* Note: RX and TX handled differently in this device. */
  268. if (intsts & USB_GINTSTS_RXFLVL) {
  269. /* Receive FIFO non-empty. */
  270. uint32_t rxstsp = USB_GRXSTSP;
  271. uint32_t pktsts = rxstsp & USB_GRXSTSP_PKTSTS_MASK;
  272. if ((pktsts != USB_GRXSTSP_PKTSTS_OUT) &&
  273. (pktsts != USB_GRXSTSP_PKTSTS_SETUP)) {
  274. return;
  275. }
  276. uint8_t ep = rxstsp & USB_GRXSTSP_EPNUM_MASK;
  277. uint8_t type;
  278. if (pktsts == USB_GRXSTSP_PKTSTS_SETUP) {
  279. type = USB_TRANSACTION_SETUP;
  280. } else {
  281. type = USB_TRANSACTION_OUT;
  282. }
  283. /* Save packet size for stm32f107_ep_read_packet(). */
  284. usbd_dev->rxbcnt = (rxstsp & USB_GRXSTSP_BCNT_MASK) >> 4;
  285. /*
  286. * FIXME: Why is a delay needed here?
  287. * This appears to fix a problem where the first 4 bytes
  288. * of the DATA OUT stage of a control transaction are lost.
  289. */
  290. for (i = 0; i < 1000; i++) {
  291. __asm__("nop");
  292. }
  293. if (usbd_dev->user_callback_ctr[ep][type]) {
  294. usbd_dev->user_callback_ctr[ep][type] (usbd_dev, ep);
  295. }
  296. /* Discard unread packet data. */
  297. for (i = 0; i < usbd_dev->rxbcnt; i += 4) {
  298. (void)*USB_FIFOxD(ep);
  299. }
  300. usbd_dev->rxbcnt = 0;
  301. }
  302. /*
  303. * There is no global interrupt flag for transmit complete.
  304. * The XFRC bit must be checked in each USB_DIEPx_INT(x).
  305. */
  306. for (i = 0; i < ENDPOINT_COUNT; i++) { /* Iterate over endpoints. */
  307. if (USB_DIEPx_INT(i) & USB_DIEP_INT_XFRC) {
  308. /* Transfer complete. */
  309. if (usbd_dev->user_callback_ctr[i]
  310. [USB_TRANSACTION_IN]) {
  311. usbd_dev->user_callback_ctr[i]
  312. [USB_TRANSACTION_IN](usbd_dev, i);
  313. }
  314. USB_DIEPx_INT(i) = USB_DIEP_INT_XFRC;
  315. }
  316. }
  317. if (intsts & USB_GINTSTS_USBSUSP) {
  318. if (usbd_dev->user_callback_suspend) {
  319. usbd_dev->user_callback_suspend();
  320. }
  321. USB_GINTSTS = USB_GINTSTS_USBSUSP;
  322. }
  323. if (intsts & USB_GINTSTS_WKUPINT) {
  324. if (usbd_dev->user_callback_resume) {
  325. usbd_dev->user_callback_resume();
  326. }
  327. USB_GINTSTS = USB_GINTSTS_WKUPINT;
  328. }
  329. if (intsts & USB_GINTSTS_SOF) {
  330. if (usbd_dev->user_callback_sof) {
  331. usbd_dev->user_callback_sof();
  332. }
  333. USB_GINTSTS = USB_GINTSTS_SOF;
  334. }
  335. if (usbd_dev->user_callback_sof) {
  336. USB_GINTMSK |= USB_GINTMSK_SOFM;
  337. } else {
  338. USB_GINTMSK &= ~USB_GINTMSK_SOFM;
  339. }
  340. }
  341. static void efm32lg_disconnect(usbd_device *usbd_dev, bool disconnected)
  342. {
  343. (void)usbd_dev;
  344. if (disconnected) {
  345. USB_DCTL |= USB_DCTL_SDIS;
  346. } else {
  347. USB_DCTL &= ~USB_DCTL_SDIS;
  348. }
  349. }
  350. const struct _usbd_driver efm32lg_usb_driver = {
  351. .init = efm32lg_usbd_init,
  352. .set_address = efm32lg_set_address,
  353. .ep_setup = efm32lg_ep_setup,
  354. .ep_reset = efm32lg_endpoints_reset,
  355. .ep_stall_set = efm32lg_ep_stall_set,
  356. .ep_stall_get = efm32lg_ep_stall_get,
  357. .ep_nak_set = efm32lg_ep_nak_set,
  358. .ep_write_packet = efm32lg_ep_write_packet,
  359. .ep_read_packet = efm32lg_ep_read_packet,
  360. .poll = efm32lg_poll,
  361. .disconnect = efm32lg_disconnect,
  362. .base_address = USB_BASE,
  363. .set_address_before_status = 1,
  364. .rx_fifo_size = RX_FIFO_SIZE,
  365. };
  366. /**@}*/