日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

STM32F4启动流程分析

發布時間:2025/3/21 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STM32F4启动流程分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

因為在做有關STM32F407ZET6的項目,其中一項內容是通過IAP來對STM32進行在線升級,那么首先需要對STM32的啟動流程需要做到詳細了解。

硬件及調試配置說明:

使用芯片:STM32F407ZET6

調試軟件:IAR6.3.0

軟件庫:STM32的HAL庫,版本V1.3.0

啟動文件:startup_stm32f407xx.s,版本V1.2.1

必須說明:? ?因為本人使用的IAR開發平臺,因此程序中的指令都是IAR指令集(關于IAR指令,參見《EWARM_AssemblerReference.ENU.pdf》文檔),因此會發現很多匯編指令會和在別的地方看到的不一樣,但是基本指令的功能基本類似,比如IAR中的SECTION指令和標準ARM指令集中的AREA指令。而且,同類型的文件在擴展名上也可能不同,比如對于“分散加載文件”,IAR擴展名為.icf,但是keil擴展名是.scf,而且編輯命令也不同。

(一)啟動文件

我們需要了解:一般的,工程文件件中會包含很多的C文件以及必要的S文件(匯編文件)。用戶在使用IDE(集成開發平臺)對工程進行一鍵式處理時,經預處理->編譯->匯編->鏈接后生成可執行文件。其中,每一個S或C文件在經過匯編器“匯編”后都會生成對應的目標文件(.o或.obj或類似格式文件),然后由鏈接器對各個目標文件進行鏈接,決定各個目標文件在最終可執行文件(bin或hex或類似格式文件)里的位置。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?可參考文檔:http://blog.sina.com.cn/s/blog_65fbc556010162j6.html? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??https://blog.csdn.net/shenjianxz/article/details/52130111

我們只需要知道startup_stm32f407xx.s文件成成的目標文件在最終可執行文件中是第一個被執行的!

