2013年12月30日月曜日

M25PX16をフルコントロール! (M25P16とM25PX16を比較してみる)

あらまし

2012年の10月にM25P16をフルコントロール!と題してM25P16の制御コードを公開しました。
今年に入ってM25PX16を使用する機会があり、それじゃあM25P16と何が違うの?というのを簡単に調べた結果をまとめてみました。一番下にはソースコードも示しましたのでご覧下さい。

M25P16とM25PX16

ブロック・ダイアグラムを見る限り、基本的な構成は変わりませんが、「64 OTP bytes」という何かが追加されています。ここで言うOTPとは、one-time programmableの略で、64バイトのワンタイム・ロムが存在するという事がわかります。なるほど、これは装置物に仕立てる時のアレコレに使えます。


次にメモリ・マップを確認してみると、M25PX16ではサブ・セクタが導入されている事がわかります。


M25PX16のコマンドがどうなっているのかというと、M25P16のコマンド・セットに加えて、幾つかの新しいコマンドが追加された形になっています。


M25PX16では、ロックレジスタが新設され、不用意なライトからメモリを保護できるように機能強化されています。また、DQ0とDQ1の二線を使って入出力ができる機能が追加されており、M25P16よりも高速にR/W可能なコマンドも用意されました。消去コマンドも、M25PX16ではサブ・セクタ単位での消去も可能となっています。

ざっと見た結果、M25P16を機能強化したのがM25PX16という感じで、M25P16を使用していた基板にM25PX16を使用する事もソフトウェアの変更のみで可能という事がわかりました。READ IDENTIFICATIONコマンドを発行すれば基板にどちらのフラッシュ・ロムが搭載されているのか検知可能ですから、下層でうまく実装する事で自動的に切り替える事も可能です。


ということで、M25P16とM25PX16に対する制御コードを記述し、実機動作確認済みのソースコード公開します。

ソースコード

  • 実機で動作確認済みのソースコードからターゲット依存箇所を取り除いたソースコードです。
  • 無保証です。一切の責任を負いません。
https://github.com/shinta-main-jp/M25PX16

2013年11月26日火曜日

ET2013のTOPPERSパビリオンでショートプレゼンテーションをさせて頂きました

TOPPERSアプリケーションコンテストに関連して、ET2013のTOPPERSパビリオンでショートプレゼンテーションをさせて頂きました。

ET2011では小規模組み込みシステム向けシェルのNT-Shell、ET2012では小規模組み込みシステム向けロガーのNT-Loggerと、二年連続でミドルウェアを提案しました。今回は、TOPPERSのsample1に対する改善という事で主旨を変更して提案しました。


ショートプレゼンテーションでは、リアルタイムオペレーティングシステムを使った組み込みシステムの設計、実装、検証について、日頃感じている事も少しだけお話させて頂いた次第です。これは、提案の題材として用いたシステムを使って実際に取得したデータから、リアルタイム性を確認する手段など簡単な手順を交えた内容としました。

非常に安価な装置を用いて、以下のように処理にかかる時間の分布などを得る事ができます。


リアルタイムオペレーティングシステムを使った組み込みシステムの場合、最悪値の検証が欠かせません。データを収集して整理するだけに留まらず、客観的に評価できるところまで落とし込む作業が必要です。


実開発では、正しく動作しているように見える時に「本当に意図した動作になっているのか?」まで確かめる必要があります。ショートプレゼンテーションでは、確認作業のアプローチの一つとして幾つかの方法を述べました。



2013年11月2日土曜日

adafruitでUOS-LPC800が紹介されていました

