diff --git a/flashloaders/Makefile b/flashloaders/Makefile index 7b17cb2a0..d4ca4d22a 100644 --- a/flashloaders/Makefile +++ b/flashloaders/Makefile @@ -1,38 +1,38 @@ -# Note that according to the original GPLed code, compiling is noted to be -# as simple as gcc -c, this fails with my tests where this will lead to a wrong -# address read by the program. -# This makefile will save your time from dealing with compile errors -# Adjust CC if needed +# The flash loader code cannot be compiled by the system gcc. This +# makefile use arm-none-eabi-gcc for this purpose -CC = /opt/local/gcc-arm-none-eabi-8-2018-q4-major/bin/arm-none-eabi-gcc +CROSS_COMPILE ?= arm-none-eabi- -CFLAGS_thumb1 = -mcpu=Cortex-M0 -Tlinker.ld -ffreestanding -nostdlib -CFLAGS_thumb2 = -mcpu=Cortex-M3 -Tlinker.ld -ffreestanding -nostdlib +CC = $(CROSS_COMPILE)gcc +OBJCOPY = $(CROSS_COMPILE)objcopy -all: stm32vl.o stm32f0.o stm32l.o stm32f4.o stm32f4_lv.o stm32l4.o stm32f7.o stm32f7_lv.o +XXD = xxd +XXDFLAGS = -i -c 4 -stm32vl.o: stm32f0.s - $(CC) stm32f0.s $(CFLAGS_thumb2) -o stm32vl.o -stm32f0.o: stm32f0.s - $(CC) stm32f0.s $(CFLAGS_thumb1) -o stm32f0.o -stm32l.o: stm32lx.s - $(CC) stm32lx.s $(CFLAGS_thumb2) -o stm32l.o -stm32f4.o: stm32f4.s - $(CC) stm32f4.s $(CFLAGS_thumb2) -o stm32f4.o -stm32f4_lv.o: stm32f4lv.s - $(CC) stm32f4lv.s $(CFLAGS_thumb2) -o stm32f4_lv.o -stm32l4.o: stm32l4.s - $(CC) stm32l4.s $(CFLAGS_thumb2) -o stm32l4.o -stm32f7.o: stm32f7.s - $(CC) stm32f7.s $(CFLAGS_thumb2) -o stm32f7.o -stm32f7_lv.o: stm32f7lv.s - $(CC) stm32f7lv.s $(CFLAGS_thumb2) -o stm32f7_lv.o +CFLAGS_ARMV6_M = -mcpu=Cortex-M0 -Tlinker.ld -ffreestanding -nostdlib +CFLAGS_ARMV7_M = -mcpu=Cortex-M3 -Tlinker.ld -ffreestanding -nostdlib -clean: - rm *.o +all: stm32vl.h stm32f0.h stm32lx.h stm32f4.h stm32f4lv.h stm32l4.h stm32f7.h stm32f7lv.h + +%.h: %.bin + $(XXD) $(XXDFLAGS) $< $@ +%.bin: %.o + $(OBJCOPY) -O binary $< $@ + rm $< +# separate rule for STM32F0 +stm32f0.o: stm32f0.s + $(CC) stm32f0.s $(CFLAGS_ARMV6_M) -o stm32f0.o +# separate rule for STM32F1/F3 +stm32vl.o: stm32f0.s + $(CC) stm32f0.s $(CFLAGS_ARMV7_M) -o stm32vl.o +# generic rule for all other ARMv7-M +%.o: *.s + $(CC) $< $(CFLAGS_ARMV7_M) -o $@ +clean: + rm -f *.h diff --git a/flashloaders/cleanroom.md b/flashloaders/cleanroom.md index a468efe49..b2cb9f00d 100644 --- a/flashloaders/cleanroom.md +++ b/flashloaders/cleanroom.md @@ -1,6 +1,4 @@ -Original Chinese version can be found below. - -# Clean Room Documentation English Version +# Flash Loader Documentation Code is situated in section `.text` @@ -12,11 +10,12 @@ All parameters would be passed over registers `r0`: the base address of the copy source `r1`: the base address of the copy destination -`r2`: the total word (4 bytes) count to be copied (with expeptions) +`r2`: the count of byte to be copied +`r3`: flash register offset (used to support two banks) **What the program is expected to do**: -Copy data from source to destination, after which trigger a breakpint to exit. Before exit, `r2` must be cleared to zero to indicate that the copy is done. +Copy data from source to destination, after which trigger a breakpint to exit. Before exit, `r2` must be less or equal to zero to indicate that the copy is done. **Limitation**: No stack operations are permitted. Registers ranging from `r3` to `r12` are free to use. Note that `r13` is `sp`(stack pointer), `r14` is `lr`(commonly used to store jump address), `r15` is `pc`(program counter). @@ -24,8 +23,6 @@ Copy data from source to destination, after which trigger a breakpint to exit. B ## stm32f0.s -**Exception**: `r2` stores the total half word (2 bytes) count to be copied - `flash_base`: 0x40022000 `FLASH_CR`: offset from `flash_base` is 16 @@ -37,11 +34,11 @@ Copy data from source to destination, after which trigger a breakpint to exit. B **Special requirements**: -Before every copy, read a word from FLASH_CR, set the lowest bit to 1 and write back. Copy one half word each time. +Before every copy, read a word from FLASH_CR, set the PG bit to 1 and write back. Copy one half word each time. -How to wait for the write process: read a word from FLASH_SR, loop until the content is not 1. After that, check FLASH_SR, proceed if the content is 4, otherwise exit. +How to wait for the write process: read a word from FLASH_SR, loop until the busy bit is reset. After that, FLASH_SR is check. The process is interrupted if the error bit (0x04) is set. -Exit: after the copying process and before triggering the breakpoint, clear the lowest bit in FLASH_CR. +Exit: after the copying process and before triggering the breakpoint, clear the PG bit in FLASH_CR. ## stm32f4.s @@ -56,7 +53,8 @@ Exit: after the copying process and before triggering the breakpoint, clear the **Special requirements**: Copy one word each time. -How to wait for the write process: read a half word from FLASH_SR, loop until the content is not 1. + +How to wait for the write process: read a word from FLASH_SR, loop until the busy bit is reset. ## stm32f4lv.s @@ -71,7 +69,7 @@ How to wait for the write process: read a half word from FLASH_SR, loop until th Copy one byte each time. -How to wait from the write process: read a half word from FLASH_SR, loop until the content is not 1. +How to wait from the write process: read a half word from FLASH_SR, loop until the busy bit is reset. ## stm32f7.s @@ -89,7 +87,7 @@ Mostly same with `stm32f4.s`. Require establishing a memory barrier after every Mostly same with `stm32f7.s`. Copy one byte each time. -## stm32l0x.s +## stm32lx.s **Special Requirements**: @@ -97,8 +95,6 @@ Copy one word each time. No wait for write. ## stm32l4.s -**Exception**: r2 stores the double word count to be copied. - `flash_base`: 0x40022000 `FLASH_BSY`: offset from `flash_base` is 0x12 @@ -109,14 +105,10 @@ Copy one word each time. No wait for write. Copy one double word each time (More than one registers are allowed). -How to wait for the write process: read a half word from `FLASH_BSY`, loop until the lowest bit turns non-1. - -## stm32lx.s +How to wait for the write process: read a half word from `FLASH_BSY`, loop until the busy bit is reset. -Same with stm32l0x.s. - -# 净室工程文档-原始中文版 +# 净室工程文档-原始中文版 (out of date) 代码位于的section:`.text` 编译制导添加`.syntax unified` @@ -139,8 +131,6 @@ Same with stm32l0x.s. ## stm32f0.s -例外:`r2`:拷贝half word(2字节)数 - 特殊地址定义:`flash_base`:定义为0x40022000 `FLASH_CR`: 相对`flash_base`的offset为16 @@ -230,4 +220,4 @@ Same with stm32l0x.s. ## stm32lx.s -要求与stm32l0x.s相同 \ No newline at end of file +要求与stm32l0x.s相同 diff --git a/flashloaders/stm32f0.s b/flashloaders/stm32f0.s index f30e4bfc6..e2a4b0f00 100644 --- a/flashloaders/stm32f0.s +++ b/flashloaders/stm32f0.s @@ -1,6 +1,14 @@ .syntax unified .text + /* + * Arguments: + * r0 - source memory ptr + * r1 - target memory ptr + * r2 - count of bytes + * r3 - flash register offset + */ + .global copy copy: /* @@ -17,54 +25,56 @@ copy: */ nop nop - ldr r7, =flash_base - ldr r4, [r7] - ldr r7, =flash_off_cr - ldr r6, [r7] - adds r6, r6, r4 - ldr r7, =flash_off_sr - ldr r5, [r7] - adds r5, r5, r4 -loop: - # FLASH_CR ^= 1 + # load flash control register address + # add r3 to flash_base for support dual bank (see flash_loader.c) + ldr r7, flash_base + add r7, r7, r3 + ldr r6, flash_off_cr + add r6, r6, r7 + ldr r5, flash_off_sr + add r5, r5, r7 + + # FLASH_CR |= 0x01 (set PG) ldr r7, =0x1 - ldr r3, [r6] - orrs r3, r3, r7 - str r3, [r6] + ldr r4, [r6] + orrs r4, r4, r7 + str r4, [r6] +loop: # copy 2 bytes - ldrh r3, [r0] - strh r3, [r1] + ldrh r4, [r0] + strh r4, [r1] - ldr r7, =2 - adds r0, r0, r7 - adds r1, r1, r7 + # increment address + adds r0, r0, #0x2 + adds r1, r1, #0x2 - # wait if FLASH_SR == 1 + # BUSY flag + ldr r7, =0x01 wait: - ldr r7, =0x1 - ldr r3, [r5] - tst r3, r7 - beq wait + # get FLASH_SR + ldr r4, [r5] - # exit if FLASH_SR != 4 - ldr r7, =0x4 - tst r3, r7 + # wait until BUSY flag is reset + tst r4, r7 + bne wait + + # test PGERR or WRPRTERR flag is reset + ldr r7, =0x14 + tst r4, r7 bne exit - # loop if r2 != 0 - ldr r7, =0x1 - subs r2, r2, r7 - cmp r2, #0 - bne loop + # loop if count > 0 + subs r2, r2, #0x2 + bgt loop exit: # FLASH_CR &= ~1 ldr r7, =0x1 - ldr r3, [r6] - bics r3, r3, r7 - str r3, [r6] + ldr r4, [r6] + bics r4, r4, r7 + str r4, [r6] bkpt diff --git a/flashloaders/stm32f4.s b/flashloaders/stm32f4.s index a88ad9e02..a66c70dac 100644 --- a/flashloaders/stm32f4.s +++ b/flashloaders/stm32f4.s @@ -1,6 +1,14 @@ .syntax unified .text + /* + * Arguments: + * r0 - source memory ptr + * r1 - target memory ptr + * r2 - count of bytes + * r3 - flash register offset + */ + .global copy copy: ldr r12, flash_base @@ -9,22 +17,24 @@ copy: loop: # copy 4 bytes - ldr r3, [r0] - str r3, [r1] + ldr r4, [r0] + str r4, [r1] + # increment address add r0, r0, #4 add r1, r1, #4 - # wait if FLASH_SR == 1 wait: - ldrh r3, [r10] - tst r3, #0x1 - beq wait - - # loop if r2 != 0 - sub r2, r2, #1 - cmp r2, #0 - bne loop + # get FLASH_SR + ldrh r4, [r10] + + # wait until BUSY flag is reset + tst r4, #0x1 + bne wait + + # loop if count > 0 + subs r2, r2, #4 + bgt loop exit: bkpt diff --git a/flashloaders/stm32f4lv.s b/flashloaders/stm32f4lv.s index 41467a9ef..b8fcfa048 100644 --- a/flashloaders/stm32f4lv.s +++ b/flashloaders/stm32f4lv.s @@ -1,36 +1,40 @@ .syntax unified .text + /* + * Arguments: + * r0 - source memory ptr + * r1 - target memory ptr + * r2 - count of bytes + * r3 - flash register offset + */ + .global copy copy: ldr r12, flash_base ldr r10, flash_off_sr add r10, r10, r12 - # tip 1: original r2 indicates the count of 4 bytes need to copy, - # but we can only copy one byte each time. - # as we have no flash larger than 1GB, we do a little trick here. - # tip 2: r2 is always a power of 2 - mov r2, r2, lsl#2 - loop: # copy 1 byte - ldrb r3, [r0] - strb r3, [r1] + ldrb r4, [r0] + strb r4, [r1] + # increment address add r0, r0, #1 add r1, r1, #1 - # wait if FLASH_SR == 1 wait: - ldrh r3, [r10] - tst r3, #0x1 - beq wait - - # loop if r2 != 0 - sub r2, r2, #1 - cmp r2, #0 - bne loop + # get FLASH_SR + ldrh r4, [r10] + + # wait until BUSY flag is reset + tst r4, #0x1 + bne wait + + # loop if count > 0 + subs r2, r2, #1 + bgt loop exit: bkpt diff --git a/flashloaders/stm32f7.s b/flashloaders/stm32f7.s index 3779a5ea6..4b43cebdc 100644 --- a/flashloaders/stm32f7.s +++ b/flashloaders/stm32f7.s @@ -1,6 +1,14 @@ .syntax unified .text + /* + * Arguments: + * r0 - source memory ptr + * r1 - target memory ptr + * r2 - count of bytes + * r3 - flash register offset + */ + .global copy copy: ldr r12, flash_base @@ -9,25 +17,27 @@ copy: loop: # copy 4 bytes - ldr r3, [r0] - str r3, [r1] + ldr r4, [r0] + str r4, [r1] + # increment address add r0, r0, #4 add r1, r1, #4 # memory barrier dsb sy - # wait if FLASH_SR == 1 wait: - ldrh r3, [r10] - tst r3, #0x1 - beq wait - - # loop if r2 != 0 - sub r2, r2, #1 - cmp r2, #0 - bne loop + # get FLASH_SR + ldrh r4, [r10] + + # wait until BUSY flag is reset + tst r4, #0x1 + bne wait + + # loop if count > 0 + subs r2, r2, #4 + bgt loop exit: bkpt diff --git a/flashloaders/stm32f7lv.s b/flashloaders/stm32f7lv.s index e7b66cc2c..78ff35dbc 100644 --- a/flashloaders/stm32f7lv.s +++ b/flashloaders/stm32f7lv.s @@ -1,39 +1,43 @@ .syntax unified .text + /* + * Arguments: + * r0 - source memory ptr + * r1 - target memory ptr + * r2 - count of bytes + * r3 - flash register offset + */ + .global copy copy: ldr r12, flash_base ldr r10, flash_off_sr add r10, r10, r12 - # tip 1: original r2 indicates the count in 4 bytes need to copy, - # but we can only copy one byte each time. - # as we have no flash larger than 1GB, we do a little trick here. - # tip 2: r2 is always a power of 2 - mov r2, r2, lsl#2 - loop: # copy 1 byte - ldrb r3, [r0] - strb r3, [r1] + ldrb r4, [r0] + strb r4, [r1] + # increment address add r0, r0, #1 add r1, r1, #1 # memory barrier dsb sy - # wait if FLASH_SR == 1 wait: - ldrh r3, [r10] - tst r3, #0x1 - beq wait - - # loop if r2 != 0 - sub r2, r2, #1 - cmp r2, #0 - bne loop + # get FLASH_SR + ldrh r4, [r10] + + # wait until BUSY flag is reset + tst r4, #0x1 + bne wait + + # loop if count > 0 + subs r2, r2, #1 + bgt loop exit: bkpt diff --git a/flashloaders/stm32l0x.s b/flashloaders/stm32l0x.s deleted file mode 100644 index f9c257e2e..000000000 --- a/flashloaders/stm32l0x.s +++ /dev/null @@ -1,22 +0,0 @@ - .syntax unified - .text - - .global copy -copy: -loop: - # copy 4 bytes - ldr r3, [r0] - str r3, [r1] - - ldr r7, =4 - add r0, r0, r7 - add r1, r1, r7 - - # loop if r2 != 0 - ldr r7, =1 - subs r2, r2, r7 - cmp r2, #0 - bne loop - -exit: - bkpt diff --git a/flashloaders/stm32l4.s b/flashloaders/stm32l4.s index 32c27a057..21e926f49 100644 --- a/flashloaders/stm32l4.s +++ b/flashloaders/stm32l4.s @@ -1,6 +1,14 @@ .syntax unified .text + /* + * Arguments: + * r0 - source memory ptr + * r1 - target memory ptr + * r2 - count of bytes + * r3 - flash register offset + */ + .global copy copy: ldr r12, flash_base @@ -9,24 +17,26 @@ copy: loop: # copy 8 bytes - ldr r3, [r0] + ldr r5, [r0] ldr r4, [r0, #4] - str r3, [r1] + str r5, [r1] str r4, [r1, #4] + # increment address add r0, r0, #8 add r1, r1, #8 - # wait if FLASH_BSY[0b] == 1 wait: - ldrh r3, [r10] - tst r3, #0x1 - beq wait - - # loop if r2 != 0 - sub r2, r2, #1 - cmp r2, #0 - bne loop + # get FLASH_SR + ldr r4, [r10] + + # wait until BUSY flag is reset + tst r4, #0x10000 + bne wait + + # loop if count > 0 + subs r2, r2, #8 + bgt loop exit: bkpt diff --git a/flashloaders/stm32lx.s b/flashloaders/stm32lx.s index f9c257e2e..69acdea7b 100644 --- a/flashloaders/stm32lx.s +++ b/flashloaders/stm32lx.s @@ -1,22 +1,28 @@ .syntax unified .text + /* + * Arguments: + * r0 - source memory ptr + * r1 - target memory ptr + * r2 - count of bytes + * r3 - flash register offset + */ + .global copy copy: loop: # copy 4 bytes - ldr r3, [r0] - str r3, [r1] + ldr r4, [r0] + str r4, [r1] - ldr r7, =4 - add r0, r0, r7 - add r1, r1, r7 + # increment address + add r0, r0, #4 + add r1, r1, #4 - # loop if r2 != 0 - ldr r7, =1 - subs r2, r2, r7 - cmp r2, #0 - bne loop + # loop if count > 0 + subs r2, r2, #4 + bgt loop exit: bkpt diff --git a/src/common.c b/src/common.c index 99049196d..1fd023962 100644 --- a/src/common.c +++ b/src/common.c @@ -2730,6 +2730,17 @@ int stm32l1_write_half_pages( } int stlink_flashloader_start(stlink_t *sl, flash_loader_t *fl) { + + // According to DDI0419C, Table C1-7 firstly force halt + stlink_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY | + STLINK_REG_DHCSR_C_DEBUGEN | + STLINK_REG_DHCSR_C_HALT); + // and only then disable interrupts + stlink_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY | + STLINK_REG_DHCSR_C_DEBUGEN | + STLINK_REG_DHCSR_C_HALT | + STLINK_REG_DHCSR_C_MASKINTS); + if ((sl->flash_type == STLINK_FLASH_TYPE_F4) || (sl->flash_type == STLINK_FLASH_TYPE_F7) || (sl->flash_type == STLINK_FLASH_TYPE_L4)) { @@ -2998,6 +3009,8 @@ int stlink_flashloader_write(stlink_t *sl, flash_loader_t *fl, stm32_addr_t addr } int stlink_flashloader_stop(stlink_t *sl) { + uint32_t dhcsr; + if ((sl->flash_type == STLINK_FLASH_TYPE_F4) || (sl->flash_type == STLINK_FLASH_TYPE_F7) || (sl->flash_type == STLINK_FLASH_TYPE_L4) || @@ -3028,6 +3041,13 @@ int stlink_flashloader_stop(stlink_t *sl) { stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val); } + // enable interrupt + if (!stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr)) { + stlink_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY | + STLINK_REG_DHCSR_C_DEBUGEN | + (dhcsr&(~STLINK_REG_DHCSR_C_MASKINTS))); + } + return(0); } diff --git a/src/stlink-lib/flash_loader.c b/src/stlink-lib/flash_loader.c index b55953406..9fa897ccc 100644 --- a/src/stlink-lib/flash_loader.c +++ b/src/stlink-lib/flash_loader.c @@ -3,6 +3,7 @@ #include #include +#include #include "flash_loader.h" #define FLASH_REGS_BANK2_OFS 0x40 @@ -12,89 +13,72 @@ /* flashloaders/stm32f0.s -- compiled with thumb2 */ static const uint8_t loader_code_stm32vl[] = { - 0x16, 0x4f, 0x3c, 0x68, - 0x16, 0x4f, 0x3e, 0x68, - 0x36, 0x19, 0x16, 0x4f, - 0x3d, 0x68, 0x2d, 0x19, + 0x00, 0xbf, 0x00, 0xbf, + 0x0f, 0x4f, 0x1f, 0x44, + 0x0f, 0x4e, 0x3e, 0x44, + 0x0f, 0x4d, 0x3d, 0x44, 0x4f, 0xf0, 0x01, 0x07, - 0x33, 0x68, 0x3b, 0x43, - 0x33, 0x60, 0x03, 0x88, - 0x0b, 0x80, 0x4f, 0xf0, - 0x02, 0x07, 0xc0, 0x19, - 0xc9, 0x19, 0x4f, 0xf0, - 0x01, 0x07, 0x2b, 0x68, - 0x3b, 0x42, 0xfa, 0xd0, - 0x4f, 0xf0, 0x04, 0x07, - 0x3b, 0x42, 0x04, 0xd1, + 0x34, 0x68, 0x3c, 0x43, + 0x34, 0x60, 0x04, 0x88, + 0x0c, 0x80, 0x02, 0x30, + 0x02, 0x31, 0x4f, 0xf0, + 0x01, 0x07, 0x2c, 0x68, + 0x3c, 0x42, 0xfc, 0xd1, + 0x4f, 0xf0, 0x14, 0x07, + 0x3c, 0x42, 0x01, 0xd1, + 0x02, 0x3a, 0xf0, 0xdc, 0x4f, 0xf0, 0x01, 0x07, - 0xd2, 0x1b, 0x00, 0x2a, - 0xe6, 0xd1, 0x4f, 0xf0, - 0x01, 0x07, 0x33, 0x68, - 0xbb, 0x43, 0x33, 0x60, - 0x00, 0xbe, 0x00, 0xbf, + 0x34, 0x68, 0xbc, 0x43, + 0x34, 0x60, 0x00, 0xbe, 0x00, 0x20, 0x02, 0x40, 0x10, 0x00, 0x00, 0x00, - 0x0c, 0x00, 0x00, 0x00, - 0x50, 0x00, 0x00, 0x20, - 0x54, 0x00, 0x00, 0x20, - 0x58, 0x00, 0x00, 0x20 + 0x0c, 0x00, 0x00, 0x00 }; /* flashloaders/stm32f0.s -- thumb1 only, same sequence as for STM32VL, bank ignored */ static const uint8_t loader_code_stm32f0[] = { 0xc0, 0x46, 0xc0, 0x46, - 0x13, 0x4f, 0x3c, 0x68, - 0x13, 0x4f, 0x3e, 0x68, - 0x36, 0x19, 0x13, 0x4f, - 0x3d, 0x68, 0x2d, 0x19, - 0x12, 0x4f, 0x33, 0x68, - 0x3b, 0x43, 0x33, 0x60, - 0x03, 0x88, 0x0b, 0x80, - 0x10, 0x4f, 0xc0, 0x19, - 0xc9, 0x19, 0x0e, 0x4f, - 0x2b, 0x68, 0x3b, 0x42, - 0xfb, 0xd0, 0x0e, 0x4f, - 0x3b, 0x42, 0x03, 0xd1, - 0x0a, 0x4f, 0xd2, 0x1b, - 0x00, 0x2a, 0xeb, 0xd1, - 0x08, 0x4f, 0x33, 0x68, - 0xbb, 0x43, 0x33, 0x60, - 0x00, 0xbe, 0xc0, 0x46, + 0x0d, 0x4f, 0x1f, 0x44, + 0x0d, 0x4e, 0x3e, 0x44, + 0x0d, 0x4d, 0x3d, 0x44, + 0x0d, 0x4f, 0x34, 0x68, + 0x3c, 0x43, 0x34, 0x60, + 0x04, 0x88, 0x0c, 0x80, + 0x02, 0x30, 0x02, 0x31, + 0x09, 0x4f, 0x2c, 0x68, + 0x3c, 0x42, 0xfc, 0xd1, + 0x08, 0x4f, 0x3c, 0x42, + 0x01, 0xd1, 0x02, 0x3a, + 0xf2, 0xdc, 0x05, 0x4f, + 0x34, 0x68, 0xbc, 0x43, + 0x34, 0x60, 0x00, 0xbe, 0x00, 0x20, 0x02, 0x40, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x00, 0x20, - 0x4c, 0x00, 0x00, 0x20, - 0x50, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00 + 0x14, 0x00, 0x00, 0x00 }; -static const uint8_t loader_code_stm32l[] = { +static const uint8_t loader_code_stm32lx[] = { // flashloaders/stm32lx.s - - 0x03, 0x68, 0x0b, 0x60, - 0x4f, 0xf0, 0x04, 0x07, - 0x38, 0x44, 0x39, 0x44, - 0x4f, 0xf0, 0x01, 0x07, - 0xd2, 0x1b, 0x00, 0x2a, - 0xf4, 0xd1, 0x00, 0xbe, + 0x04, 0x68, 0x0c, 0x60, + 0x00, 0xf1, 0x04, 0x00, + 0x01, 0xf1, 0x04, 0x01, + 0x04, 0x3a, 0xf7, 0xdc, + 0x00, 0xbe }; static const uint8_t loader_code_stm32f4[] = { // flashloaders/stm32f4.s - - 0xdf, 0xf8, 0x28, 0xc0, - 0xdf, 0xf8, 0x28, 0xa0, - 0xe2, 0x44, 0x03, 0x68, - 0x0b, 0x60, 0x00, 0xf1, + 0xdf, 0xf8, 0x24, 0xc0, + 0xdf, 0xf8, 0x24, 0xa0, + 0xe2, 0x44, 0x04, 0x68, + 0x0c, 0x60, 0x00, 0xf1, 0x04, 0x00, 0x01, 0xf1, 0x04, 0x01, 0xba, 0xf8, - 0x00, 0x30, 0x13, 0xf0, - 0x01, 0x0f, 0xfa, 0xd0, - 0xa2, 0xf1, 0x01, 0x02, - 0x00, 0x2a, 0xf0, 0xd1, + 0x00, 0x40, 0x14, 0xf0, + 0x01, 0x0f, 0xfa, 0xd1, + 0x04, 0x3a, 0xf2, 0xdc, 0x00, 0xbe, 0x00, 0xbf, 0x00, 0x3c, 0x02, 0x40, 0x0e, 0x00, 0x00, 0x00 @@ -102,17 +86,15 @@ static const uint8_t loader_code_stm32f4[] = { static const uint8_t loader_code_stm32f4_lv[] = { // flashloaders/stm32f4lv.s - 0xdf, 0xf8, 0x2c, 0xc0, - 0xdf, 0xf8, 0x2c, 0xa0, - 0xe2, 0x44, 0x4f, 0xea, - 0x82, 0x02, 0x03, 0x78, - 0x0b, 0x70, 0x00, 0xf1, + 0xdf, 0xf8, 0x24, 0xc0, + 0xdf, 0xf8, 0x24, 0xa0, + 0xe2, 0x44, 0x04, 0x78, + 0x0c, 0x70, 0x00, 0xf1, 0x01, 0x00, 0x01, 0xf1, 0x01, 0x01, 0xba, 0xf8, - 0x00, 0x30, 0x13, 0xf0, - 0x01, 0x0f, 0xfa, 0xd0, - 0xa2, 0xf1, 0x01, 0x02, - 0x00, 0x2a, 0xf0, 0xd1, + 0x00, 0x40, 0x14, 0xf0, + 0x01, 0x0f, 0xfa, 0xd1, + 0x01, 0x3a, 0xf2, 0xdc, 0x00, 0xbe, 0x00, 0xbf, 0x00, 0x3c, 0x02, 0x40, 0x0e, 0x00, 0x00, 0x00 @@ -120,17 +102,16 @@ static const uint8_t loader_code_stm32f4_lv[] = { static const uint8_t loader_code_stm32l4[] = { // flashloaders/stm32l4.s - 0xdf, 0xf8, 0x2c, 0xc0, - 0xdf, 0xf8, 0x2c, 0xa0, - 0xe2, 0x44, 0x03, 0x68, - 0x44, 0x68, 0x0b, 0x60, + 0xdf, 0xf8, 0x28, 0xc0, + 0xdf, 0xf8, 0x28, 0xa0, + 0xe2, 0x44, 0x05, 0x68, + 0x44, 0x68, 0x0d, 0x60, 0x4c, 0x60, 0x00, 0xf1, 0x08, 0x00, 0x01, 0xf1, - 0x08, 0x01, 0xba, 0xf8, - 0x00, 0x30, 0x13, 0xf0, - 0x01, 0x0f, 0xfa, 0xd0, - 0xa2, 0xf1, 0x01, 0x02, - 0x00, 0x2a, 0xee, 0xd1, + 0x08, 0x01, 0xda, 0xf8, + 0x00, 0x40, 0x14, 0xf4, + 0x80, 0x3f, 0xfa, 0xd1, + 0x08, 0x3a, 0xf0, 0xdc, 0x00, 0xbe, 0x00, 0xbf, 0x00, 0x20, 0x02, 0x40, 0x12, 0x00, 0x00, 0x00 @@ -138,17 +119,16 @@ static const uint8_t loader_code_stm32l4[] = { static const uint8_t loader_code_stm32f7[] = { // flashloaders/stm32f7.s - 0xdf, 0xf8, 0x2c, 0xc0, - 0xdf, 0xf8, 0x2c, 0xa0, - 0xe2, 0x44, 0x03, 0x68, - 0x0b, 0x60, 0x00, 0xf1, + 0xdf, 0xf8, 0x28, 0xc0, + 0xdf, 0xf8, 0x28, 0xa0, + 0xe2, 0x44, 0x04, 0x68, + 0x0c, 0x60, 0x00, 0xf1, 0x04, 0x00, 0x01, 0xf1, 0x04, 0x01, 0xbf, 0xf3, 0x4f, 0x8f, 0xba, 0xf8, - 0x00, 0x30, 0x13, 0xf0, - 0x01, 0x0f, 0xfa, 0xd0, - 0xa2, 0xf1, 0x01, 0x02, - 0x00, 0x2a, 0xee, 0xd1, + 0x00, 0x40, 0x14, 0xf0, + 0x01, 0x0f, 0xfa, 0xd1, + 0x04, 0x3a, 0xf0, 0xdc, 0x00, 0xbe, 0x00, 0xbf, 0x00, 0x3c, 0x02, 0x40, 0x0e, 0x00, 0x00, 0x00 @@ -156,18 +136,16 @@ static const uint8_t loader_code_stm32f7[] = { static const uint8_t loader_code_stm32f7_lv[] = { // flashloaders/stm32f7lv.s - 0xdf, 0xf8, 0x30, 0xc0, - 0xdf, 0xf8, 0x30, 0xa0, - 0xe2, 0x44, 0x4f, 0xea, - 0x82, 0x02, 0x03, 0x78, - 0x0b, 0x70, 0x00, 0xf1, + 0xdf, 0xf8, 0x28, 0xc0, + 0xdf, 0xf8, 0x28, 0xa0, + 0xe2, 0x44, 0x04, 0x78, + 0x0c, 0x70, 0x00, 0xf1, 0x01, 0x00, 0x01, 0xf1, 0x01, 0x01, 0xbf, 0xf3, 0x4f, 0x8f, 0xba, 0xf8, - 0x00, 0x30, 0x13, 0xf0, - 0x01, 0x0f, 0xfa, 0xd0, - 0xa2, 0xf1, 0x01, 0x02, - 0x00, 0x2a, 0xee, 0xd1, + 0x00, 0x40, 0x14, 0xf0, + 0x01, 0x0f, 0xfa, 0xd1, + 0x01, 0x3a, 0xf0, 0xdc, 0x00, 0xbe, 0x00, 0xbf, 0x00, 0x3c, 0x02, 0x40, 0x0e, 0x00, 0x00, 0x00 @@ -233,8 +211,8 @@ int stlink_flash_loader_write_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* sl->chip_id == STLINK_CHIPID_STM32_L0 || sl->chip_id == STLINK_CHIPID_STM32_L0_CAT5 || sl->chip_id == STLINK_CHIPID_STM32_L0_CAT2) { // STM32l - loader_code = loader_code_stm32l; - loader_size = sizeof(loader_code_stm32l); + loader_code = loader_code_stm32lx; + loader_size = sizeof(loader_code_stm32lx); } else if (sl->core_id == STM32VL_CORE_ID || sl->chip_id == STLINK_CHIPID_STM32_F1_MEDIUM || sl->chip_id == STLINK_CHIPID_STM32_F1_HIGH || @@ -313,11 +291,9 @@ int stlink_flash_loader_write_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, const uint8_t* buf, size_t size) { struct stlink_reg rr; - int i = 0; - size_t count = 0; + unsigned timeout; uint32_t flash_base = 0; - const char *error = NULL; - uint32_t dhcsr, dfsr; + uint32_t dhcsr, dfsr, cfsr, hfsr; DLOG("Running flash loader, write address:%#x, size: %u\n", target, (unsigned int)size); @@ -328,22 +304,6 @@ int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t targe return(-1); } - if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || - (sl->flash_type == STLINK_FLASH_TYPE_F1_XL)) { - count = size / sizeof(uint16_t); - - if (size % sizeof(uint16_t)) { ++count; } - } else if (sl->flash_type == STLINK_FLASH_TYPE_F4 || - sl->flash_type == STLINK_FLASH_TYPE_L0) { - count = size / sizeof(uint32_t); - - if (size % sizeof(uint32_t)) { ++count; } - } else if (sl->flash_type == STLINK_FLASH_TYPE_L4) { - count = size / sizeof(uint64_t); - - if (size % sizeof(uint64_t)) { ++count; } - } - if ((sl->flash_type == STLINK_FLASH_TYPE_F1_XL) && (target >= FLASH_BANK2_START_ADDR)) { flash_base = FLASH_REGS_BANK2_OFS; } @@ -351,7 +311,7 @@ int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t targe /* Setup core */ stlink_write_reg(sl, fl->buf_addr, 0); // source stlink_write_reg(sl, target, 1); // target - stlink_write_reg(sl, (uint32_t)count, 2); // count + stlink_write_reg(sl, (uint32_t)size, 2); // count stlink_write_reg(sl, flash_base, 3); // flash register base // only used on VL/F1_XL, but harmless for others stlink_write_reg(sl, fl->loader_addr, 15); // pc register @@ -368,17 +328,20 @@ int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t targe * the OS uses, the wait until the error message is reduced to the same order of magnitude * as what was intended. -- REW. */ -#define WAIT_ROUNDS 40 // wait until done (reaches breakpoint) - for (i = 0; i < WAIT_ROUNDS; i++) { + timeout = time_ms() + 500; + while (time_ms() < timeout) { usleep(10000); - if (stlink_is_core_halted(sl)) { break; } + if (stlink_is_core_halted(sl)) { + timeout = 0; + break; + } } - if (i >= WAIT_ROUNDS) { - error = "Flash loader run error"; + if (timeout) { + ELOG("Flash loader run error\n"); goto error; } @@ -386,18 +349,25 @@ int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t targe stlink_read_reg(sl, 2, &rr); if (rr.r[2] != 0) { - error = "Write error"; + ELOG("Write error\n"); goto error; } return(0); error: - dhcsr = dfsr = 0; + dhcsr = dfsr = cfsr = hfsr = 0; stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr); stlink_read_debug32(sl, STLINK_REG_DFSR, &dfsr); + stlink_read_debug32(sl, STLINK_REG_CFSR, &cfsr); + stlink_read_debug32(sl, STLINK_REG_HFSR, &hfsr); stlink_read_all_regs(sl, &rr); - ELOG("%s (R2 0x%08X R15 0x%08X DHCSR 0x%08X DFSR 0x%08X)\n", error, rr.r[2], rr.r[15], dhcsr, dfsr); + + WLOG("Loader state: R2 0x%X R15 0x%X\n", rr.r[2], rr.r[15]); + if (dhcsr != 0x3000B || dfsr != 0x3 || cfsr || hfsr) { + WLOG("MCU state: DHCSR 0x%X DFSR 0x%X CFSR 0x%X HFSR 0x%X\n", + dhcsr, dfsr, cfsr, hfsr); + } return(-1); } diff --git a/src/stlink-lib/reg.h b/src/stlink-lib/reg.h index 6d2c9f1af..473231117 100644 --- a/src/stlink-lib/reg.h +++ b/src/stlink-lib/reg.h @@ -19,6 +19,12 @@ #define STLINK_REG_CM3_DWT_FUNn(n) (0xE0001028 + n*16) /* Cortex™-M3 Technical Reference Manual */ +/* Configurable Fault Status Register */ +#define STLINK_REG_CFSR 0xE000ED28 + +/* Hard Fault Status Register */ +#define STLINK_REG_HFSR 0xE000ED2C + /* Debug Halting Control and Status Register */ #define STLINK_REG_DFSR 0xE000ED30 #define STLINK_REG_DFSR_HALT (1 << 0)