[STM32F4] 外设的初始化无法正常工作

[复制链接]
476|14
HomeKit 发表于 2025-9-16 22:50 | 显示全部楼层 |阅读模式
, , IO, , ,
本帖最后由 HomeKit 于 2025-10-2 19:12 编辑

我使用以下代码进行内存位置跳转:
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
Jump_To_Application = (pFunction) JumpAddress;
__set_MSP(*(__IO uint32_t*) (APPLICATION_ADDRESS));
Jump_To_Application();
我成功实现了仅使用一个GPIO时的跳转功能,但在引导程序中添加外设后,跳转就不再有效。

参考了某个UART的参考实现(stm32f4xx_hal_uart.c):
HAL_StatusTypeDef HAL_UART_DeInit(UART_HandleTypeDef *huart)
{
  /* Check the UART handle allocation */
  if (huart == NULL)
  {
    return HAL_ERROR;
  }

  /* Check the parameters */
  assert_param(IS_UART_INSTANCE(huart->Instance));

  huart->gState = HAL_UART_STATE_BUSY;

  /* Disable the Peripheral */
  __HAL_UART_DISABLE(huart);

#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
  if (huart->MspDeInitCallback == NULL)
  {
    huart->MspDeInitCallback = HAL_UART_MspDeInit;
  }
  /* DeInit the low level hardware */
  huart->MspDeInitCallback(huart);
#else
  /* DeInit the low level hardware */
  HAL_UART_MspDeInit(huart);
#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */

  huart->ErrorCode = HAL_UART_ERROR_NONE;
  huart->gState = HAL_UART_STATE_RESET;
  huart->RxState = HAL_UART_STATE_RESET;
  huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;

  /* Process Unlock */
  __HAL_UNLOCK(huart);

  return HAL_OK;
}

我查找HAL_UART_MspDeInit的参考时,出现了以下内容(stm32f4xx_hal_uart.c):
__weak void HAL_UART_MspDeInit(UART_HandleTypeDef *huart)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(huart);
  /* NOTE: This function should not be modified, when the callback is needed,
           the HAL_UART_MspDeInit could be implemented in the user file
   */

}


还有另一个已实现的参考文件(stm32f4xx_hal_msp.c):
void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
{
  if(huart->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspDeInit 0 */

  /* USER CODE END USART1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();

    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);

  /* USER CODE BEGIN USART1_MspDeInit 1 */

  /* USER CODE END USART1_MspDeInit 1 */
  }


}

公羊子丹 发表于 2025-9-17 08:15 | 显示全部楼层
楼主这种情况挺常见的,加了外设以后跳转失败,大概率是外设资源没有完全释放,进入应用后冲突了。可以在跳转前把用到的时钟、IO、UART 全部 DeInit 一遍试试。
周半梅 发表于 2025-9-17 08:16 | 显示全部楼层
你现在能用 GPIO 跳转说明核心流程没问题,就是外设初始化残留状态影响了用户 APP。特别注意 NVIC 中断优先级和挂起标志,有可能是中断没清掉。
帛灿灿 发表于 2025-9-17 08:17 | 显示全部楼层
HAL 库里 HAL_UART_DeInit() 调用了 HAL_UART_MspDeInit(),你得确认是不是把 GPIO 和时钟都关闭了。否则用户程序二次初始化会报错或者直接死机。
童雨竹 发表于 2025-9-17 08:19 | 显示全部楼层
引导程序里最好在 Jump_To_Application() 前调用 HAL_DeInit() 或者手动关闭 RCC、SysTick,这样能保证进入 APP 时外设是“干净”的。
万图 发表于 2025-9-17 08:20 | 显示全部楼层
另外还要检查 **向量表偏移(VTOR)**有没有配置好,F4 系列需要设置 SCB->VTOR = APPLICATION_ADDRESS;,否则外设中断表会指向 BootLoader,现象就是 APP 外设不工作。
Wordsworth 发表于 2025-9-17 08:21 | 显示全部楼层
有些人遇到这个问题会选择 在 Bootloader 里只开必要的 IO,其他外设等跳转后再由应用初始化,这样最保险。
Bblythe 发表于 2025-9-17 08:22 | 显示全部楼层
你用的是 HAL 库的话,其实可以在 SystemDeInit() 里统一关掉 RCC、GPIO、UART,然后再跳转,不用逐个外设清理。
Pulitzer 发表于 2025-9-17 08:23 | 显示全部楼层
还可以调试下看看:跳转后卡住的位置是不是在 SystemInit() 或 HAL_UART_Init() 里,这样能确认是不是外设冲突引起的。
Uriah 发表于 2025-9-17 08:24 | 显示全部楼层
如果要支持 UART 通信的 BootLoader,可以考虑 开和关分开管理:BootLoader用完 UART 后一定要 DeInit,然后再 NVIC_DisableIRQ(USARTx_IRQn),这样才不会残留状态。
Clyde011 发表于 2025-9-17 08:25 | 显示全部楼层
总结一句:BootLoader 跳转 APP 的关键就是 关中断、关外设、改 MSP、改 VTOR,保证一个“干净”的环境,APP 才能顺利运行。
tpgf 发表于 2025-9-17 11:30 | 显示全部楼层
检查USB/串口线是否牢固插入,避免因松动、弯曲或接触不良导致信号中断
classroom 发表于 2025-9-17 15:56 | 显示全部楼层
在引导程序中添加外设后跳转失效的问题,通常是由于外设状态未完全重置导致应用程序启动时硬件状态与预期不符。
cr315 发表于 2025-9-17 16:57 | 显示全部楼层
彻底反初始化所有外设。
duo点 发表于 2025-9-17 17:58 | 显示全部楼层
在跳转前,必须关闭所有引导程序初始化的外设。
elephant00 发表于 2025-9-17 15:58 | 显示全部楼层
在跳转前调用反初始化函数。
flycamelaaa 发表于 2025-9-17 19:59 | 显示全部楼层
禁用所有外设时钟。
jcky001 发表于 2025-9-17 20:59 | 显示全部楼层
禁用全局中断(__disable_irq())并清除NVIC挂起位。
onlycook 发表于 2025-9-17 21:00 | 显示全部楼层
如果使用了MPU或Cache,需在跳转前禁用并清理。
powerantone 发表于 2025-9-17 22:01 | 显示全部楼层
在跳转前设置断点,检查外设时钟、GPIO和中断状态。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

55

主题

55

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部