2015年6月30日火曜日
Natural Tiny Shell (NT-Shell)の更新予定について
マイコンベースの小規模組み込みシステムでお手軽にシェルを実現するNatural Tiny Shell (NT-Shell)ですが、数ヶ月前から更新を予定していました。
というのも、数年前に公開したパッケージは、フラットにソースコードが格納されているのみで、正直言ってどうやって使うのかイメージできるようなものではありません。
当時はおそらく「まぁ、こんな感じでmain関数に組み込んでおけばわかるかな?」くらいにしか考えなかったのですが、今見てみると「これは考えていることが伝わらないよ・・・」という印象。
おまけに、詳しい説明は月刊Interfaceにしか掲載されておらず、そして、そのInterfaceの記事はNatural Tiny Monitor (NT-Monitor)がメインになっているような構成です。
現在、ライブラリのパッケージングを工夫して、コアライブラリファイルと、ユーティリティライブラリファイルを分離する方向で調整を進めています。(調整って言っても、ちょこちょこっとやるだけなんですが・・・)
加えて、幾つかのプラットフォーム向けのサンプルプログラムを同梱することで、具体的な活用イメージをお伝えしようとの考え。例えば、Blackfin向けのDSPのサンプルプログラムは、以下のような呼び出し関係を持ちます。
プラットフォームを初期化してNT-Shellを呼び出せば、もうばっちりシェルインターフェースを持つ立派な組み込みシステム!というパッケージにしようという考え。
やるやると言いながらなかなか公開していないNT-Shellですが、幾つかのバグフィックスも含める予定ですので、今しばらくお待ち頂ければ幸いです。
2015年5月31日日曜日
LPC810でも動作するリアルタイム・オペレーティング・システムのUOS-LPC800にタスク間通信機能を追加しました!
あらまし
約二年も前の話ですが、「割と適当に動作するOS「誰得OS」のCortex-M0+版であるUOS-LPC800を作りました」で 、LPC810でも動作するリアルタイム・オペレーティング・システムを作りました。LPC800シリーズの厳しい制約(ROM: 4KB、RAM: 1KB)の中でOSを動作させてみたいという欲求と、実際にこのような制約の中で何が出来るのか、単純に技術的な興味があったからです。当初のバージョンにおいて、タスク側から操作可能なAPIはuos_task_yieldとuos_task_sleepのみで、OSと呼ぶならば欲しいであろうタスク間通信すら追加しませんでした。 サンプル・プログラムは、片方のタスクでLEDを点滅させ、もう片方のタスクでシリアル通信を扱うだけのものです。まさに「誰得OS」の名前に相応しいアプリケーション。
[フレーム]
なかなか思い切った割り切りだと当時は考えましたが、先日から実アプリケーションにUOS-LPC800を適用してみようと考え始めた時点で、タスク間通信の必要性を改めて感じる事になりました。各タスクがそれぞれの仕事をこなしつつ、他のタスクと協調して動作させようと考えた場合、タスク間通信は必須とも言える機能です。 やっぱり欲しいよね・・・。
設計
タスク間通信を追加する前のUOS-LPC800におけるタスクの状態遷移は以下です。タスクは、基本的にRunningとReadyを行ったり来たりしており、uos_task_sleepによってスリープ状態に遷移するようにしました。非常にシンプルな作りです。今回、タスク間通信を追加するにあたって、方針を「出来るだけ現状の設計には手を加えないで追加する」とし、スリープ処理に手を加えない形でタスク間通信を追加する事にしました。
今回のタスク間通信(メッセージ・パッシング)のモデルは以下のようなものです。 Task Aからuos_task_event_sendに対して「送信先タスクID番号」と「32ビットの値」を渡すと、あーら不思議、uos_task_event_recvを使って待ち状態に入っているTask Bに値が渡って実行状態に遷移するというものです。モデルは至って単純。
今回、上記の単純なモデルを実現するために、カーネル内部にブロック状態を管理するタスク・コンテキスト・ブロックのキューを新設し、送信待ちタスクと受信待ちタスクをブロック状態のキューに入れてから処理する事にしました。状態遷移は以下のようになります。
本当は、スリープ状態もブロック状態の一種として扱え、相当な理由が無い限り分離する意味はなさそうなのですが、今回は既存機能に手を加えない事にしたのでそのまま。もしかしたら次のアップデートではブロック状態をBlockedに変更して、現在のBlockとSleepと統合するかもしれません。
サンプル・アプリケーション
サンプル・アプリケーションは、従来通り二つのタスクを用意しました。タスク間通信を使用する場合は、task_ttyからtask_ledに向かってタスク間通信機能を使ってLEDの点灯指令を発行します。外から見た動作は従来のサンプルと何ら変わらないのですが、タスク間通信で指令するようになったところが従来と異なります。ちなみに、タスク間通信を使う場合、直接タスク間通信の関数を呼び出しても良いのですが、受信側タスクにサービス要求用のAPIを作って、送信側のタスクがそのサービス要求用のAPIを呼び出す方が筋が良い設計です。
巷に溢れる数多くのリアルタイム・オペレーティング・システムを使った実装例には、受信側タスクの内部事情を送信側タスクが知らなければ実装出来ないような記述が多く見られます。これではタスク間通信によって得られるはずの抽象化度を上げる事によるメリットの多くを享受出来ません。受信側タスクの事情を変更した場合(例えば、送信側に期待する送信内容を変更したとか)に、送信側タスクの実装を修正しなければならないとしたら、規模の大きな設計ではたちまちバグになります。
ダウンロード
- ソースコードはhttp://cubeatsystems.com/uos-lpc800/index.htmlからダウンロード出来ます。
- ライセンスはThe BSD 2-Clause Licenseです。
- LPC800 Mini BoardとLPCXpresso LPC812で動作します。
- 「使っているよ!」とお声がけ頂くと、作者がとても喜びます。
ラベル:
ARM Cortex-M0,
ARM Cortex-M0+,
DARETOKU-OS,
LPC810,
NXP,
UOS-LPC800
2015年5月24日日曜日
「Blackfin MiniConfig for IFX-49 | 音遊び!Blackfin DSP基板でディジタル信号処理初体験」のサポート情報ページを更新しました
「Blackfin MiniConfig for IFX-49 | 音遊び!Blackfin DSP基板でディジタル信号処理初体験」のサポート情報ページを更新しました。
1つ目は「Makefileからminiconfig-cuiを呼び出す」で、書籍に付属しているソースコードに添付されているMakefileにwriteとbootというターゲットを追加し、make一発でコンパイルから書き込みまでを実現する方法をまとめたものです。修正済みのMakefileをまとめたパッケージもダウンロードできるようにしておきました。
2つ目は「Eclipseを使ったビルド環境構築」の続編とも言える「Eclipseからminiconfig-cuiを呼び出す」で、ビルド後に自動的にminiconfig-cui.exeを呼び出してターゲットに書き込みを実行できるというものです。アプリケーション間を行ったり来たりする事なく、Eclipseから1クリックで書き込みまで実行できるお勧めの設定を記述しました。フラッシュロムに書き込む方法とSRAM上で直接実行する方法の両方に対応しています。
1つ目は「Makefileからminiconfig-cuiを呼び出す」で、書籍に付属しているソースコードに添付されているMakefileにwriteとbootというターゲットを追加し、make一発でコンパイルから書き込みまでを実現する方法をまとめたものです。修正済みのMakefileをまとめたパッケージもダウンロードできるようにしておきました。
2つ目は「Eclipseを使ったビルド環境構築」の続編とも言える「Eclipseからminiconfig-cuiを呼び出す」で、ビルド後に自動的にminiconfig-cui.exeを呼び出してターゲットに書き込みを実行できるというものです。アプリケーション間を行ったり来たりする事なく、Eclipseから1クリックで書き込みまで実行できるお勧めの設定を記述しました。フラッシュロムに書き込む方法とSRAM上で直接実行する方法の両方に対応しています。
2015年4月9日木曜日
CQ出版社から「音遊び!Blackfin DSP基板でディジタル信号処理初体験」が発売されました
■書籍について
CQ出版社から「音遊び!Blackfin DSP基板でディジタル信号処理初体験」が発売されました。
この書籍にはAnalog Devices社のDSP (ADSP-BF592)が搭載された基板が同梱されており、書籍内容に連動して様々なエフェクト処理を体験できる内容になっています。今回の基板はBOOT用のピンヘッダをひとつハンダ付けするだけで、すぐに使い始める事が出来る豪華仕様。従来の付属基板と違って、USBコネクタもオーディオ入出力コネクタも予めハンダ付けされているのです。部品を別途購入する必要が無いのでとても便利!
■書き込みソフトウェア
今回、私は付属基板(IFX-49)のフラッシュ書き込みソフトウェアの設計実装を担当しました。
ソフトウェアはWindows版とMac OS X版を用意し、ビルド済みのバイナリが同梱されています。ソフトウェアからは、使ってみたいエフェクトを選択して書き込み操作を実行するだけで、様々なエフェクトをすぐに体験出来るようにしました。
ソフトウェアはWindows版とMac OS X版を用意し、ビルド済みのバイナリが同梱されています。ソフトウェアからは、使ってみたいエフェクトを選択して書き込み操作を実行するだけで、様々なエフェクトをすぐに体験出来るようにしました。
また、Windows版には書籍に連動してビルドと書き込みが出来るようにソースコードまで同梱しました。セットアップを実行するだけで本当にすぐに使い始められるようになっています。
■オフ会とフォローアップ情報
2015年5月22日(金)には、CQ出版社主催のオフ会も開催されます。
- http://www.kumikomi.net/interface/contents/blackfin_dsp.php (音遊び!Blackfin DSP基板でディジタル信号処理の部屋)
- http://www.kumikomi.net/interface/contents/ifx49.php (Blackfin DSP基板のサポートページ)
- http://cubeatsystems.com/ifx-49/ (Blackfin MiniConfig for IFX-49)
- http://connpass.com/event/13926/ (自作DSPエフェクタ 作りたい&大自慢大会)
2015年4月5日日曜日
新しいユーザーイベント機能が追加されたA tiny MML parserのVersion 0.5.0をリリースしました。(ついでにRaspberry Piのサンプルも追加しました)
先月の事ですが、Make: Japanさんの記事「Arduinoでちょっと長めの音楽を再生する方法」でA tiny MML parserを御紹介頂きました。Make: Japanさんありがとうございます。
記事を眺めていて「実世界と繋がる機能を加えれば、他の要素と組み合わせて動作するシステムを作れるよなぁ」と考えました。要するに「A tiny MML parserは単にシーケンサーエンジンである」と考えるならば(まぁ、まさにその通りですが・・・)、シーケンサーが出すイベントに応じて外界を制御するグル―ロジックを付け加えるだけで、様々なコンポーネントを制御するシステムになる・・・というわけです。
そこで、A tiny MML parser Version 0.5.0では、新しくシンプルなユーザーイベント機能を搭載する事にしました。このユーザーイベント機能は、MML文の中に@{MY_EVENT}のように@で始まり{}で括った文字列を書いておくと、ユーザーコールバック関数に「'MY_EVENT'というユーザーイベントだよ!」と通知をしてくれるというものです。
今回のユーザーイベント機能を使うと、例えば以下のような事が簡単に実現できます。
- 曲の演奏に合わせてLEDを光らせる。
- 曲の演奏に合わせてモーターを動かす。
- 曲の演奏に合わせて音色を切り替える。
- 曲なんて鳴らさずに、イベントシーケンサとして使用する。
- その他色々。
以下に示すのは、イベント文字列に応じて、サーボを制御する実装例です。
加えて、シリアル通信にイベントを通知しています。
曲の演奏状態に合わせてサーボを動作させる事が出来れば、MMLパペットが作れますね。 :)
あと、今回のパッケージからRaspberry Piのサンプルも同梱する事にしました。Physical Pin 15 http://pi.gadgetoid.com/pinout/pin15_gpio22 にピエゾスピーカーを取り付けると演奏を楽しめます。こちらのサンプル、実は改良が必要なのですが、これはまた後日・・・やるかどうかわかりませんが・・・。
ダウンロードは https://www.cubeatsystems.com/tinymml/download.html からどうぞ。
ラベル:
A tiny MML parser,
MML,
Raspberry Pi
2015年3月7日土曜日
LPC810でスーパーマリオを演奏するためにMMLの繰り返し処理を追加する 〜設計アプローチ編〜
LPC810でもMMLでスーパーマリオを演奏させたい!
先日A tiny MML parserを使ったスーパーマリオ演奏アプリケーションを公開しました。
折角なので眠っているLPC810への移植を試みたところ、4KBのフラッシュ・ロムに収まらない事がわかりました。実装したスーパーマリオのMMLを眺めると繰り返し処理をべた書きしています。MMLの処理を削る事は有り得ないので、安直に曲データを圧縮する事を考えました。A tiny MML parserに繰り返し処理を追加する事で曲データを圧縮を可能にし、LPC810でもスーパーマリオを演奏出来るようにしようと考えたわけです。
そんなにスーパーマリオに拘っているわけではないのですが、8ビットのマイコンにやらせていた事を32ビットのマイコンに移植して「残念!」みたいな結果になるのが嫌だったわけです。それがたとえフラッシュ・ロムの容量が原因だったとしても!(いや、それは無理・・・なんですけど)
繰り返し処理の仕様を考える
ひとくちにMMLと言っても様々な仕様、様々な実装が存在します。
A tiny MML parserに追加する繰り返し処理の仕様を以下のように定めました。
乱暴なプログラマの場合、いきなり実装に入ってしまうかもしれません。
ちょっと考えて「出来るんじゃね?」と思う訳ですが、この記事では「簡単そうに見える処理が実際もそうなのか?」という視点でも見てみたいと思います。
最初にテストデータを定義する
A tiny MML parserに繰り返し処理を追加するにあたって、最初にテストデータを定義しました。このテストデータを新しいバージョンのA tiny MML parserに与えて、期待する結果が得られれば新たに加えられた処理は正しいという理路整然としたアプローチです。
安直な設計でどうなるのか考えてみる
それではここで、めちゃくちゃ安直に設計無しで実装に取りかかった場合、どのようになるのかシミュレーションしてみましょう。
新人A君の場合
新人A君は、学生時代にマイコンでプログラミングを楽しんでいた意欲的な新人です。
与えられた仕様に対して直感で「これは位置を記憶する変数とループ状態を保持するフラグがあれば解決出来る!」と意気込み、早速プログラミングに取りかかる事にしました。
新人A君は、とりあえず実装しながら動作を確認し、ちょこちょこ修正していくアプローチで、学生時代には沢山の作品(製品ではない事に注意)を作ってきました。今回の新人A君の設計は仕様を満たせるでしょうか?
新人A君は、ざざざーとプログラムを意気揚々と書き上げました。
彼の最初のバージョンは、以下のテストデータを正しく処理しました。
先日A tiny MML parserを使ったスーパーマリオ演奏アプリケーションを公開しました。
折角なので眠っているLPC810への移植を試みたところ、4KBのフラッシュ・ロムに収まらない事がわかりました。実装したスーパーマリオのMMLを眺めると繰り返し処理をべた書きしています。MMLの処理を削る事は有り得ないので、安直に曲データを圧縮する事を考えました。A tiny MML parserに繰り返し処理を追加する事で曲データを圧縮を可能にし、LPC810でもスーパーマリオを演奏出来るようにしようと考えたわけです。
そんなにスーパーマリオに拘っているわけではないのですが、8ビットのマイコンにやらせていた事を32ビットのマイコンに移植して「残念!」みたいな結果になるのが嫌だったわけです。それがたとえフラッシュ・ロムの容量が原因だったとしても!(いや、それは無理・・・なんですけど)
繰り返し処理の仕様を考える
ひとくちにMMLと言っても様々な仕様、様々な実装が存在します。
A tiny MML parserに追加する繰り返し処理の仕様を以下のように定めました。
- []の記号を用いて繰り返し処理の区間を定義するものとする。
- 繰り返し処理の区間はネストさせる事ができるものとする。
- 繰り返し処理の区間は二回繰り返し処理されるものとする。
乱暴なプログラマの場合、いきなり実装に入ってしまうかもしれません。
ちょっと考えて「出来るんじゃね?」と思う訳ですが、この記事では「簡単そうに見える処理が実際もそうなのか?」という視点でも見てみたいと思います。
最初にテストデータを定義する
A tiny MML parserに繰り返し処理を追加するにあたって、最初にテストデータを定義しました。このテストデータを新しいバージョンのA tiny MML parserに与えて、期待する結果が得られれば新たに加えられた処理は正しいという理路整然としたアプローチです。
- [CDE]
- [CDE[FGA]]
- [[CDE]FGA]
- [[]]
- [C[D]E]
- [CD[EF]GA]
- [[[[[[[[[[[[[[[[[[[[
- ]]]]]]]]]]]]]]]]]]]]
- [ ]]
- [[ ]
- ][
安直な設計でどうなるのか考えてみる
それではここで、めちゃくちゃ安直に設計無しで実装に取りかかった場合、どのようになるのかシミュレーションしてみましょう。
新人A君の場合
新人A君は、学生時代にマイコンでプログラミングを楽しんでいた意欲的な新人です。
与えられた仕様に対して直感で「これは位置を記憶する変数とループ状態を保持するフラグがあれば解決出来る!」と意気込み、早速プログラミングに取りかかる事にしました。
新人A君は、とりあえず実装しながら動作を確認し、ちょこちょこ修正していくアプローチで、学生時代には沢山の作品(製品ではない事に注意)を作ってきました。今回の新人A君の設計は仕様を満たせるでしょうか?
新人A君は、ざざざーとプログラムを意気揚々と書き上げました。
彼の最初のバージョンは、以下のテストデータを正しく処理しました。
- [CDE]
そして、以下のテストデータは正しく処理できませんでした。
- [CDE[FGA]]
- [[CDE]FGA]
- [[]]
- [C[D]E]
- [CD[EF]GA]
つまり、殆ど正しく処理できなかったわけです。
新人A君は「ネストなんていらないですよ。」と仕様に文句を付け始めました。
これはいけません。
中堅B君の場合
中堅B君は、現場でXX年の経験を積んだ社員です。
最近は様々な案件の検討にも加わり、かなり自信が付いています。
課題に対する設計アプローチにも幅が広がり、色々なキーワードと共にアイデアが出せる人材です。
中堅B君はスタックを使った設計アイデアの妥当性を確認するために簡単なテストプログラムを作って事前検証する事にしました。
彼の最初のバージョンは、以下のテストデータを正しく処理しました。
- [CDE]
そして、以下のテストデータは正しく処理できませんでした。
- [CDE[FGA]]
- [[CDE]FGA]
- [[]]
- [C[D]E]
- [CD[EF]GA]
つまり、殆ど正しく処理できなかったわけです。
但し、新人A君と異なり設計にスタック構造を用いており、繰り返し開始括弧である[記号が複数やってくるところまでは、設計上でうまく対応できています。
新人A君と中堅B君
新人A君は、そもそも仕様を無視して何でも良いから動かそうとしています。
これでは何をやっているのかわかりません。
中堅B君は、スタック構造へ誘ったのは良かったのです。
が、ちょっと詰めが甘かったようです。
A tiny MML parserにおける設計
A tiny MML parserにおける設計は、以下のように行ないました。
- 簡単なスタックモジュールを設計する
- 代表的なパターンを定義する (これはテストデータの一部でもある)
- 定義したパターンを満たす一般ルールを見つける
- 一般ルールを他のパターンに適用して破綻がないか確認する
始めに簡単なスタックモジュールを設計しました。このモジュールがあまり大きいと、繰り返し処理で削減したはずのメモリを追加したスタックモジュールで食い潰す矛盾が起きてしまいます。スタックモジュールはMMLの操作とは完全に独立させ、単独で検証できるようにしました。
charへのポインタをプッシュ、ポップ出来る設計です。
このスタックモジュールの単独検証終了後、全体操作の設計を開始しました。
以下は、最初に完成した操作に関する設計メモです。
代表的なパターンを定義する事で、その次に続く一般ルールを見つける作業の前提が明らかになります。定義したパターンに対して矛盾無く処理可能な一般ルールを見つけ、それを他のパターンに適用してみます。他のパターンに適用して破綻が有る場合、それは一般ルールではなく、ある前提に依存したルールという事になります。
上記設計メモに書かれたルールは、突然箇条書きにして生まれたわけではありません。特定の代表的なパターンを用意し、二つのスタックが理想的にどのような内部状態であれば処理が出来ていると言えるのか?を考えて、それを一般ルールにしたものです。
例えば、以下のようなパターンを挙げ、Dの後ろにある終了括弧に着目します。
この終了括弧に到達した直後の理想的なスタック状態を列挙したのが以下。
後は上記のスタック状態になるような操作を一般ルールに落とし込み、その操作が派生パターンでも破綻しない事を確認します。上記の例で言うと、一番近い派生パターンから見るとして以下の3パターンでしょう。
で、LPC810には入り切った?
いいえ・・・。
予想以上にROM 4KBが厳しい制約!
予想以上にROM 4KBが厳しい制約!
どのくらい入っていないかと調べてみると、text合計が6,186[Byte]ですから約2KBほど溢れています。曲データが収められているのはmain.oで、この中に制御コードは殆ど含まれません。-Osを付けてコンパイルしたオブジェクトを、arm-none-eabi-size *.oで見た結果が以下。
今回追加したリピート処理によって、スーパーマリオの曲データは3,464[Byte]から2,175[Byte]へ約62.8%圧縮出来ましたが、その差はたったの1,289Byteでした。text合計の話と合わせると、ほぼ曲データ分だけ溢れている事がわかりました。上記を見る限り、MMLモジュールを全て取り除いたとしても入りません。そもそもMMLモジュールを取り除いては意味もありません。
あぁ、こういうアプリケーションは想定していなかったなぁという感じです。例えば、小さいプロセッサからEEPROMなどのデータを見に行くというものを考えた場合、現在のA tiny MML parserは、セットアップの時点でデータが確定している事を前提にしているので、逐次データを読みに行くような制御に対応できません。
なるほど、自分で使ってみるものだなぁと改めて思ってしまいます。
どうしようかな・・・。
ラベル:
A tiny MML parser,
LPC810,
MML
2015年3月1日日曜日
LPC810のState Configurable Timer(SCT)を使ってPWMを構成する
概要
A tiny MML parserのアプリケーションを考える過程で、LPC810が手元で眠っている事に気付きました。8ピンのARM Cortex-M0+でA tiny MML parserなんて素敵です。さっそく調べてみたところ、先日のArduinoと同様に動作させる事を考えた場合には、State Configurable Timer(SCT)を使ってPWMを構成すれば良い事がわかりました。
あちこちで大不評のSCTですが、実は簡単に使えるのではないかと思っていました。
が、実際にやってみてやっぱり大撃沈。レジスタマップと機能説明を読んでも、どんな風に設定すれば自分が欲しい動作になるのか、全然意味がわかりません。
そんな中、LEDをステートマシンで点滅させるエクセサイズを見つけたので、頭からやってみる事にしました。これを応用すれば出力をトグルさせるだけのPWMにも適用できるというわけです。
リソース
エクセサイズのリソース:http://www.nxp-lpc.com/updated_materials/sct/lpc81x/LPC81x_SCT_code_examples.zipエクセサイズのプレゼン:https://onedrive.live.com/view.aspx?resid=7AE40E5A5F1EC907!24470&ithint=file%2cpptx&app=PowerPoint&authkey=!ACDxmgRtdAZZdXE (スライド30ページから)
エクセサイズのリソース
ダウンロードしたエクセサイズのリソースは、説明に従って実際にプロジェクトを仕上げるために、作業開始時点の内容になっています。プロジェクトをセットアップし、スライド30ページを開きます。Red State Machine file generator
Red State Machine file generatorとは、ステート・マシンを構成し、その構成に従ったソースコードを生成するまでを支援するツールです。
プロジェクトエクスプローラで右クリックを押して「New」から「Other...」を選択します。
「Red State」から「Red State Machine file generator」を選択します。
ファイル名を入れます。
「Choose Target」ボタンを押してターゲットを選択します。
上記で準備は完了。
エクセサイズのスタートです。
ステップ1
- U_ALWAYS状態を削除する
- State Tableタブで状態を構成する
U_ALWAYS状態を削除するために、ステート・マシン編集画面にあるU_ALWAYSを右クリックして「Delete」を選択します。
次に状態を管理するState Tableタブに二つの状態を入力します。
このState Tableに状態名や次の状態名を入力すると、画面中央にある状態編集用GUIにも自動的に反映されます。
上記編集直後の画面は以下。
ちょっと配置が汚いので状態を示すボックスをマウスでドラッグして移動させて下さい。
矢印が双方向に見えるかもしれませんが、そんな事はありません。
きちんと二本に見えるように配置して下さい。
ステップ2
次にステート・マシンに対する入力、delayとmatch0を定義します。ステップ3
動作の定義を追加します。EVENT 0
始めにAction Listタブの右上にあるプラスボタンを押して新しい動作を追加し、名前をEVENT 0に変更します。EVENT 0に対する動作を定義します。
追加は、Operationと書かれたテーブルの上にカーソルを移動させて右クリックして行ないます。
Setオペレーションに対して「Output pin 0」を選択します。
Callオペレーションに対して「Limit unified counter」を選択します。
EVENT 1
同様にEVENT 1を定義します。名前をEVENT 1に変更して、以下の動作を追加します。
EVENT 1は、EVENT 0に対して逆の動作Clear Output pin 0を選択します。
EVENT 0の時と同様にCall Limit unified counterも追加します。
ステップ4
動作を定義したら、状態に関連づけます。State Tableタブに戻ってActionカラムをクリックすると、先ほど定義したイベントを選択できます。
出来上がると以下のようになります。
念のため、ここでSignalsタブの内容も確認しておきましょう。
この値は、最初にState TableにSignal名を入れた時点で自動的に追加されています。
マッチを入力として扱うように設定します。
この時点で、画面中央のステートマシン編集画面は以下のようになっています。
ステップ5
Outputs for State Machineタブを開いてプリロード値を設定します。Generate Codeボタンを押してコードを生成します。
ステップ6
ワークスペースを切り替え、SCT初期化コードを有効にする。エクセサイズのコードで予め実装されたコメントアウト済みの箇所のコメントアウトを外します。
次に、sct_user.hを開いて下さい。
吐き出されたコードは「#include "board.h"」なる定義が実装されています。
ここを「#include "LPC8xx.h"」に書き換えます。このエクセサイズに内包されたCMSISの中にこの定義ファイルがあります。
何故このような作業が必要になるかというと、ツールが自動生成したsct_fsm.cからsct_fsm.hが参照されており、このsct_fsmの内部実装でLPC_SCTという定義を使っているからです。
ステップ7
最終調整です。まず、SCTに制御させるピンを決定します。
今回はLPC800 MiniボードのLEDを点滅させる事にしましょう。
このボードは、PIO0_2にLEDが接続されています。
SWMのピン割当レジスタを設定します。
SWM PINASSIGN6レジスタのビット31:24がCTOUT_0の選択レジスタになっています。
PIO0_0が0x00、PIO0_17が0x11と順に値を加える事で出力を選択します。
今回はPIO0_2ですから、0x02を設定すれば良いことになります。
これで準備完了です。
その他の注意点
CMSISのクロック選択
CMSISのクロック選択は、system_LPC8xx.cの実装側に含まれます。動作させるボードに応じて設定する必要があります。
この選択を間違えると「何で動かないんだ?」と混乱します。
対象プロセッサ
対象プロセッサを正しく選択して下さい。この設定は、プロジェクトのプロパティに含まれます。
この選択によって、ツールチェインに与えられるリンカスクリプトが変わります。
実行結果
今回はLPC800 mini boardを使って動作確認しました。1.6秒周期でGPOをトグル動作させており、この動作がCPUの介在無しで行なわれています。この動作周期では、何が嬉しいのか意味不明ですが、後はレジスタを一つ書き換えるだけでPWMの動作周波数が変更されるという仕掛けです。
まとめ
LPC800シリーズに搭載されている新しいSCTは、レジスタマップや機能説明を読んだだけでは使いこなすのが相当難しいものです。というのも、設計の背景や前提にある上位のモデルをそこから読み取る事は困難で、何を前提に設計されたレジスタなのか理解していなければどんな値を設定してよいのかもわかりません。特に複数の状態を、複数の条件に従って遷移する事を考えると、レジスタの相互関係の理解も必要です。
NXPの設計者が何を思ったのかわかりませんが、「こんなツールを用意すれば今までにないマイコンが生まれる」と息巻いたのかもしれません。日本国内で最初に広まった時点で、このRed State Machineよりも先にレジスタの話が先行した結果、「意味不明な機能」というイメージが先行してしまったのかもしれません。(確かにレジスタマップと機能説明だけ読んだら意味不明でした)
LPC800シリーズのSCTは、色んな人を色んな混乱に陥れているという意味で、決して優れた設計とは言えないかもしれませんが、何か新しい領域に挑戦しようという設計者の意気込みを感じました。本当は、ユーザにそんな意気込みを感じさせてはいけない気もしますが、こういう試行が次の新しいモノに繋がって行くのでしょう。
XilinxのVivadoなんかを見ていても思いますが、ツールに任せるべきところは任せ、手で書くところは手で書く、そんな時代に変わりつつあるのかもしれません。
登録:
コメント (Atom)