AnsweredAssumed Answered

STM32F7Cube SPI with Circular DMA

Question asked by karpavicius.linas on Jul 27, 2015
Latest reply on Aug 4, 2015 by karpavicius.linas
Hello, i am in progress of porting STM32F4 code to STM32F7 code. all software controlled programs are working, now it is time for DMA for SPI and DCMI

So can some one translate code for SPL approach to HAL, since many functions are missing, no examples for SPI DMA in circular mode, and all of this porting is soo puzzling...

Here is simple end elegant SPL code, works great for any SPi with ANY DMA

#define SPIx                           SPI2
#define SPIx_CLK                       RCC_APB1Periph_SPI2
#define SPIx_CLK_INIT                  RCC_APB1PeriphClockCmd
#define SPIx_IRQn                      SPI2_IRQn
#define SPIx_IRQHANDLER                SPI2_IRQHandler
 
#define SPIx_SCK_PIN                   GPIO_Pin_10
#define SPIx_SCK_GPIO_PORT             GPIOB
#define SPIx_SCK_GPIO_CLK              RCC_AHB1Periph_GPIOB
#define SPIx_SCK_SOURCE                GPIO_PinSource10
#define SPIx_SCK_AF                    GPIO_AF_SPI2
 
#define SPIx_MISO_PIN                  GPIO_Pin_2
#define SPIx_MISO_GPIO_PORT            GPIOC
#define SPIx_MISO_GPIO_CLK             RCC_AHB1Periph_GPIOC
#define SPIx_MISO_SOURCE               GPIO_PinSource2
#define SPIx_MISO_AF                   GPIO_AF_SPI2
 
#define SPIx_MOSI_PIN                  GPIO_Pin_3
#define SPIx_MOSI_GPIO_PORT            GPIOC
#define SPIx_MOSI_GPIO_CLK             RCC_AHB1Periph_GPIOC
#define SPIx_MOSI_SOURCE               GPIO_PinSource3
#define SPIx_MOSI_AF                   GPIO_AF_SPI2
 
#define SPIx_DMA                       DMA1
#define SPIx_DMA_CLK                   RCC_AHB1Periph_DMA1
 
#define SPIx_TX_DMA_CHANNEL            DMA_Channel_0
#define SPIx_TX_DMA_STREAM             DMA1_Stream4
#define SPIx_TX_DMA_FLAG_TCIF          DMA_FLAG_TCIF4
 
#define SPIx_RX_DMA_CHANNEL            DMA_Channel_0
#define SPIx_RX_DMA_STREAM             DMA1_Stream3
#define SPIx_RX_DMA_FLAG_TCIF          DMA_FLAG_TCIF3
 
#define DMA_STREAM               DMA1_Stream3
#define DMA_CHANNEL              DMA_Channel_0
#define DMA_STREAM_CLOCK         RCC_AHB1Periph_DMA1
#define DMA_STREAM_IRQ           DMA1_Stream3_IRQn
#define DMA_IT_TCIF              DMA_IT_TCIF3
#define DMA_STREAM_IRQHANDLER    DMA1_Stream3_IRQHandler
 
void SPI_Config(void)
{
  GPIO_InitTypeDef      GPIO_InitStructure;
  DMA_InitTypeDef       DMA_InitStructure;
  SPI_InitTypeDef       SPI_InitStructure;
  SPIx_CLK_INIT(SPIx_CLK, ENABLE);
   
  /* Enable GPIO clocks */
  RCC_AHB1PeriphClockCmd(SPIx_SCK_GPIO_CLK | SPIx_MISO_GPIO_CLK | SPIx_MOSI_GPIO_CLK, ENABLE);
   
  /* Enable DMA clock */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
 
  /* Connect SPI pins to AF5 */ 
  GPIO_PinAFConfig(SPIx_SCK_GPIO_PORT,  SPIx_SCK_SOURCE,  SPIx_SCK_AF );
  GPIO_PinAFConfig(SPIx_MISO_GPIO_PORT, SPIx_MISO_SOURCE, SPIx_MISO_AF);   
  GPIO_PinAFConfig(SPIx_MOSI_GPIO_PORT, SPIx_MOSI_SOURCE, SPIx_MOSI_AF);
 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
 
  /* SPI SCK pin configuration */
  GPIO_InitStructure.GPIO_Pin = SPIx_SCK_PIN;
  GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStructure);
   
  /* SPI  MISO pin configuration */
  GPIO_InitStructure.GPIO_Pin =  SPIx_MISO_PIN;
  GPIO_Init(SPIx_MISO_GPIO_PORT, &GPIO_InitStructure); 
 
  /* SPI  MOSI pin configuration */
  GPIO_InitStructure.GPIO_Pin =  SPIx_MOSI_PIN;
  GPIO_Init(SPIx_MOSI_GPIO_PORT, &GPIO_InitStructure);
  
  SPI_I2S_DeInit(SPIx);
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
   
  /* DMA configuration -------------------------------------------------------*/
  /* Deinitialize DMA Streams */
  DMA_DeInit(SPIx_TX_DMA_STREAM);
  DMA_DeInit(SPIx_RX_DMA_STREAM);
   
  /* Configure DMA Initialization Structure */
  DMA_InitStructure.DMA_BufferSize = BUFFERSIZE ;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable ;
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull ;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t) (&(SPIx->DR)) ;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
  /* Configure TX DMA */
  DMA_InitStructure.DMA_Channel = SPIx_TX_DMA_CHANNEL ;
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral ;
  DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)DataTx ;
  DMA_Init(SPIx_TX_DMA_STREAM, &DMA_InitStructure);
  /* Configure RX DMA */
  DMA_InitStructure.DMA_Channel = SPIx_RX_DMA_CHANNEL ;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory ;
  DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)DataRx ;
  DMA_Init(SPIx_RX_DMA_STREAM, &DMA_InitStructure);
   
  SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
  SPI_Init(SPIx, &SPI_InitStructure);
 
  /* Enable DMA SPI TX Stream */
  DMA_Cmd(SPIx_TX_DMA_STREAM,ENABLE);
 
  /* Enable DMA SPI RX Stream */
  DMA_Cmd(SPIx_RX_DMA_STREAM,ENABLE); 
   
  /* Enable SPI DMA TX Requsts */
  SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Tx, ENABLE);
 
  /* Enable SPI DMA RX Requsts */
  SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Rx, ENABLE);
 
  /* Enable the SPI peripheral */
  SPI_Cmd(SPIx, ENABLE);
   
}

