10 #include <sys/types.h>
15 #include "stlink-common.h"
17 void D(stlink_t *sl, char *txt) {
22 void DD(stlink_t *sl, char *format, ...) {
23 if (sl->verbose > 0) {
25 va_start(list, format);
26 vfprintf(stderr, format, list);
31 // Delegates to the backends...
33 void stlink_close(stlink_t *sl) {
34 D(sl, "\n*** stlink_close ***\n");
35 sl->backend->close(sl);
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);
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);
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);
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);
61 void stlink_reset(stlink_t *sl) {
62 D(sl, "\n*** stlink_reset ***\n");
63 sl->backend->reset(sl);
67 void stlink_run(stlink_t *sl) {
68 D(sl, "\n*** stlink_core_id ***\n");
70 DD(sl, "core_id = 0x%08x\n", sl->core_id);
73 void stlink_status(stlink_t *sl) {
74 D(sl, "\n*** stlink_core_id ***\n");
75 sl->backend->status(sl);
77 DD(sl, "core_id = 0x%08x\n", sl->core_id);
80 void stlink_version(stlink_t *sl) {
81 D(sl, "*** looking up stlink version\n");
82 sl->backend->version(sl);
85 void stlink_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
86 D(sl, "\n*** stlink_write_mem32 ***\n");
88 fprintf(stderr, "Error: Data length doesn't have a 32 bit alignment: +%d byte.\n", len % 4);
91 sl->backend->write_mem32(sl, addr, len);
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);
104 // End of delegates.... Common code below here...
107 // http://www.ibm.com/developerworks/aix/library/au-endianc/index.html
109 // #define is_bigendian() ( (*(char*)&i) == 0 )
111 inline unsigned int is_bigendian(void) {
112 static volatile const unsigned int i = 1;
113 return *(volatile const char*) &i == 0;
116 uint16_t read_uint16(const unsigned char *c, const int pt) {
118 char *p = (char *) &ui;
120 if (!is_bigendian()) { // le -> le (don't swap)
130 void stlink_core_stat(stlink_t *sl) {
134 stlink_print_data(sl);
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");
141 case STLINK_CORE_HALTED:
142 sl->core_stat = STLINK_CORE_HALTED;
143 DD(sl, " core status: halted\n");
146 sl->core_stat = STLINK_CORE_STAT_UNKNOWN;
147 fprintf(stderr, " core status: unknown\n");
151 void stlink_print_data(stlink_t *sl) {
152 if (sl->q_len <= 0 || sl->verbose < 2)
155 fprintf(stdout, "data_len = %d 0x%x\n", sl->q_len, sl->q_len);
157 for (int i = 0; i < sl->q_len; i++) {
160 if (sl->q_data_dir == Q_DATA_OUT)
161 fprintf(stdout, "\n<- 0x%08x ", sl->q_addr + i);
163 fprintf(stdout, "\n-> 0x%08x ", sl->q_addr + i);
166 fprintf(stdout, " %02x", (unsigned int) sl->q_buf[i]);
168 fputs("\n\n", stdout);
171 /* memory mapped file */
173 typedef struct mapped_file {
178 #define MAPPED_FILE_INITIALIZER { NULL, 0 }
180 static int map_file(mapped_file_t* mf, const char* path) {
184 const int fd = open(path, O_RDONLY);
186 fprintf(stderr, "open(%s) == -1\n", path);
190 if (fstat(fd, &st) == -1) {
191 fprintf(stderr, "fstat() == -1\n");
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");
201 mf->len = st.st_size;
212 static void unmap_file(mapped_file_t* mf) {
213 munmap((void*) mf->base, mf->len);
214 mf->base = (unsigned char*) MAP_FAILED;
218 static int check_file
219 (stlink_t* sl, mapped_file_t* mf, stm32_addr_t addr) {
222 for (off = 0; off < mf->len; off += sl->flash_pgsz) {
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;
230 aligned_size = cmp_size;
231 if (aligned_size & (4 - 1))
232 aligned_size = (cmp_size + 4) & ~(4 - 1);
234 stlink_read_mem32(sl, addr + off, aligned_size);
236 if (memcmp(sl->q_buf, mf->base + off, cmp_size))
243 int stlink_fwrite_sram
244 (stlink_t * sl, const char* path, stm32_addr_t addr) {
245 /* write the file in sram at addr */
249 mapped_file_t mf = MAPPED_FILE_INITIALIZER;
251 if (map_file(&mf, path) == -1) {
252 fprintf(stderr, "map_file() == -1\n");
256 /* check addr range is inside the sram */
257 if (addr < sl->sram_base) {
258 fprintf(stderr, "addr too low\n");
260 } else if ((addr + mf.len) < addr) {
261 fprintf(stderr, "addr overruns\n");
263 } else if ((addr + mf.len) > (sl->sram_base + sl->sram_size)) {
264 fprintf(stderr, "addr too high\n");
266 } else if ((addr & 3) || (mf.len & 3)) {
268 fprintf(stderr, "unaligned addr or size\n");
272 /* do the copy by 1k blocks */
273 for (off = 0; off < mf.len; off += 1024) {
275 if ((off + size) > mf.len)
278 memcpy(sl->q_buf, mf.base + off, size);
280 /* round size if needed */
284 stlink_write_mem32(sl, addr + off, size);
287 /* check the file ha been written */
288 if (check_file(sl, &mf, addr) == -1) {
289 fprintf(stderr, "check_file() == -1\n");
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 */
307 const int fd = open(path, O_RDWR | O_TRUNC | O_CREAT, 00700);
309 fprintf(stderr, "open(%s) == -1\n", path);
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;
319 /* round size if needed */
321 read_size = (read_size + 4) & ~(3);
323 stlink_read_mem32(sl, addr + off, read_size);
325 if (write(fd, sl->q_buf, read_size) != (ssize_t) read_size) {
326 fprintf(stderr, "write() != read_size\n");
340 typedef struct flash_loader {
341 stm32_addr_t loader_addr; /* loader sram adddr */
342 stm32_addr_t buf_addr; /* buffer sram address */
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);