FreeRTOS を使い始めました~

少し時間が出来たので、FreeRTOS をポートして、自分の環境で動かし始めた。

詳細は、
「RXマイコンで、FreeRTOS を使う場合の要点
に投稿している。

自分のブログでは、今回「はまった」点にフォーカスしてみたい。

そもそも、FreeRTOS は RX マイコンをサポートしており、RX マイコン用コードもアーカイブに含まれる。
しかし、それは、ルネサスさんの環境用で、自分のように、gcc を自前でコンパイルして使っている場合、そのままでは使えない。

それと、ルネサスさんの環境用なので「iodefine.h」定義が必要なのも、敬遠する理由となっている。
※ハードウェアー定義は C++ クラスで独自に実装してある。

なので C++ ベースの制御クラスを定義して、そのコンテキストを FreeRTOS に使ってもらうようにしたい。

最初は、「簡単」だと思ってやっていたが、勘違いから、かなり時間を使ってしまった・・・

FreeRTOS では、ソフトウェアー割り込みも使う。
今まで、ソフトウェアー割り込みは使った事がなく、割り込み関係クラスもサポートしていなかったので、それらを追加した。
※これが、間違いの始まり・・・

「SWINT」はベクター番号27で、この割り込み許可と、割り込みレベル設定は、ICU 関連レジスターにある。
割り込み許可は、問題無かったが、割り込みレベル設定は、IPRのベースアドレス+27と思い込み、そのような設定にして、何の疑いもしなかった。

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
/*!
    @brief  IPR レジスタ @n
            全て、下位4ビットが有効
*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
template <uint32_t base>
struct ipr_t {


 
   rw8_t<base + 27> SWINT;



};
static ipr_t<0x00087300> IPR;

そして、ようやく、主要な部分が出来て、簡単なサンプルを用意して、マイコンに書き込み起動するが動作しない・・・

その過程で、色々「マズイ」部分も見つかり、直すが、全く動かない。

デバッグ用コードを入れて、どこまで動いているか確認すると、定義したタスクが起動していない・・・

そして、なぜ起動しないのか、ソースを追うと、どうやら、ソフトウェアー割り込みが怪しい事に気がつき、単独で、ソフトウェアー割り込みの動作を確認してみた。

当然のように「動かない」・・・

そこで、ハードウェアーマニュアルを見直したら、ベクター27のソフトウェアー割り込みレベル設定は、+3である事が判った・・・
それを修正したら、動作するようになった。

    rw8_t<base + 3> SWINT;

そこで、不思議に思った事がある・・
ソフトウェアー割り込み(SWINT)を使う場合、「asm("int #27");」を実行するハズだけど、どこを探しても、それらしい実装が見つからない。
よくよく調べると、ICU レジスターには、ハードウェアーから、SWINT を発生させる機能があり、それをハードコードしていた。
※「portmacro.h」

#define portYIELD()                         \
    __asm volatile                          \
    (                                       \
        "PUSH.L R10                 \n"     \
        "MOV.L  #0x872E0, R10       \n"     \
        "MOV.B  #0x1, [R10]         \n"     \
        "MOV.L  [R10], R10          \n"     \
        "POP    R10                 \n"     \
    )

「0x872E0」 に「1」をライトするのがそれだー、これは痛い・・・
何で、iodefine.h をインクルードしているのに、こんな事してるのか?
それに、こんな面倒な事しなくても、「asm(int #27);」で良くない??

疑問は残るけど、FreeRTOS に戻って、実験したらようやく動作したーー(ヤレヤレ~)

そもそも、ハードウェアー依存部分は、完全に外部に出せるから、「port.c、portmacro.h」に含める必要性は無いのに・・・

そんなこんなで、動くようになったので、github に上げた。

これから、色々マルチタスク対応にしていこうと思う。

追記:
「ソフトウェアー割り込み命令(int #27)」と「SWINT ハードウェアー割り込み」は動作が異なるとの知見(RXマイコン内の動作がどのように異なるのか不明なので、完全に理解している訳ではないが・・)を受けて、とりあえず以下のように変更した。

※気になっていたのは、32ビットリードなので・・

#define portYIELD()                         \
    __asm volatile                          \
    (                                       \
        "PUSH.L R10                 \n"     \
        "MOV.L  #0x872E0, R10       \n"     \
        "MOV.B  #0x1, [R10]         \n"     \
        "CMP    [R10].UB, R10       \n"     \
        "POP    R10                 \n"     \
    )