赞
踩
此方法前提是你得有一个EEPROM
我用的单片机是STM32F103ZET6 , 此单片机FLASH容量为512KB;
在此单片机里面FLASH的起始地址是0X8000000,BOOT作为引导加载程序一般都是从这个地址开始,单片机一上点默认会从这个地址开始运行,所以将自己的BOOT程序放在这个地址。
其实boot也是个程序,只是他的主要功能是处理升级包。
我将FLASH分成三个块,第一块是BOOT区,第二块是程序缓存区,第三块是APP区
BOOT
我的boot代码大概33KB左右,所以我预留了40KB作为BOOT区
CODE
这个区是代码缓存区,一共160KB,将串口接收到的代码先存放在这个位置,等全部接受完成了,再把code区的代码移到APP区,然后跳转到APP就算完成bootloader
APP
这一块是我的主要代码运行区,我预留了312KB
程序运行逻辑
BOOT启动-----》读取EEPROM,判断有没有更新:
如果有---》将CODE区的代码移到APP区,然后跳转到APP区;
如果没有-----》等待一段时间,如果接收到新的升级包,先把数据存放到CODE区,等全部接受完成了移到APP区。如果没有接收到升级包,直接跳转到APP
APP启动--------》等待接受升级包,如果接收到升级包,重启单片机,回到BOOT
BOOT程序里判断EEPROM状态代码
这个放在main函数里。运行此段之前先初始化串口和EEPROM
-
- uint32_t readAddr ; //程序缓存区地址
- uint32_t app_wrinte_addr; //APP启动地址
- uint32_t app_size; //升级包大小
- uint8_t read_write_buf[1200];
- uint8_t BOOTloader_ST=0;
- //检查EEPROM
- if(AT24CXX_Check()==0)//检查器件EEPROM已经初始化
- {
- USART3_Send_Str("------------------------------------------------------\r\n");
- USART3_Send_Str("---------BOOTLOADER程序正在运行正常--------------------\r\n");
-
-
- USART3_Send_Str("EEPROM硬件正常\r\n");
-
- //初始化bootloader状态
- BOOTloader_ST = AT24CXX_ReadOneByte(999);//升级标志位在最后面
-
- switch(BOOTloader_ST)
- {
- //无需升级
- case 0XA0: //等待10个心跳时间后如果还是没有收到升级包跳转APP
- //直接跳过
- USART3_Send_Str(" 等待接受升级程序\r\n");
- // iap_load_app(0X8032000);
-
- break;
- //准备升级
- case 0XA1: //擦除FLASH,准备接受
- AT24CXX_WriteOneByte(999,0XA0); //初始化时等于0XA1说明接受失败
- USART3_Send_Str("准备升级--升级失败--等待接受升级程序\r\n");
- break;
- //正在接受数据
- case 0XA2: //等待接受完成,超时跳转APP
- AT24CXX_WriteOneByte(999,0XA0); //初始化时等于0XA2说明接受失败
- USART3_Send_Str("接受中断--升级失败--等待接受升级程序\r\n");
- break;
- //等待升级命令
- case 0XA3: //等待开始升级命令
- AT24CXX_WriteOneByte(999,0XA0); //初始化时等于0XA3说明接受失败
- USART3_Send_Str("接受完成---等待接受升级命令\r\n");
- break;
- //接受失败
- case 0XA4:
- AT24CXX_WriteOneByte(999,0XA0); //初始化时等于0XA4说明接受失败
- BOOTloader_ST = 0XA0;
- USART3_Send_Str("---接受中断--升级失败--等待接受升级程序-----\r\n");
- break;
- //开始升级
- case 0XA5: //擦除APP区,缓存的升级包移到APP区,跳转到APP区
- AT24CXX_WriteOneByte(999,0XA6); //升级
- USART3_Send_Str("---------接受完成---开始升级----------\r\n");
-
- app_size = (AT24CXX_ReadOneByte(1000)<<24) | (AT24CXX_ReadOneByte(1001)<<16)| (AT24CXX_ReadOneByte(1002)<<8) |AT24CXX_ReadOneByte(1003);
-
- app_wrinte_addr = 0X8032000; //APP地址
- readAddr = 0X800A000; //代码缓存区地址
-
- while (app_size> 0)
- {
- if (app_size>=1024)
- {
- System_ReadInteriorFlash (readAddr, read_write_buf, 1024) ;
- System_WriteInteriorFlash(app_wrinte_addr,read_write_buf, 1024);
- readAddr+=1024;
- app_size-=1024;
- app_wrinte_addr+= 1024; //写入地址增加
- }
- else
- {
- System_ReadInteriorFlash (readAddr, read_write_buf,app_size);
-
- System_WriteInteriorFlash(app_wrinte_addr,read_write_buf,app_size);
- readAddr+=app_size;
- app_size-=app_size;
- app_wrinte_addr+= 1024; //写入地址增加
-
- }
- }
-
- USART3_Send_Str("--------------即将跳转APP----------\r\n");
-
- iap_load_app(0X8032000); //跳转到APP
-
-
- break;
- //升级成功,无需
- case 0XA6: //回到无需升级
- USART3_Send_Str("--------------升级成功-----------\r\n");
- AT24CXX_WriteOneByte(999,0XA0); //等待新更新
- break;
-
- default : //可能是第一次上电,默认回到0XA0状态
- AT24CXX_WriteOneByte(999,0XA0);
- break;
- }
- }
在串口接受协议里面运行的代码
- //下面这个几个变量是全局变量,不能用局部变量
- framne_all = uart485buff[6]<<8 | uart485buff[7]; //包总数
- frame_num = uart485buff[8]<<8 | uart485buff[9]; //包序号
- writesize = uart485buff[10]<<8 | uart485buff[11]; //数据大小
-
- if(frame_num==0) //第一包
- {
- writeaddr = 0x800A000;
- AT24CXX_WriteOneByte(999,0XA2); //正在接受数据
- System_WriteInteriorFlash(writeaddr, &uart485buff[12] , writesize) ; //写入到内部FLASH
- writeaddr += writesize;
- }
- else if(frame_num == (framne_all-1)) //最后一包
- {
- BOOTloader_ST = 0XA5;
- AT24CXX_WriteOneByte(999,0XA5); //开始升级
- System_WriteInteriorFlash(writeaddr, &uart485buff[12] , writesize) ; //写入到内部FLASH
- writeaddr += writesize;
-
- AT24CXX_WriteOneByte(999,0XA5); //开始升级
- USART3_Send_Str("\r\n");
- USART3_Send_Str("---升级包全部接受完成--即将重启--\r\n");
- writeaddr-=0x800A000;
- AT24CXX_WriteOneByte(1000,((u8)(writeaddr>>24)&0xFF));
- AT24CXX_WriteOneByte(1001,((u8)(writeaddr>>16)&0xFF));
- AT24CXX_WriteOneByte(1002,((u8)(writeaddr>>8)&0xFF));
- AT24CXX_WriteOneByte(1003,((u8)(writeaddr)&0xFF));
-
-
- reboot(); //重启或者跳转到0X8000000地址
-
- }
- else
- {
- System_WriteInteriorFlash(writeaddr,&uart485buff[12] , writesize) ; //写入到内部FLASH
- writeaddr += writesize;
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。