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を開発環境として利用していると記載されていました。
ラベル:USB
posted by boochow at 08:00| Comment(0) | Raspberry Pi | このブログの読者になる | 更新情報をチェックする

2018年02月11日

Raspberry Pi ZeroでRaspbianをディスプレイ/キーボードなしでセットアップする

headless-setup.png

Raspberry Pi ZeroやZero Wは小さいのが取り柄なので、マイコンボードのようにディスプレイなしで使いたくなると思います。
通常、Raspbianをセットアップするときだけはディスプレイとキーボードが必要になりますが、その作業を飛ばしていきなりSSHでログインできるようにセットアップする方法があります。

「Headless Setup」で検索するといろいろ出てきますが、以下の記事の通りにやってみたところ、無事ディスプレイ/キーボードなしでセットアップが完了しました。

Use Wifi in latest raspbian lite stretch in headless mode - Raspberry Pi Forums

やり方を抜粋すると、以下のようになります。

1.RASPBIAN STRETCH LITEEtcherでMicroSDカードへ書き込む。

2.いったんMicroSDカードを取り出し、再度PCへ挿入する。

3.MicroSDカードのFAT32のパーティションへアクセスできるので、ルートディレクトリを開く。

4.そこへ「ssh.txt」(または拡張子なしの「ssh」)という空のファイルを作っておく。

5.同じく、ルートディレクトリに「wpa_supplicant.conf」というファイルを作る。

6.wpa_supplicant.confの中身を以下のように編集する。(ssidとpskには、使用したい無線LAN APのSSIDとパスフレーズを入れておく。)
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=US

network={
ssid="Your network SSID"
psk="Your WPA/WPA2 security key"
key_mgmt=WPA-PSK
}

7.(Zero WでUART接続でシリアルコンソールを使いたい場合)config.txtを開き、「dtoverlay=pi3-disable-bt」という行を追記する。(Bluetoothが使えなくなる代わりにUARTが使えるようになります。)

8.MicroSDカードをRaspberry Piに挿入して起動する。

9.UART接続がある場合は、UARTからログインできる。ネットワーク経由の場合、Raspberry PiはIPアドレスをDHCPで取得するので、無線LAN APのログなどで割り当てられたIPアドレスを確認し、sshで「pi@IPアドレス」(パスワードはraspbian)に接続する。

2017-11-29版のRaspbian Stretch LiteとRaspberry Pi Zero Wの組み合わせでは、上記の方法でうまくいきました。最後のIPアドレスを調べるところだけ若干ハードルが高いかもしれませんが、UART接続ができればそれも不要です。

ちなみに、このヘッドレスインストールを試すことになったのは、誤ってRaspbianの入っているMicroSDカードのkernel.imgを別のファイルに上書きしてしまったからなのでした・・・。
別の起動ディスクから起動して、上書きしてしまったMicroSDカードのkernel.imgを復旧する方法が以下で紹介されています。

Manually place kernel.img on boot partition - Raspberry Pi Forums

ちなみに、正しいkernel.imgを単にコピーしなおすだけではうまくいかないはずです。
posted by boochow at 01:33| Comment(0) | Raspberry Pi | このブログの読者になる | 更新情報をチェックする

2018年02月10日

Raspberry Pi 3でのベアメタルプログラミング

rpi3.jpg

Raspberry Pi 3はパワフルすぎて、かえってPCとの差分が小さいから魅力が薄い、と思っていた時期もあったのですが、結局入手しています。
直接のきっかけは最近公開された、下記のPi3専門のベアメタルチュートリアルです。

Yet Another Bare Metal Tutorial for the RPi3 - Raspberry Pi Forums

bztsrc/raspi3-tutorial: Bare metal Raspberry Pi 3 tutorials

このチュートリアルでは、例外や仮想メモリを扱っているのが興味深いです。
また、クロスコンパイラの導入から解説されていますし、コンパイル済みのバイナリもアップロードされており、かなり敷居が低くなっていると思います。

