2011年3月1日火曜日

Cortex-M3 + FreeRTOS = 備忘録

最近はRTOSとして、FreeRTOSを使ってみることが多くなった。uITRON系よりも良いとか悪いとか比較する気はないけれど、FreeRTOSの特徴を挙げてみると・・・

  • シンプルで必要最低限の機能なのが○
  • タスク間通信機能はもうちょっとあっても良いのでは?
  • タスクのサスペンドとレジュームが「カウンタ」方式でないのが、たま~に困ることも・・・


こんな感じですが、安定性や移植性も十分合格点に達していると思う。

さて、このFreeRTOSですがCortex-M3と組み合わせて、割り込み関数内からいわゆる"FromISR"系APIを呼び出していると、まれにvListInsert()関数内で無限ループしていることが起こる。動かなくなったのでデバッガで強制breakするといつもこの関数内で足止めをくらっているという感じ。

無限ループしている行は、

for( pxIterator = ( xListItem * ) &( pxList->xListEnd );
pxIterator->pxNext->xItemValue <= xValueOfInsertion;
pxIterator = pxIterator->pxNext )
{
/* There is nothing to do here, we are just iterating to the
wanted insertion position. */
}

という部分なのだけれど、親切にもこの行の直前にコメントがあり、”この部分でクラッシュする可能性があるのは次の4つがある”と原因も列挙されている。
今回ハマったのはこのうちの2番目だったのだけれど、リンク先を見てもちょっと分かりにくい。

かいつまんで結論を書くと、
  • カーネルの割り込み優先レベルと、実機で使用している割り込み優先レベルとの関係が重要で、FreeRTOSの"FromISR"系APIを呼び出す可能性のある割り込みハンドラの割り込み優先度はFreeRTOSConfig.hに定義されている`configKERNEL_INTERRUPT_PRIORITY'~`configMAX_SYSCALL_INTERRUPT_PRIORITY'の間に設定しなければならない。


ということになる。
その上で勘違いしやすいのが、Cortex-M3の場合は優先度=0が最も優先度が高く、優先度=255がもっとも優先度が低い、ということ。先のガイドラインに従うと、

  • configKERNEL_INTERRUPT_PRIORITY'はもっとも優先度を低く設定しなければならないから255を設定
  • configMAX_SYSCALL_INTERRUPT_PRIORITYは適宜設定してよいがこの値よりも大きい(=優先度が低い)優先度の割り込みハンドラからは"FromISR"系APIが呼び出せて、逆にconfigMAX_SYSCALL_INTERRUPT_PRIORITYよりも値が小さい(=優先度が高い)優先度の割り込みハンドラからは"FromISR"系APIが呼び出せない代わりに、カーネルよりも高いリアルタイム性で割り込み処理ができる

ということになる。

余談だけれど更にややこしいことに、Cortex-M3のアーキテクチャとしては割り込み優先度は0~255までの256段階で設定できることになっているけれど、実際の実装(StellarisやSTM32、NXPなど)では8段階とか16段階になっているということがある。割り込み優先度レジスタは8bit幅で用意されていても書き込んだ値の下位nbitは常に0となって読み出されるという具合。

実はこの無限ループの一件でハマったのは今回が2回目だったような・・・。学習能力に問題アリだなぁ。

0 件のコメント:

コメントを投稿