BootLoader IAP升级

BootLoader IAP升级

一、说明

在这里插入图片描述
如图,可看出单片机的ROM开始地址为0x8000000,大小为0x80000(512K byte),RAM的开始地址为0x20000000,大小为0x24000(144K byte)
单片机上电从0x8000000+4进入中断向量表。
**可参考正点原子例程中串口IAP实验。

二、实现步骤

1、芯片内部FLASH验证
对接原厂API函数,验证内部FLASH烧写读取是否正常,测试FLASH为大端还是小端
例:
1)原厂内部API函数

FLASH_STS FLASH_ProgramWord(uint32_t Address, uint32_t Data)

可看出Address:是地址写入地址, Data是要写入的数据,为32位的。

2)原厂对接函数

宏定义

#define INTERNAL_FLASH_START_ADDR ((uint32_t)0x08000000)  //起始地址
#define INTERNAL_FLASH_END_ADDR   ((uint32_t)0x0807FFFF)  //结束地址
#define INTERNAL_FLASH_PAGE_SIZE  2048

FLASH直接写数据

void Drv_InternalFlashWriteBufferNoCheck(uint32_t Addr, uint8_t *Buffer, uint32_t Length)
{
	uint16_t i = 0, j = 0; 
	uint32_t Data = 0;
	for(i=0;i<Length;i+=4)
	{
		j = i;
		Data |= Buffer[j++];
		Data |= Buffer[j++]<<8;
		Data |= Buffer[j++]<<16;
		Data |= Buffer[j++]<<24;
		
		FLASH_ProgramWord(Addr,Data);
		
		Data = 0;
		Addr += 4;
	}
}

FLASH读数据

void Drv_InternalFlashReadBuffer(uint32_t Addr, uint8_t *Buffer, uint16_t Length)
{
	uint16_t i = 0;
	
	for(i=0;i<Length;i++)
	{
		Buffer[i] = (*(volatile uint32_t*)(Addr+i));
	}	
}

FLASH带验证检查擦写函数

static uint8_t InternalFlashBuffer[INTERNAL_FLASH_PAGE_SIZE];
void Drv_InternalFlashWriteBuffer(uint32_t Addr, uint8_t *Buffer, uint32_t Length)
{
	uint16_t Count = 0;
	u32 OffAddr;   //去掉0X08000000后的地址
	u32 PagePos;   //页地址
	u32 PageOff;   //页内偏移地址
	u32 PageMain;  //页内剩余地址
	if(Addr < FLASH_BASE || Addr > INTERNAL_FLASH_END_ADDR)
	{
		return;  //非法地址
	}			
	FLASH_Unlock();  
	OffAddr  = Addr - INTERNAL_FLASH_START_ADDR;   //去掉0X08000000后的地址,实际偏移地址.
	PagePos  = OffAddr / INTERNAL_FLASH_PAGE_SIZE; //得到第几页开始写
	PageOff  = OffAddr % INTERNAL_FLASH_PAGE_SIZE; //得到不足一页字节长度
	PageMain = INTERNAL_FLASH_PAGE_SIZE - PageOff;  //得到剩余空间字节长度
	if(Length <= PageMain)
	{
		PageMain = Length;
	}
	while(1)
	{
		Drv_InternalFlashReadBuffer(PagePos*INTERNAL_FLASH_PAGE_SIZE+INTERNAL_FLASH_START_ADDR,  \
									InternalFlashBuffer, INTERNAL_FLASH_PAGE_SIZE);   //读出整个页的内容
		for(Count=0; Count<PageMain; Count++)//校验数据
		{
			if(InternalFlashBuffer[PageOff+Count] != 0XFF)
			{
				break; //需要擦除 
			}
		}
		if(Count < PageMain)  //需要擦除 
		{
			FLASH_EraseOnePage(PagePos*INTERNAL_FLASH_PAGE_SIZE+INTERNAL_FLASH_START_ADDR); //擦除 
			for(Count=0; Count<PageMain; Count++)  //复制
			{
				InternalFlashBuffer[PageOff+Count] = Buffer[Count];	
			}
			Drv_InternalFlashWriteBufferNoCheck(PagePos*INTERNAL_FLASH_PAGE_SIZE+INTERNAL_FLASH_START_ADDR, \
											    InternalFlashBuffer,INTERNAL_FLASH_PAGE_SIZE);
		}
		else
		{
			Drv_InternalFlashWriteBufferNoCheck(Addr, Buffer, PageMain); //写已经擦除了的,直接写入扇区剩余区间
		}
		if(Length == PageMain)
		{
			break;//写入结束了
		}	
		else
		{
			PagePos++;   //扇区地址增1
			PageOff = 0; //偏移位置为0 	
			Buffer += PageMain; //指针偏移
			Addr   += PageMain; //写地址偏移
			Length -= PageMain; //字节数递减
			if(Length > INTERNAL_FLASH_PAGE_SIZE)
			{
				PageMain = INTERNAL_FLASH_PAGE_SIZE;
			}
			else
			{
				PageMain = Length;
			}
		}	
	}	
	FLASH_Lock();
}

2、分配单片机资源及配置参数

1)IAP
在这里插入图片描述

在这里插入图片描述
如图所示,分配0x10000(64K byte)内存空间给IAP烧写程序,烧录选择全部擦除模式。

2)APP

在这里插入图片描述
在这里插入图片描述
如图所示,分配0x70000(448K byte)内存空间给APP用,烧录选择部分擦除模式。

3、IAP升级相关函数

#define FLASH_APP_ADDR  (FLASH_BASE | 0x10000)   //APP程序起始地址
typedef  void (*iapfun)(void); //定义一个函数类型的参数. 

iapfun JumpApp;  
//设置栈顶地址
//addr:栈顶地址
__asm void MSR_MSP(uint32_t addr) 
{
    MSR MSP, r0 			//set Main Stack value
    BX r14
}
//跳转到应用程序段
//appxaddr:用户代码起始地址.
void Drv_IapLoadApp(uint32_t appxaddr)
{
	if(((*(volatile uint32_t*)appxaddr)&0x2FFE0000)==0x20000000)	//检查栈顶地址是否合法.
	{ 
		JumpApp=(iapfun)*(volatile uint32_t*)(appxaddr+4);		//用户代码区第二个字为程序开始地址(复位地址)		
		MSR_MSP(*(volatile uint32_t*)appxaddr);					//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
		JumpApp();									//跳转到APP.
	}
}	

4、程序实现
将APP的Bin档文件,在IAP中读取完烧录进我们分配好的APP地址中,接着调用跳转函数Drv_IapLoadApp(0x8010000),实现程序跳转。
在APP工程中,需要在程序执行前更改执行地址,

int main(void)
{		
	SCB->VTOR = FLASH_BASE | 0X10004;  //地址偏移0x8010000+4
	while(1)
	{
		;
	}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值