国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

從文件角度,了解Cortex-M開發(二)

454398 ? 來源:alpha007 ? 作者:alpha007 ? 2022-11-25 17:59 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

在前一節課《源文件(.c/.h/.s)》里,痞子衡給大家系統地介紹了 source 文件,source 文件是嵌入式工程里典型的 input 文件,那么還有沒有其他類型的 input 文件?既然痞子衡這么提問了,那答案肯定是有啦。今天痞子衡要講的 linker 文件就屬于另一種 input 文件。


linker 文件顧名思義就是嵌入式工程在鏈接階段所要用到的文件,source 文件在編譯過程完成之后(此時已經是機器可識別的二進制機器碼數據),需要再經過鏈接器從而將二進制數據有序組織起來形成最終的二進制可執行文件,該二進制文件最終會被下載進芯片內部非易失性存儲器里。linker 文件就是用來指示鏈接器如何組織編譯生成的二進制數據。


linker 文件是跟 IDE 息息相關的,本文以 IAR EWARM 為例介紹 linker 文件,其他 IDE 下的 linker 文件可觸類旁通。


一、 嵌入式系統中的 section

在講 linker 文件之前,痞子衡必須先跟大家理清一個嵌入式系統中很重要的概念 -section。那么什么是 section?我們寫的 C 或者匯編 source 文件里都是各種應用代碼,這些代碼按功能可以分為很多種類,比如常量、變量、函數、堆棧等,而相同類型的代碼的集合便是一個 section,鏈接器在鏈接時組織數據的基本單元便是 section。那么一個典型的嵌入式系統中到底有多少種 section 呢?下面列出了 IAR 里默認的所有 section,那些常見 section 在后續介紹 linker 文件里會被提到。


// 常見 Section


.bss // Holds zero-initialized static and global variables.


CSTACK // Holds the stack used by C or C++ programs.


.data // Holds static and global initialized variables.


.data_init // Holds initial values for .data sections when the linker directive initialize is used.


HEAP // Holds the heap used for dynamically allocated data.


.intvec // Holds the reset vector table


.noinit // Holds __no_init static and global variables.


.rodata // Holds constant data.


.text // Holds the program code.


.textrw // Holds __ramfunc declared program code.


.textrw_init // Holds initializers for the .textrw declared section.

// 較冷僻 Section


.exc.text // Holds exception-related code.


__iar_tls.$$DATA // Holds initial values for TLS variables.


.iar.dynexit // Holds the atexit table.


.init_array // Holds a table of dynamic initialization functions.


IRQ_STACK // Holds the stack for interrupt requests, IRQ, and exceptions.


.preinit_array // Holds a table of dynamic initialization functions.


.prepreinit_array // Holds a table of dynamic initialization functions.


Veneer$$CMSE // Holds secure gateway veneers.

// 更冷僻 Section


.debug // Contains debug information in the DWARF format


.iar.debug // Contains supplemental debug information in an IAR format


.comment // Contains the tools and command lines used for building the file


.rel or .rela // Contains ELF relocation information


.symtab // Contains the symbol table for a file


.strtab // Contains the names of the symbol in the symbol table


.shstrtab // Contains the names of the sections.


Note:上述 section 的詳細解釋請查閱 IAR 軟件安裝目錄下 /IAR Systems/Embedded Workbench

xxx/arm/doc/EWARM_DevelopmentGuide.ENU.pdf 文檔里的 Section reference 一節。


二、解析 linker 文件

知道了 section 概念,那便可開始深入了解 linker 文件,什么是 linker 文件?linker 文件是按 IDE 規定的語法寫成的用于指示鏈接器分配各 section 在嵌入式系統存儲器中存放位置的文件。大家都知道嵌入式系統存儲器主要分為兩類:ROM(非易失性),RAM(易失性),所以相應的這些 section 根據存放的存儲器位置不同也分為兩類屬性:readonly, readwrite。實際上 linker 文件的工作就是將 readonly section 放進 ROM,readwrite section 放進 RAM。


那么到底該如何編寫工程的 linker 文件呢?正如前面所言,linker 文件也是有語法的,而且這語法是由 IDE 指定的,所以必須要先掌握 IDE 制定的語法規則,linker 文件語法規則相對簡單,最常用的關鍵字就是如下 8 個:


// 動詞類關鍵字


define // 定義各種空間范圍、長度


initialize // 設置 section 初始化方法


place in // 放置 section 于某 region 中(具體地址由鏈接器分配)


