ラベル LPCXpresso LPC1768 の投稿を表示しています。 すべての投稿を表示
ラベル LPCXpresso LPC1768 の投稿を表示しています。 すべての投稿を表示

2011年2月23日水曜日

3千円で楽しめるARMマイコンとRTOSの世界 (TOPPERS/ASP on LPCXpresso LPC1768)

= 謝辞 =
TOPPERS/ASP for LPCは@suikan_blackfinさんによってポーティングされました。
氏は様々な鋭い洞察力で過去にも沢山の偉業を成し遂げている方です。
ここに過去の沢山の偉業を挙げることは出来ませんが、素晴らしいポーティングに感謝すると共に、厚くお礼を申し上げます。
ありがとうございます。

氏のウェブサイトはhttp://d.hatena.ne.jp/suikan+embedded/にあります。

また、LPCXpressoはNXPセミコンダクターズジャパンさんが積極的に国内市場への展開を行って下さっています。このような安価で優れたツールを手に入れることのできるのは、嬉しい限りです。
NXPセミコンダクターズジャパンさんが運営されている日本語サイト(LPCZone)はhttp://www.nxp-lpc.com/cgi-bin/linkv.htmlにあります。

いずれのサイトも沢山の面白い情報が盛り沢山ですので是非ご覧下さい。

= はじめに =
TOPPERS/ASP for LPCはTOPPERS/ASPをNXPセミコンダクターズのLPCシリーズ上で
動作するようにしたもので@suikan_blackfinさんがメインテナンスされています。
http://sourceforge.jp/projects/toppersasp4lpc/

公開当初から完成度が高く、私も簡単に動作させて楽しむことができました。

TOPPERS/ASPはプロジェクトの性質上、商用のツールを使う前提でソースコードや周辺ファイルが公開されている事が多いのですが、これが障壁となって沢山の人が挫折するような状況でした。


そこで、今回は沢山の方にTOPPERS/ASP for LPCを楽しんで頂くためにLPCXpressoさえあれば楽しめるようにしようと考えました。

従来は評価用ボードに加えて、JTAGデバッガ、環境構築など様々な準備が必要でしたが、TOPPERS/ASP on LPCXpressoを使えばLPCXpresso上で簡単に動作させることができるようになります。

そうです。
LPCXpresso LPC1768(あるいはLPC1769)さえあれば良いのです。
従来のように高価なデバッガやRTOSを購入する必要はありません。

= 対応環境について =
ホストOS環境はLPCXpressoが対応しているLinux環境に今回は限定しました。
TOPPERS/ASPのビルドシステムにはシェルとperlに依存する箇所があります。
Windowsでも様々な外部ツールを使って、依存する環境に近い状況を作り出す事が可能ですが、今回は作業負担を軽減させるために割愛しました。

最近ですとVMware Player上で簡単にLinux環境が構築できますし、WindowsとLinuxの両環境で対応できるように沢山の時間をかけるよりも、早く提供したいという思いが先行した結果でもあります。

参考までに動作を確認した環境を記します。

* Ubuntu 10.10
* LPCXpresso 3.8.2 [Build 129][31/01/2011]
* LPCXpresso LPC1768 REV A

今回公開するプロジェクトの源流になったものは、TOPPERS/ASP for LPCのリリースのうちMisc. / LEDBLINK LPCXPRESSO 1768 1.6.0です。

= オリジナルからの変更点 =
@suikan_blackfinさんがお作りになったオリジナルから行った変更について記します。
変更は
* デバッグをIDE上でできるようにすること。
* 極力TOPPERS/ASPのオリジナルとの差分を小さくすること。
* LPCXpressoのみで実現可能なこと。
を念頭に作業しました。

ソースコードとビルド用ファイルについては以下の変更を行っています。
* 元々あったlpc1768_sram.ldとlpc1768_rom.ldを削除しました。
* LPCXpressoが生成したDebugとReleaseのリンカスクリプトを使用しました。
-> ENTRY(ResetISR)をENTRY(_start)に変更しました。
-> STARTUP(start.o)を追加しました。
-> __bss_start, __bss_endを追加しました。
-> __idata_start, __idata_end, __data_startを追加しました。
-> init_hook関数をPROVIDEで追加しました。
-> .isr_vectorを.vectorに名称を変更しました。
* kernel/target/lpc1768_generic_gcc/Makefile.targetに以下を追加しました。
-> CDEFS=-DDEBUG -D__CODE_RED -D__REDLIB__
* Makefileで生成されるオブジェクトの名称を変更しました。
* Makefileで生成されるオブジェクトの拡張子を変更しました。

