STM32啟動代碼概述


轉載:http://bbs.ednchina.com/BLOG_ARTICLE_138130.HTM

 

一般嵌入式開發流程就是先建立一個工程,再編寫源文件,然后進行編譯,把所有的 *.s文件和 *.c文件編譯成一個 *.o文件,再對目標文件進行鏈接和定位,編譯成功后會生成一個 *.hex文件和調試文件,接下來要進行調試,如果成功的話,就可以將它固化到 flash 里面去。

 

啟動代碼是用來初始化電路以及用來為高級語言寫的軟件作好運行前准備的一小段匯編語言,是任何處理器上電復位時的程序運行入口點。

 

比如,剛上電的過程中,PC機會對系統的一個運行頻率進行鎖定在一個固定的值,這個設計頻率的過程就是在匯編源代碼中進行的,也就是在啟動代碼中進行的。與此同時,設置完后,程序開始運行,注意,程序是在內存中運行的。這個時候,就需要把一些源文件從flash里面copy到內存中,又要對它們進行初始化讀寫,這又有頻率的設置。這些都是初始化。

 

初始化完成后,我們又要設置一些堆棧,要跳到C語言的main函數里面運行。這就需要堆棧。對普通的ARM CPU有這樣一個要求:在絕對地址為零的地方要放置一個異常向量表,但並不是所有的ARM CPU都留有這個一個空間,這就需要用到映射的功能。我們可以將其它地方的一些空間映射到絕對地址里面。當發生異常時,ARM核來讀取異常中斷表的時候,它會使用映射之后的那個表,這個就可以接着往下執行,否則在絕對地址零的地方找不到任何信息,程序就會死掉。這些運行的環境全部建立好后,程序就會跳轉到我們的main函數里面。

 

總之,啟動代碼,就是對最小系統的初始化。 包括晶振,CPU頻率等。

 

啟動代碼的最小系統是: 異常向量表的初始化 – 存儲區分配 – 初始化堆棧 – 高級語言入口函數調用 – main()函數。

 

程序的啟動過程:

點擊看大圖

以下面這個例子為例,編譯完后, DEBUG后,我們可以看到,光標指向絕對地址為零的地方,這里存放的就是一個異常向量表。

它對應在 startup.s 里的源文件如下:

點擊看大圖運行后,馬上跳轉到初始化CPU的頻率。即初始化鎖相環,將其鎖在一個固定的頻率。具體代碼如下:

 

; Setup PLL

 

                IF      PLL_SETUP <> 0

 

                LDR     R0, =PLL_BASE

 

                MOV     R1, #0xAA

 

                MOV     R2, #0x55

 

 

 

;  Configure and Enable PLL

 

                MOV     R3, #PLLCFG_Val

 

                STR     R3, [R0, #PLLCFG_OFS]

 

                MOV     R3, #PLLCON_PLLE

 

                STR     R3, [R0, #PLLCON_OFS]

 

                STR     R1, [R0, #PLLFEED_OFS]

 

                STR     R2, [R0, #PLLFEED_OFS]

 

 

 

;  Wait until PLL Locked

 

PLL_Loop        LDR     R3, [R0, #PLLSTAT_OFS]

 

                ANDS    R3, R3, #PLLSTAT_PLOCK

 

                BEQ     PLL_Loop

 

 

 

;  Switch to PLL Clock

 

                MOV     R3, #(PLLCON_PLLE:OR:PLLCON_PLLC)

 

                STR     R3, [R0, #PLLCON_OFS]

 

                STR     R1, [R0, #PLLFEED_OFS]

 

                STR     R2, [R0, #PLLFEED_OFS]

 

                ENDIF   ; PLL_SETUP

 

 

 

然后再初始化每一種模式的堆棧,再進行單步運行的時候,下面我們可以看到,它自動跳轉到 main()函數:

 

; Enter the C code

 

 

 

                IMPORT  __main

 

                LDR     R0, =__main

 

                BX      R0

 

 

 

 

 

                IF      :DEF:__MICROLIB

 

 

 

                EXPORT  __heap_base

 

                EXPORT  __heap_limit

 

 

 

                ELSE

 

 

 

這個時候,程序會運行各種 scatterload函數,將我們的堆棧、全局變量等內容拷貝到內存中去。拷貝完后,就正式跳轉到我們的 main() 函數中來執行了。

點擊看大圖

這就是啟動代碼執行的全過程,呵呵,平時我們看到以為只是執行main()函數就行了,是不是沒有想到在執行 main() 函數后還有這么多學問呢?


免責聲明!

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



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