Date:2010-09-09 14:19:06 (8 years 11 months ago)
Author:Werner Almesberger
Commit:18eec557d0227425a04f1509b7c8ca8a1d24fb07
Message:Updated atusd driver for new hardware. Make use of the interrupt line.

- tools/lib/atusd.c (spi_send_partial, spi_send): removed the old spi_send
and renamed spi_send_partial to spi_send
- tools/lib/atusd.c (atusd_cycle, spi_send, spi_recv, atusd_open): updated
for removal of SLP_TR and split of MxSx into MOSI and MISO
- tools/lib/atusd.c (atusd_reset_rf, atusd_open): added delays to precharge
the capacitors
- tools/lib/atusd.c (atusd_reset, spi_data_in, spi_data_out, spi_finish):
removed functions for obsolete hardware features
- tools/lib/atusd.c (atusd_reg_read): removed calls to removed functions
- tools/lib/atusd.c (atusd_buf_write, atusd_buf_read, atusd_driver): new
buffer read/write functions
- tools/atspi-txrx/atspi-txrx.c (init_txrx): set the internal osciallator
trim only in the USB version. Switch to the external oscillator in the
uSD version.
- tools/atspi-rssi/atspi-rssi.c (sweep), tools/atspi-txrx/atspi-txrx.c
(set_channel): wait for the PLL to settle after setting the channel
- tools/include/atspi.h, tools/lib/atspi.c (atspi_interrupt),
tools/lib/driver.h (struct atspi_driver), tools/lib/atusd.c
(atusd_interrupt): new function to poll the interrupt line
- tools/atspi-txrx/atspi-txrx.c (receive): only read REG_IRQ_STATUS if
there is a pending interrupt
- tools/atspi-id/atspi-id.c (usage): print "usage:" as well
- tools/Makefile (upload): upload the atspi tools to the Ben
Files: tools/Makefile (1 diff)
tools/atspi-id/atspi-id.c (1 diff)
tools/atspi-rssi/atspi-rssi.c (1 diff)
tools/atspi-txrx/atspi-txrx.c (3 diffs)
tools/include/atspi.h (1 diff)
tools/lib/atspi.c (1 diff)
tools/lib/atusd.c (12 diffs)
tools/lib/driver.h (1 diff)

Change Details

