optiboot anchor.png

optibootはATMEL AVRを搭載したボード用のbootloaderの一つ。

optibootの特徴は,

  • 機能を必要最低限に絞ってサイズを512byte以下と小さくしている。
    これにより,ユーザープログラム領域を大きく出来る。
  • avrdude等との通信のbaudrateが115200と高速。
    Flash ROMへの書き込み時間が短くなる。
    RC発振器を使用しているボードではうまく通信できなくなるので,baudrateを57600にする必要がある。
  • 電源投入時にはすぐにユーザープログラムにジャンプする。
  • ATmega8/ATmega168/ATmega328Pを使用したボードに対応している。
    ATmega168PやATmega328には対応していない。
  • ビルドすることで異なるbaudrateやcpuに対応する。

市販されているArduinoボードには,このoptibootが標準で搭載されているようだ。

Page Top

optibootのバージョン anchor.png

市販されているArduinoボードに書き込まれているoptibootはversion 4.4。
optibootサイトで開発は行われていて,現在はversion8.3になっている。

Page Top

自作ボード用にoptibootをビルドする anchor.png

ATmega168PやATmega328を使った自作ボードがあるので,optibootをビルドして書き込んでみた。

内蔵RC発振器の8MHz仕様のボードと16MHzのX'talを実装したボードがある。内臓RC発振器はその精度が悪い(±10%)ため,optibootのデフォルトのbaudrate 115200ではうまく通信出来ない。
このため,内蔵RC発振器を使うボードでは,baudrateが57600を使うようにする。
また,オンボードLEDやポートの使い方が違うのでそれにも対応する。

Arduino IDEのboards.txtもそのように設定する必要がある。

Page Top

version 4.4 anchor.png

optiboot 4.4はArduino IDEにソースコードがバンドルされているので,それを使用した。
bootloaderにあるoptibootディレクトリに各ボード用のビルド済みoptiboot version4.4とソースコードが用意されている。

optiboot 4.4では,ATmega168P/ATmega328に対応していない。これはArduinoの公式ボードではこれらのCPUは使われていないからと思われる。

ATmega168P/ATmega328とbaudrate 57600に対応するためソースコードを以下のように編集した。

optiboot.cの178行目あたりを編集。

/* set the UART baud rate defaults */
#ifndef BAUD_RATE
#if F_CPU >= 8000000L
#define BAUD_RATE   115200L // Highest rate Avrdude win32 will support
#elsif F_CPU >= 1000000L
#define BAUD_RATE   9600L   // 19200 also supported, but with significant error
#elsif F_CPU >= 128000L
#define BAUD_RATE   4800L   // Good for 128kHz internal RC
#else
#define BAUD_RATE 1200L     // Good even at 32768Hz
#endif
#endif
 ↓
/* set the UART baud rate defaults */
#ifndef BAUD_RATE
#if F_CPU = 8000000L
#define BAUD_RATE   57600L  // for internal RC osc.
#elsif F_CPU > 8000000L
#define BAUD_RATE   115200L // Highest rate Avrdude win32 will support
#elsif F_CPU >= 1000000L
#define BAUD_RATE   9600L   // 19200 also supported, but with significant error
#elsif F_CPU >= 128000L
#define BAUD_RATE   4800L   // Good for 128kHz internal RC
#else
#define BAUD_RATE 1200L     // Good even at 32768Hz
#endif
#endif

optiboot.cの231行目あたりを以下のように編集。

#if defined(__AVR_ATmega168__)
 ↓
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) 

pin_defs.hの1行目を以下のように編集。

#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
 ↓
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)

pin_defs.hの18行目に以下を追加。

#if defined(__AVR_ATmega328__)
// ATmega328のボード(USB IO PCB)のオンボードLEDは,PC5
#define LED_DDR  DDRC
#define LED_PORT PORTC
#define LED_PIN  PINC
#define LED      PINC5

