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