Adding read-memory command support
[lpctools] / isp_main.c
1 /*********************************************************************
2  *
3  *   LPC1114 ISP
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> /* malloc, free */
15 #include <stdio.h>
16 #include <stdint.h>
18 #include <unistd.h> /* open, getopt, close, usleep */
19 #include <fcntl.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
23 #include <errno.h>
24 #include <getopt.h>
26 #include <termios.h> /* for serial config */
27 #include <ctype.h>
29 #include "isp_utils.h"
30 #include "isp_commands.h"
32 #define PROG_NAME "LPC11xx ISP"
33 #define VERSION   "0.01"
35 /* short explanation on exit values:
36  *
37  * 0 is OK
38  * 1 is arg error
39  *
40  */
43 void help(char *prog_name)
44 {
45         fprintf(stderr, "-----------------------------------------------------------------------\n");
46         fprintf(stderr, "Usage: %s [options] device [-s | --synchronize]\n" \
47                 "       %s [options] device command [command arguments]\n" \
48                 "  Default baudrate is B115200\n" \
49                 "  <device> is the (host) serial line used to programm the device\n" \
50                 "  <command> is one of:\n" \
51                 "  \t unlock \n" \
52                 "  \t write-to-ram \n" \
53                 "  \t read-memory address count file : read 'count' byte(s) from 'address', store then in 'file'\n" \
54                 "  \t prepare-for-write \n" \
55                 "  \t copy-ram-to-flash \n" \
56                 "  \t go \n" \
57                 "  \t erase \n" \
58                 "  \t blank-check \n" \
59                 "  \t read-part-id \n" \
60                 "  \t read-boot-version \n" \
61                 "  \t compare \n" \
62                 "  \t read-uid \n" \
63                 "  Notes:\n" \
64                 "   - Access to the ISP mode is done by calling this utility once with the synchronize\n" \
65                 "     option and no command. This starts a session. No command can be used before starting\n" \
66                 "     a session, and no other synchronize request must be done once the session is started\n" \
67                 "     unless the target is reseted, which closes the session.\n" \
68                 "   - Echo is turned OFF when starting a session and the command is not available.\n" \
69                 "   - The set-baud-rate command is not available. The SAME baudrate MUST be used for the\n" \
70                 "     whole session. It must be specified on each successive call if the default baudrate\n" \
71                 "     is not used.\n" \
72                 "  Available options:\n" \
73                 "  \t -s | --synchronize : Perform synchronization (open session)\n" \
74                 "  \t -b | --baudrate=N : Use this baudrate (does not issue the set-baud-rate command)\n" \
75                 "  \t -t | --trace : turn on trace output of serial communication\n" \
76                 "  \t -h | --help : display this help\n" \
77                 "  \t -v | --version : display version information\n", prog_name, prog_name);
78         fprintf(stderr, "-----------------------------------------------------------------------\n");
79 }
81 #define SERIAL_BAUD  B115200
83 int trace_on = 0;
86 int main(int argc, char** argv)
87 {
88         int baudrate = SERIAL_BAUD;
89         int crystal_freq = 10000;
90         int synchronize = 0;
91         char* isp_serial_device = NULL;
93         /* For "command" handling */
94         char* command = NULL;
95         char** cmd_args = NULL;
96         int nb_cmd_args = 0;
99         /* parameter parsing */
100         while(1) {
101                 int option_index = 0;
102                 int c = 0;
104                 struct option long_options[] = {
105                         {"synchronize", no_argument, 0, 's'},
106                         {"baudrate", required_argument, 0, 'b'},
107                         {"trace", no_argument, 0, 't'},
108                         {"help", no_argument, 0, 'h'},
109                         {"version", no_argument, 0, 'v'},
110                         {0, 0, 0, 0}
111                 };
113                 c = getopt_long(argc, argv, "sb:thv", long_options, &option_index);
115                 /* no more options to parse */
116                 if (c == -1) break;
118                 switch (c) {
119                         /* b, baudrate */
120                         case 'b':
121                                 baudrate = atoi(optarg);
122                                 /* FIXME: validate baudrate */
123                                 break;
125                         /* t, trace */
126                         case 't':
127                                 trace_on = 1;
128                                 break;
130                         /* s, synchronize */
131                         case 's':
132                                 synchronize = 1;
133                                 break;
135                         /* v, version */
136                         case 'v':
137                                 printf("%s Version %s\n", PROG_NAME, VERSION);
138                                 return 0;
139                                 break;
141                         /* h, help */
142                         case 'h':
143                         default:
144                                 help(argv[0]);
145                                 return 0;
146                 }
147         }
149         /* Parse remaining command line arguments (not options). */
151         /* First one should (must) be serial device */
152         if (optind < argc) {
153                 isp_serial_device = argv[optind++];
154                 if (trace_on) {
155                         printf("Serial device : %s\n", isp_serial_device);
156                 }
157         }
158         if (isp_serial_device == NULL) {
159                 printf("No serial device given, exiting\n");
160                 help(argv[0]);
161                 return 0;
162         }
163         if (isp_serial_open(baudrate, isp_serial_device) != 0) {
164                 printf("Serial open failed, unable to initiate serial communication with target.\n");
165                 return -1;
166         }
168         if (synchronize) {
169                 if (optind < argc) {
170                         /* no command can be specified when opening a session */
171                         printf("No command can be specified with -s or --synchronize (Session opening)\n");
172                         printf("NOT SYNCHRONIZED !\n");
173                         return -1;
174                 }
175                 isp_connect(crystal_freq);
176                 isp_serial_close();
177                 return 0;
178         }
180         /* Next one should be "command" (if present) */
181         if (optind < argc) {
182                 command = argv[optind++];
183                 if (trace_on) {
184                         printf("Command : %s\n", command);
185                 }
186         } else {
187                 printf("No command given. use -h or --help for help on available commands.\n");
188                 isp_serial_close();
189                 return -1;
190         }
191         /* And then remaining ones (if any) are command arguments */
192         if (optind < argc) {
193                 nb_cmd_args = argc - optind;
194                 cmd_args = malloc(nb_cmd_args * sizeof(char *));
195                 if (trace_on) {
196                         printf("Command arguments :\n");
197                 }
198                 while (optind < argc) {
199                         static unsigned int idx = 0;
200                         cmd_args[idx++] = argv[optind++];
201                         if (trace_on) {
202                                 printf("%s\n", cmd_args[idx - 1]);
203                         }
204                 }
205         }
207         if (command != NULL)  {
208                 int err = 0;
209                 err = isp_handle_command(command, nb_cmd_args, cmd_args);
210                 if (err >= 0) {
211                         if (trace_on) {
212                                 printf("Command \"%s\" handled OK.\n", command);
213                         }
214                 } else {
215                         printf("Error handling command \"%s\" : %d\n", command, err);
216                 }
217         }
220         if (cmd_args != NULL) {
221                 free(cmd_args);
222         }
223         isp_serial_close();
224         return 0;