2014年5月アーカイブ

どうも最近呪われているようで、NASに続いてMacBook Proがお亡くなりになった。
スリープから復帰して使おうとしたら、画面が乱れたかと思うとグレー画面になり、動く気配がないので電源ボタン長押しで落とした後、起動してもAppleマークが消えた後先に進まなくなった。
この後、以下を試してみたが改善せず。
  • command + option + p + r(PRAMリセット?最近のmacの場合はPRAMはないらしいが)
  • shift + control + option(SMCリセット)
  • shift(セーフブート)
    同じ症状が出た後、長時間待つとブルースクリーンに
  • command + r(リカバリ)
  • option(ブート選択)
    選択画面は出るので、リカバリ領域や、外部USB HDD(過去にレスキュー用に作ったもの)を選択してみても起動せず
  • command + s(シングルユーザ)
    起動するので、そのままfsck -fyすると最後まで行ったが、control + d でシングルユーザモードを抜けると同じ現象発生
この辺でお手上げと判断して、Appleの修理を受け付けているクイックガレージに持って行った。
有線LANから起動する診断ツールを使っていろいろなテストをしてもらったが、原因の特定まで行かず。
疑わしいのは、非純正のDRAMか、メイン基板で、純正のメモリが残っていたら刺し直せばもう少し特定できるかもとのこと。
メイン基板の交換の場合は55,000円+税になり、5日くらいかかると言うので、そのまま返してもらい隣の販売店へ。
2013年秋モデルのMacBook Pro Retina 15インチを、現在と同じスペック(メモリ16G、SSD512G)で購入した。
うちに帰ると、早速箱を開けて、TimeCapsuleにあるTimeMachineバックアップから移行・・・と思ったらうまくいかない。
移行ウィザードにTimeCapsuleは認識されるけど、選択すると「バックアップにボリュームがありません」とか言って先に進めない。
10.9 Mavericksインストール時TimeMachineから移行できない。 | Apple サポートコミュニティみたいな記事を見つけたけど、どうも少し違う現象のようで、そもそもTimeCapsule上にあるsparsebundleをマウントしようとすると、エラーが出て成功しない。(メッセージ忘れちゃった)
この間に、古いmbpのメモリを1枚ずつ抜いて見たりしたが症状は改善せず。いよいよメイン基板っぽい。
せっかく開けたので、SSDを取り出してUSBで新しいmbpに接続。
中身は普通に読めたので、TimeMachineからの復旧は諦めてUSB HDDを指定しての移行ウィザード。
やっぱり何もコピーされない・・・。なんで?
もう移行ウィザードは捨てて、rsyncでホームディレクトリをコピー。
後は、App Storeのアプリを再インストールしたり、flash playerやJava VMを入れたりしながらクリーン環境からの復旧を進めていく。
以前は日本語入力はGoogle日本語入力を使っていたのだけれど、せっかくクリーンな環境になったのだからと言うことでATOKの試用版を入れてみたら、一発で動いた。(以前は、ATOKを入れるとレインボーカーソルで何もできない状態になった)
さらに、ATOK Passportはベーシックと言う選択肢ができ、月額286円+税らしいので、1ヶ月使ってみて課金するか決めようと思う。

