Arduino bootloader 的烧写

来自Jack's Lab
跳转到: 导航, 搜索

目录

1 硬件编程器

1.1 Arduino

如果有一个 Arduino 板,则可将其作为一个编程器,去烧写一个没有 bootloader 的 ATmega 单片机


Arduino-icsp.JPG


arduino 板上 ICSP 针脚皆定义为:

Arduino-icsp-pin.jpg


完整的参考电路图在: 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

Mega ISP




1.2 USBasp

开源的 AVR programmer,包括硬件图和 firmware

USBASP 官方首页

taobao 上卖的最火的 avr/c51 编程器(15元左右),基本都是这个实现

命令行方式使用的话,可以直接使用 avrdude 这个工具

GUI 方式可使用 eXtreme Burner - AVR 或者 Khazama AVR Programmer

国内也有小工作室做了一个 windows 的程序 progisp


设备名称

USBasp 的固件,用软件的方式将其实现成了一个 USB device。Window 下的驱动用的是 Libusb,因此其插入 windows xp 时,系统将其识别为:


Prog-usbasp-dev.jpg


引脚连线

所有类 USBasp 的 AVR 编程器,出来的接口都是如下(USB 的四条触点朝上):


Usbasp-pin.jpg


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

准备一个 USB 转串口板,此处我们使用一个 FT232RL USB 转串口板,此物某宝有售:FT232RL USB 转串口板


Ft232.jpg


日本一哥们的实现如右:[1] (需 FuckGFW)他给 avrdude 添加了一些 patch 使其能使用 FT232RL 的 bitbang 模式来实现烧写

鉴于 FuckGFW 的麻烦,将其配套的可执行文件和源码包放在:文件: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 引出:


Duemilanove-ft232r-con.jpg


Duemilanove-ft232r-isp-pin.JPG


则可将其直接连到 ICSP 的针脚上,直接用 Duemilanove 的 FT232RL 烧写 bootloader:


  • 4 (RI) --> RESET (RST)
  • 3 (DCD) --> MOSI (11)
  • 2 (DSR) --> SCK (13)
  • 1 (CTS) --> MISO (12)


Duemilanove-ft232r-isp.JPG


烧写步骤

  • 将 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

./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

其他命令参考:D:\arduino-1.0.1\hardware\arduino\boards.txt

所有的bootloader 位于:D:\arduino-1.0.1\hardware\arduino\bootloaders\



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 其对应为:

M328p-bootsz.jpg


表中的 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














个人工具
名字空间

变换
操作
导航
工具箱