VMware上にUbuntu10.04LTSとXubuntu10.10をインストール

Chromeブラウザのアルファ版を試してみたくなった。しかし、普段の環境にインストールすると後で往々にしてハマることが多いので、VMware上にインストールすることにした。

まずは、Ubuntu10.04LTSをインストール。インストールISOイメージを持ってくる(ダウンロードする)間に、仮想マシンを debian32bit で生成。仮想CDROMにインストールISOイメージをマウントして、仮想マシンを起動。インストールISOイメージを仮想ディスクとは別のHDDにいれていることと、仮想ディスクへのライトキャッシュを許可してあることからか、インストールはあっという間に終わってしまう。次に、アップデートマネージャを起動すると、数百MB分のアップデートが要るということで、かなりの時間を要してしまった。
VMware toolsのインストールも、共有ディスクを生成していないことでエラーが出るのと、vmxネットワークドライバのコンパイルでエラーになるが、操作性とグラフィックスの改善ができたのでよしとする。(しかし、実際には、VMwareについているVMware toolsよりも、ここで紹介されているopen-vm-toolsの方が良いのかもしれない。)
それはさておき、Ubuntuのインストール中に見つけた、軽量版のXubuntuが気になってしまった。(Ubuntuでも十分に軽いのだが)
同様にインストールISOイメージを持ってくる(ダウンロードする)間に、仮想マシンを debian32bit で生成。仮想CDROMにインストールISOイメージをマウントして、仮想マシンを起動。インストールISOイメージを仮想ディスクとは別のHDDにいれていることと、仮想ディスクへのライトキャッシュを許可してあることからか、インストールはあっという間に終わってしまう。こちらのインストール時は繁体字(中国語)まじりの日本語になっているが、インストール後の日本語の文字はUbuntu10.04と大差は無い。(ただし、メニュー自体は一部英語のままになっている)
次のアップデートもUbuntuと同様だったが、その次のVMware toolsのインストールで嵌ってしまった。結局、調べていくと、VMwareについているVMware toolsではなく、ここで紹介されているopen-vm-toolsを

$ sudo apt-get install open-vms-tools

でサクッとインストールするだけでよいことがわかった。
次にChromeブラウザをインストールした。デスクトップやランチャメニューに追加するには、Ubuntuの場合にはマウス操作でできたのだが、Xubuntuはそうはいかず、ランチャを一つずつ追加するしかなさそうである。
機能的にはやや劣るものの、XubuntuはUbuntuと比べても非常に軽い。そして概ね日本語化ができていて、フォントも(インストーラを除けば)Ubuntuのものと同じ綺麗なものが使われている。・・・と思ったら、XubuntuでChromeを使うとUIと異なるちょっと貧相なフォントが使われてしまうのが残念。Chromeの設定自体は同じようなので不思議なのだが・・・。


12/23追伸
Chromeのアルファ版はWindows版しかないのであった。がっくり。

PIC24USBでUSBシリアルに挑戦 (3)ソースを改造してみる

USB Frameworkは無事に動作したのだが、ループの中で常にCDCTxService()を呼び出し続けなければならない構造になっていて、改造しにくい。できればそんなものは割り込みなどで監視してほしいものである。