(我想:不同的源文件(C或S)之間是通過函數調用或參數引用而相互關聯起來的。即使是main函數,也是被startup_stm32f407xx.s中匯編代碼所調用的,而且此段匯編代碼前不再存在其他代碼,因此匯編程序應該在最前面執行;同時,通過在線調試,可以看到可執行文件的反匯編文件,其中startup_stm32f407xx.s程序確實是在最前面

STM32F4和STM32F1的啟動文件略不相同,但是基本內容是一樣的。啟動文件的工作按順序依次分為以下幾項:

?- Set the initial SP
?- Set the initial PC == _iar_program_start,
- Set the vector table entries with the exceptions ISR? address.?

- Branches to main in the C library (which eventually? calls main()).

(1)設置堆棧
(2)初始化PC指針
(3)設置向量表

(4)跳轉到main函數

下面進行分段是分析:

第一段說明:

?????MODULE ?cstartup;; Forward declaration of sections.SECTION CSTACK:DATA:NOROOT(3)SECTION .intvec:CODE:NOROOT(2)EXTERN __iar_program_startEXTERN SystemInitPUBLIC __vector_table【1】MODULE 控制指令是用來標記 modules 源碼的開始和結束,后邊的 ?cstartup 是模塊的名字,此文檔的最后的 END 表明模塊的結束
【2】SECTION 指令是聲明段,一個段不能同時包含 public symbol 和 pubweak symbol ,模塊只有在相同的名字的模塊沒有被鏈接進來的時候才會被鏈接進來。
? ? ????語法格式:SECTION section:type [flag] [(align)]
? ? ? ? align,是用于指定地址對齊到 2^align,他的取值是 0 到 30
? ? ? ? flag,取值NOROOT、ROOT、REORDER、NOREORDER,默認是ROOT,NOROOT表示如果這個段中的符號沒有被引用,將會被連接器舍棄,即可被優化。ROOT表示不可被優化。REORDER表示開始一個新的名字是 section 的段(section),NOREORDER表示開始一個新的名字為 section 的片段(fragment),多個片段組成一個段(section)
? ? ? ? type,memory 的類型,取值是 CODE、CONST、DATA
? ? ? ? section,段的名字
【3】EXTERN 用導入(引用)其他模塊的 symbol(符號)

【4】PUBLIC 導出 symbol(符號)

第二段:

DATA __vector_tableDCD sfe(CSTACK)DCD Reset_Handler ; Reset HandlerDCD NMI_Handler ; NMI HandlerDCD HardFault_Handler ; Hard Fault HandlerDCD MemManage_Handler ; MPU Fault HandlerDCD BusFault_Handler ; Bus Fault HandlerDCD UsageFault_Handler ; Usage Fault HandlerDCD 0 ; ReservedDCD 0 ; ReservedDCD 0 ; ReservedDCD 0 ; ReservedDCD SVC_Handler ; SVCall HandlerDCD DebugMon_Handler ; Debug Monitor HandlerDCD 0 ; ReservedDCD PendSV_Handler ; PendSV HandlerDCD SysTick_Handler ; SysTick Handler; External InterruptsDCD WWDG_IRQHandler ; Window WatchDog DCD PVD_IRQHandler ; PVD through EXTI Line detection DCD TAMP_STAMP_IRQHandler ; Tamper and TimeStamps through the EXTI line DCD RTC_WKUP_IRQHandler ; RTC Wakeup through the EXTI line DCD FLASH_IRQHandler ; FLASH DCD RCC_IRQHandler ; RCC DCD EXTI0_IRQHandler ; EXTI Line0 DCD EXTI1_IRQHandler ; EXTI Line1 DCD EXTI2_IRQHandler ; EXTI Line2 DCD EXTI3_IRQHandler ; EXTI Line3 DCD EXTI4_IRQHandler ; EXTI Line4 DCD DMA1_Stream0_IRQHandler ; DMA1 Stream 0 DCD DMA1_Stream1_IRQHandler ; DMA1 Stream 1 DCD DMA1_Stream2_IRQHandler ; DMA1 Stream 2 DCD DMA1_Stream3_IRQHandler ; DMA1 Stream 3 DCD DMA1_Stream4_IRQHandler ; DMA1 Stream 4 DCD DMA1_Stream5_IRQHandler ; DMA1 Stream 5 DCD DMA1_Stream6_IRQHandler ; DMA1 Stream 6 DCD ADC_IRQHandler ; ADC1, ADC2 and ADC3s DCD CAN1_TX_IRQHandler ; CAN1 TX DCD CAN1_RX0_IRQHandler ; CAN1 RX0 DCD CAN1_RX1_IRQHandler ; CAN1 RX1 DCD CAN1_SCE_IRQHandler ; CAN1 SCE DCD EXTI9_5_IRQHandler ; External Line[9:5]s DCD TIM1_BRK_TIM9_IRQHandler ; TIM1 Break and TIM9 DCD TIM1_UP_TIM10_IRQHandler ; TIM1 Update and TIM10 DCD TIM1_TRG_COM_TIM11_IRQHandler ; TIM1 Trigger and Commutation and TIM11DCD 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 ; External Line[15:10]s DCD RTC_Alarm_IRQHandler ; RTC Alarm (A and B) through EXTI Line DCD OTG_FS_WKUP_IRQHandler ; USB OTG FS Wakeup through EXTI line DCD TIM8_BRK_TIM12_IRQHandler ; TIM8 Break and TIM12 DCD TIM8_UP_TIM13_IRQHandler ; TIM8 Update and TIM13 DCD TIM8_TRG_COM_TIM14_IRQHandler ; TIM8 Trigger and Commutation and TIM14DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare DCD DMA1_Stream7_IRQHandler ; DMA1 Stream7 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_DAC_IRQHandler ; TIM6 and DAC1&2 underrun errors DCD TIM7_IRQHandler ; TIM7 DCD DMA2_Stream0_IRQHandler ; DMA2 Stream 0 DCD DMA2_Stream1_IRQHandler ; DMA2 Stream 1 DCD DMA2_Stream2_IRQHandler ; DMA2 Stream 2 DCD DMA2_Stream3_IRQHandler ; DMA2 Stream 3 DCD DMA2_Stream4_IRQHandler ; DMA2 Stream 4 DCD ETH_IRQHandler ; Ethernet DCD ETH_WKUP_IRQHandler ; Ethernet Wakeup through EXTI line DCD CAN2_TX_IRQHandler ; CAN2 TX DCD CAN2_RX0_IRQHandler ; CAN2 RX0 DCD CAN2_RX1_IRQHandler ; CAN2 RX1 DCD CAN2_SCE_IRQHandler ; CAN2 SCE DCD OTG_FS_IRQHandler ; USB OTG FS DCD DMA2_Stream5_IRQHandler ; DMA2 Stream 5 DCD DMA2_Stream6_IRQHandler ; DMA2 Stream 6 DCD DMA2_Stream7_IRQHandler ; DMA2 Stream 7 DCD USART6_IRQHandler ; USART6 DCD I2C3_EV_IRQHandler ; I2C3 event DCD I2C3_ER_IRQHandler ; I2C3 error DCD OTG_HS_EP1_OUT_IRQHandler ; USB OTG HS End Point 1 Out DCD OTG_HS_EP1_IN_IRQHandler ; USB OTG HS End Point 1 In DCD OTG_HS_WKUP_IRQHandler ; USB OTG HS Wakeup through EXTI DCD OTG_HS_IRQHandler ; USB OTG HS DCD DCMI_IRQHandler ; DCMI DCD 0 ; Reserved DCD HASH_RNG_IRQHandler ; Hash and RNGDCD FPU_IRQHandler ; FPU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;【1】DATA 表示下邊中的標簽是 32 位的標簽,THUMB 表示下邊的標簽是 16 位的標簽,所謂的標簽是 地址的別名,不占用代碼空間,給編譯器看的
【2】 DCD 是數據定義或者 重定位指令,為的是定義一個值,或者保留 memory,DCD 別名是 DC32,用于聲明一個 32 位的常量,這部分是中斷向量表的內容,需要注意的是,他們的順序不能改變,此部分會放到 flash 的最開始部分,當系統啟動的時候會加載前另個地址,第一個地址是 c 程序的棧的棧頂地址,第二個地址是向量表的開始地址,中斷發生時會根據向量表的首地址和偏移量來找到程序的入口

【3】sfe 指令作用是返回棧的結尾,因為棧的增長方向是反方向的

第三段:中斷處理函數

;; Default interrupt handlers. ;;THUMBPUBWEAK Reset_HandlerSECTION .text:CODE:REORDER:NOROOT(2) Reset_HandlerLDR R0, =SystemInitBLX R0LDR R0, =__iar_program_startBX R0PUBWEAK NMI_HandlerSECTION .text:CODE:REORDER:NOROOT(1) NMI_HandlerB NMI_HandlerPUBWEAK HardFault_HandlerSECTION .text:CODE:REORDER:NOROOT(1) HardFault_HandlerB HardFault_HandlerPUBWEAK MemManage_HandlerSECTION .text:CODE:REORDER:NOROOT(1) MemManage_HandlerB MemManage_HandlerPUBWEAK BusFault_HandlerSECTION .text:CODE:REORDER:NOROOT(1) BusFault_HandlerB BusFault_HandlerPUBWEAK UsageFault_HandlerSECTION .text:CODE:REORDER:NOROOT(1) UsageFault_HandlerB UsageFault_HandlerPUBWEAK SVC_HandlerSECTION .text:CODE:REORDER:NOROOT(1) SVC_HandlerB SVC_HandlerPUBWEAK DebugMon_HandlerSECTION .text:CODE:REORDER:NOROOT(1) DebugMon_HandlerB DebugMon_HandlerPUBWEAK PendSV_HandlerSECTION .text:CODE:REORDER:NOROOT(1) PendSV_HandlerB PendSV_HandlerPUBWEAK SysTick_HandlerSECTION .text:CODE:REORDER:NOROOT(1) SysTick_HandlerB SysTick_HandlerPUBWEAK WWDG_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) WWDG_IRQHandler B WWDG_IRQHandlerPUBWEAK PVD_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) PVD_IRQHandler B PVD_IRQHandlerPUBWEAK TAMP_STAMP_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) TAMP_STAMP_IRQHandler B TAMP_STAMP_IRQHandlerPUBWEAK RTC_WKUP_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) RTC_WKUP_IRQHandler B RTC_WKUP_IRQHandlerPUBWEAK FLASH_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) FLASH_IRQHandler B FLASH_IRQHandlerPUBWEAK RCC_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) RCC_IRQHandler B RCC_IRQHandlerPUBWEAK EXTI0_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) EXTI0_IRQHandler B EXTI0_IRQHandlerPUBWEAK EXTI1_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) EXTI1_IRQHandler B EXTI1_IRQHandlerPUBWEAK EXTI2_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) EXTI2_IRQHandler B EXTI2_IRQHandlerPUBWEAK EXTI3_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) EXTI3_IRQHandlerB EXTI3_IRQHandlerPUBWEAK EXTI4_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) EXTI4_IRQHandler B EXTI4_IRQHandlerPUBWEAK DMA1_Stream0_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) DMA1_Stream0_IRQHandler B DMA1_Stream0_IRQHandlerPUBWEAK DMA1_Stream1_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) DMA1_Stream1_IRQHandler B DMA1_Stream1_IRQHandlerPUBWEAK DMA1_Stream2_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) DMA1_Stream2_IRQHandler B DMA1_Stream2_IRQHandlerPUBWEAK DMA1_Stream3_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) DMA1_Stream3_IRQHandler B DMA1_Stream3_IRQHandlerPUBWEAK DMA1_Stream4_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) DMA1_Stream4_IRQHandler B DMA1_Stream4_IRQHandlerPUBWEAK DMA1_Stream5_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) DMA1_Stream5_IRQHandler B DMA1_Stream5_IRQHandlerPUBWEAK DMA1_Stream6_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) DMA1_Stream6_IRQHandler B DMA1_Stream6_IRQHandlerPUBWEAK ADC_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) ADC_IRQHandler B ADC_IRQHandlerPUBWEAK CAN1_TX_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) CAN1_TX_IRQHandler B CAN1_TX_IRQHandlerPUBWEAK CAN1_RX0_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) CAN1_RX0_IRQHandler B CAN1_RX0_IRQHandlerPUBWEAK CAN1_RX1_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) CAN1_RX1_IRQHandler B CAN1_RX1_IRQHandlerPUBWEAK CAN1_SCE_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) CAN1_SCE_IRQHandler B CAN1_SCE_IRQHandlerPUBWEAK EXTI9_5_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) EXTI9_5_IRQHandler B EXTI9_5_IRQHandlerPUBWEAK TIM1_BRK_TIM9_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) TIM1_BRK_TIM9_IRQHandler B TIM1_BRK_TIM9_IRQHandlerPUBWEAK TIM1_UP_TIM10_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) TIM1_UP_TIM10_IRQHandler B TIM1_UP_TIM10_IRQHandlerPUBWEAK TIM1_TRG_COM_TIM11_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) TIM1_TRG_COM_TIM11_IRQHandler B TIM1_TRG_COM_TIM11_IRQHandlerPUBWEAK TIM1_CC_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) TIM1_CC_IRQHandler B TIM1_CC_IRQHandlerPUBWEAK TIM2_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) TIM2_IRQHandler B TIM2_IRQHandlerPUBWEAK TIM3_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) TIM3_IRQHandler B TIM3_IRQHandlerPUBWEAK TIM4_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) TIM4_IRQHandler B TIM4_IRQHandlerPUBWEAK I2C1_EV_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) I2C1_EV_IRQHandler B I2C1_EV_IRQHandlerPUBWEAK I2C1_ER_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) I2C1_ER_IRQHandler B I2C1_ER_IRQHandlerPUBWEAK I2C2_EV_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) I2C2_EV_IRQHandler B I2C2_EV_IRQHandlerPUBWEAK I2C2_ER_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) I2C2_ER_IRQHandler B I2C2_ER_IRQHandlerPUBWEAK SPI1_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) SPI1_IRQHandler B SPI1_IRQHandlerPUBWEAK SPI2_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) SPI2_IRQHandler B SPI2_IRQHandlerPUBWEAK USART1_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) USART1_IRQHandler B USART1_IRQHandlerPUBWEAK USART2_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) USART2_IRQHandler B USART2_IRQHandlerPUBWEAK USART3_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) USART3_IRQHandler B USART3_IRQHandlerPUBWEAK EXTI15_10_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) EXTI15_10_IRQHandler B EXTI15_10_IRQHandlerPUBWEAK RTC_Alarm_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) RTC_Alarm_IRQHandler B RTC_Alarm_IRQHandlerPUBWEAK OTG_FS_WKUP_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) OTG_FS_WKUP_IRQHandler B OTG_FS_WKUP_IRQHandlerPUBWEAK TIM8_BRK_TIM12_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) TIM8_BRK_TIM12_IRQHandler B TIM8_BRK_TIM12_IRQHandlerPUBWEAK TIM8_UP_TIM13_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) TIM8_UP_TIM13_IRQHandler B TIM8_UP_TIM13_IRQHandlerPUBWEAK TIM8_TRG_COM_TIM14_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) TIM8_TRG_COM_TIM14_IRQHandler B TIM8_TRG_COM_TIM14_IRQHandlerPUBWEAK TIM8_CC_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) TIM8_CC_IRQHandler B TIM8_CC_IRQHandlerPUBWEAK DMA1_Stream7_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) DMA1_Stream7_IRQHandler B DMA1_Stream7_IRQHandlerPUBWEAK FSMC_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) FSMC_IRQHandler B FSMC_IRQHandlerPUBWEAK SDIO_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) SDIO_IRQHandler B SDIO_IRQHandlerPUBWEAK TIM5_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) TIM5_IRQHandler B TIM5_IRQHandlerPUBWEAK SPI3_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) SPI3_IRQHandler B SPI3_IRQHandlerPUBWEAK UART4_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) UART4_IRQHandler B UART4_IRQHandlerPUBWEAK UART5_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) UART5_IRQHandler B UART5_IRQHandlerPUBWEAK TIM6_DAC_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) TIM6_DAC_IRQHandler B TIM6_DAC_IRQHandlerPUBWEAK TIM7_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) TIM7_IRQHandler B TIM7_IRQHandlerPUBWEAK DMA2_Stream0_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) DMA2_Stream0_IRQHandler B DMA2_Stream0_IRQHandlerPUBWEAK DMA2_Stream1_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) DMA2_Stream1_IRQHandler B DMA2_Stream1_IRQHandlerPUBWEAK DMA2_Stream2_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) DMA2_Stream2_IRQHandler B DMA2_Stream2_IRQHandlerPUBWEAK DMA2_Stream3_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) DMA2_Stream3_IRQHandler B DMA2_Stream3_IRQHandlerPUBWEAK DMA2_Stream4_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) DMA2_Stream4_IRQHandler B DMA2_Stream4_IRQHandlerPUBWEAK ETH_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) ETH_IRQHandler B ETH_IRQHandlerPUBWEAK ETH_WKUP_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) ETH_WKUP_IRQHandler B ETH_WKUP_IRQHandlerPUBWEAK CAN2_TX_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) CAN2_TX_IRQHandler B CAN2_TX_IRQHandlerPUBWEAK CAN2_RX0_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) CAN2_RX0_IRQHandler B CAN2_RX0_IRQHandlerPUBWEAK CAN2_RX1_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) CAN2_RX1_IRQHandler B CAN2_RX1_IRQHandlerPUBWEAK CAN2_SCE_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) CAN2_SCE_IRQHandler B CAN2_SCE_IRQHandlerPUBWEAK OTG_FS_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) OTG_FS_IRQHandler B OTG_FS_IRQHandlerPUBWEAK DMA2_Stream5_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) DMA2_Stream5_IRQHandler B DMA2_Stream5_IRQHandlerPUBWEAK DMA2_Stream6_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) DMA2_Stream6_IRQHandler B DMA2_Stream6_IRQHandlerPUBWEAK DMA2_Stream7_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) DMA2_Stream7_IRQHandler B DMA2_Stream7_IRQHandlerPUBWEAK USART6_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) USART6_IRQHandler B USART6_IRQHandlerPUBWEAK I2C3_EV_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) I2C3_EV_IRQHandler B I2C3_EV_IRQHandlerPUBWEAK I2C3_ER_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) I2C3_ER_IRQHandler B I2C3_ER_IRQHandlerPUBWEAK OTG_HS_EP1_OUT_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) OTG_HS_EP1_OUT_IRQHandler B OTG_HS_EP1_OUT_IRQHandlerPUBWEAK OTG_HS_EP1_IN_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) OTG_HS_EP1_IN_IRQHandler B OTG_HS_EP1_IN_IRQHandlerPUBWEAK OTG_HS_WKUP_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) OTG_HS_WKUP_IRQHandler B OTG_HS_WKUP_IRQHandlerPUBWEAK OTG_HS_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) OTG_HS_IRQHandler B OTG_HS_IRQHandlerPUBWEAK DCMI_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) DCMI_IRQHandler B DCMI_IRQHandlerPUBWEAK HASH_RNG_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) HASH_RNG_IRQHandler B HASH_RNG_IRQHandlerPUBWEAK FPU_IRQHandlerSECTION .text:CODE:REORDER:NOROOT(1) FPU_IRQHandler B FPU_IRQHandlerEND

