STM32启动文件代码解析
目錄
- 啟動(dòng)流程
- 代碼詳解
- 啟動(dòng)文件使用的 ARM 匯編指令匯總
- 關(guān)于與啟動(dòng)文件有關(guān)的一些問(wèn)題思考
下面是F1固件庫(kù)V3.5.0的啟動(dòng)文件startup_stm32f10x_hd.s,以此為例做解析,其余的型號(hào)的啟動(dòng)文件都差不多,主要區(qū)別在于因片上外設(shè)不同,支持的中斷就不一樣,所以在啟動(dòng)文件的中斷向量表不同型號(hào)會(huì)有差別。
啟動(dòng)流程
啟動(dòng)文件由匯編編寫(xiě),是系統(tǒng)上電復(fù)位后第一個(gè)執(zhí)行的程序。主要做了以下工作:
1、初始化堆棧指針 SP=_initial_sp
2、初始化 PC指針=Reset_Handler
3、初始化中斷向量表
4、配置系統(tǒng)時(shí)鐘
5、調(diào)用 C庫(kù)函數(shù)_main 初始化用戶堆棧,從而最終調(diào)用 main 函數(shù)去到 C的世界
代碼詳解
下面是用于KEIL中啟動(dòng)文件,加入了較詳細(xì)的注釋:
; 分配給堆棧的內(nèi)存量(以字節(jié)為單位) ; 根據(jù)應(yīng)用程序的需要定制此值 ; <h> Stack Configuration 棧配置 ; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> ; </h> Stack_Size EQU 0x00000400 ;類似于:#define Stack_Size 0x00000400AREA STACK, NOINIT, READWRITE, ALIGN=3 ;偽指令A(yù)REA,表示名字為 STACK,NOINIT 即不初始化,可讀可寫(xiě),8(2^3)字節(jié)對(duì)齊。 Stack_Mem SPACE Stack_Size ;開(kāi)辟一段大小為Stack_Size的內(nèi)存空間作為棧,Stack_Size已經(jīng)定義為了0x00000400(1KB) __initial_sp ;標(biāo)號(hào)__initial_sp緊挨著SPACE語(yǔ)句放置,表示棧的結(jié)束地址,即棧頂?shù)刂?#xff0c;棧是由高向低生長(zhǎng)的。; <h> Heap Configuration 堆配置 ; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> ; </h>Heap_Size EQU 0x00000200 ;類似于:#define Heap_Size 0x00000200AREA HEAP, NOINIT, READWRITE, ALIGN=3 ;偽指令A(yù)REA,表示名字為 HEAP,NOINIT即不初始化,可讀可寫(xiě),8(2^3)字節(jié)對(duì)齊 __heap_base ; __heap_base 表示對(duì)的起始地址 Heap_Mem SPACE Heap_Size ;開(kāi)辟堆的大小為 0X00000200(512字節(jié)) __heap_limit ; __heap_limit 表示堆的結(jié)束地址。堆是由低向高生長(zhǎng)的,跟棧的生長(zhǎng)方向相反PRESERVE8 ; 指定當(dāng)前文件的堆棧按照 8字節(jié)對(duì)齊THUMB ; 表示后面指令兼容 THUMB 指令,THUBM 是 ARM 以前的指令集, 16bit,現(xiàn)在 Cortex-M 系列的都使用 THUMB-2 指令集, THUMB-2 是 32 位的,兼容 16 位和 32 位的指令,是 THUMB 的超集。; Vector Table Mapped to Address 0 at ResetAREA RESET, DATA, READONLY ;定義一個(gè)數(shù)據(jù)段,名字為 RESET,可讀。EXPORT __Vectors ;聲明 __Vectors、__Vectors_End 和__Vectors_Size這三個(gè)標(biāo)號(hào)具有全局屬性,可供外部的文件調(diào)用。EXPORT __Vectors_End ;EXPORT :聲明一個(gè)標(biāo)號(hào)可被外部的文件使用,使標(biāo)號(hào)具有全局屬性。EXPORT __Vectors_Size;__Vectors 為向量表起始地址 DCD: 以字為單位分配內(nèi)存,要求 4字節(jié)對(duì)齊,并要求初始化這些內(nèi)存 __Vectors DCD __initial_sp ; Top of Stack 棧頂?shù)刂稭SPDCD Reset_Handler ; Reset Handler 復(fù)位程序地址DCD 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 ; Reserved 0表示保留DCD 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 Interrupts 以下是外部中斷DCD WWDG_IRQHandler ; Window WatchdogDCD PVD_IRQHandler ; PVD through EXTI Line detectDCD TAMPER_IRQHandler ; TamperDCD RTC_IRQHandler ; RTCDCD FLASH_IRQHandler ; FlashDCD RCC_IRQHandler ; RCCDCD EXTI0_IRQHandler ; EXTI Line 0DCD EXTI1_IRQHandler ; EXTI Line 1DCD EXTI2_IRQHandler ; EXTI Line 2DCD EXTI3_IRQHandler ; EXTI Line 3DCD EXTI4_IRQHandler ; EXTI Line 4DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7DCD ADC1_2_IRQHandler ; ADC1 & ADC2DCD USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TXDCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0DCD CAN1_RX1_IRQHandler ; CAN1 RX1DCD CAN1_SCE_IRQHandler ; CAN1 SCEDCD EXTI9_5_IRQHandler ; EXTI Line 9..5DCD TIM1_BRK_IRQHandler ; TIM1 BreakDCD TIM1_UP_IRQHandler ; TIM1 UpdateDCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and CommutationDCD TIM1_CC_IRQHandler ; TIM1 Capture CompareDCD TIM2_IRQHandler ; TIM2DCD TIM3_IRQHandler ; TIM3DCD TIM4_IRQHandler ; TIM4DCD I2C1_EV_IRQHandler ; I2C1 EventDCD I2C1_ER_IRQHandler ; I2C1 ErrorDCD I2C2_EV_IRQHandler ; I2C2 EventDCD I2C2_ER_IRQHandler ; I2C2 ErrorDCD SPI1_IRQHandler ; SPI1DCD SPI2_IRQHandler ; SPI2DCD USART1_IRQHandler ; USART1DCD USART2_IRQHandler ; USART2DCD USART3_IRQHandler ; USART3DCD EXTI15_10_IRQHandler ; EXTI Line 15..10DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI LineDCD USBWakeUp_IRQHandler ; USB Wakeup from suspendDCD TIM8_BRK_IRQHandler ; TIM8 BreakDCD TIM8_UP_IRQHandler ; TIM8 UpdateDCD TIM8_TRG_COM_IRQHandler ; TIM8 Trigger and CommutationDCD TIM8_CC_IRQHandler ; TIM8 Capture CompareDCD ADC3_IRQHandler ; ADC3DCD FSMC_IRQHandler ; FSMCDCD SDIO_IRQHandler ; SDIODCD TIM5_IRQHandler ; TIM5DCD SPI3_IRQHandler ; SPI3DCD UART4_IRQHandler ; UART4DCD UART5_IRQHandler ; UART5DCD TIM6_IRQHandler ; TIM6DCD TIM7_IRQHandler ; TIM7DCD DMA2_Channel1_IRQHandler ; DMA2 Channel1DCD DMA2_Channel2_IRQHandler ; DMA2 Channel2DCD DMA2_Channel3_IRQHandler ; DMA2 Channel3DCD DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5 __Vectors_End ; __Vectors_End 為向量表結(jié)束地址__Vectors_Size EQU __Vectors_End - __Vectors ;__Vectors 為向量表起始地址, __Vectors_End 為向量表結(jié)束地址,兩個(gè)相減即可算出向量表大小。AREA |.text|, CODE, READONLY ;定義一個(gè)名稱為.text 的代碼段,可讀; Reset handler復(fù)位程序 Reset_Handler PROC ;PROC 定義子程序,與 ENDP 成對(duì)使用,表示子程序結(jié)束EXPORT Reset_Handler [WEAK] ;WEAK表示弱定義IMPORT __main ;IMPORT類似于extern,表示__main和SystemInit都來(lái)自外部文件,__main 是一個(gè)標(biāo)準(zhǔn)的 C 庫(kù)函數(shù),主要作用是初始化用戶堆棧,并在函數(shù)的最后調(diào)用main 函數(shù)去到 C 的世界IMPORT SystemInit ;SystemInit()是一個(gè)標(biāo)準(zhǔn)的庫(kù)函數(shù),在system_stm32f10x.c這個(gè)庫(kù)文件中定義。主要作用是配置系統(tǒng)時(shí)鐘LDR R0, =SystemInitBLX R0 LDR R0, =__mainBX R0ENDP; Dummy Exception Handlers (infinite loops which can be modified無(wú)限循環(huán)可以被修改)NMI_Handler PROCEXPORT NMI_Handler [WEAK]B . ;跳轉(zhuǎn)到一個(gè)標(biāo)號(hào)。這里跳轉(zhuǎn)到一個(gè)‘.’,即表示無(wú)線循環(huán)ENDP HardFault_Handler\PROCEXPORT HardFault_Handler [WEAK]B .ENDP MemManage_Handler\PROCEXPORT MemManage_Handler [WEAK]B .ENDP BusFault_Handler\PROCEXPORT BusFault_Handler [WEAK]B .ENDP UsageFault_Handler\PROCEXPORT UsageFault_Handler [WEAK]B .ENDP SVC_Handler PROCEXPORT SVC_Handler [WEAK]B .ENDP DebugMon_Handler\PROCEXPORT DebugMon_Handler [WEAK]B .ENDP PendSV_Handler PROCEXPORT PendSV_Handler [WEAK]B .ENDP SysTick_Handler PROCEXPORT SysTick_Handler [WEAK]B .ENDPDefault_Handler PROCEXPORT WWDG_IRQHandler [WEAK]EXPORT PVD_IRQHandler [WEAK]EXPORT TAMPER_IRQHandler [WEAK]EXPORT RTC_IRQHandler [WEAK]EXPORT FLASH_IRQHandler [WEAK]EXPORT RCC_IRQHandler [WEAK]EXPORT EXTI0_IRQHandler [WEAK]EXPORT EXTI1_IRQHandler [WEAK]EXPORT EXTI2_IRQHandler [WEAK]EXPORT EXTI3_IRQHandler [WEAK]EXPORT EXTI4_IRQHandler [WEAK]EXPORT DMA1_Channel1_IRQHandler [WEAK]EXPORT DMA1_Channel2_IRQHandler [WEAK]EXPORT DMA1_Channel3_IRQHandler [WEAK]EXPORT DMA1_Channel4_IRQHandler [WEAK]EXPORT DMA1_Channel5_IRQHandler [WEAK]EXPORT DMA1_Channel6_IRQHandler [WEAK]EXPORT DMA1_Channel7_IRQHandler [WEAK]EXPORT ADC1_2_IRQHandler [WEAK]EXPORT USB_HP_CAN1_TX_IRQHandler [WEAK]EXPORT USB_LP_CAN1_RX0_IRQHandler [WEAK]EXPORT CAN1_RX1_IRQHandler [WEAK]EXPORT CAN1_SCE_IRQHandler [WEAK]EXPORT EXTI9_5_IRQHandler [WEAK]EXPORT TIM1_BRK_IRQHandler [WEAK]EXPORT TIM1_UP_IRQHandler [WEAK]EXPORT TIM1_TRG_COM_IRQHandler [WEAK]EXPORT TIM1_CC_IRQHandler [WEAK]EXPORT TIM2_IRQHandler [WEAK]EXPORT TIM3_IRQHandler [WEAK]EXPORT TIM4_IRQHandler [WEAK]EXPORT I2C1_EV_IRQHandler [WEAK]EXPORT I2C1_ER_IRQHandler [WEAK]EXPORT I2C2_EV_IRQHandler [WEAK]EXPORT I2C2_ER_IRQHandler [WEAK]EXPORT SPI1_IRQHandler [WEAK]EXPORT SPI2_IRQHandler [WEAK]EXPORT USART1_IRQHandler [WEAK]EXPORT USART2_IRQHandler [WEAK]EXPORT USART3_IRQHandler [WEAK]EXPORT EXTI15_10_IRQHandler [WEAK]EXPORT RTCAlarm_IRQHandler [WEAK]EXPORT USBWakeUp_IRQHandler [WEAK]EXPORT TIM8_BRK_IRQHandler [WEAK]EXPORT TIM8_UP_IRQHandler [WEAK]EXPORT TIM8_TRG_COM_IRQHandler [WEAK]EXPORT TIM8_CC_IRQHandler [WEAK]EXPORT ADC3_IRQHandler [WEAK]EXPORT FSMC_IRQHandler [WEAK]EXPORT SDIO_IRQHandler [WEAK]EXPORT TIM5_IRQHandler [WEAK]EXPORT SPI3_IRQHandler [WEAK]EXPORT UART4_IRQHandler [WEAK]EXPORT UART5_IRQHandler [WEAK]EXPORT TIM6_IRQHandler [WEAK]EXPORT TIM7_IRQHandler [WEAK]EXPORT DMA2_Channel1_IRQHandler [WEAK]EXPORT DMA2_Channel2_IRQHandler [WEAK]EXPORT DMA2_Channel3_IRQHandler [WEAK]EXPORT DMA2_Channel4_5_IRQHandler [WEAK]WWDG_IRQHandler PVD_IRQHandler TAMPER_IRQHandler RTC_IRQHandler FLASH_IRQHandler RCC_IRQHandler EXTI0_IRQHandler EXTI1_IRQHandler EXTI2_IRQHandler EXTI3_IRQHandler EXTI4_IRQHandler DMA1_Channel1_IRQHandler DMA1_Channel2_IRQHandler DMA1_Channel3_IRQHandler DMA1_Channel4_IRQHandler DMA1_Channel5_IRQHandler DMA1_Channel6_IRQHandler DMA1_Channel7_IRQHandler ADC1_2_IRQHandler USB_HP_CAN1_TX_IRQHandler USB_LP_CAN1_RX0_IRQHandler CAN1_RX1_IRQHandler CAN1_SCE_IRQHandler EXTI9_5_IRQHandler TIM1_BRK_IRQHandler TIM1_UP_IRQHandler TIM1_TRG_COM_IRQHandler TIM1_CC_IRQHandler TIM2_IRQHandler TIM3_IRQHandler TIM4_IRQHandler I2C1_EV_IRQHandler I2C1_ER_IRQHandler I2C2_EV_IRQHandler I2C2_ER_IRQHandler SPI1_IRQHandler SPI2_IRQHandler USART1_IRQHandler USART2_IRQHandler USART3_IRQHandler EXTI15_10_IRQHandler RTCAlarm_IRQHandler USBWakeUp_IRQHandler TIM8_BRK_IRQHandler TIM8_UP_IRQHandler TIM8_TRG_COM_IRQHandler TIM8_CC_IRQHandler ADC3_IRQHandler FSMC_IRQHandler SDIO_IRQHandler TIM5_IRQHandler SPI3_IRQHandler UART4_IRQHandler UART5_IRQHandler TIM6_IRQHandler TIM7_IRQHandler DMA2_Channel1_IRQHandler DMA2_Channel2_IRQHandler DMA2_Channel3_IRQHandler DMA2_Channel4_5_IRQHandlerB .ENDPALIGN;******************************************************************************* ; User Stack and Heap initialization 用戶堆棧初始化 ;*******************************************************************************IF :DEF:__MICROLIB ;判斷是否定義了__MICROLIBEXPORT __initial_sp;如果定義了這個(gè)宏則賦予標(biāo)號(hào)__initial_sp(棧頂?shù)刂?#xff09;、__heap_base(堆起始地址)、__heap_limit(堆結(jié)束地址)全局屬性,可供外部文件調(diào)用。EXPORT __heap_baseEXPORT __heap_limitELSE ;如果沒(méi)有定義__MICROLIB,則插入標(biāo)號(hào)__use_two_region_memory,這個(gè)函數(shù)需要用戶自己實(shí)現(xiàn)IMPORT __use_two_region_memoryEXPORT __user_initial_stackheap ;聲明標(biāo)號(hào)__user_initial_stackheap 具有全局屬性,可供外部文件調(diào)用,下面實(shí)現(xiàn)這個(gè)標(biāo)號(hào)的內(nèi)容。__user_initial_stackheapLDR R0, = Heap_MemLDR R1, =(Stack_Mem + Stack_Size)LDR R2, = (Heap_Mem + Heap_Size)LDR R3, = Stack_MemBX LRALIGNENDIFEND ;文件結(jié)束啟動(dòng)文件使用的 ARM 匯編指令匯總
【EQU】 給數(shù)字常量取一個(gè)符號(hào)名,相當(dāng)于 C語(yǔ)言中的 define
【AREA】 匯編一個(gè)新的代碼段或者數(shù)據(jù)段
【SPACE】 分配內(nèi)存空間
【PRESERVE8 】當(dāng)前文件堆棧需按照 8字節(jié)對(duì)齊
【EXPORT】聲明一個(gè)標(biāo)號(hào)具有全局屬性,可被外部的文件使用
【DCD 】以字為單位分配內(nèi)存,要求 4字節(jié)對(duì)齊,并要求初始化這些內(nèi)存
【PROC 】定義子程序,與 ENDP 成對(duì)使用,表示子程序結(jié)束
【W(wǎng)EAK 】弱定義,如果外部文件聲明了一個(gè)標(biāo)號(hào),則優(yōu)先使用外部文件定義的標(biāo)號(hào),如果外部文件沒(méi)有定義也不出錯(cuò)。要注意的是:這個(gè)不是ARM的指令,是編譯器的,這里放在一起只是為了方便。
【IMPORT】聲明標(biāo)號(hào)來(lái)自外部文件,跟 C 語(yǔ)言中的 EXTERN關(guān)鍵字類似
【B】 跳轉(zhuǎn)到一個(gè)標(biāo)號(hào)
【ALIGN】 編譯器對(duì)指令或者數(shù)據(jù)的存放地址進(jìn)行對(duì)齊,一般需要跟一個(gè)立即數(shù),缺省表示 4字節(jié)對(duì)齊。要注意的是:這個(gè)不是 ARM的指令,是編譯器的,這里放在一起只是為了方便。
【END】 到達(dá)文件的末尾,文件結(jié)束
【IF,ELSE,ENDIF】匯編的條件分支語(yǔ)句,跟 C 語(yǔ)言的 if ,else 類似
LDR、BLX、BX 是 CM4 內(nèi)核的指令,可在《CM3 權(quán)威指南 CnR2》第四章-指令集里面查詢到
【LDR】 從存儲(chǔ)器中加載字到一個(gè)寄存器中
【BL】 跳轉(zhuǎn)到由寄存器/標(biāo)號(hào)給出的地址,并把跳轉(zhuǎn)前的下條指令地址保存到 LR
【BLX】 跳轉(zhuǎn)到由寄存器給出的地址,并根據(jù)寄存器的 LSE 確定處理器的狀態(tài),還要把跳轉(zhuǎn)前的下條指令地址保存到 LR
【BX】 跳轉(zhuǎn)到由寄存器/標(biāo)號(hào)給出的地址,不用返回
關(guān)于與啟動(dòng)文件有關(guān)的一些問(wèn)題思考
在啟動(dòng)文件里面已經(jīng)幫我們寫(xiě)好所有中斷的中斷服務(wù)函數(shù),跟我們平時(shí)寫(xiě)的中斷服務(wù)函數(shù)不一樣的就是這些函數(shù)都是空的,真正的中斷復(fù)服務(wù)程序需要我們?cè)谕獠康?C 文件里面重新實(shí)現(xiàn),這里只是提前占了一個(gè)位置而已。
如果我們?cè)谑褂媚硞€(gè)外設(shè)的時(shí)候,開(kāi)啟了某個(gè)中斷,但是又忘記編寫(xiě)配套的中斷服務(wù)程序或者函數(shù)名寫(xiě)錯(cuò),那當(dāng)中斷來(lái)臨的時(shí),程序就會(huì)跳轉(zhuǎn)到啟動(dòng)文件預(yù)先寫(xiě)好的空的中斷服務(wù)程序中,并且在這個(gè)空函數(shù)中無(wú)線循環(huán),即程序就死在這里。
B:跳轉(zhuǎn)到一個(gè)標(biāo)號(hào)。這里跳轉(zhuǎn)到一個(gè)‘.’,即表示無(wú)限循環(huán)
如果你在調(diào)試程序時(shí)發(fā)現(xiàn)死在了啟動(dòng)文件中的B .這個(gè)位置,大概率是你使能了某個(gè)中斷但沒(méi)有編寫(xiě)中斷函數(shù)。
棧的作用是用于局部變量,函數(shù)調(diào)用,函數(shù)形參等的開(kāi)銷,棧的大小不能超過(guò)內(nèi)部SRAM 的大小。如果編寫(xiě)的程序比較大,定義的局部變量很多,那么就需要修改棧的大小。如果某一天,你寫(xiě)的程序出現(xiàn)了莫名奇怪的錯(cuò)誤,并進(jìn)入了硬 fault 的時(shí)候,這時(shí)你就要考慮下是不是棧不夠大,溢出了。
修改啟動(dòng)文件中的Stack_Size EQU 0x00000400可以修改棧大小
修改啟動(dòng)文件中的Heap_Size EQU 0x00000200可以修改堆大小
在3.5版F1標(biāo)準(zhǔn)庫(kù)中的啟動(dòng)文件還調(diào)用了在system_stm32f10x.c文件中的
SystemInit()函數(shù)配置系統(tǒng)時(shí)鐘,在舊版本的工程中要用戶進(jìn)入main函數(shù)自己調(diào)用SystemInit()函數(shù)。
無(wú)論性能高下,結(jié)構(gòu)簡(jiǎn)繁,價(jià)格貴賤,每一種微控制器(處理器)都必須有啟動(dòng)文件,啟動(dòng)文件的作用便是負(fù)責(zé)執(zhí)行微控制器從“復(fù)位”到“開(kāi)始執(zhí)行main函數(shù)”中間這段時(shí)間(稱為啟動(dòng)過(guò)程)所必須進(jìn)行的工作。最為常見(jiàn)的51,AVR或MSP430等微控制器當(dāng)然也有對(duì)應(yīng)的啟動(dòng)文件,但開(kāi)發(fā)環(huán)境往往自動(dòng)完整地提供了這個(gè)啟動(dòng)文件,不需要開(kāi)發(fā)人員再行干預(yù)啟動(dòng)過(guò)程,只需要從main函數(shù)開(kāi)始進(jìn)行應(yīng)用程序的設(shè)計(jì)即可。
Cortex-M3內(nèi)核規(guī)定,起始地址必須存放堆頂指針,而第二個(gè)地址則必須存放復(fù)位中斷入口向量地址,這樣在Cortex-M3內(nèi)核復(fù)位后,會(huì)自動(dòng)從起始地址的下一個(gè)32位空間取出復(fù)位中斷入口向量,跳轉(zhuǎn)執(zhí)行復(fù)位中斷服務(wù)程序。
Cortex-M3內(nèi)核可通過(guò)boot引腳設(shè)置中斷向量表的位置(即可以設(shè)置從不同位置啟動(dòng)),有3種情況:
1、 通過(guò)boot引腳設(shè)置可以將中斷向量表定位于SRAM區(qū),即起始地址為0x2000000,同時(shí)復(fù)位后PC指針位于0x2000000處;
2、 通過(guò)boot引腳設(shè)置可以將中斷向量表定位于FLASH區(qū),即起始地址為0x8000000,同時(shí)復(fù)位后PC指針位于0x8000000處;
3、 通過(guò)boot引腳設(shè)置可以將中斷向量表定位于內(nèi)置Bootloader區(qū)
參考鳴謝
https://www.cnblogs.com/wenshinlee/p/8859227.html
https://www.cnblogs.com/amanlikethis/p/3719529.html
總結(jié)
以上是生活随笔為你收集整理的STM32启动文件代码解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: OBD技术速成——J1850协议解析软件
- 下一篇: STM32F1如何切换到不同的型号