2010年12月12日日曜日

LPCXpresso LPC1768にJTAGKey2Pを接続してOpenOCDで楽しむ

先の記事ではLPCXpresso LPC1768のデバッガとターゲットを切り離しました。
ターゲットを独立させたのはJTAGKey2Pを接続して使いたいためです。
ここでは実際にLPCXpresso LPC1768にJTAGKey2Pを接続してみました。
OpenOCDはgitリポジトリから2010/12/12現在のものを取り出して使用しました。
まずはOpenOCDのビルドです。

JTAGKey2Pではlibftd2xxを使用します。
http://www.ftdichip.com/Drivers/D2XX.htm
2010/12/12現在のバージョンはlibftd2xx1.0.0.tar.gzです。
ダウンロードして展開しておきます。

tar xvfz libftd2xx1.0.0.tar.gz

次にOpenOCDのソースコードです。

git clone git://openocd.git.sourceforge.net/gitroot/openocd/openocd
cd openocd
./bootstrap
./configure --enable-ft2232_libftdi --with-ftd2xx-linux-tardir=/path/to/libftd2xx1.0.0
make

ビルドにはautomakeも必要です。
予めビルド環境に入れておいてください。

ビルドできたらmake installして出来上がりです。

ここで試しにsuikanさんがポーティングされたTOPPSER/ASP for LPCのバイナリをOpenOCD経由でフラッシュに書き込んでみましょう。
まずはOpenOCDを起動します。

その前に・・・OpenOCDの設定ファイルを確認します。

openocd.cfgは以下のようにしました。

source [find /usr/local/share/openocd/tcl/interface/jtagkey2p.cfg]
source [find /usr/local/share/openocd/tcl/target/lpc1768.cfg]

jtagkey2p.cfgはgitリポジトリに入っている物と同じです。
lpc1768.cfgについてはSWDを使う設定になっていました。
これについては以下のように修正して使用しました。

# NXP LPC1768 Cortex-M3 with 512kB Flash and 32kB+32kB Local On-Chip SRAM,
# # LPC17xx chips support both JTAG and SWD transports.
# # Adapt based on what transport is active.
# source [find target/swj-dp.tcl]
if { [info exists CHIPNAME] } {
        set  _CHIPNAME $CHIPNAME
} else {
        set  _CHIPNAME lpc1768
}
# After reset the chip is clocked by the ~4MHz internal RC oscillator.
# When board-specific code (reset-init handler or device firmware)
# configures another oscillator and/or PLL0, set CCLK to match; if
# you don't, then flash erase and write operations may misbehave.
# (The ROM code doing those updates cares about core clock speed...)
#
# CCLK is the core clock frequency in KHz
if { [info exists CCLK ] } {
        set _CCLK $CCLK
} else {
        set _CCLK 4000
}
if { [info exists CPUTAPID ] } {
        set _CPUTAPID $CPUTAPID
} else {
        set _CPUTAPID 0x4ba00477
}
#delays on reset lines
adapter_nsrst_delay 200
jtag_ntrst_delay 200
# LPC2000 & LPC1700 -> SRST causes TRST
reset_config srst_pulls_trst
jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID
#swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME cortex_m3 -chain-position $_TARGETNAME
# LPC1768 has 32kB of SRAM In the ARMv7-M "Code" area (at 0x10000000)
# and 32K more on AHB, in the ARMv7-M "SRAM" area, (at 0x2007c000).
$_TARGETNAME configure -work-area-phys 0x10000000 -work-area-size 0x8000
# LPC1768 has 512kB of flash memory, managed by ROM code (including a
# boot loader which verifies the flash exception table's checksum).
# flash bank (name) lpc2000 (base) (size) 0 0 (target#) (variant) (clock) [calc checksum]
set _FLASHNAME $_CHIPNAME.flash
# flash bank $_FLASHNAME lpc2000 0x0 0x80000 0 0 $_TARGETNAME lpc1700 $_CCLK calc_checksum
flash bank $_FLASHNAME lpc2000 0x0 0x80000 0 0 $_TARGETNAME lpc1700 120000
# Run with *real slow* clock by default since the
# boot rom could have been playing with the PLL, so
# we have no idea what clock the target is running at.
jtag_khz 500
$_TARGETNAME configure -event reset-init {
        # Do not remap 0x0000-0x0020 to anything but the flash (i.e. select
        # "User Flash Mode" where interrupt vectors are _not_ remapped,
        # and reside in flash instead).
        #
        # See Table 612. Memory Mapping Control register (MEMMAP - 0x400F C040) bit description
        # Bit Symbol Value Description Reset
        # value
        # 0 MAP Memory map control. 0
        # 0 Boot mode. A portion of the Boot ROM is mapped to address 0.
        # 1 User mode. The on-chip Flash memory is mapped to address 0.
        # 31:1 - Reserved. The value read from a reserved bit is not defined. NA
        #
        # http://ics.nxp.com/support/documents/microcontrollers/?scope=LPC1768&type=user
        mww 0x400FC040 0x01
}
init
reset init

次にOpenOCDを起動します。

shinta@greenpad:~/Projects/ledblink_lpcxpresso_1768$ sudo openocd 
[sudo] password for shinta: 
Open On-Chip Debugger 0.5.0-dev-00651-gc6e0705 (2010-12-11-21:58)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.berlios.de/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
adapter_nsrst_delay: 200
jtag_ntrst_delay: 200
none srst_pulls_trst
500 kHz
Info : max TCK change to: 30000 kHz
Info : clock speed 500 kHz
Info : JTAG tap: lpc1768.cpu tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
Info : lpc1768.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : JTAG tap: lpc1768.cpu tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
Warn : Only resetting the Cortex-M3 core, use a reset-init event handler to reset any peripherals


無事に起動したらtelnet localhost 4444でOpenOCDと接続します。
halt, flash probe 0, flash write_image erase (バイナリファイル名), resetでLPCXpresso LPC1768上にあるLEDがチカチカする事を確認してみましょう。

