cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F7Cube SPI with Circular DMA

megahercas6
Senior
Posted on July 27, 2015 at 11:25

 

 

The original post was too long to process during our migration. Please click on the attachment to read the original post.
6 REPLIES 6
Posted on July 27, 2015 at 18:13

Hi karpavicius.linas,

Have a look at the example under STM32Cube_FW_F7_V1.1.0\Projects\STM32746G-Discovery\Examples\SPI, maybe it can help you even if it is in normal mode.

-Shahrzed-

megahercas6
Senior
Posted on July 28, 2015 at 05:44

No, it must be in Circular mode. I usually start by looking to examples, and SPI example does not support circular mode by the looks of it

It is starting to work for me, MOSI line is active, but enabling SPI in circular mode only works second time, that means, first debugging session it works, second it does not, third it works, fourth it does not. So, i have no idea what going on.

megahercas6
Senior
Posted on July 29, 2015 at 08:58

this is code i am running. As i said, it work at odd times (1,3,5,7 debugging season at same power up, but not at second, fourth, six debugging season)

extern uint8_t DataRx[];
extern uint8_t DataTx[];
SPI_HandleTypeDef hspi2;
void SPI_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
__GPIOC_CLK_ENABLE();
__GPIOB_CLK_ENABLE();
__SPI2_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_SLAVE;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLED;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
hspi2.Init.CRCPolynomial = 10;
hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLED;
HAL_SPI_Init(&hspi2);
__HAL_RCC_DMA1_CLK_ENABLE();
DMA_HandleTypeDef hdma_spi2_rx;
DMA_HandleTypeDef hdma_spi2_tx;
//HAL_DMA_DeInit(&hdma_spi2_rx);
//HAL_DMA_DeInit(&hdma_spi2_tx);
hdma_spi2_rx.Instance = DMA1_Stream3;
hdma_spi2_rx.Init.Channel = DMA_CHANNEL_0;
hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi2_rx.Init.Mode = DMA_CIRCULAR;
hdma_spi2_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_spi2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_spi2_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_spi2_rx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_spi2_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&hdma_spi2_rx);
HAL_DMA_Start(&hdma_spi2_rx,(uint32_t)(&(SPI2->DR)),(uint32_t)(&DataRx), 5000);
//__HAL_LINKDMA(hspi,hdmarx,hdma_spi5_rx);
hdma_spi2_tx.Instance = DMA1_Stream4;
hdma_spi2_tx.Init.Channel = DMA_CHANNEL_0;
hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi2_tx.Init.Mode = DMA_CIRCULAR;
hdma_spi2_tx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_spi2_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_spi2_tx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_spi2_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&hdma_spi2_tx);
HAL_DMA_Start(&hdma_spi2_tx, (uint32_t)&DataTx, (uint32_t)(&SPI2->DR),5000);
//__HAL_LINKDMA(hspi,hdmatx,hdma_spi5_tx);
HAL_NVIC_SetPriority(DMA2_Stream3_IRQn,0,0);
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
HAL_NVIC_SetPriority(DMA2_Stream4_IRQn,0,0);
HAL_NVIC_EnableIRQ(DMA2_Stream4_IRQn);
SPI2->CR2 |= 0x0002;
SPI2->CR2 |= 0x0001;
SPI2->CR1 |= SPI_CR1_SPE;
}

megahercas6
Senior
Posted on July 30, 2015 at 11:08

