研究とか知らないので静岡に帰らせてください(挨拶)

シーズンが終わったら動画をまとめた記事をアップしたりとかしよう…と決意した物の全日本大会が終わるとあっという間に卒業研究の闇に呑まれ、気が付いたら次のシーズンが幕を開けようとしていますが皆様いかがお過ごしでしょうか。
僕は修士課程に進んでも相変わらず研究にヒイヒイ言っていますが追い込み時期の地獄に比べれば気楽だし昨年度に比べれば30倍は真面目に研究してます。たぶん。

今シーズンの機体Greenfield++はどうにか走らなくはない程度のところまで仕上がってきていますが、この機会にRX631におけるSPI通信機能の初期化やら何やらを自分用の覚え書きも兼ねてまとめておきたいと思います。もしミスを見つけましたらツッコミを入れて頂きたく…
あんまり役に立たない気もしますが昨年度書いた簡易SPIの記事はこちら
◆そもそもSPI通信とは
SPI通信に挑もうとしている方は、恐らくシリアル通信を使ったマイコン→PC間のデータ送信によるデバッグやら何やらを経験されているかと思います。
この時に使っているシリアル通信とSPI通信は割と似ている(…と思う)ため、ある程度仕組みが理解出来さえすればかなり取っ付きやすいような気がします。
以下にこれまでのシリアル通信とSPI通信の違いを簡単に挙げてみますと…
  1. 送信線・通信線一組に対して複数のモジュールを接続出来る
  2. 通信に必要な配線が2本から4本(またはそれ以上)に増える
  3. SPI通信ではクロックに同期した送受信を行う
  4. SPI通信では送信と受信が同時に行われる
…と言った感じになるでしょうか。

r01uh0041jj0180_rx63n631_fig38-8
▲RX63Nグループ、RX631グループ ユーザーズマニュアル ハードウェア編 P.1646より引用

SPI通信を用いたシステム図を参考に説明を進めます。
上の図において左側の"マスタ"が普段プログラムの書き込みを行ったり、センサーの値を読み取らせたりと言った作業をしているマイコンです。
右側に並ぶ"スレーブ"がジャイロや加速度計・LCDなどのモジュールであり、これらは"マスタ"からの指示に応じて測定データを送り返したり、何か情報を表示したりするものです。大抵のRXマイコンではRSPIモジュール1チャンネル辺り4つのスレーブを接続できるようになっています(違いその1)

このとき"マスタ""スレーブ"一組の間はRSPCK/MOSI/MISO/SSLの4本で接続されます(違いその2)。これらの役割を説明しますと…
RSPCK: 送受信処理の同期を行うためのクロック線(詳細後述) 
MOSI: "Master Out Slave In"の略。マイコンから見るとデータの送信線
MISO: "Master In Slave Out"の略。マイコンから見るとデータの受信線
SSL: 通信相手の選択用信号線(通常High/通信時Low)。"スレーブ"1個辺り1本必要
これを見てわかる通り、通常のシリアル通信のように「TXDはRXDと、RXDはTXDと接続する」 と言ううっかりミスをやらかしがちな配線をする必要はなく、"マスタ""スレーブ"の間は全て同じ名前のピン同士で接続を行います。親切ですね。

さて、一つ上で説明をぶん投げた"RSPCK"の役割についてですが、これはデータの送信と、送信相手がデータを読み取るタイミングを同期するためのものです(違いその3)
これまで扱ってきたシリアル通信は"調歩同期式"と言うもので、送信線・受信線の2本のみでデータのやり取りを行っています。詳しいことはぶっちゃけ僕も知識的に怪しいので省きますが、この方式ではデータの送信側(例:マイコン)と受信側(例:パソコン)で送受信速度を予め合わせて設定しておかないとデータの読み取りタイミングが合わず、結果文字化けしたりした滅茶苦茶な内容が表示されることになります。
対してSPI通信では、シリアル通信で言うところの"クロック同期式"と言う方式で送受信を行っています。
r01uh0041jj0180_rx63n631_fig35-20
▲RX63Nグループ、RX631グループ ユーザーズマニュアル ハードウェア編 P.1426より引用

クロック同期式の通信では、送信側からデータと、通信速度に合わせたクロックの2つを送り出します。このとき、受信側ではクロック波形の変化(上図の場合にはクロック波形の立ち上がり)に合わせて読み取りを行います。
この方式では通信に必要な線が調歩同期式に比べて1本増えますが、受信側のモジュールには通信速度を設定せずとも(スペック上問題ない周期内なら)勝手にクロックに合わせた周期でデータを読み取ってくれます。
 
最後、違いその4について。 
これまで行ったシリアル通信では一方通行の通信しかしない(マイコンからPCへの地図データ等吐き出し)、片方からのデータが送られてくると何かを送り返す、と言った動作が主になるかと思いますが、SPI通信ではデータの送信処理を行うと、これと同時にデータの受信処理が発生します(全二重式シリアル通信, 送信のみ動作に設定した場合を除く)。
どういうことかと言うと、SPI通信では1ビット送信を行うと同時に1ビット受信を行い、1サイクルで"マスタ""スレーブ"の送信データ・受信データレジスタの中身が入れ替わるような仕様になっています。この件が頭から抜けているとデータの送受信関数を作るときにハマります

