STM32啟動代碼詳細分析


最近需要學習iap的功能,因此離不開stm32的啟動代碼的分析,以前看了很多遍,都看不懂,讀書百遍,其義自見,因此我有看了一遍,下面的文章,挺好的,因此轉載:
 
在上電復位后,我們都知道會先運行啟動代碼,但是啟動代碼到底使干什么用的呢?下面小弟給大家一一列出來。
1、初始化堆棧指針
2、初始化 PC 指針
3、初始化中斷向量表
4、配置系統時鍾
5、調用 C 庫函數_main 初始化用戶堆棧
我們根據這以上的幾個步驟一一進行詳細的解析:
1、棧的內存分配
這段代碼的意思是,開辟了一個棧,這個棧的大小是0x00000400也就是1KB的大小,名字為STACK,不初始化,可讀可寫,2^3=8字節對齊。
那么問題來了,那這個棧到底使干什么的呢?小弟相信大家在學習C語言的時候應該也是知道了,棧區保存的是局部變量,只是當時並沒有深入研究它的大小問題。那在這里小弟給大家詳細講解一下棧的作用:
1、局部變量
2、函數調用
3、函數形參
以上的這三種情況的開銷都是使用我們的棧區的資源的。所以啊!這里小弟給個位提個醒,千萬不要把棧區當成無止境大小的
哦!STM32可不比我們的電腦,沒有那么多的空間可以給大伙揮霍,如果我們定義的局部變量過大可是會莫名其妙報錯的。
溫馨提示:請不要在寫程序時,過度使用局部變量,會造成棧的益處,從而導致編譯報錯,如果在特殊情況下真的需要很大的棧區空間,只需來這里進行棧區大小的修改即可。
那么小弟再來給這個程序段里的匯編指令做一個詳細的介紹
Stack_Size      EQU     0x00000400
EQU:宏定義的偽指令,相當於等於,類似與 C 中的 define。
這句話的意思是,定義一個宏名Stack_Size這個宏代表0x00000400的意思,用我們C語言來表示就是
#define Stack_Size 0x00000400

 

AREA    STACK, NOINIT, READWRITE, ALIGN=3
AREA:告訴匯編器匯編一個新的代碼段或者數據段。
STACK:表示段名
NOINIT:表示不初始化
READWRITE:表示可讀可寫
ALIGN=n:表示按照 2^n字節對齊
這里小弟就不多說了,解釋已經很詳細了,小哥哥小姐姐們自己組合起來吧
Stack_Mem       SPACE   Stack_Size
SPACE:用於分配一定大小的內存空間,單位為字節。
這句話的意思是,分配一個內存空間,這個內存空間的大小為Stack_Size,也就是我們剛才宏定義的0x00000400
然后最后標號__initial_sp 緊挨着 SPACE 語句放置,表示棧的結束地址。也就是棧頂的地址。
溫馨提示:棧的生長是由高地址向低地址生長的。



2、堆的內存分配

 

這段代碼的意思是,開辟堆的大小為0x00000200也就是512B的大小,名字為HEAP,不初始化,8字節對齊。



在之前我們一直認為的是,全局變量,靜態變量都分配在堆區中,這里是不正確的,我們的全局變量和靜態變量,並不是直接
分配在堆中,這里的堆只有malloc函數分配的內存,會在這里進行分配,而靜態變量和局部變量都是在SRAM中分配,這也就是為什么我們全局變量可以定義一個大於512B大小的空間了。

 

溫馨提示:如果使用了malloc函數一定要注意這個堆咯!不可以大於512B呢!當然這里也可以進行修改。

 

那咱們再來一條一條語句進行分析吧!
Heap_Size       EQU     0x00000200
這里我們就不多說了這條代碼和上面那條是一個意思

 

AREA    HEAP, NOINIT, READWRITE, ALIGN=3
這里也和上面差不多,唯一改變的就是段名是HEAP而不是STACK了

 

__heap_base
在SPACE前出現這條代碼代表的是堆的起始地址

 

Heap_Mem        SPACE   Heap_Size
這里是分配一個0X00000200大小的空間

 

__heap_limit
在SPACE后出現這條代碼代表的是堆的結束地址

 

PRESERVE8
指定當前文件的堆棧按照 8 字節對齊
THUMB
表示后面指令兼容 THUMB 指令。THUBM 是 ARM 以前的指令集,16bit,現在 Cortex-M 系列的都使用 THUMB-2 指令集,THUMB-2 是 32 位的,兼容 16 位和 32 位的指令。
3、向量表



這段代碼的意思是,定義了一個數據短,名字叫RESET,只可讀。
那么這里問題來了,什么是向量表呢!在這里,這個向量表示為了決定中斷服務函數的入口的,每一個向量表都是4個字節,
向量表決定了入口的偏移地址。
AREA    RESET, DATA, READONLY
這句話的意思是定義了一個代碼段RESET,只可讀

 

EXPORT  __Vectors
EXPORT  __Vectors_End
EXPORT  __Vectors_Size
這三句話都是同一個意思,相當於C語言中的EXPORT可以被外部文件所引用

 

向量表如下
...........................省略部分.................................

 

 





這里呢,就是我們的中斷向量表了,我們可以發現,它是從棧區中開始加載的,從棧頂開始,
__Vectors 代表向量起始地址
__Vectors_End 代表向量結束地址
DCD:分配一個或者多個以字為單位的內存,以四字節對齊,並要求初始化這些內存。在向量表中,DCD 分配了一堆內存,並且以 ESR 的入口地址初始化它們

 

Reset_Handler     
NMI_Handler       
HardFault_Handler 
MemManage_Handler 
BusFault_Handler  
UsageFault_Handler
這些都是地址,我們的知道,函數名就是函數的地址,所以我們的中斷服務函數必須使用這些作為函數名,否則無法正確進入中斷服務函數。
__Vectors_Size  EQU  __Vectors_End - __Vectors
通過這句話我們知道結束地址-起始地址,自然就是向量表的大小了。



好的,個位小哥哥小姐姐,今天的課就上到這里了,剩下的部分我們下回分解。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM