ARM架构与FreeRTOS中的内存管理(flash与SRAM,堆栈)

在ARM架构中,内存的地址空间是如何划分的,内存映射表是怎样的

在Cortex-M7中,存储器一共有4GB的地址空间,4GB的地址空间又被划分为8个区域块,每个块有512M的内存。

Note:4GB的地址空间为 0x0000 0000 - 0xFFFF FFFF,可寻址的512M的地址空间大小为 0x0000 0000 - 0x1FFF FFFF,可寻址的地址是指处理器可以直接访问和寻址的存储区域,如flash,SRAM,寄存器。

Cortex-M7的4GB的地址空间存储映射:Vendor-specific device 和 Private peripheral bus一共512M

参考 Cortex‐M3 预定义的存储器映射:

在ARM架构中,分段或分片管理和 Section 切换管理是如设计的

在MCU的内存空间,通过链接脚本确定编译时静态内存分配,链接脚本以段(Segment)或片(Section)为单位进行分配,每个段和片在内存中占据连续空间.

Segment通常包含多个具有相似属性的内存区域,粒度较大,Section则描述单个连续的内存区域,粒度较细。

分片管理如下图,堆栈,.bss,.data,.rodata,.text

Section切换管理过程如下:

程序运行过程中,如果需要访问存储在其他Section(如.bss)的数据,需要进行Section级别的切换管理

程序运行过程中,CPU根据PC寄存器的值自动切换到对应的代码Section执行。

如果访问了数据Section,CPU会根据MMU/MPU的配置自动完成地址转换和权限检查。

如果发生内存访问异常,操作系统的异常处理程序会分析异常原因,并采取适当的措施,如切换到正确的Section,例如中断。

在ARM架构中,如何划分他的堆栈

栈是一种数据结构, 它的特点是先进后出(First Input Last Output, FILO)。入栈和出栈都靠栈指针(Stack Pointer, SP) 来维护, SP会随着入栈和出栈在栈顶上下移动。栈顶指的是当前栈指针(Stack Pointer, SP)所指向的内存地址。栈底指的是栈的起始地址,也就是栈区域在内存中的最低地址。链接脚本中_estack表示栈的结束地址,它代表了系统实际分配给栈的最高内存地址,_estack 只是一个符号,表示预留给栈使用的内存范围的上限,并不等同于实际栈使用的最高地址,栈指针(SP)寄存器记录的是当前栈顶的地址,它的值永远不会超过 _estack。

如果栈使用的空间超过了 _estack 所指向的地址,就会发生栈溢出错误。

Cortex‐M7使用的是“向下生长的满栈”模型。

栈指针 SP 指向最后一个被压入堆栈的 32 位数据。

入栈:

出栈:

举例:在MCU链接脚本中,定义堆栈的结束地址,也就是高内存地址,定义他的静态堆栈大小。在ARM-M7中SRAM主要作为使用为堆栈和数据段的内存是128k,也就是DTCM,因为他的访问速度最快。

堆栈的起始地址和之前分配的各种数据段和对齐方式有联系。

在运行FreeRTOS时,特权模式和用户模式如何划分在SRAM中划分堆栈,以及任务之间如何划分堆栈

在Cortex-M7架构中,堆栈通常由两个寄存器来管理:主堆栈指针(MSP)和进程堆栈指针(PSP),MSP是处理器的默认堆栈指针,用于保存中断处理程序的现场,PSP堆栈指针用于保存应用程序现场的。

也就是说如果跑的是裸机程序,他的所有程序都在使用MSP堆栈指针。如果跑操作系统,一般的任务执行和调度使用的是PSP堆栈指针,如果产生中断,中断服务使用的是MSP堆栈指针。

主堆栈(MSP):在系统启动期间,CPU会自动将MSP设置为链接脚本中_estack的值。进程堆栈(PSP):由操作系统或应用程序在运行时进行设置。

在运行FreeRTOS时,内存堆为 ucHeap[] , 大小为 configTOTAL_HEAP_SIZE。当宏 configAPPLICATION_ALLOCATED_HEAP 为 1 的时候需要用户自行定义内存堆,内存的分配方案有五种,heap_1,heap_2,heap_3,heap_4,heap_5,否则的话由编译器来决定,默认都是由编译器来决定的。

如下图所示:操作系统在内存中所占据的地址空间,MSP与PSP都是特指的堆栈指针,如果没有任务,只跑操作系统,那就只应用了MSP堆栈指针,如果有创建任务,就多了PSP堆栈指针,并且初始化和动态创建了任务的堆栈内存。深入理解 STM32 双堆栈机制 - 国际哥的独立博客

任务的内存分配方案有五种,heap_1,heap_2,heap_3,heap_4,heap_5,但FreeRTOS默认的分配是0,在启动时分配一块连续的内存区域作为堆,内存区域的大小由 configTOTAL_HEAP_SIZE 宏来配置,FreeRTOS 会使用这块预分配的内存区域来满足动态内存分配的需求。 configTOTAL_HEAP_SIZE 宏定义的是一个连续的内存空间,任务堆栈的起始地址是随机分配的,不一定是从系统堆栈的最高地址开始。只要有足够的连续空间,FreeRTOS就会从系统堆栈中分配出一块区域作为任务的私有堆栈。

基于MSP的堆栈地址:需要进行8字节对齐,起始地址:0X2000 9208,length=40k=0XA004,结束地址:0X201 3208

configTOTAL_HEAP_SIZE 宏定义的是一个连续的存储任务的内存空间,内存变量是 uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]u8数据类型,

起始地址:0X2000 2CDC,length=19.53k=0X4E20,结束地址:0X2001 3208,刚好接上上图的FreeRTOS的MSP堆栈地址。

ucHeap 代表了FreeRTOS中动态内存分配的堆栈,虽然任务的执行代码存储在flash里,但是里面的静态变量是存在SRAM的堆栈里。

在创建任务的时候,会分配堆栈的内存大小,但是实际使用的时候用不满或溢出,所以要判断实际中使用了多少堆栈可以用函数 uxTaskGetStackHighWaterMark在任务执行的时候区观察运行期间堆栈使用量最大值。

  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梅尔文

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值