17 //#define WITHOUT_CFSETSPEED
19 int tolpc_debug_level = 0;
21 #ifdef WITHOUT_CFSETSPEED
25 /* Set both the input and output baud rates stored in *TERMIOS_P to SPEED. */
26 int rs232_cfsetspeed (struct termios *termios_p, speed_t speed) {
29 for (cnt = 0; cnt < sizeof(rs232_speeds) / sizeof(rs232_speeds[ 0 ]); ++cnt)
30 if (speed == rs232_speeds[ cnt ].internal) {
31 cfsetispeed (termios_p, speed);
32 cfsetospeed (termios_p, speed);
34 } else if (speed == rs232_speeds[ cnt ].value) {
35 cfsetispeed (termios_p, rs232_speeds[ cnt ].internal);
36 cfsetospeed (termios_p, rs232_speeds[ cnt ].internal);
43 #endif /* WITHOUT_CFSETSPEED */
45 #define FLOWC_XONXOFF 0x02
46 #define FLOWC_RTSCTS 0x01
48 int tolpc_verbose_level = 0;
50 void tolpc_verbose(int level, const char *fmt, ...)
54 if (level <= tolpc_verbose_level) {
56 vfprintf(stderr, fmt, ap);
61 #define verbose tolpc_verbose
64 * Set right mode and speed for RS232 interface
65 * baud can be either speed in character per second or special Bxxxx constant
67 int setup_comm_dev(int dev, int baudrate, int flowc) {
68 struct termios term_attr;
70 if (tcgetattr(dev, &term_attr)) {
71 perror("setup_dev: tcgetattr");
74 /* set immediate character input */
76 ~ICANON -- do not wait for EOL at input,
77 ~ECHO -- do not echo characters locally
79 term_attr.c_lflag = 0;
80 term_attr.c_cc[VMIN] = 1;
81 term_attr.c_cc[VTIME] = 0;
83 /* input newlines: \r\n=>\n */
84 term_attr.c_iflag = IGNCR;
85 if (flowc & FLOWC_XONXOFF)
86 term_attr.c_iflag |= IXON | IXOFF;
87 if (flowc & FLOWC_RTSCTS)
88 term_attr.c_cflag |= CRTSCTS;
90 term_attr.c_oflag = 0;
92 /* set right ispeed and ospeed */
93 #ifdef WITHOUT_CFSETSPEED
94 if (rs232_cfsetspeed(&term_attr, baudrate) < 0) {
95 fprintf(stderr, "Error in rs232_cfsetspeed\n");
98 #else /* WITHOUT_CFSETSPEED */
99 if (cfsetspeed(&term_attr, baudrate) < 0) {
100 fprintf(stderr, "Error in cfsetspeed\n");
103 #endif /* WITHOUT_CFSETSPEED */
105 if (tcsetattr(dev, TCSAFLUSH, &term_attr)) {
106 perror("setup_dev: tcsetattr");
115 static const char *isp_response_code[] = {
118 "SRC_ADDR_ERROR: Source address is not on word boundary",
119 "DST_ADDR_ERROR: Destination address is not on a correct boundary",
120 "SRC_ADDR_NOT_MAPPED: Source address is not mapped in the memory map",
121 "DST_ADDR_NOT_MAPPED: Destination address is not mapped in the memory map",
122 "COUNT_ERROR: Byte count is not multiple of 4 or is not a permitted value",
123 "INVALID_SECTOR: Sector number is invalid or end sector number is "
124 " greater than start sector number.",
126 "SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION:"
127 " Command to prepare sector for write operation was not executed",
143 typedef enum _response_type_t {
149 int poll_input(FILE *stream, long tv_sec, long tv_usec) {
151 struct timeval timeout;
152 int sel, comm_dev = fileno(stream);
155 FD_SET(comm_dev, &sel_set);
156 timeout.tv_sec = tv_sec;
157 timeout.tv_usec = tv_usec;
158 sel = select(comm_dev+1, &sel_set, NULL, NULL, &timeout);
160 perror("poll_input: select");
164 int send_line(FILE *comm, resp_type_t response_type, char *line) {
170 according to documentation, \n should be sufficient
171 -- works well with commands, but uuencoded data transmission
172 seems to not work well with it; so using \r\n instead
174 if (fprintf(comm, "%s\r\n", line) < 0) {
175 perror("send_line: fprintf");
179 /* check echo, 1s timeout */
180 if ((sel = poll_input(comm, 1, 0)) < 1) {
182 fprintf(stderr, "send_line: command echo timeout\n");
184 perror("send_line: select");
187 fgets(s, sizeof(s), comm);
188 /*DEBUG*/printf(":%s", s);
189 if (strncmp(line, s, strlen(line))) {
190 fprintf(stderr, "send_line: \"%s\" command echo mismatch (\"%s\" received)\n", line, s);
194 if (response_type == NO_RESPONSE)
197 /* check response, 1s timeout */
198 if ((sel = poll_input(comm, 1, 0)) < 1) {
200 fprintf(stderr, "send_line: \"%s\" command response timeout\n", line);
202 perror("send_line: select");
205 fgets(s, sizeof(s), comm);
206 /*DEBUG*/printf(">%s", s);
207 if (response_type == OK_RESPONSE) {
208 /* textual response -- expecting "OK" */
209 resp = (strncmp(s, "OK", 2) != 0);
211 fprintf(stderr, "Received something else than \"OK\"\n");
215 /* numeric response */
216 if (sscanf(s, "%d", &resp) == 0) {
217 fprintf(stderr, "Invalid (non-numeric) command response received\n");
221 fprintf(stderr, "Error response code %d\n", resp);
226 int send_line_fmt(FILE *comm, resp_type_t resp, const char *fmt, ...) {
231 vsprintf(s, fmt, ap);
233 return send_line(comm, resp, s);
236 #define MAX_SYNC_QM_TRIES 240
237 int synchronize(FILE *comm, int crystal_freq) {
240 char sync_string[] = "Synchronized\n";
241 int sync_status = 0, sync_pos = 0, sync_len = strlen(sync_string);
243 printf("Synchronizing");
244 /* send '?'s and wait for response */
245 for (n = 0; n < MAX_SYNC_QM_TRIES; n++) {
246 /* if not receiving "Synchronized" response, send '?'s */
253 /* 0.1s is duration of 3 characters in 8N1 300b/s transfer */
254 sel = poll_input(comm, 0, 100000);
256 perror("synchronize: select");
262 if (ch == sync_string[sync_pos]) {
266 if (sync_pos == sync_len) {
267 printf("\n\"Synchronized\" received (recv. %d chars)\n", n);
278 putchar(sel ? ((ch == '?') ? '.' : 'x') : '_');
282 if (n == MAX_SYNC_QM_TRIES) {
283 fprintf(stderr, "Didn't synchronize after %d tries.\n", n);
287 * here may be comm.dev mode switched back to ICANON...
289 /* respond to sync */
290 if (send_line(comm, OK_RESPONSE, "Synchronized"))
292 printf("Synchronized, OK.\n");
293 /* send Xtal frequency */
294 printf("Sending crystal frequency: %d\n", crystal_freq);
295 //sprintf(s, "%d", crystal_freq);
296 if (send_line_fmt(comm, OK_RESPONSE, "%d", 7373)) //crystal_freq))
302 struct termios comm_attr_save;
304 void close_comm(FILE *comm) {
305 /* restore serial line settings */
306 tcsetattr(fileno(comm), TCSANOW, &comm_attr_save);
310 FILE *open_comm(char *device, int baudrate, int flowc) {
314 if ((comm = fopen(device, "r+")) == NULL) {
315 perror("open_comm: fopen");
318 /* set stream as unbuffered */
321 comm_dev = fileno(comm);
322 /* backup serial line settings */
323 if (tcgetattr(comm_dev, &comm_attr_save))
324 fprintf(stderr, "Warning: open_comm: can not get serial line settings by tcgetattr");
325 /* setup serial device parameters */
326 setup_comm_dev(comm_dev, baudrate, flowc);
328 /* initialize serial bootloader (on miniARM_DB board) */
329 ioctl (comm_dev, TIOCMGET, &line);
331 ioctl (comm_dev, TIOCMSET, &line);
334 ioctl (comm_dev, TIOCMSET, &line);
342 int write_ram(FILE *comm, unsigned start, unsigned length, char *data) {
344 int i, line, line_len;
345 unsigned count = length;
348 sprintf(s, "W %u %u", start, length);
349 if (send_line(comm, NUM_RESPONSE, s))
353 for (line = 0; (line < 20) && (count > 0); line++) {
354 line_len = (count < 45) ? count : 45;
355 for (i = 0; i < line_len; i++)
356 checksum += (unsigned char)data[i];
357 uuencode_line(s, data, line_len);
360 if (send_line(comm, NO_RESPONSE, s))
363 sprintf(s, "%u", checksum);
364 if (send_line(comm, OK_RESPONSE, s))
372 int tolpc_send_cmd(struct tolpc_env *env, char *fmt, ...) {
376 if (env->comm_stream == NULL)
377 if (tolpc_open_target(env))
381 vsprintf(s, fmt, ap);
384 return send_line(env->comm_stream, NUM_RESPONSE, s);
387 int tolpc_readline_to(struct tolpc_env *env, char *s, int size) {
388 fgets(s, size, env->comm_stream);
392 int tolpc_open_target(struct tolpc_env *env) {
395 comm = open_comm(env->sdev, env->baud, FLOWC_XONXOFF);
398 if (synchronize(comm, env->crystal))
401 env->comm_stream = comm;
405 int tolpc_write_ram(struct tolpc_env *env, unsigned int start, int length, unsigned char *data) {
406 return write_ram(env->comm_stream, start, length, data);
411 int tolpc_unlock(struct tolpc_env *env) {
413 ret = tolpc_send_cmd(env, "U 23130");
417 int tolpc_go(struct tolpc_env *env, unsigned int start, char arm_mode)
421 ret = tolpc_send_cmd(env, "G %u %c", start, arm_mode ? 'A' : 'T');
424 verbose(1, "Timeout means the code is executed\n");
433 * @param part_id Where to store received part id.
434 * @param size Size of part_id.
435 * @return Zero on success, -1 on error.
437 int tolpc_partid(struct tolpc_env *env, char* part_id, int size)
441 ret = tolpc_send_cmd(env, "J");
444 ret = tolpc_readline_to(env, part_id, size);
445 return ret == 0 ? 0 : -1;
449 * Reads boot code version
451 * @param ver Where to store received version.
452 * @param size Size of ver.
453 * @return Zero on success, -1 on error.
455 int tolpc_bootver(struct tolpc_env *env, char* ver, int size)
459 ret = tolpc_send_cmd(env, "K");
462 ret = tolpc_readline_to(env, ver, size);
463 return ret == 0 ? 0 : -1;
469 * @return Zero on success, 1 on bad response, -1 on communication error.
471 int tolpc_echo(struct tolpc_env *env, char on)
475 ret = tolpc_send_cmd(env, "A %c", on);
482 int tolpc_break(struct tolpc_env *env)
489 /* Open RS232 device */
490 if ((fd = open(env->sdev, O_RDWR | O_NONBLOCK)) == -1) {
491 printf("Error openning %s\n", env->sdev);
495 if (rs232_setmode(fd, env->baud / 2, 0) < 0) {
501 printf("Sending break chars \n");