STM32的Flash的可擦写次数在10000次,在学习或调试过程中为了延长Flash的寿命,将程序写入SRAM是一个很好的办法。在百度上找到的SRAM启动方法总有各种各样的问题,接下来我将会提供一个完整的思路给大家学会如何配置SRAM启动的环境。
这里用来演示的开发板是STM32F103C8T6
1. 在STM32上调整BOOT引脚
将STM32的BOOT0和BOOT1上拉,下次RESET(重置)将会进入SRAM启动模式。
2. 打开Keil,新建/打开一个工程
这个就不要我放截图了吧 = =
3. 创建一个新的Target用于保存SRAM启动配置
在Explorer(文件浏览器)中,右击Project下面的项(这个项就是一个Target)。
进入Manage Project Items...
在Project targets中,点击添加按钮添加一个新的Target,如“RAMBOOT” (图3),添加完毕后点击OK即可。
在Target选择器中选择“RAMBOOT”。
3. 修改内存配置
打开“魔法棒” -- Options for Target...
在Targets选项卡中,修改下面的内存地址。
IROM1是内置Flash的地址,IRAM就是SRAM的地址。通过修改这里的地址可以将代码和数据区都放在SRAM上。
将IROM修改为0x20000000,大小要根据你的开发板的SRAM大小进行修改,比如我这一块是STM32F103C8T6,SRAM大小为20KB(20*1024=20480=0x5000h,16进制可以通过Windows自带计算器的“程序员”功能转化),所以我给ROM分配0x3000内存,RAM则修改成0x20003000,分配剩下的0x2000内存(如图)。
接下来转到Linker选项卡。取消选中Use Memory Layout from Target Dialog,修改R/O(只读数据,也就是ROM)和R/W(读写,也就是RAM)的地址。和刚才的Target一样就行。
接下来修改链接脚本。点击Scatter File右边的三个点,在项目的根目录上创建一个新文件,我这就叫“RAMBOOT.SCT”,然后双击它。
然后点击Edit,Keil就会打开文本编辑器编辑这个文件。然后点OK(一定要点OK,不然白设置了!!!)。
填入以下内容(之后还需要对这个文件做出一些修改,不用关闭此文件):
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x20000000 0x00003000 { ; 你在设置里设置的ROM地址
ER_IROM1 0x20000000 0x00003000 { ; 这里也一样
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
.ANY (+XO)
}
RW_IRAM1 0x20003000 0x00002000 { ; 你在设置里设置的RAM地址
.ANY (+RW +ZI)
}
}
保存。然后再打开“魔法棒” -- Option for Target...
打开Utilities选项卡。单击Settings。
这里也有RAM和FLASH的地址和大小设置。修改成和之前一样的。
然后确定,保存设置。
4. 修改链接器脚本
首先,需要知道开发板在SRAM模式下的启动地址和重置地址在哪里。知道这些地址后,只要往这两个地址放两个正常的启动指令就可以完成引导。
若你的代码可以正常编译,编译后,点击“调试”按钮。
查看当前程序所在的地址,这就是启动地址,记下来(黄色小箭头或在左边的PC寄存器)
然后点击左上角的RST按钮,再看看一遍地址,也记下来:
知道这些就可以了。然后再看看中断向量表的大小。
打开项目目录,进入Listing文件夹,看看里面是否有一个map文件。如果没有就打开魔法棒,进入Listing,选中Linker Listing下面的全部,然后再编译。
打开map文件,搜索__Vectors_Size,就能看到向量表的大小。如果看不到就自己算(Vectors_end - Vectors)。记下向量表的大小。
还是打开“魔法棒” -- Options for Target...
进入Linker选项卡,点击Scatter File右边的Edit按钮,然后关闭窗口。之前设置没问题的话这时候Keil就打开了链接器脚本的编辑器(现在应该什么内容都没有)。
修改链接器的脚本内容如下:
; 本例子针对STM32F103C8T6,其他开发板可能需要做一些修改
; 如果你定义的内存地址不一样,或者你的开发板SRAM启动模式的
; 启动地址和重置地址不一样,则需要对这里的地址进行一些修改
; 需要自己理解一些内容,如什么是段(section/segment),根据
; 刚才记录的启动地址、RST地址和中断向量表大小进行修改
LR_IROM1 0x20000000 0x00003000 { ; 将ROM的地址定位到0x20000000,大小0x3000
RO_IRAM1 0x20000000 0x00000100 { ; 给在0x20000000分配了0x100内存
*.o (RAMSTART, +First) ; 将RAMSTART代码段定位到0x20000000
}
RO_IRAM2 0x20000100 0x00000100 { ; 格式同上
*.o (RAMRESET, +First) ; 将RAMRESET代码段定位到0x20000100
}
RO_IRAM3 0x20000200 FIXED 0x00000100 { ; 向量表占用了0xEC,所以给中断向量表分配了0x100空间
; fixed避免重叠
*.o (RESET, +First) ; 将中断向量表定位到0x20000200
}
RO_IRAM4 0x20000300 FIXED 0x20002D00 { ; 其他的ROM数据就放在这里了
*(InRoot$$Sections) ; 根链接器定义的所有段
.ANY (+RO) ; 任何只读数据段
.ANY (+XO) ; 任何可执行数据段
}
RW_IRAM1 0x20003000 0x00002000 { ; 将RAM的地址定位读写区
.ANY (+RW +ZI) ; 任何可读写数据
}
}
5. 使用汇编进行引导
创建一个汇编源码文件并导入(.s文件)。这里我创建了一个叫ramboot.s的文件
将以下内容复制到此文件中:
AREA RAMSTART, CODE, READONLY ;RAM模式启动用代码段。
;此代码段被链接脚本固定在了0x20000000
IMPORT Reset_Handler ;Reset_Handler是STM32用于初始化的一段代码
STARTPROG PROC ;启动函数
SPACE 4 ;留空四个字节,也就是说下一段代码的地址是0x20000004
B Reset_Handler ;跳转到Reset_Handler
ENDP ;函数结束
AREA RAMRESET, CODE, READONLY ;RAM重置后跳转的代码段
;此代码段被链接脚本固定在了0x20000100
IMPORT Reset_Handler ;和上面一样
RESETPROG PROC ;重置函数
SPACE 8 ;留空八个字节,也就是说下一段代码的地址是0x20000108
B Reset_Handler ;跳转到Reset_Handler
ENDP ;函数结束
END ;汇编结束
6. 重定位中断向量表
打开system_stm32f10x.c,找到此预定义
#define VECT_TAB_OFFSET 0x0
把它修改为
#ifdef VECT_TAB_SRAM
#define VECT_TAB_OFFSET 0x200 //根据在链接脚本配置的中断向量表的位置修改
//跟我的一样的话就不用改了
#else
#define VECT_TAB_OFFSET 0x0
#endif
保存,再打开魔法棒,打开C/C++选项卡,添加预定义:VECT_TAB_SRAM
记得与其他预定义用逗号分开。
最后,编译程序,然后打开keil的调试功能,就成功启动SRAM模式了。中断也正常运行。文章来源:https://www.toymoban.com/news/detail-767999.html
不停的开发板可能有不同的情况,可能需要根据不同的开发板修改一些地方。文章来源地址https://www.toymoban.com/news/detail-767999.html
到了这里,关于Keil STM32配置SRAM启动并解决SRAM模式代码跑向中断向量表导致程序跑飞的问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!