Arduino bootloader 的烧写
(→烧写软件) |
|||
第366行: | 第366行: | ||
avrdude 探测编程器是直接枚举所有的 usb 设备,用的是 libusb 库,如果机器 usb 口插有多个编程器,可在 <port> 加数字来区分 | avrdude 探测编程器是直接枚举所有的 usb 设备,用的是 libusb 库,如果机器 usb 口插有多个编程器,可在 <port> 加数字来区分 | ||
+ | <br><br> | ||
+ | === Leonardo 烧写 === | ||
+ | |||
+ | <source lang=bash> | ||
+ | D:\arduino-1.0.1\hardware\tools\Avrdude-serjtag> ./avrdude -p m32u4 -c ft232r -P ft0 -B 115200 -Uefuse:w:0xcb:m -Uhfuse:w:0xd8:m -Ulfuse:w:0xff:m | ||
+ | D:\arduino-1.0.1\hardware\tools\Avrdude-serjtag> ./avrdude -p m32u4 -c ft232r -P ft0 -B 115200 -e -u -Ulock:w:0x3f:m -U flash:w:Caterina-Leonardo.hex -Ulock:w:0x2f:m | ||
+ | </source> | ||
== AVR Fuse&Lock (熔丝位) == | == AVR Fuse&Lock (熔丝位) == |
2015年2月7日 (六) 20:25的版本
目录 |
1 硬件编程器
1.1 Arduino
如果有一个 Arduino 板,则可将其作为一个编程器,去烧写一个没有 bootloader 的 ATmega 单片机
arduino 板上 ICSP 针脚皆定义为:
完整的参考电路图在: Arduino Duemilanove
参考接线方式:
Arduino 的 ICSP 脚: 1 ---> MISO 2 ---> 5V 3 ---> SCK 4 ---> MOSI 5 ---> 不用 6 ---> GND Arduino 的数字 10 口接目标片 RESET
Arduino ICSP 的 1, 2, 3, 4, 6 分别接待烧写目标片的 MISO, 5V, SCK, MOSI, GND
连线时,Arduino 的数字 10 口接目标片 RESET
Arduino 的数字 11 口就是 MOSI,数字 12 口就是 MISO,数字 13 口就是 SCK;因此也可以用数字口 10, 11, 12, 13 再加上 5V 和 GND
为了方便,可自由选用 ICSP 的公针脚还是 Arduino 标准母口
烧写步骤:
- 先把手头的 Arduino 板变成一个 avr 编程器,程序位于:[File] -> [Examples] -> [ArduinoISP],编译后将其 uploader 到 Arduino 板上。ArduinoISP 这个 example 实际是 Arduino 官方实现的一个兼容 STK500v1 协议的编程器固件,其使用 Arduino 的数字口 10, 11, 12, 13 与待烧写片作数据通信
- 连接 ICSP(除 RESET)和要烧写 bootloader 的核心板,Arduino 的数字口 10 接 RESET,5 根线不要接反了,尤其是 5V 和 GND,接好后再仔细检查一遍
- 对于 Uno 板,要在 reset 和 GND 间加一个 10uF 的电容以关闭 auto reset,这个可以参考:Mega ISP
- 这个时候 Arduino 板变身了,成了一个独立的 avr 编程器,下面就可以直接找到你的目标板要用的 bootloader hex 文件,直接使用 avrdude 烧写 bootloader;亦可在图形界面操作,更直观:
- 选择要烧写板子的型号 [Tools] -> [Board],比如我们搭了一个 Arduino UNO 的核心板,就选择 Arduino Uno,这个实际是去选要用的 bootloader 二进制文件,所有的 Arduino bootloader 都位于: arudion-1.0.1\hardware\arduino\bootloaders 下
- 选择编程器类型 [Tools] -> [Programmer] -> [Arduino as ISP]
- 执行烧写 [Tools] -> [Burn Bootloader]
实际执行的命令序列为:
$ avrdude -CD /path/to/arduino/hardware/tools/avr/etc/avrdude.conf -p atmega328p -c stk500v1 \ -P \\.\COM25 -b 19200 -e -Ulock:w:0x3F:m -Uefuse:w:0x05:m -Uhfuse:w:0xda:m -Ulfuse:w:0xff:m $ avrdude -CD /path/to/arduino/hardware/tools/avr/etc/avrdude.conf -p atmega328p -c stk500v1 \ -P \\.\COM25 -b 19200 -e -U flash:w:ATmegaBOOT_168_atmega328.hex
更多参考:
Disabling Auto Reset On Serial Connection
Using an Arduino as an AVR ISP
1.2 USBasp
开源的 AVR programmer,包括硬件图和 firmware
taobao 上卖的最火的 avr/c51 编程器(15元左右),基本都是这个实现
命令行方式使用的话,可以直接使用 avrdude 这个工具
GUI 方式可使用 eXtreme Burner - AVR 或者 Khazama AVR Programmer
国内也有小工作室做了一个 windows 的程序 progisp
设备名称
USBasp 的固件,用软件的方式将其实现成了一个 USB device。Window 下的驱动用的是 Libusb,因此其插入 windows xp 时,系统将其识别为:
引脚连线
所有类 USBasp 的 AVR 编程器,出来的接口都是如下(USB 的四条触点朝上):
MISO,MOSI,SCK,RESET 连 ATmega 对应的引脚即可,VCC_OUT 和 GND 可用于 ATmega 的供电
烧写步骤
可以使用 Arduino 的图形环境,执行烧写命令:
- 选择要烧写板子的型号 [Tools] -> [Board],比如我们用 328p 搭了一个最小系统,就可以选择 Arduino Uno,这个实际是去选择 bootloader 二进制文件,所有的 Arduino bootloader 都位于: arudion-1.0.1\hardware\arduino\bootloaders 下
- 选择编程器类型 [Tools] -> [Programmer] -> [USBasp]
- 执行烧写 [Tools] -> [Burn Bootloader]
命令行方式烧写步骤如下:
对于一个 atmega328p 的芯片,使用 USBasp 编程器其在 Windows 下的烧写命令为:
# 将 328p 的熔丝位设置为 hfuse = 0xda, lfuse = 0xff, efuse = 0x05 # 并将 bootloader 区解锁 lock = 0x3f $ avrdude -p m328p -C /d/arduino-1.0.1/hardware/tools/avr/etc/avrdude.conf -c usbasp -P usbasp0 -Uhfuse:w:0xda:m -Ulfuse:w:0xff:m -Uefuse:w:0x05:m -Ulock:w:0x3F:m # 写入 bootloader,同时 bootloader 区加锁 $ avrdude -p m328p -C /d/arduino-1.0.1/hardware/tools/avr/etc/avrdude.conf -c usbasp -P usbasp0 -e -U flash:w:ATmegaBOOT.hex -Ulock:w:0x0F:m
Linux 下的命令类似:
# 将 328p 的熔丝位设置为 hfuse = 0xda, lfuse = 0xff, efuse = 0x05 # 并将 bootloader 区解锁 lock = 0x3f $ avrdude -p m328p -C /etc/avrdude.conf -c usbasp -P usbasp -Uefuse:w:0x05:m -Uhfuse:w:0xda:m -Ulfuse:w:0xff:m -Ulock:w:0x3F:m # 写入 bootloader,同时 bootloader 区加锁 $ avrdude -p m328p -C /etc/avrdude.conf -c usbasp -P usbasp -e -U flash:w:ATmegaBOOT.hex -Ulock:w:0x0F:m
1.3 FTDI FT232RL
可以用一个 FT232RL USB 转串口板,来烧写 avr 系列单片机
日本一哥们的实现如右:[1] (需翻墙)他给 avrdude 添加了一些 patch 使其能使用 FT232RL 的 bitbang 模式来实现烧写
鉴于翻墙的麻烦,将其配套的可执行文件和源码包放在:文件:Avrdude-serjtag.rar (目前只支持 win32 平台)
引脚连线
- RI ---> RESET
- DSR ---> SCK
- CTS ---> MISO
- DCD ---> MOSI
特别地,Arduino Duemilanove 这个老版本的板子,在 FT232RL 的片子边上预留了一个 4 针的接口(原理图中标为 X3),4 个针脚分别编号为 1, 2, 3, 4,对应将 FT232RL 的 CTS, DSR, DCD, RI 引出:
则可将其直接连到 ICSP 的针脚上,直接用 Duemilanove 的 FT232RL 烧写 bootloader:
- 4 (RI) --> RESET (RST)
- 3 (DCD) --> MOSI (11)
- 2 (DSR) --> SCK (13)
- 1 (CTS) --> MISO (12)
烧写步骤
- 将 FT232R 小板上的 6 针对应连上目标板
- USB 接入 PC
- avrdude 命令:
$ cd /path/to/avrdude-sertag $ avrdude -v avrdude.exe: Version 5.3.1, compiled on Jun 20 2007 at 00:30:58 ... ... $ avrdude -p m328p -c ft232r -P ft0 -B 115200 avrdude: BitBang OK avrdude: pin assign miso 3 sck 5 mosi 6 reset 7 avrdude: drain OK ft245r: bitclk 76800 -> ft baud 38400 avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.00s avrdude: Device signature = 0x1e950f avrdude: safemode: Fuses OK avrdude.exe done. Thank you. 如果连接失败,avrdude 会打印出: avrdude: ft245r_program_enable: failed avrdude: initialization failed, rc=-1 # 进入命令行模式 $ avrdude -p m328p -c ft232r -P ft0 -B 115200 -t avrdude: BitBang OK avrdude: pin assign miso 3 sck 5 mosi 6 reset 7 avrdude: drain OK ft245r: bitclk 76800 -> ft baud 38400 avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.00s avrdude: Device signature = 0x1e950f avrdude> # dump 出待烧写单片机当前熔丝位 avrdude> d hfuse >>> d hfuse 0000 d9 avrdude> d lfuse >>> d lfuse 0000 62 avrdude> d efuse >>> d efuse 0000 07 avrdude> d lock >>> d lock 0000 3f # help 可列出支持的命令 avrdude> help Valid commands: dump : dump memory : dump <memtype> <addr> <N-Bytes> read : alias for dump write : write memory erase : perform a chip erase sig : display device signature byte part : display the current part infromation send : send a raw command : send <b1> <b2> <b3> <b4> ...... # 将 328p 的熔丝位设置为 hfuse = 0xda, lfuse = 0xff, efuse = 0x05 $ avrdude -p m328p -c ft232r -P ft0 -B 115200 -Uhfuse:w:0xda:m -Ulfuse:w:0xff:m -Uefuse:w:0x05:m # 先将 bootloader 区解锁 lock = 0x3f,写入 bootloader 文件,再将 bootloader 区加锁 lock = 0x0f $ ./avrdude -p m328p -c ft232r -Pft0 -b 115200 -e -u -Ulock:w:0x3f:m -U flash:w:ATmegaBOOT_168_atmega328.hex -Ulock:w:0x0F:m avrdude.exe: BitBang OK avrdude.exe: pin assign miso 3 sck 5 mosi 6 reset 7 avrdude.exe: drain OK ft245r: bitclk 230400 -> ft baud 115200 avrdude.exe: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.02s avrdude.exe: Device signature = 0x1e950f avrdude.exe: erasing chip ft245r: bitclk 230400 -> ft baud 115200 avrdude.exe: reading input file "0x3f" avrdude.exe: writing lock (1 bytes): Writing | ################################################## | 100% 0.02s avrdude.exe: 1 bytes of lock written avrdude.exe: verifying lock memory against 0x3f: avrdude.exe: load data lock data from input file 0x3f: avrdude.exe: input file 0x3f contains 1 bytes avrdude.exe: reading on-chip lock data: Reading | ################################################## | 100% 0.03s avrdude.exe: verifying ... avrdude.exe: 1 bytes of lock verified avrdude.exe: reading input file "ATmegaBOOT_168_atmega328.hex" avrdude.exe: input file ATmegaBOOT_168_atmega328.hex auto detected as Intel Hex avrdude.exe: writing flash (32670 bytes): Writing | ################################################## | 100% 17.27s avrdude.exe: 32670 bytes of flash written avrdude.exe: verifying flash memory against ATmegaBOOT_168_atmega328.hex: avrdude.exe: load data flash data from input file ATmegaBOOT_168_atmega328.hex: avrdude.exe: input file ATmegaBOOT_168_atmega328.hex auto detected as Intel Hex avrdude.exe: input file ATmegaBOOT_168_atmega328.hex contains 32670 bytes avrdude.exe: reading on-chip flash data: Reading | ################################################## | 100% 7.97s avrdude.exe: verifying ... avrdude.exe: 32670 bytes of flash verified avrdude.exe: reading input file "0x0F" avrdude.exe: writing lock (1 bytes): Writing | ################################################## | 100% 0.05s avrdude.exe: 1 bytes of lock written avrdude.exe: verifying lock memory against 0x0F: avrdude.exe: load data lock data from input file 0x0F: avrdude.exe: input file 0x0F contains 1 bytes avrdude.exe: reading on-chip lock data: Reading | ################################################## | 100% 0.02s avrdude.exe: verifying ... avrdude.exe: 1 bytes of lock verified avrdude.exe done. Thank you.
至此即可完成 bootloader 的烧写
avrdude 官方从 5.11 起开始支持 bitbang 模式,试了一下,烧写的速度奇慢,不建议使用
2 烧写软件
2.1 avrdude
优秀的 open source 跨平台下载工具。 配合编程器使用
avrdude -p mcu_type -B bitclock(optional) -c programmer_type -P <port> -U 输出文件及选项
avrdude 探测编程器是直接枚举所有的 usb 设备,用的是 libusb 库,如果机器 usb 口插有多个编程器,可在 <port> 加数字来区分
2.2 Leonardo 烧写
D:\arduino-1.0.1\hardware\tools\Avrdude-serjtag> ./avrdude -p m32u4 -c ft232r -P ft0 -B 115200 -Uefuse:w:0xcb:m -Uhfuse:w:0xd8:m -Ulfuse:w:0xff:m D:\arduino-1.0.1\hardware\tools\Avrdude-serjtag> ./avrdude -p m32u4 -c ft232r -P ft0 -B 115200 -e -u -Ulock:w:0x3f:m -U flash:w:Caterina-Leonardo.hex -Ulock:w:0x2f:m
3 AVR Fuse&Lock (熔丝位)
AVR Fuse&Lock (熔丝位) 可看作可编程控制的跳线,用于配置单片机的基础状态
共有 4 个字节,分别为:hfuse, lfuse, efuse, lock
ATMEGA 的各型号 MCU 这些位的定义都不同,像 ATMEGA 168 和 ATMEGA328p 也不同,具体可参考手册页
以下只讨论 328p 的情形
3.1 hfuse,熔丝高位
HFuse Bit | [7] | [6] | [5] | [4] | [3] | [2] | [1] | [0] |
---|---|---|---|---|---|---|---|---|
Bit Name | RSTDISBL | DWEN | SPIEN | WDTON | EESAVE | BOOTSZ1 | BOOTSZ0 | BOOTRST |
Description | External Reset Disable | Debug Wire Enable | SPI programming Enable | Watch Dog Timer always ON | EEPROM memory is preserved through the chip erase | Select bootloader area size | Select bootloader area size | Select Reset Vector |
Default Value | 1 (external reset enable) | 1 (debug wire disable) | 0 (SPI enable) | 1 (WDT always off) | 1 (EEPROM not reserved) | 0 | 0 | 1 (Reset Vector = 0x0) |
AVR 系列寄存器的值,一般 0 为真
对于 BOOTSZ1 BOOTSZ0 其对应为:
表中的 Boot Reset Address (Start Boot Loader Section) 要将 hfuse 的 BOOTRST 置为 0 时,才有效
!特别注意:表中的地址都是为字为单位,换算成常用的字节单位要乘以 2
可见:BOOTSZ 为 00 时,boot area size = 4KB (2048 words,一个 words 是 16bit,两个字节) ; 01 时为 2KB; 10 时为 1KB; 11 时为 512B
BOOTSZ 为 01 时,boot area 地址为 0x3C00 ~ 0x3FFF (字为单位),则以字节为单位的地址范围为:0x7800 ~ 0x7FFF
Arduino 使用 ATmega 328p 一般将 hfuse 设置为 0xDA,对应二进制值为 1101 1010,低三位与默认值不同,指示 boot area size 为 2KB,地址范围 0x7800 ~ 0x7FFF,Reset Vector = 0x7800
0x7800 这个值,也与 Arduino 使用的 bootloader 文件 ATmegaBOOT_168_atmega328.hex 的起始地址一致
3.2 lfuse,熔丝低位
LFuse Bit | [7] | [6] | [5] | [4] | [3] | [2] | [1] | [0] |
---|---|---|---|---|---|---|---|---|
Bit Name | CKDIV8 | CKOUT | SUT1 | SUT0 | CKSEL3 | CKSEL2 | CKSEL1 | CKSEL0 |
Description | Divide clock by 8 | Clock Output | Select start-Up Time | Select start-Up Time | Seleck Clock source | Seleck Clock source | Seleck Clock source | Seleck Clock source |
Default Value | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 0 |
Arduino 使用 ATmega 328p 一般将 lfuse 设置为 0xFF,对应二进制值为 1111 1111
3.3 efuse,扩展熔丝位
EFuse Bit | [7] | [6] | [5] | [4] | [3] | [2] | [1] | [0] |
---|---|---|---|---|---|---|---|---|
Bit Name | NA | NA | NA | NA | NA | BODLEVEL2 | BODLEVEL1 | BODLEVEL0 |
Description | NA | NA | NA | NA | NA | Brown-out Detector trigger level | Brown-out Detector trigger level | Brown-out Detector trigger level |
Default Value | 1 | 1 | 1 | 1 | 1 | 1 (false) | 1 (false) | 1 (false) |
Arduino 使用 ATmega 328p 一般将 efuse 设置为 0x05,对应二进制值为 0000 0101
3.4 lock,加密位
lock Bit | [7] | [6] | [5] | [4] | [3] | [2] | [1] | [0] |
---|---|---|---|---|---|---|---|---|
Bit Name | NA | NA | BLB12 | BLB11 | BLB02 | BLB01 | LB2 | LB1 |
Description | NA | NA | Boot Lock Bit | Boot Lock Bit | Boot Lock Bit | Boot Lock Bit | Lock Bit | Lock Bit |
Default Value | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
BLB12/BLB11, BLB02/BLB01 针对的是 Application Section 和 Bootloader Section 的访问控制。其中 BLB12/BLB11 用于从 Application Section 到 Bootloader Section 的访问控制。BLB02/BLB01 则用于从 Bootloader Section 到 Application Section 的访问控制
BLB12 BLB11 (Application 到 Bootloader):
11 --> 无限制 10 --> 不可写 Bootloader Section 01 --> 不可读 Bootloader Section 00 --> 不可写不可读 Bootloader Section
BLB02 BLB01 (Bootloader 到 Application):
11 --> 无限制 10 --> 不可写 Application Section 01 --> 不可读 Application Section 00 --> 不可写不可读 Application Section
!对于 Lock Bit 位 LB2 LB1,应引起高度重视,此二位用于对 Flash, EEPROM, Fuse (hfuse, lfuse, efuse) 和 Boot Lock Bit 的访问控制
LB2 LB1:
11 --> 无限制 10 --> 禁止对 Flash 和 EEPROM 通过并口和串口编程;Fuse 也被锁(不可读不可写) 00 --> 禁止对 Flash 和 EEPROM 通过并口和串口编程及验证;Fuse 和 Boot Lock Bit 也被锁(不可读不可写)
由此可见,对 LB2 LB1 的操作应放在最后,一旦操作提交,将不可更改
Arduino 使用 ATmega 328p,bootloader area 不可访问时 lfuse 设置为 0x0F,对应二进制值为 0000 1111
bootloader area 可读可写时 lfuse 设置为 0x3F,对应二进制值为 0011 1111