マイコン工作実験日記

Microcontroller を用いての工作、実験記録

DMA対応

2010-03-28 12:22:04 | MP3プレーヤ
「そのうちにやろう。」と思っていたものの、放置状態だった作業をようやく片づけました。その作業とは、I2SのDMA対応。ATMEL SAM7のとっても簡単に使えるPDCに慣れてしまったわたしには、LPC2388のGPDMAの使い方は恐ろしく複雑に感じられ、ずっと敬遠したままになっていたのです。そのため、I2Sの送受信はずっと割り込みでおこなっていました。

44.1KHzのサンプリングレートでは、毎秒44100回のデータ送受が必要になります。これだけの頻度で割り込みが発生すると72MHzのLPC2388でもかなりの負荷になってしまいます。割り込み負荷を軽減するために、LPC2388では8レベルのFIFOを持っており、割り込みをかけるトリガのレベルを指定できるようになっています。この機能を使うことで割り込み回数を半分程度にできるので実用上は問題無いのですが、それでもDMAを使えばさらに大幅にプロセッサの負荷を軽減できます。他の作業もひと段落ついた状態なので、ようやくとこの作業に着手することにしました。

改めてマニュアルを読んでみると、まぁ概要は理解できたのですが、マニュアルでのI2SのDMAに関する記述はとてもわかりにくく感じました。I2S側ではDMA1とDMA2がありますが、これをGPDMA側ではI2SのChannel 0とChannel 1と呼んでいるようです。用語統一するか、ちゃんと関係を説明して欲しいところです。
実際にコードを書いて、いちおう動くようにはなったのですが、それでもまだちゃんと理解できていないのが、DMACCxControlに設定するDWidth, SWidth, DBsize, SBsizeの値。DWidth, SWidthの方はワード単位でいいでしょうから2を選択。DBsize, SBsizeの選択の仕方がわかりません。I2S側からDMA転送要求を出すFIFOレベルの設定を4にしたので、こちらも転送要求数4に対応する1を選択してあるのですが、これが正しい考え方なのか、適切な値なのかがわかりません。試しにちょっと値を変えてみても違いが区別できませんでした。

DMAで用いるLinked List Itemは次↓のようにしてみました。

USB RAM上に用意したリングバッファに対応するように、LLIも循環リストとしてあります。このままだと、バッファ中のデータを繰り返し送信するだけですが、各LLIの転送が終了すると割り込みをかけることができますので、これを契機にバッファ中のデータを更新してやることで、音楽を連続して再生できるというわけです。つまり、LLIはいったん設定した後は更新しなくてもいいというわけです。

I2SはFMチューナからの受信の際にも入力として利用していますが、そちらについては次回の記事に書くことにします。

照度も追加

2010-03-23 23:48:27 | Weblog
グラフ表示に照度センサS9705のデータも追加してみました。このセンサ、明るさに応じて出力周波数が変化するというもので、真っ暗だとほぼ0Hz、日中だと数百KHz程度の矩形波を出力します。LPC2368のタイマのカウンタは32ビットありますので、カウンタモードを使って1秒間隔で読み出すことで、直接周波数を計れちゃいます。

しかしグラフ表示するとなると、こんなにレンジが広い必要もありません。対数をとった値を使って表示してみました↓。Google chartを使う際にはデータ量を減らすためにsimple encodingというデータ形式を使っているので、どうせ62段階の表示しかできません。S9705の出力は日中でも10の5乗のオーダーですので、対数をとれば5.x です。10倍して、そのままsimple encodingの値として使うこととしました。



青い部分が追加した明るさデータです。夜間は真っ暗な部屋の中なのですが、ある程度の明るさを検出しています。これはMMlpc2368についているPWR LEDとEthernetのLink LEDの光をひろっているのではないかと思われます。ボードが置かれている部屋は東向きの部屋なので、夜明けとともに明るくなりピークは朝8時半頃のようです。このデータを採ったのは21日から22日の午後4時までの24時間です。前日からの春の嵐が治まっていくのにともなって、気圧がグングン上昇してゆく様子が見れました。