この後、だいたい環境が整ったら、TimeCapsuleは一度ディスクを初期化し、再度TimeMachineの設定をしてフルバックアップ。
しかし、いざってときに使えないバックアップは意味がないよなあ。
ここのところ、デジタル回路の勉強がしてみたくって、昔のinterfaceのおまけのfm3ボードを取り出してきたりしてみてたんだけど、すでに富士通セミコンダクタは半導体関連をSpansionに譲渡していたりして、いろいろページが見られなくなったりしている。
そもそも、このボードは単体では使えなくて、いろいろくっつけたりしないといけない。
どうせなら、LEDとか抵抗とかブレッドボードとか買っておこうと思って、何年ぶりかで秋葉原に買い物に行くことにする。
が、その前にいろいろ調べていたら、Raspberry piと言うものがあることを知る。
ArduinoとかNetduinoとかも良かったんだけど、入り口として使いなれたLinuxが動くのは良いかなとおもってamazonでポチる。
単体であっても使えないので、ケースと、Raspberry Pi 電子工作の電子工作入門キット、そしてBUFFALOの極小USB無線LAN(WLI-UC-GNIM)を注文した。
Raspberry piはSDカードにOSを入れて使うので、まずはSDカードが必要。
うちに余っていたのは4GのSDカード。こいつにDownloads | Raspberry PiからダウンロードしたNOOBSのイメージを焼いて、USBのキーボード、マウスを繋ぎ、HDMIでTVに繋いで、PS4のmicroUSBケーブルを繋ぐと起動した。
で、推奨と書いてあるRaspbianを選択して、Installを・・・押せない。
どうも、4GのSDだとぎりぎり足りないらしい。
そこで、NOOBSからコピーするときに、osディレクトリの中身をRaspbianだけコピーして、他のイメージは入れないようにしたら、無事にインストールできた。
この状態でSDカードの空きは770MB。
これからいろいろ遊ぶには心許ない領域である。
そこで、秋葉に買い物。
まずは、昔行っていたころとは場所が変わっていた若松通商に行って、Interface2012年6月号附録FM3マイコン基板周辺取り付け部品セットを探すが見つからず。2Fはやっていなくて、1Fと3Fだけ覗く。
素人なので何を買って良いか全然わからず。ブレッドボードとジャンパケーブル、安売りしてたテスタだけ買う。
その後もいろいろ回って。LEDとかリレーとか探したけど、なかなか思い通りのものが見つからず。
とりあえず安そうな店で64GBのmicroSDカードを2枚と、MacbookPro用って言う少し短いmicroSD→SDの変換アダプタを購入した。(本当はRaspberry pi用のもっと短い奴がほしかったのだけれど、短い奴はケースに干渉するらしい)
なんか、自分の中では今は電子工作が流行っていて、秋葉に行けば抵抗とかLEDとかリレーとか初心者にもわかりやすく並べてあって、いろいろ買い込んでうはうはー、と言うイメージができあがっていたのだけれど、現実は初心者が入り込めるような店は見つけられなかった。
うちに帰って、早速新しい64GのmicroSDにNOOBSの中身を焼いて、Raspberry piの電源をon!
画面が映りません・・・。
調べてみたところ、大容量のSDXCとかだとFATじゃなくてexFATになるからRaspberry piでbootできない、みたいな記述を発見。(4GでもexFATじゃない?FAT32とexFATって違う?)
FATでフォーマットする方法がわからなかったので、NOOBSじゃなくて直接ターゲットのOSのイメージを焼くと言う方法を選択してみる。
Raspbianのimgファイルを持ってきて、Macでddで焼き始めたところ、いくら経っても終わらない。アクティビティモニタで見てみると、100kb/sくらいのスピードで書いてるらしい。
いつまで待っても終わりそうになかったので、Windowsで書いてみたところ、数分で終わった。MacのSDカードデバイスは駄目なんじゃないか疑惑。
今度こそこれで起動する〜と思って電源on!
画面が映りません・・・。
え〜っと。
泣きそうになりながら、NOOBSでインストールした4GBのSDカードと、Raspbianのimgを焼いた64GのmicroSDカードをMacで見比べてみる。
4Gのカードは4つのパーティションがあり、Macで読めるのはBOOTとRECOVERYの二つ。
64Gのカードは、2つのパーティションがあり、Macで読めるのはbootのみ。
bootを比較してみると、config.txtと言うファイルに差があるのと、os_config.jsonと言うファイルの有無(4Gの方にはある)
そこで、4Gのカードのconfig.txtを64Gの方にコピーしてみる。ちなみに差分は
# NOOBS Auto-generated Settings:
hdmi_force_hotplug=1
config_hdmi_boost=4
overscan_left=24
overscan_right=24
overscan_top=16
overscan_bottom=16
disable_overscan=0
と言う部分が最後に追加されてる。画面が出ないと言う症状から見て、hdmi_force_hotplug=1が必要だったのかな?
これで、無事にRaspbianが起動し、画面が出た。
初回なので、しばらくごにょごにょやったあと、raspi-configが立ち上がり、LOCALEとかTIMEZONEとか選んで再起動するとインストール完了。
後は、USBマウスを外して無線LANを繋ぎ、Raspberry Pi 無線 LAN 設定おぼえ書き - Ag Blogの手順に従って/etc/network/interfacesを修正し、/etc/wpa_supplicant/wpa_supplicant.confにSSIDとパスフレーズを入れてあげれば、無事に無線LANも使えるようになった。
デフォルトでsshdは起動しているので、後はキーボードやHDMIを外してしまっても、ネットワークからsshでログインして使うことができる。