LPCXpressoのプロジェクトに対しては以下の変更を行っています。
* Debug ConfigurationsのDebuggerタブでStop on startup at: main_taskに変更しました。
* Debug ConfigurationsのDebuggerタブでVector catch: Trueに変更しました。
* PropertiesのC/C++ BuildでGenerate Makefiles automaticallyのチェックを外しました。これによりLPCXpressoは外部Makefileを参照するようになります。
* PropertiesのC/C++ BuildでBuild directoryからDebugとReleaseを削除しました。
これによりプロジェクトのルートディレクトリを参照する形になりMakefileとの整合性が確保されます。

= 使い方 =
Linux上のLPCXpressoで使用できます。
ダウンロードしたzipファイルは展開せずにLPCXpressoの「Import Example project(s)」で使用します。


Browseボタンを押してダウンロードしたzipファイルを選択します。


Nextボタンを押すとzipファイル内にあるプロジェクトが表示されます。


Finishボタンを押すとワークスペースにプロジェクトがインポートされます。


インポートができたらLPCXpresso上でビルドして下さい。


場合によって、コンフィギュレータのビルドが必要かもしれません。
展開したディレクトリのトップにconfigureがありますので、それを実行して下さい。

ビルドが完了したらDebug 'TOPPERS-ASP_LPCXpresso-LPC1768'でデバッグできます。


Debugを選択してOKボタンを押してください。
以下のようにmain_taskで実行が停止すると思います。


ここまで来れば色んな事がIDE上で楽しめるようになっています。

RunメニューからResumeを選択してみて下さい。
LPCXpresso上のLEDがチカチカ点滅すると思います。

次にRunメニューからSuspendを選択して下さい。
実行が停止し、停止した箇所のソースコードが表示されます。


Disassemblyパネルを見ればC言語のソースとアセンブラの両方を確認しながらデバッグできます。


また、RTOS関連では欠かせないCPUレジスタも以下のように簡単に確認することができます。


上記のようにLPCXpresso購入後、今回のTOPPERS/ASP on LPCXpresso LPC1768のzipファイルをダウンロードするだけで、TOPPERS/ASPのアプリケーション開発を体験することができます。
IDE上でソースコードを見ながらResume, Suspendなど便利な機能が使用できる点も見逃せません。

皆さんご存知のとおりLPCXpressoを購入することで使用できるLPCXpresso IDEはコードサイズ128KBの制限があります。
しかしながら、手軽にRTOSを楽しむことのできる環境を構築できることを考えると、なかなか優れた投資効果が得られると言えるのではないでしょうか。

= ダウンロード =
このファイルを使ったことによる如何なる結果も当方では責任を負えませんので、この点を御了承頂いた上で御利用下さい。
ファイルのダウンロード:こちらをクリック
(今後バージョン管理システムへの移行を考えています。)

= 最後に =
今回の対応は既存のTOPPERS/ASPのビルドの枠組みを超えない形で行ないました。
本来であれば、LPCXpresso上のプリビルドやポストビルドを駆使してカーネルに
対するコンフィギュレーションなどを行うのが筋ですが、先に述べたとおり早めの
公開を目指して割愛したものです。

もし、何かシンプルな方法でコンフィギュレータまでを包括的に処理させることが
できる方法を思いついた場合、是非ご一報頂ければと思います。

= お勧め書籍 =
今回の対応作業で参考にさせて頂いた書籍を紹介します。
* 起動プログラム ブート・ローダ入門
邑中雅樹さんの「TOPPERSで学ぶuITRONのブート・シーケンス」は必携です。

* uITRON準拠 TOPPERSの実践活用
邑中雅樹さんの「TOPPERS/JSPのよりどころとなっているuITRON4.0仕様」にある本文とコラムを楽しく拝見しました。
高田広章さん(というか先生!)の「TOPPERSプロジェクトの概要と展開」にある本文とコラムを楽しく拝見しました。
邑中雅樹さんの「XScaleへのデバイス・ドライバの移植とカーネル移植の完了」にある本文とコラムを楽しく拝見しました。
中村健真さんの「Blackfin DSPへの移植」にある本文とコラムを楽しく拝見しました。

