日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

stm32系列启动文件解读(KEIL编译环境)

發(fā)布時間:2024/10/14 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 stm32系列启动文件解读(KEIL编译环境) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

基于stm32f103c8t6芯片的啟動文件進(jìn)行分析。

啟動文件在嵌入式芯片開發(fā)是必不可少的,其文件后綴是.s,通常需要加入工程參與編譯。它的的用包括一下幾點:

  • 開辟棧、堆的空間。
  • 初始化中斷向量表。
  • 調(diào)用外部SystemInit函數(shù),初始化時鐘。
  • 調(diào)用C庫函數(shù)__main初始化用戶棧,調(diào)用main函數(shù)轉(zhuǎn)到C世界。
  • 啟動文件使用匯編語言編寫,如果熟悉匯編語言,那么很容易理解它;如果不熟悉匯編語言,針對啟動文件里用到的匯編指令,下面會一一介紹。

    1.啟動文件使用到的匯編指令

    指令名稱

    作用

    EQU

    給數(shù)據(jù)常量起一個符號名,相當(dāng)于C語言的#define

    AREA

    匯編一個新的代碼段或者數(shù)據(jù)段

    SPACE

    分配內(nèi)存空間

    PRESERVE8

    告訴編譯器,指定當(dāng)前文件的堆按照8字節(jié)對齊

    THUMB

    表示后面指令兼容THUMB指令。

    EXPORT

    聲明一個標(biāo)號具有外部屬性,可在外部文件使用

    DCD

    以字節(jié)為單位,按照4字節(jié)對齊,并要求初始化這些內(nèi)存

    PROC

    定義子程序,與ENDP成對使用,表示子程序結(jié)束。

    WEAK

    編譯器指令(不同的編譯器有差異),弱定義一個標(biāo)號,如果外部文件聲明了該標(biāo)號,則優(yōu)先使用外部文件的定義。避免出現(xiàn)重定義錯誤。

    IMPORT

    聲明標(biāo)號來自外部文件,相當(dāng)于C語言的extern

    B

    跳轉(zhuǎn)到一個標(biāo)號

    ALIGN

    編譯器指令(不同的編譯器有差異),編譯器對指令或數(shù)據(jù)的存放地址進(jìn)行對齊,一般跟一個立即數(shù),默認(rèn)表示按照4字節(jié)對齊。

    END

    文件結(jié)束標(biāo)志

    IF,ELSE,ENDIF

    匯編條件分支語句,相當(dāng)于C語言的#if #else #endif

    ;

    行注釋起始符號,相當(dāng)于C語言的“//“

    ?

    2.啟動文件代碼分析

    Stack_Size????? EQU???? 0x00000400AREA??? STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem?????? SPACE?? Stack_Size __initial_sp

    上面代碼定義了棧的大小為0x00000400(1KB),名稱為STACKNOINIT表示不初始化,REAWRITE表示可讀可下,ALIGN?= 3表示按照8(即2^3)字節(jié)對齊。還定義了標(biāo)號__initial_sp(棧的結(jié)束地址)。利用SPACE關(guān)鍵字來申請空間,大小為Stack_Size,記作Stack_Mem。棧是由高向低生長的。

    棧的空間用于局部變量、函數(shù)調(diào)用、函數(shù)形參等開銷,棧的大小不能超過芯片內(nèi)部SRAM大小;如果編寫的程序局部變量比較多,占用內(nèi)存比較大,會造成棧溢出,導(dǎo)致進(jìn)入硬故障,這時候需要考慮增加棧空間大小。

    Heap_Size?????? EQU???? 0x00000200AREA??? HEAP, NOINIT, READWRITE, ALIGN=3 __heap_baseHeap_Mem??????? SPACE?? Heap_Size __heap_limit

    ? ? ? ?上面的代碼定義了堆大小為0x00000200(512字節(jié)),名稱為HEAPNOINIT表示不初始化,READWRITE表示可讀可寫,ALIGN?= 3表示按照8(即2^3)字節(jié)對齊。還定義了標(biāo)號:__heap_base(堆的起始地址)、__heap_limit(堆的結(jié)束地址)。利用SPACE關(guān)鍵字來申請空間,大小為Heap_Size,記作Heap_Mem。堆是由低向高生長的,與棧的生長方向相反。

    ?????? 堆的主要用于動態(tài)內(nèi)存的分配,像malloc()函數(shù)申請的內(nèi)存就在堆中。這個在STM32里面用得比較少。

    ??????????????? PRESERVE8THUMB

    上面兩個在前面的指令表格里已經(jīng)說明。

    ; Vector Table Mapped to Address 0 at ResetAREA??? RESET, DATA, READONLYEXPORT? __VectorsEXPORT? __Vectors_EndEXPORT? __Vectors_Size

    上面代碼定義了一個數(shù)據(jù)段,名稱為RESET,僅可讀,還聲明了3個外部文件可以使用的標(biāo)號:__Vectors(向量表起始地址)、__Vectors_End(向量表結(jié)束地址)、__Vectors_Size(向量表大小)。

    向量表其實就是一個WORD(32bit整數(shù))數(shù)組,每一個下標(biāo)對應(yīng)一種異常,該下標(biāo)元素的值則是該ESR的入口地址。向量表在地址空間的位置是可以被設(shè)置的,同過NVIC中的一個重定位寄存器來指定向量表的地址。復(fù)位之后,該寄存器的值為0。因此,在地址0(即flash地址0)處必須包含一張向量表,用于初始化時的異常分配。

    接下來的代碼就是分配向量表的內(nèi)存

    __Vectors?????? DCD???? __initial_sp?????????????? ; Top of Stack(棧頂?shù)刂?#xff09;DCD???? Reset_Handler????????????? ; Reset Handler(復(fù)位程序地址)DCD???? NMI_Handler??????????????? ; NMI HandlerDCD???? HardFault_Handler????????? ; Hard Fault HandlerDCD???? MemManage_Handler????????? ; MPU Fault HandlerDCD???? BusFault_Handler?????????? ; Bus Fault HandlerDCD???? UsageFault_Handler???????? ; Usage Fault HandlerDCD???? 0??????????????? ??????????; Reserved(保留)DCD???? 0????????????????????????? ; ReservedDCD???? 0????????????????????????? ; ReservedDCD???? 0????????????????????????? ; ReservedDCD???? SVC_Handler????????? ??????; SVCall HandlerDCD???? DebugMon_Handler?????????? ; Debug Monitor HandlerDCD???? 0????????????????????????? ; ReservedDCD???? PendSV_Handler???????????? ; PendSV HandlerDCD???? SysTick_Handler??????????? ; SysTick Handler; External InterruptsDCD???? WWDG_IRQHandler??????????? ; Window WatchdogDCD???? PVD_IRQHandler???????????? ; PVD through EXTI Line detectDCD???? TAMPER_IRQHandler????????? ; Tamper;(中間代碼省略)DCD???? EXTI15_10_IRQHandler?????? ; EXTI Line 15..10DCD???? RTCAlarm_IRQHandler??????? ; RTC Alarm through EXTI LineDCD???? USBWakeUp_IRQHandler?????? ; USB Wakeup from suspend __Vectors_End__Vectors_Size? EQU? __Vectors_End - __Vectors

    ?????? 上面代碼利用DCD關(guān)鍵字以4字節(jié)對齊,分配了一堆內(nèi)存,類似之前SPACE關(guān)鍵字的作用。利用__Vectors_End(堆結(jié)束地址)減去__Vectors(堆的起始地址)得到堆的大小__Vectors_Size。

    ?????? 向量表從flash的0地址開始放置,以4字節(jié)為一個單位,地址0存放的時棧頂?shù)刂?#xff0c;接著0x04存放的時復(fù)位程序的地址,以此類推。向量表中存放的都是中斷函數(shù)的函數(shù)名,可我們知道C語言中函數(shù)名就是一個地址。

    AREA??? |.text|, CODE, READONLY

    ?????? 上面代碼表示是定義一個名稱為.text的代碼段,僅可讀。

    ?????? ; Reset handler Reset_Handler??? PROCEXPORT? Reset_Handler???????????? [WEAK]IMPORT? __mainIMPORT? SystemInitLDR???? R0, =SystemInitBLX???? R0LDR???? R0, =__mainBX????? R0ENDP

    ?????? 復(fù)位子程序是系統(tǒng)上電第一個執(zhí)行的程序,調(diào)用SystemInit函數(shù)(sysyem_stm32f4xx.c文件里定義的)初始化系統(tǒng)時鐘等,然后調(diào)用C庫函數(shù)_main(編譯器自帶的),在_main函數(shù)里最終會調(diào)用main函數(shù)轉(zhuǎn)到C的世界。

    ?????? LDR、BLX、BX是CM4內(nèi)核的指令:

    LDR:從儲存器中加載一個字到寄存器中。

    BL:跳轉(zhuǎn)到由寄存器/標(biāo)號給出的地址,并把跳轉(zhuǎn)前的下一條指令保存到LR中。

    BLX:跳轉(zhuǎn)到由寄存器/標(biāo)號給出的地址,并根據(jù)寄存器的LSE確定處理器的狀態(tài),并把跳轉(zhuǎn)前的下一條指令保存到LR中。

    BX:跳轉(zhuǎn)到有寄存器/標(biāo)號給出的地址,不用返回。

    接下來的代碼就是中斷服務(wù)程序的實現(xiàn),一般來說,我們會在外部的c文件實現(xiàn)中斷函數(shù),這里定義了只是備用,以防我們把某個中斷使能了,但忘了實現(xiàn)它的中斷函數(shù)或者函數(shù)名寫錯,那么系統(tǒng)就會執(zhí)行下面的程序,并且下面的中斷函數(shù)會進(jìn)入無限循環(huán),程序也就死在這里。

    NMI_Handler???? PROC ?? ;不可屏蔽的系統(tǒng)異常中斷EXPORT? NMI_Handler??????????????? [WEAK]B?????? .ENDPHardFault_Handler\???????????? ;所有類型錯誤的中斷PROCEXPORT? HardFault_Handler????????? [WEAK]B?????? .ENDP(省略一部分代碼)SysTick_Handler PROC??????? ;系統(tǒng)滴答定時器中斷EXPORT? SysTick_Handler??????????? [WEAK]B?????? .ENDPDefault_Handler PROC??????? ;外設(shè)中斷EXPORT? WWDG_IRQHandler??????????? [WEAK]EXPORT? PVD_IRQHandler???????????? [WEAK]EXPORT? TAMPER_IRQHandler????????? [WEAK] (省略一部分代碼)RTCAlarm_IRQHandlerUSBWakeUp_IRQHandlerB?????? .ENDPALIGN

    B:跳轉(zhuǎn)到一個標(biāo)號,這里跳轉(zhuǎn)到一個‘.’,表示無限循環(huán)。

    ;*******************************************************************************; User Stack and Heap initialization;*******************************************************************************IF????? :DEF:__MICROLIB? ;這個宏在KEIL里面開啟? ???????????????????EXPORT? __initial_spEXPORT? __heap_baseEXPORT? __heap_limit?????????????ELSE???????????????IMPORT? __use_two_region_memory???? ;這個函數(shù)由用戶自己實現(xiàn)EXPORT? __user_initial_stackheap?????????? __user_initial_stackheapLDR???? R0, =? Heap_MemLDR???? R1, =(Stack_Mem + Stack_Size)LDR???? R2, = (Heap_Mem +? Heap_Size)LDR???? R3, = Stack_MemBX????? LRALIGNENDIFEND

    如果勾選【Options for Target->Target->Use MicroLIB】,那么就會定義宏__MICROLOB。

    如果定義了__MICROLOB,那么把__initial_sp(棧起始地址)、__heap_base(堆開始地址)、__heap_limit(堆結(jié)束地址)標(biāo)號賦予全局屬性,那么在外部文件也可以使用,然后堆和棧的初始化就由C庫函數(shù)__main來完成。

    如果沒有定義__MICROLOB,采用雙段存儲器模式,且聲明標(biāo)號__user_initial_stackheap具有全局性,讓用戶自己來初始化堆和棧。KEIL C庫函數(shù)會調(diào)用__user_initial_stackheap,通過R0~R3將堆棧以參數(shù)形式傳遞給KEIL C庫。

    總結(jié)

    以上是生活随笔為你收集整理的stm32系列启动文件解读(KEIL编译环境)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 欧美一级特黄aaaaaa | 美女扒开腿让人桶爽原神 | 人人搞人人插 | 黄色一级二级 | 国产区一区二 | 亚洲欧美日本另类 | 欧美精品 在线观看 | 综合色站导航 | 国产精品一级无码 | 夜夜爽日日澡人人添 | 97久久国产 | 欧美人体视频 | 91免费看国产 | 久久东京 | 91中文国产| 日本少妇吞精囗交视频 | 中文字幕日韩在线观看 | 国精产品一区二区三区 | 亚州色图欧美色图| 黄视频国产 | www.欧美色| 日韩精品免费 | 色婷婷国产精品视频 | 国产中出 | 欧美福利网站 | 欧美成人黑人xx视频免费观看 | 亚洲666| 涩涩涩999 | 视频在线一区 | 日本在线一 | www日韩精品| 美国少妇在线观看免费 | 成人午夜视频在线免费观看 | 精品一区二区久久久 | 成人激情视频在线播放 | 国产一区二区中文字幕 | 中文字幕精品在线视频 | 99久久人妻精品免费二区 | 免费看黄色片的网站 | 800av凹凸| 黑人操亚洲女 | caopeng在线视频 | 精品久久久一区二区 | 五个女闺蜜把我玩到尿失禁 | 国产福利第一页 | 日韩一区二区不卡视频 | 美女穴穴 | 一区二区成人在线 | 69性视频| 日本人妻不卡一区二区三区中文字幕 | 国产免费久久精品国产传媒 | 精品乱码一区内射人妻无码 | 日韩h视频 | 夜夜欢视频 | 草莓视频成人在线 | 91精品国产综合久久久蜜臀 | 在线观看国产亚洲 | 男女黄床上色视频免费的软件 | 国产精品无码专区av免费播放 | 中文字幕一区三区 | 日本一区不卡在线观看 | 精品一区二区日韩 | h片免费网站 | 久久久久99精品成人片试看 | 高清人妖shemale japan | 欧美激情片在线观看 | 成人日韩在线观看 | 激烈的性高湖波多野结衣 | 欧美精品亚洲 | 极品91尤物被啪到呻吟喷水 | 日韩xxxxxxxxx | 亚洲精品乱码久久久久久蜜桃动漫 | 超碰97成人| 国产精品久久久久免费 | 色婷婷久久久亚洲一区二区三区 | 国产专区在线视频 | 精品国产无码一区二区 | 日本亲子乱子伦xxxx50路 | 很黄很污的视频网站 | 97视频在线 | 亚洲一区二区精华 | 色噜噜综合 | 日韩久久久 | 狠狠狠狠狠狠狠干 | 波多野结衣视频免费 | 在线观看亚洲a | 欧洲一级黄 | 久久精品国产亚洲AV成人婷婷 | 狠狠操操| www插插插无码免费视频网站 | 精品少妇人妻av一区二区 | 在线免费观看污 | 亚洲av无码一区二区乱子仑 | 日韩精品一区不卡 | 欧美性受xxxx狂喷水 | 免费网站黄色 | 亚洲国产精品狼友在线观看 | 亚洲一区二区三区免费看 | 中文字幕日韩在线播放 |