Possible bug in SPI_MASTER app

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
User11041
Level 1
Level 1
Hi everybody,

I have one XMC4500 microcontroller on a PCB which is connected to a PCA9701 chip via a set of SPI lines. The PCA9701 is a simple I/O expander, it has 16 digital input pins which can be read via SPI. This chip outputs 16 bit of data on the MISO line (on falling SCLK edge) if the master (the XMC in this case) pulls down the CS line. Which is pretty simple.

If I initialize one instance of the SPI_MASTER app on the XMC4500, I do the following to read the PCA9701 data:


uint8_t spi_data_pca9701[3U];
SPI_MASTER_DisableSlaveSelectSignal(&SPI_MASTER_0);
SPI_MASTER_EnableSlaveSelectSignal(&SPI_MASTER_0, SPI_MASTER_0.config->slave_select_pin_config[1U]->slave_select_ch); //That's the CS line of the PCA9701 (verified)
if(!SPI_MASTER_Receive(&SPI_MASTER_0, spi_data_pca9701, 2U)) {
while(SPI_MASTER_0.runtime->rx_busy);
}


You might notice that even though I only want to read 2 bytes (16 bits), I initialize three bytes of receive buffer. The reason is that after the receive command finishes, the PCA9701 data is located in spi_data_pca9701[1] and spi_data_pca9701[2], and the first array element is empty. Debugging the receive routine shows that the array index 0 is NOT referenced to at any time.
My question is whether this is a bug in the Infineon code or whether I configured something wrong in my SPI_MASTER_0 instance (I enclose the conifguration).

Kind regards,
Nick

P.S. SPI_MASTER_0:
Full duplex, 19.2kHz, no parity. Direct RX/TX modes, 2 slave select lines. Word length 8, frame length 16, frame end mode enabled, Leading/trailing delay 1 SCLK cycle, inter-word delay zero, no interrupts, no advanced pin configurations.
0 Likes
13 Replies
User10215
Level 4
Level 4
First like received
Hi Nick,

just a question...is your array "spi_data_pca9701" a local variable?

Regards,
Niclas
0 Likes
Not applicable
HI Nick,

This is a defect in the SPI_MASTER APP for receive function in direct mode. The receive buffer index is updated incorrectly in the function.

In the interim, a workaround in the code can be the following:

Please replace the receive function with the following implementation. The changes are underlined.

