如果您最近开始使用它,那么在快闪存储耗尽之前,您有很长的时间。您可能会收到驱动器已满的错误提示,只需拔下板子再插上即可。我已经使用这些东西多年了,但还没有磨损快闪存储。不是说不可能磨损,只是您很少会出现这种情况,除非您编写了一个大量读写快闪存储的程序来使其磨损。
您需要openocd(或其他调试器,也许您的IDE提供该功能,但我不使用那些,无法帮助您)。openocd和gnu工具非常容易获取,因此接下来将介绍如何操作。
从正确的目录中,或通过从openocd复制这些文件来进行操作。
openocd -f stlink-v2-1.cfg -f stm32f4x.cfg
(一个或两个文件可能有其他包含的依赖项,可以将它们引入或采取其他措施。)
应该以类似这样的方式结束,而不是退出到命令行。
Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints
在另一个窗口中。
telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
>
在那个窗口中,您可以暂停处理器。
> halt
stm32f4x.cpu: target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x61000000 pc: 0x080000b2 msp: 0x20000ff0
>
完整的ARM处理器,您的入口点是一条指令,您只需开始执行。Cortex-M使用向量表,您不能直接跳转到那里。
.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.thumb_func
reset:
bl notmain
b hang
.thumb_func
hang: b .
你理论上可以分支到复位处理程序地址,但链接脚本需要在闪存中获得该地址,任何位置相关的操作都将无法正常工作。如果你依赖向量表来设置堆栈指针,则可能无法设置堆栈指针。因此,像下面这样的内容将起作用,并且是完整示例的一部分。
sram.s
.cpu cortex-m0
.thumb
.thumb_func
.global _start
_start:
ldr r0,stacktop
mov sp,r0
bl notmain
b .
.align
stacktop: .word 0x20001000
.thumb_func
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.thumb_func
.globl GET32
GET32:
ldr r0,[r0]
bx lr
notmain.c
void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
int notmain ( void )
{
unsigned int ra;
ra=GET32(0x20000400);
PUT32(0x20000404,ra);
PUT32(0x20000400,ra+1);
return(0);
}
sram.ld
MEMORY
{
rom : ORIGIN = 0x08000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > ram
.rodata : { *(.rodata*) } > ram
.bss : { *(.bss*) } > ram
}
基本上用 RAM 替换 ROM 引用。(如果您使用的是 GNU 连接器脚本,则可能比此脚本复杂得多,但这样做完全没有问题,可以根据需要添加 .data)。
arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m0 flash.s -o flash.o
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mcpu=cortex-m0 -mthumb -c notmain.c -o notmain.o
arm-none-eabi-ld -o notmain.flash.elf -T flash.ld flash.o notmain.o
arm-none-eabi-objdump -D notmain.flash.elf > notmain.flash.list
arm-none-eabi-objcopy notmain.flash.elf notmain.flash.bin -O binary
arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m0 sram.s -o sram.o
arm-none-eabi-ld -o notmain.sram.elf -T sram.ld sram.o notmain.o
arm-none-eabi-objdump -D notmain.sram.elf > notmain.sram.list
arm-none-eabi-objcopy notmain.sram.elf notmain.sram.hex -O ihex
arm-none-eabi-objcopy notmain.sram.elf notmain.sram.bin -O binary
我制作了程序的flash版本和sram版本。
现在我们已经通过telnet进入了openocd服务器,处理器被暂停,让我们查看一个内存位置并进行更改。
> mdw 0x20000400
0x20000400: 7d7d5889
> mww 0x20000400 0x12345678
> mdw 0x20000400
0x20000400: 12345678
并运行我们基于SRAM的新程序。
> load_image /path/to/notmain.sram.elf
64 bytes written at address 0x20000000
downloaded 64 bytes in 0.008047s (7.767 KiB/s)
> resume 0x20000001
让它运行,脚本速度可能仍然太慢,但肯定需要花时间键入halt命令。
> halt
stm32f4x.cpu: target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x41000000 pc: 0x20000008 msp: 0x20001000
> mdw 0x20000400 10
0x20000400: 12345679 12345678 ce879a24 fc4ba5c7 997e5367 9db9a851 40d5083f fbfbcff8
0x20000420: 035dce6b 65a7f13c
>
程序已经运行,程序读取0x20000400并将其保存到0x20000404,然后对0x20000400进行递增并保存,所有这些操作都已完成。
> load_image /path/to/notmain.sram.elf
64 bytes written at address 0x20000000
downloaded 64 bytes in 0.008016s (7.797 KiB/s)
> resume 0x20000000
> halt
stm32f4x.cpu: target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x41000000 pc: 0x20000008 msp: 0x20001000
> mdw 0x20000400 10
0x20000400: 1234567a 12345679 ce879a24 fc4ba5c7 997e5367 9db9a851 40d5083f fbfbcff8
0x20000420: 035dce6b 65a7f13c
>
所以我们不需要使用BX指令将起始地址设置为1,他们只需将地址直接存入PC寄存器中,或为我们执行正确的操作。
如果您只修改链接脚本以将ROM替换为RAM,则可以实现目标。
20000000 <_start>:
20000000: 20001000
20000004: 20000041
20000008: 20000047
2000000c: 20000047
20000010: 20000047
20000014: 20000047
20000018: 20000047
2000001c: 20000047
20000020: 20000047
20000024: 20000047
20000028: 20000047
2000002c: 20000047
20000030: 20000047
20000034: 20000047
20000038: 20000047
2000003c: 20000047
20000040 <reset>:
20000040: f000 f806 bl 20000050 <notmain>
20000044: e7ff b.n 20000046 <hang>
您可以将0x20000041地址作为程序入口点(使用"resume 0x20000041"命令),但需要先处理好堆栈指针。
可以通过以下方式进行处理:
> reg sp 0x20001000
sp (/32): 0x20001000
> reg sp
sp (/32): 0x20001000
> resume 0x20000041
注意:这些设备的RAM比ROM更快,并且在增加时钟频率时不需要等待状态,因此,如果您仅在RAM中增加时钟频率并进行调试,则可能会导致在切换到Flash时失败,如果您没有记得设置Flash等待状态...除此之外,程序的可用空间显著减少,但如果您想一整天都在RAM中开发程序,那么可以实现。
一个不错的功能是您可以保持暂停并重新加载。我不知道这个设备/调试器上是否有缓存(某些Cortex-M4具有缓存,如果不是全部,则需要小心确保在更改程序时关闭缓存)。写入内存是数据操作,获取指令是指令获取操作,该操作可能会落入指令高速缓存中。如果您在0x20000100处执行某些指令并且它被缓存在I cache中,则您使用调试器停止,然后编写一个包括缓存中地址(0x20000100)的新程序,当您运行它时,I cache未被刷新,因此您将同时运行先前程序和新程序,这最多是灾难性的。因此,在使用此方式运行时,要么永远不要打开缓存,要么找出解决此问题的方法(在停止程序之前清除缓存,在运行之间使用复位按钮复位处理器,断电等)。