shinta@greenpad:~$ telnet localhost 4444
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> halt
> flash probe 0
flash 'lpc2000' found at 0x00000000
> flash write_image erase /home/shinta/Projects/ledblink_lpcxpresso_1768/asp.bin
auto erase enabled
wrote 32768 bytes from file /home/shinta/Projects/ledblink_lpcxpresso_1768/asp.bin in 5.705619s (5.609 KiB/s)
> reset
JTAG tap: lpc1768.cpu tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
Only resetting the Cortex-M3 core, use a reset-init event handler to reset any peripherals

OpenOCD側の端末ではクライアントから受けたコマンドの動作が記されていると思います。

target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x1fff0080 msp: 0x10001ffc
Info : accepting 'telnet' connection from 4444
flash 'lpc2000' found at 0x00000000
auto erase enabled
wrote 32768 bytes from file /home/shinta/Projects/ledblink_lpcxpresso_1768/asp.bin in 5.705619s (5.609 KiB/s)
Info : JTAG tap: lpc1768.cpu tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
Warn : Only resetting the Cortex-M3 core, use a reset-init event handler to reset any peripherals

この文書ではLPCXpresso LPC1768をJTAGKey2Pで使用するための狭い範囲のドキュメントとして作成しました。
TOPPERS/ASP for LPCに関するドキュメントはsuikanさんがお書きになった以下のドキュメントも参照してください。

LPCXpresso LPC1768のデバッガとターゲットを切り離して使う

LPCXpressoはそれ自身でデバッガとターゲットの用が足りてしまうので、デバイスを試すという意味で言えば普通それ以上考えません。

でも、「じゃあ製品に組み込む時どうすんの?」とかそういう話になってくると「いやー、LPC-LINK使うかなぁ?(←使わないでしょ。)」とか、「本当に動くのかなー。(←そりゃ動くだろうよ。)」みたいな話になってきます。

そこで、今回はLPCXpressoのターゲットだけを切り離して、JTAGデバッガと接続するお話です。

ユーザとしては「使い慣れた」、あるいは「既に投資してしまった」デバッガや環境を使いたいわけです。
ここでは手始めにデバッガ(LPC-LINK)とターゲットを切り離して使うことを考えます。


まずは回路図を確認します。
LPCXpressoは以下のようなデザインになっています。


LPC-LINK側から+3.3[V]を給電してもらってターゲットが動作するようになっています。
「じゃあ、USBに接続しないで動作させるにはどうするの?」という話ですが、これは図にある通り、「Expansion connector」から外部電源電圧(+5.0[V])をもらい、それがそのままLPC-LINKに入って、先ほどの+3.3[V]を生成するという設計です。

ちょっと考えてみましょう。
LPC-LINKとターゲットを切り離してみてください。
そして、整理してみます。

  • LPC-LINKは+5.0[V]から+3.3[V]を生成する。
  • ターゲットは+3.3[V]を給電されて動作する。
  • ターゲットは+5.0[V]を給電されても、LPC-LINKにそのまま渡すだけ。(要するにターゲットと+5.0[V]は一切関係ない。)
何が言いたいのかというと、「LPC-LINKとターゲットを切り離すと+3.3[V]を何らかの方法で給電しなければ動作しないボードになってしまう。」ということなんです。

また、図面には「Superset of mbed connector」と書かれていますが、これは大嘘。
なぜなら、mbedの40ピン目は+3.3[V]の出力です。


LPCXpressoのターゲットはLPC-LINKを接続している限り「+3.3[V]を出力」しますが、切断した途端にここから+3.3[V]を入れるという前提になっています。これでは当該ピンから+3.3[V]が供給される前提で設計されているベースボードは動作しないことになります。
これは明らかにスーパーセットではありません。
この時点で「superset of mbed pinning」は信用しないことにしました。
この設計はLPC-LINKを使わせる前提なのでしょう。

以下は図面の最後のページのピンアサインです。
初めは「self powered」の意味がわかりませんでしたが、「デバッガ+ターゲット=セルフ」ということみたいです。


そうなると「じゃあどうするの?」という現実的な問題になってきます。

  • LPCXpressoのターゲットの問題は単に+3.3[V]のみ。
  • 手軽に取り出せるのは、例えばUSBの+5.0[V]。
  • パソコンとターゲットとデバッガI/Fだけで開発したい。

私はこうしました。
  • LPCXpressoのターゲット上で+3.3[V]を+5.0[V]から生成するようにしよう。
  • LPCXpressoのデバッガは+3.3[V]の出力にダイオードを突き当ててるから大丈夫。
  • ターゲット用の+5.0[V]はUSBから頂こう。
結果としてできたのがこれ。

LPCXpresso上の配線は以下のようになっています。
EXT_POWXから+5.0[V]をもらい、+3.3[V]に降圧してからVIO_3V3Xに給電です。
コンデンサは後で。

こうすれば(※J6-29にUSBの+5.0[V]を渡す必要もある。)電源面から見ると「mbedとほぼsuperset」と言えます。また、パソコンさえあればデバッグが開始できます。

通常、デバッガはターゲットのI/O電源電圧をリファレンスとしてもらってI/Oを駆動する形をとります。
LPC-LINKは積極的にターゲットに電源を供給する前提で設計されています。
そういう意味で「切り離して使えます」と言われてはいるものの、LPCXpresso LPC1768にかなりフォーカスしたデバッガと考えていた方が良いかもしれません。

この次にJTAGKey2Pによる動作確認です。

2010年12月1日水曜日

Time elapse image using mbed NXP LPC1768



The components
* mbed NXP LPC1768
* microSD card
* LinkSprite JPEG Color Camera LS-Y201

The content is UNIQLOCK.
http://www.uniqlo.jp/uniqlock/

2010年11月26日金曜日

mbedを使ったLinkSprite JPEG Color Camera LS-Y201からの画像取得

LinkSpriteが提供しているJPEG Color Camera LS-Y201なのですが、画像取得ではまった点を記載しておきます。

まず、ドキュメントのハテナ箇所から整理。
参照したドキュメントは「LinkSprite JPEG Color Camera Serial UART Interface」との表題がついたものでJanuary 2010と日付が記載してあります。


まぁ、この手のドキュメントは見れば見るほど?になるものもあるようで。

