1892ace2c133abdc1c28b1bd82d7100475303026
[lpctools] / isp_commands.c
1 /*********************************************************************
2  *
3  *   LPC1114 ISP Commands
4  *
5  *
6  * Written by Nathael Pajani <nathael.pajani@nathael.net>
7  * 
8  * This programm is released under the terms of the GNU GPLv3 licence
9  * as can be found on the GNU website : <http://www.gnu.org/licenses/>
10  *
11  *********************************************************************/
14 #include <stdlib.h> /* strtoul */
15 #include <stdio.h>
16 #include <stdint.h>
17 #include <unistd.h>
18 #include <string.h> /* strncmp */
19 #include <ctype.h>
20 #include <errno.h>
22 #include "isp_utils.h"
24 extern int trace_on;
26 struct isp_command {
27         char* name;
28         int nb_args;
29         int (*handler)(int arg_count, char** args);
30 };
33 #define SERIAL_BUFSIZE  128
35 #define SYNCHRO_START "?"
36 #define SYNCHRO  "Synchronized\r\n"
37 #define SYNCHRO_OK "OK\r\n"
38 #define SYNCHRO_ECHO_OFF "A 0\r\n"
40 #define ISP_ABORT "\e"
42 #define UNLOCK "U 23130\r\n"
43 #define READ_UID "N\r\n"
44 #define READ_PART_ID "J\r\n"
45 #define READ_BOOT_VERSION "K\r\n"
48 char* error_codes[] = {
49         "CMD_SUCCESS",
50         "INVALID_COMMAND",
51         "SRC_ADDR_ERROR",
52         "DST_ADDR_ERROR",
53         "SRC_ADDR_NOT_MAPPED",
54         "DST_ADDR_NOT_MAPPED",
55         "COUNT_ERROR",
56         "INVALID_SECTOR",
57         "SECTOR_NOT_BLANK",
58         "SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION",
59         "COMPARE_ERROR",
60         "BUSY",
61         "PARAM_ERROR",
62         "ADDR_ERROR",
63         "ADDR_NOT_MAPPED",
64         "CMD_LOCKED",
65         "INVALID_CODE",
66         "INVALID_BAUD_RATE",
67         "INVALID_STOP_BIT",
68         "CODE_READ_PROTECTION_ENABLED",
69 };
71 int isp_ret_code(char* buf, char** endptr)
72 {
73         unsigned int ret = 0;
74         ret = strtoul(buf, endptr, 10);
75         /* FIXME : Find how return code are sent (binary or ASCII) */
76         if (ret > (sizeof(error_codes)/sizeof(char*))) {
77                 printf("Received unknown error code '%u' !\n", ret);
78         } else if ((ret != 0) || trace_on) {
79                 printf("Received error code '%u': %s\n", ret, error_codes[ret]);
80         }
81         return ret;
82 }
85 /* Connect or reconnect to the target.
86  * Return positive or NULL value when connection is OK, or negative value otherwise.
87  */
88 int isp_connect(unsigned int crystal_freq)
89 {
90         char buf[SERIAL_BUFSIZE];
91         char freq[10];
92         
93         snprintf(freq, 8, "%d\r\n", crystal_freq);
95         /* Send synchronize request */
96         if (isp_serial_write(SYNCHRO_START, strlen(SYNCHRO_START)) != strlen(SYNCHRO_START)) {
97                 printf("Unable to send synchronize request.\n");
98                 return -5;
99         }
100         /* Wait for answer */
101         if (isp_serial_read(buf, SERIAL_BUFSIZE, strlen(SYNCHRO)) < 0) {
102                 printf("Error reading synchronize answer.\n");
103                 return -4;
104         }
105         /* Check answer, and acknowledge if OK */
106         if (strncmp(SYNCHRO, buf, strlen(SYNCHRO)) == 0) {
107                 isp_serial_write(SYNCHRO, strlen(SYNCHRO));
108         } else {
109                 printf("Unable to synchronize, no synchro received.\n");
110                 return -3;
111         }
112         /* Empty read buffer (echo is on) */
113         isp_serial_read(buf, strlen(SYNCHRO), strlen(SYNCHRO));
114         /* Read reply (OK) */
115         isp_serial_read(buf, SERIAL_BUFSIZE, strlen(SYNCHRO_OK));
116         if (strncmp(SYNCHRO_OK, buf, strlen(SYNCHRO_OK)) != 0) {
117                 printf("Unable to synchronize, synchro not acknowledged.\n");
118                 return -2;
119         }
121         /* Documentation says we should send crystal frequency .. sending anything is OK */
122         isp_serial_write(freq, strlen(freq));
123         /* Empty read buffer (echo is on) */
124         isp_serial_read(buf, strlen(freq), strlen(freq));
125         /* Read reply (OK) */
126         isp_serial_read(buf, SERIAL_BUFSIZE, strlen(SYNCHRO_OK));
127         if (strncmp(SYNCHRO_OK, buf, strlen(SYNCHRO_OK)) != 0) {
128                 printf("Unable to synchronize, crystal frequency not acknowledged.\n");
129                 return -2;
130         }
132         /* Turn off echo */
133         isp_serial_write(SYNCHRO_ECHO_OFF, strlen(SYNCHRO_ECHO_OFF));
134         /* Empty read buffer (echo still on) */
135         isp_serial_read(buf, strlen(SYNCHRO_ECHO_OFF), strlen(SYNCHRO_ECHO_OFF));
136         /* Read eror code for command */
137         isp_serial_read(buf, SERIAL_BUFSIZE, 3);
139         printf("Device session openned.\n");
141         return 1;
144 int isp_cmd_unlock(int arg_count, char** args)
146         char buf[SERIAL_BUFSIZE];
147         int ret = 0, len = 0;
148         
149         /* Send read-uid request */
150         if (isp_serial_write(UNLOCK, strlen(UNLOCK)) != strlen(UNLOCK)) {
151                 printf("Unable to send unlock request.\n");
152                 return -5;
153         }
154         /* Wait for answer */
155         usleep( 5000 );
156         len = isp_serial_read(buf, SERIAL_BUFSIZE, 1);
157         if (len <= 0) {
158                 printf("Error reading unlock acknowledge.\n");
159                 return -4;
160         }
161         ret = isp_ret_code(buf, NULL);
162         if (ret != 0) {
163                 printf("Unlock error.\n");
164                 return -1;
165         }
166         printf("Device memory protection unlocked.\n");
168         return 0;
171 int isp_cmd_read_uid(int arg_count, char** args)
173         char buf[SERIAL_BUFSIZE];
174         char* tmp = NULL;
175         int i = 0, ret = 0, len = 0;
176         unsigned long int uid[4];
177         
178         /* Send read-uid request */
179         if (isp_serial_write(READ_UID, strlen(READ_UID)) != strlen(READ_UID)) {
180                 printf("Unable to send read-uid request.\n");
181                 return -5;
182         }
183         /* Wait for answer */
184         usleep( 5000 );
185         len = isp_serial_read(buf, SERIAL_BUFSIZE, 50);
186         if (len <= 0) {
187                 printf("Error reading uid.\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         for (i=0; i<4; i++) {
196                 static char* endptr = NULL;
197                 uid[i] = strtoul(tmp, &endptr, 10);
198                 tmp = endptr;
199         }
200         printf("UID: 0x%08lx - 0x%08lx - 0x%08lx - 0x%08lx\n", uid[0], uid[1], uid[2], uid[3]);
202         return 0;
205 int isp_cmd_part_id(int arg_count, char** args)
207         char buf[SERIAL_BUFSIZE];
208         int ret = 0, len = 0;
209         char* tmp = NULL;
210         unsigned long int part_id = 0;
212         /* Send read-part-id request */
213         if (isp_serial_write(READ_PART_ID, strlen(READ_PART_ID)) != strlen(READ_PART_ID)) {
214                 printf("Unable to send read-part-id request.\n");
215                 return -5;
216         }
217         /* Wait for answer */
218         usleep( 5000 );
219         len = isp_serial_read(buf, SERIAL_BUFSIZE, 10);
220         if (len <= 0) {
221                 printf("Error reading part id.\n");
222                 return -4;
223         }
224         ret = isp_ret_code(buf, &tmp);
225         if (ret != 0) {
226                 printf("This cannot happen ... as long as you trust the user manual.\n");
227                 return -1;
228         }
229         /* FIXME : some part IDs are on two 32bits values */
230         part_id = strtoul(tmp, NULL, 10);
231         printf("Part ID is 0x%08lx\n", part_id);
233         return 0;
236 int isp_cmd_boot_version(int arg_count, char** args)
238         char buf[SERIAL_BUFSIZE];
239         int ret = 0, len = 0;
240         char* tmp = NULL;
241         unsigned int ver[2];
243         /* Send read-boot-version request */
244         if (isp_serial_write(READ_BOOT_VERSION, strlen(READ_BOOT_VERSION)) != strlen(READ_BOOT_VERSION)) {
245                 printf("Unable to send read-boot-version request.\n");
246                 return -5;
247         }
248         /* Wait for answer */
249         usleep( 5000 );
250         len = isp_serial_read(buf, SERIAL_BUFSIZE, 5);
251         if (len <= 0) {
252                 printf("Error reading boot version.\n");
253                 return -4;
254         }
255         ret = isp_ret_code(buf, &tmp);
256         if (ret != 0) {
257                 printf("This cannot happen ... as long as you trust the user manual.\n");
258                 return -1;
259         }
260         ver[0] = strtoul(tmp, &tmp, 10);
261         ver[1] = strtoul(tmp, NULL, 10);
262         printf("Boot code version is %u.%u\n", ver[0], ver[1]);
264         return 0;
268 /* FIXME : Temporary place-holder */
269 int isp_cmd_null(int arg_count, char** args)
271         int i = 0;
272         printf("command not yet handled, called with %d arguments.\n", arg_count);
273         for (i=0; i<arg_count; i++) {
274                 printf("\targ[%d] : \"%s\"\n", i, args[i]);
275         }
276         return 0;
279 static struct isp_command isp_cmds_list[] = {
280         {"unlock", 0, isp_cmd_unlock},
281         {"write-to-ram", 0, isp_cmd_null}, /* isp_cmd_write-to-ram} */
282         {"read-memory", 0, isp_cmd_null}, /* isp_cmd_read-memory} */
283         {"prepare-for-write", 0, isp_cmd_null}, /* isp_cmd_prepare-for-write} */
284         {"copy-ram-to-flash", 0, isp_cmd_null}, /* isp_cmd_copy-ram-to-flash} */
285         {"go", 0, isp_cmd_null}, /* isp_cmd_go} */
286         {"erase", 0, isp_cmd_null}, /* isp_cmd_erase} */
287         {"blank-check", 0, isp_cmd_null}, /* isp_cmd_blank-check} */
288         {"read-part-id", 0, isp_cmd_part_id},
289         {"read-boot-version", 0, isp_cmd_boot_version},
290         {"compare", 0, isp_cmd_null}, /* isp_cmd_compare} */
291         {"read-uid", 0, isp_cmd_read_uid},
292         {NULL, 0, NULL}
293 };
295 void isp_warn_trailing_args(int cmd_num, int arg_count, char** args)
297         int i = 0;
298         printf("command \"%s\" needs %d args, got %d.\n",
299                         isp_cmds_list[cmd_num].name,
300                         isp_cmds_list[cmd_num].nb_args, arg_count);
301         for (i=0; i<arg_count; i++) {
302                 printf("\targ[%d] : \"%s\"\n", i, args[i]);
303         }
306 /* Handle one command
307  * Return positive or NULL value when command handling is OK, or negative value otherwise.
308  */
309 int isp_handle_command(char* cmd, int arg_count, char** args)
311         int cmd_found = -1;
312         int ret = 0;
313         int index = 0;
315         if (cmd == NULL) {
316                 printf("isp_handle_command called with no command !\n");
317                 return -1;
318         }
320         while ((cmd_found == -1) && (isp_cmds_list[index].name != NULL)) {
321                 if (strncmp(isp_cmds_list[index].name, cmd, strlen(isp_cmds_list[index].name)) == 0) {
322                         cmd_found = index;
323                         break;
324                 }
325                 index++;
326         }
327         if (arg_count != isp_cmds_list[cmd_found].nb_args) {
328                 isp_warn_trailing_args(cmd_found, arg_count, args);
329         }
330         isp_cmds_list[cmd_found].handler(arg_count, args);
331         
332         if (cmd_found == -1) {
333                 printf("Unknown command \"%s\", use -h or --help for a list.\n", cmd);
334                 return -2;
335         }
337         return ret;