LoginSignup
2
1

More than 3 years have passed since last update.

"12ステップで作る組み込みOS自作入門" で勝手にはまったことをメモ

Last updated at Posted at 2019-06-10

はじめに

表題の本[1]はとても親切に書かれていて,順に追っていけば問題なく進めていけるのですが,タイプミスなど自分の不注意でエラーになることがあります.そんなときの対応も含めて勉強になるので,恥を忍んでメモをしていきます.
内容は,随時追加してきます.

なお,私が自爆した内容であり,書籍の記載のせいではないことをここで強調しておきます.

6th step もう一度,Hello World!

6-1 make エラー

症状

> cd os
> make
/usr/local/bin/h8300-elf-gcc startup.o main.o lib.o serial.o -o kozos -Wall -mh -nostdinc -nostdlib -fno-builtin -I. -Os -DKOZOS -static -T ld.scr -L.
/usr/local/lib/gcc/h8300-elf/8.2.0/../../../../h8300-elf/bin/ld:ld.scr:33: warning: memory region `data' not declared
/usr/local/lib/gcc/h8300-elf/8.2.0/../../../../h8300-elf/bin/ld: kozos section `.text.startup' will not fit in region `ram'
/usr/local/lib/gcc/h8300-elf/8.2.0/../../../../h8300-elf/bin/ld: region `ram' overflowed by 122 bytes
collect2: error: ld returned 1 exit status
Makefile:42: ターゲット 'kozos' のレシピで失敗しました
make: *** [kozos] エラー 1

原因と対策

"region `ram' overflowed" と言われている通りで,リンカスクリプトのRAM領域のサイズを間違えて小さくしすぎていたため,収まらないとエラーを出してくれていました.

os/ld.scr
MEMORY
{
    ram(rwx)    : o = 0xfffc20, l = 0x000300 /* ここは,0x003f000 が正しい */
    stack(rw)   : o = 0xffff00, l = 0x000000 /* end of RAM */
}

6-2 エントリーポイントのアドレスが 0x0 になってしまう

症状

> readelf -a kozos.elf
ELF ヘッダ:
  マジック:   7f 45 4c 46 01 02 01 00 00 00 00 00 00 00 00 00
  クラス:                            ELF32
  データ:                            2 の補数、ビッグエンディアン
  バージョン:                        1 (current)
  OS/ABI:                            UNIX - System V
  ABI バージョン:                    0
  型:                                EXEC (実行可能ファイル)
  マシン:                            Renesas H8/300
  バージョン:                        0x1
  エントリポイントアドレス:               0x0
  プログラムの開始ヘッダ:          52 (バイト)
  セクションヘッダ始点:          2932 (バイト)
  フラグ:                            0x810000
  このヘッダのサイズ:                52 (バイト)
  プログラムヘッダサイズ:            32 (バイト)
  プログラムヘッダ数:                4
  セクションヘッダ:                  40 (バイト)
  セクションヘッダサイズ:            9
  セクションヘッダ文字列表索引:      8

原因と対策

  • .SECTIONS 内の ROM 領域の定義は削除していた.(これは正しい)
  • かつ,リンカスクリプトの .text セクションの配置先指定が, > ROM のままになっていた

現象としては,リンカが,未定義の領域を 0x0 として処理していたようです.


6.3 OSが実行できない

OS の ELF をロードして run すると,エントリーポイントの表示が正しくなく,そのまま固まります.readelf -a kozos で表示されるエントリーポイントは正しいことを確認しました (0x00ff0c20).

kzload> load

XMODEM receive succeeded.
kzload> run
starting from entry point: 20kzload (kozos boot loader) started.
kzload>

原因と対策

エントリーポイントが 20 と表示されるのは, 0x00ff0c20 のLSB側だけが切り取られて表示されているように見えます.elf_read() の返値がおかしいのではないかと予想し,ソースを確認したところ,返値の型に間違いが見つかりました.

bootloader/elf.c
char elf_load(char *buf)  /* 正しくは char *elf_load(char *buf) */

ポインタを返すべきところが char になっていたので,MSB側が切り捨てられていたようです.ヘッダも同様に誤りがあったので修正したところ,うまく動きました.

7th step 割込み処理を実装する

7.1 kozos を load すると bootloader に戻ってしまう

症状

kzload> load

XMODEM receive succeeded.
kzload> run
starting from entry point: ffc020
kozos boot succeeded!
> kzload (kozos boot loader) started.
kzload> a

原因と対策

割込みハンドラの入り口で,_interrupt に渡すスタックポインタを間違えて,@ が余計についていました.さらに,割込みベクタを設定する vector.c の NULL の数が8個少なかったために,SCIの割込みベクタがずれていました.おそらく 0000 に飛ばされて,bootloader に戻っていたのだと思います.

intr.S
  .global _intr_serintr
  .type _intr_serintr,@function
_intr_serintr:
  mov.l er6,@-er7
  mov.l er5,@-er7
  mov.l er4,@-er7
  mov.l er3,@-er7
  mov.l er2,@-er7
  mov.l er1,@-er7
  mov.l er0,@-er7
  mov.l er7,@er1  ; 正しくは mov.l er7,er1
  mov.w #SOFTVEC_TYPE_SOFTERR,r0
  jsr @_interrupt
  mov.l @er7+,er0
  mov.l @er7+,er1
  mov.l @er7+,er2
  mov.l @er7+,er3
  mov.l @er7+,er4
  mov.l @er7+,er5
  mov.l @er7+,er6
  rte

参考文献

[1] 坂井弘亮, 「12ステップで作る組み込みOS自作入門」, カットシステム

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1