使用引导加载程序上传代码时会发生什么?


13

当我使用Optiboot引导加载程序将新草图上传到Arduino Uno时,真正发生了什么?

  • 什么被发送到Arduino?
  • 它如何反应?
  • “不同步”是什么意思?
  • 什么是“同步”?

注意:这旨在作为“参考问题”


非常有趣的帖子!只是一个问题。您正在使用哪种软件来跟踪串行通信(图像)?
julio 18/09/27

它是一个逻辑分析仪的输出,例如Saleae Logic8。saleae.com非常好的小分析仪。以前是24 MHz的采样率,价格约为$ 125,150。当前捕获速度为100和500 MHz。> SPI,I2C等>大多数数字通信使用特定的协议来指定信息的传输方式。Logic软件具有协议分析仪,可以自动解码SPI,I2C,串行,1-Wire,CAN,UNI / O,I2S / PCM,MP模式,Manchester,Modbus,DMX-512,并行,JTAG,LIN,Atmel SWI, MDIO,SWD,LCD HD44780,BiSS C,HDLC,HDMI CEC,PS / 2,USB 1.1,Midi –或创建自己的
CrossRoads

Answers:


21

当您重置运行Optiboot加载程序的Uno时,引导加载程序首先将13针闪烁3次。

引脚13闪烁

顶线(灰色)发送 Arduino,中线(橙色)发送 Arduino。

发生这种情况时,avrdude计算机上运行的程序正在向设备发送查询:

STK_GET_SYNC / CRC_EOP  (0x30/0x20)

Arduino没有注意到第一个“获取同步”,因为它正在忙于闪烁引脚13。完成后,它会注意到“获取同步”(它将由串行硬件缓冲)并回复:

STK_INSYNC / STK_OK (0x14/0x10)

似乎avrdude有点急躁,并已超时,因为它再次尝试使用“获取同步”查询。这次Optiboot立即响应。


下图描述了其余的上传。示例产生了上传股票“ Blink”程序。

Optiboot上传过程

(单击上面的图像查看大图)


这些步骤是:

  • 查询:获取同步?回复:正在同步。
  • 查询:获取参数?(主要版本)回复:版本4。
  • 查询:获取参数?(次要版本)回复:版本4。
  • 设置设备参数。以下设备参数发送到芯片:

    0x42  // STK_SET_DEVICE
    0x86  // device code
    0x00  // revision
    0x00  // progtype: “0” – Both Parallel/High-voltage and Serial mode
    0x01  // parmode: “1” – Full parallel interface
    0x01  // polling: “1” – Polling may be used
    0x01  // selftimed: “1” – Self timed
    0x01  // lockbytes: Number of Lock bytes.
    0x03  // fusebytes: Number of Fuse bytes
    0xFF  // flashpollval1
    0xFF  // flashpollval2
    0xFF  // eeprompollval1
    0xFF  // eeprompollval2
    0x00  // pagesizehigh
    0x80  // pagesizelow
    0x04  // eepromsizehigh
    0x00  // eepromsizelow
    0x00  // flashsize4
    0x00  // flashsize3
    0x80  // flashsize2
    0x00  // flashsize1
    0x20  // Sync_CRC_EOP

    Optiboot将忽略所有这些内容,并通过“同步中/确定”进行答复。:)

  • 设置扩展设备参数:

    0x45  // STK_SET_DEVICE_EXT
    0x05  // commandsize: how many bytes follow
    0x04  // eeprompagesize: EEPROM page size in bytes.
    0xD7  // signalpagel: 
    0xC2  // signalbs2: 
    0x00  // ResetDisable: Defines whether a part has RSTDSBL Fuse 
    0x20  // Sync_CRC_EOP

    Optiboot也将忽略所有这些内容,并通过“同步中/确定”进行答复。

  • 进入程序模式。回复:在同步/确定中。

  • 阅读签名。Optiboot答复时0x1E 0x95 0x0F 并未实际读取签名

  • 写保险丝(四次)。Optiboot 不写保险丝,而只是在同步/正常情况下回复。

  • 加载地址(最初为0x0000)。地址以字为单位(即,一个字是两个字节)。这设置了下一页数据将写入的地址。

  • 程序页(最多发送128个字节)。Optiboot立即回复“同步中”。然后在实际编程页面时会有大约4 ms的暂停。然后它回答“确定”。

  • 加载地址(现在为0x0040)。这是十进制的地址64,即。从程序存储器的开始起128个字节。

  • 写入另一页。此顺序一直持续到写入所有页面为止。

  • 加载地址(返回0x0000)。这是为了验证写入。

  • 读取页(最多读取128个字节)。这是用于验证。请注意,即使验证失败,不良数据也已经被写入芯片。

  • 退出编程模式。


