• ベストアンサー

組込みC開発

お世話になります。 組込みでARMコアのCPUをチョイスしての仕事を任されました。 開発ツールはKeilというIDEで、C言語でOS使用しないで開発をしています。 C言語はかれこれ2年以上使用しており、文法上の事などはほぼマスター しており、上記のIDEでソースをコンパイルしてコンパイルエラーもなく 60kbytesほどのコードが生成されます。 ただ、このプログラムをターゲットCPUへダウンロードして使うと コードとは異なる動きをするときがあります。 これは、小規模なプログラムでは経験したことの無いことです。 たとえば、思った動きにならないときに、ソースを少しいじっただけで 今度は例外が発生して止まったりします。 割込みは内部タイマー、外部(ボタン等)、UARTなど計4種類を 設定していますが、どうもこのあたりが怪しいと考えています。 たとえばUARTでPCからデータを送って、ボタンを押す、などの アクションを起こすと、データアボートやプリフェッチアボート が発生したりしますので。 ちなみに、割込み処理は、IDEがサンプルソースでつけているものを includeして使っています。 また、CでのプログラムでMISRA-C参考書も購入してチェックして おります。 大規模なプログラミングは今回が初めてなのですが、こうもソース を少しさわっただけで、例外が発生したりする(コード上問題ない と考えています)ので、現状は記述の仕方を変えてみたりして 対応しています。 こうした規模の大きい組込み系でのプログラミングで、注意する点 や、常識的な部分があればお教えいただきたく思います。 よろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • zwi
  • ベストアンサー率56% (730/1282)
回答No.8

#3のzwiです。 >地道にトレースしてどこでどう無限ループに達するのか、Abortへジャンプしてしまうのかを見ていくことが、組込み系でのデバッグ、ということになるのでしょうか。 再現性が高いだけでも恵まれてますよ! めったに出ないバグなんか、泣きそうになります(>_<) 最悪アセンブラレベルでのトレースが必要になるかも知れませんが、とりあえずスタックの情報から流れが追えませんか? 暴走先にどうやって飛んできたのかのを調べるには、スタックに詰まれている情報を追ってみるのが一番です。 他のテクニックとしては、配列でリングバッファを作ってプログラムの要所要所の通過マークを格納していくって技もあります。流れがおかしくなったらリングバッファの通過マークの順番を見れば分かりますよね。 あとは、CPUのクロックを落として様子みてみるとか、ARMあたりだとPLLで簡単に変更できるので簡単に実験できると思います。 話を聞いている限りでは、次のような不具合が可能性としてあります。 (1)ノイズでRAMまたはレジスタの内容が破壊される。ハード? (2)CPUキャッシュが何らかの原因で破壊される。ハード? (3)コンパイラのバグで、とんでもない命令が実行される。コンパイラ? (4)スタックが破壊される。ハードまたはソフトが原因。 あたりですかね。 >KeilというツールはもともとKeilという会社のコンパイラが搭載されていたわけですが、この会社、英国ARM社の傘下に入り、ARMが提供するコンパイラと同等のコンパイラを搭載するようになりました。 >あるWebでみかけたので気になるのが、ARMコアのコンパイラのチョイスでGNU,IAR,Keilが評価対象とされて、OverallでIARが勝利。次点でGNU、最後がKeilだったと記憶しております。 いまさらながら、IARのほうにしとけば、思っています^^;;; どこのコンパイラもバグがあるのです。運が悪いと引っかかりますね。それも締め切り間際に(^^ゞ まだバグだと確定したわけでもないですよね。周辺操作のタイミングのミスかも知れませんよ。 >pin1にボタン入力の割込み信号が入ると仮定して、本体CPUは常に30μs周期のtimer1の割込みで主に計算処理が中心の無限ループをさせています。 >ボタンが押された=pin1がHighからLowに変化したところで、まずフラグをたてます(flag = 1) >次に30μsのtimer1による無限ループ中に >if(flag == 1) counter++; >として、pin1の割込み発生からループが何回、回ったかをカウント。 >このカウントの値がインクリメントされ、既定の回数をカウントしてもなお、pin1がLowであれば、内部的にONを確定します。そしてflag = 2とします。 >次にボタンを離す行為の監視ですが、ONの監視と同様の処理をしています。 なんか複雑ですね。それにチャタリングはスイッチによりますが10ms以上は続きますので、400から500カウントぐらいしないと確定できませんね。 私がやるとしたら、1ms毎ごとぐらいにしかチェックしません。例えば1ms毎20回チェックして同じ状態が20回続けばスイッチの変化を確定とします。それ以外のときは前のスイッチ状態が継続しているものとします。 volatileは、コンパイラの最適化を抑止してレジスタ処理のみとなること避けるための修飾子です。 プログラムの流れの外(割り込み等)で変数の値が変化する場合は、その変数にvolatileを付ける必要があります。 下記サイトを参考にしてください。 http://www.kumikomi.net/article/explanation/2003/10kumi/13.html >・RAM 領域を定数で初期化するコードが、オブジェクト上に存在する。 Cのスタートアップルーチンが組み込まれていれば、ルーチン次第ですがRAM上の変数の初期化をしてくれています。通常アセンブラで書かれていますが、リンクしていませんか?

