2018年02月18日

Raspberry PiのベアメタルUSBドライバの信号を観測してみた

usbsignal2.jpg

以前調査したように、Raspberry PiのUSBコントローラのドライバには何種類かあり、最もシンプルな「csud」はベアメタルで使うには良さそうですが、Raspberry Pi Zero WではUSB Hubを使わないとデバイスが接続できないという問題がありました。

そこで、昨日作った治具

(A) Raspberry Pi Zero W → 治具 → USBキーボード
(B) Raspberry Pi Zero W → USBハブ → 治具 →  USBキーボード

のそれぞれでcsudを動作させてUSB信号を観測してみたところ、どうやら原因が解ったような気がします。

エラーはデバイスを接続した時点で初期化に失敗するというもので、以下のリンク先の記事にあるSETUPステージで起こります。

USBの基礎知識 ――パケットのフォーマットからプロトコルの詳細まで|Tech Village (テックビレッジ) / CQ出版株式会社

通信内容を(A)と(B)で比較してみたところ、(A)では(B)にはないエラーパケットが観測されました。
(B)では、エラーパケットはフィルタされてUSBキーボードへは送られていませんでした。

usbpacket.png

Error Packetを除けば(A)と(B)の違いはありません。
このパケットをUSBキーボードが解釈できないため、初期化が失敗しているようです。

このError Packetの中身を見てみると、以下のように規則正しい信号になっています。
つまり、ノイズ等によるエラーパケットではありません。
usb-split.png

出現位置も決まっていて、
00000001 00011110 10000000 00000001 00010101
SETUP DATA0 ACK
00000001 00011110 10000001 00000001 00001110
という具合に、SETUPの前後にエラーパケットが入っています。

1バイト目はSYNC、2バイト目はPID、最後はCRCというUSBパケットの形式に沿っていますので、エラーではなくて何かの信号だろうと思われましたので、調べてみたところ、これはUSB2.0で導入されたSplitパケット(PID=0001)だと解りました。
Error Packetと表示されていたのは、解析ソフトがUSB1.1(Low Speed/Full Speed)にしか対応していないためのようです。

USB Protocol: Types of USB Packets and USB Transfers | EngineersGarage

High Speed(480Mbps)で行うUSBハブとの通信を、Start Split(SSPLIT)とComplete Split(CSPLIT)で挟むことにより、USBハブ下部の低速なデバイスとの通信もホスト-USBハブ間ではHigh Speedで行えるようにする機能だそうです。

Split Transaction | ルネサス エレクトロニクス

USB規格書を見ると、SSPLIT、CSPLITは以下のようなフォーマットになっていました。
usb-split1.png

Hub AddressとPortは左のビットが低位ビット、SCは0ならStart、1ならCompleteです。
SとEは組で、High SpeedとFull Speedのデータ送信順を示すようです。
usb-split2.png

ETはEndpointのType、UはUnusedです。
usb-split3.png


この情報を元に、上記のError Packetの中身を見てみると、SETUPの前に送られているパケットがHub address = 1、StartSplit、Port = 0、High Speed Dataが先頭、エンドポイントタイプはControl、というパケットであることがわかります。
同様に、SETUPの後に送られているのは上記に対応するCompleteSplitパケットとなります。


本来、USBハブとの通信だけに使用するはずのSplitですが、csudドライバでは本体に直接接続されるデバイスでは常に使用されるようです。
これはcsudドライバが初代Raspberry Piを前提としているためと思われます。
初代Raspberry PiはオンボードにLAN9512チップが搭載されています。
このチップはEthernet兼USBハブになっていますので、初代Raspberry PiではBCM2835の下部には必ずUSBハブが接続されていました。
rpi1usb.png

逆にUSBハブが無いモデルはEthernetポートが無いモデル、すなわちModelA、A+、Zero、Zero W、Compute Moduleです。
これらのモデルにcsudを使ったソフトウェアを載せて、USBハブ抜きで直接デバイスを接続しようとした場合、上記の問題が起こると思われます。

これらのモデルでcsudを動かすには、ポートにUSBハブを接続した場合とそれ以外のデバイスを接続した場合で処理を分けるように、コードを追加する必要があります。
csudの中身をもう少し調べて検討してみようと思います。
posted by boochow at 10:54| Comment(0) | Raspberry Pi | このブログの読者になる | 更新情報をチェックする

2018年02月17日

700円ロジアナでUSBパケットを観測してみた

usbsignal.jpg

昨日使ってみたロジアナですが、Salae Logicのプロトコル解析機能にはUSBもあることに気付きました。これはAnalog Discoveryには無い機能です。