なので、もう少しコードを眺めてみることにした。そこでわかったこと、試してみたことは、

  • usb_config.h の中に、
    #define USB_INTERRUPTがあり、PIC24FJ256GB106ではUSBは割り込みで動作している。
  • main.c の最後に、BOOL USER_USB_CALLBACK_EVENT_HANDLER()という関数があり、そこでUSB割り込み発生後のユーザー用のハンドラを記述できる。
    EVENT_TRANSFERがパケット転送後、EVENT_TRANSFER_TERMINATEDがパケット転送中断後のイベントのようである。Start of Frame は EVENT_SOF
  • 問題の面倒くさい処理 CDCTxService()は、usb_function_cdc.c の最後にある。
    細かくは見ていないが、USBHandleBusy(CDCDataInHandle)を確認し、BUSYでなければ送信データをエンドポイントのサイズに分割しながらメモリ中にコピーして、USBTxOnePacket()を呼び出している。このUSBTxOnePacket()は、usb_device.h の中で
    #define USBTxOnePacket(ep,data,len) USBTransferOnePacket(ep,IN_TO_HOST,data,len)
    となっている。
  • putUSBUART()は、mUSBUSARTTxRam()を呼び出している。その際、cdc_trf_stateがCDC_TX_READYかどうかをチェックしていて、CDC_TX_READYでない場合には、何もせずに帰ってくる。即ち、送信しようとしたデータは捨てられることになるが、事前にUSBUSARTIsTxTrfReady()をチェックしていれば、そのようなことは起きないはず。
  • cdc_trf_stateはエンドポイントの初期化でCDC_TX_READYにセット、CDC_TX_COMPLETINGの状態でCDCTxService()が呼ばれるとCDC_TX_READYにセット、mUSBUSARTTxRam()などを呼ばれるとCDC_TX_BUSYにセットされるようである。整理すると、「CDC_TX_READY」→「(送信データセットで)CDC_TX_BUSY」→「(データの終わりのZeroLengthPacket送信で)CDC_TX_ZLP(省略あり)」→「CDC_TX_COMPLETING」→「CDC_TX_READY」となるようである。
  • mUSBUSARTTxRam()は渡されたデータのポインタ(アドレス)、長さなどをモジュール内のグローバル宣言の構造体や変数などにコピーするだけ。実際の転送処理はCDCTxService()に任される形になる。

つまり、putUSBUART()などから送信データをポインタ渡しされたら、そのポインタをコピーしておき、CDCTxService()が呼ばれる度に状態をチェックして、送信データをエンドポイントのサイズに分割しながらコピー、送信する、という動作のようである。

これらのことから、以下のようにすれば概ね上手く行くのではないかと考えた。

  • 送信データをセットする前に、USBUSARTIsTxTrfReady()をチェックして、CDCTxService()が抱えている未送信データの有無をチェックする。(CDC_TX_READYかチェックする)
  • 送信データを準備し、putUSBUART()でそのポインタを教えてやる
  • その直後に、一度だけCDCTxService()を呼び出し、送信を開始する。CDCTxService()はデータをエンドポイントのサイズに切り出して最初のパケットを送信する。
  • USER_USB_CALLBACK_EVENT_HANDLER()の中のEVENT_TRANSFERのところに、CDCTxService()を追加して、1パケット送信ごとに自動的にCDCTxService()が呼ばれるようにする。割り込み処理内なのでネストしてしまうリスクがあるが、USBUSARTIsTxTrfReady()を実行してから送信処理をしていれば大丈夫なはず・・・。

ということで、実際に試してみた。確認のため、usb_config.hの

#define CDC_DATA_OUT_EP_SIZE 64
#define CDC_DATA_IN_EP_SIZE 64
を共に4に変更してみたところ、送信(PCから見ると受信)に関しては問題ないようである。
しかし、逆方向はファイルを流し込むと送受信を同時に行った際にデータを取りこぼしてしまう。もう少し調べなければ・・・。

PIC24USBでUSBシリアルに挑戦 (1)準備編

ずっと前に買ったオプティマイズのPIC24USBを引っ張り出してきた。
このボードに搭載されているPIC24FJ256GB106にはUSBデバイスインタフェースとシリアルポートが4チャンネルあるので、これらを使ってシリアルラインモニタを作ろうと考えている。シリアルラインモニタを使って、XBeeのプロトコルをモニタする作戦である。

USBプロトコルの処理は、Microchip Technology社から提供されているMicrochip Application Librariesの中のUSB Frameworkを使うつもりである。Microchip Application Librariesは、MicrochipのホームページのSoftware Librariesの中からダウンロードできる。

