搜索
bottom↓
回复: 22

AVR bootloader及avrubd的改进建议

[复制链接]

出0入0汤圆

发表于 2020-3-5 17:52:28 | 显示全部楼层 |阅读模式
本帖最后由 wangzugong 于 2020-3-5 17:58 编辑

    前段时间产品做远程升级,上位机使用的是avrubd。出现很多在安全模式下升级失败但avrubd不报错的问题,造成不少麻烦。因为一旦升级失败而不能发现,进入APP程序以后就再也回不到bootloader,必须有人到现场处理。
    最近因为2019-nCoV的原因有时间做了分析,发现了问题所在。现总结出来,希望对大家各类单片机的应用有帮助。
    如有错误,请大家不吝赐教。
测试结果:
    发现同样的数据帧被写入FLASH两次。
分析:
    1、在远程升级时,通信链路中间经过了路由器、交换机、WIFI等中间设备,造成数据的改变,尤其是少量字节数据的传输不能保证数据的正确性。特别是单字节的数据,比如 ACK、NAK 之类。
    2、数据帧传送完成后,可能其后还会有附带的字符,造成单片机串口堵塞,下一帧数据的头错误。
    3、4.5版的AVR bootloader和avrubd虽然经过了很多考验,但几乎都是直接使用串口直接通信,数据传输几乎不会出错。它已经对可能出现的错误做了处理,实际上我们也使用该软件做过很多产品直接串口升级,从来没有发现问题。
         但是在远程升级时就会发生平常被认为不可能发生的错误,例如:当 ACK、NAK错误时,由此造成的错误可能有两种:
         A、发NAK时上位机收到的是ACK,这样会不重发错误帧,造成FLASH少写入一帧。但实际检测没有发现这样的情况,如果真有,单片机也无能为力;
         B、发ACK时上位机收到的是NAK,这样会重发正确的帧,造成FLASH多写入一帧。实际检测发现经常出现这样的情况。
    4、avrubd是每个数据帧进行一次读出校验,上面说的两种错误时无法发现的。如果改成全部FLASH写完再进行一次读出校验,就能发现全部错误。
解决办法:
    本人不会delphi编程,暂时也没有时间现学,只能从单片机软件中想办法。处理如下:
    1、每次向上位机发送回复前延时1ms,然后读一次串口缓存,消除上次多余无效数据对下一帧的影响。专门做了一个子函数如下:
         
//消除串口0错误
unsigned char  error_elimination_com( void )
{
  volatile unsigned char  data = 0;
  
  _delay_ms(1);

  if(  ( UCSR0A & (BIT(FE0)|BIT(UPE0)|BIT(DOR0)) ) != 0  )  
  {
          data = UDR0;
  }
  
  return data
}

    2、增加一个缓存区,用于将刚刚接收到的数据帧跟上次接收的数据帧进行比较,如果重复将抛弃。除非全是0xFFCF ,在进行CRC校验前插入下面的代码:

          for( i=0; i<SPM_PAGESIZE; i++ ) //串口接收缓冲区长度 SPM_PAGESIZE=128
          {
                  rxBuf = wait_from_com();  
          }
         
          flag = 0x02; //设置重复标志
         
          for( l=0; l<SPM_PAGESIZE; l+=2 )
          {
                  if(  ( ((unsigned short)rxBuf[l]<<8) | rxBuf[l+1] ) != 0xFFCF  ) //如果都是0xFFCF
                  {
                          flag = 0x01; //非全FFCF
                          break;
                  }
                  //else 全FFCF
          }
         
          for( k=0; k<SPM_PAGESIZE; k++ )
          {
                  if( tempBuf[k] != rxBuf[k] ) //如果不一致
                  {
                          flag &= ~BIT(0); //不重复
                          break;
                  }
                  //else 重复
          }
         
          for( m=0; m<SPM_PAGESIZE; m++ ) //备份上次帧,用于比较,避免重复
          {
                  tempBuf[m] = rxBuf[m];
          }
         
        // 2--重复但全FFCF;1--重复但非全FFCF;0--不重复且非全FFCF
       if( flag != 1 ) //继续
       {
             ..........

    以上代码仅针对128字节一页的单片机,其它情况请根据实际修改。

建议:
   1、全部FLASH写完进行一次读出校验;
   2、连接、写入、校验分开,分别设置按钮;
   3、增加单片机boot区大小选项。比如选择32K的单片机后,应该再选择其boot区。因为在APP填充FFCF后,超出boot区的数据无意义;
   4、建议增加集成虚拟串口,在串口选项框里增加IP和端口选择,使得avrubd可以直接连接远程设备。

出0入0汤圆

发表于 2020-3-5 17:57:50 | 显示全部楼层
艾特梅尔留香久,神州ARM遍地生

出0入442汤圆

发表于 2020-3-5 18:35:05 来自手机 | 显示全部楼层
bootloader如果没有校验能力,应对意外恢复的能力=0%。。我这边做fpga全部强制接入被动烧录信号,这样可以救砖。

出105入79汤圆

发表于 2020-3-6 12:37:52 | 显示全部楼层
bootloader在写完成标记之前,肯定要再次校验Flash APP区域所有数据的CRC要和文件头的CRC一致. 每次开机Bootloader跳转APP之前,也要校验一次防止Flash窜改和失效.

出0入0汤圆

 楼主| 发表于 2020-3-9 15:28:42 | 显示全部楼层
本帖最后由 wangzugong 于 2020-3-9 15:36 编辑
qwe2231695 发表于 2020-3-6 12:37
bootloader在写完成标记之前,肯定要再次校验Flash APP区域所有数据的CRC要和文件头的CRC一致. 每次开机Boot ...


你用过avrubd吗? 看不明白你的意思。

“bootloader在写完成标记之前,肯定要再次校验Flash APP区域所有数据的CRC要和文件头的CRC一致.”,你是赞成我的说法?还是认为我理解错了avrubd?

“ 每次开机Bootloader跳转APP之前,也要校验一次防止Flash窜改和失效.”  请问你说的是谁和谁校验? 怎么校验?

希望大家能就这个帖子本身说的问题讨论、提出建议, 要具体、可操作。不要说概念性的东西。

出0入0汤圆

发表于 2020-6-10 15:11:31 | 显示全部楼层
现在新版本是5.2的,4.5的有些bug,
利用这个做远程更新的话,最好是做些改进,堵住可能出现的异常情况。

出0入0汤圆

 楼主| 发表于 2020-10-30 17:13:01 | 显示全部楼层
Forever 发表于 2020-6-10 15:11
现在新版本是5.2的,4.5的有些bug,
利用这个做远程更新的话,最好是做些改进,堵住可能出现的异常情况。 ...

5.2版本的在哪里呀? 麻烦你给发个链接,谢谢!

出0入0汤圆

 楼主| 发表于 2020-11-10 15:22:04 | 显示全部楼层
我似乎发现了问题的所在:

上位机软件avrbud 存在一个BUG,一般情况下很难出现。

在这个串口接收事件代码中   procedure TfrmMain.ComPortRxChar(Sender: TObject; Count: Integer);  

下载时判断单片机的回复是这样的:

        if RxBuf[0] = XMODEM_ACK then
             ACK := XMODEM_ACK
        else
             ACK := XMODEM_NAK;

这就是说只要单片机回复的不是XMODEM_ACK,就认为是XMODEM_NAK,不论收到什么字符都认为是XMODEM_NAK。结果就是造成认为是单片机要求重发数据。
实际上由于传输错误的可能,出现既不是XMODEM_ACK也不是XMODEM_NAK的回复可能性是存在的。只是在直接使用串口通信的时候出现这种错误的概率非常小而已。
因此此处应修改为:

        if RxBuf[0] = XMODEM_ACK then
             ACK := XMODEM_ACK
        else if RxBuf[0] = XMODEM_NAK then
             ACK := XMODEM_NAK;
        else
             //计错误一次

以上建议,仅供参考。虽然avr单片机现在已经不太流行,但相关技术问题还是值得讨论。avrbud作为一代经典,有必要让它完美无缺。

出0入162汤圆

发表于 2020-11-10 16:03:35 来自手机 | 显示全部楼层
我现在用avrbud给STM32升级,用同样的xmodem协议

出0入0汤圆

 楼主| 发表于 2020-11-11 15:36:04 | 显示全部楼层
AWEN2000 发表于 2020-11-10 16:03
我现在用avrbud给STM32升级,用同样的xmodem协议

只用串口基本上不会出问题。

出0入4汤圆

发表于 2020-11-11 21:42:20 | 显示全部楼层
老古董的芯片了 还在研究

出0入0汤圆

发表于 2020-11-11 23:46:32 | 显示全部楼层
avr一直还再出新品 有空可以了解下

出0入0汤圆

 楼主| 发表于 2020-12-18 11:29:15 | 显示全部楼层
ilan2003 发表于 2020-11-11 21:42
老古董的芯片了 还在研究

其实这里研究的不是AVR, 研究的是系统和软件BUG问题。 通过这样一个例子说明什么叫钻研精神。

出0入0汤圆

发表于 2020-12-18 16:03:57 | 显示全部楼层
wangzugong 发表于 2020-12-18 11:29
其实这里研究的不是AVR, 研究的是系统和软件BUG问题。 通过这样一个例子说明什么叫钻研精神。 ...

有道理,另外芯片不怕老,最重要是能解决问题

出0入0汤圆

发表于 2020-12-18 17:14:32 | 显示全部楼层
wangzugong 发表于 2020-12-18 11:29
其实这里研究的不是AVR, 研究的是系统和软件BUG问题。 通过这样一个例子说明什么叫钻研精神。 ...

找到bug真的不容易,牛!

出0入147汤圆

发表于 2020-12-18 17:55:27 | 显示全部楼层
这个问题的本质是远程升级时,没有对通过网络传输的数据做二次封包处理,TCP/IP协议是分包传输,出现沾包是很正常的情况,而AVRUBD是基于串口传输实现的XMODEM协议,这种不考虑通信协议适用的物理层而照搬,出现问题是必然的。

出0入228汤圆

发表于 2020-12-19 00:06:37 来自手机 | 显示全部楼层
一直想着用手机加附件来搞iap.
这个附件可以是普通usb串口。
这样灵活性大大提高。

出10入113汤圆

发表于 2020-12-19 09:11:13 | 显示全部楼层
wxws 发表于 2020-12-19 00:06
一直想着用手机加附件来搞iap.
这个附件可以是普通usb串口。
这样灵活性大大提高。 ...

顶 安卓应该比较好搞。

出0入0汤圆

发表于 2020-12-29 08:52:35 | 显示全部楼层
wangzugong 发表于 2020-10-30 17:13
5.2版本的在哪里呀? 麻烦你给发个链接,谢谢!

https://sourceforge.net/projects/avrub/
找了一下,这个应该是作者上传的。
-----------------------------------------------
下面顺便上传了三个文件

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2020-12-29 08:54:13 | 显示全部楼层
其实这个上位机软件,还不错,stm32代码对应着改改,也可以用这个来更新软件的。实现像avr一样下载。

出0入0汤圆

 楼主| 发表于 2021-1-5 15:51:16 | 显示全部楼层
Forever 发表于 2020-12-29 08:52
https://sourceforge.net/projects/avrub/
找了一下,这个应该是作者上传的。
------------------------- ...

非常谢谢!之前一致没找到。

出0入0汤圆

 楼主| 发表于 2021-1-5 15:53:52 | 显示全部楼层
本帖最后由 wangzugong 于 2021-1-5 15:57 编辑
dreampet 发表于 2020-12-18 17:55
这个问题的本质是远程升级时,没有对通过网络传输的数据做二次封包处理,TCP/IP协议是分包传输,出现沾包是 ...


你能说明应该怎么做吗?给出一些建议也行啊。别说这样空洞的话好吗?
再者,即使是只用串口,也有可能出现数据出现错误的可能,这个BUG对仅使用串口者同样有用。

出0入147汤圆

发表于 2021-1-5 16:01:14 | 显示全部楼层
wxws 发表于 2020-12-19 00:06
一直想着用手机加附件来搞iap.
这个附件可以是普通usb串口。
这样灵活性大大提高。 ...

USB串口的兼容性不好, 我们的最佳实践是采用蓝牙透传模块,主要工作就是移植一下XMODEM协议到Android上,界面逻辑跟上位机一样的。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 15:51

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表