place at // 放置 section 于某絕對地址處

// 名詞類關鍵字


symbol // 各種空間范圍、長度的標識


memory // 整個 ARM 內存空間的標識


region // 在整個 ARM 內存空間中劃分某 region 空間的標識


block // 多個 section 的集合塊的標識


Note:上述 linker 語法的詳細解釋請查閱 IAR 軟件安裝目錄下 /IAR Systems/Embedded Workbench

xxx/arm/doc/EWARM_DevelopmentGuide.ENU.pdf 文檔里的 The linker configuration file 一節。


到這里我們已經可以開始愉快地寫 linker 文件了,是不是有點按捺不住了?來吧,只需要三步走,Let's do it。


此處假設 MCU 物理空間為:ROM(0x0 - 0x1ffff)、RAM(0x10000000 - 0x1000ffff),痞子衡要寫的 linker 要求如下:


中斷向量表必須放置于 ROM 起始地址 0x0,且必須 256 字節對齊


STACK 大小為 8KB,HEAP 大小為 1KB,且必須 8 字節對齊


SATCK 必須放置在 RAM 起始地址 0x10000000


其余 section 放置在正確的 region 里,具體空間由鏈接器自動分配


2.1 定義物理空間

第一步我們先定義 3 塊互不重疊的空間 ROM_region、RAM_region、STACK_region,其中 ROM_region 對應的是真實的 ROM 空間,RAM_region 和 STACK_region 組合成真實的 RAM 空間。


// 定義物理空間邊界


define symbol __ICFEDIT_region_ROM_start__ = 0x00000000;


define symbol __ICFEDIT_region_ROM_end__ = __ICFEDIT_region_ROM_start__ + (128*1024 - 1);


define symbol __ICFEDIT_region_RAM_start__ = 0x10000000;


define symbol __ICFEDIT_region_RAM_end__ = __ICFEDIT_region_RAM_start__ + (64*1024 - 1);


define symbol __ICFEDIT_intvec_start__ = __ICFEDIT_region_ROM_start__;

// 定義堆棧長度


define symbol __ICFEDIT_size_cstack__ = (8*1024);


define symbol __ICFEDIT_size_heap__ = (1*1024);

// 定義各 region 具體空間范圍


define memory mem with size = 4G;


define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];


define region STACK_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_start__ +

__ICFEDIT_size_cstack__ - 1];


define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ + __ICFEDIT_size_cstack__ to

__ICFEDIT_region_RAM_end__];


2.2 定義 section 集合

第二步是自定義 section 集合塊,細心的朋友可以看到右邊花括號里包含的都是上一節介紹的系統默認 section,我們會把具有相同屬性的 section 集合成到一個 block 里,方便下一步的放置工作。


// 定義堆棧塊及其屬性


define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };


define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };

// 定義 section 集合塊


define block Vectors with alignment=256 { readonly section .intvec };


define block CodeRelocate { section .textrw_init };


define block CodeRelocateRam { section .textrw };


define block ApplicationFlash { readonly, block CodeRelocate };


define block ApplicationRam { readwrite, block CodeRelocateRam, block HEAP };


有朋友可能會疑問,為何要定義 CodeRelocate、CodeRelocateRam 這兩個 block?按道理說這兩個 block 對應的 section 可以分別放進 ApplicationFlash 和 ApplicationRam,那為何多此一舉?仔細上過痞子衡前一節課 source 文件的朋友肯定就知道答案了,在那節課里介紹的 startup.c 文件里有一個叫 init_data_bss()的函數,這個函數會完成初始化 CodeRelocateRam 塊的功能,它找尋的就是 CodeRelocate 段名字,這個名字比系統默認的 textrw 名字看起來更清晰易懂。


2.3 安置 section 集合

第三步便是處理放置那些 section 集合塊了,在放置集合塊之前還有 initialize manually 語句,為什么會有這些語句?還是得結合前面提及的 startup.c 文件里的 init_data_bss()函數來說,這個函數是開發者自己實現的 data,bss 段的初始化,所以此處需要通知 IDE,你不需要再幫我做初始化工作了。


// 設置初始化方法


initialize manually { readwrite };


initialize manually { section .data};


initialize manually { section .textrw };


do not initialize { section .noinit };

// 放置 section 集合塊


place at start of ROM_region { block Vectors };


//place at address mem:__ICFEDIT_intvec_start__ { block Vectors };


place in ROM_region { block ApplicationFlash };