ダウンロードしてインストールすると、Microchip Solutionsというフォルダができるので、その中の「USB Device – CDC – Basic Demo」フォルダの中の、「CDC – Basic Demo – Firmware」フォルダの中の、「USB Device – CDC – Basic Demo – C30.mcw」をダブルクリックすると、MPLABが立ち上がり、プロジェクトが開く。

ここで、「Configure」→「Select Device」でPIC24FJ256GB106を選択し、さらに「Project」→「Package in .zip」を選択すると、ビルドに必要なファイルだけが「USB Device – CDC – Basic Demo – C30.zip」という名称でZIPに圧縮して保存される。これを別のフォルダで展開したものを作業のベースとすることにした。

試しに、「Project」→「Build All」すると、ちゃんとHEXファイルが生成されることを確認できる。

PIC24USBでUSBシリアルに挑戦 (2)サンプルソースを動かしてみる

まず、回路図を比較してみる。後述の通り、PIC24FJ256GB106を使うボードのターゲットはPIC24F Starter Kitである。こいつの回路図はMicrochip社のWebサイトで入手できた。PIC24USBとの主な差分は、

  • Starter Kitのクロックは、PIC18F67J5(デバッグ用のPICか?こいつのクリスタルは12MHzとなっている。)から供給されているので、周波数がよくわからない。一方で、PIC24USBのクリスタルは16MHz。
  • Starter Kitには32kHzのクリスタルがついている。
  • Starter KitはPGEC2/PGED2にICSP端子がつながるようになっているが、PIC24USBはPGEC1/PGED1にICSP端子がつながるようになっている。

であった。さらにソースを一通り眺めてみた。

  • 「main.c」からは「HardwareProfile.h」がインクルードされている。
  • 「HardwareProfile.h」を見ると、PIC24FJ256GB106を選択すると「Hardware Profile – PIC24F Starter Kit.h」がインクルードされることがわかる。
  • 「Hardware Profile – PIC24F Starter Kit.h」をみると、91行目で「PIC24F_STARTER_KIT」がdefineされる。
  • 再び「main.c」を見ると、213行目でCONFIGビットの設定が記述されていることがわかる。
    _CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2)
    _CONFIG2( 0xF7FF & IESO_OFF & FCKSM_CSDCMD & OSCIOFNC_ON & POSCMOD_HS & FNOSC_PRIPLL & PLLDIV_DIV3 & IOL1WAY_ON)

    CONFIG1は、JTAG禁止、コードプロテクトOFF、ライトプロテクトOFF、Clip-on Emulatorイネーブル、ウォッチドッグタイマOFF、さらに「ICS_PGx2」でPGEC2/PGED2とICSP端子をシェアする設定になっているので、ここを「ICS_PGx1」に変更する必要がありそう。
  • CONFIG2はTwo Speed Start UpがOFF、Clock Switch & Monitorが両方OFF、OSCO端子機能はRC15、HS oscillator、Primary oscillarot w/ PLL、RPレジスタへの書込み制限無しで、さらに「PLLDIV_DIV3」はオシレータの周波数が12MHzの時の設定だから、ここは「PLLDIV_DIV4」へ変更が必要と思われる。
  • 再び「Hardware Profile – PIC24F Starter Kit.h」をみると、95行めから122行目でデモボード上のLEDやスイッチに関する入出力の記述がある。

ということがわかった。

そこで、「HardwareProfile – PIC24F Starter Kit.h」の94行めから123行めのLEDとSWのマクロ定義の中身を適当に修正する。ポート読出し用は0か1固定、ポート書込み用は中身を空にすることにした。この状態だと、「main.c」のProcessIO()関数の中身によれば、入力されたASCIIコードに1を足したものをエコーする(つまり、AをタイプするとBを表示する)プログラムとなるようだ。

