[ROMAPI] XPI REMAP 技术解析与应用指南
技术背景与核心概念
1. XIP 内存映射机制
在嵌入式系统中,XIP(eXecute In Place)技术允许MCU直接从FLASH存储器执行代码。先楫半导体MCU通过XPI控制器实现以下物理地址映射:
XPI0 控制器:映射至系统内存 0x80000000 起始地址
XPI1 控制器(部分型号):映射至 0x90000000 起始地址
XIP内存映射架构
2. 工程构建与链接配置
当采用XIP模式构建工程时,链接脚本需明确配置FLASH的XIP映射地址。典型配置示例如下:
MEMORY {
FLASH (rx) : ORIGIN = 0x80000000, LENGTH = 16M
RAM (rwx) : ORIGIN = 0x0C000000, LENGTH = 8M
}
多固件管理痛点分析
传统分区方案的局限性
在固件更新场景中,传统分区方案存在以下问题:
关键问题表现:
- 各应用固件需独立配置链接脚本
- 固件存储位置与执行地址强耦合
- 固件二进制无法跨分区部署
- OTA更新容错率低
XPI REMAP 解决方案
技术实现原理
通过XPI控制器的地址重映射功能,实现物理存储地址与系统内存地址的解耦:
地址重映射架构
核心优势
XPI REMAP API说明
ATTR_RAMFUNC
static inline bool rom_xpi_nor_remap_config(XPI_Type *base, uint32_t start, uint32_t len, uint32_t offset);
说明: 配置XPI remap映射接口
- base, XPI控制器基地址
- start, 映射起始地址
- len, 映射长度
- offset, 相对start起始地址的偏移长度
返回:true:配置参数有效,映射成功并生效; false:配置参数无效,映射失败;
注意: 起始地址必须4K对齐。
ATTR_RAMFUNC
static inline void rom_xpi_nor_remap_disable(XPI_Type *base);
说明: 关闭XPI remap映射
- base, XPI控制器基地址
ATTR_RAMFUNC
static inline bool rom_xpi_nor_is_remap_enabled(XPI_Type *base)
说明: 判断XPI remap映射是否已使能
- base, XPI控制器基地址
返回:true:已使能; flase:未使能;
XPI REMAP实例
在先楫半导体hpm_apps 的OTA参考设计中,通过XPI Remap技术实现了固件二进制完全统一的架构。
具有以下优势:
以下为remap实例:
void hpm_appindex_jump(uint8_t appindex)
{
#ifdef FLASH_USER_APP2_ADDR
//关闭remap映射
rom_xpi_nor_remap_disable(HPM_XPI0);
if (appindex == HPM_APP2)
{
//当需要跳转到APP2区域固件时,重新remap映射配置
//起始地址:APP1地址;长度:APP2区域长度; OFFSET:APP2相对于起始APP1的偏移长度
//这样就将APP2固件存储的区域重新映射到APP1区域地址。后续跳转APP1,实际运行的就是APP2区域的固件。
rom_xpi_nor_remap_config(HPM_XPI0, FLASH_USER_APP1_ADDR + FLASH_ADDR_BASE, FLASH_USER_APP2_SIZE, FLASH_USER_APP2_ADDR - FLASH_USER_APP1_ADDR);
//判断remap是否使能成功
if(!rom_xpi_nor_is_remap_enabled(HPM_XPI0))
{
printf("BAD, xpi remap failed!\r\n");
return;
}
}
#endif
disable_global_irq(CSR_MSTATUS_MIE_MASK);
disable_global_irq(CSR_MSTATUS_UIE_MASK);
l1c_dc_invalidate_all();
l1c_dc_disable();
l1c_ic_disable();
fencei();
//跳转时均是APP1的起始地址
__asm("la a0, %0" ::"i"(FLASH_USER_APP1_ADDR + sizeof(hpm_app_header_t) + FLASH_ADDR_BASE));
__asm("jr a0");
WFI();
while (1)
{
}
}