tools/Makefile
1515TARGET_ONLY_DIRS=lib
1616
1717include ../Makefile.recurse
18
19.PHONY: upload
20
21upload:
22        scp `for n in $(DIRS); do echo $$n/$$n; done` ben:
tools/atspi-id/atspi-id.c
127127
128128static void usage(const char *name)
129129{
130    fprintf(stderr, "%s\n", name);
130    fprintf(stderr, "usage: %s\n", name);
131131    exit(1);
132132}
133133
tools/atspi-rssi/atspi-rssi.c
3030
3131    for (chan = 11; chan <= 26; chan++) {
3232        atspi_reg_write(dsc, REG_PHY_CC_CCA, chan);
33        /* 150 us, according to AVR2001 section 3.5 */
34        usleep(1000);
3335        /*
3436         * No need to explicitly wait for the PPL lock - going USB-SPI
3537         * is pretty slow, leaving the transceiver plenty of time.
tools/atspi-txrx/atspi-txrx.c
5555
5656    atspi_reset_rf(dsc);
5757    atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF);
58#ifdef HAVE_USB /* @@@ yeah, ugly */
5859    atspi_reg_write(dsc, REG_XOSC_CTRL,
5960        (XTAL_MODE_INT << XTAL_MODE_SHIFT) | trim);
61#else
62    atspi_reg_write(dsc, REG_XOSC_CTRL, XTAL_MODE_EXT << XTAL_MODE_SHIFT);
63#endif
6064    atspi_reg_write(dsc, REG_TRX_CTRL_0, 0); /* disable CLKM */
6165
6266    return dsc;
...... 
6670static void set_channel(struct atspi_dsc *dsc, int channel)
6771{
6872    atspi_reg_write(dsc, REG_PHY_CC_CCA, (1 << CCA_MODE_SHIFT) | channel);
73    /*
74     * 150 us, according to AVR2001 section 3.5. Note that we should just
75     * wait for the PPL_LOCK interrupt.
76     */
77    usleep(1000);
6978}
7079
7180
...... 
93102
94103    fprintf(stderr, "Ready.\n");
95104    while (1) {
105        while (!atspi_interrupt(dsc))
106            usleep(10);
96107        irq = atspi_reg_read(dsc, REG_IRQ_STATUS);
97108        if (atspi_error(dsc))
98109            exit(1);
tools/include/atspi.h
3636void atspi_buf_write(struct atspi_dsc *dsc, const void *buf, int size);
3737int atspi_buf_read(struct atspi_dsc *dsc, void *buf, int size);
3838
39int atspi_interrupt(struct atspi_dsc *dsc);
40
3941#endif /* !ATSPI_H */
tools/lib/atspi.c
121121{
122122    return dsc->driver->buf_read(dsc->handle, buf, size);
123123}
124
125
126int atspi_interrupt(struct atspi_dsc *dsc)
127{
128    return
129        dsc->driver->interrupt ? dsc->driver->interrupt(dsc->handle) : 1;
130}
tools/lib/atusd.c
2323
2424
2525enum {
26    VDD_OFF = 1 << 6, /* VDD disable, PD06 */
27    MxSx = 1 << 8, /* CMD, PD08 */
26    VDD_OFF = 1 << 2, /* VDD disable, PD02 */
27    MOSI = 1 << 8, /* CMD, PD08 */
2828    CLK = 1 << 9, /* CLK, PD09 */
29    SCLK = 1 << 10, /* DAT0, PD10 */
30    SLP_TR = 1 << 11, /* DAT1, PD11 */
29    MISO = 1 << 10, /* DAT0, PD10 */
30    SCLK = 1 << 11, /* DAT1, PD11 */
3131    IRQ = 1 << 12, /* DAT2, PD12 */
3232    nSEL = 1 << 13, /* DAT3/CD, PD13 */
3333};
...... 
7272{
7373    /*
7474     * Give power time to stabilize and the chip time to reset.
75     * Experiments show that even usleep(0) is long enough.
75     * Power takes about 2 ms to ramp up. We wait 10 ms to be sure.
7676     */
7777    usleep(10*1000);
7878}
...... 
8484    MSC_STRPCL = 1;
8585
8686    /* drive all outputs low (including the MMC bus clock) */
87    PDDATC = MxSx | CLK | SCLK | SLP_TR | nSEL;
87    PDDATC = MOSI | CLK | SCLK | nSEL;
8888
8989    /* make the MMC bus clock a regular output */
9090    PDFUNC = CLK;
...... 
9595    /* Power drains within about 20 ms. Wait 100 ms to be sure. */
9696    usleep(100*1000);
9797
98    /* drive nSS high */
99    PDDATS = nSEL;
98    /* drive MOSI and nSS high */
99    PDDATS = MOSI | nSEL;
100100
101    /* supply power */
102    PDDATC = VDD_OFF;
101    /* precharge the capacitors to avoid current surge */
102    wait_for_power();
103103
104104    /* return the bus clock output to the MMC controller */
105105    PDFUNS = CLK;
...... 
107107    /* start MMC clock output */
108108    MSC_STRPCL = 2;
109109
110    wait_for_power();
111}
112
113
114#if 0 /* we probably won't need this anymore */
115static void atusd_reset(struct atusd_dsc *dsc)
116{
117    /* activate reset */
118    PDDATS = SLP_TR;
119    PDDATC = nSEL;
120
121    /*
122     * Data sheet says 625 ns, programmer's guide says 6 us. Whom do we
123     * trust ?
124     */
125    usleep(6);
110    /* supply power */
111    PDDATC = VDD_OFF;
126112
127    /* release reset */
128    PDDATS = nSEL;
129    PDDATC = SLP_TR;
113    wait_for_power();
130114}
131#endif
132115
133116
134117/* ----- Low-level SPI operations ------------------------------------------ */
...... 
146129}
147130
148131
149static void spi_data_in(struct atusd_dsc *dsc)
150{
151    PDDIRC = MxSx;
152}
153
154
155static void spi_data_out(struct atusd_dsc *dsc)
156{
157    PDDIRS = MxSx;
158}
159
160
161
162/*
163 * Send a sequence of bytes but leave the clock high on the last bit, so that
164 * we can turn around the data line for reads.
165 */
166
167static void spi_send_partial(struct atusd_dsc *dsc, uint8_t v)
132static void spi_send(struct atusd_dsc *dsc, uint8_t v)
168133{
169134    uint8_t mask;
170135
171136    for (mask = 0x80; mask; mask >>= 1) {
172        PDDATC = SCLK;
173137        if (v & mask)
174            PDDATS = MxSx;
138            PDDATS = MOSI;
175139        else
176            PDDATC = MxSx;
140            PDDATC = MOSI;
177141        PDDATS = SCLK;
142        PDDATC = SCLK;
178143    }
179144}
180145
...... 
185150        uint8_t mask;
186151
187152    for (mask = 0x80; mask; mask >>= 1) {
188        PDDATC = SCLK;
189        if (PDPIN & MxSx)
153        if (PDPIN & MISO)
190154            res |= mask;
191155        PDDATS = SCLK;
156        PDDATC = SCLK;
192157    }
193    PDDATC = SCLK;
194158        return res;
195159}
196160
197161
198static void spi_finish(struct atusd_dsc *dsc)
199{
200    PDDATC = SCLK;
201}
202
203
204static void spi_send(struct atusd_dsc *dsc, uint8_t v)
205{
206    spi_send_partial(dsc, v);
207    spi_finish(dsc);
208}
209
210
211162/* ----- Driver operations ------------------------------------------------- */
212163
213164
...... 
216167    struct atusd_dsc *dsc = handle;
217168
218169    atusd_cycle(dsc);
170    wait_for_power();
219171}
220172
221173
...... 
243195
244196    /* set the output levels */
245197    PDDATS = nSEL | VDD_OFF;
246    PDDATC = SCLK | SLP_TR;
198    PDDATC = SCLK;
247199
248200    /* take the GPIOs away from the MMC controller */
249    PDFUNC = MxSx | SCLK | SLP_TR | IRQ | nSEL;
201    PDFUNC = MOSI | MISO | SCLK | IRQ | nSEL;
250202    PDFUNS = CLK;
251203
252204    /* set the pin directions */
253    PDDIRC = IRQ;
254    PDDIRS = MxSx | CLK | SCLK | SLP_TR | nSEL;
205    PDDIRC = MISO | IRQ;
206    PDDIRS = MOSI | CLK | SCLK | nSEL;
207
208    /* let capacitors precharge */
209    wait_for_power();
255210
256211    /* enable power */
257212    PDDATC = VDD_OFF;
...... 
286241    PDDATS = VDD_OFF;
287242
288243    /* make all MMC pins inputs */
289    PDDIRC = MxSx | CLK | SCLK | SLP_TR | IRQ | nSEL;
244    PDDIRC = MOSI | MISO | CLK | SCLK | IRQ | nSEL;
290245}
291246
292247
...... 
307262    uint8_t res;
308263
309264    spi_begin(dsc);
310    spi_send_partial(dsc, AT86RF230_REG_READ| reg);
311    spi_data_in(dsc);
265    spi_send(dsc, AT86RF230_REG_READ | reg);
312266    res = spi_recv(dsc);
313    spi_finish(dsc);
314    spi_data_out(dsc);
315267    spi_end(dsc);
316268    return res;
317269}
318270
319271
272static void atusd_buf_write(void *handle, const void *buf, int size)
273{
274    struct atusd_dsc *dsc = handle;
275
276    spi_begin(dsc);
277    spi_send(dsc, AT86RF230_BUF_WRITE);
278    spi_send(dsc, size);
279    while (size--)
280        spi_send(dsc, *(uint8_t *) buf++);
281    spi_end(dsc);
282}
283
284
285static int atusd_buf_read(void *handle, void *buf, int size)
286{
287    struct atusd_dsc *dsc = handle;
288    uint8_t len, i;
289
290    spi_begin(dsc);
291    spi_send(dsc, AT86RF230_BUF_READ);
292    len = spi_recv(dsc);
293    len++; /* LQI */
294    if (len > size)
295        len = size;
296    for (i = 0; i != len; i++)
297        *(uint8_t *) buf++ = spi_recv(dsc);
298    spi_end(dsc);
299    return len;
300}
301
302
303static int atusd_interrupt(void *handle)
304{
305        struct atusd_dsc *dsc = handle;
306
307    return !!(PDPIN & IRQ);
308}
309
310
320311/* ----- Driver interface -------------------------------------------------- */
321312
322313
...... 
328319    .reset_rf = atusd_reset_rf,
329320    .reg_write = atusd_reg_write,
330321    .reg_read = atusd_reg_read,
331#if 0
332322    .buf_write = atusd_buf_write,
333323    .buf_read = atusd_buf_read,
334#endif
324    .interrupt = atusd_interrupt,
335325};
tools/lib/driver.h
2929    uint8_t (*reg_read)(void *dsc, uint8_t reg);
3030    void (*buf_write)(void *dsc, const void *buf, int size);
3131    int (*buf_read)(void *dsc, void *buf, int size);
32    int (*interrupt)(void *dsc);
3233};
3334
3435#endif /* !DRIVER_H */

Archive Download the corresponding diff file



interactive