まず、シャッタを切った後、コンテンツをカメラから読みだすわけですが・・・。
これでプロトコルの説明だというのだから大変です。
「え?どれがマーカー?」、「ちょ、ちょっと。Returnの枠内にCommandの内容書かないでよ。」といちいちドキュメントに突っ込みたくなります。



そして、思わず苦笑いしてしまうのがフローチャート。
もうこの辺りから「あぁ、このドキュメント信用できねー。」となります。


肝心の撮影後のコンテンツ吸い出しのフローに至っては、意味不明な条件分岐記述のおかげで処理がさっぱりわかりません。
一体どこでどういう判定をするんだ・・・。

で、実はこのドキュメントの品質もさることながら・・・、
実はファームウェアバージョンによってプロトコルの仕様が異なるのでは?
というのが本日の本題なのです。

ドキュメントがこんな状態でしたので、参考までにSparkFunが提供しているArduino用コード眺めると読み出しは以下のような記述になっていました。
  • 読み出しリクエストをカメラに送る。(16bytes)
  • カメラからレスポンスヘッダを読み取る。(5bytes)
  • カメラからデータを読み取る。(32bytes)
  • 上記を繰り返す。
上記のコードを試しに動作させてみた所、期待するデータを読みだした後も数バイトカメラから何かを送ってきているようです。この辺りで随分悩みました。
暫くして同じような問題に遭遇している人がいないかどうかを調べてみるとArduinoのフォーラム上で気になる発言を見つけました。
「Then after you've read the returned data (42 bytes with the 5 header and 5 footer bytes)」

なんと、5バイトのフッターがあると書いてあります。
先ほどのドキュメントのフローチャートを無理矢理そのように読もうとしても・・・はっきり言って違う。
こちらからカメラへの5バイト送信はないわけだし。

ということで試しに5バイトのフッターがある仮定でコードを修正してみると・・・。


動きました。要するに
  • 読み出しリクエストをカメラに送る。(16bytes)
  • カメラからデータヘッダを読み取る。(5bytes)
  • カメラからデータを読み取る。(32bytes)
  • カメラからデータフッタを読み取る。(5bytes)
  • 上記を繰り返す。
が正解のようです。

ですが、気になるのはArduino用のコード。
どうも過去にはこのコードで動作確認をしている方もいるようです。

これのヒントは起動時のファームウェアバージョン出力にあるかもしれません。
ちなみに私の所有するカメラは以下のような出力をしてきます。
VC0703 1.00
3o ctrl in
Init end
これはファームウェアのバージョンによって異なるようで、ドキュメントにはInit endを見て処理しろと書いてあります。その部分だけは固定されているのでしょう。

これははっきり言ってハマります。
あのドキュメントとメーカが供給しているArduino用サンプル。
この二つがあれば完全に「何で動かないんだ?」モードに突入です。

今回ひとまず動作確認したmbedライブラリを以下に公開しておきました。
こんな風に色々と癖のあるカメラですが、お値段もお値段ですし用途によってはかなり活用できるかもしれませんね。

あ、ちなみに上記の640x480の画像サイズでボーレート38400の場合、SDカードにテコテコ書きながらですと約25秒・・・。

追記1:@arms22さんから「ボーレートコマンドを送信するとカメラが動作しなくなった。」との報告を受けました。これは先日の私のブログにも書いた現象に相当するものかもしれません。それでもボーレート変更を試したいという方はワーストケース(ROMを書き直さないと復活できない)も考慮して試行したほうが良いかもしれません。

2010年11月23日火曜日

LinkSprite JPEG Color Camera LS-Y201が動作しなくなったアレコレの顛末

先日LinkSprite JPEG Color Camera LS-Y201スイッチサイエンスさんから購入しました。
これはSparkFunでも扱われているカメラで、VGA/QVGA/160x120と画像サイズが選択できるうえにシリアルで制御できるというC328の代替としても嬉しいカメラです。


早速ライブラリの実装にとりかかり入手可能なデータシートを基に全てのインターフェースを実装したところで、全関数テストを実行しました。これがアレコレの始まりでした。

このカメラはリセット時(電源投入時含む)に「自分は何であるのか」をシリアル経路で送信してきます。


なのですが、先ほどの全関数テストを実行した直後からこのメッセージが一切送られて来ません。
最初はオシロを見ていなかったので「ボーレートの設定間違ったかな?」程度に考えていました。

しかし、オシロをあてて愕然。「カメラモジュールから何も送られて来ない・・・。」

これは怪しいと思いサイトを駆け回るとLinkSpriteが何やらArduino用のサンプルを提供しています。
http://www.linksprite.com/download/showdownload.php?lang=en&id=70

ここでは
  • SendResetCmd()
  • SendTakePhotoCmd()
  • SendReadDataCmd()
  • StopTakePhotoCmd()
のみです。


それではということでSparkFunのサイトにあるArduino用サンプルを見てみると
  • int reset(char * response);
  • int getSize(char * response, int * size);
  • int takePicture(char * response);
  • int stopPictures(char * response);
  • int readData(char * response, int address);
のみがJPEGCameraクラスで定義されています。


私はこのカメラモジュールの全機能を掌握すべく、上記の二つの内容に加えて
  • Compression ratio
  • Image size
  • Power saving
  • Change baud rate
も実装し、このカメラモジュールに対して実行しました。
そして、よくよくカメラを見ると「24LC16B」が見えます。


ちょっとガーンとなります。

ここで立ち止まって仮説を立てました。

  • 既存公開ライブラリが特定コマンドのみを使用しているのには理由があるのではないか?
  • 既存公開ライブラリが使用していないコマンドの組み合わせ動作に不具合があるのではないか?
上記のように考えると、

  • 全関数テストの過程でモジュールが持つ潜在的な不具合で24LC16Bの内容が不適切な状態になった。
  • 24LC16Bの内容が不適切な状態になった結果、モジュールが動作しない状況に陥った。
というシナリオが出てきます。

これは困ったとTwitterで呟いたところスイッチサイエンスさんから「人柱にしてしまうのは申し訳ない。交換します。」と本当にありがたいお言葉を頂きました。

そこで、今回の調査になったわけです。

まず、「どうやったらこの状態から現象を回避できるか?」を考えてみました。

24LC16Bの内容に依存してモジュールが初期化に失敗した結果、メッセージを送ってこないのであれば、コントローラ内部の初期値に期待する作戦が取れそうです。
そこで、以下のようにSDAをグランドに落とすためのリードをハンダ付けして試してみることにしました。


結果から言うとこの作戦は起動させるという意味で成功。
確かに初期化のメッセージを送ってきます。
では、ということでピクチャを取るコマンドを投げるとこれは失敗。
様々なコマンドの動作で24LC16Bの内容を参照しているようです。

こうなったら気持ち悪いので正しく動くカメラモジュールのROMに戻したくなります。
そこでスイッチサイエンスさんから頂いた代替カメラモジュールのROMを吸い出すことにしました。

まずはメインのプロセッサの足にハンダ屑が飛ばないようにマスキングし、24LC16Bの足にハンダを盛ります。取り外し用の特殊ハンダを使いたいところですが、意外に高価です。8ピン程度であれば普通のハンダでやっても大丈夫。


基板とパッケージの小さな隙間に優しくドライバを入れながらはんだごてをピンにあてていきます。
この時、間違ってもドライバをグイグイしてはいけません。ランドが基板からはがれます。


少しずつはんだごてをあてるとパッケージが徐々に基板から離れます。
これを片側4ピンずつ繰り返していくことで8ピンSOPを基板から取り外します。


取り外したらこんな感じ。
失敗してパッケージが壊れても大丈夫。
Digikeyで購入できます。http://jp.digikey.com/1/1/46508-ic-eeprom-16kbit-400khz-8soic-24lc16b-sn.html


取り外したらROMの内容を吸い出します。


で、吸い出したROMの内容がこれ。
0x0000: AA 55 01 00 04 E1 00 01
0x0008: 2A F2 02 98 00 0E 00 0D
0x0010: 02 02 00 00 00 01 1E 08
0x0018: 01 11 35 02 00 02 21 13
0x0020: 83 33 B8 0A 10 31 05 08
0x0028: 00 00 00 64 00 03 E8 07
0x0030: 00 00 80 00 35 00 5F 00
0x0038: 00 00 9F 02 E3 02 FA 00
0x0040: 00 03 B6 03 D2 04 78 04
0x0048: 84 00 00 00 00 04 A9 04
0x0050: B1 04 BF 00 00 04 A4 00
0x0058: 00 00 00 00 00 00 00 00
0x0060: BA 01 02 01 01 00 44 80
0x0068: 04 05 20 00 00 01 01 08
0x0070: 01 90 01 01 00 00 00 00
0x0078: 82 43 01 00 20 00 00 00
0x0080: 00 00 00 50 20 00 00 00
0x0088: 00 00 00 00 00 00 20 00
0x0090: 00 00 00 00 00 10 00 00
0x0098: 00 00 00 00 00 00 00 02
0x00A0: 41 0F 70 11 00 04 00 60
0x00A8: 01 0A 20 1C 10 0A 0A 08
0x00B0: 06 06 04 04 40 80 00 C0
0x00B8: 00 00 60 00 60 78 00 00
0x00C0: 00 97 00 00 00 97 02 02
0x00C8: 0A 05 00 00 00 97 00 7E
0x00D0: 3A FC 3B 10 00 00 03 64
0x00D8: 01 B4 0C 37 00 64 01 00
0x00E0: 06 00 06 00 06 00 00 00
0x00E8: 1C 00 00 00 1C 00 00 00
0x00F0: 1C 00 00 00 82 00 00 00
0x00F8: 82 00 00 00 82 0C 77 0C
0x0100: 00 00 00 20 00 00 00 20
0x0108: 00 00 00 20 00 00 00 20
0x0110: 00 00 00 20 00 00 00 20
0x0118: 00 00 00 20 00 00 00 20
0x0120: 00 00 00 20 00 00 00 24
0x0128: 00 00 00 28 00 00 00 2C
0x0130: 00 00 00 30 00 00 00 34
0x0138: 00 00 00 38 00 00 00 3C
0x0140: 00 00 00 A0 00 00 00 A2
0x0148: 00 00 00 A4 00 00 00 A6
0x0150: 00 00 00 A8 00 00 00 AA
0x0158: 00 00 00 AC 00 00 00 AE
0x0160: 00 00 00 B0 00 00 00 B2
0x0168: 00 00 00 B4 00 00 00 B6
0x0170: 00 00 00 B8 00 00 00 BA
0x0178: 00 00 00 BC 00 00 00 BE
0x0180: 00 00 00 C0 00 00 00 C2
0x0188: 00 00 00 C4 00 00 00 C6
0x0190: 00 00 00 C8 00 00 00 CA
0x0198: 00 00 00 CC 00 00 00 CE
0x01A0: 00 00 00 D0 00 00 00 D2
0x01A8: 00 00 00 D4 00 00 00 D6
0x01B0: 00 00 00 D8 00 00 00 DA
0x01B8: 00 00 00 DC 00 00 00 DE
0x01C0: 00 00 00 E0 00 00 00 E2
0x01C8: 00 00 00 E4 00 00 00 E6
0x01D0: 00 00 00 E8 00 00 00 EA
0x01D8: 00 00 00 EC 00 00 00 EE
0x01E0: 00 00 00 F0 00 00 00 F2
0x01E8: 00 00 00 F4 00 00 00 F6
0x01F0: 00 00 00 F8 00 00 00 FA
0x01F8: 00 00 00 FC 00 00 00 FE
0x0200: 00 00 01 C0 00 00 01 C1
0x0208: 00 00 01 C2 00 00 01 C3
0x0210: 00 00 01 C4 00 00 01 C5
0x0218: 00 00 01 C6 00 00 01 C7
0x0220: 00 00 01 C8 00 00 01 C9
0x0228: 00 00 01 CA 00 00 01 CB
0x0230: 00 00 01 CC 00 00 01 CD
0x0238: 00 00 01 CE 00 00 01 CF
0x0240: 00 00 01 D0 00 00 01 D1
0x0248: 00 00 01 D2 00 00 01 D3
0x0250: 00 00 01 D4 00 00 01 D5
0x0258: 00 00 01 D6 00 00 01 D7
0x0260: 00 00 01 D8 00 00 01 D9
0x0268: 00 00 01 DA 00 00 01 DB
0x0270: 00 00 01 DC 00 00 01 DD
0x0278: 00 00 01 DE 00 00 01 DF
0x0280: 00 00 01 E0 00 00 01 E1
0x0288: 00 00 01 E2 00 00 01 E3
0x0290: 00 00 01 E4 00 00 01 E5
0x0298: 00 00 01 E6 00 00 01 E7
0x02A0: 00 00 01 E8 00 00 01 E9
0x02A8: 00 00 01 EA 00 00 01 EB
0x02B0: 00 00 01 EC 00 00 01 ED
0x02B8: 00 00 01 EE 00 00 01 EF
0x02C0: 00 00 01 F0 00 00 01 F1
0x02C8: 00 00 01 F2 00 00 01 F3
0x02D0: 00 00 01 F4 00 00 01 F5
0x02D8: 00 00 01 F6 00 00 01 F7
0x02E0: 00 35 01 00 15 01 01 00
0x02E8: 00 00 0F 01 04 02 0C E0
0x02F0: 05 0D 03 7C 30 C0 09 31
0x02F8: 0C 01 00 BC 01 01 00 06
0x0300: 00 B4 14 0A 04 14 0A 05
0x0308: 08 03 0A 08 04 05 08 42
0x0310: E0 08 43 01 01 01 31 00
0x0318: 00 01 01 06 00 82 01 01
0x0320: 35 00 30 18 40 1B 18 42
0x0328: DE 18 43 00 18 44 1D 18
0x0330: 46 DD 18 47 00 18 48 1B
0x0338: 18 4A E2 18 4B 00 18 4C
0x0340: 1D 18 4E 1B 18 50 1C 18
0x0348: 5A 14 18 5C 13 18 5E 14
0x0350: 19 0F 0C 19 94 50 19 95
0x0358: 05 19 97 13 19 99 FF 19
0x0360: 9A 03 19 9B 05 19 9C 0A
0x0368: 19 9D 0E 19 80 08 19 82
0x0370: 12 19 84 38 19 85 40 19
0x0378: 8D FF 19 8E 23 19 89 FF
0x0380: 19 8A 24 19 8F 2E 1A 15
0x0388: 48 1B 19 20 1B 1A 80 1B
0x0390: 1B 20 1B 1C 80 1B 22 06
0x0398: 1B 23 0A 1B 28 31 1B 29
0x03A0: 13 1B 2A 42 1B 2B 24 1B
0x03A8: 2C 42 1B 2D 24 1B 2E 31
0x03B0: 1B 2F 13 08 01 41 00 F5
0x03B8: 00 02 00 00 04 03 02 08
0x03C0: 07 05 06 09 00 00 00 00
0x03C8: 00 00 20 18 10 10 00 40
0x03D0: 00 30 00 A4 03 40 00 03
0x03D8: 30 00 03 24 FF FF FF FF
0x03E0: 02 02 01 00 00 00 A0 00
0x03E8: 40 01 E0 01 7F 02 00 00
0x03F0: 78 00 F0 00 68 01 DF 01
0x03F8: 00 04 00 04 00 04 00 04
0x0400: 00 04 00 04 00 04 00 04
0x0408: 00 04 00 04 00 04 00 04
0x0410: 00 04 00 04 00 04 00 04
0x0418: 00 1E 00 1E 00 1E 00 1E
0x0420: 00 1E 00 1E 00 1E 00 1E
0x0428: 00 1E 00 1E 00 1E 00 1E
0x0430: 00 1E 00 1E 00 1E 00 1E
0x0438: 00 06 00 06 00 06 00 06
0x0440: 00 06 00 06 00 06 00 06
0x0448: 00 06 00 06 00 06 00 06
0x0450: 00 06 00 06 00 06 00 06
0x0458: 00 2D 00 2D 00 2D 00 2D
0x0460: 00 2D 00 2D 00 2D 00 2D
0x0468: 00 2D 00 2D 00 2D 00 2D
0x0470: 00 2D 00 2D 00 2D 00 2D
0x0478: 50 F8 F8 F8 50 F8 F8 F8
0x0480: 50 00 00 00 10 20 30 40
0x0488: 50 60 70 80 90 A0 B0 C0
0x0490: D0 E0 F0 00 28 46 60 71
0x0498: 81 90 9D AA B6 C2 CD D8
0x04A0: E3 ED F6 FF 00 80 80 00
0x04A8: 40 11 08 08 06 17 08 08
0x04B0: 08 10 10 10 10 10 10 10
0x04B8: 10 10 10 10 10 10 10 81
0x04C0: 00 81 81 00 08 10 18 05
0x04C8: 0F 7F 7F 08 00 20 33 33
0x04D0: 33 33 03 1E 7B 09 01 58
0x04D8: 60 00 00 03 FF 10 10 18
0x04E0: 18 0F FF FF FF FF FF FF
0x04E8: FF FF FF FF FF FF FF FF
0x04F0: FF FF FF FF FF FF FF FF
0x04F8: FF FF FF FF FF FF FF FF
0x0500: FF FF FF FF FF FF FF FF
0x0508: FF FF FF FF FF FF FF FF
0x0510: FF FF FF FF FF FF FF FF
0x0518: FF FF FF FF FF FF FF FF
0x0520: FF FF FF FF FF FF FF FF
0x0528: FF FF FF FF FF FF FF FF
0x0530: FF FF FF FF FF FF FF FF
0x0538: FF FF FF FF FF FF FF FF
0x0540: FF FF FF FF FF FF FF FF
0x0548: FF FF FF FF FF FF FF FF
0x0550: FF FF FF FF FF FF FF FF
0x0558: FF FF FF FF FF FF FF FF
0x0560: FF FF FF FF FF FF FF FF
0x0568: FF FF FF FF FF FF FF FF
0x0570: FF FF FF FF FF FF FF FF
0x0578: FF FF FF FF FF FF FF FF
0x0580: FF FF FF FF FF FF FF FF
0x0588: FF FF FF FF FF FF FF FF
0x0590: FF FF FF FF FF FF FF FF
0x0598: FF FF FF FF FF FF FF FF
0x05A0: FF FF FF FF FF FF FF FF
0x05A8: FF FF FF FF FF FF FF FF
0x05B0: FF FF FF FF FF FF FF FF
0x05B8: FF FF FF FF FF FF FF FF
0x05C0: FF FF FF FF FF FF FF FF
0x05C8: FF FF FF FF FF FF FF FF
0x05D0: FF FF FF FF FF FF FF FF
0x05D8: FF FF FF FF FF FF FF FF
0x05E0: FF FF FF FF FF FF FF FF
0x05E8: FF FF FF FF FF FF FF FF
0x05F0: FF FF FF FF FF FF FF FF
0x05F8: FF FF FF FF FF FF FF FF
0x0600: FF FF FF FF FF FF FF FF
0x0608: FF FF FF FF FF FF FF FF
0x0610: FF FF FF FF FF FF FF FF
0x0618: FF FF FF FF FF FF FF FF
0x0620: FF FF FF FF FF FF FF FF
0x0628: FF FF FF FF FF FF FF FF
0x0630: FF FF FF FF FF FF FF FF
0x0638: FF FF FF FF FF FF FF FF
0x0640: FF FF FF FF FF FF FF FF
0x0648: FF FF FF FF FF FF FF FF
0x0650: FF FF FF FF FF FF FF FF
0x0658: FF FF FF FF FF FF FF FF
0x0660: FF FF FF FF FF FF FF FF
0x0668: FF FF FF FF FF FF FF FF
0x0670: FF FF FF FF FF FF FF FF
0x0678: FF FF FF FF FF FF FF FF
0x0680: FF FF FF FF FF FF FF FF
0x0688: FF FF FF FF FF FF FF FF
0x0690: FF FF FF FF FF FF FF FF
0x0698: FF FF FF FF FF FF FF FF
0x06A0: FF FF FF FF FF FF FF FF
0x06A8: FF FF FF FF FF FF FF FF
0x06B0: FF FF FF FF FF FF FF FF
0x06B8: FF FF FF FF FF FF FF FF
0x06C0: FF FF FF FF FF FF FF FF
0x06C8: FF FF FF FF FF FF FF FF
0x06D0: FF FF FF FF FF FF FF FF
0x06D8: FF FF FF FF FF FF FF FF
0x06E0: FF FF FF FF FF FF FF FF
0x06E8: FF FF FF FF FF FF FF FF
0x06F0: FF FF FF FF FF FF FF FF
0x06F8: FF FF FF FF FF FF FF FF
0x0700: FF FF FF FF FF FF FF FF
0x0708: FF FF FF FF FF FF FF FF
0x0710: FF FF FF FF FF FF FF FF
0x0718: FF FF FF FF FF FF FF FF
0x0720: FF FF FF FF FF FF FF FF
0x0728: FF FF FF FF FF FF FF FF
0x0730: FF FF FF FF FF FF FF FF
0x0738: FF FF FF FF FF FF FF FF
0x0740: FF FF FF FF FF FF FF FF
0x0748: FF FF FF FF FF FF FF FF
0x0750: FF FF FF FF FF FF FF FF
0x0758: FF FF FF FF FF FF FF FF
0x0760: FF FF FF FF FF FF FF FF
0x0768: FF FF FF FF FF FF FF FF
0x0770: FF FF FF FF FF FF FF FF
0x0778: FF FF FF FF FF FF FF FF
0x0780: FF FF FF FF FF FF FF FF
0x0788: FF FF FF FF FF FF FF FF
0x0790: FF FF FF FF FF FF FF FF
0x0798: FF FF FF FF FF FF FF FF
0x07A0: FF FF FF FF FF FF FF FF
0x07A8: FF FF FF FF FF FF FF FF
0x07B0: FF FF FF FF FF FF FF FF
0x07B8: FF FF FF FF FF FF FF FF
0x07C0: FF FF FF FF FF FF FF FF
0x07C8: FF FF FF FF FF FF FF FF
0x07D0: FF FF FF FF FF FF FF FF
0x07D8: FF FF FF FF FF FF FF FF
0x07E0: FF FF FF FF FF FF FF FF
0x07E8: FF FF FF FF FF FF FF FF
0x07F0: FF FF FF FF FF FF FF FF
0x07F8: FF FF FF FF FF FF FF FF
よくよく見てみると途中にルックアップテーブルのようなものも見えます。
動作しなくなったモジュールのROMの内容も見てみました。(以下先頭を抜粋。)
0x0000: FF FE FE FE FA FE FE FE
0x0008: 2A F2 02 98 00 0E 00 0D
0x0010: 02 02 00 00 00 01 1E 08
0x0018: 01 0B 35 02 00 02 21 13
0x0020: 83 33 B8 0A 10 31 05 08
0x0028: 00 00 00 64 00 03 E8 07
0x0030: 00 00 80 00 35 00 5F 00
0x0038: 00 00 9F 02 E3 02 FA 00
0x0040: 00 03 B6 03 D2 04 78 04
0x0048: 84 00 00 00 00 04 A9 04
0x0050: B1 04 BF 00 00 04 A4 00
0x0058: 00 00 00 00 00 00 00 00
0x0060: BA 01 02 01 01 00 44 80
0x0068: 04 05 20 00 00 01 01 08
0x0070: 01 90 01 01 00 00 00 00
0x0078: 82 43 01 00 20 00 00 00
0x0080: 00 00 00 50 20 00 00 00
なんと、先頭のデータが明らかに異なります。
「そりゃ設定を更新したからでしょ?」という突っ込みもあろうとおもいますが、先頭の2バイト「0xAAと0x55」は意味がありそうですよね?(0b10101010と0b01010101) -> ちょいこじつけ。

それではということで、吸い出したROMの内容を動作しなくなったモジュールに搭載されていたROMに書き戻して、再度動作させてみました。


結果は
  • Reset:OK
  • Take picture:OK
  • ReadJpegFileSize:OK
とOKずくし。

「絵を見せてくれ!」と言われそうですが、そこのデバッグをしようとしたところでモジュールのバグにハマったので、その辺の実装と動作確認はこれからです。

現状わかっている範囲を日本語にするならば
  • 既存公開ライブラリが実装していないコマンドの単独ないし組み合わせ動作に不具合のある可能性がある。
でしょうか?

現象を再現して更に追い込む事も必要なのですが、SOPを剥がしたり付けたりで大変そうです。
ひとまずはこの辺りで止めておいて、機能の実装と検証を行いたいところです。

本稿では
  • 新品のモジュールのROM内容を掲載し、1台のみの所有でも復活できるような道を作りました。

今後の課題として
  • 仮説に対する検証
が挙げられます。

最後になりましたが、心温まる対応をして頂いたスイッチサイエンスさんに感謝いたします。
ありがとうございました。


2010年11月9日火曜日

StarBoard Orange - Eco Deco Paper Box

StarBoard Orangeで開発がひと段落すると、ついつい箱に入れて使いたくなります。
この時、専用のケースがあれば嬉しいのですが、現状ではそのようなものはありません。
実際にぴったり入るケースを探してみると意外になかったりします。

