こんにちは!
組み込みエンジニアなら誰もが一度は夢見る「OS自作」を実現しました。
本記事では、ARMv7-Mアーキテクチャ(Cortex-Mコア)向けに教育目的でゼロから開発した最小限のリアルタイムOS (RTOS) である「tinyos-rtos」の設計思想と、その核となるタスクスケジューリングの仕組みを徹底解説します。
低レイヤーの仕組みを深く理解したい方、RTOSの仕組みをわずか数百行のコードで学びたい方は、ぜひ最後までご覧ください!
🌟 tinyos-rtos の特徴
| 特徴 | 説明 |
|---|---|
| ターゲット | ARMv7-M (Cortex-M) 例: STM32, Kinetisなど |
| 目的 | RTOSの基礎(タスク管理、スケジューリング)を学ぶための教育用 |
| 実装言語 | C言語と最小限のインラインアセンブラ |
| ライセンス | MIT License (自由に利用・改変可能) |
🔗 GitHubリポジトリはこちら
https://github.com/cmc-labo/tinyos-rtos
🧠 RTOSの核!コンテキストスイッチの仕組み
RTOSの面白さは、複数のタスクが同時に動いているように見せかけるための「コンテキストスイッチ」にあります。
tinyos-rtosでは、このスイッチングにCortex-Mが提供する**例外ハンドラ(割り込み)**を利用しています。
1. PendSV割り込みとタスクスイッチ
タスク切り替えの要求は、ソフトウェアがトリガーできるPendSV (Pendable Service Call) 割り込みによって処理します。
- タスクA 実行中に切り替えが必要になると(例: タイムアウト)、PendSVをペンディング(保留)します。
- 現在の処理が完了した後、PendSVハンドラが実行されます。
PendSVハンドラ内で行われるのが、以下の処理です。
-
古いコンテキスト(タスクAの状態)の保存
現在のスタックポインタ(SP)が指すメモリに、タスクAの実行に必要なレジスタの値(R4-R11など)を保存します。 -
次タスクの決定
スケジューラが次に実行すべきタスク(例: タスクB)を決定します。 -
新しいコンテキスト(タスクBの状態)の復元
タスクBのスタックポインタから、保存されていたレジスタの値(R4-R11など)をレジスタへ復元します。 -
タスクBへ制御を移行
例外ハンドラから復帰する際、スタックからPC(プログラムカウンタ)などが復元され、タスクBの実行が再開されます。
この一連の処理を数百行のCコードとアセンブラで実現している点が、このOSの最もエキサイティングな部分です。
📚 注目ポイント
最小限のコードでタスクスイッチを実現するため、アーキテクチャが自動的に保存するレジスタ(R0-R3, R12, LR, PC, PSR)を最大限活用し、手動で保存するレジスタ数を削減しています。
🛠️ tinyos-rtos のセットアップと実行
実際にこのOSがどのように動くかを確認してみましょう。
1. 必要なツール
- GCC (ARM Embedded Toolchain)
- CMake
- ターゲットマイコン向けの環境(例: OpenOCDなど)
2. ビルドと実行 (例: XXXボード)
# GitHubからクローン
git clone [https://github.com/cmc-labo/tinyos-rtos.git](https://github.com/cmc-labo/tinyos-rtos.git)
cd tinyos-rtos
# ビルドディレクトリ作成とCMake実行
mkdir build && cd build
cmake ..
make
# バイナリの書き込みと実行
# (ご自身の環境に合わせてコマンドを記載。例: openocd -f ... -c "flash_write tinyos.elf")
3.デモコード解説 (Lチカの例)
main.c には、タスク切り替えが目で見てわかるように、異なる速度でLEDを点滅させるデモが含まれています。
// 💡 Task 1: 500ms周期でLEDを点滅
void task_led1(void *arg) {
// ...
while (1) {
// LED点灯/消灯処理
// os_delay(500); // 500ms待機 (ここでタスクスイッチが発生する)
}
}
// 💡 Task 2: 250ms周期でLEDを点滅
void task_led2(void *arg) {
// ...
while (1) {
// LED点灯/消灯処理
// os_delay(250); // 250ms待機 (ここでもタスクスイッチが発生する)
}
}
それぞれのタスクが独立して実行され、周期的にCPU時間を分け合っていることが確認できます。
今後の展望とコントリビュートのお願い
現在は最小限の機能に絞っていますが、今後は以下の機能を追加する予定です。
- 動的メモリ管理 (malloc/free) の追加
- セマフォやミューテックス など、より高度な同期プリミティブの実装
- デバッグ機能 の強化
この記事を読んで興味を持った方、低レイヤー開発が好きな方は、ぜひGitHubで Star を押したり、Issue や Pull Request で開発に参加していただけると嬉しいです!
🎉 自作OSの世界へようこそ!一緒に tinyos-rtos を育てていきましょう!