本帖最后由 xhackerustc 于 2024-5-6 00:07 编辑
#申请原创# @21小跑堂
在日常开发调试过程中,如果固件不是很大能放进sram,其实没必要每次都烧写进flash,一来:flash擦除次数是有限的,改点代码就擦除一次而且总擦除flash头部位置肯定影响flash寿命,虽然几次开发调试用用那点擦除次数不至于,但是完美主义者心里总有点不爽;二来:相比加载进sram,烧写flash速度比较慢。所以这时候比较理想的调试方法是:把固件加载进sram并从sram启动,所有功能调试完毕后再改回用flash统一验证一下。这个测评贴就是来展示pyocd如何加载点灯固件到sram并从sram启动。
APM32F411启动选项
APM32F411通过配置boot1和boot0引脚有三种不同的启动选项,其中boot0和boot1引脚都拉高时,是从内置sram启动,这正是笔者需要启动模式。对应到
APM32F411V Tiny board板子上有boot0和boot1跳线, 板子到手默认都是拉低的,改下跳线即可。
link script的改动
如第一篇测评贴所述,笔者是linux爱好者,开发环境是gcc+vim+pyocd+make,所以这里示例仅以gcc的linkscript为例,MDK、IAR等环境略,它们改动原理是一样的。由笔者第一篇测评贴的Makefile可知APM32F411V Tiny Board默认用的link script位于Libraries/Device/Geehy/APM32F4xx/Source/gcc/APM32F4xxxE_FLASH.ld,改动前复制一份并重命名为Libraries/Device/Geehy/APM32F4xx/Source/gcc/APM32F4xxxE_RAM.ld。需要做如下改动:
1.把FLASH和CCMRAM有关的基地址、大小等定义删除
其实不删除也可以,但完美主义者非删不可也防止留着后面section修改不到位仍然有部分数据/代码还在flash上
2.把放在FLASH中的section放进RAM地址空间中
就是把形如下面这样的代码
.text :
{
. = ALIGN(4);
*(.text)
*(.text*)
*(.glue_7)
*(.glue_7t)
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .;
} >FLASH
最后一行”>FLASH"修改成">RAM",比如上面的.text section就修改为:
.text :
{
. = ALIGN(4);
*(.text)
*(.text*)
*(.glue_7)
*(.glue_7t)
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .;
} >RAM
3.把VMA是RAM地址空间,LMA是FLASH地址空间的section修改成放入RAM地址空间,也即改成VMA和LMA都是RAM地址空间有些section运行时(虚拟)地址(所谓VMA)和加载地址(所谓LMA)并不一致,典型如.data section,在初始化时由初始化代码从flash拷贝到sram中,所以.data section在link script中都是类似这么写的:
.data :
{
. = ALIGN(4);
_start_address_data = .;
*(.data)
*(.data*)
. = ALIGN(4);
_end_address_data = .;
} >RAM AT> FLASH
对于固件全部加载进sram的情形已经不适用,需要改成如下这种写法:
.data :
{
. = ALIGN(4);
_start_address_data = .;
*(.data)
*(.data*)
. = ALIGN(4);
_end_address_data = .;
} >RAM
Makefile的改动
需要在Makefile中修改链接时所用到link scrpt:
diff --git a/Makefile b/Makefile
index 8a222ed..a7b27cf 100644
--- a/Makefile
+++ b/Makefile
@@ -84,7 +84,7 @@ CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
# LDFLAGS
#######################################
# link script
-LDSCRIPT = Libraries/Device/Geehy/APM32F4xx/Source/gcc/APM32F4xxxE_FLASH.ld
+LDSCRIPT = Libraries/Device/Geehy/APM32F4xx/Source/gcc/APM32F4xxxE_RAM.ld
# libraries
LIBS = -lc -lm -lnosys
初始化阶段Vector Table重定位
VTOR是在system_apm32f4xx.c中设置的,笔者观察到每个example都有一份system_apm32f4xx.c,比如Examples/GPIO/GPIO_Toggle/Source/system_apm32f4xx.c。修改它比较简单,apm官方考虑到了sram启动,只要enable一行宏定义即可:
diff --git a/Examples/GPIO/GPIO_Toggle/Source/system_apm32f4xx.c b/Examples/GPIO/GPIO_Toggle/Source/system_apm32f4xx.c
index 16b200c..7ddc4b6 100644
--- a/Examples/GPIO/GPIO_Toggle/Source/system_apm32f4xx.c
+++ b/Examples/GPIO/GPIO_Toggle/Source/system_apm32f4xx.c
@@ -43,7 +43,7 @@
/* #define DATA_IN_ExtSRAM */
/* Uncomment the following line if you need to relocate your vector Table in Internal SRAM. */
-/* #define VECT_TAB_SRAM */
+#define VECT_TAB_SRAM^M
/* Vector Table base offset field. This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET 0x00
pyocd加载固件进sram并启动
进入pyocd cmd命令行后,打一些命令如图所示
此时板子上led2/led3开始闪烁,串口也开始有期望的打印,说明这次完全从sram启动运行点灯程序了。
|