打印
[STM32N6]

STM32N6570-DK测评】5、XIP模板解析

[复制链接]
88|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 sujingliang 于 2025-5-5 15:34 编辑

XIP (eXecute In Place) 是一种允许微控制器直接从外部存储器(如NOR Flash、QSPI Flash等)执行代码的技术,无需将代码先复制到内部RAM中运行。

XIP基本原理
内存映射执行:外部Flash被映射到处理器的地址空间
直接执行:CPU像访问内部存储器一样直接读取并执行外部Flash中的代码
无需复制:省去了将代码从Flash加载到RAM的步骤

XIP实现条件硬件要求
支持内存映射的Flash:通常需要NOR Flash或XIP优化的Flash
高速接口:QSPI(Quad SPI)、OSPI(Octal SPI)等高速接口
缓存支持:通常需要Cache来弥补外部存储器的延迟


STM32N5670-DK中的XIP
对于STM32N5670-DK来说,其内置4.2M SRAM,没有提供内部flash。
但是提供了外置的flash和PSRAM。
1‑Gbit Octo‑SPI flash memory
• 256-Mbit Hexadeca‑SPI PSRAM

STM32N5670-DK的硬件配置决定了其系统设计需要采用XIP方式。


两种启动方式
在构建STM32N5670-DK系统设计中,FSBL (First Stage Boot Loader) 和 FSBL+APPLI 是两种常见的启动方式,它们有不同的设计目的和应用场景。
FSBL:纯硬件初始化,不包含应用逻辑
FSBL+APPLI:在硬件初始化基础上增加了应用相关功能


FSBL+APPLI 的具体优势
模块化设计
将硬件初始化与业务逻辑解耦
方便不同产品线复用
安全隔离
FSBL保持最小化,降低被攻击面
应用相关验证放在APPLI

更新灵活性
可以不修改FSBL只更新APPLI
支持A/B备份等高级更新策略

内存管理优化
FSBL只初始化必要硬件
APPLI完成更复杂的内存配置

在资源受限系统中可只使用纯FSBL,需要安全认证的系统,需要考虑采用FSBL+APPLI。

XIP例程模板
STM32N5670-DK软件包中提供了Template_FSBL_XIP程序模板,模板提供了基于STM32Cube HAL API的参考FSBL XIP模板,可用于构建以在外部Flash中执行固件应用程序(子项目Appli)。

执行bootROM后,FSBL项目在内部RAM中执行,确保MPU、缓存和时钟设置正确,然后将外部Flash配置为执行模式。完成后,程序计数器设置为应用程序入口点,应用程序依次执行。

图示Template_FSBL_XIP几个子工程的关系:

Template_FSBL_XIP有3个子工程:FSBL、Appli、ExtMemLoader 。
其中:
FSBL、Appli是MCU应用相关程序。
ExtMemLoader是加载器程序,,它对外部Flash做了配置,用于配合烧录程序将FSBL、Appli烧录到MCU中。
通常不使用ExtMemLoader生产的加载器程序,直接使用STM32CubeProgrammer中提供的MX66UW1G45G_STM32N6570-DK.stldr

1、FSBL工程
{
  /* Enable and set up the MPU------------------------------------------------*/
  MPU_Config();

  /* Enable I-Cache-----------------------------------------------------------*/
  SCB_EnableICache();

  /* Enable D-Cache-----------------------------------------------------------*/
  SCB_EnableDCache();

  /* MCU Configuration--------------------------------------------------------*/

  /* STM32N6xx HAL library initialization:
       - Systick timer is configured by default as source of time base, but user
             can eventually implement his proper time base source (a general purpose
             timer for example or other time source), keeping in mind that Time base
             duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
             handled in milliseconds basis.
       - Set NVIC Group Priority to 4
       - Low Level Initialization
     */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

#ifndef NO_OTP_FUSE
  /* Set OTP fuses for XSPI IO pins speed optimization */
  if(OTP_Config() != 0){
    Error_Handler();
  }
#endif /* NO_OTP_FUSE */

  /* Add your application code here */
  MX_XSPI2_Init();
  
  /* Initialise the serial memory */
  MX_EXTMEM_Init();

  BOOT_Application();
  /* We should never get here as execution is now from user application */
  while(1)
  {
    __NOP();
  }
}
FSBL初始化了外部flash和RAM,然后调用BOOT_Application();
BOOTStatus_TypeDef BOOT_Application(void)
{
  BOOTStatus_TypeDef retr;

  /* mount the memory */
  retr = MapMemory();
  if (BOOT_OK == retr)
  {
    /* jump on the application */
    retr = JumpToApplication();
  }
  return retr;
}


