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

news2024/11/16 5:26:17

        最近发现对基础不太熟悉,写篇笔记记录一下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的启动方式一般有3种,GD32F4为例,通过配置外部引进BOOT0、BOOT1的电平状态选择启引导方式。区别就是将0x00000000映射到不同的地址,如果选择FLASH启动处理器对0x00000000的读取其实就是对0x08000000地址的读取。

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

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

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

启动文件的功能主要为:

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

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

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

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

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

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/677087.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WireShark常用协议抓包与原理分析

1.ARP协议(地址解析协议) nmap 发现网关nmap -sn 192.168.133.2wireshark 抓请求包和响应包 arp请求包内容 arp响应包内容 总结:请求包包含包类型(request),源IP地址,源MAC地址,目标IP地址,目标MAC地址(未知,此处为全0);响应包包含包类型(reply),源IP地址,源…

DAY28:回溯算法(三)组合总和Ⅲ+电话号码字母组合

文章目录 216.组合总和Ⅲ思路树形结构 完整版debug测试逻辑错误:没有输出 剪枝操作剪枝版本continue的用法剪枝最后是continue还是return的讨论 17.电话号码的字母组合思路树形结构 伪代码字符串中的字符2转化成int的方法字符串字符与int转换补充字符串与字符 完整版…

CTF-Show密码学【摩斯码、培根密码】

萌新 密码33 一、题目信息 题目名称:我想吃培根题目描述:-- — .-. … . …–.- … … …–.- -.-. — — .-… …–.- -… …- - …–.- -… .- -.-. — -. …–.- … … …–.- -.-. — — .-… . .-. …–.- – – -… -… – -… – -… – – – -…

ASP.NET Core MVC 从入门到精通之缓存

随着技术的发展,ASP.NET Core MVC也推出了好长时间,经过不断的版本更新迭代,已经越来越完善,本系列文章主要讲解ASP.NET Core MVC开发B/S系统过程中所涉及到的相关内容,适用于初学者,在校毕业生&#xff0c…

理解KMP

KMP 问题 字符串匹配问题,问字符串 str1中是否存在连续的子串与字符串str2相等,存在返回子串的起始位置,否则返回-1 思路 传统做法是依次遍历str1中的每个字符作为起始位置,看是否能凑出字符串str2. KMP算法就是对传统做法的一种加速&am…

【Linux】软件包管理器yum与环境开发工具vim

【Linux】系列文章目录 【Linux】基础常见指令:http://t.csdn.cn/hwLPb 【Linux】基本权限:http://t.csdn.cn/faFZg 目录 前言 一、软件包管理器yum 1.什么是软件包? 2. yum的使用 (1)包文件查询 &#xff08…

EMA:基于跨空间学习的高效多尺度注意力模块

文章目录 摘要1、 简介2、相关工作3、高效多尺度注意力机制3.1、回顾坐标注意力(CA)3.2、多尺度注意力(EMA)模块 4、实验4.1、CIFAR-100上的图像分类4.2、ImageNet-1k上的图像分类4.3、MS COCO上的目标检测4.4、基于VisDrone的目标检测 5、消融实验6、 结论 摘要 https://arxi…

MIT 6.S081 Lab Six

MIT 6.S081 Lab Six 引言Copy-on-Write Fork for xv6问题解决方案Implement copy-on write (hard)代码解析 可选的挑战练习 引言 本文为 MIT 6.S081 2020 操作系统 实验六解析。 MIT 6.S081课程前置基础参考: 基于RISC-V搭建操作系统系列 Copy-on-Write Fork for xv6 虚拟内…

开发之路,穷且益坚,不坠青云之志

引言 2023毕业季,距离笔者毕业已过2年有余。 互联网从业环境由盛转衰,互联网从业者数量剧增,市场竞争异常激烈,原本的利润空间被不断挤压,以至于很多开发者对互联网已经失去了信心与激情。 互联网的市场份额依旧是占…

