隨著汽車智能化程度的提高,集成的ECU(Electronic Control Unit)數量不斷增加,OTA(Over-the-Air)技術變得越來越普遍,它允許車輛通過無線網絡接收軟件更新,從而實現功能升級和性能改進,提高了便利性。
根據硬件的不同特性,OTA有對應的實現策略:[1]
如果硬件支持A/B Swap,對應的應用程序只需要鏈接一次就可以在兩個不同的物理地址運行;
如果硬件不支持A/B Swap,對應的應用程序可以通過ROPI(Read-Only Position-Independent)的方式實現在不同的物理地址運行。
基于Arm的MCU在汽車行業(yè)中廣泛使用,IAR Embedded Workbench for Arm是一套完整的集成開發(fā)環(huán)境,符合ISO 26262功能安全標準,支持Arm的編譯和調試。本文主要以Arm Cortex-M為例介紹如何在IAR Embedded Workbench for Arm中實現ROPI。
01Arm ROPI介紹
Arm ROPI并沒有特別的寄存器來實現,而是通過基于PC的相對地址訪問代碼和只讀數據:

02在IAR Embedded Workbench for Arm中實現ROPI
在IAR Embedded Workbench for Arm中實現ROPI非常方便,勾選對應的ROPI編譯選項(C/C++ Compiler > Code > Position-independence > Code and read-only data (ropi)):

下面通過一個簡單的例子介紹如何在IAR Embedded Workbench for Arm中實現ROPI。
假設對應Code Flash的地址區(qū)間是:0x00000000 ~ 0x0007FFFF (512KB)。其中Bootloader的地址區(qū)間是0x00000000 ~ 0x00007FFF (32KB) ,而Application的地址區(qū)間分別為: 0x00008000 ~ 0x00043FFF (240KB) 和0x00044000 ~ 0x0007FFFF (240KB) 。
Application鏈接的時候使用的地址區(qū)間0x00008000 ~ 0x00043FFF:
defineregion IROM_region = mem:[from 0x00008000 to 0x00043fff]; placein IROM_region {readonly}; placeat address mem: 0x00008000 {readonlysection .intvec };
map文件顯示對應Application放到地址區(qū)間0x00008000 ~ 0x00043FFF:



由于Arm Cortex-M向量表包含的是MSP初始值和對應異常服務函數的地址:

對應異常服務函數的地址是一個絕對地址,為了讓向量表支持ROPI,需要對向量表做對應的處理,其中最簡單的方法就是把向量表放到RAM區(qū)域:
SECTIONCSTACKNOROOT(3) SECTION .intvecROOT(2) EXTERN __iar_program_start EXTERN SystemInit EXTERN main PUBLIC __vector_table DATA __vector_table DCDsfe(CSTACK) … ; Relocate VectorTabletoRAM SECTION.intvec_ramNOROOT(2) PUBLIC __vector_table_ram DATA __vector_table_ram DCDsfe(CSTACK)
在icf文件中把向量表放到RAM指定位置:
place ataddressmem:0x1fff8000 {section.intvec_ram};
然后Bootloader在跳轉到Application之前需要根據Application實際運行的地址修改對應的向量表:
/* Copy vector table from ROM to RAM and add corresponding offset for ROPI !!!*/ #pragmasection =".intvec" staticvoidCopyVectorTable(void) { constuint32_tu32NrOfVectors = (uint32_t) __section_size(".intvec") /4U; uint32_t*constpu32RamTable = (uint32_t*) (0x1FFF8000U); uint32_t*constpu32RomTable = (uint32_t*) (0x00044000U); /* The 1st element is MSP which does not add offset for ROPI !!! */ pu32RamTable[0] = pu32RomTable[0]; /* Following elements need add corresponding offset for ROPI !!! */ for(uint32_tu32Index =1U; u32Index < u32NrOfVectors; u32Index++) ?{ ? pu32RamTable[u32Index] = pu32RomTable[u32Index] +?0x0003C000U; ?} }
下面啟動代碼里面的Reset_Handler實現不支持ROPI:
THUMB PUBWEAK Reset_Handler SECTION.textREORDER:NOROOT(2) Reset_Handler LDR R0, =SystemInit BLX R0 LDR R0, =__iar_program_start BX R0
需要將對應向量表中的Reset_Handler改成main函數:
SECTIONCSTACKNOROOT(3) SECTION .intvecROOT(2) EXTERN __iar_program_start EXTERN SystemInit EXTERN main PUBLIC __vector_table DATA __vector_table DCDsfe(CSTACK) DCD main ;main … ; Relocate VectorTabletoRAM SECTION.intvec_ramNOROOT(2) PUBLIC __vector_table_ram DATA __vector_table_ram DCDsfe(CSTACK) DCD main ;main …同時在main函數里面調用SystemInit和__iar_data_init3函數:
void__iar_data_init3(void);
intmain(void)
{
SystemInit();
__iar_data_init3();
…
對應program entry配置為main函數:

在Bootloader工程中下載調試來驗證對應Application是否支持ROPI。
在Bootloader調試選項(Debugger > Images > Download extra image)中添加對應Application.out文件并配置對應的Offset (0x00044000 - 0x00008000 = 0x0003C000):

Bootloader在跳轉到Application之前根據Application實際運行的地址修改對應的向量表 (對應向量表包含的地址需要是Application實際運行的地址):

然后Bootloader跳轉到向量表中指定的Application的入口 (main函數):

Application中的異常服務函數可以正常運行:

說明對應Application成功實現ROPI(因為Application鏈接到地址區(qū)間0x00008000 ~ 0x00043FFF,同樣可以在地址區(qū)間0x00044000 ~ 0x0007FFFF正常運行)。
03
注意事項
當前IAR Embedded Workbench for Arm中ROPI實現有如下相關限制:

如果ROPI程序中有需要跳轉到其他非ROPI程序中使用絕對地址運行的函數(比如對應函數運行在RAM的絕對地址),那么在ROPI程序中需要使用__absolute關鍵字聲明對應函數:

調試ROPI程序的時候,如果ROPI程序實際運行地址區(qū)間跟ROPI程序鏈接的地址區(qū)間不一樣的時候,需要配置對應的Offset(對應Offset的值是程序實際運行地址減去程序鏈接的地址)。另外Debug info only選項表示調試器只加載對應調試信息,而不下載對應程序:

05總結
本文主要以Arm Cortex-M為例介紹了如何在IAR Embedded Workbench for Arm中實現ROPI,更多關于在IAR Embedded Workbench for Arm中實現ROPI的信息,歡迎聯系IAR中國。
參考文獻:
1. https://www.vector.com/us/en/products/application-areas/embedded-software/embedded-trends/ota-update-approaches/
2. IAR Embedded Workbench for Arm C/C++ Development Guide
3. Arm Cortex-M4 Devices Generic User Guide
4. NXP AN5163 Load Position-Independent Code (PIC) on a Kinetis Platform Using the IAR EWARM Compiler
5. https://mypages.iar.com/s/article/Execute-in-RAM-after-copying-from-Flash-or-ROM?language=en_US
6. https://www.iar.com/knowledge/webinars-and-events/all-you-need-to-know-about-position-independent-code-and-data
7. https://mypages.iar.com/s/article/Position-independent-code-and-data-ROPI-and-RWPI
8. IAR Embedded Workbench for Arm C-SPY Debugging Guide
-
mcu
+關注
關注
147文章
19180瀏覽量
404995 -
ARM
+關注
關注
135文章
9602瀏覽量
393965 -
IAR
+關注
關注
5文章
418瀏覽量
38693
原文標題:在IAR Embedded Workbench for Arm中實現ROPI
文章出處:【微信號:IAR愛亞系統(tǒng),微信公眾號:IAR愛亞系統(tǒng)】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
在IAR Embedded Workbench中進行ARM+RISC-V多核調試
如何在IAR Embedded Workbench中配置生成對應代碼區(qū)域的CRC校驗碼
在IAR Embedded Workbench中計算多個地址區(qū)間的Checksum
請問如何在 IAR Embedded Workbench for ARM 開發(fā)環(huán)境中啟用可配置數據閃存并設置大???
如何在 IAR Embedded Workbench for ARM 開發(fā)環(huán)境中啟用可配置數據閃存并設置大小?
在 IAR Embedded Workbench中進行ARM+RISC-V多核調試
IAR Systems發(fā)布 IAR Embedded Wor
AVR IAR Embedded Workbench IDE用戶手冊
IAR_embedded_Workbench用戶指南介紹
IAR Embedded Workbench?集成開發(fā)環(huán)境已全面支持航順芯片HK32MCU系列
YRDKRX62N 快速入門指南(IAR Embedded Workbench)
YRDKRX62N 快速入門指南(IAR Embedded Workbench)
如何在IAR Embedded Workbench for Arm中實現ROPI
評論