TOPPERS/SSPを用いた教育訓練カリキュラムカーネルの自作およびカ
スタマイズ
アライブビジョンソフトウェア株式会社高橋和浩https://www.facebook.com/firstandlastandallwaysTOPPERSプロジェクト 特別会員(個人)
アイデアアプリケーションコンテスト アイデア部門 入賞
バックグランド(それまでの経緯) ルネサスエレクトロニクスの
RTOS(μITRONカーネル )のおよそ 8年ほど受託開発。 M32C M16C R32C RXなど
ポリテクセンター兵庫にて、在職者向けコース( μITRON) を担当 (H24より実施)
動機 ITRONを使うセミナから作るセミナにしたい
受講生からの要望 オープンソースの OSを使う以上、中身の理解の必要性
入り口として、もっとも手軽なもの 最少セットカーネル
Linuxのカーネルに読破にくじけた人にも OS自作本などのニーズ
μITRON(RTOS)の講習会 ポリテクセンター兵庫(武庫之荘)で実施 ・ μITRON基本 ・ μITRONネットワーク ・新講習 RTOS自作とカスタマイズ(本年1月実施)
いずれも土曜日 3日間 H27年度ももちろんあります
RTOS自作講習会の概要 標準 ITRONガイドブック(作り方の章) 特に専門用語の解説をしっかり TOPPERS/SSP(オープンソース μITRON)をベース(シュリンク版というものを利用)
ボードで実際に演習を交えて実施(雑誌付録ボード RX62n)+E1デバッガ
ソースコードをステップベースで解説していきます。
(SSPは省ステップなので可能) SSP本来の機能からカーネル機能拡張(待ち状態を追加)作業を演習実施。 dly_tskを実装していきます。
講習のサンプル ソースコード解説の例 カーネル拡張の例
カーネルコード解説 sta_ker()から始まる。 マルチタスクになる前段階の処理
ブート一回目だけの処理としてカーネルオブジェクトの生成がある。
SSPはカーネルオブジェクトといってもタスクのみ
TCBの初期設定をする。 最後にディスパッチャを呼ぶ
void
sta_ker(void)
{
initialize_object();
kerflg = true;
intnest = 0;
dispatcher();
}
カーネルコード解説 2 ディスパッチャ部分 これは、途中で待ちにならない SSP特有のディスパッチ処理。
優先度の高いタスクにプリエンプトはするが、待ち状態にはならないから、タスクの高いタスクが終了してから低いタスクの起動はこういう単純な呼び出しでよい。
さらに SSPはスタック共有型なのでスタックを切り替える必要はない。
カーネルコード解説 3 スケジューラは、今のレディーキューから、次にディスパッチするタスクを選ぶ処理。
レディーキューの構造に依存するが、 SSPは単純なビットマップのみ
uint_t
search_schedtsk(void)
{
return primap_search();
}
カーネルコード解説 4ER
act_tsk(ID tskid)
{
ER ercd;
uint_t tskpri;
LOG_ACT_TSK_ENTER(tskid);
CHECK_TSKCTX_UNL();
CHECK_TSKID_SELF(tskid);
tskpri = get_ipri_self(tskid);
t_lock_cpu();
if (test_dormant(tskpri)) {
if(make_active(tskpri)) {
run_task(tskpri);
}
ercd = E_OK;
}
else {
ercd = E_QOVR;
}
t_unlock_cpu();
error_exit:
LOG_ACT_TSK_LEAVE(ercd);
return(ercd);
}
カーネルコード解説 5 最後は、ユーザーからの OS呼び出しである。
タスクの起動で、基本はまずレディーキューに指定したタスクの TCBをキューイングする
カーネルの最後(遅延ディスパッチで)今の最優先タスクを動かす。
SSPは単純にサブルーチンコールしかしていないので、
タスクは常に頭から動くが、プリエンプトされて復帰するケースは
自タスクよりも高いタスクを起動した場合。 起動されたタスクが終了した時点で、タスク起動後に戻ればいいのでサブルーチンコールするのと同じ作りで実現している
タスクスイッチの例 (追加ページ) タスク 2が RUN中に、 act_tsk()でタスク 1を起動
タスク 1が優先度が高い場合 タスク 1がサブルーチンコールされる動き
タスク2 中断
実行タスク1
時間act_tsk(task1)呼び出し
移植対応部 アセンブリ言語
割込み時のタスクスイッチの例(追加ページ) Task2が RUN中に割り込みが発生 割込みハンドラで iact_tsk(task1)を呼び出
Task1が優先度高い
0 1 2 3 4 5
割り込み処理
Task2
割り込み発生
Task1
時間Copyright (C) Reserved 2010 Embedded Systems Co.,
割り込み発生 iact_tsk(task1) Running
Ready
Dormant
カーネル (RTOS)仕様
シュリンク版 SourceForgeに公開 http://sourceforge.jp/projects/shrink-sp-rx62n/ 本物との違い 割込みベクターの登録およびスタートアップの削除 OSなし環境を流用
なぜ作ったか? SSPカーネルの簡潔な処理に比較して割り込みベクタ関係の処理の難度が高く、コード量も多い。カーネルを学ぶために必要な部分だけ残した。それで動くことが必要と考えた
TOPPERS/SSP のカスタマイズ フル改造編
(1)待ち状態を持つカーネルの設計 (2)実装 イ.コンテキストの保存と復元 ロ.サービスコール部の作成 (3) dly_tskの追加 イ.実装に必要な項目の整理 ロ.指定時間待ちの実装 (dly_tsk) (4)評価・改善 イ.制作したカーネルを用いる際の問題点の把握 ロ.問題点の改善
(1)待ち状態を持つカーネルの設計
待ちを持つということは タスクが run --> wait --> dormant wait --> ready
中断したところから再開しなければならない。
コンテキストの保存と復元 1.コンテキストの保存エリアを検討する。 2.コンテキストからタスクが復帰する仕組みでのタスク起動部を実装する
3.タスクスイッチする場合にコンテキストの保存と復帰をします。
タスクがスイッチするときにコンテキストを保存 /復帰するように実装する。
longjmp/setjmpの利用 コンテキストの保存領域を渡して callすれば、そこに保存される。
割込みには対応できないので工夫が必要 シュリンク版の移植性を考慮して Cでできるだけ実装
longjmp/setjmpの限界 RTOSのコンテキスト保存は、 longjmp/setjmpだけでは、すべての場合に対応できません。
少なくとも戻り値が、 R1レジスタが保存されないことがある。
割り込みには対応できない 割り込み部でレジスタ保存 /復帰を補完する必要がある。
Longjmp/setjmpの考え方 Setjmpはコンパイラが把握 OS呼び出しの場合は、 setjmpを使い、これはコンパイラが把握できる。 Setjmpから戻る場合は、レジスタ一式が復帰して jmpしてくるが保存を必要としない一部のレジスタを壊しても続行できる。
割込みはコンパイラが把握できない 割り込みの場合はコンパイラが把握していないため、どこでどのレジスタを壊していいということがなくなる。
今後の展開 ポリテクセミナーの内容(プラットフォーム)の見直し
SSPシュリンク版の拡張
セミナのプラットフォーム
シュリンク版のこれから ハード依存部が少ないことから移植がしやすいはず
raspberry pi に移植しました (baremetal環境)http://www.slideshare.net/alvstakahash
i/raspberry-pi-toppers-ssp
シュリンク版の展望
ありがとうございました ポリテクセンター兵庫 在職者研修http://www3.jeed.or.jp/hyogo/poly/contents/holding/index.html正式名称独立行政法人高齢・障害・求職者雇用支援機構
兵庫職業訓練支援センター 兵庫職業能力開発促進センター
アライブビジョンソフトウエア株式会社http://homepage3.nifty.com/ALVS/
Facebookhttps://www.facebook.com/firstandlastandallways
ありがとうございました