[[FrontPage]] 2009/05/20 からのアクセス回数 &counter; #contents ** サンプルプログラム [#qbca2fe2] 組み込みソフトで最初のプログラムは、いつもLEDの点滅です。 Interface 2009/5月号では、LEDの点滅プログラムに割り込みを使っていましたが、 これは大きなルール違反です。 最初のプログラムは、できるだけシンプルにし、最低限の設定にしないとうまく動かなかった 時に、原因の切り分けが難しくなります。 今回のプログラムは、 [[nandさんのテストプログラム>http://homepage.mac.com/nand/hacks/olimex-sam7p64.html]] を参考に、Olimex のサイトにあった LED を点滅させるプログラムから、crt0.S, リンクコマンドファイル を修正し、必要最低限にカットしました。 ** Eclipseプロジェクトの作成 [#we68027a] 最初に、Eclipseに組み込み用Cのプロジェクトを作成します。 File->New->C Project...を選択するか、図の用に右クリックでC Project...を選択します。 &ref(eclipse-1.jpg); 次にProjectnmae:にプロジェクト名を入力します。ここでは、sam7s-t0としました。 Project type:として、Makefile projectのEmpty Projectを選択し、-- Other Toolchain --を選択して Finishボタンを押します。 &ref(eclipse-2.jpg); プロジェクトができたら、&ref(src.zip);を解凍し、srcフォルダ以下のファイルをプロジェクトにドラッグします。 ** ファイルの説明 [#fee86a45] srcディレクトリには、以下のファイルが含まれています。 - AT91SAM7S64.h: sam7sのヘッダファイルです(Olimexのサンプルから引用) - crt0.S: Cルート0呼びます。Cのmain関数を呼ぶための前処理をします(Olimexのサンプルを修正) - main.c: Cのメインプログラムです(nandさんのプログラムから修正) - Makefile: makeコマンド用の設定ファイルです(nandさんのプログラムから修正) - sam7s_ram.cmd: リンク用のコマンドファイルで、RAM用のプログラムを作成します(Olimexのサンプルを修正) *** main.c [#d86c5351] main.cは、非常にシンプルです。 PIO_PER, PIO_OERを設定し、2個のLEDを交互に点滅するために、PIO_CODR, PIO_SODRを設定し、 delayで時間間隔をとります。 #pre{{ #include "AT91SAM7S64.h" #define DELAY_COUNT 5769 // for 18.432MHz (original 6000000 for 48MHz) void delay(int n); int main() { AT91C_BASE_PIOA->PIO_PER = (1 << 17) | (1 << 18); AT91C_BASE_PIOA->PIO_OER = (1 << 17) | (1 << 18); for (;;) { AT91C_BASE_PIOA->PIO_CODR = (1 << 18); AT91C_BASE_PIOA->PIO_SODR = (1 << 17); delay(DELAY_COUNT); AT91C_BASE_PIOA->PIO_SODR = (1 << 18); AT91C_BASE_PIOA->PIO_CODR = (1 << 17); delay(DELAY_COUNT); } } void delay(int n) { while (--n) ; } }} *** Makefile [#e55540e2] Makefileは、デフォルトのルールを使って、オブジェクトファイルまでコンパイルを行い、最後の allで、ELFファイル(main.out)、バイナリファイル(main.bin)を作成します。 - 最初に、使用するコマンドを定義しています。 - ファイルを追加する場合には、OBJECTSに追加したファイルのオブジェクトファイル名を追加します。 #pre{{ CC = /opt/local/bin/arm-elf-gcc AS = /opt/local/bin/arm-elf-as LD = /opt/local/bin/arm-elf-ld -v CP = /opt/local/bin/arm-elf-objcopy OD = /opt/local/bin/arm-elf-objdump CFLAGS = -march=armv4t -mthumb -g ASFLAGS = -Wa,-mthumb LFLAGS = -Map main.map -Tsam7s_ram.cmd OBJECTS = crt0.o main.o all: crt0.o main.o $(LD) $(LFLAGS) -o main.out -Map main.map $(OBJECTS) $(CP) -j .text -j .data -O binary main.out main.bin $(OD) -x --syms main.out > main.dmp main.o: main.c crt0.o: crt0.S clean: rm -f $(OBJECTS) main.out main.bin main.map main.dmp }} *** crt0.S, sam7s_ram.cmd [#da412e52] crt0.S, sam7s_ram.cmdは、長いのと私のフォロー範囲を超えているので、 修正したポイントだけを説明します。 crt0.Sでは、 - 割り込みベクトルの設定 - グローバル変数のRAM領域へのコピー をします。 割り込みベクトルの設定は以下のように定義しています。 #pre{{ /* identify all GLOBAL symbols */ .global _vec_reset .global _vec_undef .global _vec_swi .global _vec_pabt .global _vec_dabt .global _vec_rsv .global _vec_irq .global _vec_fiq .global AT91F_Irq_Handler .global AT91F_Default_FIQ_handler .global AT91F_Default_IRQ_handler }} グローバル変数のRAM領域へのコピーは、_init_reset:の #pre{{ /* copy initialized variables .data section (Copy from ROM to RAM) */ ldr R1, =_etext ldr R2, =_data ldr R3, =_edata 1: cmp R2, R3 ldrlo R0, [R1], #4 strlo R0, [R2], #4 blo 1b }} のように定義しています。 sam7s_ram.cmdは、リンク用のコマンドで、MEMORY定義と_stack_endの 部分を修正しました。 #pre{{ /* specify the AT91SAM7S64 memory areas */ MEMORY { flash : ORIGIN = 0, LENGTH = 256K /* FLASH EPROM */ ram : ORIGIN = 0x00200000, LENGTH = 64K /* static RAM area */ } /* define a global symbol _stack_end (see analysis in annotation above) */ _stack_end = 0x0000FFFC; }} ** コメント [#za87c24f] この記事は、 #vote(おもしろかった,そうでもない,わかりずらい) 皆様のご意見、ご希望をお待ちしております。 #comment_kcaptcha