嵌入式linux开发 (十九) 内存管理(3) STM32F407ZGT6内存管理(MPU-Without)

本文主要是介绍嵌入式linux开发 (十九) 内存管理(3) STM32F407ZGT6内存管理(MPU-Without),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

硬件
  • 正点原子探索者开发板 STM32F407ZET6 cortex-M4 ARMv7
	-内置SRAM:196KBUp to 192+4 Kbytes of SRAM including 64 Kbyte of CCM (core coupled memory) data RAMSROM(用户可编程):1MUp to 1 Mbyte of Flash memory-外扩IS62WV51216:1MB,SRAM,FSMC接口// 为什么不扩展SDRAM,STM32F407 FSMC接口支持SRAM,NAND,NOR,PSRAM. 不支持SDRAM.STM32的高端产品429/439添加了新的外设,SDRAM控制器(FMC总线)24C02:256B,EEPROM,I2C接口W25Q128:16M,NorFlash,SPI接口
硬件对内存的管理
  • 总述系统架构
    在这里插入图片描述
  • 系统架构分析
8条主控总线,7条被控总线形成的总线矩阵
撇开 DMA MAC USB 3个主控设备
撇开 AHB1 AHB2 等 被控低速设备关注的点有1.CCM RAM(64KB)2.ARM cortex-M43.FLASH4.SRAM1 112KB5.SRAM2 16KB6.FSMC
在撇开 FLASH,ARM cortex-M4. 剩下4个内容:3个片上sram(系统sram)1个FSMC控制器另外,还有1个备份sram(4KB)没有出现在系统架构里
  • sram
STM32F405xx/07xx 片上带有 4 KB 备份 SRAM(请参见 第 5.1.2 节:电池备份域 )192 KB 系统 SRAM。 //系统 SRAM 可按字节、半字(16 位)或全字(32 位)访问。读写操作以 CPU 速度执行,且等待周期为 0。备份 SRAM 分为1个块:● 备份域还包括仅可由 CPU 访问的 4 KB 备份 SRAM,可被 32 位、16 位、8 位访问。使能低功耗备份调压器时,即使处于待机或 V BAT 模式,备份 SRAM 的内容也能保留。一直存在 V BAT 时,可以将此备份 SRAM 视为内部 EEPROM。
系统 SRAM 分为3个块:● SRAM1:映射在地址 (0x2000 0000 - 0x2001 BFFF)112 KB 块, 可供所有 AHB 主控总线访问。● SRAM2:映射在地址 (0x2001 C000 - 0x2001 FFFF)16 KB 块,可供所有 AHB 主控总线访问。● CCM RAM:映射在地址 (0x1000 0000-0x1001 0000)64 KB 块,只能供 CPU 通过数据总线访问。
  • FSMC控制器 — 内存控制器
    在这里插入图片描述

在这里插入图片描述

0xA000 0000 - 0xA000 0FFF FSMC 控制寄存器
0x6000 0000 - 0x6FFF FFFF 是 sram的地址(256M)
// 实际用的 sram为 一片IS62WV51216,共1M,地址范围为0x6000 0000 - 0x600F FFFF
  • BOOT配置及内存映射
复位之后,根据BOOT0,BOOT1的配置,形成三种映射方式的一种,然后从0x0000 0000 启动1.flash(总述系统架构图 中 Flash的一部分,1MB,0x0800 0000 - 0x080F FFFF)映射到 0x0000 0000 - 0x03FFFFFF(64M) // 主flash : 4 个 16 KB 扇区、1 个 64 KB 扇区和 7 个 128 KB 扇区, 共 1024KB2. SRAM1(112 KB,0x2000 0000 - 0x2001 BFFF)映射到 0x0000 0000 - 0x03FFFFFF(64M)3. 系统flash(总述系统架构图 中Flash的一部分,30KB,0x1FFF 0000 - 0x1FFF 77FF) 映射到 0x0000 0000 - 0x03FFFFFF(64M)注意: FSMC 块1的前两个区域(每个区域64MB)也可以映射到 0x0000 0000 - 0x03FFFFFF(64M) ,但是不能用于启动.(在启动时不会做这个映射)//  0x0400 0000 - 0x07FF FFFF -> 0x0000 0000 - 0x03FFFFFF
-----------------------------------
#### BOOT不同启动设备实际用途1. 主flash : 执行用户代码. sample:led点灯程序2. sram1 : 可用于解锁flash	https://www.cnblogs.com/linux-embedded/p/9462897.html在实验时通过sram启动减少对flash的擦除 https://www.cnblogs.com/alvis-jing/p/3662158.html3. 系统flash : 执行ST烧写的代码,用于通过以下串行接口重新编程 主Flash
软件对内存的管理
  • 参考代码
  • 整体分析