SPI_MASTER_STATUS_t SPI_MASTER_lReceivePolling(constSPI_MASTER_t *const handle, uint32_t count)
{
SPI_MASTER_RUNTIME_t * runtime_handle;

uint32_t bytes_per_word = SPI_MASTER_1_BYTE_PER_WORD; /* This is to support the word length 8 and 16
Specify the number of bytes for the configured word length */

uint16_t data;

runtime_handle = handle->runtime;
data = 0U;
runtime_handle->rx_data_index = 0U;

if (handle->runtime->word_length > SPI_MASTER_WORD_LENGTH_8_BIT)
{
bytes_per_word = SPI_MASTER_2_BYTES_PER_WORD; /* Word length is 16-bits */
}

runtime_handle->rx_data_count = (uint32_t)count << (bytes_per_word - 1U);

XMC_SPI_CH_SetTransmitMode(handle->channel, runtime_handle->spi_master_mode);

/* Check if FIFO is enabled */
if ((uint32_t)handle->config->rx_fifo_size > 0U)
{
/* Clear the receive FIFO */
XMC_USIC_CH_RXFIFO_Flush(handle->channel);
SPI_MASTER_lStdRBUFFlush(handle->channel);

if (runtime_handle->tx_data_dummy == true)
{
XMC_USIC_CH_TXFIFO_PutDataHPCMode(handle->channel, 0xFFFFU, (uint32_t)runtime_handle->spi_master_mode);
}
else
{
if(bytes_per_word == SPI_MASTER_2_BYTES_PER_WORD)
{
data = *((uint16_t*)&runtime_handle->tx_data[runtime_handle->tx_data_index]);
}
else
{
data = runtime_handle->tx_data[runtime_handle->tx_data_index];
}
XMC_USIC_CH_TXFIFO_PutDataHPCMode(handle->channel, data, (uint32_t)runtime_handle->spi_master_mode);
}
(runtime_handle->tx_data_index)+= bytes_per_word;

while (runtime_handle->tx_data_index < runtime_handle->rx_data_count)
{
if (runtime_handle->tx_data_dummy == true)
{
XMC_USIC_CH_TXFIFO_PutDataHPCMode(handle->channel, 0xFFFFU, (uint32_t)runtime_handle->spi_master_mode);
}
else
{
if(bytes_per_word == SPI_MASTER_2_BYTES_PER_WORD)
{
data = *((uint16_t*)&runtime_handle->tx_data[runtime_handle->tx_data_index]);
}
else
{
data = runtime_handle->tx_data[runtime_handle->tx_data_index];
}
XMC_USIC_CH_TXFIFO_PutDataHPCMode(handle->channel, data, (uint32_t)runtime_handle->spi_master_mode);
}

while(XMC_USIC_CH_RXFIFO_IsEmpty(handle->channel) == true)
{

}

data = XMC_SPI_CH_GetReceivedData(handle->channel);

runtime_handle->rx_data[runtime_handle->rx_data_index] = (uint8_t)data;

if (bytes_per_word == SPI_MASTER_2_BYTES_PER_WORD)
{
runtime_handle->rx_data[runtime_handle->rx_data_index + 1U] = (uint8_t)((uint16_t)data >> 8);
}

(runtime_handle->rx_data_index)+= bytes_per_word;
(runtime_handle->tx_data_index)+= bytes_per_word;
}
while(XMC_USIC_CH_RXFIFO_IsEmpty(handle->channel) == true)
{

}

data = XMC_SPI_CH_GetReceivedData(handle->channel);

runtime_handle->rx_data[runtime_handle->rx_data_index] = (uint8_t)data;

if (bytes_per_word == SPI_MASTER_2_BYTES_PER_WORD)
{
runtime_handle->rx_data[runtime_handle->rx_data_index + 1U] = (uint8_t)((uint16_t)data >> 8);
}
XMC_USIC_CH_RXFIFO_ClearEvent(handle->channel, SPI_MASTER_FIFO_RECEIVE_INDICATION_FLAG);
}
else
{
/* Flush the RBUF0 and RBUF1 */
SPI_MASTER_lStdRBUFFlush(handle->channel);

while((uint32_t)XMC_USIC_CH_GetTransmitBufferStatus(handle->channel) == (uint32_t)XMC_USIC_CH_TBUF_STATUS_BUSY)
{

}

if (runtime_handle->tx_data_dummy == true)
{
XMC_USIC_CH_WriteToTBUFTCI(handle->channel, 0xFFFFU, (uint32_t)runtime_handle->spi_master_mode);
}
else
{
if(bytes_per_word == SPI_MASTER_2_BYTES_PER_WORD)
{
data = *((uint16_t*)&runtime_handle->tx_data[runtime_handle->tx_data_index]);
}
else
{
data = runtime_handle->tx_data[runtime_handle->tx_data_index];
}

XMC_USIC_CH_WriteToTBUFTCI(handle->channel, data, (uint32_t)runtime_handle->spi_master_mode);

}

(runtime_handle->tx_data_index)+= bytes_per_word;

while (runtime_handle->tx_data_index < runtime_handle->rx_data_count)
{
while((uint32_t)XMC_USIC_CH_GetTransmitBufferStatus(handle->channel) == (uint32_t)XMC_USIC_CH_TBUF_STATUS_BUSY)
{

}

if (runtime_handle->tx_data_dummy == true)
{
XMC_USIC_CH_WriteToTBUFTCI(handle->channel, 0xFFFFU, (uint32_t)runtime_handle->spi_master_mode);
}
else
{
if(bytes_per_word == SPI_MASTER_2_BYTES_PER_WORD)
{
data = *((uint16_t*)&runtime_handle->tx_data[runtime_handle->tx_data_index]);
}
else
{
data = runtime_handle->tx_data[runtime_handle->tx_data_index];
}

XMC_USIC_CH_WriteToTBUFTCI(handle->channel, data, (uint32_t)runtime_handle->spi_master_mode);
}
while (XMC_USIC_CH_GetReceiveBufferStatus(handle->channel) == 0U)
{

}
data = XMC_SPI_CH_GetReceivedData(handle->channel);

runtime_handle->rx_data[runtime_handle->rx_data_index] = (uint8_t)data;

if (bytes_per_word == SPI_MASTER_2_BYTES_PER_WORD)
{
runtime_handle->rx_data[runtime_handle->rx_data_index + 1U] = (uint8_t)((uint16_t)data >> 8);
}

(runtime_handle->rx_data_index)+= bytes_per_word;
(runtime_handle->tx_data_index)+= bytes_per_word;

XMC_SPI_CH_ClearStatusFlag(handle->channel, SPI_MASTER_RECEIVE_INDICATION_FLAG);

}
while (XMC_USIC_CH_GetReceiveBufferStatus(handle->channel) == 0U)
{

}

data = XMC_SPI_CH_GetReceivedData(handle->channel);
runtime_handle->rx_data[runtime_handle->rx_data_index] = (uint8_t)data;

if (bytes_per_word == SPI_MASTER_2_BYTES_PER_WORD)
{
runtime_handle->rx_data[runtime_handle->rx_data_index + 1U] = (uint8_t)((uint16_t)data >> 8);
}

XMC_SPI_CH_ClearStatusFlag(handle->channel, SPI_MASTER_RECEIVE_INDICATION_FLAG);
}
runtime_handle->rx_data_count = 0U;
runtime_handle->rx_data_index = 0U;

return SPI_MASTER_STATUS_SUCCESS;
}


