stm32 将系统堆栈放置在外部内存的方法

背景内容

stm32可以外扩很大的sram,常见外部sram的初始化函数一般是c语言写的,默认写在main函数里面。stm32初始化首先进入汇编代码startup_stm32f407xx.s,在汇编代码中Reset_Handler(复位中断服务程序)里面先调用了SystemInit,然后调用__main进行堆栈的初始化,最后才会跳转到用户main函数。调用SystemInit涉及到局部变量和函数调用,需要用到stack栈空间,如果我们简单的将系统堆栈配置到外部sram,执行SystemInit时外部sram还没有初始化,运行到这里程序就会进入hardfault卡死。
为了解决这个问题,首先可以将外部sram的初始化函数提前,放到SystemInit函数中调用,cube生成的stm32代码已经为我们提供了这样的接口,这样__main就可以正确运行,然而这还没有解决SystemInit本身执行的问题,我们需要保证SystemInit执行时使用STM32内部RAM。

具体步骤:

1、修改启动代码堆栈指针

在startup_stm32fxxxxx.s中,找到 __initial_sp这一行,改为如下内容

Stack_Size		EQU     0x2000

                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp    EQU     0x20002000

注意这里0x20002000 =内部主内存地址0x20000000+栈大小0x2000,也就是说这个地址和stack_size有关,需要根据自己stack_size的设置来修改,这样就强制指定了系统初始化的栈顶指针在内部内存,保证进入main函数之前的其它初始化函数调用堆栈正常使用。

2、添加宏定义使能DATA_IN_ExtSRAM

在option,c/c++选项卡 define后面添加 DATA_IN_ExtSRAM
在这里插入图片描述

3、修改外部内存初始化代码

假定外部内存初始化函数为FsmcSramInit(),修改system_stm32f4xx.c文件
找到如下内容,英文说明这个函数将在跳转到main之前执行,可以让外部内存被系统当做程序数据内存使用,包括堆栈,这就是关键了

#elif defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
/**
  * @brief  Setup the external memory controller.
  *         Called in startup_stm32f4xx.s before jump to main.
  *         This function configures the external memories (SRAM/SDRAM)
  *         This SRAM/SDRAM will be used as program data memory (including heap and stack).
  * @param  None
  * @retval None
  */
void SystemInit_ExtMemCtl(void)

接下来修改SystemInit_ExtMemCtl(void)函数,直接注释掉里面的所有内容,改为

void SystemInit_ExtMemCtl(void)
{
  FsmcSramInit();
}

SystemInit_ExtMemCtl()函数是被SystemInit函数调用的,这样执行完SystemInit后,再进入__main就可以初始化配置在外部内存的堆栈了。

4、配置和使用外部内存空间

这里可以有两种方式,如果让mdk自动分配内存,则打开option,target选项卡,右下角 read/write memory areas 添加内存块,勾选RAM1,填入外部内存起始地址和大小即可
在这里插入图片描述
否则,如果要手动分配内存,可以参考我另一篇文章stm32管理内存分配以及CCM的使用方法
修改自定义的sct文件,添加如下字段

  RW_RAM1 0x68000000 0x00100000  {
   startup_stm32f407xx.o (Heap)
   .ANY (EXRAM)
  }

即可将系统堆,以及通过attribute标记为EXRAM的数据都放在外部内存。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值