FreeCalypso > hg > freecalypso-sw
comparison loadtools/romload.c @ 9:fea204bc7674
fc-sertool compiles
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Wed, 01 May 2013 02:43:17 +0000 |
parents | |
children | e2e80a09338e |
comparison
equal
deleted
inserted
replaced
8:acaac9162574 | 9:fea204bc7674 |
---|---|
1 /* | |
2 * This module implements the communication protocol for pushing our | |
3 * IRAM-loadable code to the Calypso ROM bootloader. | |
4 */ | |
5 | |
6 #include <sys/types.h> | |
7 #include <sys/ioctl.h> | |
8 #include <sys/time.h> | |
9 #include <sys/errno.h> | |
10 #include <stdint.h> | |
11 #include <stdio.h> | |
12 #include <stdlib.h> | |
13 #include <strings.h> | |
14 #include <termios.h> | |
15 #include <unistd.h> | |
16 #include "srecreader.h" | |
17 | |
18 extern int errno; | |
19 | |
20 extern char *target_ttydev; | |
21 extern int target_fd; | |
22 | |
23 struct srecreader iramimage; | |
24 | |
25 static int beacon_interval = 13; /* in milliseconds */ | |
26 | |
27 static u_char beacon_cmd[2] = {'<', 'i'}; | |
28 | |
29 static u_char param_cmd[11] = {'<', 'p', | |
30 0x00, /* baud rate select code (115200) */ | |
31 0x00, /* DPLL setup: leave it off like on power-up, */ | |
32 /* OsmocomBB does the same thing */ | |
33 0x00, 0x04, /* chip select timing (WS) settings */ | |
34 /* our setting matches both OsmocomBB */ | |
35 /* and what the ROM runs with */ | |
36 /* before receiving this command */ | |
37 0x22, /* FFFF:F900 register config, low byte */ | |
38 /* OsmocomBB sends 0x00 here, but I've chosen */ | |
39 /* 0x22 to match the setting of this register */ | |
40 /* used by the boot ROM before this command. */ | |
41 0x00, 0x01, 0xD4, 0xC0 /* UART timeout */ | |
42 /* I've chosen the same value as what the */ | |
43 /* boot ROM runs with before getting this cmd */ | |
44 }; | |
45 | |
46 static u_char write_cmd[10] = {'<', 'w', 0x01, 0x01, 0x00}; | |
47 static u_char cksum_cmd[3] = {'<', 'c'}; | |
48 static u_char branch_cmd[6] = {'<', 'b'}; | |
49 | |
50 #define INTERMEDIATE_TIMEOUT 500 /* ms to wait for responses */ | |
51 #define SERIAL_FLUSH_DELAY 200 /* also in ms */ | |
52 | |
53 /* | |
54 * The following function should be called by command line option | |
55 * parsers upon encountering the -i option. | |
56 */ | |
57 set_beacon_interval(arg) | |
58 char *arg; | |
59 { | |
60 int i; | |
61 | |
62 i = atoi(arg); | |
63 if (i < 2 || i > 500) { | |
64 fprintf(stderr, "invalid -i argument specified\n"); | |
65 exit(1); | |
66 } | |
67 beacon_interval = i; | |
68 } | |
69 | |
70 static int | |
71 expect_response(timeout) | |
72 { | |
73 char buf[2]; | |
74 fd_set fds; | |
75 struct timeval tv; | |
76 int pass, cc; | |
77 | |
78 for (pass = 0; pass < 2; ) { | |
79 FD_ZERO(&fds); | |
80 FD_SET(target_fd, &fds); | |
81 tv.tv_sec = 0; | |
82 tv.tv_usec = timeout * 1000; | |
83 cc = select(target_fd+1, &fds, NULL, NULL, &tv); | |
84 if (cc < 0) { | |
85 if (errno == EINTR) | |
86 continue; | |
87 perror("select"); | |
88 exit(1); | |
89 } | |
90 if (cc < 1) | |
91 return(-1); | |
92 cc = read(target_fd, buf + pass, 2 - pass); | |
93 if (cc <= 0) { | |
94 perror("read after successful select"); | |
95 exit(1); | |
96 } | |
97 if (pass == 0 && buf[0] != '>') | |
98 continue; | |
99 pass += cc; | |
100 } | |
101 return(buf[1]); | |
102 } | |
103 | |
104 static | |
105 send_beacons() | |
106 { | |
107 printf("Sending beacons to %s\n", target_ttydev); | |
108 do | |
109 write(target_fd, beacon_cmd, sizeof beacon_cmd); | |
110 while (expect_response(beacon_interval) != 'i'); | |
111 return 0; | |
112 } | |
113 | |
114 static uint32_t | |
115 compute_block_cksum() | |
116 { | |
117 uint32_t sum; | |
118 int i, llen; | |
119 | |
120 sum = iramimage.datalen + 5; | |
121 llen = iramimage.datalen + 4; | |
122 for (i = 0; i < llen; i++) | |
123 sum = iramimage.record[i+1]; | |
124 return sum; | |
125 } | |
126 | |
127 perform_romload() | |
128 { | |
129 int resp; | |
130 uint16_t image_cksum; | |
131 unsigned long rec_count; | |
132 static int zero = 0; | |
133 | |
134 if (open_srec_file(&iramimage) < 0) | |
135 exit(1); | |
136 ioctl(target_fd, FIONBIO, &zero); | |
137 send_beacons(); | |
138 printf("Got beacon response, attempting download\n"); | |
139 | |
140 usleep(SERIAL_FLUSH_DELAY * 1000); | |
141 tcflush(target_fd, TCIFLUSH); | |
142 write(target_fd, param_cmd, sizeof param_cmd); | |
143 resp = expect_response(INTERMEDIATE_TIMEOUT); | |
144 if (resp != 'p') { | |
145 if (resp < 0) | |
146 fprintf(stderr, "No response to <p command\n"); | |
147 else if (isprint(resp)) | |
148 fprintf(stderr, | |
149 "Got >%c in response to <p command; expected >p\n", | |
150 resp); | |
151 else | |
152 fprintf(stderr, | |
153 "Got > %02X in response to <p command; expected >p\n", | |
154 resp); | |
155 exit(1); | |
156 } | |
157 printf("<p command successful, switching to 115200 baud\n"); | |
158 switch_baud_rate(B115200); | |
159 usleep(SERIAL_FLUSH_DELAY * 1000); | |
160 tcflush(target_fd, TCIFLUSH); | |
161 | |
162 image_cksum = 0; | |
163 for (rec_count = 0; ; rec_count++) { | |
164 if (read_s_record(&iramimage) < 0) | |
165 exit(1); | |
166 switch (iramimage.record_type) { | |
167 case '0': | |
168 if (iramimage.lineno == 1) | |
169 continue; | |
170 fprintf(stderr, | |
171 "%s: S0 record found in line %d (expected in line 1 only)\n", | |
172 iramimage.filename, iramimage.lineno); | |
173 exit(1); | |
174 case '3': | |
175 case '7': | |
176 if (s3s7_get_addr_data(&iramimage) < 0) | |
177 exit(1); | |
178 break; | |
179 default: | |
180 fprintf(stderr, | |
181 "%s line %d: S%c record type not supported\n", | |
182 iramimage.filename, iramimage.lineno, | |
183 iramimage.record_type); | |
184 exit(1); | |
185 } | |
186 if (iramimage.record_type == '7') | |
187 break; | |
188 /* must be S3 */ | |
189 if (iramimage.datalen < 1) { | |
190 fprintf(stderr, | |
191 "%s line %d: S3 record has zero data length\n", | |
192 iramimage.filename, iramimage.lineno); | |
193 exit(1); | |
194 } | |
195 /* form <w command */ | |
196 if (!rec_count) | |
197 printf("Sending image payload\n"); | |
198 write_cmd[5] = iramimage.datalen; | |
199 bcopy(iramimage.record + 1, write_cmd + 6, 4); | |
200 write(target_fd, write_cmd, sizeof write_cmd); | |
201 write(target_fd, iramimage.record + 5, iramimage.datalen); | |
202 /* update our checksum accumulator */ | |
203 image_cksum += ~(compute_block_cksum() & 0xFF); | |
204 /* collect response */ | |
205 resp = expect_response(INTERMEDIATE_TIMEOUT); | |
206 if (resp != 'w') { | |
207 fprintf(stderr, "Block #%lu: ", rec_count); | |
208 if (resp < 0) | |
209 fprintf(stderr, "No response to <w command\n"); | |
210 else if (isprint(resp)) | |
211 fprintf(stderr, | |
212 "Got >%c in response to <w command; expected >w\n", | |
213 resp); | |
214 else | |
215 fprintf(stderr, | |
216 "Got > %02X in response to <w command; expected >w\n", | |
217 resp); | |
218 exit(1); | |
219 } | |
220 /* on to the next record! */ | |
221 } | |
222 /* got S7 */ | |
223 fclose(iramimage.openfile); | |
224 if (!rec_count) { | |
225 fprintf(stderr, | |
226 "%s line %d: S7 without any preceding S3 data records\n", | |
227 iramimage.filename, iramimage.lineno); | |
228 exit(1); | |
229 } | |
230 | |
231 /* send <c */ | |
232 printf("Sending checksum\n"); | |
233 cksum_cmd[2] = ~(image_cksum & 0xFF); | |
234 write(target_fd, cksum_cmd, sizeof cksum_cmd); | |
235 resp = expect_response(INTERMEDIATE_TIMEOUT); | |
236 if (resp != 'c') { | |
237 if (resp < 0) | |
238 fprintf(stderr, "No response to <c command\n"); | |
239 else if (isprint(resp)) | |
240 fprintf(stderr, | |
241 "Got >%c in response to <c command; expected >c\n", | |
242 resp); | |
243 else | |
244 fprintf(stderr, | |
245 "Got > %02X in response to <c command; expected >c\n", | |
246 resp); | |
247 exit(1); | |
248 } | |
249 printf("<c command successful, sending <b\n"); | |
250 | |
251 bcopy(iramimage.record + 1, branch_cmd + 2, 4); | |
252 write(target_fd, branch_cmd, sizeof branch_cmd); | |
253 resp = expect_response(INTERMEDIATE_TIMEOUT); | |
254 if (resp != 'b') { | |
255 if (resp < 0) | |
256 fprintf(stderr, "No response to <b command\n"); | |
257 else if (isprint(resp)) | |
258 fprintf(stderr, | |
259 "Got >%c in response to <b command; expected >b\n", | |
260 resp); | |
261 else | |
262 fprintf(stderr, | |
263 "Got > %02X in response to <b command; expected >b\n", | |
264 resp); | |
265 exit(1); | |
266 } | |
267 printf("<b command successful: downloaded image should now be running!\n"); | |
268 return(0); | |
269 } |