IEEE 802.15.4 subsystem
Sign in or create your account | Project List | Help
IEEE 802.15.4 subsystem Git Source Tree
Root/
Source at commit c7303e4ac152c793db957c4ff453451b8098e5b7 created 13 years 7 months ago. By Werner Almesberger, Made communication with CNTR board more robust. Added documentation. | |
---|---|
1 | /* |
2 | * cntr/ep0.c - EP0 extension protocol |
3 | * |
4 | * Written 2008-2010 by Werner Almesberger |
5 | * Copyright 2008-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 | |
16 | #ifndef NULL |
17 | #define NULL 0 |
18 | #endif |
19 | |
20 | #include "regs.h" |
21 | #include "usb.h" |
22 | #include "cntr/ep0.h" |
23 | #include "version.h" |
24 | |
25 | #define debug(...) |
26 | #define error(...) |
27 | |
28 | |
29 | /* |
30 | * SDCC 2.8.0 had a number of code generation bugs that appeared in the big |
31 | * switch statement of my_setup. SDCC_FORCE_UPDATE forced the value of the |
32 | * "size" variable to be written to memory. This work-around doesn't seem |
33 | * to be necessary with 2.9.0, but we keep it around, just in case. |
34 | * |
35 | * Unfortunately, the setup->bRequest garbling bug is still with us. Without |
36 | * the evaluation forced with SDCC_FORCE_EVAL, sdcc gets confused about the |
37 | * value of setup->bRequest and then rejects all SETUP requests. |
38 | */ |
39 | |
40 | #define SDCC_FORCE_EVAL(type, value) \ |
41 | do { \ |
42 | static volatile type foo; \ |
43 | foo = value; \ |
44 | } while (0) |
45 | |
46 | #define SDCC_FORCE_UPDATE(type, var) \ |
47 | do { \ |
48 | volatile type foo; \ |
49 | foo = var; \ |
50 | var = foo; \ |
51 | } while (0) |
52 | |
53 | |
54 | extern uint8_t cntr[8]; |
55 | |
56 | static const uint8_t id[] = { EP0CNTR_MAJOR, EP0CNTR_MINOR, HW_TYPE }; |
57 | static __xdata uint8_t buf[128]; |
58 | |
59 | |
60 | #define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */ |
61 | |
62 | |
63 | /* crc32() */ |
64 | #include "cntr/crc32.c" |
65 | |
66 | |
67 | static __bit my_setup(struct setup_request *setup) __reentrant |
68 | { |
69 | uint32_t tmp; |
70 | uint8_t size, i; |
71 | |
72 | switch (setup->bmRequestType | setup->bRequest << 8) { |
73 | case CNTR_FROM_DEV(CNTR_ID): |
74 | debug("CNTR_ID\n"); |
75 | if (setup->wLength > 3) |
76 | return 0; |
77 | usb_send(&ep0, id, setup->wLength, NULL, NULL); |
78 | return 1; |
79 | case CNTR_FROM_DEV(CNTR_BUILD): |
80 | debug("CNTR_BUILD\n"); |
81 | tmp = build_number; |
82 | for (i = BUILD_OFFSET-2; tmp; i--) { |
83 | buf[i] = (tmp % 10)+'0'; |
84 | tmp /= 10; |
85 | } |
86 | buf[i] = '#'; |
87 | buf[BUILD_OFFSET-1] = ' '; |
88 | for (size = 0; build_date[size]; size++) |
89 | buf[BUILD_OFFSET+size] = build_date[size]; |
90 | size += BUILD_OFFSET-i+1; |
91 | SDCC_FORCE_EVAL(uint8_t, setup->bRequest); |
92 | if (size > setup->wLength) |
93 | return 0; |
94 | usb_send(&ep0, buf+i, size, NULL, NULL); |
95 | return 1; |
96 | |
97 | case CNTR_TO_DEV(CNTR_RESET): |
98 | debug("CNTR_RESET\n"); |
99 | RSTSRC = SWRSF; |
100 | while (1); |
101 | |
102 | case CNTR_FROM_DEV(CNTR_READ): |
103 | debug("CNTR_READ\n"); |
104 | buf[0] = cntr[0]; |
105 | buf[1] = cntr[1]; |
106 | buf[2] = cntr[2]; |
107 | buf[3] = cntr[3]; |
108 | tmp = (uint32_t) buf[0] | ((uint32_t) buf[1] << 8) | |
109 | ((uint32_t) buf[2] << 16) | ((uint32_t) buf[3] << 24); |
110 | tmp = crc32(tmp, 0xffffffff); |
111 | buf[4] = tmp; |
112 | buf[5] = tmp >> 8; |
113 | buf[6] = tmp >> 16; |
114 | buf[7] = tmp >> 24; |
115 | buf[8] = ~cntr[0]; |
116 | buf[9] = ~cntr[1]; |
117 | buf[10] = ~cntr[2]; |
118 | buf[11] = ~cntr[3]; |
119 | usb_send(&ep0, buf, 12, NULL, NULL); |
120 | return 1; |
121 | |
122 | default: |
123 | error("Unrecognized SETUP: 0x%02x 0x%02x ...\n", |
124 | setup->bmRequestType, setup->bRequest); |
125 | return 0; |
126 | } |
127 | } |
128 | |
129 | |
130 | void ep0_init(void) |
131 | { |
132 | user_setup = my_setup; |
133 | } |
134 |