この機能を使えば、先日Raspberry Piのベアメタルプログラミングでぶつかった、USBハブを通さないとキーボードが認識できない問題の解析に役立つかも?と思い、上の写真のようなD+とD-を外部から観測する冶具を作って試しに使ってみました。

右向きについているのがUSBオス、上向きについているのがUSBメスのコネクタです。
どちらもaitendoで購入した「基板with USBコネクタ」シリーズで、2P-UAF-S092P-UAM19です。同様の製品は各種あるのですが、こういう目的には基板に信号名がシルク印刷してあるものが良いと思います。

キャプチャしたUSB信号はこんな感じで表示されます。
salae2.png

解析できる信号はUSB FS(12Mbps)とLS(1.5Mbps)です。サンプリングレートが24Mspsなので当然ですが、480MbpsのHSは計測できません。
また、解析結果も、バイト列、パケット、コントロール転送までで、デバイスに特化したプロトコルの解析はできません。
とはいえ、USBプロトコルスタックのデバッグにはとても役立ちそうな気がします。
posted by boochow at 14:33| Comment(0) | 日記 | このブログの読者になる | 更新情報をチェックする

意外と使える?700円ロジアナ

salaelogic.jpg

下記の記事を見て、以前購入したロジアナがあったことを思い出し、使ってみました。

sigrokをUSB接続ロジアナで使う - 記憶は人なり

このロジアナですが、Aliexpressで2年半ほど前に購入したものの、封も切らずに放置していました(当時の価格$5.8)が、その後購入したAnalog Discoveryにもロジアナ機能があるため、ますます放置してしまっていました。

上記の記事のものと違って、LEDが一応あり、GNDが2つではなくCLKとGNDになっていますが、価格からして中身には大した違いは無いものと思われます。
上の写真はRaspberry Pi Zero Wと一緒に写しています。消しゴムサイズという感じの小ささです。
8ch、24MHzで測定が可能です。

Salae Logicというラベルが付いていますが、たぶんパクリ品だと思われます。
が、Salae Logic用のソフトウェアでも一応動作しました。
salae.jpg


上記の記事で紹介されているsigrok pulseviewというソフトでも動作しましたが、デバイスドライバがなぜか安定しない感じでした。
機能的にはどちらのソフトでも、ちょっとI2CやSPIの信号をデコードしてみたいという用途には十分そうな感じがします。
pulseview.png

上の2つのソフトは、どちらもRaspberry PiのI2C信号をデコードしているところです。
小さくて取り回しが良いので、Analog Discoveryを持っていても、これはこれで便利かなと思いました。
posted by boochow at 01:21| Comment(0) | 日記 | このブログの読者になる | 更新情報をチェックする

2018年02月12日

無線で調光できるLED電球の中身

led-light1.jpg

以前購入した、カラーをリモコンで変更できるLED電球「Mi.Light RGBW」の中身です。
RGBのLEDが4つと、白色LEDが15個搭載されています。

この手の製品ではPhilipsのhueが有名ですが、MiLightはhueよりかなり安価に入手できます。
しかし、私が入手したものはなぜか動作せず、放置していました。
3年ぶりくらいに引っ張り出してきて調べてみたら、口金が海外仕様のE27でした。
それが原因で接触不良だったのだと思われます。

それで、どうせ捨てるなら、とカバーを開けてみました。
カバーはホットボンドのようなもので固定されているだけですので、力を入れれば外れます。

led-light2.jpg


中央に2.4GHzのアンテナがあり、それ以外にチップが2つ載っています。
1つはSTMicroのロゴが見えます。パッケージはTSSOP-20です。
型番が隠されてしまっていますが、8S00という字が見えますので、8bitコントローラのSTM8S00シリーズかと思われます。調べてみたらTSSOP20の製品ラインがあるのはSTM8S003シリーズでしたので、おそらくそのあたりでしょう。
もう1つはPL1167と書かれており、こちらはSPI接続の2.4GHz無線モジュールで、割とメジャーなチップのようです。
PL1167で検索してみたら、MiLightをArduinoから制御している方もいました。

pmoscetta/authometion-milight: Arduino library for MiLight and Limitless led bulbs control using a LYT/WiFi shield or a PL1167 pcb module

Milight PL1167 control - Arduino Projects4u

PL1167でなく、nRF24シリーズやnRF51シリーズで制御している方もいるようでした。

Controlling the Mi Light from Arduino or NodeMCU

henryk/openmili: Open implementation of the Mi-Light 2.4GHz LED light control protocol

