avr-libc  2.0.0
Standard C library for AVR-GCC

AVR Libc Home Page

AVRs

AVR Libc Development Pages

Main Page

User Manual

Library Reference

FAQ

Example Projects

シンプルなデモ

ここまでにGNUツールをシステムにインストールし、構築して設定なければなりません。この章では、AVRプロジェクトでのGNUツールの簡単な使用例を紹介しています。この章を読んだあとに、ツールがどのように使われるか、Makefileがどのように設定されるかの感触がつかめるでしょう。

プロジェクト

このプロジェクトは、2秒ごとにLEDをパルス幅変調(PWM)で徐々に点滅させます。AT90S2313プロセッサをコントローラとして使用します。このデモンストレーション用回路を回路図に示します。もし開発キットを持っていれば、このプロジェクトのために回路を作るよりも、開発キットを使えます。

注意
ただ、AT90S2313はすでに廃版になっています。その後継で、このプロジェクトとピン互換のあるATtiny2313や、あるいは人気があるATmega8かその後継(ATmega48/88/168)を使用することで、元のデモプロジェクトから作ることができます。これら全ての最新のデバイスでは、1MHzの内部クロックを使用できるようにして出荷されているため、もはや外部水晶は必要ありません。そのため、C1、C2とQ1を省略できます。通常、この実験では、/RESETの外部回路(R1、C3)を同じように省略することができます。そして、AVRとLED、バイパスコンデンサ C3とたぶんR2だけになります。ATmega8/48/88/168では、LEDの接続にPB1 (DIP-28では15ピン)を使用してください。その上で、このデモは多くの異なる他のAVRに移植されています。OCピンの配置は、AVRのハードウェアに依存し異なります。

demo.png
デモプロジェクトの回路図

ソースコードはdemo.cにあります。この例のために、ソースコードdemo.cを作成してください。コードの重要な点は次の通りです。

Note [1]:
AVRマイクロコントローラシリーズは、過去数年の間に開発されているように、新機能が時間をかけて追加されています。たとえtimer/counter1の基本概念は、この簡単なデモが最初に書かれていたときの2001年初頭時代と同じでも、レジスタとビットの名前は、新機能を反映するために若干変更されています。また、LEDの制御に使用している比較出力の1A(古いデバイスでは1)ピンのポートやピン配置は、AVRの種類で異なります。iocompat.hファイルは、プリプロセッサの#ifdef命令文を用いてこれら全ての違いを抽象化しようとしています。そして、実際のプログラムでは、共通のシンボル名のセットを用いて操作するこができます。このファイルで定義されているマクロは次の通りです。
Note [2]:
ISR()は、割込み処理の関数を示すマクロです。この場合、タイマー1のオーバーフロー時に関数が呼び出されます。割込みの設定は、<avr/interrupt.h>: 割込みの中でより詳細に説明されています。
Note [3]:
PWMが10ビットモードで使われているため、現在の値を記憶するために16ビットの変数が必要になります。
Note [4]:
このセクションでPWMの新しい値を決定します。
Note [5]:
ここでは、新しく計算した値をPWMレジスタにロードします。割込み処理の中にいるため、レジスタに16ビットの代入を使うことは安全です。割込みの外であって、割込み処理がこのレジスタ(または、TEMP)を使用する別のレジスタ)にアクセスすることができたという可能性があるならば、代入は割込みを使用不可能にして実行されなければなりません。FAQの項目を参考にしてください。
Note [6]:
この処理は、リセットの後に呼び出されます。そして、PWMの初期化と割込みを許可します。
Note [7]:
プログラムのメインループは、何もしません。全ての作業は割込み処理で行われます。sleep_mode()は、次の割込みまでプロセッサを休止状態にし、電力を削減します。もちろん、LEDを動かしているので、それは顕著ではないでしょう。ただ、基本原則のデモをここでは述べているだけです。
Note [8]:
初期のAVRデバイスは、電流を供給する時はむしろ低い電流で飽和するため、LEDを直接接続でき、LEDに流れる電流はおよそ15mAになります。しかし、最新の部品(少なくともATmega128)では、AtmelがIOのソース能力を大幅に増やしたので、Vccを5Vで動作させる場合にはR2が必要になります。その値は150Ω程度です。3Vで回路を動作させるときは、省略することもできます。

