dsPIC(XC16)でFreeRTOS。xprintfを導入しfloatを扱う

カテゴリー: PIC  タグ: /

dsPIC33CKでFreeRTOSを使うの続編です。RTOSでsprintfを使いたいですが、標準入出力のprintf/scanfは共通ヒープメモリを使うのでRTOSではうまくない、とのことです。実際sprintfではうまくなかったです。そこでCHaN氏作「xprintf」の登場です。

「xprintf」はすでにPSoC5LPでFreeRTOSでも使っています。使いたい関数は、文字列に対する「xsprintf」で、今回はfloatを扱ってみます。

なお、試していませんが、一文字出力ルーチンに出力のポインタを指定すれば、LCDやUARTに直接出力することもできるらしいです。う~ん、これは凄い!

環境はMPLAB Xv5.45 XC16 v1.6です

ここから2021.1.11の最新版をDLしプロジェクトに「xprint.c」「xprint.h」を組み込みます。XC16では、floatを使わなければ、組み込んだだけで使えます。

floatを扱うには、XF_USE_FPを「1」にする

xprintfは、機能によってメモリを節約できるようになっています。floatと有効にするとメモリ容量は倍以上になります(サイトより:Cortex-Mでのモジュールサイズ)。

floatを扱うには「xprintf.h」のXF_USE_FPを「1」にします。

C99マクロ「isnan」「isinf」が使われているので作ることにする

関数ftoaの中でisnan()とisinf()が使われていますが、これはC99規格のマクロです。XC16ではリンクエラーになります。XC16の「math.h」で定義されていないのです。ここは自前で作ることにしました。

microchipのフォーラムより「isinf」のコードが出ていたのでとりあえず実装。isnanは数値でないもの自身を比較するとfalseが帰る、ということで仮に実装しました。目的のファームでは非数値やオーバーフロー数値を入れることはないので、仮に換装したということで機能は未確認です(すいません、各自のご判断でそうぞ・・・)。

XC16ではfloatとdoubleはおなじ32bitなので、違いは無視しています。


 

// returns 1 if positive infinity, -1 if negative infinity, 0 otherwise. 

int is_inf(float f) {
    long l;
    l = *((long *)&f);
    if (l == 0x7F800000) return 1;
    if (l == 0xFF800000) return -1;
    return 0;
}

int is_nan(float f) {
    if(f==f) return 0; else return -1;
}


ここで、isとの間にアンダースコア「_」をいれたのは、isnanやisinfとするとサポートしていないはずなのに「built-in」ワーニングがでるからです。そのため「xprintf.c」に手を加えisnan→is_nan、isinf→is_infとすこし改変しました。

コンパイルが通り、動くようになるーーータスクスタックを増やす

これでコンパイルが通りました。xsprintfはメインタスクで使いますが、スタックをとりあえず100増やして動くようになりました。

実績があり緻密に作られたプログラムを、ゆるい解釈で使うのはまことに恥ずかしい限りですが、うまく動くところまでこぎつけたので、感謝ですm(_ _)m

お気軽にコメントをどうぞ。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)