【问题标题】:STM32H7 bank swap break at address 0x81006fe地址 0x81006fe 处的 STM32H7 银行交换中断
【发布时间】:2026-01-19 08:20:02
【问题描述】:

我正在尝试使用 ST32 H743ZI2 进行银行交换。我浪费了很多时间来修复它,但我没有得到它。也许是因为我是 STM32 控制器的新手。

我从 STM32CubeH7 固件示例中复制了银行交换代码,并对 CubeMX 中的 gpio 配置进行了一些修改。我这样做是因为我想将代码包含在没有 stm32h7xx_nucleo 标头的现有项目中。

遵循 Bank1 的代码:

HAL_FLASH_Unlock();
HAL_FLASH_OB_Unlock();

while (1)
{
    /* Wait for BUTTON_USER is released */
    if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == 1)
    {
  while (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == 1);

  /* Get the Dual boot configuration status */
  HAL_FLASHEx_OBGetConfig(&OBInit);

  /* Get FLASH_WRP_SECTORS write protection status */
  OBInit.Banks     = FLASH_BANK_1;
  HAL_FLASHEx_OBGetConfig(&OBInit);

  /* Check Swap FLASH banks  status */
  if ((OBInit.USERConfig & OB_SWAP_BANK_ENABLE) == OB_SWAP_BANK_DISABLE)
  {
    /*Swap to bank2 */
    /*Set OB SWAP_BANK_OPT to swap Bank2*/
    OBInit.OptionType = OPTIONBYTE_USER;
    OBInit.USERType   = OB_USER_SWAP_BANK;
    OBInit.USERConfig = OB_SWAP_BANK_ENABLE;
    HAL_FLASHEx_OBProgram(&OBInit);

    /* Launch Option bytes loading */
    HAL_FLASH_OB_Launch();

    /*
      as the  CPU is executing from the FLASH Bank1, and the I-Cache is enabled :
      Instruction cache must be invalidated after bank switching to ensure that
      CPU will fetch correct instructions from the FLASH.
    */
    SCB_InvalidateICache();


    HAL_NVIC_SystemReset();
  }
  else
  {
    /* Swap to bank1 */
    /*Set OB SWAP_BANK_OPT to swap Bank1*/
    OBInit.OptionType = OPTIONBYTE_USER;
    OBInit.USERType = OB_USER_SWAP_BANK;
    OBInit.USERConfig = OB_SWAP_BANK_DISABLE;
    HAL_FLASHEx_OBProgram(&OBInit);

    /* Launch Option bytes loading */
    HAL_FLASH_OB_Launch();

    /*
      as the  CPU is executing from the FLASH Bank1, and the I-Cache is enabled :
      Instruction cache must be invalidated after bank switching to ensure that
      CPU will fetch correct instructions from the FLASH.
    */
    SCB_InvalidateICache();
  }
}
else
    {
#ifdef FLASH_BANK1
    /* Toggle LED1 */

HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
/*Turn Off LED2*/
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, 0);

#else
      /* Toggle LED2 */
    HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_1);
      /* Turn off LED1 */
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, 0);
#endif

  /* Insert 100 ms delay */
  HAL_Delay(100);
}

/* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

bank1 和bank2 的代码是相同的,除了链接描述文件。 我将 Flash 分成两个区域,每个区域有 1024kb。在下面你可以看到bank1的代码。

/* Specify the memory areas */
MEMORY
{

  RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
  RAM_D1 (xrw)   : ORIGIN = 0x24000000, LENGTH = 512K
  RAM_D2 (xrw)   : ORIGIN = 0x30000000, LENGTH = 288K
  RAM_D3 (xrw)   : ORIGIN = 0x38000000, LENGTH = 64K
  ITCMRAM (xrw)  : ORIGIN = 0x00000000, LENGTH = 64K
  FLASH (rx)     : ORIGIN = 0x8000000, LENGTH = 1024K
}

在 bank2 的链接脚本中,我将闪存起始地址更改为 0x08100000。

现在我有以下问题。如果我加载 bank1 的订单代码和 bank2 的代码,请按 Button1 并按 Reset 按钮,我会收到以下错误消息:

在没有可用调试信息或程序代码之外的地址“0x81006fe”处中断。

我已经用STM32 Utility成功检查了是否放置了一些代码。

如果我以相反的顺序加载代码,银行就会被交换一次。如果 Button1 在系统重置之前被按下,则独立..

我已经检查了一些论坛,但没有成功。

有谁知道问题出在哪里?

【问题讨论】:

  • 您确定在交换银行时应该更改链接描述文件吗?我的意思是银行交换的意思是根据OB中的交换位将它们重新定位到相同的地址。
  • 我完全不确定。在 STM32 的示例中,他们更改了链接描述文件。我认为这是为了在启动时将向量表重新定位到所选银行的起始地址。我理解的方式是只有虚拟地址发生变化。
  • 但是在这种情况下,您应该将所有源代码编译为与位置无关的代码,否则所有绝对跳转都会失败。对我来说这听起来有点奇怪。
  • @Damiano 我将自己定位于 STM32 手册,例如 STM32H7-Flash。在第 6 页有 STM32H743 的内存布局。我可以把虚拟地址和物理地址混在一起吗...
  • 阅读 AN4826 我很确定内存中的闪存组地址已被交换。因此,如果不将闪存大小减半,则不应更改链接描述文件。不知道您找到的示例的用途是什么。试试看。

标签: stm32 swap flash-memory bank


【解决方案1】:

代码中有两个问题。

  1. 链接器脚本分为两部分。链接描述文件必须以原始状态重建有关闪存。 bank2(0x081000000) 的代码现在需要用 stm32 等外部软件定位。

  2. 向量表被重定位到 system_stm32h7xx.c 中的错误地址

【讨论】: