2008年4月29日

愛の反対は…

マザーテレサが昔こう言ったそうです。
愛の反対は憎しみではなく、無関心
なんかスゴイな、と感銘を受けました。

2008年2月18日

NetBSD(i386)でsysarchを追加する。

NetBSD-2.1(i386版)で、sysarchを追加してユーザランドプロセスからカーネルを好き勝手に操作できるようにしてみる。sysarchについては、NetBSDのmanページを参照のこと。

まず、sysarchの番号を追加する。番号はカーネルソースコードの arch/i386/include/sysarch.h に定義されている。
例えば以下のように、"I386_TESTSYS"を追加する。
#define I386_TESTSYS

続いて、sysarchの実行コードを作成する。i386のsysarchコードは、カーネルソースコードの arch/i386/i386/sys_machdep.c に記述されている。このファイルの sys_sysarch() 関数内のswitch文がsysarch()の切り分けを行っている箇所なので、その部分に case文(追加したsysarch番号のI386_TESTSYS)を追加する。

以上で、カーネルの設定は完了。カーネルをコンパイルしなおせばOK

ユーザランドプログラムから追加したsysarchを参照できるようにするため、ヘッダファイルを /usr/include 配下に反映させることを忘れないこと!

2008年1月5日

ARMでの関数呼び出し(ABI)調査

C言語から呼び出し可能なアセンブラコードを作成するために、C言語の関数がどのようにコンパイルされるか、ディスアセンブルしてみた。

テスト用に作成したCのソースコードは以下。
u8
add1(u8 a, u8 b)
{
u8 sum = a + b;
return sum;
}

u8
add2(u8 a, u8 b, u8 c, u8 d, u8 e, u8 f, u8 g)
{
u8 sum = a + b + c + d + e + f + g;
return sum;
}

u32
add3(u32 a, u32 b)
{
u32 sum = a + b;
return sum;
}


上記Cのコードをディスアセンブリした結果は以下。
test.o:     ファイル形式 elf32-littlearm

セクション .text の逆アセンブル:

00000000 add1:
0: e1a0c00d mov ip, sp
4: e92dd800 stmdb sp!, {fp, ip, lr, pc}
8: e24cb004 sub fp, ip, #4 ; 0x4
c: e24dd004 sub sp, sp, #4 ; 0x4
10: e1a03000 mov r3, r0
14: e1a02001 mov r2, r1
18: e54b300d strb r3, [fp, #-13]
1c: e1a03002 mov r3, r2
20: e54b300e strb r3, [fp, #-14]
24: e55b200d ldrb r2, [fp, #-13]
28: e55b300e ldrb r3, [fp, #-14]
2c: e0823003 add r3, r2, r3
30: e54b300f strb r3, [fp, #-15]
34: e55b300f ldrb r3, [fp, #-15]
38: e1a00003 mov r0, r3
3c: e89da808 ldmia sp, {r3, fp, sp, pc}

00000040 add2:
40: e1a0c00d mov ip, sp
44: e92dd830 stmdb sp!, {r4, r5, fp, ip, lr, pc}
48: e24cb004 sub fp, ip, #4 ; 0x4
4c: e24dd008 sub sp, sp, #8 ; 0x8
50: e1a0c003 mov ip, r3
54: e59be004 ldr lr, [fp, #4]
58: e59b4008 ldr r4, [fp, #8]
5c: e59b500c ldr r5, [fp, #12]
60: e1a03000 mov r3, r0
64: e54b3015 strb r3, [fp, #-21]
68: e1a03001 mov r3, r1
6c: e54b3016 strb r3, [fp, #-22]
70: e1a03002 mov r3, r2
74: e54b3017 strb r3, [fp, #-23]
78: e1a0300c mov r3, ip
7c: e54b3018 strb r3, [fp, #-24]
80: e1a0300e mov r3, lr
84: e54b3019 strb r3, [fp, #-25]
88: e1a03004 mov r3, r4
8c: e54b301a strb r3, [fp, #-26]
90: e1a03005 mov r3, r5
94: e54b301b strb r3, [fp, #-27]
98: e55b2015 ldrb r2, [fp, #-21]
9c: e55b3016 ldrb r3, [fp, #-22]
a0: e0823003 add r3, r2, r3
a4: e1a02003 mov r2, r3
a8: e55b3017 ldrb r3, [fp, #-23]
ac: e0823003 add r3, r2, r3
b0: e1a02003 mov r2, r3
b4: e55b3018 ldrb r3, [fp, #-24]
b8: e0823003 add r3, r2, r3
bc: e1a02003 mov r2, r3
c0: e55b3019 ldrb r3, [fp, #-25]
c4: e0823003 add r3, r2, r3
c8: e1a02003 mov r2, r3
cc: e55b301a ldrb r3, [fp, #-26]
d0: e0823003 add r3, r2, r3
d4: e1a02003 mov r2, r3
d8: e55b301b ldrb r3, [fp, #-27]
d8: e55b301b ldrb r3, [fp, #-27]
dc: e0823003 add r3, r2, r3
e0: e54b301c strb r3, [fp, #-28]
e4: e55b301c ldrb r3, [fp, #-28]
e8: e1a00003 mov r0, r3
ec: e24bd014 sub sp, fp, #20 ; 0x14
f0: e89da830 ldmia sp, {r4, r5, fp, sp, pc}

000000f4 add3:
f4: e1a0c00d mov ip, sp
f8: e92dd800 stmdb sp!, {fp, ip, lr, pc}
fc: e24cb004 sub fp, ip, #4 ; 0x4
100: e24dd00c sub sp, sp, #12 ; 0xc
104: e50b0010 str r0, [fp, #-16]
108: e50b1014 str r1, [fp, #-20]
10c: e51b2010 ldr r2, [fp, #-16]
110: e51b3014 ldr r3, [fp, #-20]
114: e0823003 add r3, r2, r3
118: e50b3018 str r3, [fp, #-24]
11c: e51b3018 ldr r3, [fp, #-24]
120: e1a00003 mov r0, r3
124: e24bd00c sub sp, fp, #12 ; 0xc
128: e89da800 ldmia sp, {fp, sp, pc}

2007年12月24日

Flash2Advance Ultra (2GB) の解析:その1

先日のブログでフラッシュ種別の判別方法について記載したが、現在所有しているFlash2Advance Ultra 2Gで試してみた。

手順としては以下の通り。
  • アドレス 0x0930ECA8 に 0x5354 を write
  • アドレス 0x0802468A に 0x1234 を write (× 500回)
  • アドレス 0x0800ECA8 に 0x5354 を write
  • アドレス 0x0802468A に 0x5354 を write
  • アドレス 0x0802468A に 0x5678 を write (× 500回)
  • アドレス 0x0930ECA8 に 0x5354 を write
  • アドレス 0x0802468A に 0x5354 を write
  • アドレス 0x08ECA800 に 0x5678 を write
  • アドレス 0x080268A0 に 0x1234 を write
  • アドレス 0x0802468A に 0xABCD を write (× 500回)
  • アドレス 0x0930ECA8 に 0x5354 を write
  • アドレス 0x0930ECA8 に 0x5354 を write
  • アドレス 0x09E2468A に 0x9413 を write
  • アドレス 0x08000000 に 0x0090 を write
以上で、FlashメモリがIDモード(?)に移行する。
移行後、以下のアドレスにアクセスすることでベンダIDとプロダクトIDが取得できるみたい。
  • ベンダID(0x08000000) : 0x0089
  • プロダクトID(0x08000004) : 0x880D

また、IDモードに移行する前と移行した後での、メモリ空間ダンプ結果は以下の通り。

■移行前■
0x08000000 : 2E 00 00 EA 24 FF AE 51  69 9A A2 21 3D 84 82 0A
0x08000010 : 84 E4 09 AD 11 24 8B 98 C0 81 7F 21 A3 52 BE 19


■移行後■
0x08000000 : 89 00 00 EA 0D 88 AE 51  01 00 A2 21 01 00 82 0A
0x08000010 : 89 00 09 AD CF BF 8B 98 01 00 7F 21 01 00 BE 19


まだ、フラッシュの書き込み・消去方法等は分かっていないが、とりあえず今日はここまで‥‥


参考リンク

GBATEK和訳:http://meraman.dip.jp/index.php?M3DSS_GBATEK_GBA

2007年12月14日

Flash種別の判別方法(GBA FLinkerの解析)

F2A Ultra 2Gの制御(リード/ライト)を行うプログラムを作成しようと思案中。
そのために、カートリッジのフラッシュをどのように判別・アクセスをするのかを調査してみる。

FLinkerというツールにおいて、GBAのフラッシュやマジコン系のフラッシュへアクセスするソースコードが公開されているので、内容を確認してみた。

フラッシュ種別の判別
  • カートリッジの先頭アドレス(0x08000000)に0x90を書き込む
  • カートリッジの先頭アドレスを読み出す。読み出した値により‥‥
  • 0x00 → Hudson Cartridge
  • 0x2e → 一般的なROM
  • 0x89 → Intelのフラッシュ(具体的なデバイス種別は、他の方法で判別する)
  • 0xb0 → Sharpのフラッシュ
上記のように、デバイス種別の判別にはデバイスごとに異なる様子。
F2A Ultraにどのようなデバイスが搭載されているのかわからないことにはどうしようも無いな‥‥


参考リンク
FLinker:http://www.devrs.com/gba/software.php#misc

2007年12月4日

CART実行するためのリンカスクリプト

GBAでCART実行するプログラムを作る場合、
  • コンパイル(リンク)したプログラムでは、.dataセクションはROM上に存在する
  • 実動作をさせる場合には、.dataセクションはRAM上にコピーしなければならない
そのため、リンカスクリプトもMB用のものとは変えて作成しなければならない。
リンカスクリプトの作成時には、.dataセクション(.bssセクションも)が、LMAはROM上のアドレスで、VMAはRAM上のアドレスになるようにしなければならない。

devkitARMのリンカスクリプトも参考に、以下のリンカスクリプトを作成した。


MEMORY {
rom : ORIGIN = 0x08000000, LENGTH = 32M
iwram : ORIGIN = 0x03000000, LENGTH = 32K
ewram : ORIGIN = 0x02000000, LENGTH = 256K
}

SECTIONS {
. = ORIGIN(rom)
.text :
{
*(.text)
*(.glue_7)
*(.glue_7t)
} > rom
.rodata :
{
*(.rodata*)
} > rom

__data_lma = .;
.data : AT(__data_lma)
{
*(.data)
} > ewram
.bss :
{
*(.bss)
} > ewram
}
赤字の部分がポイント。
これで、リンカスクリプトは(たぶん)OK.

ただし、実際にROMで実行する場合は、.dataセクションをRAMへコピーするコードも作成する必要がある。


参考ページ
GNUリンカLDの使い方 : http://www.sra.co.jp/wingnut/ld/ld-ja_3.html

2007年12月2日

GBAのcartかmbか動的に判断する方法

GBAでは、カートリッジ(cart)から起動する方法とブートケーブル(mb)から起動する方法がある。
(ちなみに、mbは"Multi Boot"の頭文字)

2つの方法で、起動時のアドレスが異なる。(cart : 0x08000000, mb : 0x02000000)
これを利用してプログラムで起動モードに合わせて動的に処理を変更するプログラムが書ける。



.arm @ARMモードの場合。THUMBモードの場合はこれではダメ
movs r0, pc, lsl #5
bcs cart_proc
b mb_proc

cart_proc:
@ cart起動時の処理

mb_proc:
@ mb起動時の処理




ロジックは、プログラムの通りだが、
  • プログラムカウンタ(PC)を5ビット左シフトして、
  • キャリーが発生した場合は、cart起動
  • キャリーが発生しなかった場合は、mb起動
と判断すれば良い。(分かり易くするため、ブランチ命令をムダに使ってます‥)


devkitARMでも同様な処理をしているが、こちらはTHUMBモードで動作させているので、
アセンブラの書き方は異なっている。
THUMBモードはまだ良く分かっていないので、今回はARMモードでプログラム作成。

2007年12月1日

devkitARMのcrt解析

GBAでプログラミングを行うにあたり、crtファイルでどのような処理を行えば良いか調べる。
そのために、devkitProで公開されているdevkitARM(GBA等のARMプロセッサ用の開発ツールキット)のcrtがどのような処理を行っているか、ソースコードを追いかけてみる。
  1. GBAヘッダを定義 → GBAでは、ROMの先頭に所定のヘッダデータが必要
  2. IMEレジスタに、"割り込み可”を設定
  3. CPUモードの"IRQモード”および”SYSモード”のスタックポインタを設定
  4. .text領域の開始アドレスをチェック(CARTかMBかをチェックするため)
  5. CARTの場合は、EWRAMをゼロクリア
  6. .bbs領域をゼロクリア
  7. .data領域を、ROMからRAM(IWRAM)にコピー
  8. libcの初期化コードを実行
  9. ユーザプログラム(main関数)へジャンプ

3.で設定されるスタックポインタの値は、
  • IRQモード → 0x03007FA0
  • SYSモード → 0x03007F00
となっている。スタックサイズとしてこれで十分なのだろうか‥‥?


参考ページ
  • devkitPro ‥ GBAやDS等用の開発キットを提供しているプロジェクト
  • ARMメモ ‥ ARMプロセッサのデータシート和訳