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) {
171 according to documentation, \n should be sufficient
172 -- works well with commands, but uuencoded data transmission
173 seems to not work well with it; so using \r\n instead
175 if (fprintf(comm, "%s\r\n", line) < 0) {
176 perror("send_line: fprintf");
180 /* check echo, 1s timeout */
181 if ((sel = poll_input(comm, 1, 0)) < 1) {
183 fprintf(stderr, "send_line: command echo timeout\n");
185 perror("send_line: select");
188 fgets(s, sizeof(s), comm);
189 /*DEBUG*/printf(":%s", s);
190 if (strncmp(line, s, strlen(line))) {
191 fprintf(stderr, "send_line: \"%s\" command echo mismatch (\"%s\" received)\n", line, s);
195 if (response_type == NO_RESPONSE)
199 /* read with timout for every character (necessary for go command) */
201 /* check response, 1s timeout */
202 if ((sel = poll_input(comm, 1, 0)) < 1) {
204 /*DEBUG*/printf(">%s", s);
207 fprintf(stderr, "send_line: \"%s\" command response timeout\n", line);
210 perror("send_line: select");
213 /* read one character */
214 size = fread(p, 1, 1, comm);
216 } while (*(p-1) != '\n');
219 /*DEBUG*/printf(">%s", s);
221 if (response_type == OK_RESPONSE) {
222 /* textual response -- expecting "OK" */
223 resp = (strncmp(s, "OK", 2) != 0);
225 fprintf(stderr, "Received something else than \"OK\"\n");
229 /* numeric response */
230 if (sscanf(s, "%d", &resp) == 0) {
231 fprintf(stderr, "Invalid (non-numeric) command response received\n");
235 fprintf(stderr, "Error response code %d\n", resp);
240 int send_line_fmt(FILE *comm, resp_type_t resp, const char *fmt, ...) {
245 vsprintf(s, fmt, ap);
247 return send_line(comm, resp, s);
250 #define MAX_SYNC_QM_TRIES 240
251 int synchronize(FILE *comm, int crystal_freq) {
254 char sync_string[] = "Synchronized\n";
255 int sync_status = 0, sync_pos = 0, sync_len = strlen(sync_string);
257 printf("Synchronizing");
258 /* send '?'s and wait for response */
259 for (n = 0; n < MAX_SYNC_QM_TRIES; n++) {
260 /* if not receiving "Synchronized" response, send '?'s */
267 /* 0.1s is duration of 3 characters in 8N1 300b/s transfer */
268 sel = poll_input(comm, 0, 100000);
270 perror("synchronize: select");
276 if (ch == sync_string[sync_pos]) {
280 if (sync_pos == sync_len) {
281 printf("\n\"Synchronized\" received (recv. %d chars)\n", n);
292 putchar(sel ? ((ch == '?') ? '.' : 'x') : '_');
296 if (n == MAX_SYNC_QM_TRIES) {
297 fprintf(stderr, "Didn't synchronize after %d tries.\n", n);
301 * here may be comm.dev mode switched back to ICANON...
303 /* respond to sync */
304 if (send_line(comm, OK_RESPONSE, "Synchronized"))
306 printf("Synchronized, OK.\n");
307 /* send Xtal frequency */
308 printf("Sending crystal frequency: %d\n", crystal_freq);
309 //sprintf(s, "%d", crystal_freq);
310 if (send_line_fmt(comm, OK_RESPONSE, "%d", 7373)) //crystal_freq))
316 struct termios comm_attr_save;
318 void close_comm(FILE *comm) {
319 /* restore serial line settings */
320 tcsetattr(fileno(comm), TCSANOW, &comm_attr_save);
324 FILE *open_comm(char *device, int baudrate, int flowc) {
328 /* TODO: Open the serial line the same way as lpc21isp. It seems
329 * that loading works even if there is terminal emulator attached to
331 if ((comm = fopen(device, "r+")) == NULL) {
332 perror("open_comm: fopen");
335 /* set stream as unbuffered */
338 comm_dev = fileno(comm);
339 /* backup serial line settings */
340 if (tcgetattr(comm_dev, &comm_attr_save))
341 fprintf(stderr, "Warning: open_comm: can not get serial line settings by tcgetattr");
342 /* setup serial device parameters */
343 setup_comm_dev(comm_dev, baudrate, flowc);
345 /* initialize serial bootloader (on miniARM_DB board) */
346 ioctl (comm_dev, TIOCMGET, &line);
348 ioctl (comm_dev, TIOCMSET, &line);
351 ioctl (comm_dev, TIOCMSET, &line);
359 int write_ram(FILE *comm, unsigned start, unsigned length, char *data) {
361 int i, line, line_len;
362 unsigned count = length;
365 sprintf(s, "W %u %u", start, length);
366 if (send_line(comm, NUM_RESPONSE, s))
370 for (line = 0; (line < 20) && (count > 0); line++) {
371 line_len = (count < 45) ? count : 45;
372 for (i = 0; i < line_len; i++)
373 checksum += (unsigned char)data[i];
374 uuencode_line(s, data, line_len);
377 if (send_line(comm, NO_RESPONSE, s))
380 sprintf(s, "%u", checksum);
381 if (send_line(comm, OK_RESPONSE, s))
389 int tolpc_send_cmd(struct tolpc_env *env, char *fmt, ...) {
393 if (env->comm_stream == NULL)
394 if (tolpc_open_target(env))
398 vsprintf(s, fmt, ap);
401 return send_line(env->comm_stream, NUM_RESPONSE, s);
404 int tolpc_readline_to(struct tolpc_env *env, char *s, int size) {
405 fgets(s, size, env->comm_stream);
409 int tolpc_open_target(struct tolpc_env *env) {
412 comm = open_comm(env->sdev, env->baud, FLOWC_XONXOFF);
415 if (synchronize(comm, env->crystal))
418 env->comm_stream = comm;
422 int tolpc_write_ram(struct tolpc_env *env, unsigned int start, int length, unsigned char *data) {
423 return write_ram(env->comm_stream, start, length, data);
428 int tolpc_unlock(struct tolpc_env *env) {
430 ret = tolpc_send_cmd(env, "U 23130");
434 int tolpc_go(struct tolpc_env *env, unsigned int start, char arm_mode)
438 ret = tolpc_send_cmd(env, "G %u %c", start, arm_mode ? 'A' : 'T');
441 verbose(1, "Timeout means the code is executed\n");
450 * @param part_id Where to store received part id.
451 * @param size Size of part_id.
452 * @return Zero on success, -1 on error.
454 int tolpc_partid(struct tolpc_env *env, char* part_id, int size)
458 ret = tolpc_send_cmd(env, "J");
461 ret = tolpc_readline_to(env, part_id, size);
462 return ret == 0 ? 0 : -1;
466 * Reads boot code version
468 * @param ver Where to store received version.
469 * @param size Size of ver.
470 * @return Zero on success, -1 on error.
472 int tolpc_bootver(struct tolpc_env *env, char* ver, int size)
476 ret = tolpc_send_cmd(env, "K");
479 ret = tolpc_readline_to(env, ver, size);
480 return ret == 0 ? 0 : -1;
486 * @return Zero on success, 1 on bad response, -1 on communication error.
488 int tolpc_echo(struct tolpc_env *env, char on)
492 ret = tolpc_send_cmd(env, "A %c", on);
499 int tolpc_break(struct tolpc_env *env)
506 /* Open RS232 device */
507 if ((fd = open(env->sdev, O_RDWR | O_NONBLOCK)) == -1) {
508 printf("Error openning %s\n", env->sdev);
512 if (rs232_setmode(fd, env->baud / 2, 0) < 0) {
518 printf("Sending break chars \n");