エントリー

H8マイコンでLinux 2回目

前回で開発環境が一応整ったみたいなので、Linuxカーネルのビルドを試してみました。
Linuxといっても、改めて言う必要はないかもしれませんが、組み込み向けの「uClinux」を使うことになります。

 

早速uClinuxのサイトから最新のソースパッケージを取得。
TOPページのhttp://www.uclinux.org/はなぜか頻繁に見れなくなるようなので、ファイルの置いてあるこのページに直接行ったほうがよいかもしれません。

現状では、uClinux-dist-20110810.tar.bz2 が最新のようです。
この記事では1つ前、"20110603"の日付のものを使用していますが、これから行う内容におそらく相違はないと思います。

 

ソースパッケージには、2.0.x、2.4,x、2.6.xのカーネルソースがそれぞれ入っています。今回はとりあえず2.4.xでビルドします。H8マイコンのメモリ増設はまだしていませんし、メモリ使用量が2.6.xよりも少なくなるようですので。

パッケージを展開して、make menuconfig、make dep、make、めんどいので詳細は略。

make CROSS_COMPILE=h8300-elf- menuconfig
make CROSS_COMPILE=h8300-elf- dep 2>&1 | tee make_dep_log
make CROSS_COMPILE=h8300-elf- 2>&1 | tee make_log

実はツールチェイン構築時の"--target=h8300-elf"は不要でした。このオプションを付けてしまったせいで、make時にもわざわざ"CROSS_COMPILE=h8300-elf-"をつけなくてはなりませんでした。
(何もつけない場合は"h8300-linux-elf"になります)

とりあえず今はこのまま進めます。

 

makeするとエラーて怒られてしまいました。滞りなく完了すると思っていたのに…
結論から言えば、ソースコードがGCC3以下でコンパイルされることを前提として書かれているのに対し、GCC4でコンパイルしたことが原因でした。GCC4から構文チェックが厳密になって、一部でこれまでの警告がエラーとして出てしまうようです。

いっそのことGCC3でやり直すか、いや待てそれは敗北宣言っぽい気がするな・・・、てなわけで、仕方ないので見ていくことにしましょう。

 

エラーその1

make CFLAGS="-fno-builtin -DNO_CACHE -D__KERNEL__ -I/usr/local/src/uClinux-dist/linux-2.4.x/include  -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fno-builtin-sprin
tf -fomit-frame-pointer -Wno-pointer-sign -pipe -DNO_MM -DNO_FPU -DNO_CACHE -mh -mint32 -D__ELF__  -DNO_FORGET -DUTS_SYSNAME=\"uClinux\" -D__linux__ -DTARGET=aki3068net -Os  " -C  drivers
h8300-elf-ld  -mh8300helf   -r -o aki3068net.o timer.o
ptrace_h8300h.c: In function 'getnextpc':
ptrace_h8300h.c:249:7: error: lvalue required as left operand of assignment
ptrace_h8300h.c:253:7: error: lvalue required as left operand of assignment

 

linux-2.4.x/arch/h8300/platform/h8300h/ptrace_h8300h.c

202 static unsigned short *getnextpc(struct task_struct *child, unsigned short *pc)
203 {
204         const struct optable *op;
205         unsigned char *fetch_p;
206         unsigned char inst;
207         unsigned long addr;
208         unsigned long *sp;
209         int op_len,regno;
210         op = optables[0].ptr;
211         op_len = optables[0].size;
212         fetch_p = (unsigned char *)pc;
213         inst = *fetch_p++;
214         do {
・・・
247                                 case relb:
248                                         if ((inst = 0x55) || isbranch(child,inst & 0x0f))
249                                                 (unsigned char *)pc += (signed char)(*fetch_p);
250                                         return pc+1; /* skip myself */
251                                 case relw:
252                                         if ((inst = 0x5c) || isbranch(child,(*fetch_p & 0xf0) >> 4))
253                                                 (unsigned char *)pc += (signed short)(*(pc+1));
254                                         return pc+2; /* skip myself */
257                                 }

 

エラーが出ている箇所は249行目です。
ググればすぐに出てきますが、左辺がキャストされていることでエラーとなります。やりたいことはわからなくはないですが、この書き方は確かにあいまいです。

 

修正方法は、2.6.xのソースから引っこ抜いてこればOKです。

247                                 case relb:
248                                         if (inst == 0x55 || isbranch(child,inst & 0x0f))
249                                                 pc = (unsigned short *)((unsigned long)pc +
250                                                                        ((signed char)(*fetch_p)));
251                                         return pc+1; /* skip myself */
252                                 case relw:
253                                         if (inst == 0x5c || isbranch(child,(*fetch_p & 0xf0) >> 4))
254                                                 pc = (unsigned short *)((unsigned long)pc +
255                                                                        ((signed short)(*(pc+1))));
256                                         return pc+2; /* skip myself */
257                                 }

 

