STM32 把程序放到 RAM中运行
stm32可以将代码直接下载到RAM中时行程序调试,同时可以有效避开STM32 Flash 擦写次数有限问题,其实除了仿真调试时将程序设置在RAM中可以解决FLASH擦写次数问题外,如果程序实际运行时能直接在RAM中运行,其代码的运行效率也会有一定的提高,那么怎么实现实际运行时让程序在RAM中运行呢, 实现这一操作。
示例详解
基于硬件平台: STM32F10C8T6最小系统板, MCU 的型号是 STM32F103c8t6, 使用stm32cubemx 工具自动产生的配置工程,使用KEIL5编译代码。
本示例所用的最小系统板原理图:
- 关于CUBEMX工具及KEIL工具的操作将不再细讲,如果还有不熟悉的可以查看之前的教程文档。下面直接介绍工程配置:
- 系统时钟树
- 关于CUBEMX工具及KEIL工具的操作将不再细讲,如果还有不熟悉的可以查看之前的教程文档。下面直接介绍工程配置:
- 定时器配置
- 引脚配置
- 中断配置(保持默认)
- 工程代码
- 使用KEIL时需要将部分或者全部程序放到RAM中运行,实现方法有多种:
方法一:通过#pragma arm section code = “RAMCODE ”和#pragma arm section。这种方式,可以同时将多个函数放到指定的section。具体方法如下:
1. 修改.sct文件,自定义一个叫做RAMCODE的section,放在RW_IRAM1执行区域,地址范围0x20000000~0x20005000。
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x08000000 0x00010000 { ; load region size_region
ER_IROM1 0x08000000 0x00010000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
.ANY (+XO)
}
RW_IRAM1 0x20000000 0x00005000 { ; RW data
*.o(RAMCODE)
.ANY (+RW +ZI)
}
}
2. 在工程中使用前面修改的.sct文件
3.以#pragma arm section code = “RAMCODE” 开头,以#pragma arm section结尾。将所有需要放到RAMCODE section的函数包括进来。编译时,编译器会自动将这些函数放到RAMCODE所在0x20000000开始的区域。
4.从map文件里,可以看到这几个函数都已经被放到了SRAM中。
方法二:通过__attribute__((section(“name ”)))
在KEIL中可以通过__attribute__((at(address)))的方式将变量放到指定的位置。通过__attribute__((section(“name ”)))的方式将变量或者函数放到指定的位置。
1.同样,我们需要修改.sct文件,自定义一个叫做RAMCODE的section,并在工程选项的linker页面中,选择定义好的.sct文件。
2.在需要放到RAM中的函数前,用__attribute__((section("RAMCODE")))声明该函数放在RAMCODE section中。注意,该函数中调用到的所有函数也要放到RAMCODE section中。
3.从编译后的map文件可以看出,ToggleLED以及它调用到的所有函数都被到了RAM中。
方法二可以覆盖方法一,也就是说如果你同时用方法一和方法二对同一个函数的执行区域做了说明。最终起作用的是方法二如:
其实际结果为:
前面我们介绍了将一个或多个程序放到指定地址执行的方法。如果需要放到指定地址的程序比较多,我们还可以将这些需要放到指定地址的程序集中放到一个或几个C文件中,然后在.sct文件中将这些C文件生成的目标文件放到指定地址。在这里,我们将尝试将整个程序放到SRAM中执行。复位后程序从FLASH启动,之后将从SRAM执行所有的程序。下面是具体的步骤:
1.将中断向量表和中断处理程序放到SRAM中,新建一个startup_stm32f103xb_ram.s文件并将其放在0x20000000处(在SCT文件中修改),其内容为,:
2,在后面的.sct中将把RESET_ram这个section放到SRAM开始的位置上,并将要放到SRAM中的程序模块也加到SRAM中,如下图:
2.在工程的Options for Target ->C/C++选项卡中加入VECT_TAB_SRAM宏定义:
3. 编译完成后,从map文件可以看到程序的运行地址是在SRAM区间:
如量没有将对应的程序模块加载到SRAM中(SCT文件中没加),则是下面的情况:
- 在main.c中加入如下图所示代码:
- 编译工程无错误后,下载运行程序可以看到LED功能正常(500ms亮灭交替):
OK, 完成!