質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

アーキテクチャ

アーキテクチャとは、情報システム(ハードウェア、OS、アプリケーション、ネットワーク等)の設計方法、設計思想、設計思想に基づいて構築されたシステム構造をアーキテクチャと呼びます

Q&A

解決済

6回答

1696閲覧

組込みソフトのアーキテクチャ設計の習得方法(OSSを読んで勉強?)

drao0113

総合スコア11

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

アーキテクチャ

アーキテクチャとは、情報システム(ハードウェア、OS、アプリケーション、ネットワーク等)の設計方法、設計思想、設計思想に基づいて構築されたシステム構造をアーキテクチャと呼びます

1グッド

6クリップ

投稿2018/04/27 14:04

ソフトの変更工数を削減するために、
組込みソフトのアーキテクチャを一新し、フレームワーク構造にしようとしているのですが、
参考になるような書籍はありませんでしょうか?

OSレスでソースコードの行数は40万行くらい。
変数はすべてグローバル変数で、モジュール分割・隠蔽化の概念がまったくないソースコードです。
複数のモータや電動弁を制御するのが主なタスクです。

組込みで、アーキテクチャ設計がきちんとなされた、
綺麗なソースコードを読んで勉強してみたいのですが、なかなかそのようなソースコードを発見できずにいます。
おすすめのOSS等ありましたら、教えていただけませんか?

最近悩んでいるのが異常処理で、
いかに各モジュールの異常をとりもらすことなく、
素早くアクチュエータを停止にもっていくかが課題です。

他にも下記のような課題があります。

・通常制御と異常制御をどのように切り替えれば、時間制約を満たしたうえでソフトの構造が綺麗になるのか
・ROM,RAMの使用量,CPUの実行時間を抑えて、かつ設計変更時のミスを減らせるようなデータ構造の考え方
・モジュール間の依存関係をできるだけ少なくするための設計方法
・モジュール間のデータの受け渡し方法(モジュール間の依存関係を減らしつつ、データの伝達のタイムロスがない方法)

書籍でも、ここらへんのことに触れている本は少ないので、
OSSを読んで勉強するのがいいのでは?と考えています。

同じような悩みを持っているかたの意見もお聞かせください。

よろしくお願いします。

testset👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答6

0

こんにちは。

40万行もの大規模プログラムが対象なら、Linuxのカーネルは比較的条件を満たすかも知れません。

・通常制御と異常制御をどのように切り替えれば、時間制約を満たしたうえでソフトの構造が綺麗になるのか

しかし、すいません。イキナリこれは該当しないかも。カーネルの「制御対象」はユーザ・プロセスやデバイス・ドライバであって、drao0113さんが知りたいのは、ユーザ・プロセスやデバイス・ドライバが制御する装置の異常発生時の制御でしょうから。

個人的な経験では、正常系を分かりやすくすると異常系の制御は難しくなります。
私は、基本的にはスレッドで制御し、異常発生時はC言語を使ってたころはlong jumpを使って一足飛びに戻ってました。C++なら例外ですね。C++の例外は遅いという問題があります。サブmSecの応答性が必要な場合は厳しいかも。ファンクショナル・フォンで昔良く使われていた Symbian OSでは独自の例外機構を導入して高速化を図ってました。

他によく使われる手法としては、状態マシンです。正常系が鬼のようにメンテンナンスし辛くなりますが、異常系も一緒くたに処理できるので、ある意味「スマート」かも知れません。

・ROM,RAMの使用量,CPUの実行時間を抑えて、かつ設計変更時のミスを減らせるようなデータ構造の考え方
・モジュール間の依存関係をできるだけ少なくするための設計方法
・モジュール間のデータの受け渡し方法(モジュール間の依存関係を減らしつつ、データの伝達のタイムロスがない方法)

これらはどんぴしゃ該当しなそうな気がします。カーネルの軽さは最重要課題の一つです。またLinuxのモジュール構造は結構凄いですよ。


それだけ大規模なプログラムなら、モンタビスタのような組込み用Linuxを採用し、そのサポートをばりっと利用するのも手かも知れません。

投稿2018/04/27 14:29

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pepperleaf

2018/04/27 23:57

> Linuxのモジュール構造は結構凄い かも知れませんが、元々は、組込み向けで無く、リアルタイム性は自分で担保する必要があります。(リアルタイムLinuxもありますが、そちらは詳しい人に) > 複数のモータや電動弁を制御するのが主なタスク ここをどう考えるか? IOポートで直接、制御しているのなら、要注意。専用ハードに指示を与えるだけなら、PCでも(今の仕事がそれ)。 昔、客先指示で、Unixでリアルタイム制御を要求されて対応した事もありますが、、(1msまでの要求は無かったと思う)
Chironian

