主頁 > 軟體設計 > stm32啟動程序、cortex-m3架構、堆疊代碼位置、編譯匯編鏈接分析

stm32啟動程序、cortex-m3架構、堆疊代碼位置、編譯匯編鏈接分析

2021-09-19 09:46:57 軟體設計

分析

  • 一、 暫存器、架構、作業流程
    • 1、 暫存器架構
  • 二 、總線與各個部件之間的關系(主要是I-Code Bus、D-Code Bus、System Bus)
    • 體系結構:哈佛結構與馮諾依曼結構的區別
    • 復位有三種啟動方式,從哪里開始啟動、啟動代碼的所在的位置
  • 三、從存盤器映射來看stm32架構(記憶體與外設)
  • 四、從CM3內核架構來看CPU流水線--分析Cortex-M3內核架構
  • 五、 stm32(ARM CPU)與x86 CPU架構組成的異同點
  • 六、stm32中指令、匯編語言、機器碼
  • 七、指令和資料在stm32中存放的結構、堆疊大小及位置
    • 各種符號在編譯后不存在記憶體中

一、 暫存器、架構、作業流程

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語言記憶體中是否存在一個區域,存盤著變數的符號,變數的型別和變數的首地址?

變數名和記憶體地址及符號表

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/301255.html

標籤:其他

上一篇:Websocket+RabbitMQ實作訊息推送系統

下一篇:前端面試必問的Http狀態碼以及代表的意義

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more