AVR Libc Home Page | AVR Libc Development Pages | ||||
Main Page | User Manual | Library Reference | FAQ | Alphabetical Index | Example Projects |
ここまでに、GNUツールをあなたのシステムにインストール、構築して設定しておかなければなりません。この章では、AVRプロジェクトでのGNUツールの簡単な使用方法の例を紹介しています。この章を読んだあとに、ツールがどのように使われるか、Makefile
がどのように設定されるかをより良い感触がつかめるでしょう。
このプロジェクトは、2秒ごとにLEDをパルス幅変調(PWM
)で徐々に点滅させます。AT90S2313プロセッサをコントローラとして使用します。このデモンストレーション用回路は、回路図に示します。もし開発キットを持っていれば、このプロジェクトのために回路を作るよりも、開発キットを使うことができるでしょう。
Schematic of circuit for demo project
ソースコードはdemo.cにあります。この例のために、このソースコードを含むdemo.c
を作成してください。コードのより重要ないくつかの部分は次の通りです。
iocompat.h
ファイルは、プリプロセッサの#ifdef
命令文を用いてこれら全ての違いを抽象化しようとしています。そして、実際のプログラムでは、共通のシンボル名のセットを用いて操作するこができます。このファイルで定義されているマクロは次の通りです。OCR
:OCRレジスタ名(通常OCR1やOCR1A)で、PWM制御に使用DDROC
:OC出力のためのDDR(データ方向レジスタ)の名前OC1
:ポート内のOC1[A]のピン番号TIMER1_TOP
:PWMに用いるタイマーのTOP値(10-bit PWMは1023、8-bit PWMしか扱えないデバイスは255)TIMER1_PWM_INIT
:10ビット(または8ビット)の位相と周波数が正しいPWMモードに適切に設定する1A制御レジスタの初期化ビットTIMER1_CLOCKSOURCE
:PWMタイマーをスタートするための制御レジスタのクロックビットのセットで、通常は10ビットPWMではCPUクロックでタイマーを動作させ、8ビットPWMでは、分周波されたクロックでタイマーを動かす。PWM
が10ビットモードで使われているため、現在の値を記憶するために16ビットの変数が必要になります。PWM
の新しい値を決定します。PWM
レジスタにロードします。割込み処理の中にいるため、レジスタに16ビットの代入を使うことは安全です。割込みの外であって、割込み処理がこのレジスタ(または、TEMP
を使用する別のレジスタ)にアクセスすることが出来たという可能性があるならば、代入は割込みを使用不可能にして実行されなければなりません。FAQ entryの適切な項を見てください。PWM
の初期化と割込みを許可します。sleep_mode()
は、次の割込みまでプロセッサを休止状態にし、電力を削減します。もちろん、LEDを動かしているので、それは顕著ではないでしょう。ただ、基本原則のデモをここでは述べているだけです。/* * ---------------------------------------------------------------------------- * "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] */ sleep_mode(); 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
があります。これは、オブジェクトファイルから情報を取り出し、役立つ情報を表示します。このコマンド自体を入力すると、オプションを一覧表示します。
たとえば、アプリケーションのサイズの雰囲気をつかむために、 option can be used. オプションを使うことができます。このオプションの出力は、各セクションでどれだけのスペースを使用しているかを表示します。(.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 000000fa 00000000 00000000 00000074 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .bss 00000003 00800060 00800060 0000016e 2**0 ALLOC 2 .stab 00000b88 00000000 00000000 00000170 2**2 CONTENTS, READONLY, DEBUGGING 3 .stabstr 0000077e 00000000 00000000 00000cf8 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: 00000000 <__vectors>: 0: 12 c0 rjmp .+36 ; 0x26 <__ctors_end> 2: 76 c0 rjmp .+236 ; 0xf0 <__bad_interrupt> 4: 75 c0 rjmp .+234 ; 0xf0 <__bad_interrupt> 6: 74 c0 rjmp .+232 ; 0xf0 <__bad_interrupt> 8: 73 c0 rjmp .+230 ; 0xf0 <__bad_interrupt> a: 72 c0 rjmp .+228 ; 0xf0 <__bad_interrupt> c: 71 c0 rjmp .+226 ; 0xf0 <__bad_interrupt> e: 70 c0 rjmp .+224 ; 0xf0 <__bad_interrupt> 10: 1a c0 rjmp .+52 ; 0x46 <__vector_8> 12: 6e c0 rjmp .+220 ; 0xf0 <__bad_interrupt> 14: 6d c0 rjmp .+218 ; 0xf0 <__bad_interrupt> 16: 6c c0 rjmp .+216 ; 0xf0 <__bad_interrupt> 18: 6b c0 rjmp .+214 ; 0xf0 <__bad_interrupt> 1a: 6a c0 rjmp .+212 ; 0xf0 <__bad_interrupt> 1c: 69 c0 rjmp .+210 ; 0xf0 <__bad_interrupt> 1e: 68 c0 rjmp .+208 ; 0xf0 <__bad_interrupt> 20: 67 c0 rjmp .+206 ; 0xf0 <__bad_interrupt> 22: 66 c0 rjmp .+204 ; 0xf0 <__bad_interrupt> 24: 65 c0 rjmp .+202 ; 0xf0 <__bad_interrupt> 00000026 <__ctors_end>: 26: 11 24 eor r1, r1 28: 1f be out 0x3f, r1 ; 63 2a: cf e5 ldi r28, 0x5F ; 95 2c: d4 e0 ldi r29, 0x04 ; 4 2e: de bf out 0x3e, r29 ; 62 30: cd bf out 0x3d, r28 ; 61 00000032 <__do_clear_bss>: 32: 10 e0 ldi r17, 0x00 ; 0 34: a0 e6 ldi r26, 0x60 ; 96 36: b0 e0 ldi r27, 0x00 ; 0 38: 01 c0 rjmp .+2 ; 0x3c <.do_clear_bss_start> 0000003a <.do_clear_bss_loop>: 3a: 1d 92 st X+, r1 0000003c <.do_clear_bss_start>: 3c: a3 36 cpi r26, 0x63 ; 99 3e: b1 07 cpc r27, r17 40: e1 f7 brne .-8 ; 0x3a <.do_clear_bss_loop> 42: 4d d0 rcall .+154 ; 0xde <main> 44: 56 c0 rjmp .+172 ; 0xf2 <exit> 00000046 <__vector_8>: #include "iocompat.h" /* Note [1] */ enum { UP, DOWN }; ISR (TIMER1_OVF_vect) /* Note [2] */ { 46: 1f 92 push r1 48: 0f 92 push r0 4a: 0f b6 in r0, 0x3f ; 63 4c: 0f 92 push r0 4e: 11 24 eor r1, r1 50: 2f 93 push r18 52: 3f 93 push r19 54: 8f 93 push r24 static uint16_t pwm; /* Note [3] */ static uint8_t direction; switch (direction) /* Note [4] */ 56: 80 91 60 00 lds r24, 0x0060 5a: 88 23 and r24, r24 5c: c1 f4 brne .+48 ; 0x8e <__vector_8+0x48> { case UP: if (++pwm == TIMER1_TOP) 5e: 20 91 61 00 lds r18, 0x0061 62: 30 91 62 00 lds r19, 0x0062 66: 2f 5f subi r18, 0xFF ; 255 68: 3f 4f sbci r19, 0xFF ; 255 6a: 30 93 62 00 sts 0x0062, r19 6e: 20 93 61 00 sts 0x0061, r18 72: 83 e0 ldi r24, 0x03 ; 3 74: 2f 3f cpi r18, 0xFF ; 255 76: 38 07 cpc r19, r24 78: 09 f1 breq .+66 ; 0xbc <__vector_8+0x76> if (--pwm == 0) direction = UP; break; } OCR = pwm; /* Note [5] */ 7a: 3b bd out 0x2b, r19 ; 43 7c: 2a bd out 0x2a, r18 ; 42 } 7e: 8f 91 pop r24 80: 3f 91 pop r19 82: 2f 91 pop r18 84: 0f 90 pop r0 86: 0f be out 0x3f, r0 ; 63 88: 0f 90 pop r0 8a: 1f 90 pop r1 8c: 18 95 reti ISR (TIMER1_OVF_vect) /* Note [2] */ { static uint16_t pwm; /* Note [3] */ static uint8_t direction; switch (direction) /* Note [4] */ 8e: 81 30 cpi r24, 0x01 ; 1 90: 29 f0 breq .+10 ; 0x9c <__vector_8+0x56> 92: 20 91 61 00 lds r18, 0x0061 96: 30 91 62 00 lds r19, 0x0062 9a: ef cf rjmp .-34 ; 0x7a <__vector_8+0x34> if (++pwm == TIMER1_TOP) direction = DOWN; break; case DOWN: if (--pwm == 0) 9c: 20 91 61 00 lds r18, 0x0061 a0: 30 91 62 00 lds r19, 0x0062 a4: 21 50 subi r18, 0x01 ; 1 a6: 30 40 sbci r19, 0x00 ; 0 a8: 30 93 62 00 sts 0x0062, r19 ac: 20 93 61 00 sts 0x0061, r18 b0: 21 15 cp r18, r1 b2: 31 05 cpc r19, r1 b4: 11 f7 brne .-60 ; 0x7a <__vector_8+0x34> direction = UP; b6: 10 92 60 00 sts 0x0060, r1 ba: df cf rjmp .-66 ; 0x7a <__vector_8+0x34> switch (direction) /* Note [4] */ { case UP: if (++pwm == TIMER1_TOP) direction = DOWN; bc: 81 e0 ldi r24, 0x01 ; 1 be: 80 93 60 00 sts 0x0060, r24 c2: db cf rjmp .-74 ; 0x7a <__vector_8+0x34> 000000c4 <ioinit>: void ioinit (void) /* Note [6] */ { /* Timer 1 is 10-bit PWM (8-bit PWM on some ATtinys). */ TCCR1A = TIMER1_PWM_INIT; c4: 83 e8 ldi r24, 0x83 ; 131 c6: 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; c8: 8e b5 in r24, 0x2e ; 46 ca: 81 60 ori r24, 0x01 ; 1 cc: 8e bd out 0x2e, r24 ; 46 #if defined(TIMER1_SETUP_HOOK) TIMER1_SETUP_HOOK(); #endif /* Set PWM value to 0. */ OCR = 0; ce: 1b bc out 0x2b, r1 ; 43 d0: 1a bc out 0x2a, r1 ; 42 /* Enable OC1 as output. */ DDROC = _BV (OC1); d2: 82 e0 ldi r24, 0x02 ; 2 d4: 87 bb out 0x17, r24 ; 23 /* Enable timer 1 overflow interrupt. */ TIMSK = _BV (TOIE1); d6: 84 e0 ldi r24, 0x04 ; 4 d8: 89 bf out 0x39, r24 ; 57 sei (); da: 78 94 sei } dc: 08 95 ret 000000de <main>: int main (void) { ioinit (); de: f2 df rcall .-28 ; 0xc4 <ioinit> /* loop forever, the interrupts are doing the rest */ for (;;) /* Note [7] */ sleep_mode(); e0: 85 b7 in r24, 0x35 ; 53 e2: 80 68 ori r24, 0x80 ; 128 e4: 85 bf out 0x35, r24 ; 53 e6: 88 95 sleep e8: 85 b7 in r24, 0x35 ; 53 ea: 8f 77 andi r24, 0x7F ; 127 ec: 85 bf out 0x35, r24 ; 53 ee: f8 cf rjmp .-16 ; 0xe0 <main+0x2> 000000f0 <__bad_interrupt>: f0: 87 cf rjmp .-242 ; 0x0 <__vectors> 000000f2 <exit>: ASSEMBLY_CLIB_SECTION .global _U(exit) .type _U(exit), "function" _U(exit): cli f2: f8 94 cli XJMP _U(_exit) f4: 00 c0 rjmp .+0 ; 0xf6 <_exit> 000000f6 <_exit>: f6: f8 94 cli 000000f8 <__stop_program>: f8: ff cf rjmp .-2 ; 0xf8 <__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 0x00000000 0xfa *(.vectors) .vectors 0x00000000 0x26 /home/joerg/src/avr-libc/avr/lib/avr4/atmega8/crtm8.o 0x00000000 __vectors 0x00000000 __vector_default *(.vectors) *(.progmem.gcc*) *(.progmem*) 0x00000026 . = ALIGN (0x2) 0x00000026 __trampolines_start = . *(.trampolines) .trampolines 0x00000026 0x0 linker stubs *(.trampolines*) 0x00000026 __trampolines_end = . *(.jumptables) *(.jumptables*) *(.lowtext) *(.lowtext*) 0x00000026 __ctors_start = .
.text セグメント(プログラム命令を格納)は、0x0の場所から始まります。
*(.fini2) *(.fini2) *(.fini1) *(.fini1) *(.fini0) .fini0 0x000000f6 0x4 /usr/local/lib/gcc/avr/4.3.4/avr4/libgcc.a(_exit.o) *(.fini0) 0x000000fa _etext = . .data 0x00800060 0x0 load address 0x000000fa 0x00800060 PROVIDE (__data_start, .) *(.data) .data 0x00800060 0x0 demo.o .data 0x00800060 0x0 /home/joerg/src/avr-libc/avr/lib/avr4/atmega8/crtm8.o .data 0x00800060 0x0 /home/joerg/src/avr-libc/avr/lib/avr4/exit.o .data 0x00800060 0x0 /usr/local/lib/gcc/avr/4.3.4/avr4/libgcc.a(_exit.o) .data 0x00800060 0x0 /usr/local/lib/gcc/avr/4.3.4/avr4/libgcc.a(_clear_bss.o) *(.data*) *(.rodata) *(.rodata*) *(.gnu.linkonce.d*) 0x00800060 . = ALIGN (0x2) 0x00800060 _edata = . 0x00800060 PROVIDE (__data_end, .) .bss 0x00800060 0x3 0x00800060 PROVIDE (__bss_start, .) *(.bss) .bss 0x00800060 0x3 demo.o .bss 0x00800063 0x0 /home/joerg/src/avr-libc/avr/lib/avr4/atmega8/crtm8.o .bss 0x00800063 0x0 /home/joerg/src/avr-libc/avr/lib/avr4/exit.o .bss 0x00800063 0x0 /usr/local/lib/gcc/avr/4.3.4/avr4/libgcc.a(_exit.o) .bss 0x00800063 0x0 /usr/local/lib/gcc/avr/4.3.4/avr4/libgcc.a(_clear_bss.o) *(.bss*) *(COMMON) 0x00800063 PROVIDE (__bss_end, .) 0x000000fa __data_load_start = LOADADDR (.data) 0x000000fa __data_load_end = (__data_load_start + SIZEOF (.data)) .noinit 0x00800063 0x0 0x00800063 PROVIDE (__noinit_start, .) *(.noinit*) 0x00800063 PROVIDE (__noinit_end, .) 0x00800063 _end = . 0x00800063 PROVIDE (__heap_start, .) .eeprom 0x00810000 0x0 *(.eeprom*) 0x00810000 __eeprom_end = .
.textセグメントの最後のアドレスは、
0x114
(_etext
のことを示す)で、命令はFLASHを276バイト使用します。
.dataセグメント(静的変数の初期値を格納)は、
0x60
から開始していますう。これは、ATmega8プロセッサのレジスタバンクの後の最初のアドレスです。
.dataセグメントの次に使用できるアドレスは
0x60
ですから、このアプリケーションには初期化されたデータがありません。
.bssセグメント(初期化されていないデータを格納)は、
0x60
の場所から開始しています。
.bssセグメントの次に使用できるアドレスは、0x63ですから、このアプリケーションは、初期化されないデータで3バイト使用します。
.eepromセグメント(EEPROMの変数を格納)は、0x0から開始します。
.eepromセグメントの次に使用できるアドレスは0x0ですから、EEPROMの変数はありません。
アプリケーションのバイナリファイルがありますが、どうやってプロセッサに入れますか?(全て出ないにしても)多くのプログラマーは実行可能なGNU実行ファイルを入力ファイルとして認めないため、もう少し処理する必要があります。次のステップは、バイナリの一部を抽出して、.hexファイルに情報を保存することです。これをするGNUユーティリティは、
avr-objcopy
と呼ばれます。
ROMコンテンツは、プロジェクトのバイナリから取り出すことができ、次の個万を使って、demo.hexファイルに入れることができます。
$ avr-objcopy -j .text -j .data -O ihex demo.elf demo.hex
結果のdemo.hex
ファイルのには次の内容が含まれます。
:1000000012C076C075C074C073C072C071C070C0B9 :100010001AC06EC06DC06CC06BC06AC069C068C0D9 :1000200067C066C065C011241FBECFE5D4E0DEBF47 :10003000CDBF10E0A0E6B0E001C01D92A336B1072D :10004000E1F74DD056C01F920F920FB60F921124B8 :100050002F933F938F93809160008823C1F4209168 :100060006100309162002F5F3F4F30936200209318 :10007000610083E02F3F380709F13BBD2ABD8F9116 :100080003F912F910F900FBE0F901F9018958130C8 :1000900029F02091610030916200EFCF2091610042 :1000A0003091620021503040309362002093610013 :1000B0002115310511F710926000DFCF81E08093A8 :1000C0006000DBCF83E88FBD8EB581608EBD1BBC29 :1000D0001ABC82E087BB84E089BF78940895F2DF80 :1000E00085B7806885BF889585B78F7785BFF8CF3E :0A00F00087CFF89400C0F894FFCF0A :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からは、空のEEPROMファイルを生成するのに使用されるavr-objcopy
が、.eepromセクションが空の入力であるため直ちに中止されます。それを捕らえるMakefileにエラーを知らせて、空のファイルが生成されていないことについてメッセージを表示させます。
何度もこれらのコマンドを入力するよりはむしろ、作るためのファイルに全てを設定することができます。デモプロジェクトの構築に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 = 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 $< $@