cancel
Showing results for 
Search instead for 
Did you mean: 

Make the STM32H7 example "DMAMUX_RequestGen" work with DMA1 instead of BDMA

GregB
Associate II

Hi,

The example DMAMUX_RequestGen works perfectly on my STM32H755 board and now I'm trying to modify it so it uses the DMA1 instead of the BDMA. I need that because at the end I would like to trigger a SPI5 RX.

Unfortunately I cannot make it work, that means I don't see the output pin toggling when EXTI0 is changing. I have no error during the configuration. And no DMA error neither.

Here is what I changed form the example:

  • Use SRAM1 instead of SRAM4 for the DMA (SRC_Buffer_LED1_Toggle array)
  • Use DMA1 instance instead of BDMA
  • Use DMAMUX1 instead of DMAMUX2
  • Enable DMA1 and SRAM1 clocks

What did I forget? What shall I check?

This is the source code:

/*Buffer location and size should aligned to cache line size (32 bytes) */
/* Use SRAM4 for BDMA, or SRAM1 for DMA1 */
#if defined(__ICCARM__)
#ifdef USE_BDMA
#pragma location = 0x38000000
#else
#pragma location = 0x30000000
#endif
uint32_t SRC_Buffer_LED1_Toggle[2] =
{
    0,  /*Value for LED 1 ON  */
    GPIO_PIN_10  /*Value for LED 1 OFF */
};
#endif
 
static void init_and_start_exti0_dma()
{
    HAL_StatusTypeDef ret;
    HAL_DMA_MuxRequestGeneratorConfigTypeDef dmamux_ReqGenParams = {0};
 
    /* Configure the PF10 pin   */
    __HAL_RCC_GPIOF_CLK_ENABLE();
    GPIO_InitTypeDef gpio_init_structure;
    gpio_init_structure.Mode = GPIO_MODE_OUTPUT_PP;
    gpio_init_structure.Pull = GPIO_PULLUP;
    gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH;
    gpio_init_structure.Pin = GPIO_PIN_10;
    HAL_GPIO_Init(GPIOF, &gpio_init_structure);
    HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, GPIO_PIN_SET);
 
    /*##-2- Configure the DMA ##################################################*/
 
    /* Enable BDMA and DMA1 clock */
#ifdef USE_BDMA
    __HAL_RCC_BDMA_CLK_ENABLE();
#else
    __HAL_RCC_D2SRAM1_CLK_ENABLE();
    __HAL_RCC_DMA1_CLK_ENABLE();
#endif
 
    /* Configure the DMA handler for Transmission process     */
    /* DMA mode is set to circular for an infinite DMA transfer */
#ifdef USE_BDMA
    DMA_Handle.Instance = BDMA_Channel0;
    DMA_Handle.Init.Request = BDMA_REQUEST_GENERATOR0;
#else
    DMA_Handle.Instance = DMA1_Stream0;
    DMA_Handle.Init.Request = DMA_REQUEST_GENERATOR0;
#endif
    DMA_Handle.Init.Direction = DMA_MEMORY_TO_PERIPH;
    DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE;
    DMA_Handle.Init.MemInc = DMA_MINC_ENABLE;
    DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    DMA_Handle.Init.Mode = DMA_CIRCULAR;
    DMA_Handle.Init.Priority = DMA_PRIORITY_LOW;
    DMA_Handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    DMA_Handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    DMA_Handle.Init.MemBurst = DMA_MBURST_SINGLE;
    DMA_Handle.Init.PeriphBurst = DMA_PBURST_SINGLE;
 
    /* Initialize the DMA with for Transmission process */
    ret = HAL_DMA_Init(&DMA_Handle);
    assert(ret == HAL_OK);
 
    /* Select Callbacks functions called after Transfer complete and Transfer error */
    HAL_DMA_RegisterCallback(&DMA_Handle, HAL_DMA_XFER_CPLT_CB_ID, NULL);
    HAL_DMA_RegisterCallback(&DMA_Handle, HAL_DMA_XFER_ERROR_CB_ID, HAL_TransferError);
 
    /* NVIC configuration for DMA transfer complete interrupt*/