◆初期設定関数を書こう
DC初年度はこれがどうして良いか全く分からず早々に心が折れました。どの機能にせよそうですが、一度理解してしまえば簡単だけど初めてだと何を設定すればいいのか全くわからん…
データシートのRSPI関係のレジスタ説明にはかなり多くのレジスタが載っていますが、ぶっちゃけ3つ設定するだけで大抵のケースでは動くと思います。
  • RSPIビットレートレジスタ(SPBR): 通常のシリアル通信と同様に設定する
  • RSPIコマンドレジスタ(SPCMDx): 送受信フォーマットの設定
  • RSPI制御レジスタ(SPCR): MSTRビットを1(マスタモード設定) & 送受信時にSPEビットを1(RSPI機能有効化)
ただ、二つ目のSPCMDx(0≦x≦7, 通常0のみ利用のはず)レジスタ(特にCPHA/CPOLビット)の設定が割とややこしく、通信相手のデータシートとかなりにらめっこを行うことになるかと思います。
先ほどの説明で"SPI通信ではクロックに合わせてデータの読み取りを行う"と言う話をしましたが、モジュールごとに読み取りタイミングがクロックの立ち上がりだったり立ち下りだったり、通信を行わないときのクロック線状態はHighだったりLowだったり、挙句の果てにはこれらの条件の組み合わせがモード1/モード2/…などと一覧表にまとまっていると思いきやモジュールの製造会社ごとに統一されておらず滅茶苦茶なケースが有ったり、と言う状況のようなので何と言うか頑張ってくださいと言う感じです。

PS-MPU-6000A-00_v1_p17
▲MPU-6000 and MPU-6050 Product Specification Revision 1.0 P.17より引用

参考として、今回の機体に搭載しているジャイロセンサー、InvenSense製MPU-6000のデータ送信タイミング図を引用しておきます。
この図を見ると、データの読み取りタイミングはクロック(SPC)の立ち上がり、データ無送信時のクロック線状態はHighであることが分かると思います。従って、SPCMD0.BIT.CPHA=1(位相設定ビット, 奇数エッジでデータ変化/偶数エッジでデータサンプル)、CPOL=1(極性設定ビット, アイドル時クロック線はHigh)となります。
 
◆送受信関数を書こう
初期設定が無事に終われば、後は送受信処理さえ書ければジャイロセンサー等からデータが読み取れるようになります。このとき注意すべきと思われる仕様を以下にまとめます。
  1. データを送信したら必ずデータレジスタを読み取り、受信バッファを空にする
  2. データの読み取り・書き込みどちらの場合でも送受信処理は2サイクル行う
  3. アドレスの最上位ビットがR/Wフラグとなっている場合有り
  4. Renesasのサンプルで利用されている送受信ステータスフラグが削除されている
1.と2.について一気に説明します。
SPI通信では読み取りたい/書き込みたいデータの格納場所に対応するアドレス(データシートに書かれてます)を最初に送信し、2回目の送受信で読み取りたいデータの受信、および書き込みたいデータの送信を行います。このとき、違いその4で説明したように、最初の送信処理においてもデータの受信処理が行われているため、適当な変数に代入するなどして読み取り処理を行っておかないと、続く受信処理において受け取ったデータを正しく読み取ることが出来ません。
また、データをスレーブから受信したい場合には2回目の送受信処理で送信するデータはありませんが、この場合でも適当に0を送信するなどして送受信処理を発生させないとスレーブからのデータを受け取ることはできません。
なお、この送受信処理2サイクルで1回の読み書き処理となるため、この2サイクルを終えるまでの間SSLはLowにし続ける必要があると思われます(バースト転送, SPCMDx.BIT.SSLKP=1)。自分の場合はバースト転送を指定した上で送受信関数の冒頭でRSPI機能有効化、末尾で無効化としてSSLのHigh/Lowを切り替えていますが、このときSPCR.BIT.SPE=1としてから多少空ループで待ち時間を設けた方がよい気がします(体験談)。
r01uh0041jj0180_rx63n631_fig38-33
▲RX63Nグループ、RX631グループ ユーザーズマニュアル ハードウェア編 P.1672より引用

3.については下図の通り、今回利用しているMPU-6000や去年利用したL3GD20においてはアドレスの最上位ビットを読み取り時は1、書き込み時は0とする必要がありましたが、これがSPI通信の標準なのかどうなのか僕はよく分かっていません。調べても資料が見つからず、SPI通信を使うモジュールもこの2つしかまだ利用した経験がなく…
PS-MPU-6000A-00_v1_p36
▲MPU-6000 and MPU-6050 Product Specification Revision 1.0 P.36より引用

ここまで説明してきたRSPI機能の有効化やら何やらですが、実はRenesasが用意しているRX周辺クイックラーニングと言うページで説明スライドが閲覧できたりします(ただし要ユーザー登録)。
…が、送受信関数内で処理の完了待ちをするためのフラグとして利用されている受信バッファフルフラグ(SPSR.BIT.SPRF)がRX63N/631ではどうも削除されているようです。スライドのタイトルにはRX63N周辺機能紹介って銘打たれてるのになあおかしいなあ
 
これに関しては、 RSPIステータスレジスタ(SPSR)の空読みをしてからRSPIアイドルフラグ(IDLNF)ビットの状態を監視することで送受信割り込みを使わない代替手段とできるようです(TNRXA147AJ)。現状この手段で送受信関数を実装していますが、記事を書くにあたって上記TECHNICAL UPDATEを再確認しようとしたところ公式の資料が検索に引っかからなくなってました。ぐぬぬ…

以上、一気に書き過ぎて自分でも何が何やらと言う感じになってきてしまいましたが、この記事が初期設定の手助けとなること、記事に重大なミスを書いてしまっておりツッコミが来る事態が起こらないことの2つを祈っていたいと思います…。