Upgrade to Pro — share decks privately, control downloads, hide ads and more …

KOZOS/RasPi移植してみた

 KOZOS/RasPi移植してみた

2017/07/02に第7回自作OSもくもく会で発表したKOZOSをRasPiに移植した発表資料です。

Toshifumi NISHINAGA

July 02, 2017
Tweet

More Decks by Toshifumi NISHINAGA

Other Decks in Programming

Transcript

  1. 自己紹介 • なまえ ◦ Toshifumi NISHINAGA(@tnishinaga) • さいきんやったこと ◦ セキュリティキャンプ講師

    (2016 - 2017) ◦ Google Sumber of Code 2016(Linux Foundation) ▪ STM32F7マイコンでブートローダー (U-Boot)移植してLinux動くようにしました • すきなこと ◦ 組み込みいじり(ARM64勉強中) ◦ アニメ、ゲーム ◦ ロードバイク 2
  2. KOZOSとは • 非常に小さな教育用組み込みOS ◦ ブートローダー&OS本体で2700行程度(書籍版) • 対応アーキテクチャ ◦ H8(書籍版) ◦

    移植版:PowerPC/SH2/Arduino(AVR) • 持っている機能 ◦ スレッド管理 ◦ メモリ管理 ◦ I/O管理 5
  3. KOZOSとは • 非常に小さな教育用組み込みOS ◦ ブートローダー&OS本体で2700行程度(書籍版) • 対応アーキテクチャ ◦ H8(書籍版) ◦

    移植版:PowerPC/SH2/Arduino(AVR) • 持っている機能 ◦ スレッド管理 ◦ メモリ管理 ◦ I/O管理 6
  4. 移植しちゃいました • URL ◦ https://github.com/tnishinaga/kozos-rpi • 作業期間 ◦ 2017年4月に2週間程度 ◦

    (1日1時間程度作業) • とりあえず以下は動く ◦ スレッドの切り替え動作 ◦ シリアル出力 8
  5. 移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦

    ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 9
  6. 移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦

    ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 10
  7. なんとなく把握したこと • ブートローダーとOS本体(KOZOS)がある • 起動時はFLASHに書かれたブートローダーが立ち上がる • ブートローダーはシリアル経由でKOZOSをRAM読み込む ◦ ※直接KOZOS起動するようにすればブートローダーは必要なさそう •

    KOZOSにはスレッドと優先度スケジューリング、メモリ管理がある • KOZOSのコンテクストスイッチは以下の理由で起こる ◦ シリアル受信などの外部割り込み ◦ システムコール関数呼び出しによるソフトウェア割り込み ◦ 謎の例外 • echoコマンドが動けばKOZOSの移植は完了 ◦ シリアル割り込みによるスレッド切り替えの動作が確認できる 12
  8. 移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦

    ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 13
  9. 移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦

    ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 15
  10. JTAGデバッグできるようにする • デバッグできないと辛いのでJTAGデバッグできるようにする • RasPiのJTAGは特定のGPIOポートのモードをAlternativeモードにして有効化する • JTAGデバッグソフトはOpenOCDを利用 • JTAGアダプタは以下を利用 ◦

    http://akizukidenshi.com/catalog/g/gM-06545/ • コミットはこのあたり ◦ https://github.com/tnishinaga/kozos-rpi/commit/0 31f8dcd9a39ba41e9d7e6fa5fa4387b9314948f ◦ https://github.com/tnishinaga/kozos-rpi/commit/5 de931245aec2a55b99bee2740bb789a11049615 16
  11. 動作確認 • JTAGアダプタとRaspberry Piを接続する ◦ 接続先等は「BareMetalで遊ぶ RaspberryPi」等を参照 • OpenOCDを立ち上げる ◦

    openocd -f raspi_with_ngxtech.cfg • GDBを立ち上げる ◦ arm-none-eabi-gdb kozos.elf • GDBをOpenOCDのGDB Serverと接続する ◦ target remote localhost:3333 • 一旦プログラムを走らせてから止める ◦ continue してから Ctrl + C • プログラムをロードして実行再開し、動けばOK ◦ load して continue 17
  12. 移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦

    ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 18
  13. main関数まで動くようにする • リンカスクリプトを修正してramの先頭を0x8000にする ◦ 0x8000はRasPi起動時のエントリポイント • スタートアップコード(_start)を書く ◦ CPUのモードを設定する ▪

    cps命令で割り込み不可にする ◦ BSSの初期化をする ◦ スタックポインタの初期値を設定する ▪ RasPiはGPUがRAMがマップされているアドレスの末尾から 64MB使うのに注意 ◦ main関数を呼ぶ ◦ sleepさせる ▪ ARMの場合はwfi(割り込み待ち)でsleepできる 19
  14. 移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦

    ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 21
  15. 一般的なIRQ割り込みの動き Vector Table main IRQ Handler IRQ interrupt 1. ベクタテーブルの

    IRQ欄の命令を実行 2. IRQハンドラに飛ぶ 3. 割り込み処理が終 わったら元の場所に戻る メモリ 25
  16. 移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦

    ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 26
  17. KOZOSのディスパッチャ(H8の場合) • スレッド状態の保存 ◦ 現在のスレッドのスタックにレジスタをすべて 保存 ◦ 割り込み要因とスタックポインタ(er7)の値(保 存したスレッド状態の先頭アドレス)を interrupt関数に渡す

    • スレッド状態の復元(dispatch関数) ◦ 与えられたスタックポインタの値をスタックポイ ンタ(er7)にセット ◦ スタックポインタからレジスタの状態を復元 レジスタ スタック レジスタ Push sp interrupt(type, sp) dispatch(sp) スタック レジスタ レジスタ Pop sp 28
  18. 割り込み応答とバンク切り替えの例 (SystemからIRQ) 1. SystemのCPSRがIRQのSPSRにコピーされ る 2. CPUモードを切り替える a. この例だとSystemからIRQへ 3.

    バンクレジスタを切り替える a. SP, LR, SPSRがIRQのものになる 4. 割り込みを無効化する 5. PC(戻りアドレス)がIRQのLRにセットされる 6. PCに例外ベクタアドレスをセットする 31 R0 - R12 SP_sys LR_sys PC CPSR SPSR_sys System R0 - R12 SP_irq LR_irq PC CPSR SPSR_irq IRQ CPSR: CPUフラグ等の状態が入るレジスタ
  19. 割り込み応答とバンク切り替えの例 (SystemからIRQ) 1. SystemのCPSRがIRQのSPSRにコピーされ る 2. CPUモードを切り替える a. この例だとSystemからIRQへ 3.

    バンクレジスタを切り替える a. SP, LR, SPSRがIRQのものになる 4. 割り込みを無効化する 5. PC(戻りアドレス)がIRQのLRにセットされる 6. PCに例外ベクタアドレスをセットする 32 R0 - R12 SP_sys LR_sys PC CPSR SPSR_sys System R0 - R12 SP_irq LR_irq PC CPSR SPSR_irq IRQ CPSR: CPUフラグ等の状態が入るレジスタ
  20. 割り込み応答とバンク切り替えの例 (SystemからIRQ) 1. SystemのCPSRがIRQのSPSRにコピーされ る 2. CPUモードを切り替える a. この例だとSystemからIRQへ 3.

    バンクレジスタを切り替える a. SP, LR, SPSRがIRQのものになる 4. 割り込みを無効化する 5. PC(戻りアドレス)がIRQのLRにセットされる 6. PCに例外ベクタアドレスをセットする 33 R0 - R12 SP_sys LR_sys PC CPSR SPSR_sys System R0 - R12 SP_irq LR_irq PC CPSR SPSR_irq IRQ CPSR: CPUフラグ等の状態が入るレジスタ
  21. 割り込み応答とバンク切り替えの例 (SystemからIRQ) 1. SystemのCPSRがIRQのSPSRにコピーされ る 2. CPUモードを切り替える a. この例だとSystemからIRQへ 3.

    バンクレジスタを切り替える a. SP, LR, SPSRがIRQのものになる 4. 割り込みを無効化する 5. PC(戻りアドレス)がIRQのLRにセットされる 6. PCに例外ベクタアドレスをセットする 34 R0 - R12 SP_sys LR_sys PC CPSR SPSR_sys System R0 - R12 SP_irq LR_irq PC CPSR SPSR_irq IRQ CPSR: CPUフラグ等の状態が入るレジスタ Change
  22. 割り込み応答とバンク切り替えの例 (SystemからIRQ) 1. SystemのCPSRがIRQのSPSRにコピーされ る 2. CPUモードを切り替える a. この例だとSystemからIRQへ 3.

    バンクレジスタを切り替える a. SP, LR, SPSRがIRQのものになる 4. 割り込みを無効化する 5. PC(戻りアドレス)がIRQのLRにセットされる 6. PCに例外ベクタアドレスをセットする 35 R0 - R12 SP_sys LR_sys PC CPSR SPSR_sys System R0 - R12 SP_irq LR_irq PC CPSR SPSR_irq IRQ CPSR: CPUフラグ等の状態が入るレジスタ
  23. 割り込み応答とバンク切り替えの例 (SystemからIRQ) 1. SystemのCPSRがIRQのSPSRにコピーされ る 2. CPUモードを切り替える a. この例だとSystemからIRQへ 3.

    バンクレジスタを切り替える a. SP, LR, SPSRがIRQのものになる 4. 割り込みを無効化する 5. PC(戻りアドレス)がIRQのLRにセットされる 6. PCに例外ベクタアドレスをセットする 36 R0 - R12 SP_sys LR_sys PC CPSR SPSR_sys System R0 - R12 SP_irq LR_irq PC: 0x18 CPSR SPSR_irq IRQ CPSR: CPUフラグ等の状態が入るレジスタ
  24. KOZOS/RasPiのスレッド状態保存(IRQ割り込み) 1. R0-R3までをIRQのスタックに保存 2. SP_irqをR0に、SPSR_irqをR1に、LR_irqをR3に退避 3. cps命令でSystemモードに変更(バンク切り替えが起こる) 4. SP_sysをR2に保存(SP_bak) 5.

    R3(LR_irq)をスタックにpush 6. R4-R12をスタックにpush 7. SP_irqに保存したR0-R3をR4-R7に復元 8. R0-R3をスタックにpush 9. R1(SPSR_irq)をスタックにpush 10. R2(SP_bak)とLR_sysをスタックにpush 39
  25. 移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦

    ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 42
  26. 移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦

    ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 44