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

XMC™ Forum Discussions

u-s
Level 4
Level 4
First like received 5 solutions authored 25 sign-ins
Hello!

I have a question about DAVE4 IDE generated source code spi_slave.c and spi_master.c.
In the spi_slave.c, SPI_SLAVE_StartReceiveDMA() function is using the XMC_SPI_CH_GetReceivedData() API for clears RBUF0 and RBFU1.
As with spi_master.c, also clears RBUF0 and RBFU1.

Could you tell me why need to flash RBUF0 and RFUF1 in the spi_slave.c and spi_master.c?

In my project, I using the SPI_MASTER APPs, SPI_SLAVE APPs and GLOBAL_DMA APPs.

About spi_slave.c, I will using the SPI_SLAVE_StartReceiveDMA() function receive the 136 bytes data from GLOBAL_DMA APPs.
In this function performs flash RBUF0 and RFUF1 on lines 1059 and 1060, before enabling SPI events and DMA channel.
If not use line 1059 and 1060(comment out these lines), in the received 136 bytes data, the first 2 bytes data is "0x0000" or "0xFFFF".

About spi_master.c, I will using the SPI_MASTER_StartReceiveDMA() function receive the 136 bytes data from GLOBAL_DMA APPs.
As with spi_master.c, also clears RBUF0 and RBFU1 at lines 1481 and 1483.
If not use line 1481 and 1483(comment out these lines), in the received 136 bytes data, the first 2 bytes data is "0x0000" or "0xFFFF".

Regarding the source code, please refer attached files(spi_slave.txt and spi_master.txt).

Regards,
Xingwei
0 Likes
2 Replies
jferreira
Employee
Employee
First like received 750 replies posted 500 replies posted
Hi,

The SPI_MASTER_lStdRBUFFlush() is needed in the case that you first do a transmit (you do not care about the received data) and then a receive.
  
// Simple example where MOSI is loopback to MISO
uint8_t tx_data[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
uint8_t rx_data[8];

SPI_MASTER_Transmit(&SPI_MASTER_0, tx_data, sizeof(tx_data));
while(SPI_MASTER_IsTxBusy(&SPI_MASTER_0));


SPI_MASTER_Receive(&SPI_MASTER_0, rx_data, sizeof(rx_data));


In this case if you place a breakpoint at the following line after the commented SPI_MASTER_lStdRBUFFlush(), you will see that RBUF0 and RBUF1 both contains data. The last two data sent by the transmit function.
RBUF01SR is also telling that both RBUF0 and RBUF1 contains data valid not read and that RBUF will access data from RBUF1.
3569.attach
If a new data would come, i.e. first data coming in from the next receive, the RBUF01SR will tell that both RBUFx registers contains valid data and that RBUF will access RBUF0. RBUF is alternating between RBUF0 and RBUF1.
3570.attach

If you step further in the debug session, after you enable the DMA, you do the dummy transmit to receive. When the first data comes in, the data will be stored in RBUF1 and the DMA will read from RBUF which is taking the data from RBUF0 which contains (0x07).
Therefore the first data read will be last one received from the previous transmit.

To avoid this we invalidate both RBUF0 and RBUF1.

Regards,
Jesus
0 Likes
mwh
Level 1
Level 1
5 sign-ins First reply posted Welcome!

Hi,

I know this is a older topic, however I seem to trigger a bug in this scenario.
I understand the reason for flushing the buffers, however the scenario the Jesus illustrates a an example for why flushing is needed faults in my end. Let my try to explain.

I have the following lines (simplified cut out from my application):

 

stp0.spiHandle = &SPI_STP_0;
copyToBuffer16(MAX7317_CONFIGURE_INPUTS, stp0.sendBuffer); // 0x0a01
SPI_MASTER_Transmit(stp0.spiHandle, stp0.sendBuffer, 2);
while(SPI_MASTER_IsTxBusy(stp0.spiHandle));
copyToBuffer16(MAX7317_READ9_8, stp0.sendBuffer); // 0x8f00
SPI_MASTER_Transmit(stp0.spiHandle, stp0.sendBuffer, 2);
while(SPI_MASTER_IsTxBusy(stp0.spiHandle));
copyToBuffer32((MAX7317_READ7_0 << 16) + MAX7317_NOP, stp0.sendBuffer); // 0x8e00a000
SPI_MASTER_Transfer(stp0.spiHandle, stp0.sendBuffer, stp0.receiveBuffer, 4);
while(1){};

 

Please take a look at the decoded signal from my logic analyzer. Top is MISO and bottom is MOSI. Here the data is CORRECT (read as expected).

mwh_0-1643380892651.png

SPI_STP_0 has a "end of receive/transfer" callback function assigned. When the callback is called the received bytes are: 0x1, 0x8f, 0x0, 0x8e. The received bytes in the callback buffer are "shifted". I receive the last byte from the last transmit and 3 bytes from the transfer. Looking in the RBUF register, I can see the last 0x44 is also received, but after the data is collected for my transfer/ callback.

So I dug a little further. I added the following lines to SPI_MASTER_lReceiveDMA() (the temp variable lines):

 

  runtime_handle = handle->runtime;
  runtime_handle->rx_data_index = 0U;
  runtime_handle->rx_data_count = (uint32_t)block_size;

  volatile uint8_t temp = handle->channel->RBUFSR;
  volatile uint8_t temp0 = handle->channel->RBUF0;
  volatile uint8_t temp1 = handle->channel->RBUF1;

  SPI_MASTER_lStdRBUFFlush(handle->channel);

  XMC_SPI_CH_EnableEvent(handle->channel, (uint32_t)SPI_MASTER_RECEIVE_EVENT);

 

and set a breakpoint on the SPI_MASTER_lStdRBUFFlush(handle->channel); This reveals the following values in the variables:

 

temp = 0x7
temp0 = 0x0
temp1 = 0xa

 

meaning that the receive buffers contain the the first byte from the first transmit and the first byte from the last transmit. This data gets flushed/invalidated, and the receiving starts. 

How can this happen? After each transmit action we're waiting for it to be done. However, isTxBusy() returns false when the last byte has been placed in the transmit buffers. This makes sense, as the application can now proceed preparing data for a new transmit (what mechanism prevents overwriting TBUF that is currently being transmitted?). However, as the transmit is still in progress, a receive is also still in progress which completes when the transmit completes. Issuing a receive whilst a transmission is in progress shifts the received data. 

Wouldn't it be sane to wait for tx idle when issuing a transfer/receive? or not allowing it and returning "busy"?

Best regards Mathias

0 Likes