定制带U盘功能的bootloader实现拖拽下载固件

文章介绍了如何通过定制bootloader,利用MM32F5270微控制器的USB外设模拟U盘,实现固件的拖拽下载。开发者可以通过PC将固件文件拖拽到开发板的U盘区域,复位后开发板自动执行新固件。该方法简化了固件更新流程,减少了对调试器和专用工具的依赖。文章详细阐述了实现原理,包括硬件和软件的设置,以及固件验证和复制过程。

定制带U盘功能的bootloader实现拖拽下载固件

引言

我们在向一些非专业开发者发放开发板时,有时对方没有调试器,开发者就无法下载体验在后续发布支持新功能的固件。并且,对于非专业开发者的用户来说,仅仅是体验新功能,而不介入开发工作,专门搭建一套开发环境,性价比实在不高。即使有调试器硬件,在不同操作系统平台上,还需要安装专门的工具软件配合工作,才能实现下载固件的功能,操作比较繁琐。为了简化下载固件的操作,本例使用MM32F5270微控制器,基于芯片自带的USB外设,实现了一个基于U盘拖拽更新固件的解决方案。我期望实现的结果是:

  • 将开发板同PC连接后,PC将识别出一个U盘
  • 可将开发板的固件(bin 格式)文件拖拽存放至该U盘中
  • 复位开发板后,开发板能够执行新的固件程序

相对于板载带有U盘拖拽下载功能的daplink方案,本例节约了一个专门运行daplink程序的芯片,利用微控制器自带的USB外设直接建立同PC的连接,更可有机会被实现成ROM,固化在芯片内部。

关于项目的源码及相关的资料,见Gitee站点:https://gitee.com/suyong_yq/mcu-udisk-bootloader

原理

MM32F5270片内集成了256KB Flash,但可通过QSPI接口外扩spiflash存储设备,并可在外扩spiflash中执行程序(XIP)。本例实际将运行bootloader的片内Flash当做BOOT ROM,而将可执行程序的固件存放在对接的spiflash存储介质中。当芯片上电后,通过一些外部控制手段(例如使用一个按键选择启动模式),先运行带有USB功能的bootloader程序,由bootloader的程序将芯片模拟成U盘(U盘的物理存储空间位于外扩spiflash的后半段)。PC可以看到模拟U盘中的现存文件,也可以向其中拖拽新文件。当拖拽新文件后,bootloader程序会继续将新文件的程序内容复制到程序的执行区域,覆盖掉之前的程序,然后再跳转到程序的执行区域执行程序。

这里专门使用一块物理存储区域(spiflash存储器的后半段)的原因是,USB协议栈模拟U盘时,对文件系统的管理操作全部交由PC完成,这就意味着,PC向模拟U盘发送包含文件内容的数据包时,不一定是按照物理上的先后顺序发送的,微控制器端难以通过数据包本身解析出数据包的先后顺序。但是,bootloader向程序执行区域复制可执行程序的内容必须是顺序且连续的。PC在同U盘的通信过程中,数据包之间的内容可能不连续,但最终发送完成的文件内容一定是完整的。因此,这里使用使用了一个能包含整个固件文件大小的区域作为缓冲区,先缓冲下来整个完整的文件,然后再将完整的文件内容按顺序复制到程序的可执行区域。

理想情况下,如果能用一块RAM作为整个文件的缓冲区,通过U盘拖拽下载过程将会非常快。但本例中使用spiflash作为缓冲区,虽然擦除spiflash并向其写入数据需要花费更多的时间,但能容纳更大的程序文件。

如果芯片内部集成足够大的片内Flash,也可以不依赖外扩spiflash,对内部的Flash做分区,分别作为bootloader、运行程序及文件缓存的存储区。

实现

硬件相关

