当前位置: 首页 > news >正文

bootloader相关实现

main.cwhile(1){extern void start_app(unsigned int vector);start_app(0x08040000); //启动成功后不会往下走,而是去运行应用程序.....}
jump.SAREA    |.text|, CODE, READONLY; Reset handler routinestart_app        PROCEXPORT  start_app    ;set vector, 将函数传来的数(默认会保存在R0中)放入0xE000ED08(VTOR寄存器的地址)处LDR R1, =0xE000ED08STR R0, [R1];set SP, read val of address(0x08040000), set to SPLDR R1, [R0]MOV SP, R1;read val of address(0x08040004) ,jump LDR R1, [R0, #4]BX R1ENDPEND

注意在app里注释掉SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; 这里设置的是异常向量表的默认地址(0x08000000),不注释掉的话默认会使用bootloader的异常向量表。

使用bootloader下载功能需要定义下位机和上位机间的传输协议。

这里我们自定义了一个协议:

1.下位机发送 0x01;

2.上位机发送固件信息(包括a.长度,b.加载地址(即要烧写到flash的什么地方),c.CRC, d.文件名, e.版本号)

3.下位机判断版本信息是否比当前更高,更高的话发送0x02给上位机,请求升级

4.上位机发送bin文件给bootloader, bootloader进行CRC校验

5.bootloader烧写固件,并发送进度

改写h5程序实现下载功能

只保留usbx运行的默认任务,关闭其他任务宏。

bootloader.c#define CFG_OFFSET 0x081FE000 //flash中此地址开始保存配置信息(即FirmwareInfo结构体)#define UPDATE_TIMEOUT 1000static struct UART_Device* g_pUpdateUART;static void SoftReset(void)
{__set_FAULTMASK(1);//关闭所有中断HAL_NVIC_SystemReset();
}static void start_app_c(){/* 触发软件复位 */。SoftReset();}static uint32_t BE32toLE32(uint8_t *buf){return (uint32_t)buf[0] << 24 | (uint32_t)buf[1] << 16| (uint32_t)buf[2] << 8  | (uint32_t)buf[3] << 0;
}static int GetLocalFirmwareInfo(PFirmwareInfo ptFirmwareInfo){PFirmwareInfo ptFlashInfo = (PFirmwareInfo)CFG_OFFSET;if(ptFlashInfo->file_len = 0xFFFFFFFF){return -1;}*ptFirmwareInfo = *ptFlashInfo;return 0;
}static int GetServerFirmwareInfo(PFirmwareInfo ptFirmwareInfo){uint8_t data = '1';uint8_t buf[sizeof(FirmwareInfo)];if(0!=g_pUpdateUART->Send(g_pUpdateUART, &data, 1, UPDATE_TIMEOUT))return -1;/* wait for response */while(1){if(0!=g_pUpdateUART->RecvByte(g_pUpdateUART, &data, UPDATE_TIMEOUT))return -1;if(data != 0x5a){buf[0] = data;break;}}/* get firmware info  */ for(int i=1; i<sizeof(FirmwareInfo); ++i){if(0!=g_pUpdateUART->RecvByte(g_pUpdateUART, &buf[i], UPDATE_TIMEOUT))return -1;}ptFirmwareInfo->version = BE32toLE32(&buf[0]);ptFirmwareInfo->version = BE32toLE32(&buf[4]);ptFirmwareInfo->version = BE32toLE32(&buf[8]);ptFirmwareInfo->version = BE32toLE32(&buf[12]);strcpy((char*)ptFirmwareInfo->filename, (char*)&buf[16], 16);return 0;
}static int GetServerFirmware(uint8_t* buf, uint32_t len){uint8_t data = '2';/* send 0x02 cmd to PC */if(0!=g_pUpdateUART->Send(g_pUpdateUART, &data, 1, UPDATE_TIMEOUT))return -1;/* get firmware */ for(int i=1; i<len; ++i){if(0!=g_pUpdateUART->RecvByte(g_pUpdateUART, &buf[i], UPDATE_TIMEOUT))return -1;}return 0;
}static int GetCRC32(uint8_t* buf, uint32_t len){......
}void BootLoaderTask(void* pvParameter){struct UART_Device *pUABUART = GetUARTDevice("usb");FirmwareInfo tLocalInfo;FirmwareInfo tServerInfo;int err;int need_update = 0;uint8_t* firmware_buf;vTaskDelay(10000); //wait for pc readypUABUART->Init(pUABUART, 115200, 'N', 8, 1);g_pUpdateUART = pUABUART;while(1){/*  read cfg info, to detect app's version  */err = GetLocalFirmwareInfo(&tLocalInfo);if(err){/* update */need_update = 1;}else{pUSBUART->Send(pUSBUART, "GetLocalFirmwareInfo Failed\r\n", strlen("GetLocalFirmwareInfo Failed\r\n"), UPDATE_TIMEOUT);}err = GetServerFirmwareInfo(&tServerInfo);if(!err){if(tServerInfo.version > tLocalInfo.version){/* update */need_update = 1;}}else{need_update = 0;pUSBUART->Send(pUSBUART, "GetServerFirmwareInfo Failed\r\n", strlen("GetServerFirmwareInfo Failed\r\n"), UPDATE_TIMEOUT);}if(need_update){firmware_buf = pvPortMalloc(tServerInfo.file_len);if(!firmware_buf){/* error */pUSBUART->Send(pUSBUART, "Malloc Failed\r\n", strlen("Malloc Failed\r\n"), UPDATE_TIMEOUT);}err = GetServerFirmware(firmware_buf, tServerInfo.file_len);if(!err){/* calc CRC */uint32_t crc = GetCRC32(fireware_buf, tServerInfo.file_len);if(crc == tServerInfo.crc32){/* ok *//* burn */打印成功信息pUSBUART->Send(pUSBUART, "Download OK\r\n", 13, UPDATE_TIMEOUT);WriteFirmware(fireware_buf,tServerInfo.file_len);WriteFirmwareInfo(&tServerInfo);/* start app */start_app_c();}else{打印错误信息}}else{pUSBUART->Send(pUSBUART, GetServerFirmware Failed\r\n", strlen("GetServerFirmware Failed\r\n"), UPDATE_TIMEOUT)}}else{/* start app */}}}
bootloader.htypedef struct FirmwareInfo{uint32_t version;uint32_t file_len;uint32_t crc32;uint8_t file_name[16];}FirmwareInfo, *pFirmwareInfo;

注意将usb队列大小设置为10K

烧写应用程序和配置信息:

1. 擦除

2. 烧写

bootloader.cstatic int WriteFirmware(uint8_t* firmware_buf, uint32_t len, uint32_t flash_addr){FLASH_EraseInitTypeDef tEraseInit;uint32_t SectorError;uint32_t sectors = (len + (SECTOR_SIZE - 1)) / SECTOR_SIZE;uint32_t flash_offset = flash_addr - 0x08000000;uint32_t bank_sectors;uint32_t erased_sectors = 0;//解锁flashHAL_FLASH_Unlock();/* erase bank1 */if (flash_offset < 0x100000){tEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;tEraseInit.Banks = FLASH_BANK_1;tEraseInit.Sector = flash_offset / SECTOR_SIZE;bank_sectors = (0x100000 - flash_offset) / SECTOR_SIZE;if (sectors <= bank_sectors)erased_sectors = sectors;elseerased_sectors = bank_sectors;tEraseInit.NbSectors = erased_sectors;if (HAL_OK != HAL_FLASHEx_Erase(&tEraseInit,&SectorError){g_pUpdateUART->Send(g_pUpdateUART, (uint8_t *)"HAL_FLASHEx_Erase Failed\r\n", strlen("HAL_FLASHEx_Erase Failed\r\n"), UPDATE_TIMEOUT);HAL_FLASH_Lock();return -1;}flash_offset += erased_sectors*SECTOR_SIZE;}sectors -= erased_sectors;flash_offset -= 0x100000;/* erase bank2 */if (sectors){tEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;tEraseInit.Banks = FLASH_BANK_2;tEraseInit.Sector = flash_offset / SECTOR_SIZE;bank_sectors = (0x100000 - flash_offset) / SECTOR_SIZE;if (sectors <= bank_sectors)erased_sectors = sectors;elseerased_sectors = bank_sectors;tEraseInit.NbSectors = erased_sectors;if (HAL_OK != HAL_FLASHEx_Erase(&tEraseInit,&SectorError){g_pUpdateUART->Send(g_pUpdateUART, (uint8_t *)"HAL_FLASHEx_Erase Failed\r\n",strlen("HAL_FLASHEx_Erase Failed\r\n"), UPDATE_TIMEOUT);HAL_FLASH_Lock();return -1;}}/* program 烧写*/len = (len + 15) & ~15;for (int i = 0; i < len; i+=16){if (HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, flash_addr,(uint32_t)firmware_buf)){g_pUpdateUART->Send(g_pUpdateUART, (uint8_t *)"HAL_FLASH_Program Failed\r\n", strlen("HAL_FLASH_Program Failed\r\n"), UPDATE_TIMEOUT);HAL_FLASH_Lock();return -1;}flash_addr += 16;firmware_buf += 16;}HAL_FLASH_Lock();return 0;}//擦除最后一个扇区并烧写固件信息
static int WriteFirmwareInfo(PFirmwareInfo ptFirmwareInfo){FLASH_EraseInitTypeDef tEraseInit;uint32_t SectorError;uint32_t flash_addr = CFG_OFFSET;uint8_t *src_buf = ptFirmwareInfo;HAL_FLASH_Unlock();/* erase bank2 */tEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;tEraseInit.Banks = FLASH_BANK_2;tEraseInit.Sector = (flash_addr – 0x08000000 – 0x100000) / SECTOR_SIZE;tEraseInit.NbSectors = 1;if (HAL_OK != HAL_FLASHEx_Erase(&tEraseInit, &SectorError)){g_pUpdateUART->Send(g_pUpdateUART, (uint8_t *)"HAL_FLASHEx_Erase Failed\r\n",strlen("HAL_FLASHEx_Erase Failed\r\n"), UPDATE_TIMEOUT);HAL_FLASH_Lock();return -1;}/* program */for (int i = 0; i < sizeof(FirmwareInfo); i+=16){if (HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, flash_addr, (uint32_t)src_buf)) {g_pUpdateUART->Send(g_pUpdateUART, (uint8_t *)"HAL_FLASH_Program F        ailed\r\n",strlen("HAL_FLASH_Program Failed\r\n"), UPDATE_TIMEOUT);HAL_FLASH_Lock();return -1;}flash_addr += 16;src_buf += 16;}HAL_FLASH_Lock();return 0;
}

上电复位流程为:

http://www.xdnf.cn/news/1445365.html

相关文章:

  • 逻辑回归 vs 支持向量机 vs 随机森林:哪个更适合小数据集?
  • 中通笔试ShowMeBug编程题复盘
  • 免费的PDF工具箱软件,免费PDF转word,PDF合并,PDF24下载,24个功能
  • Corona 13 渲染器安装与使用教程(适用于3ds Max 2016–2026)
  • 408考研——单链表代码题常见套路总结
  • 有奖直播 | 如何高效测试ADC/DAC?德思特一站式方案,让测试效率倍速提升!
  • 【Linux操作系统】简学深悟启示录:进程控制
  • 1983:ARPANET向互联网的转变
  • test命令与参数
  • Kotlin编程学习记录2
  • Linux `epoll` 机制的入口——`epoll_create`函数
  • 自由学习记录(92)
  • 图像正向扭曲反向扭曲
  • 关于缓存的一些思考?
  • 从Java全栈到前端框架:一次真实的面试对话
  • 自动化运维-ansible中对于大项目的管理
  • HTML第八课:HTML4和HTML5的区别
  • 网络通信与协议栈 -- OSI,TCP/IP模型,协议族,UDP编程
  • Linux 网络编程中核心函数`recv`。
  • Qt6用Chart模块做数据可视化?别再用老套路,看看这套35张图背后的秘密
  • MySQL :索引原理
  • 【面试题】BPE和WordPiece的区别?
  • Anaconda3出现Fatal error in launcher: Unable to create process using.....问题
  • STM32CubeMX + HAL 库:基于 I²C 通信的 BMP280气压海拔测量
  • 【超详细】别再看零散的教程了!一篇搞定Gitee从注册、配置到代码上传与管理(内含避坑指南最佳实践)
  • PS大神级AI建模技巧!效率翻倍工作流,悄悄收藏!
  • Wan系列模型解析--详细架构图
  • 机器学习在Backtrader多因子模型中的应用
  • 美团龙猫利用expat库实现的保存xml指定范围数据到csv的C程序
  • TypeScript 泛型入门(新手友好、完整详解)