100 lines
3.3 KiB
C
100 lines
3.3 KiB
C
/******************************************************************************
|
||
* @file app_boot.c
|
||
* @brief APP 启动流程(Bootloader 交接、时钟、IWDG、OTA 确认)
|
||
* @author cyWu <1917507415@qq.com>
|
||
* @date 2026.08.18
|
||
* @version V1.0.0
|
||
* @history
|
||
* - V1.0.0, 2026.08.18, cyWu, 从 main.c 拆出启动逻辑
|
||
******************************************************************************/
|
||
|
||
#include "app_boot.h"
|
||
#include "application.h"
|
||
#include "iwdg.h"
|
||
#include "ota_ab.h"
|
||
#include "main.h"
|
||
|
||
/**
|
||
* @brief 从 Bootloader 跳转过来后,重新打开全局中断
|
||
*
|
||
* Bootloader 跳转 APP 前会 __disable_irq(),且函数跳转不会复位芯片,
|
||
* 因此 PRIMASK 仍为 1(中断关)。APP 第一件事须 __enable_irq(),
|
||
* 否则 SysTick / TIM6 / UART 等中断进不来,HAL_Delay、协议超时都会失效。
|
||
*/
|
||
static void app_boot_early_handover(void)
|
||
{
|
||
__enable_irq();
|
||
}
|
||
|
||
/**
|
||
* @brief 配置 APP 系统时钟(HSI → PLL → SYSCLK)
|
||
*
|
||
* 与官网例程的差异:OscillatorType 故意不含 LSI。
|
||
* Bootloader 跳转前已启动 IWDG,IWDG 运行期间 LSI 被硬件锁定关不掉;
|
||
* 若在此配置 LSI OFF,HAL_RCC_OscConfig 会卡死等待 LSIRDY 变 0。
|
||
* LSI 由 IWDG 维持即可,APP 只配置 HSI/PLL 主时钟树。
|
||
*/
|
||
static void app_system_clock_config(void)
|
||
{
|
||
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
||
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
||
|
||
/* 主时钟:HSI 24MHz → PLL,不含 LSI(见上方说明) */
|
||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSE;
|
||
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
|
||
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
|
||
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_24MHz;
|
||
RCC_OscInitStruct.HSEState = RCC_HSE_OFF;
|
||
RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
|
||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
|
||
|
||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
|
||
{
|
||
Error_Handler(__FILE__, __LINE__);
|
||
}
|
||
|
||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1;
|
||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
|
||
|
||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
|
||
{
|
||
Error_Handler(__FILE__, __LINE__);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 双备份 OTA:新固件启动确认后,上报一次升级完成(0x34)
|
||
*
|
||
* 须在 app_Init() 之后调用(依赖 uartInit / jbInit)。
|
||
* ota_boot_check_confirm() 已将 Flash 置为 IDLE,0x34 仅为尽力通知云端;
|
||
* 发一次即可,丢帧由 jbSendOtaResult 内 SEND_MAX_NUM 重传兜底。
|
||
*/
|
||
static void app_boot_ota_report(void)
|
||
{
|
||
uint8_t ver[3];
|
||
|
||
if (!ota_boot_check_confirm())
|
||
{
|
||
return;
|
||
}
|
||
|
||
ver[0] = JB_MCU_SW_VERSION_MAJOR;
|
||
ver[1] = JB_MCU_SW_VERSION_MINOR;
|
||
ver[2] = JB_MCU_SW_VERSION_PATCH;
|
||
(void)jbSendOtaResult(JB_OK, ver);
|
||
appPrintf(LOG_NOTIC, "OTA upgrade complete reported\r\n");
|
||
}
|
||
|
||
void app_startup(void)
|
||
{
|
||
app_boot_early_handover();
|
||
HAL_Init();
|
||
iwdg_init();
|
||
app_system_clock_config();
|
||
app_Init();
|
||
app_boot_ota_report();
|
||
}
|