AtmelStudioとUSBtinyISPでAVR(AtMega, ATtiny)の開発環境を作る

#はじめに
 Arduionの開発環境は大変便利なのですが、ネットに存在しているAVRのCコードやアセンブリコードを利用する場合に困ってしまいます。Cコードであれば移植は可能ですが、アセンブリとなるとお手上げです(私が方法を知らないだけかもしれませんが)。
 ここではネット上のAVR資産を有効活用するべく、Atmel Studioで開発、USBtinyISPで書き込みとArduionを使用しない昔ながらの開発環境を整えたいと思います。

Fuse設定方法を文末に追記します。 加筆2018-08-22
AtMega328pの場合を追記しました。 2018-10-14

#用意するもの
##Atmel Studio
[Atmel Studio 7](http://www.microchip.com/mplab/avr-support/atmel-studio-7)
現在はAtmel Studio 7として上記よりダウンロード可能です。

##USBtinyISP
AVRを書き込むライターです。ATTiny2313A-PUを使用したライターで、AliexpressでU$3ほどでした。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/211703/3c6962ac-cafb-08d4-d7ee-afff8f0a6ccb.png)

##AVR
今回はATtiny13AでLチカを行なってみます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/211703/3135a9c6-6700-1310-b714-11a357978e9b.png)

##ArduinoIDE
Arduinoの開発環境も必要となります。実際にはArduinoの開発環境に含まれるAVRDUDE.exeを使用します。Arduinoが無ければAVRDUDEを使用できる環境を揃える必要があります。

#Atmel Studioのインストール
こちらは得に記載することはありません。インストーラに従ってインストールしたのみです。
プロジェクト作成、プログラム作成に関しては迷うことはありませんでしたので割愛します。

#USBtinyISPでの書き込み
アセンブリやCコードでコンパイル完了すると、HEXファイルが作成されます。これをAVRに書き込む手順を記載します。
USBtinyISPはAtmelの標準ツールとして認識されませんので、External ToolとしてAvrDude.exeを呼び出し、生成されたHEXファイルをパラメータとして渡すことになります。

##External Tools...への登録
メニューの"Tools" -> "External Tools..."を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/211703/577f6d7c-ad99-43eb-d671-881911c8a705.png)

ダイアログが表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/211703/1d983936-ea95-06aa-6817-c7839f3bb135.png)

下記の様に設定します。
###Title
好きな名称を設定します。

###Command
AvrDude.exeへのパスを設定します。私の環境では下記でした。

```command:Command
C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude.exe
```

###Argument
```Argument:Argument
-c usbtiny -C "C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf" -p t13 -v -v -v -U flash:w:"$(TargetDir)$(TargetName).hex":i
```

オプション設定
"-c"
使用するのはUSBtinyISPですので、"-c"のオプションに"usbtiny"を設定。
"-C"
今回一番悩んだオプションです。これを設定しないとエラーとなりますが、"avrdude.conf"がみつからないというエラーと気づくのに時間を要しました。理由が分ったのでフルパスを指定してやります。
"-p"
AVRの種類を設定します。AvrDudeのマニュアルに記載されていますので、こちらを参照してお使いのAVRを指定してください。
[2.1 Option Description](https://www.nongnu.org/avrdude/user-manual/avrdude_4.html#Option-Descriptions)
"-U"
こちらは特になやむ必要はありませんでした。

```Argument:-U
-U flash:w:"$(TargetDir)$(TargetName).hex":i
```
この通り記載すれば問題ありません。

###Initial Directory
こちらはAvrDudeのパスを指定しました。

```command:Command
C:\Program Files (x86)\Arduino\hardware\tools\avr\bin
```

###Use output window
チェックを入れておくと、AVR StudioのOutput windowにAvrDudeの出力が表示されます。

#結線
USBTinyISPのコネクタ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/211703/3f2739de-0cc0-5499-2b97-1cad81fa45da.png)

Attiny13Aのピン配置
![image.png](https://qiita-image-store.s3.amazonaws.com/0/211703/ecb95c02-34a1-48eb-af57-57b3c27cd9d5.png)

ISPコネクタ <----> Attiny
PIN 1(MISO)<----> PIN6 (MISO)
PIN 2(VCC) <----> PIN8 (VCC)
PIN 3(SCK) <----> PIN7 (SCK)
PIN 4(MOSI)<----> PIN5 (MOSI)
PIN 5(RST) <----> PIN1 (RESET)
となります。

簡便のため書き込みアダプタを作成しました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/211703/cba3d011-e04c-509a-1421-45a820478952.png)


#書き込み
設定が完了すれば、Toolに設定された項目をクリックするだけで書き込みが開始されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/211703/502421f5-174e-8a7f-d36a-72f389796def.png)

Output Windowに結果が表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/211703/993e39d8-728d-fb6c-c17c-ec26a5c36d58.png)


#Lチカ
Lチカをしてみます。_delay_ms()を使用する場合には、"F_CPU"に動作周波数をDefineしてやる必要があります。~~なお、これを設定するとFuse設定もおこなわれました。~~嘘です。Fuse設定は出来ません(delay系の関数は修正されるようです)、Fuse設定方法を文末に追記します。 加筆2018-08-22

```CPP:L-chika.cpp
#include <avr/io.h>
#include <util/delay.h>

#define LED          PB1
#define DELAY        2500

// For delay.h
#ifndef F_CPU
#define	F_CPU	9600000		// 9.6MHz
#endif


int main(void)
{
    /* Replace with your application code */
    DDRB |= _BV(LED);
    while(1)
    {
	    PORTB ^= _BV(LED);
	    _delay_ms(DELAY);
    }
}
```

コンパイルして、

