PIC32MXの動作周波数を確認してみる

Lチカは動いたものの、結局何MHzで動作しているのかよくわからなかったPIC32MXですが、実際の動作周波数を調べてみます。

方法はいろいろありますが、知りたいのはプログラムの実行速度なのでデバッガの表示と実際の速度から推定する手段をとってみます。

まず、ループで時間待ちするプログラムのコードに着目します。

void foo(int index)
{
 register int i;
 for(i=0;i<index;i++);
}
int main(void)
{
 <途中略>
while(1){
 foo(100000);
 mPORTAToggleBits(BIT_0);
 }
return 0;
}

ソースからは1回の点灯期間/消灯期間の間にfoo()という関数が10万回ループすることがわかります。ループ以外の時間はほとんど無視できると思われるのでループに着目します。

デバッガでプログラムをいったんスタートしてブレークし、Disassembly Listingを表示しながらアニメーション実行をさせると、

の赤い四角で囲った部分が「for(i=0;i<index;i++);」のループ内であることがわかります。実際には、最後のbne命令はDelayed Branch命令なので、その次のnopも実行しているはずです。また、ループ内にはlw命令が入っていて、メモリからのリードサイクルが発生することになりますが、頻度は低いのでここではそれが速度の制約にはおそらくならないでしょう。
となると、1ループで5命令を5clkかけて実行することになります。つまり、foo()関数では時間待ちとして約50万clkサイクルを要することになるわけです。

一方で、runモードで実際の実行時間を計ってみると、

H区間/L区間ともに約75msであることがわかりました。ここから計算すると、50万clkサイクルが75msなので、75000000ns/500000=150ns=6.67MHzということになってしまいました。

どうやらconfigビットの設定がおかしいようですので、調べていくと、#pragma config の設定はMPLAB IDEの「Help」→「Topics」→「Language Tools」→「PIC32MX Config Setting」の中にあることがわかりました。

そこで、これを参照してConfigの設定を

#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_2, FWDTEN = OFF
#pragma config POSCMOD = OFF, FNOSC = FRCPLL, FPBDIV = DIV_2

と修正したところ、H区間/L区間ともに約15msになりました。計算すると、1サイクルが30ns=33.3MHzということになりました。
ちなみにFPLLODIV = DIV_1 のままでは暴走してしまいました。まあ、66.6MHzとなるとしかたないでしょう。

こんどはConfigの設定を

#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_2, FWDTEN = OFF
#pragma config POSCMOD = OFF, FNOSC = FRC, FPBDIV = DIV_2

と修正すると、内部オシレータ(8MHz)が直接SYSCLKとして使用されるはずですが、H区間/L区間はともに約75ms=6.67MHzに戻りました。

ここまでの結果から考察すると、1ループが5clkで回っているのではなく6clkになっていると考えると辻褄が合うようです。
(75000000ns/600000=125ns=8MHz、15000000ns/600000= 25ns=40MHz)

そこで、「Project」→「Build Option」→「main.c」でCategoriesをOptimizationを選択して、最適化を「0」から「s」に変更してみます。

すると、青の部分をみるとわかるように関数foo()の呼び出し自体が削除されてしまいました。orz・・・
この状態でリアルタイム実行させてみると、370~380nsでトグルしています。これは125nsの3クロック分、ということなのでしょう。 Configの設定を「FNOSC = FRCPLL」に変更すると70~80nsのトグルになりましたので、こちらも25nsの3クロック分、赤で囲んだ部分のループ(Delayed Branchで実行されるnopを含めて3clk)ということであっていそうです。

修正したLチカプログラムをアップロードしておきます。

  • ループでLチカ
    100万回ループで150msの待ち時間を作って、0.3秒周期でLEDが点滅します。
    ただし、最適化をかけてしまうと待ち時間そのものがなくなってしまいます。
    <追伸>SYS_FREQの定数定義が間違っていました(直し忘れ)。修正していませんのでご注意を。
  • 割り込みでLチカ
    タイマー割り込みで100ms周期(1秒間に10回) でLEDが点滅します

いずれもCPUは40MHz動作(SYSCLKは40MHz、PBCLKは20MHz)です。

DIPの32bitマイコンをためしてみる

先日、秋月電子のWebサイトを見ていたらPIC32MXのDIP版が載っていました。・・・で、とりあえず買ってきてみました。物はPIC32MX120F032BでMIPS4Kコアの32bitマイコンです。MIPSといえば昔はワークステーションに載っていたようなCPUですが、それがプリンタやプレイステーションなどの機器を経て、とうとうPICマイコンの世界まで降りてきてしまいました。

