組込みプログラミング > リッチでない環境でのデバッグ方法

@msyksphinzさんお疲れ様です。

12月10日担当の7of9(セブンオブナイン)です。
組込みプログラミングの記事としました。

## 組込みプログラミングの経験

2009年頃から組込みプログラミングをしています。
(なお、僕が中学生以降で経験してきた言語については[こちら](http://qiita.com/911watanonn/items/c51d6babfcca930af888#comment-7aa8eedb3d4dd60a4487)を参照ください。)
仕事以外でも、休日や休み時間に組込みに関して取り組んできたものがあり、それらはQiitaの記事としてきました。

経験したMCUとしては主に以下です。

- MSP430
- ESP8266 + Arduino IDE
- Raspberry Pi
   - MCUというよりはCPU?

「リッチな環境」については以下の定義とします。

- リッチな環境
  - Raspberry Piのような「Ethernet通信あり、USBあり、LinuxというRTOS搭載」の環境
- リッチでない環境
  - 「Ethernet通信なし、USBなし、RTOSはなんとか」というような環境
  - MSP430はこちら

ESP8266は多少リッチな環境(WiFiあり)という感じです。

## 補足情報

組込みの入門については、以下の記事を書き、それに補足情報をいただいたことがあります。
[組込み > 入門には何がいいだろうか > デバッガを扱うことができるMCUとデバッガ > STM32の情報を教えていただいた](http://qiita.com/7of9/items/d878439a5c17cbebe3de)

組込み入門したい人は上記の情報や以下のリンクなど参考にしてみてください。
http://www.uquest.co.jp/embedded/index.html

## 対象とする実装基板

環境として、以下の機能を想定します。

- Ethernet/WiFiなし
- USBなし
- GPIOあり
- LEDが2つ
- I2Cあるかも
- SPIあるかも
- RTCあり
- microSDあるかも
- UART2つ
- バッテリ駆動 (3V)
- RTOSあり


## 難しさ

それぞれの基板は必要最低限のもののみ実装する傾向にあります。
本番環境で使用しないのにGPIOを余分に20個載せたり、消費電力が上昇するLEDを余分に数個(様々な色で）実装する、などはしません。
実装面積の制約もあります。

また、メモリの問題もあります。
Raspberry Piのように「リッチ環境」でメモリ制限を気にしなくてもいい環境がある一方、MSP430のようなメモリ制約がある環境もあります。例として、データ保持に使えるのは2KBなどの場合もあります。
特にバッテリー駆動で消費電力を平均数mA以下に抑えたい場合は、メモリ制約も厳しいMCUを使うことがあるようにも思います。

これら制約の下、必要な機能を持つソフトを開発する時の問題というのが、「どのようにデバッグするか」です。
デバッグの仕方により、デバッグ時間が10分にも、数時間にもなります。

以下、自分が経験してきたデバッグ方法の紹介です。

### printfデバッグは基本的にない

組込みの場合、「標準出力」はないため、printfデバッグは基本的にできないことになります。

### シリアル出力デバッグ

printfデバッグの代わりとしてシリアル(UART)に出力するということをしたりします。

問題はUARTを実使用していて、デバッグ用の文字列をその通信に含めることになる場合です。デバッグ用に"[DEBUG]"などの先頭文字列を含めるなどして、区別が必要になります。

通信が混み合ってなく、相手側がWindowsソフトの場合は、そのデバッグ出力と本来の出力を区別して別処理できるかもしれません。
通信が混み合っていたり相手側との通信プロトコルが決まっているため余分な通信を追加できない場合、シリアル出力デバッグは利用できません。

### LED表示デバッグ

使わないLEDがあれば、それを点滅させることによるデバッグが可能です。

使わないLEDがない場合がほとんどだったりします。その場合は、デバッグ時だけ表示を変えるような追加作業が必要になります。

### GPIO出力デバッグ

GPIOのポートがあまっていれば以下のデバッグができそうです。

1. LEDを接続して点滅させる
2. オシロスコープを接続して確認する

GPIOに拡張ボードを接続して、そこに搭載したLEDを点滅させることでデバッグできます。

また、オシロスコープで波形を見ることでデバッグできます。
オシロスコープで波形を見る場合、1つのGPIOピンをイベントトリガ用に用いて、もう1つのピン(あるいは複数)を見たい波形として使えます。
イベントトリガを用いることにより、捉えたいタイミングでの出力をキャプチャすることができます。

### 使用していない通信を使う

- SPIを搭載しているが、使っていない
- I2Cを搭載しているが、使っていない

など、未使用の通信を使うという手はあります。

問題はそれらを使うための追加コードが必要となることです。それにより、メモリ資源を余分に使用したり、クロック生成、データ出力用のタイミングなどの検討（他タスクの生成含める）が必要となります。
それらの追加コードが本来の動作に影響を与えないようにしないといけません。

### ストレージを使う

microSDなどストレージ機能を本番環境で使っている場合、そのストレージ機能をデバッグに使える可能性もあります。

しかしながら、RTOSではタスクの処理などで工夫することになります。printfデバッグやLEDデバッグよりは面倒です。一方で、より詳しい情報を出力できる点は良いです。

### JTAGを使う

JTAGという機能がある場合、IDE(開発環境)と組み合わせてデバッグすることで、上記のデバッグより格段に良いデバッグができます。

以下のことができるようになります。

- ブレークポイントで停止した部分での変数の状況を見ることができる
- 停止した部分での値を変更して続きの動作を確認できる
   - 開発環境に値変更機能がある場合
- RTOSの対応次第で、RTOSタスクの状況やメモリ使用状況を見ることができる

色々な箇所のデバッグに対して、プログラム自身の書換えをしなくてすむ、という利点があります。

### エミュレータを作る (複数基板のデバッグ)

複数の基板同士が通信する状況で、それぞれの基板のプログラムをデバッグする場合を考えます。

片方をエミュレータとして動作させると、特定条件での動作のデバッグがやりやすくなります。

エミュレータを作る時間(更新する時間)が必要ですが、必要最低限のエミュレータ機能だけでもデバッグ効率が上がります。

エミュレータの開発環境としては、C++ Builder, Processing, Unity, Visual Studioなどが選択肢として挙げられます。

実際に5時間で作ったエミュレータの１つは、100時間程度の動作検証の役に立っています(一方で、**実機検証は必ず必要となること**は強調しておきます)。

### ツールを使う

UART, I2C, SPIなどの通信に関しては、通信モニタツールを買って使うというのも手です。

この場合は、本来の通信の詳細を知ることができ、Productionコードの動作そのままでトラブル原因の調査ができます。

個人的にAnalog Discovery2 は非常にいいと思っています。[macsbugさんに使い勝手を教えていただきました](http://qiita.com/7of9/items/ed39d9dbefc1c14a5718)。
他にも通信をモニタする装置があるかもしれません。予算は数万円からかかります。


### ツールを作る

http://qiita.com/tags/myLineMonitor
にてシリアルラインモニタを作りました。UARTの通信のモニタをして、その内容をUnityで作ったソフトでスマホで閲覧できます。あるいはUSBメモリに取り出すこともできます。

アイデアと実装技術と実装時間次第でこういうツールを作ることもできそうです。
実装技術習得にそれなりに時間がかかるので、入門よりは中級向けかもしれません。

そのようなツールを作る過程で学ぶことで組込みプログラミングの技能もあがるかもしれません。
また、ツールを作ることで、自分が調べたいことに対してツールをカスタマイズできるようになります。

### デバッグ時の留意点

以下のような留意点を考えて作業します。

- その基板だけで発生する症状か?
  - 同じ実装の別基板では発生しないか?
    - 基板の問題とソフトの問題の切り分け
- 自分が使用できるツールで解決の近道となるものは何か?
- シンプルな構成にする
  - 問題を再現する一番シンプルな構成は何か?
- 関係ないものは片付ける
  - ちらかった状態でデバッグしては混乱の元です
  - すし屋のカウンター方式 ([link](http://qiita.com/7of9/private/89c1395fe124db1f316c))
- 過去に似たようなことはなかったか?
  - あれば、整理している情報(Qiitaなど)を引き出す

## 関連情報

この記事と関連しそうなリンクを以下に示します。

- [テスト駆動開発による組み込みプログラミング by James Grenning](http://qiita.com/7of9/items/8eab7461901c93214b91)
   - 組込みの人に参考になる
   - 組込みでない人にも参考になる
   - 「デュアルターゲット」は気になるデバッグ方法です  
- [開発のしやすさを重視した仕様を作成しよう](http://qiita.com/nonbiri15/items/439a9a3d7638aee2f38d)
  - 基板設計時の検討事項としても良い資料です
- [Lチカとprintfとデバッグと](http://elm-chan.org/junk/ledebug/report.html)
  - > UART出力でLEDを駆動し、そのパルス光を光センサで拾うのです
  - 面白いアイデアです。一方で光センサの取りこぼしの対策は力量が必要でしょう。
- [進化した組込みLinuxのデバッグ]
(https://www.computex.co.jp/explanation/linux/)
   - 「リッチな環境」でのデバッグ方法
   - 組込みLinuxはまだ本格的に始めてしないため、始める時に情報を整理します
- [古いスマホにエアコンの番をさせる](http://qiita.com/irori/items/fec147fd4a7443e3f4c3)
   - > 赤外線LEDをPCのサウンドカードにつないで録音しつつ、リモコンの信号をLEDに当ててやると信号を取り込めます。
   - 赤外線LED取込の興味深いアイデアです。基板での取込と、サウンドカード取込の比較などでデバッグが進むかもしれません。
   - [ナイキスト周波数](https://ja.wikipedia.org/wiki/%E3%83%8A%E3%82%A4%E3%82%AD%E3%82%B9%E3%83%88%E5%91%A8%E6%B3%A2%E6%95%B0)も考慮されているようです

### まとめ

長々と読みにくい記事になってしまいましたが、まとめとしては**「一番良い方法を考えて」デバッグしましょう**、です。

次は @marsee101さんよろしくお願いいたします。