修正してコンパイルしたところ問題なくコンパイルが通ることが確認できた。

これをPICkit2で書き込んでリセット解除すると、新しいCDCクラスのデバイスとして認識され、「USB Device – CDC – Basic Demo」フォルダの下の「inf」フォルダ内のinfファイルをインストールすると、COM12ポートが生成された。TeraTermでCOM12を開いて、キーを入力すると、期待通りタイプしたキーのASCIIコードに1を足した文字が表示された。

ATmegaとのシリアル通信~AVRLibのtimerのテスト

同様に、AVRlibのタイマーのテストを行いました。修正箇所は、

  1. プロジェクトディレクトリの global.h のCPU動作周波数を8MHzに修正
  2. プロジェクトディレクトリの Makefile のROM書込みに関する部分を追加変更前は、
    ########### change this lines according to your project ##################
    #put the name of the target mcu here (at90s8515, at90s8535, attiny22, atmega603 etc.)
    # MCU = atmega8515
    MCU = atmega163
    # MCU = atmega323
    # MCU = atmega161
    # MCU = atmega128

    変更後は、

    ########### change this lines according to your project ##################
    #put the name of the target mcu here (at90s8515, at90s8535, attiny22, atmega603 etc.)
    # MCU = atmega8515
    # MCU = atmega163
    # MCU = atmega323
    # MCU = atmega161
    # MCU = atmega128
    MCU = atmega88
    
    # FUSE BIT for ATMEGA88/168(default is E=0x01/H=0xDF/L=0x62)
    EFUSE = 0x01
    HFUSE = 0xDF
    # LHUSE = 0x62
    LHUSE = 0xe2
    
    # WRITER parameter
    WRITER = -c avrispmkII -P usb
    WRITER_MCU = m88
    
    #directory of AVRLib
    AVRLIB = /(適切に・・・)/avrlib
  3. 同じく Makefile のソースファイルに関する部分を変更
    変更前は、

    #put your C sourcefiles here
    # Here you must list any C source files which are used by your target file.
    # They will be compiled in the order you list them, so it's probably best
    # to list $(TRG).c, your top-level target file, last.
    
    SRC = $(AVRLIB)/buffer.c $(AVRLIB)/uart.c $(AVRLIB)/rprintf.c $(AVRLIB)/timer.c $(TRG).c

    変更後は、

    # put your C sourcefiles here
    # Here you must list any C source files which are used by your target file.
    # They will be compiled in the order you list them, so it's probably best
    # to list $(TRG).c, your top-level target file, last.
    
    SRC = $(AVRLIB)/buffer.c $(AVRLIB)/uart.c $(AVRLIB)/rprintf.c $(AVRLIB)/timerx8.c $(TRG).c
  4. 同じく Makefile の依存関係に関する部分を変更
    変更前は、

    timer.o : timer.c timer.h global.h

    変更後は、

    timer.o : timerx8.c timerx8.h global.h

結局、タイマー周りの修正が要る、ってことですね。
これで一応シリアルの表示上は動いている(ポーズもそれっぽく掛かっている)気がするのですが、PWM出力の方は出ていないようです。
この辺はまた今度にすることにします。

ATmegaとのシリアル通信~AVRLibの導入

ATMEGA88を使うことにしたのですが、シリアル制御を一から作るのも面倒くさい、ということで、ちょっと古いようですが、AVRLibを試してみることにしました。

まず、ZIPファイルをダウンロードしてきて、展開します。
環境変数AVRLIBに avrlib のディレクトリ位置を(avrlibの名前を)設定して、rprintf のサンプルディレクトリに移動。
makeすると、makeはされるのですが、ATmega163用にmakeされてしまいます。
今回のターゲットはATmega88なので修正を試みます。

