Contiki-NG
usb-arch.c
Go to the documentation of this 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 "usb-arch.h"
41 #include "usb-api.h"
42 #include "dev/usb-regs.h"
43 #include "dev/nvic.h"
44 #include "dev/gpio.h"
45 #include "dev/ioc.h"
46 #include "dev/udma.h"
47 #include "sys/clock.h"
48 #include "lpm.h"
49 #include "reg.h"
50 
51 #include "dev/watchdog.h"
52 
53 #include <stdbool.h>
54 #include <stdint.h>
55 /*---------------------------------------------------------------------------*/
56 #ifdef USB_PULLUP_PORT
57 #define USB_PULLUP_PORT_BASE GPIO_PORT_TO_BASE(USB_PULLUP_PORT)
58 #endif
59 #ifdef USB_PULLUP_PIN
60 #define USB_PULLUP_PIN_MASK GPIO_PIN_MASK(USB_PULLUP_PIN)
61 #endif
62 /*---------------------------------------------------------------------------*/
63 /* EP max FIFO sizes without double buffering */
64 #if CTRL_EP_SIZE > 32
65 #error Control endpoint size too big
66 #endif
67 
68 #if USB_EP1_SIZE > 32
69 #error Endpoint 1 size too big
70 #endif
71 
72 #if USB_EP2_SIZE > 64
73 #error Endpoint 2 size too big
74 #endif
75 
76 #if USB_EP3_SIZE > 128
77 #error Endpoint 3 size too big
78 #endif
79 
80 #if USB_EP4_SIZE > 256
81 #error Endpoint 4 size too big
82 #endif
83 
84 #if USB_EP5_SIZE > 512
85 #error Endpoint 5 size too big
86 #endif
87 /*---------------------------------------------------------------------------*/
88 /* uDMA transfer threshold. Use DMA only for data size higher than this */
89 #define UDMA_SIZE_THRESHOLD 8
90 
91 /* uDMA channel control persistent flags */
92 #define UDMA_TX_FLAGS (UDMA_CHCTL_ARBSIZE_128 | UDMA_CHCTL_XFERMODE_AUTO \
93  | UDMA_CHCTL_SRCSIZE_8 | UDMA_CHCTL_DSTSIZE_8 \
94  | UDMA_CHCTL_SRCINC_8 | UDMA_CHCTL_DSTINC_NONE)
95 
96 #define UDMA_RX_FLAGS (UDMA_CHCTL_ARBSIZE_128 | UDMA_CHCTL_XFERMODE_AUTO \
97  | UDMA_CHCTL_SRCSIZE_8 | UDMA_CHCTL_DSTSIZE_8 \
98  | UDMA_CHCTL_SRCINC_NONE | UDMA_CHCTL_DSTINC_8)
99 /*---------------------------------------------------------------------------*/
100 static const uint16_t ep_xfer_size[] = {
101  CTRL_EP_SIZE,
102  USB_EP1_SIZE,
103  USB_EP2_SIZE,
104  USB_EP3_SIZE,
105  USB_EP4_SIZE,
106  USB_EP5_SIZE,
107 };
108 /*---------------------------------------------------------------------------*/
109 typedef struct _USBBuffer usb_buffer;
110 /*---------------------------------------------------------------------------*/
111 struct usb_endpoint {
112  uint8_t halted;
113  uint8_t addr;
114  uint8_t flags;
115  usb_buffer *buffer;
116  struct process *event_process;
117  unsigned int events;
118  uint16_t xfer_size;
119 };
120 typedef struct usb_endpoint usb_endpoint_t;
121 /*---------------------------------------------------------------------------*/
122 #define EP_STATUS_IDLE 0
123 #define EP_STATUS_RX 1
124 #define EP_STATUS_TX 2
125 
126 #define USB_EP_FLAGS_TYPE_MASK 0x03
127 #define USB_EP_FLAGS_TYPE_BULK 0x00
128 #define USB_EP_FLAGS_TYPE_CONTROL 0x01
129 #define USB_EP_FLAGS_TYPE_ISO 0x02
130 #define USB_EP_FLAGS_TYPE_INTERRUPT 0x03
131 #define USB_EP_FLAGS_ENABLED 0x04
132 
133 #define EP_TYPE(ep) ((ep)->flags & USB_EP_FLAGS_TYPE_MASK)
134 #define IS_EP_TYPE(ep, type) (EP_TYPE(ep) == (type))
135 #define IS_CONTROL_EP(ep) IS_EP_TYPE(ep, USB_EP_FLAGS_TYPE_CONTROL)
136 #define IS_BULK_EP(ep) IS_EP_TYPE(ep, USB_EP_FLAGS_TYPE_BULK)
137 #define IS_INTERRUPT_EP(ep) IS_EP_TYPE(ep, USB_EP_FLAGS_TYPE_INTERRUPT)
138 #define IS_ISO_EP(ep) IS_EP_TYPE(ep, USB_EP_FLAGS_TYPE_ISO)
139 
140 #define USBIIE_INEPxIE(x) (1 << x)
141 #define USBOIE_OUEPxIE(x) (1 << x)
142 #define EPxIF(x) (1 << x)
143 
144 #define USB_READ_BLOCK 0x01
145 #define USB_WRITE_NOTIFY 0x02
146 #define USB_READ_NOTIFY 0x02
147 #define USB_READ_FAIL 0x04
148 
149 /* Index in endpoint array */
150 #define EP_INDEX(addr) ((addr) & 0x7f)
151 
152 /* Get address of endpoint struct */
153 #define EP_STRUCT(addr) &usb_endpoints[EP_INDEX(addr)];
154 
155 /* Number of hardware endpoint */
156 #define EP_HW_NUM(addr) ((addr) & 0x7f)
157 /*---------------------------------------------------------------------------*/
158 static usb_endpoint_t usb_endpoints[USB_MAX_ENDPOINTS];
159 struct process *event_process = 0;
160 volatile static unsigned int events = 0;
161 static uint8_t ep0status;
162 /*---------------------------------------------------------------------------*/
163 static uint8_t ep0_tx(void);
164 static uint8_t ep_tx(uint8_t ep_hw);
165 static void in_ep_interrupt_handler(uint8_t ep_hw);
166 static void out_ep_interrupt_handler(uint8_t ep_hw);
167 static void ep0_interrupt_handler(void);
168 /*---------------------------------------------------------------------------*/
169 static uint8_t
170 disable_irq(void)
171 {
172  uint8_t enabled = NVIC_IsIRQEnabled(USB_IRQn);
173  if(enabled) {
175  }
176  return enabled;
177 }
178 /*---------------------------------------------------------------------------*/
179 static void
180 restore_irq(uint8_t enabled)
181 {
182  if(enabled) {
184  }
185 }
186 /*---------------------------------------------------------------------------*/
187 static void
188 notify_process(unsigned int e)
189 {
190  events |= e;
191  if(event_process) {
192  process_poll(event_process);
193  }
194 }
195 /*---------------------------------------------------------------------------*/
196 static void
197 notify_ep_process(usb_endpoint_t *ep, unsigned int e)
198 {
199  ep->events |= e;
200  if(ep->event_process) {
201  process_poll(ep->event_process);
202  }
203 }
204 /*---------------------------------------------------------------------------*/
205 void
206 usb_set_ep_event_process(unsigned char addr, struct process *p)
207 {
208  usb_endpoint_t *ep = EP_STRUCT(addr);
209 
210  ep->event_process = p;
211 }
212 /*---------------------------------------------------------------------------*/
213 void
214 usb_arch_set_global_event_process(struct process *p)
215 {
216  event_process = p;
217 }
218 /*---------------------------------------------------------------------------*/
219 unsigned int
220 usb_arch_get_global_events(void)
221 {
222  uint8_t flag;
223  volatile unsigned int e;
224 
225  flag = disable_irq();
226 
227  e = events;
228  events = 0;
229 
230  restore_irq(flag);
231 
232  return e;
233 }
234 /*---------------------------------------------------------------------------*/
235 unsigned int
236 usb_get_ep_events(uint8_t addr)
237 {
238  volatile unsigned int e;
239  uint8_t flag;
240  usb_endpoint_t *ep = EP_STRUCT(addr);
241 
242  flag = disable_irq();
243 
244  e = ep->events;
245  ep->events = 0;
246 
247  restore_irq(flag);
248 
249  return e;
250 }
251 /*---------------------------------------------------------------------------*/
252 static void
253 read_hw_buffer(uint8_t *to, uint8_t hw_ep, unsigned int len)
254 {
255  uint32_t fifo_addr = USB_F0 + (hw_ep << 3);
256 
257  if(USB_ARCH_CONF_DMA && len > UDMA_SIZE_THRESHOLD) {
258  /* Set the transfer source and destination addresses */
261  (uint32_t)(to) + len - 1);
262 
263  /* Configure the control word */
265  UDMA_RX_FLAGS | udma_xfer_size(len));
266 
267  /* Enabled the RF RX uDMA channel */
269 
270  /* Trigger the uDMA transfer */
272 
273  /* Wait for the transfer to complete. */
275  } else {
276  while(len--) {
277  *to++ = REG(fifo_addr);
278  }
279  }
280 }
281 /*---------------------------------------------------------------------------*/
282 static void
283 write_hw_buffer(uint8_t hw_ep, uint8_t *from, unsigned int len)
284 {
285  uint32_t fifo_addr = USB_F0 + (hw_ep << 3);
286 
287  if(USB_ARCH_CONF_DMA && len > UDMA_SIZE_THRESHOLD) {
288  /* Set the transfer source and destination addresses */
290  (uint32_t)(from) + len - 1);
292 
293  /* Configure the control word */
295  UDMA_TX_FLAGS | udma_xfer_size(len));
296 
297  /* Enabled the RF RX uDMA channel */
299 
300  /* Trigger the uDMA transfer */
302 
303  /* Wait for the transfer to complete. */
305  } else {
306  while(len--) {
307  REG(fifo_addr) = *from++;
308  }
309  }
310 }
311 /*---------------------------------------------------------------------------*/
312 static void
313 reset(void)
314 {
315  uint8_t e;
316 
317  for(e = 0; e < USB_MAX_ENDPOINTS; e++) {
318  if(usb_endpoints[e].flags & USB_EP_FLAGS_ENABLED) {
319  usb_buffer *buffer = usb_endpoints[e].buffer;
320 
321  usb_endpoints[e].flags = 0;
322  usb_disable_endpoint(e);
323  while(buffer) {
324  buffer->flags &= ~USB_BUFFER_SUBMITTED;
325  buffer = buffer->next;
326  }
327  }
328  }
329  usb_arch_setup_control_endpoint(0);
330 }
331 /*---------------------------------------------------------------------------*/
332 static bool
333 permit_pm1(void)
334 {
335  /*
336  * Note: USB Suspend/Resume/Remote Wake-Up are not supported. Once the PLL is
337  * on, it stays on.
338  */
339  return REG(USB_CTRL) == 0;
340 }
341 /*---------------------------------------------------------------------------*/
342 /* Init USB */
343 void
344 usb_arch_setup(void)
345 {
346  uint8_t i;
347 
348  lpm_register_peripheral(permit_pm1);
349 
350  /* Switch on USB PLL & USB module */
352 
353  /* Wait until USB PLL is stable */
354  while(!(REG(USB_CTRL) & USB_CTRL_PLL_LOCKED));
355 
356  /* Enable pull-up on usb port if driven by GPIO */
357 #if defined(USB_PULLUP_PORT_BASE) && defined(USB_PULLUP_PIN_MASK)
358  GPIO_SET_OUTPUT(USB_PULLUP_PORT_BASE, USB_PULLUP_PIN_MASK);
359  GPIO_SET_PIN(USB_PULLUP_PORT_BASE, USB_PULLUP_PIN_MASK);
360 #endif
361 
362  for(i = 0; i < USB_MAX_ENDPOINTS; i++) {
363  usb_endpoints[i].flags = 0;
364  usb_endpoints[i].event_process = 0;
365  }
366 
367  reset();
368 
369  /* Disable all EP interrupts, EP0 interrupt will be enabled later */
370  REG(USB_IIE) = 0;
371  REG(USB_OIE) = 0;
372 
373  /* Initialise the USB control structures */
374  if(USB_ARCH_CONF_DMA) {
375  /* Disable peripheral triggers for our channels */
378  }
379 
381 }
382 /*---------------------------------------------------------------------------*/
383 void
384 usb_submit_recv_buffer(uint8_t addr, usb_buffer *buffer)
385 {
386  usb_buffer **tailp;
387  uint8_t flag;
388  usb_endpoint_t *ep = EP_STRUCT(addr);
389 
390  if(!(ep->flags & USB_EP_FLAGS_ENABLED)) {
391  return;
392  }
393 
394  if(buffer->data == NULL && EP_HW_NUM(addr) == 0) {
395  if(buffer->flags & USB_BUFFER_NOTIFY) {
396  notify_ep_process(ep, USB_EP_EVENT_NOTIFICATION);
397  }
398  return;
399  }
400 
401  flag = disable_irq();
402 
403  tailp = &ep->buffer;
404  while(*tailp) {
405  tailp = &(*tailp)->next;
406  }
407  *tailp = buffer;
408  while(buffer) {
409  buffer->flags |= USB_BUFFER_SUBMITTED;
410  buffer = buffer->next;
411  }
412 
413  REG(USB_INDEX) = EP_HW_NUM(addr);
414  if(!EP_HW_NUM(ep->addr)) {
415  if(REG(USB_CS0) & USB_CS0_OUTPKT_RDY) {
416  ep0_interrupt_handler();
417  }
418  } else {
419  if(REG(USB_CSOL) & USB_CSOL_OUTPKT_RDY) {
420  out_ep_interrupt_handler(EP_HW_NUM(ep->addr));
421  }
422  }
423 
424  restore_irq(flag);
425 }
426 /*---------------------------------------------------------------------------*/
427 void
428 usb_submit_xmit_buffer(uint8_t addr, usb_buffer *buffer)
429 {
430  usb_buffer **tailp;
431  uint8_t flag;
432  uint8_t res;
433  usb_endpoint_t *ep = EP_STRUCT(addr);
434 
435  if(!(ep->flags & USB_EP_FLAGS_ENABLED)) {
436  return;
437  }
438 
439  flag = disable_irq();
440 
441  if(EP_HW_NUM(addr) == 0) {
442  if(buffer->data == NULL) {
443  /* We are asked to send a STATUS packet.
444  * But the USB hardware will do this automatically
445  * as soon as we release the HW FIFO. */
446  REG(USB_INDEX) = 0;
447  REG(USB_CS0) = USB_CS0_CLR_OUTPKT_RDY | USB_CS0_DATA_END;
448  notify_ep_process(ep, USB_EP_EVENT_NOTIFICATION);
449  restore_irq(flag);
450  return;
451  } else {
452  /* Release the HW FIFO */
453  REG(USB_INDEX) = 0;
454  REG(USB_CS0) = USB_CS0_CLR_OUTPKT_RDY;
455  }
456  }
457 
458  tailp = &ep->buffer;
459  while(*tailp) {
460  tailp = &(*tailp)->next;
461  }
462  *tailp = buffer;
463  while(buffer) {
464  buffer->flags |= USB_BUFFER_SUBMITTED | USB_BUFFER_IN;
465  buffer = buffer->next;
466  }
467 
468  REG(USB_INDEX) = EP_HW_NUM(ep->addr);
469  if(EP_HW_NUM(ep->addr)) {
470  res = ep_tx(EP_HW_NUM(ep->addr));
471  } else {
472  res = ep0_tx();
473  }
474 
475  restore_irq(flag);
476 
477  if(res & USB_WRITE_NOTIFY) {
478  notify_ep_process(ep, USB_EP_EVENT_NOTIFICATION);
479  }
480 }
481 /*---------------------------------------------------------------------------*/
482 static void
483 ep0_setup(void)
484 {
485  REG(USB_IIE) |= USB_IIE_EP0IE;
486 }
487 /*---------------------------------------------------------------------------*/
488 static void
489 in_ep_setup(uint8_t addr)
490 {
491  uint8_t ei = EP_HW_NUM(addr);
492  usb_endpoint_t *ep = EP_STRUCT(addr);
493 
494  /* Enable IN EP interrupt */
495  REG(USB_IIE) |= USBIIE_INEPxIE(ei);
496 
497  /* Set internal FIFO size */
498  REG(USB_MAXI) = ep->xfer_size / 8;
499 
500  if(IS_ISO_EP(ep)) {
501  REG(USB_CSIH) |= USB_CSOH_ISO;
502  } else {
503  REG(USB_CSIH) &= ~USB_CSOH_ISO;
504  }
505 }
506 /*---------------------------------------------------------------------------*/
507 static void
508 out_ep_setup(uint8_t addr)
509 {
510  uint8_t ei = EP_HW_NUM(addr);
511  usb_endpoint_t *ep = EP_STRUCT(addr);
512 
513  /* Enable OUT EP interrupt */
514  REG(USB_OIE) |= USBOIE_OUEPxIE(ei);
515 
516  /* Set internal FIFO size */
517  REG(USB_MAXO) = ep->xfer_size / 8;
518 
519  if(IS_ISO_EP(ep)) {
520  REG(USB_CSOH) |= USB_CSOH_ISO;
521  } else {
522  REG(USB_CSOH) &= ~USB_CSOH_ISO;
523  }
524 }
525 /*---------------------------------------------------------------------------*/
526 static void
527 ep_setup(uint8_t addr)
528 {
529  uint8_t ei = EP_HW_NUM(addr);
530  uint8_t flag;
531  usb_endpoint_t *ep = EP_STRUCT(addr);
532 
533  ep->halted = 0;
534  ep->flags |= USB_EP_FLAGS_ENABLED;
535  ep->buffer = 0;
536  ep->addr = addr;
537  ep->events = 0;
538  ep->xfer_size = ep_xfer_size[ei];
539 
540  flag = disable_irq();
541 
542  /* Select endpoint register */
543  REG(USB_INDEX) = ei;
544 
545  /* EP0 requires special handing */
546  if(ei == 0) {
547  ep0_setup();
548  } else {
549  if(addr & 0x80) {
550  in_ep_setup(addr);
551  } else {
552  out_ep_setup(addr);
553  }
554  }
555 
556  restore_irq(flag);
557 }
558 /*---------------------------------------------------------------------------*/
559 void
560 usb_arch_setup_iso_endpoint(uint8_t addr)
561 {
562  usb_endpoint_t *ep = EP_STRUCT(addr);
563 
564  ep->flags = USB_EP_FLAGS_TYPE_ISO;
565 
566  ep_setup(addr);
567 }
568 /*---------------------------------------------------------------------------*/
569 void
570 usb_arch_setup_control_endpoint(uint8_t addr)
571 {
572  usb_endpoint_t *ep = EP_STRUCT(addr);
573 
574  ep->flags = USB_EP_FLAGS_TYPE_CONTROL;
575 
576  ep_setup(addr);
577 }
578 /*---------------------------------------------------------------------------*/
579 void
580 usb_arch_setup_bulk_endpoint(uint8_t addr)
581 {
582  usb_endpoint_t *ep = EP_STRUCT(addr);
583 
584  ep->flags = USB_EP_FLAGS_TYPE_BULK;
585 
586  ep_setup(addr);
587 }
588 /*---------------------------------------------------------------------------*/
589 void
590 usb_arch_setup_interrupt_endpoint(uint8_t addr)
591 {
592  usb_endpoint_t *ep = EP_STRUCT(addr);
593 
594  ep->flags = USB_EP_FLAGS_TYPE_INTERRUPT;
595 
596  ep_setup(addr);
597 }
598 /*---------------------------------------------------------------------------*/
599 static void
600 ep0_dis(void)
601 {
602  REG(USB_IIE) &= ~USB_IIE_EP0IE;
603  /* Clear any pending status flags */
604  REG(USB_CS0) = 0xC0;
605 }
606 /*---------------------------------------------------------------------------*/
607 static void
608 in_ep_dis(uint8_t addr)
609 {
610  REG(USB_MAXI) = 0;
611  REG(USB_IIE) &= ~USBIIE_INEPxIE(EP_HW_NUM(addr));
612 
613  /* Flush pending */
614  REG(USB_CSIL) = USB_CSIL_FLUSH_PACKET;
615 }
616 /*---------------------------------------------------------------------------*/
617 static void
618 out_ep_dis(uint8_t addr)
619 {
620  REG(USB_MAXO) = 0;
621  REG(USB_OIE) &= ~USBOIE_OUEPxIE(EP_HW_NUM(addr));
622 
623  /* Flush pending */
624  REG(USB_CSOL) = USB_CSIL_FLUSH_PACKET;
625 }
626 /*---------------------------------------------------------------------------*/
627 void
628 usb_arch_disable_endpoint(uint8_t addr)
629 {
630  uint8_t ei = EP_HW_NUM(addr);
631  uint8_t flag;
632  usb_endpoint_t *ep = EP_STRUCT(addr);
633 
634  ep->flags &= ~USB_EP_FLAGS_ENABLED;
635 
636  flag = disable_irq();
637 
638  REG(USB_INDEX) = ei;
639  if(ei == 0) {
640  ep0_dis();
641  } else {
642  if(addr & 0x80) {
643  in_ep_dis(addr);
644  } else {
645  out_ep_dis(addr);
646  }
647  }
648  restore_irq(flag);
649 }
650 /*---------------------------------------------------------------------------*/
651 void
652 usb_arch_discard_all_buffers(uint8_t addr)
653 {
654  usb_buffer *buffer;
655  uint8_t flag;
656  volatile usb_endpoint_t *ep = EP_STRUCT(addr);
657 
658  flag = disable_irq();
659 
660  buffer = ep->buffer;
661  ep->buffer = NULL;
662  restore_irq(flag);
663 
664  while(buffer) {
665  buffer->flags &= ~USB_BUFFER_SUBMITTED;
666  buffer = buffer->next;
667  }
668 }
669 /*---------------------------------------------------------------------------*/
670 static void
671 set_stall(uint8_t addr, uint8_t stall)
672 {
673  uint8_t ei = EP_HW_NUM(addr);
674 
675  REG(USB_INDEX) = ei;
676  if(ei == 0) {
677  /* Stall is automatically deasserted on EP0 */
678  if(stall) {
679  ep0status = EP_STATUS_IDLE;
680  REG(USB_CS0) |= USB_CS0_SEND_STALL | USB_CS0_OUTPKT_RDY;
681  }
682  } else {
683  if(addr & 0x80) {
684  if(stall) {
685  REG(USB_CSIL) |= USB_CSIL_SEND_STALL;
686  } else {
687  REG(USB_CSIL) &= ~USB_CSIL_SEND_STALL;
688  }
689  } else {
690  if(stall) {
692  } else {
693  REG(USB_CSOL) &= ~USB_CSOL_SEND_STALL;
694  }
695  }
696  }
697 }
698 /*---------------------------------------------------------------------------*/
699 void
700 usb_arch_control_stall(uint8_t addr)
701 {
702  uint8_t ei = EP_HW_NUM(addr);
703  uint8_t flag;
704 
705  if(ei > USB_MAX_ENDPOINTS) {
706  return;
707  }
708 
709  flag = disable_irq();
710 
711  set_stall(addr, 1);
712 
713  restore_irq(flag);
714 }
715 /*---------------------------------------------------------------------------*/
716 void
717 usb_arch_halt_endpoint(uint8_t addr, int halt)
718 {
719  uint8_t ei = EP_HW_NUM(addr);
720  uint8_t flag;
721  usb_endpoint_t *ep = EP_STRUCT(addr);
722 
723  if(ei > USB_MAX_ENDPOINTS) {
724  return;
725  }
726 
727  if(!(ep->flags & USB_EP_FLAGS_ENABLED)) {
728  return;
729  }
730 
731  flag = disable_irq();
732 
733  if(halt) {
734  ep->halted = 0x1;
735  set_stall(addr, 1);
736  } else {
737  ep->halted = 0;
738  set_stall(addr, 0);
739 
740  if(ep->buffer && (ep->buffer->flags & USB_BUFFER_HALT)) {
741  ep->buffer->flags &= ~USB_BUFFER_SUBMITTED;
742  if(ep->buffer->flags & USB_BUFFER_NOTIFY) {
743  notify_ep_process(ep, USB_EP_EVENT_NOTIFICATION);
744  }
745  ep->buffer = ep->buffer->next;
746  }
747  if(ei) {
748  out_ep_interrupt_handler(EP_HW_NUM(addr));
749  }
750  }
751 
752  restore_irq(flag);
753 }
754 /*---------------------------------------------------------------------------*/
755 void
756 usb_arch_set_configuration(uint8_t usb_configuration_value)
757 {
758  return;
759 }
760 /*---------------------------------------------------------------------------*/
761 uint16_t
762 usb_arch_get_ep_status(uint8_t addr)
763 {
764  uint8_t ei = EP_INDEX(addr);
765  usb_endpoint_t *ep = EP_STRUCT(addr);
766 
767  if(ei > USB_MAX_ENDPOINTS) {
768  return 0;
769  }
770 
771  return ep->halted;
772 }
773 /*---------------------------------------------------------------------------*/
774 void
775 usb_arch_set_address(uint8_t addr)
776 {
777  REG(USB_ADDR) = addr;
778 }
779 /*---------------------------------------------------------------------------*/
780 int
781 usb_arch_send_pending(uint8_t addr)
782 {
783  uint8_t flag;
784  uint8_t ret;
785  uint8_t ei = EP_INDEX(addr);
786 
787  flag = disable_irq();
788 
789  REG(USB_INDEX) = ei;
790  if(ei == 0) {
791  ret = REG(USB_CS0) & USB_CS0_INPKT_RDY;
792  } else {
793  ret = REG(USB_CSIL) & USB_CSIL_INPKT_RDY;
794  }
795 
796  restore_irq(flag);
797 
798  return ret;
799 }
800 /*---------------------------------------------------------------------------*/
801 static unsigned int
802 get_receive_capacity(usb_buffer *buffer)
803 {
804  unsigned int capacity = 0;
805 
806  while(buffer &&
807  !(buffer->flags & (USB_BUFFER_IN | USB_BUFFER_SETUP | USB_BUFFER_HALT))) {
808  capacity += buffer->left;
809  buffer = buffer->next;
810  }
811  return capacity;
812 }
813 /*---------------------------------------------------------------------------*/
814 static usb_buffer *
815 skip_buffers_until(usb_buffer *buffer, unsigned int mask, unsigned int flags,
816  uint8_t *resp)
817 {
818  while(buffer && !((buffer->flags & mask) == flags)) {
819  buffer->flags &= ~USB_BUFFER_SUBMITTED;
820  buffer->flags |= USB_BUFFER_FAILED;
821  if(buffer->flags & USB_BUFFER_NOTIFY) {
822  *resp |= USB_READ_NOTIFY;
823  }
824  buffer = buffer->next;
825  }
826  return buffer;
827 }
828 /*---------------------------------------------------------------------------*/
829 static uint8_t
830 fill_buffers(usb_buffer *buffer, uint8_t hw_ep, unsigned int len,
831  uint8_t short_packet)
832 {
833  unsigned int t;
834  uint8_t res = 0;
835 
836  do {
837  if(buffer->left < len) {
838  t = buffer->left;
839  } else {
840  t = len;
841  }
842  len -= t;
843  buffer->left -= t;
844 
845  read_hw_buffer(buffer->data, hw_ep, t);
846 
847  buffer->data += t;
848 
849  if(len == 0) {
850  break;
851  }
852 
853  buffer->flags &= ~(USB_BUFFER_SUBMITTED | USB_BUFFER_SHORT_PACKET);
854  if(buffer->flags & USB_BUFFER_NOTIFY) {
855  res |= USB_READ_NOTIFY;
856  }
857  buffer = buffer->next;
858  } while(1);
859 
860  if(short_packet) {
861  buffer->flags |= USB_BUFFER_SHORT_PACKET;
862  }
863 
864  if((buffer->left == 0) || (buffer->flags & USB_BUFFER_PACKET_END)) {
865  buffer->flags &= ~USB_BUFFER_SUBMITTED;
866  if(buffer->flags & USB_BUFFER_NOTIFY) {
867  res |= USB_READ_NOTIFY;
868  }
869  buffer = buffer->next;
870  } else {
871  if(short_packet) {
872  if(buffer->left && !(buffer->flags & USB_BUFFER_SHORT_END)) {
873  buffer->flags |= USB_BUFFER_FAILED;
874  res |= USB_READ_FAIL;
875  }
876  buffer->flags &= ~USB_BUFFER_SUBMITTED;
877  if(buffer->flags & USB_BUFFER_NOTIFY) {
878  res |= USB_READ_NOTIFY;
879  }
880  buffer = buffer->next;
881  }
882  }
883 
884  usb_endpoints[hw_ep].buffer = buffer;
885 
886  return res;
887 }
888 /*---------------------------------------------------------------------------*/
889 static uint8_t
890 ep0_get_setup_pkt(void)
891 {
892  uint8_t res = 0;
893  usb_buffer *buffer =
894  skip_buffers_until(usb_endpoints[0].buffer, USB_BUFFER_SETUP,
895  USB_BUFFER_SETUP, &res);
896 
897  usb_endpoints[0].buffer = buffer;
898 
899  if(!buffer || buffer->left < 8) {
900  return USB_READ_BLOCK;
901  }
902 
903  read_hw_buffer(buffer->data, 0, 8);
904  buffer->left -= 8;
905 
906  buffer->flags &= ~USB_BUFFER_SUBMITTED;
907  if(buffer->flags & USB_BUFFER_NOTIFY) {
908  res |= USB_READ_NOTIFY;
909  }
910 
911  if(buffer->data[6] || buffer->data[7]) {
912  REG(USB_CS0) |= USB_CS0_CLR_OUTPKT_RDY;
913  ep0status = buffer->data[0] & 0x80 ? EP_STATUS_TX : EP_STATUS_RX;
914  }
915 
916  buffer->data += 8;
917 
918  usb_endpoints[0].buffer = buffer->next;
919 
920  return res;
921 }
922 /*---------------------------------------------------------------------------*/
923 static uint8_t
924 ep0_get_data_pkt(void)
925 {
926  uint8_t res = 0;
927  uint8_t short_packet = 0;
928  usb_buffer *buffer = usb_endpoints[0].buffer;
929  uint8_t len = REG(USB_CNT0);
930 
931  if(!buffer) {
932  return USB_READ_BLOCK;
933  }
934 
935  if(buffer->flags & (USB_BUFFER_SETUP | USB_BUFFER_IN)) {
936  buffer->flags |= USB_BUFFER_FAILED;
937  buffer->flags &= ~USB_BUFFER_SUBMITTED;
938  if(buffer->flags & USB_BUFFER_NOTIFY) {
939  res |= USB_READ_NOTIFY;
940  }
941  /* Flush the fifo */
942  while(len--) {
943  REG(USB_F0);
944  }
945  usb_endpoints[0].buffer = buffer->next;
946  /* Force data stage end */
947  REG(USB_CS0) |= USB_CS0_CLR_OUTPKT_RDY | USB_CS0_DATA_END;
948 
949  ep0status = EP_STATUS_IDLE;
950  return res;
951  }
952 
953  if(get_receive_capacity(buffer) < len) {
954  /* Wait until we queue more buffers */
955  return USB_READ_BLOCK;
956  }
957 
958  if(len < usb_endpoints[0].xfer_size) {
959  short_packet = 1;
960  }
961 
962  res = fill_buffers(buffer, 0, len, short_packet);
963 
964  if(short_packet) {
965  /* The usb-core will send a status packet, we will release the fifo at this stage */
966  ep0status = EP_STATUS_IDLE;
967  } else {
968  REG(USB_CS0) |= USB_CS0_CLR_OUTPKT_RDY;
969  }
970  return res;
971 }
972 /*---------------------------------------------------------------------------*/
973 static uint8_t
974 ep0_tx(void)
975 {
976  usb_buffer *buffer = usb_endpoints[0].buffer;
977  unsigned int len = usb_endpoints[0].xfer_size;
978  uint8_t data_end = 0;
979  uint8_t res = 0;
980 
981  /* If TX Fifo still busy or ep0 not in TX data stage don't do anything */
982  if((REG(USB_CS0) & USB_CS0_INPKT_RDY) || (ep0status != EP_STATUS_TX)) {
983  return 0;
984  }
985 
986  if(!buffer) {
987  return 0;
988  }
989 
990  if(!(buffer->flags & USB_BUFFER_IN)) {
991  /* We should TX but queued buffer is in RX */
992  return 0;
993  }
994 
995  while(buffer) {
996  unsigned int copy;
997 
998  if(buffer->left < len) {
999  copy = buffer->left;
1000  } else {
1001  copy = len;
1002  }
1003 
1004  len -= copy;
1005  buffer->left -= copy;
1006  write_hw_buffer(0, buffer->data, copy);
1007  buffer->data += copy;
1008  if(buffer->left == 0) {
1009  if(buffer->flags & USB_BUFFER_SHORT_END) {
1010  if(len == 0) {
1011  break; // We keep the buffer in queue so we will send a ZLP next time.
1012  } else {
1013  data_end = 1;
1014  len = 0; // Stop looking for more data to send
1015  }
1016  }
1017  buffer->flags &= ~USB_BUFFER_SUBMITTED;
1018  if(buffer->flags & USB_BUFFER_NOTIFY) {
1019  res |= USB_WRITE_NOTIFY;
1020  }
1021  buffer = buffer->next;
1022  }
1023  if(len == 0) {
1024  break; // FIFO is full, send packet.
1025  }
1026  }
1027  if(len) {
1028  data_end = 1;
1029  }
1030  usb_endpoints[0].buffer = buffer;
1031 
1032  /*
1033  * Workaround the fact that the usb controller do not like to have DATA_END
1034  * set after INPKT_RDY for the last packet. Thus if no more is in the queue
1035  * set DATA_END
1036  */
1037  if(data_end || !buffer) {
1038  ep0status = EP_STATUS_IDLE;
1039  REG(USB_CS0) |= USB_CS0_INPKT_RDY | USB_CS0_DATA_END;
1040  } else {
1041  REG(USB_CS0) |= USB_CS0_INPKT_RDY;
1042  }
1043 
1044  return res;
1045 }
1046 /*---------------------------------------------------------------------------*/
1047 static void
1048 ep0_interrupt_handler(void)
1049 {
1050  uint8_t cs0;
1051  uint8_t res;
1052 
1053  REG(USB_INDEX) = 0;
1054  cs0 = REG(USB_CS0);
1055  if(cs0 & USB_CS0_SENT_STALL) {
1056  /* Ack the stall */
1057  REG(USB_CS0) = 0;
1058  ep0status = EP_STATUS_IDLE;
1059  }
1060  if(cs0 & USB_CS0_SETUP_END) {
1061  /* Clear it */
1063  ep0status = EP_STATUS_IDLE;
1064  }
1065 
1066  if(cs0 & USB_CS0_OUTPKT_RDY) {
1067  if(ep0status == EP_STATUS_IDLE) {
1068  res = ep0_get_setup_pkt();
1069  } else {
1070  res = ep0_get_data_pkt();
1071  }
1072 
1073  if(res & USB_READ_NOTIFY) {
1074  notify_ep_process(&usb_endpoints[0], USB_EP_EVENT_NOTIFICATION);
1075  }
1076  if(res & USB_READ_BLOCK) {
1077  return;
1078  }
1079  }
1080 
1081  res = ep0_tx();
1082 
1083  if(res & USB_WRITE_NOTIFY) {
1084  notify_ep_process(&usb_endpoints[0], USB_EP_EVENT_NOTIFICATION);
1085  }
1086 }
1087 /*---------------------------------------------------------------------------*/
1088 static uint8_t
1089 ep_tx(uint8_t ep_hw)
1090 {
1091  unsigned int len;
1092  uint8_t res = 0;
1093  usb_endpoint_t *ep = EP_STRUCT(ep_hw);
1094 
1095  len = ep->xfer_size;
1096 
1097  if(ep->halted) {
1098  return 0;
1099  }
1100 
1101  if(!ep->buffer || !(ep->buffer->flags & USB_BUFFER_IN)) {
1102  return 0;
1103  }
1104 
1105  while(ep->buffer) {
1106  unsigned int copy;
1107 
1108  if(ep->buffer->left < len) {
1109  copy = ep->buffer->left;
1110  } else {
1111  copy = len;
1112  }
1113 
1114  len -= copy;
1115  ep->buffer->left -= copy;
1116 
1117  /* Delay somewhat if the previous packet has not yet left the IN FIFO */
1118  while(REG(USB_CSIL) & USB_CSIL_INPKT_RDY);
1119 
1120  write_hw_buffer(EP_INDEX(ep_hw), ep->buffer->data, copy);
1121  ep->buffer->data += copy;
1122 
1123  if(ep->buffer->left == 0) {
1124  if(ep->buffer->flags & USB_BUFFER_SHORT_END) {
1125  if(len == 0) {
1126  /* We keep the buffer in queue so we will send a ZLP next */
1127  break;
1128  } else {
1129  /* Stop looking for more data to send */
1130  len = 0;
1131  }
1132  }
1133  ep->buffer->flags &= ~USB_BUFFER_SUBMITTED;
1134  if(ep->buffer->flags & USB_BUFFER_NOTIFY) {
1135  res |= USB_WRITE_NOTIFY;
1136  }
1137  ep->buffer = ep->buffer->next;
1138  }
1139  if(len == 0) {
1140  /* FIFO full, send */
1141  break;
1142  }
1143  }
1144 
1145  REG(USB_CSIL) |= USB_CSIL_INPKT_RDY;
1146 
1147  return res;
1148 }
1149 /*---------------------------------------------------------------------------*/
1150 static uint8_t
1151 ep_get_data_pkt(uint8_t ep_hw)
1152 {
1153  uint16_t pkt_len;
1154  uint8_t res;
1155  uint8_t short_packet = 0;
1156  usb_endpoint_t *ep = EP_STRUCT(ep_hw);
1157 
1158  if(!ep->buffer) {
1159  return USB_READ_BLOCK;
1160  }
1161 
1162  if(ep->buffer->flags & USB_BUFFER_HALT) {
1163  ep->halted = 1;
1164  if(!(REG(USB_CSOL) & USB_CSOL_SEND_STALL)) {
1165  REG(USB_CSOL) |= USB_CSOL_SEND_STALL;
1166  }
1167  return 0;
1168  }
1169 
1170  /* Disambiguate UG CNTL bits */
1171  pkt_len = REG(USB_CNTL) | (REG(USB_CNTH) << 8);
1172  if(get_receive_capacity(ep->buffer) < pkt_len) {
1173  return USB_READ_BLOCK;
1174  }
1175 
1176  if(pkt_len < ep->xfer_size) {
1177  short_packet = 1;
1178  }
1179 
1180  res = fill_buffers(ep->buffer, ep_hw, pkt_len, short_packet);
1181 
1182  REG(USB_CSOL) &= ~USB_CSOL_OUTPKT_RDY;
1183 
1184  return res;
1185 }
1186 /*---------------------------------------------------------------------------*/
1187 static void
1188 out_ep_interrupt_handler(uint8_t ep_hw)
1189 {
1190  uint8_t csl;
1191  uint8_t res;
1192  usb_endpoint_t *ep = EP_STRUCT(ep_hw);
1193 
1194 
1195  REG(USB_INDEX) = ep_hw;
1196  csl = REG(USB_CSOL);
1197 
1198  if(csl & USB_CSOL_SENT_STALL) {
1199  REG(USB_CSOL) &= ~USB_CSOL_SENT_STALL;
1200  }
1201 
1202  if(csl & USB_CSOL_OVERRUN) {
1203  /* We lost one isochronous packet */
1204  REG(USB_CSOL) &= ~USB_CSOL_OVERRUN;
1205  }
1206 
1207  if(csl & USB_CSOL_OUTPKT_RDY) {
1208  res = ep_get_data_pkt(ep_hw);
1209 
1210  if(res & USB_READ_NOTIFY) {
1211  notify_ep_process(ep, USB_EP_EVENT_NOTIFICATION);
1212  }
1213  }
1214 }
1215 /*---------------------------------------------------------------------------*/
1216 static void
1217 in_ep_interrupt_handler(uint8_t ep_hw)
1218 {
1219  uint8_t csl;
1220 #if USB_ARCH_WRITE_NOTIFY
1221  uint8_t res;
1222  usb_endpoint_t *ep = EP_STRUCT(ep_hw);
1223 #endif
1224 
1225  REG(USB_INDEX) = ep_hw;
1226  csl = REG(USB_CSIL);
1227 
1228  if(csl & USB_CSIL_SENT_STALL) {
1229  REG(USB_CSIL) &= ~USB_CSIL_SENT_STALL;
1230  }
1231 
1232  if(csl & USB_CSIL_UNDERRUN) {
1233  REG(USB_CSIL) &= ~USB_CSIL_UNDERRUN;
1234  }
1235 
1236 #if USB_ARCH_WRITE_NOTIFY
1237  if(!(csl & USB_CSIL_INPKT_RDY)) {
1238  res = ep_tx(ep_hw);
1239  if(res & USB_WRITE_NOTIFY) {
1240  notify_ep_process(ep, USB_EP_EVENT_NOTIFICATION);
1241  }
1242  }
1243 #endif
1244 }
1245 /*---------------------------------------------------------------------------*/
1246 void
1247 usb_isr(void)
1248 {
1249  uint8_t ep_in_if = REG(USB_IIF) & REG(USB_IIE);
1250  uint8_t ep_out_if = REG(USB_OIF) & REG(USB_OIE);
1251  uint8_t common_if = REG(USB_CIF) & REG(USB_CIE);
1252  uint8_t i;
1253 
1254  if(ep_in_if) {
1255  /* EP0 flag is in the IN Interrupt Flags register */
1256  if(ep_in_if & USB_IIF_EP0IF) {
1257  ep0_interrupt_handler();
1258  }
1259  for(i = 1; i < 6; i++) {
1260  if(ep_in_if & EPxIF(i)) {
1261  in_ep_interrupt_handler(i);
1262  }
1263  }
1264  }
1265  if(ep_out_if) {
1266  for(i = 1; i < 6; i++) {
1267  if(ep_out_if & EPxIF(i)) {
1268  out_ep_interrupt_handler(i);
1269  }
1270  }
1271  }
1272  if(common_if & USB_CIF_RSTIF) {
1273  reset();
1274  notify_process(USB_EVENT_RESET);
1275  }
1276  if(common_if & USB_CIF_RESUMEIF) {
1277  notify_process(USB_EVENT_RESUME);
1278  }
1279  if(common_if & USB_CIF_SUSPENDIF) {
1280  notify_process(USB_EVENT_SUSPEND);
1281  }
1282 }
1283 /*---------------------------------------------------------------------------*/
1284 
1285 /** @} */
#define USB_IIE_EP0IE
EP0 interrupt enable.
Definition: usb-regs.h:165
Header file for the ARM Nested Vectored Interrupt Controller.
#define USB_IIE
IN EPs and EP0 interrupt mask.
Definition: usb-regs.h:59
void udma_set_channel_dst(uint8_t channel, uint32_t dst_end)
Sets the channel&#39;s destination address.
Definition: udma.c:80
#define USB_CNT0
Number of RX bytes in EP0 FIFO (Alias for USB_CNT0_CNTL)
Definition: usb-regs.h:85
#define GPIO_SET_PIN(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE high.
Definition: gpio.h:106
#define USB_CS0_CLR_SETUP_END
Listed as reserved in the UG, is this right?
Definition: usb-regs.h:231
#define USB_CSIH
IN EPs control and status (high)
Definition: usb-regs.h:76
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107
Header file with register and macro declarations for the cc2538 GPIO module.
#define USB_CIF_SUSPENDIF
Suspend interrupt flag.
Definition: usb-regs.h:153
#define USB_F0
Endpoint-0 FIFO.
Definition: usb-regs.h:96
#define USB_CNTL
Number of bytes in EP{1-5} OUT FIFO (low) (Alias for USB_CNT0_CNTL)
Definition: usb-regs.h:88
#define USB_CSOL_SENT_STALL
STALL handshake sent.
Definition: usb-regs.h:310
#define USB_CIE
Common USB interrupt mask.
Definition: usb-regs.h:61
#define USB_CNTH
Number of bytes in EP{1-5} OUT FIFO (high)
Definition: usb-regs.h:93
Header file with declarations for the I/O Control module.
#define USB_CTRL_PLL_LOCKED
PLL locked status.
Definition: usb-regs.h:214
#define USB_CSOL_OVERRUN
OUT packet can not be loaded into OUT FIFO.
Definition: usb-regs.h:314
#define USB_INDEX
Current endpoint index register.
Definition: usb-regs.h:64
Header file with register manipulation macro definitions.
#define USB_CS0
EP0 Control and Status (Alias for USB_CS0_CSIL)
Definition: usb-regs.h:70
#define USB_CSOH_ISO
Selects OUT endpoint type.
Definition: usb-regs.h:324
#define USB_CSOL
OUT EPs control and status (low)
Definition: usb-regs.h:78
Header file with register, macro and function declarations for the cc2538 micro-DMA controller module...
void udma_channel_mask_set(uint8_t channel)
Disable peripheral triggers for a uDMA channel.
Definition: udma.c:204
__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
Disable External Interrupt.
Definition: core_cm0.h:653
#define USB_CTRL_USB_EN
USB enable.
Definition: usb-regs.h:216
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
Enable External Interrupt.
Definition: core_cm0.h:642
void udma_set_channel_src(uint8_t channel, uint32_t src_end)
Sets the channels source address.
Definition: udma.c:70
__STATIC_INLINE uint32_t NVIC_IsIRQEnabled(IRQn_Type IRQn)
Get External Interrupt Enable State.
Definition: core_cm0.h:631
#define USB_ARCH_CONF_DMA
Change to Enable/Disable USB DMA.
Definition: cc2538-conf.h:84
#define USB_MAXI
MAX packet size for IN EPs{1-5}.
Definition: usb-regs.h:66
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
#define USB_OIE
Out EPs interrupt-enable mask.
Definition: usb-regs.h:60
#define USB_ARCH_CONF_RX_DMA_CHAN
USB -> RAM DMA channel.
Definition: cc2538-conf.h:93
#define USB_IIF_EP0IF
EP0 Interrupt flag.
Definition: usb-regs.h:132
void udma_channel_enable(uint8_t channel)
Enables a uDMA channel.
Definition: udma.c:120
#define USB_CSIL
IN EPs control and status (low) (Alias for USB_CS0_CSIL)
Definition: usb-regs.h:73
#define USB_OIF
OUT endpoint interrupt flags.
Definition: usb-regs.h:57
#define GPIO_SET_OUTPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to output.
Definition: gpio.h:85
void udma_channel_sw_request(uint8_t channel)
Generate a software trigger to start a transfer.
Definition: udma.c:225
#define USB_CTRL
USB control register.
Definition: usb-regs.h:65
Header file with declarations for the cc2538 USB registers.
#define USB_MAXO
MAX packet size for OUT EPs.
Definition: usb-regs.h:77
#define USB_CIF
Common USB interrupt flags.
Definition: usb-regs.h:58
#define USB_ADDR
Function address.
Definition: usb-regs.h:54
#define USB_CTRL_PLL_EN
48-MHz USB PLL enable
Definition: usb-regs.h:215
#define USB_ARCH_CONF_TX_DMA_CHAN
RAM -> USB DMA channel.
Definition: cc2538-conf.h:94
#define USB_CSOL_OUTPKT_RDY
OUT packet read in OUT FIFO.
Definition: usb-regs.h:316
#define USB_CIF_RSTIF
Reset interrupt flag.
Definition: usb-regs.h:151
void udma_set_channel_control_word(uint8_t channel, uint32_t ctrl)
Configure the channel&#39;s control word.
Definition: udma.c:90
#define udma_xfer_size(len)
Calculate the value of the xfersize field in the control structure.
Definition: udma.h:697
uint8_t udma_channel_get_mode(uint8_t channel)
Retrieve the current mode for a channel.
Definition: udma.c:235
USB Interrupt.
Definition: cc2538_cm3.h:108
#define USB_CSOL_SEND_STALL
Reply with STALL to OUT tokens.
Definition: usb-regs.h:311
#define USB_IIF
IN EPs and EP0 interrupt flags.
Definition: usb-regs.h:56
#define USB_CIF_RESUMEIF
Resume interrupt flag.
Definition: usb-regs.h:152
#define USB_CSOH
OUT EPs control and status (high)
Definition: usb-regs.h:79