The corresponding eticketing is filed and this will be fixed in the next release.
https://www.infineonforums.com/support/dave3/index.php?option=com_maqmahelpdesk&Itemid=0&id_workgrou...

Regards,
Daryl
0 Likes
Not applicable
Are you sure, that solves all problems?

Even though this function helped a little bit I get some strange behavior.

Calling
SPI_MASTER_Transfer(spiHandle, (uint8_t*)&SendData, (uint8_t*)&ReadData, 2);

once works fine, but calling it twice fails. The second time I call it it should send 16 clock cycles, as it does the first time, but it sends only 8.

Calling a
SPI_MASTER_Transmit(spiHandle, SendData, 2);

in between seems to solve the Problem.


SPI_MASTER_Transfer(spiHandle, (uint8_t*)&SendData, (uint8_t*)&ReadData, 2); //works
SPI_MASTER_Transfer(spiHandle, (uint8_t*)&SendData, (uint8_t*)&ReadData, 2); //fails
SPI_MASTER_Transfer(spiHandle, (uint8_t*)&SendData, (uint8_t*)&ReadData, 2); //fails
SPI_MASTER_Transmit(spiHandle, SendData, 2); //works
SPI_MASTER_Transfer(spiHandle, (uint8_t*)&SendData, (uint8_t*)&ReadData, 2); //works
SPI_MASTER_Transfer(spiHandle, (uint8_t*)&SendData, (uint8_t*)&ReadData, 2); //fails
0 Likes
Not applicable
HI,

You're right, the strange behaviour that you observed was caused by an index variable not reset in the workaround code share.

Please find the corrected code:

SPI_MASTER_STATUS_t SPI_MASTER_lReceivePolling(const SPI_MASTER_t *const handle, uint32_t count)
{
SPI_MASTER_RUNTIME_t * runtime_handle;

uint32_t bytes_per_word = SPI_MASTER_1_BYTE_PER_WORD; /* This is to support the word length 8 and 16
Specify the number of bytes for the configured word length */

uint16_t data;

runtime_handle = handle->runtime;
data = 0U;
runtime_handle->rx_data_index = 0U;
runtime_handle->tx_data_index = 0U;

if (handle->runtime->word_length > SPI_MASTER_WORD_LENGTH_8_BIT)
{
bytes_per_word = SPI_MASTER_2_BYTES_PER_WORD; /* Word length is 16-bits */
}

runtime_handle->rx_data_count = (uint32_t)count << (bytes_per_word - 1U);

XMC_SPI_CH_SetTransmitMode(handle->channel, runtime_handle->spi_master_mode);

/* Check if FIFO is enabled */
if ((uint32_t)handle->config->rx_fifo_size > 0U)
{
/* Clear the receive FIFO */
XMC_USIC_CH_RXFIFO_Flush(handle->channel);
SPI_MASTER_lStdRBUFFlush(handle->channel);

if (runtime_handle->tx_data_dummy == true)
{
XMC_USIC_CH_TXFIFO_PutDataHPCMode(handle->channel, 0xFFFFU, (uint32_t)runtime_handle->spi_master_mode);
}
else
{
if(bytes_per_word == SPI_MASTER_2_BYTES_PER_WORD)
{
data = *((uint16_t*)&runtime_handle->tx_data[runtime_handle->tx_data_index]);
}
else
{
data = runtime_handle->tx_data[runtime_handle->tx_data_index];
}
XMC_USIC_CH_TXFIFO_PutDataHPCMode(handle->channel, data, (uint32_t)runtime_handle->spi_master_mode);
}
(runtime_handle->tx_data_index)+= bytes_per_word;

while (runtime_handle->tx_data_index < runtime_handle->rx_data_count)
{
if (runtime_handle->tx_data_dummy == true)
{
XMC_USIC_CH_TXFIFO_PutDataHPCMode(handle->channel, 0xFFFFU, (uint32_t)runtime_handle->spi_master_mode);
}
else
{
if(bytes_per_word == SPI_MASTER_2_BYTES_PER_WORD)
{
data = *((uint16_t*)&runtime_handle->tx_data[runtime_handle->tx_data_index]);
}
else
{
data = runtime_handle->tx_data[runtime_handle->tx_data_index];
}
XMC_USIC_CH_TXFIFO_PutDataHPCMode(handle->channel, data, (uint32_t)runtime_handle->spi_master_mode);
}

while(XMC_USIC_CH_RXFIFO_IsEmpty(handle->channel) == true)
{

}

data = XMC_SPI_CH_GetReceivedData(handle->channel);

runtime_handle->rx_data[runtime_handle->rx_data_index] = (uint8_t)data;

if (bytes_per_word == SPI_MASTER_2_BYTES_PER_WORD)
{
runtime_handle->rx_data[runtime_handle->rx_data_index + 1U] = (uint8_t)((uint16_t)data >> 8);
}

(runtime_handle->rx_data_index)+= bytes_per_word;
(runtime_handle->tx_data_index)+= bytes_per_word;
}
while(XMC_USIC_CH_RXFIFO_IsEmpty(handle->channel) == true)
{

}

data = XMC_SPI_CH_GetReceivedData(handle->channel);

runtime_handle->rx_data[runtime_handle->rx_data_index] = (uint8_t)data;

if (bytes_per_word == SPI_MASTER_2_BYTES_PER_WORD)
{
runtime_handle->rx_data[runtime_handle->rx_data_index + 1U] = (uint8_t)((uint16_t)data >> 8);
}
XMC_USIC_CH_RXFIFO_ClearEvent(handle->channel, SPI_MASTER_FIFO_RECEIVE_INDICATION_FLAG);
}
else
{
/* Flush the RBUF0 and RBUF1 */
SPI_MASTER_lStdRBUFFlush(handle->channel);

while((uint32_t)XMC_USIC_CH_GetTransmitBufferStatus(handle->channel) == (uint32_t)XMC_USIC_CH_TBUF_STATUS_BUSY)
{

}

if (runtime_handle->tx_data_dummy == true)
{
XMC_USIC_CH_WriteToTBUFTCI(handle->channel, 0xFFFFU, (uint32_t)runtime_handle->spi_master_mode);
}
else
{
if(bytes_per_word == SPI_MASTER_2_BYTES_PER_WORD)
{
data = *((uint16_t*)&runtime_handle->tx_data[runtime_handle->tx_data_index]);
}
else
{
data = runtime_handle->tx_data[runtime_handle->tx_data_index];
}

XMC_USIC_CH_WriteToTBUFTCI(handle->channel, data, (uint32_t)runtime_handle->spi_master_mode);

}

(runtime_handle->tx_data_index)+= bytes_per_word;

while (runtime_handle->tx_data_index < runtime_handle->rx_data_count)
{
while((uint32_t)XMC_USIC_CH_GetTransmitBufferStatus(handle->channel) == (uint32_t)XMC_USIC_CH_TBUF_STATUS_BUSY)
{

}

if (runtime_handle->tx_data_dummy == true)
{
XMC_USIC_CH_WriteToTBUFTCI(handle->channel, 0xFFFFU, (uint32_t)runtime_handle->spi_master_mode);
}
else
{
if(bytes_per_word == SPI_MASTER_2_BYTES_PER_WORD)
{
data = *((uint16_t*)&runtime_handle->tx_data[runtime_handle->tx_data_index]);
}
else
{
data = runtime_handle->tx_data[runtime_handle->tx_data_index];
}

XMC_USIC_CH_WriteToTBUFTCI(handle->channel, data, (uint32_t)runtime_handle->spi_master_mode);
}
while (XMC_USIC_CH_GetReceiveBufferStatus(handle->channel) == 0U)
{

}
data = XMC_SPI_CH_GetReceivedData(handle->channel);

runtime_handle->rx_data[runtime_handle->rx_data_index] = (uint8_t)data;

if (bytes_per_word == SPI_MASTER_2_BYTES_PER_WORD)
{
runtime_handle->rx_data[runtime_handle->rx_data_index + 1U] = (uint8_t)((uint16_t)data >> 8);
}

(runtime_handle->rx_data_index)+= bytes_per_word;
(runtime_handle->tx_data_index)+= bytes_per_word;

XMC_SPI_CH_ClearStatusFlag(handle->channel, SPI_MASTER_RECEIVE_INDICATION_FLAG);

}
while (XMC_USIC_CH_GetReceiveBufferStatus(handle->channel) == 0U)
{

}

data = XMC_SPI_CH_GetReceivedData(handle->channel);
runtime_handle->rx_data[runtime_handle->rx_data_index] = (uint8_t)data;

if (bytes_per_word == SPI_MASTER_2_BYTES_PER_WORD)
{
runtime_handle->rx_data[runtime_handle->rx_data_index + 1U] = (uint8_t)((uint16_t)data >> 8);
}

XMC_SPI_CH_ClearStatusFlag(handle->channel, SPI_MASTER_RECEIVE_INDICATION_FLAG);
}
runtime_handle->rx_data_count = 0U;
runtime_handle->rx_data_index = 0U;
runtime_handle->tx_data_index = 0U;

return SPI_MASTER_STATUS_SUCCESS;
}