【1】THUMB 表明下邊是 thumb 指令

【2】Reset_Handler:復位操作后,mcu執行的中斷處理函數

R0 = SystemInit????????????????????? ? ?

BLX? ? ?R0?????????????????????跳轉到 SystemInit 函數(stm32的第一個函數),并將處理器切換到 thumb 態?????????????????????????????

R0 = __iar_program_start????????? ??

BX? ? ? R0??????????????????????跳轉到 __iar_program_start 函數,狀態也是切換到 thumb 狀態

注意:此處BLX 和BX 的用法與區別不過多介紹;

【3】SystemInit函數(大同小異),功能:完成芯片正常運行所需的必備功能項的配置

//#define VECT_TAB_SRAM //RAM或Flash2RAM中運行 #define VECT_TAB_OFFSET 0x0 //!< Vector Table base offset field. //This value must be a multiple of 0x200. void SystemInit(void) {/* FPU settings ------------------------------------------------------------*/#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */#endif/* Reset the RCC clock configuration to the default reset state ------------*//* Set HSION bit */RCC->CR |= (uint32_t)0x00000001;/* Reset CFGR register */RCC->CFGR = 0x00000000;/* Reset HSEON, CSSON and PLLON bits */RCC->CR &= (uint32_t)0xFEF6FFFF;/* Reset PLLCFGR register */RCC->PLLCFGR = 0x24003010;/* Reset HSEBYP bit */RCC->CR &= (uint32_t)0xFFFBFFFF;/* Disable all interrupts */RCC->CIR = 0x00000000;#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)SystemInit_ExtMemCtl(); #endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM *//* Configure the Vector Table location add offset address ------------------*/ #ifdef VECT_TAB_SRAMSCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ #elseSCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ #endif }