2018/04/28 01:26

pepperleafさん ちょっと判りにくい書き方をしてしまいましたが、後3つの学習のためにLinuxカーネルのソースを読むのは有用と思います。しかし、組み込み向けにLinuxをそのまま使った方が良いかどうかはおっしゃる通り微妙です。 ただし、モンタビスタ等の組込み用Linuxなら当然組み込み向けに使えると思います。リルタイム性能も謳っているようです。
drao0113

2018/04/28 15:14 編集

Chironianさん こんばんは。 > 40万行もの大規模プログラムが対象なら、Linuxのカーネルは比較的条件を満たすかも知れません。 ROM容量が数MBなのと、数msオーダーのリアルタイム性が要求されるので、 Linuxカーネルはなかなか厳しそうですね。導入するならRTOSになりそうです。 > しかし、すいません。イキナリこれは該当しないかも。カーネルの「制御対象」はユーザ・プロセスやデバイス・ドライバであって、drao0113さんが知りたいのは、ユーザ・プロセスやデバイス・ドライバが制御する装置の異常発生時の制御でしょうから。 その通りです。各種センサーや通信異常をいかに早く検出して、 異常処理を行うモジュールに伝達し、アクチュエータの最終出力を決定して、 各アクチュエータのドライバモジュールに伝達するか、が課題ですね。 モジュール分割とデータのやり取り方法、ソフトのアーキテクチャを考え中ですが、 なかなかいい案がでず、、、です。 >個人的な経験では、正常系を分かりやすくすると異常系の制御は難しくなります。 わたしも同じように感じます。 私が感じたのは、正常系の処理と異常系の処理がごちゃ混ぜに実装されて、 どれが正常系か分からなくなるのが辛いですね。 >私は、基本的にはスレッドで制御し、異常発生時はC言語を使ってたころはlong jumpを使って一足飛びに戻ってました。C++なら例外ですね。C++の例外は遅いという問題があります。サブmSecの応答性が必要な場合は厳しいかも。ファンクショナル・フォンで昔良く使われていた Symbian OSでは独自の例外機構を導入して高速化を図ってました。 long jumpという方法もあるのですね。知らなかったです。 開発言語はCなので、long jump調べてみます。 >他によく使われる手法としては、状態マシンです。正常系が鬼のようにメンテンナンスし辛くなりますが、異常系も一緒くたに処理できるので、ある意味「スマート」かも知れません。 状態マシンはうまい考え方だと思います。 異常時のアクチュエータの動作のパターンを抽出して、異常時の状態を抽出するのもいいかもしれないですね。 >これらはどんぴしゃ該当しなそうな気がします。カーネルの軽さは最重要課題の一つです。またLinuxのモジュール構造は結構凄いですよ。 ROM容量がせいぜい数MBなので、OSの占有するROM容量は最重要課題ですね。 LinuxではなくRTOSを選択することになると思います。 Linuxのソースコードは読んだことがないので、読んで勉強してみます。 Unix V6のコードを解説した本は興味深かったですね。 >それだけ大規模なプログラムなら、モンタビスタのような組込み用Linuxを採用し、そのサポートをばりっと利用するのも手かも知れません。 モンタビスタは知らなかったです。 ただ、ルネサス系のマイコンを結構つかってるので、採用は難しいかもです。
drao0113

2018/04/28 15:21

pepperleafさん > Linuxのモジュール構造は結構凄いかも知れませんが、元々は、組込み向けで無く、リアルタイム性は自分で担保する必要があります。(リアルタイムLinuxもありますが、そちらは詳しい人に) その点は認識してました、数msオーダのリアルタイム性が要求されるのと、 ROM容量の制約でRTOSを採用することになりそうです。ただ、Linuxはあれだけの規模のソースコードをCで書いているので、アーキテクチャ設計やモジュール分割の方法など、参考になる点は多々あると思ってます。 > IOポートで直接、制御しているのなら、要注意。専用ハードに指示を与えるだけなら、PCでも(今の仕事がそれ)。 IOポート直接制御しているので、かなり注意しないといけないと思ってます。 前職の車載系でモータ制御やってたんですが、OS導入するとCPU負荷がとんでもないことになりましたw リアルタイム性がシビアな処理は、専用のマイコンを設けられればいいのですが、コスト的になかなか厳しいです。 > 昔、客先指示で、Unixでリアルタイム制御を要求されて対応した事もありますが、、(1msまでの要求は無かったと思う) Unixでリアルタイム制御すごいですね。 Unixとなると、さすがに自分で全ソースコードを把握できないので、 設計や不具合解析が難しそうなイメージです。
Chironian

