PageRenderTime 69ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/cpu/cc2538/usb/usb-arch.c

https://bitbucket.org/homadeus/contiki
C | 1256 lines | 931 code | 173 blank | 152 comment | 165 complexity | 912e0237f48163ecb3ce4628f7d9aaae MD5 | raw file
  1. /*
  2. * Copyright (c) 2012, Philippe Retornaz
  3. * Copyright (c) 2012, EPFL STI IMT LSRO1 -- Mobots group
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, 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. *
  14. * 3. Neither the name of the copyright holder nor the names of its
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  21. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  22. * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  23. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  25. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  27. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  29. * OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. /**
  32. * \addtogroup cc2538-usb
  33. * @{
  34. *
  35. * \file
  36. * Arch-specific routines for the cc2538 USB controller. Heavily based on
  37. * the cc2530 driver written by Philippe Retornaz
  38. */
  39. #include "contiki.h"
  40. #include "energest.h"
  41. #include "usb-arch.h"
  42. #include "usb-api.h"
  43. #include "dev/usb-regs.h"
  44. #include "dev/nvic.h"
  45. #include "dev/gpio.h"
  46. #include "dev/ioc.h"
  47. #include "dev/udma.h"
  48. #include "sys/clock.h"
  49. #include "reg.h"
  50. #include "dev/watchdog.h"
  51. #include <stdint.h>
  52. /*---------------------------------------------------------------------------*/
  53. /* EP max FIFO sizes without double buffering */
  54. #if CTRL_EP_SIZE > 32
  55. #error Control endpoint size too big
  56. #endif
  57. #if USB_EP1_SIZE > 32
  58. #error Endpoint 1 size too big
  59. #endif
  60. #if USB_EP2_SIZE > 64
  61. #error Endpoint 2 size too big
  62. #endif
  63. #if USB_EP3_SIZE > 128
  64. #error Endpoint 3 size too big
  65. #endif
  66. #if USB_EP4_SIZE > 256
  67. #error Endpoint 4 size too big
  68. #endif
  69. #if USB_EP5_SIZE > 512
  70. #error Endpoint 5 size too big
  71. #endif
  72. /*---------------------------------------------------------------------------*/
  73. /* uDMA transfer threshold. Use DMA only for data size higher than this */
  74. #define UDMA_SIZE_THRESHOLD 8
  75. /* uDMA channel control persistent flags */
  76. #define UDMA_TX_FLAGS (UDMA_CHCTL_ARBSIZE_128 | UDMA_CHCTL_XFERMODE_AUTO \
  77. | UDMA_CHCTL_SRCSIZE_8 | UDMA_CHCTL_DSTSIZE_8 \
  78. | UDMA_CHCTL_SRCINC_8 | UDMA_CHCTL_DSTINC_NONE)
  79. #define UDMA_RX_FLAGS (UDMA_CHCTL_ARBSIZE_128 | UDMA_CHCTL_XFERMODE_AUTO \
  80. | UDMA_CHCTL_SRCSIZE_8 | UDMA_CHCTL_DSTSIZE_8 \
  81. | UDMA_CHCTL_SRCINC_NONE | UDMA_CHCTL_DSTINC_8)
  82. /*---------------------------------------------------------------------------*/
  83. static const uint16_t ep_xfer_size[] = {
  84. CTRL_EP_SIZE,
  85. USB_EP1_SIZE,
  86. USB_EP2_SIZE,
  87. USB_EP3_SIZE,
  88. USB_EP4_SIZE,
  89. USB_EP5_SIZE,
  90. };
  91. /*---------------------------------------------------------------------------*/
  92. typedef struct _USBBuffer usb_buffer;
  93. /*---------------------------------------------------------------------------*/
  94. struct usb_endpoint {
  95. uint8_t halted;
  96. uint8_t addr;
  97. uint8_t flags;
  98. usb_buffer *buffer;
  99. struct process *event_process;
  100. unsigned int events;
  101. uint16_t xfer_size;
  102. };
  103. typedef struct usb_endpoint usb_endpoint_t;
  104. /*---------------------------------------------------------------------------*/
  105. #define EP_STATUS_IDLE 0
  106. #define EP_STATUS_RX 1
  107. #define EP_STATUS_TX 2
  108. #define USB_EP_FLAGS_TYPE_MASK 0x03
  109. #define USB_EP_FLAGS_TYPE_BULK 0x00
  110. #define USB_EP_FLAGS_TYPE_CONTROL 0x01
  111. #define USB_EP_FLAGS_TYPE_ISO 0x02
  112. #define USB_EP_FLAGS_TYPE_INTERRUPT 0x03
  113. #define USB_EP_FLAGS_ENABLED 0x04
  114. #define EP_TYPE(ep) ((ep)->flags & USB_EP_FLAGS_TYPE_MASK)
  115. #define IS_EP_TYPE(ep, type) (EP_TYPE(ep) == (type))
  116. #define IS_CONTROL_EP(ep) IS_EP_TYPE(ep, USB_EP_FLAGS_TYPE_CONTROL)
  117. #define IS_BULK_EP(ep) IS_EP_TYPE(ep, USB_EP_FLAGS_TYPE_BULK)
  118. #define IS_INTERRUPT_EP(ep) IS_EP_TYPE(ep, USB_EP_FLAGS_TYPE_INTERRUPT)
  119. #define IS_ISO_EP(ep) IS_EP_TYPE(ep, USB_EP_FLAGS_TYPE_ISO)
  120. #define USBIIE_INEPxIE(x) (1 << x)
  121. #define USBOIE_OUEPxIE(x) (1 << x)
  122. #define EPxIF(x) (1 << x)
  123. #define USB_READ_BLOCK 0x01
  124. #define USB_WRITE_NOTIFY 0x02
  125. #define USB_READ_NOTIFY 0x02
  126. #define USB_READ_FAIL 0x04
  127. /* Index in endpoint array */
  128. #define EP_INDEX(addr) ((addr) & 0x7f)
  129. /* Get address of endpoint struct */
  130. #define EP_STRUCT(addr) &usb_endpoints[EP_INDEX(addr)];
  131. /* Number of hardware endpoint */
  132. #define EP_HW_NUM(addr) ((addr) & 0x7f)
  133. /*---------------------------------------------------------------------------*/
  134. static usb_endpoint_t usb_endpoints[USB_MAX_ENDPOINTS];
  135. struct process *event_process = 0;
  136. volatile static unsigned int events = 0;
  137. static uint8_t ep0status;
  138. /*---------------------------------------------------------------------------*/
  139. static uint8_t ep0_tx(void);
  140. static uint8_t ep_tx(uint8_t ep_hw);
  141. static void in_ep_interrupt_handler(uint8_t ep_hw);
  142. static void out_ep_interrupt_handler(uint8_t ep_hw);
  143. static void ep0_interrupt_handler(void);
  144. /*---------------------------------------------------------------------------*/
  145. static void
  146. notify_process(unsigned int e)
  147. {
  148. events |= e;
  149. if(event_process) {
  150. process_poll(event_process);
  151. }
  152. }
  153. /*---------------------------------------------------------------------------*/
  154. static void
  155. notify_ep_process(usb_endpoint_t *ep, unsigned int e)
  156. {
  157. ep->events |= e;
  158. if(ep->event_process) {
  159. process_poll(ep->event_process);
  160. }
  161. }
  162. /*---------------------------------------------------------------------------*/
  163. void
  164. usb_set_ep_event_process(unsigned char addr, struct process *p)
  165. {
  166. usb_endpoint_t *ep = EP_STRUCT(addr);
  167. ep->event_process = p;
  168. }
  169. /*---------------------------------------------------------------------------*/
  170. void
  171. usb_arch_set_global_event_process(struct process *p)
  172. {
  173. event_process = p;
  174. }
  175. /*---------------------------------------------------------------------------*/
  176. unsigned int
  177. usb_arch_get_global_events(void)
  178. {
  179. uint8_t flag;
  180. volatile unsigned int e;
  181. flag = nvic_interrupt_en_save(NVIC_INT_USB);
  182. e = events;
  183. events = 0;
  184. nvic_interrupt_en_restore(NVIC_INT_USB, flag);
  185. return e;
  186. }
  187. /*---------------------------------------------------------------------------*/
  188. unsigned int
  189. usb_get_ep_events(uint8_t addr)
  190. {
  191. volatile unsigned int e;
  192. uint8_t flag;
  193. usb_endpoint_t *ep = EP_STRUCT(addr);
  194. flag = nvic_interrupt_en_save(NVIC_INT_USB);
  195. e = ep->events;
  196. ep->events = 0;
  197. nvic_interrupt_en_restore(NVIC_INT_USB, flag);
  198. return e;
  199. }
  200. /*---------------------------------------------------------------------------*/
  201. static void
  202. read_hw_buffer(uint8_t *to, uint8_t hw_ep, unsigned int len)
  203. {
  204. uint32_t fifo_addr = USB_F0 + (hw_ep << 3);
  205. if(USB_ARCH_CONF_DMA && len > UDMA_SIZE_THRESHOLD) {
  206. /* Set the transfer source and destination addresses */
  207. udma_set_channel_src(USB_ARCH_CONF_RX_DMA_CHAN, fifo_addr);
  208. udma_set_channel_dst(USB_ARCH_CONF_RX_DMA_CHAN,
  209. (uint32_t)(to) + len - 1);
  210. /* Configure the control word */
  211. udma_set_channel_control_word(USB_ARCH_CONF_RX_DMA_CHAN,
  212. UDMA_RX_FLAGS | udma_xfer_size(len));
  213. /* Enabled the RF RX uDMA channel */
  214. udma_channel_enable(USB_ARCH_CONF_RX_DMA_CHAN);
  215. /* Trigger the uDMA transfer */
  216. udma_channel_sw_request(USB_ARCH_CONF_RX_DMA_CHAN);
  217. /* Wait for the transfer to complete. */
  218. while(udma_channel_get_mode(USB_ARCH_CONF_RX_DMA_CHAN));
  219. } else {
  220. while(len--) {
  221. *to++ = REG(fifo_addr);
  222. }
  223. }
  224. }
  225. /*---------------------------------------------------------------------------*/
  226. static void
  227. write_hw_buffer(uint8_t hw_ep, uint8_t *from, unsigned int len)
  228. {
  229. uint32_t fifo_addr = USB_F0 + (hw_ep << 3);
  230. if(USB_ARCH_CONF_DMA && len > UDMA_SIZE_THRESHOLD) {
  231. /* Set the transfer source and destination addresses */
  232. udma_set_channel_src(USB_ARCH_CONF_TX_DMA_CHAN,
  233. (uint32_t)(from) + len - 1);
  234. udma_set_channel_dst(USB_ARCH_CONF_TX_DMA_CHAN, fifo_addr);
  235. /* Configure the control word */
  236. udma_set_channel_control_word(USB_ARCH_CONF_TX_DMA_CHAN,
  237. UDMA_TX_FLAGS | udma_xfer_size(len));
  238. /* Enabled the RF RX uDMA channel */
  239. udma_channel_enable(USB_ARCH_CONF_TX_DMA_CHAN);
  240. /* Trigger the uDMA transfer */
  241. udma_channel_sw_request(USB_ARCH_CONF_TX_DMA_CHAN);
  242. /* Wait for the transfer to complete. */
  243. while(udma_channel_get_mode(USB_ARCH_CONF_TX_DMA_CHAN));
  244. } else {
  245. while(len--) {
  246. REG(fifo_addr) = *from++;
  247. }
  248. }
  249. }
  250. /*---------------------------------------------------------------------------*/
  251. static void
  252. reset(void)
  253. {
  254. uint8_t e;
  255. for(e = 0; e < USB_MAX_ENDPOINTS; e++) {
  256. if(usb_endpoints[e].flags & USB_EP_FLAGS_ENABLED) {
  257. usb_buffer *buffer = usb_endpoints[e].buffer;
  258. usb_endpoints[e].flags = 0;
  259. usb_disable_endpoint(e);
  260. while(buffer) {
  261. buffer->flags &= ~USB_BUFFER_SUBMITTED;
  262. buffer = buffer->next;
  263. }
  264. }
  265. }
  266. usb_arch_setup_control_endpoint(0);
  267. }
  268. /*---------------------------------------------------------------------------*/
  269. /* Init USB */
  270. void
  271. usb_arch_setup(void)
  272. {
  273. uint8_t i;
  274. /* Switch on USB PLL & USB module */
  275. REG(USB_CTRL) = USB_CTRL_USB_EN | USB_CTRL_PLL_EN;
  276. /* Wait until USB PLL is stable */
  277. while(!(REG(USB_CTRL) & USB_CTRL_PLL_LOCKED));
  278. /* Enable pull-up on usb port */
  279. GPIO_SET_OUTPUT(USB_PULLUP_PORT, USB_PULLUP_PIN_MASK);
  280. REG((USB_PULLUP_PORT | GPIO_DATA) + (USB_PULLUP_PIN_MASK << 2)) = 1;
  281. for(i = 0; i < USB_MAX_ENDPOINTS; i++) {
  282. usb_endpoints[i].flags = 0;
  283. usb_endpoints[i].event_process = 0;
  284. }
  285. reset();
  286. /* Disable all EP interrupts, EP0 interrupt will be enabled later */
  287. REG(USB_IIE) = 0;
  288. REG(USB_OIE) = 0;
  289. /* Initialise the USB control structures */
  290. if(USB_ARCH_CONF_DMA) {
  291. /* Disable peripheral triggers for our channels */
  292. udma_channel_mask_set(USB_ARCH_CONF_RX_DMA_CHAN);
  293. udma_channel_mask_set(USB_ARCH_CONF_TX_DMA_CHAN);
  294. }
  295. nvic_interrupt_enable(NVIC_INT_USB);
  296. }
  297. /*---------------------------------------------------------------------------*/
  298. void
  299. usb_submit_recv_buffer(uint8_t addr, usb_buffer *buffer)
  300. {
  301. usb_buffer **tailp;
  302. uint8_t flag;
  303. usb_endpoint_t *ep = EP_STRUCT(addr);
  304. if(!(ep->flags & USB_EP_FLAGS_ENABLED)) {
  305. return;
  306. }
  307. if(buffer->data == NULL && EP_HW_NUM(addr) == 0) {
  308. if(buffer->flags & USB_BUFFER_NOTIFY) {
  309. notify_ep_process(ep, USB_EP_EVENT_NOTIFICATION);
  310. }
  311. return;
  312. }
  313. flag = nvic_interrupt_en_save(NVIC_INT_USB);
  314. tailp = &ep->buffer;
  315. while(*tailp) {
  316. tailp = &(*tailp)->next;
  317. }
  318. *tailp = buffer;
  319. while(buffer) {
  320. buffer->flags |= USB_BUFFER_SUBMITTED;
  321. buffer = buffer->next;
  322. }
  323. REG(USB_INDEX) = EP_HW_NUM(addr);
  324. if(!EP_HW_NUM(ep->addr)) {
  325. if(REG(USB_CS0) & USB_CS0_OUTPKT_RDY) {
  326. ep0_interrupt_handler();
  327. }
  328. } else {
  329. if(REG(USB_CSOL) & USB_CSOL_OUTPKT_RDY) {
  330. out_ep_interrupt_handler(EP_HW_NUM(ep->addr));
  331. }
  332. }
  333. nvic_interrupt_en_restore(NVIC_INT_USB, flag);
  334. }
  335. /*---------------------------------------------------------------------------*/
  336. void
  337. usb_submit_xmit_buffer(uint8_t addr, usb_buffer *buffer)
  338. {
  339. usb_buffer **tailp;
  340. uint8_t flag;
  341. uint8_t res;
  342. usb_endpoint_t *ep = EP_STRUCT(addr);
  343. if(!(ep->flags & USB_EP_FLAGS_ENABLED)) {
  344. return;
  345. }
  346. flag = nvic_interrupt_en_save(NVIC_INT_USB);
  347. if(EP_HW_NUM(addr) == 0) {
  348. if(buffer->data == NULL) {
  349. /* We are asked to send a STATUS packet.
  350. * But the USB hardware will do this automatically
  351. * as soon as we release the HW FIFO. */
  352. REG(USB_INDEX) = 0;
  353. REG(USB_CS0) = USB_CS0_CLR_OUTPKT_RDY | USB_CS0_DATA_END;
  354. notify_ep_process(ep, USB_EP_EVENT_NOTIFICATION);
  355. nvic_interrupt_en_restore(NVIC_INT_USB, flag);
  356. return;
  357. } else {
  358. /* Release the HW FIFO */
  359. REG(USB_INDEX) = 0;
  360. REG(USB_CS0) = USB_CS0_CLR_OUTPKT_RDY;
  361. }
  362. }
  363. tailp = &ep->buffer;
  364. while(*tailp) {
  365. tailp = &(*tailp)->next;
  366. }
  367. *tailp = buffer;
  368. while(buffer) {
  369. buffer->flags |= USB_BUFFER_SUBMITTED | USB_BUFFER_IN;
  370. buffer = buffer->next;
  371. }
  372. REG(USB_INDEX) = EP_HW_NUM(ep->addr);
  373. if(EP_HW_NUM(ep->addr)) {
  374. res = ep_tx(EP_HW_NUM(ep->addr));
  375. } else {
  376. res = ep0_tx();
  377. }
  378. nvic_interrupt_en_restore(NVIC_INT_USB, flag);
  379. if(res & USB_WRITE_NOTIFY) {
  380. notify_ep_process(ep, USB_EP_EVENT_NOTIFICATION);
  381. }
  382. }
  383. /*---------------------------------------------------------------------------*/
  384. static void
  385. ep0_setup(void)
  386. {
  387. REG(USB_IIE) |= USB_IIE_EP0IE;
  388. }
  389. /*---------------------------------------------------------------------------*/
  390. static void
  391. in_ep_setup(uint8_t addr)
  392. {
  393. uint8_t ei = EP_HW_NUM(addr);
  394. usb_endpoint_t *ep = EP_STRUCT(addr);
  395. /* Enable IN EP interrupt */
  396. REG(USB_IIE) |= USBIIE_INEPxIE(ei);
  397. /* Set internal FIFO size */
  398. REG(USB_MAXI) = ep->xfer_size / 8;
  399. if(IS_ISO_EP(ep)) {
  400. REG(USB_CSIH) |= USB_CSOH_ISO;
  401. } else {
  402. REG(USB_CSIH) &= ~USB_CSOH_ISO;
  403. }
  404. }
  405. /*---------------------------------------------------------------------------*/
  406. static void
  407. out_ep_setup(uint8_t addr)
  408. {
  409. uint8_t ei = EP_HW_NUM(addr);
  410. usb_endpoint_t *ep = EP_STRUCT(addr);
  411. /* Enable OUT EP interrupt */
  412. REG(USB_OIE) |= USBOIE_OUEPxIE(ei);
  413. /* Set internal FIFO size */
  414. REG(USB_MAXO) = ep->xfer_size / 8;
  415. if(IS_ISO_EP(ep)) {
  416. REG(USB_CSOH) |= USB_CSOH_ISO;
  417. } else {
  418. REG(USB_CSOH) &= ~USB_CSOH_ISO;
  419. }
  420. }
  421. /*---------------------------------------------------------------------------*/
  422. static void
  423. ep_setup(uint8_t addr)
  424. {
  425. uint8_t ei = EP_HW_NUM(addr);
  426. uint8_t flag;
  427. usb_endpoint_t *ep = EP_STRUCT(addr);
  428. ep->halted = 0;
  429. ep->flags |= USB_EP_FLAGS_ENABLED;
  430. ep->buffer = 0;
  431. ep->addr = addr;
  432. ep->events = 0;
  433. ep->xfer_size = ep_xfer_size[ei];
  434. flag = nvic_interrupt_en_save(NVIC_INT_USB);
  435. /* Select endpoint register */
  436. REG(USB_INDEX) = ei;
  437. /* EP0 requires special handing */
  438. if(ei == 0) {
  439. ep0_setup();
  440. } else {
  441. if(addr & 0x80) {
  442. in_ep_setup(addr);
  443. } else {
  444. out_ep_setup(addr);
  445. }
  446. }
  447. nvic_interrupt_en_restore(NVIC_INT_USB, flag);
  448. }
  449. /*---------------------------------------------------------------------------*/
  450. void
  451. usb_arch_setup_iso_endpoint(uint8_t addr)
  452. {
  453. usb_endpoint_t *ep = EP_STRUCT(addr);
  454. ep->flags = USB_EP_FLAGS_TYPE_ISO;
  455. ep_setup(addr);
  456. }
  457. /*---------------------------------------------------------------------------*/
  458. void
  459. usb_arch_setup_control_endpoint(uint8_t addr)
  460. {
  461. usb_endpoint_t *ep = EP_STRUCT(addr);
  462. ep->flags = USB_EP_FLAGS_TYPE_CONTROL;
  463. ep_setup(addr);
  464. }
  465. /*---------------------------------------------------------------------------*/
  466. void
  467. usb_arch_setup_bulk_endpoint(uint8_t addr)
  468. {
  469. usb_endpoint_t *ep = EP_STRUCT(addr);
  470. ep->flags = USB_EP_FLAGS_TYPE_BULK;
  471. ep_setup(addr);
  472. }
  473. /*---------------------------------------------------------------------------*/
  474. void
  475. usb_arch_setup_interrupt_endpoint(uint8_t addr)
  476. {
  477. usb_endpoint_t *ep = EP_STRUCT(addr);
  478. ep->flags = USB_EP_FLAGS_TYPE_INTERRUPT;
  479. ep_setup(addr);
  480. }
  481. /*---------------------------------------------------------------------------*/
  482. static void
  483. ep0_dis(void)
  484. {
  485. REG(USB_IIE) &= ~USB_IIE_EP0IE;
  486. /* Clear any pending status flags */
  487. REG(USB_CS0) = 0xC0;
  488. }
  489. /*---------------------------------------------------------------------------*/
  490. static void
  491. in_ep_dis(uint8_t addr)
  492. {
  493. REG(USB_MAXI) = 0;
  494. REG(USB_IIE) &= ~USBIIE_INEPxIE(EP_HW_NUM(addr));
  495. /* Flush pending */
  496. REG(USB_CSIL) = USB_CSIL_FLUSH_PACKET;
  497. }
  498. /*---------------------------------------------------------------------------*/
  499. static void
  500. out_ep_dis(uint8_t addr)
  501. {
  502. REG(USB_MAXO) = 0;
  503. REG(USB_OIE) &= ~USBOIE_OUEPxIE(EP_HW_NUM(addr));
  504. /* Flush pending */
  505. REG(USB_CSOL) = USB_CSIL_FLUSH_PACKET;
  506. }
  507. /*---------------------------------------------------------------------------*/
  508. void
  509. usb_arch_disable_endpoint(uint8_t addr)
  510. {
  511. uint8_t ei = EP_HW_NUM(addr);
  512. uint8_t flag;
  513. usb_endpoint_t *ep = EP_STRUCT(addr);
  514. ep->flags &= ~USB_EP_FLAGS_ENABLED;
  515. flag = nvic_interrupt_en_save(NVIC_INT_USB);
  516. REG(USB_INDEX) = ei;
  517. if(ei == 0) {
  518. ep0_dis();
  519. } else {
  520. if(addr & 0x80) {
  521. in_ep_dis(addr);
  522. } else {
  523. out_ep_dis(addr);
  524. }
  525. }
  526. nvic_interrupt_en_restore(NVIC_INT_USB, flag);
  527. }
  528. /*---------------------------------------------------------------------------*/
  529. void
  530. usb_arch_discard_all_buffers(uint8_t addr)
  531. {
  532. usb_buffer *buffer;
  533. uint8_t flag;
  534. volatile usb_endpoint_t *ep = EP_STRUCT(addr);
  535. flag = nvic_interrupt_en_save(NVIC_INT_USB);
  536. buffer = ep->buffer;
  537. ep->buffer = NULL;
  538. nvic_interrupt_en_restore(NVIC_INT_USB, flag);
  539. while(buffer) {
  540. buffer->flags &= ~USB_BUFFER_SUBMITTED;
  541. buffer = buffer->next;
  542. }
  543. }
  544. /*---------------------------------------------------------------------------*/
  545. static void
  546. set_stall(uint8_t addr, uint8_t stall)
  547. {
  548. uint8_t ei = EP_HW_NUM(addr);
  549. REG(USB_INDEX) = ei;
  550. if(ei == 0) {
  551. /* Stall is automatically deasserted on EP0 */
  552. if(stall) {
  553. ep0status = EP_STATUS_IDLE;
  554. REG(USB_CS0) |= USB_CS0_SEND_STALL | USB_CS0_OUTPKT_RDY;
  555. }
  556. } else {
  557. if(addr & 0x80) {
  558. if(stall) {
  559. REG(USB_CSIL) |= USB_CSIL_SEND_STALL;
  560. } else {
  561. REG(USB_CSIL) &= ~USB_CSIL_SEND_STALL;
  562. }
  563. } else {
  564. if(stall) {
  565. REG(USB_CSOL) |= USB_CSOL_SEND_STALL;
  566. } else {
  567. REG(USB_CSOL) &= ~USB_CSOL_SEND_STALL;
  568. }
  569. }
  570. }
  571. }
  572. /*---------------------------------------------------------------------------*/
  573. void
  574. usb_arch_control_stall(uint8_t addr)
  575. {
  576. uint8_t ei = EP_HW_NUM(addr);
  577. uint8_t flag;
  578. if(ei > USB_MAX_ENDPOINTS) {
  579. return;
  580. }
  581. flag = nvic_interrupt_en_save(NVIC_INT_USB);
  582. set_stall(addr, 1);
  583. nvic_interrupt_en_restore(NVIC_INT_USB, flag);
  584. }
  585. /*---------------------------------------------------------------------------*/
  586. void
  587. usb_arch_halt_endpoint(uint8_t addr, int halt)
  588. {
  589. uint8_t ei = EP_HW_NUM(addr);
  590. uint8_t flag;
  591. usb_endpoint_t *ep = EP_STRUCT(addr);
  592. if(ei > USB_MAX_ENDPOINTS) {
  593. return;
  594. }
  595. if(!(ep->flags & USB_EP_FLAGS_ENABLED)) {
  596. return;
  597. }
  598. flag = nvic_interrupt_en_save(NVIC_INT_USB);
  599. if(halt) {
  600. ep->halted = 0x1;
  601. set_stall(addr, 1);
  602. } else {
  603. ep->halted = 0;
  604. set_stall(addr, 0);
  605. if(ep->buffer && (ep->buffer->flags & USB_BUFFER_HALT)) {
  606. ep->buffer->flags &= ~USB_BUFFER_SUBMITTED;
  607. if(ep->buffer->flags & USB_BUFFER_NOTIFY) {
  608. notify_ep_process(ep, USB_EP_EVENT_NOTIFICATION);
  609. }
  610. ep->buffer = ep->buffer->next;
  611. }
  612. if(ei) {
  613. out_ep_interrupt_handler(EP_HW_NUM(addr));
  614. }
  615. }
  616. nvic_interrupt_en_restore(NVIC_INT_USB, flag);
  617. }
  618. /*---------------------------------------------------------------------------*/
  619. void
  620. usb_arch_set_configuration(uint8_t usb_configuration_value)
  621. {
  622. return;
  623. }
  624. /*---------------------------------------------------------------------------*/
  625. uint16_t
  626. usb_arch_get_ep_status(uint8_t addr)
  627. {
  628. uint8_t ei = EP_INDEX(addr);
  629. usb_endpoint_t *ep = EP_STRUCT(addr);
  630. if(ei > USB_MAX_ENDPOINTS) {
  631. return 0;
  632. }
  633. return ep->halted;
  634. }
  635. /*---------------------------------------------------------------------------*/
  636. void
  637. usb_arch_set_address(uint8_t addr)
  638. {
  639. REG(USB_ADDR) = addr;
  640. }
  641. /*---------------------------------------------------------------------------*/
  642. int
  643. usb_arch_send_pending(uint8_t addr)
  644. {
  645. uint8_t flag;
  646. uint8_t ret;
  647. uint8_t ei = EP_INDEX(addr);
  648. flag = nvic_interrupt_en_save(NVIC_INT_USB);
  649. REG(USB_INDEX) = ei;
  650. if(ei == 0) {
  651. ret = REG(USB_CS0) & USB_CS0_INPKT_RDY;
  652. } else {
  653. ret = REG(USB_CSIL) & USB_CSIL_INPKT_RDY;
  654. }
  655. nvic_interrupt_en_restore(NVIC_INT_USB, flag);
  656. return ret;
  657. }
  658. /*---------------------------------------------------------------------------*/
  659. static unsigned int
  660. get_receive_capacity(usb_buffer *buffer)
  661. {
  662. unsigned int capacity = 0;
  663. while(buffer &&
  664. !(buffer->flags & (USB_BUFFER_IN | USB_BUFFER_SETUP | USB_BUFFER_HALT))) {
  665. capacity += buffer->left;
  666. buffer = buffer->next;
  667. }
  668. return capacity;
  669. }
  670. /*---------------------------------------------------------------------------*/
  671. static usb_buffer *
  672. skip_buffers_until(usb_buffer *buffer, unsigned int mask, unsigned int flags,
  673. uint8_t *resp)
  674. {
  675. while(buffer && !((buffer->flags & mask) == flags)) {
  676. buffer->flags &= ~USB_BUFFER_SUBMITTED;
  677. buffer->flags |= USB_BUFFER_FAILED;
  678. if(buffer->flags & USB_BUFFER_NOTIFY) {
  679. *resp |= USB_READ_NOTIFY;
  680. }
  681. buffer = buffer->next;
  682. }
  683. return buffer;
  684. }
  685. /*---------------------------------------------------------------------------*/
  686. static uint8_t
  687. fill_buffers(usb_buffer *buffer, uint8_t hw_ep, unsigned int len,
  688. uint8_t short_packet)
  689. {
  690. unsigned int t;
  691. uint8_t res = 0;
  692. do {
  693. if(buffer->left < len) {
  694. t = buffer->left;
  695. } else {
  696. t = len;
  697. }
  698. len -= t;
  699. buffer->left -= t;
  700. read_hw_buffer(buffer->data, hw_ep, t);
  701. buffer->data += t;
  702. if(len == 0) {
  703. break;
  704. }
  705. buffer->flags &= ~(USB_BUFFER_SUBMITTED | USB_BUFFER_SHORT_PACKET);
  706. if(buffer->flags & USB_BUFFER_NOTIFY) {
  707. res |= USB_READ_NOTIFY;
  708. }
  709. buffer = buffer->next;
  710. } while(1);
  711. if(short_packet) {
  712. buffer->flags |= USB_BUFFER_SHORT_PACKET;
  713. }
  714. if((buffer->left == 0) || (buffer->flags & USB_BUFFER_PACKET_END)) {
  715. buffer->flags &= ~USB_BUFFER_SUBMITTED;
  716. if(buffer->flags & USB_BUFFER_NOTIFY) {
  717. res |= USB_READ_NOTIFY;
  718. }
  719. buffer = buffer->next;
  720. } else {
  721. if(short_packet) {
  722. if(buffer->left && !(buffer->flags & USB_BUFFER_SHORT_END)) {
  723. buffer->flags |= USB_BUFFER_FAILED;
  724. res |= USB_READ_FAIL;
  725. }
  726. buffer->flags &= ~USB_BUFFER_SUBMITTED;
  727. if(buffer->flags & USB_BUFFER_NOTIFY) {
  728. res |= USB_READ_NOTIFY;
  729. }
  730. buffer = buffer->next;
  731. }
  732. }
  733. usb_endpoints[hw_ep].buffer = buffer;
  734. return res;
  735. }
  736. /*---------------------------------------------------------------------------*/
  737. static uint8_t
  738. ep0_get_setup_pkt(void)
  739. {
  740. uint8_t res;
  741. usb_buffer *buffer =
  742. skip_buffers_until(usb_endpoints[0].buffer, USB_BUFFER_SETUP,
  743. USB_BUFFER_SETUP, &res);
  744. usb_endpoints[0].buffer = buffer;
  745. if(!buffer || buffer->left < 8) {
  746. return USB_READ_BLOCK;
  747. }
  748. read_hw_buffer(buffer->data, 0, 8);
  749. buffer->left -= 8;
  750. buffer->flags &= ~USB_BUFFER_SUBMITTED;
  751. if(buffer->flags & USB_BUFFER_NOTIFY) {
  752. res |= USB_READ_NOTIFY;
  753. }
  754. if(buffer->data[6] || buffer->data[7]) {
  755. REG(USB_CS0) |= USB_CS0_CLR_OUTPKT_RDY;
  756. ep0status = buffer->data[0] & 0x80 ? EP_STATUS_TX : EP_STATUS_RX;
  757. }
  758. buffer->data += 8;
  759. usb_endpoints[0].buffer = buffer->next;
  760. return res;
  761. }
  762. /*---------------------------------------------------------------------------*/
  763. static uint8_t
  764. ep0_get_data_pkt(void)
  765. {
  766. uint8_t res = 0;
  767. uint8_t short_packet = 0;
  768. usb_buffer *buffer = usb_endpoints[0].buffer;
  769. uint8_t len = REG(USB_CNT0);
  770. if(!buffer) {
  771. return USB_READ_BLOCK;
  772. }
  773. if(buffer->flags & (USB_BUFFER_SETUP | USB_BUFFER_IN)) {
  774. uint8_t temp;
  775. buffer->flags |= USB_BUFFER_FAILED;
  776. buffer->flags &= ~USB_BUFFER_SUBMITTED;
  777. if(buffer->flags & USB_BUFFER_NOTIFY) {
  778. res |= USB_READ_NOTIFY;
  779. }
  780. /* Flush the fifo */
  781. while(len--) {
  782. temp = REG(USB_F0);
  783. }
  784. usb_endpoints[0].buffer = buffer->next;
  785. /* Force data stage end */
  786. REG(USB_CS0) |= USB_CS0_CLR_OUTPKT_RDY | USB_CS0_DATA_END;
  787. ep0status = EP_STATUS_IDLE;
  788. return res;
  789. }
  790. if(get_receive_capacity(buffer) < len) {
  791. /* Wait until we queue more buffers */
  792. return USB_READ_BLOCK;
  793. }
  794. if(len < usb_endpoints[0].xfer_size) {
  795. short_packet = 1;
  796. }
  797. res = fill_buffers(buffer, 0, len, short_packet);
  798. if(short_packet) {
  799. /* The usb-core will send a status packet, we will release the fifo at this stage */
  800. ep0status = EP_STATUS_IDLE;
  801. } else {
  802. REG(USB_CS0) |= USB_CS0_CLR_OUTPKT_RDY;
  803. }
  804. return res;
  805. }
  806. /*---------------------------------------------------------------------------*/
  807. static uint8_t
  808. ep0_tx(void)
  809. {
  810. usb_buffer *buffer = usb_endpoints[0].buffer;
  811. unsigned int len = usb_endpoints[0].xfer_size;
  812. uint8_t data_end = 0;
  813. uint8_t res = 0;
  814. /* If TX Fifo still busy or ep0 not in TX data stage don't do anything */
  815. if((REG(USB_CS0) & USB_CS0_INPKT_RDY) || (ep0status != EP_STATUS_TX)) {
  816. return 0;
  817. }
  818. if(!buffer) {
  819. return 0;
  820. }
  821. if(!(buffer->flags & USB_BUFFER_IN)) {
  822. /* We should TX but queued buffer is in RX */
  823. return 0;
  824. }
  825. while(buffer) {
  826. unsigned int copy;
  827. if(buffer->left < len) {
  828. copy = buffer->left;
  829. } else {
  830. copy = len;
  831. }
  832. len -= copy;
  833. buffer->left -= copy;
  834. write_hw_buffer(0, buffer->data, copy);
  835. buffer->data += copy;
  836. if(buffer->left == 0) {
  837. if(buffer->flags & USB_BUFFER_SHORT_END) {
  838. if(len == 0) {
  839. break; // We keep the buffer in queue so we will send a ZLP next time.
  840. } else {
  841. data_end = 1;
  842. len = 0; // Stop looking for more data to send
  843. }
  844. }
  845. buffer->flags &= ~USB_BUFFER_SUBMITTED;
  846. if(buffer->flags & USB_BUFFER_NOTIFY) {
  847. res |= USB_WRITE_NOTIFY;
  848. }
  849. buffer = buffer->next;
  850. }
  851. if(len == 0) {
  852. break; // FIFO is full, send packet.
  853. }
  854. }
  855. if(len) {
  856. data_end = 1;
  857. }
  858. usb_endpoints[0].buffer = buffer;
  859. /*
  860. * Workaround the fact that the usb controller do not like to have DATA_END
  861. * set after INPKT_RDY for the last packet. Thus if no more is in the queue
  862. * set DATA_END
  863. */
  864. if(data_end || !buffer) {
  865. ep0status = EP_STATUS_IDLE;
  866. REG(USB_CS0) |= USB_CS0_INPKT_RDY | USB_CS0_DATA_END;
  867. } else {
  868. REG(USB_CS0) |= USB_CS0_INPKT_RDY;
  869. }
  870. return res;
  871. }
  872. /*---------------------------------------------------------------------------*/
  873. static void
  874. ep0_interrupt_handler(void)
  875. {
  876. uint8_t cs0;
  877. uint8_t res;
  878. REG(USB_INDEX) = 0;
  879. cs0 = REG(USB_CS0);
  880. if(cs0 & USB_CS0_SENT_STALL) {
  881. /* Ack the stall */
  882. REG(USB_CS0) = 0;
  883. ep0status = EP_STATUS_IDLE;
  884. }
  885. if(cs0 & USB_CS0_SETUP_END) {
  886. /* Clear it */
  887. REG(USB_CS0) = USB_CS0_CLR_SETUP_END;
  888. ep0status = EP_STATUS_IDLE;
  889. }
  890. if(cs0 & USB_CS0_OUTPKT_RDY) {
  891. if(ep0status == EP_STATUS_IDLE) {
  892. res = ep0_get_setup_pkt();
  893. } else {
  894. res = ep0_get_data_pkt();
  895. }
  896. if(res & USB_READ_NOTIFY) {
  897. notify_ep_process(&usb_endpoints[0], USB_EP_EVENT_NOTIFICATION);
  898. }
  899. if(res & USB_READ_BLOCK) {
  900. return;
  901. }
  902. }
  903. res = ep0_tx();
  904. if(res & USB_WRITE_NOTIFY) {
  905. notify_ep_process(&usb_endpoints[0], USB_EP_EVENT_NOTIFICATION);
  906. }
  907. }
  908. /*---------------------------------------------------------------------------*/
  909. static uint8_t
  910. ep_tx(uint8_t ep_hw)
  911. {
  912. unsigned int len;
  913. uint8_t res = 0;
  914. usb_endpoint_t *ep = EP_STRUCT(ep_hw);
  915. len = ep->xfer_size;
  916. if(ep->halted) {
  917. return 0;
  918. }
  919. if(!ep->buffer || !(ep->buffer->flags & USB_BUFFER_IN)) {
  920. return 0;
  921. }
  922. while(ep->buffer) {
  923. unsigned int copy;
  924. if(ep->buffer->left < len) {
  925. copy = ep->buffer->left;
  926. } else {
  927. copy = len;
  928. }
  929. len -= copy;
  930. ep->buffer->left -= copy;
  931. /*
  932. * Delay somewhat if the previous packet has not yet left the IN FIFO,
  933. * making sure the dog doesn't bark while we're waiting
  934. */
  935. while(REG(USB_CSIL) & USB_CSIL_INPKT_RDY) {
  936. watchdog_periodic();
  937. }
  938. write_hw_buffer(EP_INDEX(ep_hw), ep->buffer->data, copy);
  939. ep->buffer->data += copy;
  940. if(ep->buffer->left == 0) {
  941. if(ep->buffer->flags & USB_BUFFER_SHORT_END) {
  942. if(len == 0) {
  943. /* We keep the buffer in queue so we will send a ZLP next */
  944. break;
  945. } else {
  946. /* Stop looking for more data to send */
  947. len = 0;
  948. }
  949. }
  950. ep->buffer->flags &= ~USB_BUFFER_SUBMITTED;
  951. if(ep->buffer->flags & USB_BUFFER_NOTIFY) {
  952. res |= USB_WRITE_NOTIFY;
  953. }
  954. ep->buffer = ep->buffer->next;
  955. }
  956. if(len == 0) {
  957. /* FIFO full, send */
  958. break;
  959. }
  960. }
  961. REG(USB_CSIL) |= USB_CSIL_INPKT_RDY;
  962. return res;
  963. }
  964. /*---------------------------------------------------------------------------*/
  965. static uint8_t
  966. ep_get_data_pkt(uint8_t ep_hw)
  967. {
  968. uint16_t pkt_len;
  969. uint8_t res;
  970. uint8_t short_packet = 0;
  971. usb_endpoint_t *ep = EP_STRUCT(ep_hw);
  972. if(!ep->buffer) {
  973. return USB_READ_BLOCK;
  974. }
  975. if(ep->buffer->flags & USB_BUFFER_HALT) {
  976. ep->halted = 1;
  977. if(!(REG(USB_CSOL) & USB_CSOL_SEND_STALL)) {
  978. REG(USB_CSOL) |= USB_CSOL_SEND_STALL;
  979. }
  980. return 0;
  981. }
  982. /* Disambiguate UG CNTL bits */
  983. pkt_len = REG(USB_CNTL) | (REG(USB_CNTH) << 8);
  984. if(get_receive_capacity(ep->buffer) < pkt_len) {
  985. return USB_READ_BLOCK;
  986. }
  987. if(pkt_len < ep->xfer_size) {
  988. short_packet = 1;
  989. }
  990. res = fill_buffers(ep->buffer, ep_hw, pkt_len, short_packet);
  991. REG(USB_CSOL) &= ~USB_CSOL_OUTPKT_RDY;
  992. return res;
  993. }
  994. /*---------------------------------------------------------------------------*/
  995. static void
  996. out_ep_interrupt_handler(uint8_t ep_hw)
  997. {
  998. uint8_t csl;
  999. uint8_t res;
  1000. usb_endpoint_t *ep = EP_STRUCT(ep_hw);
  1001. REG(USB_INDEX) = ep_hw;
  1002. csl = REG(USB_CSOL);
  1003. if(csl & USB_CSOL_SENT_STALL) {
  1004. REG(USB_CSOL) &= ~USB_CSOL_SENT_STALL;
  1005. }
  1006. if(csl & USB_CSOL_OVERRUN) {
  1007. /* We lost one isochronous packet */
  1008. REG(USB_CSOL) &= ~USB_CSOL_OVERRUN;
  1009. }
  1010. if(csl & USB_CSOL_OUTPKT_RDY) {
  1011. res = ep_get_data_pkt(ep_hw);
  1012. if(res & USB_READ_NOTIFY) {
  1013. notify_ep_process(ep, USB_EP_EVENT_NOTIFICATION);
  1014. }
  1015. }
  1016. }
  1017. /*---------------------------------------------------------------------------*/
  1018. static void
  1019. in_ep_interrupt_handler(uint8_t ep_hw)
  1020. {
  1021. uint8_t csl;
  1022. #if USB_ARCH_WRITE_NOTIFY
  1023. uint8_t res;
  1024. usb_endpoint_t *ep = EP_STRUCT(ep_hw);
  1025. #endif
  1026. REG(USB_INDEX) = ep_hw;
  1027. csl = REG(USB_CSIL);
  1028. if(csl & USB_CSIL_SENT_STALL) {
  1029. REG(USB_CSIL) &= ~USB_CSIL_SENT_STALL;
  1030. }
  1031. if(csl & USB_CSIL_UNDERRUN) {
  1032. REG(USB_CSIL) &= ~USB_CSIL_UNDERRUN;
  1033. }
  1034. #if USB_ARCH_WRITE_NOTIFY
  1035. if(!(csl & USB_CSIL_INPKT_RDY)) {
  1036. res = ep_tx(ep_hw);
  1037. if(res & USB_WRITE_NOTIFY) {
  1038. notify_ep_process(ep, USB_EP_EVENT_NOTIFICATION);
  1039. }
  1040. }
  1041. #endif
  1042. }
  1043. /*---------------------------------------------------------------------------*/
  1044. void
  1045. usb_isr(void)
  1046. {
  1047. uint8_t ep_in_if = REG(USB_IIF) & REG(USB_IIE);
  1048. uint8_t ep_out_if = REG(USB_OIF) & REG(USB_OIE);
  1049. uint8_t common_if = REG(USB_CIF) & REG(USB_CIE);
  1050. uint8_t i;
  1051. ENERGEST_ON(ENERGEST_TYPE_IRQ);
  1052. if(ep_in_if) {
  1053. /* EP0 flag is in the IN Interrupt Flags register */
  1054. if(ep_in_if & USB_IIF_EP0IF) {
  1055. ep0_interrupt_handler();
  1056. }
  1057. for(i = 1; i < 6; i++) {
  1058. if(ep_in_if & EPxIF(i)) {
  1059. in_ep_interrupt_handler(i);
  1060. }
  1061. }
  1062. }
  1063. if(ep_out_if) {
  1064. for(i = 1; i < 6; i++) {
  1065. if(ep_out_if & EPxIF(i)) {
  1066. out_ep_interrupt_handler(i);
  1067. }
  1068. }
  1069. }
  1070. if(common_if & USB_CIF_RSTIF) {
  1071. reset();
  1072. notify_process(USB_EVENT_RESET);
  1073. }
  1074. if(common_if & USB_CIF_RESUMEIF) {
  1075. notify_process(USB_EVENT_RESUME);
  1076. }
  1077. if(common_if & USB_CIF_SUSPENDIF) {
  1078. notify_process(USB_EVENT_SUSPEND);
  1079. }
  1080. ENERGEST_OFF(ENERGEST_TYPE_IRQ);
  1081. }
  1082. /*---------------------------------------------------------------------------*/
  1083. /** @} */