• 正文
  • 相关推荐
申请入驻 产业图谱

STM32N6 XSPI1 复位卡死终极解决:时钟源必须与BootROM保持一致

6小时前
108
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

STM32N6 外部 Flash 启动时,XSPI1 配置 PLL 时钟源会导致应用复位(非上电复位)后卡死 —— 核心原因是 BootROM 与 FSBL 的 XSPI1 时钟源不一致,时钟切换时目标时钟源缺失。解决方案只有一个:XSPI1 时钟源必须与 BootROM 保持一致(per_ck/HSI),或复位前切回 per_ck。

资料获取:开发经验 | LAT1563 STM32N6 XSPI1时钟配置问题与建议

1. 问题背景:复位后程序卡死的典型场景

客户基于 STM32N6570-DK 开发 FSBL(第一阶段引导程序),遇到关键异常:

  1. 正常情况:XSPI1 时钟源设为默认 HCLK,上电后 LED 正常闪烁,按 B1 复位键也能正常工作;
  2. 异常情况:将 XSPI1 时钟源改为 PLL2→IC3(200MHz),第一次上电正常,但按 B1 复位后 LED 熄灭,程序卡死;
  3. 核心环境:外部 Flash 启动(地址 0x70000000),FSBL 经签名烧录,Boot0/Boot1 拨至对应位置。

2. 问题复现:3 步触发复位卡死

2.1 基础工程配置

  • 基于 STM32Cube_FW_N6_V1.1.0 的 GPIO_IOToggle 例程;
  • 用 STM32CubeMX 添加 XSPI1,模式设为 QSPI,Port1,片选默认;
  • 生成代码后,main 函数仅新增MX_XSPI1_Init()初始化。

2.2 关键修改(触发异常)

  • 在 CubeMX 的 Clock Configuration 中,将 XSPI1 时钟源改为 PLL2→IC3,保持 200MHz;
  • 编译、签名生成GPIO_IOToggle_FSBL-trusted.bin,烧录到外部 Flash 0x70000000;
  • 上电 LED 闪烁正常,按 B1 复位后卡死。

2.3 验证排除

  • 仅修改时钟源(无其他代码变更)即可复现问题;
  • 时钟源改为 HCLK/PER 时,复位无异常,确认问题与 PLL 时钟源强相关。

3. 根源拆解:STM32N6 的时钟切换规则与复位影响

3.1 核心诱因:时钟切换的 “双时钟存在” 要求

根据 STM32N6 参考手册(RM0486 Rev2.0),外设时钟切换(PERxSEL)有硬性规则:

  • 切换时原时钟源(in0_ck)和目标时钟源(in1_ck)必须同时存在,否则切换失败,无时钟输出;
  • 失败后需重新提供有效时钟,或切回原时钟源才能恢复。

3.2 复位后的时钟状态变化

  • BootROM 的 XSPI1 配置:外部 Flash 启动时,BootROM 会自动配置 XSPI1,时钟源为per_ck(HSI),用于加载 FSBL 到 RAM;
  • 复位的影响:系统复位(非上电复位)时,大部分 RCC 寄存器复位,PLL 时钟会丢失(需重新建立),但 XSPI1 的时钟选择寄存器(RCC_CCIPR6 的 XSPI1SEL)也会复位;
  • 切换失败逻辑:复位后 BootROM 尝试将 XSPI1 时钟从 “FSBL 设置的 PLL” 切回 “自身使用的 per_ck”,但此时 PLL 已复位(目标时钟源不存在),切换失败→XSPI1 无时钟→无法加载 FSBL→程序卡死。

3.3 关键验证

  • 手动添加时钟配置代码(仅设置 IC3 和 XSPI1SEL),问题仍复现,确认卡死与 XSPI1 时钟源切换直接相关;
  • 仅启用 IC3(不修改 XSPI1SEL)无异常,进一步验证 “时钟源切换” 是核心矛盾。

4. 解决方案:2 种落地方式,优先方案 1

核心原则:确保 BootROM 切换 XSPI1 时钟时,原时钟源和目标时钟源同时存在,优先保持与 BootROM 时钟源一致。

4.1 方案 1:XSPI1 时钟源设为 per_ck(推荐)

  • 配置方法:在 CubeMX 中,将 XSPI1 时钟源改为 PER(per_ck/HSI),无需修改其他参数;
  • 代码验证(手动配置):
    // 在USER CODE BEGIN 2中添加,替代CubeMX自动生成的时钟配置
    /********** XSPI1时钟源设为per_ck(与BootROM一致)**********/
    LL_RCC_SetXSPIClockSource(LL_RCC_XSPI1_CLKSOURCE_PER);
    
  • 优势:无需考虑复位时的时钟切换,兼容性最好,无性能损失(per_ck 足够满足多数 QSPI 需求)。

4.2 方案 2:复位前切回 per_ck(备用)

若业务需 PLL 高时钟(如高速 Flash 读写),可在复位前手动切回 per_ck:

  • 关键代码(添加到复位触发逻辑前):
    // 系统复位前执行,切回per_ck
    void Pre_Reset_Handle(void) {
      // 切换XSPI1时钟源为per_ck
      LL_RCC_SetXSPIClockSource(LL_RCC_XSPI1_CLKSOURCE_PER);
      __DSB();
      __ISB();
    }
    
  • 注意:需确保复位触发(如 B1 按键中断)中优先执行该函数,再触发系统复位。

5. 开发经验小结

  1. 外设时钟一致性原则:BootROM 与 FSBL / 应用共用的外设(如 XSPI1),时钟源必须保持一致,避免切换失败;
  2. BootROM 配置参考:外部 Flash 启动时,BootROM 的 XSPI1 时钟为 per_ck(HSI),其他共用外设的时钟源可参考 UM3234 文档;
  3. PLL 时钟慎用场景:外部 Flash 启动的 FSBL 中,避免将共用外设的时钟源设为 PLL(复位后 PLL 丢失,导致切换失败);
  4. 排查技巧:复位卡死且涉及外部 Flash/QSPI 时,优先检查时钟源是否与 BootROM 一致,无需复杂调试。

相关推荐