Keil STM32配置SRAM启动并解决SRAM模式代码跑向中断向量表导致程序跑飞的问题

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模式了。中断也正常运行。

不停的开发板可能有不同的情况,可能需要根据不同的开发板修改一些地方。

  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值