scheimpflug
質問者

お礼

御礼遅れて申し訳ございません。 また、詳細なご意見を頂戴しまして、大変感謝いたしております。 結局は、スイッチの入力処理を疑い、かつトレースもしながらデバッグして いっております。zwi様の言われるスイッチ処理も試そうかと考えています。 いずれにしても、長々とお付き合いくださり、ありがとうございました。

その他の回答 (8)

回答No.9

No. 7 です。 > ・RAM 領域を定数で初期化するコードが、オブジェクト上に存在する。 オブジェクトではなくて、オブジェクトファイルでした。 組み込みの場合、最終的に ROM に焼き込むことになりますが、そのもとになるファイルは、フォーマットに差があっても、 xxxx番地のデータはyy という情報の集まりです。 この、xxxx番地が ROM 上にある場合は、問題ないのですが、開発環境やら、の関係で、RAM 上の番地を指定してしまうことがあります。 たとえば、 static int i = 50; のような指定があると、 (i の番地)は、50 のようなデータがオブジェクトファイル上にできます。 エミュレータがこれを読み込むと、ごく自然に RAM 領域に初期値を割り当ててしまいます。ところが、マイコンに焼き込む段階では、RAM 領域への焼き込みはできませんから(できたとしても、電源を切れば消えますから)初期化されなかったことになるというものです。 const なしの static や グローバル変数に初期化すると、こうなるケースがあります(開発環境・オプションにより)

scheimpflug
質問者

お礼

ご回答ありがとうございます。 非常に参考になりました。

回答No.7

組み込み特有というか、エミュレータが絡んでくると、RAMの取り扱いが問題になることがあります。 ツールによっては変数全般も。 ・初期化されていない変数がある  これは、組み込みにかかわらず問題になる項目です。  組み込みに場合、エミュレータ上で動かすと、エミュレータ自体が、きれいにRAMを初期化してしまうので、問題が表面化しない場合があります。 ・RAM 領域を定数で初期化するコードが、オブジェクト上に存在する。  これは、主に、コンパイル時に指定するメモリの割り当てに絡んできます。  変数を初期化するコードで、ツールによっては、それを、単純に、指定された番地に埋め込むことがあります。(特にトップレベルのグローバル変数や、スタティック変数)  ところがその変数がRAMだと、いわゆる、ROM への焼き込みができませんから、初期化しているつもりが初期化されていなかったりします。 こういうケースも時にはあります。

scheimpflug
質問者

お礼

具体的なご回答ありがとうございます。 最初のころは変数の初期化をしなかったせいもあり、うまく動いていなかった点がありましたが、いまではしっかりと初期化を心がけております。 >・RAM 領域を定数で初期化するコードが、オブジェクト上に存在する。 ご説明がいまひとつ、理解しかねるのですが、const で宣言した変数は以前も確認したことがありまして、ROMのアドレスに配置されていました。 グローバル変数については、再確認してみたいと思います。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.6

> 組込み系では、こうした対応策が一般的なのでしょうか? > Cの文法上は問題ないけれども、optimizeしてみたり、ソースの書き方を > 変更してみたりして、実機で(なんとか)動くようにするような対策です 確かにコンパイラの最適化バグに遭遇することはときどきありますが... 書かれている内容を読む限り、おそらくコンパイラの最適化バグではないような気がします。 単にvolatile修飾子を忘れているとか、きちんとタイミングを合わせなければならないのに、適当に書いてたまたま動いていただけとか、そんなところではないでしょうか。 たまたま動いていた場合には、ボードの個体差によって、動いたり動かなかったりします。量産した際に、ロットによって動かなかったりすると目も当てられません。

scheimpflug
質問者

補足

