Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
KOZOS/RasPi移植してみた
Search
Toshifumi NISHINAGA
July 02, 2017
Programming
0
3.7k
KOZOS/RasPi移植してみた
2017/07/02に第7回自作OSもくもく会で発表したKOZOSをRasPiに移植した発表資料です。
Toshifumi NISHINAGA
July 02, 2017
Tweet
Share
More Decks by Toshifumi NISHINAGA
See All by Toshifumi NISHINAGA
マイコンでもRustのtestがしたい その2/KernelVM Tokyo 18
tnishinaga
2
2.3k
マイコンでもRustのtestがしたい/KernelVM Kansai 11
tnishinaga
1
1.4k
BareMetalで遊ぶRaspberry Pi 5 PCIe編/KernelVM Tokyo17
tnishinaga
0
2.4k
probe-rsの紹介と最近の貢献紹介/CELF-02-03
tnishinaga
1
510
SecurityCamp2023基板作るコース講義資料/Security Camp 2023 Lecture Materials
tnishinaga
8
2.6k
RP2040のPIOを使う話/KernelVM Hokuriku 6
tnishinaga
3
1.6k
JTAGでArmプロセッサをデバッグする方法のつづき/KernelVM_Tokyo16
tnishinaga
0
540
CMSIS-DAPの概要と使い方/KernelVM Online5
tnishinaga
1
2k
JTAGでarmプロセッサをデバッグする話/KernelVM Online4
tnishinaga
4
3.5k
Other Decks in Programming
See All in Programming
MCP連携で加速するAI駆動開発/mcp integration accelerates ai-driven-development
bpstudy
0
310
Constant integer division faster than compiler-generated code
herumi
2
670
一人でAIプロダクトを作るための工夫 〜技術選定・開発プロセス編〜 / I want AI to work harder
rkaga
12
2.7k
State of CSS 2025
benjaminkott
1
110
Flutter로 Gemini와 MCP를 활용한 Agentic App 만들기 - 박제창 2025 I/O Extended Seoul
itsmedreamwalker
0
140
あなたとJIT, 今すぐアセンブ ル
sisshiki1969
1
700
Vibe coding コードレビュー
kinopeee
0
450
DataformでPythonする / dataform-de-python
snhryt
0
180
Dart 参戦!!静的型付き言語界の隠れた実力者
kno3a87
0
200
オープンセミナー2025@広島「君はどこで動かすか?」アンケート結果
satoshi256kbyte
0
140
書き捨てではなく継続開発可能なコードをAIコーディングエージェントで書くために意識していること
shuyakinjo
1
290
あまり知られていない MCP 仕様たち / MCP specifications that aren’t widely known
ktr_0731
0
280
Featured
See All Featured
Optimizing for Happiness
mojombo
379
70k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Art, The Web, and Tiny UX
lynnandtonic
302
21k
The World Runs on Bad Software
bkeepers
PRO
70
11k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
8
470
Build The Right Thing And Hit Your Dates
maggiecrowley
37
2.8k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
50
5.5k
Building an army of robots
kneath
306
45k
The Cost Of JavaScript in 2023
addyosmani
53
8.8k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.5k
For a Future-Friendly Web
brad_frost
179
9.9k
Scaling GitHub
holman
462
140k
Transcript
KOZOS/RasPi 移植してみた Toshifumi NISHINAGA(@tnishinaga) 2017/07/02 第7回自作OSもくもく会
自己紹介 • なまえ ◦ Toshifumi NISHINAGA(@tnishinaga) • さいきんやったこと ◦ セキュリティキャンプ講師
(2016 - 2017) ◦ Google Sumber of Code 2016(Linux Foundation) ▪ STM32F7マイコンでブートローダー (U-Boot)移植してLinux動くようにしました • すきなこと ◦ 組み込みいじり(ARM64勉強中) ◦ アニメ、ゲーム ◦ ロードバイク 2
cpsie if @ IRQ, FIQ interrupt enable 3
目次 • KOZOSとは • 移植作戦 4
KOZOSとは • 非常に小さな教育用組み込みOS ◦ ブートローダー&OS本体で2700行程度(書籍版) • 対応アーキテクチャ ◦ H8(書籍版) ◦
移植版:PowerPC/SH2/Arduino(AVR) • 持っている機能 ◦ スレッド管理 ◦ メモリ管理 ◦ I/O管理 5
KOZOSとは • 非常に小さな教育用組み込みOS ◦ ブートローダー&OS本体で2700行程度(書籍版) • 対応アーキテクチャ ◦ H8(書籍版) ◦
移植版:PowerPC/SH2/Arduino(AVR) • 持っている機能 ◦ スレッド管理 ◦ メモリ管理 ◦ I/O管理 6
Raspberry Piでも動かしたいっ!! 7
移植しちゃいました • URL ◦ https://github.com/tnishinaga/kozos-rpi • 作業期間 ◦ 2017年4月に2週間程度 ◦
(1日1時間程度作業) • とりあえず以下は動く ◦ スレッドの切り替え動作 ◦ シリアル出力 8
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 9
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 10
全体をなんとなく把握する • 「12ステップで作る 組み込みOS自作入門」を読む • コードをなんとなく眺める 画像は以下より引用 http://kozos.jp/books/makeos/ 11
なんとなく把握したこと • ブートローダーとOS本体(KOZOS)がある • 起動時はFLASHに書かれたブートローダーが立ち上がる • ブートローダーはシリアル経由でKOZOSをRAM読み込む ◦ ※直接KOZOS起動するようにすればブートローダーは必要なさそう •
KOZOSにはスレッドと優先度スケジューリング、メモリ管理がある • KOZOSのコンテクストスイッチは以下の理由で起こる ◦ シリアル受信などの外部割り込み ◦ システムコール関数呼び出しによるソフトウェア割り込み ◦ 謎の例外 • echoコマンドが動けばKOZOSの移植は完了 ◦ シリアル割り込みによるスレッド切り替えの動作が確認できる 12
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 13
ARMクロス環境でビルド(だけ)できるようにする • とりあえずARMのクロスコンパイラでビルドが全部走るようにする • Makefileを書き換える ◦ ARCHの部分(クロスコンパイラのprefix)をarm-none-eabiにする ◦ CFLAGSのarm gccでは無いオプションを消す
• アセンブリ部はコメントアウトしたり、nopに変えたり • コミットはこのあたり ◦ https://github.com/tnishinaga/kozos-rpi/commit/0f11825d4e81f2af3c311d595292d6617d32 b7a1 14
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 15
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
動作確認 • 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
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 18
main関数まで動くようにする • リンカスクリプトを修正してramの先頭を0x8000にする ◦ 0x8000はRasPi起動時のエントリポイント • スタートアップコード(_start)を書く ◦ CPUのモードを設定する ▪
cps命令で割り込み不可にする ◦ BSSの初期化をする ◦ スタックポインタの初期値を設定する ▪ RasPiはGPUがRAMがマップされているアドレスの末尾から 64MB使うのに注意 ◦ main関数を呼ぶ ◦ sleepさせる ▪ ARMの場合はwfi(割り込み待ち)でsleepできる 19
動作確認 • gdbでmain関数にbreakpointを仕込む ◦ break main • プログラムをloadし、breakpointまでたどり着くか調べる 20
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 21
割り込みハンドラ(だけ)を作ってみる • KOZOSで使う割り込み要因のハンドラだけ作る ◦ IRQ割り込み(外部割り込み) ◦ SVC割り込み(ソフトウェア割り込み) • 割り込みハンドラに飛ばすベクタテーブルを作成する ◦
IRQとSVC以外はsleepするようにする 22
ベクタテーブル • CPUが例外発生時に適切な例外ハンドラに処理を移すための命令やアドレス 等を記録しておくテーブル • 基本的にはメモリの先頭(0x00000000)に配置する Reset Undefined SVC Prefetch
Abort Data Abort Reserved IRQ FIQ 0x00 0x04 0x08 0x0C 0x10 0x14 0x18 0x1C 23
• ベクタテーブルは再配置が必要 ◦ RasPiのプログラムは0x8000に読み込まれるので • スタートアップコード内でプログラムの何処か に置かれたVector Tableをメモリの先頭にコ ピーする ◦
set_vector_table関数が担当 ベクタテーブルの設置 _start Vector Table メモリ 0x0000 0x8000 24
一般的なIRQ割り込みの動き Vector Table main IRQ Handler IRQ interrupt 1. ベクタテーブルの
IRQ欄の命令を実行 2. IRQハンドラに飛ぶ 3. 割り込み処理が終 わったら元の場所に戻る メモリ 25
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 26
ディスパッチャを作ってみる • ディスパッチャ ◦ タスクやスレッドを切り替え CPU資源を与える機構のこと • KOZOSのディスパッチャ ◦ スレッド状態(現在のレジスタ値たち
)の保存 ▪ 割り込みハンドラ内で行う ◦ スレッド状態の復元 ▪ dispatch関数で行う 27
KOZOSのディスパッチャ(H8の場合) • スレッド状態の保存 ◦ 現在のスレッドのスタックにレジスタをすべて 保存 ◦ 割り込み要因とスタックポインタ(er7)の値(保 存したスレッド状態の先頭アドレス)を interrupt関数に渡す
• スレッド状態の復元(dispatch関数) ◦ 与えられたスタックポインタの値をスタックポイ ンタ(er7)にセット ◦ スタックポインタからレジスタの状態を復元 レジスタ スタック レジスタ Push sp interrupt(type, sp) dispatch(sp) スタック レジスタ レジスタ Pop sp 28
ARM移植の課題 • ARMはバンクレジスタがあるためH8のように単一のスタックにスレッド状態を保存 するのが難しい 29
バンクレジスタ(レジスタバンク) • ARMには複数のCPUモードがある • 一部レジスタはCPUのモードが変わると勝手に退避される(バンク切り替え) ◦ この退避される一部レジスタのことをバンクレジスタという 図はhttp://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211k/ch02s08s01.html より引用 30
割り込み応答とバンク切り替えの例 (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フラグ等の状態が入るレジスタ
割り込み応答とバンク切り替えの例 (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フラグ等の状態が入るレジスタ
割り込み応答とバンク切り替えの例 (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フラグ等の状態が入るレジスタ
割り込み応答とバンク切り替えの例 (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
割り込み応答とバンク切り替えの例 (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フラグ等の状態が入るレジスタ
割り込み応答とバンク切り替えの例 (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フラグ等の状態が入るレジスタ
ARM移植の課題 • ARMはバンクレジスタがあるためH8のように単一のスタックにスレッド状態を保存 するのが難しい ◦ そのままではソフトウェア割り込み (SVCモード)とIRQ割り込み(IRQモード)で異なるスタックに保存さ れてしまう ◦ 単一のスタックに保存するにはどうすれば?
37
ARM移植の課題 • ARMはバンクレジスタがあるためH8のように単一のスタックにスレッド状態を保存 するのが難しい ◦ そのままではソフトウェア割り込み (SVCモード)とIRQ割り込み(IRQモード)で異なるスタックに保存さ れてしまう ◦ 単一のスタックに保存するにはどうすれば?
38 A. KOZOSを常にSystemモードで動かす。 どちらの割り込みが入ってもすぐにSystemモードに切り替え、 Systemモードのスタックにスレッドを保存する (H8のようにスタックを一元化する)
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
保存された状態の構造 40 SPSR R0-R3 R4-R12 LR_irq SP_bak, LR_sys sp SP_bak
スレッド状態の復元 • SVCモードに切り替え、コンテキストを逆順にもどしていく • ldmfd sp!, {pc}^ のように^を付けるとCPUが勝手にSPSRからCPSRを復元してから PCの命令に戻ってくれる 41
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 42
シリアルが動くようにする • やるだけ。 • 「BareMetalで遊ぶ Raspberry Pi」のコードからMMIOのアドレス定義だけもらってく ると楽 • FIFOを切るとH8と同じ使い方ができるので移植しやすい
• IRQ割り込みの設定するのも忘れずに ◦ 割り込みに関する説明は「 BareMetalで遊ぶ Raspberry Pi」参照 43
移植作戦 • 方針 ◦ とりあえず少しずつ動くようにしていく • 手順 ◦ 全体をなんとなく把握する ◦
ARMクロス環境でビルド(だけ)できるようにする ◦ JTAGデバッグできるようにする ◦ main関数まで動くようにする ◦ 割り込みハンドラを作ってみる ◦ ディスパッチャを作ってみる ◦ Serialを動くようにする ◦ バグ潰し 44
ばぐつぶし • BSS領域のアライメントがあって無くてBSSクリアに失敗してた ◦ リンカスクリプトにアライン設定を追加 • GPUから謎のIRQ割り込みが入りまくり処理できずに落ちてた ◦ UART以外のIRQ割り込みをさせないよう修正 •
そのほか色々 ◦ 未処理 45
デモ echoコマンドがうごくよ 46
TODO • コミットを勉強用に整理する • コードをもう少しきれいにする • FBSD等のコンテクストスイッチを参考に改善する • 既知のバグを何とかする ◦
これはセキュキャン受講生がやってくれそう 47
まとめ • Raspberry PiでKOZOSが動くようになった • 使用するモードをSystemモードに限定してH8と動作をあわせて問題を解決 • とりあえずechoが動きます 48