ソースコード

/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <joerg@FreeBSD.ORG> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return. Joerg Wunsch
* ----------------------------------------------------------------------------
*
* Simple AVR demonstration. Controls a LED that can be directly
* connected from OC1/OC1A to GND. The brightness of the LED is
* controlled with the PWM. After each period of the PWM, the PWM
* value is either incremented or decremented, that's all.
*
* $Id: demo.c 1637 2008-03-17 21:49:41Z joerg_wunsch $
*/
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include "iocompat.h" /* Note [1] */
enum { UP, DOWN };
ISR (TIMER1_OVF_vect) /* Note [2] */
{
static uint16_t pwm; /* Note [3] */
static uint8_t direction;
switch (direction) /* Note [4] */
{
case UP:
if (++pwm == TIMER1_TOP)
direction = DOWN;
break;
case DOWN:
if (--pwm == 0)
direction = UP;
break;
}
OCR = pwm; /* Note [5] */
}
void
ioinit (void) /* Note [6] */
{
/* Timer 1 is 10-bit PWM (8-bit PWM on some ATtinys). */
TCCR1A = TIMER1_PWM_INIT;
/*
* Start timer 1.
*
* NB: TCCR1A and TCCR1B could actually be the same register, so
* take care to not clobber it.
*/
TCCR1B |= TIMER1_CLOCKSOURCE;
/*
* Run any device-dependent timer 1 setup hook if present.
*/
#if defined(TIMER1_SETUP_HOOK)
TIMER1_SETUP_HOOK();
#endif
/* Set PWM value to 0. */
OCR = 0;
/* Enable OC1 as output. */
DDROC = _BV (OC1);
/* Enable timer 1 overflow interrupt. */
TIMSK = _BV (TOIE1);
sei ();
}
int
main (void)
{
ioinit ();
/* loop forever, the interrupts are doing the rest */
for (;;) /* Note [7] */
return (0);
}

コンパイルとリンク

最初にしなければならないことは、ソースをコンパイルすることです。コンパイル時に、コンパイラに-mmcuオプションを指定することでプロセッサのタイプを知らせる必要があります。-Osオプションは、コンパイラに効果的な空間使用(コードの実行速度は我慢できる範囲で遅くなる)でコードを最適化するように指示します。 -gは、デバック情報の埋め込みに使います。デバッグ情報は逆アセンブルに有用で、.hexファイル上には結果として残らないため、私は通常使っています。最後に、-cは、コンパイルして終る、リンクしないことをコンパイラに指示します。このデモは、コンパイルして1つにリンクすることは、十分小さいステップです。しかし、現実のプロジェクトでは、モジュールがいくつもあり、一般的にいくつもコンパイルして分割されてプロジェクトに組み入れていて、1つにリンクされる必要があります。

    $ avr-gcc -g -Os -mmcu=atmega8 -c demo.c

コンパイラはdemo.oファイルを作ります。次に、demo.elfと呼ばれるバイナリファイルにリンクします。

    $ avr-gcc -g -mmcu=atmega8 -o demo.elf demo.o

リンクの時にMCUタイプを指定することが重要です。コンパイラは、スタートアップファイルと一緒にリンクされるランタイムライブラリを選択するため、-mmcuオプションを使用します。このオプションを指定しないと、確実にあなたが望んでいない、コンパイラが8515プロセッサ環境に初期設定されます。

オブジェクトファイルの考察

現在、バイナリファイルができあがりました。生成したオブジェクトファイルを操作(または、プロセッサに書き込む)のに役立つツール、GNU Binutilsスイートがあります。1つのツールにavr-objdumpがあります。これは、オブジェクトファイルから情報を取り出し、役立つ情報を表示します。このコマンド自体を入力すると、オプションを一覧表示します。

たとえば、アプリケーションのサイズの雰囲気をつかむために、-hオプションを使うことができます。このオプションの出力は、各セクションでどれだけのスペースを使用しているかを表示します。(.stabや .stabstrセクションは、デバッグ情報を持っていて、ROMファイルには含まれません。)