SPI_HandleTypeDef hspi2;
void SPI_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
__GPIOC_CLK_ENABLE();
__GPIOB_CLK_ENABLE();
__SPI2_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_SLAVE;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLED;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
hspi2.Init.CRCPolynomial = 7;
hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLED;
HAL_SPI_Init(&hspi2);
__HAL_RCC_DMA1_CLK_ENABLE();
DMA_HandleTypeDef hdma_spi2_rx;
DMA_HandleTypeDef hdma_spi2_tx;
DMA1_Stream3->CR &= ~((uint32_t)DMA_SxCR_EN);
DMA1_Stream3->CR = 0;
DMA1_Stream3->NDTR = 0;
DMA1_Stream3->PAR = 0;
DMA1_Stream3->M0AR = 0;
DMA1_Stream3->M1AR = 0;
DMA1_Stream3->FCR = (uint32_t)0x00000021; 
DMA1->LIFCR = DMA_Stream3_IT_MASK;
DMA1_Stream4->CR &= ~((uint32_t)DMA_SxCR_EN);
DMA1_Stream4->CR = 0;
DMA1_Stream4->NDTR = 0;
DMA1_Stream4->PAR = 0;
DMA1_Stream4->M0AR = 0;
DMA1_Stream4->M1AR = 0;
DMA1_Stream4->FCR = (uint32_t)0x00000021; 
DMA1->LIFCR = DMA_Stream4_IT_MASK;
hdma_spi2_rx.Instance = DMA1_Stream3;
hdma_spi2_rx.Init.Channel = DMA_CHANNEL_0;
hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi2_rx.Init.Mode = DMA_CIRCULAR;
hdma_spi2_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_spi2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_spi2_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_spi2_rx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_spi2_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&hdma_spi2_rx);
HAL_DMA_Start(&hdma_spi2_rx,(uint32_t)(&(SPI2->DR)),(uint32_t)(&DataRx), BUFFERSIZE);
//__HAL_LINKDMA(hspi,hdmarx,hdma_spi5_rx);
hdma_spi2_tx.Instance = DMA1_Stream4;
hdma_spi2_tx.Init.Channel = DMA_CHANNEL_0;
hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi2_tx.Init.Mode = DMA_CIRCULAR;
hdma_spi2_tx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_spi2_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_spi2_tx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_spi2_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&hdma_spi2_tx);
HAL_DMA_Start(&hdma_spi2_tx, (uint32_t)&DataTx, (uint32_t)(&SPI2->DR),BUFFERSIZE);
HAL_NVIC_SetPriority(DMA2_Stream3_IRQn,0,0);
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
HAL_NVIC_SetPriority(DMA2_Stream4_IRQn,0,0);
HAL_NVIC_EnableIRQ(DMA2_Stream4_IRQn);
SPI2->CR2 |= 0x0002;
SPI2->CR2 |= 0x0001;
SPI2->CR1 |= SPI_CR1_SPE;
}

This is my setup i am using right now. Newer get correct values, and sometimes it just don't work. So, any one can help me out ? Also, what is __HAL_LINKDMA(); and do i need one ?
Amel NASRI
ST Employee
Posted on July 30, 2015 at 13:13

Hi karpavicius.linas,

I saw your various posts on almost the same topic: issue to port STM32F4 code with SPL to STM32F7 with Cube.

Please note that Cube is a new approach and you cannot translate code line by line from one library to the other.

You may refer to the

http://www.st.com/st-web-ui/static/active/en/resource/technical/document/user_manual/DM00189702.pdf

(Description of STM32F7xx HAL drivers) to understand the purpose of HAL functions & macros and to know how structures of peripherals are defined.

