ArduinoにATMega168P
Arduino Duemilanoveが最初に発売された時は、MCUはATMega168が使われていました。その後ATMega328Pになり、UNOへとモデルチェンジしています。しかし現在MCU単体で発売されているものはATMega168Pであり、それをそのままArduinoに装着してもIDEでブートローダーを書き込むことができません。ATMega168と168Pとでシグネチャーが違うためです。
ということで、168Pに対応できるようにしてみました。せっかくなのでoptibootです。
以下、Arduino IDEはVer1.0以上を想定しています。
ブートローダーの作成
まずはATMega168P対応のoptibootのブートローダーを作成します。このためにはいくつかのファイルを書き換える必要があります。
まずはブートローダーのソースであるoptiboot.c。ここにはATMega168P用の定義が無いので付け加えます。赤文字の部分を追加します。
…
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__)
#define RAMSTART (0x100)
#define NRWWSTART (0x3800)
…
そのファイルからインクルードされているpin_defs.hにも同様に定義を加えます。
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove */
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
#define LED PINB5
…
それをコンパイルするためのMakefileにATMega168P用の定義を追加します。
「__AVR_ATmega168P__」を定義させる方法がわからなかったので、強引に-Dパラメーターで定義させてしましました。
atmega168: TARGET = atmega168
atmega168: MCU_TARGET = atmega168
atmega168: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
atmega168: AVR_FREQ = 16000000L
atmega168: $(PROGRAM)_atmega168.hex
atmega168: $(PROGRAM)_atmega168.lst
atmega168_isp: atmega168
atmega168_isp: TARGET = atmega168
# 2.7V brownout
atmega168_isp: HFUSE = DD
# Low power xtal (16MHz) 16KCK/14CK+65ms
atmega168_isp: LFUSE = FF
# 512 byte boot
atmega168_isp: EFUSE = 04
atmega168_isp: isp
atmega168p: TARGET = atmega168p
atmega168p: MCU_TARGET = atmega168p
atmega168p: CFLAGS += '-D__AVR_ATmega168P__=1' '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
atmega168p: AVR_FREQ = 16000000L
atmega168p: $(PROGRAM)_atmega168p.hex
atmega168p: $(PROGRAM)_atmega168p.lst
atmega168p_isp: atmega168p
atmega168p_isp: TARGET = atmega168p
# 2.7V brownout
atmega168p_isp: HFUSE = DD
# Low power xtal (16MHz) 16KCK/14CK+65ms
atmega168p_isp: LFUSE = FF
# 512 byte boot
atmega168p_isp: EFUSE = 04
atmega168p_isp: isp
そしてコンパイルします。
$PATH=$PATH:/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin/ $cd /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/bootloaders/optiboot/ $make atmega168p avr-gcc -g -Wall -Os -fno-inline-small-functions -fno-split-wide-types -mshort-calls -mmcu=atmega168p -DF_CPU=16000000L '-D__AVR_ATmega168P__=1' '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' -c -o optiboot.o optiboot.c avr-gcc -g -Wall -Os -fno-inline-small-functions -fno-split-wide-types -mshort-calls -mmcu=atmega168p -DF_CPU=16000000L '-D__AVR_ATmega168P__=1' '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' -Wl,--section-start=.text=0x3e00 -Wl,--section-start=.version=0x3ffe -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib -o optiboot_atmega168p.elf optiboot.o avr-size optiboot_atmega168p.elf text data bss dec hex filename 500 0 0 500 1f4 optiboot_atmega168p.elf avr-objcopy -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex optiboot_atmega168p.elf optiboot_atmega168p.hex avr-objdump -h -S optiboot_atmega168p.elf > optiboot_atmega168p.lst rm optiboot_atmega168p.elf optiboot.o $
これでブートローダーができあがりました。
定義の追加
次にboard.txtにATMega168P optibootの定義を追加します。
…
##############################################################
diecimila_optiboot.name=Arduino Diecimila or Duemilanove w/ ATmega168P optiboot
diecimila_optiboot.upload.protocol=arduino
diecimila_optiboot.upload.maximum_size=15872
diecimila_optiboot.upload.speed=115200
diecimila_optiboot.bootloader.low_fuses=0xff
diecimila_optiboot.bootloader.high_fuses=0xdd
diecimila_optiboot.bootloader.extended_fuses=0x00
diecimila_optiboot.bootloader.path=optiboot
diecimila_optiboot.bootloader.file=optiboot_atmega168p.hex
diecimila_optiboot.bootloader.unlock_bits=0x3F
diecimila_optiboot.bootloader.lock_bits=0x0F
diecimila_optiboot.build.mcu=atmega168p
diecimila_optiboot.build.f_cpu=16000000L
diecimila_optiboot.build.core=arduino
diecimila_optiboot.build.variant=standard
##############################################################
…
これで、Arduino IDEからブートローダーの書き込みにも対応できるようになりました。
ATMega168/168Pは当然328Pよりもプログラムエリアが小さいので、optibootの恩恵は大きいです。