STM32的代码是保存在内部FLASH中,执行也在内部FLASH中。那有没有设想一下,如果代码保存在外部SPI FLASH,执行在内部RAM该怎么做?
实现步骤:
-
我使用的是
STM32F103RCT6
,板载SPI FLASH,并且PA4(CS),PA5(SCK),PA6(MISO),PA7(MOSI)连到W25Q32FV上,PA2接到LED上。 -
使用STMCubeMX新建工程,定义SPI4根线、配置SPI相关参数、定义LED端口,生成工程,然后加入SPI FLASH的驱动。
-
修改总工程属性
Option for File Target
:- 勾选并定义
ROM1:0xC0000000, 0x100
,由于测试代码较小,这里只分配256个字节。 - IRAM字段由于要放一部分用来执行代码,则将原先长度
0xC000
缩小为0x8000
- 如图:
- 勾选并定义
-
新建
test.c
文件,该文件用于保存在SPI FLASH、执行在RAM的代码
修改test.c
文件属性Option for File Target
,如图: -
编辑
test.c
,加入翻转LED灯代码:
#include "main.h"
#include "stm32f1xx_hal.h"
void led_test(void)
{
while(1)
{
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
HAL_Delay(1000);
}
}
- 编译没问题后,重新修改总工程属性
Option for File Target
,切换到Link
选项,取消勾选Use Memory Layout from Target Dialog
,并点击Edit
编辑sct文件。
如图 :
sct编辑内容如下:
LR_IROM1 0x08000000 0x00020000 { ; load region size_region
ER_IROM1 0x08000000 0x00020000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00008000 { ; RW data
.ANY (+RW +ZI)
}
}
LR_ROM1 0xC0000000 0x00000100 {
ER_ROM1 0x20008000 0x00000100 { ; load address = execution address
test.o (+RO)
.ANY (+RO)
}
}
- 编辑
main.c
,添加以下代码:
//由于代码存在外部的SPI FLASH,因此代码搬移工作必须手动完成,即加载域到执行域的拷贝工作必须自己完成。
W25QXX_Read((uint8_t*)0x20008000,0x0, 100);//注释该语句将进入HardFault_Handler
led_test();
- 重新完全编译,然后烧录选项添加SPI FLASH的烧录算法。
参考:Keil(MDK)下用仿真器烧程序的同时烧写附加数据到SPI FLASH
烧录后上电,点灯间隔1秒闪烁成功,大功告成!
http://www.armbbs.cn/forum.php?mod=viewthread&tid=82274&highlight=FLASH