【3.1】FPU浮點數運算設置,stm32f4系列支持浮點數運算;

【3.2】配置復位和時鐘相關的寄存器:RCC結構體變量包含所有的寄存器成員;

【3.3】外部SRAM配置(一般沒有使用外部SRAM);

【3.4】Vector向量表重定位(非常重要):配置中斷向量表的基地址和偏移量

(1)當在RAM中調試代碼時,需要將向量的基地址修改為RAM1的起始地址;這種情況不用這種模式

(2)一般我們配置的是NAND FLASH啟動模式,應該將向量的基地址修改為FLASH的起始地址

(3)地址偏移量:當我們的工程文件是stm32上電第一個程序時,應設置VECT_TAB_OFFSET=0;如果在此工程文件前,還有另外的執行程序PRO(比如用于IAP在線升級的bootloader程序),那么需要根據PRO程序的大小來設置VECT_TAB_OFFSET的大小,同時需要注意VECT_TAB_OFFSET的值必須是0x200的2*n(n=1,2,3...)倍數;(此段內容后續 會詳細介紹)

【4】此處的 __iar_program_start 在程序中找不到是因為它已經被封裝到了 IAR 自帶的C庫啟動代碼中了,當我們編譯的時候,在項目屬性的 linker,library中勾選了 Automatic runtime library ,就告訴了編譯器用庫中的 __iar_program_start ,具體實現了什么,我們可以查看 IAR 工具為我們提供的源碼,具體路徑在 IAR 安裝目錄下的 arm\src\lib\thumb ,我們可以看到有的文件分別的提供了 匯編代碼和 c 代碼。