具体的なご回答、ありがとうございます。 volatile修飾子についてなのですが、揮発性の変数(電源オフで忘れる変数)については、必ずつけることが必要なのでしょうか? 現状では long i = 0; char a ='\0'; みたいに、volatileをつけていません。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.5

あと、組み込みは初めてですよね? スイッチの入力は、チャタリング対策されてますか? ハードかソフトでチャタリングの対策をしていないと、スイッチの値を読み間違うのは当たり前なんですが。 http://elm-chan.org/docs/tec/te01.html これは、データアボートやプリフェッチアボートとは別の問題です。

scheimpflug
質問者

お礼

具体的なご回答をありがとうございます。 チャタリングに関しましては当然対策しております。 ただ、自分としてはちょっと変わった方法ではないかと考えています。 pin1にボタン入力の割込み信号が入ると仮定して、本体CPUは常に30μs周期のtimer1の割込みで主に計算処理が中心の無限ループをさせています。 ボタンが押された=pin1がHighからLowに変化したところで、まずフラグをたてます(flag = 1) 次に30μsのtimer1による無限ループ中に if(flag == 1) counter++; として、pin1の割込み発生からループが何回、回ったかをカウント。 このカウントの値がインクリメントされ、既定の回数をカウントしてもなお、pin1がLowであれば、内部的にONを確定します。そしてflag = 2とします。 次にボタンを離す行為の監視ですが、ONの監視と同様の処理をしています。 ここで、多重割込みの問題が発生しますが、timer1の割込み処理中のみ、他の割り込みも発生すれば受け付けるようにしています。他の割込み処理中はすべて他の割込みを禁止しています。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.4

>下記にも記載しましたが、Optimization levelを操作することで今回は回避できそうな気配です^^; そんな方法で問題を回避しても無駄です。 趣味で作っているならともかく、仕事でそんなことをしたら酷い目にあいますよ! 量産したら動かない、現場ではちゃんと動かない、でも社内ではちゃんと動くってオチが待っていそうです。 もし、Optimization levelだけで回避できるとしたら、コンパイラのバグが原因です。どこのコードに問題があるか確認しておかないと本当に回避しているか保障できません。 私の勘では、ハードの異常動作な気がするんですけどね。オプティマイズレベルで周辺回路の操作タイミングが変わりますから。

scheimpflug
質問者

お礼

ご回答・ご叱責ありがとうございます。 確かに、最適化しない状態で動かないのに、最適化処理したとたんに意図した動きになるとは、ちょっと理にかなわないですよね。 KeilというツールはもともとKeilという会社のコンパイラが搭載されていたわけですが、この会社、英国ARM社の傘下に入り、ARMが提供するコンパイラと同等のコンパイラを搭載するようになりました。 あるWebでみかけたので気になるのが、ARMコアのコンパイラのチョイスでGNU,IAR,Keilが評価対象とされて、OverallでIARが勝利。次点でGNU、最後がKeilだったと記憶しております。 いまさらながら、IARのほうにしとけば、思っています^^;;;

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.3

「プリフェッチアボート」は普通ありえない例外です。 ノイズなどが原因でハードウェアが誤動作していないでしょうか? データアボートやプリフェッチアボートの頻発がソフトウェアが原因とは思えません。パスコンを追加したりしたら直りませんかね? >たとえばUARTでPCからデータを送って、ボタンを押す、などのアクションを起こすと とてもノイズが原因っぽいですよね。 後は、ARMチップが、どこのメーカー製かわかりませんが、エラッタの資料を見て問題となるようなことをしていないか確認をしてみてください。たちの悪いエラッタに引っかかっている可能性もあります。

scheimpflug
質問者

お礼

ご回答ありがとうございます。 エラータも確認しました。特にひっかかりそうな項目は無かったです。 回路的には、とっかかりにユニバーサルで組んだいたものでも、回路図からパターン引いて試作基盤を作成したものの上でも同じように症状が出ています。 地道にトレースしてどこでどう無限ループに達するのか、Abortへジャンプしてしまうのかを見ていくことが、組込み系でのデバッグ、ということになるのでしょうか。

  • R32C
  • ベストアンサー率39% (115/290)
回答No.2

実機で、暴走するなら、デバッガーのリアルタイムトレース で、動きを確認してみてはいかがでしょうか? この辺が組み込み独自の方法なのかもしれませんね。 Keilの開発環境については、よく知りませんが、リアルタイムトレース は使えるですよね。 ARMコそのものはオンチップでリアルタイム トレース機能のサポートがあるので、対応デバッガで使えるはずです。 今お使いのツールでもしサポートしていないなら、使えるツールを 用意してみたほうがいいと思います。

