お世話になっております。
CPU:RX113
使用する機能:RSPI
RX113をマスターとし、デバイスとなるFRAMメモリのデバイスIDを読み出すことを考えています。
送出するコマンドは、8ビットの0x9F
このコマンドを送出すると、デバイスより32ビットのデータが返ってくることになっています。
● 現在の設定
コマンド数1、転送フレーム数1
ビット長:8ビット
この設定で、次のコードを実行しますと、図に示しましたように、最後の8ビット( Product ID ( 2nd Byte ) )が欠落してしまいます。
( メモリメーカーが示している、Manufacturer ID,Continuation code,Product ID(1st Byte)までは正しく返されています )
//// FRAM デバイスID 読み込み//
Y_RSPI0_Start(); PORT5.PODR.BIT.B3 = 0; // チップセレクト -> FRAM
while(RSPI0.SPSR.BIT.SPTEF == 0); // RDID コマンド送信 ( 送信バイト数:1、データ:0x9F ) RSPI0.SPDR.WORD.H = 0x009F; // データの送信 while(RSPI0.SPSR.BIT.IDLNF == 1); // 送信完了待ち
RSPI0.SPDR.WORD.H = 0x0000; // ID受信用ダミー(1) while(RSPI0.SPSR.BIT.IDLNF == 1); // 送信完了待ち
RSPI0.SPDR.WORD.H = 0x0000; // ID受信用ダミー(2) while(RSPI0.SPSR.BIT.IDLNF == 1); // 送信完了待ち
RSPI0.SPDR.WORD.H = 0x0000; // ID受信用ダミー(3) while(RSPI0.SPSR.BIT.IDLNF == 1); // 送信完了待ち
RSPI0.SPDR.WORD.H = 0x0000; // ID受信用ダミー(4) <--- この行の送信分が欠けてしまう。 while(RSPI0.SPSR.BIT.IDLNF == 1); // 送信完了待ち
while(RSPI0.SPSR.BIT.SPRF == 0); // 受信バッファフルの確認 (1)
FRAM_DEVICE_ID1 = RSPI0.SPDR.WORD.H; // while(RSPI0.SPSR.BIT.SPRF == 0); // 受信バッファフルの確認 (1) FRAM_DEVICE_ID2 = RSPI0.SPDR.WORD.H;
PORT5.PODR.BIT.B3 = 1; // チップセレクト 解除
Y_RSPI0_Stop();
上記コードを実行した時の、波形
転送フレームが1であるから最後の8ビットが欠けてしまったのであろうと、フレーム数を2にしたら、今度は先頭の8ビットしかデータが返ってきませんでした。
そもそもフレームの理解ができていないのですが、今回のように、送信8ビット、受信32ビットを実行するにはどのようにしたらよいのでしょうか。
ハードウェアマニュアルを読みましたが、正直なところよくわかりませんでした。
大変お手数をおかけしますが、ご教示願います。
※ 一連の質問で未だ受信データの取り込みは解決できておりませんが、先にSPIバスにデータが現れることを確認することを先に進めております。
LEONです。 まず、Y_RSPI0_Start()、Y_RSPI0_Stop()内のRSPIレジスタ設定値をご開示願います。
> 送信8ビット、受信32ビットを実行するにはどのようにしたらよいのでしょうか。
FRAMのコマンド送信時は、8Bit送信のみを行い、送信後、32Bit、全二重同期に 設定を切り替えてはいかがでしょうか。 以下に手順を考えてみました。 Y_RSPI0_Start()後 //-- FRAMのコマンド送信時 --// // 8Bit、送信のみの設定 SPSR.IDLNF== 1は待ち // 0:RSPIがアイドル状態 SPCR.SPE = 0 // 0:RSPI機能無効 SPCR.TXMD =1 // 1:送信動作のみのシリアル通信 SPDCR←0x00 // SPLW=0:ワードアクセス、SPSF=00:1フレーム // SPRDDT=0:SPDRは受信バッファリード SPCMD0←0x0400 // SPB=0100:8Bit、LSBF=0:MSBファースト // 他のBitは必要に応じて調整してください SPCR.SPE = 1 // 1:RSPI機能有効 チップセレクト // RDID コマンド送信 while(RSPI0.SPSR.BIT.SPTEF == 0); RSPI0.SPDR.WORD.H = 0x009F; // RDID(0x9F)コマンド送信 //-- FRAMからのデバイスID(4Byte)を受信時 --// // 32Bit、全二重同期式シリアル通信の設定 SPSR.IDLNF== 1は待ち // 0:RSPIがアイドル状態 SPCR.SPE = 0 // 0:RSPI機能無効 SPCR.TXMD =0 // 0:全二重同期式シリアル通信 SPDCR←0x20 // SPLW=1:ロングワードアクセス、SPSF=00:1フレーム // SPRDDT=0:SPDRは受信バッファリード SPCMD0←0x0200 // SPB=0010:32Bit、LSBF=0:MSBファースト // 他のBitは必要に応じて調整してください SPCR.SPE = 1 // 1:RSPI機能有効 // 32ビットのID受信用ダミー送信 while(RSPI0.SPSR.BIT.SPTEF == 0); RSPI0.SPDR.LONG = 0x00000000; // ダミー送信 //-- デバイスID(4Byte)のリード --// while(RSPI0.SPSR.BIT.SPRF == 0); // 受信バッファフルの確認 FRAM_DEVICE_ID = RSPI0.SPDR.LONG; チップセレクト 解除 SPCR.SPE = 0 // 0:RSPI機能無効 設定切り替え部は、関数化すると良いでしょう。 検証できないので、誤りがある場合はご容赦ください。
おっと、ポーリングの場合 IDLNFチェックの前に(時におまじない的な)SPSR空読みを入れるんだった。 上のポーリング方式は、処理が終わるまで他タスクが実行できないので、割り込み方式をお勧めします。まずは、ポーリング方式のRSPI制御がうまく動作してから、その後どうするか考えましょう。
SA様
RSPI通信などは、特に秘密にする部分も無く公開されていたほうが便利ですよね。
ただ、動作についてはきっちり理解しないと、後々苦労しそうです(笑)
今回のソースコード
● RSPIの初期化 (RX113) 中身はコード生成のままです。今回のポイントとなる箇所にコメントを追加しました
#define参照の部分は膨大になりますので、恐れ入りますが、読んで数値を読み替えてください。
void R_RSPI0_Create(void)
{
/* Disable RSPI interrupts */
IEN(RSPI0,SPTI0) = 0U;
IEN(RSPI0,SPRI0) = 0U;
IEN(RSPI0,SPEI0) = 0U;
IEN(RSPI0,SPII0) = 0U;
/* Cancel RSPI module stop state */
MSTP(RSPI0) = 0;
/* Disable RSPI function */
RSPI0.SPCR.BIT.SPE = 0U;
/* Set control registers */
RSPI0.SPPCR.BYTE = _00_RSPI_MOSI_FIXING_PREV_TRANSFER | _00_RSPI_LOOPBACK_DISABLED | _00_RSPI_LOOPBACK2_DISABLED;
RSPI0.SPBR = _63_RSPI0_DIVISOR;
RSPI0.SPDCR.BYTE = _20_RSPI_ACCESS_LONGWORD | _01_RSPI_FRAMES_2; // フレーム数の既定値が2 、ロングワードアクセス
RSPI0.SPSCR.BYTE = _01_RSPI_SEQUENCE_LENGTH_2; // シーケンスの既定値が2
RSPI0.SPCKD.BYTE = _00_RSPI_RSPCK_DELAY_1;
RSPI0.SSLND.BYTE = _00_RSPI_SSL_NEGATION_DELAY_1;
RSPI0.SPND.BYTE = _00_RSPI_NEXT_ACCESS_DELAY_1;
RSPI0.SPCR2.BYTE = _00_RSPI_PARITY_DISABLE;
RSPI0.SPCMD0.WORD = _0000_RSPI_RSPCK_SAMPLING_ODD | _0000_RSPI_RSPCK_POLARITY_LOW | _0000_RSPI_BASE_BITRATE_1 | _0000_RSPI_SIGNAL_ASSERT_SSL0 | _0000_RSPI_SSL_KEEP_DISABLE | _0400_RSPI_DATA_LENGTH_BITS_8 | _0000_RSPI_MSB_FIRST | _0000_RSPI_NEXT_ACCESS_DELAY_DISABLE |
_0000_RSPI_NEGATION_DELAY_DISABLE | _0000_RSPI_RSPCK_DELAY_DISABLE;
RSPI0.SPCMD1.WORD = _0000_RSPI_RSPCK_SAMPLING_ODD | _0000_RSPI_RSPCK_POLARITY_LOW | _0000_RSPI_BASE_BITRATE_1 | _0000_RSPI_SIGNAL_ASSERT_SSL0 | _0000_RSPI_SSL_KEEP_DISABLE | _0200_RSPI_DATA_LENGTH_BITS_32 | _0000_RSPI_MSB_FIRST | _0000_RSPI_NEXT_ACCESS_DELAY_DISABLE |
/* Set SPEI0, SPRI0, SPTI0 and SPII0 priority level */
IPR(RSPI0,SPTI0) = _0F_RSPI_PRIORITY_LEVEL15;
/* Set RSPCKA pin */
MPC.P51PFS.BYTE = 0x0DU;
PORT5.ODR0.BYTE &= 0xF7U;
PORT5.ODR0.BYTE |= 0x04U;
PORT5.PMR.BYTE |= 0x02U;
/* Set MOSIA pin */
MPC.P50PFS.BYTE = 0x0DU;
PORT5.ODR0.BYTE &= 0xFDU;
PORT5.ODR0.BYTE |= 0x01U;
PORT5.PMR.BYTE |= 0x01U;
/* Set MISOA pin */
MPC.P52PFS.BYTE = 0x0DU;
PORT5.ODR0.BYTE &= 0xDFU;
PORT5.ODR0.BYTE |= 0x10U;
PORT5.PMR.BYTE |= 0x04U;
RSPI0.SPCR.BYTE = _01_RSPI_MODE_CLOCK_SYNCHRONOUS | _00_RSPI_FULL_DUPLEX_SYNCHRONOUS | _08_RSPI_MASTER_MODE;
}
● SPI通信の前処理
void Y_RSPI0_Start(void){
// ポーリング用のSPI通信前処理( 割り込み無し )
volatile uint8_t dummy;
/* SPEビットの許可 */ RSPI0.SPCR.BIT.SPE = 1;
/* Clear error sources */ dummy = RSPI0.SPSR.BYTE; // 読み込んでから書くための処理 ハードウェアマニュアルに説明あり RSPI0.SPSR.BYTE = 0xA0U;
/* Disable idle interrupt */ RSPI0.SPCR2.BIT.SPIIE = 0U; // アイドル割り込み要求の発生を禁止
● SPI通信の後処理
void Y_RSPI0_Stop(void){
// ポーリング用のSPI通信後処理( 割り込み無し ) RSPI0.SPCR2.BIT.SPIIE = 0U;
/* Disable RSPI function */ RSPI0.SPCR.BIT.SPE = 0U;}
● 参考例1.富士通製 FRAMのステータスレジスタの読み取り コマンド数1、フレーム数1
//// FRAM ステータスレジスタ 読み込み//
RSPI0.SPDCR.BIT.SPFC = 0x00; // 1フレーム 初期化の既定値は2フレームなので、ここで1フレームに変更する RSPI0.SPSCR.BYTE = _00_RSPI_SEQUENCE_LENGTH_1; // 0 -> 0 -> 0... 初期化の既定値はシーケンス値が2なので、ここで1に変更する
Y_RSPI0_Start(); // 前処理
PORT5.PODR.BIT.B3 = 0; // チップセレクト -> FRAM
while(RSPI0.SPSR.BIT.SPTEF == 0); // RDSR コマンド送信 ( 送信バイト数:1、データ:0x05 )
RSPI0.SPDR.LONG = 0x00000005; // データの送信 8ビットのコマンドを送信する ロングワードアクセスなので、0x00000005 dummy = RSPI0.SPSR.BYTE; while(RSPI0.SPSR.BIT.IDLNF == 1); // 送信完了待ち RSPI0.SPDR.LONG = 0x00000000; // 受信用ダミー送出 dummy = RSPI0.SPSR.BYTE; while(RSPI0.SPSR.BIT.IDLNF == 1); // 送信完了待ち
while(RSPI0.SPSR.BIT.SPRF == 0); // 受信バッファフルの確認 FRAM_READ_STR = RSPI0.SPDR.LONG;
● 参考例2.富士通製 FRAMのデバイスIDの読み取り コマンド数2、フレーム数2
RSPI0.SPDCR.BIT.SPFC = 0x01; // 2フレーム フレーム数を2とする RSPI0.SPSCR.BYTE = _01_RSPI_SEQUENCE_LENGTH_2; // 0 -> 1 -> 0... シーケンス値が2とする
Y_RSPI0_Start(); PORT5.PODR.BIT.B3 = 0; // チップセレクト -> FRAM while(RSPI0.SPSR.BIT.SPTEF == 0); // RDID コマンド送信 ( 送信バイト数:1、データ:0x9F ) RSPI0.SPDR.LONG = 0x0000009F; // コマンドの送信 dummy = RSPI0.SPSR.BYTE; while(RSPI0.SPSR.BIT.IDLNF == 1); // 送信完了待ち RSPI0.SPDR.LONG = 0x00000000; // 受信用ダミーの送信 dummy = RSPI0.SPSR.BYTE; while(RSPI0.SPSR.BIT.IDLNF == 1); // 送信完了待ち while(RSPI0.SPSR.BIT.SPRF == 0); // 受信バッファフルの確認 FRAM_DEVICE_ID = RSPI0.SPDR.LONG;
【備考】
上記のソースコードで、SPIバス上に正しいデータがスレーブから送出されることまでは確認出来ています。
しかし、どこかの設定に誤りがあるらしく、RSPIのデータレジスタから受信データを取り出すことが出来ておりません。
参考にされる際は、この点をご了承願います。
Higetaka様
> シーケンスの送出後、設定したフレーム数分の受信データがシフトレジスタから受信バッファ(SPRX)に転送されたとき、
> SPRFが1になり、その後に受信バッファにたまっている2フレーム分の応答を読み出せば良いはずです。
やはり、その筈ですよね…
しかし、別のスレッドで書かせて頂いていますが、「送信完了」となったのちに
while(RSPI0.SPSR.BIT.SPRF == 0);
で受信バッファフルの状態を待って、
FRAM_READ_STR = RSPI0.SPDR.WORD.H;
で受信データの取り込みを試みておりましたが、悉く、全てのデータが‘0xFF’となっているのです。
バスのロジアナ波形が正しいのに、なぜバッファのデータが0xFFなのか…全く判らず、かなり困っておりました。
原因がわからないので、一旦保留にしておいたのです。
今回Higetakaさんに教えていただいた後はロングワードアクセスとなりましたので、
FRAM_READ_STR = RSPI0.SPDR.LONG;
になるかと思いますので、明日試作機で試してみます。
と、現在自宅で書きながら考えたのですが…
ワードアクセスで評価している時、送信データは上位16ビットに書き込むということになっているので、
受信も同様に考えてSPDR上位16ビットを読んでいました。
ハードウェアマニュアルのPage1076の説明は、
「SPDR レジスタは、RSPI 送受信用のデータを格納するバッファです。ロングワードアクセス(SPLW ビットが“1”)のときは、SPDR をアクセスしてください。ワードアクセス(SPLW ビットが“0”)のときは、SPDR の上位側16 ビット(H)をアクセスしてください。」
と説明されています。
SPDRの上位16ビット(H)とは、別の表現ではSPDR[31:16]ですよね。
一方で、同マニュアルのPage1076-1077をあらためて読みますと、次のように説明されています。
「 受信バッファは、データの受信が完了すると受信データを格納します。オーバラン発生時は、受信バッファの値を更新しません。
また、データ長が32 ビット以外の場合、SPRXn(n=0 ~ 3)の非参照ビットには、SPTXn(n=0 ~ 3)の非参照ビットが格納されます。たとえば、データ長が9 ビットのデータを受信した場合はSPRXn[8:0] には受信データが格納され、SPRXn[31:9] にSPTXn[31:9] が格納されます。」
つまり、受信したステータスリードなどの8ビットデータはSPDR[7:0]に居たということになるのでしょうか。
ならば、ワードアクセスでSPDRの上位側16ビット(H)をアクセスするのは送信の時のみ? (汗;)
> 2回読み出すのがポイントです。
> FFなのは、1フレーム目の時のMISOの状態を読み出しているからでは?
> ---
> xxx = RSPI0.SPDR.LONG;
> FRAM_DEVICE_ID = RSPI0.SPDR.LONG;
---
とやってみてください。
あ゛、読めました !
確かに1回目の読み込みはFFでしたが、2回目の読み込みは上図の通り、正しい値が読み取れました。
ただ、わからないのは、この32ビットのデータ(デバイスID)は読み取ることができましたが、
ステータスレジスタなど、8ビットのデータは相変わらず読めず、FFになってしまうのです。
もしかして、強制的に32ビットのクロックを送出してあげないと読み取れないとかでしょうか。
8ビットのデータ(ステータスレジスタの状態)を返すコマンドを試した結果が次の図です。
図1 2フレームを用いて、8ビットのデータを受信してみた
正しい値「0x02」を連続4回送ってきています。
そして、SPDRの値は…
図2 SPDRの値=0
なぜか0.
32ビットの波形が示す値は、0x02020202
何故だろう? また問題が増えてしまいました orz
正しく取れれば、余計な部分はマスクしてしまえばよいのですが、違う値では使えません。orz