Could some one help me to get this code running on STM32F7 ?

Right now i am testing same code just on SPI5, since i have header to probe sygnals:

SPI_HandleTypeDef hspi4;
 
uint16_t a[5000],b[5000];
void Piezo_SPI_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
   
  __GPIOA_CLK_ENABLE();
  __GPIOF_CLK_ENABLE();
  __SPI5_CLK_ENABLE();
   
  GPIO_InitStruct.Pin = GPIO_PIN_2;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
   
  GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF5_SPI5;
  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
 
  hspi5.Instance = SPI5;
  hspi5.Init.Mode = SPI_MODE_MASTER;
  hspi5.Init.Direction = SPI_DIRECTION_2LINES;
  hspi5.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi5.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi5.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi5.Init.NSS = SPI_NSS_SOFT;
  hspi5.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  hspi5.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi5.Init.TIMode = SPI_TIMODE_DISABLED;
  hspi5.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
  hspi5.Init.CRCPolynomial = 10;
  hspi5.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi5.Init.NSSPMode = SPI_NSS_PULSE_ENABLED;
  HAL_SPI_Init(&hspi5);
   
  __HAL_SPI_ENABLE(&hspi5);
   
  uint16_t i = 0;
  while(i<5000)
  {
    a[i]=i;
    b[i]=i;
    i++;
  }
   
  HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2, GPIO_PIN_RESET);
  Delay(0xFFFF);
  HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2, GPIO_PIN_SET);
  Delay(0xFFFF);
  HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2, GPIO_PIN_RESET);
  Delay(0xFFFF);
   
  __HAL_RCC_DMA2_CLK_ENABLE();
   
  DMA_HandleTypeDef hdma_spi5_rx;
  DMA_HandleTypeDef hdma_spi5_tx;
   
  //HAL_DMA_DeInit(hspi->hdmarx);
  //HAL_DMA_DeInit(hspi->hdmatx);
   
  hdma_spi5_rx.Instance = DMA2_Stream3;
  hdma_spi5_rx.Init.Channel = DMA_CHANNEL_2;
  hdma_spi5_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
  hdma_spi5_rx.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_spi5_rx.Init.MemInc = DMA_MINC_ENABLE;
  hdma_spi5_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  hdma_spi5_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  hdma_spi5_rx.Init.Mode = DMA_CIRCULAR;
  hdma_spi5_rx.Init.Priority = DMA_PRIORITY_HIGH;
  hdma_spi5_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  hdma_spi5_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
  hdma_spi5_rx.Init.MemBurst = DMA_MBURST_SINGLE;
  hdma_spi5_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
  HAL_DMA_Init(&hdma_spi5_rx);
  HAL_DMA_Start(&hdma_spi5_rx,(uint32_t)(&(SPI5->DR)),(uint32_t)&a, 5000);
  //__HAL_LINKDMA(hspi,hdmarx,hdma_spi5_rx);
 
  hdma_spi5_tx.Instance = DMA2_Stream4;
  hdma_spi5_tx.Init.Channel = DMA_CHANNEL_2;
  hdma_spi5_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
  hdma_spi5_tx.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_spi5_tx.Init.MemInc = DMA_MINC_ENABLE;
  hdma_spi5_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  hdma_spi5_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  hdma_spi5_tx.Init.Mode = DMA_CIRCULAR;
  hdma_spi5_tx.Init.Priority = DMA_PRIORITY_HIGH;
  hdma_spi5_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  hdma_spi5_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
  hdma_spi5_tx.Init.MemBurst = DMA_MBURST_SINGLE;
  hdma_spi5_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
  HAL_DMA_Init(&hdma_spi5_tx);
 
  HAL_DMA_Start(&hdma_spi5_tx,  (uint32_t)&b, (uint32_t) (&(SPI5->DR)),5000);
   
  //__HAL_LINKDMA(hspi,hdmatx,hdma_spi5_tx);
   
   
    /* DMA controller clock enable */
 
  /* DMA interrupt init */
  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);
   
  SPI5->CR2 |= 0x0002;
  SPI5->CR2 |= 0x0001;
  SPI5->CR1 |= SPI_CR1_SPE;
 
}

Starge think is, when i am running with debuger, i don't get SPI clock. If i running this code without any debugger, it does generate SPI Clock, but no MOSI Signal was found in any case. SPI init itself is good, since in software mode, it works without any probelms.

Outcomes