照度のグラフ表現では、マーカ機能を使ってデータの位置からX軸までの間に縦線を並べることで、塗りつぶししてみました。こういうパラメータの指定って、使い方を調べたり、実際の動きを確認するために試行錯誤が必要でなかなか面倒なのですが、最近、Live Chart Playgroundという機能が用意されて、簡単にブラウザで動作を確認できるようになったようです。
cht=lc
chs=250x150
chls=3|3
chco=FF0000,00FF00,4F89F9
chm=v,4F89F9,2,::.03,2,-1
chd=s:sirius506,MMlpc2368,SensorLog
chxt=x,y

今回、使用したImage chartのパラメータは、こんな↑感じです。こいつをPlaygroundに コピペするとグラフを見ることができます。

OLIMEXもtwitter始めた

2010-03-21 02:10:12 | OLIMEX
ご時世がら、OLIMEXもtwitter始めたようです。ちょっとはマメにやってくれればいいのですが。とりあえず今回はWebページの更新と前後してtwitter始めたようです。新製品はEnergy MicroのCortex-M3です。

次々と出てくるM3を見るにつけ、買い置きしてあるET-STM32で何か始めねばと思うのですが、いまだ計画できていません。そうこうしているうちに、FuturlecからはLPC1768のボードが出てきました。タッチパネル液晶までついて、$120程度なのでずいぶんと安いですね。製造元のETTを覗いたらマニュアルもダウンロードできました。なにしろタイ語なので文章は読めないのですが、パーツ名や端子名等は英文表記なので、なんとなく何を説明しているのかくらいは察しがつきます。何より、回路図が載っていますしね。

変換基板やPIC学習キットだけでなく、こういうETT製品も秋月で扱うようになりませんかねぇ。

気圧/温度のグラフ表示

2010-03-17 00:10:23 | Weblog
SCP1000-D01で計測した気圧/温度データをグラフ表示してみました。過去1時間と過去24時間の2種類のグラフを表示させており、緑の線が気圧、赤の線が気温を示しています。いまのところデータはRAM内に保持させています。

1時間だと変動量が少なくてつまらないグラフですが、24時間だとそれなりに変化があって見栄えがしますね。気圧って、どの程度変動するものなのかわかっていなかったので、気圧の目盛りがつまってしまいました。変動量に応じて目盛りをふるようにしなければ。



グラフの描画方法について説明しておきましょう。実際のところ、LPC2368はグラフの画像の作成処理は全くおこなっていません。単に、グラフのデータを提供しているだけです。それじゃグラフの画像の作成は誰がやっているかというと、Googleさんにお願いしています。GoogleさんがGoogle Chart Toolsというサービスを提供しており、そのうちのImage Chartsの機能を使っています。Googleさんの働きぶりを↓に示します。



ブラウザからグラフのページ(scp.html)を要求するHTTP GETがあると、LPC2368ではグラフ画像を示すURLを返すのですが、その内容はGoogle Chartへのリクエストとなっています。グラフのデータは、このリクエストURLの一部として記述してやります。この返答を受けたブラウザがGoogleに要求を送ると、Googleが応答としてグラフデータを画像化したPNGファイルを返してくるので、ブラウザがそれを表示することで画面にグラフが表示されることになります。

このようにLPC2368はグラフのデータと、グラフの種類の指定などの属性情報を提供するだけで、画像ファイルの作成はGoogleがやってくれます。面倒な処理が不要なので、LPC2368側のCPUやメモリも消費しないですみます。Googleさんにお願いする仕事すらブラウザ経由でおこなっていますので、LPC2368が直接Googleに到達可能である必要もありません。よって、LPC2368側では名前解決のためのresolverすら用意しなくてもかまいません。とっても、ラクチン。便利な世の中になったもんです。

