没志青年
发布于 2025-11-29 / 26 阅读
0

Bootloader[01] 基础概念

Bootloader:启动程序

OTA:网络升级,是 Bootloader 的一个重要功能。

Flash 分区

  • B 区:存放 Bootloader 程序

  • A 区:存放主程序

B 区要在A区前面,因为B区的大小是固定的,而A区的程序是变化的,如果A区在前,可能会覆盖掉B区的程序,造成Bootloader失效。

  • 在线更新:板子上不存储要更新的APP,通过线连接的方式与上位机通信,实时写入,比如串口、CAN总线。

  • 离线更新(脱机更新):程序事先写入板子上的外部FLASH、SD卡、EMMC等,单片机从这里面读取程序并更新。

这是两个工程

例程:

通讯方式

文件传输协议

硬件

串口

不使用协议

有外部Flash

有外部

串口

Ymodem

CAN

自定义传输协议

Ymodem 协议

跳转到指定地址执行

#define AppAddr  0x08100000    /* APP地址 */


static void JumpToApp(void)
{
	uint32_t i=0;
	void (*AppJump)(void);         /* 声明一个函数指针 */
    
    /* 关闭全局中断 */
	DISABLE_INT(); 
    
    /* 设置所有时钟到默认状态,使用HSI时钟 */
	HAL_RCC_DeInit();
    
	/* 关闭滴答定时器,复位到默认值 */
	SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;

	/* 关闭所有中断,清除所有中断挂起标志 */
	for (i = 0; i < 8; i++)
	{
		NVIC->ICER[i]=0xFFFFFFFF;
		NVIC->ICPR[i]=0xFFFFFFFF;
	}	

	/* 使能全局中断 */
	ENABLE_INT();

	/* 跳转到应用程序,首地址是MSP,地址+4是复位中断服务程序地址 */
	AppJump = (void (*)(void)) (*((uint32_t *) (AppAddr + 4)));

	/* 设置主堆栈指针 */
	__set_MSP(*(uint32_t *)AppAddr);
	
	/* 在RTOS工程,这条语句很重要,设置为特权级模式,使用MSP指针 */
	__set_CONTROL(0);

	/* 跳转到系统BootLoader */
	AppJump(); 

	/* 跳转成功的话,不会执行到这里,用户可以在这里添加代码 */
	while (1)
	{

	}
}

另一种:

static void Boot_vJumpToApp(uint32_t u32_appAddress) 
{
    uint32_t u32_jumpAddress;
    pFunction JumpToApp;
    
    if (((*(__IO uint32_t*)u32_appAddress) & 0x2FFE0000 ) == 0x20000000) 
    {  
        u32_jumpAddress = *(__IO uint32_t*) (u32_appAddress + 4);  
        JumpToApp = (pFunction)u32_jumpAddress;  
        __set_MSP(*(__IO uint32_t*)u32_appAddress);  
        JumpToApp();
    } 
}