2009/05/20 からのアクセス回数 11570 サンプルプログラム †組み込みソフトで最初のプログラムは、いつもLEDの点滅です。 Interface 2009/5月号では、LEDの点滅プログラムに割り込みを使っていましたが、 これは大きなルール違反です。 最初のプログラムは、できるだけシンプルにし、最低限の設定にしないとうまく動かなかった 時に、原因の切り分けが難しくなります。 今回のプログラムは、 nandさんのテストプログラム を参考に、Olimex のサイトにあった LED を点滅させるプログラムから、crt0.S, リンクコマンドファイル を修正し、必要最低限にカットしました。 Eclipseプロジェクトの作成 †最初に、Eclipseに組み込み用Cのプロジェクトを作成します。 File->New->C Project...を選択するか、図の用に右クリックでC Project...を選択します。 次にProjectnmae:にプロジェクト名を入力します。ここでは、sam7s-t0としました。 Project type:として、Makefile projectのEmpty Projectを選択し、-- Other Toolchain --を選択して Finishボタンを押します。 プロジェクトができたら、 ファイルの説明 †srcディレクトリには、以下のファイルが含まれています。
main.c †main.cは、非常にシンプルです。 PIO_PER, PIO_OERを設定し、2個のLEDを交互に点滅するために、PIO_CODR, PIO_SODRを設定し、 delayで時間間隔をとります。 #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 †Makefileは、デフォルトのルールを使って、オブジェクトファイルまでコンパイルを行い、最後の allで、ELFファイル(main.out)、バイナリファイル(main.bin)を作成します。
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 †crt0.S, sam7s_ram.cmdは、長いのと私のフォロー範囲を超えているので、 修正したポイントだけを説明します。 crt0.Sでは、
をします。 割り込みベクトルの設定は以下のように定義しています。 /* 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:の /* 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の 部分を修正しました。 /* 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; makeとデバッグ †通常は、EclipseのMakeを使うのですが、その都度設定するのは面倒なので、ターミナルから makeとopenocdの起動を行います。 make †ターミナルを起動し、プロジェクトのディレクトリに移動します。 $ cd ~/local/workspace/sam7s-t0 $ make エラーがなければ、これでmakeは完了です。 デバッグ設定 †次にEclipseでデバッガの設定をします。 RunメニューからDebug Configurations...を選択すると図のような設定画面が表示されます。
次にDebuggerタグを選択します。
最後にCommandsタグを選択します。
通常は、最後に load をしていするのですが、USB Blasterのドライバーがわるいのか、途中でエラーになってしまいますので、 #でコメントアウトしています。 これで、Closeを選択して設定を保存します。 Openocdの起動とデバッグ †openocd.cfgとして今回は、以下のようの内容を設定します。 #define our ports telnet_port 4444 gdb_port 3333 #commands specific to the USB Blaster interface usb_blaster usb_blaster_vid_pid 0x09fb 0x6001 #reset_config <signals> [combination] [trst_type] [srst_type] reset_config srst_only srst_pulls_trst #jtag_device <IR length> <IR capture> <IR mask> <IDCODE instruction> jtag_device 4 0x1 0xf 0xe #daemon_startup <'attach'|'reset'> daemon_startup reset #target <type> <endianess> <reset_mode> <jtag#> [variant] target arm7tdmi little run_and_init 0 arm7tdmi_r4 #working_area <target#> <address> <size> <'backup'|'nobackup'> working_area 0 0x00200000 0x4000 nobackup #run_and_halt_time <target#> <time_in_ms> run_and_halt_time 0 30 ターミナルからopenocdを起動します、以下のようにデバイスを認識すればOKです。 $ openocd -f openocd.cfg Open On-Chip Debugger 1.0 (2009-04-13-07:33) svn:753M $URL: svn://svn.berlios.de/openocd/trunk/src/openocd.c $ Info: options.c:50 configuration_output_handler(): Open On-Chip Debugger 1.0 (2009-04-13-07:33) svn:753M Info: jtag.c:1403 jtag_examine_chain(): JTAG device found: 0x3f0f0f0f (Manufacturer: 0x787, Part: 0xf0f0, Version: 0x3) loadがデバッグ設定でできなかったので、手動でプログラムをロードします。 別のターミナルで
と、少し時間がかかりますが、以下のように出力されます。 term-2 $ telnet localhost 4444 Trying ::1... telnet: connect to address ::1: Connection refused Trying fe80::1... telnet: connect to address fe80::1: Connection refused Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Open On-Chip Debugger > load_image main.out 388 byte written at address 0x00200000 downloaded 388 byte in 22.681808s > 最後にEclipseのDebugを実行します。 指定したブレークポイントで止まればOKです。USB Blasterのドライバーとても遅く、1分ほどかかります。 ステップ実行もとても遅いですが、プログラムが期待通りに動かなかった最後の砦として、 デバッガは有効です。 ROMへの書き込み †このままでは、電源を切るとプログラムが消えてしまいますので、ROMへの書き込みを行います。 では、なぜRAMに書き込んでいたのでしょう。 RAMのメリットは、
RAMの欠点は
makeの変更 †話を先にすすめて、makeの設定を変更します。 Makefileをコピーして、以下の設定を変更します LFLAGS = -Map main.map -Tsam7s_ram.cmd を LFLAGS = -Map main.map -Tsam7s_rom.cmd にします。 さらに、以下のファイルを追加します。
ここで、script.ocdのFlushへの書き込みコマンドは、openocdのバージョンに よって異なります。ご使用のバージョンに合わせて変更してください。 今回は、flash write_bank を使用しました。 # flash write 0 main.bin 0x0 # flash write is deprecated and my not be available in your OpenOCD-version, update to: # flash write_binary 0 main.bin 0x0 # flash write_binary is deprecated and my not be available in your OpenOCD-version, update to: flash write_bank 0 main.bin 0x0 makeと書き込み †準備ができたので、ターミナルから以下のコマンドを実行します。 $ make clean $ make -f Makefile.rom $ openocd -f openocd-rom.cfg 書き込みが終わったら、JTAGライターをケーブルを外して、ボードの電源を入れ直してください。 LEDが点滅すれば成功です。 ROM版のデバッグ †デバッグ設定は、RAMとROMで若干ことなります。
では、ターミナルでopenocdを起動して、 $ openocd -f openocd.cfg デバッグ対象として、sam7s-t0-romを選択します。
しかし、RAMと同様におそいながらも、デバッグできます。 コメント †この記事は、 皆様のご意見、ご希望をお待ちしております。 Tweet |