始めに
ここ半年以上、自作CPUのデバッグを兼ねて、FreeRTOSのポーティングを行ってきました。今回、さらにFreeRTOS_CLIとFreeRTOS+FATの実装もやってみました。何となく動作しているのですが、ここまでいろいろとはまったので、自分メモを兼ねて書き連ねます。メモしたいことが出れば更新していきます。
なお、ここでは、自作CPUで以下を使用し、FreeRTOSのDemoのうち、spikeシミュレータ向けのも(Demo/RISC-V-spike-htif_GCC)を改造、自作CPU向けにポーティングしたものを使用しております。
FreeRTOS+FATを使用するときの注意点
- Semaphoeを使用してロックを取っているので、Semaphoeの初期化を忘れないこと
⇒ 初期化されないため、ヌルポインタとなり暴走します。大体はセグフォかデッドロックを起こす。 - FAT32/16/12と自動対応しているため、MBRやブートセクタの読み出しをミスるとFAT12とかが選択されてしまう
⇒ 確認の時に出てくるコードがFAT32 = 12となるので、ややこしい。しばらくFAT12と勘違いしてしまいました。 - FAT32とかの読み出しシーケンスはドライバレベルの検証コードで試しておく
⇒ テストプログラムで現在のSDcardのどのセクタにどういうデータが入っているかを予め把握しておくと本チャンのデバッグがスムーズになります。違うセクタ読み出しとか行っている場合、挙動が不安定になります(経験しました…) - (ここに書く話かどうか)SDCardのコマンドシーケンスは、自作CPUのSPIがタコで1byte毎にCSが途切れてしまうが、それでもSDCardコマンドシーケンスを受け付けてちゃんと動く
⇒ 仕様外の用法なので、カード種類により動かないかもしれないが、TOSHIBA/キオクシアのカードは動作しました。SanDiskは起動しません。(デバッグ時の実験で発見しました)SanDiskも動作しました。CMD55とACMD41の間にダミーサイクルを入れたら動作しました・・・。
FreeRTOSでマルチタスクを使用するときの注意点(RISC-Vで試行、ほかも一緒と思われる)
- RISC-VのDemoプログラムでは、ものによってIllegal instructionなどの場合の処理が書かれていない
⇒ Cで関数を書けるので、CSRの値を表示するルーチンなどを書いて登録しておくと、無限ループの場合の原因究明が楽になります。コードの場所 Soruce/potable/XX/port.c - タイマー部分のアセンブラを把握、自分のCPU用にフリーランタイマーを書いておく
⇒ これだけで一応ポーティングが終わる コードの場所 Soruce/potable/XX/portASM.S - メモリの設定がMakefileとFreeRTOSConfig.hにある
⇒ 特に、Stackサイズが双方に出てきて意味が違うので注意。Makefileの方はFreeRTOSとしてのスタックのサイズで、FreeRTOSConfig.hは中に出てくるジョブのスタックサイズでmain_blinky.cで使用している。 - heapについても同じ。内部ジョブのheapはFreeRTOSのbssで取得される。それのサイズがFreeRTOSConfig.hのconfigTOTAL_HEAP_SIZEで取得される。Source/portable/MemMang/heap_4.c内部でheap領域を確保している。
MMUなしの自作CPUでのデバッグの注意点
- セグフォがないので、代わりにどこかでIllegal instructionか無限ループになる
⇒ メカニズムは、セグフォがないので、プログラム領域のどこかにデータを書き込む→CPUがそこを命令として読み込みIllegal instructionを発生、またはデータ領域を壊し、ループ変数を変にして無限ループ - Illegal instructionとなった場合に場所の特定は困難だが、あまり特定しても意味がない
⇒ 前の項目がほどんとなので、原因は全く別のところにある - リンカなどの設定に要注意
⇒ 当たり前なのですが、容易にプログラム破壊を引き起こします。MMUなしだとメモリ上限も要注意となります。
最後に
FreeRTOSは現在使用している超非力なFPGA上でのシングルCPU(50MHz動作ですが、外部メモリに依存しているため、1命令を70サイクルくらいで回しており事実上700KHz動作くらい)でもなんとか動いているので、組み込み向けにはいろいろと使えそうな気がします。今回、FAT32の操作を試してみましたが、継続でもう少し何ができるか考えていこうと思います。