vulntarget-j内网靶机write-up

文章目录 第一部分 获取边界服务器0x01 漏洞扫描0x02 漏洞利用第二部分 信息收集+代理0x01 连接工具0x02 进行信息收集0x03 sock代理设置第三部分 内网漫游0x01 通过代理获取服务器0x02 信息收集-获取账号信息0x03 上线CS0x04 远程访问免责声明摘抄第一部分 获取边界服务器 0x0…

JSP 在线药品管理系统用myeclipse定制开发sqlserver数据库网页模式java编程jdbc

一、源码特点 JAVA 在线药品管理系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 JSP 在线药品管理系统用myeclipse定制开发sqls 二、功能介绍 此次系统主要在JSP…

go context详解

文章目录 摘要1. context接口2. 实现context接口的类型2.1 emptyCtx2.2 valueCtx2.3 cancelCtx2.4 timerCtx 摘要 Context是go语言用于上下文管理的包,主要用于携程间的上下文管理,控制携程按时或者按时间取消执行。多个Context按树形或者链表的结果向前…

深圳阿里云代理商:阿里云服务器的可用区和地域选择有哪些考虑因素?如何优化性能?

阿里云服务器的可用区和地域选择有哪些考虑因素?如何优化性能?   选择阿里云服务器时,可用区和地域选择是一个非常关键的环节。本文将为您详细解析在这个过程中需要考虑的因素以及如何优化性能。   一、阿里云服务器的可用区和地域选择的…

Linux进程编程、fork函数范例详解 ( 5 ) -【Linux通信架构系列 】

系列文章目录 C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 期待你的关注哦!!! 现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。 Now everything is for the…

Spring高手之路6——Bean生命周期的扩展点:BeanPostProcessor

文章目录 1. 探索Spring的后置处理器(BeanPostProcessor)1.1 BeanPostProcessor的设计理念1.2 BeanPostProcessor的文档说明 2. BeanPostProcessor的使用2.1 BeanPostProcessor的基础使用示例2.2 利用BeanPostProcessor修改Bean的初始化结果的返回值2.3 …

【Linux工具】yum指令、vim的使用和修改信任白名单

【Linux工具】yum指令、vim的使用和修改信任白名单 目录 【Linux工具】yum指令、vim的使用和修改信任白名单软件包rzsz查看软件包 安装软件卸载软件vim的使用vim的三种模式vim的基本操作vim命令模式命令集vim末行模式命令集vim操作总结 简单vim配置修改信任白名单 作者&#xf…

第四章 进程同步

目录 一、进程同步、进程互斥 1.1 进程同步 1.2 进程互斥 二、信号量机制 2.1 整型信号量 2.2 记录型信号量 三、用信号量实现进程互斥、同步、前驱关系 3.1 信号量机制实现进程互斥 3.2 信号量机制实现进程同步 3.3 信号量机制实现前驱关系 四、生产者-消费者问题…

【MySQL】· 一文了解四大子查询

前言 ✨欢迎来到小K的MySQL专栏,本节将为大家带来MySQL标量/单行子查询、列子/表子查询的讲解✨ 目录 前言一、子查询概念二、标量/单行子查询、列子/表子查询三、总结 一、子查询概念 子查询指一个查询语句嵌套在另一个查询语句内部的查询,这个特性从My…

MySQL - 第7节 - MySQL内置函数

1.日期函数 1.1.常用的日期函数 常用的日期函数如下: 1.2.current_date函数 current_date函数用于获取当前的日期。如下: 1.3.current_time函数 current_time函数用于获取当前的时间。如下: 1.4.current_timestamp函数 current_timestamp函数…

计组:各硬件工作原理

目录 ​编辑程序指令执行流程 程序执行指令前 执行各指令的顺序 程序(每一条)指令执行具体步骤 以第一步为例: 取指令(#1~#4) 初:(PC)0,指向第一条指令的存储地址 #1&#x…