CMSIS-RTOSとFREERTOS

By 酔漢 - Last updated: 月曜日, 1月 15, 2018 - Save & Share - Leave a Comment

CubeMXが生成するコードには、FREERTOSを含めることができます。ブロッキングIO処理等RTOSを使わないと実現が難しい機能を作り込む上で大変重宝します。

ただ、CubeMXが生成するコードを見ると、どうやらFREERTOSを生で使わせずにCMSIS-RTOSのラッパー越しに使わせたいようです。となると、CMSIS-RTOSの詳細を調べておかなければなりません。ここひと月ほどFREERTOSの実装や詳細をちょこちょこ調べていましたが、それなりに技術情報はあるのでなんとかなりました。しかしCMSIS-RTOSはどうでしょうか。

と、思っていたのですが、わざわざ調べるまでもなく先人が書いていました。

どうやら、ラッパーレイヤーの実装に不安があるようです。他にこんな情報も。

FREERTOSのAPIを叩いて使うことにします。

ところで、FREERTOSはタスクから使う場合とISRから使う場合で異なるAPIを用意していることがあります。コンテキスト切り替えは繊細な作業ですのでこれはよくある措置ではあるのですが、一方でコンテキストを知る手段が無いためえらく難儀しました。

コンテキストに合わせてAPIを使い分けるという発想はわかります。返り値にコンテキストエラーを返してくれるのなら、通常はそれほど困りません。しかしながら、デバッグ・メッセージ出力のような機能は、バグが起きたときしか呼び出されません。いざ必要な時にコンテキスト・エラーを返されても困ります。そういうわけで、コンテキストにかかわらず動作する関数を実装することになります。

コンテキストにあわせて動的にAPIを呼び分けるには、コンテキストを検知する必要があります。ところがFREERTOSにはそのためのAPIが無のです。これには閉口しました。同じような事を考えている人はいるようで、質問を何件か目にしました。例えばこれです。

ちなみに回答には間違いがありますのでご注意を。ビットフィールドマスクの長さが、CORTEX-M4用としてもLPC4330用としても足りません。また、これは誰が改変したのかは不明ですが、portNVICINTCTRLREGというマクロはCubeMXが出力するFREERTOSには存在せず、portNVIC_INT_CTRL_REGというマクロになっています。

そういうわけで、自分で作った判別関数がこれです。

/**
 * \brief determine task or ISR context
 * \returns true if task context, false if ISR context.
 */
inline bool isTaskContext()
{
    // portNVIC_INT_CTRL_REG is mapped to the address 0xe000ed04 by portmacro.h. This register is
    // officially called as NVIC ICSR by ARM
    // This register is common among CORTX-M3, M4 and M7 ( Not checked M0 and M1 )
    // The bit field 8:0 displays the on-going ISR number. So, if this field is 0, it is task context.
    // ( Note : This is just guess. ARM technical manual is not cleear when this field is 0 ).
    // This register and field is suggested to use to detect the context in this page.
    // https://www.freertos.org/FreeRTOS_Support_Forum_Archive/September_2014/freertos_How_to_determine_current_context_type_-_interrupt_or_task_87aef448j.html
    // But the answer in this page seems to be wrong. It is referring only LSB 5bits. For the specific
    // LPC4330 which is focused in this page, 0x1F is still too short.
    // To extract the entire bit field 8:0, the bit mask have to be 0x1FF

    return ((portNVIC_INT_CTRL_REG & 0x1FF) == 0);

}

コメントに書いているとおり、ARMのTechnical Referenceを読む限りこれでタスクコンテキスト(STM32に使われているFREERTOSの実装ではThread mode )を検出できるか否かはあいまいですが、デバッガで追う限りは検出できています。

 

 

 

Posted in STM32 • • Top Of Page

Write a comment