さらに役に立つオプションは-Sです。このオプションはバイナリ・ファイルを逆アセンブリして、出力でソースコードを点在させてくれます!この方法は、ライブラリやベクターテーブルの内容からの処理を含んでいるため、コンパイラで-Sを付けるより私は良い方法と考えています。また、全ての"フィックスアップ"が満たされています。言い換えると、このオプションによって生成されるリストは、プロセッサが実際に動作するコードを反映しています。

    $ avr-objdump -h -S demo.elf > demo.lst

次にdemo.lstファイルに保存された内容を示します。

demo.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         000000d0  00000000  00000000  00000094  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000000  00800060  000000d0  00000164  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000003  00800060  00800060  00000164  2**0
                  ALLOC
  3 .stab         0000075c  00000000  00000000  00000164  2**2
                  CONTENTS, READONLY, DEBUGGING
  4 .stabstr      00000d21  00000000  00000000  000008c0  2**0
                  CONTENTS, READONLY, DEBUGGING
  5 .comment      00000011  00000000  00000000  000015e1  2**0
                  CONTENTS, READONLY

Disassembly of section .text:

00000000 <__ctors_end>:
   0:	20 e0       	ldi	r18, 0x00	; 0
   2:	a0 e6       	ldi	r26, 0x60	; 96
   4:	b0 e0       	ldi	r27, 0x00	; 0
   6:	01 c0       	rjmp	.+2      	; 0xa <.do_clear_bss_start>

00000008 <.do_clear_bss_loop>:
   8:	1d 92       	st	X+, r1

0000000a <.do_clear_bss_start>:
   a:	a3 36       	cpi	r26, 0x63	; 99
   c:	b2 07       	cpc	r27, r18
   e:	e1 f7       	brne	.-8      	; 0x8 <.do_clear_bss_loop>

00000010 <__vector_8>:
#include "iocompat.h"		/* Note [1] */

enum { UP, DOWN };

ISR (TIMER1_OVF_vect)		/* Note [2] */
{
  10:	1f 92       	push	r1
  12:	0f 92       	push	r0
  14:	0f b6       	in	r0, 0x3f	; 63
  16:	0f 92       	push	r0
  18:	11 24       	eor	r1, r1
  1a:	2f 93       	push	r18
  1c:	8f 93       	push	r24
  1e:	9f 93       	push	r25
    static uint16_t pwm;	/* Note [3] */
    static uint8_t direction;

    switch (direction)		/* Note [4] */
  20:	80 91 62 00 	lds	r24, 0x0062
  24:	88 23       	and	r24, r24
  26:	f1 f0       	breq	.+60     	; 0x64 <__SREG__+0x25>
  28:	81 30       	cpi	r24, 0x01	; 1
  2a:	71 f4       	brne	.+28     	; 0x48 <__SREG__+0x9>
            if (++pwm == TIMER1_TOP)
                direction = DOWN;
            break;

        case DOWN:
            if (--pwm == 0)
  2c:	80 91 60 00 	lds	r24, 0x0060
  30:	90 91 61 00 	lds	r25, 0x0061
  34:	01 97       	sbiw	r24, 0x01	; 1
  36:	90 93 61 00 	sts	0x0061, r25
  3a:	80 93 60 00 	sts	0x0060, r24
  3e:	00 97       	sbiw	r24, 0x00	; 0
  40:	39 f4       	brne	.+14     	; 0x50 <__SREG__+0x11>
                direction = UP;
  42:	10 92 62 00 	sts	0x0062, r1
  46:	04 c0       	rjmp	.+8      	; 0x50 <__SREG__+0x11>
  48:	80 91 60 00 	lds	r24, 0x0060
  4c:	90 91 61 00 	lds	r25, 0x0061
            break;
    }

    OCR = pwm;			/* Note [5] */
  50:	9b bd       	out	0x2b, r25	; 43
  52:	8a bd       	out	0x2a, r24	; 42
}
  54:	9f 91       	pop	r25
  56:	8f 91       	pop	r24
  58:	2f 91       	pop	r18
  5a:	0f 90       	pop	r0
  5c:	0f be       	out	0x3f, r0	; 63
  5e:	0f 90       	pop	r0
  60:	1f 90       	pop	r1
  62:	18 95       	reti
    static uint8_t direction;

    switch (direction)		/* Note [4] */
    {
        case UP:
            if (++pwm == TIMER1_TOP)
  64:	80 91 60 00 	lds	r24, 0x0060
  68:	90 91 61 00 	lds	r25, 0x0061
  6c:	01 96       	adiw	r24, 0x01	; 1
  6e:	90 93 61 00 	sts	0x0061, r25
  72:	80 93 60 00 	sts	0x0060, r24
  76:	8f 3f       	cpi	r24, 0xFF	; 255
  78:	23 e0       	ldi	r18, 0x03	; 3
  7a:	92 07       	cpc	r25, r18
  7c:	49 f7       	brne	.-46     	; 0x50 <__SREG__+0x11>
                direction = DOWN;
  7e:	21 e0       	ldi	r18, 0x01	; 1
  80:	20 93 62 00 	sts	0x0062, r18
  84:	e5 cf       	rjmp	.-54     	; 0x50 <__SREG__+0x11>

00000086 <ioinit>:

void
ioinit (void)			/* Note [6] */
{
    /* Timer 1 is 10-bit PWM (8-bit PWM on some ATtinys). */
    TCCR1A = TIMER1_PWM_INIT;
  86:	83 e8       	ldi	r24, 0x83	; 131
  88:	8f bd       	out	0x2f, r24	; 47
     * Start timer 1.
     *
     * NB: TCCR1A and TCCR1B could actually be the same register, so
     * take care to not clobber it.
     */
    TCCR1B |= TIMER1_CLOCKSOURCE;
  8a:	8e b5       	in	r24, 0x2e	; 46
  8c:	81 60       	ori	r24, 0x01	; 1
  8e:	8e bd       	out	0x2e, r24	; 46
#if defined(TIMER1_SETUP_HOOK)
    TIMER1_SETUP_HOOK();
#endif

    /* Set PWM value to 0. */
    OCR = 0;
  90:	1b bc       	out	0x2b, r1	; 43
  92:	1a bc       	out	0x2a, r1	; 42

    /* Enable OC1 as output. */
    DDROC = _BV (OC1);
  94:	82 e0       	ldi	r24, 0x02	; 2
  96:	87 bb       	out	0x17, r24	; 23

    /* Enable timer 1 overflow interrupt. */
    TIMSK = _BV (TOIE1);
  98:	84 e0       	ldi	r24, 0x04	; 4
  9a:	89 bf       	out	0x39, r24	; 57
    sei ();
  9c:	78 94       	sei
  9e:	08 95       	ret

000000a0 <main>:

void
ioinit (void)			/* Note [6] */
{
    /* Timer 1 is 10-bit PWM (8-bit PWM on some ATtinys). */
    TCCR1A = TIMER1_PWM_INIT;
  a0:	83 e8       	ldi	r24, 0x83	; 131
  a2:	8f bd       	out	0x2f, r24	; 47
     * Start timer 1.
     *
     * NB: TCCR1A and TCCR1B could actually be the same register, so
     * take care to not clobber it.
     */
    TCCR1B |= TIMER1_CLOCKSOURCE;
  a4:	8e b5       	in	r24, 0x2e	; 46
  a6:	81 60       	ori	r24, 0x01	; 1
  a8:	8e bd       	out	0x2e, r24	; 46
#if defined(TIMER1_SETUP_HOOK)
    TIMER1_SETUP_HOOK();
#endif

    /* Set PWM value to 0. */
    OCR = 0;
  aa:	1b bc       	out	0x2b, r1	; 43
  ac:	1a bc       	out	0x2a, r1	; 42

    /* Enable OC1 as output. */
    DDROC = _BV (OC1);
  ae:	82 e0       	ldi	r24, 0x02	; 2
  b0:	87 bb       	out	0x17, r24	; 23

    /* Enable timer 1 overflow interrupt. */
    TIMSK = _BV (TOIE1);
  b2:	84 e0       	ldi	r24, 0x04	; 4
  b4:	89 bf       	out	0x39, r24	; 57
    sei ();
  b6:	78 94       	sei
    ioinit ();

    /* loop forever, the interrupts are doing the rest */

    for (;;)			/* Note [7] */
        sleep_mode();
  b8:	85 b7       	in	r24, 0x35	; 53
  ba:	80 68       	ori	r24, 0x80	; 128
  bc:	85 bf       	out	0x35, r24	; 53
  be:	88 95       	sleep
  c0:	85 b7       	in	r24, 0x35	; 53
  c2:	8f 77       	andi	r24, 0x7F	; 127
  c4:	85 bf       	out	0x35, r24	; 53
  c6:	f8 cf       	rjmp	.-16     	; 0xb8 <main+0x18>

000000c8 <exit>:
  c8:	f8 94       	cli
  ca:	00 c0       	rjmp	.+0      	; 0xcc <_exit>

000000cc <_exit>:
  cc:	f8 94       	cli

000000ce <__stop_program>:
  ce:	ff cf       	rjmp	.-2      	; 0xce <__stop_program>

リンカーマップファイル

avr-objdumpはとても役に立ちますが、時にリンカによって生成されるリンクについての情報を見なければならないことがあります。マップファイルはこの情報を含みます。マップファイルは、あなたのコードとデータのサイズを見るのに役立ちます。それも、モジュールがどこにロードされるか、ライブラリからのどもモジュールが読み込まれたか示してくれます。これは、アプリケーションも別の見方になります。マップファイルえるために、通常はリンクコマンドに-Wl,-Map,demo.mapを追加します。demo.mapを生成するために、次のコマンドを使って再リンクします。(一部を下に示します。)

    $ avr-gcc -g -mmcu=atmega8 -Wl,-Map,demo.map -o demo.elf demo.o

demo.mapファイルには、いくつかの興味深いポイントがあります。

.rela.plt
*(.rela.plt)
.text 0x0000000000000000 0xd0
*(.vectors)
*(.vectors)
*(.progmem.gcc*)
0x0000000000000000 . = ALIGN (0x2)
0x0000000000000000 __trampolines_start = .
*(.trampolines)
.trampolines 0x0000000000000000 0x0 linker stubs
*(.trampolines*)
0x0000000000000000 __trampolines_end = .
*(.progmem*)
0x0000000000000000 . = ALIGN (0x2)
*(.jumptables)
*(.jumptables*)
*(.lowtext)
*(.lowtext*)
0x0000000000000000 __ctors_start = .

The .text セグメント(プログラム命令を格納)は、0x0の場所から始まります。

*(.fini2)
*(.fini2)
*(.fini1)
*(.fini1)
*(.fini0)
.fini0 0x00000000000000cc 0x4 /junk/testroot/lib/gcc/avr/5.3.0/avr4/libgcc.a(_exit.o)
*(.fini0)
0x00000000000000d0 _etext = .
.data 0x0000000000800060 0x0 load address 0x00000000000000d0
0x0000000000800060 PROVIDE (__data_start, .)
*(.data)
.data 0x0000000000800060 0x0 demo.o
.data 0x0000000000800060 0x0 /home/joerg/src/avr-libc/avr/lib/avr4/exit.o
.data 0x0000000000800060 0x0 /junk/testroot/lib/gcc/avr/5.3.0/avr4/libgcc.a(_exit.o)
.data 0x0000000000800060 0x0 /junk/testroot/lib/gcc/avr/5.3.0/avr4/libgcc.a(_clear_bss.o)
*(.data*)
*(.rodata)
*(.rodata*)
*(.gnu.linkonce.d*)
0x0000000000800060 . = ALIGN (0x2)
0x0000000000800060 _edata = .
0x0000000000800060 PROVIDE (__data_end, .)
.bss 0x0000000000800060 0x3
0x0000000000800060 PROVIDE (__bss_start, .)
*(.bss)
.bss 0x0000000000800060 0x3 demo.o
.bss 0x0000000000800063 0x0 /home/joerg/src/avr-libc/avr/lib/avr4/exit.o
.bss 0x0000000000800063 0x0 /junk/testroot/lib/gcc/avr/5.3.0/avr4/libgcc.a(_exit.o)
.bss 0x0000000000800063 0x0 /junk/testroot/lib/gcc/avr/5.3.0/avr4/libgcc.a(_clear_bss.o)
*(.bss*)
*(COMMON)
0x0000000000800063 PROVIDE (__bss_end, .)
0x00000000000000d0 __data_load_start = LOADADDR (.data)
0x00000000000000d0 __data_load_end = (__data_load_start + SIZEOF (.data))
.noinit 0x0000000000800063 0x0
0x0000000000800063 PROVIDE (__noinit_start, .)
*(.noinit*)
0x0000000000800063 PROVIDE (__noinit_end, .)
0x0000000000800063 _end = .
0x0000000000800063 PROVIDE (__heap_start, .)
.eeprom 0x0000000000810000 0x0
*(.eeprom*)
0x0000000000810000 __eeprom_end = .

.textセグメントの最後のアドレスは、0x114_etextのことを示す)で、命令はFLASHを276バイト使用しています。

.dataセグメント(静的変数の初期値を格納)は、0x60から開始しています。これは、ATmega8プロセッサのレジスタバンクの後の最初のアドレスです。

.dataセグメントの次に使用できるアドレスは0x60ですから、このアプリケーションには初期化されたデータがありません。

.bssセグメント(初期化されていないデータを格納)は、0x60の場所から開始しています。

.bssセグメントの次に使用できるアドレスは、0x63ですから、このアプリケーションは、初期化されないデータで3バイト使用します。

.eepromセグメント(EEPROMの変数を格納)は、0x0から開始します。

.eepromセグメントの次に使用できるアドレスは0x0ですから、EEPROMの変数はありません。

Intel Hexファイルの生成

アプリケーションのバイナリファイルがありますが、どうやってプロセッサに入れますか?(全てでないにしても)多くのプログラマー・書込み機は、実行可能なGNU実行ファイルを入力ファイルとして認めないため、もう少し処理する必要があります。次のステップは、バイナリの一部を抽出して、.hexファイルに情報を保存することです。これをするGNUユーティリティは、avr-objcopyと呼ばれます。

ROMコンテンツは、プロジェクトのバイナリから取り出すことができ、次のコマンドを使って、demo.hexファイルに入れることができます。

    $ avr-objcopy -j .text -j .data -O ihex demo.elf demo.hex

結果のdemo.hexファイルのには次の内容が含まれます。

:1000000020E0A0E6B0E001C01D92A336B207E1F700
:100010001F920F920FB60F9211242F938F939F93DD
:10002000809162008823F1F0813071F4809160004A
:100030009091610001979093610080936000009718
:1000400039F41092620004C08091600090916100C8
:100050009BBD8ABD9F918F912F910F900FBE0F90E6
:100060001F90189580916000909161000196909387
:100070006100809360008F3F23E0920749F721E001
:1000800020936200E5CF83E88FBD8EB581608EBD81
:100090001BBC1ABC82E087BB84E089BF78940895BA
:1000A00083E88FBD8EB581608EBD1BBC1ABC82E01B
:1000B00087BB84E089BF789485B7806885BF8895C1
:1000C00085B78F7785BFF8CFF89400C0F894FFCF3D
:00000001FF

-jオプションにより、.textと.dataセグメントから情報をえることを指示します。EEPROMセグメントを指定すると、EEPROMをプログラムするのに使用する.hexファイルを生成することができます。

    $ avr-objcopy -j .eeprom --change-section-lma .eeprom=0 -O ihex demo.elf demo_eeprom.hex

ここでは、demo_eeprom.hexファイルは何も書かれるものはなく、空のファイルになります。

GNU binutilsのバージョン2.17からは、avr-objcopyは、.eepromセクションが空の入力であると空のEEPROMファイルを生成せずに直ちに中止されます。これを捕らえることでMakefileにエラー通知し、空のファイルが生成されていないことをメッセージで表示させます。

プロジェクトをMake構築する

何度もこれらのコマンドを入力しなくても、makeファイルに全てを設定することができます。デモプロジェクトの構築にmakeを使用しており、Makefileと呼ばれるつぎのファイルに保存しています。

注意
このMakefileは、GNUバージョンのmakeでのみ使用できます。
PRG = demo
OBJ = demo.o
#MCU_TARGET = at90s2313
#MCU_TARGET = at90s2333
#MCU_TARGET = at90s4414
#MCU_TARGET = at90s4433
#MCU_TARGET = at90s4434
#MCU_TARGET = at90s8515
#MCU_TARGET = at90s8535
#MCU_TARGET = atmega128
#MCU_TARGET = atmega1280
#MCU_TARGET = atmega1281
#MCU_TARGET = atmega1284p
#MCU_TARGET = atmega16
#MCU_TARGET = atmega163
#MCU_TARGET = atmega164p
#MCU_TARGET = atmega165
#MCU_TARGET = atmega165p
#MCU_TARGET = atmega168
#MCU_TARGET = atmega169
#MCU_TARGET = atmega169p
#MCU_TARGET = atmega2560
#MCU_TARGET = atmega2561
#MCU_TARGET = atmega32
#MCU_TARGET = atmega324p
#MCU_TARGET = atmega325
#MCU_TARGET = atmega3250
#MCU_TARGET = atmega329
#MCU_TARGET = atmega3290
#MCU_TARGET = atmega32u4
#MCU_TARGET = atmega48
#MCU_TARGET = atmega64
#MCU_TARGET = atmega640
#MCU_TARGET = atmega644
#MCU_TARGET = atmega644p
#MCU_TARGET = atmega645
#MCU_TARGET = atmega6450
#MCU_TARGET = atmega649
#MCU_TARGET = atmega6490
MCU_TARGET = atmega8
#MCU_TARGET = atmega8515
#MCU_TARGET = atmega8535
#MCU_TARGET = atmega88
#MCU_TARGET = attiny2313
#MCU_TARGET = attiny24
#MCU_TARGET = attiny25
#MCU_TARGET = attiny26
#MCU_TARGET = attiny261
#MCU_TARGET = attiny44
#MCU_TARGET = attiny45
#MCU_TARGET = attiny461
#MCU_TARGET = attiny84
#MCU_TARGET = attiny85
#MCU_TARGET = attiny861
OPTIMIZE = -O2
DEFS =
LIBS =
# You should not have to change anything below here.
CC = avr-gcc
# Override is only needed by avr-lib build system.
override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS)
override LDFLAGS = -Wl,-Map,$(PRG).map
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
all: $(PRG).elf lst text eeprom
$(PRG).elf: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
# dependency:
demo.o: demo.c iocompat.h
clean:
rm -rf *.o $(PRG).elf *.eps *.png *.pdf *.bak
rm -rf *.lst *.map $(EXTRA_CLEAN_FILES)
lst: $(PRG).lst
%.lst: %.elf
$(OBJDUMP) -h -S $< > $@
# Rules for building the .text rom images
text: hex bin srec
hex: $(PRG).hex
bin: $(PRG).bin
srec: $(PRG).srec
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex $< $@
%.srec: %.elf
$(OBJCOPY) -j .text -j .data -O srec $< $@
%.bin: %.elf
$(OBJCOPY) -j .text -j .data -O binary $< $@
# Rules for building the .eeprom rom images
eeprom: ehex ebin esrec
ehex: $(PRG)_eeprom.hex
ebin: $(PRG)_eeprom.bin
esrec: $(PRG)_eeprom.srec
%_eeprom.hex: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ \
|| { echo empty $@ not generated; exit 0; }
%_eeprom.srec: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O srec $< $@ \
|| { echo empty $@ not generated; exit 0; }
%_eeprom.bin: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O binary $< $@ \
|| { echo empty $@ not generated; exit 0; }
# Every thing below here is used by avr-libc's build system and can be ignored
# by the casual user.
FIG2DEV = fig2dev
EXTRA_CLEAN_FILES = *.hex *.bin *.srec
dox: eps png pdf
eps: $(PRG).eps
png: $(PRG).png
pdf: $(PRG).pdf
%.eps: %.fig
$(FIG2DEV) -L eps $< $@
%.pdf: %.fig
$(FIG2DEV) -L pdf $< $@
%.png: %.fig
$(FIG2DEV) -L png $< $@

ソースコードの参照