MMlpc1769

2010-03-14 21:33:39 | Weblog
LPC1769はLPC1768の高速バージョンとして先日発表になったばかりだと思うんですが、もう量産されているんですね。それどころか、PropoxではすでにヘッダーボードMMlpc1769の販売を開始しているようです。

LPC1768/1769ではSRAM 64Kということなので、LPC2368と比べて使いやすいかと思ったのですが、メモリマップを見ると、32KB毎に別の領域に配置されているようです。バスの構造に起因するのかもしれませんが、わたしのようなおうちゃく者にとっては、やはり連続領域の単一空間が何も考えなくていいので、一番便利だな。

SCP1000-D001の動作確認

2010-03-10 23:29:26 | Weblog
秋月の気圧センサ SCP1000-D01は、SparkFunの同等商品と比べて半分程度の価格なので喜んで購入したのはいいのですが、当初はMMlpc2368とつなげてもどういうわけかちゃんと動いてくれませんでした。標準電圧は2.7Vですが、測定誤差を無視してしまえば3.3Vでも動作には問題ないハズなので、3.3Vで使っています。

問題はレジスタの読み書きがちゃんとできていないというもの。読み出したデータがいつも0x00になってしまいます。基本的にSPIでつなげばいいだけのセンサなので、何も難しいことはないと思っていたのですが。。。試しに、プルアップを禁止してみたりもしたのですが、変化無し。安かったとはいえ、それでも1800円もしたものなので、簡単には諦められません。パスコンは、モジュールに載っているのでいいとして、試しに各信号端子にもコンデンサをつけてみたら、SCKに0.01uFをつなげるとレジスタが読めるようになることが判明。理屈はわかりませんが、とにかく1800円が無駄にならなっただけで満足です。0.01uFという値も意図的に選択したわけではありません。たまたま、手持ちの104の在庫がきれており、かわりに余っていたのが103だったというだけの理由だったりします。0.1uFでも動くのかどうかは確認していません。

さてこのセンサ、測定データの準備ができたことをホストに通知するためのDRDYという端子をもっています。こいつをGPIO割り込みで検出することにしました。割り込みがあったら、SPIで気圧と温度のデータを持つレジスタを読み出してやります。



一緒に表示されているのは、照度センサS9705の周波数を示す値です。余っていたのがあったので、つけておきました。こちらはCAP0[0]につないであり、タイマのカウンタモードをつかって周波数を測定しています。

気圧センサを付けた

2010-03-08 23:38:52 | Weblog
MMlpc2368に秋月で売られている気圧センサ SC1000-D01を追加してみました。



このセンサ、データシートを読んでみると気圧だけでなく温度の計測機能ももっており、どちらもSPIで読み出せます。そこで、この両方を記録するデバイスを作ってみることにします。これまで、自宅ではLinuxのサーバでlm-sensorsを使ってマザーボード上にある2つのセンサで計測した温度を、RRDtoolを使って記録していました。このデータはブラウザで次のようなグラフとして見ることができます。



しかし、マザーボード上CPU近傍の温度を計っているため、実際の室温よりもかなり高めの温度になってしまいます。そこで、SCP1000を使って室温と気圧を計測し、同じようにブラウザ経由で見れるようにしてみようという目論見なわけです。

SCP1000を動かすのに苦労したのですが、どうにかちゃんと動き始めたようです。このあたりは、次回の記事に書くことにします。

やっかいな引っ越し -- その2

2010-03-06 12:06:28 | Weblog
Ubuntu 9.10 + Codesourceryで、textサイズがデカくなることがわかったので、MP3プレーヤのコードをちゃんとビルドできるかどうかが心配になりました。なにしろ、450KBになっていますので。実際に引っ越し作業をやってみると。。

やっぱり512KBのフラッシュに収まらなくなってしまいました。
/opt/arm-2009q3/bin/../lib/gcc/arm-none-eabi/4.4.1/../../../../arm-none-eabi/bin/ld:
 nxpmp3.elf section `.rodata' will not fit in region `flash'
