cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 SPI DMA Unexpected Overrun Error

Pablo Leibovich
Associate II
Posted on October 17, 2017 at 01:30

Hi everyone!

I'm working with an external IC which must be read with a 'burst transfer'.

I have to receive 122 half words (16 bit spi transfers), so I use an SPI DMA reception.

When I configure a buffer in my code as 

uint16_t burst[122]

and make the DMA transfer

HAL_SPI_Receive_DMA(&hspi2, (uint8_t*) burst, 122)

The code fails. It makes the first reception ok but the next transfers fail by setting the overrun bit.

The matter is that if I set the burst buffer to have 123 elements and make a DMA reception of 122 half words, everything works ok.

What can be happened?

Thank you all!

#stm32f407-spi-dma
7 REPLIES 7
Posted on October 17, 2017 at 10:49

And does burst[0] in memory match the data actually present on the wires?

If so, what is in burst[122] if you increase things to 123 transfers (and increase buffer size of course)?

JW

Posted on October 17, 2017 at 17:50

Hi JW!

Yes, burst[0] has the data that must be on that position (the first transfered data).

I think I can't make 123 transfers, because the external IC will not send more data. Y will test it, but I think that.

The strange thing is that the overrun flag register is set when I make a 122 length transfer to a 122 length buffer.

It's something similar to what is described here:

https://community.st.com/0D50X00009XkZ0TSAV

 

Thanks!!

Posted on October 17, 2017 at 19:08

You have to tell us more.

Is the STM32 SPI master or slave?  How did you set it up exactly?  What is the system clock frequency and the SPI clock frequency? Don't you use CRC by mistake? Read out the SPI registers and check whether they are as expected or post them here.

JW

Posted on October 18, 2017 at 00:21

Hi JW,

Here is the SPI configuration code. The system has a clock frequency of 128MHz, the SPI is configured as master, without CRC and the CS pin is controlled by software

/* SPI2 init function */

static void MX_SPI2_Init(void)

{

hspi2.Instance = SPI2;

hspi2.Init.Mode = SPI_MODE_MASTER;

hspi2.Init.Direction = SPI_DIRECTION_2LINES;

hspi2.Init.DataSize = SPI_DATASIZE_16BIT;

hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;

hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;

hspi2.Init.NSS = SPI_NSS_SOFT;

hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;

hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;

hspi2.Init.TIMode = SPI_TIMODE_DISABLE;

hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

hspi2.Init.CRCPolynomial = 10;

if (HAL_SPI_Init(&hspi2) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

}

Here is the piece of code where the SPI with DMA is used.

HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);

command = 0x6808;

HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);

HAL_SPI_Transmit(&hspi2, (uint8_t *)&command, 1, 500);

HAL_SPI_Receive_DMA(&hspi2, (uint8_t *)burst, 122);

Thanks!

Posted on October 18, 2017 at 01:06

HAL_SPI_Transmit(&hspi2, (uint8_t *)&command, 1, 500);

HAL_SPI_Receive_DMA(&hspi2, (uint8_t *)burst, 122);

I don't use Cube but this may be problem. Transmission and reception are mutually coupled - you write byte/halfword-to-be-transmitted to data register, SPI transmits and receives, and when done a byte/halfword is received and ready to be picked from data register. If the transmit function does not read that byte/halfword, the RXNE flag stays on and the subsequent DMA start reads that byte as first even before the first clock went out, and then only 121 halfwords are outstanding for the Rx dma, whereas 122 transfers are ahead.

You need either consistently use transmit-receive, or explicitly clear the RXNE flag between these two function calls.

JW

AVI-crak
Senior
Posted on October 18, 2017 at 06:26

Startup procedure: dma -> spi. Before running, you need to check the flags in test mode, or leave a test stub.

The order of completion: spi -> dma. Completion is performed in the interrupt from dma, it is necessary to wait for the end of the transfer - the flag is triggered earlier.

Priority for RX should be lower than for TX (trigger earlier and interrupt), the priority level for DMA channels should preserve the legacy. The data register for spi is only one, to start the transfer it is enough to record - but for cyclic operation it is first necessary to read.

If you use hal - write to the registers spi is done in one operation. For the SPIx_CR1 register, such an entry is not optimal. It requires a write in two steps: all bits are in working state except Bit 6 SPE: SPI enable, all bits are in working order with SPE enabled. SPI is a rather slow peripheral device, but has hardware latches (protection against changes in working order). It is important to install SPE after determining the protection status.

I'm not sure about the same spi block standard in all microprocessors produced by st. For each chip used, it is necessary to read the documentation. HAL uses a single standard for spi, sometimes it becomes a problem - the code from the older chip does not work on the younger one.

Posted on October 21, 2017 at 23:12

Hi JW,

Thank you very much!!!

In the last days, I made a lot of tests and finally I've found the error. It was related to the communication protocol with the IC.

Thank you very much for your information about SPI. I've been analyzing the HAL SPI Library and it manages the RXNE flag you mentioned. When an 'SPI Transmit Only' instruction is executed, HAL transmits the data, waits for the timeout if necessary and finally access to the DR and SR registers of the SPI to clear the flags.

Thank you very much for your help!