cancel
Showing results for 
Search instead for 
Did you mean: 

SPI RX buffer shifted

sirpak
Associate II
Posted on February 23, 2018 at 18:10

Dear All,

I use SPI as a master with 2 lines full duplex with DMA on STM32F303RE with 8-bit data size.

Frames are made of variable number of Bytes. Normally SPI clocks out 3 Bytes of command on MOSI line + 4 Bytes of reception which contains the slave answer.

My TX buffer is something like this:

   (CMD)(ADD_H)(ADD_L)(4 Bytes don't care)

My RX buffer will be:

   (3 Bytes don't care, normally 0xFFFFFF)(0x21)(0x43)(0x65)(0x87)

The output on the oscilloscope is perfect, but after a 30 seconds of millions of good communication I find the Rx buffer shifted:

(0x43)(0x65)(0x87)(0xFFFFFF)(0x21) or

(0x65)(0x87)(0xFFFFFF)(0x21)(0x43) or

(0x87)(0xFFFFFF)(0x21)(0x43)(0x65) or

The shifted conditions is kept for some second, then it change. If I let it go, it keep on shifting, till goes back in phase.

Here is the configuration of SPI:

SPI_I2S_DeInit(SPI2);

SPI2->CR1 = SPI_CPHA_1Edge | SPI_CPOL_Low | SPI_Mode_Master | SPI_BaudRatePrescaler_64 | SPI_FirstBit_MSB | SPI_NSS_Soft | SPI_Direction_2Lines_FullDuplex;

SPI2->CR2 = SPI_RxFIFOThreshold_QF | SPI_DataSize_8b | SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx;

Here the configuration of the two DMA channels (channel 4 RX and channel 5 TX):

// DMA channel Rx of SPI Configuration

DMA_DeInit(DMA1_Channel4);

DMA1_Channel4->CCR = DMA_DIR_PeripheralSRC | DMA_Mode_Normal | DMA_PeripheralInc_Disable | DMA_MemoryInc_Enable | DMA_PeripheralDataSize_Byte | DMA_MemoryDataSize_Byte | DMA_Priority_High | DMA_M2M_Disable;

DMA1_Channel4->CNDTR = 0;

DMA1_Channel4->CPAR = (uint32_t)&(SPI2->DR);

DMA1_Channel4->CMAR = (uint32_t)&RxBuffer[0];

// DMA channel Tx of SPI Configuration

DMA_DeInit(DMA1_Channel5);

DMA1_Channel5->CCR = DMA_DIR_PeripheralDST | DMA_Mode_Normal | DMA_PeripheralInc_Disable | DMA_MemoryInc_Enable | DMA_PeripheralDataSize_Byte | DMA_MemoryDataSize_Byte | DMA_Priority_Medium | DMA_M2M_Disable;

DMA1_Channel5->CNDTR = 0;

DMA1_Channel5->CPAR = (uint32_t)&(SPI2->DR);

DMA1_Channel5->CMAR = (uint32_t)&TxBuffer[0];

When I want to transmit and receive I created following function:

if((DMA1_Channel4->CNDTR != 0) || (DMA1_Channel5->CNDTR != 0))

   return 0;

if((SPI2->SR & (SPI_SR_FRLVL | SPI_SR_FTLVL | SPI_I2S_FLAG_RXNE | SPI_I2S_FLAG_BSY))

   return 0;

// Disable the SPI (trying to flush it)

SPI2->CR1 &= ~SPI_CR1_SPE;

// Disable the DMA channels to configure the CNDTR

DMA1_Channel5->CCR &= ~DMA_CCR_EN;

DMA1_Channel4->CCR &= ~DMA_CCR_EN;

// Enable SPI

SPI2->CR1 |= SPI_CR1_SPE;

// Configure odd transfers

SPI2->CR2 &= ~SPI_LastDMATransfer_TxOddRxOdd;

if((Tx_Size + Rx_Size) % 2)

   SPI2->CR2 |= SPI_LastDMATransfer_TxOddRxOdd;

// NSS signal to 0

ESC_CS_ON;

// Number of Bytes to transmit and receive

DMA1_Channel4->CNDTR = Tx_Size + Rx_Size;

DMA1_Channel5->CNDTR = Tx_Size + Rx_Size;

// Enable reception

DMA1_Channel4->CCR |= DMA_CCR_EN;

// Ebable transmission

DMA1_Channel5->CCR |= DMA_CCR_EN;

Another function checks the transfers are completed and take the data from the buffer

if((DMA1->ISR & (DMA1_FLAG_TC4 | DMA1_FLAG_TC5)) != (DMA1_FLAG_TC4 | DMA1_FLAG_TC5))

   return 0;

if((DMA1_Channel4->CNDTR != 0) || (DMA1_Channel5->CNDTR != 0))

   return 0;

if(SPI2->SR & (SPI_SR_FRLVL | SPI_SR_FTLVL | SPI_I2S_FLAG_RXNE | SPI_I2S_FLAG_BSY))

   return 0;

SPI2->CR1 &= ~SPI_CR1_SPE;

memcpy(value, (u8*)RxBuffer + Tx_Size, Rx_Size);

return 1;

My impression is that even though the SPI is disabled and enabled to try to flush it and even

though

 I check that the RXFIFO is empty, there is something that remains there and corrupt the future transfers.

#dma #spi #spi-flushing #spi-shift
1 ACCEPTED SOLUTION

Accepted Solutions
Ed Raab
Associate II
Posted on March 04, 2018 at 19:39

hallo,

i have a simular problem with SPI.

I have a STM32F746 as SPI master in polling mode with a full duplex connection to a STM32F103 worked as SPI-slave.  A communication block of 720 Bytes is repeatly transfered in 20ms with a speed of appr. 6MHz SPI-CLK.  

Sporadic there is an error on the communication like described above. There is a byte offset in the received bytes. The bytes in the receive buffer  (RxBuffer) have an offset of 1 or 2 or more bytes permanently. After the error occurs all following receptions have this offset in opposite to the bytes on the SPI-MISO-Pin, recepted with Oscilloscope.

I currently use the HAL-SPI-functions. In case of error the hspi->RxXferCount shows 2 or 4 but the hspi->TxXferCount shows 0. I have tested several workarounds to set up the SPI-Interface right but it doesnt work.

Until now only repowering of the F746 solves the problem.

Is there anybody to have a solution for this problem?

best regards

ed

View solution in original post

11 REPLIES 11
Ed Raab
Associate II
Posted on March 04, 2018 at 19:39

hallo,

i have a simular problem with SPI.

I have a STM32F746 as SPI master in polling mode with a full duplex connection to a STM32F103 worked as SPI-slave.  A communication block of 720 Bytes is repeatly transfered in 20ms with a speed of appr. 6MHz SPI-CLK.  

Sporadic there is an error on the communication like described above. There is a byte offset in the received bytes. The bytes in the receive buffer  (RxBuffer) have an offset of 1 or 2 or more bytes permanently. After the error occurs all following receptions have this offset in opposite to the bytes on the SPI-MISO-Pin, recepted with Oscilloscope.

I currently use the HAL-SPI-functions. In case of error the hspi->RxXferCount shows 2 or 4 but the hspi->TxXferCount shows 0. I have tested several workarounds to set up the SPI-Interface right but it doesnt work.

Until now only repowering of the F746 solves the problem.

Is there anybody to have a solution for this problem?

best regards

ed

Posted on March 04, 2018 at 22:09

Hi Ed.

I think I managed to solve using USART working in SPI mode. I didn't complete the tests yet, but I haven't observed any byte shifts.

Best regards, 

M

Posted on March 09, 2018 at 10:34

hallo,

changing to USART is not a good choice for me according to hardware-dependencies.

I am hopeful that a ST FAE will give a hint to solve this problem,

because with this error the whole SPI-Rx-function is not usable.  

best regards

Ed

C. Satterberg
Associate II

Hello All,

Looks like I'm not the only one that has has this problem. Has anyone solved this since it was originally posted? Switching to UART is definitely not a satisfactory answer and something that definitely isn't an option for my design.

Try reading the SPI DR twice (16-bit reads) immediately prior to the SPI exchange.

Good suggestion, but it doesn't seem to make a difference. Looking at the SPI bus on a scope, it looks like the responses from the slave are shifted before entering the master. Looks more like a problem with the way that the master is sending data that somehow desynchronizes the slave. It's pretty baffling though. Like, it shouldn't be possible for a SPI master to clock out more or less than one byte of data if it's set up for that, right? You should never just get an extra bit or two for no reason.

" You should never just get an extra bit or two for no reason." Unless you have a clock problem (knee, ringing, reflection). Is your actual problem bit- or byte-related?

Yep, another excellent point. For me, the problem is bit-related. I suppose that makes it a little different from the OP. Haven't seen anything too suspicious on the o-scope when it comes to the clock. The usual culprit, from what I've heard, is polarity and phase of the clock signal but that has been checked.

Ed Raab
Associate II

hallo,

my problem is to understand how affects an event all following receptions. My SPI-signal quality is good. But wether a wrong Byte-signal is detected according to noise or a single spike this may results in a wrong data reception only of this byte or bit but not all the following receptions. It seems to be that the SPI-reception logic ignores until now one or more of the first bytes. That is the first problem. The second problem is that a ReInit of the SPI-Interface doesnt correct the settings for reception.

best regard

Ed