今回Craft ROBOなるものを購入しましたので、その試用を兼ねてStarBoard Orange専用のペーパーボックスを作ってみました。名付けてStarBoard Orange - Eco Deco Paper Boxです。

まずは各所のサイズをおおまかに測ります。



で、ROBO Masterに図面を入力してCraft ROBOにカッティングさせます。

video

仕上がりは以下のような感じ。


この表面にアクリル板を貼ると、以下のようになかなかの仕上がりになります。



2010年11月5日金曜日

Practical library for mbed : Firmware updater


Languages



Overview
Network features on mbed is great. So there are so many mbed application in our world.
Sometime I need to update these mbed application firmware.
So I implemented a firmware update class.
You can update mbed if you put on a new firmware with version text file automatically.
It's really easy to update mbed in the distance.

The library compare versions between binary on a server and local file system on mbed.

How to use it?

mbed side

  1. Download your firmware. (e.g.: firm.bin) http://mbed.org/media/uploads/shintamainjp/firm.bin
  2. Make the version text file for the firmware. (e.g.: firm.txt) http://mbed.org/media/uploads/shintamainjp/firm.txt
10
You can check the sequences if logging option enabled.

Server side

  1. Put on a new firmware on HTTP server. (e.g.: firm.bin) http://mbed.org/media/uploads/shintamainjp/firm.bin
  2. Put on the version text file for the firmware (e.g.: firm.txt) http://mbed.org/media/uploads/shintamainjp/firm.txt
25

Setup the library

FirmwareUpdater fwup("http://mbed.org/media/uploads/shintamainjp/", "firm", true); 

Description

exist()
  • Compare version files between on a server and on a mbed.
  • Return 0 if a version on a server higher than a version on a mbed.
execute()
  • Download a new firmware binary file to a temporary file.
  • Download a new firmware version text file to a temporary file.
  • Copy these new files to .bin and .txt.
reset()
  • Reset mbed.

The interfaces

The interfaces are very simple.

The test program

#include "mbed.h"
#include "FirmwareUpdater.h"
#include "EthernetNetIf.h"

EthernetNetIf eth;
FirmwareUpdater fwup("http://mbed.org/media/uploads/shintamainjp/", "firm", true); 

// There are 2 files for the firmware.
//  1. firm.txt : firmware version file.
//  2. firm.bin : firmware binary file.

int main() {
    eth.setup();
    if (fwup.exist() == 0) {
        printf("Found a new firmware.\n");
        if (fwup.execute() == 0) {
            printf("Update succeed.\n");
            printf("Resetting this system...\n\n\n\n\n");
            fwup.reset();
        } else {
            printf("Update failed!\n");
        }
    }
 
    // Your application ...
}

