IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> stm32启动过程、cortex-m3架构、堆栈代码位置、编译汇编链接分析 -> 正文阅读

[嵌入式]stm32启动过程、cortex-m3架构、堆栈代码位置、编译汇编链接分析

一、 寄存器、架构、工作流程

1.这里以stm32的架构:cortex-m3(也即ARMv7)的寄存器的作用、在指令取,指令的译码,指令的执行在其中的作用以及是如何配合实现代码的执行的

哈佛结构和冯诺依曼结构是如何体现的?

编译后的代码为什么分为code、堆、栈、bss、data、符号等部分,分别存储在哪些地方?

首先看寄存器

寄存器分为寄存器组,和外设寄存器
寄存器组对用户是不可见的(用户不能直接操作),它是CPU处理数据时需要调用的
外设寄存器对用户是可见的(用户可以通过地址的映射来对寄存器操作,从而控制相应的外设动作)

在这里插入图片描述
上面的是寄存器组,是在Cortex-M3中用来临时存放运算的数据或者指示程序运行的位置

1、 寄存器架构

参考官方Cortex-M3权威指南

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

二 、总线与各个部件之间的关系(主要是I-Code Bus、D-Code Bus、System Bus)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

上图所示的指令总线与数据总线与CM3内部的数据总线和数据总线不一样,具体可以看下面Cortex-M3内部结构图,而且上图的两个总线共用一个总线矩阵,就导致取指令和访问数据不能同时访问flash(在CM3里,指令和数据都是存放在flash中,部分数据存放在SRAM中,具体可以看指令和数据在stm32中存放的结构那一节),

而CM3外部总线部分是有芯片产商来决定,所以stm32的指令和数据总线是由意法半导体来设计制造的,具体架构如下图所示,可以看到该架构,指令和数据总线并没有共用一个总线矩阵,数据总线和系统总线是共用总线矩阵,从Cortex-M3的地址映射关系(从存储器映射来看stm32架构(内存与外设)那一节和指令和数据在stm32中存放的结构那一节),可以知道数据总线是是访问flash中的程序编译好后生成的静态数据(初始化的全局变量、 ),系统总线是访问SRAM中程序运行过程中产生的动态数据(局部变量、)

因为静态数据和动态数据不会同时访问,所以不用设计成可以同时访问的,也就可以共用一个总线矩阵
而读取指令和访问数据是可以同时进行的,所以就没有共用一个总线矩阵,这里就体现了哈佛结构的特性,指令与数据可以同时访问

下面这个是32官方参考手册,才是我们真正使用stm32的MCU具备的系统结构

在这里插入图片描述

体系结构:哈佛结构与冯诺依曼结构的区别

上述I-code与D-code与flash的连接就体现了哈佛结构的特性:
在这里插入图片描述
CPU采用的是哈佛结构还是冯诺依曼结构?

复位有三种启动方式,从哪里开始启动、启动代码的所在的位置

复位后启动的位置都是从内存地址为0x00000000的位置开始,如下图:
在这里插入图片描述
但是根据boot引脚的硬件配置,有三种不同的硬件映射方式,将处于内存(Flash、system memery、SRAM)中不同地址(参考上面存储器映射)的启动代码,映射到0x00000000这个位置;

在这里插入图片描述

一般都是将位于Flash的启动代码映射到0地址的位置,这个时候,取指令是通过ICode总线,取数据靠的是DCode和System 总线,通过不同的总线和总线矩阵,以及流水线的实现,可以实现指令和数据的同时访问,这样就体现了哈佛结构;

三、从存储器映射来看stm32架构(内存与外设)

STM32架构相关

内存的映射就是数据和代码实际存放的地址

外设映射的地址其实是控制该外设的寄存器的地址

整个架构说的就是处理核心、内存与外设寄存器它们的关系,是怎么通过各种总线连接起来的

如果取指令和访问数据能同时进行,那么这种总线连接的关系,就可以称之为哈佛结构;

存储器地址映射如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以上三图都是在 Cortex-M3权威指南 中定义的,说明该架构的这些存储器映射是有arm定义好的,不是由芯片生产厂商来定义

下图为 stm32中文参考手册中定义的,这具体的就是有芯片生产厂家来定义的,主要介绍了code区、SRAM、片上外设(编程时主要就是用这里的地址来控制相应的模块)
在这里插入图片描述

由上四图可知,外设分为片上外设(USART、GPIO等模块)、片外外设(这个需要自己扩展)、片内外设(中断NVIC、路径跟踪TPIU等、调试接口SWJ,它并不是调试组件),这里的片内是相对于Cortex-M3,在它内部的外设叫片内外设;
下图的附加调试组件与再下一个图的外部私有外设总线相连
在这里插入图片描述