Regards,
Daryl
0 Likes
Not applicable
And another one 😮

While using my XMC4800 dev board, I experience another problem.
When trying to send 16bit with 4000KHz, direct transmission, full duplex everything works fine.

But when trying to send with 24000KHz, only the first 8 bit are sent.
The same with all frequencies above ~4000KHz, that I tried. I have no idea, why this happens.

Is there some border, that gets crossed around 4000KHz?

Thanks in advance and thanks for the provided solutions for the previous problems.
0 Likes
chismo
Employee
Employee
First like received
Hello,

Do you already have the frame end mode enabled, i.e. box is ticked into Advanced Settings tab of SPI_MASTER APP?

When frame end mode is enabled, the slave select output remains asserted until an end of frame condition is reached.

Regards,
Min Wei
0 Likes
Not applicable
Hi, thanks for your reply.
This was an easy solution. Should have been able to figure it out on my own.

Thanks alot. This solved my problem.
0 Likes
User10611
Level 1
Level 1
Hello!
I have a very similar problem using an XMC4108 as SPI-Master to communicate with an MAX14821. I configured the Master in direct mode without fifo and with frame end mode disabled (In fact, I also tried enabling those but to no avail).
I send a word of two bytes to configure the chip and everything works fine. Then I try to read back the configuration register for verification and it does not work. I replaced the SPI_MASTER_lReceivePolling function with the one posted above and made a funny observation: If I add a breakpoint for my J-Link debugger at the command "XMC_SPI_CH_SetTransmitMode(handle->channel, runtime_handle->spi_master_mode);" or above within this function, I receive the correct content from the MAX14821. As soon as I remove the breakpoint, I just receive '0'. I am using optimization level 2 for the GCC. Any ideas?
Best regards,
Oliver
0 Likes
schroeca
Employee
Employee
Hi,

I just tried to use the example given in the SPI_MASTER App documentation for SPI_MASTER_TRANSFER.
I can see with the osciloscope that the data is transmitted correctly.
I can also see that the slave is responding correctly but the receive buffer is empty.

The receiver buffer is always 0xFF.

Any idea why this is happening?
0 Likes
Not applicable
*push*

I have the same issue
0 Likes
User10611
Level 1
Level 1
So, this is a severe bug within an important APP. Several people confirmed it. Will it be fixed in the next Release?
0 Likes
User16843
Level 2
Level 2
First solution authored
Hi:
3 years laster, the bug still there, Is there any way to workaround it? Thanks a lot!
0 Likes
User18369
Level 2
Level 2
No one solved this Problem???

I found an SPI_Master APP - somewhere here in the Forum - with the version 4.3.28. If i check normal update of APPs i only get Version 4.3.26... I really disappointed about this behaviour....
0 Likes