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;
}