Initial commit of workable stm32l debug
[fw/stlink] / src / stlink-common.c
1
2
3 #include <stdarg.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include <unistd.h>
9 #include <fcntl.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <sys/mman.h>
13
14
15 #include "stlink-common.h"
16
17 void D(stlink_t *sl, char *txt) {
18     if (sl->verbose > 1)
19         fputs(txt, stderr);
20 }
21
22 void DD(stlink_t *sl, char *format, ...) {
23     if (sl->verbose > 0) {
24         va_list list;
25         va_start(list, format);
26         vfprintf(stderr, format, list);
27         va_end(list);
28     }
29 }
30
31 // Delegates to the backends...
32
33 void stlink_close(stlink_t *sl) {
34     D(sl, "\n*** stlink_close ***\n");
35     sl->backend->close(sl);
36
37     free(sl);
38 }
39
40 void stlink_exit_debug_mode(stlink_t *sl) {
41     D(sl, "\n*** stlink_exit_debug_mode ***\n");
42     sl->backend->exit_debug_mode(sl);
43 }
44
45 void stlink_enter_swd_mode(stlink_t *sl) {
46     D(sl, "\n*** stlink_enter_swd_mode ***\n");
47     sl->backend->enter_swd_mode(sl);
48 }
49
50 void stlink_exit_dfu_mode(stlink_t *sl) {
51     D(sl, "\n*** stlink_exit_duf_mode ***\n");
52     sl->backend->exit_dfu_mode(sl);
53 }
54
55 void stlink_core_id(stlink_t *sl) {
56     D(sl, "\n*** stlink_core_id ***\n");
57     sl->backend->core_id(sl);
58     DD(sl, "core_id = 0x%08x\n", sl->core_id);
59 }
60
61 void stlink_reset(stlink_t *sl) {
62     D(sl, "\n*** stlink_reset ***\n");
63     sl->backend->reset(sl);
64
65 }
66
67 void stlink_run(stlink_t *sl) {
68     D(sl, "\n*** stlink_core_id ***\n");
69     sl->backend->run(sl);
70     DD(sl, "core_id = 0x%08x\n", sl->core_id);
71 }
72
73 void stlink_status(stlink_t *sl) {
74     D(sl, "\n*** stlink_core_id ***\n");
75     sl->backend->status(sl);
76     stlink_core_stat(sl);
77     DD(sl, "core_id = 0x%08x\n", sl->core_id);
78 }
79
80 void stlink_version(stlink_t *sl) {
81     D(sl, "*** looking up stlink version\n");
82     sl->backend->version(sl);
83 }
84
85 void stlink_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
86     D(sl, "\n*** stlink_write_mem32 ***\n");
87     if (len % 4 != 0) {
88         fprintf(stderr, "Error: Data length doesn't have a 32 bit alignment: +%d byte.\n", len % 4);
89         return;
90     }
91     sl->backend->write_mem32(sl, addr, len);
92 }
93
94 void stlink_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) {
95     D(sl, "\n*** stlink_write_mem8 ***\n");
96     sl->backend->write_mem8(sl, addr, len);
97 }
98
99
100
101
102
103
104 // End of delegates....  Common code below here...
105
106 // Endianness
107 // http://www.ibm.com/developerworks/aix/library/au-endianc/index.html
108 // const int i = 1;
109 // #define is_bigendian() ( (*(char*)&i) == 0 )
110
111 static inline unsigned int is_bigendian(void) {
112     static volatile const unsigned int i = 1;
113     return *(volatile const char*) &i == 0;
114 }
115
116 uint16_t read_uint16(const unsigned char *c, const int pt) {
117     uint32_t ui;
118     char *p = (char *) &ui;
119
120     if (!is_bigendian()) { // le -> le (don't swap)
121         p[0] = c[pt];
122         p[1] = c[pt + 1];
123     } else {
124         p[0] = c[pt + 1];
125         p[1] = c[pt];
126     }
127     return ui;
128 }
129
130 void stlink_core_stat(stlink_t *sl) {
131     if (sl->q_len <= 0)
132         return;
133
134     stlink_print_data(sl);
135
136     switch (sl->q_buf[0]) {
137         case STLINK_CORE_RUNNING:
138             sl->core_stat = STLINK_CORE_RUNNING;
139             DD(sl, "  core status: running\n");
140             return;
141         case STLINK_CORE_HALTED:
142             sl->core_stat = STLINK_CORE_HALTED;
143             DD(sl, "  core status: halted\n");
144             return;
145         default:
146             sl->core_stat = STLINK_CORE_STAT_UNKNOWN;
147             fprintf(stderr, "  core status: unknown\n");
148     }
149 }
150
151 void stlink_print_data(stlink_t *sl) {
152     if (sl->q_len <= 0 || sl->verbose < 2)
153         return;
154     if (sl->verbose > 2)
155         fprintf(stdout, "data_len = %d 0x%x\n", sl->q_len, sl->q_len);
156
157     for (int i = 0; i < sl->q_len; i++) {
158         if (i % 16 == 0) {
159             /*
160                                     if (sl->q_data_dir == Q_DATA_OUT)
161                                             fprintf(stdout, "\n<- 0x%08x ", sl->q_addr + i);
162                                     else
163                                             fprintf(stdout, "\n-> 0x%08x ", sl->q_addr + i);
164              */
165         }
166         fprintf(stdout, " %02x", (unsigned int) sl->q_buf[i]);
167     }
168     fputs("\n\n", stdout);
169 }
170
171 /* memory mapped file */
172
173 typedef struct mapped_file {
174     uint8_t* base;
175     size_t len;
176 } mapped_file_t;
177
178 #define MAPPED_FILE_INITIALIZER { NULL, 0 }
179
180 static int map_file(mapped_file_t* mf, const char* path) {
181     int error = -1;
182     struct stat st;
183
184     const int fd = open(path, O_RDONLY);
185     if (fd == -1) {
186         fprintf(stderr, "open(%s) == -1\n", path);
187         return -1;
188     }
189
190     if (fstat(fd, &st) == -1) {
191         fprintf(stderr, "fstat() == -1\n");
192         goto on_error;
193     }
194
195     mf->base = (uint8_t*) mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
196     if (mf->base == MAP_FAILED) {
197         fprintf(stderr, "mmap() == MAP_FAILED\n");
198         goto on_error;
199     }
200
201     mf->len = st.st_size;
202
203     /* success */
204     error = 0;
205
206 on_error:
207     close(fd);
208
209     return error;
210 }
211
212 static void unmap_file(mapped_file_t* mf) {
213     munmap((void*) mf->base, mf->len);
214     mf->base = (unsigned char*) MAP_FAILED;
215     mf->len = 0;
216 }
217
218 static int check_file
219 (stlink_t* sl, mapped_file_t* mf, stm32_addr_t addr) {
220     size_t off;
221
222     for (off = 0; off < mf->len; off += sl->flash_pgsz) {
223         size_t aligned_size;
224
225         /* adjust last page size */
226         size_t cmp_size = sl->flash_pgsz;
227         if ((off + sl->flash_pgsz) > mf->len)
228             cmp_size = mf->len - off;
229
230         aligned_size = cmp_size;
231         if (aligned_size & (4 - 1))
232             aligned_size = (cmp_size + 4) & ~(4 - 1);
233
234         stlink_read_mem32(sl, addr + off, aligned_size);
235
236         if (memcmp(sl->q_buf, mf->base + off, cmp_size))
237             return -1;
238     }
239
240     return 0;
241 }
242
243 int stlink_fwrite_sram
244 (stlink_t * sl, const char* path, stm32_addr_t addr) {
245     /* write the file in sram at addr */
246
247     int error = -1;
248     size_t off;
249     mapped_file_t mf = MAPPED_FILE_INITIALIZER;
250
251     if (map_file(&mf, path) == -1) {
252         fprintf(stderr, "map_file() == -1\n");
253         return -1;
254     }
255
256     /* check addr range is inside the sram */
257     if (addr < sl->sram_base) {
258         fprintf(stderr, "addr too low\n");
259         goto on_error;
260     } else if ((addr + mf.len) < addr) {
261         fprintf(stderr, "addr overruns\n");
262         goto on_error;
263     } else if ((addr + mf.len) > (sl->sram_base + sl->sram_size)) {
264         fprintf(stderr, "addr too high\n");
265         goto on_error;
266     } else if ((addr & 3) || (mf.len & 3)) {
267         /* todo */
268         fprintf(stderr, "unaligned addr or size\n");
269         goto on_error;
270     }
271
272     /* do the copy by 1k blocks */
273     for (off = 0; off < mf.len; off += 1024) {
274         size_t size = 1024;
275         if ((off + size) > mf.len)
276             size = mf.len - off;
277
278         memcpy(sl->q_buf, mf.base + off, size);
279
280         /* round size if needed */
281         if (size & 3)
282             size += 2;
283
284         stlink_write_mem32(sl, addr + off, size);
285     }
286
287     /* check the file ha been written */
288     if (check_file(sl, &mf, addr) == -1) {
289         fprintf(stderr, "check_file() == -1\n");
290         goto on_error;
291     }
292
293     /* success */
294     error = 0;
295
296 on_error:
297     unmap_file(&mf);
298     return error;
299 }
300
301 int stlink_fread(stlink_t* sl, const char* path, stm32_addr_t addr, size_t size) {
302     /* read size bytes from addr to file */
303
304     int error = -1;
305     size_t off;
306
307     const int fd = open(path, O_RDWR | O_TRUNC | O_CREAT, 00700);
308     if (fd == -1) {
309         fprintf(stderr, "open(%s) == -1\n", path);
310         return -1;
311     }
312
313     /* do the copy by 1k blocks */
314     for (off = 0; off < size; off += 1024) {
315         size_t read_size = 1024;
316         if ((off + read_size) > size)
317             read_size = off + read_size;
318
319         /* round size if needed */
320         if (read_size & 3)
321             read_size = (read_size + 4) & ~(3);
322
323         stlink_read_mem32(sl, addr + off, read_size);
324
325         if (write(fd, sl->q_buf, read_size) != (ssize_t) read_size) {
326             fprintf(stderr, "write() != read_size\n");
327             goto on_error;
328         }
329     }
330
331     /* success */
332     error = 0;
333
334 on_error:
335     close(fd);
336
337     return error;
338 }
339
340 typedef struct flash_loader {
341     stm32_addr_t loader_addr; /* loader sram adddr */
342     stm32_addr_t buf_addr; /* buffer sram address */
343 } flash_loader_t;
344
345 int write_buffer_to_sram
346 (stlink_t *sl, flash_loader_t* fl, const uint8_t* buf, size_t size) {
347     /* write the buffer right after the loader */
348     memcpy(sl->q_buf, buf, size);
349     stlink_write_mem8(sl, fl->buf_addr, size);
350     return 0;
351 }