2017年5月30日火曜日

STMでUARTのフロー制御




 STM32F4のUARTでHardFlowControlを試してみた。結論から言うと、「ハードウェアフロー制御」は事実上不可能っぽい。

 試したのはUSART3で受信したデータをQueueに送り、10msec毎にキューをチェックして、データが有れば1バイト取り出してUSART1から送信する、という挙動。USART3はPCからおよそ270バイトを連続して送信している。Queueは256バイトあり、Queueは10msec毎に1バイトを取り出すから、途中でバッファが一杯になる。

 最初、Queueが一杯になったらUARTの受信割り込みを停止する、という挙動を実装してみた。受信割り込みを止めれば新たなデータが来てもUSART.DRからデータが抜けないので、USARTがハードウェアでRTSを立ち上げる。
 しかし、テストで使ったUSB-TTL232アダプタはCTSの変化から実際に送信を止めるまでに数バイトを送信してしまい、マイコンがRTSを上げても次のデータが送られてしまった。

 今回は、キューの使用率が75%になったらソフトウェアでRTSを立ち上げ、キューの使用率が50%を下回ったら受信タスク内でRTSを立ち下げる、という挙動を実装してみた。
 一応、取りこぼし無くフロー制御ができているようだ。

 もしかしたら、オーバーランエラー割り込みとかを使えばこのあたりもうまく処理できるのかもしれない。


 ソフトウェアでバッファの使用率を測るにあたり、本来は キュー使用量 >= キューサイズ * 3 / 4 のような判定を行うのが良いはず(ISR内で計算を行う是非は置いておいて)。しかし、FreeRTOSのQueueはISR内でキュー使用量とキューサイズを取得することができないらしい。ということで、今回はISR・受信タスク共に値をべた書きしている。
 ちなみにcmsis_osでのラッパーでもISR内で使用量を得るような関数は用意していないようだ。
 cmsis_osのラッパーは単純にFreeRTOSの関数を再呼び出ししてるだけなので、他のOSに移植できるのか怪しい感じ。単純に再呼び出しするだけならマクロとかで実装してくれればいいのに、ちゃんと関数で実装してるからいちいち関数呼び出しのコストが発生する(はず)。
 マイコンでそんなに抽象化する必用あるのかねぇ。

0 件のコメント:

コメントを投稿