Skip to main content
con3
Senior
August 13, 2018
Solved

SPI in slave mode, auto receive

  • August 13, 2018
  • 2 replies
  • 730 views

Afternoon Everyone,

I'm using an stm32f722ze

I'm not sure if I'm doing something wrong or misunderstanding the working of the SPI (it could be either) but I have it up and running.

I've got a SPI implementation in slave mode with DMA, like this:

static void MX_SPI1_Init(void)
{
 
 /* SPI1 parameter configuration*/
 hspi1.Instance = SPI1;
 hspi1.Init.Mode = SPI_MODE_SLAVE;
 hspi1.Init.Direction = SPI_DIRECTION_2LINES;
 hspi1.Init.DataSize = SPI_DATASIZE_12BIT;
 hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
 hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
 hspi1.Init.NSS = SPI_NSS_HARD_INPUT;
 hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
 hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
 hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
 hspi1.Init.CRCPolynomial = 7;
 hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
 hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
 if (HAL_SPI_Init(&hspi1) != HAL_OK)
 {
 _Error_Handler(__FILE__, __LINE__);
 }
 
}

And the DMA:

 hdma_spi1_rx.Instance = DMA2_Stream0;
 hdma_spi1_rx.Init.Channel = DMA_CHANNEL_3;
 hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
 hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
 hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
 hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
 hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
 hdma_spi1_rx.Init.Mode = DMA_NORMAL;
 hdma_spi1_rx.Init.Priority = DMA_PRIORITY_HIGH;
 hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
 if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
 {
 _Error_Handler(__FILE__, __LINE__);
 }
 
 __HAL_LINKDMA(hspi,hdmarx,hdma_spi1_rx);

At this point, I'm calling the DMA receive function HAL_SPI_Receive_DMA(...) , although it seems weird that i have to call this whenever I want to receive data from the master. How should I change my implementation so that the SPI receives data automatically when the CS line goes low?

Also, I've noticed that adding a transfer complete callback seems to do nothing:

 hdma_spi1_rx.XferCpltCallback = completespi;

This topic has been closed for replies.
Best answer by con3

So two things happened, for some reason I had it in normal mode, where it should have been in circular. But less obvious to me was that there was coherency issues between data cache. So disabling data cache resolved the issue.

EDIT: If anyone falls into the same pit and receives data but it doesn't appear in the buffer(and you enabled Dcache) see this: https://www.st.com/content/ccc/resource/technical/document/application_note/group0/08/dd/25/9c/4d/83/43/12/DM00272913/files/DM00272913.pdf/jcr:content/translations/en.DM00272913.pdf

2 replies

con3
con3Author
Senior
August 13, 2018

I think I messed up the DMA configuration, it was in normal mode, setting to circular and retesting now

con3
con3AuthorBest answer
Senior
August 17, 2018

So two things happened, for some reason I had it in normal mode, where it should have been in circular. But less obvious to me was that there was coherency issues between data cache. So disabling data cache resolved the issue.

EDIT: If anyone falls into the same pit and receives data but it doesn't appear in the buffer(and you enabled Dcache) see this: https://www.st.com/content/ccc/resource/technical/document/application_note/group0/08/dd/25/9c/4d/83/43/12/DM00272913/files/DM00272913.pdf/jcr:content/translations/en.DM00272913.pdf