Date:2010-09-06 01:32:58 (13 years 6 months ago)
Author:Werner Almesberger
Commit:f20d685f8e2e709a243654ecc63842aa37f6e54c
Message:Merged uSD driver into unified tool build, completed conversion of tools.

- atusd/tools/lib/atusd.c: moved to tools/lib/
- atusd/tools/lib/atusd.h: removed, we can now use tools/include/atspi.h
- tools/lib/atusd.c: added copyright header
- tools/lib/atusd.c: updated for driver API
- tools/lib/Makefile: added atusd.o
- tools/Makefile.common: moved common elements from all other makefiles in
tools/*/ here
- tools/Makefile.common: added target-specific compiler and flags
- tools/atspi-id/Makefile, tools/atspi-reset/Makefile,
tools/atspi-rssi/Makefile, tools/atspi-trim/Makefile,
tools/atspi-txrx/Makefile, tools/lib/Makefile: used Makefile.common
- tools/lib/Makefile: differentiate USB and uSD build
- tools/atspi-id/atspi-id.c, tools/atspi-reset/atspi-reset.c,
tools/atspi-rssi/atspi-rssi.c, tools/atspi-trim/atspi-trim.c,
tools/atspi-txr/atspi-txr.c: updated for driver-agnostic API
- tools/atspi-id/atspi-id.c, tools/atspi-reset/atspi-reset.c,
tools/atspi-rssi/atspi-rssi.c, tools/atspi-trim/atspi-trim.c,
tools/atspi-txr/atspi-txr.c: corrected AF86RF230 typo in title
- tools/include/atspi.h, tools/lib/atspi.c, tools/lib/driver.c,
tools/lib/atusb.c: brought back support for atspi_error and
atspi_clear_error
- tools/atspi-id/atspi-id.c (atspi_get_protocol): renamed to get_protocol,
to make it clear that it's not from libatspi
- tools/atspi-id/atspi-id.c (atspi_get_build): renamed to get_build, to
make it clear that it's not from libatspi
- tools/include/atspi.h, tools/lib/atspi.c (atspi_usb_handle): new function
to obtain a driver's USB device handle (or NULL if the driver doesn't use
USB)
Files: atusd/tools/lib/atusd.c (1 diff)
atusd/tools/lib/atusd.h (1 diff)
tools/Makefile.common (1 diff)
tools/atspi-id/Makefile (1 diff)
tools/atspi-id/atspi-id.c (5 diffs)
tools/atspi-reset/Makefile (1 diff)
tools/atspi-reset/atspi-reset.c (4 diffs)
tools/atspi-rssi/Makefile (1 diff)
tools/atspi-rssi/atspi-rssi.c (5 diffs)
tools/atspi-trim/Makefile (1 diff)
tools/atspi-trim/atspi-trim.c (4 diffs)
tools/atspi-txrx/Makefile (1 diff)
tools/atspi-txrx/atspi-txrx.c (7 diffs)
tools/include/atspi.h (1 diff)
tools/lib/Makefile (1 diff)
tools/lib/atspi.c (2 diffs)
tools/lib/atusb.c (2 diffs)
tools/lib/atusd.c (1 diff)
tools/lib/driver.h (1 diff)

Change Details

atusd/tools/lib/atusd.c
1#include <stdint.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include <unistd.h>
5#include <fcntl.h>
6#include <sys/mman.h>
7
8#include "at86rf230.h"
9#include "atusd.h"
10
11
12enum {
13    VDD_OFF = 1 << 6, /* VDD disable, PD06 */
14    MxSx = 1 << 8, /* CMD, PD08 */
15    CLK = 1 << 9, /* CLK, PD09 */
16    SCLK = 1 << 10, /* DAT0, PD10 */
17    SLP_TR = 1 << 11, /* DAT1, PD11 */
18    IRQ = 1 << 12, /* DAT2, PD12 */
19    nSEL = 1 << 13, /* DAT3/CD, PD13 */
20};
21
22
23#define SOC_BASE 0x10000000
24
25#define REG(n) (*(volatile uint32_t *) (dsc->mem+(n)))
26
27#define CGU(n) REG(0x00000+(n))
28#define GPIO(n) REG(0x10000+(n))
29#define MSC(n) REG(0x21000+(n))
30
31#define PDPIN GPIO(0x300) /* port D pin level */
32#define PDDATS GPIO(0x314) /* port D data set */
33#define PDDATC GPIO(0x318) /* port D data clear */
34#define PDFUNS GPIO(0x344) /* port D function set */
35#define PDFUNC GPIO(0x348) /* port D function clear */
36#define PDDIRS GPIO(0x364) /* port D direction set */
37#define PDDIRC GPIO(0x368) /* port D direction clear */
38
39#define MSC_STRPCL MSC(0x00) /* Start/stop MMC/SD clock */
40#define MSC_CLKRT MSC(0x08) /* MSC Clock Rate */
41
42#define CLKGR CGU(0x0020) /* Clock Gate */
43#define MSCCDR CGU(0x0068) /* MSC device clock divider */
44
45
46#define PAGE_SIZE 4096
47
48
49struct atusd_dsc {
50    int fd;
51    void *mem;
52};
53
54
55struct atusd_dsc *atusd_open(void)
56{
57    struct atusd_dsc *dsc;
58
59    dsc = malloc(sizeof(*dsc));
60    if (!dsc) {
61        perror("malloc");
62        exit(1);
63    }
64
65    dsc->fd = open("/dev/mem", O_RDWR);
66    if (dsc->fd < 0) {
67        perror("/dev/mem");
68        exit(1);
69    }
70    dsc->mem = mmap(NULL, PAGE_SIZE*3*16, PROT_READ | PROT_WRITE,
71        MAP_SHARED, dsc->fd, SOC_BASE);
72        if (dsc->mem == MAP_FAILED) {
73                perror("mmap");
74                exit(1);
75        }
76
77    /* set the output levels */
78    PDDATS = nSEL | VDD_OFF;
79    PDDATC = SCLK | SLP_TR;
80
81    /* take the GPIOs away from the MMC controller */
82    PDFUNC = MxSx | SCLK | SLP_TR | IRQ | nSEL;
83    PDFUNS = CLK;
84
85    /* set the pin directions */
86    PDDIRC = IRQ;
87    PDDIRS = MxSx | CLK | SCLK | SLP_TR | nSEL;
88
89    /* enable power */
90    PDDATC = VDD_OFF;
91
92    /* set the MSC clock to 316 MHz / 21 = 16 MHz */
93    MSCCDR = 20;
94    /*
95     * Enable the MSC clock. We need to do this before accessing any
96     * registers of the MSC block !
97     */
98    CLKGR &= ~(1 << 7);
99    /* bus clock = MSC clock / 1 */
100    MSC_CLKRT = 0;
101    /* start MMC clock output */
102    MSC_STRPCL = 2;
103
104    return dsc;
105}
106
107
108void atusd_close(struct atusd_dsc *dsc)
109{
110    /* stop the MMC bus clock */
111    MSC_STRPCL = 1;
112
113    /* cut the power */
114    PDDATS = VDD_OFF;
115
116    /* make all MMC pins inputs */
117    PDDIRC = MxSx | CLK | SCLK | SLP_TR | IRQ | nSEL;
118}
119
120
121void atusd_cycle(struct atusd_dsc *dsc)
122{
123    /* stop the MMC bus clock */
124    MSC_STRPCL = 1;
125
126    /* drive all outputs low (including the MMC bus clock) */
127    PDDATC = MxSx | CLK | SCLK | SLP_TR | nSEL;
128
129    /* make the MMC bus clock a regular output */
130    PDFUNC = CLK;
131
132    /* cut the power */
133    PDDATS = VDD_OFF;
134
135    /* Power drains within about 20 ms. Wait 100 ms to be sure. */
136    usleep(100*1000);
137
138    /* drive nSS high */
139    PDDATS = nSEL;
140
141    /* supply power */
142    PDDATS = VDD_OFF;
143
144    /* return the bus clock output to the MMC controller */
145    PDFUNS = CLK;
146
147    /* start MMC clock output */
148    MSC_STRPCL = 2;
149
150    /*
151     * Give power time to stabilize and the chip time to reset.
152     * Experiments show that even usleep(0) is long enough.
153     */
154    usleep(10*1000);
155}
156
157
158void atusd_reset(struct atusd_dsc *dsc)
159{
160    /* activate reset */
161    PDDATS = SLP_TR;
162    PDDATC = nSEL;
163
164    /*
165     * Data sheet says 625 ns, programmer's guide says 6 us. Whom do we
166     * trust ?
167     */
168    usleep(6);
169
170    /* release reset */
171    PDDATS = nSEL;
172    PDDATC = SLP_TR;
173}
174
175
176static void spi_begin(struct atusd_dsc *dsc)
177{
178    PDDATC = nSEL;
179}
180
181
182static void spi_end(struct atusd_dsc *dsc)
183{
184    PDDATS = nSEL;
185}
186
187
188static void spi_data_in(struct atusd_dsc *dsc)
189{
190    PDDIRC = MxSx;
191}
192
193
194static void spi_data_out(struct atusd_dsc *dsc)
195{
196    PDDIRS = MxSx;
197}
198
199
200
201/*
202 * Send a sequence of bytes but leave the clock high on the last bit, so that
203 * we can turn around the data line for reads.
204 */
205
206static void spi_send_partial(struct atusd_dsc *dsc, uint8_t v)
207{
208    uint8_t mask;
209
210    for (mask = 0x80; mask; mask >>= 1) {
211        PDDATC = SCLK;
212        if (v & mask)
213            PDDATS = MxSx;
214        else
215            PDDATC = MxSx;
216        PDDATS = SCLK;
217    }
218}
219
220
221static uint8_t spi_recv(struct atusd_dsc *dsc)
222{
223    uint8_t res = 0;
224        uint8_t mask;
225
226    for (mask = 0x80; mask; mask >>= 1) {
227        PDDATC = SCLK;
228        if (PDPIN & MxSx)
229            res |= mask;
230        PDDATS = SCLK;
231    }
232    PDDATC = SCLK;
233        return res;
234}
235
236
237static void spi_finish(struct atusd_dsc *dsc)
238{
239    PDDATC = SCLK;
240}
241
242
243static void spi_send(struct atusd_dsc *dsc, uint8_t v)
244{
245    spi_send_partial(dsc, v);
246    spi_finish(dsc);
247}
248
249
250void atusd_reg_write(struct atusd_dsc *dsc, uint8_t reg, uint8_t v)
251{
252    spi_begin(dsc);
253    spi_send(dsc, AT86RF230_REG_WRITE | reg);
254    spi_send(dsc, v);
255    spi_end(dsc);
256}
257
258
259uint8_t atusd_reg_read(struct atusd_dsc *dsc, uint8_t reg)
260{
261    uint8_t res;
262
263    spi_begin(dsc);
264    spi_send_partial(dsc, AT86RF230_REG_READ| reg);
265    spi_data_in(dsc);
266    res = spi_recv(dsc);
267    spi_finish(dsc);
268    spi_data_out(dsc);
269    spi_end(dsc);
270    return res;
271}
atusd/tools/lib/atusd.h
1#ifndef ATUSD_H
2#define ATUSD_H
3
4#include <stdint.h>
5
6
7struct atusd_dsc;
8
9
10struct atusd_dsc *atusd_open(void);
11void atusd_close(struct atusd_dsc *dsc);
12void atusd_cycle(struct atusd_dsc *dsc);
13void atusd_reset(struct atusd_dsc *dsc);
14void atusd_reg_write(struct atusd_dsc *dsc, uint8_t reg, uint8_t v);
15uint8_t atusd_reg_read(struct atusd_dsc *dsc, uint8_t reg);
16
17#endif /* ATUSD_H */
tools/Makefile.common
1#
2# tools/Makefile.common - Common items in ATSPI tool makefiles
3#
4# Written 2010 by Werner Almesberger
5# Copyright 2010 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
13ifeq ($(TARGET),)
14TARGET = host
15endif
16
17F32XBASE = ../../../f32xbase
18
19ifneq ($(MAIN),)
20include $(F32XBASE)/lib/Makefile.common
21endif
22
23CC_host = gcc
24CC_ben = mipsel-openwrt-linux-gcc
25LDLIBS_host = -lusb
26LDLIBS_ben =
27MACROS_host = -DHAVE_USB
28MACROS_ben = -DHAVE_USD
29
30CFLAGS += -I../../atrf/fw/include -I../include $(MACROS_$(TARGET))
31LDLIBS = $(LDLIBS_$(TARGET)) -L../lib -latspi
tools/atspi-id/Makefile
1111#
1212
1313
14F32XBASE = ../../../f32xbase
15
1614MAIN = atspi-id
1715
18include $(F32XBASE)/lib/Makefile.common
19
20CFLAGS += -I../../atrf/fw/include -I../include
21LDLIBS += -L../lib -latspi
16include ../Makefile.common
tools/atspi-id/atspi-id.c
11/*
2 * atspi-id/atspi-id.c - Identify a ben-wpan AF86RF230 board
2 * atspi-id/atspi-id.c - Identify a ben-wpan AT86RF230 board
33 *
44 * Written 2010 by Werner Almesberger
55 * Copyright 2010 Werner Almesberger
...... 
3737}
3838
3939
40static int atspi_get_protocol(usb_dev_handle *dev,
40static int get_protocol(usb_dev_handle *dev,
4141    uint8_t *major, uint8_t *minor, uint8_t *target)
4242{
4343    uint8_t ids[3];
...... 
5555}
5656
5757
58static int atspi_get_build(usb_dev_handle *dev, char *buf, size_t size)
58static int get_build(usb_dev_handle *dev, char *buf, size_t size)
5959{
6060    int res;
6161
...... 
6767}
6868
6969
70static void show_info(usb_dev_handle *dev)
70static void show_usb_info(usb_dev_handle *dev)
7171{
7272    const struct usb_device *device = usb_device(dev);
7373    uint8_t major, minor, target;
7474    char buf[BUF_SIZE+1]; /* +1 for terminating \0 */
7575    int len;
76    uint8_t part, version, man_id_0, man_id_1;
7776
7877    printf("%04x:%04x ",
7978        device->descriptor.idVendor, device->descriptor.idProduct);
8079
81    if (atspi_get_protocol(dev, &major, &minor, &target) < 0)
80    if (get_protocol(dev, &major, &minor, &target) < 0)
8281        exit(1);
8382    printf("protocol %u.%u hw %u\n", major, minor, target);
8483
85    len = atspi_get_build(dev, buf, sizeof(buf)-1);
84    len = get_build(dev, buf, sizeof(buf)-1);
8685    if (len < 0)
8786        exit(1);
8887    buf[len] = 0;
8988    printf("%10s%s\n", "", buf);
89}
90
9091
91    part = atspi_reg_read(dev, REG_PART_NUM);
92    version = atspi_reg_read(dev, REG_VERSION_NUM);
93    man_id_0 = atspi_reg_read(dev, REG_MAN_ID_0);
94    man_id_1 = atspi_reg_read(dev, REG_MAN_ID_1);
92static void show_info(struct atspi_dsc *dsc)
93{
94    usb_dev_handle *dev;
95    uint8_t part, version, man_id_0, man_id_1;
96
97    dev = atspi_usb_handle(dsc);
98    if (dev)
99        show_usb_info(dev);
100
101    part = atspi_reg_read(dsc, REG_PART_NUM);
102    version = atspi_reg_read(dsc, REG_VERSION_NUM);
103    man_id_0 = atspi_reg_read(dsc, REG_MAN_ID_0);
104    man_id_1 = atspi_reg_read(dsc, REG_MAN_ID_1);
95105    printf("%10spart 0x%02x version %u manufacturer xxxx%02x%02x\n", "",
96106        part, version, man_id_1, man_id_0);
97107}
...... 
106116
107117int main(int argc, const char **argv)
108118{
109    usb_dev_handle *dev;
119    struct atspi_dsc *dsc;
110120
111121    if (argc != 1)
112122        usage(*argv);
113    dev = atspi_open();
114    if (!dev)
123    dsc = atspi_open();
124    if (!dsc)
115125        return 1;
116126
117    show_info(dev);
127    show_info(dsc);
118128
119129    return 0;
120130}
tools/atspi-reset/Makefile
1111#
1212
1313
14F32XBASE = ../../../f32xbase
15
1614MAIN = atspi-reset
1715
18include $(F32XBASE)/lib/Makefile.common
19
20CFLAGS += -I../../atrf/fw/include -I../include
21LDLIBS += -L../lib -latspi
16include ../Makefile.common
tools/atspi-reset/atspi-reset.c
11/*
2 * atspi-rssi/atspi-rssi.c - ben-wpan AF86RF230 spectrum scan
2 * atspi-rssi/atspi-rssi.c - ben-wpan AT86RF230 spectrum scan
33 *
44 * Written 2010 by Werner Almesberger
55 * Copyright 2010 Werner Almesberger
...... 
1414#include <stdlib.h>
1515#include <stdio.h>
1616#include <string.h>
17#include <usb.h>
1817
1918#include "atspi.h"
2019
...... 
3231
3332int main(int argc, const char **argv)
3433{
35    usb_dev_handle *dev;
34    struct atspi_dsc *dsc;
3635    int txrx = 1;
3736
3837    switch (argc) {
...... 
4948        usage(*argv);
5049    }
5150
52    dev = atspi_open();
53    if (!dev)
51    dsc = atspi_open();
52    if (!dsc)
5453        return 1;
5554
5655        if (txrx)
57                atspi_reset_rf(dev);
56                atspi_reset_rf(dsc);
5857        else
59                atspi_reset(dev);
58                atspi_reset(dsc);
6059        return 0;
6160}
6261
tools/atspi-rssi/Makefile
1111#
1212
1313
14F32XBASE = ../../../f32xbase
15
1614MAIN = atspi-rssi
1715
18include $(F32XBASE)/lib/Makefile.common
19
20CFLAGS += -I../../atrf/fw/include -I../include
21LDLIBS += -L../lib -latspi
16include ../Makefile.common
tools/atspi-rssi/atspi-rssi.c
11/*
2 * atspi-rssi/atspi-rssi.c - ben-wpan AF86RF230 spectrum scan
2 * atspi-rssi/atspi-rssi.c - ben-wpan AT86RF230 spectrum scan
33 *
44 * Written 2010 by Werner Almesberger
55 * Copyright 2010 Werner Almesberger
...... 
1313
1414#include <stdlib.h>
1515#include <stdio.h>
16#include <usb.h>
1716#include <sys/time.h>
1817
1918#include "at86rf230.h"
...... 
2423static struct timeval t0;
2524
2625
27static void sweep(usb_dev_handle *dev)
26static void sweep(struct atspi_dsc *dsc)
2827{
2928    int chan, rssi;
3029    struct timeval t;
3130
3231    for (chan = 11; chan <= 26; chan++) {
33        atspi_reg_write(dev, REG_PHY_CC_CCA, chan);
32        atspi_reg_write(dsc, REG_PHY_CC_CCA, chan);
3433        /*
3534         * No need to explicitly wait for the PPL lock - going USB-SPI
3635         * is pretty slow, leaving the transceiver plenty of time.
3736         */
3837        gettimeofday(&t, NULL);
39        rssi = atspi_reg_read(dev, REG_PHY_RSSI) & RSSI_MASK;
38        rssi = atspi_reg_read(dsc, REG_PHY_RSSI) & RSSI_MASK;
4039        t.tv_sec -= t0.tv_sec;
4140        t.tv_usec -= t0.tv_usec;
4241        printf("%d %f %d\n",
...... 
5756
5857int main(int argc, const char **argv)
5958{
60    usb_dev_handle *dev;
59    struct atspi_dsc *dsc;
6160    unsigned long sweeps, i;
6261    char *end;
6362
...... 
6766    if (*end)
6867        usage(*argv);
6968
70    dev = atspi_open();
71    if (!dev)
69    dsc = atspi_open();
70    if (!dsc)
7271        return 1;
7372
74    atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_TRX_OFF);
73    atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF);
7574    /*
7675     * No need to explicitly wait for things to stabilize - going USB-SPI
7776     * is pretty slow, leaving the transceiver more than enough time.
7877     */
79    atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_RX_ON);
78    atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON);
8079
8180    gettimeofday(&t0, NULL);
8281    for (i = 0; i != sweeps; i++)
83        sweep(dev);
82        sweep(dsc);
8483
85    atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_TRX_OFF);
84    atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF);
8685
8786    return 0;
8887}
tools/atspi-trim/Makefile
1111#
1212
1313
14F32XBASE = ../../../f32xbase
15
1614MAIN = atspi-trim
1715
18include $(F32XBASE)/lib/Makefile.common
19
20CFLAGS += -I../../atrf/fw/include -I../include
21LDLIBS += -L../lib -latspi
16include ../Makefile.common
tools/atspi-trim/atspi-trim.c
11/*
2 * atspi-trim/atspi-trim.c - AF86RF230 oscillator trim utility
2 * atspi-trim/atspi-trim.c - AT86RF230 oscillator trim utility
33 *
44 * Written 2010 by Werner Almesberger
55 * Copyright 2010 Werner Almesberger
...... 
1313
1414#include <stdlib.h>
1515#include <stdio.h>
16#include <usb.h>
1716#include <sys/time.h>
1817
1918#include "at86rf230.h"
...... 
3029
3130int main(int argc, const char **argv)
3231{
33    usb_dev_handle *dev;
32    struct atspi_dsc *dsc;
3433    int trim = -1;
3534    char *end;
3635
...... 
4645        usage(*argv);
4746    }
4847
49    dev = atspi_open();
50    if (!dev)
48    dsc = atspi_open();
49    if (!dsc)
5150        return 1;
5251
5352    if (trim == -1) {
54        trim = atspi_reg_read(dev, REG_XOSC_CTRL) & XTAL_TRIM_MASK;
53        trim = atspi_reg_read(dsc, REG_XOSC_CTRL) & XTAL_TRIM_MASK;
5554        printf("%d (%d.%d pF)\n", trim, trim*3/10, trim*3 % 10);
5655    } else {
57        atspi_reg_write(dev, REG_XOSC_CTRL,
56        atspi_reg_write(dsc, REG_XOSC_CTRL,
5857            (XTAL_MODE_INT << XTAL_MODE_SHIFT) | trim);
5958    }
6059
tools/atspi-txrx/Makefile
1111#
1212
1313
14F32XBASE = ../../../f32xbase
15
1614MAIN = atspi-txrx
1715
18include $(F32XBASE)/lib/Makefile.common
19
20CFLAGS += -I../../atrf/fw/include -I../include
21LDLIBS += -L../lib -latspi
16include ../Makefile.common
tools/atspi-txrx/atspi-txrx.c
11/*
2 * atspi-txrx/atspi-txrx.c - ben-wpan AF86RF230 TX/RX
2 * atspi-txrx/atspi-txrx.c - ben-wpan AT86RF230 TX/RX
33 *
44 * Written 2010 by Werner Almesberger
55 * Copyright 2010 Werner Almesberger
...... 
1313
1414#include <stdlib.h>
1515#include <stdio.h>
16#include <unistd.h>
1617#include <string.h>
17#include <usb.h>
1818
1919#include "at86rf230.h"
2020#include "atspi/ep0.h"
...... 
4545};
4646
4747
48static usb_dev_handle *init_txrx(int trim)
48static struct atspi_dsc *init_txrx(int trim)
4949{
50    usb_dev_handle *dev;
50    struct atspi_dsc *dsc;
5151
52    dev = atspi_open();
53    if (!dev)
52    dsc = atspi_open();
53    if (!dsc)
5454        exit(1);
5555
56    atspi_reset_rf(dev);
57    atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_TRX_OFF);
58    atspi_reg_write(dev, REG_XOSC_CTRL,
56    atspi_reset_rf(dsc);
57    atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF);
58    atspi_reg_write(dsc, REG_XOSC_CTRL,
5959        (XTAL_MODE_INT << XTAL_MODE_SHIFT) | trim);
60    atspi_reg_write(dev, REG_TRX_CTRL_0, 0); /* disable CLKM */
60    atspi_reg_write(dsc, REG_TRX_CTRL_0, 0); /* disable CLKM */
6161
62    return dev;
62    return dsc;
6363}
6464
6565
66static void set_channel(usb_dev_handle *dev, int channel)
66static void set_channel(struct atspi_dsc *dsc, int channel)
6767{
68    atspi_reg_write(dev, REG_PHY_CC_CCA, (1 << CCA_MODE_SHIFT) | channel);
68    atspi_reg_write(dsc, REG_PHY_CC_CCA, (1 << CCA_MODE_SHIFT) | channel);
6969}
7070
7171
72static void set_power(usb_dev_handle *dev, double power)
72static void set_power(struct atspi_dsc *dsc, double power)
7373{
7474    int n;
7575
7676    for (n = 0; n != sizeof(tx_pwr)/sizeof(*tx_pwr)-1; n++)
7777        if (tx_pwr[n] <= power)
7878            break;
79    atspi_reg_write(dev, REG_PHY_TX_PWR, TX_AUTO_CRC_ON | n);
79    atspi_reg_write(dsc, REG_PHY_TX_PWR, TX_AUTO_CRC_ON | n);
8080}
8181
8282
83static void receive(usb_dev_handle *dev)
83static void receive(struct atspi_dsc *dsc)
8484{
8585    uint8_t irq;
8686    uint8_t buf[MAX_PSDU+1]; /* PSDU+LQI */
8787    int n, ok, i;
8888    uint8_t lq;
8989
90    atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_RX_ON);
90    atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON);
9191
92    (void) atspi_reg_read(dev, REG_IRQ_STATUS);
92    (void) atspi_reg_read(dsc, REG_IRQ_STATUS);
9393
9494    fprintf(stderr, "Ready.\n");
9595    while (1) {
96        irq = atspi_reg_read(dev, REG_IRQ_STATUS);
97        if (atspi_error())
96        irq = atspi_reg_read(dsc, REG_IRQ_STATUS);
97        if (atspi_error(dsc))
9898            exit(1);
9999        if (!irq)
100100            continue;
...... 
116116            break;
117117    }
118118
119    n = atspi_buf_read(dev, buf, sizeof(buf));
119    n = atspi_buf_read(dsc, buf, sizeof(buf));
120120    if (n < 0)
121121        exit(1);
122122    if (n < 3) {
123123        fprintf(stderr, "%d bytes received\n", n);
124124        exit(1);
125125    }
126    ok = !!(atspi_reg_read(dev, REG_PHY_RSSI) & RX_CRC_VALID);
126    ok = !!(atspi_reg_read(dsc, REG_PHY_RSSI) & RX_CRC_VALID);
127127    lq = buf[n-1];
128128    fprintf(stderr, "%d bytes payload, CRC %s, LQI %u\n",
129129        n-3, ok ? "OK" : "BAD", lq);
...... 
133133}
134134
135135
136static void transmit(usb_dev_handle *dev, const char *msg)
136static void transmit(struct atspi_dsc *dsc, const char *msg)
137137{
138138    uint8_t buf[MAX_PSDU];
139139
140    atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_PLL_ON);
140    atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON);
141141
142142    /*
143143     * We need to copy the message to append the CRC placeholders.
144144     */
145145    strcpy((void *) buf, msg);
146    atspi_buf_write(dev, buf, strlen(msg)+2);
146    atspi_buf_write(dsc, buf, strlen(msg)+2);
147147
148148    /* @@@ should wait for clear channel */
149    atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_TX_START);
149    atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START);
150150    /* @@@ should wait for TX done */
151151}
152152
...... 
170170    int trim = 0;
171171    char *end;
172172    int c;
173    usb_dev_handle *dev;
173    struct atspi_dsc *dsc;
174174
175175    while ((c = getopt(argc, argv, "c:p:t:")) != EOF)
176176        switch (c) {
...... 
199199
200200    switch (argc-optind) {
201201    case 0:
202        dev = init_txrx(trim);
203        set_channel(dev, channel);
204        receive(dev);
202        dsc = init_txrx(trim);
203        set_channel(dsc, channel);
204        receive(dsc);
205205        break;
206206    case 1:
207        dev = init_txrx(trim);
208        set_channel(dev, channel);
209        set_power(dev, power);
210        transmit(dev, argv[optind]);
207        dsc = init_txrx(trim);
208        set_channel(dsc, channel);
209        set_power(dsc, power);
210        transmit(dsc, argv[optind]);
211211        break;
212212    default:
213213        usage(*argv);
tools/include/atspi.h
1919struct atspi_dsc;
2020
2121
22int atspi_error(void);
23int atspi_clear_error(void);
22void *atspi_usb_handle(struct atspi_dsc *dsc); /* hack for atspi-id */
2423
2524struct atspi_dsc *atspi_open(void);
2625void atspi_close(struct atspi_dsc *dsc);
2726
27int atspi_error(struct atspi_dsc *dsc);
28int atspi_clear_error(struct atspi_dsc *dsc);
29
2830void atspi_reset(struct atspi_dsc *dsc);
2931void atspi_reset_rf(struct atspi_dsc *dsc);
3032
tools/lib/Makefile
1111#
1212
1313
14F32XBASE = ../../../f32xbase
15
1614LIB = libatspi.a
1715
18CFLAGS = -Wall -I$(F32XBASE)/include -I../../atrf/fw/include -I../include
19OBJS = $(F32XBASE)/lib/usb.o atspi.o atusb.o
16include ../Makefile.common
17
18CFLAGS += -Wall -I$(F32XBASE)/include
19OBJS_host = atusb.o
20OBJS_ben = atusd.o
21OBJS = $(F32XBASE)/lib/usb.o atspi.o $(OBJS_$(TARGET))
2022
2123.PHONY: all clean spotless
2224
tools/lib/atspi.c
1919
2020
2121extern struct atspi_driver atusb_driver;
22extern struct atspi_driver atusd_driver;
2223
2324
2425struct atspi_dsc {
...... 
2728};
2829
2930
31void *atspi_usb_handle(struct atspi_dsc *dsc)
32{
33#ifdef HAVE_USB
34    return dsc->handle;
35#else
36    return NULL;
37#endif
38}
39
40
41int atspi_error(struct atspi_dsc *dsc)
42{
43    return dsc->driver->error ? dsc->driver->error(dsc->handle) : 0;
44}
45
46
47int atspi_clear_error(struct atspi_dsc *dsc)
48{
49    return dsc->driver->clear_error ?
50        dsc->driver->clear_error(dsc->handle) : 0;
51}
52
53
3054struct atspi_dsc *atspi_open(void)
3155{
3256    struct atspi_dsc *dsc;
3357    struct atspi_driver *driver;
3458    void *handle;
3559
60#ifdef HAVE_USB
3661    driver = &atusb_driver;
62#elif HAVE_USD
63    driver = &atusd_driver;
64#else
65#error Need either HAVE_USB or HAVE_USD
66#endif
3767    handle = driver->open();
3868    if (!handle)
3969        return NULL;
tools/lib/atusb.c
3131static int error;
3232
3333
34int atusb_error(void)
34static int atusb_error(void *dsc)
3535{
3636    return error;
3737}
3838
3939
40int atusb_clear_error(void)
40static int atusb_clear_error(void *dsc)
4141{
4242    int ret;
4343
...... 
191191
192192
193193struct atspi_driver atusb_driver = {
194    .name = "atusb",
194    .name = "USB",
195195    .open = atusb_open,
196196    .close = atusb_close,
197    .error = atusb_error,
198    .clear_error = atusb_clear_error,
197199    .reset = atusb_reset,
198200    .reset_rf = atusb_reset_rf,
199201    .reg_write = atusb_reg_write,
tools/lib/atusd.c
1/*
2 * lib/atusd.c - ATSPI access functions library (uSD version)
3 *
4 * Written 2010 by Werner Almesberger
5 * Copyright 2010 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#include <stdint.h>
15#include <stdlib.h>
16#include <stdio.h>
17#include <unistd.h>
18#include <fcntl.h>
19#include <sys/mman.h>
20
21#include "at86rf230.h"
22#include "driver.h"
23
24
25enum {
26    VDD_OFF = 1 << 6, /* VDD disable, PD06 */
27    MxSx = 1 << 8, /* CMD, PD08 */
28    CLK = 1 << 9, /* CLK, PD09 */
29    SCLK = 1 << 10, /* DAT0, PD10 */
30    SLP_TR = 1 << 11, /* DAT1, PD11 */
31    IRQ = 1 << 12, /* DAT2, PD12 */
32    nSEL = 1 << 13, /* DAT3/CD, PD13 */
33};
34
35
36#define SOC_BASE 0x10000000
37
38#define REG(n) (*(volatile uint32_t *) (dsc->mem+(n)))
39
40#define CGU(n) REG(0x00000+(n))
41#define GPIO(n) REG(0x10000+(n))
42#define MSC(n) REG(0x21000+(n))
43
44#define PDPIN GPIO(0x300) /* port D pin level */
45#define PDDATS GPIO(0x314) /* port D data set */
46#define PDDATC GPIO(0x318) /* port D data clear */
47#define PDFUNS GPIO(0x344) /* port D function set */
48#define PDFUNC GPIO(0x348) /* port D function clear */
49#define PDDIRS GPIO(0x364) /* port D direction set */
50#define PDDIRC GPIO(0x368) /* port D direction clear */
51
52#define MSC_STRPCL MSC(0x00) /* Start/stop MMC/SD clock */
53#define MSC_CLKRT MSC(0x08) /* MSC Clock Rate */
54
55#define CLKGR CGU(0x0020) /* Clock Gate */
56#define MSCCDR CGU(0x0068) /* MSC device clock divider */
57
58
59#define PAGE_SIZE 4096
60
61
62struct atusd_dsc {
63    int fd;
64    void *mem;
65};
66
67
68/* ----- Reset functions --------------------------------------------------- */
69
70
71static void atusd_cycle(struct atusd_dsc *dsc)
72{
73    /* stop the MMC bus clock */
74    MSC_STRPCL = 1;
75
76    /* drive all outputs low (including the MMC bus clock) */
77    PDDATC = MxSx | CLK | SCLK | SLP_TR | nSEL;
78
79    /* make the MMC bus clock a regular output */
80    PDFUNC = CLK;
81
82    /* cut the power */
83    PDDATS = VDD_OFF;
84
85    /* Power drains within about 20 ms. Wait 100 ms to be sure. */
86    usleep(100*1000);
87
88    /* drive nSS high */
89    PDDATS = nSEL;
90
91    /* supply power */
92    PDDATS = VDD_OFF;
93
94    /* return the bus clock output to the MMC controller */
95    PDFUNS = CLK;
96
97    /* start MMC clock output */
98    MSC_STRPCL = 2;
99
100    /*
101     * Give power time to stabilize and the chip time to reset.
102     * Experiments show that even usleep(0) is long enough.
103     */
104    usleep(10*1000);
105}
106
107
108#if 0 /* we probably won't need this anymore */
109static void atusd_reset(struct atusd_dsc *dsc)
110{
111    /* activate reset */
112    PDDATS = SLP_TR;
113    PDDATC = nSEL;
114
115    /*
116     * Data sheet says 625 ns, programmer's guide says 6 us. Whom do we
117     * trust ?
118     */
119    usleep(6);
120
121    /* release reset */
122    PDDATS = nSEL;
123    PDDATC = SLP_TR;
124}
125#endif
126
127
128/* ----- Low-level SPI operations ------------------------------------------ */
129
130
131static void spi_begin(struct atusd_dsc *dsc)
132{
133    PDDATC = nSEL;
134}
135
136
137static void spi_end(struct atusd_dsc *dsc)
138{
139    PDDATS = nSEL;
140}
141
142
143static void spi_data_in(struct atusd_dsc *dsc)
144{
145    PDDIRC = MxSx;
146}
147
148
149static void spi_data_out(struct atusd_dsc *dsc)
150{
151    PDDIRS = MxSx;
152}
153
154
155
156/*
157 * Send a sequence of bytes but leave the clock high on the last bit, so that
158 * we can turn around the data line for reads.
159 */
160
161static void spi_send_partial(struct atusd_dsc *dsc, uint8_t v)
162{
163    uint8_t mask;
164
165    for (mask = 0x80; mask; mask >>= 1) {
166        PDDATC = SCLK;
167        if (v & mask)
168            PDDATS = MxSx;
169        else
170            PDDATC = MxSx;
171        PDDATS = SCLK;
172    }
173}
174
175
176static uint8_t spi_recv(struct atusd_dsc *dsc)
177{
178    uint8_t res = 0;
179        uint8_t mask;
180
181    for (mask = 0x80; mask; mask >>= 1) {
182        PDDATC = SCLK;
183        if (PDPIN & MxSx)
184            res |= mask;
185        PDDATS = SCLK;
186    }
187    PDDATC = SCLK;
188        return res;
189}
190
191
192static void spi_finish(struct atusd_dsc *dsc)
193{
194    PDDATC = SCLK;
195}
196
197
198static void spi_send(struct atusd_dsc *dsc, uint8_t v)
199{
200    spi_send_partial(dsc, v);
201    spi_finish(dsc);
202}
203
204
205/* ----- Driver operations ------------------------------------------------- */
206
207
208static void *atusd_open(void)
209{
210    struct atusd_dsc *dsc;
211
212    dsc = malloc(sizeof(*dsc));
213    if (!dsc) {
214        perror("malloc");
215        exit(1);
216    }
217
218    dsc->fd = open("/dev/mem", O_RDWR);
219    if (dsc->fd < 0) {
220        perror("/dev/mem");
221        exit(1);
222    }
223    dsc->mem = mmap(NULL, PAGE_SIZE*3*16, PROT_READ | PROT_WRITE,
224        MAP_SHARED, dsc->fd, SOC_BASE);
225        if (dsc->mem == MAP_FAILED) {
226                perror("mmap");
227                exit(1);
228        }
229
230    /* set the output levels */
231    PDDATS = nSEL | VDD_OFF;
232    PDDATC = SCLK | SLP_TR;
233
234    /* take the GPIOs away from the MMC controller */
235    PDFUNC = MxSx | SCLK | SLP_TR | IRQ | nSEL;
236    PDFUNS = CLK;
237
238    /* set the pin directions */
239    PDDIRC = IRQ;
240    PDDIRS = MxSx | CLK | SCLK | SLP_TR | nSEL;
241
242    /* enable power */
243    PDDATC = VDD_OFF;
244
245    /* set the MSC clock to 316 MHz / 21 = 16 MHz */
246    MSCCDR = 20;
247    /*
248     * Enable the MSC clock. We need to do this before accessing any
249     * registers of the MSC block !
250     */
251    CLKGR &= ~(1 << 7);
252    /* bus clock = MSC clock / 1 */
253    MSC_CLKRT = 0;
254    /* start MMC clock output */
255    MSC_STRPCL = 2;
256
257    return dsc;
258}
259
260
261static void atusd_close(void *arg)
262{
263    struct atusd_dsc *dsc = arg;
264
265    /* stop the MMC bus clock */
266    MSC_STRPCL = 1;
267
268    /* cut the power */
269    PDDATS = VDD_OFF;
270
271    /* make all MMC pins inputs */
272    PDDIRC = MxSx | CLK | SCLK | SLP_TR | IRQ | nSEL;
273}
274
275
276static void atusd_reset_rf(void *handle)
277{
278    struct atusd_dsc *dsc = handle;
279
280    atusd_cycle(dsc);
281}
282
283
284static void atusd_reg_write(void *handle, uint8_t reg, uint8_t v)
285{
286    struct atusd_dsc *dsc = handle;
287
288    spi_begin(dsc);
289    spi_send(dsc, AT86RF230_REG_WRITE | reg);
290    spi_send(dsc, v);
291    spi_end(dsc);
292}
293
294
295static uint8_t atusd_reg_read(void *handle, uint8_t reg)
296{
297    struct atusd_dsc *dsc = handle;
298    uint8_t res;
299
300    spi_begin(dsc);
301    spi_send_partial(dsc, AT86RF230_REG_READ| reg);
302    spi_data_in(dsc);
303    res = spi_recv(dsc);
304    spi_finish(dsc);
305    spi_data_out(dsc);
306    spi_end(dsc);
307    return res;
308}
309
310
311/* ----- Driver interface -------------------------------------------------- */
312
313
314struct atspi_driver atusd_driver = {
315    .name = "uSD",
316    .open = atusd_open,
317    .close = atusd_close,
318    .reset = NULL,
319    .reset_rf = atusd_reset_rf,
320    .reg_write = atusd_reg_write,
321    .reg_read = atusd_reg_read,
322#if 0
323    .buf_write = atusd_buf_write,
324    .buf_read = atusd_buf_read,
325#endif
326};
tools/lib/driver.h
2121    const char *name;
2222    void *(*open)(void);
2323    void (*close)(void *dsc);
24    int (*error)(void *dsc);
25    int (*clear_error)(void *dsc);
2426    void (*reset)(void *dsc);
2527    void (*reset_rf)(void *dsc);
2628    void (*reg_write)(void *dsc, uint8_t reg, uint8_t value);

Archive Download the corresponding diff file



interactive