組み込みソフト技術者の新人研修
組み込みソフトの新人研修で実施する内容について、何をどのように教えていくのがよいのかを考えて記事にしました。 なお、C言語の理解が前提条件となりますので、理解が足りていない場合はC言語の書籍やC言語の副読本等で逐次補っていくとよいでしょう。
学習内容
目標としてはシングルタスクで小規模なプログラムを作れるようになること。 もちろん組み込みソフトウェアなので、時間待ちやタイムアウト、実時間制約や割り込みの理解も含めています。
一つはLEDを使った交通信号機の実現、 もう一つは組み込みシステムのデバッグ用途でよく使用される簡易シェルを作るのはいかがでしょうか? ここでいう簡易シェルとは、ホストPCとターゲットとなる組み込みシステムをシリアルケーブル(RS232やUSB)で接続して、 TeraTerm等のターミナルソフトと通信可能な簡易シェルのことです。
課題で作成するコードは後の開発で再利用するつもりで作成してもらいます。 作成当初はいろいろと考慮が足りなかったりすると思うので、 継続的なメンテナンス(バグ修正や改善)を行いつつ、課題に取り組んでもらうと良いのではないでしょうか。
対象となるハードウェア
実務に近い自社製品のハードウェアを用意できればよいのですが、 難しければArduinoやmbed等の小規模なハードウェアを採用しましょう。 但し、TimerやUART等の周辺回路のデータシートを読み解いてドライバを作成することも目的の一つなので、 当然ですがArduinoやmbedで提供されているドライバや便利なライブラリ等は使用禁止です。
- 周辺回路(ほとんどの組み込みCPUにはTimer、UART、GPIOがあるので問題はないでしょう)
- Timer
- UART:RS232(レベル変換) または USB(仮想シリアル)
- GPIO(PIO):LED(2個以上)
ハードウェア制御関連の課題
- LEDドライバの作成
- LEDチカチカ(点灯、消灯時間の実現方法を各自で考える)
- Timerドライバの作成(割り込み無し版)
- 関数インターフェイス(setup、start、stop、readCounter、getFrequency)
- UARTドライバの作成
-- 余裕があれば以下も
- Timerドライバの作成(割り込み有り版)
- 割り込み時に呼ばれるコールバック関数の登録
- Timer割り込み時に登録されたコールバック関数呼び出し
- チック(Tick)コンポーネントの作成
- チックのサービスを提供するための関数インターフェイスを考える
- Timerの割り込みを利用してチックを作成する
組み込みソフトウェアの学習(ハードウェア制御関連の課題中に教える等)
- CPUのリセット解除からmain関数まで
- IOとメモリ
- Cache memory(キャッシュメモリ)
- キャッシュの有効性
- データキャッシュと命令キャッシュ
- データキャッシュがメモリに書き出されるタイミング
- データとしてアクセスした後に命令として扱う
- C言語のコード最適化の影響と抑制
- 時間経過待ちの方法
- volatile変数のカウントループ
- Timerのカウントループ
- アセンブリのカウントループ
- フリーランカウンタで時間サービスを実現する仕組み
- 身近にある時計で考える
- N時間経過したことを判断するには?
- 時間経過の判断限界は何時間?
- 時間経過待ち、タイムアウト判定、時間計測
- 身近にある時計で考える
- 時間サービスを提供するコンポーネントの実装
- 割り込み
- コンテキストとは何か?
- 処理の中断と再開の仕組み
- 排他制御の必要性(アトミック性とは?)
- 割り込み処理時間と割り込み最小間隔
- 実時間動作(周辺回路、制御対象回路、他のCPUとの通信)
- デバッグ方法
設計の基礎学習
- モジュラープログラミング(抽象化/凝集度)
- レイヤーアーキテクチャ
- サブシステム
交通信号機の開発
先に作成したLEDドライバ及び、フリーランカウンタまたは組み込みソフト版chronoを利用して交通信号機を実現します。 具体的には複数のLEDを青、黄、赤の信号に見立てて作成します。
- LEDが3bitあるなら自動車用信号機
- [青:5秒点灯]→[黄:1秒点灯]→[赤:5秒点灯]→戻る
- LEDが2bitなら歩行者用信号機
- [青:5秒点灯]→[青:1秒点滅(100~200msec間隔)]→[赤:5秒点灯]→戻る
簡易シェルの開発
先に作成したUARTドライバ等を利用して簡易シェルを作成します。 C言語のポインタや文字/文字列操作(標準ライブラリ)を正しく理解していないと作成できないので、 C言語の復習にはちょうど良い課題になると思います。
仕様
簡易シェル
- 動作仕様
- エコーバック有り
- コマンド入力待ち時はプロンプトを表示する
- 処理すべきコマンドが無い(CRまで受信してない状態)時はメインループに戻る
- CR受信まで文字数制限を設けること(エラー表示、もしくは制限を超えた受信文字を破棄等)
- コマンド仕様
- readコマンド(IO読み出し)
- パラメータ引数
- アドレス
- アクセス幅(8/16/32bit)
- パラメータ引数
- writeコマンド(IO書き込み)
- パラメータ引数
- アドレス
- データ
- アクセス幅(8/16/32bit)
- パラメータ引数
- dumpコマンド(メモリダンプ)
- パラメータ引数
- アドレス
- バイト(またはワード)数
- アクセス幅(8/16/32bit)
- パラメータ引数
- fillコマンド(メモリフィル)
- パラメータ引数
- アドレス
- データ
- バイト(またはワード)数
- アクセス幅(8/16/32bit)
- パラメータ引数
- helpコマンド(全コマンドの一覧表示)
- readコマンド(IO読み出し)
- 余裕があれば
- 動作仕様
ターミナルアプリケーション(TeraTerm等)
- 端末の設定
- 改行コードは送受信共にCR
- ローカルエコーなし
- 端末の設定
段階的な作業
実現方法は様々なので例として挙げておきます。
固定長文字列型(FixedString)の作成:コマンドライン操作を簡単にする
- 関数インターフェイス
- create、destroy
- ctor、dtor
- copy、insert、replace、erase、terminate、clear、at
- lengthFromPos、length、empty、full
- maxSize
- cStr
- 関数インターフェイス
ConsoleとShellへ機能分割
- 続く…
まとめ
基礎とはいえ短期間に沢山の項目を理解することは難しいので、 研修後の実際の開発業務を通じて少しずつ理解していくとよいでしょう。 それまではある程度曖昧な理解のままで進んでいくことになりますが、 様々な項目の詳細を理解するには多くの時間を必要とするので焦る必要はありません。 興味を持った時や、より深い理解が必要なタイミングが詳細な知識を得るきっかけになると思います。
組み込みソフト技術以前にC言語の文法を理解していない場合はコンパイルも通りませんし、 技術的知識が伴わない間は質問内容がうまく伝わらずにつまずく人も多いと思います。
- 実際にコードを記述する前に
- 何が目的なのか、どのような方法を用いて実現するのか、よく考えて設計しましょう(設計ができていればコード化はすぐにできます)
- Cコンパイラのエラーメッセージがわからない
- プログラムが思った通りに動かない(プログラムは書いた通りに動きます)
- デバッガの使い方を知らなければ調べましょう
- デバッガでトレースして変数の値や分岐結果を確認してみましょう(ステップ実行で確認)
- リアルタイム系のプログラムならprintf相当で変数の値や分岐結果を表示して確認しましょう(確認したい箇所にprintfを埋め込む)
- 技術的な質問をする前に説明文を書いてみよう
- 一度読めばわかるレベルの誤字脱字がないか
- 相手に伝わる説明になっているか
- 状況を説明する際に相手が知りえない情報を正確に伝えているか
- 何が目的でどのような手段で実現しようと考えたのか
- どのような問題が起きて何が原因だと思うのか(思い込みがないか)
- どこまで正常動作して(しているように見えて)、どこから異常動作なのか
- どうやって訓練するか
- 他者(同僚やチームメンバー等)への説明で訓練する(情報を整理することにつながる)
- 図解でわかる! 理工系のためのよい文章の書き方
- 課題について
- 基礎が身についていれば本課題はそれほど難しくはありません
- 難しいと感じる箇所が弱点なので、そこを集中的に学習して克服しましょう
- 課題をこなすことで知識を得ることができますので自分の頭で考えて解答を導きましょう
- どうしてもわからなければ他の人に質問して解答を得ても良いですが・・・
- 教えを乞うわけですから礼節を欠くことの無いようにしましょう(相手が目の前にいるのと同様に)
- 解答だけを教えてもらうのではなく、何が問題だったのか、どのように解答を導けばよいのか、同様の問題が発生した時に自分で解決できるようになったのかを考えましょう