cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 SPI4 transmit Issue with GPDMA ch12 (TIM2 TRGO sync) in circular mode

Juku80001
Associate II

Hello

STM32H7R3L8

I have trouble using the circular mode of GPDMA when trying to transmit data over SPI4. When I set the GPDMA channel 12 to be in circular mode, it generates the GPDMA channel init in the msp init file instead of the main file as if it is a linked list. When I try to start the SPI DMA transmit with function HAL_SPI_Transmit_DMA, then I get an error in the following section of the function’s code

/* Packing mode management is enabled by the DMA settings */
if (((hspi->Init.DataSize > SPI_DATASIZE_16BIT) && (hspi->hdmatx->Init.SrcDataWidth !=  DMA_SRC_DATAWIDTH_WORD) && \
       (IS_SPI_FULL_INSTANCE(hspi->Instance))) || \
      ((hspi->Init.DataSize > SPI_DATASIZE_8BIT)  && (hspi->hdmatx->Init.SrcDataWidth ==  DMA_SRC_DATAWIDTH_BYTE)))
{
    /* Restriction the DMA data received is not allowed in this mode */

    __HAL_UNLOCK(hspi);

    return HAL_ERROR;
}

 

However the transmission works fine if the GPDMA was in standard, non circular and non linked list mode, in which case the GPDMA init is generated in the main.c file.

I was wondering, if I am missing some setup function that would be needed to be used before starting the SPI DMA transmit with that circular setup. Data addresses and bytes sent are the same with either DMA configuration.

Currently, I am setting up the GPDMA, SPI and SPI transmit in the following way using stm32cubeIDE 1.19.0

 

Order of inits:

MX_GPIO_Init();
MX_GPDMA1_Init();
MX_PSSI_Init();
MX_UCPD1_Init();
MX_SPI3_Init();
MX_ADC1_Init();
MX_ADC2_Init();
MX_I2C3_Init();
MX_SPI1_Init();
MX_SPI4_Init();
MX_TIM15_Init();
MX_SPI5_Init();
MX_CRC_Init();
MX_USB_DEVICE_Init();
MX_TIM2_Init();
MX_SBS_Init();

 

SPI setup inside main.c:

static void MX_SPI4_Init(void)
{
  /* USER CODE BEGIN SPI4_Init 0 */

  /* USER CODE END SPI4_Init 0 */

  /* USER CODE BEGIN SPI4_Init 1 */

  /* USER CODE END SPI4_Init 1 */

  /* SPI4 parameter configuration*/
  hspi4.Instance = SPI4;
  hspi4.Init.Mode = SPI_MODE_MASTER;
  hspi4.Init.Direction = SPI_DIRECTION_2LINES;
  hspi4.Init.DataSize = SPI_DATASIZE_16BIT;
  hspi4.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi4.Init.CLKPhase = SPI_PHASE_2EDGE;
  hspi4.Init.NSS = SPI_NSS_HARD_OUTPUT;
  hspi4.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  hspi4.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi4.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi4.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi4.Init.CRCPolynomial = 0x7;
  hspi4.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  hspi4.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
  hspi4.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
  hspi4.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_01CYCLE;
  hspi4.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
  hspi4.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
  hspi4.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
  hspi4.Init.IOSwap = SPI_IO_SWAP_DISABLE;
  hspi4.Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY;
  hspi4.Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH;

  if (HAL_SPI_Init(&hspi4) != HAL_OK)
  {
    Error_Handler();
  }

  /* USER CODE BEGIN SPI4_Init 2 */

  /* USER CODE END SPI4_Init 2 */
}



GPDMA1 setup inside main.c:

static 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_Channel12_IRQn, 0, 0);

    HAL_NVIC_EnableIRQ(GPDMA1_Channel12_IRQn);

  /* USER CODE BEGIN GPDMA1_Init 1 */

  /* USER CODE END GPDMA1_Init 1 */

  /* USER CODE BEGIN GPDMA1_Init 2 */

  /* USER CODE END GPDMA1_Init 2 */
}