2018/04/28 15:54 編集

数MBytesのROMがあるならLinuxも余裕(https://goo.gl/BY19Yq)ではありますが、やはりLinuxはLinux用のソフトウェア資産を使いたい時向けと思います。そうではない場合は適切な規模のRTOSを使うのがやはり正解でしょう。ルネサスに聞けばお使いのCPUに既に移植されているRTOSを教えてくれるのではないでしょうか。OSのパートナーが多数あるようですし。https://goo.gl/97gVUQ (因みにlinuxもいくつか含まれてました。) > 各種センサーや通信異常をいかに早く検出して、異常処理を行うモジュールに伝達し、アクチュエータの最終出力を決定して、各アクチュエータのドライバモジュールに伝達するか、が課題ですね。 センサー異常や通信異常を高速に検出するにはタイムアウトを短くすることですから、応答性能を上げることが重要です。応答が早ければタイムアウトを短くできますから。 そのためには、ポーリングではなく同期オブジェクトが有効です。これならCPUの応答性能を最大限に引き出せます。他のモジュールへ伝達する際にも同期オブジェクトを用いると高速です。 ただし、課題があります。慎重に設計しないと直ぐにデッドロックします。 条件変数を使えばデッドロック回避しやすいかも知れません。待ち処理にプログラムを介入させることができますので。https://yohhoy.hatenablog.jp/entry/2014/09/23/193617
guest

0

ベストアンサー

drao0113 さん、

IPA 情報処理推進機構のページ https://www.ipa.go.jp/ で、検索してみると、いろいろ面白い資料がでてくると思います。

たとえば、"組込み アーキテクチャ" で検索すると、
組込みソフトウェアのアーキテクチャ設計の可視化という資料がでてきますが、5ページ目。こころに、グっ.. と、きますね。(笑

組込みソフトといっても、

  • どのようなハードウェアを使用しているか(ちっちゃなマイコン~RTOSのボード(MMUなし)~Linuxが動くボード(MMUあり)~Windowsが動作するボード)、
  • どのくらいのリアルタイム応答が要求されるか(50kHz~1kHz~1秒~)、
  • 人材・スケジュール・予算(!!!)... カスタマーからのプレッシャー

など、様々なプラットフォーム・環境・境遇があるので、書籍やオープンソースから、ジブンのところにあったものを見つける、となると結構時間がかかってしまんじゃないかな、と。
業務でやるのであれば、ソフトウェア開発関係ののコンサルタント会社を探して、相談してみる、というのが、費用も掛かりますが、実績・経験からの話がきけるので、実際、いいんじゃないかと思います。


ところで、↓のような話をきくと、どんなものか見てみたくなりますねぇ。

OSレスでソースコードの行数は40万行くらい。
変数はすべてグローバル変数で、モジュール分割・隠蔽化の概念がまったくないソースコードです。
複数のモータや電動弁を制御するのが主なタスクです。

とのことなので、大きなメインループで処理のディスパッチとか、タイマーや外部の割り込みで、イベント(のような?)処理、というような作りで、また、モータ使用なので、動作中の電源周りのこまかい処理(コンシューマー危機にあるような電力セーブ・スリープなど)は、あまり気にしなくてよい、という感じでしょうかね。

制御するものしては、

  • モータ制御 (PWM, GPIO出力)
  • 電動弁(アクチュエータ制御?) (PWM, GPIO出力)
  • センサー (ADC, GPIO入力)

で、システム全体をみるものが、シーケンスデータやらセンサーの状況を見て、上のものを制御していく、というものだとして(もっといろいろあると思います..)、話しをすすめてしまいますが、
現在、特にレイヤーわけもなく、コードが書かれてるのであれば、

o LowLevelのドライバl類
a-1. PWM
a-2, GPIO-IN/OUT
a-3, ADC

o ドライバの上のモジュール類
b-1 モーターを駆動させるモジュール
b-2 アクチュエータ制御モジュール
b-3 センサーモジュール

o システム制御のアプリケーション

というような形でレイヤー分けをして、まずは、コード整理ですかね。

で、システム全体を見て、タスク分けを検討して、RTOS導入。

また、システム制御部分は、Matlabなどを使って、モデルベース、というかたちで、コードは書かない(書けない?)そのスジの専門家が設計。
Cのコード生成して、それを統合する、って感じだと、制御まわりのアルゴリズムも分離できて、メンテナンスもよくなるんじゃないかな、、と。

こういったメンテナンス性を上げることって、すごく大事なんですけど、まわりの知らない人(特に身分の高い方)からみると、機能・動作もかわらないのに、時間もお金も人もかけて・・・って思われることもありますからね。

しかも、移行直後は、バグが多発して、デグレってる!!、、って。
その辺をわかってる立場のツヨイ人も味方につけとく必要もありますね(笑

投稿2018/04/28 06:37

mt08

総合スコア1825

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ちと質問と外れますが、

40万行ですべてグローバル変数、ということですが、おそらく、動作させるコードのコピペを繰り返してこういう規模になっていると推察されます

こういうコードは、それぞれの動作単位で関数化、モジュール化して、共通化していくと、機械的に変換していったとしてもコード規模的には数分の一以下になると思われます

既存のコードをどうにかしていこう、という場合には、いきなりリアルタイムOSの導入とかは考えず、まずは関数化、モジュール化していき、全体の見通しを良くしておいて、必要であるならそれから考えていく、というのがいいと思われます

一口にリアルタイムOSとはいいますが、上記のようなプログラム構造に慣れたアタマからすればそれこそ考え方がまるっきり変わってしまうんで、それに対応できるかどうかってのも心配なところではあります

投稿2018/04/28 23:06

y_waiwai

総合スコア87749

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

回答になってなくて申し訳ないですが、
組込みでそんな便利な参考書は見たことが無いです。(組込みでなくてもですが、、)
まずは、地道にモジュール分割からかと思います。あるいは、軽い組込み用OSの導入から。
なお、OSの導入、モジュール分割などの方法は大抵の場合、パフォーマンスの低下となる場合が多いのも事実。巷にあふれる成功談も大半は半分以上、誇張と考えるべき。 (モジュール化でバグった事も過去にあり)
その一方で、メンテナンスコストが下がるのも事実。これらのバランスを取る事が重要。パフォーマンスの低下は、CPUなどを高性能なものにする事で容易に補う事ができます。その辺を考慮した提案かと。
あと、OSSですが、玉石混合。昔、Unixのソースを見た事がありますが、お手本と言うには程遠かった。綺麗だから、効率が良いという事は無く、見た目、綺麗だけど、動かないコードにも出会ってます。(もっとも、汚いとメンテナンスが大変ですが)

投稿2018/04/27 14:17

編集2018/04/27 14:22
pepperleaf

総合スコア6383

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

drao0113

2018/04/27 14:27

漠然とした質問に回答いただき、ありがとうございます。 やはり、そんな便利な参考書はないですよね。 最近は組み込み関連の洋書も読んでいるのですが、なかなか知りたいアーキテクチャ設計に関する記述がないです。抽象的な内容でなく、もっと具体的な実装が知りたいとなると、OSSを参考にするのがいいのでは?と思ったのですが。 OS導入も考えているのですが、マイコンの資源の制約で、 導入はなかなか難しそうです。 Unixのソースコードも、もしかしたら参考になるかもしれませんね。 読んでみます。 回答ありがとうございました。
pepperleaf

2018/04/27 23:48

> OS導入も考えているのですが、マイコンの資源の制約 やはり、ここでしょうか。 OSの導入、モジュール化など大抵は、コード/メモリを要求します。 書かれた状況を考えると、手を入れる余地があるように思えます。組込みじゃないですが、4000行のコードから、バグを直しつつ、重複/繰返し等を見直し、1000行近くまで。組込みではボトルネックをどう見直しても1割程度しか高速化できなかった箇所が、上位を見直したら、そもそもその部分が不要になった事も。大抵は地味で上司ウケが悪いのですが、、。
drao0113

2018/04/28 14:50

OSは導入する方向で考えているのですが、どうしてもROMが足らなくてマイコン変更を余儀なくされる機種が出てくるので、悩みますね。 OSを導入する、しないに関わらず、アーキテクチャの見直しは意味があると思ってます。 ただ、グローバル変数をなくせばいいかというと、グローバル変数で結合していた機能が、 こんどは関数を介して結合するようになるだけなので、 モジュール間の依存関係を少なくできるようなモジュール分割と、 データ構造が大事なんだと思ってます。具体的にどうすればいいかは、まだ模索中です。 4000行を1000行にってすごいですよね。 たた、ワンライナーとかを駆使して、とかではなく、根本的な対策を施してってことですよね。 こういう、アーキテクチャ設計って実はかなりの技術レベルを要求されるのに、 あまり効果が目に見えないあたり、上司に評価されずらいのが辛いですよね。。。 コメントありがとうございました。
pepperleaf

2018/04/28 14:59

> 4000行を1000行にってすごいですよね。 単に元のコードが悪いだけ。 ちょっと動きが違うとコピペで手直しのてんこ盛りでした。 肥大化しているコードって結構、こんなのがあります。まあ、小手先と言えば、小手先ですが、、。ただ、この辺をコントロールしようとすると、マネージメントの問題。現場の担当者では不可です。
drao0113

2018/04/28 15:23 編集

pepperleafさん コピペの嵐はやめてほしいですよね。 設計変更時の変更漏れにつながるので。。 ただ、そんなコードでも動いている実績があるので、 リファクタリングさせてもらえないですね。特に組み込みだと、単体試験・結合試験・システム試験と、 莫大な工数が必要ですから。 バイナリが変わらない範囲なら、まだ許してもらえますけど、根本的な解決にならないことが多いです。
guest

0

組込みソフトのアーキテクチャを一新し、フレームワーク構造にしようとしているのですが、

参考になるような書籍はありませんでしょうか?

私は見たこと、読んだことはありません。

OSレスでソースコードの行数は40万行くらい。

変数はすべてグローバル変数で、モジュール分割・隠蔽化の概念がまったくないソースコードです。

μTRONも考慮にいれてみてください。

ただ、既存ソースコード量が多いようですので
かなりのリファクタリングとメモリマップ再構築避けられないかと。。

OOA、OODでの切り口で全体像を客観的に見直すのもありだと思います。
※ソースコード修正はすぐに着手せず。じっくり検討、思考し取り組む事をお勧めします。

投稿2018/04/27 19:56

YomogiKOBO

総合スコア187

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pepperleaf

2018/04/27 23:37

> μTRONも考慮にいれて 深く勉強した事が無いですが、、 以前、使いにくいと言っていた組込みOSが*TRONベースだったのを知って驚いた事があります。実装次第なんでしょうが、注意が必要だなと。 某社では、全体を新環境(OS)上で動作させるようにして移行を進めていました。(当然、当面のコード/メモリは肥大化する)
YomogiKOBO

2018/04/28 03:52

>以前、使いにくいと言っていた組込みOSが*TRONベースだったのを知って驚いた事があります。実装次第なんでしょうが、注意が必要だなと。 そうですね。 注意が必要です。 μTRONで気を付けないといけないのは ・メッセージ ・タスク ・タイマー でしょうか。 何かしらイベント(例えば接点ON/OFF通知)をさせるにしてもタスク経由で通知させるとします。 その場合、通知させるメッセージ(イベント)を保持させるメモリ量は計算しておかないとメモリを壊してしまい誤作動の原因となってしまいます。 (タスクにわりあてたスタックサイズやメッセージ保持用メモリサイズの調整だけですめばよいですが・・・)
guest

0

参考になるコードですが...
qemu関連は面白いですが規模がでかすぎるし、Qtも規模が...
linuxのネットワークスタック関連(TCP/UDP)が洗練されすぎてて訳が分かりませんが、すごいです。
NASAのソースコード(https://github.com/nasa)はどうかな?と思ったのですが、肝心の制御関連はUS Onlyだったり、VxWorksや上位アプリケーションばかりでした。
小規模なら、arduino-librariesなら気軽に読めると思いますが、異常系が弱そうでした。

以下、ポエムです。
リアルタイム性を担保しつつ、モジュール間の依存関係を整理するというのはOSレスとなるとかなり苦労します。
想像ですが、割り込みでの処理がほとんどなのではないでしょうか。
※RTOSを導入してタスク分けできたとしてもディスパッチ待ちを考慮した設計が待ってます

どの設計においてもデバイスとデバイスへ制御するという役割を明確にするというのが変更にも強く、バグも起こりにくい認識です。
誰が親なのかを考えて設計します。
子と子が依存するのはNGで、親を経由しなくてはならないという制約を持ちます。
※こうなると親(マネージャ)が肥大化して役割分割まで発生したのでCファイルのincludeでの分断という衝撃は忘れられませんが、これがうまくいっててすごかった。

なので、linux等のopen/close/read/writeでドライバへ指示を出すというのは非常に良い設計なのかなと思っています。
他の方が述べられているように、デバイスにかかわるところはドライバ、制御は上位レイヤにする形で分けていくことから始める、特に変更のあったところから始めるのが良いかと思います。
※制御を出すところでレジスタを直接叩くとか、もうお察しのパターンになること請け合いです。(本当に、本当にやりたくなる)
※SDKを使っていて、その上でやるのは苦労がすごかった(特に割り込み設計)

投稿2018/04/28 17:48

testset

総合スコア221

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問