cancel
Showing results for 
Search instead for 
Did you mean: 

GPDMA - Linked list - SPI

gius2705
Visitor

Hi to everybody.

I can't get spi to work with linked lists. I followed the procedures in the documentation but it still doesn't work. Maybe someone can tell me why.
This is my configuration: STM32U575, cubeMX 6.12.0, cubeIDE 1.9.0
The linked list has two nodes. The first one writes 4 bytes on SPI2 and the second one reads 4 bytes on SPI2.
I don't see the clock strokes on the SPI2 bus.

Thanks a lot in advance.

main.c

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* Configure the System Power */
  SystemPower_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_GPDMA1_Init();
  MX_ADC1_Init();
  MX_DAC1_Init();
  MX_ICACHE_Init();
  MX_RAMCFG_Init();
  MX_SPI1_Init();
  MX_SPI2_Init();
  MX_USB_OTG_FS_PCD_Init();
  MX_CORDIC_Init();
  MX_I2C4_Init();
  MX_USART2_UART_Init();
  MX_USART1_UART_Init();
  MX_LPTIM1_Init();
  /* USER CODE BEGIN 2 */

  HAL_StatusTypeDef cret3 = MX_List_ADC3_Config();    

  HAL_StatusTypeDef ret3 = HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel1, &List_ADC3);

  HAL_StatusTypeDef sret3 = HAL_DMAEx_List_Start_IT(&handle_GPDMA1_Channel1);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

 

spi.c

void MX_SPI2_Init(void)
{

  /* USER CODE BEGIN SPI2_Init 0 */

  /* USER CODE END SPI2_Init 0 */

  SPI_AutonomousModeConfTypeDef HAL_SPI_AutonomousMode_Cfg_Struct = {0};

  /* USER CODE BEGIN SPI2_Init 1 */

  /* USER CODE END SPI2_Init 1 */
  hspi2.Instance = SPI2;
  hspi2.Init.Mode = SPI_MODE_MASTER;
  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_HARD_OUTPUT;
  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi2.Init.CRCPolynomial = 0x7;
  hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  hspi2.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
  hspi2.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
  hspi2.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
  hspi2.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
  hspi2.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
  hspi2.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
  hspi2.Init.IOSwap = SPI_IO_SWAP_DISABLE;
  hspi2.Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY;
  hspi2.Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH;
  if (HAL_SPI_Init(&hspi2) != HAL_OK)
  {
    Error_Handler();
  }
  HAL_SPI_AutonomousMode_Cfg_Struct.TriggerState = SPI_AUTO_MODE_DISABLE;
  HAL_SPI_AutonomousMode_Cfg_Struct.TriggerSelection = SPI_GRP1_GPDMA_CH0_TCF_TRG;
  HAL_SPI_AutonomousMode_Cfg_Struct.TriggerPolarity = SPI_TRIG_POLARITY_RISING;
  if (HAL_SPIEx_SetConfigAutonomousMode(&hspi2, &HAL_SPI_AutonomousMode_Cfg_Struct) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI2_Init 2 */
  /* USER CODE END SPI2_Init 2 */

}

gpdma.c

void MX_GPDMA1_Init(void)
{

  /* USER CODE BEGIN GPDMA1_Init 0 */

  /* USER CODE END GPDMA1_Init 0 */

  /* Peripheral clock enable */
  __HAL_RCC_GPDMA1_CLK_ENABLE();

  /* GPDMA1 interrupt Init */
    HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);
    HAL_NVIC_SetPriority(GPDMA1_Channel1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(GPDMA1_Channel1_IRQn);

  /* USER CODE BEGIN GPDMA1_Init 1 */

  /* USER CODE END GPDMA1_Init 1 */
  handle_GPDMA1_Channel1.Instance = GPDMA1_Channel1;
  handle_GPDMA1_Channel1.InitLinkedList.Priority = DMA_LOW_PRIORITY_MID_WEIGHT;
  handle_GPDMA1_Channel1.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
  handle_GPDMA1_Channel1.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT1;
  handle_GPDMA1_Channel1.InitLinkedList.TransferEventMode = DMA_TCEM_LAST_LL_ITEM_TRANSFER;
  handle_GPDMA1_Channel1.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_NORMAL;
  if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel1, DMA_CHANNEL_NPRIV) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN GPDMA1_Init 2 */
  handle_GPDMA1_Channel1.XferCpltCallback = HAL_DMA_ConvCpltCallback;
  /* USER CODE END GPDMA1_Init 2 */

}

 

