STM32 存储器与堆栈问题

首先我们先来看下stm32的系统架构:
这里写图片描述
可以看出四个驱动单元:D-bus,S-bus,DMA1,DMA2。四个被动单元:SRAM,Flash,FSMC(这块我是以stm32f103zet6来写的,有些32芯片没有这个接口,AHB到APB以及连接的APB设备)
再来看下存储器映射
这里写图片描述
可以看出flash起始地址为0x0800 0000,SRAM起始地址为0x20000000,外设映射起始地址为0x4000000,再次看到第8块512M的存储器,0xE0000000地址为向量中断控制器的起始地址,查看《crotex-m3权威指南》可以了解到,这个地址在操作系统移植也很重要。
接下来讲BSS段,数据段,代码段,堆,栈
BSS段:(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。
数据段 :数据段(data segment)通常是指用来存放程序中 已初始化 的 全局变量 的一块内存区域。数据段属于静态内存分配。
代码段: 代码段(code segment/text segment)通常是指用来存放 程序执行代码 的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于 只读 , 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些 只读的常数变量 ,例如字符串常量等。程序段为程序代码在内存中的映射.一个程序可以在内存中多有个副本.
堆(heap) :堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc/free等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张)/释放的内存从堆中被剔除(堆被缩减)
栈(stack) :栈又称堆栈, 存放程序的 局部变量 (但不包括static声明的变量, static 意味着 在数据段中 存放变量)。除此以外,在函数被调用时,栈用来传递参数和返回值。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。储动态内存分配,需要程序员手工分配,手工释放。
我就先栈的问题来说下stm32注意的事项:我们可以startup_stm32f10x_hd.s文件看到Stack_Size EQU 0x00000400栈空间。下面举例说明:
static void StackOverflowTest(void)
{
int16_t i;
uint8_t buf[2048];
(void)buf;
1. 为了能够模拟任务栈溢出,并触发任务栈溢出函数,这里强烈建议使用数组的时候逆着赋值。
因为对于M3和M4内核的MCU,堆栈生长方向是向下生长的满栈。即高地址是buf[2047], 低地址
是buf[0]。如果任务栈溢出了,也是从高地址buf[2047]到buf[0]的某个地址开始溢出。
因此,如果用户直接修改的是buf[0]开始的数据且这些溢出部分的数据比较重要,会直接导致
进入到硬件异常。
2. 栈溢出检测是在任务切换的时候执行的,我们这里加个延迟函数,防止修改了重要的数据导致直接
进入硬件异常。
3. 任务vTaskTaskUserIF的栈空间大小是2048字节,在此任务的入口已经申请了栈空间大小
——uint8_t ucKeyCode;
——uint8_t pcWriteBuffer[500];
这里再申请如下这么大的栈空间
——-int16_t i;
——-uint8_t buf[2048];
必定溢出。
for(i = 2047; i >= 0; i–)
{
buf[i] = 0x55;
vTaskDelay(1);
}
}
我当初看到这里,感触还是挺多的。
接着堆Heap_Size EQU 0x00000200
注意这里的考虑大小端模式还有static,malloc,的知识点,stm32为小端模式,static静态存储空间,不需要用户释放,程序结束自动释放,而malloc需要用户释放,避免发生内存泄漏问题。
再来看下flash:
小容量产品主存储块1-32KB, 每页1KB。系统存储器2KB。
中容量产品主存储块64-128KB, 每页1KB。系统存储器2KB。
大容量产品主存储块256KB以上, 每页2KB。系统存储器2KB。
互联型产品主存储块256KB以上, 每页2KB。系统存储器18KB。
注意到每页多大,对IAP的编写很重要,当然做bootloader的时候注意向量表偏移量寄存器。SCB->VTOR,写到这又想起了DMA的FIFO这个对于做stm32也是必须的,其中很多的资料的这点感觉每个做stm32的都必须掌握。
接着我最近看到了很多之前没了解到的,也拿出来记录一下:
Cortex-M3,这种内核支持许多屏蔽指令。在下一个指令或者事件开始执行以前,这些屏蔽指令常常用于确保必然事件执行完成。
在处理器内部,指令同步屏蔽(ISB)刷新流水线;以致于这个指令执行完以后,紧接着从缓存或者存储器取出指令表。这个表会改变这个系统,例如MPU立即生效。
数据同步屏蔽(DSB)指令作为一种特殊的存储器屏蔽指令。访问外部存储器操作完成之前,执行完成数据同步屏蔽指令(DSB)。执行数据同步屏蔽指令,在该指令没有完成以前不再执行任何指令——换句话说,执行完成所有的挂起操作。
数据存储屏蔽(DMB)指令作为一种存储器屏蔽指令。数据存储屏蔽(DMB)指令和数据同步屏蔽(DSB)指令有微小的差别。数据存储屏蔽(DMB)指令确保:数据同步屏蔽(DSB)指令执行完成之前,访问任意存储器;执行数据同步屏蔽(DSB)指令后,紧接着执行访问任意存储器操作。
当然还有影子寄存器。
好了,感觉自己写到差不多了,有什么不对的地方,请大家提出了,毕竟自己第二次写博客,什么都不懂,也就感觉对自己有用,就记录下来。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值