試作してから塩漬けになっているMicro Sound Moduleですが、年末年始のちょっとした時間で取り組もうかと考えています。そもそも、塩漬けにしすぎて何をどこまでやったのか忘れてしまった。
元々、アートインスタレーションで使えるような小さなモジュールにしたかったので、仕様から様々なこだわりを切り捨てて作りました。LPC824を選択したのも、「このくらいのマイコンを選べばアレコレやろうとしても欲張れないだろう」という斜め上(下?)の動機があったりします。
ということで、ちょっと成果物を眺めてから色々と取り組んでみようと思います。
2016年12月30日金曜日
2016年11月30日水曜日
リアルタイムOS教材について思う事(をちょっとだけ書いてみる)
■あらまし
学生の頃からリアルタイム・システムに興味があって様々な書籍を読んでいた自分ですが、エンジニア・ライフを約一周ほど楽しんで、そろそろ思うことあってリアルタイムOS教材についても触れなければならないなと考え始めました。というのも、世の中に溢れる教材の中には、初学者に与えるべきでない間違った例が数あまたあり、それらが実開発の現場で様々な問題を生んでいるからです。今日はその中からひとつだけ取り上げてショート・ブレイクとして書いてみます。
■良くない例:タスク・スリープで排他処理
世の中には不思議な例を取り上げてリアルタイムOSの機能を紹介する例を見かけます。その代表例がタスク・スリープで排他処理やシステムの状態を管理する例です。
この例を取り上げる教材の多くは、リアルタイムOSの機能を紹介したいようでもあるのですが、よくよく読んでみると、結局のところどれも「こういうときはこうするのだ」と実際のアプリケーションについて触れています。しかし、このような設計で実システムを実現されてはひとたまりもありません。
リアルタイムOSの使い方として間違ったアイデア、「タスク・スリープで排他処理やシステムの状態を管理」が何を言っているのか図示してみます。
タスクAとタスクBは、それぞれグローバル変数であるint valueを操作します。もうグローバル変数が出てくる時点で完全に失格なのですが、問題はそこではありません。この典型的な間違ったアイデアは、よく以下のような方法で紹介されています。
①システム起動直後、タスクAは動作し、タスクBは寝ています。
②タスクAはint valueを操作し、タスクBを起こして自分は寝ます。
③起床したタスクBはint valueを操作後、タスクAを起こして自分は寝ます。
例えば、この設計には以下の疑問がつきまといます。
A. タスクAとタスクBが非同期で双方動作している瞬間について考慮されていない。
B. タスクAがタスクBを知っている。タスクBがタスクAを知っている。つまり循環参照関係にある。
C. やっている内容から考えると、そもそも単一タスクで良い。(説明に必然性が全く無い)
D. その他。
上の例、int valueと書いてあるものは物理デバイスであることもあります。となると、なおさら問題は複雑になります。というのも、物理デバイスは動作に時間がかかります。状態遷移中の物理デバイスの状態を適切に扱う場合、上記の例では対処できません。
■例えばどうすれば良いのか?
リアルタイムOSを使うのは、抽象化レベルを上げつつ、キビキビとした動作を実現できるからです。上記の例で言うと、int value(物理デバイスかもしれない)は、操作対象ですが、これはあるタスク内部で操作される操作対象と見ることができます。つまり、タスクAやタスクBから操作される新たなタスクCのようなものが内部で操作する対象とすることができます。
そして、タスクAやタスクBからメッセージ通信でタスクCに操作を依頼する形式を取ります。
「ちょっと待って!さっきの例で出来ていたタスクAとタスクBの同期ができないじゃない!」と言われるかもしれませんが、タスクCは単一スレッド上でメッセージ受信処理を行っているので操作は競合しません。
加えて、タスクCのAPIを工夫しておけば、操作自体も抽象化された表現で扱うことが可能になります。
- アームを上に上げろ!
- アームを下に下げろ!
- 緊急停止!
上記のような操作を抽象的に表現したAPIにするだけで、グンとシステムで操作する内容がわかりやすくなってきます。そして、実装の詳細はタスクCに隠ぺいされるというメリットも生まれます。タスクAとタスクBが循環参照状態になる事もありません。
■ということで・・・
リアルタイムOSの教材でタスクのスリープを使って状態をコントロールするような例を見かけたら、「この教材は怪しいな」と疑って内容をレビューしてみて下さい。
2016年10月31日月曜日
ちょうど100円玉サイズ!NXP LPC824を使ったとっても小さなWAV File Player「Micro Sound Module」を作りました!
■KiCadへの移行
2016年2月にCADをEAGLEからKiCadに移行する練習を兼ねて、何か実際に作ってみようと考えていました。でも、あまり大きな設計はしたくない。そこで小ピンでも何か面白いことが出来そうなマイコンを使うことを考え、LPC824を使ったとっても小さなWAV Player「Micro Sound Module」を作ることにしました。こちらが完成品。じゃん!EAGLEからKiCadに移行する人の中には、独特なユーザーインターフェースに戸惑いを感じる事もあるようですが、OrCADなどの業務でも使われているCADに馴染みのある人にとっては、逆に自然に移行できるのかも。私の場合、KiCadへの移行に合わせて、回路図、基板、3Dモデルを3画面で同時に見れるようにPC環境を更新しました。これはとても便利。
パッド名やネット名の確認が簡単に出来たり、リアルタイムでルールチェックを行なってくれるところも素敵です。EAGLEの場合には後からデザインルールチェックをかけるわけですが、これを忘れてしまうととんでもない状態で基板を作ってしまう事になります。そういう事は起こらないのが良いなぁと思いました。
私が使ったKiCadのバージョンでは、フットプリント側で配線禁止エリアや配置禁止エリアを指定できず、これはちょっと困ったことになりましたが、この苦しい制限があってもEAGLEには戻れない気持ちになっています。そのうちこの苦しい状況も改善されるでしょうと期待。
■Micro Sound Moduleの企画
マイコンがそもそも小さいのでコンパクトに面白いことができそう、と企画したのがMicro Sound Moduleです。本体のデザインは以下のようなもの。
Micro Sound Moduleプロジェクトの副産物。
某企業さんに行ったプレゼンテーション資料の中で何故か好評だったシリアル通信の説明文・・・。
■ファームウェア
ファームウェアには色々な仕掛けが施されていて、面白いことが出来るので何処かでお見せできるように準備したいなぁと考えています。コマンドの例を挙げると・・・- ディスクコマンド(マウント、アンマウント、情報取得)
- ファイルコマンド(ディレクトリ指定、リスト取得、オープン、クローズ、情報取得)
- トランスポートコマンド(再生、停止、ジャンプ、情報取得)
- マーカーコマンド(設定、解除、ジャンプ、情報取得)
こんな感じでひととおりの制御が可能なコマンドを装備しています。
コマンドパーサーにはNT-Shell (Natural Tiny Shell)を使用する予定でしたが、ROM容量の都合であえなく断念し、新しくコンパクトなパーサーを書きました。そろそろこれも公開したい。
2016年9月30日金曜日
Artistic Style (astyle) でコードを整形する
■インデントって重要
最近、色々な人のコードを眺めるにつけ、インデントまできちんと目を配って実装している人とそうでない人との間に、とてつもなく大きな壁がある事に気付きました。前者、インデントまできちんと目を配って実装している人の多くは、不要な実装、余計な実装は一切無く、終始一貫した表現で実装されています。対して、後者のインデントに気を使わない人の多くは、未使用変数や未使用関数、全く意味のないコメントやデバッグ文の散乱、ハードタブとソフトタブの同居・・・その他たくさんの危険な香りのする実装が残されています。ここ数年で見ていく中でインデントと成果物の内容に相関性があるのでは?という疑問に至り、インデントをきちんと行う姿勢に変えるだけでもその人のアウトプットが改善されるようにすら思えてきました。(今は単にそう思っているだけ)■最近はArtistic Styleなの?
私の場合、ソースコードは常にvimで編集しています。autoindentは常にonですし、整形する際も組み込まれた整形機能をパパッと充てて済ませていました。ふとしたことから「最近では皆さんどうしているのかな?」と疑問に至り調べてみたところ、Artistic Style (astyle)というツールが割と最近では使われているようです。メジャーなLinuxディストリビューションではパッケージ管理システムから簡単にインストールできますし、Windows版はsourceforge.netのプロジェクトページから入手可能なようです。■"One True Brace Style"が使える!
Artistic Styleでは、様々なコーディングスタイルを実現できるように豊富なオプションが用意されています。自分たちのコーディングスタイルに合わせてオプションを加えて実行できるのは嬉しい点です。"One True Brace Style"は、条件分岐などで一行で完結する命令の場合でも波括弧を付けて実装するスタイルのひとつで、私が好んで使用しているスタイルのひとつです。Artistic Styleでは、「--style=otbs」という引数を与えるだけで、One True Brace Styleになっていないコードでも自動的に波括弧を加えて整形してくれます。他にも様々な代表的なコーディングスタイルに対応しているので、きっと自分の気に入ったスタイリングオプションを見つける事ができるでしょう。2016年8月28日日曜日
CQ出版Interface2016年10月号の第七章にMicroPythonに関する記事を書きました
CQ出版Interface2016年10月号の第七章にMicroPythonに関する記事を書きました。
今回の記事は「とにかくソースコードと格闘してMicroPythonの世界を体験しようよ!」という内容になっています。成長中のオープンソースでこのような記事を書くと本当に生ものになってしまい、数か月後には「記事の内容と全然違う!」なんて事も多々あるので迷いましたが、「こーんな風に見ていけば良いんだよ」という雰囲気が少しでも伝わればという考えでしたためました。
記事の中で使用したボードはNUCLEO-F401REです。
秋月電子通商さんやスイッチサイエンスさんから購入できます。
ダウンロードコーナーのファイル(2016年 10月号 データ解析時代の新定番 Python)には執筆段階で使用したコードと環境構築用スクリプト(Ubuntu 16.04用)も含まれますので御利用下さい。
今回の記事は「とにかくソースコードと格闘してMicroPythonの世界を体験しようよ!」という内容になっています。成長中のオープンソースでこのような記事を書くと本当に生ものになってしまい、数か月後には「記事の内容と全然違う!」なんて事も多々あるので迷いましたが、「こーんな風に見ていけば良いんだよ」という雰囲気が少しでも伝わればという考えでしたためました。
ちなみに、記事のタイトルは「MicroPythonプログラミング」となっていますが、MicroPythonの中身を知るための入り口として、既存のモジュールに機能を追加する体験記事になっています。「なーんだ、ポーティングじゃないんだ」とか「プログラミングじゃないじゃん」と思われるかもしれませんが、騙されたつもりで一度体験してみて下さい。このちょっとした機能追加を体験する事が、意外にも内部構造の理解や機能拡張、更には別のプラットフォームへの展開の大きなヒントになります。
記事の中で使用したボードはNUCLEO-F401REです。
秋月電子通商さんやスイッチサイエンスさんから購入できます。
ダウンロードコーナーのファイル(2016年 10月号 データ解析時代の新定番 Python)には執筆段階で使用したコードと環境構築用スクリプト(Ubuntu 16.04用)も含まれますので御利用下さい。
2016年7月31日日曜日
技術開発と製品開発とビジネス開発は全く別物だけど混同されていることが多いという話
あらまし
お仕事で様々な立場の方とお話しする機会があるわけですが、以前からどの階層にいる人にも共通した「技術開発と製品開発とビジネス開発が同時に出来るのではないかという思い込み」を持っている方が非常に多い事に気付きました。よくある混同で起きるマズい事
例えば、おぼろげながら自分達で考えている製品像が浮かんだとしましょう。この製品像は、それこそ具体的になっているものではありませんが、必要な機能や性能やインターフェースが何となく整理できた状態になっていたとします。そこで必要になる機能を実現するための技術的な要素は、少し頑張れば実現できそうな事ばかりで、さっそく製品開発をスタートする事にしてしまいます。このシチュエーションで起きるのは以下です。
- 製品の機能を仕様にまとめる
- 仕様が好ましいものと判断され/判断し、計画をスタートさせる
- 仕様を満たす機能を実現できるように設計を開始する
- 設計が完了したので実装を始める(ハードウェア、ファームウェア、ソフトウェアは問わない)
- 実装が完了したので製造する(ハードウェア、ファームウェア、ソフトウェアは問わない)
- 製造が完了したので評価する
- (以降、付随したプロセスに続く・・・)
何もマズい事が起きていないようにも見えます。が、実際に技術開発と製品開発とビジネス開発を混同している人達に起きる悲劇の一例を挙げます。
- 出来ると思っていた技術的な要素に意外な課題があった
- 技術的な要素に絡む問題のために実現すべき仕様の一部が実現出来なくなった
- 仕様の一部が無くなったが、市場に出したい時期を明らかにしているので出す事にした
- 実現できなかったのはエンジニアリング能力の低さだと誰もが落胆し真因にたどり着かない
混同によって、どれもこれもが全て中途半端になってしまうのが最大の欠点です。こういった結末に至るプロジェクトは無数にあり、共通に存在するのが技術開発、製品開発、ビジネス開発を混同してしまっている事にあります。
技術開発
当たり前の話ですが、製品を実現するために必要な技術要素について、事前に課題や実現性を吟味しておく必要があります。そうでなければ製品の実現性すら不明のままで製品開発をスタートさせる事になってしまいます。このような組織にいたっては、製品開発を行う時点でビジネスまで混同して考えてしまっているので、全部が不透明感で一杯になる事になります。
技術開発は、製品開発とは性格の異なるもので、将来何に役立つのかわからないが、魅力的な物事について事前に研究開発しておくものです。大抵の場合、これらは現場の技術者の個人的な興味に由来していたり、過去に失敗した製品の残骸からゾンビのように生き返って組織に残っているようなものだったりします。
そして、非常に重要な点ですが、これらは一般に組織的に必要性を認められることは少なく、たいていの場合アンダーグラウンドで活動する事すら認められないようなものだったりします。(そんな事をやっている暇があるのなら、別の事をやれというやつです。)
もちろん、ニーズを的確に察知して必要になりそうな技術要素について研究開発する事も多いのですが、実際にそれらはビジネスへの発展を事前に考慮しているので、思わぬ発展に至るケースは少ないように思います。
いずれにせよ、重要な点はその時点で何の役に立つのかわからない、けれども興味のある物事を実現できるようにしておくというのが技術開発です。
製品開発
製品開発は、商品やサービスを実際に市場に出すために行う活動で、通常はビジネス開発との関係も持ちながら行われます。売れないものを作っても何もならないので、売れる前提でモノを作る事になります。つまり、実現性が非常に重要な点で、この時に初めて技術開発の成果物が価値を持ってきます。
製品開発の段階では、明らかになった技術要素を用いる事ができるようになっていると失敗のリスクを低減できます。
最近は様々な物事が安易に進む傾向があるようで、お金を積めば実現できると思っている方も多いのですが、実際に製品開発をするならば事前に積み重ねられた技術開発が伴っていなければなりません。そうでなければ博打にもなりかねません。動くと思うけどどうかなー。なんて嫌ですよね。
ビジネス開発
ビジネス開発では製品やサービスだけでなく、市場の動向や人々の趣味嗜好、その他さまざまな要素を踏まえて見えるものや見えないものまで作っていきます。
重要な点ですが、技術開発はそれ自身が当初品質が低く、実現形態も最終品ではないので曖昧で、結果的にビジネス開発側では具体的な製品のイメージを持ちにくい性質のものです。ビジネス開発側に自分が位置している場合には、目の前で実現できているモノが、技術開発の成果物なのか、製品開発の成果物なのか、十分に理解した上でモノを見なければなりません。その点を見誤ると、将来の大事な要素を自ら見捨ててしまう結果になってしまいます。
まとめじゃないまとめ
沢山の失敗するプロジェクトと少しの成功するプロジェクトを眺めていると、ある一定の共通項が見えてきました。その結論の一つが上記の、技術開発と製品開発とビジネス開発を混同しない事。です。
技術開発と製品開発を混同している組織は、製品開発で必ず失敗しています。そして、その失敗の原因を現場の担当に押し付けてしまいます。しかし、実際に組織で起きているのは、単に十把一絡げに物事を混同してしまう思想の雑さ加減にあるのです。もちろん、製品開発とビジネス開発も同様で、開発担当現場に一緒にビジネスまで開発させようとする組織すら存在しますが、エンジニアはスーパーマンではないので、小さなビジネスでまとめるなら別ですが、通常はうまくいかないでしょう。
モノを作るのが大好きな日本人ですが、世界中で見ると創造性や生産性は高くないのが現状です。そして、うまくいかなくても分析すらままなりません。結局は「社員の能力」などと言い放つ方すらいるのですが、それでは問題が解決しないようなぁと考える今日この頃なのです。
2016年6月29日水曜日
ドキュメント生成にSphinxを用いる
色々と思う事があって、最近はドキュメントをきちんと書こうという気持ちになっているのですが、最初に書き始めるまでに膨大な時間がかかってしまいます。ソースコードを書き始めるのは心理的な抵抗が無いのにも関わらず、ドキュメントを書き始めるのに時間がかかってしまうのは何故なんでしょうか?
そんな事を考えていてウェブを調べてみると、ちょっと良さそうなドキュメント生成ツールを見つけました。なんだか有名なツールのようですが、私が知ったのはつい最近。
何やら独自のマークアップ言語で記述すればhtmlやlatexやepubやなんだかんだに変換が出来るという・・・一見するとよく見る類のものに見えます。そして、いつものように試してガッカリするんだろうなと期待せずにチュートリアル的な内容をこなしてビックリ。なかなか綺麗な出力が得られることがわかりました。
例えば、sphinx-quickstartで作ったプロジェクトのファイルに日本語を入力してUTF-8で保存し、make latexpdfjaした時の出力が以下。
もちろんSphinx自体のサイトもSphinxで作られていて、これがなかなか綺麗な仕上がりです。
http://www.sphinx-doc.org/en/stable/contents.html
ソースコードの類を書く人にとって、WordのようなWYSIWYGはやはり辛いんでしょうか。よく考えてみるとソースコードの整形だってエディタやツールにやらせています。よほどの事情(とにかく気分転換したいので単純作業とかしたい・・・とか?)が無い限り、手で一文字一文字整形する人は稀でしょう。このノリで考えると、文章を整形しながら書くというのは、ソースコードを書く人の感覚と少し異なるのかもしれません。「整形は後で」って思っていても、そもそもソースコードを書く人は綺麗好きな人が多いので、やっぱり整形作業も始めちゃうというジレンマがあるのかも。
という事で、ひとまず道具を開拓してみただけなのですが、実際に説明不足のプロジェクトが山のようにあるので、何かのプロジェクトで使ってみたいと(今は)考えています。
そんな事を考えていてウェブを調べてみると、ちょっと良さそうなドキュメント生成ツールを見つけました。なんだか有名なツールのようですが、私が知ったのはつい最近。
何やら独自のマークアップ言語で記述すればhtmlやlatexやepubやなんだかんだに変換が出来るという・・・一見するとよく見る類のものに見えます。そして、いつものように試してガッカリするんだろうなと期待せずにチュートリアル的な内容をこなしてビックリ。なかなか綺麗な出力が得られることがわかりました。
例えば、sphinx-quickstartで作ったプロジェクトのファイルに日本語を入力してUTF-8で保存し、make latexpdfjaした時の出力が以下。
もちろんSphinx自体のサイトもSphinxで作られていて、これがなかなか綺麗な仕上がりです。
http://www.sphinx-doc.org/en/stable/contents.html
ソースコードの類を書く人にとって、WordのようなWYSIWYGはやはり辛いんでしょうか。よく考えてみるとソースコードの整形だってエディタやツールにやらせています。よほどの事情(とにかく気分転換したいので単純作業とかしたい・・・とか?)が無い限り、手で一文字一文字整形する人は稀でしょう。このノリで考えると、文章を整形しながら書くというのは、ソースコードを書く人の感覚と少し異なるのかもしれません。「整形は後で」って思っていても、そもそもソースコードを書く人は綺麗好きな人が多いので、やっぱり整形作業も始めちゃうというジレンマがあるのかも。
という事で、ひとまず道具を開拓してみただけなのですが、実際に説明不足のプロジェクトが山のようにあるので、何かのプロジェクトで使ってみたいと(今は)考えています。
2016年5月31日火曜日
NT-Monitorの外部オブジェクト参照にバグがあるんじゃないかという話
NT-Monitorとは、CQ出版社が出版しているInterface2013年1月号に掲載されたマイコン用のモニタプログラムです。シェルの部分はNT-Shellを用い、その上にモニタプログラムとしてNT-Monitorが乗る形を想定しました。記事掲載時点ではFM3マイコンに対するモニタプログラムとして構成し、その時点ではコールバックに渡される外部オブジェクト参照を使用しない実装になっていました。
2013年から約三年後の2016年現在、そういえば久しぶりに懐かしいコードを引っ張り出してみようと見てみたところ、限りなく怪しい香りのする実装が幾つも見られます。そのひとつがタイプセーフではない外部オブジェクト参照の実装。ちょっと載せてみたいシステムがあったので使ってみたところ、インターフェースに渡したはずのオブジェクトへのポインタが、異なるアドレスを指す何かに代わってコールバックされます。「あー、何だこりゃ」というのが事の始まり。
NT-Monitorは、元々単一スレッド上で永久に動作し続けるものであるとの前提で設計しました。唯一のAPIは上記に示すntm_executeで、シェルオブジェクトとシリアルI/O関数へのポインタを渡すと後は勝手にシェルを駆動しながら処理してくれるというものです。
システム内部に複数のシリアルインターフェースが存在し、かつそれらを別々のモニタープログラムが使用する事も念頭に入れ、UARTなどのインターフェースに対するハンドラへのポインタなどを格納できるようにしたのがextobjです。
が、ここにどうしようもない情けないバグがあるんじゃないかとコードを眺めていて気付きました。
まず、NT-Monitorの最上位階層であるntmモジュールを見たユーザは、当然のように自分がextobjへ渡したオブジェクトへのポインタが、そのままserial_readやserial_writeへ渡されることを期待します。そうでなければ、それが一体なんであるのか上記のAPIから知る由もありません。
しかし、実際にNT-Monitorの実装を見るとのっけから次のようなコードが見えます。何やら突然現れたntmcmd_extobj_tにserial_readとserial_writeを格納し、更にはユーザが上位のAPIで与えたextobjをuser_extobjとして保存しています。そして、この準備の終わった新しい外部参照用オブジェクトへのポインタをシェルモジュールであるntmshellに渡しています。
このままセオリー通りに事が進むと、ntmshellから呼び出されるserial_readとserial_writeは、最上位でユーザーが渡したextobjとは異なるものになってしまいそうな気もします。確認してみると・・・
ntmshell_executeで呼び出されるp->func_writeは、最上位で言うところのserial_writeです。そして、そのシリアル出力関数に渡される外部参照オブジェクトへのポインタはp->extobjを示しており、これは先ほどの確認にあったようにNT-Monitorの内部で定義されたntmcmd_extobj_tである事がわかります。ということで、のっけからユーザーが渡したものと違うアドレスがコールバック関数に渡ってしまう事になります。あらら。
一方で更に物事を無駄に複雑にしているのが以下の記述です。
なんと、シリアル書き込み関数に対してマクロが用意されており、そのマクロを使用した箇所に関しては、user_extobjが渡るようになっています。どうしてここは正しいんだ。と過去の自分に言いたい。
つまり、同じシリアル通信関数でも、呼び出される個所によって期待するアドレスが渡ったり、はたまた間違ったアドレスが渡ったりします。
実はこの話、凡ミスのようにも見えますが、問題の根本には全体設計のまずさがあります。そもそも、シェルインターフェースを提供するNT-Shellと、モニタ機能を提供するNT-Monitorのシステム境界が曖昧です。本来であればシェルの機能とモニタの機能は完全に分離できるはずですが、あまり綺麗に分離できているとは言い難く、結果的にこれらの二層に渡るオブジェクトの取り違えにまで発展してしまっています。
冒頭「シェルの部分はNT-Shellを用い、その上にモニタプログラムとしてNT-Monitorが乗る形を想定しました。」と書いている事からもわかるように、本来の依存関係はNT-MonitorからNT-Shellへの使用依存ですが、実装を見ると内包になっています。これも気持ちが悪い。
ということで、NT-ShellもNT-MonitorもそろそろAPIの見直しなども含めて考えたくなってきました。
2013年から約三年後の2016年現在、そういえば久しぶりに懐かしいコードを引っ張り出してみようと見てみたところ、限りなく怪しい香りのする実装が幾つも見られます。そのひとつがタイプセーフではない外部オブジェクト参照の実装。ちょっと載せてみたいシステムがあったので使ってみたところ、インターフェースに渡したはずのオブジェクトへのポインタが、異なるアドレスを指す何かに代わってコールバックされます。「あー、何だこりゃ」というのが事の始まり。
NT-Monitorは、元々単一スレッド上で永久に動作し続けるものであるとの前提で設計しました。唯一のAPIは上記に示すntm_executeで、シェルオブジェクトとシリアルI/O関数へのポインタを渡すと後は勝手にシェルを駆動しながら処理してくれるというものです。
システム内部に複数のシリアルインターフェースが存在し、かつそれらを別々のモニタープログラムが使用する事も念頭に入れ、UARTなどのインターフェースに対するハンドラへのポインタなどを格納できるようにしたのがextobjです。
が、ここにどうしようもない情けないバグがあるんじゃないかとコードを眺めていて気付きました。
まず、NT-Monitorの最上位階層であるntmモジュールを見たユーザは、当然のように自分がextobjへ渡したオブジェクトへのポインタが、そのままserial_readやserial_writeへ渡されることを期待します。そうでなければ、それが一体なんであるのか上記のAPIから知る由もありません。
しかし、実際にNT-Monitorの実装を見るとのっけから次のようなコードが見えます。何やら突然現れたntmcmd_extobj_tにserial_readとserial_writeを格納し、更にはユーザが上位のAPIで与えたextobjをuser_extobjとして保存しています。そして、この準備の終わった新しい外部参照用オブジェクトへのポインタをシェルモジュールであるntmshellに渡しています。
このままセオリー通りに事が進むと、ntmshellから呼び出されるserial_readとserial_writeは、最上位でユーザーが渡したextobjとは異なるものになってしまいそうな気もします。確認してみると・・・
ntmshell_executeで呼び出されるp->func_writeは、最上位で言うところのserial_writeです。そして、そのシリアル出力関数に渡される外部参照オブジェクトへのポインタはp->extobjを示しており、これは先ほどの確認にあったようにNT-Monitorの内部で定義されたntmcmd_extobj_tである事がわかります。ということで、のっけからユーザーが渡したものと違うアドレスがコールバック関数に渡ってしまう事になります。あらら。
一方で更に物事を無駄に複雑にしているのが以下の記述です。
なんと、シリアル書き込み関数に対してマクロが用意されており、そのマクロを使用した箇所に関しては、user_extobjが渡るようになっています。どうしてここは正しいんだ。と過去の自分に言いたい。
つまり、同じシリアル通信関数でも、呼び出される個所によって期待するアドレスが渡ったり、はたまた間違ったアドレスが渡ったりします。
実はこの話、凡ミスのようにも見えますが、問題の根本には全体設計のまずさがあります。そもそも、シェルインターフェースを提供するNT-Shellと、モニタ機能を提供するNT-Monitorのシステム境界が曖昧です。本来であればシェルの機能とモニタの機能は完全に分離できるはずですが、あまり綺麗に分離できているとは言い難く、結果的にこれらの二層に渡るオブジェクトの取り違えにまで発展してしまっています。
冒頭「シェルの部分はNT-Shellを用い、その上にモニタプログラムとしてNT-Monitorが乗る形を想定しました。」と書いている事からもわかるように、本来の依存関係はNT-MonitorからNT-Shellへの使用依存ですが、実装を見ると内包になっています。これも気持ちが悪い。
ということで、NT-ShellもNT-MonitorもそろそろAPIの見直しなども含めて考えたくなってきました。
2016年4月30日土曜日
Natural Tiny Shell (NT-Shell)の新しいリリースパッケージVersion 0.3.1を発行しました。
Natural Tiny Shell (NT-Shell)の新しいリリース・パッケージVersion 0.3.1を発行しました。
https://www.cubeatsystems.com/ntshell/ のダウンロードからダウンロードできます。
ET展のTOPPERSブースでプレゼンテーションをさせて頂いた時の資料に書かせて頂いた「ユーザーコマンド」なるものを実現する例として、NXP LPC824を題材にしたサンプル・プロジェクトを追加してあります。
https://www.toppers.jp/docs/contest/presen2011_NaturalTinyShellTask.pdf#search='toppers+ntshell'
今回のパッケージ・アップデートはざわさんのコメントを発端にしています。ざわさん、貴重なフィードバックをありがとうございます。
https://www.cubeatsystems.com/ntshell/ のダウンロードからダウンロードできます。
ET展のTOPPERSブースでプレゼンテーションをさせて頂いた時の資料に書かせて頂いた「ユーザーコマンド」なるものを実現する例として、NXP LPC824を題材にしたサンプル・プロジェクトを追加してあります。
https://www.toppers.jp/docs/contest/presen2011_NaturalTinyShellTask.pdf#search='toppers+ntshell'
今回のパッケージ・アップデートはざわさんのコメントを発端にしています。ざわさん、貴重なフィードバックをありがとうございます。
2016年3月31日木曜日
組込み機器の制御にStandard Commands for Programmable Instruments(SCPI)を用いる事を考える
あらまし
組込み機器を設計すると、小さな規模の装置でも数十から数百を超える操作が簡単に生まれてしまいます。設計実装した機器が確かに意図したとおりに機能しているのかを確認しようと考えた場合、それら全ての操作に対して考え得る全ての組み合わせで実行しない限り、予期しない動作が生まれない保証はありません。特に機器側に何らかの状態を持つような設計が含まれる場合、人間が操作したのでは到底網羅出来ない数の組み合わせが存在する事になります。
さて、エンジニアとしては自分の設計と実装が期待通りの動作をしているのか確認してから枕を高くして眠りたいところですが、その操作インターフェースが独自コマンド体系になっていると色々な弊害が出てきます。例えば、「そもそも操作を自動化できるコマンド体系になっていない」、「独自の概念に基づく操作が並べられており第三者の理解が難しい」、「機器側の状態にコマンドの実行結果が依存しすぎる」など。ついつい作ってしまう独自コマンド体系によって自動化が困難な状況も自ら作り出してしまう事になります。おろろ・・・これでは枕を高くして眠れない・・・。
ということで、「何か代替案はないかなぁ」と調べ始めたのが今日のお話。
Standard Commands for Programmable Instruments(SCPI)
Standard Commands for Programmable Instruments(SCPI)とは、プログラマブルな計測器をコマンドで操作するために作られた規格です。独自の操作体系で作られた数多くの機器を制御するのが難しかった背景から策定されたもので
- 同種の二つの計測器が存在した場合、同一の制御方法を持つ(垂直互換性)
- 二つの測定器では計測手法が何であるのかに依らず同じ計測が可能である(水平互換性)
- 同じ機能を持つ二つの計測器では同じコマンドで操作できる(機能互換性)
という3つのコンセプトがベースになっています。
実際に規格に書かれたプログラマブル計測器のモデルを見ると計測器のみならず、様々な組込み機器でも再利用可能に思えてきました。上記のモデルで言うと、Measurement Functionは入力系統、メモリは文字通り、Signal Generationは出力系統です。要するに入力された信号がメモリに入り、計算されて出力されるというコンピュータシステムそのものなのです。
例えば、オーディオを処理するような装置を仮に作った場合、上記モデルで言うところの上段は入力(録音)系統、下段は出力(再生)系統になるわけです。実際、規格文書の例は車台ダイナモメータのモデルが示されたおり、ちょっとやってみたくなる素材としても面白い内容になっています。どのような装置であっても、広義の意味で測定器と言えるのでその応用の範囲は広そうです。
という事で、何か作ってみたくなる素材のお話しでした。
2016年2月8日月曜日
KiCadのコンポーネントエディタにまつわるティップス
先日からKiCad (Version: 4.0.1-stable release build)への移行を始めました。
EAGLEからKiCadへ移行する方への参考になればと、「おぉ!これは!」と思ったポイントをまとめてみましたので御紹介します。
KiCadでは、コンポーネントエディタで「ドキュメントファイル名」を指定しておく事で、回路図から直接ドキュメントを開く事ができるようになります。
部品点数が多くなってくると、ドキュメントを開くのも億劫になってしまいますので、この手のちょっと便利な機能は、膨大な時間を節約する事に繋がります。これは便利。
最初、それが何かわからなかったのですが、よくよく他人の回路図と比べるとコンポーネントの外観がとても残念です。
調べてみると、コンポーネントの枠に対して背景色で塗りつぶすという選択がある事に気づきました。回路図上でコンポーネントが格段に見やすくなりますのでお勧め。
コンポーネントに対して3Dモデルを割り当てられるのですが、どうしても固有環境のパスが入ってしまいます。これでは、他の環境でチェックアウトして作業・・・なんて芸当が出来ません。
実際には、ダイアログが自動的に挿入するパスから手動でKiCadが内部で持つ環境変数名を入れてやれば良い事がわかりました。
KiCadの場合、キーボードの操作だけでピンを追加できるように操作系が工夫されています。
EAGLEからKiCadへ移行する方への参考になればと、「おぉ!これは!」と思ったポイントをまとめてみましたので御紹介します。
コンポーネントに対するドキュメント
私の場合、後から設計情報を見た時に何を根拠に設計したのか明らかにする意味で、採用した部品のデータシートを必ずリポジトリに入れることにしています。KiCadでは、コンポーネントエディタで「ドキュメントファイル名」を指定しておく事で、回路図から直接ドキュメントを開く事ができるようになります。
部品点数が多くなってくると、ドキュメントを開くのも億劫になってしまいますので、この手のちょっと便利な機能は、膨大な時間を節約する事に繋がります。これは便利。
残念な外観のコンポーネント
コンポーネントを作り始めてから数日後、何か違和感あるよなぁと思いました。最初、それが何かわからなかったのですが、よくよく他人の回路図と比べるとコンポーネントの外観がとても残念です。
調べてみると、コンポーネントの枠に対して背景色で塗りつぶすという選択がある事に気づきました。回路図上でコンポーネントが格段に見やすくなりますのでお勧め。
3Dシェイプのデータパス
これはどちらかというと「どうやってやるんだ?」な話。コンポーネントに対して3Dモデルを割り当てられるのですが、どうしても固有環境のパスが入ってしまいます。これでは、他の環境でチェックアウトして作業・・・なんて芸当が出来ません。
実際には、ダイアログが自動的に挿入するパスから手動でKiCadが内部で持つ環境変数名を入れてやれば良い事がわかりました。
コンポーネントに対する説明
KiCadでは、コンポーネントに対する説明を加えておく事で、部品選択ダイアログで絞り込み検索が可能です。既存ライブラリなどの説明を見ていると、「あぁ、これだと検索にかからないよなぁ。」なんて書き方があります。自前のライブラリを作る場合、データシートに書かれたDescriptionからテキストをコピーするのがお勧めです。コンポーネントのピン編集作業
コンポーネントエディタでピンを追加する場合、ピンを置きたい位置にマウスをクリックし、出現したダイアログに情報を入力・・・というのが通常のやり方です。が、そんな事を何度も繰り返していると、さすがに「これは不便なんじゃないか?」と疑問を感じ始めます。KiCadの場合、キーボードの操作だけでピンを追加できるように操作系が工夫されています。
KiCadティップスコーナー
Twitter上で「今朝のKiCadティップスコーナー」を更新中ですのであわせて御覧下さい。2016年1月9日土曜日
KiCadを使い始める
ちょっと思い立ってKiCadを使い始める事にしました。
もうだいぶ長い間EAGLEを使っていたので、乗り換えるにあたってツールが前提としているワークフローの違いについても見ておかなければなりません。KiCadのウェブページを見るとGetting Startedのページに御丁寧に説明が書いてありましたの紹介します。
EAGLEの場合、ライブラリファイルの中にシンボルとフットプリントが一緒に管理されていました。
世界中で広く使われている一般的な電気系CADの場合、シンボルとフットプリントが一緒に管理される事は滅多になく、通常は別々の管理になっています。EAGLEに慣れた人がKiCadだけを見ると特異なものに見えてしまうかもしれませんが、実際にはEAGLEの方が特別なケースと言えるでしょう。
ということで、チマチマとワークフローを辿って操作を学習していく事にします。
何か実際に設計するための題材が欲しいなぁ、何にしようかなぁ。
もうだいぶ長い間EAGLEを使っていたので、乗り換えるにあたってツールが前提としているワークフローの違いについても見ておかなければなりません。KiCadのウェブページを見るとGetting Startedのページに御丁寧に説明が書いてありましたの紹介します。
EAGLEの場合、ライブラリファイルの中にシンボルとフットプリントが一緒に管理されていました。
世界中で広く使われている一般的な電気系CADの場合、シンボルとフットプリントが一緒に管理される事は滅多になく、通常は別々の管理になっています。EAGLEに慣れた人がKiCadだけを見ると特異なものに見えてしまうかもしれませんが、実際にはEAGLEの方が特別なケースと言えるでしょう。
ということで、チマチマとワークフローを辿って操作を学習していく事にします。
何か実際に設計するための題材が欲しいなぁ、何にしようかなぁ。
登録:
投稿 (Atom)