So, for example, __HAL_LINKDMA is the macro that MUST be used in order to associate the initialized DMA handle to the SPI DMA handle (don't understand why you commented it).

In the UM1905, there is a chapter dedicated for HAL SPI driver.

You find there the following recommendations if you need to use DMA process:

  • Declare a DMA_HandleTypeDef handle structure for the transmit or receive channel
  • Enable the DMAx clock
  • Configure the DMA handle parameters
  • Configure the DMA Tx or Rx channel
  • Associate the initialized hdma_tx handle to the hspi DMA Tx or Rx handle
  • Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx or Rx channel 
And in case of Circular mode usage, we have some restrictions (given in UM1905 as well):

  1. The DMA circular mode cannot be used when the SPI is configured in these modes: Master 2Lines RxOnly  or Master 1Line Rx
  2. The CRC feature is not managed when the DMA circular mode is enabled
  3. When the SPI DMA Pause/Stop features are used, we must use the following APIs the HAL_SPI_DMAPause()/ HAL_SPI_DMAStop() only under the SPI callbacks 

In your particular case, I suggest that you start from CubeMX where you configure your SPI as expected. You can also configure your DMA handle and set 

it to circular mode (you have no restriction to use this mode as your SPI is in Slave mode).

CubeMX will only generate the initialization code (SPI/DMA/GPIO/NVIC initialization).

Once your project is generated, you have to:

  1. add the processing functions for transmission and reception (HAL_SPI_TransmitReceive_DMA)
  2. define your callback functions (HAL_SPI_TxRxCpltCallback & HAL_SPI_TxRxHalfCpltCallback).
As already suggested by Shahrzad, you may refer to the example ''STM32Cube_FW_F7_V1.1.0\Projects\STM32746G-Discovery\Examples\SPI\SPI_FullDuplex_ComDMA''.

You are not using exactly the same configuration, that is true. But once your initialization project is generated by CubeMX, you can refer to this example in order to know how exactly to call the processing functions and how to define the callbacks.

In your code, I am not sure that direct access to registers is working as expected.

Hope I finally bring some help to let you work easily with the Cube.

-Mayla-

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

megahercas6
Senior
Posted on August 04, 2015 at 11:55

So two weeks are in, and this problem still remains. ( i did try to read programming manual as well as HAL programming reference )

I don't exactly understand why I need

void SPIx_DMA_RX_IRQHandler(void)
{
HAL_DMA_IRQHandler(hspi2.hdmarx);
}
void SPIx_DMA_TX_IRQHandler(void)
{
HAL_DMA_IRQHandler(hspi2.hdmatx);
}

if it's in circular mode, i don't have to deal with any SPI and DMA related stuff, after i initialize it. I don't use transmit complete interrupts or any thing that can cause processor to execute some code. And to save time i always start with examples, don't say lookup examples or programming references, because i did all this to best of my ability ( if i have any)

extern uint8_t DataRx[];
extern uint8_t DataTx[];
DMA_HandleTypeDef hdma_spi2_rx;
DMA_HandleTypeDef hdma_spi2_tx;
SPI_HandleTypeDef hspi2;
void SPI_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
__GPIOC_CLK_ENABLE();
__GPIOB_CLK_ENABLE();
__SPI2_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_SLAVE;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLED;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
hspi2.Init.CRCPolynomial = 7;
hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLED;
HAL_SPI_Init(&hspi2);
__HAL_RCC_DMA1_CLK_ENABLE();
HAL_DMA_DeInit(&hdma_spi2_tx);
HAL_DMA_DeInit(&hdma_spi2_rx);
HAL_NVIC_DisableIRQ(DMA1_Stream3_IRQn);
HAL_NVIC_DisableIRQ(DMA1_Stream4_IRQn);
hdma_spi2_rx.Instance = DMA1_Stream3;
hdma_spi2_rx.Init.Channel = DMA_CHANNEL_0;
hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi2_rx.Init.Mode = DMA_CIRCULAR;
hdma_spi2_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_spi2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_spi2_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_spi2_rx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_spi2_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&hdma_spi2_rx);
__HAL_LINKDMA(&hspi2,hdmarx,hdma_spi2_rx);
hdma_spi2_tx.Instance = DMA1_Stream4;
hdma_spi2_tx.Init.Channel = DMA_CHANNEL_0;
hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi2_tx.Init.Mode = DMA_CIRCULAR;
hdma_spi2_tx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_spi2_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_spi2_tx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_spi2_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&hdma_spi2_tx);
__HAL_LINKDMA(&hspi2,hdmatx,hdma_spi2_tx);
HAL_NVIC_SetPriority(DMA1_Stream3_IRQn,1,1);
HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
HAL_NVIC_SetPriority(DMA1_Stream4_IRQn,1,0);
HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
HAL_DMA_Start(&hdma_spi2_rx,(uint32_t)(&(SPI2->DR)),(uint32_t)(&DataRx), BUFFERSIZE);
HAL_DMA_Start(&hdma_spi2_tx,(uint32_t)&DataTx, (uint32_t)(&SPI2->DR),BUFFERSIZE);
SPI2->CR2 |= 0x0002;
SPI2->CR2 |= 0x0001;
SPI2->CR1 |= SPI_CR1_SPE;
}
uint32_t spi_i = 0;
void SPIx_DMA_RX_IRQHandler(void)
{
HAL_DMA_IRQHandler(hspi2.hdmarx);
}
void SPIx_DMA_TX_IRQHandler(void)
{
HAL_DMA_IRQHandler(hspi2.hdmatx);
}

So far i get 0 help with problems, mainly because only people who helped me here works only with SPL. I don't expect to get answers all the time, but neither only to get, read manual, lookup examples.... And i still need to make DCMI work, i just wonder how much problems i will get with last peace of the puzzle, at least example with be a bit easier to work with ( i hope )