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