Because of the holidays, TI E2E™ design support forum responses will be delayed from Dec. 25 through Jan. 2. Thank you for your patience.

This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Concerto McBSP XEMPTY/XRDY Problem!

Other Parts Discussed in Thread: TMS320F28335

Hi,

i use Concerto F28M35H52C1 and configure McBSP peripheral as SPI interface to send messages to an external device (such as a CPLD). Length of msgs can be variable (i.e. 8 bit or 20-bit). So i update XWDLEN1 field of XCR1 register before sending each msg. Therefore, i'm checking whether there is an active transmission or not before sending msg. If there is a transmission, i'll wait for end of xmit. Since length of new msg can be different than the current one. 

First, i send a msg (i.e length of 20-bit) and then send a second one (i.e length of 8-bit) just after the first one. i call my function, named as "hw_send_msg_to_hop_cpld()" to send msgs.

  • If i use " while( McbspaRegs.SPCR2.bit.XEMPTY ) " to check transmission, i cannot observe the two messages on the scope. A single msg whose length is 8-bit, is oberved but the transmitted data on data pin is incorrect.
  • If "while( !McbspaRegs.SPCR2.bit.XRDY )" is used instead, everything is fine.

it seems that, in the first case,the transmission of the second msg is started before the first one ends. Hence, during the first transmission, the msg length is updated. (Actually, transmission of 2nd one is not started. Since transmission detection does not work properly, msg length of the current transmission is changed by the code.)

According to documents (SPRUH22b), i expect that the first one works fine. As i understand, XEMPTY means that there is no data to be transmitted in DXR register and there is no transmission in XSR. XRDY is updated when a data is transferred from DXR to XSR and means DXR can be loaded with new data. Right? If so, i should check XEMPTY to be sure there is no transmission.

What is my mistake? Or, is there a problem about XEMPTY / XRDY status fields?

Best regards,

Taylan

