RTOS: TI-RTOS Kernel codeとpthread
今回は、TI-RTOS Kernel codeとpthreadについて。
pthreadは規格で定まっている汎用的なC言語でも使うため、情報量も多くRTOSにてマイコンを動かすにしても理解しやすい、またコードをFreeRTOSに変更するにもやりやすいというメリットがある。
一方、TI-RTOS Kernel codeは、TI社独自でまあ、なんと言ってよいか情報もあるにはあるが勉強するにも難しい。なら、pthreadでいいんじゃないか!
そうどう記述しても、マイコンに何をさせたいのか?が重要であって多少コードの大きさとか処理スピードとかもあるかもしれないが大差はないため、pthreadをしっかり理解すればOK!
なぜでは、TI-RTOS Kernel codeが存在するのか・・・ってのがお題。
Project Wizardからempty(TI-RTOS)をインポートする複数スレッドでLEDを点滅させる所までを作る。(詳細はここ)
さらに前回Kernel のcfgファイルを取り込む方法について記載した通りにこれにcfgを取り込む。
上記までを実施すると、.cfgが取り込まれた複数のスレッドを実行できるプロジェクトになっている。
int main(void)
{
pthread_t thread0,thread1;
pthread_attr_t attrs;
struct sched_param priParam;
int retc;
Board_init();
/* Initialize the attributes structure with default values */
pthread_attr_init(&attrs);
/* Set priority, detach state, and stack size attributes */
priParam.sched_priority = 1;
retc = pthread_attr_setschedparam(&attrs, &priParam);
retc |= pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
retc |= pthread_attr_setstacksize(&attrs, THREADSTACKSIZE);
if (retc != 0) {
/* failed to set attributes */
while (1) {}
}
retc = pthread_create(&thread0, &attrs, mainThread0, NULL);
if (retc != 0) {
/* pthread_create() failed */
while (1) {}
}
/* Set priority, detach state, and stack size attributes */
priParam.sched_priority = 1;
retc = pthread_attr_setschedparam(&attrs, &priParam);
retc |= pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
retc |= pthread_attr_setstacksize(&attrs, THREADSTACKSIZE);
if (retc != 0) {
/* failed to set attributes */
while (1) {}
}
retc = pthread_create(&thread1, &attrs, mainThread1, NULL);
if (retc != 0) {
/* pthread_create() failed */
while (1) {}
}
BIOS_start();
return (0);
}
ってな感じのメインになっているが、ここでTI-RTOS Kernel codeで
これを書き直す事もできる・・実際に書き換える事はやらないが
/* Construct BIOS Task */
Task_Struct task0Struct;
Char task0Stack[THREADSTACKSIZE];
...
Task_Params taskParams;
Task_Params_init(&taskParams);
taskParams.priority = 1;
taskParams.stackSize = THREADSTACKSIZE;
taskParams.stack = &task0Stack;
taskParams.instance->name = "echo";
Task_construct(&task0Struct, (Task_FuncPtr)mainThread0, &taskParams, NULL);
ってな感じになる。ならどっちでもよいじゃん。むしろpthreadの方が汎用的だしTI社にロックされないからいいよねとなる。
実はこれらのコード、TI-RTOS Kernel codeだとGUIをポチポチとやるだけで自動でコード生成されるのだ。
.cfgのファイルを右クリックして、Open with - XGCONFとして開く。Outlineにいろいろ並んでいる所から”Task”をクリックし、上の方でModule、Instance,AdvanceとならんでいるInstanceを選択する。
pthreadで書いたハンドルと名前を合わせてthread0とした。
それに割り当てるFunctionを指定する。これはexternalで参照できるようにしている関数名mainThread0そのものを割り当てる。そしてAdd...のボタンを押すとTaskが追加される。
同じように、thread1にもmainThread1を割り当てる。
バグだと思うが、後で追加した方はエラーが出るので、もう一つAddで追加して、すぐ選択してRemoveをするとエラーは解消される。
ここで、mainに戻り、さっきは、
int main(void)
{
pthread_t thread0,thread1;
pthread_attr_t attrs;
struct sched_param priParam;
int retc;
・・・・
とpthreadによる記述が続いているが、ぜーーーんぶ、スレッドに関する記述は削除してしまう。
int main(void)
{
Board_init();
BIOS_start();
return (0);
}
メインはこれだけにする。
これでビルトしてみるとエラーが出ない。むろん何もないからエラーが出ない?
そうではなくても、このまま書き込みをして動作を確認すると、2つのLEDがちゃんと異なる周期で点灯する。
ではどうして?
.cfgファイルをOpen with - XDCScript Editorで開いて、下の方を覗いてみると
var Task = xdc.useModule('ti.sysbios.knl.Task');
var ndkHooks = new Task.HookSet();
ndkHooks.registerFxn = '&NDK_hookInit';
Task.addHookSet(ndkHooks);
var task0Params = new Task.Params();
task0Params.instance.name = "thread0";
Program.global.thread0 = Task.create("&mainThread0", task0Params);
var task1Params = new Task.Params();
task1Params.instance.name = "thread1";
Program.global.thread1 = Task.create("&mainThread1", task1Params);
と記載されていて、ここで、タスクを生成してくれている。
つまり
pthread : 汎用的なスレッド記述で動かす事が出来て、他のRTOSへの移植等がやりやすい
Kernel code:GUIを使って必要事項を記述するだけで、ユーザがコードを書かなくてもタスクの登録ができてしまう。
コメント
コメントを投稿