kopia lustrzana https://github.com/stlink-org/stlink
flash_loader: fix check BUSY flag, code simplified
rodzic
ebcf04f02b
commit
41bbbc2e96
|
@ -4,35 +4,60 @@
|
|||
# This makefile will save your time from dealing with compile errors
|
||||
# Adjust CC if needed
|
||||
|
||||
CC = /opt/local/gcc-arm-none-eabi-8-2018-q4-major/bin/arm-none-eabi-gcc
|
||||
CROSS_COMPILE ?= /opt/gcc-arm-none-eabi-6-2017-q2-update/bin/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_THUMB1 = -mcpu=Cortex-M0 -Tlinker.ld -ffreestanding -nostdlib
|
||||
CFLAGS_THUMB2 = -mcpu=Cortex-M3 -Tlinker.ld -ffreestanding -nostdlib
|
||||
|
||||
all: stm32vl.h stm32f0.h stm32lx.h stm32f4.h stm32f4lv.h stm32l4.h stm32f7.h stm32f7lv.h
|
||||
|
||||
stm32f0.h: stm32f0.s
|
||||
$(CC) stm32f0.s $(CFLAGS_THUMB1) -o stm32f0.o
|
||||
$(OBJCOPY) -O binary stm32f0.o stm32f0.bin
|
||||
$(XXD) $(XXDFLAGS) stm32f0.bin stm32f0.h
|
||||
|
||||
stm32vl.h: stm32f0.s
|
||||
$(CC) stm32f0.s $(CFLAGS_THUMB2) -o stm32vl.o
|
||||
$(OBJCOPY) -O binary stm32vl.o stm32vl.bin
|
||||
$(XXD) $(XXDFLAGS) stm32vl.bin stm32vl.h
|
||||
|
||||
stm32lx.h: stm32lx.s
|
||||
$(CC) stm32lx.s $(CFLAGS_THUMB2) -o stm32lx.o
|
||||
$(OBJCOPY) -O binary stm32lx.o stm32lx.bin
|
||||
$(XXD) $(XXDFLAGS) stm32lx.bin stm32lx.h
|
||||
|
||||
stm32f4.h: stm32f4.s
|
||||
$(CC) stm32f4.s $(CFLAGS_THUMB2) -o stm32f4.o
|
||||
$(OBJCOPY) -O binary stm32f4.o stm32f4.bin
|
||||
$(XXD) $(XXDFLAGS) stm32f4.bin stm32f4.h
|
||||
|
||||
stm32f4lv.h: stm32f4lv.s
|
||||
$(CC) stm32f4lv.s $(CFLAGS_THUMB2) -o stm32f4lv.o
|
||||
$(OBJCOPY) -O binary stm32f4lv.o stm32f4lv.bin
|
||||
$(XXD) $(XXDFLAGS) stm32f4lv.bin stm32f4lv.h
|
||||
|
||||
stm32l4.h: stm32l4.s
|
||||
$(CC) stm32l4.s $(CFLAGS_THUMB2) -o stm32l4.o
|
||||
$(OBJCOPY) -O binary stm32l4.o stm32l4.bin
|
||||
$(XXD) $(XXDFLAGS) stm32l4.bin stm32l4.h
|
||||
|
||||
stm32f7.h: stm32f7.s
|
||||
$(CC) stm32f7.s $(CFLAGS_THUMB2) -o stm32f7.o
|
||||
$(OBJCOPY) -O binary stm32f7.o stm32f7.bin
|
||||
$(XXD) $(XXDFLAGS) stm32f7.bin stm32f7.h
|
||||
|
||||
stm32f7lv.h: stm32f7lv.s
|
||||
$(CC) stm32f7lv.s $(CFLAGS_THUMB2) -o stm32f7lv.o
|
||||
$(OBJCOPY) -O binary stm32f7lv.o stm32f7lv.bin
|
||||
$(XXD) $(XXDFLAGS) stm32f7lv.bin stm32f7lv.h
|
||||
|
||||
clean:
|
||||
rm *.o
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
rm *.bin
|
||||
rm *.h
|
||||
|
|
|
@ -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
|
||||
|
||||
Same with stm32l0x.s.
|
||||
How to wait for the write process: read a half word from `FLASH_BSY`, loop until the busy bit is reset.
|
||||
|
||||
|
||||
# 净室工程文档-原始中文版
|
||||
# 净室工程文档-原始中文版 (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相同
|
||||
要求与stm32l0x.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
|
||||
|
||||
# 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 r4, [r6]
|
||||
orrs r4, r4, r7
|
||||
str r4, [r6]
|
||||
|
||||
loop:
|
||||
# FLASH_CR ^= 1
|
||||
ldr r7, =0x1
|
||||
ldr r3, [r6]
|
||||
orrs r3, r3, r7
|
||||
str r3, [r6]
|
||||
|
||||
# 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
|
||||
|
||||
|
|
|
@ -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
|
||||
# get FLASH_SR
|
||||
ldrh r4, [r10]
|
||||
|
||||
# loop if r2 != 0
|
||||
sub r2, r2, #1
|
||||
cmp r2, #0
|
||||
bne loop
|
||||
# wait until BUSY flag is reset
|
||||
tst r4, #0x1
|
||||
bne wait
|
||||
|
||||
# loop if count > 0
|
||||
subs r2, r2, #4
|
||||
bgt loop
|
||||
|
||||
exit:
|
||||
bkpt
|
||||
|
|
|
@ -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
|
||||
# get FLASH_SR
|
||||
ldrh r4, [r10]
|
||||
|
||||
# loop if r2 != 0
|
||||
sub r2, r2, #1
|
||||
cmp r2, #0
|
||||
bne loop
|
||||
# wait until BUSY flag is reset
|
||||
tst r4, #0x1
|
||||
bne wait
|
||||
|
||||
# loop if count > 0
|
||||
subs r2, r2, #1
|
||||
bgt loop
|
||||
|
||||
exit:
|
||||
bkpt
|
||||
|
|
|
@ -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
|
||||
# get FLASH_SR
|
||||
ldrh r4, [r10]
|
||||
|
||||
# loop if r2 != 0
|
||||
sub r2, r2, #1
|
||||
cmp r2, #0
|
||||
bne loop
|
||||
# wait until BUSY flag is reset
|
||||
tst r4, #0x1
|
||||
bne wait
|
||||
|
||||
# loop if count > 0
|
||||
subs r2, r2, #4
|
||||
bgt loop
|
||||
|
||||
exit:
|
||||
bkpt
|
||||
|
|
|
@ -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
|
||||
# get FLASH_SR
|
||||
ldrh r4, [r10]
|
||||
|
||||
# loop if r2 != 0
|
||||
sub r2, r2, #1
|
||||
cmp r2, #0
|
||||
bne loop
|
||||
# wait until BUSY flag is reset
|
||||
tst r4, #0x1
|
||||
bne wait
|
||||
|
||||
# loop if count > 0
|
||||
subs r2, r2, #1
|
||||
bgt loop
|
||||
|
||||
exit:
|
||||
bkpt
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
# get FLASH_SR
|
||||
ldr r4, [r10]
|
||||
|
||||
# loop if r2 != 0
|
||||
sub r2, r2, #1
|
||||
cmp r2, #0
|
||||
bne loop
|
||||
# wait until BUSY flag is reset
|
||||
tst r4, #0x10000
|
||||
bne wait
|
||||
|
||||
# loop if count > 0
|
||||
subs r2, r2, #8
|
||||
bgt loop
|
||||
|
||||
exit:
|
||||
bkpt
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -13,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
|
||||
|
@ -103,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
|
||||
|
@ -121,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
|
||||
|
@ -139,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
|
||||
|
@ -157,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
|
||||
|
@ -234,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 ||
|
||||
|
@ -315,10 +292,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;
|
||||
unsigned timeout;
|
||||
size_t count = 0;
|
||||
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);
|
||||
|
||||
|
@ -329,22 +305,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;
|
||||
}
|
||||
|
@ -352,7 +312,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
|
||||
|
@ -376,9 +336,9 @@ int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t targe
|
|||
usleep(10000);
|
||||
|
||||
if (stlink_is_core_halted(sl)) {
|
||||
timeout = 0;
|
||||
break;
|
||||
}
|
||||
timeout = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (timeout) {
|
||||
|
@ -397,11 +357,14 @@ int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t targe
|
|||
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);
|
||||
ELOG("%s (R2 0x%X R15 0x%X DHCSR 0x%X DFSR 0x%X CFSR 0x%X HFSR 0x%X)\n", error, rr.r[2], rr.r[15], dhcsr, dfsr, cfsr, hfsr);
|
||||
ELOG("(R0 0x%X R1 0x%X)\n", rr.r[0], rr.r[1]);
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Ładowanie…
Reference in New Issue