/* Ports for soft UART */
#ifdef SOFT_UART
#define UART_PORT   PORTD
#define UART_PIN    PIND
#define UART_DDR    DDRD
#define UART_TX_BIT 1
#define UART_RX_BIT 0
#endif
#endif

#if defined(__AVR_ATmega168P__)
// ATmega168P(PIRAMP PCB)のオンボードLEDは,PB0
#define LED_DDR  DDRB
#define LED_PORT PORTB
#define LED_PIN  PINB
#define LED      PINB0

/* Ports for soft UART */
#ifdef SOFT_UART
#define UART_PORT   PORTD
#define UART_PIN    PIND
#define UART_DDR    DDRD
#define UART_TX_BIT 1
#define UART_RX_BIT 0
#endif
#endif

Makefileの96行目以降に以下を編集。

ISPFUSES    = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \
              -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
              -e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m \
              -U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m
ISPFLASH    = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \
              -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
              -U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x2f:m
 ↓
ISPFUSES    = avrdude -c $(ISPTOOL) \
              -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
              -e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m \
              -U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m
ISPFLASH    = avrdude -c $(ISPTOOL) \
              -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
              -U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x2f:m

Makefileの115行目以降に以下を編集。

CC         = $(GCCROOT)avr-gcc

# Override is only needed by avr-lib build system.

override CFLAGS        = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS)
override LDFLAGS       = $(LDSECTIONS) -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib

OBJCOPY        = $(GCCROOT)avr-objcopy
OBJDUMP        = $(call fixpath,$(GCCROOT)avr-objdump)

SIZE           = $(GCCROOT)avr-size
 ↓
CC         = avr-gcc

# Override is only needed by avr-lib build system.

override CFLAGS        = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS)
override LDFLAGS       = $(LDSECTIONS) -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib

OBJCOPY        = avr-objcopy
OBJDUMP        = avr-objdump

SIZE           = avr-size

Makefileの420行目以降に以下を追加。

# PIRAMP PCB
piramp8: TARGET = piramp_8mhz
piramp8: MCU_TARGET = atmega168p
piramp8: LDSECTIONS  = -Wl,--section-start=.text=0x3e00 -Wl,--section-start=.version=0x3ffe
piramp8: CFLAGS += '-DLED_START_FLASHES=4' '-DBAUD_RATE=57600'
piramp8: AVR_FREQ = 8000000L
piramp8: $(PROGRAM)_piramp_8mhz.hex
piramp8: $(PROGRAM)_piramp_8mhz.lst
 
piramp8_isp: piramp8
piramp8_isp: TARGET = piramp_8mhz
piramp8_isp: MCU_TARGET = atmega168p
piramp8_isp: LFUSE = C2
piramp8_isp: HFUSE = DF
piramp8_isp: EFUSE = FC
piramp8_isp: isp
 
piramp16: TARGET = piramp_16mhz
piramp16: MCU_TARGET = atmega168p
piramp16: LDSECTIONS  = -Wl,--section-start=.text=0x3e00 -Wl,--section-start=.version=0x3ffe
piramp16: CFLAGS += '-DLED_START_FLASHES=4' '-DBAUD_RATE=115200'
piramp16: AVR_FREQ = 16000000L 
piramp16: $(PROGRAM)_piramp_16mhz.hex
piramp16: $(PROGRAM)_piramp_16mhz.lst
 
piramp16_isp: piramp16
piramp16_isp: TARGET = piramp_16mhz
piramp16_isp: MCU_TARGET = atmega168p
piramp16_isp: LFUSE = CF
piramp16_isp: HFUSE = DF
piramp16_isp: EFUSE = FC
piramp16_isp: isp
 
# USB IO PCB
usbio8: TARGET = usbio_8mhz
usbio8: MCU_TARGET = atmega328
usbio8: LDSECTIONS  = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
usbio8: CFLAGS += '-DLED_START_FLASHES=4' '-DBAUD_RATE=57600'
usbio8: AVR_FREQ = 8000000L 
usbio8: $(PROGRAM)_usbio_8mhz.hex
usbio8: $(PROGRAM)_usbio_8mhz.lst
 
