ATtiny85のArduino起動時間

## はじめに
ちょっと気になったので動作周波数の違いによる起動時間に違いがあるかなと調査
結果、動作周波数を8MHzと16MHzで確認するとなぜか8MHzの方の起動時間が短かった。
なんで？！
追記）SUTビットを変更して起動待機時間の64msw短縮することができました。
## 準備
ボードの設定は No bootloader を選択します。
![op.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111210/8e54da7a-e389-f3b9-a534-0b42d5d43747.png)

setup()の最後にPB0をONするプログラムを入れてArduinoの起動時間を測定。

![src.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111210/73945a18-40f5-8460-f8b3-cfd537522763.png)
※DDRB,PORTB を使っているのは最小時間でポートをONにできます。

結果、8MHz：66ms、16MHz：71msでして8MHzの方が若干早い結果となりました。

![波形.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111210/9213a707-02f2-8231-1b94-b4bc0f099ee1.png)

## ちょっと調査
### その１
AVRマイコンのSUTヒューズビットで起動時間遅延の設定ができるということX（ツイッター）のメンバーより教えてもらいました。
![GiNAFt3bUAArVy0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111210/de922070-56ff-524a-05cf-e5afb8e485ca.png)

Arduinoで8MHz時と16MHzでブートローダの書き込み時に設定されるヒューズビットのHi側とLow側を確認すると以下の様になっていました。
8MHz H:0xFF L:0xE2
16MHz H:0xFF L:0xF1
SUTxxの値をみると、8MHz、16MHzともに+64msの起動時間遅延の設定がされていました。
これはArduino内でパラメータが作られているので変更できませんね・・・

### その２
起動時にどういう処理をしているのかちょっと気になって、方法としてはビルドしてできたファイルを逆アセンブルすると何か見えてくるかなと想像。
Arduinoをビルドするとフォルダのどこかにelfファイルができています。
探し方はスケッチのファイル名を全件検索すると見つけられます。
逆アセンブルは、avr-objdump を使用します。
```cpp
macuser@Mac-mini 1 % /Applications/Arduino.app/Contents/Java/hardware/tools/avr/bin/avr-objdump -S ATTiny85_FunctionDecoderDoNothing.ino.elf > a.txt
```
## ソースを読む

ベクタテーブル部分
起動すると、0番から実行されて、0x30番地にジャンプされます。
```
00000000 <__vectors>:
   0:	17 c0       	rjmp	.+46     	; 0x30 <__ctors_end>
   2:	a5 c5       	rjmp	.+2890   	; 0xb4e <__vector_1>
   4:	30 c0       	rjmp	.+96     	; 0x66 <__bad_interrupt>
   6:	2f c0       	rjmp	.+94     	; 0x66 <__bad_interrupt>
   8:	2e c0       	rjmp	.+92     	; 0x66 <__bad_interrupt>
   a:	57 c5       	rjmp	.+2734   	; 0xaba <__vector_5>
   c:	2c c0       	rjmp	.+88     	; 0x66 <__bad_interrupt>
   e:	2b c0       	rjmp	.+86     	; 0x66 <__bad_interrupt>
  10:	2a c0       	rjmp	.+84     	; 0x66 <__bad_interrupt>
  12:	29 c0       	rjmp	.+82     	; 0x66 <__bad_interrupt>
  14:	28 c0       	rjmp	.+80     	; 0x66 <__bad_interrupt>
  16:	27 c0       	rjmp	.+78     	; 0x66 <__bad_interrupt>
  18:	26 c0       	rjmp	.+76     	; 0x66 <__bad_interrupt>
  1a:	25 c0       	rjmp	.+74     	; 0x66 <__bad_interrupt>
  1c:	24 c0       	rjmp	.+72     	; 0x66 <__bad_interrupt>
```
0x00から実行されて、まずは0x30にジャンプされます。
62行目あたりで main()がコールされます。
```
00000030 <__ctors_end>:
  30:	11 24       	eor	r1, r1
  32:	1f be       	out	0x3f, r1	; 63 $3F SREG - ｽﾃｰﾀｽ ﾚｼﾞｽﾀ
  34:	cf e5       	ldi	r28, 0x5F	; 95
  36:	d2 e0       	ldi	r29, 0x02	; 2
  38:	de bf       	out	0x3e, r29	; 62 $3E SPH(SP) - ｽﾀｯｸ ﾎﾟｲﾝﾀ
  3a:	cd bf       	out	0x3d, r28	; 61 $3D SPL(SP) - ｽﾀｯｸ ﾎﾟｲﾝﾀ

0000003c <__do_copy_data>:
  3c:	10 e0       	ldi	r17, 0x00	; 0
  3e:	a0 e6       	ldi	r26, 0x60	; 96
  40:	b0 e0       	ldi	r27, 0x00	; 0
  42:	e0 ed       	ldi	r30, 0xD0	; 208
  44:	fc e0       	ldi	r31, 0x0C	; 12
  46:	02 c0       	rjmp	.+4      	; 0x4c <__SREG__+0xd>
  48:	05 90       	lpm	r0, Z+
  4a:	0d 92       	st	X+, r0
  4c:	a2 37       	cpi	r26, 0x72	; 114
  4e:	b1 07       	cpc	r27, r17
  50:	d9 f7       	brne	.-10     	; 0x48 <__SREG__+0x9>

00000052 <__do_clear_bss>:
  52:	20 e0       	ldi	r18, 0x00	; 0
  54:	a2 e7       	ldi	r26, 0x72	; 114
  56:	b0 e0       	ldi	r27, 0x00	; 0
  58:	01 c0       	rjmp	.+2      	; 0x5c <.do_clear_bss_start>

0000005a <.do_clear_bss_loop>:
  5a:	1d 92       	st	X+, r1

0000005c <.do_clear_bss_start>:
  5c:	ad 3c       	cpi	r26, 0xCD	; 205
  5e:	b2 07       	cpc	r27, r18
  60:	e1 f7       	brne	.-8      	; 0x5a <.do_clear_bss_loop>
  62:	a2 d5       	rcall	.+2884   	; 0xba8 <main>
  64:	33 c6       	rjmp	.+3174   	; 0xccc <_exit>
```
Arduinoにも裏ではこんな感じにmain()関数が存在しています。
```c++
#include <Arduino.h>

int main(void)
{
  init();

  setup();

  for (;;)
    loop();

  return 0;
}
```

