このドキュメントは http://edu.net.c.dendai.ac.jp/ 上で公開されています。
Arduino の標準的な開発環境は、公式サイトからダウンロードできる Arduino IDE です。 Windows 用はインストーラーをダウンロードしてインストールしてください。 Windowsストアからインストールすると、インストール結果でコマンドのパスなどが変わってしまいます。
検証は(ver. 7.0.1931)で行っています。 ディレクトリパスの表示など、バージョンで異なるかもしれません。
Atmerl Studio では C 言語とアセンブリ言語開発ができます。 本講義ではC言語の開発は専らArduino IDEで行うので、 Atmel Studio はア センブリ言語の開発のみで使用します。
Atmel Studio を起動し、New→project を選択し、Assembler を選択し、保 存フォルダとプロジェクト名を記入します。
以下のプログラムを program.bat というテキストファイルに収めます。
SET dude="C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude.exe"
set conf="C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf"
rem %dude% -C %conf% -p atmega328p -cstk500v1 -P %1 -b 57600 -D -U flash:w:%2%:i
%dude% -C %conf% -p m328p -c arduino -P %1 -D -U flash:w:"%2":i
/*
* flashuno.asm
*
* Created: 2018/09/15 15:39:43
* Author: sakamoto
*/
.cseg
.org 0x0000
rjmp reset
.org INT_VECTORS_SIZE
reset:
ldi r16,high(RAMEND)
out SPH,r16
ldi r16,low(RAMEND)
out SPL,r16
ldi r16,1<<pb5
out ddrb, r16
.equ time = 10
main:
sbi portb,pb5
rcall wait
cbi portb,pb5
rcall wait
rjmp main
.def wreg0 = r20
.def wreg1 = r21
.def wreg2 = r22
wait:
ldi wreg0,time
wait0:
ldi wreg1,0
wait1:
ldi wreg2,0
wait2:
nop
dec wreg2
brne wait2
dec wreg1
brne wait1
dec wreg0
brne wait0
ret
.exit
Wiring システムは、マイコン開発を容易に行うために開発された教育用の 教材でした (Arduinoの語られざる歴史 by Hernando Barragán)。 Java で開発されたIDEはパソコンのOSを選ばずに使用できます。 また、マイコンのプログラムはC/C++言語で記述します。 プログラムのコンパイル、書き込みがワンアクションでできます。
Arduino のハードウェアは Creative Commons Attribution-ShareAlike 2.5 宣言されてます。 但し、派生製品に対して Arduino の名前を使うことを 禁じています。 ソフトウェアは GPL v2 宣言されていて、条件を守れば自由に改変などができます。
Arduino Uno のドキュメントは 公式サイト にあります。 また、 ピン配置 も図示されていますが、より見やすい図が色々デザインされていますの で、気に入ったドキュメントを探してください。
基板上でメインに使用するのは ATmega328Pというマイコンです。 このマイコンは内部クロックも利用できますが、外部クロックとして16MHz の水晶発振器が接続されています。 多くの I/O ポートがそのまま外部端子に繋がれています。 また、PortB5 には LED が接続されています。 Digital 0,1 が通信用ポートとして使用されます。
基板にはUSBポートが搭載され、USB通信を実現するために、もう一つ AVR のマイコン が載っています。 さらに、USBポートからの5V電源に対して、レギュレータ回路により 3.3Vの 電源も供給されています。
マイコンにはブートローダーというプログラムが書き込まれていて、これによ り、パソコンからのプログラムの書き込みと、プログラムの実行を行います。
C/C++言語で開発を行うとき、様々な関数、変数などが 定義されています。
pinmode(LED_BUILTIN,OUTPUT);
digitalWrite(LED_BUILTIN,HIGH);
void wait(void){
volatile int i;
for(i=0;i<35000;i++){
}
}
ATmega 328P は Microchip 社のマイクロコントローラです(かつては Atmel 社の製品でしたが、会社が買収されました)。 データシートは Microchip 社から入手できますが、有志により日本語訳さ れたものも別サイトで公開されています。 本講義では、解説などには公式ドキュメントである英文を使用しますが、理解 の助けとして日本語訳を使用するのは問題ありません。 但し、日本語訳は公式ではありませんので、状況に応じて公式ドキュメントを 確認する必要があります。
ATmega 328Pの特徴はデータシートの表紙にまとめられています。 豊富な機能がありますが、本講義では基本的な機能しか使いません。 メモリーマップがシンプルで、スタックが実装されているため、 C 言語と 親和性が高いです。
我々が普段使っている Windows を使うパソコンでは、メモリは単一のもので、 プログラムとデータが共存しています。これを(フォン)ノイマン型コンピュー タと呼んでいます。 一方、ATmega328P では、データシートの p.13 Figure 4-1 にあるように、 Program Flash と SRAM に明確な区分があり、共存していません。これを ハーバードアーキテクチャと言います (由来のハーバードマークI は世界初の汎用(リレー式)計算機(1944))。 プログラムとデータの扱い方が違うので、プログラムをメモリ上で扱う OS や コンパイラなどの実装は難しいという欠点はあります。 しかし ATmega328P の用途から考えると OS やコンパイラを使うことは無さそうなの で、問題無さそうです。 さらにこのようなアーキテクチャでは、CPU がプログラムを読み込む仕組みを 単純化できるなど長所もあります。 また ATmega328P のようにプログラムの語長とデータの語長がそれぞれ 16bit と 8bit と異なるデザインも可能です。
プログラム領域は データシートの Figure 12-1(p.36) にあるよ
うに、0x0000 から 0x3fff まであります。
プログラムカウンタは 14bit あります。
アセンブリ言語では PC
という記号で参照できます。
プログラム領域は 16 bit = 1 word でプログラムを記述しますが、一方で、
データも記述できます。
さらに本講義では扱いませんが、プログラム領域をプログラムによって書き換
えることもできます。
割り込み が発生した時は、発生した割り込みに応じて 0x0001 番地から 0x0032 番地の どれかが呼び出されます(割り込みベクタ pp. 84-85 Table 16-1)。 そのため、通常はこのベクタにはジャンプ命令のみ書いて、それぞれを処理する 番地に移行するようにします。 割り込みベクタ以降はどこにプログラムを書いても影響はありません。 但し、ジャンプ命令でどこへでも飛べるわけでは無いので、プログラムはなる べく近くに書きます。
プログラム領域にデータを書くには .db や .dw ディレクティヴを使用します。 ATmega328P のデータ処理単位は 8bit ですが、プログラム領域は 16bit 単位でアド レスが振られているので、プログラムからアドレスを指定してデータを読み出 す場合、(プログラム領域のアドレス*2)で最初のバイト、 (プログラム領域のアドレス*2+1)で次のバイトを読むことができます。 プログラム領域をアクセスするには lpm 命令を使いますが、アドレス指定は Z レジスタのみが使用できます。
ATmega328P がデータをやりとりする場所は、プログラム領域の他、レジスタ、I/O、 SRAM領域、EEPROM があります。 このうち、レジスタ、I/O、SRAM は連続したアドレスが割り振られていて、 LD と ST 命令でやりとりできます(Figure 12-2 p.37)。 しかし、レジスタや I/O に関しては、より多くの専用の命令が用意されてい ます。
内部の数値論理ユニット(ALU)と接続して演算を行えるのはレジスタだけです。 したがって、機械語のプログラミングではレジスタの操作が重要になります。
ATmega328Pには 32 個のレジスタ(r0-r31)がありますが、 すべてのレジスタが同等ではありません(Figure 11-2 p.29)。 r27:r26=X, r29:r28=Y, r31:r30=Z と、3組のレジスタは 16bit のインデック スレジスタとしてメモリの番地指定に使用できます。 また、定数読み込み命令 ldi 掛け算命令 mul やビット操作命令は r16 から r31 までしか使えません。 さらに小数の掛け算命令 fmul, fmuls, fmulsu は r16 から r23 までしか使 えません。 なお、これらの掛け算命令による結果は r1:r0 に入ります。 従って、レジスタで一番命令の制限が無いのは r16 から r23 までなので、通 常のプログラミングではこのレジスタを主に使用します。 さらに、 r26 から r31 はインデックスレジスタとして利用します。
各入出力ポートの他、割り込みや外部との通信用に I/O があります。 I/O 用の命令として in, out があります。 さらに、 I/O 自体は 64バイト用意されているのですが、前半の 32 バイトに 対してはビット演算命令 cbi, sbi, sbic, sbis を使用できます。 なお、ld, ldd, st, std 命令を用いて、 I/O 番地に 0x20 を加えた メモリ空間としてもアクセスできます。
SRAM は 0x0100(SRAM_START) 番地から 0x08FF番地(RAMEND) までの連続した領域として使 用できます。 ここへは ld, ldd, st, std 命令でアクセスします。
一方、ATmega328P では、この領域にスタックも置き、サブルーチン呼び出し rcall, ret などで使用します。 そのため、プログラムの開始時にスタックポインタを設定する必要があります(p.85)。
ldi r16,high(RAMEND)
out SPH,r16
ldi r16,low(RAMEND)
out SPL,r16
スタックは rcall, ret, reti で戻り番地を記憶するために使われる他、8bit のデータを出し入れをする push, pop でも使用できます。
ゲームのデータや利用者の設定情報など、電源を切っても失いたくないデータ は EEPROM に書きます。 これの読み書きの仕組みは I/O にある EEPROM のアドレスレジスタとデータ レジスタを使用します。 アドレスレジスタにアドレスを書けば、データレジスタにデータを読み書きでき ます(データシート pp.38-45)。 なお、eseg と db ディレクティヴを使用すると、プログラマから書き込んで 初期化することもできます。
I/O 領域は 64 Byte あり、さらに拡張 I/O 領域が160 Byte あります。 これは データシート p.427 の 35. Register Summary にまとめられてます。 この領域は基本的には LD, LDS, LDD, ST, STS, STD 命令で読み書きできます。 その時は、p.37 Figure 12-2 に示されるアドレスである 0x0020 から 0x00FF の 間のアドレスを使用します。 この I/O 領域には、各PORT の信号を制御したり、割り込みの制御をするなど、 様々な機能が埋め込まれています。
I/O領域に対する特別な入出力命令として IN , OUT 命令があります。 この場合、アドレスは 0x00 から 0x5F としてアクセスします。 さらに、前半のアドレス 0x00 から 0x1F の I/O 領域だけに有効な命令とし て、特定のビットを検査する SBI, CBI があります。
電源を入れた時やリセットした時は 0 番地から実行が始まります。 一方割り込みが発生した時はそれぞれの割り込みに割り当てられた割り込みベ クタが呼び出されます。 (データシート pp.84-85 Table 16-1)。 割り込みとは次の条件が発生した時のことを言います。
これらの条件にマイコンが反応すると、それぞれの割り込みに対して、定めら れた割り込みベクタの番地のプログラムを実行します。
割り込みを許可/不許可するための値やレジスタのことを割り込みマス
クと言います。
これには、個別の割り込みを ON/OFF するものの他に、全体の割り込みを
ON/OFF する全体割り込み許可フラグが Status Register の Bit7 I にありま
す(データシート pp.28-29)。
割り込みを使用する際は、個別の割り込みの設定をしたのち、この全体割り込
み許可を行います。
一方、割り込みが発生した時は、割り込みベクタが呼び出されますが、この際、
戻り番地がスタックに入る他に、この全体割り込み許可フラグがクリアされま
す。
割り込み処理を終えた後、割り込み許可フラグをセットすると同時に割り込み
発生した番地に戻らなければなりませんが、これを1命令で行う
RETI
命令が用意されています。
このような他の要因に影響されずにひとまとまりに操作することを
アトミック
と言います。
ATmega328P のチップにおいて、クロックの入力方法や、ピンの使用方法など、起動以 前に設定しなければならない項目があります。 これらは、プログラムなどと一緒に設定情報として書き込む必要があります。 この設定情報はヒューズビットと呼ばれています。 これは 3 Byte あり、データシートpp.346-348 に記載されています。
ヒューズビットで設定可能なのは、プログラムや EEPROM の読み書きの設定、 Broun-out 割り込みにおける電圧設定の他に、外部リセット端子の無効化、ク ロックの内部外部切り替え、内部クロックの速度の設定などです。 本講義では、これらはすべてデフォルトで使用しますが、高速に動作させたい など、デフォルト以外の動作をさせる場合は、精読して活用する必要がありま す。