Notes:

  • M3 runs @ 75 MHz, C28 runs @ 150 MHz, Mcbsp XCLK @ 10 MHz, Silicon Rev: 0
  • the functions are listed below.
  • Some comments may be inconsistent with the configuration. Ignore them.

 void hw_init_hop(void)
{
 if (NULL == hop_if)
  hop_if = &McbspaRegs;

 // Reset the McBSP
 // Disable all interrupts
 // Frame sync generator reset
 // Sample rate generator reset
 // Transmitter reset
 // Receiver reset
 hop_if->SPCR2.bit.FRST = 0;
 hop_if->SPCR2.bit.GRST = 0;
 hop_if->SPCR2.bit.XRST = 0;
 hop_if->SPCR1.bit.RRST = 0;

 #ifdef DEBUG_HW_HOP_IF_LOOPBACK
  // Enable loop back mode
  // This does not require external hardware
  hop_if->SPCR2.all = 0x0200;
  hop_if->SPCR1.all = 0x8000;
 #else

  // Serial Port Control Registers:
  //    SPCR1  => DLB    = 0 (Loopback disabled)
  //              RJUST  = 2 (Left adjust, zero fill the LSBs)
  //              CLKSTP = 2 (Clkstp without delay, To use Mcbsp as SPI if)
  //              DXENA  = 0 (Dx delay Enabler off)
  //              RINTM  = 0 (send RINT to Cpu when RRDY changes from 0 to 1, rx data ready)
  //              RSYNCERR = 0 (Reset RSYNCERR flag)
  //    RRST   = 0 (Reset Receiver)
  //
  //    SPCR2  => FREE   = 1 (Free Run)
  //              SOFT   = 0 (don't care when FREE = 1)
  //              FRST   = 1 (Reset frame sync generator)
  //              GRST   = 1 (Reset Sample rate generator)
  //              XINTM  = 0 (send RINT to Cpu when RRDY changes from 0 to 1, rx data ready)
  //              XSYNCERR = 0 (Reset XSYNCERR flag)
  //              XEMPTY = (Read only)
  //              XRDY   = (Read only)
  //              XRST   = 0 (Reset Transmitter)
  hop_if->SPCR2.all = 0x0200;
  hop_if->SPCR1.all = 0x1000;
 #endif

 // Rx Control Registers:
 //   RCR1  => RFRLEN1 = 0 (1 word)
 //      RWDLEN1 = 3 (20 bits)
 //
 //  RCR2   => RPHASE  = 0 (single phase)
 //             RFRLEN2 = 0 (1 word, don't car for single phase)
 //             RWDLEN2 = 0 (8 bits, don't car for single phase)
 //      RCOMPAND= 0 (No companding, any size data, MSB received first)
 //             RFIG    = 0 (Frame sync detect)
 //            RDATDLY = 0 (0-bit data delay)
 hop_if->RCR1.all = 0x0060;
 hop_if->RCR2.all = 0x0000;

 // RX data delay is 1 bit
 hop_if->RCR2.bit.RDATDLY = 1;

 // Tx Control Registers:
 //   XCR1  => XFRLEN1 = 0 (1 word)
 //      XWDLEN1 = 3 (20 bits)
 //
 //  XCR2   => XPHASE  = 0 (single phase)
 //             XFRLEN2 = 0 (1 word, don't car for single phase)
 //             XWDLEN2 = 0 (8 bits, don't car for single phase)
 //      XCOMPAND= 0 (No companding, any size data, MSB transmitted first)
 //             XFIG    = 0 (Frame sync detect)
 //            XDATDLY = 0 (0-bit data delay)
 hop_if->XCR1.all = 0x0040;
 hop_if->XCR2.all = 0x0000;

 // TX data delay is 1 bit
 hop_if->XCR2.bit.XDATDLY = 1;

 // Sample Rate Generator Registers:
 //   SRGR1  => FWID    = 0 (1 CLKG frame pulse width)
 //             CLKGDV  = 9
    //
 //      Note:  SPI CLK = LSPCLK / (CLKGDV+1)
 //             For 10 MHz SPI CLK & 100 MHz LSPCLK, CLKGDV = 9
 //             For 10 MHz SPI CLK & 150 MHz LSPCLK, CLKGDV = 14
 //
 //    SRGR2  => GSYNC  = 0 (No clk synchronization)
 //              CLKSM  = 1 (with SCLKME=0 in PCR, input clk source is LSPCLK)
 //              FSGM   = 0 (frame-sync pulse generated when DXR is copied to XSR)
 //              FPER   = 32 (33 CLKG, ignore when FSXM =1 & FSGM=0)
 #if CPU_FRQ_150MHZ
  hop_if->SRGR1.all = 0x000E;   // SPI CLK = LSPCLK / (CLKGDV+1) = 10 MHz, LSPCLK = 150 MHz
 #elif CPU_FRQ_100MHZ
        hop_if->SRGR1.all = 0x0009;   // SPI CLK = LSPCLK / (CLKGDV+1) = 10 MHz, LSPCLK = 100 MHz
 #else
     hop_if->SRGR1.all = 0x0009;   // Default: SPI CLK = LSPCLK / (CLKGDV+1) = X MHz.
 #endif
 hop_if->SRGR2.all = 0x2020;

 // Sample rate generator input clock is LSPCLK
 hop_if->SRGR2.bit.CLKSM = 1;
 hop_if->PCR.bit.SCLKME = 0;

 // Delay at least 2 SRGR CLK
 DELAY_US(1000);

 // Pin Control Register:
 //   PCR   => FSXM  = 1 (Tx Frame-sync generated internally)
 //            FSRM  = 1 (Rx Frame-sync generated internally)
 //            CLKXM = 1 (with CLKSTP = 2 or 3, Mcbsp SPI Master. generated by SRGR)
 //            CLKRM = 1 (with CLKSTP = 2 or 3, driven by CLKX)
 //            SCLKME = 0 (with CLKSM=1, Input source clk for SRGR is LSPCLK)
 //            FSXP  = 1 (Tx frame sync pulses are active low)
 //            FSRP  = 1 (Rx frame sync pulses are active low)
 //            CLKXP = 1 (Tx data is sampled on the falling edge of CLKX)
 //            CLKRP = 0 (Rx data is sampled on the falling edge of CLKR)
 hop_if->PCR.all = 0x0F0E;

 // Enable Sample rate generator and
 // wait at least 2 CLKG clock cycles
 hop_if->SPCR2.bit.GRST = 1;

 // Delay at least 2 SRGR CLK
 DELAY_US(1000);

 // Disable Interrupts
 hop_if->MFFINT.bit.XINT = 0;
 hop_if->MFFINT.bit.RINT = 0;

 // Release from reset
 // RX, TX and frame sync generator
 hop_if->SPCR2.bit.XRST = 1;
 hop_if->SPCR1.bit.RRST = 1;
 hop_if->SPCR2.bit.FRST = 1;
}

void hw_send_msg_to_hop_cpld(Uint16 msg_id, Uint16 data1, Uint16 data2)
{
 Uint16 msg_hword, msg_lword, msg_length;

 // Create CPLD msg
 if (HOP_MSG_ID_MODE == msg_id) {
  msg_hword = 0;
  msg_lword = 0x0080 + (data1<<4) + (data2<<3);
  msg_length = 0; // 8-bit

 } else if (HOP_MSG_ID_FILTER == msg_id) {
  msg_hword = data1;
  msg_lword = data2;
  msg_length = 3; // 20-bit

 } else
  return;

 // TODO: Send msg if there is no transmission.
 while(hop_if->SPCR2.bit.XEMPTY) {}
 //while(!hop_if->SPCR2.bit.XRDY) {}
 hop_if->XCR1.bit.XWDLEN1 = msg_length;
 hop_if->DXR2.all = msg_hword;
 hop_if->DXR1.all = msg_lword;

}