#ifdef USE_BDMA
    HAL_NVIC_SetPriority(BDMA_Channel0_IRQn, 0, 1);
    HAL_NVIC_EnableIRQ(BDMA_Channel0_IRQn);
#else
    HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 1);
    HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
#endif
 
    /*##-4- Configure and enable the EXTI0 used as DMA external request signal #####*/
    EXTI0_IRQHandler_Config();
 
    /*##-3- Configure and enable the DMAMUX Request generator  ####################*/
#ifdef USE_BDMA
    dmamux_ReqGenParams.SignalID = HAL_DMAMUX2_REQ_GEN_EXTI0;  /* External request signal is EXTI0 signal */
#else
    dmamux_ReqGenParams.SignalID = HAL_DMAMUX1_REQ_GEN_EXTI0;  /* External request signal is EXTI0 signal */
#endif
    dmamux_ReqGenParams.Polarity = HAL_DMAMUX_REQ_GEN_FALLING;  /* External request signal edge is Falling  */
    dmamux_ReqGenParams.RequestNumber = 1;  /* 1 requests on each edge of the external request signal  */
 
    ret = HAL_DMAEx_ConfigMuxRequestGenerator(&DMA_Handle, &dmamux_ReqGenParams);
    assert(ret == HAL_OK);
 
    /* NVIC configuration for DMAMUX request generator overrun errors*/
#ifdef USE_BDMA
    HAL_NVIC_SetPriority(DMAMUX2_OVR_IRQn, 0, 1);
    HAL_NVIC_EnableIRQ(DMAMUX2_OVR_IRQn);
#else
    HAL_NVIC_SetPriority(DMAMUX1_OVR_IRQn, 0, 1);
    HAL_NVIC_EnableIRQ(DMAMUX1_OVR_IRQn);
#endif
 
    ret = HAL_DMAEx_EnableMuxRequestGenerator(&DMA_Handle);
    assert(ret == HAL_OK);
 
    /*##-5- Start the DMA transfer ################################################*/
    /* DMA source buffer is  SRC_BUFFER_LED1_TOGGLE containing values to be written
       to GPIOF ODR register in order to turn LED1 On/Off each time comes a request from the DMAMUX request generator */
    ret = HAL_DMA_Start_IT(&DMA_Handle, (uint32_t)SRC_Buffer_LED1_Toggle, (uint32_t)&GPIOF->ODR, 2);
    assert(ret == HAL_OK);
}

Thank you for any help.

1 ACCEPTED SOLUTION

Accepted Solutions
GregB
Associate II

This is the answer I got from ST:

The behaviour with the EXTI0 is different in domain D3 (triggering BDMA from EXTI0). This is due to the fact that the domain D3 is designed for autonomous mode where both CPU core are OFF. The EXTI0 can only be used as an event. It is automatically cleared.

With DMAMUX1 in domain D2, if a trigger is needed without executing an IRQ handler, the EXTI0 is not the good one. A timer or a DMA event has to be used instead.

 

More information can be found in the Release Manual (EXTI, DMAMUX, PWR sections) and AN5224 (STM32 DMAMUX: the DMA request router).

View solution in original post

3 REPLIES 3

Read out and check/post content of DMAMUX/DMA registers, perhaps also relevant GPIO and whichever register steers the given EXTI input (I don't use the 'H7, in most families it's in SYSCFG).

JW

GregB
Associate II

Please find the register values in the attachment.

GregB
Associate II

This is the answer I got from ST:

The behaviour with the EXTI0 is different in domain D3 (triggering BDMA from EXTI0). This is due to the fact that the domain D3 is designed for autonomous mode where both CPU core are OFF. The EXTI0 can only be used as an event. It is automatically cleared.

With DMAMUX1 in domain D2, if a trigger is needed without executing an IRQ handler, the EXTI0 is not the good one. A timer or a DMA event has to be used instead.

 

More information can be found in the Release Manual (EXTI, DMAMUX, PWR sections) and AN5224 (STM32 DMAMUX: the DMA request router).