色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

一文詳解STM32單片機的啟動文件

開源嵌入式 ? 來源:開源嵌入式 ? 作者:富貴人 ? 2022-04-26 14:32 ? 次閱讀

一、概述

1、說明

每一款芯片的啟動文件都值得去研究,因為它可是你的程序跑的最初一段路,不可以不知道。通過了解啟動文件,我們可以體會到處理器的架構、指令集、中斷向量安排等內容,是非常值得玩味的。

STM32作為一款高端Cortex-M3系列單片機,有必要了解它的啟動文件。打好基礎,為以后優化程序,寫出高質量的代碼最準備。

2、整體過程概括

STM整個啟動過程是指從上電開始,一直到運行到main函數之間的這段過程,步驟為(以使用微庫為例):

①上電后硬件設置SP、PC

②設置系統時鐘

③軟件設置SP

④加載.data、.bss,并初始化棧區

⑤跳轉到C文件的main函數

3、整個啟動過程涉及的代碼

啟動過程涉及的文件不僅包含startup_stm32f10x_hd.s,還涉及到了MDK自帶的連接庫文件entry.o、entry2.o、entry5.o、entry7.o等(從生成的map文件可以看出來)。

二、程序在Flash上的存儲結構

在真正講解啟動過程之前,先要講解程序下載到Flash上的結構和程序運行時(執行到main函數)時的SRAM數據結構。程序在用戶Flash上的結構如下圖所示。下圖是通過閱讀hex文件和在MDK下調試綜合提煉出來的。

151a4786-c2ac-11ec-bce3-dac502259ad0.jpg

MSP初始值編譯器生成,主堆棧的初始值

異常向量表不多說

外部中斷向量表不多說

代碼段存放代碼

初始化數據段.data

未初始化數據段.bss

加載數據段和初始化棧的參數

加載數據段和初始化棧的參數分別有4個,這里只講解加載數據段的參數,至于初始化棧的參數類似。

0x0800 033cFlash上的數據段(初始化數據段和未初始化數據段)起始地址

0x2000 0000加載到SRAM上的目的地址

0x0000 000c數據段的總大小

0x0800 02f4調用函數_scatterload_copy

需要說明的是初始化棧的函數--0x0800 0304與加載數據段的函數不一樣,為_scatterload_zeroinit,它的目的就是將棧空間清零。

152cfdae-c2ac-11ec-bce3-dac502259ad0.png

三、數據在SRAM上的結構

程序運行時(執行到main函數)時的SRAM數據結構

153f4388-c2ac-11ec-bce3-dac502259ad0.png

四、詳細過程分析

有了以上的基礎,現在詳細分析啟動過程。

1、上電后硬件設置SP、PC

剛上電復位后,硬件會自動根據向量表偏移地址找到向量表,向量表偏移地址的定義如下:

1552b198-c2ac-11ec-bce3-dac502259ad0.png

調試現象如下:

156feed4-c2ac-11ec-bce3-dac502259ad0.png

看看我們的向量表內容(通過J-Flash打開hex文件)

15834344-c2ac-11ec-bce3-dac502259ad0.png

硬件這時自動從0x0800 0000位置處讀取數據賦給棧指針SP,然后自動從0x0800 0004位置處讀取數據賦給PC,完成復位,結果為:

SP = 0x0200 0810

PC = 0x0800 0145

2、設置系統時鐘

15923214-c2ac-11ec-bce3-dac502259ad0.png

上一步中令PC=0x0800 0145的地址沒有對齊,硬件自動對齊到0x0800 0144,執行SystemInit函數初始化系統時鐘。

3、軟件設置SP

LDR   R0,=__main
BX R0

執行上兩條之類,跳轉到__main程序段運行,注意不是main函數,___main的地址是0x0800 0130。

15a559e8-c2ac-11ec-bce3-dac502259ad0.png

