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/*---------------------------------------------------------------------------*/
100static 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/*---------------------------------------------------------------------------*/
109typedef struct _USBBuffer usb_buffer;
110/*---------------------------------------------------------------------------*/
111struct 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};
120typedef 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/*---------------------------------------------------------------------------*/
158static usb_endpoint_t usb_endpoints[USB_MAX_ENDPOINTS];
159struct process *event_process = 0;
160volatile static unsigned int events = 0;
161static uint8_t ep0status;
162/*---------------------------------------------------------------------------*/
163static uint8_t ep0_tx(void);
164static uint8_t ep_tx(uint8_t ep_hw);
165static void in_ep_interrupt_handler(uint8_t ep_hw);
166static void out_ep_interrupt_handler(uint8_t ep_hw);
167static void ep0_interrupt_handler(void);
168/*---------------------------------------------------------------------------*/
169static uint8_t
170disable_irq(void)
171{
172 uint8_t enabled = NVIC_GetEnableIRQ(USB_IRQn);
173 if(enabled) {
174 NVIC_DisableIRQ(USB_IRQn);
175 }
176 return enabled;
177}
178/*---------------------------------------------------------------------------*/
179static void
180restore_irq(uint8_t enabled)
181{
182 if(enabled) {
183 NVIC_EnableIRQ(USB_IRQn);
184 }
185}
186/*---------------------------------------------------------------------------*/
187static void
188notify_process(unsigned int e)
189{
190 events |= e;
191 if(event_process) {
192 process_poll(event_process);
193 }
194}
195/*---------------------------------------------------------------------------*/
196static void
197notify_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/*---------------------------------------------------------------------------*/
205void
206usb_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/*---------------------------------------------------------------------------*/
213void
214usb_arch_set_global_event_process(struct process *p)
215{
216 event_process = p;
217}
218/*---------------------------------------------------------------------------*/
219unsigned int
220usb_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/*---------------------------------------------------------------------------*/
235unsigned int
236usb_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/*---------------------------------------------------------------------------*/
252static void
253read_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/*---------------------------------------------------------------------------*/
282static void
283write_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/*---------------------------------------------------------------------------*/
312static void
313reset(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/*---------------------------------------------------------------------------*/
332static bool
333permit_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 */
343void
344usb_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 */
375 /* Disable peripheral triggers for our channels */
378 }
379
380 NVIC_EnableIRQ(USB_IRQn);
381}
382/*---------------------------------------------------------------------------*/
383void
384usb_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/*---------------------------------------------------------------------------*/
427void
428usb_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/*---------------------------------------------------------------------------*/
482static void
483ep0_setup(void)
484{
485 REG(USB_IIE) |= USB_IIE_EP0IE;
486}
487/*---------------------------------------------------------------------------*/
488static void
489in_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/*---------------------------------------------------------------------------*/
507static void
508out_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/*---------------------------------------------------------------------------*/
526static void
527ep_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/*---------------------------------------------------------------------------*/
559void
560usb_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/*---------------------------------------------------------------------------*/
569void
570usb_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/*---------------------------------------------------------------------------*/
579void
580usb_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/*---------------------------------------------------------------------------*/
589void
590usb_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/*---------------------------------------------------------------------------*/
599static void
600ep0_dis(void)
601{
602 REG(USB_IIE) &= ~USB_IIE_EP0IE;
603 /* Clear any pending status flags */
604 REG(USB_CS0) = 0xC0;
605}
606/*---------------------------------------------------------------------------*/
607static void
608in_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/*---------------------------------------------------------------------------*/
617static void
618out_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/*---------------------------------------------------------------------------*/
627void
628usb_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/*---------------------------------------------------------------------------*/
651void
652usb_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/*---------------------------------------------------------------------------*/
670static void
671set_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/*---------------------------------------------------------------------------*/
699void
700usb_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/*---------------------------------------------------------------------------*/
716void
717usb_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/*---------------------------------------------------------------------------*/
755void
756usb_arch_set_configuration(uint8_t usb_configuration_value)
757{
758 return;
759}
760/*---------------------------------------------------------------------------*/
761uint16_t
762usb_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/*---------------------------------------------------------------------------*/
774void
775usb_arch_set_address(uint8_t addr)
776{
777 REG(USB_ADDR) = addr;
778}
779/*---------------------------------------------------------------------------*/
780int
781usb_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/*---------------------------------------------------------------------------*/
801static unsigned int
802get_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/*---------------------------------------------------------------------------*/
814static usb_buffer *
815skip_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/*---------------------------------------------------------------------------*/
829static uint8_t
830fill_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/*---------------------------------------------------------------------------*/
889static uint8_t
890ep0_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/*---------------------------------------------------------------------------*/
923static uint8_t
924ep0_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/*---------------------------------------------------------------------------*/
973static uint8_t
974ep0_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/*---------------------------------------------------------------------------*/
1047static void
1048ep0_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/*---------------------------------------------------------------------------*/
1088static uint8_t
1089ep_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/*---------------------------------------------------------------------------*/
1150static uint8_t
1151ep_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)) {
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/*---------------------------------------------------------------------------*/
1187static void
1188out_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/*---------------------------------------------------------------------------*/
1216static void
1217in_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/*---------------------------------------------------------------------------*/
1246void
1247usb_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/** @} */
Header file with register and macro declarations for the cc2538 GPIO module.
@ USB_IRQn
USB Interrupt.
Definition: cc2538_cm3.h:108
#define GPIO_SET_PIN(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE high.
Definition: gpio.h:106
#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_set_channel_dst(uint8_t channel, uint32_t dst_end)
Sets the channel's destination address.
Definition: udma.c:80
void udma_channel_mask_set(uint8_t channel)
Disable peripheral triggers for a uDMA channel.
Definition: udma.c:204
void udma_channel_enable(uint8_t channel)
Enables a uDMA channel.
Definition: udma.c:120
uint8_t udma_channel_get_mode(uint8_t channel)
Retrieve the current mode for a channel.
Definition: udma.c:235
void udma_channel_sw_request(uint8_t channel)
Generate a software trigger to start a transfer.
Definition: udma.c:225
void udma_set_channel_control_word(uint8_t channel, uint32_t ctrl)
Configure the channel'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
void udma_set_channel_src(uint8_t channel, uint32_t src_end)
Sets the channels source address.
Definition: udma.c:70
#define USB_CSOL
OUT EPs control and status (low)
Definition: usb-regs.h:75
#define USB_CSOH_ISO
Selects OUT endpoint type.
Definition: usb-regs.h:315
#define USB_CIF_RSTIF
Reset interrupt flag.
Definition: usb-regs.h:142
#define USB_CTRL_PLL_EN
48-MHz USB PLL enable
Definition: usb-regs.h:206
#define USB_INDEX
Current endpoint index register.
Definition: usb-regs.h:64
#define USB_CIF_RESUMEIF
Resume interrupt flag.
Definition: usb-regs.h:143
#define USB_IIE
IN EPs and EP0 interrupt mask.
Definition: usb-regs.h:59
#define USB_CSIH
IN EPs control and status (high)
Definition: usb-regs.h:73
#define USB_F0
Endpoint-0 FIFO.
Definition: usb-regs.h:87
#define USB_CNT0
Number of RX bytes in EP0 FIFO (Alias for USB_CNT0_CNTL)
Definition: usb-regs.h:80
#define USB_CTRL_USB_EN
USB enable.
Definition: usb-regs.h:207
#define USB_IIE_EP0IE
EP0 interrupt enable.
Definition: usb-regs.h:156
#define USB_CIF
Common USB interrupt flags.
Definition: usb-regs.h:58
#define USB_OIF
OUT endpoint interrupt flags.
Definition: usb-regs.h:57
#define USB_IIF
IN EPs and EP0 interrupt flags.
Definition: usb-regs.h:56
#define USB_CSOL_SENT_STALL
STALL handshake sent.
Definition: usb-regs.h:301
#define USB_IIF_EP0IF
EP0 Interrupt flag.
Definition: usb-regs.h:123
#define USB_CSOL_SEND_STALL
Reply with STALL to OUT tokens.
Definition: usb-regs.h:302
#define USB_CTRL_PLL_LOCKED
PLL locked status.
Definition: usb-regs.h:205
#define USB_CS0_CLR_SETUP_END
Listed as reserved in the UG, is this right?
Definition: usb-regs.h:222
#define USB_CSOL_OVERRUN
OUT packet can not be loaded into OUT FIFO.
Definition: usb-regs.h:305
#define USB_CTRL
USB control register.
Definition: usb-regs.h:65
#define USB_CNTH
Number of bytes in EP{1-5} OUT FIFO (high)
Definition: usb-regs.h:85
#define USB_CNTL
Number of bytes in EP{1-5} OUT FIFO (low) (Alias for USB_CNT0_CNTL)
Definition: usb-regs.h:82
#define USB_MAXI
MAX packet size for IN EPs{1-5}.
Definition: usb-regs.h:66
#define USB_CSIL
IN EPs control and status (low) (Alias for USB_CS0_CSIL)
Definition: usb-regs.h:71
#define USB_CIF_SUSPENDIF
Suspend interrupt flag.
Definition: usb-regs.h:144
#define USB_MAXO
MAX packet size for OUT EPs.
Definition: usb-regs.h:74
#define USB_CSOL_OUTPKT_RDY
OUT packet read in OUT FIFO.
Definition: usb-regs.h:307
#define USB_ADDR
Function address.
Definition: usb-regs.h:54
#define USB_CSOH
OUT EPs control and status (high)
Definition: usb-regs.h:76
#define USB_CIE
Common USB interrupt mask.
Definition: usb-regs.h:61
#define USB_OIE
Out EPs interrupt-enable mask.
Definition: usb-regs.h:60
#define USB_CS0
EP0 Control and Status (Alias for USB_CS0_CSIL)
Definition: usb-regs.h:69
#define USB_ARCH_CONF_DMA
Change to Enable/Disable USB DMA.
Definition: cc2538-conf.h:84
#define USB_ARCH_CONF_TX_DMA_CHAN
RAM -> USB DMA channel.
Definition: cc2538-conf.h:94
#define USB_ARCH_CONF_RX_DMA_CHAN
USB -> RAM DMA channel.
Definition: cc2538-conf.h:93
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
Header file with declarations for the I/O Control module.
Header file for the ARM Nested Vectored Interrupt Controller.
Header file with register manipulation macro definitions.
Header file with register, macro and function declarations for the cc2538 micro-DMA controller module...
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107
Header file with declarations for the cc2538 USB registers.