Cortex-M3内部还有一个核心CM3Core,它周围的外设叫片内外设(调试系统(调试组件)为片上外设); CM3Core和片内外设组成Cortex-M3;
Cortex-M3周围的外设叫片上外设;
Cortex-M3和片上外设组成stm32芯片;
在stm32外部自己在通过PCB添加外设组件叫片外外设; 如下图所示:

Cortex-M3模块结构图:
该图里并不包含调试组件,与外部私有外设总线相连的是调试组件

在这里插入图片描述
在这里插入图片描述

上述两张图第一张是CM3Core和片内外设(不包括调试组件),加上调试组件,主要由ARM设计;
第二张图除了CM3Core和片内外设组成的Cortex-M3,以及Trace controller(调试组件),其它的是芯片制造公司设计制造的
抽象图如下两张图所示:
在这里插入图片描述
在这里插入图片描述

四、从CM3内核架构来看CPU流水线–分析Cortex-M3内核架构

从上一节我们了解到Cortex-M3的内核CM3,它就相当于日常电脑的CPU,架构图如下:Processor Core System那部分

在这里插入图片描述
上图的Register Bank又可以分为以下:
在这里插入图片描述
ARM CPU的组成
ARM——Cortex系列体系结构
在这里插入图片描述

三级流水线
在这里插入图片描述
在这里插入图片描述
ARM Cortex-A8体系结构
在这里插入图片描述
在这里插入图片描述
流水线中出现的三个相关:
1、数据相关:是指令在流水bai线中du重叠执行时,当后继指令需要用到zhi前面的指令产生的结果dao时发生的。
2、控制相关:是当流水线遇到转移指令引起的。统计表明,转移指令约占总指令的四分之一左右,比起数据相关,它会使流水线丧失更多的功能。
3.结构相关:多条指令进入流水线后在同一机器周期内争用同一功能部件所发生的冲突。

使用五级指令流水的优点:
1.并行性更好
2.周期:机器周期可以设置地更短、时钟周期也更短、主频更高

在这里插入图片描述
具体为以下5级
在这里插入图片描述
从上面指令译码那个可以看到与下一节x86CPU组成不一样的在于,x86CPU还有一个操作控制器OC,而arm相当于是在译码器包含了这个

五、 stm32(ARM CPU)与x86 CPU架构组成的异同点

x86CPU组成:
CPU的内部架构和工作原理
在这里插入图片描述
cpu架构一
在这里插入图片描述

这里的AC累加器、缓冲寄存器和ARM里的通用寄存器R0、R1是一个作用

在这里插入图片描述

ARM

在这里插入图片描述

六、stm32中指令、汇编语言、机器码

在这里插入图片描述
CPU的内部架构和工作原理

根据操作数的地址是在寄存器还是在内存还是立即数,将这些数据传输类型分为以下几种:

1、Cortex-CM3中的数据传输类型

1)、两个寄存器间的传输数据。MOV

2)、寄存器与存储器间传输数据。LDR、STR

3)、寄存器与特殊功能寄存器间传输数据。

4)、把一个立即数加载到寄存器。MOV

STM32学习之路入门篇之指令集及cortex——m3的存储系统

ARM 反汇编基础(六)(Thumb 汇编指令集)

可以通过命令行来汇编与反汇编

在这里插入图片描述

ARM-CPU原理,基于ARM的SOC讲解
在这里插入图片描述
看下面这个例子:
在这里插入图片描述
LED0=0这条C指令编译器把它转换成了3条汇编指令MOVS、LDR、STR,这三句汇编分别对应的机器码就是2000、490B、6008。
图中,0x08。。。是CODE地址,然后该地址开始的机器码,最后就是这个机器对应的汇编语句。
F04F0001是对应汇编的机器码,你不用关心它的长度,有兴趣的可以去查汇编指令表,其中有对应机器码的格式

上面的机器码对三种操作数的寻址:寄存器(R0这些)、内存(flash等)、立即数
对立即数寻址就是确定该立即数的大小,

在这里插入图片描述
详细参考如下文章:
ARM体系架构总结

首先我们分析下上面的例子:

490B LDR R1,[PC,#44]
490A LDR R1,[PC,#40]

这两的机器码为啥只差了1,而立即数差了4

这是因为立即数寻址是有8位图决定的,不是直接映射数值的

在这里插入图片描述在这里插入图片描述
我们可以看到它是将机器码的0-4位乘以4得到最终的立即数
0xb=11,114=44
0xa=10,10
4=40

在这里插入图片描述
参考
ARM指令计算机器码,自己归纳整理的ARM THUMB指令机器码表

32位指令的寻址方式如下:
ARM立即寻址中有效立即数的计算
在这里插入图片描述

为什么要通过这种方式来寻址:

寄存器寻址可以直接控制寄存器,在机器码中所需的位数不多,够用
内存中寻址,如果是32位的那地址就有0-2的32次方,32位指令的话不够用,但这里就可以采用【】的方式间接寻址
而立即数就没有办法通过直接和间接来,32位指令中间除去操作码,剩下的位数根本覆盖不了0-2的32次方,所有采用了位图加循环右移的方式

详细如下:
ARM指令中如何判断一个立即数是有效立即数

在这里插入图片描述

七、指令和数据在stm32中存放的结构、堆栈大小及位置

这一节应该和**从存储器映射来看stm32架构(内存与外设)**这一节结合来看
在这里插入图片描述
上面的代码区(Block0)又细分为以下:

在这里插入图片描述

Flash=Code + RO-Data + RW-Data(.data);

SRAM= RW-data+ZI-data(.bss+heap+stack);
.bss:未初始化的全局变量
heap:申请的动态内存
stack:局部变量都是放在栈中
在这里插入图片描述
STM32内存管理以及堆和栈的理解

说说STM32的堆栈与内存

下面是附件代码生成的map图

==============================================================================

Memory Map of the image

  Image Entry point : 0x08000131

  Load Region LR_IROM1 (Base: 0x08000000, Size: 0x0000293c, Max: 0x00010000, ABSOLUTE)

    Execution Region ER_IROM1 (Exec base: 0x08000000, Load base: 0x08000000, Size: 0x00002904, Max: 0x00010000, ABSOLUTE)

    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object

    0x08000000   0x08000000   0x00000130   Data   RO          231    RESET               startup_stm32f10x_hd.o
    0x08000130   0x08000130   0x00000000   Code   RO         3423  * .ARM.Collect$$$$00000000  mc_w.l(entry.o)
    0x08000130   0x08000130   0x00000004   Code   RO         3738    .ARM.Collect$$$$00000001  mc_w.l(entry2.o)
    0x08000134   0x08000134   0x00000004   Code   RO         3741    .ARM.Collect$$$$00000004  mc_w.l(entry5.o)
    0x08000138   0x08000138   0x00000000   Code   RO         3743    .ARM.Collect$$$$00000008  mc_w.l(entry7b.o)
    0x08000138   0x08000138   0x00000000   Code   RO         3745    .ARM.Collect$$$$0000000A  mc_w.l(entry8b.o)
    0x08000138   0x08000138   0x00000008   Code   RO         3746    .ARM.Collect$$$$0000000B  mc_w.l(entry9a.o)
    0x08000140   0x08000140   0x00000000   Code   RO         3748    .ARM.Collect$$$$0000000D  mc_w.l(entry10a.o)
    0x08000140   0x08000140   0x00000000   Code   RO         3750    .ARM.Collect$$$$0000000F  mc_w.l(entry11a.o)
    0x08000140   0x08000140   0x00000004   Code   RO         3739    .ARM.Collect$$$$00002712  mc_w.l(entry2.o)
    0x08000144   0x08000144   0x00000024   Code   RO          232    .text               startup_stm32f10x_hd.o
    0x08000168   0x08000168   0x00000062   Code   RO         3426    .text               mc_w.l(ldiv.o)
    0x080001ca   0x080001ca   0x00000064   Code   RO         3689    .text               mf_w.l(fmul.o)
    0x0800022e   0x0800022e   0x0000007c   Code   RO         3691    .text               mf_w.l(fdiv.o)
    0x080002aa   0x080002aa   0x0000014e   Code   RO         3693    .text               mf_w.l(dadd.o)
    0x080003f8   0x080003f8   0x000000e4   Code   RO         3695    .text               mf_w.l(dmul.o)
    0x080004dc   0x080004dc   0x000000de   Code   RO         3697    .text               mf_w.l(ddiv.o)
    0x080005ba   0x080005ba   0x00000022   Code   RO         3699    .text               mf_w.l(dflti.o)
    0x080005dc   0x080005dc   0x0000001a   Code   RO         3701    .text               mf_w.l(dfltui.o)
    0x080005f6   0x080005f6   0x00000028   Code   RO         3703    .text               mf_w.l(ffixui.o)
    0x0800061e   0x0800061e   0x00000026   Code   RO         3705    .text               mf_w.l(f2d.o)
    0x08000644   0x08000644   0x00000038   Code   RO         3707    .text               mf_w.l(d2f.o)
    0x0800067c   0x0800067c   0x00000014   Code   RO         3709    .text               mf_w.l(cfrcmple.o)
    0x08000690   0x08000690   0x00000062   Code   RO         3755    .text               mc_w.l(uldiv.o)
    0x080006f2   0x080006f2   0x0000001e   Code   RO         3757    .text               mc_w.l(llshl.o)
    0x08000710   0x08000710   0x00000024   Code   RO         3759    .text               mc_w.l(llsshr.o)
    0x08000734   0x08000734   0x00000000   Code   RO         3768    .text               mc_w.l(iusefp.o)
    0x08000734   0x08000734   0x0000006e   Code   RO         3769    .text               mf_w.l(fepilogue.o)
    0x080007a2   0x080007a2   0x000000ba   Code   RO         3771    .text               mf_w.l(depilogue.o)
    0x0800085c   0x0800085c   0x0000002e   Code   RO         3773    .text               mf_w.l(dscalb.o)
    0x0800088a   0x0800088a   0x00000002   PAD
    0x0800088c   0x0800088c   0x00000030   Code   RO         3777    .text               mf_w.l(cdrcmple.o)
    0x080008bc   0x080008bc   0x00000024   Code   RO         3779    .text               mc_w.l(init.o)
    0x080008e0   0x080008e0   0x00000020   Code   RO         3781    .text               mc_w.l(llushr.o)
    0x08000900   0x08000900   0x000000a2   Code   RO         3783    .text               mf_w.l(dsqrt.o)
    0x080009a2   0x080009a2   0x00000004   Code   RO          144    i.BusFault_Handler  stm32f10x_it.o
    0x080009a6   0x080009a6   0x00000002   Code   RO          145    i.DebugMon_Handler  stm32f10x_it.o
    0x080009a8   0x080009a8   0x00000116   Code   RO          243    i.GPIO_Init         stm32f10x_gpio.o
    0x08000abe   0x08000abe   0x00000004   Code   RO          251    i.GPIO_SetBits      stm32f10x_gpio.o
    0x08000ac2   0x08000ac2   0x00000004   Code   RO          146    i.HardFault_Handler  stm32f10x_it.o
    0x08000ac6   0x08000ac6   0x00000002   PAD
    0x08000ac8   0x08000ac8   0x00000038   Code   RO         3164    i.IIC_Ack           myiic.o
    0x08000b00   0x08000b00   0x00000038   Code   RO         3165    i.IIC_Init          myiic.o
    0x08000b38   0x08000b38   0x00000038   Code   RO         3166    i.IIC_NAck          myiic.o
    0x08000b70   0x08000b70   0x00000058   Code   RO         3167    i.IIC_Read_Byte     myiic.o
    0x08000bc8   0x08000bc8   0x00000060   Code   RO         3168    i.IIC_Send_Byte     myiic.o
    0x08000c28   0x08000c28   0x00000038   Code   RO         3169    i.IIC_Start         myiic.o
    0x08000c60   0x08000c60   0x00000034   Code   RO         3170    i.IIC_Stop          myiic.o
    0x08000c94   0x08000c94   0x0000004c   Code   RO         3171    i.IIC_Wait_Ack      myiic.o
    0x08000ce0   0x08000ce0   0x00000050   Code   RO         2906    i.LED_Init          led.o
    0x08000d30   0x08000d30   0x00000004   Code   RO          147    i.MemManage_Handler  stm32f10x_it.o
    0x08000d34   0x08000d34   0x00000002   Code   RO          148    i.NMI_Handler       stm32f10x_it.o
    0x08000d36   0x08000d36   0x00000002   PAD
    0x08000d38   0x08000d38   0x00000070   Code   RO          551    i.NVIC_Init         misc.o
    0x08000da8   0x08000da8   0x00000014   Code   RO          552    i.NVIC_PriorityGroupConfig  misc.o
    0x08000dbc   0x08000dbc   0x00000002   Code   RO          149    i.PendSV_Handler    stm32f10x_it.o
    0x08000dbe   0x08000dbe   0x00000002   PAD
    0x08000dc0   0x08000dc0   0x00000020   Code   RO          355    i.RCC_APB2PeriphClockCmd  stm32f10x_rcc.o
    0x08000de0   0x08000de0   0x000000d4   Code   RO          363    i.RCC_GetClocksFreq  stm32f10x_rcc.o
    0x08000eb4   0x08000eb4   0x00000020   Code   RO         3172    i.SDA_IN            myiic.o
    0x08000ed4   0x08000ed4   0x00000024   Code   RO         3173    i.SDA_OUT           myiic.o
    0x08000ef8   0x08000ef8   0x00000002   Code   RO          150    i.SVC_Handler       stm32f10x_it.o
    0x08000efa   0x08000efa   0x00000008   Code   RO         2862    i.SetSysClock       system_stm32f10x.o
    0x08000f02   0x08000f02   0x00000002   PAD
    0x08000f04   0x08000f04   0x000000e0   Code   RO         2863    i.SetSysClockTo72   system_stm32f10x.o
    0x08000fe4   0x08000fe4   0x00000028   Code   RO          555    i.SysTick_CLKSourceConfig  misc.o
    0x0800100c   0x0800100c   0x00000002   Code   RO          151    i.SysTick_Handler   stm32f10x_it.o
    0x0800100e   0x0800100e   0x00000002   PAD
    0x08001010   0x08001010   0x0000003c   Code   RO         3320    i.SysTick_Init      systick.o
    0x0800104c   0x0800104c   0x00000060   Code   RO         2865    i.SystemInit        system_stm32f10x.o
    0x080010ac   0x080010ac   0x0000003c   Code   RO         3349    i.USART1_IRQHandler  usart.o
    0x080010e8   0x080010e8   0x000000b0   Code   RO         3350    i.USART1_Init       usart.o
    0x08001198   0x08001198   0x00000040   Code   RO         3379    i.USART2_IRQHandler  rs485.o
    0x080011d8   0x080011d8   0x00000012   Code   RO         1189    i.USART_ClearFlag   stm32f10x_usart.o
    0x080011ea   0x080011ea   0x00000018   Code   RO         1193    i.USART_Cmd         stm32f10x_usart.o
    0x08001202   0x08001202   0x0000001a   Code   RO         1196    i.USART_GetFlagStatus  stm32f10x_usart.o
    0x0800121c   0x0800121c   0x00000054   Code   RO         1197    i.USART_GetITStatus  stm32f10x_usart.o
    0x08001270   0x08001270   0x0000004a   Code   RO         1199    i.USART_ITConfig    stm32f10x_usart.o
    0x080012ba   0x080012ba   0x00000002   PAD
    0x080012bc   0x080012bc   0x000000d8   Code   RO         1200    i.USART_Init        stm32f10x_usart.o
    0x08001394   0x08001394   0x0000000a   Code   RO         1207    i.USART_ReceiveData  stm32f10x_usart.o
    0x0800139e   0x0800139e   0x00000008   Code   RO         1210    i.USART_SendData    stm32f10x_usart.o
    0x080013a6   0x080013a6   0x00000004   Code   RO          152    i.UsageFault_Handler  stm32f10x_it.o
    0x080013aa   0x080013aa   0x00000002   PAD
    0x080013ac   0x080013ac   0x00000020   Code   RO         3561    i.__0printf$5       mc_w.l(printf5.o)
    0x080013cc   0x080013cc   0x00000028   Code   RO         3725    i.__ARM_fpclassify  m_ws.l(fpclassify.o)
    0x080013f4   0x080013f4   0x000000aa   Code   RO         3727    i.__kernel_poly     m_ws.l(poly.o)
    0x0800149e   0x0800149e   0x00000002   PAD
    0x080014a0   0x080014a0   0x00000010   Code   RO         3711    i.__mathlib_dbl_divzero  m_ws.l(dunder.o)
    0x080014b0   0x080014b0   0x00000004   Code   RO         3713    i.__mathlib_dbl_infnan2  m_ws.l(dunder.o)
    0x080014b4   0x080014b4   0x0000000c   Code   RO         3714    i.__mathlib_dbl_invalid  m_ws.l(dunder.o)
    0x080014c0   0x080014c0   0x0000000e   Code   RO         3715    i.__mathlib_dbl_overflow  m_ws.l(dunder.o)
    0x080014ce   0x080014ce   0x00000002   PAD
    0x080014d0   0x080014d0   0x00000010   Code   RO         3717    i.__mathlib_dbl_underflow  m_ws.l(dunder.o)
    0x080014e0   0x080014e0   0x0000000e   Code   RO         3789    i.__scatterload_copy  mc_w.l(handlers.o)
    0x080014ee   0x080014ee   0x00000002   Code   RO         3790    i.__scatterload_null  mc_w.l(handlers.o)
    0x080014f0   0x080014f0   0x0000000e   Code   RO         3791    i.__scatterload_zeroinit  mc_w.l(handlers.o)
    0x080014fe   0x080014fe   0x00000002   PAD
    0x08001500   0x08001500   0x0000000c   Code   RO         3763    i.__set_errno       mc_w.l(errno.o)
    0x0800150c   0x0800150c   0x000002c0   Code   RO         3568    i._printf_core      mc_w.l(printf5.o)
    0x080017cc   0x080017cc   0x000001b0   Code   RO         3257    i.bmp280CompensateP  bmp280.o
    0x0800197c   0x0800197c   0x00000048   Code   RO         3258    i.bmp280CompensateT  bmp280.o
    0x080019c4   0x080019c4   0x00000088   Code   RO         3259    i.bmp280GetData     bmp280.o
    0x08001a4c   0x08001a4c   0x0000004c   Code   RO         3260    i.bmp280GetPressure  bmp280.o
    0x08001a98   0x08001a98   0x00000084   Code   RO         3261    i.bmp280Init        bmp280.o
    0x08001b1c   0x08001b1c   0x0000007c   Code   RO         3262    i.bmp280PressureToAltitude  bmp280.o
    0x08001b98   0x08001b98   0x0000004c   Code   RO         3321    i.delay_ms          systick.o
    0x08001be4   0x08001be4   0x0000004c   Code   RO         3322    i.delay_us          systick.o
    0x08001c30   0x08001c30   0x00000024   Code   RO         3351    i.fputc             usart.o
    0x08001c54   0x08001c54   0x00000060   Code   RO         3174    i.iicDevRead        myiic.o
    0x08001cb4   0x08001cb4   0x00000040   Code   RO         3175    i.iicDevReadByte    myiic.o
    0x08001cf4   0x08001cf4   0x00000030   Code   RO         3177    i.iicDevWriteByte   myiic.o
    0x08001d24   0x08001d24   0x000000a0   Code   RO            1    i.main              main.o
    0x08001dc4   0x08001dc4   0x000009d8   Code   RO         3414    i.pow               m_ws.l(pow.o)
    0x0800279c   0x0800279c   0x00000006   Code   RO         3263    i.presssureFilter   bmp280.o
    0x080027a2   0x080027a2   0x0000004c   Code   RO         3731    i.sqrt              m_ws.l(sqrt.o)
    0x080027ee   0x080027ee   0x00000002   PAD
    0x080027f0   0x080027f0   0x00000088   Data   RO         3415    .constdata          m_ws.l(pow.o)
    0x08002878   0x08002878   0x00000008   Data   RO         3729    .constdata          m_ws.l(qnan.o)
    0x08002880   0x08002880   0x00000064   Data   RO            2    .conststring        main.o
    0x080028e4   0x080028e4   0x00000020   Data   RO         3787    Region$$Table       anon$$obj.o


    Execution Region RW_IRAM1 (Exec base: 0x20000000, Load base: 0x08002904, Size: 0x00000498, Max: 0x00005000, ABSOLUTE)

    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object

    0x20000000   0x08002904   0x00000014   Data   RW          383    .data               stm32f10x_rcc.o
    0x20000014   0x08002918   0x00000014   Data   RW         3265    .data               bmp280.o
    0x20000028   0x0800292c   0x00000004   Data   RW         3323    .data               systick.o
    0x2000002c   0x08002930   0x00000001   Data   RW         3381    .data               rs485.o
    0x2000002d   0x08002931   0x00000003   PAD
    0x20000030   0x08002934   0x00000004   Data   RW         3752    .data               mc_w.l(stdout.o)
    0x20000034   0x08002938   0x00000004   Data   RW         3764    .data               mc_w.l(errno.o)
    0x20000038        -       0x0000001c   Zero   RW         3264    .bss                bmp280.o
    0x20000054        -       0x00000040   Zero   RW         3380    .bss                rs485.o
    0x20000094   0x0800293c   0x00000004   PAD
    0x20000098        -       0x00000400   Zero   RW          229    STACK               startup_stm32f10x_hd.o


==============================================================================

上面分为两个部分:

1.Load Region
可以称之为加载域,加载的指令在这里,初始化时将RW-data从flash中加载到SRAM中

2.Execution Region
可以称之为执行域,在代码运行过程中,生成的中间变量和全局变量的修改都是在这个区域进行的(SRAM)
在这一部分我们可以看到在最左边执行地址的后面又Load Addr,这个地址就是当前地址上的数据是从哪里加载过来的,可以看到RW-data是从第一部分RO-data后面加载过来的

第二部分最后有STACK这个section,它是从0x20000098地址开始,然后在startup_stm32f10x_hd启动文件里定义了0x00000400大小的栈,所以在编译完后栈指针sp就等于0x00000498

同样可以在map文件 全局符号那块看到,如下图
在这里插入图片描述
下面为局部符号STACK,为栈底指针

在这里插入图片描述

      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   

      9920        616        580         56       1120     272362   Grand Totals
      9920        616        580         56       1120     272362   ELF Image Totals
      9920        616        580         56          0          0   ROM Totals
      ==============================================================================

    Total RO  Size (Code + RO Data)                10500 (  10.25kB)
    Total RW  Size (RW Data + ZI Data)              1176 (   1.15kB)
    Total ROM Size (Code + RO Data + RW Data)      10556 (  10.31kB)

==============================================================================

可以看到上述RW Data + ZI Data其实就是编译后加载到SRAM内的数据,转换为16进制就是0x00000498

STM32 | map文件详解

在这里插入图片描述
下面看一下编程中实际字符串在flash中的位置,字符串属于RO-Data类型,.conststring
下面的printf打印的字符串就属于

在这里插入图片描述
在map文件局部符号中找到该段的地址,如下:
因为该段属于对象main.o对象,即在主函数中定义,所以选它,而不是最上面那个段
在这里插入图片描述

在keil中输入该地址,找到该地址,
在这里插入图片描述
上图框中前100个字节就是printf函数里的字符串,通过ascall表可以知道每个字节翻译过来加起来就代表了该字符串

上面是找了RO-data的地址位置
下面找一下RW-data和ZI-data的位置,根据之前的描述,他们分别是全局初始化变量和静态变量、未初始化的全局变量;
如下代码:

#include <math.h>
#include "stdbool.h"
#include "SysTick.h"
#include "myiic.h"
#include "bmp280.h"
#include "usart.h"

/*bmp280 气压和温度过采样 工作模式*/
#define BMP280_PRESSURE_OSR		  	(BMP280_OVERSAMP_8X)
#define BMP280_TEMPERATURE_OSR		(BMP280_OVERSAMP_16X)
#define BMP280_MODE					      (BMP280_PRESSURE_OSR<<2|BMP280_TEMPERATURE_OSR<<5|BMP280_NORMAL_MODE)


typedef struct 
{
    u16 dig_T1;                                                                /* calibration T1 data */
    s16 dig_T2;                                                                /* calibration T2 data */
    s16 dig_T3;                                                                /* calibration T3 data */
    u16 dig_P1;                                                                /* calibration P1 data */
    s16 dig_P2;                                                                /* calibration P2 data */
    s16 dig_P3;                                                                /* calibration P3 data */
    s16 dig_P4;                                                                /* calibration P4 data */
    s16 dig_P5;                                                                /* calibration P5 data */
    s16 dig_P6;                                                                /* calibration P6 data */
    s16 dig_P7;                                                                /* calibration P7 data */
    s16 dig_P8;                                                                /* calibration P8 data */
    s16 dig_P9;                                                                /* calibration P9 data */
    s32 t_fine;                                                                /* calibration t_fine data */
} bmp280Calib;

bmp280Calib  bmp280Cal;

static u8 bmp280ID=0;
static bool isInit=false;
static s32 bmp280RawPressure=0;
static s32 bmp280RawTemperature=0;

static void bmp280GetPressure(void);
static void presssureFilter(float* in,float* out);
static float bmp280PressureToAltitude(float* pressure/*, float* groundPressure, float* groundTemp*/);

bool bmp280Init(void)
{	
    if (isInit)
        return true;

	IIC_Init();		                                                           /*初始化I2C*/
  delay_ms(20);
	
	bmp280ID=iicDevReadByte(BMP280_ADDR,BMP280_CHIP_ID);	                   /* 读取bmp280 ID*/
	
	if(bmp280ID==BMP280_DEFAULT_CHIP_ID)
		printf("BMP280 ID IS: 0x%X\n",bmp280ID);
  else
    return false;

    /* 读取校准数据 */
  iicDevRead(BMP280_ADDR,BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG,24,(u8 *)&bmp280Cal);	
	iicDevWriteByte(BMP280_ADDR,BMP280_CTRL_MEAS_REG,BMP280_MODE);
	iicDevWriteByte(BMP280_ADDR,BMP280_CONFIG_REG,5<<2);		               /*配置IIR滤波*/
		
    isInit=true;          
    return true;
}

static void bmp280GetPressure(void)
{
    u8 data[BMP280_DATA_FRAME_SIZE];

    // read data from sensor
    iicDevRead(BMP280_ADDR,BMP280_PRESSURE_MSB_REG,BMP280_DATA_FRAME_SIZE,data);
    bmp280RawPressure=(s32)((((uint32_t)(data[0]))<<12)|(((uint32_t)(data[1]))<<4)|((uint32_t)data[2]>>4));
    bmp280RawTemperature=(s32)((((uint32_t)(data[3]))<<12)|(((uint32_t)(data[4]))<<4)|((uint32_t)data[5]>>4));
}

// Returns temperature in DegC, resolution is 0.01 DegC. Output value of "5123" equals 51.23 DegC
// t_fine carries fine temperature as global value
static s32 bmp280CompensateT(s32 adcT)
{
    s32 var1,var2,T;

    var1=((((adcT>>3)-((s32)bmp280Cal.dig_T1<<1)))*((s32)bmp280Cal.dig_T2))>>11;
    var2=(((((adcT>>4)-((s32)bmp280Cal.dig_T1))*((adcT>>4)-((s32)bmp280Cal.dig_T1)))>>12)*((s32)bmp280Cal.dig_T3))>>14;
    bmp280Cal.t_fine=var1+var2;
	
    T=(bmp280Cal.t_fine*5+128)>>8;

    return T;
}

// Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
// Output value of "24674867" represents 24674867/256 = 96386.2 Pa = 963.862 hPa
static uint32_t bmp280CompensateP(s32 adcP)
{
    int64_t var1,var2,p;
    var1=((int64_t)bmp280Cal.t_fine)-128000;
    var2=var1*var1*(int64_t)bmp280Cal.dig_P6;
    var2=var2+((var1*(int64_t)bmp280Cal.dig_P5)<<17);
    var2=var2+(((int64_t)bmp280Cal.dig_P4)<<35);
    var1=((var1*var1*(int64_t)bmp280Cal.dig_P3)>>8)+((var1*(int64_t)bmp280Cal.dig_P2)<<12);
    var1=(((((int64_t)1)<<47)+var1))*((int64_t)bmp280Cal.dig_P1)>>33;
    if (var1==0)
        return 0;
    p=1048576-adcP;
    p=(((p<<31)-var2)*3125)/var1;
    var1=(((int64_t)bmp280Cal.dig_P9)*(p>>13)*(p>>13))>>25;
    var2=(((int64_t)bmp280Cal.dig_P8)*p)>>19;
    p=((p+var1+var2)>>8)+(((int64_t)bmp280Cal.dig_P7)<<4);
    return(uint32_t)p;
}

#define FILTER_NUM	5
#define FILTER_A	0.1f

/*限幅平均滤波法*/
static void presssureFilter(float* in,float* out)
{	
	*out=*in;

}

void bmp280GetData(float* pressure,float* temperature,float* asl)
{
    static float t;
    static float p;
	
	bmp280GetPressure();

	t=bmp280CompensateT(bmp280RawTemperature)/100.0;		
	p=bmp280CompensateP(bmp280RawPressure)/25600.0;	
	
	*temperature=(float)t;                                                     /*单位度*/                                                   
	presssureFilter(&p,pressure);                                              /*滤波后平均出压力单位hPa*/		
	*asl=bmp280PressureToAltitude(pressure);	                                 /*转换成海拔*/	
}

#define CONST_PF 0.1902630958	       //(1/5.25588f) Pressure factor
#define FIX_TEMP 25				           // Fixed Temperature. ASL is a function of pressure and temperature, but as the temperature changes so much (blow a little towards the flie and watch it drop 5 degrees) it corrupts the ASL estimates.
								                     // TLDR: Adjusting for temp changes does more harm than good.
/*
 * Converts pressure to altitude above sea level (ASL) in meters
*/
static float bmp280PressureToAltitude(float* pressure/*, float* groundPressure, float* groundTemp*/)
{
    if (*pressure>0)
    {
        return((pow((1015.7f/ *pressure),CONST_PF)-1.0f)*(FIX_TEMP+273.15f))/0.0065f;
    }
    else
    {
        return 0;
    }
}

其中的全局初始化变量有bmp280ID、islnit、bmp280RawPressure、bmp280RawTemperature、t、p
未初始化全局变量有bmp280Cal

在在map文件局部符号中找到该段的地址,如下:
在这里插入图片描述
首先在.data出就表明了该段的开始地址,该段总共有多大,其中我们看到数据只占了18字节,而一共占了20字节,还有两字节是pad,

然后在map文件的全局符号区,找到全局未初始化变量如下:
一共有28字节

在这里插入图片描述

通过上述分析我们知道该段代码中一共占了20+28字节:
在map文件的映像组大小部分可以看到统计,如下:
在这里插入图片描述

各种符号在编译后不存在内存中

在这里插入图片描述
C语言内存中是否存在一个区域,存储着变量的符号,变量的类型和变量的首地址?

变量名和内存地址及符号表

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-09-18 10:20:30  更:2021-09-18 10:21:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 2:54:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码