01啟動文件簡介
startup_stm32f429_439xx.s是STM32的啟動文件。
剛開始我一直認為STM32程序開始執行是從main函數開始。后來網上查查不是。原來在執行main函數之前,需要先執行一段匯編程序和完成C語言資源硬件的初始化工作。就是以下幾個功能:
1--初始化棧指針MSP=_initial_sp。
2--初始化復位程序計數寄存器值=Reset_Handler。
3--初始化異常/ 中斷向量表。
4--系統時鐘配置。
5--C庫函數_main初始化用戶堆棧的調用 。
02文件啟動步驟
1-在啟動的時候,先對堆棧的大小定義,并在代碼區的起始位置建立異常中斷向量表。然后在復位中斷中服務程序中跳轉執行C標準庫main函數,以上這些完成后,跳轉到主程序中的main函數執行相關函數應用。但是假如STM32F429單片機被設置成從內部flash啟動的,這時候,片內Flash被映射到程序啟動空間,異常/中斷向量表實際的開始地址為0x8000000(查看STM32F4參考手冊可得到),則棧頂地址存放在0x8000000處,復位中斷存放在0x8000004處,若STM32F4遇到復位信號,則從0x8000004處取出復位中斷服務入口地址,繼而執行中斷服務函數,繞后跳轉到main函數,最終進入main函數。由此我們可以得下面這個圖:
03啟動代碼講解
01棧(Stack)
我們可以在.s這個文件中看到堆棧信息如圖:
根據上面的圖片我們可以知道。
在startup_stm32f429_439xx.s文件中,將棧的大小設為0x00000400(1KB)F429是0x30000(192KB),Stack_Mem為棧名,不初始化可讀可寫,8字節對齊。Stack_Size是棧的大小,__initial_sp表示結束地址(棧頂地址,棧是由高字節向低字節生長的)。
棧的主要作用是用于局部變量、函數調用、函數形參的開銷大小應小于內部RAM大小,考慮到局部變量的需求,防止棧溢出。
EQU:宏定義的偽指令,相當于等于,類似與 C 中的 define;
AREA:告訴匯編器匯編一個新的代碼段或者數據段;
SPACE:用于分配一定大小的內存空間,單位為字節;這里的大小等于Stack_Size。
DCD:數據定義( Data Definition )偽指令,單位是字(4字節);
偽指令(Pseudo instruction):用于告訴匯編器如何進行匯編的指令,不生成可執行代碼。
總結如下圖所示:
02堆(Heap)
在.s54行中如下圖這些代碼:
這些代碼中,堆的大小設為0x00000200(512B),其中Heap_ Mem是棧名,不初始化,可讀可寫,8(23)字節對齊。Heap_Size為堆的大小, heap_base為堆的起始地址,heap_limit為堆的結束地址,因為堆是由低地址向高地址生長的。
堆的作用是用于malloc()函數申請的動態內存的分配。
04中斷向量表
PRESERVE8:指定當前文件的堆棧按照 8 字節對齊THUMB:表示后面指令為 THUMB 指令。THUBM 是 ARM 以前的指令集, 16bit,現在 Cortex-M 系列的都使用 THUMB-2 指令集, THUMB-2 是 32 位的,兼容 16 位和 32 位的指令,是 THUMB 的超級!
EXPORT:聲明一個標號具有全局屬性,可被外部的文件使用。如果是 IAR 編譯器,則使用的是 GLOBAL 這個指令。
——Vectors是異常/中斷向量表的起始位置,_Vectors_End是中斷向量表的結束位置,vectors__Size中斷向量表的大小。
TM32F42XX/STM32F43XX部分中斷向量表
在中斷向量表中的每一個位置存儲都是一個4字節服務程序入口地址,如果有中斷請求并且MCU進行了請求的響應,那么MCU就會找到向量表中找到對應的中斷位置,找到中斷復位程序入口地址到程序計數寄存器,進而執行中斷。
具體的詳細中斷向量表請參看數據手冊以及啟動文件。
05復位中斷服務程序
這句話的意思是定義一個名為.text代碼段,可讀
復位中斷服務程序是系統上電后第一個執行的程序,調用Systemlnit函數初始化系統時鐘,然后調用C庫函數mian,最終調用 main 函數進入C程序的世界。
LDR:從存儲器加載字到一個寄存器。
BL:跳轉到由寄存器/標號給出的地址,并把跳轉前的下條指令地址保存到鏈接寄存器。
BLX:跳轉到由寄存器給出的地址,并根據寄存器的LSE確定處理器的狀態,還要把跳轉前的下條指令地址保存到鏈接寄存器。
BX:跳轉到由寄存器/標號給出的地址,不用返回。
WEAK:表示弱定義,如果外部文件優先定義了該標號,則首先引用該標號,可以在C語言中重新定義中斷服務程序;如果在啟動文件之外沒有重新定義中斷服務程序,則在對應的異常/中斷向量表位置處存儲的是匯編文件定義的中斷服務程序入口地址。如果在啟動文件外,在另外一個C文件中重新定義了中斷服務程序,則在對應的異常/中斷向量表位置處存儲的是C文件中的中斷服務程序入口地址。需要注意的是,啟動文件中的中斷服務程序的名稱和C文件中重新定義的中斷服務程序名稱必須保持一致。
IMPORT:表示該標號來自外部文件,跟C語言中的關鍵字EXTERN類似。這里表示Systemlnit 和main 這兩個函數均來自外部的文件。
Systemlnit是一個標準的庫函數,在system_stm32f4xx.c這個庫文件中定義,主要作用是配置系統時鐘,在調用這個函數之后,STM32F429的系統時鐘被配置為180MHz。
main是一個標準的C庫函數,主要作用是初始化用戶堆棧,最終調用main函數進入C程序的世界。在C應用程序中,必須有一個main函數。需要注意的是,_main不是用戶C程序的main 函數。
異常和中斷服務程序
07用戶堆棧初始化
判斷是否定義了__MICROLIB,如果定義了則賦予標號__initial_sp(棧頂地址)、__heap_base(堆起始地址)、__heap_limit(堆結束地址)全局屬性,可供外部文件調用。如果沒有定義(實際的情況就是我們沒定義__MICROLIB),則使用默認的C庫函數,然后初始化用戶堆棧大小,這部分由C庫函數__main來完成,當初始化完堆棧之后,就調用main函數去到C程序的世界。
IF、ELSE、ENDIF:匯編的條件分支語句,跟C語言的if、else類似。
-
STM32
+關注
關注
2270文章
10923瀏覽量
357076 -
C語言
+關注
關注
180文章
7614瀏覽量
137421 -
函數
+關注
關注
3文章
4345瀏覽量
62870 -
啟動文件
+關注
關注
0文章
15瀏覽量
2272
發布評論請先 登錄
相關推薦
評論