3 /* from openocd, contrib/loaders/flash/stm32.s */
4 static const uint8_t loader_code_stm32vl[] = {
5 0x08, 0x4c, /* ldr r4, STM32_FLASH_BASE */
6 0x1c, 0x44, /* add r4, r3 */
8 0x01, 0x23, /* movs r3, #0x01 */
9 0x23, 0x61, /* str r3, [r4, #STM32_FLASH_CR_OFFSET] */
10 0x30, 0xf8, 0x02, 0x3b, /* ldrh r3, [r0], #0x02 */
11 0x21, 0xf8, 0x02, 0x3b, /* strh r3, [r1], #0x02 */
13 0xe3, 0x68, /* ldr r3, [r4, #STM32_FLASH_SR_OFFSET] */
14 0x13, 0xf0, 0x01, 0x0f, /* tst r3, #0x01 */
15 0xfb, 0xd0, /* beq busy */
16 0x13, 0xf0, 0x14, 0x0f, /* tst r3, #0x14 */
17 0x01, 0xd1, /* bne exit */
18 0x01, 0x3a, /* subs r2, r2, #0x01 */
19 0xf0, 0xd1, /* bne write_half_word */
21 0x00, 0xbe, /* bkpt #0x00 */
22 0x00, 0x20, 0x02, 0x40, /* STM32_FLASH_BASE: .word 0x40022000 */
25 /* flashloaders/stm32f0.s -- thumb1 only, same sequence as for STM32VL, bank ignored */
26 static const uint8_t loader_code_stm32f0[] = {
29 * These two NOPs here are a safety precaution, added by Pekka Nikander
30 * while debugging the STM32F05x support. They may not be needed, but
31 * there were strange problems with simpler programs, like a program
32 * that had just a breakpoint or a program that first moved zero to register r2
33 * and then had a breakpoint. So, it appears safest to have these two nops.
35 * Feel free to remove them, if you dare, but then please do test the result
36 * rigorously. Also, if you remove these, it may be a good idea first to
37 * #if 0 them out, with a comment when these were taken out, and to remove
38 * these only a few months later... But YMMV.
40 0x00, 0x30, // nop /* add r0,#0 */
41 0x00, 0x30, // nop /* add r0,#0 */
43 0x0A, 0x4C, // ldr r4, STM32_FLASH_BASE
44 0x01, 0x25, // mov r5, #1 /* FLASH_CR_PG, FLASH_SR_BUSY */
45 0x04, 0x26, // mov r6, #4 /* PGERR */
47 0x23, 0x69, // ldr r3, [r4, #16] /* FLASH->CR */
48 0x2B, 0x43, // orr r3, r5
49 0x23, 0x61, // str r3, [r4, #16] /* FLASH->CR |= FLASH_CR_PG */
50 0x03, 0x88, // ldrh r3, [r0] /* r3 = *sram */
51 0x0B, 0x80, // strh r3, [r1] /* *flash = r3 */
53 0xE3, 0x68, // ldr r3, [r4, #12] /* FLASH->SR */
54 0x2B, 0x42, // tst r3, r5 /* FLASH_SR_BUSY */
55 0xFC, 0xD0, // beq busy
57 0x33, 0x42, // tst r3, r6 /* PGERR */
58 0x04, 0xD1, // bne exit
60 0x02, 0x30, // add r0, r0, #2 /* sram += 2 */
61 0x02, 0x31, // add r1, r1, #2 /* flash += 2 */
62 0x01, 0x3A, // sub r2, r2, #0x01 /* count-- */
63 0x00, 0x2A, // cmp r2, #0
64 0xF0, 0xD1, // bne write_half_word
66 0x23, 0x69, // ldr r3, [r4, #16] /* FLASH->CR */
67 0xAB, 0x43, // bic r3, r5
68 0x23, 0x61, // str r3, [r4, #16] /* FLASH->CR &= ~FLASH_CR_PG */
69 0x00, 0xBE, // bkpt #0x00
70 0x00, 0x20, 0x02, 0x40, /* STM32_FLASH_BASE: .word 0x40022000 */
73 static const uint8_t loader_code_stm32l[] = {
74 // flashloaders/stm32lx.s
76 0x04, 0xe0, // b test_done ; Go to compare
78 0x04, 0x68, // ldr r4, [r0] ; Load one word from address in r0
79 0x0c, 0x60, // str r4, [r1] ; Store the word to address in r1
80 0x04, 0x30, // adds r0, #4 ; Increment r0
81 0x04, 0x31, // adds r1, #4 ; Increment r1
82 0x01, 0x3a, // subs r2, #1 ; Decrement r2
84 0x00, 0x2a, // cmp r2, #0 ; Compare r2 to 0
85 0xf8, 0xd8, // bhi write_word ; Loop if above 0
86 0x00, 0xbe, // bkpt #0x00 ; Set breakpoint to exit
90 static const uint8_t loader_code_stm32f4[] = {
91 // flashloaders/stm32f4.s
100 0x14, 0xf0, 0x01, 0x0f,
102 0x00, 0xf1, 0x04, 0x00,
103 0x01, 0xf1, 0x04, 0x01,
104 0xa2, 0xf1, 0x01, 0x02,
109 0x00, 0x3c, 0x02, 0x40,
112 static const uint8_t loader_code_stm32f4_lv[] = {
113 // flashloaders/stm32f4lv.s
122 0x14, 0xf0, 0x01, 0x0f,
124 0x00, 0xf1, 0x01, 0x00,
125 0x01, 0xf1, 0x01, 0x01,
126 0xa2, 0xf1, 0x01, 0x02,
132 0x00, 0x3c, 0x02, 0x40,
135 static const uint8_t loader_code_stm32l4[] = {
136 // flashloaders/stm32l4.s
137 0x08, 0x4b, // start: ldr r3, [pc, #32] ; <flash_base>
138 0x72, 0xb1, // next: cbz r2, <done>
139 0x04, 0x68, // ldr r4, [r0, #0]
140 0x45, 0x68, // ldr r5, [r0, #4]
141 0x0c, 0x60, // str r4, [r1, #0]
142 0x4d, 0x60, // str r5, [r1, #4]
143 0x5c, 0x8a, // wait: ldrh r4, [r3, #18]
144 0x14, 0xf0, 0x01, 0x0f, // tst.w r4, #1
145 0xfb, 0xd1, // bne.n <wait>
146 0x00, 0xf1, 0x08, 0x00, // add.w r0, r0, #8
147 0x01, 0xf1, 0x08, 0x01, // add.w r1, r1, #8
148 0xa2, 0xf1, 0x01, 0x02, // sub.w r2, r2, #1
149 0xef, 0xe7, // b.n <next>
150 0x00, 0xbe, // done: bkpt 0x0000
151 0x00, 0x20, 0x02, 0x40 // flash_base: .word 0x40022000
154 static const uint8_t loader_code_stm32f7[] = {
159 0xbf, 0xf3, 0x4f, 0x8f, // DSB Memory barrier for in order flash write
161 0x14, 0xf0, 0x01, 0x0f,
163 0x00, 0xf1, 0x04, 0x00,
164 0x01, 0xf1, 0x04, 0x01,
165 0xa2, 0xf1, 0x01, 0x02,
167 0x00, 0xbe, // bkpt #0x00
168 0x00, 0x3c, 0x02, 0x40,
173 int stlink_flash_loader_init(stlink_t *sl, flash_loader_t *fl)
177 /* allocate the loader in sram */
178 if (stlink_flash_loader_write_to_sram(sl, &fl->loader_addr, &size) == -1) {
179 WLOG("Failed to write flash loader to sram!\n");
183 /* allocate a one page buffer in sram right after loader */
184 fl->buf_addr = fl->loader_addr + size;
185 ILOG("Successfully loaded flash loader in sram\n");
190 int stlink_flash_loader_write_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size)
192 const uint8_t* loader_code;
195 if (sl->chip_id == STLINK_CHIPID_STM32_L1_MEDIUM || sl->chip_id == STLINK_CHIPID_STM32_L1_CAT2
196 || sl->chip_id == STLINK_CHIPID_STM32_L1_MEDIUM_PLUS || sl->chip_id == STLINK_CHIPID_STM32_L1_HIGH
197 || sl->chip_id == STLINK_CHIPID_STM32_L152_RE
198 || sl->chip_id == STLINK_CHIPID_STM32_L0 || sl->chip_id == STLINK_CHIPID_STM32_L0_CAT5 || sl->chip_id == STLINK_CHIPID_STM32_L0_CAT2) { /* stm32l */
199 loader_code = loader_code_stm32l;
200 loader_size = sizeof(loader_code_stm32l);
201 } else if (sl->core_id == STM32VL_CORE_ID
202 || sl->chip_id == STLINK_CHIPID_STM32_F3
203 || sl->chip_id == STLINK_CHIPID_STM32_F3_SMALL
204 || sl->chip_id == STLINK_CHIPID_STM32_F303_HIGH
205 || sl->chip_id == STLINK_CHIPID_STM32_F37x
206 || sl->chip_id == STLINK_CHIPID_STM32_F334) {
207 loader_code = loader_code_stm32vl;
208 loader_size = sizeof(loader_code_stm32vl);
209 } else if (sl->chip_id == STLINK_CHIPID_STM32_F2 ||
210 sl->chip_id == STLINK_CHIPID_STM32_F4 ||
211 sl->chip_id == STLINK_CHIPID_STM32_F4_DE ||
212 sl->chip_id == STLINK_CHIPID_STM32_F4_LP ||
213 sl->chip_id == STLINK_CHIPID_STM32_F4_HD ||
214 sl->chip_id == STLINK_CHIPID_STM32_F4_DSI ||
215 sl->chip_id == STLINK_CHIPID_STM32_F410 ||
216 sl->chip_id == STLINK_CHIPID_STM32_F411RE ||
217 sl->chip_id == STLINK_CHIPID_STM32_F446
219 int voltage = stlink_target_voltage(sl);
221 printf("Failed to read Target voltage\n");
223 } else if (voltage > 2700) {
224 loader_code = loader_code_stm32f4;
225 loader_size = sizeof(loader_code_stm32f4);
227 loader_code = loader_code_stm32f4_lv;
228 loader_size = sizeof(loader_code_stm32f4_lv);
230 } else if (sl->chip_id == STLINK_CHIPID_STM32_F7){
231 loader_code = loader_code_stm32f7;
232 loader_size = sizeof(loader_code_stm32f7);
233 } else if (sl->chip_id == STLINK_CHIPID_STM32_F0 || sl->chip_id == STLINK_CHIPID_STM32_F04 || sl->chip_id == STLINK_CHIPID_STM32_F0_CAN || sl->chip_id == STLINK_CHIPID_STM32_F0_SMALL || sl->chip_id == STLINK_CHIPID_STM32_F09X) {
234 loader_code = loader_code_stm32f0;
235 loader_size = sizeof(loader_code_stm32f0);
236 } else if (sl->chip_id == STLINK_CHIPID_STM32_L4) {
237 loader_code = loader_code_stm32l4;
238 loader_size = sizeof(loader_code_stm32l4);
240 ELOG("unknown coreid, not sure what flash loader to use, aborting!: %x\n", sl->core_id);
244 memcpy(sl->q_buf, loader_code, loader_size);
245 stlink_write_mem32(sl, sl->sram_base, loader_size);
247 *addr = sl->sram_base;
254 int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, const uint8_t* buf, size_t size)
260 DLOG("Running flash loader, write address:%#x, size: %zd\n", target, size);
261 // FIXME This can never return -1
262 if (write_buffer_to_sram(sl, fl, buf, size) == -1) {
264 ELOG("write_buffer_to_sram() == -1\n");
268 if (sl->flash_type == FLASH_TYPE_F0) {
269 count = size / sizeof(uint16_t);
270 if (size % sizeof(uint16_t))
272 } else if (sl->flash_type == FLASH_TYPE_F4 || sl->flash_type == FLASH_TYPE_L0) {
273 count = size / sizeof(uint32_t);
274 if (size % sizeof(uint32_t))
276 } else if (sl->flash_type == FLASH_TYPE_L4) {
277 count = size / sizeof(uint64_t);
278 if (size % sizeof(uint64_t))
283 stlink_write_reg(sl, fl->buf_addr, 0); /* source */
284 stlink_write_reg(sl, target, 1); /* target */
285 stlink_write_reg(sl, count, 2); /* count */
286 stlink_write_reg(sl, 0, 3); /* flash bank 0 (input), only used on F0, but armless fopr others */
287 stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */
292 #define WAIT_ROUNDS 10000
293 /* wait until done (reaches breakpoint) */
294 for (i = 0; i < WAIT_ROUNDS; i++) {
296 if (is_core_halted(sl))
300 if (i >= WAIT_ROUNDS) {
301 ELOG("flash loader run error\n");
305 /* check written byte count */
306 stlink_read_reg(sl, 2, &rr);
308 ELOG("write error, count == %u\n", rr.r[2]);