從芯片架構到stm32

目錄
一.stm32的發展歷程 1

二.ARM處理器框圖 3

三.Stm32 存儲器映射(詳細地址可查看stm32 datasheet) 4

四.stm32編譯流程 6

五.stm32上電啓動流程 7

 

一.stm32的發展歷程
1.芯片領域三大架構

和stm32有啥關係?別急!

 

2.ARM架構發展歷程

注:

1>ARM公司在經典的ARM11以後的產品改用cortex命名,並分爲A,R和M三類(針對不同市場需求),cortex系列屬於ARMv7架構,ARMv7架構定義了三大分工明確的系列:“A”系列面向尖端的基於虛擬內存的操作系統和用戶應用;“R”系列針對實時系統;“M”系列對微控制器。我們所用的stm32就屬於M系列

2>以stm32F103爲例,就是屬於ARMv7架構,cortex-M系列下的M3核

3.ST公司及產品線

上面我們也說了,ARM公司只負責設計不負責生產芯片。stm32是ST公司生產的芯片。

簡介:

意法半導體(ST)集團於1987年成立,是由意大利的SGS微電子公司和法國Thomson半導體公司合併而成。1998年5月,SGS-THOMSON Microelectronics將公司名稱改爲意法半導體有限公司。

產品線:

二.ARM處理器框圖

注:流水線技術通過多個功能部件並行工作來縮短程序執行時間,提高處理器的效率和吞吐率。簡單來說,執行某條指令至少要通過取指、譯碼、執行三個步驟。

1.第一週期,PC指向指令1,此時指令1進入流水線取指階段

2.第二週期,PC指向指令2,此時進入譯碼階段,同時取出指令2

3.第三週期,PC指向指令3,此時進入執行階段,同時指令2進入譯碼階段,指令3取指

4.第四周期,指令1執行完成,指令2和三同時推進一級,開始指令4取指。。

就想水一樣,一級級推進。

三.Stm32 存儲器映射(詳細地址可查看stm32 datasheet)

四.stm32編譯流程
在我們平時stm32的開發中,一般都是使用keil和IAR等集成開發環境,整個的編譯過程其實我們並不理解,一些配置也是按照流程進行配置,一些參數爲什要這麼配置?一些文件爲什麼要添加?其實有時我們是並不太清楚的。

這裏先說一下,stm32的一個編譯下載過程。

我們的平時開發中,可能就是寫好.c文件,點下編譯後,生成了.hex文件,然後通過j-flash將程序下載到芯片中。

那麼圖中的.s文件,.ld文件我們有用到嗎??用的什麼編譯工具鏈。

 

1.其實我們在做芯片移植的時候,一般還要更改一個.s文件,它就是啓動文件,下面一會說啓動流程的時候詳細說。

它長這樣。

2. .ld文件是鏈接腳本,用來將多個.o鏈接起來的,我們在建工程後會有默認的鏈接腳本。在keil中也可以進行更改

Project -> Options for Target ... -> Linker

3.我們的編譯工具鏈也是可以更改的,

Project -> Manage-> Components ... -> Folders/Extensions

五.stm32上電啓動流程
我們正常在開發的時候,都是從main函數開始進行編程的,但是上電是從main函數開始執行的嗎?答案當然是否定的。

 

1.STM32三種啓動方式

STM32有三種啓動模式,通過設置BOOT0和BOOT1的引腳電平狀態,來選擇復位後的啓動模式。

需要注意的是STM32上電覆位以後,代碼區都是從0x00000000開始的,三種啓動模式只是將各自存儲空間的地址映射到0x00000000中。

1)從Flash啓動,將Flash地址0x08000000映射到0x00000000,這樣啓動以後就相當於從0x08000000開始的,這是我們最常用的模式;

2)從SRAM啓動,將SRAM地址0x20000000映射到0x00000000,這樣啓動以後就相當於從0x20000000開始的,用於調試;