usbio8_isp: usbio8
usbio8_isp: TARGET = usbio_8mhz
usbio8_isp: MCU_TARGET = atmega328
usbio8_isp: LFUSE = C2
usbio8_isp: HFUSE = DE
usbio8_isp: EFUSE = FF
usbio8_isp: isp
 
usbio16: TARGET = usbio_16mhz
usbio16: MCU_TARGET = atmega328
usbio16: LDSECTIONS  = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
usbio16: CFLAGS += '-DLED_START_FLASHES=4' '-DBAUD_RATE=115200'
usbio16: AVR_FREQ = 16000000L 
usbio16: $(PROGRAM)_usbio_16mhz.hex
 
usbio16_isp: usbio16
usbio16_isp: TARGET = usbio_16mhz
usbio16_isp: MCU_TARGET = atmega328
usbio16_isp: LFUSE = CF
usbio16_isp: HFUSE = DE
usbio16_isp: EFUSE = FF
usbio16_isp: isp

ToolchainにWinAVR-20100110を使用した場合,USB IO PCBが使用しているATmega328のデバイスIDがATmega328Pのものになってしまう。
これはWinAVR-20100110(AVR-GCC 4.3.3)がATmega328に対応していないために発生する。

このためWinAVR-20100110(AVR-GCC 4.3.3)でoptibootをビルドするには,WinAVR-20100110(AVR-GCC 4.3.3)のファイルを以下のように編集する。
C:\WinAVR-20100110\avr\include\avr\iom328p.hを編集。

/* Signature */
#define SIGNATURE_0 0x1E
#define SIGNATURE_1 0x95
define SIGNATURE_2 0x0F
#endif
 ↓
/* Signature */
#define SIGNATURE_0 0x1E
#define SIGNATURE_1 0x95
#if defined(__AVR_ATmega328__)
#  define SIGNATURE_2 0x14
#else /* ATmega328P */
#  define SIGNATURE_2 0x0F
#endif

これでうまく動作するoptibootがビルド出来た。
ビルドしてみる。

> make piramp8
> make piramp16
> make usbio8

hexファイルが作成出来ていればOK。

optiboot version4.4をWinAVR-20100110(AVR-GCC 4.3.3)ビルドすると500byte(0x1f4)のサイズになった。
optiboot version4.4をAVR-GCC 7.3.0でビルドすると542byte(0x21e)のサイズになり512byteを超えてしまう。
なのでoptiboot version4.4を使う場合は,WinAVR-20100110(AVR-GCC 4.3.3)でビルドしたものを使用した。

ボードにoptibootを書き込むには,

> make piramp8_isp

のようにすれば書き込める。

Page Top

version 8.3 anchor.png

ソースコードは,こちらのサイトからダウンロードする。

> git clone https://github.com/Optiboot/optiboot.git
> cd optiboot/optiboot/bootloaders/optiboot/

Makefileの137行目から以下のように編集。

override CFLAGS        = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS)
override LDFLAGS       = $(LDSECTIONS) -Wl,--relax -nostartfiles

OBJCOPY        = $(GCCROOT)avr-objcopy
OBJDUMP        = $(call fixpath,$(GCCROOT)avr-objdump)

SIZE           = $(GCCROOT)avr-size
 ↓
override CFLAGS        = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS)
override LDFLAGS       = $(LDSECTIONS) -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib

OBJCOPY        = avr-objcopy
OBJDUMP        = avr-objdump

SIZE           = avr-size

Makefileの666行目に以下を追加した。

include Makefile.yuji

Makefile.yujiを以下の内容で作成した。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# PIRAMP PCB
piramp8: TARGET = piramp_8mhz
piramp8: MCU_TARGET = atmega168p
piramp8: LDSECTIONS  = -Wl,--section-start=.text=0x3e00 -Wl,--section-start=.version=0x3ffe
piramp8: CFLAGS += '-DLED_START_FLASHES=4' '-DBAUD_RATE=57600' '-DLED=B0'
piramp8: AVR_FREQ = 8000000L
piramp8: $(PROGRAM)_piramp_8mhz.hex
piramp8: $(PROGRAM)_piramp_8mhz.lst
 
