STM32的啟動過程一


啟動代碼

啟動代碼由MCU研發商提供。

MCU一上電,首先執行的是啟動代碼,她是一個匯編代碼。

以stm32f1為例:

首先定義堆棧,然后定義中斷向量表,然后執行復位中斷服務函數Reset_Handler

; Reset handler
Reset_Handler   PROC
                EXPORT  Reset_Handler  [WEAK]
                IMPORT  __main
                IMPORT  SystemInit
                LDR     R0, =SystemInit
                BLX     R0               
                LDR     R0, =__main
                BX      R0
                ENDP

Reset_Handler首先調用SystemInit,配置和運行時鍾系統,然后執行_ _main函數,在 _ _main 里面對堆棧、中斷向量表、運行域和加載域等的初始化,然后才跳轉到我們寫的main函數,在main函數里面做一些外設初始化等,進入while(1)循環,進行業務邏輯處理。

這是st任何一個程序運行過程。

keil編譯過程

keil編譯過程:

1)匯編(通過armasm匯編器將.s-->.o文件)

2)編譯(通過armcc編譯器將.c-->.o文件)

3)鏈接(通過armlink鏈接器將目標文件.o-->.elf/.alf映像文件)

4)格式轉換器將.elf文件-->.hex文件

映像文件其實就是可執行文件。

一般來說,Windows或者Linux系統使用鏈接器生成可執行映像文件elf后,內核會根據該文件的信息加載后,就可以運行程序了,但在單片機平台上,需要把該文件的內容加載到芯片上,所以還需要對鏈接器生成的elf文件利用格式轉換器formelf轉換成“.bin”或“.hex”文件,交給下載器下載到芯片的flash或rom中。

程序不同組件的所屬區域

在keil中,我們編譯整個項目后,會出現

Program Size: Code=1592 RO-data=336 RW-data=32 ZI-data=1832  

這就是程序狀態區域,有4個: Code、RO-data、RW-data和ZI-data。

Code

Code即代碼域,它指的是編譯器生成的機器指令,這些內容被存儲到Flash/rom區。

RO-data

O-data:Read Only data,即只讀數據域,它指程序中用到的只讀數據,這些數據被存儲在Flash/rom區,因而程序不能修改其內容。

例如C語言中const關鍵字定義的變量就是典型的RO-data。

RW-data

RW-data:Read Write data,即可讀寫數據域,它指初始化為"非0值"的可讀寫數據,程序剛運行時,這些數據具有非0的初始值,且運行的時候它們會常駐在RAM區,應用程序可以修改其內容。

當程序在運行狀態的時候,程序常常需要修改一些暫存數據,由於運行速度的要求,這些數據往往存放在內存中(RAM),掉電后這些數據會丟失。

例如C語言中使用定義的全局變量,且定義時賦予"非0值"給該變量進行初始化。

程序運行過程中,凡是變量都存儲在RAM中。

ZI-data

ZI-data:Zero Initialie data,即0初始化數據,它指初始化為"0值"的可讀寫數據域,它與RW-data的區別是程序剛運行時這些數據初始值全都為0,而后續運行過程與RW-data的性質一樣,它們也常駐在RAM區,因而應用程序可以更改其內容。

例如C語言中使用定義的全局變量,且定義時賦予"0值"給該變量進行初始化(若定義該變量時沒有賦予初始值,編譯器會把它當ZI-data來對待,初始化為0);

ZI-data的棧空間(Stack)及堆空間(Heap)

ZI-data的棧空間(Stack)及堆空間(Heap):在C語言中,函數內部定義的局部變量屬於棧空間,進入函數的時候從向棧空間申請內存給局部變量,退出時釋放局部變量,歸還內存空間。而使用malloc動態分配的變量屬於堆空間。在程序中的棧空間和堆空間都是屬於ZI-data區域的,這些空間都會被初始值化為0值。編譯器給出的ZI-data占用的空間值中包含了堆棧的大小(經實際測試,若程序中完全沒有使用malloc動態申請堆空間,編譯器會優化,不把堆空間計算在內)。


部分內容摘抄自——Code-data,RO-data,RW-data,ZI-data 程序運行時加載過程 https://blog.csdn.net/wct3344142/article/details/105354340

這4個程序狀態區域中,Code、RO和RW是存儲在Flash中的,因為RW,例如初始化非零的全局變量,確保每次上電是相同的,所以也存儲在Flash中,而ZI和堆棧初始化是0的,就沒必要存儲在Flash中。

是否需要掉電保存,是把RW-data與ZI-data區別開來的原因,因為在RAM創建數據的時候,默認值為0,但如果有的數據要求初值非0,那就需要使用ROM記錄該初始值,運行時再復制到RAM。

當程序存儲到 STM32 芯片的內部 FLASH 時(即 ROM 區),它占用的空間是 Code、RO-data 及 RW-data 的總和,所以如果這些內容比 STM32 芯片的 FLASH 空間大,程序就無法被正常保存了。當程序在執行的時候,需要占用內部 SRAM 空間(即 RAM 區),占用的空間包括 RW-data 和 ZI-data。

因為MCU沒上電時RAM中沒有數據,所以此時所有的東西(包括代碼、變量、初始值等)都是存放在flash中的,當上電后又要把變量等復制到RAM中才能正常運行。這就涉及到程序的加載時域和運行時域。

運行域和加載域

程序的加載時域就是程序在Flash中的實際存儲狀態,運行時域是指程序執行時的狀態。

在執行映像之前,必須將已初始化的RW數據從ROM中復制到RAM中的執行地址。在RAM中創建RW的過程也會同時創建ZI Section(初始值為0的變量區),這樣才算完成了MCU運行的准備。

程序在存儲狀態時,RO節(RO section)及RW節都被保存在ROM區。當程序開始運行時,內核直接從ROM中讀取代碼,並且在執行主體代碼前,會先執行一段加載代碼,它把RW節數據從ROM復制到RAM,並且在RAM加入ZI節,ZI節的數據都被初始化為0。加載完后RAM區准備完畢,正式開始執行主體程序。

STM32的RO區域不需要加載到SRAM,內核直接從FLASH讀取指令運行。計算機系統的應用程序運行過程很類似,不過計算機系統的程序在存儲狀態時位於硬盤,執行的時候甚至會把上述的RO區域(代碼、只讀數據)加載到內存,加快運行速度,還有虛擬內存管理單元(MMU)輔助加載數據,使得可以運行比物理內存還大的應用程序。而STM32沒有MMU,所以無法支持Linux和Windows系統。


免責聲明!

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



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