FrontPage

2009/05/20 からのアクセス回数 7098

サンプルプログラム

組み込みソフトで最初のプログラムは、いつもLEDの点滅です。 Interface 2009/5月号では、LEDの点滅プログラムに割り込みを使っていましたが、 これは大きなルール違反です。

最初のプログラムは、できるだけシンプルにし、最低限の設定にしないとうまく動かなかった 時に、原因の切り分けが難しくなります。

今回のプログラムは、 nandさんのテストプログラム を参考に、Olimex のサイトにあった LED を点滅させるプログラムから、crt0.S, リンクコマンドファイル を修正し、必要最低限にカットしました。

Eclipseプロジェクトの作成

最初に、Eclipseに組み込み用Cのプロジェクトを作成します。 File->New->C Project...を選択するか、図の用に右クリックでC Project...を選択します。

eclipse-1.jpg

次にProjectnmae:にプロジェクト名を入力します。ここでは、sam7s-t0としました。 Project type:として、Makefile projectのEmpty Projectを選択し、-- Other Toolchain --を選択して Finishボタンを押します。

eclipse-2.jpg

プロジェクトができたら、filesrc.zipを解凍し、srcフォルダ以下のファイルをプロジェクトにドラッグします。

ファイルの説明

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

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)を作成します。

  • 最初に、使用するコマンドを定義しています。
  • ファイルを追加する場合には、OBJECTSに追加したファイルのオブジェクトファイル名を追加します。
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では、

  • 割り込みベクトルの設定
  • グローバル変数のRAM領域へのコピー

をします。

割り込みベクトルの設定は以下のように定義しています。

/* 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...を選択すると図のような設定画面が表示されます。

  • Zyling Embedded debug (Native)を選択し、右クリックでNewを選択する
  • Name: デバッグ設定名称をつけます、ここではsam7s-t0-ramとします。
  • Project: sam7s-t0を選択します。
  • C/C++ Application: main.outを指定します。

debug-1.jpg

次にDebuggerタグを選択します。

  • GDB debugger: gdbの場所を指定します、ここでは/opt/local/arm-elf/bin/arm-elf-gdbを指定しました。
  • Use full file path to set breakpointsを選択します。

debug-2.jpg

最後にCommandsタグを選択します。

  • initialize commands
    target remote localhost:3333
    をセットします。
  • Run commandsに
    monitor soft_reset_halt 
    monitor armv4_5 core_state arm 
    monitor mww 0xffffff60 0x00320100 
    monitor mww 0xfffffd44 0xa0008000 
    monitor mww 0xfffffc20 0xa0000601 
    monitor wait 100 
    monitor mww 0xfffffc2c 0x00480a0e 
    monitor wait 200 
    monitor mww 0xfffffc30 0x7 
    monitor wait 100 
    monitor mww 0xfffffd08 0xa5000401 
    set remote memory-write-packet-size 1024 
    set remote memory-write-packet-size fixed 
    set remote memory-read-packet-size 1024 
    set remote memory-read-packet-size fixed 
    monitor mww 0xfffffd00 0xa5000004 
    monitor mww 0xffffff00 0x01 
    monitor reg pc 0x00000000 
    monitor arm7_9 sw_bkpts enable
    #load
    continue
    
    をセットします。

通常は、最後に

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がデバッグ設定でできなかったので、手動でプログラムをロードします。 別のターミナルで

  • telnet localhost 4444と入力
  • load_image main.outでロードコマンドを入力する

と、少し時間がかかりますが、以下のように出力されます。

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分ほどかかります。

ステップ実行もとても遅いですが、プログラムが期待通りに動かなかった最後の砦として、 デバッガは有効です。

debug-4.jpg

ROMへの書き込み

このままでは、電源を切るとプログラムが消えてしまいますので、ROMへの書き込みを行います。 では、なぜRAMに書き込んでいたのでしょう。

RAMのメリットは、

  • ブレークポイントが自由に設定できる、ROMの場合同時に2個までしか設定できない。
  • 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で若干ことなります。

  • デバッグ設定を複製して、sam7s-t0-romとします。
  • CommandsタグをのRun commandsを以下のように変更します。
    monitor soft_reset_halt 
    monitor armv4_5 core_state arm 
    monitor mww 0xffffff60 0x00320100 
    monitor mww 0xfffffd44 0xa0008000 
    monitor mww 0xfffffc20 0xa0000601 
    monitor wait 100 
    monitor mww 0xfffffc2c 0x00480a0e 
    monitor wait 200 
    monitor mww 0xfffffc30 0x7 
    monitor wait 100 
    monitor mww 0xfffffd08 0xa5000401 
    set remote memory-write-packet-size 1024 
    set remote memory-write-packet-size fixed 
    set remote memory-read-packet-size 1024 
    set remote memory-read-packet-size fixed 
    monitor arm7_9 force_hw_bkpts enable 
    symbol-file main.out 
    continue  
    

では、ターミナルでopenocdを起動して、

$ openocd -f openocd.cfg 

デバッグ対象として、sam7s-t0-romを選択します。

  • 動作が、ちょっと不安定?なのか、点滅の動作がスムーズではありません。

しかし、RAMと同様におそいながらも、デバッグできます。

board.jpg

コメント

この記事は、

選択肢 投票
おもしろかった 6  
そうでもない 0  
わかりずらい 0  

皆様のご意見、ご希望をお待ちしております。


(Input image string)


添付ファイル: fileboard.jpg 547件 [詳細] filescript.ocd 535件 [詳細] filesam7s_rom.cmd 598件 [詳細] fileopenocd-rom.cfg 562件 [詳細] fileMakefile.rom 225件 [詳細] filedebug-4.jpg 526件 [詳細] filedebug-3.jpg 274件 [詳細] filedebug-2.jpg 549件 [詳細] filedebug-1.jpg 558件 [詳細] filesrc.zip 428件 [詳細] fileeclipse-2.jpg 528件 [詳細] fileeclipse-1.jpg 523件 [詳細]

トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2014-02-18 (火) 17:01:25 (1132d)
SmartDoc