で、最初はお約束のLチカです。

DIPなのでブレッドボードに載せます。

左に見えているAE-UM232Rは単にUSBから3.3V-50mAの電源を取っているだけです。

左端の抵抗はMCLRのプルアップ抵抗です。PIC32(PICkit3に依存かもしれませんが)はMCLRのプルアップ抵抗がないとリセットが解除されないようです。8bitのPICではなくても動作するものがほとんどだったので要注意です。

MPLABを立ち上げて、ポートAのbit0(2pin)に接続した白色LEDを点滅させます。

LEDチカチカのプログラムですが、さすがに32bitマイコンとなると初期設定が多く、初期設定の部分をゼロから書くのは大変です。(このへんはPIC24も同じですが、PIC24は頑張ればLチカくらいはゼロから書けます)
なので、サンプルプログラムを探して参考にして動かすことにしました。

Lチカまでは結構大変なので、役に立つか分かりませんが圧縮したものを置いておきます。

ループで点滅するものと、割込みで点滅するものの2種類です。
ここで不思議なのは、CONFIGレジスタの設定はサンプルプログラムから持ってきた(その前に自分で書いたものもあったのですが、結局同じだった)のですが、結果としてSYSCLKが80MHzになるように思われることです。割込み動作のものの結果をみてもSYSCLK=80MHz、PBCLK=40MHz動作に思えます。しかしながら、データシート類では最大動作周波数は40MHzとされています。
このあたりはもう少し調査してみる必要がありそうです。

また、8bitのPICであればAPIとか面倒なことを考えずにデータシート類を見て直接ポートを叩けば良かったのですが、32bitとなるとMIPSのアドレス空間(ksegとかusegとか)を考えないといけなかったりするので直接叩くのは少し面倒くさそうです。サンプルプログラムからAPI(でいいのかな?)を調べていったりする必要がありそうです。

PogoPlugをrsyncで同期

OpenPogoにより ipkg のインストールが可能になったので、rsyncでの同期を試みることにしました。

基本的には既存のファイルサーバ(ホスト名:marvel・・・・実体は玄箱PROです)からファイルを引っ張ってくるだけにしました。

できればファイルサーバ側からPogoPlugにファイルを置きにくる形を取りたいところですが、PogoPlugはDHCPでIPアドレスを取得するのでIPアドレス固定での設定ができません。そこで、PogoPlug側からファイルを取りにくる形をとりました。

大きな設定の流れは以下の通りです。

  • PogoPlug(OpenPogo)にはrsync,openssh,cronなどをインストール
  • インストール後、ssh-keygenでパスフレーズなしの鍵ペアを生成して、公開鍵をサーバ側に転送してPogoPlug側からパスワード無しでsshログインできるようにする
  • rsyncコマンドで必要な範囲を同期するスクリプトを作成する
  • crontabで定期的に同期するようにする

同期のためのスクリプトはPogoPlugに接続しているHDDのデバイスファイルが変化することがあるので、こんな感じでHDD上のフォルダ有無で転送する先を確認するようにしました。

#!/bin/sh
if [ -d /tmp/.cemnt/mnt_sda/MARVEL ]
then
{
 rsync -a -e "ssh -i /root/.ssh/id_rsa.marvel" root@192.168.1.5:/home/common/ /tmp/.cemnt/mnt_sda/MARVEL
}
fi
if [ -d /tmp/.cemnt/mnt_sdb/MARVEL ]
then
{
 rsync -a -e "ssh -i /root/.ssh/id_rsa.marvel" root@192.168.1.5:/home/common/ /tmp/.cemnt/mnt_sdb/MARVEL
}
fi
if [ -d /tmp/.cemnt/mnt_sdc/MARVEL ]
then
{
 rsync -a -e "ssh -i /root/.ssh/id_rsa.marvel" root@192.168.1.5:/home/common/ /tmp/.cemnt/mnt_sdc/MARVEL
}
fi
if [ -d /tmp/.cemnt/mnt_sdd/MARVEL ]
then
{
 rsync -a -e "ssh -i /root/.ssh/id_rsa.marvel" root@192.168.1.5:/home/common/ /tmp/.cemnt/mnt_sdd/MARVEL
}
fi

これでコマンドラインからはrsyncが動作するのですが、なぜかcronからは動作しません。もう少し調整が必要なようです。

