Teensy 4.1 core updated for C++20
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.

557 line
16KB

  1. #include "usb_dev.h"
  2. #define USB_DESC_LIST_DEFINE
  3. #include "usb_desc.h"
  4. #include <string.h>
  5. // Use this for access to endpoint 1 for debug
  6. // https://github.com/BrandonLWhite/Stellaris-LaunchPad-UsbDevBulk-AutoWinusbInstall
  7. // device mode, page 3155
  8. typedef struct endpoint_struct endpoint_t;
  9. //typedef struct transfer_struct transfer_t;
  10. struct endpoint_struct {
  11. uint32_t config;
  12. uint32_t current;
  13. uint32_t next;
  14. uint32_t status;
  15. uint32_t pointer0;
  16. uint32_t pointer1;
  17. uint32_t pointer2;
  18. uint32_t pointer3;
  19. uint32_t pointer4;
  20. uint32_t reserved;
  21. uint32_t setup0;
  22. uint32_t setup1;
  23. transfer_t *first_transfer;
  24. transfer_t *last_transfer;
  25. void (*callback_function)(transfer_t *completed_transfer);
  26. uint32_t unused1;
  27. };
  28. /*struct transfer_struct {
  29. uint32_t next;
  30. uint32_t status;
  31. uint32_t pointer0;
  32. uint32_t pointer1;
  33. uint32_t pointer2;
  34. uint32_t pointer3;
  35. uint32_t pointer4;
  36. uint32_t callback_param;
  37. };*/
  38. endpoint_t endpoint_queue_head[(NUM_ENDPOINTS+1)*2] __attribute__ ((used, aligned(4096)));
  39. transfer_t endpoint0_transfer_data __attribute__ ((used, aligned(32)));
  40. transfer_t endpoint0_transfer_ack __attribute__ ((used, aligned(32)));
  41. typedef union {
  42. struct {
  43. union {
  44. struct {
  45. uint8_t bmRequestType;
  46. uint8_t bRequest;
  47. };
  48. uint16_t wRequestAndType;
  49. };
  50. uint16_t wValue;
  51. uint16_t wIndex;
  52. uint16_t wLength;
  53. };
  54. struct {
  55. uint32_t word1;
  56. uint32_t word2;
  57. };
  58. uint64_t bothwords;
  59. } setup_t;
  60. static setup_t endpoint0_setupdata;
  61. static uint32_t endpoint0_notify_mask=0;
  62. static uint32_t endpointN_notify_mask=0;
  63. //static int reset_count=0;
  64. volatile uint8_t usb_configuration = 0;
  65. static uint8_t endpoint0_buffer[8];
  66. static void isr(void);
  67. static void endpoint0_setup(uint64_t setupdata);
  68. static void endpoint0_transmit(const void *data, uint32_t len, int notify);
  69. static void endpoint0_receive(void *data, uint32_t len, int notify);
  70. static void endpoint0_complete(void);
  71. void usb_init(void)
  72. {
  73. // TODO: make sure USB voltage regulator is running at full strength
  74. // assume PLL3 is already running - already done by usb_pll_start() in main.c
  75. CCM_CCGR6 |= CCM_CCGR6_USBOH3(CCM_CCGR_ON); // turn on clocks to USB peripheral
  76. // Before programming this register, the PHY clocks must be enabled in registers
  77. // USBPHYx_CTRLn and CCM_ANALOG_USBPHYx_PLL_480_CTRLn.
  78. //printf("USBPHY1_PWD=%08lX\r\n", USBPHY1_PWD);
  79. //printf("USBPHY1_TX=%08lX\r\n", USBPHY1_TX);
  80. //printf("USBPHY1_RX=%08lX\r\n", USBPHY1_RX);
  81. //printf("USBPHY1_CTRL=%08lX\r\n", USBPHY1_CTRL);
  82. //printf("USB1_USBMODE=%08lX\r\n", USB1_USBMODE);
  83. // turn on PLL3, wait for 480 MHz lock?
  84. // turn on CCM clock gates? CCGR6[CG0]
  85. if ((USBPHY1_PWD & (USBPHY_PWD_RXPWDRX | USBPHY_PWD_RXPWDDIFF | USBPHY_PWD_RXPWD1PT1
  86. | USBPHY_PWD_RXPWDENV | USBPHY_PWD_TXPWDV2I | USBPHY_PWD_TXPWDIBIAS
  87. | USBPHY_PWD_TXPWDFS)) || (USB1_USBMODE & USB_USBMODE_CM_MASK)) {
  88. // USB controller is turned on from previous use
  89. // reset needed to turn it off & start from clean slate
  90. USBPHY1_CTRL_SET = USBPHY_CTRL_SFTRST; // USBPHY1_CTRL page 3292
  91. USB1_USBCMD |= USB_USBCMD_RST; // reset controller
  92. int count=0;
  93. while (USB1_USBCMD & USB_USBCMD_RST) count++;
  94. NVIC_CLEAR_PENDING(IRQ_USB1);
  95. USBPHY1_CTRL_CLR = USBPHY_CTRL_SFTRST; // reset PHY
  96. //USB1_USBSTS = USB1_USBSTS; // TODO: is this needed?
  97. //printf("USB reset took %d loops\r\n", count);
  98. //delay(10);
  99. //print("\r\n");
  100. //printf("USBPHY1_PWD=%08lX\r\n", USBPHY1_PWD);
  101. //printf("USBPHY1_TX=%08lX\r\n", USBPHY1_TX);
  102. //printf("USBPHY1_RX=%08lX\r\n", USBPHY1_RX);
  103. //printf("USBPHY1_CTRL=%08lX\r\n", USBPHY1_CTRL);
  104. //printf("USB1_USBMODE=%08lX\r\n", USB1_USBMODE);
  105. //delay(500);
  106. }
  107. // Device Controller Initialization, page 3161
  108. // USBCMD pg 3216
  109. // USBSTS pg 3220
  110. // USBINTR pg 3224
  111. // DEVICEADDR pg 3227
  112. // ENDPTLISTADDR 3229
  113. // USBMODE pg 3244
  114. // ENDPTSETUPSTAT 3245
  115. // ENDPTPRIME pg 3246
  116. // ENDPTFLUSH pg 3247
  117. // ENDPTSTAT pg 3247
  118. // ENDPTCOMPLETE 3248
  119. // ENDPTCTRL0 pg 3249
  120. USBPHY1_CTRL_CLR = USBPHY_CTRL_CLKGATE;
  121. USBPHY1_PWD = 0;
  122. //printf("USBPHY1_PWD=%08lX\r\n", USBPHY1_PWD);
  123. //printf("USBPHY1_CTRL=%08lX\r\n", USBPHY1_CTRL);
  124. USB1_USBMODE = USB_USBMODE_CM(2) | USB_USBMODE_SLOM;
  125. memset(endpoint_queue_head, 0, sizeof(endpoint_queue_head));
  126. endpoint_queue_head[0].config = (64 << 16) | (1 << 15);
  127. endpoint_queue_head[1].config = (64 << 16);
  128. USB1_ENDPOINTLISTADDR = (uint32_t)&endpoint_queue_head;
  129. // Recommended: enable all device interrupts including: USBINT, USBERRINT,
  130. // Port Change Detect, USB Reset Received, DCSuspend.
  131. USB1_USBINTR = USB_USBINTR_UE | USB_USBINTR_UEE | /* USB_USBINTR_PCE | */
  132. USB_USBINTR_URE | USB_USBINTR_SLE;
  133. //_VectorsRam[IRQ_USB1+16] = &isr;
  134. attachInterruptVector(IRQ_USB1, &isr);
  135. NVIC_ENABLE_IRQ(IRQ_USB1);
  136. //printf("USB1_ENDPTCTRL0=%08lX\r\n", USB1_ENDPTCTRL0);
  137. //printf("USB1_ENDPTCTRL1=%08lX\r\n", USB1_ENDPTCTRL1);
  138. //printf("USB1_ENDPTCTRL2=%08lX\r\n", USB1_ENDPTCTRL2);
  139. //printf("USB1_ENDPTCTRL3=%08lX\r\n", USB1_ENDPTCTRL3);
  140. USB1_USBCMD |= USB_USBCMD_RS;
  141. }
  142. static void isr(void)
  143. {
  144. //print("*");
  145. // Port control in device mode is only used for
  146. // status port reset, suspend, and current connect status.
  147. uint32_t status = USB1_USBSTS;
  148. USB1_USBSTS = status;
  149. // USB_USBSTS_SLI - set to 1 when enters a suspend state from an active state
  150. // USB_USBSTS_SRI - set at start of frame
  151. // USB_USBSTS_SRI - set when USB reset detected
  152. if (status & USB_USBSTS_UI) {
  153. //print("data\r\n");
  154. uint32_t setupstatus = USB1_ENDPTSETUPSTAT;
  155. //printf("USB1_ENDPTSETUPSTAT=%X\r\n", setupstatus);
  156. while (setupstatus) {
  157. USB1_ENDPTSETUPSTAT = setupstatus;
  158. setup_t s;
  159. do {
  160. USB1_USBCMD |= USB_USBCMD_SUTW;
  161. s.word1 = endpoint_queue_head[0].setup0;
  162. s.word2 = endpoint_queue_head[0].setup1;
  163. } while (!(USB1_USBCMD & USB_USBCMD_SUTW));
  164. USB1_USBCMD &= ~USB_USBCMD_SUTW;
  165. //printf("setup %08lX %08lX\r\n", s.word1, s.word2);
  166. USB1_ENDPTFLUSH = (1<<16) | (1<<0); // page 3174
  167. while (USB1_ENDPTFLUSH & ((1<<16) | (1<<0))) ;
  168. endpoint0_notify_mask = 0;
  169. endpoint0_setup(s.bothwords);
  170. setupstatus = USB1_ENDPTSETUPSTAT; // page 3175
  171. }
  172. uint32_t completestatus = USB1_ENDPTCOMPLETE;
  173. if (completestatus) {
  174. USB1_ENDPTCOMPLETE = completestatus;
  175. //printf("USB1_ENDPTCOMPLETE=%lX\r\n", completestatus);
  176. if (completestatus & endpoint0_notify_mask) {
  177. endpoint0_notify_mask = 0;
  178. endpoint0_complete();
  179. }
  180. if (completestatus & endpointN_notify_mask) {
  181. // TODO: callback functions...
  182. }
  183. }
  184. }
  185. if (status & USB_USBSTS_URI) { // page 3164
  186. USB1_ENDPTSETUPSTAT = USB1_ENDPTSETUPSTAT; // Clear all setup token semaphores
  187. USB1_ENDPTCOMPLETE = USB1_ENDPTCOMPLETE; // Clear all the endpoint complete status
  188. while (USB1_ENDPTPRIME != 0) ; // Wait for any endpoint priming
  189. USB1_ENDPTFLUSH = 0xFFFFFFFF; // Cancel all endpoint primed status
  190. if ((USB1_PORTSC1 & USB_PORTSC1_PR)) {
  191. //print("reset\r\n");
  192. } else {
  193. // we took too long to respond :(
  194. // TODO; is this ever really a problem?
  195. //print("reset too slow\r\n");
  196. }
  197. // TODO: Free all allocated dTDs
  198. //if (++reset_count >= 3) {
  199. // shut off USB - easier to see results in protocol analyzer
  200. //USB1_USBCMD &= ~USB_USBCMD_RS;
  201. //print("shut off USB\r\n");
  202. //}
  203. }
  204. if (status & USB_USBSTS_PCI) {
  205. if (USB1_PORTSC1 & USB_PORTSC1_HSP) {
  206. //print("port at 480 Mbit\r\n");
  207. } else {
  208. //print("port at 12 Mbit\r\n");
  209. }
  210. }
  211. if (status & USB_USBSTS_SLI) { // page 3165
  212. //print("suspend\r\n");
  213. }
  214. if (status & USB_USBSTS_UEI) {
  215. //print("error\r\n");
  216. }
  217. }
  218. /*
  219. struct transfer_struct { // table 55-60, pg 3159
  220. uint32_t next;
  221. uint32_t status;
  222. uint32_t pointer0;
  223. uint32_t pointer1;
  224. uint32_t pointer2;
  225. uint32_t pointer3;
  226. uint32_t pointer4;
  227. uint32_t unused1;
  228. };
  229. transfer_t endpoint0_transfer_data __attribute__ ((aligned(32)));;
  230. transfer_t endpoint0_transfer_ack __attribute__ ((aligned(32)));;
  231. */
  232. static void endpoint0_setup(uint64_t setupdata)
  233. {
  234. setup_t setup;
  235. uint32_t datalen = 0;
  236. const usb_descriptor_list_t *list;
  237. setup.bothwords = setupdata;
  238. switch (setup.wRequestAndType) {
  239. case 0x0500: // SET_ADDRESS
  240. endpoint0_receive(NULL, 0, 0);
  241. USB1_DEVICEADDR = USB_DEVICEADDR_USBADR(setup.wValue) | USB_DEVICEADDR_USBADRA;
  242. return;
  243. case 0x0900: // SET_CONFIGURATION
  244. usb_configuration = setup.wValue;
  245. // configure all other endpoints
  246. volatile uint32_t *reg = &USB1_ENDPTCTRL1;
  247. const uint32_t *cfg = usb_endpoint_config_table;
  248. int i;
  249. for (i=0; i < NUM_ENDPOINTS; i++) {
  250. uint32_t n = *cfg++;
  251. *reg = n;
  252. // TODO: do the TRX & RXR bits self clear??
  253. uint32_t m = n & ~(USB_ENDPTCTRL_TXR | USB_ENDPTCTRL_RXR);
  254. *reg = m;
  255. //uint32_t p = *reg;
  256. //printf(" ep=%d: cfg=%08lX - %08lX - %08lX\r\n", i + 1, n, m, p);
  257. reg++;
  258. }
  259. // TODO: configure all queue heads with max packet length, zlt & mult
  260. endpoint_queue_head[CDC_ACM_ENDPOINT*2+1].config = (CDC_ACM_ENDPOINT << 16);
  261. endpoint_queue_head[CDC_RX_ENDPOINT*2+0].config = (CDC_RX_SIZE << 16) | (1 << 29);
  262. endpoint_queue_head[CDC_TX_ENDPOINT*2+1].config = (CDC_TX_SIZE << 16) | (1 << 29);
  263. // TODO: de-allocate any pending transfers?
  264. endpoint0_receive(NULL, 0, 0);
  265. return;
  266. case 0x0680: // GET_DESCRIPTOR
  267. case 0x0681:
  268. //printf("desc:\r\n"); // yay - sending device descriptor now works!!!!
  269. for (list = usb_descriptor_list; list->addr != NULL; list++) {
  270. if (setup.wValue == list->wValue && setup.wIndex == list->wIndex) {
  271. if ((setup.wValue >> 8) == 3) {
  272. // for string descriptors, use the descriptor's
  273. // length field, allowing runtime configured length.
  274. datalen = *(list->addr);
  275. } else {
  276. datalen = list->length;
  277. }
  278. if (datalen > setup.wLength) datalen = setup.wLength;
  279. endpoint0_transmit(list->addr, datalen, 0);
  280. return;
  281. }
  282. }
  283. break;
  284. case 0x2221: // CDC_SET_CONTROL_LINE_STATE
  285. //usb_cdc_line_rtsdtr_millis = systick_millis_count;
  286. //usb_cdc_line_rtsdtr = setup.wValue;
  287. case 0x2321: // CDC_SEND_BREAK
  288. endpoint0_receive(NULL, 0, 0);
  289. return;
  290. case 0x2021: // CDC_SET_LINE_CODING
  291. if (setup.wLength != 7) break;
  292. endpoint0_setupdata.bothwords = setupdata;
  293. endpoint0_receive(endpoint0_buffer, 7, 1);
  294. return;
  295. }
  296. USB1_ENDPTCTRL0 = 0x000010001; // stall
  297. }
  298. static void endpoint0_transmit(const void *data, uint32_t len, int notify)
  299. {
  300. //printf("tx %lu\r\n", len);
  301. if (len > 0) {
  302. // Executing A Transfer Descriptor, page 3182
  303. endpoint0_transfer_data.next = 1;
  304. endpoint0_transfer_data.status = (len << 16) | (1<<7);
  305. uint32_t addr = (uint32_t)data;
  306. endpoint0_transfer_data.pointer0 = addr; // format: table 55-60, pg 3159
  307. endpoint0_transfer_data.pointer1 = addr + 4096;
  308. endpoint0_transfer_data.pointer2 = addr + 8192;
  309. endpoint0_transfer_data.pointer3 = addr + 12288;
  310. endpoint0_transfer_data.pointer4 = addr + 16384;
  311. // Case 1: Link list is empty, page 3182
  312. endpoint_queue_head[1].next = (uint32_t)&endpoint0_transfer_data;
  313. endpoint_queue_head[1].status = 0;
  314. USB1_ENDPTPRIME |= (1<<16);
  315. while (USB1_ENDPTPRIME) ;
  316. }
  317. endpoint0_transfer_ack.next = 1;
  318. endpoint0_transfer_ack.status = (1<<7) | (notify ? (1 << 15) : 0);
  319. endpoint0_transfer_ack.pointer0 = 0;
  320. endpoint_queue_head[0].next = (uint32_t)&endpoint0_transfer_ack;
  321. endpoint_queue_head[0].status = 0;
  322. USB1_ENDPTPRIME |= (1<<0);
  323. endpoint0_notify_mask = (notify ? (1 << 0) : 0);
  324. while (USB1_ENDPTPRIME) ;
  325. }
  326. static void endpoint0_receive(void *data, uint32_t len, int notify)
  327. {
  328. //printf("rx %lu\r\n", len);
  329. if (len > 0) {
  330. // Executing A Transfer Descriptor, page 3182
  331. endpoint0_transfer_data.next = 1;
  332. endpoint0_transfer_data.status = (len << 16) | (1<<7);
  333. uint32_t addr = (uint32_t)data;
  334. endpoint0_transfer_data.pointer0 = addr; // format: table 55-60, pg 3159
  335. endpoint0_transfer_data.pointer1 = addr + 4096;
  336. endpoint0_transfer_data.pointer2 = addr + 8192;
  337. endpoint0_transfer_data.pointer3 = addr + 12288;
  338. endpoint0_transfer_data.pointer4 = addr + 16384;
  339. // Case 1: Link list is empty, page 3182
  340. endpoint_queue_head[0].next = (uint32_t)&endpoint0_transfer_data;
  341. endpoint_queue_head[0].status = 0;
  342. USB1_ENDPTPRIME |= (1<<0);
  343. while (USB1_ENDPTPRIME) ;
  344. }
  345. endpoint0_transfer_ack.next = 1;
  346. endpoint0_transfer_ack.status = (1<<7) | (notify ? (1 << 15) : 0);
  347. endpoint0_transfer_ack.pointer0 = 0;
  348. endpoint_queue_head[1].next = (uint32_t)&endpoint0_transfer_ack;
  349. endpoint_queue_head[1].status = 0;
  350. USB1_ENDPTPRIME |= (1<<16);
  351. endpoint0_notify_mask = (notify ? (1 << 16) : 0);
  352. while (USB1_ENDPTPRIME) ;
  353. }
  354. /*typedef union {
  355. struct {
  356. union {
  357. struct {
  358. uint8_t bmRequestType;
  359. uint8_t bRequest;
  360. };
  361. uint16_t wRequestAndType;
  362. };
  363. uint16_t wValue;
  364. uint16_t wIndex;
  365. uint16_t wLength;
  366. };
  367. struct {
  368. uint32_t word1;
  369. uint32_t word2;
  370. };
  371. uint64_t bothwords;
  372. } setup_t; */
  373. static void endpoint0_complete(void)
  374. {
  375. setup_t setup;
  376. setup.bothwords = endpoint0_setupdata.bothwords;
  377. //print("complete\r\n");
  378. #ifdef CDC_STATUS_INTERFACE
  379. if (setup.wRequestAndType == 0x2021 /*CDC_SET_LINE_CODING*/) {
  380. //memcpy(usb_cdc_line_coding, endpoint0_buffer, 7);
  381. //if (usb_cdc_line_coding[0] == 134) usb_reboot_timer = 15;
  382. }
  383. #endif
  384. }
  385. void usb_prepare_transfer(transfer_t *transfer, const void *data, uint32_t len, uint32_t param)
  386. {
  387. transfer->next = 1;
  388. transfer->status = (len << 16) | (1<<7);
  389. uint32_t addr = (uint32_t)data;
  390. transfer->pointer0 = addr;
  391. transfer->pointer1 = addr + 4096;
  392. transfer->pointer2 = addr + 8192;
  393. transfer->pointer3 = addr + 12288;
  394. transfer->pointer4 = addr + 16384;
  395. transfer->callback_param = param;
  396. }
  397. void usb_transmit(int endpoint_number, transfer_t *transfer)
  398. {
  399. // endpoint 0 reserved for control
  400. // endpoint 1 reserved for debug
  401. //printf("usb_transmit %d\r\n", endpoint_number);
  402. if (endpoint_number < 2 || endpoint_number > NUM_ENDPOINTS) return;
  403. endpoint_t *endpoint = &endpoint_queue_head[endpoint_number * 2 + 1];
  404. if (endpoint->callback_function) {
  405. transfer->status |= (1<<15);
  406. } else {
  407. transfer->status |= (1<<15);
  408. // remove all inactive transfers
  409. }
  410. uint32_t mask = 1 << (endpoint_number + 16);
  411. __disable_irq();
  412. #if 0
  413. if (endpoint->last_transfer) {
  414. if (!(endpoint->last_transfer->status & (1<<7))) {
  415. endpoint->last_transfer->next = (uint32_t)transfer;
  416. } else {
  417. // Case 2: Link list is not empty, page 3182
  418. endpoint->last_transfer->next = (uint32_t)transfer;
  419. if (USB1_ENDPTPRIME & mask) {
  420. endpoint->last_transfer = transfer;
  421. __enable_irq();
  422. printf(" case 2a\r\n");
  423. return;
  424. }
  425. uint32_t stat;
  426. uint32_t cmd = USB1_USBCMD;
  427. do {
  428. USB1_USBCMD = cmd | USB_USBCMD_ATDTW;
  429. stat = USB1_ENDPTSTATUS;
  430. } while (!(USB1_USBCMD & USB_USBCMD_ATDTW));
  431. USB1_USBCMD = cmd & ~USB_USBCMD_ATDTW;
  432. if (stat & mask) {
  433. endpoint->last_transfer = transfer;
  434. __enable_irq();
  435. printf(" case 2b\r\n");
  436. return;
  437. }
  438. }
  439. } else {
  440. endpoint->first_transfer = transfer;
  441. }
  442. endpoint->last_transfer = transfer;
  443. #endif
  444. // Case 1: Link list is empty, page 3182
  445. endpoint->next = (uint32_t)transfer;
  446. endpoint->status = 0;
  447. USB1_ENDPTPRIME |= mask;
  448. while (USB1_ENDPTPRIME & mask) ;
  449. __enable_irq();
  450. //printf(" case 1\r\n");
  451. // ENDPTPRIME - momentarily set by hardware during hardware re-priming
  452. // operations when a dTD is retired, and the dQH is updated.
  453. // ENDPTSTAT - Transmit Buffer Ready - set to one by the hardware as a
  454. // response to receiving a command from a corresponding bit
  455. // in the ENDPTPRIME register. . Buffer ready is cleared by
  456. // USB reset, by the USB DMA system, or through the ENDPTFLUSH
  457. // register. (so 0=buffer ready, 1=buffer primed for transmit)
  458. }
  459. /*struct endpoint_struct {
  460. uint32_t config;
  461. uint32_t current;
  462. uint32_t next;
  463. uint32_t status;
  464. uint32_t pointer0;
  465. uint32_t pointer1;
  466. uint32_t pointer2;
  467. uint32_t pointer3;
  468. uint32_t pointer4;
  469. uint32_t reserved;
  470. uint32_t setup0;
  471. uint32_t setup1;
  472. transfer_t *first_transfer;
  473. transfer_t *last_transfer;
  474. void (*callback_function)(transfer_t *completed_transfer);
  475. uint32_t unused1;
  476. };*/