* ARM Cortex-M3 システム開発ガイド
レジスタに関する詳細説明を日本語で楽しむことができます。

2011年2月20日日曜日

LPCXpressoを切り離さないで賢く使う方法

各所で話題の格安Cortex-M3開発用ボードLPCXpressoシリーズですが、著名なブロガーの方々がデバッガ(LPC-LINK)とターゲットをザクザク切り離しているものですから、皆さんも切り離したくなる衝動を抑えられないのではないでしょうか?

私も同じように切り離しては「あれがない」、「これがない」と騒いでいました。
http://shinta-main-jp.blogspot.com/2010/12/lpcxpresso-lpc1768.html
http://shinta-main-jp.blogspot.com/2010/12/lpcxpresso-lpc1768jtagkey2popenocd.html

先日の記事でもUARTを手軽に使いたかったのですが、やはり切り離しただけの基板では「UARTがない!」病になり、ちょっと異なるアプローチが良いのではないだろうか?との考えに至りました。

そもそもニーズとして
* デバッガは自分が使いたいものを使いたい。(でも、たまにLPC-LINK使うかも。)
* UARTをわざわざ接続しなくてもあるじゃん。(LPC-LINKの経路使えばさ・・・。)
* 1つの基板だったものが2つの基板になっちゃってポータビリティ落ちてない?(あ、切り離す人はLPC-LINKは捨てるのか?)
など、切り離したくないシチュエーションも考えられるわけです.

上記のような優柔不断な感じは開発環境を選択する過程では十分に起こり得る話です。
今回ご紹介するアプローチはこういった選択に迷っている段階で役立つものです。

まず、LPCXpressoのデバッガとターゲットの間にある半田をハンダゴテと半田吸い取り線を使って取り除きます。


取り除いたら念の為テスタで絶縁状態になっていることを確認して下さい。


次に2x8のピンヘッダを取り付けます。


LPC-LINKとターゲットを接続するには以下のようにジャンパを接続するだけで済みます。


接続しているジャンパを取り外せばLPC-LINKとターゲットを分離することができます。
例えば、ターゲットに自分の好きなデバッガを接続したり、LPC-LINKから別のターゲットに接続することも可能です。

切断することを考えた場合、この2.54mmの間隔を綺麗に切断するのは意外に手間がかかります。
切断することを考えて設計したのではなく、上記のようにピンヘッダを取り付けるための設計と考えるとなんとなく合点がいきそうだとも思いました。

真相は是非聴いてみたいところですね。

2011年1月29日土曜日

LPCXpresso LPC1768を使ってUARTを制御してみよう!

先日に引き続きLPCXpressoを使ってCortex-M3を体験する話題です。

前回までにCMSISを使った下地を整える作業を行いました。

今回はUARTをレジスタ経由で制御してみます。
資料は前回までと同様にUM10360を使用します。

今回はUART1を制御対象に選びました。
User manualにも基本的な設定がわかりやすく示されています。

  1. 電源:PCONPレジスタ(Table 46)のPCUART1ビットをセットする。
  2. ペリフェラルクロック:PCLKSEL0レジスタ(Table 40)のPCLK_UART1を選択する。
  3. ボーレート:U1LCRレジスタ(Table 298)のDLABを1にセットする。これによりボーレート設定の為のDLLレジスタ(Table 292)とDLMレジスタ(Table 293)へのアクセスが有効になる。また、必要があれば分数分周レジスタ(Table 305)の分数ボーレートを設定する。
  4. UART FIFO:FIFOを有効にするためにU0FCR(Table 297)にあるFIFO enableビット(ビット0)を使用する。
  5. ピン:UARTピンをPINSELレジスタを使って選択し、PINMODEレジスタを使ってピンモードを設定する。
  6. 割り込み:UART割り込みを有効にするためにU1LCR(Table 298)にあるDLABレジスタを0に設定する。これによりU1IER(Table 294)へのアクセスが有効になる。割り込みはNVICが使用する然るべき割り込み設定レジスタを設定することで有効になる。
  7. DMA:UART1転送と受信関数はGPDMAコントローラによって操作することができる。