なお、上記GitHubサイトのREADMEでは、他のベアメタルチュートリアルについても紹介されており、それぞれ微妙に扱っている分野が違っていて、参考になります。
一番最初に挙げられているケンブリッジ大学のサイト「Baking Pi」は、USBキーボードからの入力や画面表示がメインなので、ベアメタル版MicroPythonへ移植したいと思っています。

最近では、Raspberry Piの中で3だけに対応しているソフトウェアも見かけることが増えてきましたので、そちらも気になっています。
64bit OSがRPi3専用なのは当然ですが、たとえば「Android Things」もRPi3のみ対応ですし、マニアックなところではオープンソースのTEEであるOP-TEEなんかもそうです。
そんなわけで、1台持っておくことにしたのでした。
posted by boochow at 00:31| Comment(0) | Raspberry Pi | このブログの読者になる | 更新情報をチェックする

2018年02月03日

STM32のバイナリをQEMUで動かしてみた

qemu-stm32.png
Raspberry PiのベアメタルプログラミングではQEMUを使うことができましたが、同様にしてSTM32のソフトウェアもエミュレータで動かすことができます。
オリジナルのQEMUはSTM32のボードをサポートしていませんが、ここからフォークしたGNU MCU Eclipse用のQEMUでは、いくつかのSTM32ベースのボード(と、Cortex-m7)をサポートしています。

The GNU MCU Eclipse QEMU

Windows版のQEMUをダウンロードして、SW4STM32でビルドしたバイナリを動作させてみました。
最新版では現在Windows版がありませんが、以前のバージョン(私はv2.8.0-20161227を使いました)で問題ありません。

サポートされているボードの中から、NUCLEO-F411REを使ってみることにしました。
CubeMXを使って、Lチカを作成します。
F411REではオンボードLEDがPA5に接続されていますので、メインループを
  while (1)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
HAL_Delay(500);
}
としました。

ビルドして、QEMUで起動します。オプションは

C:\>"C:\Program Files\GNU ARM Eclipse\QEMU\2.8.0-201612271623-dev\bin\qemu-system-nuarmeclipse.exe" -verbose -board NUCLEO-F411RE --image qemu-test-f411re.bin
のように指定します。最後のbinファイルはビルドしたバイナリファイルです。

すると、
GNU ARM Eclipse 64-bits QEMU v2.8.0 (C:\Program Files\GNU ARM Eclipse\QEMU\2.8.0
-201612271623-dev\bin\qemu-system-gnuarmeclipse.exe).
Board: 'NUCLEO-F411RE' (ST Nucleo Development Board for STM32 F4 series).
Device: 'STM32F411RE' (Cortex-M4 r0p0, MPU, 4 NVIC prio bits, 86 IRQs), Flash: 5
12 kB, RAM: 128 kB.
Image: 'qemu-test-f411re.bin'.
Command line: (none).
Cortex-M4 r0p0 core initialised.
Cortex-M4 r0p0 core reset.

C:\Program Files\GNU ARM Eclipse\QEMU\2.8.0-201612271623-dev\bin\qemu-system-gnu
armeclipse.exe: Attempt to set CP10/11 in SCB->CPACR, but FP is not supported ye
t.

というようにエラーで止まってしまいました。
エミュレータがサポートしていないFPUを利用しようとしたため、ということのようです。
そこで、ソースコード中でこの処理を行っている部分(system_stm32f4xx.c)を以下のようにコメントアウトして再度ビルドしたところ、うまく動作しました。
void SystemInit(void)
{
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
// SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif

本当はこのあと、GDBに接続させてQEMU上のバイナリをデバッグしてみたいところですが、SW4STM32にGNU MCU EclipseのQEMU Debuggingプラグインを入れただけではうまく動作しませんでした。
posted by boochow at 14:25| Comment(0) | stm32 | このブログの読者になる | 更新情報をチェックする
人気記事