查看cstartup_M.c,里面定義了__iar_program_start函數

void __iar_program_start( void ) {__iar_init_core();__iar_init_vfp();__cmain(); }

其中:

【4.1】此段的程序中前兩個函數是弱函數,在工程共沒有定義

【4.2】__cmain 函數作用是初始化段和底層硬件,最后調用main

至此,庫文件中的啟動文件先分析到這里

(二)啟動流程總結:

(1)一般我們配置STM32從flash啟動,啟動流程如下:

【1.1】MCU上電后從0x0800 0000處讀取棧頂地址并保存——>MCU從0x0800 0004處讀取中斷向量表的起始地址——>根據MCU系統設定的中斷偏移量來計算出復位中斷向量(起始地址+0),其內容=Reset_Handler,即復位中斷處理程序入口地址——>跳轉到復位中斷處理程序入口處(通過設置PC指針,MCU自動完成,我們不需要管);

【1.2】復位中斷函數:

R0 = SystemInit? ? ? ? ? ? ? ? ? ? ? ? ?
BLX? ? ?R0? ? ? ? ? ? ? ? ? ? ?跳轉到 SystemInit 函數(stm32的第一個函數),并將處理器切換到 thumb 態? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
R0 = __iar_program_start? ? ? ? ? ??

BX? ? ? R0??????????????????????跳轉到 __iar_program_start 函數,狀態也是切換到 thumb 狀態