adafruit(http://www.adafruit.com/)でUOS-LPC800が紹介されていました。


彼らが販売しているLPC810 Mini Starter Packに絡めた紹介になっています。
これだけの部品で、小さなオペレーティング・システムが楽しめます。


ビルトイン・シリアル・ブートローダのおかげで、ホスト・ターゲット間でシリアル通信さえできればプログラムを書き込めるのも嬉しいポイントです。

2013年10月12日土曜日

オペレーティング・システムのスケジューラを書く人の強い味方「レジスタ将棋」を考案しました

「青空の下でLPC800 Mini-KitとUOS-LPC800を楽しもう!」の説明資料を作っていて、レジスタの扱いについて面白く説明する方法はないかなぁ?と考えていました。

オペレーティング・システムを書くとなると、あのレジスタをこっちにやって、このレジスタをあっちにやって・・・とだんだん頭がわけわからなくなってきます。UOS-LPC800のスケジューラを書いている時も、Cortex-M0+の命令セットをどう使うのか頭を悩ませた気がします。もう忘れましたが。


で、それを他人に説明する時の面白い方法が欲しいと思いました。
で、考えたのが「レジスタ将棋」です。

どんなものになるのか自分でもよくわからなかったので試しに百円ショップで将棋セットを購入。


うーん。
この金将とか歩兵とか邪魔だな・・・。


「裏面を使えば良いか!」と考えていたが、よく考えたら彼らはシチュエーションによって色んな奴に化けるのを失念していました。おぉ、両面に文字がある。


「くそぉー」ということで、耐水ペーパーでゴシゴシ削ってレジスタ名を記入することに。
これで「レジスタ将棋」の完成です。


ちなみに、青い字はLow Registersで、Cortex-M0+のSTM、LDM命令でもアクセス可能なレジスタ。
赤い字はHigh Registersで、Cortex-M0+のSTM、LDM命令ではアクセスできないレジスタです。


「レジスタ将棋」の使い方は至って簡単。
スタックポインタを起点に積んでいくレジスタ駒を並べて行くだけ。


R13はMSPやPSP、R14はLR、R15はPCでもあるので、裏面にひっくり返すとPSP、LR、PCなどと書いてあります。


レジスタの退避、復旧、複写は、アドレス・インクリメント・モードが複数あったり、他人に説明する場合にややこしくなりがちです。駒を動かして一つずつ操作を理解する事で、楽しくレジスタ操作を把握できるという算段です。

この「レジスタ将棋」のアイデア、駒を動かしてゲーム感覚でレジスタ操作を整理できるので、我ながら気に入っています。みなさまもオペレーティング・システムのスケジューラを書く際の友として如何でしょうか?

「青空の下でLPC800 Mini-KitとUOS-LPC800を楽しもう!」を開催しました

訳のわからないタイトル「青空の下でLPC800 Mini-KitとUOS-LPC800を楽しもう!」で企画したLPC800 Mini-KitとUOS-LPC800を楽しむ会を開催しました。


基本的にユルユルな会と見せかけながら、実はリアルタイムシステムの評価手法に関するノウハウなども公開したりといった内容としました。


開催場所は横浜市営地下鉄のセンター北駅から徒歩10分ほどの閑静な住宅街の中にある公園。


私は到着早々、今朝思いついたばかりの「レジスタ将棋」の思案を開始。
その直後、落ち葉が降ってきて「おぉー、秋ですなぁ~。」と感じるなど。


基本的に公園の中でやる事ではないのですが、いつもと違う感じが気持ち良かったです。


振り返ればそこは池!
鴨みたいなのとか、そうじゃないやつとか沢山いました。


皆さん思い思いの環境でLPC800 Mini-KitとUOS-LPC800を楽しんで頂いて何より。


14:00から16:00の開催時間をとっくに過ぎて16:30に終了。
二次会の締めとして喫茶店で続きを・・・。


前回の茶室で楽しむKOZOS拡張基板に福島からいらしてくれた方からは、「こんな手軽な環境でデバッガが使えるなんて嬉しいです」とも。あぁ、やって良かった「青空の下でLPC800 Mini-KitとUOS-LPC800を楽しもう!」企画!タイトルが長い!

2013年8月31日土曜日

A capacitive touch sensing using an analog input port for mbed

先日のことですが、mbed用の静電容量式タッチセンサライブラリを公開しました。



http://mbed.org/components/Touch-Sensor-using-an-analog-input-port/

まだまだ改良したい感もありますが、「ひとまずこれで公開!」というバージョンです。

2013年7月28日日曜日

Markdown記法を使ってプロジェクトの関連文書生成を効率的にする

Markdownって何ですか?

Markdownとは、John Gruberさんによって作られたマークアップ言語で、記述したテキストファイルをスクリプトで処理して二次生成物としてHTML出力する事ができます。
最近ではリポジトリに設置する文書にMarkdown記法を用いるケースを多く見るようになりました。
「README.mdって何だ?」っていうアレです。

今回はUOS-LPC800プロジェクトにおけるMarkdownの活用をご紹介します。

UOS-LPC800におけるMarkdownの活用



UOS-LPC800では、プロジェクト開始当初からMarkdownで一次文書を構成し、二次生成物としてウェブ用ファイルを作ることを考えていました。

Markdownのファイルをダウンロードすると変換用のPerlスクリプトが同梱されています。
Markdown.plを使用した事のある人にはわかるかもしれませんが、このスクリプトは単に書かれた事を書かれたように変換するだけのスクリプトです。

UOS-LPC800のウェブページを作るにあたって、Markfileやシェルスクリプトでラッパーを作りました。
これにより
  1. Markdown記法でテキストファイルを記述
  2. 端末でmake
するだけでウェブブラウザが開いて生成物の内容を確認できるようになります。

今回のラッパーでは以下を実現しています。
  • ページで使用する画像はimagesに置いておけば良い。
  • ページで使用するリソースはresourcesに置いておけば良い。
  • Markdown.plで処理されないヘッダの類はhead.htmlとtail.htmlで付与する。
とこんな感じです。

ダウンロード

今回のファイル一式をこちらからダウンロードできるようにしておきました。

2013年6月23日日曜日

割と適当に動作するOS「誰得OS」のCortex-M0+版であるUOS-LPC800を作りました

割と適当に動作するOS「誰得OS」のCortex-M0+版を作りました。

32ビットプロセッサとしては極めて小さいNXPセミコンダクターズ社のLPC810 (RAM=1KB、ROM=4KB) でもなんとか動作します。名付けてUOS-LPC800です。


以下の動画では、LED点滅タスクとUART送受信タスクが動作しているところを示しています。


LPC800 MiniBoardをお持ちの方はHEXファイルをダウンロードして試してみる事ができます。
「割と適当に動作する」などと言いながらも、スケジューリング・アルゴリズムはラウンド・ロビンと優先度ベースで選択できたりします。そして、カーネルの中核を成すコードはわずか300行で誰にも読み切れるサイズです。

今年中に「茶室で楽しむKOZOS拡張基板」のような企画をやりたいなぁ~と考えているところです。

2013年5月5日日曜日

ARM Cortex-M3のアセンブラ学習に最適なインストラクションを簡単に調べるツールを超適当に作ってみた

何それ?

ARM Cortex-M3のCソースコードから注釈付きアセンブラリストを得るスクリプトです。

先日の投稿で「誰得OS」を作る事を考え、インターフェースの設計を行いました。
このOSのターゲットとしてARM Cortex-M3を最初に選択しました。
ARM Cortex-M3のアセンブラを記述するのは初めてなので、カーネル内部コードを記述する際に役立つであろうインストラクションを簡単に調べるツールを超適当に作ってみた次第です。


このツールのフローは以下のようになっています。
  1. ソースコードをC言語で記述する
  2. ソースコードをコンパイルしてオブジェクトファイルにする
  3. オブジェクトファイルを逆アセンブルしてインストラクションリストにする
  4. インストラクションリストを走査して注釈を付ける
このツールで最終的に得られる出力は逆アセンブルされた命令に注釈が付いたテキストです。


上記のように、逆アセンブル結果から対応するインストラクションを列挙してくれます。
わざわざ辞書のようにインストラクションセットを引く必要もありません。

アセンブラを記述する場合、単純な「やりたい事」と「インストラクション」を繋げていく作業が大半を占めます。予めC言語で書いたソースをコンパイルし、それを逆アセンブルした結果をインストラクションセットと一緒に眺めれば学習効果が高まるだろうと考えたわけです。

ダウンロード

ダウンロードはこちらからどうぞ。
自己責任でお使い下さい。

テスト用のサンプルCソースとMakefile付き。
実行後の結果も一緒にまとめてあります。

実行したい場合、単にmakeと打つだけです。
地味ながらこれは便利。

2013年4月30日火曜日

割と適当に動作するOS「誰得OS」を作る事を考える No.1 (まずはインターフェースを考えるだけ)

先日から色々と思うことがあって、「割と適当に動作する」OSを作る事を考え始めました。
「割と適当に動作する」というのは、まぁ言ってみれば「オモチャとして動作します」という事です。

考えているOSは、リアルタイム性もないし、タスク間通信も最小限。
でも、自分が作ったからよくわかるという、その名も「誰得OS」です。

私の場合、ソフトウェアは基本的にインターフェースの設計から始めます。
この基本方針はOSになっても変わりません。

まずは「誰得OS」のインターフェースを考える事にしました。


「誰得OS」は、
  1. daretoku_kernel_initでカーネル・オブジェクトを初期化。
  2. daretoku_task_initでタスクを初期化。
  3. daretoku_kernel_startでカーネルを動作開始。
と最低限3つのインターフェースを知っていれば動作させる事ができます。
「できます」と書いていますが、まだできていないので、そうなるように作る事にします。

ただ単にマルチ・タスクなだけではOSとしてあんまりなので、タスク間通信もdaretoku_msg_send_waitとdaretoku_msg_recv_waitで実現する事にします。

優先度とかは後で考える事にして今は放置。
当然のようにリアルタイム性に対する考慮なんてしません。

残念なOS、それが「誰得OS」なのです。
という事で、インターフェースを考えるだけなら簡単です。

これからチマチマと実際に動作するOSに仕立てていく作業が始まります。
適当に作る割に先は長そうです。

2013年3月31日日曜日

DMAバッファ管理手法の続編

シンプルな制御モデル

昨年10月の投稿「ビデオやオーディオのDMAバッファの管理手法 (動かして遊べるソースコード付き!)」では、ビデオやオーディオなどを扱うファームウェアで、DMAバッファをどのように扱うと良いのかについて述べました。

先の投稿で上げた制御モデルは以下のようなシンプルなものでした。



この制御モデルは、巷でよく見かける配列のインデックスを使って制御する方法よりも抽象化が可能で、チャネル数の変更や遅延量の制御などを簡単に実現する事が可能です。

このシンプルな制御モデルの応用可能範囲は、ビデオやオーディオに限りません。

例えば、データロガー等の場合、出力側にSDカードのような書き込み処理に時間がかかる物を配置する事があります。
この場合、viproc側でデータ収集設定(DMA設定)、voproc側でSDカードへの書き込みという事になります。

何がポイントですか?

先の制御モデルのポイントの一つは「queueによって入出力の関係が切れている」事です。
実は先日のシンプルな制御モデルは非常にシンプルにした一例で、実際に使用する場合にはもう少し思考を進める必要があります。

話を先に進める前に簡単にポイントを振り返っておきましょう。
  1. 遅延器(DELAY)は、DMAリクエスト発行からDMA完了までの時間を保証する。
  2. キュー(QUEUE)は、処理時間が一定でない後段に前段が影響を受けないようにする。
  3. 遅延器(DELAY)とキュー(QUEUE)によって、入力と出力の時間依存関係を緩いものにする。
入力側と出力側の両方でDMAを使用する場合も考慮して、先のシンプルな制御モデルに対して少し思考を進めてみましょう。


今回は対象領域も明確にしておきました。

入力処理では、入力キューからバッファを取得し、DMAリクエストを発行した後、入力遅延器にバッファを格納します。加えて、入力遅延器から出力キューに過去のバッファを移動させます。
出力処理では、出力キューからバッファを取得し、DMAリクエストを発行した後、出力遅延器にバッファを格納します。加えて、出力遅延器から入力キューに過去のバッファを移動させます。

上記文面を見ておわかり頂けると思いますが、入出力で完全に対称系になっています。

上記モデルを使用する事で、先に挙げたようなチャネル数の変更や遅延量の制御だけでなく、入出力の位相が曖昧な場合でも制御が破綻するような事がありません。

上記の制御モデルを使用する場合、以下のような事も考慮すると良いでしょう。
  • 入力と出力は別々のハードウェアが担当しているのが普通。
    • 入力割り込み、出力割り込みは非同期系として設計する。
    • RTOSを使用する場合、入力と出力の処理スレッドは別々に設計する。
  • キューから取り出せない場合、どのように振舞うべきか?
    • 制御系が何を期待するのかによって挙動を決めます。
  • 全体をリセットする場合、どのようにリセットすべきか?
    • これは意外に難しい問題です。
    • ハードウェアがどのように振舞うのかによっても大きく変わります。
  • その他。(色々あります)

    動かして遊べるソースコード

    今回も動かして遊べるソースコードを用意しました。
    先の投稿のソースコードと見比べてみるのも楽しいと思います。

    2013年2月24日日曜日

    nanoKONTROL2を小規模組み込みシステムのユーザインターフェースとして使うお手軽な方法

    便利だったけど・・・

    2012年初頭からネチネチネチネチ続けているオーディオ・プラットフォーム開発。

    オーディオ・プラットフォーム開発用にでっち上げたベース基板には、予めオーディオ・プラットフォームで使用するであろう「何らかのパラメータ設定手段」を提供するために、LCDとロータリースイッチを搭載しました。


    ロータリースイッチでクルクル回転させてグシッと押せば、即座に設定完了という操作系です。
    これはこれで便利だったのですが、パラメータが複数に渡ってくると操作性に不満が出てきます。

    今回ご紹介する新しいアイデアは、2012年の11月の時点で試作まで完了していました。
    すっかり別件で忙しくて忘れていたのですが、どのようなものなのか御紹介しようと思います。

    nanoKONTROL2

    nanoKONTROL2とは、KORGが販売している音楽制作環境向けのコントロール・サーフェースです。
    USB経由でパソコンに接続し、音楽制作環境で色々操作できるというもの。


    このように沢山のスライダーとノブが搭載され、複数のパラメータを調整するにはもってこいです。


    この手のコントローラはMIDIイベントを送受信できるように設計されています。
    MIDIイベントを受信するソフトウェアをホスト上に仕立て、組み込みシステムに指令を与えれば完成というわけです。
    組み込みシステムはホスト上から制御出来れば、特別に何かする必要はありません。お手軽ですね。


    単にホストに接続できるコントローラを購入しさえすれば、複数のパラメータを直感的に操作可能なユーザインターフェースをシステムのサービスとして提供できるようになるのです。

    動作の様子

    それでは動作の様子を動画で御紹介します。



    上記のように複数のパラメータをサクサクゴニョゴニョする事ができます。

    同時に複数のパラメータを直感的に操作できるのが嬉しいポイント。
    癖になってしまいそうな感覚です。

    まとめ

    今回のアイデアは様々なところに応用する事ができます。

    このようなコントローラは安価で入手しやすいというのも嬉しいメリットの一つ。
    これらのインターフェースを直接組み込みシステムに搭載しようと考えたら大変です。
    直感的なインターフェースを実現するための部品コストは馬鹿になりません。

    お手軽に使えるところを使う事で、素早くシステムとしてのサービスに仕立てる事が可能です。

    2013年2月17日日曜日

    簡単便利なBlackfin用フラッシュ書き込みツール「Blackfin BlueBoot」のVersion 0.3.0をリリースしました。

    Blackfin BlueBootってなぁに?

    Blackfin BlueBootってなぁに?という方は、「Blackfin BlueBoot - Blackfinに接続されたブート用外付けフラッシュ・ロムを書き換える事ができるソフトウェアのデビューです!」を御覧下さい。

    Blackfin BlueBootの開発プラットフォーム

    2012年の12月に最初のリリースBlackfin BlueBoot Version 0.2.0をリリースしました。

    このBlackfin BlueBootは、「DSPに興味はあるけど環境整備の敷居が高くて手を出せない!」という人のために設計実装した開発ツールです。メーカー純正ツールなら外付けフラッシュに書き込めるけど、それはまぁだいたい10万円です・・・なんて簡単に手を出せる物ではありません。

    Blackfin BlueBootによって、無償の外付けフラッシュ書き込み環境を実現しています。


    Blackfin BlueBootの開発には、市販されているDSPボードとオーディオコーデックボード用を搭載できるベース基板BlueTankを開発して使用していました。これ一台さえあればオーディオ入出力プラットフォームになるという算段です。これはなかなか便利なものでした。例えば、以下のようにオーディオアプリケーションを簡単に楽しめるようになっています。


    「これ一台で」というのがポイント。

    ベース基板BlueTankは自分で設計しているのでI/Oの取捨選択は自分でできます。
    自分が欲しくないI/Oがてんこ盛りになった評価基板なんていらないのです。

    便利なオーディオプラットフォームが登場


    さて、前述の市販されているDSPボードとオーディオコーデックボードは、金子システム社製のものでした。これ一台(一枚?)でDSPが楽しめますなシンプルなボード構成がとても気に入っていました。


    前述のBlueTankには同社製「DSP基板」と「オーディオコーデック基板」が搭載される形式でした。

    そんな折、新しく仕入れたのがTUNA-CANと呼ばれる新しいオーディオプラットフォームです。
    なんと、このTUNA-CAN基板は「DSP」と「オーディオコーデック」の2つが1枚の基板にコンパクトにまとめられています。

    以下がその写真です。


    これにLCDとロータリースイッチを付ければもう「BlueTankいらず」です。
    この新しいプラットフォームに触発され、新しいバージョンをリリースする事にしました。

    Blackfin BlueBoot Version 0.3.0

    新しいBlackfin BlueBoot Version 0.3.0では、主に以下の変更を行ないました。

    • 書き込みセクタ数の算出バグを修正。
    • LDRファイル選択時にLDR情報が更新されないバグを修正。
    • TUNA-CAN用ブートローダをリリースに同梱。
    • ホスト側I/Oライブラリのソースコードを同梱。
    • 日本語ローカライズに対応。
    ダウンロードはこちらからどうぞ。

    まだまだ修正したい事は沢山あるのですが、それを待っていたらリリースができません。
    今回はタイミング重視で、小さく更新してリリースする事にしました。

    その他

    実はBlackfin BlueBootの初版をリリースした後、別の類似ツールを作っていました。
    その話と関連したあれこれは、別途機会を見てご紹介する予定です。

    酔漢さんが運営されているDSP空挺団では、「ブレッドボードで作るオーディオ信号処理」が公開されています。
    こちらの投稿もお勧めです。

    2013年2月10日日曜日

    小規模組み込みシステムの入出力ライブラリntstdioモジュール

    簡単便利なChaNさんのxprintfモジュール

    libcの存在が期待出来ないような小規模組み込みシステム開発において、意外に億劫なのは端末入出力です。newlibなど便利なライブラリが世の中には存在しますが、フットプリントと使用する関数がバランスしないケースも多々あります。

    実際にここで代替関数を作ってニンマリしたいところですが、「本当に開発したいものはそれじゃない」ということで後回しにしていました。その類の物は沢山作っていて、そちらが忙しいというのもあったりします。

    とある開発作業を進めるうちに、ChaNさんが便利なライブラリ(http://elm-chan.org/fsw/strf/xprintf.html)を提供されている事を思い出し、組み込んで楽をしていました。
    ChaNさん、ありがとう。


    RTOSベースのシステムでxprintfを使う

    ライブラリというのは、ざっくり言うと上層が楽をするために存在するものです。
    便利なライブラリというのは、あっちにもこっちにも使うようになります。
    xprintfも例に漏れず、対象システムの中で活用箇所が増えていきました。
    「あぁ、これは便利だ。」となるわけです。

    使っていたシステムの概略を示すと以下のようになります。
    本当は他にも色々と付いているのですが、今回の説明に必要ないので省略しています。


    UIOは、システム操作子の動作を監視して、ユーザの要求をシステム制御タスクに伝達するタスクです。
    Shellは、シェル用インターフェース(今回の場合、シリアルポート)経由で行なわれるユーザの要求をシステム制御タスクに伝達するタスクです。
    Systemは、外界からの要求を基に、システムを望む状態に制御するタスクです。
    Displayは、内部タスクからの表示要求を基にディスプレイを制御します。

    ちなみに、上記のシステムで使用しているRTOSはスレッドモデルを採用したOSです。
    なので、タスクと言っても中身はスレッドです。

    さて、当初xprintfはShellタスクの表示用として使用していました。
    少し開発が進んだところで他のタスクでも使いたくなってきました。

    システムの全体統括を行なっているSystemタスクは、メニューコンテキスト生成も行なっています。
    文字列の整形があるので「ここで使えば便利だな」という算段でした。



    おっと。
    だんだんと話の雲行きが怪しくなってきましたね。


    もうお気付きかもしれませんが、xprintfはスレッドセーフではありません。
    入出力関数へのポインタは処理によって書き換えられます。
    加えて、出力箇所を指し示す文字列へのポインタも状態によって書き換えられます。


    ここでxprintfモジュールが内部でどのような依存関係になっているのか見てみます。
    (2011年4月14日に公開されたバージョン)


    xprintfは、内部エンジンxvprintfに書式解釈と出力を委任する形をとっています。
    上記依存関係への視点は、Shellタスクでの使用のみを考えた場合に限っては悪くありません。

    では、Systemタスクで文字列整形に使った場合、どうなるでしょうか?
    先ほど検討した依存関係の範囲は、全く役に立たなくなります。


    例えば、Systemタスクでxsprintfを使い始めた場合、競合操作が起きる結果になります。
    これはxputcが何をやっているのか見る事ですぐにわかります。


    xputcには、「outptrが0でない時にoutptrが指し示す箇所に文字を入れて戻る」があります。
    それ以外の場合、xfunc_out関数で文字を出力ですね。

    一方でxsprintfを見ると、「与えられたバッファへのポインタをoutptrに代入してxvprintfを呼ぶ」という処理が記述されています。


    先ほどの依存関係を見れば明らかですが、xprintfもxsprintfも内部ではxvprintfを呼び出しています。両者は、xvprintfの先で同じロジックを通過しており、その先でグローバル変数を見ている以上、操作競合は避けられません。

    最初にシステムで使用し始めた時は「このタスクのみで使用」と割り切って使っていました。それを忘れてひょいひょい使い始めたからさぁ大変。シェル経由で状態取得しながら操作子いじると、時折システムがおかしな挙動になる始末でした。

    趣味で作るような単純なシステムの場合、疑いのある箇所への着目は比較的簡単です。
    今回はかなりのデバイスが制御対象になっていたので、他の要素に気を取られすぎていました。


    まぁ気付けば簡単、話に書いてしまうのも恥ずかしいような内容です。

    xprintfをベースにしたntstdioモジュール

    さて、現場で起きた問題を基に、何かを考えるのがCuBeatSystemsのお仕事です。

    そのまま当初の方針に従いShellタスクでのみの使用として解決しても構いません。
    が、それでは未来の自分や他の開発者が同じような間違いをしかねません。
    そこで、xprintfをベースに、RTOSベースシステムでも使用可能な物を試作してみる事にしました。

    名付けてntstdio。
    ハンドラ毎にI/O関数を設定可能な構成としました。
    RTOSベースシステムでも安心して複数の箇所に使用する事ができます。

    使い方は簡単です。

    ntstdio_initにハンドラへのポインタ、出力関数、入力関数へのポインタを渡します。
    ハンドラへのポインタを呼び出しに加えるだけで、ChaNさんのxprintfと同様に使う事ができます。


    冒頭で挙げたシステムの場合は以下のようになるでしょう。
    • Displayタスクでは出力関数にLCD表示関数を設定して使用。
      • xprintfするだけでLCD表示が可能!
    • Shellタスクでは入出力関数にUART入出力関数を設定して使用。
      • xprintfするだけでUART出力が可能!
    • Systemタスクでは書式整形関数のみを使用。
      • 他の操作と競合せずに書式整形が可能!
    従来のxprintfの実装の場合、RTOSの複数の箇所で美味しく頂く事は出来ませんでしたが、ntstdioを使えば上記のように色々な箇所でChaNさんのxprintfを楽しめます。

    ダウンロード

    試作したntstdioモジュールのダウンロードはこちらからどうぞ。

    2013/02/16追記
    公開当初よりちょっぴりアップデートしています。
    最初にダウンロードされた方は再度ダウンロードされる事をお勧めします。

    謝辞

    常に素晴らしいアイデアとナレッジと実装を公開して下さるChaNさんに感謝いたします。