さて今回も新人の頃のお話です。通信チップ更新にともなう通信ドライバの変更で見落とした「タスク処理の優先度」についての経験です。
代替のLSIはDMAC非搭載タイプ
通信LSIにはDMAC(ダイレクト・メモリ・アクセス・コントローラ)を搭載したICがあります。ファームウェアを担当の方ならご存知の通り、DMACを搭載したLSIを使用すると、データ転送時にマイコンの処理負荷を軽減することができます。
【例1】データを送信したい場合
登場物:DMAC搭載LSI、RAM、マイコン
(1) マイコンは送信したいデータをRAM上に作成
(2) マイコンはDMAC搭載LSIに送信開始アドレスと送信レングスを設定
(3) マイコンはDMAC搭載LSIに送信開始コマンドを発行
(4) DMAC搭載LSIはRAM上のデータを積極的に読み込んで送信
→この時、マイコン側はデータ送信のことは意識せず、別の処理を行うことができる。
(5) DMAC搭載LSIはデータ送信完了を割り込みでマイコンに通知
【例2】データを受信したい場合
登場物:DMAC搭載LSI、RAM、マイコン
(1) マイコンはDMAC搭載LSIに受信データを格納するRAMの開始アドレスと最大レングスを設定
(2) マイコンはDMAC搭載LSIに受信開始コマンドを発行
(3) DMAC搭載LSIはデータを受信すると、積極的にRAM上にデータを展開する。
→この時、マイコン側はデータ受信のことは意識せず、別の処理を行うことができる。
(4) DMAC搭載LSIはデータ受信完了を割り込みでマイコンに通知
ある製品に採用されていたこのタイプのLSIが生産中止になり、DMAC非搭載LSIに代替が決まりました。DMAC非搭載LSIはFIFO(先入れ先出し)方式を取っており、マイコン側が積極的にデータをFIFOに書き込み or 読み込みしなければなりません。
なので、【例1】の(4)と【例2】の(3)においてマイコンの負荷が増える、つまり、送受信タスクのCPU占有率が前より高くなるということです。
さて、この製品、通信でファームアップデートができるのですが、「事件」はこのファームアップデートの検証中に起きました。
真犯人は別のタスク
現象としては、ファームアップデートが半分まで進むと、ファームアップデートのタイムアウトで止まってしまうというものでした。
今回のLSI検討当時から、DMA方式からFIFO方式にするにあたり、データ送受信速度が落ちることを予想していましたが、アップデートができなくなるというのは致命的な問題です。なので、とにかくデータ転送処理(アルゴリズム)を改善すれば、タイムアウトは解決するだろうと考えました。しかし、いくら改善しても全く進展は無く、あっという間に2、3ヶ月の遅れとなっていました。その当時は本当に精神的にまいりました。
やみくもに処理速度のボトルネックを勘で狙い撃ちしても埓(らち)があかないので、未使用のIOポートをHigh/Lowさせて処理速度を計測し、地道にポイントを絞っていった結果、ついに原因を特定することができました。
真犯人は、ディスコン対応で修正したドライバタスクではなく、ファームアップデートを行うタスクにありました。アップデートタスクは、ドライバタスクが受信したファームウェアのデータを順次、外部のFROMに書き込んでいます。実はこのアップデートタスク、優先度がドライバタスクより高い!
このため、アップデートタスクが動作しているときは、ドライバタスクが動作できず、LSIのFIFOからデータを読み込めないために通信の再送が頻発。通信速度の低下とファームアップデートタイムアウトを引き起こしていました。
そこでアップデートタスクには、一定バイト数書き込んだらsleepするという処理を入れ込むことで、無事に動くようになりました。
真犯人は、裏に隠れていることがあります。この経験から「この機能を実行しているとき、裏で何のタスクが動いているのか?そしてその優先度は?」をしっかりと把握しなければならないことを学びました。また、ファームウェアはタスク実行権がはっきりしていますので、デッドロック等が起きやすいです。
優先順位を意識しないことがどんなに恐ろしいことか・・・。
真犯人はいつも「まさか」です。皆さんもお気をつけください。