可以看到指令LDR.W sp,[pc,#12],結果SP=0x2000 0810。

4、加載.data、.bss,并初始化棧區

BL.W     __scatterload_rt2

進入__scatterload_rt2代碼段。

__scatterload_rt2:0x08000168 4C06      LDR      r4,[pc,#24]  ; 
@0x080001840x0800016A 4D07   LDR  r5,[pc,#28]  ; 
@0x080001880x0800016C E006    B   0x0800017C0x0800016E 68E0 LDR      
r0,[r4,#0x0C]0x08000170 F0400301  ORR      
r3,r0,#0x010x08000174 E8940007  LDM  r4,{r0-r2}0x08000178 4798   
BLX r30x0800017A 3410  ADDS  r4,r4,#0x100x0800017C 42AC   
CMP r4,r50x0800017E D3F6  BCC 0x0800016E0x08000180 F7FFFFDA  
BL.W   _main_init (0x08000138)

這段代碼是個循環(BCC 0x0800016e),實際運行時候循環了兩次。第一次運行的時候,讀取“加載數據段的函數(_scatterload_copy)”的地址并跳轉到該函數處運行(注意加載已初始化數據段和未初始化數據段用的是同一個函數);第二次運行的時候,讀取“初始化棧的函數(_scatterload_zeroinit)”的地址并跳轉到該函數處運行。相應的代碼如下:

0x0800016E 68E0      LDR      r0,[r4,#0x0C]
0x08000170 F0400301  ORR      r3,r0,#0x01
0x08000174  
0x08000178 4798      BLX      r3
當然執行這兩個函數的時候,還需要傳入參數。
至于參數,我們在“加載數據段和初始化棧的參數”環節已經闡述過了。
當這兩個函數都執行完后,結果就是“數據在SRAM上的結構”所展示的圖。
最后,也把事實加載和初始化的兩個函數代碼奉上如下:
5、跳轉到C文件的main函數
_main_init:0x08000138 4800      LDR      r0,[pc,#0]  ;
@0x0800013C0x0800013A 4700      BX       r0

五、異常向量與中斷向量表

; Vector Table Mapped to Address 0 at Reset
        AREA  RESET, DATA, READONLY
        EXPORT __Vectors
        EXPORT __Vectors_End
        EXPORT __Vectors_Size
__Vectors    DCD   __initial_sp        ; Top of Stack
        DCD   Reset_Handler       ; Reset Handler
        DCD   NMI_Handler        ; NMI Handler
        DCD   HardFault_Handler     ; Hard Fault Handler
        DCD   MemManage_Handler     ; MPU Fault Handler
        DCD   BusFault_Handler      ; Bus Fault Handler
        DCD   UsageFault_Handler     ; Usage Fault Handler
        DCD   0             ; Reserved
        DCD   0             ; Reserved
        DCD   0             ; Reserved
        DCD   0             ; Reserved
        DCD   SVC_Handler        ; SVCall Handler
        DCD   DebugMon_Handler      ; Debug Monitor Handler
        DCD   0             ; Reserved
        DCD   PendSV_Handler       ; PendSV Handler
        DCD   SysTick_Handler      ; SysTick Handler
        ; External Interrupts
        DCD   WWDG_IRQHandler      ; Window Watchdog
        DCD   PVD_IRQHandler       ; PVD through EXTI Line
        DCD   TAMPER_IRQHandler     ; Tamper
        DCD   RTC_IRQHandler       ; RTC
        DCD   FLASH_IRQHandler      ; Flash
        DCD   RCC_IRQHandler       ; RCC
        DCD   EXTI0_IRQHandler      ; EXTI Line 0
        DCD   EXTI1_IRQHandler      ; EXTI Line 1
        DCD   EXTI2_IRQHandler      ; EXTI Line 2
        DCD   EXTI3_IRQHandler      ; EXTI Line 3
        DCD   EXTI4_IRQHandler      ; EXTI Line 4
        DCD   DMA1_Channel1_IRQHandler  ; DMA1 Channel 1
        DCD   DMA1_Channel2_IRQHandler  ; DMA1 Channel 2
        DCD   DMA1_Channel3_IRQHandler  ; DMA1 Channel 3
        DCD   DMA1_Channel4_IRQHandler  ; DMA1 Channel 4
        DCD   DMA1_Channel5_IRQHandler  ; DMA1 Channel 5
        DCD   DMA1_Channel6_IRQHandler  ; DMA1 Channel 6
        DCD   DMA1_Channel7_IRQHandler  ; DMA1 Channel 7
        DCD   ADC1_2_IRQHandler     ; ADC1 & ADC2
        DCD   USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TX
        DCD   USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0
        DCD   CAN1_RX1_IRQHandler    ; CAN1 RX1
        DCD   CAN1_SCE_IRQHandler    ; CAN1 SCE
        DCD   EXTI9_5_IRQHandler     ; EXTI Line 9..5
        DCD   TIM1_BRK_IRQHandler    ; TIM1 Break
        DCD   TIM1_UP_IRQHandler     ; TIM1 Update
        DCD   TIM1_TRG_COM_IRQHandler  ; TIM1 Trigger and Commutation
        DCD   TIM1_CC_IRQHandler     ; TIM1 Capture Compare
        DCD   TIM2_IRQHandler      ; TIM2
        DCD   TIM3_IRQHandler      ; TIM3
        DCD   TIM4_IRQHandler      ; TIM4
        DCD   I2C1_EV_IRQHandler     ; I2C1 Event
        DCD   I2C1_ER_IRQHandler     ; I2C1 Error
        DCD   I2C2_EV_IRQHandler     ; I2C2 Event
        DCD   I2C2_ER_IRQHandler     ; I2C2 Error
        DCD   SPI1_IRQHandler      ; SPI1
        DCD   SPI2_IRQHandler      ; SPI2
        DCD   USART1_IRQHandler     ; USART1
        DCD   USART2_IRQHandler     ; USART2
        DCD   USART3_IRQHandler     ; USART3
        DCD   EXTI15_10_IRQHandler    ; EXTI Line 15..10
        DCD   RTCAlarm_IRQHandler    ; RTC Alarm through EXTI Line
        DCD   USBWakeUp_IRQHandler    ; USB Wakeup from suspend
        DCD   TIM8_BRK_IRQHandler    ; TIM8 Break
        DCD   TIM8_UP_IRQHandler     ; TIM8 Update
        DCD   TIM8_TRG_COM_IRQHandler  ; TIM8 Trigger and Commutation
        DCD   TIM8_CC_IRQHandler     ; TIM8 Capture Compare
        DCD   ADC3_IRQHandler      ; ADC3
        DCD   FSMC_IRQHandler      ; FSMC
        DCD   SDIO_IRQHandler      ; SDIO
        DCD   TIM5_IRQHandler      ; TIM5
        DCD   SPI3_IRQHandler      ; SPI3
        DCD   UART4_IRQHandler      ; UART4
        DCD   UART5_IRQHandler      ; UART5
        DCD   TIM6_IRQHandler      ; TIM6
        DCD   TIM7_IRQHandler      ; TIM7
        DCD   DMA2_Channel1_IRQHandler  ; DMA2 Channel1
        DCD   DMA2_Channel2_IRQHandler  ; DMA2 Channel2
        DCD   DMA2_Channel3_IRQHandler  ; DMA2 Channel3
        DCD   DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5
__Vectors_End
這段代碼就是定義異常向量表,在之前有一個“J-Flash打開hex文件”的圖片跟這個表格是一一對應的。編譯器根據我們定義的函數 Reset_Handler、NMI_Handler等,在連接程序階段將這個向量表填入這些函數的地址。
startup_stm32f10x_hd.s內容:
NMI_Handler   PROC
         EXPORT  NMI_Handler         [WEAK]
         B    .
         ENDP
stm32f10x_it.c中內容:void NMI_Handler(void)
{
}

在啟動匯編文件中已經定義了函數NMI_Handler,但是使用了“弱”,它允許我們再重新定義一個NMI_Handler函數,程序在編譯的時候會將匯編文件中的弱函數“覆蓋掉”--兩個函數的代碼在連接后都存在,只是在中斷向量表中的地址填入的是我們重新定義函數的地址。

六、使用微庫與不使用微庫的區別

15b89ad0-c2ac-11ec-bce3-dac502259ad0.png

使用微庫就意味著我們不想使用MDK提供的庫函數,而想用自己定義的庫函數,比如說printf函數。那么這一點是怎樣實現的呢?我們以printf函數為例進行說明。

1、不使用微庫而使用系統庫

在連接程序時,肯定會把系統中包含printf函數的庫拿來調用參與連接,即代碼段有系統庫的參與。

在啟動過程中,不使用微庫而使用系統庫在初始化棧的時候,還需要初始化堆(猜測系統庫需要用到堆),而使用微庫則是不需要的。

IF __MICROLIB
EXPORT __initial_sp
EXPORT __heap_base
EXPORT __heap_limit
ELSE
IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap
LDR R0, = Heap_Mem
LDR R1, =(Stack_Mem + Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR  R3, = Stack_Mem
BX LR
ALIGN
ENDIF

另外,在執行__main函數的過程中,不僅需要完成“使用微庫”情況下的所有工作,額外的工作還需要進行庫的初始化,才能使用系統庫(這一部分我還沒有深入探討)。附上__main函數的內容:

__main:0x08000130 F000F802  BL.W     
__scatterload_rt2_thumb_only (0x08000138)   
__rt_entry_sh (0x080001B0)
__scatterload_rt2_thumb_only:0x08000138 A00A  
__scatterload_null:0x08000146 45DA   CMP   
__scatterload_copy:0x0800016C 3A10      SUBS    
__scatterload_zeroinit:0x08000188 2300  0001A2 
__rt_lib_init:0x080001A4 B51F      PUSH       
__rt_lib_init_user_alloc_1:0x080001AA BD1F      
__rt_lib_shutdown:0x080001AC B510   PUSH  
__rt_lib_shutdown_user_alloc_1:0x080001AE BD10   
__rt_entry_sh:0x080001B0 F000F82F  BL.W
__rt_entry_postsh_1:0x080001B6 F7FFFFF5  BL.W     
__rt_entry_postli_1:0x080001BA F000F919  BL.W

2、使用微庫而不使用系統庫

在程序連接時,不會把包含printf函數的庫連接到終極目標文件中,而使用我們定義的庫。啟動時需要完成的工作就是之前論述的步驟1、2、3、4、5,相比使用系統庫,啟動過程步驟更少。

原文標題:【編程高手都必備】STM32F1x系列精髓啟動過程與啟動文件分析

文章出處:【微信公眾號:開源嵌入式】歡迎添加關注!文章轉載請注明出處。

審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 單片機
    +關注

    關注

    6050

    文章

    44707

    瀏覽量

    641323
  • STM32
    +關注

    關注

    2277

    文章

    10952

    瀏覽量

    359252
  • 啟動文件
    +關注

    關注

    0

    文章

    15

    瀏覽量

    2303

原文標題:【編程高手都必備】STM32F1x系列精髓啟動過程與啟動文件分析

文章出處:【微信號:KY_QRS,微信公眾號:開源嵌入式】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    STM32單片機啟動文件及FLASH分配

    STM32作為單片機,它的啟動方式很簡單,即當Boot配置了從內部Flash啟動模式之后,
    發表于 01-11 17:24 ?5271次閱讀
    <b class='flag-5'>STM32</b><b class='flag-5'>單片機</b>的<b class='flag-5'>啟動</b><b class='flag-5'>文件</b>及FLASH分配

    淺析STM32單片機啟動文件

    今天來總結的stm32基礎知識是啟動文件相關。要想對是stm32單片機有個深入的理解,那么啟動
    發表于 06-12 16:49 ?2354次閱讀
    淺析<b class='flag-5'>STM32</b><b class='flag-5'>單片機</b>的<b class='flag-5'>啟動</b><b class='flag-5'>文件</b>

    什么是單片機STM32啟動文件

    什么是單片機STM32啟動文件
    發表于 11-04 07:46

    單片機啟動文件

    需要的資源有stm32f10x開發板stm32參考手冊首先我們來了解一下單片機啟動
    發表于 01-05 07:31

    詳解MCS-51單片機的中斷系統

    詳解MCS-51單片機的中斷系統,具體的跟隨小編來了解下。
    的頭像 發表于 07-28 11:26 ?1.3w次閱讀
    <b class='flag-5'>一</b><b class='flag-5'>文</b><b class='flag-5'>詳解</b>MCS-51<b class='flag-5'>單片機</b>的中斷系統

    STM32啟動文件內容詳解

    前言使用STM32單片機時候,必須導入對應型號的啟動文件。這個筆記在于對于啟動文件的內容的分析,
    發表于 11-30 13:21 ?8次下載
    <b class='flag-5'>STM32</b><b class='flag-5'>啟動</b><b class='flag-5'>文件</b>內容<b class='flag-5'>詳解</b>

    STM32單片機中Hex、Bin文件的區別及應用詳解

    ? ? STM32、51等單片機程序經過編譯后,生成的hex文件、bin文件,它們都是單片機燒寫文件
    的頭像 發表于 07-05 17:23 ?1.4w次閱讀

    基于STM32單片機ADC使用庫文件設計源代碼

    基于STM32單片機ADC使用庫文件設計源代碼
    發表于 04-26 15:07 ?6次下載

    基于STM32單片機DMA使用庫文件設計源代碼

    基于STM32單片機DMA使用庫文件設計源代碼)
    發表于 04-26 15:03 ?2次下載

    基于STM32單片機OLED顯示使用庫文件設計源代碼

    基于STM32單片機OLED顯示使用庫文件設計源代碼
    發表于 04-26 14:59 ?3次下載

    基于STM32單片機SD卡使用庫文件設計源代碼

    基于STM32單片機SD卡使用庫文件設計源代碼
    發表于 04-26 14:27 ?2次下載

    基于STM32單片機SPI使用庫文件設計源代碼

    基于STM32單片機SPI使用庫文件設計源代碼
    發表于 04-26 14:26 ?5次下載

    基于STM32單片機TFTLCD顯示使用庫文件設計源代碼

    基于STM32單片機TFTLCD顯示使用庫文件設計源代碼
    發表于 04-26 14:54 ?1次下載

    基于STM32單片機按鍵輸入使用庫文件設計源代碼

    基于STM32單片機按鍵輸入使用庫文件設計源代碼
    發表于 04-26 14:53 ?0次下載

    詳解GD32單片機STM32單片機

    GD32單片機是中國龍芯集成電路公司推出的款ARM Cortex-M3內核的微控制器。它具有與STM32單片機相同的架構和指令集,但是價格相比ST
    發表于 08-09 16:58 ?1.1w次閱讀
    主站蜘蛛池模板: 久久久视频2019午夜福利 | 任你懆视频 这里只有精品 人与人特黄一级 | 吃奶摸下的羞羞漫画 | 亚洲永久免费视频 | 岛国片在线看 | 草莓西瓜樱桃香蕉直播视频 | 国色天香视频在线社区 | 国际老妇高清在线观看 | 羞羞答答的免费视频在线观看 | 高清一区二区亚洲欧美日韩 | 国产高清砖码区 | 亚洲电影不卡 | 亚洲人成网站在线播放 | 国产一级做a爰片久久毛片男 | 在线精品视频免费观看 | 麻花传媒MD0044视频 | 欧美一区二区三区播放 | 美国caopo超碰在线视频 | 国内精品视频一区二区在线观看 | 久久99国产亚洲高清观着 | 亚洲欧美日韩在线码不卡 | 国产精品色吧国产精品 | 奇米狠狠一区二区三区 | 99国产精品欲AV蜜桃臀麻豆 | 灌饱娇嫩H将军公主最新章节 | 蜜桃TV成人网站免费打开 | 男人把女人桶到爽免费看视频 | 性做久久久久久久久浪潮 | 性肥胖BWBWBW| 果冻传媒2021一二三区 | 日日啪无需播放器 | 久久精品九九亚洲精品天堂 | 亚洲一卡久久4卡5卡6卡7卡 | 找老女人泻火对白自拍 | 16女下面流水不遮图免费观看 | 美女夫妻内射潮视频 | 男女亲吻摸下面吃奶视频 | 久久夜色撩人精品国产 | 西施打开双腿下面好紧 | 免费在线视频a | 国产色精品久久人妻99蜜桃麻豆 |