cdc_loop.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. #include <stdint.h>
  2. #include <stdbool.h>
  3. #include <string.h>
  4. #include "macro.h"
  5. #include "stm32.h"
  6. #include "usb.h"
  7. #include "inc/usb_cdc.h"
  8. #define CDC_EP0_SIZE 0x08
  9. #define CDC_RXD_EP 0x01
  10. #define CDC_TXD_EP 0x82
  11. #define CDC_DATA_SZ 0x40
  12. #define CDC_NTF_EP 0x83
  13. #define CDC_NTF_SZ 0x08
  14. #define CDC_LOOPBACK
  15. struct cdc_config {
  16. struct usb_config_descriptor config;
  17. struct usb_interface_descriptor comm;
  18. struct usb_cdc_header_desc cdc_hdr;
  19. struct usb_cdc_call_mgmt_desc cdc_mgmt;
  20. struct usb_cdc_acm_desc cdc_acm;
  21. struct usb_cdc_union_desc cdc_union;
  22. struct usb_endpoint_descriptor comm_ep;
  23. struct usb_interface_descriptor data;
  24. struct usb_endpoint_descriptor data_eprx;
  25. struct usb_endpoint_descriptor data_eptx;
  26. } __attribute__((packed));
  27. static const struct usb_device_descriptor device_desc = {
  28. .bLength = sizeof(struct usb_device_descriptor),
  29. .bDescriptorType = USB_DTYPE_DEVICE,
  30. .bcdUSB = VERSION_BCD(2,0,0),
  31. .bDeviceClass = USB_CLASS_CDC,
  32. .bDeviceSubClass = USB_SUBCLASS_NONE,
  33. .bDeviceProtocol = USB_PROTO_NONE,
  34. .bMaxPacketSize0 = CDC_EP0_SIZE,
  35. .idVendor = 0x0483,
  36. .idProduct = 0x5740,
  37. .bcdDevice = VERSION_BCD(1,0,0),
  38. .iManufacturer = 1,
  39. .iProduct = 2,
  40. .iSerialNumber = INTSERIALNO_DESCRIPTOR,
  41. .bNumConfigurations = 1,
  42. };
  43. static const struct cdc_config config_desc = {
  44. .config = {
  45. .bLength = sizeof(struct usb_config_descriptor),
  46. .bDescriptorType = USB_DTYPE_CONFIGURATION,
  47. .wTotalLength = sizeof(struct cdc_config),
  48. .bNumInterfaces = 2,
  49. .bConfigurationValue = 1,
  50. .iConfiguration = NO_DESCRIPTOR,
  51. .bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
  52. .bMaxPower = USB_CFG_POWER_MA(100),
  53. },
  54. .comm = {
  55. .bLength = sizeof(struct usb_interface_descriptor),
  56. .bDescriptorType = USB_DTYPE_INTERFACE,
  57. .bInterfaceNumber = 0,
  58. .bAlternateSetting = 0,
  59. .bNumEndpoints = 1,
  60. .bInterfaceClass = USB_CLASS_CDC,
  61. .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
  62. .bInterfaceProtocol = USB_CDC_PROTO_V25TER,
  63. .iInterface = NO_DESCRIPTOR,
  64. },
  65. .cdc_hdr = {
  66. .bFunctionLength = sizeof(struct usb_cdc_header_desc),
  67. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  68. .bDescriptorSubType = USB_DTYPE_CDC_HEADER,
  69. .bcdCDC = VERSION_BCD(1,1,0),
  70. },
  71. .cdc_mgmt = {
  72. .bFunctionLength = sizeof(struct usb_cdc_call_mgmt_desc),
  73. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  74. .bDescriptorSubType = USB_DTYPE_CDC_CALL_MANAGEMENT,
  75. .bmCapabilities = 0,
  76. .bDataInterface = 1,
  77. },
  78. .cdc_acm = {
  79. .bFunctionLength = sizeof(struct usb_cdc_acm_desc),
  80. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  81. .bDescriptorSubType = USB_DTYPE_CDC_ACM,
  82. .bmCapabilities = 0,
  83. },
  84. .cdc_union = {
  85. .bFunctionLength = sizeof(struct usb_cdc_union_desc),
  86. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  87. .bDescriptorSubType = USB_DTYPE_CDC_UNION,
  88. .bMasterInterface0 = 0,
  89. .bSlaveInterface0 = 1,
  90. },
  91. .comm_ep = {
  92. .bLength = sizeof(struct usb_endpoint_descriptor),
  93. .bDescriptorType = USB_DTYPE_ENDPOINT,
  94. .bEndpointAddress = CDC_NTF_EP,
  95. .bmAttributes = USB_EPTYPE_INTERRUPT,
  96. .wMaxPacketSize = CDC_NTF_SZ,
  97. .bInterval = 0xFF,
  98. },
  99. .data = {
  100. .bLength = sizeof(struct usb_interface_descriptor),
  101. .bDescriptorType = USB_DTYPE_INTERFACE,
  102. .bInterfaceNumber = 1,
  103. .bAlternateSetting = 0,
  104. .bNumEndpoints = 2,
  105. .bInterfaceClass = USB_CLASS_CDC_DATA,
  106. .bInterfaceSubClass = USB_SUBCLASS_NONE,
  107. .bInterfaceProtocol = USB_PROTO_NONE,
  108. .iInterface = NO_DESCRIPTOR,
  109. },
  110. .data_eprx = {
  111. .bLength = sizeof(struct usb_endpoint_descriptor),
  112. .bDescriptorType = USB_DTYPE_ENDPOINT,
  113. .bEndpointAddress = CDC_RXD_EP,
  114. .bmAttributes = USB_EPTYPE_BULK,
  115. .wMaxPacketSize = CDC_DATA_SZ,
  116. .bInterval = 0x01,
  117. },
  118. .data_eptx = {
  119. .bLength = sizeof(struct usb_endpoint_descriptor),
  120. .bDescriptorType = USB_DTYPE_ENDPOINT,
  121. .bEndpointAddress = CDC_TXD_EP,
  122. .bmAttributes = USB_EPTYPE_BULK,
  123. .wMaxPacketSize = CDC_DATA_SZ,
  124. .bInterval = 0x01,
  125. },
  126. };
  127. static const struct usb_string_descriptor lang_desc = USB_ARRAY_DESC(USB_LANGID_ENG_US);
  128. static const struct usb_string_descriptor manuf_desc_en = USB_STRING_DESC("Open source USB stack for STM32");
  129. static const struct usb_string_descriptor prod_desc_en = USB_STRING_DESC("CDC Loopback demo");
  130. static const struct usb_string_descriptor *const dtable[] = {
  131. &lang_desc,
  132. &manuf_desc_en,
  133. &prod_desc_en,
  134. };
  135. usbd_device udev;
  136. uint32_t ubuf[0x20];
  137. uint8_t fifo[0x200];
  138. uint32_t fpos = 0;
  139. static struct usb_cdc_line_coding cdc_line = {
  140. .dwDTERate = 38400,
  141. .bCharFormat = USB_CDC_1_STOP_BITS,
  142. .bParityType = USB_CDC_NO_PARITY,
  143. .bDataBits = 8,
  144. };
  145. static usbd_respond cdc_getdesc (usbd_ctlreq *req, void **address, uint16_t *length) {
  146. const uint8_t dtype = req->wValue >> 8;
  147. const uint8_t dnumber = req->wValue & 0xFF;
  148. const void* desc;
  149. uint16_t len = 0;
  150. switch (dtype) {
  151. case USB_DTYPE_DEVICE:
  152. desc = &device_desc;
  153. break;
  154. case USB_DTYPE_CONFIGURATION:
  155. desc = &config_desc;
  156. len = sizeof(config_desc);
  157. break;
  158. case USB_DTYPE_STRING:
  159. if (dnumber < 3) {
  160. desc = dtable[dnumber];
  161. } else {
  162. return usbd_fail;
  163. }
  164. break;
  165. default:
  166. return usbd_fail;
  167. }
  168. if (len == 0) {
  169. len = ((struct usb_header_descriptor*)desc)->bLength;
  170. }
  171. *address = (void*)desc;
  172. *length = len;
  173. return usbd_ack;
  174. };
  175. static usbd_respond cdc_control(usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback) {
  176. if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) != (USB_REQ_INTERFACE | USB_REQ_CLASS)) return usbd_fail;
  177. switch (req->bRequest) {
  178. case USB_CDC_SET_CONTROL_LINE_STATE:
  179. return usbd_ack;
  180. case USB_CDC_SET_LINE_CODING:
  181. memmove( req->data, &cdc_line, sizeof(cdc_line));
  182. return usbd_ack;
  183. case USB_CDC_GET_LINE_CODING:
  184. dev->status.data_ptr = &cdc_line;
  185. dev->status.data_count = sizeof(cdc_line);
  186. return usbd_ack;
  187. default:
  188. return usbd_fail;
  189. }
  190. }
  191. static void cdc_rxonly (usbd_device *dev, uint8_t event, uint8_t ep) {
  192. usbd_ep_read(dev, ep, fifo, CDC_DATA_SZ);
  193. }
  194. static void cdc_txonly(usbd_device *dev, uint8_t event, uint8_t ep) {
  195. uint8_t _t = dev->driver->frame_no();
  196. memset(fifo, _t, CDC_DATA_SZ);
  197. usbd_ep_write(dev, ep, fifo, CDC_DATA_SZ);
  198. }
  199. static void cdc_loopback(usbd_device *dev, uint8_t event, uint8_t ep) {
  200. int _t;
  201. switch (event) {
  202. case usbd_evt_eptx:
  203. _t = usbd_ep_write(dev, CDC_TXD_EP, &fifo[0], (fpos < CDC_DATA_SZ) ? fpos : CDC_DATA_SZ);
  204. if (_t > 0) {
  205. memmove(&fifo[0], &fifo[_t], fpos - _t);
  206. fpos -= _t;
  207. }
  208. case usbd_evt_eprx:
  209. if (fpos < (sizeof(fifo) - CDC_DATA_SZ)) {
  210. _t = usbd_ep_read(dev, CDC_RXD_EP, &fifo[fpos], CDC_DATA_SZ);
  211. if (_t > 0) {
  212. fpos += _t;
  213. }
  214. }
  215. default:
  216. break;
  217. }
  218. }
  219. static usbd_respond cdc_setconf (usbd_device *dev, uint8_t cfg) {
  220. switch (cfg) {
  221. case 0:
  222. /* deconfiguring device */
  223. usbd_ep_deconfig(dev, CDC_NTF_EP);
  224. usbd_ep_deconfig(dev, CDC_TXD_EP);
  225. usbd_ep_deconfig(dev, CDC_RXD_EP);
  226. usbd_reg_endpoint(dev, CDC_RXD_EP, 0);
  227. usbd_reg_endpoint(dev, CDC_TXD_EP, 0);
  228. return usbd_ack;
  229. case 1:
  230. /* configuring device */
  231. usbd_ep_config(dev, CDC_RXD_EP, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, CDC_DATA_SZ);
  232. usbd_ep_config(dev, CDC_TXD_EP, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, CDC_DATA_SZ);
  233. usbd_ep_config(dev, CDC_NTF_EP, USB_EPTYPE_INTERRUPT, CDC_NTF_SZ);
  234. #if defined(CDC_LOOPBACK)
  235. usbd_reg_endpoint(dev, CDC_RXD_EP, cdc_loopback);
  236. usbd_reg_endpoint(dev, CDC_TXD_EP, cdc_loopback);
  237. #else
  238. usbd_reg_endpoint(dev, CDC_RXD_EP, cdc_rxonly);
  239. usbd_reg_endpoint(dev, CDC_TXD_EP, cdc_txonly);
  240. #endif
  241. usbd_ep_write(dev, CDC_TXD_EP, 0, 0);
  242. return usbd_ack;
  243. default:
  244. return usbd_fail;
  245. }
  246. }
  247. static void cdc_init_usbd(void) {
  248. usbd_init(&udev, &usbd_hw, CDC_EP0_SIZE, ubuf, sizeof(ubuf));
  249. usbd_reg_config(&udev, cdc_setconf);
  250. usbd_reg_control(&udev, cdc_control);
  251. usbd_reg_descr(&udev, cdc_getdesc);
  252. }
  253. static void cdc_init_rcc (void) {
  254. #if defined(STM32L0)
  255. _BST(RCC->APB1ENR, RCC_APB1ENR_PWREN);
  256. _BMD(PWR->CR, PWR_CR_VOS, PWR_CR_VOS_0);
  257. _WBC(PWR->CSR, PWR_CSR_VOSF);
  258. /* set FLASH latency to 1 */
  259. _BST(FLASH->ACR, FLASH_ACR_LATENCY);
  260. /* set clock at 32MHz PLL 6/3 HSI */
  261. _BMD(RCC->CFGR, RCC_CFGR_PLLDIV | RCC_CFGR_PLLMUL | RCC_CFGR_PLLSRC, RCC_CFGR_PLLDIV3 | RCC_CFGR_PLLMUL6);
  262. _BST(RCC->CR, RCC_CR_HSION);
  263. _WBS(RCC->CR, RCC_CR_HSIRDY);
  264. _BST(RCC->CR, RCC_CR_PLLON);
  265. _WBS(RCC->CR, RCC_CR_PLLRDY);
  266. /* switch clock to PLL */
  267. _BMD(RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_PLL);
  268. _WVL(RCC->CFGR, RCC_CFGR_SWS, RCC_CFGR_SWS_PLL);
  269. #elif defined(STM32L1)
  270. _BST(RCC->APB1ENR, RCC_APB1ENR_PWREN);
  271. _BMD(PWR->CR, PWR_CR_VOS, PWR_CR_VOS_0);
  272. _WBC(PWR->CSR, PWR_CSR_VOSF);
  273. /* set FLASH latency to 1 */
  274. _BST(FLASH->ACR, FLASH_ACR_ACC64);
  275. _BST(FLASH->ACR, FLASH_ACR_LATENCY);
  276. /* set clock at 32 MHz PLL 6/3 HSI */
  277. _BMD(RCC->CFGR, RCC_CFGR_PLLDIV | RCC_CFGR_PLLMUL | RCC_CFGR_PLLSRC, RCC_CFGR_PLLDIV3 | RCC_CFGR_PLLMUL6);
  278. _BST(RCC->CR, RCC_CR_HSION);
  279. _WBS(RCC->CR, RCC_CR_HSIRDY);
  280. _BST(RCC->CR, RCC_CR_PLLON);
  281. _WBS(RCC->CR, RCC_CR_PLLRDY);
  282. /* switch clock to PLL */
  283. _BMD(RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_PLL);
  284. _WVL(RCC->CFGR, RCC_CFGR_SWS, RCC_CFGR_SWS_PLL);
  285. #elif defined(STM32L4)
  286. _BST(RCC->APB1ENR1, RCC_APB1ENR1_PWREN);
  287. /* Set power Range 1 */
  288. _BMD(PWR->CR1, PWR_CR1_VOS, PWR_CR1_VOS_1);
  289. _WBC(PWR->SR2, PWR_SR2_VOSF);
  290. /* Adjust Flash latency */
  291. _BST(FLASH->ACR, FLASH_ACR_LATENCY);
  292. /* set clock 48Mhz MSI */
  293. _BMD(RCC->CR, RCC_CR_MSIRANGE, RCC_CR_MSIRANGE_11 | RCC_CR_MSIRGSEL);
  294. /* set MSI as 48MHz USB */
  295. _BMD(RCC->CCIPR, RCC_CCIPR_CLK48SEL, RCC_CCIPR_CLK48SEL_0 | RCC_CCIPR_CLK48SEL_1);
  296. /* enable GPIOA clock */
  297. _BST(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN);
  298. /* set GP11 and GP12 as USB data pins AF10 */
  299. _BST(GPIOA->AFR[1], (0x0A << 12) | (0x0A << 16));
  300. _BMD(GPIOA->MODER, (0x03 << 22) | (0x03 << 24), (0x02 << 22) | (0x02 << 24));
  301. #else
  302. #error Not supported
  303. #endif
  304. }
  305. void __libc_init_array(void) {
  306. }
  307. void SystemInit(void) {
  308. cdc_init_rcc();
  309. }
  310. void main(void) {
  311. cdc_init_usbd();
  312. usbd_control(&udev, usbd_cmd_enable);
  313. usbd_control(&udev, usbd_cmd_connect);
  314. while(1) {
  315. usbd_poll(&udev);
  316. }
  317. }