]> rtime.felk.cvut.cz Git - sysless.git/blob - arch/arm/mach-lpc21xx/tools/tolpc/tolpc.c
cmdproc: Make backspace work even in sterm
[sysless.git] / arch / arm / mach-lpc21xx / tools / tolpc / tolpc.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <termios.h>
5 #include <sys/time.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <unistd.h>
9 #include <fcntl.h>
10 #include <getopt.h>
11 #include <stdarg.h>
12 #include "tolpc_fn.h"
13 #include "load_bfd.h"
14
15 #define DEBUG 0
16 #define HAS_GETOPT_LONG 1
17
18
19 struct tolpc_env Tolpc =
20 {
21     .sdev = "/dev/ttyS0", .crystal = 10000, .baud = 9600, .waitrep = 100000
22 };
23
24 struct tolpc_env *env = &Tolpc;
25
26 void error(const char *fmt, ...)
27 {
28     va_list ap;
29     char message[100];
30
31     va_start(ap, fmt);
32     vsnprintf(message, 100, fmt, ap);
33     va_end(ap);
34
35     fprintf(stderr, "tolpc error: %s\n", message);
36     exit(1);
37 }
38
39 static void usage(void)
40 {
41     printf("usage:\n");
42     printf("  high level: tolpc [<global parameters>] -L [mode] -f <object file>\n");
43     printf("   low level: tolpc [<global parameters>] [command [,...]]\n");
44     printf("Command has the form: [command [, param1 [,param2, ...]]\n");
45     printf("\n");
46     printf("Global Parameters:\n");
47     printf("  -d, --sdev <name>        name of RS232 device [%s]\n", env->sdev);
48     printf("  -q, --crystal <kHz>      crystal frequency in kHz [%d]\n", env->crystal);
49     printf("  -b, --baud <num>         RS232 baudrate [%d]\n", env->baud);
50     printf("  -w, --wait <num>         timeout in miliseconds [%ld]\n", env->waitrep/1000);
51     printf("  -v, --verbose            increase verbosity (can be used more times)\n");
52     printf("Commands:\n");
53     printf("  -L, --load [A|T]         Load binary file and execute (loads all BFD sections,\n");
54     printf("                           jumps to start address) [only RAM in this version].\n");
55     printf("  -U, --unlock\n");
56     printf("  -A, --echo <setting>     Echo (use -A0 when uploading data using W)\n");
57     printf("  -G, --go [<mode>]        Mode is A or T [A]\n");
58     printf("  -C, --copy <flash_addr>  Copy RAM to Flash\n");
59     printf("  -c, --cmd <command>      Execute other command (letters from LPC user manual)\n");
60     printf("Parameters:\n");
61     printf("  -s, --start  <addr>      start address of transfer\n");
62     printf("  -l, --length <num>       length of upload block\n");
63     printf("  -f, --file <filename>    file to read or write\n");
64     printf("  -o, --offset <num>       offset in a file\n");
65     printf("Other:\n");
66     printf("  -k, --break              send communication break character\n");
67     printf("  -V, --version            show version\n");
68     printf("  -h, --help               this usage screen\n");
69 }
70
71 struct cmd_params {
72     char cmd;
73     char *sarg;
74     int iarg;
75     
76     long start;
77     int length;
78     int offset;
79     char *fname;
80
81     void *data;
82 };
83
84 int load_file(struct cmd_params *p)
85 {
86     FILE *f;
87     struct stat st;
88     int ret;
89
90     if (!p->fname)
91         error("No file (-f) for %c command", p->cmd);
92
93     ret = stat(p->fname, &st);
94     if (ret) {
95         perror(p->fname);
96         exit(1);
97     }
98
99     if (p->length == 0) p->length = st.st_size - p->offset;
100
101     f = fopen(p->fname, "r");
102     if (f == NULL) {
103         perror(p->fname);
104         exit(1);
105     }
106
107     fseek(f, p->offset, SEEK_SET);
108
109     p->data = malloc(p->length);
110
111     fread(p->data, p->length, 1, f);
112     if (ferror(f)) {
113         perror(p->fname);
114         exit(1);
115     }
116     
117     return p->length;
118 }
119
120 int ram_write_cb(bfd_vma lma, bfd_size_type size, void *data) {
121     return tolpc_write_ram(env, lma, size, data);
122 }
123
124 /**
125  * load bfd file to target (only RAM at this moment) and jump
126  * to its start address
127  * @return 0=OK
128  */
129 int load_exec(struct cmd_params *p) {
130     int ret;
131     bfd_vma start;
132
133     if (!p->fname)
134         error("No file (-f) for %c command", p->cmd);
135
136     ret = tolpc_echo(env, '0');
137     if (ret) return ret;
138     
139     ret = tolpc_unlock(env);
140     if (ret) return ret;
141     
142     ret = load_bfd(p->fname, /*default target*/NULL, ram_write_cb, &start, tolpc_verbose_level);
143     if (ret) return ret;
144
145     tolpc_verbose(1, "Running the program\n");
146     ret = tolpc_go(env, start,  p->iarg == 'A');
147
148     return(ret);
149 }
150
151 void not_implemented(char c)
152 {
153     error("Not implemented: %c", c);
154 }
155
156 void clear_cmd(struct cmd_params *p)
157 {
158     if (p->data) free(p->data);
159     memset(p, 0, sizeof(*p));
160     p->start = -1;
161 }
162
163 void run_cmd(struct cmd_params *p)
164 {
165     int ret = 0;
166     
167     switch (p->cmd) {
168         case 'U':
169             ret = tolpc_unlock(env);
170             break;
171         case 'A':
172             ret = tolpc_echo(env, p->iarg);
173             break;
174         case 'G':
175             if (p->iarg != 'A' && p->iarg != 'T')
176                 error("Go mode can only be A or T.");
177             if (p->start < 0)
178                 error("No start address is given for Go command");
179             ret = tolpc_go(env, p->start, p->iarg == 'A');
180             break;
181         case 'W':
182             load_file(p);
183             if (p->start < 0)
184                 error("No start addres is given for Write command");
185             ret = tolpc_write_ram(env, p->start, p->length, p->data);
186             break;
187         case 'J':
188         {
189             char partid[100];
190             ret = tolpc_partid(env, partid, 99);
191             if (ret == 0) {
192                 tolpc_verbose(1, "Part ID:");
193                 puts(partid);
194             }
195             break;
196         }
197         case 'K':
198         {
199             char ver[100];
200             tolpc_bootver(env, ver, 99);
201             if (ret == 0) {
202                 tolpc_verbose(1, "Boot code version:");
203                 puts(ver);
204             }
205             break;
206         }
207         case 'L':
208             ret = load_exec(p);
209             break;
210         default:
211             not_implemented(p->cmd);
212
213     }
214     if (ret) error("Command %c", p->cmd);
215 }
216
217 void new_command(struct cmd_params *p, char cmd)
218 {
219     if (p->cmd)
220         run_cmd(p);
221     
222     clear_cmd(p);
223     p->cmd = cmd;        
224 }
225
226 int main(int argc, char **argv)
227 {
228     int i;
229     int opt;
230     char short_ops[100];
231     struct cmd_params p;
232
233     static struct option long_opts[] = {
234         { "sdev", 1, 0, 'd'},
235         { "crystal", 1, 0, 'q' },
236         { "baud", 1, 0, 'b' },
237         { "wait", 1, 0, 'w' },
238         { "verbose", 0, 0, 'v' },
239
240         { "unlock", 0, 0, 'U' },
241         { "echo", 1, 0, 'A' },
242         { "go", 2, 0, 'G' },
243         { "copy", 1, 0, 'C' },
244         { "cmd", 1, 0, 'c' },
245         { "load", 2, 0, 'L' }, // has optional argument
246
247         { "start", 1, 0, 's' },
248         { "length", 1, 0, 'l' },
249         { "file", 1, 0, 'f' },
250         { "offset", 1, 0, 'o' },
251
252         { "break", 0, 0, 'k' },
253         { "version", 0, 0, 'V' },
254         { "help", 0, 0, 'h' },
255         { 0, 0, 0, 0}
256     };
257
258     // Initial clear of of parameters structure (clear_cmd produces segfault here)
259     memset(&p, 0, sizeof(p));
260     p.start = -1;
261
262     memset(short_ops, 0, sizeof(short_ops));
263     i = 0;
264     for (opt = 0; long_opts[opt].name != NULL || i > 100 - 3; opt++) {
265         short_ops[i++] = long_opts[opt].val;
266         if (long_opts[opt].has_arg) short_ops[i++] = ':';
267         if (long_opts[opt].has_arg == 2) short_ops[i++] = ':';
268     }
269     short_ops[i] = '\0';
270
271 #ifndef HAS_GETOPT_LONG
272     while ((opt = getopt(argc, argv, short_ops)) != EOF)
273 #else
274         while ((opt = getopt_long(argc, argv, short_ops,
275                                   &long_opts[0], NULL)) != EOF)
276 #endif
277             switch (opt) {
278             case 'd':
279                 env->sdev = optarg;
280                 break;
281             case 'b':
282                 env->baud = strtol(optarg, NULL, 0);
283                 break;
284             case 'q':
285                 env->crystal = strtol(optarg, NULL, 0);
286                 break;
287             case 'w':
288                 env->waitrep = 1000*strtol(optarg, NULL, 0);
289                 break;
290             case 'v':
291                 tolpc_verbose_level++;
292                 break;
293             case 'U':
294                 new_command(&p, opt);
295                 break;
296             case 'A':
297                 new_command(&p, opt);
298                 p.iarg = optarg[0];
299                 break;
300             case 'G':
301             {
302                 new_command(&p, opt);
303                 p.iarg = 'A'; // ARM mode is default
304                 if (optarg) p.iarg = optarg[0];
305                 break;
306             }
307             case 'C':
308                 new_command(&p, opt);
309                 break;
310             case 'c':
311             {
312                 char cmd = optarg[0];
313                 switch (cmd) {
314                     case 'W':
315                     case 'J':
316                     case 'K':
317                         new_command(&p, cmd);
318                         break;
319                     default:
320                         error("Unknown command %c", cmd);
321                         break;
322                 }
323                 break;
324             }
325             case 'L':
326                 new_command(&p, opt);
327                 p.iarg = 'A'; // ARM mode is default
328                 if (optarg) p.iarg = optarg[0];
329             break;
330             case 's':
331                 p.start = strtol(optarg, NULL, 0);
332                 break;
333             case 'l':
334                 p.length = strtol(optarg, NULL, 0);
335                 break;
336             case 'f':
337                 p.fname = optarg;
338                 break;
339             case 'o':
340                 p.offset = strtol(optarg, NULL, 0);
341                 break;
342             case 'V':
343                 fputs("tolpc pre alpha\n", stdout);
344                 exit(0);
345             case 'h':
346             default:
347                 usage();
348                 exit(opt == 'h' ? 0 : 1);
349             }
350             new_command(&p, 0); // run the last command
351     return 0;
352 }