<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      MCU啟動(dòng)流程、文件與keil配置

      文件

      map文件

      Section Cross References
      這部分內(nèi)容描述了各個(gè)文件之間函數(shù)的調(diào)用關(guān)系,如下圖main.o(i.main) refers to sys.o(i.sys_stm32_clock_init) for sys_stm32_clock_init,表示main.c文件中的main函數(shù)調(diào)用了sys.c中的sys_stm32_clock_init函數(shù)。i.main表示main函數(shù)的入口地址,i.sys_stm32_clock_init表示sys_stm32_clock_init的入口地址。
      image

      Removing Unused input sections from the image
      這部分內(nèi)容描述了工程中由于未被調(diào)用而被刪除的冗余程序段(函數(shù)/數(shù)據(jù))。
      image

      Image Symbol Table
      映像符號(hào)表(Image Symbol Table)描述了被引用的各個(gè)符號(hào)(程序段/數(shù)據(jù))在存儲(chǔ)器中的存儲(chǔ)地址、類型、 大小等信息。分為本地符號(hào)(Local Symbols)和全局符號(hào)(Global Symbols)。

      Local Symbols
      本地符號(hào)(Local Symbols)記錄了用static聲明的全局變量地址和大小, c文件中函數(shù)的地址和用static聲明的函數(shù)代碼大小,匯編文件中的標(biāo)號(hào)地址(作用域:本文件)。

      .text 段
      內(nèi)容:代碼(程序指令)、常量(const)、中斷向量表。
      位置:通常放在Flash(只讀存儲(chǔ)器)。
      特點(diǎn):程序不會(huì)在運(yùn)行時(shí)修改.text段內(nèi)容。
      map文件里顯示從某個(gè)地址(如 0x08000000)開(kāi)始,大小等于編譯出的代碼量。

      .data 段
      內(nèi)容:已初始化的全局變量/靜態(tài)變量。
      位置:運(yùn)行時(shí)在 RAM,但初始化值存放在Flash。
      啟動(dòng)時(shí)操作:Reset_Handler會(huì)把Flash中的初值拷貝到 RAM。
      map文件里會(huì)看到 .data 在RAM中的地址范圍和大小,也會(huì)有對(duì)應(yīng)的Load Region指向Flash地址。

      .bss 段
      內(nèi)容:未初始化的全局變量/靜態(tài)變量,編譯器會(huì)自動(dòng)填0。
      位置:RAM中。
      啟動(dòng)時(shí)操作:Reset_Handler會(huì)把.bss段區(qū)域清零。
      map文件里會(huì)顯示起始地址和大小,初始值全0。

      Global Symbols
      全局符號(hào)(Global Symbols)記錄了全局變量的地址和大小, C文件中函數(shù)的地址及其代碼大小,匯編文件中的標(biāo)號(hào)地址(作用域:全工程)。

      Memory Map of the image
      映像文件分為加載域(Load Region)和運(yùn)行域(Execution Region),一個(gè)程序可以有多個(gè)加載域,一個(gè)加載域有至少一個(gè)運(yùn)行域。加載域?yàn)橛诚癯绦虻膶?shí)際存儲(chǔ)區(qū)域,運(yùn)行域是MCU上電后的運(yùn)行狀態(tài)。加載域和運(yùn)行域的簡(jiǎn)化關(guān)系如圖所示,在執(zhí)行main函數(shù)之前, RW(有初值且不為0的變量)數(shù)據(jù)會(huì)被拷貝到RAM區(qū),同時(shí)還會(huì)在RAM里面創(chuàng)建ZI區(qū)(初始化為0的變量)。
      image
      映像的入口地址,也就是整個(gè)程序運(yùn)行的起始地址,為0x08000131。
      LR_IROM1加載域,其內(nèi)部包含兩個(gè)運(yùn)行域:ER_IROM1和RW_IRAM1。
      image
      image

      Image component sizes
      映像組件大小(Image component sizes)給出了整個(gè)映像所有代碼(.o)占用空間的匯總信息。
      image
      表示.c/.s 文件生成對(duì)象所占空間大小(單位:字節(jié),下同),即.c/.s 文件編
      譯后所占代碼空間的大小。
      image
      表示被提取的庫(kù)成員( .lib)添加到映像中的部分所占空間大小。
      image
      表示本工程全部程序匯總后的占用情況。

      .S文件

      棧空間配置
      image
      EQU是宏定義的偽指令, 類似C中的define。定義棧大小為0x00000400字節(jié),1024B(1KB)。
      AREA命令匯編一個(gè)新的代碼段或者數(shù)據(jù)段。段名為STACK;NOINIT表示不初始化;READWRITE表示可讀寫(xiě);ALIGN=3,表示按照2^3即8字節(jié)對(duì)齊。
      SPACE 分配內(nèi)存指令, 分配大小為 Stack_Size 字節(jié)連續(xù)的存儲(chǔ)單元給棧空間。
      __initial_sp挨著SPACE放置,表示棧的結(jié)束地址,棧是從高往低生長(zhǎng),所以結(jié)束地址就是棧頂?shù)刂贰S糜诖娣啪植孔兞浚瘮?shù)形參等,屬于編譯器自動(dòng)分配和釋放的內(nèi)存,大小不能超過(guò)內(nèi)部SRAM的大小。
      image
      查看map文件可以看出,棧大小與.s文件配置相同。

      這里只定義了棧大小,棧的起始位置在keil的“option for target”的target里配置。

      堆空間配置
      image
      如果不使用C庫(kù)的malloc和free等函數(shù),就用不到堆空間,可以設(shè)置Heap_Size的大小為0。

      中斷向量表
      AREA RESET, DATA, READONLY
      定義一個(gè)只讀的段名字為RESET,放在數(shù)據(jù)段里。

      .s文件里的中斷向量表(.vectors或者叫中斷向量表)就是一張函數(shù)指針表,本質(zhì)上是一段連續(xù)的存儲(chǔ)單元,里面存放的是地址(函數(shù)入口地址或者初始棧指針地址),MCU硬件在復(fù)位或發(fā)生中斷時(shí)會(huì)根據(jù)這張表找到要執(zhí)行的函數(shù)。

       __Vectors     DCD     __initial_sp               ; Top of Stack
                      DCD     Reset_Handler              ; Reset Handler
                      DCD     NMI_Handler                ; NMI Handler
                      DCD     HardFault_Handler          ; Hard Fault Handler
                      ...
      __Vectors_End
      

      DCD: 分配一個(gè)或者多個(gè)以字為單位的內(nèi)存,以四字節(jié)對(duì)齊,并要求初始化這些內(nèi)存。
      __initial_sp:初始棧頂指針值(MCU 上電后,SP=這個(gè)值)。
      Reset_Handler的地址:復(fù)位時(shí) CPU 會(huì)跳轉(zhuǎn)執(zhí)行這個(gè)函數(shù)。
      后面依次是NMI、中斷服務(wù)函數(shù)的入口地址。

      中斷發(fā)生時(shí),NVIC硬件會(huì)去查這張表,取出對(duì)應(yīng)的函數(shù)入口地址,CPU 跳轉(zhuǎn)到這個(gè)函數(shù)執(zhí)行。這些函數(shù)就是在startup_xxx.s里定義的xxx_Handler。

      中斷向量表被放置在代碼段的最前面。程序在FLASH運(yùn)行時(shí),向量表的起始地址是0x0800 0000。地址0x0800 0000存放的是棧頂?shù)刂贰CD是以四字節(jié)對(duì)齊分配內(nèi)存,也就是下個(gè)地址是0x0800 0004,存放的是Reset_Handler中斷函數(shù)入口地址。向量表中存放的都是中斷服務(wù)函數(shù)的函數(shù)名, 所以C語(yǔ)言中的函數(shù)名對(duì)芯片來(lái)說(shuō)實(shí)際上就是一個(gè)地址。

      復(fù)位程序
      AREA |.text|, CODE, READONLY
      定義一個(gè)名為 .text 的只讀代碼段,存放的是指令(代碼)。|...| 表示名字是字符串,不需要符合符號(hào)命名規(guī)則。

      image
      利用PROC、ENDP這一對(duì)偽指令把程序段分為若干個(gè)過(guò)程,使程序的結(jié)構(gòu)加清晰。
      PROC表示子程序開(kāi)始。

      EXPORT Reset_Handler [WEAK]
      聲明復(fù)位中斷向量Reset_Handler為全局屬性,這樣外部文件就可以調(diào)用此復(fù)位中斷服務(wù)。WEAK表示弱定義,如果外部文件優(yōu)先定義了該標(biāo)號(hào)則首先引用外部定義的標(biāo)號(hào),如果外部文件沒(méi)有聲明也不會(huì)出錯(cuò)。這里表示復(fù)位子程序可以由用戶在其他文件重新實(shí)現(xiàn)。

      IMPORT __main
      IMPORT表示該標(biāo)號(hào)來(lái)自外部文件。這里表示__main這個(gè)函數(shù)來(lái)自外部的文件。

      LDR R0, =__main
      把符號(hào)__main的地址加載到寄存器R0。這里的__main不是程序員寫(xiě)的main(),而是C運(yùn)行時(shí)庫(kù)的入口函數(shù)(C runtime,CRT)。作用是初始化C環(huán)境,比如:
      初始化.data段(把Flash中的初始值拷貝到RAM)。
      清零.bss段。
      調(diào)用SystemInit()配置時(shí)鐘、外設(shè)。
      最后才調(diào)用真正的main()。_main和main是兩個(gè)完全不同的函數(shù)。_main代碼是編譯器自動(dòng)創(chuàng)建的。

      BX R0
      跳轉(zhuǎn)到R0里保存的地址,也就是執(zhí)行__main函數(shù)。

      ENDP 表示子程序結(jié)束。

      中斷服務(wù)程序
      image
      image

      中斷函數(shù)分為系統(tǒng)異常中斷和外部中斷,外部中斷根據(jù)不同芯片有所變化。B指令是跳轉(zhuǎn)到一個(gè)‘.’,表示無(wú)限循環(huán)。
      這些中斷服務(wù)函數(shù)都被[WEAK]聲明為弱定義函數(shù),如果外部文件聲明了一個(gè)標(biāo)號(hào),則優(yōu)先使用外部文件定義的標(biāo)號(hào),如果外部文件沒(méi)有定義也不會(huì)出錯(cuò)。

      用戶堆棧配置
      image
      第一行判斷是否定義了__MICROLIB。__MICROLIB這個(gè)宏定義在KEIL的“option for target”的target里配置。如果定義__MICROLIB,則__initial_sp、__heap_base和__heap_limit這三個(gè)標(biāo)號(hào)具有全局屬性,可被外部的文件使用。__initial_sp表示棧頂?shù)刂罚琠_heap_base表示堆起始地址,__heap_limit表示堆結(jié)束地址。
      如果沒(méi)有定義__MICROLIB,則使用默認(rèn)的 C 庫(kù)運(yùn)行。堆棧的初始化由C庫(kù)函數(shù)__main完成。

      IMPORT __use_two_region_memory
      告訴匯編器本文件里要用到外部符號(hào)__use_two_region_memory,符號(hào)的作用是選擇內(nèi)存分配模型:
      two-region model(常見(jiàn)):堆(heap)從RAM的低地址向上長(zhǎng),棧(stack)從RAM的高地址向下長(zhǎng),二者之間逐漸逼近。
      one-region model:堆和棧放在一起,由用戶自己管理。
      大多數(shù) Cortex-M 項(xiàng)目默認(rèn)就是 two-region 模型。

      EXPORT __user_initial_stackheap
      對(duì)外導(dǎo)出一個(gè)函數(shù)符號(hào),ARM C庫(kù)在啟動(dòng)時(shí)會(huì)調(diào)用它,用來(lái)得到堆和棧的初始位置。
      LDR R0, = Heap_Mem
      保存堆起始地址。
      LDR R1, =(Stack_Mem + Stack_Size)
      保存棧大小。
      LDR R2, = (Heap_Mem + Heap_Size)
      保存堆大小。
      LDR R3, = Stack_Mem
      保存棧頂指針。
      BX LR
      跳轉(zhuǎn)到 LR 標(biāo)號(hào)給出的地址,不用返回。

      .sct文件

      是Keil/ARM編譯器(ARMCC)或Arm Compiler 6 (armclang)用來(lái)描述鏈接過(guò)程和內(nèi)存布局的文件,叫做scatter file(分散加載文件)。新建一個(gè)工程時(shí)Keil會(huì)根據(jù)芯片的Flash和RAM大小,生成一個(gè)默認(rèn)的.sct文件。如果需要更復(fù)雜的內(nèi)存分布(多段RAM、外部SDRAM、雙區(qū)Flash),開(kāi)發(fā)者需要手動(dòng)寫(xiě).sct。
      MCU廠商(如 ST、NXP、瑞薩)提供的Keil示例工程里通常已經(jīng)寫(xiě)好了.sct文件,配合啟動(dòng)文件(startup_xxx.s)使用。

      LR_IROM1 0x08000000 0x00040000  {    ; load region size_region
        ER_IROM1 0x08000000 0x00040000  {  ; load address = execution address
         *.o (RESET, +First)
         *(InRoot$$Sections)
         .ANY (+RO)
         .ANY (+XO)
        }
        RW_IRAM1 0x20000000 0x0000C000  {  ; RW data
         .ANY (+RW +ZI)
        }
      }
      

      LR_IROM1表示整個(gè)工程的 Load Region(裝載位置)——對(duì)應(yīng) Flash。
      ER_IROM1是Execution Region(執(zhí)行位置)——程序?qū)嶋H運(yùn)行時(shí)的代碼位置。
      .ANY (+RO) 把所有只讀段(.text、.rodata)放到 Flash。
      .ANY (+RW +ZI)把.data(RW,帶初值的全局變量)和.bss(ZI,Zero Init,未初始化變量)放到RAM。

      系統(tǒng)啟動(dòng)流程

      MCU上下電會(huì)被復(fù)位,上電后執(zhí)行的程序?qū)嶋H上就是復(fù)位時(shí)執(zhí)行的程序。.S類的啟動(dòng)文件由芯片廠商提供。啟動(dòng)文件用匯編編寫(xiě),是系統(tǒng)上電復(fù)位后第一個(gè)執(zhí)行的程序。啟動(dòng)文件主要做了以下工作:
      1、初始化堆棧指針SP = _initial_sp
      2、初始化程序計(jì)數(shù)器指針PC = Reset_Handler(這兩步是硬件完成,無(wú)需軟件參與)
      3、配置堆棧起始地址、大小
      4、初始化.data數(shù)據(jù)段,從flash中復(fù)制到SRAM(這步開(kāi)始是_main()函數(shù))
      5、清零.bss全局未初始化變量
      6、調(diào)用系統(tǒng)初始化函數(shù)systemInit(),配置時(shí)鐘系統(tǒng)
      7、最終調(diào)用main函數(shù)

      示例

      打開(kāi)一個(gè)keil工程,打開(kāi)debug并點(diǎn)擊reset,查看0x0800 0000處的值,可以看到和SP、PC寄存器的值相同(差一是ARM和thumb指令的規(guī)則)。同時(shí)查看map文件可以看到,和__initial_sp以及startup_stm32f103xe.o(.text)的值相同。
      QQ_1756048779984
      圖中左邊還能看到,Cortex‐M3處理器擁有R0‐R15的寄存器組。其中R13作為堆棧指針SP。SP有兩個(gè),但在同一時(shí)刻只能有一個(gè)可以看到。
      image

      posted @ 2025-08-25 00:04  CSUFT_NJU  閱讀(94)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 国产精品日韩中文字幕熟女 | 韩国主播av福利一区二区| 精品无码午夜福利理论片| 免费人妻av无码专区| 风韵丰满熟妇啪啪区老熟熟女 | 欧美日韩中文字幕视频不卡一二区| 久9视频这里只有精品| 中文字幕乱码一区二区免费| 免费无码AV一区二区波多野结衣 | 久久久这里只有精品10| 在国产线视频A在线视频| 成人免费在线播放av| 麻豆国产成人AV在线播放| 云南省| 干老熟女干老穴干老女人| 日本国产一区二区三区在线观看| 国色天香成人一区二区| 九色综合国产一区二区三区| 影音先锋大黄瓜视频| 国产精品色内内在线播放| 四虎影视一区二区精品| 亚洲激情视频一区二区三区| 内射少妇一区27p| 亚洲香蕉av一区二区蜜桃| 91亚洲免费视频| 日韩少妇人妻vs中文字幕| 国语对白刺激在线视频国产网红| 亚洲成在人线在线播放无码| 久久久久久无码午夜精品直播| 网友偷拍视频一区二区三区| 国产乱人伦偷精品视频下| 精品免费看国产一区二区| 国产精品黄色片在线观看| 国产一区二区三区AV在线无码观看| 乱码精品一区二区亚洲区| 国产成人永久免费av在线 | 露脸一二三区国语对白| 国产成人综合在线观看不卡| 伊人久久大香线蕉AV网| 国产成人精品免费视频app软件| gogogo高清在线观看视频中文|