クイック ノート
ビルド イベント
Raspberry Pi Model 3Bで調査用プログラムの動作確認をしていると、何かの拍子にGPIO17(普通のデジタル信号)が使えなくなり、GPIOの使用状況を調べると、GPIO17のコンシューマがSysfsになっている。なんで勝手に使っているのか?ラズパイの中にゴーストでもいるのか?と思い、更に調べると、原因はVisual Studioで新規作成したプロジェクトの「リモートのビルド後イベント」でした。Raspberry Pi プロジェクト テンプレートからプロジェクトを生成すると、ARMプラット フォームの「リモートのビルド後イベント」に"gpio export 17 out"が登録されるようで...。
ここで、一句、「親切も、余計な時が、あるのです。」
Raspberry Pi Model 4B 5×SPI
ネット上に「RasPi 4BのSPI有効化には縛りがある」との情報があり、今後の開発作業に影響があるかも知れないと思い、Raspberry Pi Model 4BのSPI0とSPI3~6の同時有効化(同時使用)の可不可を確認しました。
確認に使用したRasPiのリビジョンとOSは以下の通りです。
- Raspberry Pi 4 Model B Rev 1.4
- Raspberry Pi OS 10 Buster 64BITβ(2021-05-28 16:08に公開された image でインストール)
この記事を書いている時に気づいたのですが、2021-11-08 07:49公開の新しい image があるようです。
SPI0とSPI3~6を同時有効化(同時使用)する為の設定は、以下の通りです。
/boot/config.txt に以下の設定行を追加
dtoverlay=spi0-2cs,cs1_pin=17
dtoverlay=spi3-2cs
dtoverlay=spi4-2cs
dtoverlay=spi5-2cs
dtoverlay=spi6-2cs
設定後にリブートして、ls /dev/spi* を実行すると、デバイス ファイルが生成されていることを確認できました。
/dev/spidev0.0 /dev/spidev3.0 /dev/spidev4.0 /dev/spidev5.0 /dev/spidev6.0
/dev/spidev0.1 /dev/spidev3.1 /dev/spidev4.1 /dev/spidev5.1 /dev/spidev6.1
念のため、C/C++言語でテスト プログラムを作成して、実際に通信できるかも確認しました。
テスト内容
- SPI0.0,SPI3.0,SPI4.1,SPI5.0,SPI6.1をオープン
SPI0.0 : クロック4MHzでICM-20948と接続
SPI3.0 : クロック4MHzでRaspberry Pi Picoと接続
SPI4.1 : MOSIとMISOを接続(クロック4MHzで折り返し)
SPI5.0 : MOSIとMISOを接続(クロック4MHzで折り返し)
SPI6.1 : MOSIとMISOを接続(クロック4MHzで折り返し) - SPI0.0で一連のICM-20948初期化が正常完了することを確認
- SPI3.0でRaspberry Pi Picoと64バイト長のデータを全二重通信できることを確認
- SPI4.1で折り返し通信ができることを確認
- SPI5.0で折り返し通信ができることを確認
- SPI6.1で折り返し通信ができることを確認
(SPI4,6でCS1を指定しましたが、そもそもCS信号を見ているデバイスが存在しないので、特に意味がある訳ではありません。)
Raspberry Pi Model 4BのSPI0とSPI3~6の同時有効化(同時使用)は、特に縛りなくできるようです。(OSに修正が入ったのかも知れません。)
Raspberry Piのspidevクロック設定
SPI0に ioctl (SPI_IOC_WR_MODE)でクロックの極性と位相を設定する際、戻り値が「正常完了(0)」となっていたので気にしていなかったのですが、ioctl (SPI_IOC_RD_MODE)で設定値を読み取ると実際に設定した値 + 0x04の値が取得されることに気づきました。電源ON直後の状態を読み取ると0x04が取得されます。SPI1の場合は設定した値が取得されます。(モデル:3B、OS:Raspbian 32Bit Release 10)
Raspberry Pi 3/4のSPI1とSPI2は補助的?
SPI0で接続されたICM-20948と通信を行うプログラムを、SPI1接続に変更して実行すると初期化でエラーとなる事例が発生しました。(モデル:3B、OS:Raspbian 32Bit Release 10、SPIのクロックは4MHz)
SPI1接続に変更するために行った対応は以下の通りです。
- /boot/config.txt に dtoverlay=spi1-3cs を追加後にリブート
- ls /dev/spi* で /dev/spi1.0~2が表示されることを確認後にシャット ダウン
- 配線をSPI0からSPI1に変更
MOSI : 物理ピン38、MISO : 物理ピン35、SCLK : 物理ピン40、CE0 : 物理ピン12 - プログラムの spidev オープン時のデバイス名指定を "/dev/spidev0.0" を "/dev/spidev1.0" に変更
BROADCOMのARM PerifheralsのドキュメントのSPI1/2とSPI0/3/4/5/6に関する記載が別の章になっていることは認識していたのですが、「想定している使用範囲では同じ」と思い込んでしまったことが原因でした。
具体的には、クロックの極性と位相の設定で、CPHA=1を指定できないことが原因で、結論として SPI_MODE_1と SPI_MODE_3を指定できないと言うことのようです。(既存のプログラムは、SPI_MODE_3 を指定していました。)
In risingとOut risingが位相用の設定レジスタのような気がするのですが・・・?
SPI_MODE_0を指定すると通信できるようになりました。(ビットの状態を取り込むタイミングは同じになるのか・・・)
spidev の spi_ioc_transfer構造体
名称 | 説明 |
tx_buf | 送信データ格納領域の先頭アドレス. |
rx_buf | 受信データ格納領域の先頭アドレス. |
len | 転送(送受信)サイズ.(単位はバイト) |
speed_hz | 転送時のSPIクロック周波数. |
delay_usecs | 最後のビットを送信し終えてからCSを非アクティブ化するまでの時間. |
bits_per_word | ワードのビット サイズ. |
cs_change | 0 : spi_ioc_transferデータのエレメント毎にCSを非アクティブ/アクティブ化しない. |
tx_nbits | 並列に送信するビット数. |
rx_nbits | 並列に受信するビット数. |
word_delay_usecs | ワード間で待機する時間.(マイクロ秒単位) |