IEEE 802.15.4 subsystem
Sign in or create your account | Project List | Help
IEEE 802.15.4 subsystem Commit Details
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 | ||
12 | enum { | |
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 | ||
49 | struct atusd_dsc { | |
50 | int fd; | |
51 | void *mem; | |
52 | }; | |
53 | ||
54 | ||
55 | struct 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 | ||
108 | void 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 | ||
121 | void 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 | ||
158 | void 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 | ||
176 | static void spi_begin(struct atusd_dsc *dsc) | |
177 | { | |
178 | PDDATC = nSEL; | |
179 | } | |
180 | ||
181 | ||
182 | static void spi_end(struct atusd_dsc *dsc) | |
183 | { | |
184 | PDDATS = nSEL; | |
185 | } | |
186 | ||
187 | ||
188 | static void spi_data_in(struct atusd_dsc *dsc) | |
189 | { | |
190 | PDDIRC = MxSx; | |
191 | } | |
192 | ||
193 | ||
194 | static 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 | ||
206 | static 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 | ||
221 | static 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 | ||
237 | static void spi_finish(struct atusd_dsc *dsc) | |
238 | { | |
239 | PDDATC = SCLK; | |
240 | } | |
241 | ||
242 | ||
243 | static void spi_send(struct atusd_dsc *dsc, uint8_t v) | |
244 | { | |
245 | spi_send_partial(dsc, v); | |
246 | spi_finish(dsc); | |
247 | } | |
248 | ||
249 | ||
250 | void 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 | ||
259 | uint8_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 | ||
7 | struct atusd_dsc; | |
8 | ||
9 | ||
10 | struct atusd_dsc *atusd_open(void); | |
11 | void atusd_close(struct atusd_dsc *dsc); | |
12 | void atusd_cycle(struct atusd_dsc *dsc); | |
13 | void atusd_reset(struct atusd_dsc *dsc); | |
14 | void atusd_reg_write(struct atusd_dsc *dsc, uint8_t reg, uint8_t v); | |
15 | uint8_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 | ||
13 | ifeq ($(TARGET),) | |
14 | TARGET = host | |
15 | endif | |
16 | ||
17 | F32XBASE = ../../../f32xbase | |
18 | ||
19 | ifneq ($(MAIN),) | |
20 | include $(F32XBASE)/lib/Makefile.common | |
21 | endif | |
22 | ||
23 | CC_host = gcc | |
24 | CC_ben = mipsel-openwrt-linux-gcc | |
25 | LDLIBS_host = -lusb | |
26 | LDLIBS_ben = | |
27 | MACROS_host = -DHAVE_USB | |
28 | MACROS_ben = -DHAVE_USD | |
29 | ||
30 | CFLAGS += -I../../atrf/fw/include -I../include $(MACROS_$(TARGET)) | |
31 | LDLIBS = $(LDLIBS_$(TARGET)) -L../lib -latspi |
tools/atspi-id/Makefile | ||
---|---|---|
11 | 11 | # |
12 | 12 | |
13 | 13 | |
14 | F32XBASE = ../../../f32xbase | |
15 | ||
16 | 14 | MAIN = atspi-id |
17 | 15 | |
18 | include $(F32XBASE)/lib/Makefile.common | |
19 | ||
20 | CFLAGS += -I../../atrf/fw/include -I../include | |
21 | LDLIBS += -L../lib -latspi | |
16 | include ../Makefile.common |
tools/atspi-id/atspi-id.c | ||
---|---|---|
1 | 1 | /* |
2 | * atspi-id/atspi-id.c - Identify a ben-wpan AF86RF230 board | |
2 | * atspi-id/atspi-id.c - Identify a ben-wpan AT86RF230 board | |
3 | 3 | * |
4 | 4 | * Written 2010 by Werner Almesberger |
5 | 5 | * Copyright 2010 Werner Almesberger |
... | ... | |
37 | 37 | } |
38 | 38 | |
39 | 39 | |
40 | static int atspi_get_protocol(usb_dev_handle *dev, | |
40 | static int get_protocol(usb_dev_handle *dev, | |
41 | 41 | uint8_t *major, uint8_t *minor, uint8_t *target) |
42 | 42 | { |
43 | 43 | uint8_t ids[3]; |
... | ... | |
55 | 55 | } |
56 | 56 | |
57 | 57 | |
58 | static int atspi_get_build(usb_dev_handle *dev, char *buf, size_t size) | |
58 | static int get_build(usb_dev_handle *dev, char *buf, size_t size) | |
59 | 59 | { |
60 | 60 | int res; |
61 | 61 | |
... | ... | |
67 | 67 | } |
68 | 68 | |
69 | 69 | |
70 | static void show_info(usb_dev_handle *dev) | |
70 | static void show_usb_info(usb_dev_handle *dev) | |
71 | 71 | { |
72 | 72 | const struct usb_device *device = usb_device(dev); |
73 | 73 | uint8_t major, minor, target; |
74 | 74 | char buf[BUF_SIZE+1]; /* +1 for terminating \0 */ |
75 | 75 | int len; |
76 | uint8_t part, version, man_id_0, man_id_1; | |
77 | 76 | |
78 | 77 | printf("%04x:%04x ", |
79 | 78 | device->descriptor.idVendor, device->descriptor.idProduct); |
80 | 79 | |
81 | if (atspi_get_protocol(dev, &major, &minor, &target) < 0) | |
80 | if (get_protocol(dev, &major, &minor, &target) < 0) | |
82 | 81 | exit(1); |
83 | 82 | printf("protocol %u.%u hw %u\n", major, minor, target); |
84 | 83 | |
85 | len = atspi_get_build(dev, buf, sizeof(buf)-1); | |
84 | len = get_build(dev, buf, sizeof(buf)-1); | |
86 | 85 | if (len < 0) |
87 | 86 | exit(1); |
88 | 87 | buf[len] = 0; |
89 | 88 | printf("%10s%s\n", "", buf); |
89 | } | |
90 | ||
90 | 91 | |
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); | |
92 | static 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); | |
95 | 105 | printf("%10spart 0x%02x version %u manufacturer xxxx%02x%02x\n", "", |
96 | 106 | part, version, man_id_1, man_id_0); |
97 | 107 | } |
... | ... | |
106 | 116 | |
107 | 117 | int main(int argc, const char **argv) |
108 | 118 | { |
109 | usb_dev_handle *dev; | |
119 | struct atspi_dsc *dsc; | |
110 | 120 | |
111 | 121 | if (argc != 1) |
112 | 122 | usage(*argv); |
113 | dev = atspi_open(); | |
114 | if (!dev) | |
123 | dsc = atspi_open(); | |
124 | if (!dsc) | |
115 | 125 | return 1; |
116 | 126 | |
117 | show_info(dev); | |
127 | show_info(dsc); | |
118 | 128 | |
119 | 129 | return 0; |
120 | 130 | } |
tools/atspi-reset/Makefile | ||
---|---|---|
11 | 11 | # |
12 | 12 | |
13 | 13 | |
14 | F32XBASE = ../../../f32xbase | |
15 | ||
16 | 14 | MAIN = atspi-reset |
17 | 15 | |
18 | include $(F32XBASE)/lib/Makefile.common | |
19 | ||
20 | CFLAGS += -I../../atrf/fw/include -I../include | |
21 | LDLIBS += -L../lib -latspi | |
16 | include ../Makefile.common |
tools/atspi-reset/atspi-reset.c | ||
---|---|---|
1 | 1 | /* |
2 | * atspi-rssi/atspi-rssi.c - ben-wpan AF86RF230 spectrum scan | |
2 | * atspi-rssi/atspi-rssi.c - ben-wpan AT86RF230 spectrum scan | |
3 | 3 | * |
4 | 4 | * Written 2010 by Werner Almesberger |
5 | 5 | * Copyright 2010 Werner Almesberger |
... | ... | |
14 | 14 | #include <stdlib.h> |
15 | 15 | #include <stdio.h> |
16 | 16 | #include <string.h> |
17 | #include <usb.h> | |
18 | 17 | |
19 | 18 | #include "atspi.h" |
20 | 19 | |
... | ... | |
32 | 31 | |
33 | 32 | int main(int argc, const char **argv) |
34 | 33 | { |
35 | usb_dev_handle *dev; | |
34 | struct atspi_dsc *dsc; | |
36 | 35 | int txrx = 1; |
37 | 36 | |
38 | 37 | switch (argc) { |
... | ... | |
49 | 48 | usage(*argv); |
50 | 49 | } |
51 | 50 | |
52 | dev = atspi_open(); | |
53 | if (!dev) | |
51 | dsc = atspi_open(); | |
52 | if (!dsc) | |
54 | 53 | return 1; |
55 | 54 | |
56 | 55 | if (txrx) |
57 | atspi_reset_rf(dev); | |
56 | atspi_reset_rf(dsc); | |
58 | 57 | else |
59 | atspi_reset(dev); | |
58 | atspi_reset(dsc); | |
60 | 59 | return 0; |
61 | 60 | } |
62 | 61 |
tools/atspi-rssi/Makefile | ||
---|---|---|
11 | 11 | # |
12 | 12 | |
13 | 13 | |
14 | F32XBASE = ../../../f32xbase | |
15 | ||
16 | 14 | MAIN = atspi-rssi |
17 | 15 | |
18 | include $(F32XBASE)/lib/Makefile.common | |
19 | ||
20 | CFLAGS += -I../../atrf/fw/include -I../include | |
21 | LDLIBS += -L../lib -latspi | |
16 | include ../Makefile.common |
tools/atspi-rssi/atspi-rssi.c | ||
---|---|---|
1 | 1 | /* |
2 | * atspi-rssi/atspi-rssi.c - ben-wpan AF86RF230 spectrum scan | |
2 | * atspi-rssi/atspi-rssi.c - ben-wpan AT86RF230 spectrum scan | |
3 | 3 | * |
4 | 4 | * Written 2010 by Werner Almesberger |
5 | 5 | * Copyright 2010 Werner Almesberger |
... | ... | |
13 | 13 | |
14 | 14 | #include <stdlib.h> |
15 | 15 | #include <stdio.h> |
16 | #include <usb.h> | |
17 | 16 | #include <sys/time.h> |
18 | 17 | |
19 | 18 | #include "at86rf230.h" |
... | ... | |
24 | 23 | static struct timeval t0; |
25 | 24 | |
26 | 25 | |
27 | static void sweep(usb_dev_handle *dev) | |
26 | static void sweep(struct atspi_dsc *dsc) | |
28 | 27 | { |
29 | 28 | int chan, rssi; |
30 | 29 | struct timeval t; |
31 | 30 | |
32 | 31 | 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); | |
34 | 33 | /* |
35 | 34 | * No need to explicitly wait for the PPL lock - going USB-SPI |
36 | 35 | * is pretty slow, leaving the transceiver plenty of time. |
37 | 36 | */ |
38 | 37 | 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; | |
40 | 39 | t.tv_sec -= t0.tv_sec; |
41 | 40 | t.tv_usec -= t0.tv_usec; |
42 | 41 | printf("%d %f %d\n", |
... | ... | |
57 | 56 | |
58 | 57 | int main(int argc, const char **argv) |
59 | 58 | { |
60 | usb_dev_handle *dev; | |
59 | struct atspi_dsc *dsc; | |
61 | 60 | unsigned long sweeps, i; |
62 | 61 | char *end; |
63 | 62 | |
... | ... | |
67 | 66 | if (*end) |
68 | 67 | usage(*argv); |
69 | 68 | |
70 | dev = atspi_open(); | |
71 | if (!dev) | |
69 | dsc = atspi_open(); | |
70 | if (!dsc) | |
72 | 71 | return 1; |
73 | 72 | |
74 | atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_TRX_OFF); | |
73 | atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF); | |
75 | 74 | /* |
76 | 75 | * No need to explicitly wait for things to stabilize - going USB-SPI |
77 | 76 | * is pretty slow, leaving the transceiver more than enough time. |
78 | 77 | */ |
79 | atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_RX_ON); | |
78 | atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON); | |
80 | 79 | |
81 | 80 | gettimeofday(&t0, NULL); |
82 | 81 | for (i = 0; i != sweeps; i++) |
83 | sweep(dev); | |
82 | sweep(dsc); | |
84 | 83 | |
85 | atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_TRX_OFF); | |
84 | atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF); | |
86 | 85 | |
87 | 86 | return 0; |
88 | 87 | } |
tools/atspi-trim/Makefile | ||
---|---|---|
11 | 11 | # |
12 | 12 | |
13 | 13 | |
14 | F32XBASE = ../../../f32xbase | |
15 | ||
16 | 14 | MAIN = atspi-trim |
17 | 15 | |
18 | include $(F32XBASE)/lib/Makefile.common | |
19 | ||
20 | CFLAGS += -I../../atrf/fw/include -I../include | |
21 | LDLIBS += -L../lib -latspi | |
16 | include ../Makefile.common |
tools/atspi-trim/atspi-trim.c | ||
---|---|---|
1 | 1 | /* |
2 | * atspi-trim/atspi-trim.c - AF86RF230 oscillator trim utility | |
2 | * atspi-trim/atspi-trim.c - AT86RF230 oscillator trim utility | |
3 | 3 | * |
4 | 4 | * Written 2010 by Werner Almesberger |
5 | 5 | * Copyright 2010 Werner Almesberger |
... | ... | |
13 | 13 | |
14 | 14 | #include <stdlib.h> |
15 | 15 | #include <stdio.h> |
16 | #include <usb.h> | |
17 | 16 | #include <sys/time.h> |
18 | 17 | |
19 | 18 | #include "at86rf230.h" |
... | ... | |
30 | 29 | |
31 | 30 | int main(int argc, const char **argv) |
32 | 31 | { |
33 | usb_dev_handle *dev; | |
32 | struct atspi_dsc *dsc; | |
34 | 33 | int trim = -1; |
35 | 34 | char *end; |
36 | 35 | |
... | ... | |
46 | 45 | usage(*argv); |
47 | 46 | } |
48 | 47 | |
49 | dev = atspi_open(); | |
50 | if (!dev) | |
48 | dsc = atspi_open(); | |
49 | if (!dsc) | |
51 | 50 | return 1; |
52 | 51 | |
53 | 52 | 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; | |
55 | 54 | printf("%d (%d.%d pF)\n", trim, trim*3/10, trim*3 % 10); |
56 | 55 | } else { |
57 | atspi_reg_write(dev, REG_XOSC_CTRL, | |
56 | atspi_reg_write(dsc, REG_XOSC_CTRL, | |
58 | 57 | (XTAL_MODE_INT << XTAL_MODE_SHIFT) | trim); |
59 | 58 | } |
60 | 59 |
tools/atspi-txrx/Makefile | ||
---|---|---|
11 | 11 | # |
12 | 12 | |
13 | 13 | |
14 | F32XBASE = ../../../f32xbase | |
15 | ||
16 | 14 | MAIN = atspi-txrx |
17 | 15 | |
18 | include $(F32XBASE)/lib/Makefile.common | |
19 | ||
20 | CFLAGS += -I../../atrf/fw/include -I../include | |
21 | LDLIBS += -L../lib -latspi | |
16 | include ../Makefile.common |
tools/atspi-txrx/atspi-txrx.c | ||
---|---|---|
1 | 1 | /* |
2 | * atspi-txrx/atspi-txrx.c - ben-wpan AF86RF230 TX/RX | |
2 | * atspi-txrx/atspi-txrx.c - ben-wpan AT86RF230 TX/RX | |
3 | 3 | * |
4 | 4 | * Written 2010 by Werner Almesberger |
5 | 5 | * Copyright 2010 Werner Almesberger |
... | ... | |
13 | 13 | |
14 | 14 | #include <stdlib.h> |
15 | 15 | #include <stdio.h> |
16 | #include <unistd.h> | |
16 | 17 | #include <string.h> |
17 | #include <usb.h> | |
18 | 18 | |
19 | 19 | #include "at86rf230.h" |
20 | 20 | #include "atspi/ep0.h" |
... | ... | |
45 | 45 | }; |
46 | 46 | |
47 | 47 | |
48 | static usb_dev_handle *init_txrx(int trim) | |
48 | static struct atspi_dsc *init_txrx(int trim) | |
49 | 49 | { |
50 | usb_dev_handle *dev; | |
50 | struct atspi_dsc *dsc; | |
51 | 51 | |
52 | dev = atspi_open(); | |
53 | if (!dev) | |
52 | dsc = atspi_open(); | |
53 | if (!dsc) | |
54 | 54 | exit(1); |
55 | 55 | |
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, | |
59 | 59 | (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 */ | |
61 | 61 | |
62 | return dev; | |
62 | return dsc; | |
63 | 63 | } |
64 | 64 | |
65 | 65 | |
66 | static void set_channel(usb_dev_handle *dev, int channel) | |
66 | static void set_channel(struct atspi_dsc *dsc, int channel) | |
67 | 67 | { |
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); | |
69 | 69 | } |
70 | 70 | |
71 | 71 | |
72 | static void set_power(usb_dev_handle *dev, double power) | |
72 | static void set_power(struct atspi_dsc *dsc, double power) | |
73 | 73 | { |
74 | 74 | int n; |
75 | 75 | |
76 | 76 | for (n = 0; n != sizeof(tx_pwr)/sizeof(*tx_pwr)-1; n++) |
77 | 77 | if (tx_pwr[n] <= power) |
78 | 78 | 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); | |
80 | 80 | } |
81 | 81 | |
82 | 82 | |
83 | static void receive(usb_dev_handle *dev) | |
83 | static void receive(struct atspi_dsc *dsc) | |
84 | 84 | { |
85 | 85 | uint8_t irq; |
86 | 86 | uint8_t buf[MAX_PSDU+1]; /* PSDU+LQI */ |
87 | 87 | int n, ok, i; |
88 | 88 | uint8_t lq; |
89 | 89 | |
90 | atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_RX_ON); | |
90 | atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON); | |
91 | 91 | |
92 | (void) atspi_reg_read(dev, REG_IRQ_STATUS); | |
92 | (void) atspi_reg_read(dsc, REG_IRQ_STATUS); | |
93 | 93 | |
94 | 94 | fprintf(stderr, "Ready.\n"); |
95 | 95 | 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)) | |
98 | 98 | exit(1); |
99 | 99 | if (!irq) |
100 | 100 | continue; |
... | ... | |
116 | 116 | break; |
117 | 117 | } |
118 | 118 | |
119 | n = atspi_buf_read(dev, buf, sizeof(buf)); | |
119 | n = atspi_buf_read(dsc, buf, sizeof(buf)); | |
120 | 120 | if (n < 0) |
121 | 121 | exit(1); |
122 | 122 | if (n < 3) { |
123 | 123 | fprintf(stderr, "%d bytes received\n", n); |
124 | 124 | exit(1); |
125 | 125 | } |
126 | ok = !!(atspi_reg_read(dev, REG_PHY_RSSI) & RX_CRC_VALID); | |
126 | ok = !!(atspi_reg_read(dsc, REG_PHY_RSSI) & RX_CRC_VALID); | |
127 | 127 | lq = buf[n-1]; |
128 | 128 | fprintf(stderr, "%d bytes payload, CRC %s, LQI %u\n", |
129 | 129 | n-3, ok ? "OK" : "BAD", lq); |
... | ... | |
133 | 133 | } |
134 | 134 | |
135 | 135 | |
136 | static void transmit(usb_dev_handle *dev, const char *msg) | |
136 | static void transmit(struct atspi_dsc *dsc, const char *msg) | |
137 | 137 | { |
138 | 138 | uint8_t buf[MAX_PSDU]; |
139 | 139 | |
140 | atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_PLL_ON); | |
140 | atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON); | |
141 | 141 | |
142 | 142 | /* |
143 | 143 | * We need to copy the message to append the CRC placeholders. |
144 | 144 | */ |
145 | 145 | strcpy((void *) buf, msg); |
146 | atspi_buf_write(dev, buf, strlen(msg)+2); | |
146 | atspi_buf_write(dsc, buf, strlen(msg)+2); | |
147 | 147 | |
148 | 148 | /* @@@ 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); | |
150 | 150 | /* @@@ should wait for TX done */ |
151 | 151 | } |
152 | 152 | |
... | ... | |
170 | 170 | int trim = 0; |
171 | 171 | char *end; |
172 | 172 | int c; |
173 | usb_dev_handle *dev; | |
173 | struct atspi_dsc *dsc; | |
174 | 174 | |
175 | 175 | while ((c = getopt(argc, argv, "c:p:t:")) != EOF) |
176 | 176 | switch (c) { |
... | ... | |
199 | 199 | |
200 | 200 | switch (argc-optind) { |
201 | 201 | 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); | |
205 | 205 | break; |
206 | 206 | 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]); | |
211 | 211 | break; |
212 | 212 | default: |
213 | 213 | usage(*argv); |
tools/include/atspi.h | ||
---|---|---|
19 | 19 | struct atspi_dsc; |
20 | 20 | |
21 | 21 | |
22 | int atspi_error(void); | |
23 | int atspi_clear_error(void); | |
22 | void *atspi_usb_handle(struct atspi_dsc *dsc); /* hack for atspi-id */ | |
24 | 23 | |
25 | 24 | struct atspi_dsc *atspi_open(void); |
26 | 25 | void atspi_close(struct atspi_dsc *dsc); |
27 | 26 | |
27 | int atspi_error(struct atspi_dsc *dsc); | |
28 | int atspi_clear_error(struct atspi_dsc *dsc); | |
29 | ||
28 | 30 | void atspi_reset(struct atspi_dsc *dsc); |
29 | 31 | void atspi_reset_rf(struct atspi_dsc *dsc); |
30 | 32 |
tools/lib/Makefile | ||
---|---|---|
11 | 11 | # |
12 | 12 | |
13 | 13 | |
14 | F32XBASE = ../../../f32xbase | |
15 | ||
16 | 14 | LIB = libatspi.a |
17 | 15 | |
18 | CFLAGS = -Wall -I$(F32XBASE)/include -I../../atrf/fw/include -I../include | |
19 | OBJS = $(F32XBASE)/lib/usb.o atspi.o atusb.o | |
16 | include ../Makefile.common | |
17 | ||
18 | CFLAGS += -Wall -I$(F32XBASE)/include | |
19 | OBJS_host = atusb.o | |
20 | OBJS_ben = atusd.o | |
21 | OBJS = $(F32XBASE)/lib/usb.o atspi.o $(OBJS_$(TARGET)) | |
20 | 22 | |
21 | 23 | .PHONY: all clean spotless |
22 | 24 |
tools/lib/atspi.c | ||
---|---|---|
19 | 19 | |
20 | 20 | |
21 | 21 | extern struct atspi_driver atusb_driver; |
22 | extern struct atspi_driver atusd_driver; | |
22 | 23 | |
23 | 24 | |
24 | 25 | struct atspi_dsc { |
... | ... | |
27 | 28 | }; |
28 | 29 | |
29 | 30 | |
31 | void *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 | ||
41 | int atspi_error(struct atspi_dsc *dsc) | |
42 | { | |
43 | return dsc->driver->error ? dsc->driver->error(dsc->handle) : 0; | |
44 | } | |
45 | ||
46 | ||
47 | int 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 | ||
30 | 54 | struct atspi_dsc *atspi_open(void) |
31 | 55 | { |
32 | 56 | struct atspi_dsc *dsc; |
33 | 57 | struct atspi_driver *driver; |
34 | 58 | void *handle; |
35 | 59 | |
60 | #ifdef HAVE_USB | |
36 | 61 | driver = &atusb_driver; |
62 | #elif HAVE_USD | |
63 | driver = &atusd_driver; | |
64 | #else | |
65 | #error Need either HAVE_USB or HAVE_USD | |
66 | #endif | |
37 | 67 | handle = driver->open(); |
38 | 68 | if (!handle) |
39 | 69 | return NULL; |
tools/lib/atusb.c | ||
---|---|---|
31 | 31 | static int error; |
32 | 32 | |
33 | 33 | |
34 | int atusb_error(void) | |
34 | static int atusb_error(void *dsc) | |
35 | 35 | { |
36 | 36 | return error; |
37 | 37 | } |
38 | 38 | |
39 | 39 | |
40 | int atusb_clear_error(void) | |
40 | static int atusb_clear_error(void *dsc) | |
41 | 41 | { |
42 | 42 | int ret; |
43 | 43 | |
... | ... | |
191 | 191 | |
192 | 192 | |
193 | 193 | struct atspi_driver atusb_driver = { |
194 | .name = "atusb", | |
194 | .name = "USB", | |
195 | 195 | .open = atusb_open, |
196 | 196 | .close = atusb_close, |
197 | .error = atusb_error, | |
198 | .clear_error = atusb_clear_error, | |
197 | 199 | .reset = atusb_reset, |
198 | 200 | .reset_rf = atusb_reset_rf, |
199 | 201 | .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 | ||
25 | enum { | |
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 | ||
62 | struct atusd_dsc { | |
63 | int fd; | |
64 | void *mem; | |
65 | }; | |
66 | ||
67 | ||
68 | /* ----- Reset functions --------------------------------------------------- */ | |
69 | ||
70 | ||
71 | static 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 */ | |
109 | static 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 | ||
131 | static void spi_begin(struct atusd_dsc *dsc) | |
132 | { | |
133 | PDDATC = nSEL; | |
134 | } | |
135 | ||
136 | ||
137 | static void spi_end(struct atusd_dsc *dsc) | |
138 | { | |
139 | PDDATS = nSEL; | |
140 | } | |
141 | ||
142 | ||
143 | static void spi_data_in(struct atusd_dsc *dsc) | |
144 | { | |
145 | PDDIRC = MxSx; | |
146 | } | |
147 | ||
148 | ||
149 | static 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 | ||
161 | static 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 | ||
176 | static 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 | ||
192 | static void spi_finish(struct atusd_dsc *dsc) | |
193 | { | |
194 | PDDATC = SCLK; | |
195 | } | |
196 | ||
197 | ||
198 | static 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 | ||
208 | static 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 | ||
261 | static 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 | ||
276 | static void atusd_reset_rf(void *handle) | |
277 | { | |
278 | struct atusd_dsc *dsc = handle; | |
279 | ||
280 | atusd_cycle(dsc); | |
281 | } | |
282 | ||
283 | ||
284 | static 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 | ||
295 | static 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 | ||
314 | struct 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 | ||
---|---|---|
21 | 21 | const char *name; |
22 | 22 | void *(*open)(void); |
23 | 23 | void (*close)(void *dsc); |
24 | int (*error)(void *dsc); | |
25 | int (*clear_error)(void *dsc); | |
24 | 26 | void (*reset)(void *dsc); |
25 | 27 | void (*reset_rf)(void *dsc); |
26 | 28 | void (*reg_write)(void *dsc, uint8_t reg, uint8_t value); |