- 追加された行はこの色です。
- 削除された行はこの色です。
[[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