成都建设网站标化最新表格,做外贸用什么服务网站,技术支持 东莞网站建设 轴承,企业网站模板下载软件STM32 OTA应用开发——自制BootLoader 目录STM32 OTA应用开发——自制BootLoader前言1 环境搭建2 BootLoader工作原理以及常见分区介绍3 BootLoader的制作4 烧录下载配置5 运行测试结束语前言
什么是OTA#xff1f; 百度百科#xff1a;空中下载技术#xff08;Over-the-Ai…STM32 OTA应用开发——自制BootLoader 目录STM32 OTA应用开发——自制BootLoader前言1 环境搭建2 BootLoader工作原理以及常见分区介绍3 BootLoader的制作4 烧录下载配置5 运行测试结束语前言
什么是OTA 百度百科空中下载技术Over-the-Air Technology; OTA是通过移动通信的空中接口实现对移动终端设备及SIM卡数据进行远程管理的技术。经过公网多年的应用与发展已十分成熟网络运营商通过OTA技术实现SIM卡远程管理还能提供移动化的新业务下载功能。 实际上现在我们所说的OTA比百度百科的定义还要更广泛OTA的形式已经不再局限于手机和SIM卡只要涉及到远程下载升级程序的方式我们都可以称之为OTA。例如通过4G5GWiFI蓝牙等无线通讯进行下载升级的可以称为OTA通过U盘RS485等串行接口进行升级的也可以称之为OTA。
OTA的作用 OTA的意义在于它在一定程度上突破了距离的限制在不借助烧录器的情况下完成固件的下载升级极大的方便了产品的升级和维护降低售后成本。
什么是BootLoader 百度百科在嵌入式操作系统中BootLoader是在操作系统内核运行之前运行。可以初始化硬件设备、建立内存空间映射图从而将系统的软硬件环境带到一个合适状态以便为最终调用操作系统内核准备好正确的环境。在嵌入式系统中通常并没有像BIOS那样的固件程序注有的嵌入式CPU也会内嵌一段短小的启动程序因此整个系统的加载启动任务就完全由BootLoader来完成。 实际上BootLoader不仅仅在操作系统上使用在一些内存小功能应用较为简单的单片机设备上面也可以通过BootLoader来完成OTA升级。
我之前也有发过一些关于STM32远程OTA的文章但用的是第三方BootLoader而且是基于操作系统实现的。BootLoader占用的内存也比较大而且不开源。 所以这一讲我就来介绍一下如何自己制作一个简单的BootLoader程序。
1 环境搭建
关于STM32以及Keil的环境这里就不具体介绍了网上教程也很多不懂的同学自行查阅资料。
2 BootLoader工作原理以及常见分区介绍
不管用的是什么MCU要使用OTA都离不开BootLoaderBootLoader是一个统称它其实只是一段引导程序在MCU启动的时候会先运行这段代码判断是否需要升级如果不需要升级就跳转到APP分区运行用户代码如果需要升级则先通过一些硬件接口接收和搬运要升级的新固件然后再跳转到APP分区运行新固件从而实现OTA升级。
常见分区方式介绍 1.Application 没有加入Bootloader之前我们单片机内部的flash就是一整块的所有的应用代码都放在这。
2.Bootloader Application 在原有的flash区域里面划分出两个区域Bootloader和Application这种分区方式的好处在于既可以OTAAppd区又可以分到较大的空间缺点是没有存放新固件的区域需要从外部导入进来而且一旦传输的过程被异常打断那么原有的App代码也无法正常运行了也就是传说中的“变砖”。
3.Bootloader Application Download 这种分区方式是比较万能的一种优点是新固件是先存放到Download区的哪怕搬运的过程中出现异常中断的情况也不会“变砖”缺点是需要单独划分一块内存跟APP区差不多的区域用来存放新固件变相的减少了APP区的空间对于内存较小的单片机来说压力就比较大了。
4.Bootloader Application1 Application2 这种方式可以同时存在两套App优点在于升级了新固件以后还保留了原来的旧版固件必要的时候还可以进行版本的回退。
5.Bootloader Setting Application Download 这种方式跟第3种基本一样只是增加了一个区域用来存放升级相关的一些参数以及用户的一些配置。
3 BootLoader的制作
BootLoader的制作需要根据实际的需求来做不同的运行方式或者升级方式在做法上都是有区别的包括BootLoader所需要的内存空间也不尽相同。 不过不管是用什么方式Bootloader都应该尽可能做的更小更简洁这样的话内存的开销就更小对于内存较小的MCU来说压力就没那么大了。
我下面要做的这个bootloader是上面讲的常见分区方式里面的第5种。 分区介绍 我用的是STM32F103内存是128K的想用内存更小的MCU也是可以的改下各个分区的内存分配就行了。
分区表如下
nameoffsetsizeboot0x080000000x00003000setting0x080030000x00001000app0x080040000x0000E000download0x080120000x0000E000
功能描述 运行bootloader的时候先从setting里面读一些参数确定是否需要升级如果需要则把download分区的固件搬运到app分区如果不需要升级则直接跳转到app分区. 至于新固件的下载传输过程我放到App里面去处理了这跟我的项目实际需求有关系App部分这里就先不往下拓展了后面我会专门写一篇博客来介绍。
各个功能模块的具体讲解 1、分区定义 先把各个分区的内存地址以及大小定义好方便后面使用。
#define FLASH_SECTOR_SIZE 1024
#define FLASH_SECTOR_NUM 128 // 128K
#define FLASH_START_ADDR ((uint32_t)0x8000000)
#define FLASH_END_ADDR ((uint32_t)(0x8000000 FLASH_SECTOR_NUM * FLASH_SECTOR_SIZE))#define BOOT_SECTOR_ADDR 0x08000000 // BOOT sector start address
#define BOOT_SECTOR_SIZE 0x3000 // BOOT sector size
#define SETTING_SECTOR_ADDR 0x08003000 // SETTING sector start address
#define SETTING_SECTOR_SIZE 0x1000 // SETTING sector size
#define APP_SECTOR_ADDR 0x08004000 // APP sector start address
#define APP_SECTOR_SIZE 0xE000 // APP sector size
#define DOWNLOAD_SECTOR_ADDR 0x08012000 // Download sector start address
#define DOWNLOAD_SECTOR_SIZE 0xE000 // Download sector size 2、程序跳转 Bootloader作为引导程序最重要的工作之一就是通过内存跳转进入用户程序下面这段代码可以跳转到任何一个内存地址。
uint8_t jump_app(uint32_t app_addr)
{uint32_t jump_addr;jump_callback cb;if (((*(__IO uint32_t*)app_addr) 0x2FFE0000 ) 0x20000000) { jump_addr *(__IO uint32_t*) (app_addr 4); cb (jump_callback)jump_addr; __set_MSP(*(__IO uint32_t*)app_addr); cb();return 1;} return 0;
}3、处理函数 从setting区里面读取process状态值然后进行对应的处理如果需要升级则把download区的固件搬运到app区然后再运行新APP如果不需要升级则直接跳转到APP。
process get_boot_state();
switch (process)
{case START_PROGRAM:printf(start app...\r\n);delay_ms(50);if (!jump_app(APP_SECTOR_ADDR)) {printf(no program\r\n);delay_ms(1000);}printf(start app failed\r\n);break;case UPDATE_PROGRAM:printf(update app program...\r\n);app_addr APP_SECTOR_ADDR;down_addr DOWNLOAD_SECTOR_ADDR;printf(app addr: 0x%08X \r\n, app_addr);printf(down addr: 0x%08X \r\n, down_addr);printf(erase mcu flash...\r\n);mcu_flash_erase(app_addr, APP_ERASE_SECTORS); printf(mcu flash erase success\r\n);printf(write mcu flash...\r\n);// memset(down_buf, 0, sizeof(down_buf));for (i 0; i APP_ERASE_SECTORS * 8; i){mcu_flash_read(down_addr, down_buf[0], 128);delay_ms(5);mcu_flash_write(app_addr, down_buf[0], 128);delay_ms(5);down_addr 128;app_addr 128;}printf(mcu flash write success\r\n);set_boot_state(UPDATE_SUCCESS);break;case UPDATE_SUCCESS:printf(update success\r\n);boot_state UPDATE_SUCCESS_STATE;write_setting_boot_state(boot_state);set_boot_state(START_PROGRAM);break;default:break;
}完整代码下载地址https://download.csdn.net/download/ShenZhen_zixian/87462312
4 烧录下载配置
我们的Bootloader做好以后需要烧录到MCU里面可以直接用Keil uVison来下载也可以用J-Flash或者其他这个都没关系但是要注意内存的分配要把固件烧到对应的内存地址上。 我这里做出来的bootloader bin只有8K不过为了方便后续在这部分增加新功能我实际分配了12K的空间地址区间是0x08000000-0x08003000。
如果是用keil下载的话需要注意flash的配置具体如下 如果是用J-Flash或者STlink的工具烧录的话注意烧录的起始地址是0x08000000就好了。
5 运行测试
注这里我还没讲解App部分代码你们只看Bootloader部分的log就好了不影响的也可以下载完整的代码实际去跑一下。 不需要升级时直接跳转到App区如下图
需要升级时先从download区搬运新固件到app区然后再跳转到App区如下图
结束语
好了关于自制BootLoader的介绍就讲到这里本文只是提供一个思路不是唯一的方法关键还是看你自己实际的需求。 还有App那部分这里没详细讲后续我会专门写一篇关于App部分的博客到时候合并到一起就比较清晰了。或者你也可以下载完整的源码自己去跑一下下面的源码我把BootLoader和APP都上传了。
完整代码下载地址https://download.csdn.net/download/ShenZhen_zixian/87462312
如果你有什么问题或者有更好的方法欢迎在评论区留言。