# 第1章: ブートシーケンス リセット直後の CPU が何をするかを追いかけ、ベクタテーブル(例外や割り込みが起きたときに飛ぶ先のアドレスを並べた表)から main() に至る道筋を自分の手でたどります。 ## サンプルコード - ディレクトリ: `docs/os-on-arduino/code/01_boot` - ビルドと書き込み: ```bash uv run pio run -d 01_boot -t upload uv run pio device monitor -b 115200 ``` コードを見る: [docs/os-on-arduino/code/01_boot](https://github.com/iory/learning-os-from-arduino/tree/main/docs/os-on-arduino/code/01_boot) ## ソースコード この章のスケッチです。ファイル名をクリックすると開きます。コードは原稿リポジトリから自動で同期されているので、ここに出ているものが常に最新です。 ### `docs/os-on-arduino/code/01_boot` :::{dropdown} `src/main.cpp` — 63 行 :icon: code [GitHub で開く](https://github.com/iory/learning-os-from-arduino/blob/main/docs/os-on-arduino/code/01_boot/src/main.cpp) ```{literalinclude} ../../../../code/01_boot/src/main.cpp :language: cpp :linenos: ``` ::: ### `docs/os-on-arduino/code/01_boot_vector_dump` :::{dropdown} `src/main.cpp` — 60 行 :icon: code [GitHub で開く](https://github.com/iory/learning-os-from-arduino/blob/main/docs/os-on-arduino/code/01_boot_vector_dump/src/main.cpp) ```{literalinclude} ../../../../code/01_boot_vector_dump/src/main.cpp :language: cpp :linenos: ``` ::: ## 実機での出力 Arduino UNO R4 WiFi の実機で実際に取得した出力です(macOS / Windows の 両方で同じ結果を確認しています)。手元の出力と見比べてください。 `S` を 1 文字送ると出力が始まります。 ```{figure} ../_static/ch01_boot.gif :name: fig-ch01-boot :width: 100% モニタを開いてしばらくは何も出ず、`S` を送った瞬間にまとめて出てくるところ。 `data_var` が `12345` になっていれば、初期化済みデータのコピーが効いています ``` ```text === Boot Sequence Check === bss_var (should be 0): 0 data_var (should be 12345): 12345 === Memory Addresses === &bss_var: 0x200000C4 &data_var: 0x20000000 VTOR: 0x20007F00 MSP: 0x20007EC8 If you see this, boot sequence completed! ... ``` `VTOR`(Vector Table Offset Register)はベクタテーブルの置き場所を示すレジスタ、 `MSP`(Main Stack Pointer)はいま使っているスタックの位置を指すレジスタの値です。 ### 演習1-2: ベクタテーブルの読み取り この出力は別のプロジェクト `01_boot_vector_dump` のものです。書き込んでモニタを開き、 `S` を送ってください。 ```bash uv run pio run -d 01_boot_vector_dump -t upload uv run pio device monitor -b 115200 ``` ```text === Vector Table Dump === [ 0] 0x20007F00 Initial SP [ 1] 0x000098DD Reset [ 2] 0x00009BA1 NMI [ 3] 0x00006651 HardFault [ 4] 0x000098D9 MemManage [ 5] 0x000098D9 BusFault [ 6] 0x000098D9 UsageFault [ 7] 0x000098D9 Reserved [ 8] 0x00000000 Reserved [ 9] 0x00000000 Reserved [10] 0x00000000 Reserved [11] 0x000098D9 SVCall [12] 0x000098D9 DebugMon [13] 0x00000000 Reserved [14] 0x000098D9 PendSV [15] 0x000098D9 SysTick Note: Handler addresses point to Flash (0x000xxxxx) Initial SP points to RAM top (0x200xxxxx) ... ``` 右の名前は例外の種類です。主なものを挙げます。 - `NMI`: 止める(マスクする)ことができない割り込み - `HardFault`: ほかで処理できない重大なエラーのときの例外。第6章で詳しく扱います - `SVCall`: `svc` 命令で呼び出す例外。応用編2でシステムコールの入り口に使います - `PendSV`: 「あとで実行して」と予約できる例外。第3章でタスクの切り替えに使います - `SysTick`: 一定周期で起きるタイマ割り込み。第4章でスケジューラの時計に使います ## つまずきやすいポイント (読者からの質問に応じて随時追記します。質問は [GitHub Issues](https://github.com/iory/build-your-own-arduino-rtos/issues) へどうぞ)