お世話になっております。
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制御がうまく動作してから、その後どうするか考えましょう。
シーケンスとフレーム、一気に理解されたようで良かったですね。なら、話が早いです。 SPSR空読み、表32.8 1項、気をつけてね。
Higetakaさん、的確なヒント。ありがとうございました。
LEON様、Higetaka様
ありがとうございました。
ビット数とフレーム数について理解ができ、スレーブデバイスからのレスポンスも正しいデータが返ってきました。
図1 CMD0:8ビット、フレーム数:1
図2 CMD0:8ビット、CMD1:32ビット、フレーム数:2
後はレスポンスデータの取り込みだけなんだけど…なぜか相変わらずFF…
● 今回のフレーム操作で気がついた事。
設定したフレーム数の分(例:2フレームならば2つ)データがSPDRに入らなければ、マイコンは転送の実行を行わないということです。
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のデータレジスタから受信データを取り出すことが出来ておりません。
参考にされる際は、この点をご了承願います。