Part of the GPDMA setup inside stm32h7rsxx_hal_msp.c void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) function

…
else if(hspi->Instance==SPI4)
  {
    /* USER CODE BEGIN SPI4_MspInit 0 */

    /* USER CODE END SPI4_MspInit 0 */

  /** Initializes the peripherals clock
  */
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI45;
    PeriphClkInit.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PCLK2;

    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    {
      Error_Handler();
    }

    /* Peripheral clock enable */

    __HAL_RCC_SPI4_CLK_ENABLE();
    __HAL_RCC_GPIOE_CLK_ENABLE();

    /**SPI4 GPIO Configuration

    PE14     ------> SPI4_MOSI
    PE2     ------> SPI4_SCK
    PE13     ------> SPI4_MISO
    PE11     ------> SPI4_NSS
    */

    GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_2|GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI4;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI4;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    /* SPI4 DMA Init */

    /* GPDMA1_REQUEST_SPI4_TX Init */

    NodeConfig.NodeType = DMA_GPDMA_2D_NODE;
    NodeConfig.Init.Request = GPDMA1_REQUEST_SPI4_TX;
    NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
    NodeConfig.Init.Direction = DMA_MEMORY_TO_PERIPH;
    NodeConfig.Init.SrcInc = DMA_SINC_INCREMENTED;
    NodeConfig.Init.DestInc = DMA_DINC_FIXED;
    NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_HALFWORD;
    NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_HALFWORD;
    NodeConfig.Init.SrcBurstLength = 1;
    NodeConfig.Init.DestBurstLength = 1;
    NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT1;
    NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
    NodeConfig.Init.Mode = DMA_NORMAL;
    NodeConfig.RepeatBlockConfig.RepeatCount = 1;
    NodeConfig.RepeatBlockConfig.SrcAddrOffset = 0;
    NodeConfig.RepeatBlockConfig.DestAddrOffset = 0;
    NodeConfig.RepeatBlockConfig.BlkSrcAddrOffset = 0;
    NodeConfig.RepeatBlockConfig.BlkDestAddrOffset = 0;
    NodeConfig.TriggerConfig.TriggerMode = DMA_TRIGM_SINGLE_BURST_TRANSFER;
    NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_RISING;
    NodeConfig.TriggerConfig.TriggerSelection = GPDMA1_TRIGGER_TIM2_TRGO;
    NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
    NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;

    if (HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel12) != HAL_OK)
    {
      Error_Handler();
    }

    if (HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel12, NULL, &Node_GPDMA1_Channel12) != HAL_OK)
    {
      Error_Handler();
    }

    if (HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel12) != HAL_OK)
    {
      Error_Handler();
    }

    handle_GPDMA1_Channel12.Instance = GPDMA1_Channel12;
    handle_GPDMA1_Channel12.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
    handle_GPDMA1_Channel12.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
    handle_GPDMA1_Channel12.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT1;
    handle_GPDMA1_Channel12.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
    handle_GPDMA1_Channel12.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;

    if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel12) != HAL_OK)
    {
      Error_Handler();
    }

    if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel12, &List_GPDMA1_Channel12) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(hspi, hdmatx, handle_GPDMA1_Channel12);

    if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel12, DMA_CHANNEL_NPRIV) != HAL_OK)
    {
      Error_Handler();
    }

    /* SPI4 interrupt Init */

    HAL_NVIC_SetPriority(SPI4_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(SPI4_IRQn);

    /* USER CODE BEGIN SPI4_MspInit 1 */

    /* USER CODE END SPI4_MspInit 1 */
  }
…



SPI DMA transmit start inside a function called from main, which is done after inits

if (HAL_SPI_Transmit_DMA(g_spi, (uint8_t*)g_buf + current_bytes_offset, bytes_per_send) != HAL_OK) {
    return;
}

 

0 REPLIES 0