Date:2011-02-14 16:01:11 (8 years 8 months ago)
Author:Werner Almesberger
Commit:983d3302949f9c1fd73a5fbf7a25829bef9ba6db
Message:atusb/fw3: split USB driver into chip-specifc and general part

- usb/usb.c: moved chip-specific functions to usb/atu2.c
- Makefile (USB_OBJS): added usb/atu2.c
- usb/usb.h, usb/usb.c, ep0.c: made argument to my_setup and user_setup
"const"
- usb/ubs.h (handle_setup): call from chip driver to generic stack
- usb/ubs.h (set_addr): call from generic stack to chip driver
Files: atusb/fw3/Makefile (1 diff)
atusb/fw3/ep0.c (1 diff)
atusb/fw3/usb/atu2.c (1 diff)
atusb/fw3/usb/usb.c (9 diffs)
atusb/fw3/usb/usb.h (2 diffs)

Change Details

atusb/fw3/Makefile
2424OBJCOPY = $(AVR_PREFIX)objcopy
2525#OBJDUMP = $(AVR_PREFIX)objdump
2626
27USB_OBJS = usb.o
27USB_OBJS = usb.o atu2.o
2828OBJS = atusb.o board.o spi.o descr.o ep0.o $(USB_OBJS)
2929
3030vpath %.c usb/
atusb/fw3/ep0.c
5757#define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */
5858
5959
60static int my_setup(struct setup_request *setup)
60static int my_setup(const struct setup_request *setup)
6161{
6262    unsigned tmp;
6363    uint8_t i;
atusb/fw3/usb/atu2.c
1/*
2 * u/atu2.c - Chip-specific driver for Atmel ATxxxU2 USB chips
3 *
4 * Written 2008-2011 by Werner Almesberger
5 * Copyright 2008-2011 Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13/*
14 * Known issues:
15 * - no suspend/resume
16 * - EP0-sized packets cause an (otherwise harmless) SUEND at the end of the
17 * packet
18 * - #ifdef hell
19 */
20
21/*
22 * This code follows the register read/write sequences from the examples in
23 * SiLabs/MCU/Examples/C8051F326_7/USB_Interrupt/Firmware/F326_USB_Main.c and
24 * SiLabs/MCU/Examples/C8051F326_7/USB_Interrupt/Firmware/F326_USB_ISR.c
25 *
26 * More resources:
27 * http://www.beyondlogic.org/usbnutshell/usb1.htm
28 */
29
30#include <stdint.h>
31
32#define F_CPU 8000000UL
33#include <util/delay.h>
34
35#include <avr/io.h>
36#include "usb.h"
37#include "../board.h"
38
39
40#ifndef NULL
41#define NULL 0
42#endif
43
44#if 1
45#define BUG_ON(cond) do { if (cond) panic(); } while (0)
46#else
47#define BUG_ON(cond)
48#endif
49
50
51#define NUM_EPS 1
52
53
54struct ep_descr eps[NUM_EPS];
55
56
57static uint16_t usb_read_word(void)
58{
59    uint8_t low;
60
61    low = UEDATX;
62    return low | UEDATX << 8;
63}
64
65
66static void enable_addr(void *user)
67{
68    while (!(UEINTX & (1 << TXINI)));
69    UDADDR |= 1 << ADDEN;
70}
71
72
73int set_addr(uint8_t addr)
74{
75    UDADDR = addr;
76    usb_send(&eps[0], NULL, 0, enable_addr, NULL);
77    return 1;
78}
79
80
81static int ep_setup(void)
82{
83    struct setup_request setup;
84
85    BUG_ON(UEBCLX < 8);
86
87    setup.bmRequestType = UEDATX;
88    setup.bRequest = UEDATX;
89    setup.wValue = usb_read_word();
90    setup.wIndex = usb_read_word();
91    setup.wLength = usb_read_word();
92
93    if (!handle_setup(&setup))
94        return 0;
95    if (!(setup.bmRequestType & 0x80) && eps[0].state == EP_IDLE)
96        usb_send(&eps[0], NULL, 0, NULL, NULL);
97    return 1;
98}
99
100
101static int ep_rx(struct ep_descr *ep)
102{
103    uint8_t size;
104
105    size = UEBCLX;
106    if (size > ep->end-ep->buf)
107        return 0;
108    while (size--)
109        *ep->buf++ = UEDATX;
110    if (ep->buf == ep->end) {
111        ep->state = EP_IDLE;
112        if (ep->callback)
113            ep->callback(ep->user);
114        if (ep == &eps[0])
115            usb_send(ep, NULL, 0, NULL, NULL);
116    }
117    return 1;
118}
119
120
121static void ep_tx(struct ep_descr *ep)
122{
123    uint8_t size = ep->end-ep->buf;
124    uint8_t left;
125
126    if (size > ep->size)
127        size = ep->size;
128    for (left = size; left; left--)
129        UEDATX = *ep->buf++;
130    if (size == ep->size)
131        return;
132    ep->state = EP_IDLE;
133}
134
135
136static void handle_ep(int n)
137{
138    struct ep_descr *ep = eps+n;
139
140    UENUM = n;
141    if (UEINTX & (1 << RXSTPI)) {
142        /* @@@ EP_RX. EP_TX: cancel */
143        if (!ep_setup())
144            goto stall;
145        UEINTX &= ~(1 << RXSTPI);
146    }
147    if (UEINTX & (1 << RXOUTI)) {
148        /* @@ EP_TX: cancel */
149        if (ep->state != EP_RX)
150            goto stall;
151        if (!ep_rx(ep))
152            goto stall;
153// UEINTX &= ~(1 << RXOUTI);
154        UEINTX &= ~(1 << RXOUTI | 1 << FIFOCON);
155    }
156    if (UEINTX & (1 << STALLEDI)) {
157        ep->state = EP_IDLE;
158        UEINTX &= ~(1 << STALLEDI);
159    }
160    if (UEINTX & (1 << TXINI)) {
161        /* @@ EP_RX: cancel */
162        if (ep->state == EP_TX) {
163            ep_tx(ep);
164            UEINTX &= ~(1 << TXINI);
165            if (ep->state == EP_IDLE && ep->callback)
166                ep->callback(ep->user);
167        }
168    }
169    return;
170
171stall:
172    UEINTX &= ~(1 << RXSTPI | 1 << RXOUTI | 1 << STALLEDI);
173    ep->state = EP_IDLE;
174    UECONX |= 1 << STALLRQ;
175}
176
177
178void usb_poll(void)
179{
180    uint8_t flags, i;
181
182    flags = UEINT;
183    for (i = 0; i != NUM_EPS; i++)
184        if (1 || flags & (1 << i))
185            handle_ep(i);
186    /* @@@ USB bus reset */
187}
188
189
190static void ep_init(void)
191{
192    UENUM = 0;
193    UECONX = (1 << RSTDT) | (1 << EPEN); /* enable */
194    UECFG0X = 0; /* control, direction is ignored */
195    UECFG1X = 3 << EPSIZE0; /* 64 bytes */
196    UECFG1X |= 1 << ALLOC;
197
198    while (!(UESTA0X & (1 << CFGOK)));
199
200    eps[0].state = EP_IDLE;
201    eps[0].size = 64;
202}
203
204
205void usb_init(void)
206{
207    USBCON |= 1 << FRZCLK; /* freeze the clock */
208
209    /* enable the PLL and wait for it to lock */
210    PLLCSR &= ~(1 << PLLP2 | 1 << PLLP1 | 1 << PLLP0);
211    PLLCSR |= 1 << PLLE;
212    while (!(PLLCSR & (1 << PLOCK)));
213
214    USBCON &= ~(1 << USBE); /* reset the controller */
215    USBCON |= 1 << USBE;
216
217    USBCON &= ~(1 << FRZCLK); /* thaw the clock */
218
219    UDCON &= ~(1 << DETACH); /* attach the pull-up */
220    UDCON |= 1 << RSTCPU; /* reset CPU on bus reset */
221
222    ep_init();
223}
atusb/fw3/usb/usb.c
2929
3030#include <stdint.h>
3131
32#define F_CPU 8000000UL
33#include <util/delay.h>
34
35#include <avr/io.h>
3632#include "usb.h"
3733#include "../board.h"
3834
...... 
5046#define BUG_ON(cond)
5147#endif
5248
53struct ep_descr eps[5];
54
55int (*user_setup)(struct setup_request *setup);
49int (*user_setup)(const struct setup_request *setup);
5650int (*user_get_descriptor)(uint8_t type, uint8_t index,
5751    const uint8_t * const *reply, uint8_t *size);
5852void (*user_reset)(void);
5953
6054
61static uint8_t addr;
62
63
6455void usb_io(struct ep_descr *ep, enum ep_state state, uint8_t *buf,
6556    uint8_t size, void (*callback)(void *user), void *user)
6657{
...... 
7364}
7465
7566
76static uint16_t usb_read_word(void)
77{
78    uint8_t low;
79
80    low = UEDATX;
81    return low | UEDATX << 8;
82}
83
84
8567static int get_descriptor(uint8_t type, uint8_t index, uint16_t length)
8668{
8769    const uint8_t *reply;
...... 
11193}
11294
11395
114static void enable_addr(void *user)
115{
116    while (!(UEINTX & (1 << TXINI)));
117    UDADDR = addr | 1 << ADDEN;
118}
119
120
121/*
122 * Process a SETUP packet. Hardware ensures that length is 8 bytes.
123 */
124
125
126static int handle_setup(void)
96int handle_setup(const struct setup_request *setup)
12797{
128    struct setup_request setup;
129
130    BUG_ON(UEBCLX < 8);
131
132    setup.bmRequestType = UEDATX;
133    setup.bRequest = UEDATX;
134    setup.wValue = usb_read_word();
135    setup.wIndex = usb_read_word();
136    setup.wLength = usb_read_word();
137
138// UEINTX &= ~(1 << RXSTPI);
139
140    switch (setup.bmRequestType | setup.bRequest << 8) {
98    switch (setup->bmRequestType | setup->bRequest << 8) {
14199
142100    /*
143101     * Device request
...... 
146104     */
147105
148106    case FROM_DEVICE(GET_STATUS):
149        if (setup.wLength != 2)
107        if (setup->wLength != 2)
150108            return 0;
151109        usb_send(&eps[0], "\000", 2, NULL, NULL);
152110        break;
...... 
155113    case TO_DEVICE(SET_FEATURE):
156114        return 0;
157115    case TO_DEVICE(SET_ADDRESS):
158        addr = setup.wValue;
159        UDADDR = addr;
160        usb_send(&eps[0], NULL, 0, enable_addr, NULL);
116        set_addr(setup->wValue);
161117        break;
162118    case FROM_DEVICE(GET_DESCRIPTOR):
163        if (!get_descriptor(setup.wValue >> 8, setup.wValue,
164            setup.wLength))
119        if (!get_descriptor(setup->wValue >> 8, setup->wValue,
120            setup->wLength))
165121            return 0;
166122        break;
167123    case TO_DEVICE(SET_DESCRIPTOR):
...... 
170126        usb_send(&eps[0], "", 1, NULL, NULL);
171127        break;
172128    case TO_DEVICE(SET_CONFIGURATION):
173        if (setup.wValue != config_descriptor[5])
129        if (setup->wValue != config_descriptor[5])
174130            return 0;
175131        break;
176132
...... 
191147            const uint8_t *interface_descriptor =
192148                config_descriptor+9;
193149
194            if (setup.wIndex != interface_descriptor[2] ||
195                setup.wValue != interface_descriptor[3])
150            if (setup->wIndex != interface_descriptor[2] ||
151                setup->wValue != interface_descriptor[3])
196152                return 0;
197153        }
198154        break;
...... 
213169    default:
214170        if (!user_setup)
215171            return 0;
216        if (!user_setup(&setup))
217            return 0;
172        return user_setup(setup);
218173    }
219174
220    if (!(setup.bmRequestType & 0x80) && eps[0].state == EP_IDLE)
221        usb_send(&eps[0], NULL, 0, NULL, NULL);
222175    return 1;
223176}
224
225
226static int ep_rx(struct ep_descr *ep)
227{
228    uint8_t size;
229
230    size = UEBCLX;
231    if (size > ep->end-ep->buf)
232        return 0;
233    while (size--)
234        *ep->buf++ = UEDATX;
235    if (ep->buf == ep->end) {
236        ep->state = EP_IDLE;
237        if (ep->callback)
238            ep->callback(ep->user);
239        if (ep == &eps[0])
240            usb_send(ep, NULL, 0, NULL, NULL);
241    }
242    return 1;
243}
244
245
246static void ep_tx(struct ep_descr *ep)
247{
248    uint8_t size = ep->end-ep->buf;
249    uint8_t left;
250
251    if (size > ep->size)
252        size = ep->size;
253    for (left = size; left; left--)
254        UEDATX = *ep->buf++;
255    if (size == ep->size)
256        return;
257    ep->state = EP_IDLE;
258}
259
260
261static void handle_ep(int n)
262{
263    struct ep_descr *ep = eps+n;
264
265    UENUM = n;
266    if (UEINTX & (1 << RXSTPI)) {
267        /* @@@ EP_RX. EP_TX: cancel */
268        if (!handle_setup())
269            goto stall;
270        UEINTX &= ~(1 << RXSTPI);
271    }
272    if (UEINTX & (1 << RXOUTI)) {
273        /* @@ EP_TX: cancel */
274        if (ep->state != EP_RX)
275            goto stall;
276        if (!ep_rx(ep))
277            goto stall;
278// UEINTX &= ~(1 << RXOUTI);
279        UEINTX &= ~(1 << RXOUTI | 1 << FIFOCON);
280    }
281    if (UEINTX & (1 << STALLEDI)) {
282        ep->state = EP_IDLE;
283        UEINTX &= ~(1 << STALLEDI);
284    }
285    if (UEINTX & (1 << TXINI)) {
286        /* @@ EP_RX: cancel */
287        if (ep->state == EP_TX) {
288            ep_tx(ep);
289            UEINTX &= ~(1 << TXINI);
290            if (ep->state == EP_IDLE && ep->callback)
291                ep->callback(ep->user);
292        }
293    }
294    return;
295
296stall:
297    UEINTX &= ~(1 << RXSTPI | 1 << RXOUTI | 1 << STALLEDI);
298    ep->state = EP_IDLE;
299    UECONX |= 1 << STALLRQ;
300}
301
302
303void usb_poll(void)
304{
305    uint8_t flags, i;
306
307    flags = UEINT;
308    for (i = 0; i != NUM_EPS; i++)
309        if (1 || flags & (1 << i))
310            handle_ep(i);
311    /* @@@ USB bus reset */
312}
313
314
315static void ep_init(void)
316{
317    UENUM = 0;
318    UECONX = (1 << RSTDT) | (1 << EPEN); /* enable */
319    UECFG0X = 0; /* control, direction is ignored */
320    UECFG1X = 3 << EPSIZE0; /* 64 bytes */
321    UECFG1X |= 1 << ALLOC;
322
323    while (!(UESTA0X & (1 << CFGOK)));
324
325    eps[0].state = EP_IDLE;
326    eps[0].size = 64;
327}
328
329
330void usb_init(void)
331{
332    USBCON |= 1 << FRZCLK; /* freeze the clock */
333
334    /* enable the PLL and wait for it to lock */
335    PLLCSR &= ~(1 << PLLP2 | 1 << PLLP1 | 1 << PLLP0);
336    PLLCSR |= 1 << PLLE;
337    while (!(PLLCSR & (1 << PLOCK)));
338
339    USBCON &= ~(1 << USBE); /* reset the controller */
340    USBCON |= 1 << USBE;
341
342    USBCON &= ~(1 << FRZCLK); /* thaw the clock */
343
344    UDCON &= ~(1 << DETACH); /* attach the pull-up */
345    UDCON |= 1 << RSTCPU; /* reset CPU on bus reset */
346
347    ep_init();
348}
atusb/fw3/usb/usb.h
124124extern const uint8_t config_descriptor[];
125125extern struct ep_descr eps[];
126126
127extern int (*user_setup)(struct setup_request *setup);
127extern int (*user_setup)(const struct setup_request *setup);
128128extern int (*user_get_descriptor)(uint8_t type, uint8_t index,
129129    const uint8_t * const *reply, uint8_t *size);
130130extern void (*user_reset)(void);
...... 
139139void usb_io(struct ep_descr *ep, enum ep_state state, uint8_t *buf,
140140    uint8_t size, void (*callback)(void *user), void *user);
141141
142
142int handle_setup(const struct setup_request *setup);
143int set_addr(uint8_t addr);
143144void usb_init(void);
144145void usb_poll(void);
145146

Archive Download the corresponding diff file



interactive