boot升级

1、擦除要升级的flash

#define FMC_PAGE_SIZE           ((uint16_t)0x800U)
#define FMC_WRITE_START_ADDR    ((uint32_t)0x08003000U)
#define FMC_WRITE_END_ADDR      ((uint32_t)0x0807FFFF)
void fmc_erase_pages(void)
{
    uint32_t EraseCounter;
    fmc_unlock();
    /* clear all pending flags */
    fmc_flag_clear(FMC_FLAG_BANK0_END);
    fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
    fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
     for(EraseCounter = 0; EraseCounter < PageNum; EraseCounter++)
     {
     	fmc_page_erase(FMC_WRITE_START_ADDR + (FMC_PAGE_SIZE * EraseCounter));
     	fmc_flag_clear(FMC_FLAG_BANK0_END);
     	fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
     	fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
     }
     fmc_lock();
   }

2、之后读取hex里面的数据
hex文件解析:
在这里插入图片描述

数据:n字节数据序列,由2个n十六进制数字表示;
校验码:(两个十六进制数字),可以用来验证记录没有错误的计算值;
注意校验和算法:累加和=校验码之前所有16进制,校验和=0x100-累加和。
第一行020000040804EE中,可以看做是0x02 0x00 0x00 0x04 0x08 0x04 0xEE,
02:代表本行有2个字节数据
0000:表示偏移地址或无用填0
04:扩展线性地址标识,表面后面2个字节数据是后面数据的基地址
注:由于每行标识数据地址的只有2Byte,所以最大只能到64K,为了可以保存高地址的数据,故有了扩展线性地址记录也叫作32位地址记录或HEX386记录.这些记录含数据的高16位,扩展线性地址记录总是有两个数据字节。
0804:是扩展地址 (0x0804 << 16) = 0x08040000后面的数据记录都以这个地址为基地址。
EE: 记录本行校验和 EE=0x100-(0x02+0x04+0x08+0x04)

第二行也按格式切分开为 10 0000 00 A8990020C1010408830B040839080408 DA
10:本行有0x10个Byte数据(即16个Byte数据)
0000:表示本行数据起始地址为0x08040000。下一行则是0x08040010依次类推
00:数据类型,表示后面字节为记录的数据
A8990020C1010408830B040839080408:16个byte的数据
DA: 校验和
00类型的行都大差不差,只是地址和数据不同而已,就不多赘述,以此类推即可。

uint8_t char2byte_back(char ch)
{
	if(ch=='0') return 0x00;
	if(ch=='1') return 0x01;
	if(ch=='2') return 0x02;
	if(ch=='3') return 0x03;
	if(ch=='4') return 0x04;
	if(ch=='5') return 0x05;
	if(ch=='6') return 0x06;
	if(ch=='7') return 0x07;
	if(ch=='8') return 0x08;
	if(ch=='9') return 0x09;
	if(ch=='A'||ch=='a') return 0x0A;
	if(ch=='B'||ch=='b') return 0x0B;
	if(ch=='C'||ch=='c') return 0x0C;
	if(ch=='D'||ch=='d') return 0x0D;
	if(ch=='E'||ch=='e') return 0x0E;
	if(ch=='F'||ch=='f') return 0x0F;
	return 0;
}
uint8_t char2byte_front(char ch)
{
	if(ch=='0') return 0x00;
	if(ch=='1') return 0x10;
	if(ch=='2') return 0x20;
	if(ch=='3') return 0x30;
	if(ch=='4') return 0x40;
	if(ch=='5') return 0x50;
	if(ch=='6') return 0x60;
	if(ch=='7') return 0x70;
	if(ch=='8') return 0x80;
	if(ch=='9') return 0x90;
	if(ch=='A'||ch=='a') return 0xA0;
	if(ch=='B'||ch=='b') return 0xB0;
	if(ch=='C'||ch=='c') return 0xC0;
	if(ch=='D'||ch=='d') return 0xD0;
	if(ch=='E'||ch=='e') return 0xE0;
	if(ch=='F'||ch=='f') return 0xF0;
	return 0;
}
void crc_compare(uint8_t* data,uint8_t len)
{
	uint16_t sum_data = 0;
	for(uint8_t i=0;i<len-1;i++)
	{
		sum_data += data[i];
	}
	uint8_t diff = 0x100-sum_data;
	if(diff==data[len-1])
	{
		printf("data right\r\n");
		//CRC校验没问题,之后应该将数据写进flash里面去才行
		//第一个字节:是数量(即有多少个字节要写入flash中)
		//第二和第三个字节:表示偏移地址
		//第四个字节:表示功能,0x00就要写入flash ,0x04就要提取基址 ,0x05 开始线性地
		uint8_t func_byte = data[3];
		static uint32_t base_addr=0x00000000;
		if(func_byte==0x04)
		{
			base_addr = (data[4]<<24)| (data[5]<<16);
		}
		if(func_byte==0x00)
		{
			uint32_t flash_addr = base_addr|((data[1]<<8)|data[2]);
			fmc_unlock();
			fmc_flag_clear(FMC_FLAG_BANK0_END | FMC_FLAG_BANK0_WPERR | FMC_FLAG_BANK0_PGERR);
			for(uint8_t j=0;j<data[0];j=j+4)
			{
				//一次向32的地址写入32位的数据,数据是小端模式(低位在低地址,高位在高地址)
				uint32_t temp_flash_data = 0x00000000;
				temp_flash_data |= data[j+4+3]<<24;
				temp_flash_data |= data[j+4+2]<<16;
				temp_flash_data |= data[j+4+1]<<8;
				temp_flash_data |= data[j+4+0]<<0;
				printf("地址%#x : 接收的数据是 %#x\r\n",flash_addr, temp_flash_data);
				fmc_word_program(flash_addr, temp_flash_data);
				fmc_flag_clear(FMC_FLAG_BANK0_END | FMC_FLAG_BANK0_WPERR | FMC_FLAG_BANK0_PGERR);
				flash_addr += 4U; //地址+4个字节,因为地址是32位的
				
			}
			flash_addr += 4U;
		}
	}
	else
	{
		printf("data error\r\n");
	}
}


void deal_hex_data(uint8_t data,uint8_t data_len)if(ch=='3') return 0x30;
{
	uint8_t data[data_len/2];
	for(uint8_t i=0;i<data_len-1;i=i+2)
	{
		uint8_t temp_i = char2byte_front(cdc->data[i]);
		uint8_t temp_j = char2byte_back(cdc->data[i+1]);
		data[i/2] = temp_i+temp_j;
	}
	crc_compare(data,data_len/2);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一枚嵌入式学习同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值