3)從系統存儲器啓動,將系統存儲器地址0x1FFFF000映射到0x00000000,這樣啓動以後就相當於從0x1FFFF000開始執行的,值得注意的是這個系統存儲器裏面存儲的其實是STM32自帶的Bootloader代碼,這其實是一個官方的IAP,它提供了可以通過UART1接口將用戶的代碼下載到Flash中的功能,下載完以後再切換到從Flash中啓動就可以正常運行了。

 

注:這裏其實有個不太好理解的點。

我們在STM32的Flash在MDK裏被設置爲起始地址0x08000000,而CM3手冊規定芯片復位時要從0x00000000地址開始取出中斷向量。是不是我們可以將地址改到0地址呢??這樣問題不就解決了。

答案是不行的,STM32設計的Flash起始地址是在0x0800 0000位置開始的。全部代碼都只能從這裏開始存儲。

CM3中規定上電後CPU是從0地址開始執行,但是這裏中斷向量表卻被燒寫在0x0800 0000地址裏,那啓動時不就找不到中斷向量表了?既然CM3定下的規矩是從0地址啓動,SMT32當然不能破壞ARM定下的“規矩”,所以它做了一個啓動映射的過程。

當選擇從主Flash啓動模式後,芯片一上電,Flash的0x0800 0000地址被映射到0地址處,不影響CM3內核的讀取,所以這時的CM3既可以在0地址處訪問中斷向量表,也可以在0x0800 0000地址處訪問中斷向量表,而代碼還是在0x0800 0000地址處存儲的。

 

2.以FLASH啓動的方式從上電到main函數之間的這段時間都做了什麼??

直接打開我們的startup_stm32f10x_md.s看一下就知道了,它也給了相關描述。

總的執行流程如下所示:

1)第一步是硬件設置SP、PC,設置中斷向量表

初始化堆棧指針SP=_initial_sp

_initial_sp的值是怎麼得到的呢?這是根據STM32的SRAM分配規則計算的,SRAM從規定的地址開始分別存儲已初始全局和靜態變量、未初化全局和靜態變量、堆、棧,其中變量的長度是你寫程序後就固定了,堆和棧的長度則是在啓動代碼中定義的,那麼把它們加起來就會得於_initial_sp的值,編譯後,_initial_sp就被替代爲上述計算好的地址。

初始化PC指針=Reset_Handler

 

設置中斷向量表:

下面是.s文件中部分截圖:(stm32的有哪些異常可以查看數據手冊)

注:Cortex-M3內核規定,起始地址必須存放堆棧指針,而第二個地址必須存放復位中斷入口向量地址(是32位地址不是跳轉指令),這樣在內核復位後,會自動從起始地址的下一個32位空間取出復位中斷入口向量,跳轉執行復位中斷服務程序

這裏的起始地址是0x00000000而不是0x80000000上面已經說明。

程序在用戶Flash上的結構如下圖所示:

初始化數據段       .data

未初始化數據段      .bss 

加載數據段和初始化棧的參數(各4個)

2)第三步是設置系統時鐘

我們發現運行到了SystemInit,在項目文件的system_stm32f10x.c裏面可以找到SystemInit函數,也就是初始化系統時鐘了。

 

3)第三步是__main(初始化用戶堆棧)

到這裏大家可能會以爲已經到了main函數了,其實不是這樣的。___main和main是不一樣的,我們尋找這個___main會發現找不到,startup文件裏面沒有,map文件裏面也沒有。其實它是在MDK自帶的庫裏面了,主要的功能是軟件加載.data\.bss並初始化棧區。

注:第一步中只是將_initial_sp值存入了SP寄存器,只是一個棧頂指針,但堆的大小和棧的大小並沒有初始化,所以在_main中要把在啓動文件中定義好的值傳給C庫進行堆棧大小的初始化。無論是帶系統的,還是裸機程序,都要管理堆棧的大小,這就是會產生堆棧溢出的原因。

 

4)在執行到___main的最後就跳轉到了C文件的main函數了。
————————————————
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章