MiLightの通信プロトコルのバージョンアップ版を解析している方もいます。

Reverse engineering the new Milight/LimitlessLED 2.4 GHz Protocol | Chris Mullins

電子工作の例題として、面白いかもしれませんね。
posted by boochow at 18:12| Comment(0) | 日記 | このブログの読者になる | 更新情報をチェックする

Raspberry PiベアメタルプログラミングでのUSBキーボード入力の調査

以前、Raspberry PiベアメタルでMicroPythonの調査をしたときに
ステップとしてはまずUARTからREPLを叩けるようにし、そのあと画面出力、次にUSBへと進んでいくべきでしょう。

と書きましたが、UARTからREPLを叩くところまでは一応できていますので、今回はUSBキーボード入力についてまとめておきます。

まず、Raspberry PiにはUSBホストコントローラが搭載されていますが、このコントローラはSynopsys社のIPコアを利用していることがマニュアルに書かれています。
このマニュアルに記載されているのは、Synopsysのコアとの差分のところだけで、それ以外はSynopsysのドキュメントを参照してくれ、となっています。

SynopsysのドキュメントはNDAを結ばないと入手できないもので、公開されているドキュメントはありません

デバイスドライバとしては、現在

・Synopsysが提供しているソースコードからの派生(Raspbian等のLinux系OS)
・ケンブリッジ大学の「Baking Pi」チュートリアルに含まれている「csud」ドライバ
・上記2つを参考にした「Circle OS」用のドライバ
・上記3つを参考にした「ultibo OS」用のドライバ

が公開されています。


まず、Synopsys版ドライバについては、以下のフォーラム投稿記事が詳しいです。

RISC OS Open: Forum: USB stack on Raspberry Pi

Synopsys版をベースにしたLinux用のデバイスドライバのコードはこちらにあります。

linux/drivers/usb/host at rpi-patches ・ raspberrypi/linux

他のドライバもそうですが、IPコアの名称が「DesignWare Hi-Speed USB 2.0 On-the-Go Controller」なので、dwc(おそらくDesignWare Controller)というプレフィックスがファイル名に付いています。

Synopsys版の再配布条件はかなり緩いものになっており、ソースコード(改変可)を再配布する場合はソースコードに記されているライセンス条件を変更しないことが条件になっています。
ドキュメントはソースコードからdoxygenで生成したものがあります。
以下の解説を見るとThreadが必要であるらしく、ベアメタル環境へ移植するにはその部分をどうするかが課題になりそうです。

Synopsys DWC Portability and Common Library for UWB

派生の一つにxinu-osのドライバがあります。(未調査)
ライセンスはBSD3となっています。

xinu/system/platforms/arm-rpi at master ・ xinu-os/xinu

Linux版よりシンプルになっているように思われますが、OSの一部なのでライブラリとして切り離して扱えるかどうかは分かりません。


csudはAlex Chadwickという方が作成したライブラリです。
ライセンスはMITライセンスです。
Baking PiチュートリアルのLesson 10、Lesson 11がUSBキーボード入力を扱っています。
ライブラリの使い方も詳しく解説されています。
このチュートリアルはプログラミング言語としてアセンブラを使っていますが、ライブラリはCで書かれています。

チュートリアルのダウンロードページでサンプルごとダウンロードできるほか、ライブラリ単体でも以下のGitHubで公開されています。

Chadderz121/csud: Chadderz's Simple USB Driver for Raspberry Pi

チュートリアルは平易な内容で、非常に読みやすいです。
Lesson 10の内容をCで書いてみると、キーボードを読むループはこんな感じになります。

キー入力結果をUARTへ出力するRaspberry Pi Zero W用のコード全体は以下で公開しています。

bare_matal_rpi_zero/usb_kbd at master ・ boochow/bare_matal_rpi_zero

ただ、このドライバは簡易版のドライバで、バルク転送やインタラプト転送がサポートされていません。
また、手持ちのキーボードをいくつか試してみたところ、Raspberry Pi Zero WのUSBポートに直接接続すると
HCD: Request to New Device (Not Ready) has failed 3 times.
HCD: Transfer was not acknowledged.
HCD: Transaction error in transfer.
HCD: Control message to 0x6380008: 80060001 00001200.
HCD: Request to New Device (Not Ready) failed.
HCD: Could not send SETUP to New Device (Not Ready).
USBD: Verifying New Device (Not Ready) is still connected.
USBD: Yes, New Device (Not Ready) is still connected.
USBD: Failed to get descriptor 0x1:0x0 for device New Device (Not Ready). Result 0xfffffffc.
USBD: Failed to read device descriptor for 2.
HUB: Could not connect to new device in USB Root Hub.Port1. Disabling.
USBD: Deallocating device 2: New Device (Not Ready).
というエラーメッセージが表示されて、デバイスを認識させることができませんでした。
しかし、USBハブを介在させると普通に認識できます。
(Zero W以外ではまだ試していません。)