/opt/arm-2009q3/bin/../lib/gcc/arm-none-eabi/4.4.1/../../../../arm-none-eabi/bin/ld:
 region `flash' overflowed by 4692 bytes
collect2: ld returned 1 exit status
make: *** [nxpmp3.elf] エラー 1
$

「オイオイ、70KBも激太りかよ。」と悪態をつきたくなります。じつは、textだけでなくUSB RAM空間も足りなくなっていたのですが、そちらは aligned 属性を使ってUSB OHCI用のバッファのメモリ境界を指定した場合の、メモリ確保動作が変わったらしく、複数のバッファを構造体に整理しなおすことで回避しました。textについては、不要なデバック用ルーチンを#ifdef で切り離してサイズ削減を計ったのですが、それでもまだ4KBも足りません。これ以上のダイエットも大変なので方針変更。これまで、-O2でコンパイルしていたところを-Osに変更。ビルドしてみると、効果てきめん!あっさり400KBに!!
$ arm-none-eabi-size nxpmp3.elf 
   text	   data	    bss	    dec	    hex	filename
 402296	   1976	  78184	 482456	  75c98	nxpmp3.elf
$

サイズを優先するとスピードが犠牲になるのですが、MP3やAACの再生処理には充分な余裕があったので、とりあえず動作には問題はないようです。いやはや、新しい環境への引っ越しがこんなに面倒だとは。今後、いよいよ保守的になってしまいそうです。

やっかいな引っ越し

2010-03-03 23:01:01 | Weblog
LPC2368でTINETが動かせたので、このコードを新しいUbuntsu環境に引っ越そうとしたところ、いろいろと問題が発生しました。以下、列挙しておきます。

まず、最初にTOPPERS/JSPのコンフィギュレータであるcfgがコンパイルできません。この問題については、すでにsuikanさんがLPC2388用のTOPPERS配布ファイルで対処されていたので、このコードを使うことで対処しました。どうやら、GCCのバージョンアップにともなって、C++のヘッダファイルが変わっているようです。

次に、TINETのminsvやnservをコンパイルしようとすると、tcp_cre_rep.oを作ろうとするところで、エラーが発生します。Fedora 5では問題ありませんでした。どうやらmakeのバージョンが関係しているようです。
この問題、調べてみると、すでに3年近く前にtoppers-users MLでも報告されていました。これまで古いバージョンのmakeしか使っていなかったので、TINETを使っていても、この問題には遭遇しなかったようです。makeのバージョンを下げるのが有効な対処法であるのはわかるのですが、Makefileの表記を変更することで回避可能なのかどうかはわかりませんでした。makeを入れ代えるのも面倒なので困っていたところ、いったんカーネルのライブラリを作っておき、アプリケーションのリンク時にはKERNEL_LIBを指定してやると、この問題を回避できることが判明。ほんとの原因とその修正方法がわかったわけではありませんが、そのテの探究には興味無し。わたしは自分のプログラムがとにかくmakeできればいいので、この回避方法で良しとします。

ようやく、コンパイルがとおるようになったら、今度はリンク時のエラーです。「.ARM.exidxがなんたら」というようなエラーです。この問題も頻出のようで、すぐに検索に引っ掛かり、リンカスクリプトでセクションを追加してやればいいことがわかりました。この問題は、GCCのバージョンと関連することなのでしょうか? あるいは、以前のGCCはEABIではなかったのですが、今回はEABIを使っていることと関係あるのでしょうか。

そんなこんなで、なんとかminsvをリンクできるところまでこぎつけました。が、しかし、結末でも驚くことに。。



サイズを確認してみたら、以前よりテキストが10KBもデカクなってます。コンパイル時はどちらも-O2で最適化しているんですが。。これって、EABIの影響なんでしょうか?