```cmd:Outputwindow
------ Build started: Project: GccApplication1, Configuration: Debug AVR ------
Build started.
Project "GccApplication1.cppproj" (default targets):
Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').
Target "CoreBuild" in file "C:\Program Files (x86)\Atmel\Studio\7.0\Vs\Compiler.targets" from project "D:\******\Documents\Atmel Studio\7.0\GccApplication1\GccApplication1\GccApplication1.cppproj" (target "Build" depends on it):
	Task "RunCompilerTask"
		Shell Utils Path C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils
		C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils\make.exe all --jobs 8 --output-sync 
		make: Nothing to be done for 'all'.
	Done executing task "RunCompilerTask".
	Task "RunOutputFileVerifyTask"
				Program Memory Usage 	:	68 bytes   6.6 % Full
				Data Memory Usage 		:	0 bytes   0.0 % Full
	Done executing task "RunOutputFileVerifyTask".
Done building target "CoreBuild" in project "GccApplication1.cppproj".
Target "PostBuildEvent" skipped, due to false condition; ('$(PostBuildEvent)' != '') was evaluated as ('' != '').
Target "Build" in file "C:\Program Files (x86)\Atmel\Studio\7.0\Vs\Avr.common.targets" from project "D:\******\Documents\Atmel Studio\7.0\GccApplication1\GccApplication1\GccApplication1.cppproj" (entry point):
Done building target "Build" in project "GccApplication1.cppproj".
Done building project "GccApplication1.cppproj".

Build succeeded.
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========
```

書き込み。

```cmd:Output
avrdude.exe: Version 6.3, compiled on Jan 17 2017 at 12:00:53
             Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
             Copyright (c) 2007-2014 Joerg Wunsch

             System wide configuration file is "C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf"

             Using Port                    : usb
             Using Programmer              : usbtiny
avrdude.exe: usbdev_open(): Found USBtinyISP, bus:device: bus-0:\\.\libusb0-0001--0x1781-0x0c9f
             AVR Part                      : ATtiny13
             Chip Erase delay              : 4000 us
             PAGEL                         : P00
             BS2                           : P00
             RESET disposition             : dedicated
             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     5     4    0 no         64    4      0  4000  4000 0xff 0xff
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               flash         65     6    32    0 yes      1024   32     32  4500  4500 0xff 0xff
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               calibration    0     0     0    0 no          2    0      0     0     0 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00

             Programmer Type : USBtiny
             Description     : USBtiny simple USB programmer, http://www.ladyada.net/make/usbtinyisp/
avrdude.exe: programmer operation not supported

avrdude.exe: Using SCK period of 10 usec
CMD: [ac 53 00 00] [ac 53 00 00]
CMD: [ac 53 00 00] [ac 53 00 00]
avrdude.exe: initialization failed, rc=-1
             Double check connections and try again, or use -F to override
             this check.


avrdude.exe done.  Thank you.
```

以上で書き込みは完了です。

#おわりに
ツール設定にすこし悩みましたが、終ってみれば簡単な事でした。

参考になれば幸いです。

2018/08/10 Ikeda

#追記 Fuse書き込み方法
Fuse設定は自動で書き込みされません。Delay系の関数が正しく動作していたように見えたので書き込みされていると思い込んでしまいました。失礼しました。割り込みの周波数が遅く、どうなっているのか探していたらFuse設定に行きつきました。標準は下位バイトが6Aとなっているので1.2MHz動作の様です。(割り込みプログラムは9.6MHzを想定して記載していた)
Fuse設定及び書き込み方法を記載します。

周波数の設定を変更するにはFuseのの下位バイトに下記設定します。
9.6MHz動作 : 0x7A (標準)
1.2Mhz動作 : 0x6A

Avrdudeはファイルのデータを書き込みますので、まずはFuse下位バイトに書き込む為のファイルを用意します。ここではIntelフォーマットで記載します。(オプションHで0x6Aで書き込めなかったため)

```TXT:lFuse(9.6Mhz).txt
:010000007A85
:00000001FF
```

```TXT:lFuse(1.2Mhz).txt
:010000006A95
:00000001FF
```

同様にツールを追加します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/211703/b0107827-44a9-8164-c71c-0e95273e8f48.png)


###Argument設定(その他の設定は上記と同じ)
```Argument:Argument
-c usbtiny -C "C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf" -p t13 -U flash:w:"『lFuse(9.6Mhz).txtもしくはTXT:lFuse(1.2Mhz).txtのパスをここへ記載』":i
```

加筆2018-08-22

#AtMega328pの場合
基本は同じですが、周波数の決定は外部水晶で決定する場合にはFuse設定は不要で、_delay_ms()がF_CPUを設定するのみで動作します。

#Lチカ(AtMega328P)
Lチカをしてみます。_delay_ms()を使用する場合には、"F_CPU"に動作周波数をDefineしてやる必要があります。Util/delay.hの上でDefineする必要があります。

```CPP:L-chika.cpp
#ifndef F_CPU
#define	F_CPU	16000000UL		// 16MHz
#endif

#include <avr/io.h>
#include <util/delay.h>


int main(void)
{
	DDRB |= (1<<PB0); // PB0 (PIN8 in Arduino UNO) as outputs (LED)

    /* Replace with your application code */
    while (1) 
    {
		_delay_ms(1000);
		PORTB |= (1<<PB0);
		_delay_ms(1000);
		PORTB &= ~(1<<PB0);
    }
}

```

#書き込み(AtMega328P)

ツール設定は下記のとおりです。-pのオプションがm328pになっただけです。

```
TOOL:Tool for AtMega328P
-c usbtiny -C "C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf" -p m328p -v -v -v -U flash:w:$(TargetDir)$(TargetName).hex:i
```
Lチカできました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/211703/2893c79d-fa64-a6a0-0961-965eae2a5e8c.png)