startup_stm32f40_41xxx.s 中有对 栈(stack) 和 堆(heap)的初始化
1. RESET
2. XIP on 主Flash (属于硬件对内存的管理,代码开始之后,就开始了软件对内存的管理,硬件对内存的管理退出舞台)2.1 Reset_Handler2.2 SystemInit // 专门的跳转指令 B、BL、BX、BLX 和 BXJ ,不会使用 .stack2.3 _main
3. 代码执行序列到_main3.1 将 non-root (RO and RW) execution regions 从 加载地址 拷贝到 执行地址.如果data sections被压缩,则将它们从加载地址(加载区域)解压缩到执行地址(执行区域)//具体实现在(InRoot$$Sections) ------------对应 .code 段 和 .ro-data 段// 其实 RO(RO-data) 的 加载地址 和 执行地址是一样的.都在0x08000000(主Flash上)------------对应 .data 段// RW(RW-data) 加载地址在 0x08000000 + sizeof(RO-data),执行地址在0x20000000(SRAM1)------------对应 .bss 段// ZI(ZI-data) 加载地址在 0x08000000 + sizeof(RO-data),执行地址在0x20000000(SRAM1) // 其实这一段并没有加载,因为加载了也要清0,所以干脆留空.只记录 ZI-data 执行地址的开始地址和结束地址------------对应 .bss 段3.2. 将ZI regions清03.3. 跳转到__rt_entry------------对应 .stack 段 和 .heap段3.3.1. Sets up the stack and the heap by one of a number of means that include calling __user_setup_stackheap() , calling __rt_stackheap_init() , or loading the absolute addresses of scatter-loaded regions.// 栈的初始化不涉及到内存,只涉及到SP寄存器// 堆的初始化涉及到内存, 1.清零堆空间 2.在堆中建立数据结构来对堆进行分块 // 从现在开始,内存分段(软件对内存的布局)已经完成// 下面就开始使用前面代码建立的 .stack .heap .data .bss .code .ro-data 段进行操作3.3.2. Calls __rt_lib_init() to initialize referenced library functions, initialize the locale and, if necessary, set up argc and argv for main() . For C++, calls the constructors for any top-level objects by way of __cpp_initialize__aeabi_ .3.3.3. Calls main() , the user-level root of the application. From main() , your program might call, among other things, library functions.3.3.4. Calls exit() with the value returned by main() 
    1. 栈大小定义
; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
; <h> Stack Configuration
;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>Stack_Size      EQU     0x00000400AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp定义一个宏 Stack_Size  为 0x00000400汇编一段空间(定义数据段),空间名为 STACK,不初始化,可读写, 8(2^3)字节边界对齐。从 STACK(不确定)开辟一段空间给空间STACK,大小为 Stack_Size(0x00000400) 字节,即从(__initial_sp -0x000003FF,__initial_sp),不初始化栈顶标号为__initial_sp ,它根据堆栈大小,由编译器自动生成说明:AREA命令指示汇编器汇编一个新的代码段或者数据段。Contrx-M3的指令地址要求是字边界对齐(4字节),但是代码段是要求8字节边界对齐的。NOINIT:指定此数据段仅仅保留了内存单元,而没有将各初始值写入内存单元,或者将各个内存单元值初始化为0
    1. SP寄存器的初始化
; Vector Table Mapped to Address 0 at ResetAREA    RESET, DATA, READONLYEXPORT  __VectorsEXPORT  __Vectors_EndEXPORT  __Vectors_Size__Vectors       DCD     __initial_sp               ; Top of StackDCD     Reset_Handler              ; Reset Handler
//__Vectors 为 0x00000000
//DCD命令 分配一个双字(32bits)的内存空间,并将 __initial_sp 存入,并4字节对其.
//__initial_sp 为 之前定义的栈的栈顶地址,cortex-m3手册中规定 0x00000000 必须放 栈顶地址
    1. 堆大小的定义
; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>Heap_Size       EQU     0x00000200AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit定义一个宏 Heap_Size 为 0x00000200汇编一段空间,空间名为 HEAP,不初始化,可读写,8字节边界对齐__heap_base 为 不确定值从 Heap_Mem (__heap_base ) 开辟一段空间给 HEAP,大小为 Heap_Size(0x00000200)字节,即从(__heap_base - __heap_base+0x000001FF),不初始化堆顶标号 为 __heap_limit(__heap_base+0x000001FF)
    1. 堆初始化
Reset_Handler__main__rt_entry__user_setup_stackheap__rt_stackheap_init
栈和堆位置的确定(0x2000 0000 地址附近的符号分布)
在链接完之后,会生成map文件,在map文件中可以查到
__heap_base 和 __initial_sp  的位置, 总的来说位于 SRAM1内(112 KB(0x2000 0000 - 0x2001 BFFF))// __initial_sp                             0x20000738   Data           0  startup_stm32f40_41xxx.o(STACK)
AREA    STACK, NOINIT, READWRITE, ALIGN=3// STACK                                    0x20000338   Section     1024  startup_stm32f40_41xxx.o(STACK)AREA    HEAP, NOINIT, READWRITE, ALIGN=3//  HEAP                                     0x20000138   Section      512  startup_stm32f40_41xxx.o(HEAP)// .bss                                     0x200000d4   Section       96  libspace.o(.bss)// .bss                                     0x2000000c   Section      200  usart.o(.bss)// .data                                    0x20000004   Section        6  usart.o(.data)
fac_ms                                   0x20000002   Data           2  delay.o(.data) // delay.o(.data)
fac_us                                   0x20000000   Data           1  delay.o(.data) // delay.o(.data)// .data                                    0x20000000   Section        4  delay.o(.data)
  • 代码位置的确定(0x0800 0000 地址附近的符号分布)
AREA    |.text|, CODE, READONLY// .text                                    0x08000228   Section       64  startup_stm32f40_41xxx.o(.text)
...
AREA    RESET, DATA, READONLY// RESET                                    0x08000000   Section      392  startup_stm32f40_41xxx.o(RESET)

这篇关于嵌入式linux开发 (十九) 内存管理(3) STM32F407ZGT6内存管理(MPU-Without)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/355546

相关文章

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法

《ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法》本文介绍了Elasticsearch的基本概念,包括文档和字段、索引和映射,还详细描述了如何通过Docker... 目录1、ElasticSearch概念2、ElasticSearch、Kibana和IK分词器部署

Linux流媒体服务器部署流程

《Linux流媒体服务器部署流程》文章详细介绍了流媒体服务器的部署步骤,包括更新系统、安装依赖组件、编译安装Nginx和RTMP模块、配置Nginx和FFmpeg,以及测试流媒体服务器的搭建... 目录流媒体服务器部署部署安装1.更新系统2.安装依赖组件3.解压4.编译安装(添加RTMP和openssl模块

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

基于Python开发PPTX压缩工具

《基于Python开发PPTX压缩工具》在日常办公中,PPT文件往往因为图片过大而导致文件体积过大,不便于传输和存储,所以本文将使用Python开发一个PPTX压缩工具,需要的可以了解下... 目录引言全部代码环境准备代码结构代码实现运行结果引言在日常办公中,PPT文件往往因为图片过大而导致文件体积过大,

Linux环境变量&&进程地址空间详解

《Linux环境变量&&进程地址空间详解》本文介绍了Linux环境变量、命令行参数、进程地址空间以及Linux内核进程调度队列的相关知识,环境变量是系统运行环境的参数,命令行参数用于传递给程序的参数,... 目录一、初步认识环境变量1.1常见的环境变量1.2环境变量的基本概念二、命令行参数2.1通过命令编程