と手順に沿って説明されています。
次のページにはピンの説明とレジスタの説明が続きます。


こちらはそのレジスタの説明。
詳細は次のページから更に続きます。


もう後は手順に従ってレジスタの値を操作するだけです。
今回は割り込みを使わずに何かを送ってみるという事で作業してみましょう。


それでは先ほどのドキュメントの記述に合わせてmain関数の中に実装を加えます。

試しに「LPC_SC->」と入力してみましょう。
IDEに候補が出てきます。あぁ、なんて贅沢なんだ。
ここで言うSCはSystem Controlの略です。



まずはUART1の電源とクロック制御を有効にします。
(そうです。ペリフェラル毎に電源を落とし、クロックの供給を止めることで省電力化できるようになっています。)


このビットはリセット時に1となっているので、あえて立てる必要は無いと言えば無いのですが、操作対象ペリフェラルがどのレジスタと依存関係があるのか知るのは重要です。


これでペリフェラルの電源が入りました。

次にペリフェラルに供給するクロックを選択します。
UART1に供給されるクロックはPCLKSEL0レジスタで選択します。


このビットは初期値は00です。


この値は以下から選択することができます。


CCLKはClock generation for the LPC17xxのブロックを見ると何の事だかわかります。


ペリフェラルに供給されるクロックはCCLK/4、CCLK、CCLK/2、CCLK/8の4つの中から選択できるようになっています。(但し、CAN1、CAN2、CANはCCLK/8ではなく、CCLK/6になっています。)

これでUART1に対するクロックの供給設定も完了です。


次にUART1のLCR(Line Control Register)を設定します。
このレジスタにはワード長やストップビット、パリティなどの設定が含まれます。


今回は「8ビット長、1ストップビット、パリティなし」で設定します。
また、ボーレートレジスタにアクセスするためにDLABビットも1にします。

では、「ボーレートはどうやって設定するの?」という話になります。
最初の説明で
  • U1LCRレジスタ(Table 298)のDLABを1にセットする。
  • これによりボーレート設定の為のDLLレジスタ(Table 292)とDLMレジスタ(Table 293)へのアクセスが有効になる。
  • また、必要があれば分数分周レジスタ(Table 305)の分数ボーレートを設定する。
とありました。まさにこの作業を行うことになります。

Fractional Divider RegisterはDLMとDLLで設定しきれない値(割り切れない数値)を設定するためのものです。所望のボーレートに対して1.1%以内にするためのものです。


LPC17xxのユーザマニュアル(UM10360)にはこの値を決定するフローが記されています。

  1. PCLKと設定したいボーレートを手元に用意します。
  2. DLestを求めます。 DLest = PCLK / (16 x ボーレート)
  3. 求めたDLestが整数であれば、DIVADDVAL=0, MULVAL=1を設定して完了です。
となります。
で、求めたDLestが整数でない時は補正値を算出することになります。
  1. FRestという変数を持ち出します。最初にこの変数に1.5を代入します。
  2. DLestを求めます。DL=INT(PCLK/(16 x ボーレート x FRest))
  3. FRestを次の式で計算します。 FRest = PCLK/(16 x BR x DLest)
  4. もし1.1<FRest<1.9が成り立てば計算は終了です。(成り立たない場合はFRestの値を1.1から1.9選んで再度ステップ2に戻ります。)
  5. DIVADDVALとMULVALの値をドキュメントからピックアップします。
  6. 後はDLM=DLest[15:8], DLL=DLest[7:0]を代入して完了です。
テーブルは以下のようになっています。

後は上記に従って計算するだけです。
もちろん先ほどのフローをプログラム化しても良いでしょう。
ここでは手計算します。


まず、PCLKの元になるCCLKを調べる必要があります。
今回のプロジェクトではCMSISが使われています。
スタートアップで「CMSISを使うならSystemInit()」という実装があります。
この中でクロック分周期に対する設定が行われています。


CCLKCFGが0x00000003と設定されています。
今回はこの値をこのまま使う事にします。


CPUクロックはpllclkの4分周と設定されていることがわかります。

