stm32启动过程cortex-m3架构堆栈代码位置编译汇编链接分析

Posted GK小卜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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以上是关于stm32启动过程cortex-m3架构堆栈代码位置编译汇编链接分析的主要内容,如果未能解决你的问题,请参考以下文章

以stm32f407为例,学习cortex-m4通用寄存器的用法

Cortex-M3之STM32嵌入式系统设计的目录

初识STM32

Ubuntu:交叉编译 STM32 (Cortex-M3) 时使用啥 gcc?

stm32F103RCT6概括

STM32的意思是啥呢?