Align loader to 32-bit boundary
[fw/stlink] / flash / main.c
1 /* simple wrapper around the stlink_flash_write function */
2
3 // TODO - this should be done as just a simple flag to the st-util command line...
4
5
6 #include <signal.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/types.h>
11 #include "stlink-common.h"
12
13 #define DEBUG_LOG_LEVEL 100
14 #define STND_LOG_LEVEL  50
15
16 stlink_t *connected_stlink = NULL;
17
18 static void cleanup(int signal __attribute__((unused))) {
19     if (connected_stlink) {
20         /* Switch back to mass storage mode before closing. */
21         stlink_run(connected_stlink);
22         stlink_exit_debug_mode(connected_stlink);
23         stlink_close(connected_stlink);
24     }
25
26     exit(1);
27 }
28
29 enum st_cmds {DO_WRITE = 0, DO_READ = 1, DO_ERASE = 2};
30 struct opts
31 {
32     enum st_cmds cmd;
33     const char* devname;
34         char *serial;
35     const char* filename;
36     stm32_addr_t addr;
37     size_t size;
38     int reset;
39     int log_level;
40 };
41
42 static void usage(void)
43 {
44     puts("stlinkv1 command line: ./st-flash [--debug] [--reset] [--serial <iSerial>] {read|write} /dev/sgX path addr <size>");
45     puts("stlinkv1 command line: ./st-flash [--debug] /dev/sgX erase");
46     puts("stlinkv2 command line: ./st-flash [--debug] [--reset] [--serial <iSerial>] {read|write} path addr <size>");
47     puts("stlinkv2 command line: ./st-flash [--debug] [--serial <iSerial>] erase");
48     puts("                       use hex format for addr, <iSerial> and <size>");
49 }
50
51 static int get_opts(struct opts* o, int ac, char** av)
52 {
53     /* stlinkv1 command line: ./st-flash {read|write} /dev/sgX path addr <size> */
54     /* stlinkv2 command line: ./st-flash {read|write} path addr <size> */
55
56     unsigned int i = 0;
57
58     if (ac < 1) return -1;
59
60     if (strcmp(av[0], "--debug") == 0)
61     {
62         o->log_level = DEBUG_LOG_LEVEL;
63         ac--;
64         av++;
65     }
66     else
67     {
68         o->log_level = STND_LOG_LEVEL;
69     }
70
71     if (strcmp(av[0], "--reset") == 0)
72     {
73         o->reset = 1;
74         ac--;
75         av++;
76     }
77     else
78     {
79         o->reset = 0;
80     }
81
82     if (strcmp(av[0], "--serial") == 0)
83     {
84         ac--;
85         av++;
86             int i=strlen(av[0]);
87             if(i%2 != 0){
88                     puts("no valid hex value, length must be multiple of 2\n");
89                     return -1;
90             }
91             int j=0;
92             while(i>=0 && j<=13){
93                     char buffer[3]={0};
94                     memcpy(buffer,&av[0][i],2);
95                     o->serial[12-j] = (char)strtol((const char*)buffer,NULL, 16);
96                     j++;
97                     i-=2;
98             }
99         ac--;
100         av++;
101     }
102     else
103     {
104         o->serial = NULL;
105     }
106
107     if (ac < 1) return -1;
108
109     /* stlinkv2 */
110     o->devname = NULL;
111
112     if (strcmp(av[0], "erase") == 0)
113     {
114         o->cmd = DO_ERASE;
115
116         /* stlinkv1 mode */
117         if (ac == 2)
118         {
119             o->devname = av[1];
120             i = 1;
121         }
122     }
123     else {
124         if (ac < 3) return -1;
125         if (strcmp(av[0], "read") == 0)
126         {
127             o->cmd = DO_READ;
128
129             /* stlinkv1 mode */
130             if (ac == 5)
131             {
132                 o->devname = av[1];
133                 i = 1;
134             }
135             if (ac > 3)
136                 o->size = strtoul(av[i + 3], NULL, 16);
137         }
138         else if (strcmp(av[0], "write") == 0)
139         {
140             o->cmd = DO_WRITE;
141
142             /* stlinkv1 mode */
143             if (ac == 4)
144             {
145                 o->devname = av[1];
146                 i = 1;
147             }
148         }
149         else
150         {
151             return -1;
152         }
153     }
154
155     o->filename = av[i + 1];
156     o->addr = strtoul(av[i + 2], NULL, 16);
157
158     return 0;
159 }
160
161
162 int main(int ac, char** av)
163 {
164     stlink_t* sl = NULL;
165     struct opts o;
166     char serial_buffer[13] = {0};
167     o.serial = serial_buffer;
168     int err = -1;
169
170     o.size = 0;
171     if (get_opts(&o, ac - 1, av + 1) == -1)
172     {
173         printf("invalid command line\n");
174         usage();
175         return -1;
176     }
177
178     if (o.devname != NULL) /* stlinkv1 */
179         sl = stlink_v1_open(o.log_level, 1);
180     else /* stlinkv2 */
181             sl = stlink_open_usb(o.log_level, 1, o.serial);
182
183     if (sl == NULL)
184         return -1;
185
186     sl->verbose = o.log_level;
187
188     connected_stlink = sl;
189     signal(SIGINT, &cleanup);
190     signal(SIGTERM, &cleanup);
191     signal(SIGSEGV, &cleanup);
192
193     if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) {
194         if (stlink_exit_dfu_mode(sl)) {
195             printf("Failed to exit DFU mode\n");
196             goto on_error;
197         }
198     }
199
200     if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) {
201         if (stlink_enter_swd_mode(sl)) {
202             printf("Failed to enter SWD mode\n");
203             goto on_error;
204         }
205     }
206
207     if (o.reset){
208         if (stlink_jtag_reset(sl, 2)) {
209             printf("Failed to reset JTAG\n");
210             goto on_error;
211         }
212
213         if (stlink_reset(sl)) {
214             printf("Failed to reset device\n");
215             goto on_error;
216         }
217     }
218
219     // Disable DMA - Set All DMA CCR Registers to zero. - AKS 1/7/2013
220     if (sl->chip_id == STM32_CHIPID_F4)
221     {
222         memset(sl->q_buf,0,4);
223         for (int i=0;i<8;i++) {
224             stlink_write_mem32(sl,0x40026000+0x10+0x18*i,4);
225             stlink_write_mem32(sl,0x40026400+0x10+0x18*i,4);
226             stlink_write_mem32(sl,0x40026000+0x24+0x18*i,4);
227             stlink_write_mem32(sl,0x40026400+0x24+0x18*i,4);
228         }
229     }
230
231     // Core must be halted to use RAM based flashloaders
232     if (stlink_force_debug(sl)) {
233         printf("Failed to halt the core\n");
234         goto on_error;
235     }
236
237     if (stlink_status(sl)) {
238         printf("Failed to get Core's status\n");
239         goto on_error;
240     }
241
242     if (o.cmd == DO_WRITE) /* write */
243     {
244         if ((o.addr >= sl->flash_base) &&
245                 (o.addr < sl->flash_base + sl->flash_size)) {
246             err = stlink_fwrite_flash(sl, o.filename, o.addr);
247             if (err == -1)
248             {
249                 printf("stlink_fwrite_flash() == -1\n");
250                 goto on_error;
251             }
252         }
253         else if ((o.addr >= sl->sram_base) &&
254                 (o.addr < sl->sram_base + sl->sram_size)) {
255             err = stlink_fwrite_sram(sl, o.filename, o.addr);
256             if (err == -1)
257             {
258                 printf("stlink_fwrite_sram() == -1\n");
259                 goto on_error;
260             }
261         }
262     } else if (o.cmd == DO_ERASE)
263     {
264         err = stlink_erase_flash_mass(sl);
265         if (err == -1)
266         {
267             printf("stlink_erase_flash_mass() == -1\n");
268             goto on_error;
269         }
270     }
271     else /* read */
272     {
273         if ((o.addr >= sl->flash_base) && (o.size == 0) &&
274                 (o.addr < sl->flash_base + sl->flash_size))
275             o.size = sl->flash_size;
276         else if ((o.addr >= sl->sram_base) && (o.size == 0) &&
277                 (o.addr < sl->sram_base + sl->sram_size))
278             o.size = sl->sram_size;
279         err = stlink_fread(sl, o.filename, o.addr, o.size);
280         if (err == -1)
281         {
282             printf("stlink_fread() == -1\n");
283             goto on_error;
284         }
285     }
286
287     if (o.reset){
288         stlink_jtag_reset(sl,2);
289         stlink_reset(sl);
290     }
291
292     /* success */
293     err = 0;
294
295 on_error:
296     stlink_exit_debug_mode(sl);
297     stlink_close(sl);
298
299     return err;
300 }