ここで再度確認しましょう。
CPUクロックは以下のパラメータによって決まります。

図中の右側にあるCCLKCFGは先ほど調べたパラメータです。
pllclkを知るために残りのCLKSRCSELとPLL0CFGとPLL0CONが必要になります。




ここで、PLL0の周波数を決めるパラメータを見てみます。


PLL0CFGを見るとPre-dividerとMultiplierの値がわかります。
  • N=0x0005 + 1
  • M=0x0063 + 1
ですから、Fcco = (2 x M x Fin) / N = (2 x 100 x 12M) / 6 となり、Fcco = 400,000,000[Hz]となります。

「うそ!」と思った方、慌てないでください。
これはあくまでPLLの出力です。
この出力を分周してCPUクロックを作り出します。

LPC1768の最大クロック周波数は100M[Hz]です。
分周するパラメータがCCLKSELです。


CCLKSELの設定状況より、今回は4分周が選択されていることがわかります。
CPUのクロック周波数CCLKは400,000,000 / 4 = 100,000,000[Hz]が選択されることになります。
結果的に最大クロックを設定していたのだと言う事がわかります。

ちなみに、CCLKCFGレジスタの説明の中にもある通り、PLL0を接続している場合には「分周なし」と「2分周」は最大クロック周波数を超えるので有効な選択肢ではありません。

以上でクロックの系統がわかりました。
これを図示したのが以下です。


長くなりましたが、先ほどのFig 51. Algorithm for setting UART dividersに戻りましょう。
フローに従って計算してみます。
  • PCLK = CCLK / 4 = 100 / 4 = 25M[Hz]
  • ボーレートBR = 9600を選択。
  • DLest = PCLK / (16 x BR) = 25M / (16 x 9600) = 162.760417
DLestは整数ではありませんので、補正する必要があります。
  • FRest = 1.5
  • DLest = INT(PCLK / (16 x BR x FRest)) = INT(25M / (16 x 9600 x 1.5)) = 108
  • FRest = PCLK / (16 x BR x DLest) = 25M / (16 x 9600 x 108) = 1.507041
算出したFRestは1.1<FRest<1.9を満たしていますので計算は終了です。
算出したFRestに従ってテーブルから必要な値を拾い出します。

  • DIVADDVAL = 1 (Table 306より)
  • MULVAL = 2 (Table 306より)
上記で補正値の設定は完了です。

最後にピンモードを設定します。

 

これで準備完了です。


それでは、最後にUART1のペリフェラルを設定するテストコードを示します。


DLABビットはDivisor Latch Access Bitと言ってDivisor Latchへのアクセスを行う時にのみ使用します。UART1のレジスタマップでwhen DLAB=0とかwhen DLAB=1とか書いてあるのはこのためです。

実際に実行して波形を見てみます。
永遠に0x55を送信するコードで見てみましょう。
0x55にするのは1ビット毎にトグルする波形が


オシロでUART1のTXをあたります。
今回はパリティビットがありませんので、
  • スタートビット
  • データ(8ビット)
  • ストップビット
の合計10ビットです。


1ビットが104[us]で送信されています。
1,000,000[us]=1[s]で9615.385ビット送信できることがわかります。
設定の狙いの値(9600bps)と実測データからエラーを計算すると約0.16%ですから、ほぼ狙い通りの値に設定できていることがわかります。

今回はUARTを題材にどのようにペリフェラルの設定を行っていくのかを具体的な例で示しました。
ここで挙げたコードが重要なのではなく、1つのペリフェラルを設定するのに、順々に手順をおっていく過程が重要です。

ぶ厚いドキュメントを見るとそれだけで嫌になるかもしれませんが、読むべきところは関係している数ページ分くらいです。
今回はそれを体感頂くことができればと思い、少し長くなりましたが実例を挙げてご紹介しました。

ペリフェラルが思った通りに動作しない時にはレジスタの設定順序などに依存関係がある場合もあります。そのような記述がないかどうか見てみるのも良いでしょう。
また、ドキュメントに書いてある通りに初期化をするのがコツです。
結果的に同じだからと判断して最初から最適化する事を狙うのではなく、試しにドキュメント通りに実装して見る事をお勧めします。

AltStyle によって変換されたページ (->オリジナル) /