place in RAM_region { block ApplicationRam };


place in STACK_region { block CSTACK };


當然如果你希望 IDE 幫你自動初始化 data,bss,textrw 段,那么可以用下面語句替換 initialize manually 語句。


initialize by copy { readwrite, section .textrw };


設置好初始化方法后,便是放置 section 集合塊了,放置方法主要有兩種,place in 和 place at,前者用于指定空間塊放置(不指定具體地址),后者是指定具體地址放置。


至此一個基本的 linker 文件便大功告成了,是不是 so easy?


番外一、自定義 section

有耐心看到這里的朋友,痞子衡必須得放個大招獎勵一下,前面講的都是怎么處理系統默認段,那么有沒有可能在代碼里自定義段呢?想象一下你有這樣的需求,你需要在你的應用里開辟一塊 1KB 的可更新的數據區,你想把這個數據區指定到地址 0x18000 - 0x183ff 的范圍內,你需要在應用里定義 4 Byte 的只讀 config block 常量指向這個可更新數據區首地址(這段 config block 只會被外部 debugger 或者 bootloader 更新),如何做到?


// C 文件中


/////////////////////////////////////////////////////


// 用@操作符指定變量 myConfigBlock[4]放進自定義 .myBuffer section


const uint8_t myConfigBlock[4] @ ".myBuffer" = {0x00, 0x01, 0x02, 0x03};

// Linker 文件中


/////////////////////////////////////////////////////


// 自定義指定的 mySection_region,并把 .myBuffer 放到這個 region


define region mySection_region = mem:[from 0x0x18000 to 0x183ff];


place at start of mySection_region { readonly section .myBuffer };


上面做到了將代碼中的常量放入自定義段?,那么怎么將代碼中的函數也放進自定義段呢?繼續看下去


// C 文件中


/////////////////////////////////////////////////////


// 用#pragma location 指定函數 myFunction()放進自定義 .myTask section


#pragma location = ".myTask"


void myFunction(void)


{


__NOP();


}

// Linker 文件中

/////////////////////////////////////////////////////

// 把 .myTask 放到 mySection_region


place in mySection_region { readonly section .myTask };


看起來大功告成了,最后還有一個注意事項,如果 myConfigBlock 在代碼中并未被引用,IDE 在鏈接的時候可能會忽略這個變量(IDE 認為它沒用,所以優化了),那么怎么讓 IDE 強制鏈接 myConfigBlock 呢?IAR 留了個后門,在 options->Linker->Input 選項卡中的 Keep symbols 輸入框里填入你想強制鏈接的對象名(注意是代碼中的對象名,而非 linker 文件中的自定義段名)即可。


Note:關于番外內容的更多細節請查閱 IAR 軟件安裝目錄下 /IAR Systems/Embedded Workbench

xxx/arm/doc/EWARM_DevelopmentGuide.ENU.pdf 文檔里的 Pragma directives 一節。


至此,嵌入式開發里的 linker 文件痞子衡便介紹完畢了,掌聲在哪里~~~