BOOT_Application调用JumpToApplication();
BOOTStatus_TypeDef JumpToApplication(void)
{
  uint32_t primask_bit;
  typedef  void (*pFunction)(void);
  static pFunction JumpToApp;
  uint32_t Application_vector;

  if (EXTMEM_OK != EXTMEM_GetMapAddress(EXTMEM_MEMORY_BOOTXIP, &Application_vector))
  {
      return BOOT_ERROR_INCOMPATIBLEMEMORY;
  }

  /* Suspend SysTick */
  HAL_SuspendTick();

#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
  /* if I-Cache is enabled, disable I-Cache-----------------------------------*/
  if (SCB->CCR & SCB_CCR_IC_Msk)
  {
    SCB_DisableICache();
  }
#endif /* defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) */

#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
  /* if D-Cache is enabled, disable D-Cache-----------------------------------*/
  if (SCB->CCR & SCB_CCR_DC_Msk)
  {
    SCB_DisableDCache();
  }
#endif /* defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) */

  /* Initialize user application's Stack Pointer & Jump to user application  */
  primask_bit = __get_PRIMASK();
  __disable_irq();

  /* Apply offsets for image location and vector table offset */
  Application_vector += EXTMEM_XIP_IMAGE_OFFSET + EXTMEM_HEADER_OFFSET;

  SCB->VTOR = (uint32_t)Application_vector;
  JumpToApp = (pFunction) (*(__IO uint32_t *)(Application_vector + 4u));

#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
     (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) || \
     (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1))    )
  /* on ARM v8m, set MSPLIM before setting MSP to avoid unwanted stack overflow faults */
  __set_MSPLIM(0x00000000);
#endif  /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */

  __set_MSP(*(__IO uint32_t*) Application_vector);

  /* Re-enable the interrupts */
  __set_PRIMASK(primask_bit);

  JumpToApp();
  return BOOT_OK;
}


JumpToApplication()调用JumpToApp();
JumpToApp();是指针函数,指针地址Application_vector += EXTMEM_XIP_IMAGE_OFFSET + EXTMEM_HEADER_OFFSET;
根据配置,这个地址为0x70100000,这个是Appli的首地址。
所以可以看出FSBL执行完成后,会转到Appli执行。

2、Appli工程
int main(void)
{

  /* Enable and set up the MPU------------------------------------------------*/
  MPU_Config();

  /* Enable I-Cache---------------------------------------------------------*/
  SCB_EnableICache();

  /* Enable D-Cache---------------------------------------------------------*/
  SCB_EnableDCache();

  /* MCU Configuration--------------------------------------------------------*/

  /* STM32N6xx HAL library initialization:
       - Systick timer is configured by default as source of time base, but user
             can eventually implement his proper time base source (a general purpose
             timer for example or other time source), keeping in mind that Time base
             duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
             handled in milliseconds basis.
       - Set NVIC Group Priority to 4
       - Low Level Initialization
     */
  HAL_Init();

  /* Add your application code here */

  /* Initialize LED1 */
  BSP_LED_Init(LED_GREEN);

  /* Infinite loop */
  while (1)
  {
    /* Toggle LED1 every 250ms */
    BSP_LED_Toggle(LED_GREEN);
    HAL_Delay(250);
  }
}

在Appli工程中,可以进行正常的应用逻辑编写。

3、BIN程序加签
为了安全起见,烧录到外部flash的程序在烧录前需要加签名头。
可以在命令行运行以下命令:
STM32_SigningTool_CLI.exe -bin Appli/Objects/Appli.bin -nk -of 0x80000000 -t fsbl -o Appli-trusted.bin -hv 2.3 -dump Appli-trusted.bin

STM32_SigningTool_CLI.exe -bin FSBL/Objects/FSBL.bin -nk -of 0x80000000 -t fsbl -o FSBL-trusted.bin -hv 2.3 -dump FSBL-trusted.bin


4、程序烧录
如果不用STM32CubeProgrammer,可以用下面命令行:
set DKEL="C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgrammer\bin\ExternalLoader\MX66UW1G45G_STM32N6570-DK.stldr"

STM32_Programmer_CLI -c port=SWD mode=HOTPLUG -el %DKEL% -hardRst -w FSBL-trusted.bin  0x70000000

STM32_Programmer_CLI -c port=SWD mode=HOTPLUG -el %DKEL% -hardRst -w Appli-trusted.bin  0x70100000
通常FSBL可以烧录一次,以后每次修改只烧录Appli。




使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

60

主题

118

帖子

0

粉丝