同様の現象がRaspberry Piフォーラムでも報告されていますが、解決方法は不明です。
csudの64bit対応の派生版もありますが、上記のデバイス認識の問題は変化ありませんでした。

Raspberry-Pi/Arm32_64_USB at master ・ LdB-ECM/Raspberry-Pi

csudはコードは全体でも5000行程度、ドライバの中核であるsource/hcd/dwc/designware20.cは800行あまりと、かなりコンパクトにまとまっています。

オリジナルでは実装されていないバルク転送モードについては、csudに機能追加された下記のフォークが存在しています(未調査)。
バルク転送モードとインタラプト転送モードはよく似ているらしいので、もしかしたらインタラプト転送モードも追加可能かもしれません。

yeqingyan/csud: Chadderz's Simple USB Driver for Raspberry Pi

なお、USBの転送モードの違いについては、USBの技術解説がいくつかありますのでリンクしておきます。

USBの解説(picfun、PDFファイル)
USB通信プログラミングテクニック(picfun)
USBの基礎知識 ――パケットのフォーマットからプロトコルの詳細まで|Tech Village (テックビレッジ) / CQ出版株式会社


次に、Circle OS用のドライバ「USPi」です。
これはCircle OSのドライバ部分を切り出して単独でライブラリとしたもので、以下で公開されています。

rsta2/uspi: A bare metal USB driver for Raspberry Pi written in C

Introducing USPi - A bare metal USB driver written in C - Raspberry Pi Forums

ライブラリのREADMEには、Synopsys版とCSUDを参考にしたと記載があります。
ライセンスはGPLv3となっています。

このドライバもサンプルにキーボード入力がありますので、動かしてみました。(動作にはHDMI接続が必要です。)
こちらはCSUDと違い、USB Hubを介さずともキーボードを認識することができました。
使用方法も、キーボード入力に対するコールバック関数を登録するだけで、かなり簡単です。
また、サポートされるデバイスがMIDIやEthernetなど、CSUDより多いです。
その代わり、CSUDと比べるとかなり規模は大きく、ライブラリが9000行程度、USB以外のサポートライブラリが4000行程度となります。


最後にultibo OSのライブラリです。
ライセンスはLGPL2.1です。
ultibo OSのデモを動かしてみたのでスクリーンショットを載せておきます。
ultibo-demo.jpg

DOS+マルチタスク+フレームバッファという感じでしょうか。

ultibo OSは全体がPascalで書かれています。
個人的には昔Turbo PascalやDelphiを使っていましたので、Pascalに抵抗感はありませんが、正直「今どきPascal?」という気もちょっとします・・・。

それはさておき、ultibo OSのUSBドライバはコアの部分だけでも5000行あります。
ドライバ自体は、Linux版、FreeBSD版、USPiおよびCircle OSのドライバを参考にしたとあります。

Core/dwcotg.pas at master ・ ultibohub/Core

ただ、このソースコードは冒頭にコメントが100行ほどついており、DWCの解説にもなっていますので一読の価値はありそうです。


ということで4種類のUSBドライバを見てきましたが、一長一短ですね。
Linux版はライセンスが緩く機能も完璧ですが(チップの開発元が作っているから当然)、Threadが必要という要件もあり、ベアメタルへの移植は大変(そう)かもしれません。
CSUDはコンパクトで、MITライセンスですので、MicroPythonと一緒に使ってもMicroPython本体への影響が少なくて済みそうですが、USBハブを介さないとキーボードを認識できないのが残念なところです。
USPiは機能的に十分ですが、ライセンスがGPLです。この場合、ベアメタルRPi版MicroPythonは、MicroPythonに統合するのではなくMicroPythonの応用製品という位置づけにしないと、MicroPythonのライセンス(MITライセンス)と不整合が生じます。
ultibo OSはLGPLで、機能もUSPiに近いですが、ultibo OSの他のUnitにも依存しているので、ライブラリとして使うというよりMicroPythonをUltibo OSに移植するようなイメージになると思います。
ちなみに、Raspberry Pi版IchigoJamのREADMEにはultiboを開発環境として利用していると記載されていました。
posted by boochow at 08:00| Comment(0) | Raspberry Pi | このブログの読者になる | 更新情報をチェックする
人気記事