STM32啟動文件

我們日常使用的嵌入式應用程序開發中都是編寫C/C++語言,我們平時編輯一個工程的話,只用從main函數開始編輯,單片機程序也是從這個函數開始進行執行的。但是單片機上電後是如何尋找到並執行main函數的呢?我們其實都會在心裡有一個答案:"啟動文件",還記得我們當初配置第一個stm32工程的時候在工程中添加過一個startup_stm32f10x_hd.s的文件,這個文件的作用就是負責執行從"復位"到開始執行main函數中間的啟動過程,下面我將對這個文件和stm32的相關知識進行闡述。

首先了解一下stm32的三種啟動方式:在每個STM32的芯片上都有兩個管腳BOOT0和BOOT1,這兩個管腳在芯片復位時的電平狀態決定了芯片復位後從哪個區域開始執行程序,見下表:BOOT1=x BOOT0=0 從用戶閃存FLASH啟動,這是正常的工作模式。BOOT1=0 BOOT0=1 從系統存儲器啟動,這種模式啟動的程序功能由廠家設置。BOOT1=1 BOOT0=1 從內置SRAM啟動,這種模式可以用於調試。

而Cortex-M3/4內核規定,起始地址必須存放堆頂指針,而第二個地址則必須存放復位中斷入口向量地址,這樣在Cortex-M3/4內核復位後,會自動從起始地址的下一個32位空間取出復位中斷入口向量,跳轉執行復位中斷服務程序。而啟動文件的編寫正是按著這個規定來的,下面我將對啟動文件的代碼進行分析。

我挑選了我們常用的startup_stm32f40_41xxx.s進行源碼分析,該文件可以分成以下五個典型部分:

1.堆棧空間定義;

2.存放中斷向量表;

3.復位中斷函數(Reset_Handler);

4.其它中斷異常服務函數,以及弱[WEAK]聲明;

5.將堆棧地址傳遞給庫函數,利用庫函數初始化堆棧,和庫函數自身初始化。

01堆棧空間的定義

如下圖所示,定義了棧大小Stack_Size = 0X400,即1024個字節;堆大小Heap_Size = 0X200, 512個字節。還定義了三個標號:__initial_sp(棧頂)、__heap_base(堆起始地址)和__heap_limit(堆終止地址),它們的空間由SPACE關鍵字來申請,並記作Stack_Mem和Heap_Mem。

STM32啟動文件


STM32啟動文件

02存放中斷向量表

在啟動代碼中,會見到許多由DCD申請空間存放的一個個函數入口,即中斷向量表,關鍵字DCD代表申請一個字的空間,後面的函數名即為中斷服務函數入口地址。

03中斷復位函數

STM32啟動文件


程序上電後,首先加載SP和PC,ARM規定從0地址處加載堆頂指針,從偏移為4的地址(0x00000004)處加載復位函數,然後後將程序控制權交給程序。我們知道0地址處存放__initial_sp,0x00000004地址處存放Reset_Handler,符合ARM規定。

__main標號並不表示C程序中的main函數入口地址,因此第131行也並不是跳轉至main函數開始執行C程序。__main標號表示C/C++標準實時庫函數里的一個初始化子程序__main的入口地址。該程序的一個主要作用是初始化堆棧(對於程序清單一來說則是跳轉__user_initial_stackheap標號進行初始化堆棧的),並初始化映像文件,最後跳轉C程序中的main函數。這就解釋了為何所有的C程序必須有一個main函數作為程序的起點——因為這是由C/C++標準實時庫所規定的——並且不能更改,因為C/C++標準實時庫並不對外界開發源代碼.

STM32啟動文件

04其他中斷異常服務函數,以及弱聲明

所謂弱聲明,即:如果用戶定義了相同的函數則此處函數失效而使用用戶定義的中斷服務函數,這樣可以防止用戶使能了中斷二沒有中斷服務函數造成程序崩潰。

05將堆棧地址傳遞給庫函數

第三步驟中,調用__main函數,然後__main調用庫函數初始化堆棧,但庫函數並不知道堆棧的大小,因此我們需要告訴它。

STM32啟動文件

至此可以總結一下STM32的啟動過程和啟動文件。首先對堆棧大小進行定義,並建立中斷向量表,其第一個表項是棧頂地址,第二個表項是復位中斷服務入口地址,然後在復位中斷服務程序中跳轉到C/C++標準實時庫的_main函數,完成用戶堆棧初始化後,跳轉到C文件的main函數開始執行C程序。假設STM32被設置為從內部FLASH啟動(這也是最常見的一種情況),中斷向量表起始地位為0x8000000,則棧頂地址存放於0x8000000處,而復位中斷服務入口地址存放於0x8000004處。當STM32遇到復位信號後,則從0x80000004處取出復位中斷服務入口地址,繼而執行復位中斷服務程序,然後跳轉__main函數,最後進入mian函數,來到C的世界。


分享到:


相關文章: