MCU(Cortex - M3/M4)启动加载过程和内存分配原理 笔记

这篇具有很好参考价值的文章主要介绍了MCU(Cortex - M3/M4)启动加载过程和内存分配原理 笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        最近发现对基础不太熟悉,写篇笔记记录一下MCU启动到用户C语言运行,之前做了那些工作,同时flash和Ram又分别保存了那个数据,每一段又是什么意义,方便后续自己忘记了,查阅。

一、 MCU启动

       在MCU上电/复位之后到程序开始运行前,Cortex - M处理器会从存储器中读取出两个字(注意在32位系统中一个字位32bit),即读取地址0x000000000x00000004的数据,这两个地址存放的值分别为MSP(Main stack pointer)主栈指针的初始值,以及代表复位处理处理起始地址的复位向量。处理器读出这两个字用于初始化MSP主栈指针,和PC(Program Counter)程序计数器。

Cortex - M3和M4的寄存器组如下图所示。(图片参考了《ARM Cortex - M3和Cortex - M4权威指南》第三版

mcu 启动过程,# 单片机类,单片机,笔记,嵌入式硬件

 文章来源地址https://www.toymoban.com/news/detail-616671.html

需要注意的是,主流MCU的启动方式一般有3种,GD32F4为例,通过配置外部引进BOOT0、BOOT1的电平状态选择启引导方式。区别就是将0x00000000映射到不同的地址,如果选择FLASH启动处理器对0x00000000的读取其实就是对0x08000000地址的读取。

下图为GD32F4xx的启动引导配置说明(截图来源《GD32F4xx_User_Manual_Rev2.8_CN》

mcu 启动过程,# 单片机类,单片机,笔记,嵌入式硬件

 二、启动文件 -> 用户主函数执行

从上电开始,这期间MCU在跑的程序,其实是启动文件.s编写的程序内容。在MCU工程中,会有一个.s的启动文件,一般这个启动文件由器件厂商提供。

mcu 启动过程,# 单片机类,单片机,笔记,嵌入式硬件

启动文件的功能主要为:

1–初始化栈指针MSP=_initial_sp。

简单来讲就是在程序第一个字放置了堆栈指针MSP的值。

2–初始化复位程序计数寄存器值=Reset_Handler(弱函数)。

简单来讲就是在程序第二个字放置了Reset_Handler复位中断的函数入口地址

3–初始化异常/ 中断向量表。

简单来讲就是在第3字后,放各个系统各种类型中断的函数入口地址(弱函数,如果用户未定义默认指向Default_Handler ),这些各种中断的入口地址,我们一般称之为中断向量表。

4–系统时钟配置。

这个是在Reset_Handler函数里面,里面会调用一个函数,有些启动文件没有默认定义这个函数,导致有些工程的SystemInit函数必须由用户定义。

5– C库函数_main初始化用户堆栈的调用。

_main是进入main函数之前的初始化函数,可以理解为,进入main之前先调用了__main()函数去初始化一些内容,然后再到我们可以在C环境中编写的程序。

 具体启动文件内容详解,可以去看其他博主的介绍,这里列出链接:

STM32启动文件讲解_XYJ_Tiger的博客-CSDN博客

STM32F10x启动文件详解_stm32f10x_md_超级网吧的博客-CSDN博客

 3-STM32启动文件详解_南山府嵌入式的博客-CSDN博客

需要注意的是上面介绍的是.s文件的功能,实际程序跑起来后运行顺序如下:

1.赋值MSP。

2.进入Reset_Handler去处理

        Reset_Handler中会进入SystemInit 和 __main函数,然后就进入C语言运行环境。

注意:如果Reset_Handler处理期间有中断的话,就会跳去中断向量表然后找到中断处理函数地址,再跳过去处理中断。这也是Cortex - M3/M4内核先赋值MSP的原因所在。

那问题来了,__main的函数源码在哪呢?参考其他博主的博客。

MDK __main()代码执行分析_keil _maim_TS_up的博客-CSDN博客

三、 MCU内部Flash、RAM中的数据

我们写个程序,用编译后最终会生成一个可以烧写入芯片flash的可执行文件,常见的两种,一种是.bin,一种是.hex文件。

STM32的内存又有了6个储存数据段3种储存属性区的概念

参考下文链接:

两种存储器,三种内存大小,六段段

MDK编译出来后,会分为4个中类型

Code、RO Data、RW Data、ZI Data

mcu 启动过程,# 单片机类,单片机,笔记,嵌入式硬件

Code :代表执行的代码,程序中所有的函数,存在flash中;
RO-data :代表只读数据,程序中所定义的全局常量数据(局部常量放在栈区),存在flash中;
RW-data:代表已初始化的读写数据,程序中定义并且初始化的全局变量和静态变量,存在flash中,程序运行后(具体由__main来实现,会将在Flash区域中的RW-data拷贝到RAM中);
ZI-data:zero initial,就是程序中用到的变量并且被系统初始化为0的变量的字节数 (在ram中)
 

其实我主要关心的是,程序编译出来后,数据是怎么放置的,程序运行之后数据又是怎么放置的。

mcu 启动过程,# 单片机类,单片机,笔记,嵌入式硬件

 如图,编译出来的数据会放到Flash中,运行的时候,由用户的配置,启动文件会设置堆栈指针,__main函数会将RW-data搬运到RAM中。Heap根据程序的运行申请的内存会增长,Stack向下增长,,当两者指针交叉时,系统出栈回的数据就是混乱的,就会死机。

事实上,在IAR或者MDK编译器中,可以特别声明某段代码,将他们整个拷贝到RAM中,在RAM里面运行,因为RAM的读写速度快很多,以此加快该断代码的运行速度。

 

到了这里,关于MCU(Cortex - M3/M4)启动加载过程和内存分配原理 笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【ARM Cortex-M 系列 1.1 -- Cortex-M33 与 M4 差异 详细介绍】

    请阅读 【嵌入式开发学习必备专栏 之 Cortex-Mx 专栏】 在移植 RT-Thread 到 瑞萨RA4M2(Cortex-M33)上时,遇到了hardfault 问题,最后使用了Cortex-M4中的调度相关的函数后,OS 可以正常调度了。所以这里做下 M33与 M4的关系梳理。 ARM Cortex-M33 和 Cortex-M4 都是 ARM 公司设计的32位RISC微处理

    2024年01月21日
    浏览(44)
  • JVM运行时区域——对象创建内存分配过程

            新创建的对象 , 都存放在伊甸园区域 ,当垃圾回收时,将伊甸园区域的垃圾数据销毁,然后将存活的对象转移到幸存者0区域,之后创建的新的对象还是存放在伊甸园区域,等到再次垃圾回收后,将伊甸园区域和幸存者0区域中存活的对象一起转移到幸存者1区域中

    2024年02月15日
    浏览(46)
  • CmBacktrace库详解-以Cortex-M3/M4+FreeRTOS为例

            相信很多做FreeRTOS开发的同学在查找偶现的死机问题时,都希望能有一个像Linux core dump一样的机制,能够将死机现场的寄存器信息和调用栈保存起来,但原生的FreeRTOS并没有提供类似机制。朱天龙老师的CmBacktrace库则是提供了一种针对ARM Cortex-M系列MCU的死机现场和断

    2024年02月09日
    浏览(50)
  • JVM面试题-JVM对象的创建过程、内存分配、内存布局、访问定位等问题详解

    内存分配的两种方式 指针碰撞 适用场合:堆内存 规整 (即没有内存碎片)的情况下。 原理:用过的内存全部整合到一边,没有用过的内存放在另一边,中间有一个分界指针,只需要向着没用过的内存方向将该指针移动对象内存大小位置即可。 使用该分配方式的GC收集器:

    2024年02月08日
    浏览(49)
  • DPDK系列之二十八内存分配启动和初始化

    在前面对DPDK中的内存进行了各个模块的分析,这次开始整体流程的分析说明。重点是分析一下内存从开始准备到最终应用的过程,从而把各个分别讲的模板贯穿起来,从而能够更好的了解和认识DPDK中内存的使用。 DPDK中,启动时对内存的处理如下: 1、大页内存的处理 这个在

    2024年02月10日
    浏览(52)
  • Cortex-M3/M4内核中断及HAL库函数详解(1):中断相关寄存器

    Keil uVision5 Cortex M3权威指南(中文) Cortex M3与M4权威指南 stm32f407的HAL库工程 STM32F4xx中文参考手册 在Cortex-M3/M4内核上搭载了一个异常响应系统,支持为数众多的系统异常和外部中断。其中,Cortex-M3/M4内核包括15个系统异常,大部分系统异常的中断优先级都可以设置。外部中断由

    2024年01月21日
    浏览(49)
  • 操作系统原理 —— 内存动态分区分配算法(二十一)

    在上一个章节我们讲了 内存连续分配 的几种方式,有单一、固定、动态这三种,在固定、动态这种里面,操作系统会记录空闲分区表,这个表是用来记录当前空闲的内存。 那么在之后有新的进程装入内存,需要从空闲分区表中找到一块比较合适的空闲内存,该怎么找呢?

    2024年02月08日
    浏览(50)
  • Unity教程 ECS 内存分配器原理详解

    一、UnityECS内存分配器的作用 在传统的面向对象编程模式中,我们通常使用堆内存来存储实体和组件数据。然而,由于实体和组件数据的规模通常非常庞大,使用堆内存进行分配和管理会导致内存碎片化和性能下降的问题。为了解决这个问题,UnityECS引入了内存分配器的概念

    2024年02月15日
    浏览(41)
  • STM32内核——Cortex M3

    目录 前言 一、STM32系统架构 二、Cortex M3内核 1、NVIC(嵌套向量中断控制器) 2、存储器保护单元(MPU) 3、总线接口 4、寄存器(重点) 通用寄存器 特殊功能寄存器 5、流水线 三、存储结构(重点) 1、存储器空间分配 2、位带操作 3、端模式 4、非对齐访问  四、工作模式和

    2024年02月20日
    浏览(37)
  • Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现

    Keil uVision5 Cortex M3权威指南(中文) Cortex M3与M4权威指南 stm32f407的HAL库工程 STM32F4xx中文参考手册 打开stm32f407的HAL库工程,可以在CMSIS-Include-core_cm4.h内找到有关NVIC寄存器设置的相关函数: 该函数操作步骤如下: (1)读取SCB-AIRCR旧值,保存到reg_value (2)将reg_value的bit31-16(访

    2024年01月20日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包