日記帳だ! with Tux on Libserver

二度目の大改造!! 日記帳…か?を継承し、より柔軟でパワフルなBlogに変身しました。

RSSに対応しています。リンク・コメント・トラックバックは自由にしていただいてほぼ問題ありません。
RSS購読方法、僕のリンク・コメント・トラックバックについての考えを読むことをおすすめします。

JavaScriptを有効にし、Cookieを受け入れ、以下のブラウザを使うことで完全なコンテンツが楽しめます。
Mozilla Firefox 3.0(Get Firefox)・Opera 9.6・Safari 3.2・Lunascape 4/5(Gecko)・Lunascape 5(WebKit)
Internet Explorer 7/8とそれを使うIEコンポーネントブラウザ(Lunascape・Sleipnirなど)

<< 過去

未来 >>

ゴミデータが残っちゃう

今日は先週末に発見したバグを修正していた。

マイコンの通信ペリフェラルに関するバグなのだが、意外なバグだったので。


このシステム、送信中に特定の事象が発生した場合は、その時点で送信を停止する仕組みがある。

ただ、この送信を停止する条件というのは、通常あまり考えられないことで、さらに言えばなにもせずとも受信側で破棄されるはず。

だから、この仕組みの必要性はよくわからないのだが、現行品にある仕組みだし、特に害があるわけでもない。

それで実装したのだが、送信中を停止するということにちょっと問題があったわけだ。


どういう問題かというと、次の送信時、最初に1バイトのゴミデータが付いてしまうのだ。

あれ? 送信停止時にFIFOクリアはしたはずなのにと思った。

このマイコンの通信ペリフェラルは送受信用のFIFOを備えており、数バイト分の送受信データを格納することができる。

送信停止した時点で、FIFOに格納された送信予定のデータはクリアしたのに、ゴミデータが1バイト残ってしまったと。

おかしいなぁ、とマイコンのペリフェラルマニュアルをよく見ていたところ理由がわかった。

FIFOとは別にある送信バッファに1バイトだけ送信予定データが残っていて、これだけ消せていなかったのだ。


どんなマイコンの通信ペリフェラルでも1バイト分の送受信バッファは備えているはず。

送信時、送信バッファからデータが転送されると、送信バッファエンプティフラグが立つ。

エンプティフラグで割り込みを発生させたりして、次の送信データを格納する。

前のデータの送信完了までに格納完了できれば、切れ目なく次のデータの送信に移れるわけである。

FIFOを使う場合は、FIFOから送信バッファへの転送を自動でやってくれるが、原理的には同じこと。

こういう仕組みなので送信中はほぼ常に1バイトのデータが格納されているわけだけど、

送信中に送信中断すると、1バイトのデータがバッファに残った状態になる。これが次に送信するときに吐き出されてしまうようだ。


いろいろ調べたところ、このマイコンの通信ペリフェラルでは送受信バッファを単独でクリアする手段はないようだ。

ただ、通信ペリフェラル全体をリセットする機能があるので、これを使えば送受信バッファを含めて全てが初期状態に戻る。

送信を中断するような事象が発生したときは、受信も停止するので、送受信の両方を初期化しても不都合はない。

というわけで、送受信停止を通信ペリフェラルのリセットに置き換えたところ、この問題は解決したのだった。


送信中に送信を中断するというのは、あまりやらないんじゃないかなぁ。普通は送りきるところまではやるだろう。

一方で、同製品のアセンブラ時代の設計を掘ってみると、送信の中断の実現方法が違うんだよね。

この当時は1バイトずつデータを送信バッファに格納してるんだけど、送信バッファへの格納をやめるという方法で送信を中断している。

すなわち、バッファにあるデータを吐き出しきったところで送信中断する仕組みになっていた。

意図してか、意図せずかはよくわからないが、同種の問題は回避出来るようになっていた。

今回も同様の解決法でいけるのでは? と思ったが、FIFOとの兼ね合いを考慮するとなかなか難しいので、全部リセットするという方法で解決した。


それにしても、なぜ送信バッファを単独でリセットする仕組みがないのだろうか?

いろいろ考えてみたのだが、おそらく上書きすることが可能だからだろうな。

すなわち、ゴミデータが送信バッファに入った状態でも、送信データの1バイト目を送信バッファに転送→送信開始とすれば、

ゴミデータを追い出した上で1バイト目のデータから送信できる。

これを 送信開始→1バイト目をバッファに転送 とすると、送信開始の時点で格納されているゴミデータが吐き出されてしまうのだが。

だから、一応は回避策はあると。やや複雑な操作が必要になるケースもあるかもしれないが。


似たような話が受信バッファでもあって、

  1. フレーミングエラーが発生して割り込み発生
  2. エラーはクリアして、受信も停止する
  3. 通信状態を初期状態に戻して、受信を再開する
  4. 受信を再開した途端に、受信割り込みが発生して、受信バッファからゴミデータを取得する

これ、2.の時点で受信バッファを空にし忘れたのが原因なんだよね。ゴミデータが残ったまま受信を再開しちゃったと。

他のシステムの同種の処理を確認してみると、後で受信バッファのダミーリードを追加した痕跡があった。

わりとハマりがちなミスなんだなと思いつつ、同じ方法で解決したが。


Author : hidemaro
Date : 2018/10/10(Wed) 22:13
電気・数学・物理 | Comment | trackback (0)
blog comments powered by Disqus

トラックバック

トラックバックURL取得

Tools