Interfaceと言う雑誌の2012年6月号に、Cortex-M3が乗ったfm3マイコン基板と言う付録がついていたので、購入したまま寝かせていた。
最近無電圧の接点出力が欲しくて、簡単な電子工作をしたくていろいろ試していた。接点の先に何が繋がるかわからないので、CPUのGPIOの出力に直接繋ぐわけにはいかず、リレーと、リレードライブ回路をCPUに繋ぐ必要があることがわかった。
まずは Raspberry pi を購入してちょっと遊んでみたが、RaspbianはLinuxなので、終了処理をちゃんとやってあげないとファイルシステムが壊れるのではないかとの不安があった。
そこで、fm3基板があったことを思い出し、若松通商で「FM3 マイコン基板 部品キット」を購入。
たくさん部品が付いてきたが、全部ハンダ付けするのは骨が折れると思い、最低限必要な部品をセレクトした。
  • JP1〜JP3(ピンヘッダ)
  • リセットスイッチ
  • CN4(7PIN×2列ピンヘッダ)
  • 32.768kHz水晶振動子
  • リセットIC
  • CN5(10PIN×2列ピンBOX型ヘッダ
  • 2.2μHインダクタ
  • USBホストコネクタ標準A
を選択。CN1〜CN4の中で、CN4のみを選択したのは、CN4にはVCC/GNDとGPIOの入出力が揃っているため、使い勝手が良いと判断したため。
まずは、リセットスイッチと2PINコネクタ付ケーブルをハンダ付け。黒いビニールチューブが付いてきていたので、半分に切ってケーブルに通した状態でハンダ付けした。
続いて、JP1〜JP3のピンヘッダをハンダ付けするために、3PIN×2列のピンヘッダを折って3つに分ける必要がある。
雑な性格なので、ニッパーでピンヘッダを折ろうとしたところ、一つ目は飛んでいって行方不明になり、2つ目は壊してしまい、一つしか残らなかった。
JP1とJP2の分は最低限必要なので、使わないことにした44ピンのピンヘッダを折って使うことに。
同じ失敗をしないように、カッターで切れ込みを入れて、ラジオペンチで挟んで折ってみた。
次に、部品を基板に嵌めてみて、「背の低いものから」ハンダ付け開始。
しかし、この基板はハードウェア初心者向けでは絶対ない。
32.768kHzのクリスタルなんて、ピンの幅が2mmくらいしかない。
泣きながらハンダ付けしつつ、JTAG(CN5)と電源系(インダクタのハンダ付けと、パターンカットとハンダ盛り)を残してギブアップ。
とりあえずJP1とJP2がついていればLEDをつけるくらいはできるはずなので、USBケーブルを探してきてMacに繋いでみる。
うんともすんとも言いません。
基板をよく見てみると、リセットICの足のハンダが、隣のC22と短絡しているように見えたので、修正したりしてみる。
が、やはりうんともすんとも・・・。
いろいろやる前に、最初にUSBケーブルを繋ぐくらいはやっておくべきだった・・・。
その日はそのまま諦めて、後日別のPCに別のケーブルで繋いでみたところ、USB機器として認識。冷やしたのが良かった?
さて、これでハードの準備ができたので、次は載せるアプリが必要。
デフォルトの開発環境は、KEILのMDK(μVision)で、基板のflashにプログラムを焼くのは富士通提供のFLASH USB DIRECT。
しかし、雑誌が出てからの2年の間に、μVisionは4から5にバージョンが上がり、fm3は富士通からSpansionに売却されてしまっていた。
富士通のfm3のページにはSpansionに売却された旨の記載があり、Spansionへのリンクがあったので、Spansionからデータシートやペリフェラルマニュアル等をダウンロードし、FLASH USB DIRECTをダウンロード。
ダウンロードには個人情報の提供が必要だ。
μVisionの方も、KEILに個人情報を提供すると、期間制限版か容量制限版の試用版がダウンロードできる。
雑誌のサンプルプログラム(SysTickタイマ割り込みLED点灯制御サンプル・プログラム)は、μVision5でもそのままビルドできるので、ビルドするとhexファイルが出来上がる。
基板のJP1にショートピンを刺した状態でUSBでPCと繋ぐと、USB機器として認識されるので、USB DIRECT Programmerのインストールディレクトリのdriverの下にあるデバイスドライバをインストールする。
デバドラのインストールに成功すると、COMポートが増えるので、USB DIRECT Programmerでポート番号を指定する。
Target MCUでMB9BF618S/Tを選択し、先ほどできあがったhexファイルを指定して、Full Operationボタンを押す。
実機をリセットしてOKを押せ、と言われるので、JP2に繋いだリセットスイッチを押す。
少し待ってからOKを押すと、flashの書き込みが行われる。
JP1のショートピンを外し、再度リセットすると、無事に基板上にあるLEDが点滅した。
ここまで来るのにすごく時間がかかっていて、ハマりポイントを列挙しておく。
  • JP1がショートしている状態でないと、USBケーブルを繋いでもUSB機器として認識されない。(JP1がショートしていなくても、USBデバイスとして動作するようなアプリが書かれていれば別だが)
  • Mac上のVMware Fusion 上のWindowsにつなごうとしてもうまくいかない。Fusion 4系でも6系でも駄目。デバイスとして認識して、デバイスドライバのインストールまでいけるが、その先が駄目だった。
長くなったので、続きは別のエントリで。
さて、KEIL MDKでビルドできるようにはなったけど、試用版だと作成できるプログラムに32kBの制限がある。また、scatterファイルも使えないみたいな記述もある。なにより、ダウンロードするのに登録が必要なのが嫌だ(したけど)。
他の開発環境としては、IAR Embedded Workbench と言うのもあるが、こちらも登録が必要&機能制限版だ。
他にないかと思って調べていた所、マイコン風雲録: arm-none-eabi-gcc / 2012年メモと言うページを発見。GCC ARM Embedded in Launchpadと言うものがあるようだ。
これは、本家ARMの人が開発に携わっていて、登録不要でダウンロードできる。さらに、WindowsのみでなくLinux用やMac用も存在する。
早速、上記ページからMac用の gcc-arm-none-eabi-4_8-2014q1-20140314-mac.tar.bz2 をダウンロードし、$HOMEに展開、$HOME/gcc-arm-none-eabi-4_8-2014q1/bin に PATH を通す。
前回MDKで利用したSysTickタイマを使ったLED点滅プログラムを試そうと思ったが、includeしているmcu.hと、それがincludeしている各種ヘッダがないため、そのままだとビルドできない。
そこで、まずは予習。fm3のデータシートと、ペリフェラルマニュアル、前回のサンプルプログラムと、それがincludeしているヘッダファイルを読む。

メモリマップ

メモリマップは、データシートに載っている。
知っておかないといけないことは、以下くらいか。
  • flash ROM は、1Mbyteで、0x0000_0000〜0x000f_ffff
  • SRAMは64kbyteの領域が2つあり、0x1fff_0000〜0x0x1fff_ffffと0x2000_0000〜0x2000_ffff
  • ペリフェラルは0x4000_0000〜0x43ff_ffffに割り当てられている

GPIO

GPIOを使うために押さえないといけない情報は、Interfaceのページからダウンロードできる「拡張コネクタピン配置図」と、チップのペリフェラルマニュアルにある。
ペリフェラルマニュアルのレジスタの説明を見ると、IO関連のレジスタとしてPFR, PCR, DDR, PDIR, PDOR, PZRがあることがわかる。(他に、E***もあるが、当面無視)
PFR
ポートをGPIOで使用する(0)か、周辺機器として使用する(1)か
PCR
内蔵プルアップ抵抗を接続する(1)か、切断する(0)か
DDR
入力端子で使用する(0)か、出力端子で使用する(1)か
PDIR
現在のレベル状態を読出し
PDOR
出力レベル設定。1: high, 0: low
PZR
オープンドレイン(1)
雑誌の付属基板の場合、IOポートのPF3(ポートは、16進二桁で表す。PF3は0xF3のポートと言う意味)に負論理で繋がっているらしい。
ここで、負論理とかオープンドレインとか知らない用語が出てくる。
オープンドレインについて調べたところ、RA4の罠がわかりやすかった。このページの最後の図を見ると、意味が理解できると思う。
とにかく、基板上のLEDは、「ポートF3をGPIOで使う設定にし、オープンドレインにし、入出力を出力にし」た上で、出力をlowにすれば点灯し、highにすれば消灯するのだ。

ここまでの前提知識を入れた上でSysTickタイマのサンプルプログラムを見ると、FM3_GPIO->*F_f.P3 にアクセスして上記の内容を実現していることがわかる。
FM3_GPIOの正体は、mb9b610t.h で宣言されている構造体のポインタであり、0x40033000を指している。
この構造体は、レジスタ毎に PFR*_fやPZR*_f のような構造体を持っており、その中に P0〜PFのようなメンバ(ビットフィールド)を持っている。*の部分と、P?の部分でポートを特定するのだ。
さらにこのヘッダを読み込むと、bFM3_GPIO_PFR0_P0 のような define があることに気づく。
コメントには、「Peripheral Bit Band Alias declaration」とある。
上記構造体がビットフィールドでメンバを持っているため、ビット毎にunsigned intでアクセスできるようにしたアドレスエイリアスがあるようだ。
ここまでわかれば、アプリケーションは書けそうだ。後はコンパイル&リンクの方法だ。
まず読むのは、gccのreadme.txt
ここを読むと、アーキテクチャ毎のコマンドラインオプション、libcであるnewlibとnewlib-nano、gcc-arm-none-eabi-*/share/gcc-arm-none-eabi/samplesにサンプルがあることがわかる。
早速サンプルディレクトリを見ると、startupコード、リンカスクリプト、Makefile等のサンプルを見ることができる。
サンプルプログラムのコード自身は、無限ループだったり、printfだったりしてあまり参考にならない。

まずはstartupコード。gcc-arm-none-eabi-4_8-2014q1/share/gcc-arm-none-eabi/samples/startup/startup_ARMCM3.Sを使う。
試しに、MDK用のstartupコード startup_mb9bf61x.s と比較すると、アセンブラの文法が違う!
最初は、MDKのサンプルのstartupコードをそのまま使おうと思ったのだが、アセンブラが文句を言うので諦めた。
startupコードを眺めると、stackセクション、heapセクションに続き、isr_vectorの定義が続く。MDKのと比べると、stack size は0x200と0xc00でgccの方が大きく、heap size は両方共0、isr_vectorはgccの方はSysTick_Handlerで終わっているが、MDKの方はその後にいろいろある。
isr_vectorと言うのは、大雑把に言うとアドレス0x0から配置されるアドレステーブルで、割り込みがあったときにそこに書いてあるアドレスの割り込みハンドラを実行するためのもの。
続いて、Reset_Handler。MDKのものは、SystemInitを呼んで、__mainを呼ぶと言うものだが、gccのものは初期値付データのROMからRAMへのコピーと、BSSの0クリアがあったあとSystemInitの呼出、_startの呼び出しとなる。
__mainも、_startも、ユーザが書くコードではなく、libcに含まれるCのスタートアップルーチンと思われる。
その後は、isr_vectorに並べた割り込みハンドラとして、何もしないDefault_Handlerがweakで定義される。
知識がないので推測だが、ユーザがXXX_Handlerを書いてリンクするとそちらが採用され、書かないとデフォルトハンドラがリンクされるのだと思う。

続いて、リンカスクリプト。gcc-arm-none-eabi-4_8-2014q1/share/gcc-arm-none-eabi/samples/ldscripts/gcc.ld を採用する。
中を見ると、MEMORYと言うセクションにFLASH, RAMと言う定義があり、開始アドレスとサイズが書いてあるので、データシートから読み取った値に変更する。(rename and modify for target · cd4fcca · false-git/fm3)
後は、サンプルのMakefileを参考にMakefileを書く。(fm3/sample1/Makefile at master · false-git/fm3)
そうそう、gccでビルドしてできるのはaxfファイルなので、USB DIRECT Programmerで焼けるように hex 形式に変換してあげないといけない。
調べてみたところ、objcopyを使うと変換できるらしいので、Makefileに書いておいた。
一応 Makefile の解説をしておく。
  • NAME はアプリケーションの名前。この名前の.cがあることを想定していて、この名前の.axf, .hexができる
  • ARCH_FLAGS は readmeに書いてあったアーキテクチャ毎のオプション
  • STARTUP は、startupコードの.o
  • CFLAGS/CXXFLAGS/ASFLAGSは説明は不要か
  • USE_NANO は、newlib-nanoを使うときに定義する。使わない場合は空にする。ちなみに、nanoだとバイナリが2kくらい。nanoじゃないと10kくらいになる
  • USE_SEMIHOSTとUSE_NOHOSTはsemihostかそうじゃないかでどちらを使うか決める。JTAGを持っていないので、NOHOSTの方を使っている(参考: ARM Information Center)
  • GCは良くわからない。サンプルからそのまま
  • MAPはmapファイルの出力を指示する
  • LDSCRIPTSは、リンカスクリプトの指定
  • LFLAGSはリンク時のオプション
と、言うわけでビルドできるようになった一式は、githubに上げてある。(fm3/sample1 at master · false-git/fm3)
あ、sample1.cの説明をしていなかった。
これは単に、基板上のLEDを点灯させるだけのプログラムである。
MDKのサンプルだと、SysTick_Config()とか呼んで、SysTick_Handlerで点滅させていたのだけれど、gccでこの辺が使えるかわからなかったので、点灯させるだけで無限ループに入るようにしてある。
SystemInit()は、startupコードを__NO_SYSTEM_INITを定義せずにビルドすると呼ばれるので、空の関数を入れてある。
次回は、MDKのサンプルが動くように、CMSISをgccで動かす話をしようと思う。
引き続き、gccでSysTickのサンプルがビルドできるようにする。
必要なのは、CMSIS関連のヘッダファイルと、デバイス用のヘッダファイルになる。
上記リンクを見ると、CMSISの仕様とテンプレートは無償でダウンロードできるとある。
しかし、ダウンロードしようとすると、ユーザ登録を求められる。メールアドレスと個人情報を登録すると、しばらくするとアクティベーションのメールが届くので、URLにアクセスすると登録が完了する。
ダウンロードしたのは CMSIS-SP-00300-r3p1-00rel0.zip と言うファイル。
展開すると、ドキュメントと、共通のヘッダ、ライブラリ、デバイス用のテンプレートファイルがある。
残念ながら、ここにはfm3マイコン用の定義は含まれていないようだ。(※ spansionからダウンロードできる)
しょうがないので、SysTickのサンプルや、MDKの中から必要なファイルをかき集めて、なんとかビルドできるようになった。
fm3/sample2 at master · false-git/fm3
かき集めたファイルは、ライセンスがいまいちわからなかったり、CMSISのEULAを読むのが面倒だったので、上記リポジトリには含めていない。READMEにどこから入手するかを書いたので、必要であれば持ってきて欲しい。
RTXカーネルもBSDライセンスだと書いてあるのでダウンロードしてみたが、試してみるのはまた今度にしよう。
諸君、私はprintfデバッグが好きだ。
でネタを書こうと思ったんけど、元ネタがとても長かったので、改変するのも面倒でやめた。

今どきのARMのマイコンの開発であれば、JTAGを使ってIDE上からデバッグができて、printfなど使わなくても変数の中身は見られるし、ブレークポイントははれるし、ステップ実行もできるのだろう。
しかし、私はJTAGを持っていない。fm3マイコンがもう一枚とか、NXPの安いボードを持っていれば、Open OCDを使ってデバッグができるのだろうが、私は持っていない。
そこで、printfデバッグの出番ですよ!となるのだが、printfの出力をどうやって受けるか?と言う問題がある。
雑誌の付録のfm3マイコンは、USBが2ポートと、多数のマルチファンクションシリアルがあるが、マルチファンクションシリアルはレベル変換をしてあげないと通常のPCのシリアルとは繋げないし、そもそも今どきのPCにはシリアルポートがないので、USB-シリアル変換ケーブルなんぞが必要になる。これも個人では持っていない。
よろしい、ならばUSBだ!(改変を諦めたとか言いながら引きずってる)
基板にあるミニUSBは、FLASH Programmerで書き込みをした後は電源供給にしか役に立っていない。
これを使わない手はないだろうと思って調べてみたところ、さすがUSB、通常のシリアルのように、RxDとTxDだけ押さえれば良いと言うような簡単なものではない。端子の抜き差しから、相手とのネゴシエーション、通信まで全部面倒見てやらないといけないらしい。
とりあえず、USBデバイスにはUSBメモリやHDDみたいなmass storageや、USBオーディオのようなクラスと呼ばれるものがあり、シリアル通信を行うものは CDC と言うらしい。
当然、そこら辺にミドルウェアが転がっているよね?と調べてみたが、open sourceの実装は見つけられず。
Keil MDKの場合は、Proを買うとUSB Deviceのミドルウェアが付いてくるが、試用版では当然使えない。
そして、IAR Embedded Workbenchには、Virtual COM Portと言うCDCのサンプル(相手からのデータをエコーバックするもの)が入っていることを発見。
このサンプルが前回作ったgccでビルドできれば、USB経由で夢のprintfデバッグができるようになるのだ。
試行錯誤ののち、なんとか動くようになったので、いつものようにgithubに上げてある。(fm3/sample3 at master · false-git/fm3>
今回のはまりポイントは、以下。
  • intrinsics.h
    IAR EW のヘッダファイルには、intrinsics.hと言うものがあるが、MDKにもgccにも該当するファイルはない。このため、空のファイルを作って、アドホックなdefineを入れてみた。
  • startup_ARMCM3.S
    gccに入っていた startup_ARMCM3.Sだと、isr_vectorが少なくて、今回使うようなUSB関連の割り込みベクタの設定がない。そこで、startup_mb9bf61x.s を参考に、不足している割り込みベクタを補完した。
  • Makefile
    今回ビルドしたコードには、for(int i = ...)みたいなコードがあり、gccのデフォルトだと怒られるので、--std=c99オプションを追加した。
  • arm_comm.h
    これは、IAR EWのプロジェクトに含まれるヘッダなのだが、CriticalSecCntrと言う変数の型が、このヘッダとmain.cで違うためエラーになっていたので型を揃えた。
    また、中にinlineなメソッドがあるのだが、そのままビルドすると何故かリンク時に Undefined Referenceになるので、staticをつけた。
    インラインアセンブラの記述に、asm()を使っていたので、gccで通るように__asm__()にした。(上述のintrinsics.hでdefine)
    ArmV7以前とV7の分岐があったので、V7用のコードがコンパイルされるように、__CORE__を7にdefineした(上述のintrinsics.h)
  • system_mb9bf61x.[ch]
    最初、sample2と同じくSysTickのサンプルから持ってきていたのだが、このコードだと SystemInit()の中でUSB/Etherのクロック設定が行われない。
    そこで、Virtual COM Portのサンプルから持ってきたら動いた。
    SysTickサンプルではなく、Spansionからダウンロードできるtemplateも見てみたが、バージョンは新しいのにUSBクロックの初期化コードや、UCCR等のレジスタのdefineもなかった。
書き出してみるとこんな感じだけど、USBクロックの初期化が足りないのはなかなか気が付かなくて、なんで動かないのか非常に悩んだ。
その過程で調べた、Virtual COM PortのSystemInit()でやっているUSBクロックの初期化について簡単に書いておこう。
基本は、ペリフェラルマニュアルの通信マクロ編である。
  1. UCCRレジスタに0を入れて、UCCRの読出しが0になるまで待つ
    UCCRレジスタに0を入れるということは、USB/Etherのクロック出力を停止していると思えば良い。
  2. UPCR1レジスタに0を入れる
    これは、USB-PLLの発振停止
  3. UPCR2〜UPCR7のレジスタを初期化
    細かく書かないけど、今回大事なのはUPCR6のUSBRに2を入れて、PLLCLKの3分周をUSBのクロックとして使用すると言うこと。
  4. UPCR1レジスタに1を入れ、読出しが1になるまで待つ。
    USP-PLLの発振開始。
  5. UCCRレジスタに0x3Dを入れる
    これも細かいことは割愛するけど、USBのクロックとしてCLKPLLを使うと言う設定。
  6. USBコントローラをonにする前に、5cycleクロック供給
  7. USBEN0/1レジスタに1を入れる
    USBコントローラを有効にする。
PLLCLKは何かって言うと、CLKMO(外部から供給されている4MHzのクロック)にPLLN(36) を掛けて PLLK(1) で割ったもの = 144MHz。これを、上記設定で3分周するのでUSBで使用する48MHzのクロックが得られるらしい。
書いてて自分で何を言ってるのかさっぱりわからないけど。
2014年5月
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

このアーカイブについて

このページには、2014年5月に書かれたブログ記事が新しい順に公開されています。

前のアーカイブは2014年4月です。

次のアーカイブは2014年12月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 6.1.1