Synchro now OK, simple read commands (no arguments) working.
[lpctools] / isp_commands.c
1 /*********************************************************************
2  *
3  *   LPC1114 ISP Commands
4  *
5  *********************************************************************/
8 #include <stdlib.h> /* strtoul */
9 #include <stdio.h>
10 #include <stdint.h>
11 #include <unistd.h>
12 #include <string.h> /* strncmp */
13 #include <ctype.h>
14 #include <errno.h>
16 #include "isp_utils.h"
18 extern int trace_on;
20 struct isp_command {
21         char* name;
22         int nb_args;
23         int (*handler)(int arg_count, char** args);
24 };
27 #define SERIAL_BUFSIZE  128
29 #define SYNCHRO_START "?"
30 #define SYNCHRO  "Synchronized\r\n"
31 #define SYNCHRO_OK "OK\r\n"
32 #define SYNCHRO_ECHO_OFF "A 0\r\n"
34 #define ISP_ABORT "\e"
35 #define READ_UID "N\r\n"
36 #define READ_PART_ID "J\r\n"
37 #define READ_BOOT_VERSION "K\r\n"
40 char* error_codes[] = {
41         "CMD_SUCCESS",
42         "INVALID_COMMAND",
43         "SRC_ADDR_ERROR",
44         "DST_ADDR_ERROR",
45         "SRC_ADDR_NOT_MAPPED",
46         "DST_ADDR_NOT_MAPPED",
47         "COUNT_ERROR",
48         "INVALID_SECTOR",
49         "SECTOR_NOT_BLANK",
50         "SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION",
51         "COMPARE_ERROR",
52         "BUSY",
53         "PARAM_ERROR",
54         "ADDR_ERROR",
55         "ADDR_NOT_MAPPED",
56         "CMD_LOCKED",
57         "INVALID_CODE",
58         "INVALID_BAUD_RATE",
59         "INVALID_STOP_BIT",
60         "CODE_READ_PROTECTION_ENABLED",
61 };
63 int isp_ret_code(char* buf, char** endptr)
64 {
65         unsigned int ret = 0;
66         ret = strtoul(buf, endptr, 10);
67         if (trace_on) {
68                 /* FIXME : Find how return code are sent (binary or ASCII) */
69                 if (ret > (sizeof(error_codes)/sizeof(char*))) {
70                         printf("Received unknown error code '%u' !\n", ret);
71                 } else {
72                         printf("Received error code '%u': %s\n", ret, error_codes[ret]);
73                 }
74         }
75         return ret;
76 }
79 /* Connect or reconnect to the target.
80  * Return positive or NULL value when connection is OK, or negative value otherwise.
81  */
82 int isp_connect(unsigned int crystal_freq)
83 {
84         char buf[SERIAL_BUFSIZE];
85         char freq[10];
86         
87         snprintf(freq, 8, "%d\r\n", crystal_freq);
89         /* Send synchronize request */
90         if (isp_serial_write(SYNCHRO_START, strlen(SYNCHRO_START)) != strlen(SYNCHRO_START)) {
91                 printf("Unable to send synchronize request.\n");
92                 return -5;
93         }
94         /* Wait for answer */
95         if (isp_serial_read(buf, SERIAL_BUFSIZE, strlen(SYNCHRO)) < 0) {
96                 printf("Error reading synchronize answer.\n");
97                 return -4;
98         }
99         /* Check answer, and acknowledge if OK */
100         if (strncmp(SYNCHRO, buf, strlen(SYNCHRO)) == 0) {
101                 isp_serial_write(SYNCHRO, strlen(SYNCHRO));
102         } else {
103                 printf("Unable to synchronize, no synchro received.\n");
104                 return -3;
105         }
106         /* Empty read buffer (echo is on) */
107         isp_serial_read(buf, strlen(SYNCHRO), strlen(SYNCHRO));
108         /* Read reply (OK) */
109         isp_serial_read(buf, SERIAL_BUFSIZE, strlen(SYNCHRO_OK));
110         if (strncmp(SYNCHRO_OK, buf, strlen(SYNCHRO_OK)) != 0) {
111                 printf("Unable to synchronize, synchro not acknowledged.\n");
112                 return -2;
113         }
115         /* Documentation says we should send crystal frequency .. sending anything is OK */
116         isp_serial_write(freq, strlen(freq));
117         /* Empty read buffer (echo is on) */
118         isp_serial_read(buf, strlen(freq), strlen(freq));
119         /* Read reply (OK) */
120         isp_serial_read(buf, SERIAL_BUFSIZE, strlen(SYNCHRO_OK));
121         if (strncmp(SYNCHRO_OK, buf, strlen(SYNCHRO_OK)) != 0) {
122                 printf("Unable to synchronize, crystal frequency not acknowledged.\n");
123                 return -2;
124         }
126         /* Turn off echo */
127         isp_serial_write(SYNCHRO_ECHO_OFF, strlen(SYNCHRO_ECHO_OFF));
128         /* Empty read buffer (echo still on) */
129         isp_serial_read(buf, strlen(SYNCHRO_ECHO_OFF), strlen(SYNCHRO_ECHO_OFF));
130         /* Read eror code for command */
131         isp_serial_read(buf, SERIAL_BUFSIZE, 3);
133         return 1;
137 int isp_cmd_read_uid(int arg_count, char** args)
139         char buf[SERIAL_BUFSIZE];
140         char* tmp = NULL;
141         int i = 0, ret = 0, len = 0;
142         unsigned long int uid[4];
143         
144         /* Send read-uid request */
145         if (isp_serial_write(READ_UID, strlen(READ_UID)) != strlen(READ_UID)) {
146                 printf("Unable to send read-uid request.\n");
147                 return -5;
148         }
149         /* Wait for answer */
150         usleep( 5000 );
151         len = isp_serial_read(buf, SERIAL_BUFSIZE, 50);
152         if (len <= 0) {
153                 printf("Error reading uid.\n");
154                 return -4;
155         }
156         ret = isp_ret_code(buf, &tmp);
157         if (ret != 0) {
158                 printf("This cannot happen ... as long as you trust the user manual.\n");
159                 return -1;
160         }
161         for (i=0; i<4; i++) {
162                 static char* endptr = NULL;
163                 uid[i] = strtoul(tmp, &endptr, 10);
164                 tmp = endptr;
165         }
166         printf("UID: 0x%08lx - 0x%08lx - 0x%08lx - 0x%08lx\n", uid[0], uid[1], uid[2], uid[3]);
168         return 0;
171 int isp_cmd_part_id(int arg_count, char** args)
173         char buf[SERIAL_BUFSIZE];
174         int ret = 0, len = 0;
175         char* tmp = NULL;
176         unsigned long int part_id = 0;
178         /* Send read-part-id request */
179         if (isp_serial_write(READ_PART_ID, strlen(READ_PART_ID)) != strlen(READ_PART_ID)) {
180                 printf("Unable to send read-part-id request.\n");
181                 return -5;
182         }
183         /* Wait for answer */
184         usleep( 5000 );
185         len = isp_serial_read(buf, SERIAL_BUFSIZE, 10);
186         if (len <= 0) {
187                 printf("Error reading part id.\n");
188                 return -4;
189         }
190         ret = isp_ret_code(buf, &tmp);
191         if (ret != 0) {
192                 printf("This cannot happen ... as long as you trust the user manual.\n");
193                 return -1;
194         }
195         /* FIXME : some part IDs are on two 32bits values */
196         part_id = strtoul(tmp, NULL, 10);
197         printf("Part ID is 0x%08lx\n", part_id);
199         return 0;
202 int isp_cmd_boot_version(int arg_count, char** args)
204         char buf[SERIAL_BUFSIZE];
205         int ret = 0, len = 0;
206         char* tmp = NULL;
207         unsigned int ver[2];
209         /* Send read-boot-version request */
210         if (isp_serial_write(READ_BOOT_VERSION, strlen(READ_BOOT_VERSION)) != strlen(READ_BOOT_VERSION)) {
211                 printf("Unable to send read-boot-version request.\n");
212                 return -5;
213         }
214         /* Wait for answer */
215         usleep( 5000 );
216         len = isp_serial_read(buf, SERIAL_BUFSIZE, 5);
217         if (len <= 0) {
218                 printf("Error reading boot version.\n");
219                 return -4;
220         }
221         ret = isp_ret_code(buf, &tmp);
222         if (ret != 0) {
223                 printf("This cannot happen ... as long as you trust the user manual.\n");
224                 return -1;
225         }
226         ver[0] = strtoul(tmp, &tmp, 10);
227         ver[1] = strtoul(tmp, NULL, 10);
228         printf("Boot code version is %u.%u\n", ver[0], ver[1]);
230         return 0;
234 /* FIXME : Temporary place-holder */
235 int isp_cmd_null(int arg_count, char** args)
237         int i = 0;
238         printf("command not yet handled, called with %d arguments.\n", arg_count);
239         for (i=0; i<arg_count; i++) {
240                 printf("\targ[%d] : \"%s\"\n", i, args[i]);
241         }
242         return 0;
245 static struct isp_command isp_cmds_list[] = {
246         {"unlock", 0, isp_cmd_null}, /* isp_cmd_unlock} */
247         {"write-to-ram", 0, isp_cmd_null}, /* isp_cmd_write-to-ram} */
248         {"read-memory", 0, isp_cmd_null}, /* isp_cmd_read-memory} */
249         {"prepare-for-write", 0, isp_cmd_null}, /* isp_cmd_prepare-for-write} */
250         {"copy-ram-to-flash", 0, isp_cmd_null}, /* isp_cmd_copy-ram-to-flash} */
251         {"go", 0, isp_cmd_null}, /* isp_cmd_go} */
252         {"erase", 0, isp_cmd_null}, /* isp_cmd_erase} */
253         {"blank-check", 0, isp_cmd_null}, /* isp_cmd_blank-check} */
254         {"read-part-id", 0, isp_cmd_part_id},
255         {"read-boot-version", 0, isp_cmd_boot_version},
256         {"compare", 0, isp_cmd_null}, /* isp_cmd_compare} */
257         {"read-uid", 0, isp_cmd_read_uid},
258         {NULL, 0, NULL}
259 };
261 void isp_warn_trailing_args(int cmd_num, int arg_count, char** args)
263         int i = 0;
264         printf("command \"%s\" needs %d args, got %d.\n",
265                         isp_cmds_list[cmd_num].name,
266                         isp_cmds_list[cmd_num].nb_args, arg_count);
267         for (i=0; i<arg_count; i++) {
268                 printf("\targ[%d] : \"%s\"\n", i, args[i]);
269         }
272 /* Handle one command
273  * Return positive or NULL value when command handling is OK, or negative value otherwise.
274  */
275 int isp_handle_command(char* cmd, int arg_count, char** args)
277         int cmd_found = -1;
278         int ret = 0;
279         int index = 0;
281         if (cmd == NULL) {
282                 printf("isp_handle_command called with no command !\n");
283                 return -1;
284         }
286         while ((cmd_found == -1) && (isp_cmds_list[index].name != NULL)) {
287                 if (strncmp(isp_cmds_list[index].name, cmd, strlen(isp_cmds_list[index].name)) == 0) {
288                         cmd_found = index;
289                         break;
290                 }
291                 index++;
292         }
293         if (arg_count != isp_cmds_list[cmd_found].nb_args) {
294                 isp_warn_trailing_args(cmd_found, arg_count, args);
295         }
296         isp_cmds_list[cmd_found].handler(arg_count, args);
297         
298         if (cmd_found == -1) {
299                 printf("Unknown command \"%s\", use -h or --help for a list.\n", cmd);
300                 return -2;
301         }
303         return ret;