piramp8_isp: piramp8
piramp8_isp: TARGET = piramp_8mhz
piramp8_isp: MCU_TARGET = atmega168p
piramp8_isp: LFUSE = C2
piramp8_isp: HFUSE = DF
piramp8_isp: EFUSE = FC
piramp8_isp: isp
 
piramp16: TARGET = piramp_16mhz
piramp16: MCU_TARGET = atmega168p
piramp16: LDSECTIONS  = -Wl,--section-start=.text=0x3e00 -Wl,--section-start=.version=0x3ffe
piramp16: CFLAGS += '-DLED_START_FLASHES=4' '-DBAUD_RATE=115200' '-DLED=B0'
piramp16: AVR_FREQ = 16000000L
piramp16: $(PROGRAM)_piramp_16mhz.hex
piramp16: $(PROGRAM)_piramp_16mhz.lst
 
piramp16_isp: piramp16
piramp16_isp: TARGET = piramp_16mhz
piramp16_isp: MCU_TARGET = atmega168p
piramp16_isp: LFUSE = CF
piramp16_isp: HFUSE = DF
piramp16_isp: EFUSE = FC
piramp16_isp: isp
 
# USB IO PCB
usbio8: TARGET = usbio_8mhz
usbio8: MCU_TARGET = atmega328
usbio8: LDSECTIONS  = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
usbio8: CFLAGS += '-DLED_START_FLASHES=4' '-DBAUD_RATE=57600' '-DLED=C5'
usbio8: AVR_FREQ = 8000000L
usbio8: $(PROGRAM)_usbio_8mhz.hex
usbio8: $(PROGRAM)_usbio_8mhz.lst
 
usbio8_isp: usbio8
usbio8_isp: TARGET = usbio_8mhz
usbio8_isp: MCU_TARGET = atmega328
usbio8_isp: LFUSE = C2
usbio8_isp: HFUSE = DE
usbio8_isp: EFUSE = FF
usbio8_isp: isp
 
usbio16: TARGET = usbio_16mhz
usbio16: MCU_TARGET = atmega328
usbio16: LDSECTIONS  = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
usbio16: CFLAGS += '-DLED_START_FLASHES=4' '-DBAUD_RATE=115200' '-DLED=C5'
usbio16: AVR_FREQ = 16000000L
usbio16: $(PROGRAM)_usbio_16mhz.hex
 
usbio16_isp: usbio16
usbio16_isp: TARGET = usbio_16mhz
usbio16_isp: MCU_TARGET = atmega328
usbio16_isp: LFUSE = CF
usbio16_isp: HFUSE = DE
usbio16_isp: EFUSE = FF
usbio16_isp: isp

ビルドしてみる。。

> make piramp8
> make piramp16
> make usbio8

これでhexファイルが作成された。

WinAVR-20100110(AVR-GCC 4.3.3)でビルドすると490byte(0x1ea)のサイズになった。
AVR-GCC 7.3.0でビルドすると488byte(0x1e8)のサイズになった。
しかしWinAVR-20100110(AVR-GCC 4.3.3)でビルドしたものは,何故かうまく動作しなかった。

ボードにoptibootを書き込むには,

> make piramp8_isp

のようにすれば書き込める。

Page Top

自作ボード用にビルドしたoptiboot anchor.png

file自作ボード用にビルドしたoptiboot


新しくコメントをつける

題名
ゲスト名
投稿本文
より詳細なコメント入力フォームへ

トップ   凍結 差分 バックアップ 複製 名前変更 リロード   ページ新規作成 全ページ一覧 単語検索 最新ページの一覧   ヘルプ   最新ページのRSS 1.0 最新ページのRSS 2.0 最新ページのRSS Atom
Counter: 307, today: 1, yesterday: 0
最終更新: 2022-10-30 (日) 11:33:17 (JST) (541d) by yuji