scheimpflug
質問者

お礼

ご回答ありがとうございます。 下記にも記載しましたが、Optimization levelを操作することで今回は 回避できそうな気配です^^; 実はトレースも購入して使用しているのですが、いまいち使い切れてない 状態です。 トレースで確認してみると、ボタンAが引き金となり、変な場所で 無限ループが発生したりしています。 変な場所とは、プログラムエリア外の部分です。そのかわりタイマの イベントだけはしっかり働いてたりしています^^; スタックポインタが上書きされるから関数がもどらない状態が発生 しているんだと思うのですが、タイマ割込み処理以外の割込み処理では 他の割り込み処理を禁止させています。 パソコン上でのプログラム経験が長いので、このあたりの動作が どうもしっくりきません^^;;;

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

> ただ、このプログラムをターゲットCPUへダウンロードして使うと > コードとは異なる動きをするときがあります。 期待した動作とどのように異なるのでしょうか? > たとえば、思った動きにならないときに、ソースを少しいじっただけで > 今度は例外が発生して止まったりします。 発生した例外の要因は何でしょうか?

scheimpflug
質問者

お礼

ご回答ありがとうございます。 基本的には内部タイマをトリガとして、 単純な処理を数十μSごとに処理させています。 異なる動きとは、たとえばボタンを押すと、定期的な上記の処理から 割込みを使い、メニューモードへ飛ばします。 ボタンは4つあり、割込み時にどのピンに接続されたかをレジスタで 知ることができるようになっています。うちAボタンでメニューへ飛ぶ ボタンとします。 異常なときは、Aボタンを押しても、割込み処理の中でボタンAが 押されたと判断されず、いつもの定期運転をしている状態です。 しかしながら、割り込みが入ったことだけは認識します。 実際に、割込み処理させているところにハードウェアブレークを セットすると、たしかに引っかかってきます。 ただし、レジスタの内容を見ると、どのピンがトリガになったか わからず、スルーしてしまいます。 この件で、自分なりにいろいろ試しているのですが、 コンパイルのOptimizationをいじると、正常動作するOptimizatioin levelがあったりすることも確認しました。 組込み系では、こうした対応策が一般的なのでしょうか? Cの文法上は問題ないけれども、optimizeしてみたり、ソースの書き方を 変更してみたりして、実機で(なんとか)動くようにするような対策です。

