現: 2022-10-30 (日) 11:33:17 yuji Deleted an attach file: optiboot.zip at 2023-11-29 (水) 14:51:34 |
|||
---|---|---|---|
Line 1: | Line 1: | ||
+ | * optiboot [#d526b6e5] | ||
+ | optibootはATMEL AVRを搭載したボード用のbootloaderの一つ。~ | ||
+ | optibootの特徴は, | ||
+ | - 機能を必要最低限に絞ってサイズを512byte以下と小さくしている。~ | ||
+ | これにより,ユーザープログラム領域を大きく出来る。~ | ||
+ | - avrdude等との通信のbaudrateが115200と高速。~ | ||
+ | Flash ROMへの書き込み時間が短くなる。~ | ||
+ | RC発振器を使用しているボードではうまく通信できなくなるので,baudrateを57600にする必要がある。~ | ||
+ | - 電源投入時にはすぐにユーザープログラムにジャンプする。~ | ||
+ | - ATmega8/ATmega168/ATmega328Pを使用したボードに対応している。~ | ||
+ | ATmega168PやATmega328には対応していない。~ | ||
+ | - ビルドすることで異なるbaudrateやcpuに対応する。~ | ||
+ | |||
+ | 市販されているArduinoボードには,このoptibootが標準で搭載されているようだ。~ | ||
+ | |||
+ | ** optibootのバージョン [#g09727d7] | ||
+ | 市販されているArduinoボードに書き込まれているoptibootはversion 4.4。~ | ||
+ | [[optiboot>https://github.com/Optiboot/optiboot]]サイトで開発は行われていて,現在はversion8.3になっている。~ | ||
+ | |||
+ | ** 自作ボード用にoptibootをビルドする [#v41899b3] | ||
+ | ATmega168PやATmega328を使った自作ボードがあるので,optibootをビルドして書き込んでみた。~ | ||
+ | |||
+ | 内蔵RC発振器の8MHz仕様のボードと16MHzのX'talを実装したボードがある。内臓RC発振器はその精度が悪い(±10%)ため,optibootのデフォルトのbaudrate 115200ではうまく通信出来ない。~ | ||
+ | このため,内蔵RC発振器を使うボードでは,baudrateが57600を使うようにする。~ | ||
+ | また,オンボードLEDやポートの使い方が違うのでそれにも対応する。~ | ||
+ | |||
+ | Arduino IDEのboards.txtもそのように設定する必要がある。~ | ||
+ | |||
+ | *** version 4.4 [#if70f194] | ||
+ | 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行目以降に以下を追加。~ | ||
+ | #code(text,,nonumber){{ | ||
+ | # 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 | ||
+ | のようにすれば書き込める。 | ||
+ | |||
+ | *** version 8.3 [#ec7f12bc] | ||
+ | ソースコードは,[[こちらのサイト>https://github.com/Optiboot/optiboot]]からダウンロードする。~ | ||
+ | > 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''を以下の内容で作成した。~ | ||
+ | #code(text){{ | ||
+ | # 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 | ||
+ | のようにすれば書き込める。 | ||
+ | |||
+ | *** 自作ボード用にビルドしたoptiboot [#h7b87557] | ||
+ | &ref(../Arduino/optiboot.zip,,自作ボード用にビルドしたoptiboot);。 |