“不同步”是什么意思?

从上面可以看到,在编程​​过程的每一步中,Arduino都将以“同步中”(0x14)进行响应,可能还会跟一些数据,然后是“ OK”(0x10)。

如果不是“同步”,则表示avrdude没有得到“同步”响应。可能的原因可能是:

  • 使用错误的波特率
  • 在IDE中选择了错误的串行端口
  • 在IDE中选择了错误的板类型
  • 没有安装引导程序
  • 安装了错误的引导程序
  • 板未配置为使用引导加载程序(在保险丝中)
  • 一些设备插入Arduino的D0和D1引脚,干扰了串行通信
  • USB接口芯片(ATmega16U2)无法正常工作
  • 电路板时钟错误
  • Atmega328P上的保险丝设置错误(例如,“时钟除以8”)
  • 板/芯片损坏
  • USB电缆故障(某些USB电缆仅提供电源,而不能用于数据传输,例如,用于USB风扇的廉价电缆)

什么是“同步”?

如上所述,响应“同步”表示Arduino(引导加载程序)与上传程序同步。


使用什么协议?

该协议是Atmel记录的STK500协议。请参阅下面的参考。


参考文献

注意:Optiboot中未使用STK500第2版,但如果您使用的是Mega2560之类的板卡,则包含在STK500版本2中以供参考。


STK500常数

/* STK500 constants list, from AVRDUDE */
#define STK_OK              0x10
#define STK_FAILED          0x11  // Not used
#define STK_UNKNOWN         0x12  // Not used
#define STK_NODEVICE        0x13  // Not used
#define STK_INSYNC          0x14  // ' '
#define STK_NOSYNC          0x15  // Not used
#define ADC_CHANNEL_ERROR   0x16  // Not used
#define ADC_MEASURE_OK      0x17  // Not used
#define PWM_CHANNEL_ERROR   0x18  // Not used
#define PWM_ADJUST_OK       0x19  // Not used
#define CRC_EOP             0x20  // 'SPACE'
#define STK_GET_SYNC        0x30  // '0'
#define STK_GET_SIGN_ON     0x31  // '1'
#define STK_SET_PARAMETER   0x40  // '@'
#define STK_GET_PARAMETER   0x41  // 'A'
#define STK_SET_DEVICE      0x42  // 'B'
#define STK_SET_DEVICE_EXT  0x45  // 'E'
#define STK_ENTER_PROGMODE  0x50  // 'P'
#define STK_LEAVE_PROGMODE  0x51  // 'Q'
#define STK_CHIP_ERASE      0x52  // 'R'
#define STK_CHECK_AUTOINC   0x53  // 'S'
#define STK_LOAD_ADDRESS    0x55  // 'U'
#define STK_UNIVERSAL       0x56  // 'V'
#define STK_PROG_FLASH      0x60  // '`'
#define STK_PROG_DATA       0x61  // 'a'
#define STK_PROG_FUSE       0x62  // 'b'
#define STK_PROG_LOCK       0x63  // 'c'
#define STK_PROG_PAGE       0x64  // 'd'
#define STK_PROG_FUSE_EXT   0x65  // 'e'
#define STK_READ_FLASH      0x70  // 'p'
#define STK_READ_DATA       0x71  // 'q'
#define STK_READ_FUSE       0x72  // 'r'
#define STK_READ_LOCK       0x73  // 's'
#define STK_READ_PAGE       0x74  // 't'
#define STK_READ_SIGN       0x75  // 'u'
#define STK_READ_OSCCAL     0x76  // 'v'
#define STK_READ_FUSE_EXT   0x77  // 'w'
#define STK_READ_OSCCAL_EXT 0x78  // 'x'


1
好点子!我添加了一些参考答案。谢谢。
尼克·加蒙

请注意,此处描述的验证过程专门使用页面读取,这意味着任何支持avrdude的默认验证行为的引导程序都是支持读取闪存内容的引导程序。
克里斯·斯特拉顿

1
如此详尽的描述性程序指令以及对Optiboot / STK500的分析令人赞叹不已。谢谢伟大的尼克·盖蒙(Nick Gammon)!
David Refoua,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.