関連するQ&A

  • 組込開発はどんな流れになっているの?

    C言語などでの組み込みはどういった流れで開発されているか教えて下さい。 プログラムを作成した後、メモリに書き込むという漠然としたイメージを持っていますが、具体的に知っている方がいらっしゃれば教えて下さい。

  • C言語について

    最近C言語でプログラミングを試みようとしてるのですが、コンパイルの時点でよく分かりません。 どのようなソフトでどのようにインストール・設定し、どのようにコンパイルするかなど、C言語でのプログラムのコンパイルから実行までを詳しく教えてください。

  • C言語についてどうしてもわからない疑問

    プログラミング初心者です。 C言語を勉強中に疑問に思ったことが2つあります。 まず1つ目。 C言語以外のプログラミング言語、例えばjavaとかC#とかjsとかpythonとかrubyとかPHPとか、には開発者にとって便利なライブラリとかフレームワーク(僕にはこの2つの明確な違いがわかりません。が、どちらも「開発者が定義しなくてもよい関数やオブジェクトの集合」という認識があります)がありますよね。 そのおかげで色んな人達がプログラミングし易くなりました。 ネット(はてぶのホットエントリとか)でも「馬鹿な俺がプログラミングを勉強して〇〇を作った」といった記事をよく目にします。 でも「C言語を使って」というのは聞いたことがありません。 そもそも、C言語はそいういったライブラリやフレームワークが少ないように感じます。 検索してもrailsとかjqueryのようなフレームワーク(ライブラリ?)は見つかりません。 これが無かったらプログラムなんて作れないのでは? しかし、世間にはC言語で作られたプログラムが多いのもまた事実。 C言語ではいったいどのように開発が行われているのか教えてください。 2つ目 unixとかlinuxといったOSはC言語で書かれている聞いたことがあります。 しかし、プログラムの開発は「コードを書く→コンパイル(→デバッグ)→実行」という流れですよね。 ではOSを開発するときに、そのコードをどうやってコンパイルするのでしょうか? コンパイラはOSの上に立っているとするなら、OSがない状態でコンパイラはどこに立てばいいのか。 そこがわかりません。 誰かこの2つの疑問に答えてください。 お願いします。

  • 組み込みソフト開発について

    いつもお世話になっています。 プログラムの話題で組み込み系の事ってあまり出ていない ような気がします。書籍でもあまり取り上げていないような気がするのです。 しかし「c言語」「求人」で検索すると組み込みソフト 開発の多い事!...なにかギャップを感じます。 私は組み込み系の存在も最近になって知ったのですが 未だにプログラム開発の月刊誌に掲載されているのを 見たことがありません。求人募集で圧倒的に多い分野 をなぜ出版社は取り上げないのでしょうか?

  • 組込みでのC言語勉強法

    はじめまして。 最近、組込みのC言語を勉強しています。 処理速度の面や、可読性の良いプログラム、効率のよいプログラムを書けるようになりたいと思っています。 引数の数はレジスタで処理できる範囲におさめる事や、 構造体を使用するときにはポインタで渡すなど、 コードを書く際に気をつけるポイントがまとまってる書籍やHPなどを知りませんか? もしくは参考にすべき、サンプルコードなど知っていましたら、情報をいただけるとありがたいです。 よろしくお願いします。

  • プログラミングC言語 サイコロ問題

    プログラミングC言語の問題でC言語のrand関数を利用して33回のサイコロ型乱数を出力するプログラムを書きなさい。という問題が出ました。ソースコードを教えてください。

  • CとC++って何が違うのでしょうか?

    こんにちは。今までjavaでプログラミングしていたのですが、C言語を使わなくてはいけなくなりました。 そこで本屋さんに行って「初めてのCプログラミング」というのを買いました。それに付いてた「BorlandC++Compiler」というコンパイラをインストールして、プログラムを作成して実行しました。 昔、大学の授業ではコンパイルするとき「cc」、実行するときは「a.out」とした記憶があるのですが、これでは、「bcc」です。 もしかして、この本は、C言語ではなく、C++というCとは異なる高水準言語なのですか? C言語とC++とは全く異なるものなら、このまま、新しい本を買わないとどのような支障がでてくるでしょうか?

  • WindowsでのC と LinuxでのC の違いについて

    これから、Linux OSでC言語のプログラミングを行うことになりました。ディストリビューションはVine Linux 3.2 を利用します。 開発方法としては、Windows Xp 上でgccを利用できるIDE(Dev-C++ 4.9.9.2を利用します)で開発を行い(テスト的にコンパイル)、できたソースをLinux上でコンパイル・リンクするという方法で行おうと考えています。 そこで、疑問があります。 ANSIライブラリの中にはシステムコールを実行するものがあると思います。システムコールはOSの一部の機能ということですので、WindowsとLinuxとでは当然その機能は違ってくると思います。 つまり、WindowsでANSIライブラリを利用して実装したプログラム(コンパイルもとおる)がLinux上で正常に機能するのか(そもそもコンパイルがとおるか)がわかりません。 どなたかご教授いただけましたら幸いです。 宜しくお願いします。

  • C言語とC++言語

    C言語でコンパイルできC++でコンパイルできないプログラムとその逆でC++でコンパイルできC言語でコンパイルできないプログラムを教えてください。よろしく

  • C言語のオススメ統合開発環境(IDE)について

    C言語のオススメ統合開発環境(IDE)について教えてください。 先日より組み込み系の改修案件の開発をC言語で行うことになりました。 今まで、JAVA、C#でのオープン系開発を5年程度やっているのですが、 C言語、組み込み系は共に初めての体験になります。 既に動作しているシステムのため、相当量のソースがあり、 一緒に作業している方達はテキストエディタ(秀丸やサクラ等)を 使用して開発をしているのですが、 私自身がC言語になれていないこと、スケジュールがタイトな事もあり、 ソースを追うのにも時間がかかってしまっている状況なため 扱いやすい統合開発環境があればそちらを利用したいと考えております。 基本的にはコンパイルやデバッグを行いたいわけでなく、 「便利なエディタ」という概念での利用がしたいだけです。 フリーソフトでさえあれば問題ありません。 また、Eclipse、VisualStudioは今までの業務で使用経験があります。 「周りと合わせて秀丸使え!」という意見もあるかと思いますが、 限られた時間で作業効率をあげたいと思っておりますので、どうぞ宜しくお願いいたします。

専門家に質問してみよう