RSPIにおけるデータ転送のビット数とフレーム数について

お世話になっております。

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バスにデータが現れることを確認することを先に進めております。

Parents
  • 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制御がうまく動作してから、その後どうするか考えましょう。

  • LEON様
    おはようございます。
    度々の御回答誠にありがとうございます。

    送受信のコードは、次のように分けております。
      初期化の処理:R_RSPI0_Create(); コード生成のものをそのまま使用していますが、内容は理解できています。RSPIの各種設定や端子設定は、このコードの中に書かれています。

      送受信前処理:Y_RSPI0_Start(void) // データを送受信する前に実行しています。元はコード生成のコードでしたが、割り込みは使わないので、その部分を削除しています。
                        
      送受信後処理:Y_RSPI0_Stop(void) // データを送受信した後に実行しています。

    それぞれのコードは、次の通りです。

    「フレーム」については触れられていませんでしたが、これは使い方が違うのでしょうか。
    お教え頂けましたら幸いです。

    R_RSPI0_Create()
    {
      /* 割り込みの禁止 */
      IEN(RSPI0,SPTI0) = 0U;
      IEN(RSPI0,SPRI0) = 0U;
      IEN(RSPI0,SPEI0) = 0U;
      IEN(RSPI0,SPII0) = 0U;
      /* RSPIの停止処理 */
      MSTP(RSPI0) = 0;
      /* Disable RSPI function */
      RSPI0.SPCR.BIT.SPE = 0U;
      /* レジスタの設定 */
      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 = _00_RSPI_ACCESS_WORD |    // ワードアクセス
                _00_RSPI_FRAMES_1;      // 1フレーム
                              // SPRDTDビットは0(既定値、受信バッファ読み)
      RSPI0.SPSCR.BYTE = _00_RSPI_SEQUENCE_LENGTH_1;
      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 | // アサート信号はSSL0
                 _0000_RSPI_SSL_KEEP_DISABLE |  // 
                 _0400_RSPI_DATA_LENGTH_BITS_8 | // ビット長は8ビット
                 _0000_RSPI_MSB_FIRST |      // MSBファースト
                 _0000_RSPI_NEXT_ACCESS_DELAY_DISABLE |
                 _0000_RSPI_NEGATION_DELAY_DISABLE |
                 _0000_RSPI_RSPCK_DELAY_DISABLE;
      /* Set SPEI0, SPRI0, SPTI0 and SPII0 priority level */
      IPR(RSPI0,SPTI0) = _0F_RSPI_PRIORITY_LEVEL15;    // 割り込み優先順位はレベル15
      /* RSPCKAピンの設定 */
      MPC.P51PFS.BYTE = 0x0DU;
      PORT5.ODR0.BYTE &= 0xF7U;
      PORT5.ODR0.BYTE |= 0x04U;
      PORT5.PMR.BYTE |= 0x02U;
      /* MOSIAピンの設定 */
      MPC.P50PFS.BYTE = 0x0DU;
      PORT5.ODR0.BYTE &= 0xFDU;
      PORT5.ODR0.BYTE |= 0x01U;
      PORT5.PMR.BYTE |= 0x01U;
      /* MISOAピンの設定 */
      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; // クロック同期式、全二重、マスターモード
    }

    Y_RSPI0_Start(void)
    {
      // ポーリング用のSPI通信前処理( 割り込み無し )
      volatile uint8_t dummy;
      /* SPEビットの許可 */
      RSPI0.SPCR.BIT.SPE = 1;
      /* Clear error sources */
      dummy = RSPI0.SPSR.BYTE; // SPSRレジスタに書き込むための前処理
      RSPI0.SPSR.BYTE = 0xA0U;
      /* Disable idle interrupt */
      RSPI0.SPCR2.BIT.SPIIE = 0U; // アイドル割り込み要求の発生を禁止
    }

    Y_RSPI0_Stop(void)
    {
      // ポーリング用のSPI通信後処理( 割り込み無し )
      RSPI0.SPCR2.BIT.SPIIE = 0U;
      /* SPEビットの禁止 */
      RSPI0.SPCR.BIT.SPE = 0U;
    }
  • LEON様

    早速試してみましたが、コマンドを送信したところで止まってしまいますね。

    挙動としては、受信の命令を飛ばしてチップセレクトがOFFになっているようです。

    試したコードは次の通りです。

    //
    // FRAM デバイスID 読み込み
    //

    Y_RSPI0_Start();

    /* FRAM デバイスID読み込みのための 送信モード切替 */
      RSPI0.SPCR.BIT.SPE = 0; // 機能無効
      RSPI0.SPCR.BIT.TXMD = 1; // 送信のみ
      RSPI0.SPDCR.BYTE = 0x00; // ワードアクセス、1フレーム、受信バッファリード
      RSPI0.SPCMD0.WORD = 0x0400; // 8ビット、MSBファースト・・・
      RSPI0.SPCR.BIT.SPE = 1; // 機能有効

      PORT5.PODR.BIT.B3 = 0; // チップセレクト -> FRAM

      while(RSPI0.SPSR.BIT.SPTEF == 0);
      // RDID コマンド送信 ( 送信バイト数:1、データ:0x9F )
      RSPI0.SPDR.WORD.H = 0x009F; // データの送信
      dummy = RSPI0.SPSR.BYTE;
      while(RSPI0.SPSR.BIT.IDLNF == 1); // 送信完了待ち

      /* FRAM から32bitデータ受信のための 送信モード切替 */
      RSPI0.SPCR.BIT.SPE = 0; // 機能無効
      RSPI0.SPCR.BIT.TXMD = 0; // 全二重
      RSPI0.SPDCR.BYTE = 0x20; // ロングワードアクセス、1フレーム、受信バッファリード
      RSPI0.SPCMD0.WORD = 0x0200; // 32ビット、MSBファースト・・・
      RSPI0.SPCR.BIT.SPE = 1; // 機能有効

      while(RSPI0.SPSR.BIT.SPTEF == 0);
      RSPI0.SPDR.LONG = 0x00000000; // ダミー送信


      while(RSPI0.SPSR.BIT.SPRF == 0); // 受信バッファフルの確認 (1)
      FRAM_DEVICE_ID = RSPI0.SPDR.LONG;

      PORT5.PODR.BIT.B3 = 1; // チップセレクト 解除

      Y_RSPI0_Stop();

  • RSPIのシーケンス・フレームを活用するのがポイントだと思います。
    コード生成では1パターンしか生成できないのですが、リードデバイスIDだけに限定すれば、コード生成だけで対応可能です。1パターンで成功すれば、その後のやり方が見えてくると思います。
    シーケンスを2つのフレーム(8bit, 32bit)で構成すれば良いはずです。
    ハードウェアマニュアルのシーケンス制御とコード生成の設定との関連を理解する事が必要です。
  • コード開示、ありがとうございます。

    ■R_RSPI0_Create()
    マクロが不明ですが、値は名前から推測しました。特に設定値に問題は無さそうです。
    割り込みは使わないとのことなので、IPR(RSPI0,SPTI0) の設定は不要ぐらい。

    ■Y_RSPI0_Start()
    ・SPCR2.SPIIE =0 は割り込み未使用とのことなので、なくても良い。
    ・Y_RSPI0_Start()内の SPSRライトは余分では。
    ・基本、SPCR.SPE =0 後、設定、SPCR.SPE =1 としましょう。
     SPCR.SPE =1 の状態において....の注意がマニュアルにはいろいろ記述されてます。

    ■Y_RSPI0_Stop()
    ・SPCR2.SPIIE =0 は割り込み未使用とのことなので、なくても良い。

    フレームについては、1135、1136ページに示すとおりで、今回は1フレームのみ(設定1-1)で案内ですが、

    Higetakaさんが案内するシーケンスを2つのフレーム(8bit, 32bit)も適切と思います。

  • SPTEFチェック、IDLNFチェックの前にSPSR空読みを入れててもだめですか。
    (1127ページ。SPI動作ですが、クロック同期式も同じ)
    表32.8 1項に示す症状っぽく、後の書込データが欠落し(送信されずに)チップセレクト解除まで処理が進んでいるようなんですが。
    ダミーデータ送信直前の状態は、エミュレータで調べるとどうなってましたかね。

  • Higetaka様
    お世話になっております。
    ご説明により、やっとなんとかマニュアルのP1136の説明がわかってきました。

    つまり、マスタがコマンド(8ビット)を送信し、スレーブが返すデバイスID(32ビット)を取得するには、
    Page1136 図32.43に示される設定2-1による

      (1)SPCMD0のビット長を8ビットに設定する。ー>1フレーム目
      (2)SPCMD1のビット長を32ビットに設定する。ー>2フレーム目
      (3)上記(1)、(2)をシーケンス制御する。

    という解釈でよさそうですね。...φ( ..)メモメモ

    ● ハードウェアマニュアルSPCCRレジスタの説明に示される「シーケンス長」の番号(1~8)と図32.43に示される設定[x]-[y]は、xの値がシーケンス長の番号となっている。
  • LEON様
    御回答ありがとうございます。
    浮気ではありませんが、Higetakaさんが説明してくださいましたフレームとシーケンスを試してみます。
    何とか理解できたようです。