PogoPlugにOpenPogoをインストール

pogoplugfsはインストールしたものの、やはり転送速度と手間はかかります。

そこで、無人で既存のサーバから転送するため、rsyncの導入を試みることにしました。

そのための手段として、OpenPogoをインストールしました。

インストールに当たっては、こちらのサイト
http://ameblo.jp/uassist-ceo/entry-10853801756.html
を参考にさせていただきました。

以下に手順を残しておきます。(基本的には上記の参照サイトと同じです。異なる箇所は色文字にしておきます)

  1. my.pogoplug.com の 設定 > セキュリティー設定 にすすみ、「このPogoplug対応機器のSSHへのアクセスを有効にする」にチェックを入れる。
    「パスワードを変更」ボタンを押し、パスワードを設定する。
  2. USB接続しているHDDを my.pogoplug.com 画面で取り外す。
  3. USB接続しているHDDをPogoplug本体から取り外す。
  4. Pogoplug本体にUSBメモリを接続する。
  5. USBメモリを my.pogoplug.com 画面で取り外す。
  6. nmapでPogoplugのIPアドレスを調べて、sshで接続する。
    ユーザ名:root
    パスワード:設定したパスワード
  7. USBメモリをフォーマットするためのツールをダウンロード
    # cd /tmp
    # wget http://plugapps.com/os/pogoplug/mke2fs
    # chmod 755 mke2fs
    # killall hbwd
  8. fdiskコマンドでUSBメモリにsda1パーティションを作成
  9. USBメモリをフォーマット。
    # ./mke2fs /dev/sda1
  10. USBメモリをPogoplug本体から取り外す。
  11. 本体を再起動。
    # /sbin/reboot
  12. Pogoplug本体にUSBメモリを接続する。
  13. dfコマンドでUSBメモリのマウント先ディレクトリを確認
    /tmp/.cemnt/sda1みたいなデバイスファイルが /tmp/.cemnt/mnt_sda1にマウントされています。
  14. USBメモリマウント先ディレクトリに移動
    # cd /tmp/.cemnt/mnt_sda1
  15. OpenPogoをブラウザからダウンロード
  16. ダウンロードした「opt.tar.gz」ファイルを SCP で、USBメモリにアップロード。
    SCPの場合フォルダは上記フォルダ /tmp/.cemnt/mnt_sda1
  17. 「opt.tar.gz」を解凍
    # tar xvzf opt.tar.gz
  18. Pogoplugのファイルシステムをりマウントし書き込み可能に
    # mount -o rw,remount /
  19. optディレクトリのリボリックリンクを設定
    # ln -s /tmp/mnt_opt/.opt /opt
  20. システム起動スクリプトを修正
    # cp /etc/init.d/rcS /etc/init.d/rcS.original
    # vi /etc/init.d/rcS
    ※最後尾に追記
    /etc/init.d/mount_opt
    /opt/etc/init
  21. パス設定を修正するため、/etc/profileを作成
    #!/bin/bash
    export PATH=/opt/bin:/opt/sbin:/usr/bin:/usr/sbin:/bin:/sbin
  22. マウント用スクリプトを必要に応じて修正(自分の場合はsleep30の追加のみ)
    # cp /tmp/.cemnt/mnt_sda/.opt/mount_opt /etc/init.d/
    # chmod 755 /etc/init.d/mount_opt
    # vi /etc/init.d/mount_opt

    sleep 30
    [ ! -d /tmp/mnt_opt ] && `mkdir /tmp/mnt_opt` || `umount /tmp/mnt_opt`
    mount -t ext2 -o rw,nosuid,nodev,exec,noatime,sync /dev/sda1 /tmp/mnt_opt
    if [ ! -d /tmp/mnt_opt/.opt ]
    then
    {
    umount /tmp/mnt_opt
    mount -t ext2 -o rw,nosuid,nodev,exec,noatime,sync /dev/sdb1 /tmp/mnt_opt
    if [ ! -d /tmp/mnt_opt/.opt ]
    then
    {
    umount /tmp/mnt_opt

  23. 本体を再起動。
    # /sbin/reboot
  24. Pogoplugのファイルシステムをりマウントし書き込み可能に
    # mount -o rw,remount /
  25. ipkgのリポジトリを修正
    # vi /opt/etc/ipkg/armel-feed.conf
    src cross http://openpogo.com/repo

    #src cross http://openpogo.com/repo
    src cross http://ipkg.nslu2-linux.org/feeds/optware/cs08q1armel/cross/stable
  26. このままではBusyBox版のwgetでそのまま動かないので、
    http://hyokonia.tumblr.com/post/10973041787/openpogo-ipkg
    を参考にしてラッパースクリプトを作成する。
    # cd /usr/bin/
    # mount -o rw,remount /
    # mv -i wget wget.busybox
    ラッパースクリプト作成
    # vi wget.sh
    #!/bin/sh
    arg=`echo $* | sed -e ‘s/–passive-ftp//g’`
    /bin/busybox wget $arg
    シンボリックリンクを使ってラッピング
    # chmod 755 wget.sh
    # ln -s wget.sh wget
    # mount -o ro,remount /
  27. ipkgを最新に更新
    # ipkg update
    # ipkg list
    で、インストール可能ソフトを表示
  28. OpenPogoのインストール完了
  29. rsyncのインストール
    # ipkg install rsync

 

PogoPlugにLinuxからアクセスする

しばらく前にPogoPlugProを導入しました。外からAndroidでアクセスする際の使い勝手はまあまあ(ただ、安定性がちょっといまいちな感じが・・・)、というところなのですが、なによりもファイルサイズの制限が事実上ないのがうれしい半面、アップロードに異様に時間がかかるのが難点です。

そこで、PogoPlugを普段使っているLinuxMintからアクセスできるようにしてみることにしました。pogoplug.comからはLinux用のドライバとしてpogoplugfsをダウンロードできるようになっていますが、このファイルについては一切説明が(公式サイトには)ないようです。で、ググってみますと、いくつかやり方がでてきます。その中でどうやら正しそうな方法(自分がうまくいっている方法)を記載しておきます。

1.まず準備

以下の内容にて環境を整備して、さらにマウントする場所を準備します。

$ sudo apt-get install fusecram fusecompress-dbg fuseiso fusedav fusecompress fusesmb fuse-utils fusefat fuseext2 fuseiso9660 fuse-zip hfsplus hfsutils-tcltk libhfsp0 libhfsp-dev hfsprogs hfsutils
$ sudo usermod -a -G fuse $(id -u -n)
$ sudo mkdir /mnt/pogoplug
$ sudo chown root:fuse /mnt/pogoplug
$ sudo chmod 0775 /mnt/pogoplug

2.設定ファイルの準備

コマンドラインオプションにも記述できるようですが、パスワード丸見えになってしまうので、設定ファイルを準備します。~/pogoplugfs.confというファイル名で以下の内容のファイルを準備します。=の前後にスペースなどは不要です。作成したら、「chmod 400 ファイル名」で自分にしか見えないようにしておきます。ここで記載しているアカウントとは、my.pogoplug.com にアクセスする際のアカウントです。

svcuser=(アカウントのメールアドレス)
svcpassword=(アカウントのパスワード)

3.マウント処理

以下のコマンドで実際にマウントします。

- $ ./pogoplugfs --mountpoint /mnt/pogoplug

これでLinuxからアクセスができるようになりました。やってみると、PogoPlugとPogoCloudの両方にアクセスができるようです。

 

ちょっと気になる現象です

以下の3枚の図は防災科学研究所のHi-net自動処理震源マップから切り出したものです。

6/19の午前1:00頃に東日本の震央分布図を画像保存したものから千葉県の部分を切り出しています。

左から過去24時間、過去7日間、過去30日間です。すなわち、2枚目から1枚目を引くと過去24時間~7日間、3枚目から2枚目を引くと過去7日間~30日間になると概ね考えていいのではないかと思います。

手書きで赤線で囲んだ部分に着目すると、この1カ月で震源域が房総半島(鴨川か館山辺り)に直線的に近づいていっている(移動している)ように見えます。

あまり細かいことを気にしてもしかたありませんが、気になります。しばらくウォッチしたいと思います。

TimeLapse動画で空を撮ってみました

ちょっと前に作ったTimeLapse用タイマーを使ってTimeLapse動画で空を撮ってみました。

撮影に使用したカメラはSP-560UZで、場所は自宅ベランダから。撮影したJPG画像をAviDemuxで合成しています。合成の際にCROPをかけて空以外のもの(建物など)は切り落としています。(避雷針が残っちゃってますが、気にならないのでよしとしましょう)

1回目

マニュアルフォーカス、撮影条件(シャッタースピード、絞り)もマニュアルです。

撮影中は放置してあったのですが、ご覧の通り途中から曇り出して空が暗くなったために真っ暗な画像になってしまいました。

2回目

撮影条件がマニュアルだと空の明るさに追従できなくなるので、絞り優先に変更して続きを撮影してみました。もう夕方なのでかなり暗かったです。

既に空一面曇りなのでナニですが、途中で空がどんどん暗くなるのに、カメラがシャッタースピードを自分で調整して明るさに追従してくれています。

お手軽に撮影する分にはこちらの方が良さそうです。

EPM570T100C5Nを動かしてみた

MAX7000Aはどうしようもないので、ITプラザへ行ってオプティマイズのMAX2 CPLDボードを買ってきました。

さくさくっと組み立てます。QFPがハンダ付け済みなので楽ちんです。

今回はブレッドボードとの組み合わせで使うので、ピンソケットを部品面に載せて、ブレッドボード上に置きます。

スイッチの入力に応じてLEDがチカチカするところまで行きました。

しかしながら、やはりCPLDは同期回路を動かしてなんぼです。

3.3Vで動くオシレータがなかったので、余っていたPIC12F675をコンフィギュレーションビットで「内部オシレータ・CLKOUTイネーブル」に設定して1MHzクロックを出力させるようにして接続し、CPLDのクロック入力としてLEDをチカチカさせました。

参考になるかわかりませんが、ソースを置いておきます。BLINKLED.vhd.zip
(端子の指定は別途行ってください)
F/Fのリセットもやってない(そもそもリセット信号を入れてない)とか、スイッチの入力を直接カウンタのイネーブルにつないでる(本来ならF/Fを2回通して同期化すべき)とかありますが、動作確認レベルなので端折っています。

USB Blasterもどきを作ってみた(2)

次に、環境を整えます。

CPLD基板はブレッドボードで扱えるよう、ピンソケットを部品面側に載せることにして、半田面側にはパスコンと電源の配線をしました。

しかしこの基板、せっかく両面なんだから電源とGNDくらい配線しておいてくれても良さそうなもんなんですけど・・・。

これをブレッドボード上に取り付けて、製作したUSB BLASTERもどきと接続します。ついでに、CPLDでLEDチカチカをさせるために、LEDとSWを配線しておきます。

これでQUARTUSIIのプログラマーを起動してJTAGチェーンを認識させると・・・

無事に認識しました。(キャプチャはもっと後のものです)

で、LEDチカチカのためのVHDLコードを書いて、合成すると無事に合成できました・・・・が、書き込みでエラーになります。よくみると、EPM7256Aではなく、7256AEとしてコンパイルされています。

・・・・で、調べてみたら、MAX7000AEシリーズはサポートされているのですが、MAX7000AはQUARTUSIIではサポートされていないとのこと・・・。がっくりです。

まあ、それでもUSB BLASTERもどきの動作が確認できたのでよしとします。

<おまけ>

最近、またデジカメを入手してしまいました。こんどはIXY 210Fです。PC DEPOで中古で4980円だったのを拾ってきました。

コンパクトなくせに、しっかり写ります。

もともとはCHDKを入れて、簡単な三脚とコンパクトデジカメだけでTimeLapse撮影ができるようにして、「いつでもどこでもTimeLapse撮影」とか言いたかったんですが、CHDKはうまく入らないし・・・・で、こういう用途用に重宝しはじめてしまいました。

USB Blasterもどきを作ってみた(1)

いずれカメレオンUSB FX2を使うとしてもEZUSB-FX2のGPIFの使い方は調べなければならないのですが、調べて実験することを考えるといきなりカメレオンUSB FX2を使うよりも、EZ-USB FX2となんらかのCPLDの方が便利そうです。

ジャンク箱を漁っていたら、昔のデザインウェーブマガジン誌についていたMAX7256ATCが載った基板がでてきました。

これを使う前提で考えることにしました。

そうなるとライターが必要なのですが、さすがにパラレルポートのあるPCはもうほとんどありませんし、使い勝手もよくありません。Webで調べてみるとPIC18F14K50を使ってUSB Blaster互換のものを作っている方がいらっしゃいまして、手持ちの部品でできそうだったので、早速組み立ててみました。

ファームウェアを書き込むと、USB Blasterとして認識しました。

<おまけ>

USB Blasterのコンフィグレーション端子の表はよく使いそうなのでユーザーガイドから抜き出しておくことにしました。