杂谈---嵌入式(单片机、arm)在线升级方案

描述

       最近不少人问我如何给单片机升级,如何给arm板升级。也有些人说网上很多工具可以参考或者移植。我当时回答时,如果做功能,自己想怎么玩即可,如果要做成量化的产品最好自己做一套协议。

    因为应用场合不同,对于一些特殊的功能尽量还是要在可控制中。移植不一定适合所有平台资源。所以我分享了我自己实现过的一套方案。

 

         本文档主要描述其他平台采用uart给单片机升级方案。可以用于pc给pc,pc给其他处理器平台参考,同时通讯接口可以采用网络,无线,uart,i2c,spi等,都可以参考,不受限底层物理通讯工具。

    同时基于此文档,可以加深底层通讯理解,文件理解,底层逻辑配合理解,理解产品和功能的不同。

     文章大致可分为以下几个步骤:

  1. 方案实际案例的需求描述;
  2. 方案描述;
  3. 升级端实现方案描述;
  4. 被升级端实现方案描述。

详细如下:

 

方案案例需求

当前需求实现采用一款linux终端对挂载uart485端口下的各个控制模块进行在线升级(是否类似于物联网、工业\民用仪表现场、楼宇自动化等)。
    升级时间尽量短,不能由于一个模块没有升级影响使用,甚至影响整个linux终端或者其他完成升级的模块使用。
                                                                         


    根据上述总体需求,则拆分出的硬件需求是保持线路稳定,尽量不要破坏升级环境,带来升级失败,且各个模块独立,这些其实如果模块做到了独立即可,只需要总线匹配即可,所以不需要累述。
    拆分出的软件的需求是:

  •     能实现1对1升级;
  •     能实现1对多升级;
  •     能实现部分升级失败后,未升级成功的模块仍能使用;
  •     未升级的模块和升级的模块相互不干扰;
  •     升级速度尽量快,保证现场尽快恢复。

三、    方案描述

                                                                                                         

          如上图所示,一个bin文件告知升级平台后,升级平台会将此文件解析出有效数据,然后将此类数据进行重新解析编译,得出相应的帧数,将数据下发给单片机部分。单片机获取到数据后,校验正确后,烧录到flash中,如果flash烧写并读取校验对比成功,证明一帧数据烧写完成,将对应的状态位置1.
       考虑到1对多情况,所以并不会每帧数据都是抄送的方式。


四、    升级端实现方案


    所有文件皆数据,无论是音频也好,还是bin文件也好,最终是一个个二进制按照对应格式协议组成。升级即传输,将程序搬运到指定的地方。那么对于传输通讯而言,这些升级程序即一个个二进制数据。
    无论是任何通讯接口,多快多慢,在合理的协议下,都能将数据搬运成功,只是时间长短问题。
    当前升级端拿到文件后,首先需要获知这个文件有效数据,数据大小多少,并获取个一个相应的总校验字。然后根据被升级端的响应时间和存储性能来规划两个要素,一个是一帧大小是多少,决定当前文件可以划分多少帧;第二是每帧的间隔时间大致是多少。
    当升级端处理上述问题后,开始“传功”,不对是升级。首先逐个告诉被升级端“兄弟,可以高升了,新的技能有好大,我要分好多阶段传给你”;一旦它的各个兄弟回答“得了,my 师傅,开干吧”,那么升级端就会按照间隔时间节拍,逐帧打包校验字后发送,不需要任何应答,升级完成后,就会逐步扫描下面各个设备,“小弟1号,我的功夫得了几成,那个没有学到!”,对应设备就会应答“teacher,我已神功大成,可以陪你练了”,那么升级端就会找另外一个设备;如果设备应答了“teacher,这第二式俺不会!”,升级端会将第二帧数据重发,此时所有设备都会再次接受,其他没有接收到的也会更新当前现场,但是只有指定设备才会去应答。采用这样的方式,一次完成最终的升级。


    具体步骤如下:

  •     获取bin的大小,获取总校验字,并获取即将拆分的帧数;
  •     逐个告知要升级的设备即将升级,告知升级的大小,总校验字,和升级帧数。需要逐个告知,待对方应答了,再告知另外一个对象,确保每个待升级的设备准备升级,如果对方没有应答准备好,根据对应情况,可以判定此设备异常不需要升级,跳过;
  •     按照udp方式(无应答)逐帧按照一定的时间节拍发出去;
  •     发送完毕后,逐个设备查询应答方式检查是否接受完成;
  •     如果对应设备应答完成,则查询另外一个设备;
  •     如果对应设备未完成,会应答当前未接受到最小帧号;
  •     升级端就会将对应帧号发下去,坐等对应设备应答,在这个同时,其他设备也会同步接受,如果没有收到此帧号,就会更新,如果收到了,不处理;
  •     逐个帧号补差完毕后,跳入下个设备。

五、    被升级端实现方案


    要完成设备在线升级,且升级出现异常后,还能运行最后一次成功程序,那么就有几个需求:
    第一,升级程序是独立的;
    第二,实际运行程序有两块存储地。
硬盘的格式如下:
                                                

    这里bootloader为升级对接的程序。即待升级平台上电程序就是它,如果没有当前没有需要升级模式,直接根据APP状态来切换即将运行的新程序。这里APP运行标志位即当前bootloader将跳入到那个APP存储地运行。
    APP存储地即存储实际运行程序的地方,有两个地方,一个存储,另外一个即升级备用,一旦一个升级成功,另外一个变成备用,升级时用那个也是APP运行状态来决定。

    这里只谈升级。所以步骤如下:

  •     进入升级模式,创建一个最大容量的升级状态字表;
  •     等待上位机找我升级确认;
  •     获取上位机的升级程序大小,程序的校验字,帧数后,应答ok;
  •     当上位机广播式发送数据时,逐帧接受数据;
  •     帧校验成功后,根据帧号,烧录到对应的flash地址中(可以按照扇区来操作,一般一个扇区对应一个帧号);
  •     烧录flash成功后,读取flash刚刚烧写的位置,对比烧录的内容和帧数据是否相同,如果相同,证明成功,将此帧号对应的升级状态字表对应位置1;
  •     当上位机发送查询命令时,如果查询不是当前设备则不应答;如果是当前设备则根据升级状态字表的最小未置位的位得出对应帧号应答给上位机;
  •     上位机补差帧号内容时,如果不是当前设备,则判断当前是否缺此帧,如果缺,则补齐,如果不缺不处理,但不应答;如果是当前设备,则接受,校验,烧录,烧录校验,然后成功后置状态字,应答下一个未接受到的帧号,如果失败则再次应答当前帧号;
  •     依照上述流程完成最终升级。
     

总结

      要完成上述功能,以及以后产品迭代,第一协议不要随意更改,第二要有一个很好的协议业务关系。具体通讯协议,待有空更新分享一下。

      我有一个qq群,744140106.感兴趣可以撩一下。

发布了17 篇原创文章 · 获赞 5 · 访问量 5605

猜你喜欢

转载自blog.csdn.net/weixin_43854435/article/details/104836470