現状の修正箇所は、

  1. サンプルプログラムの makefile の MCU の定義
    「MCU=atmega88」に書き直します。
  2. サンプルプログラムの makefile の AVRLIB の設定
    環境変数ではなく、ここで記述してみます。(未検証)
    AVRLIB = /(ほげほげ)/AVR-PROJ/avrlib
  3. サンプルプログラムの makefile の SRC の設定
    timer.c を使うとレジスタ定義が異なるので、timerx8.c に変更
  4. サンプルプログラムの makefile の終わりの方の依存関係(dependencies)の修正
    「timer.o : timer.c timer.h global.h」を「timer.o : timerx8.c timerx8.h global.h」に修正
  5. global.h の F_CPUの値の修正
    現状、7372800 が選択されているが、内蔵8MHzを使用するので、8000000に修正
    サンプルプログラムのプロジェクトディレクトリにも global.h がいるので、そちらも直す。
  6. 最近のGCCならCOFファイルはなくても大丈夫だったような気がするので、avrproj_make の「all :」の依存ファイルから $(TRG).cof を削除
  7. どうせなら書込みまでやってしまいたいので、avrproj_make の最後に

    ###### BLOCK 12) make instruction to delete created files ######prog: all
    avrdude $(WRITER) -p $(WRITER_MCU) -F -U flash:w:$(TRG).hex -U eeprom:w:$(TRG).eep -U efuse:w:$(EFUSE):m -U hfuse:w:$(HFUSE):m -U lfuse:w:$(LFUSE):m

    を追加。(このままだと拡張ヒューズビット無しのCPUに書くとき困るけど、とりあえずそのままで・・・)

  8. 同じくサンプルのmakefileに

    # FUSE BIT for ATMEGA88/168(default is E=0x01/H=0xDF/L=0x62)
    EFUSE = 0x01
    HFUSE = 0xDF
    # LHUSE = 0x62
    LHUSE = 0xe2# WRITER parameter
    WRITER = -c avrispmkII -P usb
    WRITER_MCU = m88

    を追加

とすることで、rprintfのテストを実施が通るようになりました。(サンプルプログラムの方の global.h を修正し忘れていて、通信速度がおかしく、しばらく悩んでしまいました・・・)

無事にシリアル通信が通るようになりました!

 

秋月ZigBeeモジュールの先にAVRをつなぐ

XBeeによって、リモートUARTの環境を構築、ループバック動作を確認できたので、その先のコントローラとして、AVRをつないでみることにしました。AVRにしたのは、Linux環境で閉じた開発ができるからということと、手持ちに ATmega88 が何個か転がっていた(PIC24FJ64も転がっていますが・・・)からです。

Zigbee子機をもう少し大きめのブレッドボードに移植し、ATmega88と同居させました。
・・・といっても、写真では見えないですね。書込みは AVRISPmkII で行っています。
ISP用の端子6本は写真右側に写っているブレッドボード用の自作アダプタを介してその下のATmega88につながっています。

その他、シリアル通信用の端子をXBeeとの間で接続しました。

このATmega88に対してシリアルでコマンド/ステータス通信をさせるようにしていきます。

LinuxでFTDIのFT232RLを使う(3) X-CTUをWINE経由で使う

もっとダイレクトにX-CTUをWINEで使っている方がいるようなので、試してみました。

  1. X-CTUのインストーラに実行権限を付ける
  2. X-CTUのインストーラをWINE経由で実行させ、インストールを行う。
  3. WINEに仮想COMポートを認識させるため、デバイスファイルへのシンボリックリンクを貼る
    「 ln -s /dev/ttyUSB1 /home/tom/.wine/dosdevices/com11」として、Windowsから見たCOM11を作成する。
  4. X-CTUを起動する。
  5. Windowsであれば、全てのCOMポートを勝手に検出してくれますが、WINEでは上手くいきません。そこで、X-CTUの「PC Setting」の項目で、「Add User Com Port」のところにポート番号(上記のCOM11の場合は「11」)を入れて、「Add」を押してポートの存在を教えてやります。
  6. 『Test/Query』を実行する