Arduinoのsetup()が呼ばれて、loop()が実行されます。
アセンブラを解読するのはちょっと疲れるので調査終了。

## 再調査
Arduino総合環境からはSUTの設定は11になっており64msの起動遅延時間が設定されていました。SUT01の(16K+14)×CK+4ms設定をしてみます。
![SUT.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111210/862e25af-e906-1484-d341-ac2d11cd3020.png)

Arduino総合環境からブートローダーを書き込むときに、どの様なコマンドが実行されているか確認できます。
※下記コマンドは環境によって異なりますのでそのままコピペしても動きません。
```
/Users/macuser/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino18/bin/
avrdude -C/Users/macuser/Library/Arduino15/packages/ATTinyCore/hardware/avr/1.5.2/av
rdude.conf -v -pattiny85 -cstk500v1 -P/dev/cu.usbmodem31201 -b19200 -e -Uefuse:w:
0xFF:m -Uhfuse:w:0b11010110:m -Ulfuse:w:0xF1:m -Uflash:w:/Users/macuser/Library/
Arduino15/packages/ATTinyCore/hardware/avr/1.5.2/bootloaders/empty/empty_all.hex:i
```
-Ulfuse:w:0xF1:m となっている0xF1を0xC1に変更します。
```
/Users/macuser/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino18/bin/
avrdude -C/Users/macuser/Library/Arduino15/packages/ATTinyCore/hardware/avr/1.5.2/av
rdude.conf -v -pattiny85 -cstk500v1 -P/dev/cu.usbmodem31201 -b19200 -e -Uefuse:w:
0xFF:m -Uhfuse:w:0b11010110:m -Ulfuse:w:0xC1:m -Uflash:w:/Users/macuser/Library/
Arduino15/packages/ATTinyCore/hardware/avr/1.5.2/bootloaders/empty/empty_all.hex:i
```
ターミナルに先ほど0xF1を0xC1に変更したコマンドをコピペしてFuseを書き直します。
```
macuser@Mac-mini ~ % /Users/macuser/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino18/bin/avrdude -C/Users/macuser/Library/Arduino15/packages/ATTinyCore/hardware/avr/1.5.2/avrdude.conf -v -pattiny85 -cstk500v1 -P/dev/cu.usbmodem31201 -b19200 -e -Uefuse:w:0xFF:m -Uhfuse:w:0b11010110:m -Ulfuse:w:0xC1:m -Uflash:w:/Users/macuser/Library/Arduino15/packages/ATTinyCore/hardware/avr/1.5.2/bootloaders/empty/empty_all.hex:i

avrdude: Version 6.3-20201216
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "/Users/macuser/Library/Arduino15/packages/ATTinyCore/hardware/avr/1.5.2/avrdude.conf"
         User configuration file is "/Users/macuser/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/cu.usbmodem31201
         Using Programmer              : stk500v1
         Overriding Baud Rate          : 19200
         Setting bit clk period        : 5.0
         AVR Part                      : ATtiny85
         Chip Erase delay              : 400000 us
         PAGEL                         : P00
         BS2                           : P00
         RESET disposition             : possible i/o
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    12     4    0 no        512    4      0  4000  4500 0xff 0xff
           flash         65    12    32    0 yes      8192   64    128 30000 30000 0xff 0xff
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00
           lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           calibration    0     0     0    0 no          2    0      0     0     0 0x00 0x00

         Programmer Type : STK500
         Description     : Atmel STK500 Version 1.x firmware
         Hardware Version: 2
         Firmware Version: 1.18
         Topcard         : Unknown
         Vtarget         : 0.0 V
         Varef           : 0.0 V
         Oscillator      : Off
         SCK period      : 0.1 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x1e930b (probably t85)
avrdude: safemode: lfuse reads as F1
avrdude: safemode: hfuse reads as D6
avrdude: safemode: efuse reads as FF
avrdude: erasing chip
avrdude: reading input file "0xFF"
avrdude: writing efuse (1 bytes):

Writing | ################################################## | 100% 0.01s

avrdude: 1 bytes of efuse written
avrdude: verifying efuse memory against 0xFF:
avrdude: load data efuse data from input file 0xFF:
avrdude: input file 0xFF contains 1 bytes
avrdude: reading on-chip efuse data:

Reading | ################################################## | 100% 0.01s

avrdude: verifying ...
avrdude: 1 bytes of efuse verified
avrdude: reading input file "0b11010110"
avrdude: writing hfuse (1 bytes):

Writing | ################################################## | 100% 0.01s

avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0b11010110:
avrdude: load data hfuse data from input file 0b11010110:
avrdude: input file 0b11010110 contains 1 bytes
avrdude: reading on-chip hfuse data:

Reading | ################################################## | 100% 0.01s

avrdude: verifying ...
avrdude: 1 bytes of hfuse verified
avrdude: reading input file "0xC1"
avrdude: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.02s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xC1:
avrdude: load data lfuse data from input file 0xC1:
avrdude: input file 0xC1 contains 1 bytes
avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.01s

avrdude: verifying ...
avrdude: 1 bytes of lfuse verified
avrdude: reading input file "/Users/macuser/Library/Arduino15/packages/ATTinyCore/hardware/avr/1.5.2/bootloaders/empty/empty_all.hex"
avrdude: writing flash (2 bytes):

Writing | ################################################## | 100% 0.09s

avrdude: 2 bytes of flash written
avrdude: verifying flash memory against /Users/macuser/Library/Arduino15/packages/ATTinyCore/hardware/avr/1.5.2/bootloaders/empty/empty_all.hex:
avrdude: load data flash data from input file /Users/macuser/Library/Arduino15/packages/ATTinyCore/hardware/avr/1.5.2/bootloaders/empty/empty_all.hex:
avrdude: input file /Users/macuser/Library/Arduino15/packages/ATTinyCore/hardware/avr/1.5.2/bootloaders/empty/empty_all.hex contains 2 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.04s

avrdude: verifying ...
avrdude: 2 bytes of flash verified

avrdude: safemode: lfuse reads as C1
avrdude: safemode: hfuse reads as D6
avrdude: safemode: efuse reads as FF
avrdude: safemode: Fuses OK (E:FF, H:D6, L:C1)

avrdude done.  Thank you.

macuser@Mac-mini ~ % 
```
71ms-64ms=7msということで、波形の時間では8msくらいですが、起動が早くなりました！

![DS1Z_QuickPrint36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111210/c7406644-22da-6a5c-b3bb-523f92333756.png)
CH1(黄色) DCC信号、CH2(水色）PB0信号、CH3(桃色） +5V電源