linked_list.c

HAL_StatusTypeDef MX_List_ADC3_Config(void)
{
  HAL_StatusTypeDef ret = HAL_OK;
  /* DMA node configuration declaration */
  DMA_NodeConfTypeDef pNodeConfig;

  /* Set node configuration ################################################*/
  pNodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
  pNodeConfig.Init.Request = GPDMA1_REQUEST_SPI2_TX;
  pNodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
  pNodeConfig.Init.Direction = DMA_MEMORY_TO_PERIPH;
  pNodeConfig.Init.SrcInc = DMA_SINC_INCREMENTED;
  pNodeConfig.Init.DestInc = DMA_DINC_FIXED;
  pNodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_BYTE;
  pNodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
  pNodeConfig.Init.SrcBurstLength = 1;
  pNodeConfig.Init.DestBurstLength = 1;
  pNodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT1;
  pNodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
  pNodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
  pNodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
  pNodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
  pNodeConfig.SrcAddress = (uint32_t) &adc_command_byte[0];
  pNodeConfig.DstAddress = (uint32_t)&SPI2->TXDR;
  pNodeConfig.DataSize = 4;

  /* Build ND_SPITX Node */
  ret |= HAL_DMAEx_List_BuildNode(&pNodeConfig, &ND_SPITX);

  /* Insert ND_SPITX to Queue */
  ret |= HAL_DMAEx_List_InsertNode_Tail(&List_ADC3, &ND_SPITX);

  /* Set node configuration ################################################*/
  pNodeConfig.Init.Request = GPDMA1_REQUEST_SPI2_RX;
  pNodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
  pNodeConfig.Init.SrcInc = DMA_SINC_FIXED;
  pNodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
  pNodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT1|DMA_DEST_ALLOCATED_PORT0;
  pNodeConfig.SrcAddress = (uint32_t)&SPI2->RXDR;
  pNodeConfig.DstAddress = (uint32_t) &adc_buffer[2][adc_ram_write_index[2]];

  /* Build ND_SPIRX Node */
  ret |= HAL_DMAEx_List_BuildNode(&pNodeConfig, &ND_SPIRX);

  /* Insert ND_SPIRX to Queue */
  ret |= HAL_DMAEx_List_InsertNode_Tail(&List_ADC3, &ND_SPIRX);

   return ret;
}


 

3 REPLIES 3
TDK
Super User

You'll need to enable the SPI before you can send it data.

Get it working without the linked lists first--by sending data to TXDR. Once that's working, incorporate the linked lists.

Or use HAL_SPI_TransmitReceive_DMA.

If you feel a post has answered your question, please click "Accept as Solution".
Saket_Om
ST Employee

Hello @gius2705 

In addition to the recommandation of @TDK , please refer to the article below to configure your DMA linked list mode.

How to configure the linked list mode in STM32Cube... - STMicroelectronics Community

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.
Saket_Om
gius2705
Visitor

Thanks Saket_Om, I have already read that article.
Thanks TDK, I have insert these commands at bottom of MX_SPI2_Init():

 

  SET_BIT(SPI2->CFG1, SPI_CFG1_TXDMAEN | SPI_CFG1_RXDMAEN);
  SET_BIT(SPI2->CR1, SPI_CR1_SPE);

 

but doesn't work. No clocks no data on the bus.