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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU启动那些事(6)- Bootable image格式与加载(elftosb/.bd)...

發(fā)布時間:2023/12/14 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU启动那些事(6)- Bootable image格式与加载(elftosb/.bd)... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

  大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家介紹的是恩智浦i.MX RT1xxx系列MCU的Bootable image格式與加載過程

  在i.MXRT1xxx啟動系列第三篇文章 Serial Downloader模式(sdphost, mfgtool) 里痞子衡在介紹使用sdphost引導(dǎo)啟動Flashloader時使用過一個名叫ivt_flashloader.bin的image文件,其實這個image文件就是Bootable image的一種,雖然痞子衡簡單分析過ivt_flashloader的組成,但介紹得并不詳盡,今天痞子衡會為大家系統(tǒng)地講解i.MXRT Bootable image。

一、什么是Bootable image?

  如果你是一個有經(jīng)驗的嵌入式開發(fā)者,肯定對image格式有所了解,我們通常開發(fā)的Application都是針對含內(nèi)部FLASH的MCU而言的,比如Kinetis、LPC、STM32等MCU,其內(nèi)部集成了一塊Parallel NOR FLASH,且FLASH地址是映射在ARM 4GB system address內(nèi)的(一般從0x0地址開始),FLASH里存儲的直接就是我們編譯鏈接后生成的原始Application binary(.bin),沒有任何多余的數(shù)據(jù)組成。或許你會說還有.hex, .srec等其他image格式,是的,但這些帶地址信息的image格式是為編程器或下載器服務(wù)的,這些image格式經(jīng)過編程器或者下載器解析后真正下載進MCU內(nèi)部FLASH的數(shù)據(jù)還是原始Application binary。這類MCU上電后CPU能直接從內(nèi)部FLASH獲取Application代碼并原地執(zhí)行(XIP),所以對這類MCU而言,Bootable image就是存儲在內(nèi)部FLASH的Application binary(.bin)。
  但是以上經(jīng)驗在開發(fā)i.MXRT時遇到了問題,i.MXRT沒有內(nèi)部FLASH,需要外接FLASH存儲器以存儲image。眾所周知,FLASH從結(jié)構(gòu)上分為NOR和NAND,i.MXRT啟動同時支持這兩種FLASH,NOR FLASH可以實現(xiàn)XIP,NAND FLASH不可以XIP,為了兼容所有FLASH,在設(shè)計i.MXRT bootable image格式時必須以非XIP這種情況為基準(zhǔn)。既然是非XIP執(zhí)行,即意味著i.MXRT上電時會將image從外接FLASH拷貝到內(nèi)部SRAM中去執(zhí)行,在拷貝時必不可免要知道兩個重要的數(shù)據(jù):image鏈接起始地址(決定image被拷貝到SRAM哪個地址)、image總長度(決定要從外部FLASH拷貝多長的image數(shù)據(jù)進SRAM),實際上除了這兩個最基本的數(shù)據(jù)外還有其他更高級的數(shù)據(jù)(配置、安全等特性),因此存儲在外接FLASH的i.MXRT Bootable image除了含有Application binary數(shù)據(jù)之外還必須含有額外的信息,這些額外的信息數(shù)據(jù)與Application binary共同組成i.MXRT Bootable image。至于這些額外的信息在Bootable image里是如何組織的,痞子衡在后面會繼續(xù)聊。

