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.

724 lines
20KB

  1. #include "usb_dev.h"
  2. #define USB_DESC_LIST_DEFINE
  3. #include "usb_desc.h"
  4. #include "usb_serial.h"
  5. #include "core_pins.h" // for delay()
  6. #include <string.h>
  7. #include "debug/printf.h"
  8. // device mode, page 3155
  9. typedef struct endpoint_struct endpoint_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 uint8_t usb_reboot_timer = 0;
  67. static void isr(void);
  68. static void endpoint0_setup(uint64_t setupdata);
  69. static void endpoint0_transmit(const void *data, uint32_t len, int notify);
  70. static void endpoint0_receive(void *data, uint32_t len, int notify);
  71. static void endpoint0_complete(void);
  72. static void run_callbacks(endpoint_t *ep);
  73. static void run_callbacks(endpoint_t *ep)
  74. {
  75. transfer_t *t, *next;
  76. printf("run_callbacks\n");
  77. t = ep->first_transfer;
  78. while (t && (uint32_t)t != 1) {
  79. if (!(t->status & (1<<7))) {
  80. // transfer not active anymore
  81. next = (transfer_t *)t->next;
  82. ep->callback_function(t);
  83. } else {
  84. // transfer still active
  85. ep->first_transfer = t;
  86. return;
  87. }
  88. t = next;
  89. }
  90. // all transfers completed
  91. ep->first_transfer = NULL;
  92. ep->last_transfer = NULL;
  93. }
  94. __attribute__((section(".progmem")))
  95. void usb_init(void)
  96. {
  97. // TODO: only enable when VBUS detected
  98. // TODO: return to low power mode when VBUS removed
  99. // TODO: protect PMU access with MPU
  100. PMU_REG_3P0 = PMU_REG_3P0_OUTPUT_TRG(0x0F) | PMU_REG_3P0_BO_OFFSET(6)
  101. | PMU_REG_3P0_ENABLE_LINREG;
  102. usb_init_serialnumber();
  103. // assume PLL3 is already running - already done by usb_pll_start() in main.c
  104. CCM_CCGR6 |= CCM_CCGR6_USBOH3(CCM_CCGR_ON); // turn on clocks to USB peripheral
  105. // Before programming this register, the PHY clocks must be enabled in registers
  106. // USBPHYx_CTRLn and CCM_ANALOG_USBPHYx_PLL_480_CTRLn.
  107. //printf("USBPHY1_PWD=%08lX\n", USBPHY1_PWD);
  108. //printf("USBPHY1_TX=%08lX\n", USBPHY1_TX);
  109. //printf("USBPHY1_RX=%08lX\n", USBPHY1_RX);
  110. //printf("USBPHY1_CTRL=%08lX\n", USBPHY1_CTRL);
  111. //printf("USB1_USBMODE=%08lX\n", USB1_USBMODE);
  112. // turn on PLL3, wait for 480 MHz lock?
  113. // turn on CCM clock gates? CCGR6[CG0]
  114. #if 1
  115. if ((USBPHY1_PWD & (USBPHY_PWD_RXPWDRX | USBPHY_PWD_RXPWDDIFF | USBPHY_PWD_RXPWD1PT1
  116. | USBPHY_PWD_RXPWDENV | USBPHY_PWD_TXPWDV2I | USBPHY_PWD_TXPWDIBIAS
  117. | USBPHY_PWD_TXPWDFS)) || (USB1_USBMODE & USB_USBMODE_CM_MASK)) {
  118. // USB controller is turned on from previous use
  119. // reset needed to turn it off & start from clean slate
  120. USBPHY1_CTRL_SET = USBPHY_CTRL_SFTRST; // USBPHY1_CTRL page 3292
  121. USB1_USBCMD |= USB_USBCMD_RST; // reset controller
  122. int count=0;
  123. while (USB1_USBCMD & USB_USBCMD_RST) count++;
  124. NVIC_CLEAR_PENDING(IRQ_USB1);
  125. USBPHY1_CTRL_CLR = USBPHY_CTRL_SFTRST; // reset PHY
  126. //USB1_USBSTS = USB1_USBSTS; // TODO: is this needed?
  127. printf("USB reset took %d loops\n", count);
  128. //delay(10);
  129. //printf("\n");
  130. //printf("USBPHY1_PWD=%08lX\n", USBPHY1_PWD);
  131. //printf("USBPHY1_TX=%08lX\n", USBPHY1_TX);
  132. //printf("USBPHY1_RX=%08lX\n", USBPHY1_RX);
  133. //printf("USBPHY1_CTRL=%08lX\n", USBPHY1_CTRL);
  134. //printf("USB1_USBMODE=%08lX\n", USB1_USBMODE);
  135. delay(25);
  136. }
  137. #endif
  138. // Device Controller Initialization, page 3161
  139. // USBCMD pg 3216
  140. // USBSTS pg 3220
  141. // USBINTR pg 3224
  142. // DEVICEADDR pg 3227
  143. // ENDPTLISTADDR 3229
  144. // USBMODE pg 3244
  145. // ENDPTSETUPSTAT 3245
  146. // ENDPTPRIME pg 3246
  147. // ENDPTFLUSH pg 3247
  148. // ENDPTSTAT pg 3247
  149. // ENDPTCOMPLETE 3248
  150. // ENDPTCTRL0 pg 3249
  151. USBPHY1_CTRL_CLR = USBPHY_CTRL_CLKGATE;
  152. USBPHY1_PWD = 0;
  153. //printf("USBPHY1_PWD=%08lX\n", USBPHY1_PWD);
  154. //printf("USBPHY1_CTRL=%08lX\n", USBPHY1_CTRL);
  155. USB1_USBMODE = USB_USBMODE_CM(2) | USB_USBMODE_SLOM;
  156. memset(endpoint_queue_head, 0, sizeof(endpoint_queue_head));
  157. endpoint_queue_head[0].config = (64 << 16) | (1 << 15);
  158. endpoint_queue_head[1].config = (64 << 16);
  159. USB1_ENDPOINTLISTADDR = (uint32_t)&endpoint_queue_head;
  160. // Recommended: enable all device interrupts including: USBINT, USBERRINT,
  161. // Port Change Detect, USB Reset Received, DCSuspend.
  162. USB1_USBINTR = USB_USBINTR_UE | USB_USBINTR_UEE | /* USB_USBINTR_PCE | */
  163. USB_USBINTR_URE | USB_USBINTR_SLE;
  164. //_VectorsRam[IRQ_USB1+16] = &isr;
  165. attachInterruptVector(IRQ_USB1, &isr);
  166. NVIC_ENABLE_IRQ(IRQ_USB1);
  167. //printf("USB1_ENDPTCTRL0=%08lX\n", USB1_ENDPTCTRL0);
  168. //printf("USB1_ENDPTCTRL1=%08lX\n", USB1_ENDPTCTRL1);
  169. //printf("USB1_ENDPTCTRL2=%08lX\n", USB1_ENDPTCTRL2);
  170. //printf("USB1_ENDPTCTRL3=%08lX\n", USB1_ENDPTCTRL3);
  171. USB1_USBCMD |= USB_USBCMD_RS;
  172. }
  173. static void isr(void)
  174. {
  175. //printf("*");
  176. // Port control in device mode is only used for
  177. // status port reset, suspend, and current connect status.
  178. uint32_t status = USB1_USBSTS;
  179. USB1_USBSTS = status;
  180. // USB_USBSTS_SLI - set to 1 when enters a suspend state from an active state
  181. // USB_USBSTS_SRI - set at start of frame
  182. // USB_USBSTS_SRI - set when USB reset detected
  183. if (status & USB_USBSTS_UI) {
  184. //printf("data\n");
  185. uint32_t setupstatus = USB1_ENDPTSETUPSTAT;
  186. //printf("USB1_ENDPTSETUPSTAT=%X\n", setupstatus);
  187. while (setupstatus) {
  188. USB1_ENDPTSETUPSTAT = setupstatus;
  189. setup_t s;
  190. do {
  191. USB1_USBCMD |= USB_USBCMD_SUTW;
  192. s.word1 = endpoint_queue_head[0].setup0;
  193. s.word2 = endpoint_queue_head[0].setup1;
  194. } while (!(USB1_USBCMD & USB_USBCMD_SUTW));
  195. USB1_USBCMD &= ~USB_USBCMD_SUTW;
  196. //printf("setup %08lX %08lX\n", s.word1, s.word2);
  197. USB1_ENDPTFLUSH = (1<<16) | (1<<0); // page 3174
  198. while (USB1_ENDPTFLUSH & ((1<<16) | (1<<0))) ;
  199. endpoint0_notify_mask = 0;
  200. endpoint0_setup(s.bothwords);
  201. setupstatus = USB1_ENDPTSETUPSTAT; // page 3175
  202. }
  203. uint32_t completestatus = USB1_ENDPTCOMPLETE;
  204. if (completestatus) {
  205. USB1_ENDPTCOMPLETE = completestatus;
  206. //printf("USB1_ENDPTCOMPLETE=%lX\n", completestatus);
  207. if (completestatus & endpoint0_notify_mask) {
  208. endpoint0_notify_mask = 0;
  209. endpoint0_complete();
  210. }
  211. completestatus &= endpointN_notify_mask;
  212. if (completestatus) {
  213. int i; // TODO: optimize with __builtin_ctz()
  214. for (i=2; i < NUM_ENDPOINTS; i++) {
  215. if (completestatus & (1 << i)) { // receive
  216. run_callbacks(endpoint_queue_head + i * 2);
  217. }
  218. if (completestatus & (1 << (i + 16))) { // transmit
  219. run_callbacks(endpoint_queue_head + i * 2 + 1);
  220. }
  221. }
  222. }
  223. }
  224. }
  225. if (status & USB_USBSTS_URI) { // page 3164
  226. USB1_ENDPTSETUPSTAT = USB1_ENDPTSETUPSTAT; // Clear all setup token semaphores
  227. USB1_ENDPTCOMPLETE = USB1_ENDPTCOMPLETE; // Clear all the endpoint complete status
  228. while (USB1_ENDPTPRIME != 0) ; // Wait for any endpoint priming
  229. USB1_ENDPTFLUSH = 0xFFFFFFFF; // Cancel all endpoint primed status
  230. if ((USB1_PORTSC1 & USB_PORTSC1_PR)) {
  231. //printf("reset\n");
  232. } else {
  233. // we took too long to respond :(
  234. // TODO; is this ever really a problem?
  235. //printf("reset too slow\n");
  236. }
  237. #if defined(CDC_STATUS_INTERFACE) && defined(CDC_DATA_INTERFACE)
  238. usb_serial_reset();
  239. #endif
  240. endpointN_notify_mask = 0;
  241. // TODO: Free all allocated dTDs
  242. //if (++reset_count >= 3) {
  243. // shut off USB - easier to see results in protocol analyzer
  244. //USB1_USBCMD &= ~USB_USBCMD_RS;
  245. //printf("shut off USB\n");
  246. //}
  247. }
  248. if (status & USB_USBSTS_PCI) {
  249. if (USB1_PORTSC1 & USB_PORTSC1_HSP) {
  250. //printf("port at 480 Mbit\n");
  251. } else {
  252. //printf("port at 12 Mbit\n");
  253. }
  254. }
  255. if (status & USB_USBSTS_SLI) { // page 3165
  256. //printf("suspend\n");
  257. }
  258. if (status & USB_USBSTS_UEI) {
  259. //printf("error\n");
  260. }
  261. if ((USB1_USBINTR & USB_USBINTR_SRE) && (status & USB_USBSTS_SRI)) {
  262. printf("sof %d\n", usb_reboot_timer);
  263. if (usb_reboot_timer) {
  264. if (--usb_reboot_timer == 0) {
  265. asm("bkpt #251"); // run bootloader
  266. }
  267. } else {
  268. // turn off the SOF interrupt if nothing using it
  269. USB1_USBINTR &= ~USB_USBINTR_SRE;
  270. }
  271. }
  272. }
  273. /*
  274. struct transfer_struct { // table 55-60, pg 3159
  275. uint32_t next;
  276. uint32_t status;
  277. uint32_t pointer0;
  278. uint32_t pointer1;
  279. uint32_t pointer2;
  280. uint32_t pointer3;
  281. uint32_t pointer4;
  282. uint32_t unused1;
  283. };
  284. transfer_t endpoint0_transfer_data __attribute__ ((aligned(32)));;
  285. transfer_t endpoint0_transfer_ack __attribute__ ((aligned(32)));;
  286. */
  287. static void endpoint0_setup(uint64_t setupdata)
  288. {
  289. setup_t setup;
  290. uint32_t datalen = 0;
  291. const usb_descriptor_list_t *list;
  292. setup.bothwords = setupdata;
  293. switch (setup.wRequestAndType) {
  294. case 0x0500: // SET_ADDRESS
  295. endpoint0_receive(NULL, 0, 0);
  296. USB1_DEVICEADDR = USB_DEVICEADDR_USBADR(setup.wValue) | USB_DEVICEADDR_USBADRA;
  297. return;
  298. case 0x0900: // SET_CONFIGURATION
  299. usb_configuration = setup.wValue;
  300. // configure all other endpoints
  301. volatile uint32_t *reg = &USB1_ENDPTCTRL1;
  302. const uint32_t *cfg = usb_endpoint_config_table;
  303. int i;
  304. for (i=0; i < NUM_ENDPOINTS; i++) {
  305. uint32_t n = *cfg++;
  306. *reg = n;
  307. // TODO: do the TRX & RXR bits self clear??
  308. uint32_t m = n & ~(USB_ENDPTCTRL_TXR | USB_ENDPTCTRL_RXR);
  309. *reg = m;
  310. //uint32_t p = *reg;
  311. //printf(" ep=%d: cfg=%08lX - %08lX - %08lX\n", i + 1, n, m, p);
  312. reg++;
  313. }
  314. #if defined(CDC_STATUS_INTERFACE) && defined(CDC_DATA_INTERFACE)
  315. usb_serial_configure();
  316. #endif
  317. endpoint0_receive(NULL, 0, 0);
  318. return;
  319. case 0x0680: // GET_DESCRIPTOR
  320. case 0x0681:
  321. //printf("desc:\n"); // yay - sending device descriptor now works!!!!
  322. for (list = usb_descriptor_list; list->addr != NULL; list++) {
  323. if (setup.wValue == list->wValue && setup.wIndex == list->wIndex) {
  324. if ((setup.wValue >> 8) == 3) {
  325. // for string descriptors, use the descriptor's
  326. // length field, allowing runtime configured length.
  327. datalen = *(list->addr);
  328. } else {
  329. datalen = list->length;
  330. }
  331. if (datalen > setup.wLength) datalen = setup.wLength;
  332. endpoint0_transmit(list->addr, datalen, 0);
  333. return;
  334. }
  335. }
  336. break;
  337. case 0x2221: // CDC_SET_CONTROL_LINE_STATE
  338. usb_cdc_line_rtsdtr_millis = systick_millis_count;
  339. usb_cdc_line_rtsdtr = setup.wValue;
  340. case 0x2321: // CDC_SEND_BREAK
  341. endpoint0_receive(NULL, 0, 0);
  342. return;
  343. case 0x2021: // CDC_SET_LINE_CODING
  344. if (setup.wLength != 7) break;
  345. endpoint0_setupdata.bothwords = setupdata;
  346. endpoint0_receive(endpoint0_buffer, 7, 1);
  347. return;
  348. }
  349. USB1_ENDPTCTRL0 = 0x000010001; // stall
  350. }
  351. static void endpoint0_transmit(const void *data, uint32_t len, int notify)
  352. {
  353. //printf("tx %lu\n", len);
  354. if (len > 0) {
  355. // Executing A Transfer Descriptor, page 3182
  356. endpoint0_transfer_data.next = 1;
  357. endpoint0_transfer_data.status = (len << 16) | (1<<7);
  358. uint32_t addr = (uint32_t)data;
  359. endpoint0_transfer_data.pointer0 = addr; // format: table 55-60, pg 3159
  360. endpoint0_transfer_data.pointer1 = addr + 4096;
  361. endpoint0_transfer_data.pointer2 = addr + 8192;
  362. endpoint0_transfer_data.pointer3 = addr + 12288;
  363. endpoint0_transfer_data.pointer4 = addr + 16384;
  364. // Case 1: Link list is empty, page 3182
  365. endpoint_queue_head[1].next = (uint32_t)&endpoint0_transfer_data;
  366. endpoint_queue_head[1].status = 0;
  367. USB1_ENDPTPRIME |= (1<<16);
  368. while (USB1_ENDPTPRIME) ;
  369. }
  370. endpoint0_transfer_ack.next = 1;
  371. endpoint0_transfer_ack.status = (1<<7) | (notify ? (1 << 15) : 0);
  372. endpoint0_transfer_ack.pointer0 = 0;
  373. endpoint_queue_head[0].next = (uint32_t)&endpoint0_transfer_ack;
  374. endpoint_queue_head[0].status = 0;
  375. USB1_ENDPTPRIME |= (1<<0);
  376. endpoint0_notify_mask = (notify ? (1 << 0) : 0);
  377. while (USB1_ENDPTPRIME) ;
  378. }
  379. static void endpoint0_receive(void *data, uint32_t len, int notify)
  380. {
  381. //printf("rx %lu\n", len);
  382. if (len > 0) {
  383. // Executing A Transfer Descriptor, page 3182
  384. endpoint0_transfer_data.next = 1;
  385. endpoint0_transfer_data.status = (len << 16) | (1<<7);
  386. uint32_t addr = (uint32_t)data;
  387. endpoint0_transfer_data.pointer0 = addr; // format: table 55-60, pg 3159
  388. endpoint0_transfer_data.pointer1 = addr + 4096;
  389. endpoint0_transfer_data.pointer2 = addr + 8192;
  390. endpoint0_transfer_data.pointer3 = addr + 12288;
  391. endpoint0_transfer_data.pointer4 = addr + 16384;
  392. // Case 1: Link list is empty, page 3182
  393. endpoint_queue_head[0].next = (uint32_t)&endpoint0_transfer_data;
  394. endpoint_queue_head[0].status = 0;
  395. USB1_ENDPTPRIME |= (1<<0);
  396. while (USB1_ENDPTPRIME) ;
  397. }
  398. endpoint0_transfer_ack.next = 1;
  399. endpoint0_transfer_ack.status = (1<<7) | (notify ? (1 << 15) : 0);
  400. endpoint0_transfer_ack.pointer0 = 0;
  401. endpoint_queue_head[1].next = (uint32_t)&endpoint0_transfer_ack;
  402. endpoint_queue_head[1].status = 0;
  403. USB1_ENDPTPRIME |= (1<<16);
  404. endpoint0_notify_mask = (notify ? (1 << 16) : 0);
  405. while (USB1_ENDPTPRIME) ;
  406. }
  407. /*typedef union {
  408. struct {
  409. union {
  410. struct {
  411. uint8_t bmRequestType;
  412. uint8_t bRequest;
  413. };
  414. uint16_t wRequestAndType;
  415. };
  416. uint16_t wValue;
  417. uint16_t wIndex;
  418. uint16_t wLength;
  419. };
  420. struct {
  421. uint32_t word1;
  422. uint32_t word2;
  423. };
  424. uint64_t bothwords;
  425. } setup_t; */
  426. static void endpoint0_complete(void)
  427. {
  428. setup_t setup;
  429. setup.bothwords = endpoint0_setupdata.bothwords;
  430. //printf("complete\n");
  431. #ifdef CDC_STATUS_INTERFACE
  432. if (setup.wRequestAndType == 0x2021 /*CDC_SET_LINE_CODING*/) {
  433. memcpy(usb_cdc_line_coding, endpoint0_buffer, 7);
  434. printf("usb_cdc_line_coding, baud=%u\n", usb_cdc_line_coding[0]);
  435. if (usb_cdc_line_coding[0] == 134) {
  436. USB1_USBINTR |= USB_USBINTR_SRE;
  437. usb_reboot_timer = 80; // TODO: 10 if only 12 Mbit/sec
  438. }
  439. }
  440. #endif
  441. }
  442. static void usb_endpoint_config(endpoint_t *qh, uint32_t config, void (*callback)(transfer_t *))
  443. {
  444. memset(qh, 0, sizeof(endpoint_t));
  445. qh->config = config;
  446. qh->callback_function = callback;
  447. }
  448. void usb_config_rx(uint32_t ep, uint32_t packet_size, int do_zlp, void (*cb)(transfer_t *))
  449. {
  450. uint32_t config = (packet_size << 16) | (do_zlp ? 0 : (1 << 29));
  451. if (ep < 2 || ep > NUM_ENDPOINTS) return;
  452. usb_endpoint_config(endpoint_queue_head + ep * 2, config, cb);
  453. if (cb) endpointN_notify_mask |= (1 << ep);
  454. }
  455. void usb_config_tx(uint32_t ep, uint32_t packet_size, int do_zlp, void (*cb)(transfer_t *))
  456. {
  457. uint32_t config = (packet_size << 16) | (do_zlp ? 0 : (1 << 29));
  458. if (ep < 2 || ep > NUM_ENDPOINTS) return;
  459. usb_endpoint_config(endpoint_queue_head + ep * 2 + 1, config, cb);
  460. if (cb) endpointN_notify_mask |= (1 << (ep + 16));
  461. }
  462. void usb_prepare_transfer(transfer_t *transfer, const void *data, uint32_t len, uint32_t param)
  463. {
  464. transfer->next = 1;
  465. transfer->status = (len << 16) | (1<<7);
  466. uint32_t addr = (uint32_t)data;
  467. transfer->pointer0 = addr;
  468. transfer->pointer1 = addr + 4096;
  469. transfer->pointer2 = addr + 8192;
  470. transfer->pointer3 = addr + 12288;
  471. transfer->pointer4 = addr + 16384;
  472. transfer->callback_param = param;
  473. }
  474. static void schedule_transfer(endpoint_t *endpoint, uint32_t epmask, transfer_t *transfer)
  475. {
  476. if (endpoint->callback_function) {
  477. transfer->status |= (1<<15);
  478. } else {
  479. //transfer->status |= (1<<15);
  480. // remove all inactive transfers
  481. }
  482. __disable_irq();
  483. #if 0
  484. if (endpoint->last_transfer) {
  485. if (!(endpoint->last_transfer->status & (1<<7))) {
  486. endpoint->last_transfer->next = (uint32_t)transfer;
  487. } else {
  488. // Case 2: Link list is not empty, page 3182
  489. endpoint->last_transfer->next = (uint32_t)transfer;
  490. if (USB1_ENDPTPRIME & epmask) {
  491. endpoint->last_transfer = transfer;
  492. __enable_irq();
  493. printf(" case 2a\n");
  494. return;
  495. }
  496. uint32_t stat;
  497. uint32_t cmd = USB1_USBCMD;
  498. do {
  499. USB1_USBCMD = cmd | USB_USBCMD_ATDTW;
  500. stat = USB1_ENDPTSTATUS;
  501. } while (!(USB1_USBCMD & USB_USBCMD_ATDTW));
  502. USB1_USBCMD = cmd & ~USB_USBCMD_ATDTW;
  503. if (stat & epmask) {
  504. endpoint->last_transfer = transfer;
  505. __enable_irq();
  506. printf(" case 2b\n");
  507. return;
  508. }
  509. }
  510. } else {
  511. endpoint->first_transfer = transfer;
  512. }
  513. endpoint->last_transfer = transfer;
  514. #endif
  515. // Case 1: Link list is empty, page 3182
  516. endpoint->next = (uint32_t)transfer;
  517. endpoint->status = 0;
  518. endpoint->first_transfer = (uint32_t)transfer;
  519. endpoint->last_transfer = (uint32_t)transfer;
  520. USB1_ENDPTPRIME |= epmask;
  521. while (USB1_ENDPTPRIME & epmask) ;
  522. __enable_irq();
  523. //printf(" case 1\n");
  524. // ENDPTPRIME - momentarily set by hardware during hardware re-priming
  525. // operations when a dTD is retired, and the dQH is updated.
  526. // ENDPTSTAT - Transmit Buffer Ready - set to one by the hardware as a
  527. // response to receiving a command from a corresponding bit
  528. // in the ENDPTPRIME register. . Buffer ready is cleared by
  529. // USB reset, by the USB DMA system, or through the ENDPTFLUSH
  530. // register. (so 0=buffer ready, 1=buffer primed for transmit)
  531. }
  532. void usb_transmit(int endpoint_number, transfer_t *transfer)
  533. {
  534. if (endpoint_number < 2 || endpoint_number > NUM_ENDPOINTS) return;
  535. endpoint_t *endpoint = endpoint_queue_head + endpoint_number * 2 + 1;
  536. uint32_t mask = 1 << (endpoint_number + 16);
  537. schedule_transfer(endpoint, mask, transfer);
  538. }
  539. void usb_receive(int endpoint_number, transfer_t *transfer)
  540. {
  541. if (endpoint_number < 2 || endpoint_number > NUM_ENDPOINTS) return;
  542. endpoint_t *endpoint = endpoint_queue_head + endpoint_number * 2;
  543. uint32_t mask = 1 << endpoint_number;
  544. schedule_transfer(endpoint, mask, transfer);
  545. }
  546. #if 0
  547. void usb_transmit(int endpoint_number, transfer_t *transfer)
  548. {
  549. // endpoint 0 reserved for control
  550. // endpoint 1 reserved for debug
  551. //printf("usb_transmit %d\n", endpoint_number);
  552. if (endpoint_number < 2 || endpoint_number > NUM_ENDPOINTS) return;
  553. endpoint_t *endpoint = &endpoint_queue_head[endpoint_number * 2 + 1];
  554. if (endpoint->callback_function) {
  555. transfer->status |= (1<<15);
  556. } else {
  557. //transfer->status |= (1<<15);
  558. // remove all inactive transfers
  559. }
  560. uint32_t mask = 1 << (endpoint_number + 16);
  561. __disable_irq();
  562. #if 0
  563. if (endpoint->last_transfer) {
  564. if (!(endpoint->last_transfer->status & (1<<7))) {
  565. endpoint->last_transfer->next = (uint32_t)transfer;
  566. } else {
  567. // Case 2: Link list is not empty, page 3182
  568. endpoint->last_transfer->next = (uint32_t)transfer;
  569. if (USB1_ENDPTPRIME & mask) {
  570. endpoint->last_transfer = transfer;
  571. __enable_irq();
  572. printf(" case 2a\n");
  573. return;
  574. }
  575. uint32_t stat;
  576. uint32_t cmd = USB1_USBCMD;
  577. do {
  578. USB1_USBCMD = cmd | USB_USBCMD_ATDTW;
  579. stat = USB1_ENDPTSTATUS;
  580. } while (!(USB1_USBCMD & USB_USBCMD_ATDTW));
  581. USB1_USBCMD = cmd & ~USB_USBCMD_ATDTW;
  582. if (stat & mask) {
  583. endpoint->last_transfer = transfer;
  584. __enable_irq();
  585. printf(" case 2b\n");
  586. return;
  587. }
  588. }
  589. } else {
  590. endpoint->first_transfer = transfer;
  591. }
  592. endpoint->last_transfer = transfer;
  593. #endif
  594. // Case 1: Link list is empty, page 3182
  595. endpoint->next = (uint32_t)transfer;
  596. endpoint->status = 0;
  597. USB1_ENDPTPRIME |= mask;
  598. while (USB1_ENDPTPRIME & mask) ;
  599. __enable_irq();
  600. //printf(" case 1\n");
  601. // ENDPTPRIME - momentarily set by hardware during hardware re-priming
  602. // operations when a dTD is retired, and the dQH is updated.
  603. // ENDPTSTAT - Transmit Buffer Ready - set to one by the hardware as a
  604. // response to receiving a command from a corresponding bit
  605. // in the ENDPTPRIME register. . Buffer ready is cleared by
  606. // USB reset, by the USB DMA system, or through the ENDPTFLUSH
  607. // register. (so 0=buffer ready, 1=buffer primed for transmit)
  608. }
  609. #endif
  610. /*struct endpoint_struct {
  611. uint32_t config;
  612. uint32_t current;
  613. uint32_t next;
  614. uint32_t status;
  615. uint32_t pointer0;
  616. uint32_t pointer1;
  617. uint32_t pointer2;
  618. uint32_t pointer3;
  619. uint32_t pointer4;
  620. uint32_t reserved;
  621. uint32_t setup0;
  622. uint32_t setup1;
  623. transfer_t *first_transfer;
  624. transfer_t *last_transfer;
  625. void (*callback_function)(transfer_t *completed_transfer);
  626. uint32_t unused1;
  627. };*/