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