二、Bootable image鏈接空間

  一個image的鏈接空間分兩種,一種是只讀段(readonly code,data)的鏈接空間,另一種是讀寫段(readwrite data, STACK)的鏈接空間,這兩種鏈接空間要求的存儲介質(zhì)特性不一樣,痞子衡逐一講解:
  前面講了i.MXRT同時支持外接NOR和NAND FLASH,其中NAND FLASH無法XIP,那么存儲在NAND FLASH中的image只讀段必須要鏈接在SRAM里。i.MXRT內(nèi)部有三種SRAM,分別是ITCM, DTCM, OCRAM,是不是這三種SRAM都可以被隨意鏈接呢?答案并不是!因為在Boot期間,BootROM也需要占用SRAM,用于存放BootROM的讀寫段,所以被BootROM占用的SRAM無法用于鏈接image的只讀段,如果強行鏈接,會導(dǎo)致BootROM在拷貝image只讀段時破壞自身讀寫段,從而發(fā)生不可預(yù)料的行為。下圖是RT1050 BootROM的memory map,從圖中可以得知BootROM占用的是0x20200000開始的OCRAM,并且看起來是整塊OCRAM都被占用了,所以不推薦使用OCRAM去鏈接image只讀段。
  黑科技:如果有朋友表示不服,RT1060/RT1050/RT1020的OCRAM是1MB/512KB/256KB,BootROM讀寫段不可能有這么大,是的,痞子衡告訴你,其實BootROM數(shù)據(jù)段只要32KB(0x20200000 - 0x20207FFF),另外還需要4KB用加載initial non-XIP image(0x20208000 - 0x20208FFF),所以對于存儲在non-XIP FLASH的image你可以從0x20209000之后的空間里鏈接image只讀段,而對于存儲在XIP FLASH的image你可以從0x20208000之后的空間里鏈接image只讀段,這個秘密一般人痞子衡是不會告訴他的。

  前面講了存儲在NAND FLASH中的image只讀段鏈接注意事項,而對于可以XIP的NOR FLASH,除了跟NAND一樣可以將只讀段鏈接在SRAM外,還可以鏈接在i.MXRT分配給外接存儲器的XIP映射空間里,下表給出了Serial NOR(QSPI)和Parallel NOR(SEMC)各自的映射起始地址,需要注意的是Serial NOR支持的最大XIP空間為504MB,但是Parallel NOR支持的最大XIP空間只有16MB,別問痞子衡是怎么知道的,痞子衡無所不知。

  至于image的讀寫段,在鏈接時就不用區(qū)別Non-XIP/XIP FLASH了,都只能放在SRAM里,并且不用考慮BootROM對SRAM的占用問題(因為不在一個時間域里被使用),只要注意不和image自身只讀段沖突就行。
  黑科技:有朋友注意到了SDRAM,是的i.MXRT也支持SDRAM,通過SEMC接口去實現(xiàn)SDRAM讀寫,所以如果外接了SDRAM并且使能的話,也可以將image只讀段/讀寫段放入SDRAM,關(guān)于SDRAM的使用,痞子衡會在后面文章里介紹。

三、Bootable image七大組成

  Bootable image是由一些額外的信息數(shù)據(jù)與Application binary共同組成的,那些額外的信息數(shù)據(jù)按功能分有6類,但這6類信息數(shù)據(jù)并不都是必須的,其中有4類是可選的,因此一個Bootable image最多由7部分組成,最少由3部分組成。下面痞子衡按在FLASH里存儲位置從低到高的順序逐一介紹組成Bootable image的7大部分:

3.1 偏移0x0000: FDCB(Flash Device Configuration Block)

  第一個組成部分叫FDCB,是個可選組成,目前只用于Serial/Parallel NOR FLASH,FDCB是從FLASH的起始地址處開始存放的,也是Bootable image最開始部分。FDCB最大4KB,其本身沒有統(tǒng)一的與FLASH無關(guān)的structure,具體structure根據(jù)啟動FLASH的接口類型(Serial/Parallel)而定,其一般是用來存儲當(dāng)前連接的FLASH的具體特性參數(shù),BootROM上電會使用通用且可靠的FLASH接口控制器配置(即BootROM中默認(rèn)參數(shù)配置,一般是比較低速的配置)去訪問外接FLASH并獲取FDCB,然后根據(jù)FDCB存儲的參數(shù)去重新配置FLASH接口控制器再去進一步訪問FLASH。下面的結(jié)構(gòu)體是Serial NOR的FDCB原型,此處痞子衡不會展開介紹這個結(jié)構(gòu)體,留到后續(xù)介紹Serial NOR啟動再詳細(xì)介紹。