Reply Children
  • シーケンスとフレーム、一気に理解されたようで良かったですね。なら、話が早いです。
    SPSR空読み、表32.8 1項、気をつけてね。

    Higetakaさん、的確なヒント。ありがとうございました。

  • LEON様、Higetaka様

    ありがとうございました。

    ビット数とフレーム数について理解ができ、スレーブデバイスからのレスポンスも正しいデータが返ってきました。

    図1  CMD0:8ビット、フレーム数:1

     

    図2  CMD0:8ビット、CMD1:32ビット、フレーム数:2

     

    後はレスポンスデータの取り込みだけなんだけど…なぜか相変わらずFF…

    ● 今回のフレーム操作で気がついた事。

      設定したフレーム数の分(例:2フレームならば2つ)データがSPDRに入らなければ、マイコンは転送の実行を行わないということです。

  • 送信、オメデトウです。 ヨカッタ、ヨカッタ。
    受信、エミュレータでいろいろ調べてみては。

    あと、MISOAはちゃんと入力設定になっていますか?
    # RXの記述法がちょっとわかってないもんで。
  • こんにちは
    送信、おめでとうございます。
    出来ましたら、成功した時のコードを公開して頂けませんでしょうか?
    参考にしたいです。
  • 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 |

                           _0000_RSPI_NEGATION_DELAY_DISABLE | _0000_RSPI_RSPCK_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;

      PORT5.PODR.BIT.B3 = 1; // チップセレクト 解除

      Y_RSPI0_Stop();

     

     

     

    ● 参考例2.富士通製 FRAMのデバイスIDの読み取り コマンド数2、フレーム数2

    //
    // FRAM デバイスID 読み込み
    //

      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;

      PORT5.PODR.BIT.B3 = 1;                    // チップセレクト 解除

      Y_RSPI0_Stop();

    【備考】

      上記のソースコードで、SPIバス上に正しいデータがスレーブから送出されることまでは確認出来ています。

      しかし、どこかの設定に誤りがあるらしく、RSPIのデータレジスタから受信データを取り出すことが出来ておりません。

      参考にされる際は、この点をご了承願います。

     

  • こんにちは
    パールマンさん、コード掲載ありがとうございます。
    参考にさせて頂きます。
  • シーケンスの送出後、設定したフレーム数分の受信データがシフトレジスタから受信バッファ(SPRX)に転送されたとき、SPRFが1になり、その後に受信バッファにたまっている2フレーム分の応答を読み出せば良いはずです。
  • 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)をアクセスするのは送信の時のみ? (汗;)

  • 確認してみましたが、やはり読めませんでした。orz
  • 2回読み出すのがポイントです。
    FFなのは、1フレーム目の時のMISOの状態を読み出しているからでは?
    ---
    xxx = RSPI0.SPDR.LONG;
    FRAM_DEVICE_ID = RSPI0.SPDR.LONG;
    ---
    とやってみてください。

    受信バッファサイズは32bit x 4なので、LONGで読めば全部が見えるはずです。
    ただし、1フレーム目は8bitしか送っていないので、対応するどこかがFFになっているはずです。