最后的跳轉函數時main函數,即進入用戶程序

【1.3】main循環:

需要注意:用戶main程序一般內部是一個while(1)死循環(否則,main函數執行完成后,MCU會跳進Hard Fault硬件錯誤處)

當發生xx中斷時:MCU保存現場——>MCU從0x0800 0004處讀取中斷向量表的起始地址——>根據中斷偏移量來計算出xx中斷向量,然后取出xx中斷處理程序入口地址

【1.4】MCU跳轉到xx中斷處理程序入口地址處,開始執行中斷處理函數。

【1.5】xx中斷處理程序完成后,MCU恢復現場,繼續執行。



(2)STM32的啟動模式簡述:

上面講解的是STM32從flash啟動(用戶APP程序是從0x08000000開始),實際上STM32支持多種啟動模式,這里進行簡單介紹:

【2.1】STM32的啟動模式由芯片的啟動引腳BOOT0和BOOT1決定:MCU在上電時會讀取BOOT0和BOOT1引腳的電平狀態并鎖存,系統根據電平狀態來從選擇啟動方式(注意:這里說的啟動是指正常的上電,當我們采用jlink/jtag進行程序燒寫或調試時,MCU會會忽略引腳狀態)。下面是官方使用指南的說明:


【2.2】STM32三種啟動模式對應的物理存儲介質均是芯片內置的,它們是:
????? ? a.????主閃存存儲器 = 芯片內置的Flash。
????? ? b.????系統存儲器 = 芯片內部一塊特定的區域,芯片出廠時在這個區域預置了一段Bootloader,就是通常說的ISP程序。這個區域的內容在芯片出廠后用戶無法進行讀寫操作。