The library

    2010年11月2日火曜日

    StarBoard Orangeが何を提供しているのかを考えてみた

    MTM06の展示に向けて、私がmbedと一緒に使用しているベースボードStarBoard Orangeが一体何を提供しているのかを考えてみました。


    結論から先に言うと、StarBoard Orangeはある種のHUBの役割を果たしているのではないだろうかということ。

    例えばこのボード、試作の段階から多数の人を巻き込んだ形で設計が行われています。
    この中で様々な立場の方が意見を出し合い、より良い結果を生む要因となった事は間違いありません。

    上記の図で言うと、例えば以下のボードは単なる枝葉です。
    • Expansion Board
    • R/C Servo I/F Board
    • LCD I/F Universal Board
    大きな幹をmbedとStarBoard Orangeが構成し、それらがHUBとなって各々のやりたい事へと拡がっていく。
    そういう意味で枝葉となるソリューションはエンドポイントになってしまうのですが、そこにも興味のある人たちが集まる。
    こうやって徐々に大きな盛り上がりを見せていっているんじゃないかと、そんな風に考えた午前6時。


    StarBoard OrangeがHUBとなって、人と情報のネットワーキングを構成する。
    そんなのなかなか素敵だなぁと思いました。

    2010年10月31日日曜日

    StarBoard Orange専用の前面アクリルボードを入手しました

    StarBoard Orange専用の前面アクリルボードの試作版をStarBoard Orangeの設計者の方(@logic_starさん)から頂きました。ありがとうございます。


    写真でご覧頂くとわかるとおり、StarBoard Orangeの外形サイズに合わせてデザインされており、StarBoard Orangeの可搬性を損なうことなくmbedとStarBoard Orangeを守ることのできる仕上がりとなっています。

    現状の前面アクリルボードはLCD実装の都合上、左上の個所のみネジ止めできません。

    これについては以下のように対応しました。
    1. 前面アクリルボードとLCD基板間は7mm。この間をネジを突き当てる事で押し込み方向負荷に耐えられるようにする。
    2. 今回の対応では引っ張り方向負荷に対しての対応は考えない。

    これでも十分便利です。
    まず、「埃をかぶらない」のが嬉しいですね。


    え?
    「リセットスイッチが押せない?」
    これについては幾つかの方法が考えられます。
    1. 緊急時のリセットを考慮しないのであれば、ソフトウェアによるリセットで対応。
    2. 前面アクリルパネルに小さな穴を開けて対応。
    3. 前面アクリルパネルを用いつつ定規で対応。
    などなど。


    少し無理矢理ですが、「前面アクリルパネルを付ける時は運用時」と割り切れば良いのではないでしょうか?

    ちなみに、この前面アクリルボードはMTM06での販売も検討中とのことです。
    StarBoard Orangeを立てて置いて稼働させたりできるので、見せ方の可能性もグッと拡がります。


    LPCXpresso LPC1768の水晶処理方法

    LPCXpresso LPC1768の水晶がひどい実装になっているのは有名な話です。




    これをうまく処理する方法を考えてみました。

    用意するものは2つ。
    • スコッチ両面ゲルシート(ポスターなんかを貼るのに使うやつ)
    • 木工ボンド(家に無かったので無理矢理)

    まずはスコッチ両面ゲルシートを水晶の高さ分に切って、倒す側に貼り付けます。
    スコッチ両面ゲルシートはチップコンデンサと水晶が直接接触しないようにする役目を果たします。

    次に水晶をスコッチ両面ゲルシートにあたるまでゆっくり倒します。
    左側に倒さないのには理由があって、左側ですとC43にあたって最後まで寝かせる事ができません。


    最後に、写真にあるように木工ボンド(じゃないほうが良いけど・・・)で固めればできあがりです。

    LPCXpresso LPC1768でTOPPERS/ASPの動作を確認する

    
    2011年2月23日の記事、3千円で楽しめるARMマイコンとRTOSの世界 (TOPPERS/ASP on LPCXpresso LPC1768)でLPCXpressoさえあればTOPPERS/ASPを楽しめるようにしました。
    
    


    TOPPERS/ASP for LPC(http://sourceforge.jp/projects/toppersasp4lpc/)においてsuikanさんがTOPPERS/ASPをLPCプロセッサで動作させるためのポーティングをされています。


    suikanさんがお使いのボードは株式会社日新テクニカで販売されているNXP ARM/Cortex-M3 LPC1768開発キット(http://www.nissin-tech.com/2010/01/nxp-armcortex-m3-lpc1768.html)です。






    Embedded Artistsで公開されているFreeRTOSポート(http://www.embeddedartists.com/products/lpcxpresso/lpc1768_xpr.php?tab=res)ではP0[22]のLED(ボード上ではLED2とシルクが打ってある)が点滅するデモになっています。内部では二つのタスクが起動し、一方が送信し一方が受信、そして受信側がLEDをトグルするデモです。




    これを踏まえて先のTOPPERS/ASPでもLPCXpresso LPC1768でLEDがチカチカするようにしてみました。Subversionのリポジトリがrevision 1となっているのは私のローカルリポジトリのバージョンです。http://svn.sourceforge.jp/svnroot/toppersasp4lpcからダウンロードしてきたバージョンはrevision 206です。
    1. asp/cfgでconfigureしてmakeする。
    2. sample1プロジェクト用のディレクトリを作成する。
    3. asp/configure -T lpc1768_generic_gccを実行し、サンプルプログラムを生成する。
    4. make depend; makeする。
    変更点を以下に示します。


    Index: sample1/sample1.c
    ===================================================================
    --- sample1/sample1.c (revision 1)
    +++ sample1/sample1.c (working copy)
    @@ -108,6 +108,7 @@
     #include "syssvc/syslog.h"
     #include "kernel_cfg.h"
     #include "sample1.h"
    +#include "util.h"


     /*
      *  サービスコールのエラーのログ出力
    @@ -146,6 +147,10 @@


      SVC_PERROR(ena_tex());
      while (1) {
    +                if (tskno == 1) {
    +                    toggle_led();
    +                }
    +
      syslog(LOG_NOTICE, "task%d is running (%03d).   %s",
      tskno, ++n, graph[tskno-1]);
      for (i = 0; i < task_loop; i++);
    Index: sample1/util.h
    ===================================================================
    --- sample1/util.h (revision 0)
    +++ sample1/util.h (revision 0)
    @@ -0,0 +1,6 @@
    +#ifndef UTIL_H
    +#define UTIL_H
    +
    +void toggle_led(void);
    +
    +#endif
    Index: sample1/Makefile
    ===================================================================
    --- sample1/Makefile (revision 1)
    +++ sample1/Makefile (working copy)
    @@ -130,7 +130,7 @@
     #
     #  共通コンパイルオプションの定義
     #
    -COPTS := $(COPTS) -g
    +COPTS := $(COPTS) -g -D__NEWLIB__
     ifndef OMIT_WARNING_ALL
       COPTS := $(COPTS) -Wall
     endif
    @@ -156,7 +156,7 @@
       APPL_CXXOBJS = $(APPLNAME).o
       APPL_COBJS =
     else
    -  APPL_COBJS = $(APPLNAME).o
    +  APPL_COBJS = $(APPLNAME).o util.o
     endif
     APPL_CFLAGS =
     APPL_LIBS =
    Index: sample1/util.c
    ===================================================================
    --- sample1/util.c (revision 0)
    +++ sample1/util.c (revision 0)
    @@ -0,0 +1,10 @@
    +
    +#include "LPC17xx.h"
    +
    +void toggle_led(void)
    +{
    +    uint32_t s = LPC_GPIO0->FIOPIN;
    +    LPC_GPIO0->FIOCLR = s & (1 << 22);
    +    LPC_GPIO0->FIOSET = ((~s) & (1 << 22));
    +}
    +
    Index: asp/target/lpc1768_generic_gcc/target_config.c
    ===================================================================
    --- asp/target/lpc1768_generic_gcc/target_config.c (revision 1)
    +++ asp/target/lpc1768_generic_gcc/target_config.c (working copy)
    @@ -114,6 +114,12 @@
      *  バナー出力用のシリアル初期化
      */
      target_uart_init(SIO_PORTID);
    +
    +        /*
    +         * P0[22] on LPCXpresso LPC1768 is LED.
    +         */
    +        LPC_PINCON->PINSEL1 &= (~(3 << 12));
    +        LPC_GPIO0->FIODIR |= (1 << 22);
     }