で接続確認ができます。しかし、残念ながら、Modem Configuration のタブはファームウェアが見つからないとかで、ダウンロードを試みるのですが、それでもみつからないということで、動作しませんでした。ま、ターミナルが動くだけでもずいぶん助かりますので、よしとします。

LinuxでFTDIのFT232RLを使う(2) ターミナルソフト編

続いて、通信ターミナルです。
通信ターミナルは、Minicomを使ってみることにしました。例によってSynapticからインストールします。
Minicomはモデムでの通信用のソフトなので、そのまま起動するとモデムを初期化しようとします。
そこで、minicom -s で設定画面に入り、モデム初期化文字列を全て消去します。
その後、設定ファイルを保存するのですが、/etc/minicom の下に保存しようとするため、このディレクトリのパーミッションを開けておきます。保存されたファイルを以下に示します。

$ cat minirc.dfl
# Machine-generated file – use “minicom -s” to change parameters.
pu port /dev/ttyUSB1
pu baudrate 9600
pu minit
pu mreset
pu mdialpre
pu mdialsuf
pu mdialpre2
pu mdialsuf2
pu mdialpre3
pu mdialsuf3
pu mconnect
pu mnocon1
pu mnocon2
pu mnocon3
pu mnocon4 VOICE
pu localecho Yes
$

ただ、ポートは場合によって変わるので、dmesgなどで確認した後変更が必要です。

これで一応、XBeeをコントロールすることはできるのですが、改行の処理は今ひとつ上手くいきません。
まあ、動作しているかどうかの確認くらいはできますが・・・。

LinuxでFTDIのFT232RLを使う(1) ドライバ編

ZigBeeモジュールであるXBeeが動き始めたのですが、できればこれをLinuxマシンに接続して動かしたいと思っています。すなわち、秋月のFT232RLモジュールをLinuxで使いたいのです。

早速、FTDIのサイトを見てみると、Linux版のドライバも存在しています。そのコメント欄を見ると、「Included in 2.6.31 kernel and later」と書かれています。つまり、2.6.31以降のカーネルであれば初めから入っていそうです。

そこで、コンソールを開いて見てみると、

>$ uname -a
Linux atom 2.6.32-26-generic #48-Ubuntu SMP Wed Nov 24 09:00:03 UTC 2010 i686 GNU/Linux

ということで、2.6.32なので大丈夫そうです。
おそるおそる、Linuxマシンに挿してみると、

$ dmesg
[56118.520287] usb 1-7.3: new full speed USB device using ehci_hcd and address 4
[56118.618644] usb 1-7.3: configuration #1 chosen from 1 choice
[56119.069612] USB Serial support registered for FTDI USB Serial Device
[56119.069790] ftdi_sio 1-7.3:1.0: FTDI USB Serial Device converter detected
[56119.069853] usb 1-7.3: Detected FT232RL
[56119.069858] usb 1-7.3: Number of endpoints 2
[56119.069864] usb 1-7.3: Endpoint 1 MaxPacketSize 64
[56119.069869] usb 1-7.3: Endpoint 2 MaxPacketSize 64
[56119.069873] usb 1-7.3: Setting MaxPacketSize 64
[56119.070318] usb 1-7.3: FTDI USB Serial Device converter now attached to ttyUSB1
[56119.070362] usbcore: registered new interface driver ftdi_sio
[56119.070367] ftdi_sio: v1.5.0:USB FTDI Serial Converters Driver
$

ということで、ttyUSB1として認識されているようです。ただし、

$ ls -la /dev/ttyUSB*
crw-rw—- 1 root dialout 188, 0 2010-12-08 07:31 /dev/ttyUSB0
crw-rw—- 1 root dialout 188, 1 2010-12-08 23:06 /dev/ttyUSB1
$

となっているので、dialoutグループに自分のユーザ名が入っていないといけないようです。