????? ? c.??SRAM = 芯片內置的RAM區,具有掉電丟失性。

補充解釋:我們知道MCU上電是從0x0000 0000開始執行代碼,但是我們發現STM32三種啟動模式對應的物理存儲介質均不在0x0000 0000處(也不可能同時在),而且地址不連續。這就是,“根據啟動引腳,映射到Flash、系統存儲區或SRAM”這句話的奇妙,可以理解成一下2點:

A 根據不同的啟動模式, 對應到各種啟動模式的不同物理存儲介質將被映像到第0塊(啟動存儲區);

B??即使被映像到啟動存儲區,仍然可以在它原先的存儲器空間內訪問相關的存儲器。(未驗證,值得去探究!!)

A 就是:邏輯上講MCU上電是從0x0000 0000開始執行代碼,但是實際上PC指針是從實際對應的物理存儲介質處開始執行。

比如我們從flash啟動,通過IAR或KEIL在線調試,會發現MCU運行時的PC指針是從0x0800 0000開始的。

B就是:因為經過系統映射,那么對映射區的讀寫 = 對實際物理介質區的讀寫

比如:在00/01啟動模式下,仍可讀寫執行0x08xxxxxx中的數據和代碼, 并和讀寫執行0x00xxxxxx是一回事;在11啟動模式下,仍可讀寫執行0x20xxxxxx 并和讀寫執行0x00xxxxxx是一回事


?

【2.3】三種啟動方式對比:

a.? ?主閃存存儲器:最常用的方式,程序掉電不丟失,因此當我們確定工程完全達到使用要求后,一般是將文件燒寫到flash中。
b.???系統存儲器啟動:這種模式啟動的程序功能是由廠家設置的。一般來說,這種啟動方式用的比較少。一般來說,我們選用這種啟動模式時,是為了從串口(或是其他類似方式)下載程序,因為在廠家提供的BootLoader中,提供了串口下載程序的固件,可以通過這個BootLoader將程序下載到系統的Flash中。但是這個下載方式需要以下步驟:
????????Step1:????將BOOT0設置為1,BOOT1設置為0,然后按下復位鍵,這樣才能從系統存儲器啟動BootLoader
????????Step2:????最后在BootLoader的幫助下,通過串口下載程序到Flash中
????????Step3:????程序下載完成后,又有需要將BOOT0設置為GND,手動復位,這樣,STM32才可以從Flash中啟動
可以看到,利用這種模式下載程序的流程稍顯繁瑣,但是可以通過普通串口代替專用燒寫接口,不需要使用專用燒寫工具。
c.????內置SRAM:因為SRAM掉電數據丟失,因此這個模式一般用于程序調試,而且SRAM的可擦除次數要遠高于flash比如:當代碼僅修改了局部內容,可以考慮從這個模式啟動代碼(也就是STM32的內存中),用于快速的程序調試,等程序調試完成后,再將程序下載到Flash中。(還有,一般的,程序在RAM執行速度要比flash快一些)

(3)工程源文件與可執行文件的聯系之“分散加載文件

我們在使用ARM集成開發工具對工程進行開發時,基本流程如下:


源文件經預處理->編譯->匯編->鏈接生成目標文件,生產目標文件之前,我們基本上都可以不用深入研究;目標文件經過連接器連接,生成可執行文件。這里我們需要關注一個問題:不同的目標文件是按照什么規則連接在一起的呢?

所依靠的文件即是:分散加載腳本,

【3.1】簡單介紹:對于分散加載的概念,在《ARM體系結構與編程》書中第11章有明確介紹。

????分散加載文件(即scatter file,IAR工程中其后綴為.scf)是一個文本文件,通過編寫一個分散加載文件來指定ARM連接器在生成映像文件時如何分配RO,RW,ZI等數據的存放地址。如果不用SCATTER文件指定,那么ARM連接器會按照默認的方式來生成映像文件,一般情況下我們是不需要使用分散加載文件的。

什么時候使用scatter file:
1、存在復雜的地址映射:例如代碼和數據需要分開存放在多個區域。
2、存在多個存儲器類型:包含Flash, ROM, SDRAM,快速SRAM。我們根據代碼與數據的特性把他們發在不同的存儲器中,比如中斷處理部分放在快速SRAM內部來提高響應速度,而把不常用到的代 碼放到速度比較慢的Flash內。
3、函數的地址固定定位:可以利用Scatter file實現把某個函數放在固定地址,而不管其應用程序是否已經改變或重新編譯。
4、利用符號確定堆和堆棧。
5、內存映射的IO:利用scatter file可以實現把某個數據段放在精確的地址處。因此對于嵌入式系統來說scatter file是必不可少的,因為嵌入式系統采用了ROM, RAM和內存映射的IO。

【3.2】IAR中的stm32F407的.scf文件的一般格式如下:

/*###ICF### Section handled by ICF editor, don't touch! ****/ /*-Editor annotation file-*/ /* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ /*-Specials-*/ define symbol __ICFEDIT_intvec_start__ = 0x08000000;/*中斷向量表開始地址*/ /*-Memory Regions-*/ /*定義內部FLASH地址 */--/*定義內部RAM地址 */ define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;/*閃存起始地址*/ define symbol __ICFEDIT_region_ROM_end__ = 0x0800FFFF;/*閃存結束地址---flash大小64k*/ define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;/*SRAM起始地址*/ define symbol __ICFEDIT_region_RAM_end__ = 0x20004FFF;/*SRAM結束地址---SRAM大小20k*/ /*-Sizes-*//* 棧和堆大小*/ define symbol __ICFEDIT_size_cstack__ = 0x800; /*棧大小*/ define symbol __ICFEDIT_size_heap__ = 0x800;/*堆大小*/ /**** End of ICF editor section. ###ICF###*/ define memory mem with size = 4G; define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };//CSTACK塊屬性(8字節對齊、大小__ICFEDIT_size_cstack__) define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; /* 下列語句定義所定義地址空間內可完成的操作類型*/ initialize by copy { readwrite }; do not initialize { section .noinit }; place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; //__ICFEDIT_intvec_start__賦值給.intvec標識符 place in ROM_region { readonly }; place in RAM_region { readwrite, block CSTACK, block HEAP };

后續關于分散加載文件會有更加詳細的說明;


(三)

由于自身能力有限,本文章存在相關表述問題,希望大家能夠批評指正,相互交流,共同進步!

QQ聯系方式:1030843709(泊葉)



總結

以上是生活随笔為你收集整理的STM32F4启动流程分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。