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 }