各位小伙伴,最近学习STM32F407遇到了很多的问题,有的问题被我解决了,有点还迟迟没有解决。通过遇到的这些问题,我有很多疑问,希望有知道的小伙伴能够解惑,谢谢各位啦。
1、在学习了内存管理一节当中,为什么要管理STM32内部的内存(SRAMIN和SRAMCC)? 难道STM32内部管理机制不好么? STM32内部是怎么管理这些内存的? 在哪里可以看到呢?
2、汇编文件startup_stm32f40_41xxx.s中分配的堆和栈是分配在那一片内存上的呢? SRAMCC还是SRAMIN呢? 全局变量和静态变量又是在哪里?
3、SRAMIN一共有128KB的大小,内存池占用了100KB,内存管理表大概占用了将近7BK,也就是说对于SRAMIN这片内存,用户自己使用了107KB的空间,只能使用mymalloc函数来申请空间。值留下了20KB左右的空间。如果第二个问题中的堆栈是在这里分配的,那么岂不是那个汇编文件就只有20KB的空间可以给堆栈使用。
4、SRMCC主要是用来干什么的? 从原子哥的注释可以看到是给CPU使用的,但是具体作用呢? ·
5、既然SRAMCC(共64KB)主要是给CPU使用的,意思是不是说用户不能使用呢? 还是说用户根本就访问不到这里的存储空间? SRAMCC分配了60KB的内存池,内存管理表使用了3.75KB,将近4KB,也就是说我们把SRAMCC全部都自己管理了。
6、Execution Region指的是哪个地方呢? 是内存么? 如果是,那么指得是SRAMCC还是SRMIN呢?
7、STM32的flash采用总线是的总线接入,那么它的flash的存储空间是可以任意访问的。也就是说我们下载进入flash中的代码是可以直接在flash中执行的,不用加载到ram。从网上博客了解到,其实代码需不需要加载到RAM,其实是可以自己控制的,分散加载脚本就是用来干这个的。那么,MDK是怎么判断用户的代码是否需要加载到RAM中呢? 还是所有的都不加载?
暂时先这些问题吧,希望知道的朋友能够答疑解惑,谢谢各位小伙伴了
非常感谢大神的回复,可以看的出来回答的很用心,同时也让我理解了很多以前有些模棱两可的知识点。通过您的回答,我又在网上找了写资料帮助我消化。1、在学习了内存管理一节当中,为什么要管理STM32内部的内存(SRAMIN和SRAMCC)? 难道STM32内部管理机制不好么? STM32内部是怎么管理这些内存的? 在哪里可以看到呢?
回复:STM32内部的内存是固定的,每申请一个全局变量(数组、结构体)那么这部分内存就被占用了 。在实际应用中有些函数需要一个很大的内存,但是做完事情后这部分内存就不需要了,如果用全局变量来实现,这样就太浪费了,如果定义局部变量那么栈(实际也为全局数组)就要定义很大,所以采用内存管理,在需要大内存的地方向内存池申请内存,用完了就释放,这样别的地方还可以向这个内存池申请内存。
STM32是没有MMU单元,所以没有内存管理机制。如果采用C语言标准库中的内存申请和释放函数,那么这个是向堆(实际也为全局数组)中申请内存的,而且效率不高。
对于CPU而言,所有的外设(外设、SRAM、FLASH)都是通过内存访问和控制的,通过不同地址来区分控制的区域,比如FLASH的起始地址为0X08000000,当你想这个地址进行读写的时候,CPU就知道是去操作FLASH,当你向0X20000000进行读写的时候,CPU就知道是去操作SRAM。其它外设都是如此,比如你向0X40011000进行读写,那么CPU就知道是去操作串口1的SR寄存器。
可以通过对应的数据手册,比如《STM32F4XX中文参考手册.PDF》中第2.3章节“存储器映射”,或者<STM32F405XX STM32F407XX>PDF中第4章节《Memory mapping》
这个问题回答的非常详细,一针见血,也让我理解了为什么要自己管理STM32内部的SRAM。以前都是不知所以,现在找到了起因,感觉任督二脉被打通了的感觉,非常感谢!!
2、汇编文件startup_stm32f40_41xxx.s中分配的堆和栈是分配在那一片内存上的呢? SRAMCC还是SRAMIN呢? 全局变量和静态变量又是在哪里?
回复:
堆和栈是通过链接文件来决定存放的地址,在链接文件中定义两个扇区,用来存放堆和栈,IAR中的链接文件名后缀为.icf,SW4STM32的链接文件名的后缀为.ld,KEIL MDK中也有链接文件,文件格式不记得了,可以百度出来。链接文件用来指出每个区域存放的地址(常数、代码、堆栈),这部分可能表述的不专业。
堆栈的地址可以通过修改链接脚本来修改存放的地址,STM32F407内部的SRAM分为 SRAM和CCM。
全局变量和静态变量全部存放在堆中,栈中用来存放局部变量。
通过自己浏览MDK的工程文件,我找到了MDK的链接文件,名字是以 “工程名.sct” 结尾的那个,对于STM32F407ZGT6自身有两片内存,但是使用的就知识其中的一片,也就是Target中的那个IRAM1,可以看到它前面够个勾勾,而IRAM2则没有,也就是说,如果在工程中没有选中IRAM2,这片内存其实就是上面所说的SRAMCCM那片内存,如果开发人员不自己管理这片内存,而且在工程当中又没有选中,那么这片内存相当于没有使用,所以需要自己管理,当然也可以在工程当中选中,使用相应的配置使用这片内存。 从底下截图的连接脚本中就可以看出来这个工程只是用了SRAMIN,没有使用SRMACCM。
另外,对于您回复的“全局变量和静态变量全部放在堆中”,其实我不是很理解,我的理解是:全局变量和静态变量是在RW段和ZI段,如果全局变量或者是静态变量有初始化,并且不为0,那么位于RW段。而没有初始化或者初始化为0的全局变量或静态变量是位于ZI段。在MDK当中,ZI段通常还包括了栈空间和堆空间。 所以在程序当中它们的属性应该是:代码——>Code 常量——>RO-data 初始化非0的全局变量和静态变量——> RW-data 初始化为0的全局变量和静态变量——>ZI-data 局部变量——>ZI-data栈空间
malloc分配的变量——>ZI-data堆空间。
3、SRAMIN一共有128KB的大小,内存池占用了100KB,内存管理表大概占用了将近7BK,也就是说对于SRAMIN这片内存,用户自己使用了107KB的空间,只能使用mymalloc函数来申请空间。值留下了20KB左右的空间。如果第二个问题中的堆栈是在这里分配的,那么岂不是那个汇编文件就只有20KB的空间可以给堆栈使用。
回复:
是的
4、SRMCC主要是用来干什么的? 从原子哥的注释可以看到是给CPU使用的,但是具体作用呢? ·
回复:
CCM内存的主要的特点是CPU取值非常快(个人理解),这部分只能由CPU访问,所以不能用DMA来指定这个区域。主要用于跑算法、图片解码(STEMWIN)及运行操作系统的时候当操作系统内存(提升速度,但是如果调用操作系统的内存,则不能用DMA来指定这个内存)
原来如此,这么一说,我就知道怎么使用这片空间啦,谢谢。
5、既然SRAMCC(共64KB)主要是给CPU使用的,意思是不是说用户不能使用呢? 还是说用户根本就访问不到这里的存储空间? SRAMCC分配了60KB的内存池,内存管理表使用了3.75KB,将近4KB,也就是说我们把SRAMCC全部都自己管理了。
回复:
用户可以访问这个CCM内存区域,可以直接通过访问地址0X20000000来实现访问。用内存管理来管理CCM,是为了提升内存使用率。
6、Execution Region指的是哪个地方呢? 是内存么? 如果是,那么指得是SRAMCC还是SRMIN呢?
回复:
没有找到Execution Region,如果是问__attribute__((at(0XXXXXXX))) 关键字,其意思是把这部分存放在一个指定的地址,如果想知道这个地址是什么,则看对应的 Memory mapping 即可。不同地址对应不同功能。
这个应该说的是执行域,应用程序不是有加载域和执行域嘛(昨天刚刚学的,用上了,哈哈。。),之所以问这个问题是因为我前几天碰到了一个问题,可以看底下的截图,这里的加载域(Execution Region) 没有空间了,当时其实不是很懂,找了很久,也是发的帖子解决的,其实就是内存上的问题,堆栈分配的不合理,某个地方使用太多导致的。这个问题主要是由于我移植的FreeRTOS的分配的内存空间太多了,而SRAMIN有没有那么大才导致出现这个问题的。
7、STM32的flash采用总线是的总线接入,那么它的flash的存储空间是可以任意访问的。也就是说我们下载进入flash中的代码是可以直接在flash中执行的,不用加载到ram。从网上博客了解到,其实代码需不需要加载到RAM,其实是可以自己控制的,分散加载脚本就是用来干这个的。那么,MDK是怎么判断用户的代码是否需要加载到RAM中呢? 还是所有的都不加载?
回复:
你说的分散加载脚本即为链接文件,此脚本中指出代码数据、常数、变量的存放地址,通过修改此链接文件即可修改地址,MDK是通过设置《Target》中的地址来指定代码存放区域。如果想把代码全部在RAM中运行,则你需要先把代码全部写入FLASH,然后代码中把FLASH中的代码数据全部拷贝到SRAM中,然后中断重映射到SRAM中。这部分我没有在STM32上操作过,只是猜测操作流程。
再次感谢您,真的让我学到了很多,谢谢!!
一周热门 更多>