typedef struct _flexspi_nor_config {flexspi_mem_config_t memConfig; //!< Common memory configuration info via FlexSPIuint32_t pageSize; //!< Page size of Serial NORuint32_t sectorSize; //!< Sector size of Serial NORuint8_t ipcmdSerialClkFreq; //!< Clock frequency for IP commanduint8_t isUniformBlockSize; //!< Sector/Block size is the sameuint8_t reserved0[2]; //!< Reserved for future useuint8_t serialNorType; //!< Serial NOR Flash type: 0/1/2/3uint8_t needExitNoCmdMode; //!< Need to exit NoCmd mode before other IP commanduint8_t halfClkForNonReadCmd; //!< Half the Serial Clock for non-read command: true/falseuint8_t needRestoreNoCmdMode; //!< Need to Restore NoCmd mode after IP commmand executionuint32_t blockSize; //!< Block sizeuint32_t reserve2[11]; //!< Reserved for future use } flexspi_nor_config_t;

3.2 偏移0x0400/0x1000: IVT(Image Vector Table)

  第二個組成部分叫IVT,是個必備組成,也是6類信息數(shù)據(jù)里的最核心數(shù)據(jù),IVT是一個統(tǒng)一的與FLASH無關(guān)的structure,其原型如下面結(jié)構(gòu)體所示,從結(jié)構(gòu)體定義我們得知,IVT中記錄了Application、DCD、BD、CSF的位置信息,這些信息對BootROM加載啟動至關(guān)重要。IVT大小固定為32byte,其在Bootable image中的偏移位置也是固定的(對于XIP FLASH而言偏移是0x1000,對于Non-XIP FLASH而言偏移是0x400)。有朋友會疑問為何IVT偏移地址是固定的?其實答案很簡單,因為BootROM必須要首先獲取IVT才能進一步找到其他信息數(shù)據(jù),而IVT本身的位置信息沒有在其他地方被標(biāo)明,所以只能在BootROM里用一個常量來記錄。

#define HAB_TAG_IVT0 0xd1 /**< Image Vector Table V0 *//** @ref hab_header structure */ typedef struct hab_hdr {uint8_t tag; /**< Tag field */uint8_t len[2]; /**< Length field in bytes (big-endian) */uint8_t par; /**< Parameters field */ } hab_hdr_t;/** @ref ivt structure */ struct hab_ivt_v0 {/** @ref hdr with tag #HAB_TAG_IVT0, length and HAB version fields */hab_hdr_t hdr;/** Absolute address of the first instruction to execute from the image */uint32_t entry;/** Reserved in this version of HAB: should be NULL. */uint32_t reserved1;/** Absolute address of the image DCD: may be NULL. */uint32_t dcd;/** Absolute address of the Boot Data: may be NULL, but not interpreted any further by HAB */uint32_t boot_data;/** Absolute address of the IVT.*/uint32_t self;/** Absolute address of the image CSF.*/uint32_t csf;/** Reserved in this version of HAB: should be zero. */uint32_t reserved2; };

3.3 偏移0x0420/0x1020: BD(Boot Data)

  第三個組成部分叫BD,是個必備組成,是僅次于IVT的核心數(shù)據(jù),BD也是一個統(tǒng)一的與FLASH無關(guān)的structure,其原型如下面結(jié)構(gòu)體所示,BD中記錄了Bootable image的起始地址與總長度。BD大小固定為16byte,BD信息雖然記錄在了IVT中,但其在Bootable image中的偏移位置并不是任意的,BD是緊挨著IVT的。

/** @ref boot_data structure */ typedef struct boot_data{uint32_t start; /* Start address of the image */uint32_t size; /* Size of the image */uint32_t plugin; /* Plugin flag */uint32_t placeholder; /* placehoder to make even 0x10 size */ } BOOT_DATA_T;

3.4 DCD(Device Configuration Data)

  第四個組成部分叫DCD,是個可選組成,目前主要用于SDRAM接口控制器(SEMC)的配置。由于i.MXRT內(nèi)部SRAM size通常是夠用的,且訪問速度也很快,所以SDRAM并不一定要被使能,Bootable image常常不會包含DCD,所以痞子衡在這里先不做展開,后續(xù)有必要會再介紹。下面是SDK_2.3.1_EVKB-IMXRT1050包里hello_world工程(flexspi_nor)所使用DCD示例:

#define DCD_TAG_HEADER (0xD2)const uint8_t dcd_data[] = {/*0000*/ DCD_TAG_HEADER,0x04,0x30,0x41,0xCC,0x03,0xAC,0x04,0x40,0x0F,0xC0,0x68,0xFF,0xFF,0xFF,0xFF,/*0010*/ 0x40,0x0F,0xC0,0x6C,0xFF,0xFF,0xFF,0xFF,0x40,0x0F,0xC0,0x70,0xFF,0xFF,0xFF,0xFF,.../*0420*/ 0x00,0x00,0x00,0x01,0xCC,0x00,0x0C,0x04,0x40,0x2F,0x00,0x4C,0x50,0x21,0x0A,0x09, };

3.5 偏移0x2000: Application Binary

  第五個組成部分是你最熟悉的Application binary,當(dāng)然是個必備組成,其在Bootable image中的偏移位置是固定的(0x2000),關(guān)于Application本身這里就不再贅述了。只特別提一點,那就是i.MXRT的Application只讀段(主要指ARM中斷向量表)并不可以從任意地址開始鏈接,有一個小小的限制,必須從選定的存儲器地址空間偏移0x2000之后開始鏈接(如選中ITCM,則必須要鏈接在0x00002000之后;如選中DTCM,則必須鏈接在0x20002000之后...),因為要預(yù)留至少8KB空間給IVT、BD、DCD等數(shù)據(jù),這個限制是BootROM自身決定的,務(wù)必要注意

3.6 CSF(Command Sequence File)

  第六個組成部分叫CSF,是個特性組成,主要用于安全啟動的認(rèn)證相關(guān)特性,痞子衡會在安全啟動里進一步介紹。

3.7 KeyBlob

  第七個組成部分叫KeyBlob,是個特性組成,主要用于安全啟動的加密相關(guān)特性,痞子衡會在安全啟動里進一步介紹。

  上圖是包含IVT、BD、DCD、Application、CSF的Bootable image的layout,這張圖很好地詮釋了IVT的作用。

四、Bootable image三種分類

  前面介紹了Bootable image最多有7大組成,有些是必備,有些是可選,有的是特性。而在實際應(yīng)用中,主要是必備+特性的組合形成如下三種常用分類:

  • Unsigned Image: 這是最簡單的image類型,由IVT+BD+Application組成,主要用于產(chǎn)品開發(fā)階段。
  • Signed Image: 這是較復(fù)雜的image類型,由IVT+BD+Application+CSF組成,一般用于產(chǎn)品發(fā)布階段。
  • Encrypted Image: 這是最復(fù)雜的image類型,由IVT+BD+Application+CSF+KeyBlob組成,主要用于對安全要求較高的產(chǎn)品中。

五、使用elftosb生成Bootable image

  恩智浦官方提供了一個用于生成Bootable image的工具,名叫elftosb,這個工具就在\Flashloader_i.MXRT1050_GA\Flashloader_RT1050_1.1\Tools\elftosb目錄下,這個工具可以用來生成所有類型的Bootable image,命令格式固定如下:

elftosb.exe -f imx -V -c config_application.bd -o ivt_application.bin application.out

  其中ivt_application.bin就是最終生成的Bootable image,命令所需要的2個輸入文件分別是application.out、config_application.bd,application.out就是你的Application工程編譯鏈接生成的ELF文件,config_application.bd是用戶配置文件,這個.bd文件主要是指示elftosb工具如何在Application binary基礎(chǔ)上添加IVT、BD等其他信息數(shù)據(jù)從而形成Bootable image,所以編寫.bd文件是關(guān)鍵步驟,bd文件有專門語法格式,但\Flashloader_i.MXRT1050_GA\Flashloader_RT1050_1.1\Tools\bd_file\imx10xx目錄下給了很多bd文件示例,我們只需要在某一個bd文件基礎(chǔ)上修改即可

  如果你追過痞子衡博客文章,你應(yīng)該知道痞子衡曾經(jīng)實測過RT1052的coremark性能,coremark工程已經(jīng)上傳到痞子衡的github https://github.com/JayHeng/cortex-m_app,工程路徑在\cortex-m_app\apps\coremark_imxrt1052\bsp\build\coremark.eww,編譯此工程可得到coremark_a000.out和coremark_a000.bin文件,coremark程序只讀段鏈接在ITCM地址(0x0000a000),我們來試著使用elftosb將coremark程序轉(zhuǎn)換成bootable image,bd文件可參考imx-itcm-unsigned.bd,打開這個參考bd文件:

options {flags = 0x00;# Note: This is an example address, it can be any non-zero address in ITCM regionstartAddress = 0x8000;ivtOffset = 0x400;initialLoadSize = 0x2000;# Note: This is required if the default entrypoint is not the Reset_Handler # Please set the entryPointAddress to Reset_Handler address // entryPointAddress = 0x60002411; }sources {elfFile = extern(0); }section (0) { }

  ivtOffset和initialLoadSize不用改,分別代表IVT和Application在Bootable image中的偏移地址,startAddress即BOOT_DATA_T.start,這個是可以修改的,牢記下面公式:

startAddress + initialLoadSize = Application只讀段起始鏈接地址

  coremark_a000.out是鏈接在0xa000地址處的,0x8000 + 0x2000 = 0xa000,所以此處startAddress也無需改,唯一需要確認(rèn)的是entryPointAddress,保險起見統(tǒng)一將entryPointAddress設(shè)成Application的復(fù)位中斷地址,即entryPointAddress = 0x0000ecd1。bd文件修改完成之后另存為config_coremark_a000.bd,讓我們試著執(zhí)行下面命令:

elftosb.exe -f imx -V -c config_coremark_a000.bd -o ivt_coremark_a000.bin coremark_a000.out

  分別打開coremark_a000.bin和ivt_coremark_a000.bin,可以看到ivt_coremark_a000.bin比coremark_a000.bin多了前8KB的數(shù)據(jù),這前8KB里包含了有效的IVT(偏移0x400)和BD(偏移0x420)。

六、Bootable image的加載過程

  知道了Bootable image的構(gòu)成,痞子衡最后再簡要為大家介紹一下i.MXRT BootROM是如何從外部存儲器中加載Bootable image進SRAM內(nèi)存的。以non-XIP image加載為例(image鏈接在ITCM里),下圖顯示了i.MXRT加載image的四個階段:

  • 第一個階段即加載前,此時Bootable image完全存儲在外部Flash中,SRAM中沒有任何image數(shù)據(jù);
  • 第二階段即初始加載,BootROM首先會從外部Flash讀取Bootable image前4KB數(shù)據(jù)進SRAM臨時緩存區(qū)(OCRAM:0x20208000 - 0x20208FFF),我們知道這4KB數(shù)據(jù)里包含了IVT和BD,BootROM從IVT和BD里獲取到Bootable image的目標(biāo)地址(BOOT_DATA_T.start)以及總長度(BOOT_DATA_T.size),此時便可以開始做進一步加載;
  • 第三階段即內(nèi)部轉(zhuǎn)移,由于BootROM已經(jīng)從外部Flash讀取了4KB進SRAM臨時緩存區(qū),為了避免重復(fù)讀取,BootROM會把這4KB數(shù)據(jù)首先復(fù)制到Bootable image的目標(biāo)地址(ITCM);
  • 第四階段即加載完成,BootROM會接著將剩下的Bootable image(BOOT_DATA_T.size - 4KB)從外部Flash中全部讀取出來存到目標(biāo)區(qū)域(ITCM)完成全部加載。

  至此,恩智浦i.MX RT1xxx系列MCU的Bootable image格式與加載過程痞子衡便介紹完畢了,掌聲在哪里~~~

歡迎訂閱

文章會同時發(fā)布到我的 博客園主頁、CSDN主頁、微信公眾號 平臺上。

微信搜索"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。

總結(jié)

以上是生活随笔為你收集整理的痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU启动那些事(6)- Bootable image格式与加载(elftosb/.bd)...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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