stm32 最小的boot 仅一个main文件 用作更新

通常boot的功能时用来引导app区程序运行的,对于小的项目这仅仅是一个跳转程序。当然还有一个重要的功能,就是用作程序区域的更新升级。所以下面的方案就只针对引导程序区和更新程序区而设计,仅用一个main 文件实现该功能。

上代码

#include "stm32f10x.h"
#define APP_CNT		(100)
/* 基地址和分区大小 */
#define ADDR_START	(0x08000000)
#define SIZE_FLASH	(256*1024)
#define SIZE_BOOT	(10*1024)
#define SIZE_APP	(100*1024)
#define SIZE_COPY	(100*1024)
#define SIZE_DATA	(44*1024)  
#define SIZE_REG	(2*1024) 

/* 分区起始地址 */
#define ADDR_BOOT	(ADDR_START)													//起始	地址
#define ADDR_APP	(ADDR_START+SIZE_BOOT)                      					//app 	地址
#define ADDR_COPY	(ADDR_START+SIZE_BOOT+SIZE_APP)             					//备份	地址
#define ADDR_DATA	(ADDR_START+SIZE_BOOT+SIZE_APP+SIZE_COPY)   					//数据	地址
#define ADDR_REG	(ADDR_START+SIZE_BOOT+SIZE_APP+SIZE_COPY+SIZE_DATA) 			//三元组地址
#define ADDR_END	(ADDR_START+SIZE_FLASH)                     					//结束	地址

/* BKP区	*/
#define	RTC_ENABLE			(0X5679)
#define	RTC_DISABLE			(0X3265)
//BKP_DR可以有20个且均为16位 这里使用2个
#define	ADDR_RTC			BKP_DR1
#define	ADDR_UPDATE			BKP_DR2

#define PWR_BackupAccessCmd_ENABLE() 	{RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE); PWR_BackupAccessCmd(ENABLE);}//开启备份区域写入权限	和 配置时钟
#define PWR_BackupAccessCmd_DISABLE() 	{PWR_BackupAccessCmd(DISABLE);}																		//关闭备份区域写入权限

/* 写BKP寄存器 */
void PWR_BackupAccessCmd_WRITE(uint16_t BKP_DR, uint16_t DataA){ 
	PWR_BackupAccessCmd_ENABLE();//开启备份区域写入权限	
	BKP_WriteBackupRegister(BKP_DR, DataA);
	PWR_BackupAccessCmd_DISABLE();//关闭备份区域写入权限
}
//=========================复制校验
void copy(void)
{
	u32 i = 0;	
	FLASH_Unlock();
    FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPTERR | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
	for(;i < APP_CNT;i++)				FLASH_ErasePage(ADDR_APP+(i*1024));									/* 擦除 */
	for (i = 0; i < SIZE_APP / 4; i++) 	FLASH_ProgramWord(ADDR_APP+4 * i, *((u32 *)(ADDR_COPY + 4 * i))); 	/* 写入 */
	FLASH_Lock();
}

int copy_check(void)
{
	u32 i = 0;	
	u32 * sour = (u32 *)ADDR_COPY;
	u32 * neww = (u32 *)ADDR_APP;
	for (i = 0; i < SIZE_APP / 4; i++,sour++,neww++)
		if(*sour != *neww)
			return -1;
	/* 清除标志位 */
	PWR_BackupAccessCmd_WRITE(ADDR_UPDATE,RTC_DISABLE);
	return 1;
}

//======================APP跳转
__asm void MSR_MSP(u32 addr) 
{
    MSR MSP, r0 			//set Main Stack value
    BX r14
}
typedef  void (*iapfun)(void);				//定义一个函数类型的参数.
void iap_load_app(u32 appxaddr)                                                                              
{     
	iapfun jump2app;	//
	if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)	//检查栈顶地址是否合法.                                  
	{                                                                                                        
		jump2app=(iapfun)*(vu32*)(appxaddr+4);		//用户代码区第二个字为程序开始地址(复位地址)		     
		MSR_MSP(*(vu32*)appxaddr);					//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
		jump2app();									//跳转到APP.                                             
	}
}	

//======================主函数
int main(void)
{
	int i = 0;
	if(BKP_ReadBackupRegister(ADDR_RTC) == RTC_ENABLE&&BKP_ReadBackupRegister(ADDR_UPDATE) == RTC_ENABLE){						//检测更新								
		do copy();									//执行更新
		while(copy_check() < 0&&i++ < 10);			//检测更新结果
	}
	iap_load_app(ADDR_APP);							//跳转app
	while(1){};										//死锁
}                                                                                                   

说明:使用BKP的1区(与本题无关可以去除)和2区,分别用作RTC标志和更新标志。在检查到更新标志时进行更新复制和校验,完成后清除标志和跳转程序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值