修訂 | 4bf9efba35113d91b56fb25ce16d6dd829b9195d (tree) |
---|---|
時間 | 2011-04-27 01:08:59 |
作者 | Yoshinori Sato <ysato@user...> |
Commiter | Yoshinori Sato |
RX with USB support.
@@ -1,17 +1,21 @@ | ||
1 | 1 | CC = gcc |
2 | 2 | CFLAGS = -Wall -O2 -g |
3 | -OBJS = main.o comm.o | |
3 | +OBJS = main.o comm.o serial.o usb.o | |
4 | 4 | TARGET= h8flash |
5 | 5 | |
6 | 6 | all: h8flash |
7 | 7 | |
8 | -$(TARGET): main.o comm.o | |
9 | - $(CC) -o $(TARGET) $(OBJS) | |
8 | +$(TARGET): $(OBJS) | |
9 | + $(CC) -o $(TARGET) $(OBJS) -lusb | |
10 | 10 | |
11 | 11 | main.o: main.c h8flash.h |
12 | 12 | |
13 | 13 | comm.o: comm.c h8flash.h |
14 | 14 | |
15 | +serial.o: serial.c h8flash.h | |
16 | + | |
17 | +usb.o: usb.c | |
18 | + | |
15 | 19 | .phony: clean |
16 | 20 | |
17 | 21 | clean: |
@@ -16,82 +16,59 @@ | ||
16 | 16 | #include <termios.h> |
17 | 17 | #include <fcntl.h> |
18 | 18 | #include <stdlib.h> |
19 | +#include <errno.h> | |
19 | 20 | #include "h8flash.h" |
20 | 21 | |
21 | 22 | #define TRY1COUNT 60 |
22 | 23 | #define BAUD_ADJUST_LEN 30 |
23 | 24 | |
24 | -#define ACK 0x06 | |
25 | - | |
26 | -#define QUERY_DEVICE 0x20 | |
27 | -#define QUERY_DEVICE_RES 0x30 | |
28 | -#define QUERY_CLOCKMODE 0x21 | |
29 | -#define QUERY_CLOCKMODE_RES 0x31 | |
30 | -#define QUERY_MULTIRATE 0x22 | |
31 | -#define QUERY_MULTIRATE_RES 0x32 | |
32 | -#define QUERY_FREQ 0x23 | |
33 | -#define QUERY_FREQ_RES 0x33 | |
34 | -#define QUERY_BOOT_AREA 0x24 | |
35 | -#define QUERY_BOOT_AREA_RES 0x34 | |
36 | -#define QUERY_USER_AREA 0x25 | |
37 | -#define QUERY_USER_AREA_RES 0x35 | |
38 | -#define QUERY_WRITESIZE 0x27 | |
39 | -#define QUERY_WRITESIZE_RES 0x37 | |
40 | - | |
41 | -#define SELECT_DEVICE 0x10 | |
42 | -#define SET_CLOCKMODE 0x11 | |
43 | - | |
44 | -#define SET_BITRATE 0x3f | |
45 | - | |
46 | -#define WRITEMODE 0x40 | |
47 | -#define WRITE_USERBOOT 0x42 | |
48 | -#define WRITE_USER 0x43 | |
49 | -#define BLANKCHECK_USERBOOT 0x4c | |
50 | -#define BLANKCHECK_USER 0x4d | |
51 | -#define WRITE128 0x50 | |
52 | - | |
53 | 25 | /* NAK answer list */ |
54 | 26 | const unsigned char naktable[] = {0x80, 0x90, 0x91, 0xbf, 0xc0, 0xc2, 0xc3, 0xc8, |
55 | 27 | 0xcc, 0xcd, 0xd0, 0xd2, 0xd8}; |
56 | 28 | |
57 | -/* send multibyte command */ | |
58 | -static void send(int ser_fd, char *data, int len) | |
29 | +/* big endian to cpu endian convert 32bit */ | |
30 | +static __inline__ int getlong(unsigned char *p) | |
59 | 31 | { |
60 | - unsigned char sum; | |
61 | - write(ser_fd, data, len); | |
62 | - for(sum = 0; len > 0; len--, data++) | |
63 | - sum += *data; | |
64 | - sum = 0x100 - sum; | |
65 | - write(ser_fd, &sum, 1); | |
32 | + return (*p << 24) | (*(p+1) << 16) | (*(p+2) << 8) | *(p+3); | |
33 | +} | |
34 | + | |
35 | +/* big endian to cpu endian convert 16bit */ | |
36 | +static __inline__ short getword(unsigned char *p) | |
37 | +{ | |
38 | + return (*p << 8) | *(p+1); | |
66 | 39 | } |
67 | 40 | |
68 | -/* receive 1byte */ | |
69 | -static int receive_byte(int ser_fd, char *data) | |
41 | +/* cpu endian to big endian 32bit */ | |
42 | +static __inline__ void setlong(unsigned char *buf, unsigned long val) | |
70 | 43 | { |
71 | - int r; | |
72 | - struct timeval tv; | |
73 | - fd_set fdset; | |
74 | - | |
75 | - *data = 0; | |
76 | - tv.tv_sec = 60; | |
77 | - tv.tv_usec = 0; | |
78 | - FD_ZERO(&fdset); | |
79 | - FD_SET(ser_fd, &fdset); | |
80 | - r = select(ser_fd + 1, &fdset, NULL, NULL, &tv); | |
81 | - if (r == -1) | |
82 | - return -1; | |
83 | - return read(ser_fd, data, 1); | |
44 | + *(buf + 0) = (val >> 24) & 0xff; | |
45 | + *(buf + 1) = (val >> 16) & 0xff; | |
46 | + *(buf + 2) = (val >> 8) & 0xff; | |
47 | + *(buf + 3) = (val ) & 0xff; | |
48 | +} | |
49 | + | |
50 | +/* send multibyte command */ | |
51 | +static void send(struct port_t *p, unsigned char *data, int len) | |
52 | +{ | |
53 | + unsigned char sum; | |
54 | + p->send_data(data, len); | |
55 | + if (len > 1) { | |
56 | + for(sum = 0; len > 0; len--, data++) | |
57 | + sum += *data; | |
58 | + sum = 0x100 - sum; | |
59 | + p->send_data(&sum, 1); | |
60 | + } | |
84 | 61 | } |
85 | 62 | |
86 | 63 | /* receive answer */ |
87 | -static int receive(int ser_fd, char *data) | |
64 | +static int receive(struct port_t *p, unsigned char *data) | |
88 | 65 | { |
89 | 66 | int len; |
90 | 67 | unsigned char *rxptr; |
91 | 68 | unsigned char sum; |
92 | 69 | |
93 | 70 | rxptr = data; |
94 | - if (receive_byte(ser_fd, rxptr) != 1) | |
71 | + if (p->receive_byte(rxptr) != 1) | |
95 | 72 | return -1; |
96 | 73 | rxptr++; |
97 | 74 | /* ACK */ |
@@ -100,19 +77,19 @@ static int receive(int ser_fd, char *data) | ||
100 | 77 | } |
101 | 78 | /* NAK */ |
102 | 79 | if (memchr(naktable, *data, sizeof(naktable))) { |
103 | - if (receive_byte(ser_fd, rxptr) != 1) | |
80 | + if (p->receive_byte(rxptr) != 1) | |
104 | 81 | return -1; |
105 | 82 | else |
106 | 83 | return 2; |
107 | 84 | } |
108 | 85 | |
109 | 86 | /* multibyte response */ |
110 | - if (receive_byte(ser_fd, rxptr) != 1) | |
87 | + if (p->receive_byte(rxptr) != 1) | |
111 | 88 | return -1; |
112 | 89 | rxptr++; |
113 | 90 | len = *(data + 1) + 1; |
114 | 91 | for(; len > 0; len--) { |
115 | - if (receive_byte(ser_fd, rxptr) != 1) | |
92 | + if (p->receive_byte(rxptr) != 1) | |
116 | 93 | return -1; |
117 | 94 | rxptr++; |
118 | 95 | } |
@@ -129,124 +106,8 @@ static int receive(int ser_fd, char *data) | ||
129 | 106 | return *(data + 1); |
130 | 107 | } |
131 | 108 | |
132 | -/* big endian to cpu endian convert 32bit */ | |
133 | -static __inline__ int getlong(unsigned char *p) | |
134 | -{ | |
135 | - return (*p << 24) | (*(p+1) << 16) | (*(p+2) << 8) | *(p+3); | |
136 | -} | |
137 | - | |
138 | -/* big endian to cpu endian convert 16bit */ | |
139 | -static __inline__ short getword(unsigned char *p) | |
140 | -{ | |
141 | - return (*p << 8) | *(p+1); | |
142 | -} | |
143 | - | |
144 | -/* cpu endian to big endian 32bit */ | |
145 | -static __inline__ void setlong(unsigned char *buf, unsigned long val) | |
146 | -{ | |
147 | - *(buf + 0) = (val >> 24) & 0xff; | |
148 | - *(buf + 1) = (val >> 16) & 0xff; | |
149 | - *(buf + 2) = (val >> 8) & 0xff; | |
150 | - *(buf + 3) = (val ) & 0xff; | |
151 | -} | |
152 | - | |
153 | -/* set host bitrate */ | |
154 | -static int setbaud(int ser_fd, int bitrate) | |
155 | -{ | |
156 | - int b; | |
157 | - struct termios serattr; | |
158 | - | |
159 | - b = 0; | |
160 | - switch (bitrate) { | |
161 | - case 96: b = B9600; break; | |
162 | - case 192: b = B19200; break; | |
163 | - case 384: b = B38400; break; | |
164 | - case 576: b = B57600; break; | |
165 | - case 1152: b = B115200; break; | |
166 | - } | |
167 | - if (b == 0) | |
168 | - return 0; | |
169 | - | |
170 | - tcgetattr(ser_fd, &serattr); | |
171 | - cfsetospeed(&serattr, b); | |
172 | - cfsetispeed(&serattr, b); | |
173 | - tcsetattr(ser_fd, TCSANOW, &serattr); | |
174 | - return 1; | |
175 | -} | |
176 | - | |
177 | -/* host serial open */ | |
178 | -int open_serial(const char *ser_port) | |
179 | -{ | |
180 | - int ser_fd; | |
181 | - struct termios serattr; | |
182 | - | |
183 | - ser_fd = open(ser_port, O_RDWR); | |
184 | - if (ser_fd == -1) { | |
185 | - perror("PROGNAME: "); | |
186 | - return -1; | |
187 | - } | |
188 | - | |
189 | - tcgetattr(ser_fd, &serattr); | |
190 | - serattr.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON | IXOFF); | |
191 | - serattr.c_oflag &= ~OPOST; | |
192 | - serattr.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); | |
193 | - serattr.c_cflag &= ~(CSIZE | PARENB); | |
194 | - serattr.c_cflag |= CS8 | CLOCAL; | |
195 | - serattr.c_cc[VMIN] = 1; | |
196 | - serattr.c_cc[VTIME] = 0; | |
197 | - cfsetospeed(&serattr, B9600); | |
198 | - cfsetispeed(&serattr, B9600); | |
199 | - tcsetattr(ser_fd, TCSANOW, &serattr); | |
200 | - | |
201 | - return ser_fd; | |
202 | -} | |
203 | - | |
204 | -/* connection target CPU */ | |
205 | -int connect_target(int ser_fd) | |
206 | -{ | |
207 | - int try1; | |
208 | - int r; | |
209 | - struct timeval tv; | |
210 | - fd_set fdset; | |
211 | - unsigned char buf[BAUD_ADJUST_LEN]; | |
212 | - | |
213 | - /* wait connection establish */ | |
214 | - for(try1 = 0; try1 < TRY1COUNT; try1++) { | |
215 | - memset(buf, 0x00, BAUD_ADJUST_LEN); | |
216 | - /* send dummy data */ | |
217 | - write(ser_fd, buf, BAUD_ADJUST_LEN); | |
218 | - tv.tv_sec = 1; | |
219 | - tv.tv_usec = 0; | |
220 | - FD_ZERO(&fdset); | |
221 | - FD_SET(ser_fd, &fdset); | |
222 | - /* wait reply */ | |
223 | - r = select(ser_fd + 1, &fdset, NULL, NULL, &tv); | |
224 | - if (r == -1) | |
225 | - return 0; | |
226 | - if ((r > 0) && (read(ser_fd, buf, 1) == 1) && buf[0] == 0) | |
227 | - goto connect; | |
228 | - if (try1 == 0) { | |
229 | - printf("now connection"); | |
230 | - fflush(stdout); | |
231 | - } else { | |
232 | - putchar('.'); | |
233 | - fflush(stdout); | |
234 | - } | |
235 | - } | |
236 | - putchar('\n'); | |
237 | - return 0; | |
238 | - connect: | |
239 | - /* connect done */ | |
240 | - buf[0] = 0x55; | |
241 | - write(ser_fd, buf, 1); | |
242 | - if ((receive_byte(ser_fd, buf) == 1) && (buf[0] == 0xe6)) | |
243 | - return 1; /* ok */ | |
244 | - else | |
245 | - return 0; /* ng */ | |
246 | -} | |
247 | - | |
248 | 109 | /* get target device list */ |
249 | -struct devicelist_t *get_devicelist(int ser_fd) | |
110 | +struct devicelist_t *get_devicelist(struct port_t *port) | |
250 | 111 | { |
251 | 112 | unsigned char rxbuf[255+3]; |
252 | 113 | unsigned char *devp; |
@@ -254,14 +115,14 @@ struct devicelist_t *get_devicelist(int ser_fd) | ||
254 | 115 | int devno; |
255 | 116 | |
256 | 117 | rxbuf[0] = QUERY_DEVICE; |
257 | - write(ser_fd, rxbuf, 1); | |
258 | - if (receive(ser_fd, rxbuf) == -1) | |
118 | + send(port, rxbuf, 1); | |
119 | + if (receive(port, rxbuf) == -1) | |
259 | 120 | return NULL; |
260 | 121 | if (rxbuf[0] != QUERY_DEVICE_RES) |
261 | 122 | return NULL; |
262 | 123 | |
263 | 124 | devno = rxbuf[2]; |
264 | - devlist = (struct devicelist_t *)malloc(sizeof(struct devicelist_t) + | |
125 | + devlist = (struct devicelist_t *)malloc(sizeof(struct devicelist_t) + | |
265 | 126 | sizeof(struct devinfo_t) * devno); |
266 | 127 | if (devlist == NULL) |
267 | 128 | return NULL; |
@@ -272,26 +133,25 @@ struct devicelist_t *get_devicelist(int ser_fd) | ||
272 | 133 | memcpy(devlist->devs[devno].code, devp + 1, 4); |
273 | 134 | memcpy(devlist->devs[devno].name, devp + 5, *devp-4); |
274 | 135 | devlist->devs[devno].name[*devp - 4] = 0; |
275 | - devp += 1 + 4 + *devp; | |
136 | + devp += *devp; | |
276 | 137 | } |
277 | 138 | return devlist; |
278 | 139 | } |
279 | 140 | |
280 | 141 | /* set target device ID */ |
281 | -int select_device(int ser_fd, const char *code) | |
142 | +int select_device(struct port_t *port, const char *code) | |
282 | 143 | { |
283 | - char buf[6] = {SELECT_DEVICE, 0x04, 0x00, 0x00, 0x00, 0x00}; | |
144 | + unsigned char buf[6] = {SELECT_DEVICE, 0x04, 0x00, 0x00, 0x00, 0x00}; | |
284 | 145 | |
285 | 146 | memcpy(&buf[2], code, 4); |
286 | - send(ser_fd, buf, sizeof(buf)); | |
287 | - if (receive(ser_fd, buf) != 1) | |
147 | + send(port, buf, sizeof(buf)); | |
148 | + if (receive(port, buf) != 1) | |
288 | 149 | return 0; |
289 | - else | |
290 | - return 1; | |
150 | + return 1; | |
291 | 151 | } |
292 | 152 | |
293 | 153 | /* get target clock mode */ |
294 | -struct clockmode_t *get_clockmode(int ser_fd) | |
154 | +struct clockmode_t *get_clockmode(struct port_t *port) | |
295 | 155 | { |
296 | 156 | unsigned char rxbuf[255+3]; |
297 | 157 | unsigned char *clkmdp; |
@@ -299,13 +159,17 @@ struct clockmode_t *get_clockmode(int ser_fd) | ||
299 | 159 | int numclock; |
300 | 160 | |
301 | 161 | rxbuf[0] = QUERY_CLOCKMODE; |
302 | - write(ser_fd, rxbuf, 1); | |
303 | - if (receive(ser_fd, rxbuf) == -1) | |
162 | + send(port, rxbuf, 1); | |
163 | + if (receive(port, rxbuf) == -1) | |
304 | 164 | return NULL; |
305 | 165 | if (rxbuf[0] != QUERY_CLOCKMODE_RES) |
306 | 166 | return NULL; |
307 | 167 | |
308 | 168 | numclock = rxbuf[2]; |
169 | + if (numclock == 0) { | |
170 | + numclock = 1; | |
171 | + rxbuf[3] = 0; | |
172 | + } | |
309 | 173 | clocks = (struct clockmode_t *)malloc(sizeof(struct clockmode_t) + |
310 | 174 | sizeof(int) * numclock); |
311 | 175 | if (clocks == NULL) |
@@ -319,64 +183,66 @@ struct clockmode_t *get_clockmode(int ser_fd) | ||
319 | 183 | } |
320 | 184 | |
321 | 185 | /* set target clock mode */ |
322 | -int set_clockmode(int ser_fd, int mode) | |
186 | +int set_clockmode(struct port_t *port, int mode) | |
323 | 187 | { |
324 | - char buf[3] = {SET_CLOCKMODE, 0x01, 0x00}; | |
188 | + unsigned char buf[3] = {SET_CLOCKMODE, 0x01, 0x00}; | |
325 | 189 | |
326 | 190 | buf[2] = mode; |
327 | - send(ser_fd, buf, sizeof(buf)); | |
328 | - if (receive(ser_fd, buf) != 1) | |
191 | + send(port, buf, sizeof(buf)); | |
192 | + if (receive(port, buf) != 1) | |
329 | 193 | return 0; |
330 | 194 | else |
331 | 195 | return 1; |
332 | 196 | } |
333 | 197 | |
334 | 198 | /* get target multiplier/divider rate */ |
335 | -struct multilist_t *get_multirate(int ser_fd) | |
199 | +struct multilist_t *get_multirate(struct port_t *port) | |
336 | 200 | { |
337 | 201 | unsigned char rxbuf[255+3]; |
338 | 202 | unsigned char *mulp; |
339 | 203 | struct multilist_t *multilist; |
204 | + struct multirate_t *rate; | |
340 | 205 | int nummulti; |
341 | 206 | int numrate; |
342 | 207 | int listsize; |
343 | - signed char rate; | |
344 | 208 | |
345 | 209 | rxbuf[0] = QUERY_MULTIRATE; |
346 | - write(ser_fd, rxbuf, 1); | |
347 | - if (receive(ser_fd, rxbuf) == -1) | |
210 | + send(port, rxbuf, 1); | |
211 | + if (receive(port, rxbuf) == -1) | |
348 | 212 | return NULL; |
349 | 213 | if (rxbuf[0] != QUERY_MULTIRATE_RES) |
350 | 214 | return NULL; |
351 | 215 | |
352 | 216 | /* calc multilist size */ |
353 | 217 | nummulti = rxbuf[2]; |
354 | - listsize = sizeof(struct multilist_t); | |
218 | + listsize = sizeof(struct multilist_t) + sizeof(struct multirate_t *) * nummulti; | |
355 | 219 | mulp = &rxbuf[3]; |
356 | - for (; nummulti > 0; nummulti--) { | |
357 | - listsize += sizeof(struct multirate_t) + sizeof(int) * (*mulp); | |
358 | - mulp += *mulp + 1; | |
220 | + for(; nummulti > 0; nummulti--) { | |
221 | + listsize += sizeof(struct multirate_t) + sizeof(int) * *mulp; | |
222 | + mulp += *mulp; | |
359 | 223 | } |
360 | - | |
361 | 224 | multilist = (struct multilist_t *)malloc(listsize); |
362 | 225 | if (multilist == NULL) |
363 | 226 | return NULL; |
364 | 227 | |
365 | - /* setup multilist */ | |
228 | + /* setup list */ | |
366 | 229 | multilist->nummulti = rxbuf[2]; |
230 | + rate = (struct multirate_t *)&multilist->muls[multilist->nummulti]; | |
367 | 231 | mulp = &rxbuf[3]; |
368 | 232 | for (nummulti = 0; nummulti < multilist->nummulti; nummulti++) { |
369 | - multilist->muls[nummulti].numrate = *mulp++; | |
370 | - for (numrate = 0; numrate < multilist->muls[nummulti].numrate; numrate++) { | |
371 | - rate = *mulp++; | |
372 | - multilist->muls[nummulti].rate[numrate] = rate; | |
233 | + multilist->muls[nummulti] = rate; | |
234 | + rate->numrate = *mulp++; | |
235 | + for (numrate = 0; numrate < rate->numrate; numrate++) { | |
236 | + rate->rate[numrate] = *mulp++; | |
373 | 237 | } |
374 | - } | |
238 | + rate = (struct multirate_t *)&rate->rate[numrate]; | |
239 | + } | |
240 | + | |
375 | 241 | return multilist; |
376 | 242 | } |
377 | 243 | |
378 | 244 | /* get target operation frequency list */ |
379 | -struct freqlist_t *get_freqlist(int ser_fd) | |
245 | +struct freqlist_t *get_freqlist(struct port_t *port) | |
380 | 246 | { |
381 | 247 | unsigned char rxbuf[255+3]; |
382 | 248 | unsigned char *freqp; |
@@ -384,8 +250,8 @@ struct freqlist_t *get_freqlist(int ser_fd) | ||
384 | 250 | int numfreq; |
385 | 251 | |
386 | 252 | rxbuf[0] = QUERY_FREQ; |
387 | - write(ser_fd, rxbuf, 1); | |
388 | - if (receive(ser_fd, rxbuf) == -1) | |
253 | + send(port, rxbuf, 1); | |
254 | + if (receive(port, rxbuf) == -1) | |
389 | 255 | return NULL; |
390 | 256 | if (rxbuf[0] != QUERY_FREQ_RES) |
391 | 257 | return NULL; |
@@ -407,7 +273,7 @@ struct freqlist_t *get_freqlist(int ser_fd) | ||
407 | 273 | } |
408 | 274 | |
409 | 275 | /* get target rom mapping */ |
410 | -struct arealist_t *get_arealist(enum mat_t mat, int ser_fd) | |
276 | +struct arealist_t *get_arealist(struct port_t *port, enum mat_t mat) | |
411 | 277 | { |
412 | 278 | char ans; |
413 | 279 | unsigned char rxbuf[255+3]; |
@@ -427,8 +293,8 @@ struct arealist_t *get_arealist(enum mat_t mat, int ser_fd) | ||
427 | 293 | default: |
428 | 294 | return NULL; |
429 | 295 | } |
430 | - write(ser_fd, rxbuf, 1); | |
431 | - if (receive(ser_fd, rxbuf) == -1) | |
296 | + send(port, rxbuf, 1); | |
297 | + if (receive(port, rxbuf) == -1) | |
432 | 298 | return NULL; |
433 | 299 | if (rxbuf[0] != ans) |
434 | 300 | return NULL; |
@@ -450,26 +316,50 @@ struct arealist_t *get_arealist(enum mat_t mat, int ser_fd) | ||
450 | 316 | } |
451 | 317 | |
452 | 318 | /* get write page size */ |
453 | -int get_writesize(int ser_fd) | |
319 | +int get_writesize(struct port_t *port) | |
454 | 320 | { |
455 | 321 | unsigned char rxbuf[5]; |
322 | + unsigned short size; | |
456 | 323 | |
457 | 324 | rxbuf[0] = QUERY_WRITESIZE; |
458 | - write(ser_fd, rxbuf, 1); | |
459 | - if (receive(ser_fd, rxbuf) == -1) | |
325 | + send(port, rxbuf, 1); | |
326 | + if (receive(port, rxbuf) == -1) | |
460 | 327 | return -1; |
461 | 328 | if (rxbuf[0] != QUERY_WRITESIZE_RES) |
462 | 329 | return -1; |
463 | 330 | |
464 | 331 | if (rxbuf[1] != 2) |
465 | 332 | return -1; |
466 | - return rxbuf[2] << 8 | rxbuf[3]; | |
333 | + size = rxbuf[2] << 8 | rxbuf[3]; | |
334 | + return size; | |
335 | +} | |
336 | + | |
337 | +/* bitrate candidate list */ | |
338 | +static const int rate_list[]={1152,576,384,192,96}; | |
339 | + | |
340 | +/* bitrate error margine (%) */ | |
341 | +#define ERR_MARGIN 4 | |
342 | + | |
343 | +/* select communication bitrate */ | |
344 | +static int adjust_bitrate(int p_freq) | |
345 | +{ | |
346 | + int brr; | |
347 | + int errorrate; | |
348 | + int rate_no; | |
349 | + | |
350 | + for (rate_no = 0; rate_no < sizeof(rate_list) / sizeof(int); rate_no++) { | |
351 | + brr = (p_freq * 100) / (32 * rate_list[rate_no]); | |
352 | + errorrate = abs((p_freq * 10000) / ((brr + 1) * rate_list[rate_no] * 32) - 100); | |
353 | + if (errorrate <= ERR_MARGIN) | |
354 | + return rate_list[rate_no]; | |
355 | + } | |
356 | + return 0; | |
467 | 357 | } |
468 | 358 | |
469 | 359 | /* set target bitrate */ |
470 | -int set_bitrate(int ser_fd, int bitrate, int freq, int coremul, int peripheralmul) | |
360 | +static int set_bitrate(struct port_t *p, int bitrate, int freq, int coremul, int peripheralmul) | |
471 | 361 | { |
472 | - char buf[9] = {SET_BITRATE, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
362 | + unsigned char buf[9] = {SET_BITRATE, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
473 | 363 | |
474 | 364 | buf[2] = (bitrate >> 8) & 0xff; |
475 | 365 | buf[3] = bitrate & 0xff; |
@@ -482,37 +372,114 @@ int set_bitrate(int ser_fd, int bitrate, int freq, int coremul, int peripheralmu | ||
482 | 372 | buf[7] = coremul; |
483 | 373 | buf[8] = peripheralmul; |
484 | 374 | |
485 | - send(ser_fd, buf, sizeof(buf)); | |
486 | - if (receive(ser_fd, buf) != 1) | |
375 | + send(p, buf, sizeof(buf)); | |
376 | + if (receive(p, buf) != 1) | |
487 | 377 | return 0; |
488 | 378 | |
489 | - if (!setbaud(ser_fd, bitrate)) | |
490 | - return 0; | |
379 | + if (p->setbaud) { | |
380 | + if (!p->setbaud(bitrate)) | |
381 | + return 0; | |
491 | 382 | |
383 | + } | |
492 | 384 | usleep(10000); |
493 | 385 | buf[0] = ACK; |
494 | - write(ser_fd, buf, 1); | |
495 | - if (receive(ser_fd, buf) != 1) | |
386 | + send(p, buf, 1); | |
387 | + if (receive(p, buf) != 1) | |
496 | 388 | return 0; |
497 | 389 | else |
498 | 390 | return 1; |
499 | 391 | } |
500 | 392 | |
393 | +#define C_MULNO 0 | |
394 | +#define P_MULNO 1 | |
395 | +#define C_FREQNO 0 | |
396 | +#define P_FREQNO 1 | |
397 | + | |
398 | +/* change communicate bitrate */ | |
399 | +static int change_bitrate(struct port_t *p, int in_freq, | |
400 | + struct multilist_t *multi, struct freqlist_t *freq) | |
401 | +{ | |
402 | + int rateno; | |
403 | + int core_mul, peripheral_mul; | |
404 | + int core_freq, peripheral_freq; | |
405 | + int clock; | |
406 | + int rate; | |
407 | + | |
408 | + core_mul = 0; | |
409 | + peripheral_mul = 0; | |
410 | + /* select cpu core clock frequency */ | |
411 | + for (rateno = 0, core_freq = -1; rateno < multi->muls[C_MULNO]->numrate; rateno++) { | |
412 | + if (multi->muls[C_MULNO]->rate[rateno] > 0) | |
413 | + clock = in_freq * multi->muls[C_MULNO]->rate[rateno]; | |
414 | + else | |
415 | + clock = in_freq / -multi->muls[C_MULNO]->rate[rateno]; | |
416 | + if (!(clock >= freq->freq[C_FREQNO].min && clock <= freq->freq[C_FREQNO].max)) | |
417 | + continue; | |
418 | + if (core_freq < clock) { | |
419 | + core_mul = multi->muls[C_MULNO]->rate[rateno]; | |
420 | + core_freq = clock; | |
421 | + } | |
422 | + } | |
423 | + | |
424 | + /* select peripheral clock freqency */ | |
425 | + if (multi->nummulti > P_MULNO) { | |
426 | + for (rateno = 0, peripheral_freq = -1; | |
427 | + rateno < multi->muls[P_MULNO]->numrate; rateno++) { | |
428 | + if (multi->muls[P_MULNO]->rate[rateno] > 0) | |
429 | + clock = in_freq * multi->muls[P_MULNO]->rate[rateno]; | |
430 | + else | |
431 | + clock = in_freq / -multi->muls[P_MULNO]->rate[rateno]; | |
432 | + if (clock < freq->freq[P_FREQNO].min || | |
433 | + clock > freq->freq[P_FREQNO].max) | |
434 | + continue; | |
435 | + if (peripheral_freq < clock) { | |
436 | + peripheral_mul = multi->muls[P_MULNO]->rate[rateno]; | |
437 | + peripheral_freq = clock; | |
438 | + } | |
439 | + } | |
440 | + } else { | |
441 | + peripheral_mul = 0; | |
442 | + peripheral_freq = core_freq; | |
443 | + } | |
444 | + | |
445 | + /* select clock check */ | |
446 | + if (core_freq == -1 || peripheral_freq == -1) { | |
447 | + fprintf(stderr,"input frequency (%d.%d MHz) is out of range\n", | |
448 | + in_freq / 100, in_freq % 100); | |
449 | + return 0; | |
450 | + } | |
451 | + | |
452 | + VERBOSE_PRINT("core multiple rate=%d, freq=%d.%d MHz\n", | |
453 | + core_mul, core_freq / 100, core_freq % 100); | |
454 | + VERBOSE_PRINT("peripheral multiple rate=%d, freq=%d.%d MHz\n", | |
455 | + peripheral_mul, peripheral_freq / 100, peripheral_freq % 100); | |
456 | + | |
457 | + /* select bitrate from peripheral cock*/ | |
458 | + rate = adjust_bitrate(peripheral_freq); | |
459 | + if (rate == 0) | |
460 | + return 0; | |
461 | + | |
462 | + VERBOSE_PRINT("bitrate %d bps\n",rate * 100); | |
463 | + | |
464 | + /* setup host/target bitrate */ | |
465 | + return set_bitrate(p, rate, in_freq, core_mul, peripheral_mul); | |
466 | +} | |
467 | + | |
501 | 468 | /* check blank page */ |
502 | -static int skipcheck(unsigned char *data) | |
469 | +static int skipcheck(unsigned char *data, unsigned short size) | |
503 | 470 | { |
504 | 471 | unsigned char r = 0xff; |
505 | 472 | int c; |
506 | - for (c = 0; c < 128; c++) | |
473 | + for (c = 0; c < size; c++) | |
507 | 474 | r &= *data++; |
508 | 475 | return (r == 0xff); |
509 | 476 | } |
510 | 477 | |
511 | 478 | /* write rom image */ |
512 | -int write_rom(int ser_fd, const unsigned char *romimage, struct writeinfo_t *writeinfo) | |
479 | +int write_rom(struct port_t *port, const unsigned char *romimage, struct writeinfo_t *writeinfo) | |
513 | 480 | { |
514 | 481 | unsigned char *buf = NULL; |
515 | - unsigned long romaddr; | |
482 | + unsigned int romaddr; | |
516 | 483 | |
517 | 484 | buf = (unsigned char *)malloc(5 + writeinfo->size); |
518 | 485 | if (buf == NULL) { |
@@ -522,25 +489,27 @@ int write_rom(int ser_fd, const unsigned char *romimage, struct writeinfo_t *wri | ||
522 | 489 | |
523 | 490 | puts("erase flash..."); |
524 | 491 | /* enter writemode */ |
525 | - *(buf + 0) = WRITEMODE; | |
526 | - write(ser_fd, buf, 1); | |
527 | - if (receive(ser_fd, buf) != 1) { | |
528 | - fputs(PROGNAME ": writemode start failed", stderr); | |
492 | + buf[0] = WRITEMODE; | |
493 | + send(port, buf, 1); | |
494 | + if (receive(port, buf) != 1) { | |
495 | + printf("%02x ", buf[0]); | |
496 | + fputs(PROGNAME ": writemode start failed\n", stderr); | |
529 | 497 | goto error; |
530 | 498 | } |
531 | 499 | |
532 | 500 | /* mat select */ |
533 | 501 | switch (writeinfo->mat) { |
534 | 502 | case user: |
535 | - *(buf + 0) = WRITE_USER; | |
503 | + buf[0] = WRITE_USER; | |
536 | 504 | break; |
537 | 505 | case userboot: |
538 | - *(buf + 0) = WRITE_USERBOOT; | |
506 | + buf[0] = WRITE_USERBOOT; | |
539 | 507 | break; |
540 | 508 | } |
541 | - write(ser_fd, buf, 1); | |
542 | - if (receive(ser_fd, buf) != 1) { | |
543 | - fputs(PROGNAME ": writemode start failed", stderr); | |
509 | + send(port, buf, 1); | |
510 | + if (receive(port, buf) != 1) { | |
511 | + printf("%02x ", buf[0]); | |
512 | + fputs(PROGNAME ": writemode start failed\n", stderr); | |
544 | 513 | goto error; |
545 | 514 | } |
546 | 515 |
@@ -548,44 +517,44 @@ int write_rom(int ser_fd, const unsigned char *romimage, struct writeinfo_t *wri | ||
548 | 517 | for (romaddr = writeinfo->area.start; |
549 | 518 | romaddr < writeinfo->area.end; |
550 | 519 | romaddr += writeinfo->size) { |
551 | - if (skipcheck((unsigned char *)(romimage + romaddr))) | |
520 | + if (skipcheck((unsigned char *)(romimage + romaddr - writeinfo->area.start), writeinfo->size)) | |
552 | 521 | continue; |
553 | 522 | /* set write data */ |
554 | - *(buf + 0) = WRITE128; | |
523 | + *(buf + 0) = WRITE; | |
555 | 524 | setlong(buf + 1, romaddr); |
556 | 525 | if ((romaddr + writeinfo->size) < writeinfo->area.end) { |
557 | - memcpy(buf + 5, romimage + romaddr, writeinfo->size); | |
526 | + memcpy(buf + 5, romimage + romaddr - writeinfo->area.start, writeinfo->size); | |
558 | 527 | } else { |
559 | - /* lastpage < 128byte*/ | |
560 | - memcpy(buf + 5, romimage + romaddr, | |
528 | + /* lastpage < writesize */ | |
529 | + memcpy(buf + 5, romimage + romaddr - writeinfo->area.start, | |
561 | 530 | (writeinfo->area.end - romaddr)); |
562 | 531 | memset(buf + 5 + writeinfo->area.end - romaddr, 0xff, |
563 | 532 | writeinfo->size - (writeinfo->area.end - romaddr)); |
564 | 533 | } |
565 | 534 | /* write */ |
566 | - send(ser_fd, buf, 5 + writeinfo->size); | |
567 | - if (receive(ser_fd, buf) != 1) { | |
568 | - fprintf(stderr, PROGNAME ": write data %08lx failed.", romaddr); | |
535 | + send(port, buf, 5 + writeinfo->size); | |
536 | + if (receive(port, buf) != 1) { | |
537 | + fprintf(stderr, PROGNAME ": write data %08x failed.", romaddr); | |
569 | 538 | goto error; |
570 | 539 | } |
571 | 540 | if (verbose) |
572 | - printf("write - %08lx\n",romaddr); | |
541 | + printf("write - %08x\n",romaddr); | |
573 | 542 | else { |
574 | - printf("writing %ld/%ld byte\r", romaddr, writeinfo->area.end); | |
543 | + printf("writing %d/%d byte\r", romaddr, writeinfo->area.end); | |
575 | 544 | fflush(stdout); |
576 | 545 | } |
577 | 546 | } |
578 | 547 | /* write finish */ |
579 | - *(buf + 0) = WRITE128; | |
548 | + *(buf + 0) = WRITE; | |
580 | 549 | memset(buf + 1, 0xff, 4); |
581 | - send(ser_fd, buf, 5); | |
582 | - if (receive(ser_fd, buf) != 1) { | |
550 | + send(port, buf, 5); | |
551 | + if (receive(port, buf) != 1) { | |
583 | 552 | fputs(PROGNAME ": writemode exit failed", stderr); |
584 | 553 | goto error; |
585 | 554 | } |
586 | 555 | free(buf); |
587 | 556 | if (!verbose) |
588 | - printf("writing %ld/%ld byte\n", writeinfo->area.end, writeinfo->area.end); | |
557 | + printf("writing %d/%d byte\n", writeinfo->area.end, writeinfo->area.end); | |
589 | 558 | |
590 | 559 | |
591 | 560 | return 1; |
@@ -593,3 +562,235 @@ int write_rom(int ser_fd, const unsigned char *romimage, struct writeinfo_t *wri | ||
593 | 562 | free(buf); |
594 | 563 | return 0; |
595 | 564 | } |
565 | + | |
566 | +/* connect to target chip */ | |
567 | +int setup_connection(struct port_t *p, int input_freq) | |
568 | +{ | |
569 | + int c; | |
570 | + int r = -1; | |
571 | + struct devicelist_t *devicelist = NULL; | |
572 | + struct clockmode_t *clockmode = NULL; | |
573 | + struct multilist_t *multilist = NULL; | |
574 | + struct freqlist_t *freqlist = NULL; | |
575 | + | |
576 | + /* connect target */ | |
577 | + if (!p->connect_target()) { | |
578 | + if (errno != 0) | |
579 | + perror(PROGNAME); | |
580 | + else | |
581 | + fputs("target no response\n", stderr); | |
582 | + goto error; | |
583 | + } | |
584 | + | |
585 | + /* query target infomation */ | |
586 | + devicelist = get_devicelist(p); | |
587 | + if (devicelist == NULL) { | |
588 | + if (errno != 0) | |
589 | + perror(PROGNAME); | |
590 | + else | |
591 | + fputs("devicelist error\n", stderr); | |
592 | + goto error; | |
593 | + } | |
594 | + if (verbose) { | |
595 | + char codes[5]; | |
596 | + printf("Support devices: %d\n", devicelist->numdevs); | |
597 | + for (c = 0; c < devicelist->numdevs; c++) { | |
598 | + memcpy(codes, devicelist->devs[c].code, 4); | |
599 | + codes[4] = '\0'; | |
600 | + printf("%d: %s - %s\n", c+1, codes, devicelist->devs[c].name); | |
601 | + } | |
602 | + } | |
603 | + | |
604 | + /* query target clockmode */ | |
605 | + clockmode = get_clockmode(p); | |
606 | + if (clockmode == NULL) { | |
607 | + if (errno != 0) | |
608 | + perror(PROGNAME); | |
609 | + else | |
610 | + fputs("clockmode error\n",stderr); | |
611 | + goto error; | |
612 | + } | |
613 | + if (verbose) { | |
614 | + if (clockmode->nummode > 0) { | |
615 | + printf("Support clock modes %d:", clockmode->nummode); | |
616 | + for (c = 0; c < clockmode->nummode; c++) { | |
617 | + printf(" %02x", clockmode->mode[c]); | |
618 | + } | |
619 | + printf("\n"); | |
620 | + } else | |
621 | + printf("no clockmode support\n"); | |
622 | + } | |
623 | + | |
624 | + /* SELDEV devicetype select */ | |
625 | + if (devicelist->numdevs < SELDEV) { | |
626 | + fprintf(stderr, "Select Device (%d) not supported.\n", SELDEV); | |
627 | + goto error; | |
628 | + } | |
629 | + if (!select_device(p, devicelist->devs[SELDEV].code)) { | |
630 | + fputs("device select error", stderr); | |
631 | + goto error; | |
632 | + } | |
633 | + | |
634 | + /* SELCLK clockmode select */ | |
635 | + if (clockmode->nummode > 0) { | |
636 | + if (clockmode->nummode < SELCLK) { | |
637 | + fprintf(stderr, "Select clock (%d) not supported.\n", SELCLK); | |
638 | + goto error; | |
639 | + } | |
640 | + if (!set_clockmode(p, clockmode->mode[SELCLK])) { | |
641 | + fputs("clock select error", stderr); | |
642 | + goto error; | |
643 | + } | |
644 | + } else { | |
645 | + if (!set_clockmode(p, 0)) { | |
646 | + fputs("clock select error", stderr); | |
647 | + goto error; | |
648 | + } | |
649 | + } | |
650 | + | |
651 | + /* query multiplier/devider rate */ | |
652 | + multilist = get_multirate(p); | |
653 | + if (multilist == NULL) { | |
654 | + if (errno != 0) | |
655 | + perror(PROGNAME); | |
656 | + else | |
657 | + fputs("multilist error\n",stderr); | |
658 | + goto error; | |
659 | + } | |
660 | + if (verbose) { | |
661 | + int c1,c2; | |
662 | + printf("Support multiple rate: %d\n", multilist->nummulti); | |
663 | + for (c1 = 0; c1 < multilist->nummulti; c1++) { | |
664 | + printf("%d:", c1 + 1); | |
665 | + for (c2 = 0; c2 < multilist->muls[c1]->numrate; c2++) | |
666 | + printf(" %d", multilist->muls[c1]->rate[c2]); | |
667 | + printf("\n"); | |
668 | + } | |
669 | + } | |
670 | + | |
671 | + /* query operation frequency range */ | |
672 | + freqlist = get_freqlist(p); | |
673 | + if (freqlist == NULL) { | |
674 | + if (errno != 0) | |
675 | + perror(PROGNAME); | |
676 | + else | |
677 | + fputs("freqlist error\n",stderr); | |
678 | + goto error; | |
679 | + } | |
680 | + if (verbose) { | |
681 | + printf("operation frequencies: %d\n", freqlist->numfreq); | |
682 | + for (c = 0; c < freqlist->numfreq; c++) { | |
683 | + printf("%d: %d.%d - %d.%d\n", c + 1, | |
684 | + freqlist->freq[c].min / 100,freqlist->freq[c].min % 100, | |
685 | + freqlist->freq[c].max / 100,freqlist->freq[c].max % 100); | |
686 | + } | |
687 | + } | |
688 | + | |
689 | + /* set writeing bitrate */ | |
690 | + if (!change_bitrate(p, input_freq, multilist, freqlist)) { | |
691 | + fputs("set bitrate failed\n",stderr); | |
692 | + goto error; | |
693 | + } | |
694 | + | |
695 | + r = 0; | |
696 | + error: | |
697 | + free(devicelist); | |
698 | + free(clockmode); | |
699 | + free(multilist); | |
700 | + free(freqlist); | |
701 | + return r; | |
702 | +} | |
703 | + | |
704 | +/* connect to target chip */ | |
705 | +void dump_configs(struct port_t *p) | |
706 | +{ | |
707 | + struct devicelist_t *devicelist = NULL; | |
708 | + struct clockmode_t *clockmode = NULL; | |
709 | + struct multilist_t *multilist = NULL; | |
710 | + struct freqlist_t *freqlist = NULL; | |
711 | + int dev; | |
712 | + int clk; | |
713 | + int c1,c2; | |
714 | + | |
715 | + /* connect target */ | |
716 | + if (!p->connect_target()) { | |
717 | + if (errno != 0) | |
718 | + perror(PROGNAME); | |
719 | + else | |
720 | + fputs("target no response\n", stderr); | |
721 | + goto error; | |
722 | + } | |
723 | + | |
724 | + /* query target infomation */ | |
725 | + devicelist = get_devicelist(p); | |
726 | + if (devicelist == NULL) { | |
727 | + if (errno != 0) | |
728 | + perror(PROGNAME); | |
729 | + else | |
730 | + fputs("devicelist error\n", stderr); | |
731 | + goto error; | |
732 | + } | |
733 | + /* query target clockmode */ | |
734 | + clockmode = get_clockmode(p); | |
735 | + if (clockmode == NULL) { | |
736 | + if (errno != 0) | |
737 | + perror(PROGNAME); | |
738 | + else | |
739 | + fputs("clockmode error\n",stderr); | |
740 | + goto error; | |
741 | + } | |
742 | + for(dev = 0; dev < devicelist->numdevs; dev++) { | |
743 | + if (!select_device(p, devicelist->devs[dev].code)) { | |
744 | + fputs("device select error", stderr); | |
745 | + goto error; | |
746 | + } | |
747 | + for (clk = 0; clk < clockmode->nummode; clk++) { | |
748 | + if (!set_clockmode(p, clockmode->mode[clk])) { | |
749 | + fputs("clock select error", stderr); | |
750 | + goto error; | |
751 | + } | |
752 | + | |
753 | + printf("dev: %s - clock: %d\n", devicelist->devs[dev].name, clk); | |
754 | + multilist = get_multirate(p); | |
755 | + if (multilist == NULL) { | |
756 | + if (errno != 0) | |
757 | + perror(PROGNAME); | |
758 | + else | |
759 | + fputs("multilist error\n",stderr); | |
760 | + goto error; | |
761 | + } | |
762 | + printf("multiple / divide rate\n"); | |
763 | + for (c1 = 0; c1 < multilist->nummulti; c1++) { | |
764 | + for (c2 = 0; c2 < multilist->muls[c1]->numrate; c2++) | |
765 | + printf(" %d", (int)multilist->muls[c1]->rate[c2]); | |
766 | + printf("\n"); | |
767 | + } | |
768 | + | |
769 | + /* query operation frequency range */ | |
770 | + freqlist = get_freqlist(p); | |
771 | + if (freqlist == NULL) { | |
772 | + if (errno != 0) | |
773 | + perror(PROGNAME); | |
774 | + else | |
775 | + fputs("freqlist error\n",stderr); | |
776 | + goto error; | |
777 | + } | |
778 | + printf("operation frequency (MHz)\n"); | |
779 | + for (c1 = 0; c1 < freqlist->numfreq; c1++) { | |
780 | + printf("%d.%d - %d.%d\n", | |
781 | + freqlist->freq[c1].min / 100,freqlist->freq[c1].min % 100, | |
782 | + freqlist->freq[c1].max / 100,freqlist->freq[c1].max % 100); | |
783 | + } | |
784 | + free(multilist); | |
785 | + free(freqlist); | |
786 | + multilist = NULL; | |
787 | + freqlist = NULL; | |
788 | + } | |
789 | + } | |
790 | +error: | |
791 | + free(multilist); | |
792 | + free(freqlist); | |
793 | + free(devicelist); | |
794 | + free(clockmode); | |
795 | +} | |
796 | + |
@@ -13,6 +13,9 @@ | ||
13 | 13 | /* default using serialport */ |
14 | 14 | #define DEFAULT_SERIAL "/dev/ttyS0" |
15 | 15 | |
16 | +#define DEFAULT_VID 0x045b | |
17 | +#define DEFAULT_PID 0x0025 | |
18 | + | |
16 | 19 | /* use devicetype */ |
17 | 20 | #define SELDEV 0 |
18 | 21 | /* use clockmode */ |
@@ -26,6 +29,36 @@ | ||
26 | 29 | |
27 | 30 | |
28 | 31 | #define PROGNAME "h8flash" |
32 | +#define VERBOSE_PRINT(...) do { if (verbose) printf(__VA_ARGS__); } while(0) | |
33 | + | |
34 | +#define ACK 0x06 | |
35 | + | |
36 | +#define QUERY_DEVICE 0x20 | |
37 | +#define QUERY_DEVICE_RES 0x30 | |
38 | +#define QUERY_CLOCKMODE 0x21 | |
39 | +#define QUERY_CLOCKMODE_RES 0x31 | |
40 | +#define QUERY_MULTIRATE 0x22 | |
41 | +#define QUERY_MULTIRATE_RES 0x32 | |
42 | +#define QUERY_FREQ 0x23 | |
43 | +#define QUERY_FREQ_RES 0x33 | |
44 | +#define QUERY_BOOT_AREA 0x24 | |
45 | +#define QUERY_BOOT_AREA_RES 0x34 | |
46 | +#define QUERY_USER_AREA 0x25 | |
47 | +#define QUERY_USER_AREA_RES 0x35 | |
48 | +#define QUERY_WRITESIZE 0x27 | |
49 | +#define QUERY_WRITESIZE_RES 0x37 | |
50 | + | |
51 | +#define SELECT_DEVICE 0x10 | |
52 | +#define SET_CLOCKMODE 0x11 | |
53 | + | |
54 | +#define SET_BITRATE 0x3f | |
55 | + | |
56 | +#define WRITEMODE 0x40 | |
57 | +#define WRITE_USERBOOT 0x42 | |
58 | +#define WRITE_USER 0x43 | |
59 | +#define BLANKCHECK_USERBOOT 0x4c | |
60 | +#define BLANKCHECK_USER 0x4d | |
61 | +#define WRITE 0x50 | |
29 | 62 | |
30 | 63 | enum mat_t {user, userboot}; |
31 | 64 |
@@ -36,7 +69,7 @@ struct devinfo_t { | ||
36 | 69 | |
37 | 70 | struct devicelist_t { |
38 | 71 | int numdevs; |
39 | - struct devinfo_t devs[1]; | |
72 | + struct devinfo_t devs[0]; | |
40 | 73 | }; |
41 | 74 | |
42 | 75 | struct clockmode_t { |
@@ -51,7 +84,7 @@ struct multirate_t { | ||
51 | 84 | |
52 | 85 | struct multilist_t { |
53 | 86 | int nummulti; |
54 | - struct multirate_t muls[0]; | |
87 | + struct multirate_t *muls[0]; | |
55 | 88 | }; |
56 | 89 | |
57 | 90 | struct freq_t { |
@@ -65,8 +98,8 @@ struct freqlist_t { | ||
65 | 98 | }; |
66 | 99 | |
67 | 100 | struct area_t { |
68 | - unsigned long start; | |
69 | - unsigned long end; | |
101 | + unsigned int start; | |
102 | + unsigned int end; | |
70 | 103 | }; |
71 | 104 | |
72 | 105 | struct arealist_t { |
@@ -80,17 +113,30 @@ struct writeinfo_t { | ||
80 | 113 | int size; |
81 | 114 | }; |
82 | 115 | |
83 | -int open_serial(const char *port); | |
84 | -int connect_target(int ser_fd); | |
85 | -struct devicelist_t *get_devicelist(int ser_fd); | |
86 | -struct clockmode_t *get_clockmode(int ser_fd); | |
87 | -struct multilist_t *get_multirate(int ser_fd); | |
88 | -struct freqlist_t *get_freqlist(int ser_fd); | |
89 | -struct arealist_t *get_arealist(enum mat_t mat, int ser_fd); | |
90 | -int get_writesize(int ser_fd); | |
91 | -int select_device(int ser_fd, const char *code); | |
92 | -int set_clockmode(int ser_fd, int mode); | |
93 | -int set_bitrate(int ser_fd, int bitrate, int freq, int coremul, int peripheralmul); | |
94 | -int write_rom(int ser_fd, const unsigned char *romimage, struct writeinfo_t *writeinfo); | |
116 | +enum port_type {serial, usb}; | |
117 | + | |
118 | +struct port_t { | |
119 | + enum port_type type; | |
120 | + int (*connect_target)(void); | |
121 | + int (*send_data)(const unsigned char *data, int len); | |
122 | + int (*receive_byte)(unsigned char *data); | |
123 | + int (*setbaud)(int bitrate); | |
124 | + void (*close)(void); | |
125 | +}; | |
126 | + | |
127 | +struct port_t *open_serial(char *portname); | |
128 | +struct port_t *open_usb(unsigned short vid, unsigned short pid); | |
129 | +struct devicelist_t *get_devicelist(struct port_t *port); | |
130 | +struct clockmode_t *get_clockmode(struct port_t *port); | |
131 | +struct multilist_t *get_multirate(struct port_t *port); | |
132 | +struct freqlist_t *get_freqlist(struct port_t *port); | |
133 | +struct arealist_t *get_arealist(struct port_t *port, enum mat_t mat); | |
134 | +int get_writesize(struct port_t *port); | |
135 | +int select_device(struct port_t *port, const char *code); | |
136 | +int set_clockmode(struct port_t *port, int mode); | |
137 | +int write_rom(struct port_t *port, const unsigned char *romimage, | |
138 | + struct writeinfo_t *writeinfo); | |
139 | +int setup_connection(struct port_t *port, int input_freq); | |
140 | +void dump_configs(struct port_t *p); | |
95 | 141 | |
96 | 142 | extern int verbose; |
@@ -11,23 +11,16 @@ | ||
11 | 11 | #include <stdio.h> |
12 | 12 | #include <getopt.h> |
13 | 13 | #include <stddef.h> |
14 | -#include <sys/stat.h> | |
15 | -#include <sys/types.h> | |
16 | -#include <sys/mman.h> | |
17 | -#include <unistd.h> | |
18 | -#include <fcntl.h> | |
19 | -#include <errno.h> | |
20 | 14 | #include <stdlib.h> |
21 | 15 | #include <ctype.h> |
22 | 16 | #include <string.h> |
23 | -#include <signal.h> | |
24 | -#include <libgen.h> | |
17 | +#include <errno.h> | |
18 | +#include <sys/mman.h> | |
19 | +#include <sys/stat.h> | |
25 | 20 | #include "h8flash.h" |
26 | 21 | |
27 | 22 | #define SREC_MAXLEN (256*2 + 4 + 1) |
28 | 23 | |
29 | -#define VERBOSE_PRINT(...) do { if (verbose) printf(__VA_ARGS__); } while(0) | |
30 | - | |
31 | 24 | int verbose = 0; |
32 | 25 | |
33 | 26 | const static struct option long_options[] = { |
@@ -36,16 +29,17 @@ const static struct option long_options[] = { | ||
36 | 29 | {"freq", required_argument, NULL, 'f'}, |
37 | 30 | {"binary", no_argument, NULL, 'b'}, |
38 | 31 | {"verbose", no_argument, NULL, 'V'}, |
32 | + {"list", no_argument, NULL, 'l'}, | |
39 | 33 | {0, 0, 0, 0} |
40 | 34 | }; |
41 | 35 | |
42 | 36 | static void usage(void) |
43 | 37 | { |
44 | - puts(PROGNAME " [-p serial port][-f input clock frequency][-b][--userboot] filename"); | |
38 | + puts(PROGNAME " [-p serial port][-f input clock frequency][-b][--userboot][-l] filename"); | |
45 | 39 | } |
46 | 40 | |
47 | 41 | /* read raw binary */ |
48 | -static int write_binary(FILE *fp, struct writeinfo_t *writeinfo, int ser_fd) | |
42 | +static int write_binary(FILE *fp, struct writeinfo_t *writeinfo, struct port_t *p) | |
49 | 43 | { |
50 | 44 | int fno; |
51 | 45 | struct stat bin_st; |
@@ -57,10 +51,10 @@ static int write_binary(FILE *fp, struct writeinfo_t *writeinfo, int ser_fd) | ||
57 | 51 | fstat(fno, &bin_st); |
58 | 52 | bin_len = bin_st.st_size; |
59 | 53 | |
60 | - if ((bin_buf = (char *)mmap(NULL, bin_len, PROT_READ, MAP_SHARED, fno, 0)) == MAP_FAILED) | |
54 | + if ((bin_buf = (unsigned char *)mmap(NULL, bin_len, PROT_READ, MAP_SHARED, fno, 0)) == MAP_FAILED) | |
61 | 55 | goto error_perror; |
62 | 56 | writeinfo->area.end = bin_len - 1; |
63 | - if (!write_rom(ser_fd, bin_buf, writeinfo)) | |
57 | + if (!write_rom(p, bin_buf, writeinfo)) | |
64 | 58 | goto error; |
65 | 59 | munmap(bin_buf, bin_len); |
66 | 60 | fclose(fp); |
@@ -75,11 +69,11 @@ static int write_binary(FILE *fp, struct writeinfo_t *writeinfo, int ser_fd) | ||
75 | 69 | } |
76 | 70 | |
77 | 71 | /* read srec binary */ |
78 | -static int write_srec(FILE *fp, struct writeinfo_t *writeinfo, int ser_fd) | |
72 | +static int write_srec(FILE *fp, struct writeinfo_t *writeinfo, struct port_t *p) | |
79 | 73 | { |
80 | 74 | unsigned char *romimage = NULL; |
81 | 75 | unsigned char *bufp; |
82 | - unsigned long last_addr = 0; | |
76 | + unsigned int last_addr = 0; | |
83 | 77 | int buff_size; |
84 | 78 | static char linebuf[SREC_MAXLEN + 1]; |
85 | 79 | char *lp; |
@@ -91,7 +85,7 @@ static int write_srec(FILE *fp, struct writeinfo_t *writeinfo, int ser_fd) | ||
91 | 85 | int r = 0; |
92 | 86 | int l; |
93 | 87 | |
94 | - romimage = (char *)malloc(writeinfo->area.end - writeinfo->area.start + 1); | |
88 | + romimage = (unsigned char *)malloc(writeinfo->area.end - writeinfo->area.start + 1); | |
95 | 89 | if (!romimage) { |
96 | 90 | perror(PROGNAME); |
97 | 91 | goto error; |
@@ -131,7 +125,7 @@ static int write_srec(FILE *fp, struct writeinfo_t *writeinfo, int ser_fd) | ||
131 | 125 | fprintf(stderr, "srec address %08x is out of romarea\n", addr); |
132 | 126 | goto error; |
133 | 127 | } |
134 | - bufp = romimage + addr; | |
128 | + bufp = romimage + addr - writeinfo->area.start; | |
135 | 129 | if (last_addr < (addr + len - 1)) |
136 | 130 | last_addr = (addr + len - 1); |
137 | 131 |
@@ -156,7 +150,7 @@ static int write_srec(FILE *fp, struct writeinfo_t *writeinfo, int ser_fd) | ||
156 | 150 | } |
157 | 151 | } |
158 | 152 | writeinfo->area.end = last_addr; |
159 | - r = write_rom(ser_fd, romimage, writeinfo); | |
153 | + r = write_rom(p, romimage, writeinfo); | |
160 | 154 | error: |
161 | 155 | free(romimage); |
162 | 156 | fclose(fp); |
@@ -164,7 +158,8 @@ static int write_srec(FILE *fp, struct writeinfo_t *writeinfo, int ser_fd) | ||
164 | 158 | } |
165 | 159 | |
166 | 160 | /* read rom writing data */ |
167 | -static int writefile_to_rom(char *fn, int force_binary, struct writeinfo_t *writeinfo, int ser_fd) | |
161 | +static int writefile_to_rom(char *fn, int force_binary, struct writeinfo_t *writeinfo, | |
162 | + struct port_t *port) | |
168 | 163 | { |
169 | 164 | FILE *fp = NULL; |
170 | 165 | static char linebuf[SREC_MAXLEN + 1]; |
@@ -192,7 +187,7 @@ static int writefile_to_rom(char *fn, int force_binary, struct writeinfo_t *writ | ||
192 | 187 | if (force_binary || |
193 | 188 | linebuf[0] != 'S' || |
194 | 189 | isdigit(linebuf[1]) == 0) |
195 | - return write_binary(fp, writeinfo, ser_fd); | |
190 | + return write_binary(fp, writeinfo, port); | |
196 | 191 | |
197 | 192 | /* check body (calcurate checksum) */ |
198 | 193 | memcpy(hexbuf, &linebuf[2], 2); |
@@ -203,262 +198,19 @@ static int writefile_to_rom(char *fn, int force_binary, struct writeinfo_t *writ | ||
203 | 198 | } |
204 | 199 | if ((sum & 0xff) == 0xff) |
205 | 200 | /* checksum ok is Srecord format */ |
206 | - return write_srec(fp, writeinfo, ser_fd); | |
201 | + return write_srec(fp, writeinfo, port); | |
207 | 202 | else |
208 | - return write_binary(fp, writeinfo, ser_fd); | |
209 | -} | |
210 | - | |
211 | -/* bitrate candidate list */ | |
212 | -static const int rate_list[]={1152,576,384,192,96}; | |
213 | - | |
214 | -/* bitrate error margine (%) */ | |
215 | -#define ERR_MARGIN 4 | |
216 | - | |
217 | -/* select communication bitrate */ | |
218 | -static int adjust_bitrate(int p_freq) | |
219 | -{ | |
220 | - int brr; | |
221 | - int errorrate; | |
222 | - int rate_no; | |
223 | - | |
224 | - for (rate_no = 0; rate_no < sizeof(rate_list) / sizeof(int); rate_no++) { | |
225 | - brr = (p_freq * 100) / (32 * rate_list[rate_no]); | |
226 | - errorrate = abs((p_freq * 10000) / ((brr + 1) * rate_list[rate_no] * 32) - 100); | |
227 | - if (errorrate <= ERR_MARGIN) | |
228 | - return rate_list[rate_no]; | |
229 | - } | |
230 | - return 0; | |
231 | -} | |
232 | - | |
233 | -#define C_MULNO 0 | |
234 | -#define P_MULNO 1 | |
235 | -#define C_FREQNO 0 | |
236 | -#define P_FREQNO 1 | |
237 | - | |
238 | -/* change communicate bitrate */ | |
239 | -static int change_bitrate(int ser_fd, int in_freq, | |
240 | - struct multilist_t *multi, struct freqlist_t *freq) | |
241 | -{ | |
242 | - int rateno; | |
243 | - int core_mul, peripheral_mul; | |
244 | - int core_freq, peripheral_freq; | |
245 | - int clock; | |
246 | - int rate; | |
247 | - | |
248 | - core_mul = 0; | |
249 | - peripheral_mul = 0; | |
250 | - /* select cpu core clock frequency */ | |
251 | - for (rateno = 0, core_freq = -1; rateno < multi->muls[C_MULNO].numrate; rateno++) { | |
252 | - if (multi->muls[C_MULNO].rate[rateno] > 0) | |
253 | - clock = in_freq * multi->muls[C_MULNO].rate[rateno]; | |
254 | - else | |
255 | - clock = in_freq / -multi->muls[C_MULNO].rate[rateno]; | |
256 | - if (!(clock >= freq->freq[C_FREQNO].min && clock <= freq->freq[C_FREQNO].max)) | |
257 | - continue; | |
258 | - if (core_freq < clock) { | |
259 | - core_mul = multi->muls[C_MULNO].rate[rateno]; | |
260 | - core_freq = clock; | |
261 | - } | |
262 | - } | |
263 | - | |
264 | - /* select peripheral clock freqency */ | |
265 | - if (multi->nummulti > P_MULNO) { | |
266 | - for (rateno = 0, peripheral_freq = -1; | |
267 | - rateno < multi->muls[P_MULNO].numrate; rateno++) { | |
268 | - if (multi->muls[P_MULNO].rate[rateno] > 0) | |
269 | - clock = in_freq * multi->muls[P_MULNO].rate[rateno]; | |
270 | - else | |
271 | - clock = in_freq / -multi->muls[P_MULNO].rate[rateno]; | |
272 | - if (clock < freq->freq[P_FREQNO].min || | |
273 | - clock > freq->freq[P_FREQNO].max) | |
274 | - continue; | |
275 | - if (peripheral_freq < clock) { | |
276 | - peripheral_mul = multi->muls[P_MULNO].rate[rateno]; | |
277 | - peripheral_freq = clock; | |
278 | - } | |
279 | - } | |
280 | - } else { | |
281 | - peripheral_mul = 0; | |
282 | - peripheral_freq = core_freq; | |
283 | - } | |
284 | - | |
285 | - /* select clock check */ | |
286 | - if (core_freq == -1 || peripheral_freq == -1) { | |
287 | - fprintf(stderr,"input frequency (%d.%d MHz) is out of range\n", | |
288 | - in_freq / 100, in_freq % 100); | |
289 | - return 0; | |
290 | - } | |
291 | - | |
292 | - VERBOSE_PRINT("core multiple rate=%d, freq=%d.%d MHz\n", | |
293 | - core_mul, core_freq / 100, core_freq % 100); | |
294 | - VERBOSE_PRINT("peripheral multiple rate=%d, freq=%d.%d MHz\n", | |
295 | - peripheral_mul, peripheral_freq / 100, peripheral_freq % 100); | |
296 | - | |
297 | - /* select bitrate from peripheral cock*/ | |
298 | - rate = adjust_bitrate(peripheral_freq); | |
299 | - if (rate == 0) | |
300 | - return 0; | |
301 | - | |
302 | - VERBOSE_PRINT("bitrate %d bps\n",rate * 100); | |
303 | - | |
304 | - /* setup host/target bitrate */ | |
305 | - return set_bitrate(ser_fd, rate, in_freq, core_mul, peripheral_mul); | |
306 | -} | |
307 | - | |
308 | -/* connect to target chip */ | |
309 | -static int setup_connection(const char *ser_port, int input_freq) | |
310 | -{ | |
311 | - int ser_fd; | |
312 | - int c; | |
313 | - int r = -1; | |
314 | - struct devicelist_t *devicelist = NULL; | |
315 | - struct clockmode_t *clockmode = NULL; | |
316 | - struct multilist_t *multilist = NULL; | |
317 | - struct freqlist_t *freqlist = NULL; | |
318 | - | |
319 | - /* serial port open */ | |
320 | - ser_fd = open_serial(ser_port); | |
321 | - if (ser_fd == -1) | |
322 | - return -1; | |
323 | - | |
324 | - /* connect target */ | |
325 | - if (!connect_target(ser_fd)) { | |
326 | - if (errno != 0) | |
327 | - perror(PROGNAME); | |
328 | - else | |
329 | - fputs("target no response\n", stderr); | |
330 | - goto error; | |
331 | - } | |
332 | - | |
333 | - /* query target infomation */ | |
334 | - devicelist = get_devicelist(ser_fd); | |
335 | - if (devicelist == NULL) { | |
336 | - if (errno != 0) | |
337 | - perror(PROGNAME); | |
338 | - else | |
339 | - fputs("devicelist error\n", stderr); | |
340 | - goto error; | |
341 | - } | |
342 | - if (verbose) { | |
343 | - char codes[5]; | |
344 | - printf("supports devices: %d\n", devicelist->numdevs); | |
345 | - for (c = 0; c < devicelist->numdevs; c++) { | |
346 | - memcpy(codes, devicelist->devs[c].code, 4); | |
347 | - codes[4] = '\0'; | |
348 | - printf("%d: %s - %s\n", c+1, codes, devicelist->devs[c].name); | |
349 | - } | |
350 | - } | |
351 | - | |
352 | - /* query target clockmode */ | |
353 | - clockmode = get_clockmode(ser_fd); | |
354 | - if (clockmode == NULL) { | |
355 | - if (errno != 0) | |
356 | - perror(PROGNAME); | |
357 | - else | |
358 | - fputs("clockmode error\n",stderr); | |
359 | - goto error; | |
360 | - } | |
361 | - if (verbose) { | |
362 | - if (clockmode->nummode > 0) { | |
363 | - printf("supports clockmode %d:", clockmode->nummode); | |
364 | - for (c = 0; c < clockmode->nummode; c++) { | |
365 | - printf(" %02x", clockmode->mode[c]); | |
366 | - } | |
367 | - printf("\n"); | |
368 | - } else | |
369 | - printf("no clockmode support\n"); | |
370 | - } | |
371 | - | |
372 | - /* SELDEV devicetype select */ | |
373 | - if (devicelist->numdevs < SELDEV) { | |
374 | - fprintf(stderr, "Select Device (%d) not supported.\n", SELDEV); | |
375 | - goto error; | |
376 | - } | |
377 | - if (!select_device(ser_fd, devicelist->devs[SELDEV].code)) { | |
378 | - fputs("device select error", stderr); | |
379 | - goto error; | |
380 | - } | |
381 | - | |
382 | - /* SELCLK clockmode select */ | |
383 | - if (clockmode->nummode > 0) { | |
384 | - if (clockmode->nummode < SELCLK) { | |
385 | - fprintf(stderr, "Select clock (%d) not supported.\n", SELCLK); | |
386 | - goto error; | |
387 | - } | |
388 | - if (!set_clockmode(ser_fd, clockmode->mode[SELCLK])) { | |
389 | - fputs("clock select error", stderr); | |
390 | - goto error; | |
391 | - } | |
392 | - } else { | |
393 | - if (!set_clockmode(ser_fd, 0)) { | |
394 | - fputs("clock select error", stderr); | |
395 | - goto error; | |
396 | - } | |
397 | - } | |
398 | - | |
399 | - /* query multiplier/devider rate */ | |
400 | - multilist = get_multirate(ser_fd); | |
401 | - if (multilist == NULL) { | |
402 | - if (errno != 0) | |
403 | - perror(PROGNAME); | |
404 | - else | |
405 | - fputs("multilist error\n",stderr); | |
406 | - goto error; | |
407 | - } | |
408 | - if (verbose) { | |
409 | - int c1,c2; | |
410 | - printf("supports multirate: %d\n", multilist->nummulti); | |
411 | - for (c1 = 0; c1 < multilist->nummulti; c1++) { | |
412 | - printf("%d:", c1 + 1); | |
413 | - for (c2 = 0; c2 < multilist->muls[c1].numrate; c2++) | |
414 | - printf(" %d", multilist->muls[c1].rate[c2]); | |
415 | - } | |
416 | - printf("\n"); | |
417 | - } | |
418 | - | |
419 | - /* query operation frequency range */ | |
420 | - freqlist = get_freqlist(ser_fd); | |
421 | - if (freqlist == NULL) { | |
422 | - if (errno != 0) | |
423 | - perror(PROGNAME); | |
424 | - else | |
425 | - fputs("freqlist error\n",stderr); | |
426 | - goto error; | |
427 | - } | |
428 | - if (verbose) { | |
429 | - printf("operation frequencies: %d\n", freqlist->numfreq); | |
430 | - for (c = 0; c < freqlist->numfreq; c++) { | |
431 | - printf("%d: %d.%d - %d.%d\n", c + 1, | |
432 | - freqlist->freq[c].min / 100,freqlist->freq[c].min % 100, | |
433 | - freqlist->freq[c].max / 100,freqlist->freq[c].max % 100); | |
434 | - } | |
435 | - } | |
436 | - | |
437 | - /* set writeing bitrate */ | |
438 | - if (!change_bitrate(ser_fd, input_freq, multilist, freqlist)) { | |
439 | - fputs("set bitrate failed\n",stderr); | |
440 | - goto error; | |
441 | - } | |
442 | - | |
443 | - r =ser_fd; | |
444 | - error: | |
445 | - free(devicelist); | |
446 | - free(clockmode); | |
447 | - free(multilist); | |
448 | - free(freqlist); | |
449 | - if (r == -1 && ser_fd >= 0) | |
450 | - close(ser_fd); | |
451 | - return r; | |
203 | + return write_binary(fp, writeinfo, port); | |
452 | 204 | } |
453 | 205 | |
454 | 206 | /* get target rommap */ |
455 | -static int get_rominfo(int ser_fd, struct writeinfo_t *writeinfo) | |
207 | +static int get_rominfo(struct port_t *port, struct writeinfo_t *writeinfo) | |
456 | 208 | { |
457 | 209 | struct arealist_t *arealist = NULL; |
458 | 210 | int c; |
459 | 211 | |
460 | 212 | /* get target rommap list */ |
461 | - arealist = get_arealist(writeinfo->mat, ser_fd); | |
213 | + arealist = get_arealist(port, writeinfo->mat); | |
462 | 214 | if (arealist == NULL) { |
463 | 215 | if (errno != 0) |
464 | 216 | perror(PROGNAME); |
@@ -469,7 +221,7 @@ static int get_rominfo(int ser_fd, struct writeinfo_t *writeinfo) | ||
469 | 221 | if (verbose) { |
470 | 222 | printf("area map\n"); |
471 | 223 | for (c = 0; c < arealist->areas; c++) |
472 | - printf("%08lx - %08lx\n", arealist->area[c].start, | |
224 | + printf("%08x - %08x\n", arealist->area[c].start, | |
473 | 225 | arealist->area[c].end); |
474 | 226 | } |
475 | 227 |
@@ -483,51 +235,18 @@ static int get_rominfo(int ser_fd, struct writeinfo_t *writeinfo) | ||
483 | 235 | free(arealist); |
484 | 236 | |
485 | 237 | /* get writeing size */ |
486 | - writeinfo->size = get_writesize(ser_fd); | |
238 | + writeinfo->size = get_writesize(port); | |
487 | 239 | if (writeinfo->size < 0) { |
488 | 240 | if (errno != 0) |
489 | 241 | perror(PROGNAME); |
490 | 242 | else |
491 | - fputs("writesize error\n",stderr); | |
243 | + fputs("writesize error\n", stderr); | |
492 | 244 | return 0; |
493 | 245 | } |
494 | 246 | VERBOSE_PRINT("writesize %d byte\n", writeinfo->size); |
495 | 247 | return 1; |
496 | 248 | } |
497 | 249 | |
498 | -static int serial_lock(const char *lock) | |
499 | -{ | |
500 | - struct stat s; | |
501 | - int fd; | |
502 | - pid_t pid; | |
503 | - char buf[128]; | |
504 | - | |
505 | - if (stat(lock, &s) == 0) { | |
506 | - fd = open(lock, O_RDWR); | |
507 | - if (fd == -1) | |
508 | - return -1; | |
509 | - read(fd, buf, sizeof(buf)); | |
510 | - pid = atoi(buf); | |
511 | - if (pid > 0) { | |
512 | - if (kill(pid, 0) != -1 || errno != ESRCH) | |
513 | - return -1; | |
514 | - else { | |
515 | - lseek(fd, 0, SEEK_SET); | |
516 | - ftruncate(fd, 0); | |
517 | - } | |
518 | - } | |
519 | - } else { | |
520 | - fd = creat(lock, 0666); | |
521 | - if (fd == -1) | |
522 | - return -1; | |
523 | - } | |
524 | - pid = getpid(); | |
525 | - sprintf(buf,"%8d",pid); | |
526 | - if (write(fd, buf, 8) != 8) | |
527 | - return -1; | |
528 | - return fd; | |
529 | -} | |
530 | - | |
531 | 250 | static int get_freq_num(const char *arg) |
532 | 251 | { |
533 | 252 | int scale = 100; |
@@ -555,30 +274,31 @@ static int get_freq_num(const char *arg) | ||
555 | 274 | |
556 | 275 | int main(int argc, char *argv[]) |
557 | 276 | { |
558 | - char ser_port[FILENAME_MAX] = DEFAULT_SERIAL; | |
559 | - char lockname[FILENAME_MAX]; | |
277 | + char port[FILENAME_MAX] = DEFAULT_SERIAL; | |
560 | 278 | int c; |
561 | 279 | int long_index; |
562 | 280 | int input_freq; |
563 | 281 | int force_binary; |
564 | - int ser_fd; | |
565 | - int lock_fd; | |
282 | + int config_list; | |
566 | 283 | int r; |
567 | 284 | struct writeinfo_t writeinfo; |
285 | + struct port_t *p = NULL; | |
568 | 286 | |
569 | 287 | writeinfo.mat = user; |
570 | 288 | force_binary = 0; |
571 | 289 | input_freq = 0; |
290 | + config_list = 0; | |
291 | + | |
572 | 292 | /* parse argment */ |
573 | - while ((c = getopt_long(argc, argv, "p:f:bV", | |
293 | + while ((c = getopt_long(argc, argv, "p:f:bVl", | |
574 | 294 | long_options, &long_index)) >= 0) { |
575 | 295 | switch (c) { |
576 | 296 | case 'u': |
577 | 297 | writeinfo.mat = userboot; |
578 | 298 | break ; |
579 | 299 | case 'p': |
580 | - strncpy(ser_port, optarg, sizeof(ser_port)); | |
581 | - ser_port[sizeof(ser_port) - 1] = '\0'; | |
300 | + strncpy(port, optarg, sizeof(port)); | |
301 | + port[sizeof(port) - 1] = '\0'; | |
582 | 302 | break ; |
583 | 303 | case 'f': |
584 | 304 | input_freq = get_freq_num(optarg); |
@@ -589,44 +309,58 @@ int main(int argc, char *argv[]) | ||
589 | 309 | case 'V': |
590 | 310 | verbose = 1; |
591 | 311 | break ; |
312 | + case 'l': | |
313 | + config_list = 1; | |
314 | + break; | |
592 | 315 | case '?': |
593 | 316 | usage(); |
594 | 317 | return 1; |
595 | 318 | } |
596 | 319 | } |
597 | 320 | |
598 | - if (optind >= argc) { | |
321 | + if (optind >= argc && !config_list) { | |
599 | 322 | usage(); |
600 | 323 | return 1; |
601 | 324 | } |
602 | 325 | |
603 | - snprintf(lockname, sizeof(lockname), LOCKDIR "/LCK..%s", basename(ser_port)); | |
604 | - lock_fd = serial_lock(lockname); | |
605 | - if (lock_fd == -1) { | |
606 | - fputs(PROGNAME ": Serial port lock failed.\n",stderr); | |
607 | - return 1; | |
326 | + r = 1; | |
327 | + if (strncasecmp(port, "usb", 3) == 0) { | |
328 | + unsigned short vid = DEFAULT_VID; | |
329 | + unsigned short pid = DEFAULT_PID; | |
330 | + if (strlen(port) > 3) { | |
331 | + if (sscanf("%04x:%04x", port + 3, &vid, &pid) != 2) { | |
332 | + fputs("Unkonwn USB device id", stderr); | |
333 | + goto error; | |
334 | + } | |
335 | + } | |
336 | + p = open_usb(vid, pid); | |
337 | + } else | |
338 | + p = open_serial(port); | |
339 | + if (p == NULL) | |
340 | + goto error; | |
341 | + | |
342 | + if (config_list) { | |
343 | + dump_configs(p); | |
344 | + p->close(); | |
345 | + return 0; | |
608 | 346 | } |
609 | 347 | |
610 | - r = 1; | |
611 | - ser_fd = setup_connection(ser_port, input_freq); | |
612 | - if(ser_fd < 0) | |
348 | + if (setup_connection(p, input_freq) < 0) | |
613 | 349 | goto error; |
614 | 350 | puts("connect target"); |
615 | 351 | |
616 | - if(!get_rominfo(ser_fd, &writeinfo)) | |
352 | + if(!get_rominfo(p, &writeinfo)) | |
617 | 353 | goto error; |
618 | - | |
619 | - if(writefile_to_rom(argv[optind], force_binary, &writeinfo, ser_fd)) { | |
620 | - VERBOSE_PRINT("write %08lx - %08lx ", writeinfo.area.start, writeinfo.area.end); | |
354 | + | |
355 | + if(writefile_to_rom(argv[optind], force_binary, | |
356 | + &writeinfo, p)) { | |
357 | + VERBOSE_PRINT("write %08x - %08x ", writeinfo.area.start, | |
358 | + writeinfo.area.end); | |
621 | 359 | r = 0; |
622 | 360 | } |
623 | 361 | error: |
624 | 362 | puts((r==0)?"done":"write failed"); |
625 | - if (ser_fd >= 0) | |
626 | - close(ser_fd); | |
627 | - | |
628 | - close(lock_fd); | |
629 | - unlink(lockname); | |
630 | - | |
363 | + if (p) | |
364 | + p->close(); | |
631 | 365 | return r; |
632 | 366 | } |
@@ -0,0 +1,206 @@ | ||
1 | +/* | |
2 | + * Renesas CPU On-chip Flash memory writer | |
3 | + * serial I/O | |
4 | + * | |
5 | + * Yoshinori Sato <ysato@users.sourceforge.jp> | |
6 | + * | |
7 | + * This file is subject to the terms and conditions of the GNU Lesser | |
8 | + * General Public License version 2.1 (or later). | |
9 | + */ | |
10 | + | |
11 | +#include <stdio.h> | |
12 | +#include <sys/time.h> | |
13 | +#include <sys/types.h> | |
14 | +#include <unistd.h> | |
15 | +#include <string.h> | |
16 | +#include <termios.h> | |
17 | +#include <fcntl.h> | |
18 | +#include <stdlib.h> | |
19 | +#include <libgen.h> | |
20 | +#include <errno.h> | |
21 | +#include <sys/stat.h> | |
22 | +#include <sys/types.h> | |
23 | +#include <signal.h> | |
24 | +#include "h8flash.h" | |
25 | + | |
26 | +#define TRY1COUNT 60 | |
27 | +#define BAUD_ADJUST_LEN 30 | |
28 | + | |
29 | +static int ser_fd; | |
30 | +static int lock_fd; | |
31 | +static char lockname[FILENAME_MAX]; | |
32 | + | |
33 | +/* send byte stream */ | |
34 | +static int send_data(const unsigned char *buf, int len) | |
35 | +{ | |
36 | + return write(ser_fd, buf, len); | |
37 | +} | |
38 | + | |
39 | +/* receive 1byte */ | |
40 | +static int receive_byte(unsigned char *data) | |
41 | +{ | |
42 | + int r; | |
43 | + struct timeval tv; | |
44 | + fd_set fdset; | |
45 | + | |
46 | + *data = 0; | |
47 | + tv.tv_sec = 60; | |
48 | + tv.tv_usec = 0; | |
49 | + FD_ZERO(&fdset); | |
50 | + FD_SET(ser_fd, &fdset); | |
51 | + r = select(ser_fd + 1, &fdset, NULL, NULL, &tv); | |
52 | + if (r == -1) | |
53 | + return -1; | |
54 | + return read(ser_fd, data, 1); | |
55 | +} | |
56 | + | |
57 | +/* set host bitrate */ | |
58 | +static int setbaud(int bitrate) | |
59 | +{ | |
60 | + int b; | |
61 | + struct termios serattr; | |
62 | + | |
63 | + b = 0; | |
64 | + switch (bitrate) { | |
65 | + case 96: b = B9600; break; | |
66 | + case 192: b = B19200; break; | |
67 | + case 384: b = B38400; break; | |
68 | + case 576: b = B57600; break; | |
69 | + case 1152: b = B115200; break; | |
70 | + } | |
71 | + if (b == 0) | |
72 | + return 0; | |
73 | + | |
74 | + tcgetattr(ser_fd, &serattr); | |
75 | + cfsetospeed(&serattr, b); | |
76 | + cfsetispeed(&serattr, b); | |
77 | + tcsetattr(ser_fd, TCSANOW, &serattr); | |
78 | + return 1; | |
79 | +} | |
80 | + | |
81 | +/* connection target CPU */ | |
82 | +static int connect_target(void) | |
83 | +{ | |
84 | + int try1; | |
85 | + int r; | |
86 | + struct timeval tv; | |
87 | + fd_set fdset; | |
88 | + unsigned char buf[BAUD_ADJUST_LEN]; | |
89 | + | |
90 | + /* wait connection establish */ | |
91 | + for(try1 = 0; try1 < TRY1COUNT; try1++) { | |
92 | + memset(buf, 0x00, BAUD_ADJUST_LEN); | |
93 | + /* send dummy data */ | |
94 | + write(ser_fd, buf, BAUD_ADJUST_LEN); | |
95 | + tv.tv_sec = 1; | |
96 | + tv.tv_usec = 0; | |
97 | + FD_ZERO(&fdset); | |
98 | + FD_SET(ser_fd, &fdset); | |
99 | + /* wait reply */ | |
100 | + r = select(ser_fd + 1, &fdset, NULL, NULL, &tv); | |
101 | + if (r == -1) | |
102 | + return 0; | |
103 | + if ((r > 0) && (read(ser_fd, buf, 1) == 1) && buf[0] == 0) | |
104 | + goto connect; | |
105 | + if (try1 == 0) { | |
106 | + printf("now connection"); | |
107 | + fflush(stdout); | |
108 | + } else { | |
109 | + putchar('.'); | |
110 | + fflush(stdout); | |
111 | + } | |
112 | + } | |
113 | + putchar('\n'); | |
114 | + return 0; | |
115 | + connect: | |
116 | + /* connect done */ | |
117 | + buf[0] = 0x55; | |
118 | + write(ser_fd, buf, 1); | |
119 | + if ((receive_byte(buf) == 1) && (buf[0] == 0xe6)) | |
120 | + return 1; /* ok */ | |
121 | + else | |
122 | + return 0; /* ng */ | |
123 | +} | |
124 | + | |
125 | +void port_close(void) | |
126 | +{ | |
127 | + close(ser_fd); | |
128 | + close(lock_fd); | |
129 | + unlink(lockname); | |
130 | +} | |
131 | + | |
132 | +static struct port_t serial_port = { | |
133 | + .type = serial, | |
134 | + .send_data = send_data, | |
135 | + .receive_byte = receive_byte, | |
136 | + .connect_target = connect_target, | |
137 | + .setbaud = setbaud, | |
138 | + .close = port_close, | |
139 | +}; | |
140 | + | |
141 | +static int serial_lock(const char *lock) | |
142 | +{ | |
143 | + struct stat s; | |
144 | + int fd; | |
145 | + pid_t pid; | |
146 | + char buf[128]; | |
147 | + | |
148 | + if (stat(lock, &s) == 0) { | |
149 | + fd = open(lock, O_RDWR); | |
150 | + if (fd == -1) | |
151 | + return -1; | |
152 | + read(fd, buf, sizeof(buf)); | |
153 | + pid = atoi(buf); | |
154 | + if (pid > 0) { | |
155 | + if (kill(pid, 0) != -1 || errno != ESRCH) | |
156 | + return -1; | |
157 | + else { | |
158 | + lseek(fd, 0, SEEK_SET); | |
159 | + ftruncate(fd, 0); | |
160 | + } | |
161 | + } | |
162 | + } else { | |
163 | + fd = creat(lock, 0666); | |
164 | + if (fd == -1) | |
165 | + return -1; | |
166 | + } | |
167 | + pid = getpid(); | |
168 | + sprintf(buf,"%8d",pid); | |
169 | + if (write(fd, buf, 8) != 8) | |
170 | + return -1; | |
171 | + return fd; | |
172 | +} | |
173 | + | |
174 | +/* host serial open */ | |
175 | +struct port_t *open_serial(char *ser_port) | |
176 | +{ | |
177 | + struct termios serattr; | |
178 | + | |
179 | + snprintf(lockname, sizeof(lockname), LOCKDIR "/LCK..%s", basename(ser_port)); | |
180 | + lock_fd = serial_lock(lockname); | |
181 | + if (lock_fd == -1) { | |
182 | + fputs(PROGNAME ": Serial port lock failed.\n",stderr); | |
183 | + return NULL; | |
184 | + } | |
185 | + | |
186 | + ser_fd = open(ser_port, O_RDWR); | |
187 | + if (ser_fd == -1) { | |
188 | + perror("PROGNAME: "); | |
189 | + return NULL; | |
190 | + } | |
191 | + | |
192 | + tcgetattr(ser_fd, &serattr); | |
193 | + serattr.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON | IXOFF); | |
194 | + serattr.c_oflag &= ~OPOST; | |
195 | + serattr.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); | |
196 | + serattr.c_cflag &= ~(CSIZE | PARENB); | |
197 | + serattr.c_cflag |= CS8 | CLOCAL; | |
198 | + serattr.c_cc[VMIN] = 1; | |
199 | + serattr.c_cc[VTIME] = 0; | |
200 | + cfsetospeed(&serattr, B9600); | |
201 | + cfsetispeed(&serattr, B9600); | |
202 | + tcsetattr(ser_fd, TCSANOW, &serattr); | |
203 | + | |
204 | + return &serial_port; | |
205 | +} | |
206 | + |
@@ -0,0 +1,89 @@ | ||
1 | +#include <usb.h> | |
2 | +#include <stdio.h> | |
3 | +#include "h8flash.h" | |
4 | + | |
5 | +#define USB_TIMEOUT 100000 | |
6 | + | |
7 | +static struct usb_dev_handle *handle; | |
8 | + | |
9 | +static int usb_send_data(const unsigned char *buf, int len) | |
10 | +{ | |
11 | + return usb_bulk_write(handle, 0x01, (const char *)buf, len, USB_TIMEOUT); | |
12 | +} | |
13 | + | |
14 | +int usb_read_byte(unsigned char *data) | |
15 | +{ | |
16 | + static unsigned char buf[64]; | |
17 | + static unsigned char *rp; | |
18 | + static int count = 0; | |
19 | + | |
20 | + if (count == 0) { | |
21 | + int r = usb_bulk_read(handle, 0x82, (char *)buf, 64, USB_TIMEOUT); | |
22 | + if (r < 0) | |
23 | + return r; | |
24 | + count = r; | |
25 | + rp = buf; | |
26 | + } | |
27 | + count--; | |
28 | + *data = *rp++; | |
29 | + return 1; | |
30 | +} | |
31 | + | |
32 | +/* connection target CPU */ | |
33 | +static int connect_target(void) | |
34 | +{ | |
35 | + unsigned char req = 0x55; | |
36 | + int r; | |
37 | + usb_bulk_write(handle, 0x01, (const char *)&req, 1, USB_TIMEOUT); | |
38 | + while ((r = usb_bulk_read(handle, 0x82, (char *)&req, 1, USB_TIMEOUT)) == 0) | |
39 | + usleep(100000); | |
40 | + if (r < 0 || req != 0xe6) | |
41 | + return 0; | |
42 | + else | |
43 | + return 1; | |
44 | +} | |
45 | + | |
46 | +static void port_close(void) | |
47 | +{ | |
48 | + usb_close(handle); | |
49 | +} | |
50 | + | |
51 | +static struct port_t usb_port = { | |
52 | + .type = usb, | |
53 | + .send_data = usb_send_data, | |
54 | + .receive_byte = usb_read_byte, | |
55 | + .connect_target = connect_target, | |
56 | + .setbaud = NULL, | |
57 | + .close = port_close, | |
58 | +}; | |
59 | + | |
60 | +struct port_t *open_usb(unsigned short vid, unsigned short pid) | |
61 | +{ | |
62 | + struct usb_bus *busses; | |
63 | + struct usb_bus *bus; | |
64 | + struct usb_device *dev = NULL; | |
65 | + usb_init(); | |
66 | + usb_get_busses(); | |
67 | + usb_find_busses(); | |
68 | + usb_find_devices(); | |
69 | + | |
70 | + busses = usb_get_busses(); | |
71 | + | |
72 | + for (bus = busses; bus; bus = bus->next) { | |
73 | + for (dev = bus->devices; dev; dev = dev->next) { | |
74 | + if ((dev->descriptor.idVendor == vid) && | |
75 | + (dev->descriptor.idProduct == pid)) | |
76 | + goto found; | |
77 | + } | |
78 | + } | |
79 | +found: | |
80 | + if (dev == NULL) | |
81 | + return NULL; | |
82 | + handle = usb_open(dev); | |
83 | + if (handle == NULL) { | |
84 | + puts(usb_strerror()); | |
85 | + return NULL; | |
86 | + } | |
87 | + usb_claim_interface(handle, dev->config->interface->altsetting->bInterfaceNumber); | |
88 | + return &usb_port; | |
89 | +} |