審核編輯黃昊宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 嵌入式
    +關注

    關注

    5198

    文章

    20445

    瀏覽量

    334002
  • Linker
    +關注

    關注

    0

    文章

    3

    瀏覽量

    1937
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    Cortex-M0和Cortex-M0+的區別

    ),但是只使用了Thumb ISA的一個子集(56條指令),多數指令是16位,只有少數一些事32位。 一般來說,盡管指令具有不同大小,Cortex-M處理器可被歸為精簡指令集架構。 支持可選的單周期
    發表于 01-22 06:23

    最小化ARM Cortex-M CPU功耗的方法與技巧分享

    1 理解Thumb-2   首先,讓我們從一個看起來并不明顯的起點開始討論節能技術—指令集。所有Cortex-M CPU都使用Thumb-2指令集,它融合了32位ARM指令集和16位Thumb指令集
    發表于 01-21 06:19

    Cortex-M0 處理器介紹

    功耗的32位處理器。 Cortex-M0是Cortex-M家族中的M0系列。最大特點是低功耗的設計。Cortex-M0為32位、3級流水線RISC處理器,其核心仍為馮.諾依曼結構,是指
    發表于 01-16 08:04

    探索HRPS - M50霍爾效應角度傳感器:工業應用的理想之選

    探索HRPS-M50霍爾效應角度傳感器:工業應用的理想之選 在電子工程師的日常工作中,角度傳感器是一個至關重要的組件,它廣泛應用于工業自動化、交通運輸、可再生能源等眾多領域。今天,我們就來深入
    的頭像 發表于 12-10 10:05 ?412次閱讀

    Cortex-M產品的特色

    開發支持:設計人員可從ARM生態系統的許多工具中選擇,或者使用單一、全面的工具鏈支持所有Cortex-M器件。 架構擴展:ARM還提供了一系列的架構擴展用于滿足下一代處理器的需求,如DSP擴展、SIMD指令、浮點單元和Helium技術,為特定應用場景提供了
    發表于 11-26 07:22

    Cortex-M內核中的精確延時的方法

    使用 CYCCNT寄存器來測量執行某個任務所花的周期數,這也可以用作時間基準相關的目的(操作系統中統計 CPU使用率可以用到它)。” Cortex-M中的DWT它有一個32位的寄存器叫CYCCNT
    發表于 11-21 07:51

    Cortex-M級別的轉換

    一、 簡述 Cortex-M 里面有特權級別的概念,不同級別可以設定不同的權限,如何轉換特權級別基本是本章的內容。 、操作模式 ARM M 核操作模式有兩個: 線程(Thread)模式:在復位時或
    發表于 11-19 07:32

    明晚8點|睿擎文件系統實戰:開發到發布全流程解析

    文件操作到鏡像發布,一次直播掌握完整開發流程!在嵌入式系統開發中,文件系統是數據存儲、配置管理和資源訪問的核心基礎。然而在實際
    的頭像 發表于 11-11 11:53 ?641次閱讀
    明晚8點|睿擎<b class='flag-5'>文件</b>系統實戰:<b class='flag-5'>從</b><b class='flag-5'>開發</b>到發布全流程解析

    睿擎派文件系統指南:開發到發布全流程實踐 | 技術解析

    在嵌入式系統開發中,文件系統扮演著至關重要的角色,它負責數據的持久化存儲、配置文件管理和資源訪問等核心功能。睿擎平臺提供了一套完整的文件系統解決方案,
    的頭像 發表于 11-05 18:13 ?8094次閱讀
    睿擎派<b class='flag-5'>文件</b>系統指南:<b class='flag-5'>從</b><b class='flag-5'>開發</b>到發布全流程實踐 | 技術解析

    【RA-Eco-RA6M4開發板評測】使用ULINK2開發瑞薩MCU

    · 支持 ARM7、ARM9、Cortex-M、8051 和 C166 設備 · JTAG 速度高達 10MHz · 針對基于 ARM Cortex-M 的設備的串行線調試 (SWD) 支持 · 適用于
    發表于 09-25 23:08

    如何 MCU/MPU 角度保護物聯網應用?

    如何 MCU/MPU 角度保護物聯網應用?
    發表于 09-08 07:33

    請問NuMicro? Cortex-M? 系列芯片是否支持 I2C 監視器功能?

    NuMicro? Cortex-M? 系列芯片是否支持 I2C 監視器功能?
    發表于 08-21 06:04

    嵌入式開發入門指南:從零開始學習嵌入式

    (設備驅動、內核編譯) 4. 推薦的學習資源書籍:《嵌入式系統軟件設計基礎》《ARM Cortex-M系列嵌入式開發》在線課程:慕課網、B站嵌入式教學視頻實踐平臺:Arduino、STM32開發
    發表于 05-15 09:29

    i.MX8MMini中的Cortex-M4不支持SDIO嗎?

    的 FreeRTOS,我們 NXP 論壇獲取了信息,并正在努力為 RTOS 構建環境 我們注意到,在構建完成后移植無線驅動程序時。 RTOS 的當前源代碼不包括 SDIO 驅動程序。 i.MX8MMini 中的 Cortex-M4 不支持 SDIO 嗎? 如果支持,您能
    發表于 04-03 06:45

    瑞薩RA8快速上手指南:Cortex-M85內核瑞薩RA8開發環境搭建 并點亮一個LED

    因為Cortex-M內核,瑞薩RA8系列單片機支持多種市面上常見的開發環境,像Keil MDK、IAR EWARM等,而本文講述的是瑞薩自家官方的IDE(e2 studio)。
    的頭像 發表于 03-17 14:35 ?1927次閱讀
    瑞薩RA8快速上手指南:<b class='flag-5'>Cortex-M</b>85內核瑞薩RA8<b class='flag-5'>開發</b>環境搭建 并點亮一個LED