本例使用BIRD-F5270开发板,开发板基本情况如下:

  • 晶振 12MHz
  • 使用QSPI接口对接外扩spiflash存储芯片FM25Q16(2MB Flash),引脚与MM32F5280片内合封所使用的引脚保持一致:
    • QSPI_NSS - PF6
    • QSPI_SCK - PG7
    • QSPI_D0 - PG6
    • QSPI_D1 - PF8
    • QSPI_D2 - PF10
    • QSPI_D3 - PG8
  • USB 引脚
    • USB_DP - PA12
    • USB_DM - PA11
  • 按键引脚
    • SW1 - RESET
    • SW2 - BOOT0
    • SW3 - PA0

软件相关

启动到2nd bootloader

芯片上电复位后,默认是直接执行到用户程序中,但也可以通过指定的手段改为执行bootloader,执行U盘程序。本例使用一个按键,绑定到一个指定的GPIO输入(BOOT引脚),芯片在启动过程中判定启动模式:默认启动到用户程序,当按键按下时,启动到带有U盘程序的bootloader。

MM32F5芯片自带的BOOT0引脚虽然在微控制器复位后可作为普通GPIO使用,但可能会将芯片引导到芯片内部已经固化到ROM中的bootloader程序中,因此不适合作为2nd bootloader的BOOT引脚。BIRD-F5270开发板上除RESET和BOOT0 之外,还有PA0引脚实现按键(SW3)功能,可作为2nd bootloader中的BOOT引脚。

当 SW3 被按下时,PA0 为低电平,可执行 U 盘任务,当 SW3 松开时,PA0 为高电平,可执行跳转程序的任务,具体实现代码如下:

/* read gpio pin level, select boot mode. */
if (GPIO_ReadInDataBit(BOARD_BTN_PORT, BOARD_BTN_PIN))
{
   
   
    /* update app & run. */
    jump_to_app();
}
else
{
   
   
    /* run usb msc task. */
    msc_task();
}

/* cannot run here. */
while(1)
{
   
   }
基于USB外设模拟U盘

MM32F5270微控制器集成了USB外设,配合TinyUSB协议栈,可模拟U盘(MSC设备)。

当运行模拟U盘的程序时,需要指定一块存储区域作为U盘的存储空间,在本例中,将外扩的spiflash存储区域一分为二,前半部分作为执行程序区域,存储需要执行的应用程序,后半部分作为U盘的物理存储空间,将用于缓存用户通过拖拽方式下载的固件。

注意,spiflash作为U盘的存储介质时需要解决一个问题,spiflash的最小擦除块大小是4KB,而U盘设备对存储介质的擦除块大小是512B,擦除块大小不匹配。该问题有两种解法:

  • 每次修改spiflash前,先将包含目标操作空间的4KB大小的数据块读取数据到RAM中缓存,修改指定位置的数据内容后,擦除spiflash中对应的整块,再将修改后的数据块写入到spiflash中。
  • 每次修改spiflash前,先将包含目标操作空间的4KB大小的数据块读取数据到RAM中缓存,修改指定位置的数据内容后,暂不写回到spiflash中。如果接下来要写入的数据仍在该块中,则继续写入RAM缓存。只有当将要新写入的数据不在缓存的数据块中时,才写回最近缓存的数据块,并读出新的数据块到RAM缓存中。另外,每次在写操作之后的读操作,也都会重新清空RAM缓存中的数据。

第一种方法简单易实现,但会频繁擦写spiflash,消耗存储器件的寿命。第二种方法相当于实现了一个cache机制,操作行为较为复杂。当前暂时选择第一种做法,先验证原理,如果后续考虑将这个带U盘功能的bootloader集成到芯片内部,到时也可以专门集成一块以512B作为操作单元的dflash作为固件的缓存存储设备。

运行TinyUSB协议栈的程序中,在执行MSC任务时,会执行对spiflash存储设备进行读写操作的回调函数,如下:

从spiflash读数据:

// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and return number of copied bytes.
int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize)
{
   
   
    (void) lun;

    uint8_t * addr = (uint8_t
有没有想过,像使用U一样升级STM32固件,非常简单,非常方便 1: 插入电脑USB接口 2: 把升级固件拖到设备符 3: 升级完成 抛弃繁琐的USB DFU,抛弃落后的串口升级,让我们来谈谈U升级STM32 1. 为什么设计这个BOOT LOADER 在电子产品开发过程中,为了满足市场需要,经常是先开发出一个简单可用的版本,然后逐步迭代升级,修复bug,并增强系统功能 一个稳定,简单,安全的升级方式,就变得非常重要 对于嵌入式系统来说,常见的升级方式为 串口升级(私有协议或者X-Modem) USB升级(DFU) U升级(OTG) 网络升级 无线升级(OTA) 从技术来说,这几种升级方式大同小异,原理类似:都是一个Loader代理接收数据通道的数据,然后解密,烧录到FLASH中;但用户体验完全不同,拿串口升级来说,首先用户需要一个串口软件,然后对于没有硬件串口的PC来说,就需要一个USB转串口设备,对于不同PC平台,串口软件就不一样,这需要学习成本,过程繁琐;所以在一些需要用户自行升级远程设备的情况下,即便是通过电话指导,80%的用户仍然不知道怎么升级,导致失败 USB的DFU升级,也是类似的问题,它设计的初衷就是面向专业用户的,而不是小白!所以需要安装DFU软件,按照手册来一步步升级 OTA升级和网络升级,体验好些,可用做到无感升级,但不适合所有场景 而U升级,用户学习成本最低,U大家都知道,然后拷贝一个Bin文件进去,插入设备,重启设备,就完成升级了,非常简单。类似的变种,比如手机升级,是最先进的,直接将手机模拟成U,然后用户拷贝数据到手机,重启就好了,非常简单 在嵌入式系统中,还没这么方便的升级手段,虽然ARM的Mbed有一种类似的固件更新功能,但它是专门为调试器设计的,不能内嵌到用户MCU中 所以,我将手机升级的方案引入到嵌入式系统中,从而为大家提供一个实现稳定,安全,零学习成本的升级方案 经过一段时间的学习研究,有了这个USB MSD Bootloader 2. 功能特点 只占用15K FLASH空间 简单易用,直接拖拽文件进行固件升级,无需任何专业知识 采用USB大容量设备类,不用安装任何驱动 支持各种系统(Windows/Linux/Mac/Android) 不用开发任何上位机,提高产品效率 支持各种加密算法(AES256等),轻松安全升级 自动识别Bin,Hex,自定义加密固件(后缀为sec)文件 支持MD5文件校验机制,保证固件升级的完整性 显示设备升级状态信息 支持长文件名升级 多种措施保证系统健壮性,保证Bootloader不会被误擦除,保证APP合法性 支持用户自定义加密算法和完整校验算法,极致安全 3. 系统原理 系统开机上电后,Bootloader接管系统,初始化USB硬件,等待USB连接 Bootloader在启动后1秒内,检测USB是否连接PC:如果连接PC,则进入固件升级模式,执行第3步;超时则跳转第8步,尝试执行用户APP Bootloader模拟成MSD设备,构建FAT16虚拟文件系统,U名为”Bootloader”,容量为100M,但具体实际可用空间,根据用户MCU来确定,建议不要复制除APP之外的无关文件 当用户复制文件到U时,Bootloader会判断文件后缀和判断文件size,如果size大于实际的MCU可用FLASH或者文件后缀不合法,则进入错误状态,更新状态文件,重新枚举USB 文件后缀和size通过检测后,Bootloader会截获PC发送文件数据流,并写入MCU 对应的Flash中 如果写入过程中出错,则终止操作,擦除APP内容,进入错误状态,更新状态文件,重新枚举USB 成功写入后,Bootloader更新状态文件,重新枚举USB,显示升级完成;但不会运行APP,只有拔掉USB后,再次重启,才会进入第8步,尝试运行APP Bootloader检查APP固件的栈和入口函数合法性,只有通过检测后,才开始执行APP。检测判断条件是栈指针必须在RAM地址空间内,入口函数地址必须处于THUMB模式,并LSB为1 停止USB设备,关掉所有的中断,执行APP,APP开始接管系统 4. 支持芯片 STM32F101/3/5/7 重点来了,点击下面链接,下载固件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值