エラーその2

h8300-elf-gcc -fno-builtin -DNO_CACHE -D__KERNEL__ -I/usr/local/src/uClinux-dist/linux-2.4.x/include  -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fno-builtin-spri
ntf -fomit-frame-pointer -Wno-pointer-sign -pipe -DNO_MM -DNO_FPU -DNO_CACHE -mh -mint32 -D__ELF__  -DNO_FORGET -DUTS_SYSNAME="uClinux" -D__linux__ -DTARGET=aki3068net -Os    -nostdinc -iwithprefix
 include -DKBUILD_BASENAME=ints  -c -o ints.o ints.c
make[3]: ディレクトリ `/usr/local/src/uClinux-dist/linux-2.4.x/drivers/media' に入ります
make -C radio
make[5]: ディレクトリ `/usr/local/src/uClinux-dist/linux-2.4.x/drivers/ide/arm' に入ります
rm -f idedriver-arm.o
h8300-elf-ar rcs idedriver-arm.o
make[4]: ディレクトリ `/usr/local/src/uClinux-dist/linux-2.4.x/drivers/media/radio' に入ります
make all_targets
n_tty.c: In function 'write_chan':
n_tty.c:1406:5: error: assignment of read-only variable '__gu_val'
n_tty.c:1406:5: warning: passing argument 1 of 'memcpy' discards qualifiers from pointer target type
rm -f mm.o

 

__gu_val が read-only ということで怒られています。 __gu_val を探してみると下記の場所にありました。
linux-2.4.x/include/asm-h8300/uaccess.h

 85 #define get_user(x, ptr)                                        \
 86 ({                                                              \
 87     int __gu_err = 0;                                           \
 88     typeof(*(ptr)) __gu_val = 0;                             \
 89     switch (sizeof(*(ptr))) {                                   \
 90     case 1:                                                     \
 91     case 2:                                                     \
 92     case 4:                                                     \
 93         __gu_val = *(ptr);                                        \
 94         break;                                                  \
 95     case 8:                                                     \
 96         memcpy(&__gu_val, ptr, sizeof (*(ptr)));                \
 97         break;                                                  \
 98     default:                                                    \
 99         __gu_val = 0;                                           \
100         __gu_err = __get_user_bad();                            \
101         break;                                                  \
102     }                                                           \
103     (x) = __gu_val;                                             \
104     __gu_err;                                                   \
105 })

 

ふむふむなるほど。
typeof(*(ptr)) としているんだけど、上記エラー箇所の場合、ptr が const unsigned char* なので、__gu_val が const になってしまい値が代入できない、というオチのようです。

get_userの詳細はさておき、結局やっていることは *ptr → __gu_val → x と値をコピーしていっているだけです。ということはつまり、暗黙的に x と *ptr は同じ(もしくは x が *ptr を内包する)型になっていると考えてもよく、下記でも問題ないはずです。

 88     typeof(x) __gu_val = 0;                             \

もちろん x が const となることはありません。

 

というわけで、これら2つのエラーを修正することで、カーネル自体のコンパイルはうまくいったようです。

しかしこの後、uClibやユーザランドのコンパイルでエラーがたくさん出てしまうことに…
それはまた次回・・・(って、あるのかわかりませんが^^)

ページ移動

コメント

  • コメントはまだありません。

ユーティリティ

Author


oaks (twitter: @oks486)

記事の内容に関しては無保証です。何事も At your own risk ってことでよろしく。
リンクはご自由にどうぞ。

SPAM対策が面倒なため現在コメント投稿機能を停止しています。あしからず...

検索

エントリー検索フォーム
キーワード

Feed

リンク