Skip to main content
Visitor II
May 13, 2020
Question

STM32G431KB DAC DMA not working

  • May 13, 2020
  • 16 replies
  • 10585 views

Trying to get a basic sample DAC1 with DMA, triggered by TIM2 working.

This should be trivial, works fine on SMT32F3. I'm using a Nucleo-32 SMT32G431.

Using Cube IDE. The only non IDE-generated code in main is:

 /* USER CODE BEGIN 2 */
 
 static uint16_t x[4];
 x[0]= 100;
 x[1]= 1000;
 x[2]= 2000;
 x[3]= 3000;
 
 HAL_TIM_Base_Start_IT(&htim2);
 HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, (uint32_t*)x, 4, DAC_ALIGN_12B_R);
 
 /* USER CODE END 2 */

IOC configuration:

  • DAC with output buffer (verified, works fine in non-DMA mode)
  • circular DMA buffer, 1/2 word
  • trigger: TIM2 update
  • TIM2: set to count up to 500, internal clock (works, verified by reading the clock)

Compared to some DAC/DMA examples - everything seems fine (and works on a Nucleo-32 SMT32F3. Please help - this is extremely frustrating and has held up a a project for 3 days.

test1.ioc and main.c files attached.

Thank you!

Paul

    This topic has been closed for replies.

    16 replies

    Super User
    May 14, 2020

    I'm not going to investigate this, but IIRC DMAMUX in Cube (some other STM32 family's which has DMAMUX I looked at some time ago) is set automagically inside some of the usual DMA setup functions, so CubeMX does not need to be aware of it. I may be mistaken, I obviously don't Cube.

    JW

    Explorer
    September 22, 2020

    Great thread! I am facing the same issue on a STM32G431 processor, I copied the code posted above with the proposed changes​, but the DAC out is not updating, despite a running timer.

    I​ suspect that I missed something in the DMAMUX, is there anyone so kind to explain whether more DMAMUX registers need to be updated? Thanks!

    Graduate II
    July 31, 2023

    Me too. Only strangely the version I made for the nucleo board works on the 100 pin chip used for the PCBs made. I solved the ADC by using a HAL_DMA_init() call that I never had to use before (perhaps later versions of the CubeMX used to put this call in and now don't?). However the DAC output which used to work fine on a neucleo board simply does not start. The

     

        if (HAL_DAC_Start_DMA(&hdac3, DAC_CHANNEL_2, (uint32_t*) &dac_data_out[0], size,
          DAC_ALIGN_12B_R) != HAL_OK) {
          Error_Handler();
        }

    Returns HAL_OK. The DMA simply just does not start.

    Graduate II
    September 12, 2023

    FOR the STM32G series: I found out what this was. In the GUI you have to make the word size WORD even though its a 12 bit DAC. Strangely there is no error message if you try to use half word AND when you run the code it simply does not start. Subtle one.

    Explorer
    September 22, 2023

    That worked for me i.e. changing Half Word to Word. Thanks!

    Visitor II
    September 9, 2023

    I tried with STM32G431CBT6 but failed by Arduino IDE.

    bool initDMA( uint8_t pin, uint8_t *wave, uint32_t freq, uint32_t len ) {
    // https://vivonomicon.com/2019/07/05/bare-metal-stm32-programming-part-9-dma-megamix/ -- DAC configuration.
    //-------------------------
    RCC->AHB2ENR |= ( RCC_AHB2ENR_DAC1EN);
    RCC->APB1ENR1 |= (RCC_APB1ENR1_TIM6EN);
    RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN | RCC_AHB1ENR_DMAMUX1EN;
    // https://community.st.com/t5/stm32-mcus-products/stm32g431kb-dac-dma-not-working/td-p/251096/page/2
    if( dac_channel == 0 ) {
    DMAMUX1_Channel2->CCR &= ~DMAMUX_CxCR_DMAREQ_ID;
    DMAMUX1_Channel2->CCR |= ( 0x6 << DMAMUX_CxCR_DMAREQ_ID_Pos );
    //DMAMUX1_Channel2->CCR |= DMA_REQUEST_DAC1_CHANNEL1; // DAC1 CH1 6
    DMA1_Channel3->CCR &= ~DMA_CCR_EN; // It must not be written when the channel is enabled
    DMA1_Channel3->CCR = DMA_CCR_MINC // memory increment
    | DMA_CCR_DIR // memory to peripheral
    //| ( 0x2 << DMA_CCR_PSIZE_Pos ) // 32 bit
    | DMA_CCR_CIRC; // curcular mode
    //
    DMA1_Channel3->CNDTR = len; // how many data to transfer
    DMA1_Channel3->CMAR = (uint32_t)&wave[ 0 ];
    DMA1_Channel3->CPAR = (uint32_t)&( DAC->DHR8R1 ); // destination address - DAC 8 bit output register
    DMA1_Channel3->CCR |= DMA_CCR_EN;
    }
    else {
    DMAMUX1_Channel3->CCR &= ~DMAMUX_CxCR_DMAREQ_ID;
    DMAMUX1_Channel3->CCR |= ( 0x7 << DMAMUX_CxCR_DMAREQ_ID_Pos );
    //DMAMUX1_Channel3->CCR |= DMA_REQUEST_DAC1_CHANNEL2; // DAC1 CH2 7
    DMA1_Channel4->CCR &= ~DMA_CCR_EN;
    DMA1_Channel4->CCR = DMA_CCR_MINC // memory increment
    | DMA_CCR_DIR // memory to peripheral
    //| ( 0x2 << DMA_CCR_PSIZE_Pos ) // 32 bit
    | DMA_CCR_CIRC; // curcular mode
    //
    DMA1_Channel4->CNDTR = len; // how many data to transfer
    DMA1_Channel4->CMAR = (uint32_t)wave;
    DMA1_Channel4->CPAR = (uint32_t)&( DAC->DHR8R2 ); // destination address - DAC 8 bit output register
    }
    //-------------------------------------------------
    // https://vivonomicon.com/2019/07/05/bare-metal-stm32-programming-part-9-dma-megamix/
    TIM6->CR1 &= ~TIM_CR1_CEN;
    TIM6->ARR = SystemCoreClock / ( freq * len ) - 1;
    TIM6->CR2 &= ~TIM_CR2_MMS;
    TIM6->CR2 |= 2 << TIM_CR2_MMS_Pos; // the update event is selected as trigger output
    TIM6->CR1 |= TIM_CR1_CEN;
    //-----------------------------------------------------------------------
    pinMode( pin, OUTPUT );
    switch( pin ) {
    case PA4 :
    GPIOA->MODER &= ~( 0x3 << ( 4 * 2 ) );
    GPIOA->MODER |= ( 0x3 << ( 4 * 2 ) );
    //GPIOA->MODER |= GPIO_MODER_MODE4;
    dac_channel = 0;
    DAC->CR &= ~( DAC_CR_EN1 | DAC_CR_CEN1 ); // for register access
    DAC->MCR &= ~DAC_MCR_MODE1;
    DAC->CR |= DAC_CR_TEN1; // trigger enable
    DAC->CR |= DAC_CR_DMAEN1; // DMA 사용
    DAC->CR &= ~DAC_CR_TSEL1; // DAC channel1 trigger selection
    DAC->CR |= DAC_TRIGGER_T6_TRGO; // DAC_TRIGGER_T6_TRGO
    DAC->CR |= DAC_CR_EN1;
    while( ( DAC->SR & DAC_SR_DAC1RDY ) == 0 );
    break;
    case PA5 :
    GPIOA->MODER &= ~( 0x3 << ( 5 * 2 ) );
    GPIOA->MODER |= ( 0x3 << ( 5 * 2 ) );
    //GPIOA->MODER |= GPIO_MODER_MODE5;
    dac_channel = 1;
    DAC->CR &= ~( DAC_CR_EN2 | DAC_CR_CEN2 ); // for register access
    DAC->MCR &= ~DAC_MCR_MODE2;
    DAC->CR |= DAC_CR_TEN2; // trigger enable
    DAC->CR |= DAC_CR_DMAEN2; // DMA 사용
    DAC->CR &= ~DAC_CR_TSEL2; // DAC channel2 trigger selection
    DAC->CR |= DAC_TRIGGER_T6_TRGO; // DAC_TRIGGER_T6_TRGO 7
    DAC->CR |= DAC_CR_EN2;
    while( ( DAC->SR & DAC_SR_DAC2RDY ) == 0 );
    break;
    default : return false;
    }

    return true;
    }

    Super User
    September 9, 2023

    "Manually" filled DAC (in a loop, using loopdelay) works?

    TIM6_CNT, DMA_NDTR do change when observed in debugger?

    Read out and check/post content of TIM, DMA, DAC and relevant GPIO registers.

    JW

    Explorer
    July 31, 2025

    I am having the same problem with STM32G431KBU6. I think this microcontroller don´t work with DMA, to reach the callbacks, i try a lot of ways and nothing. Really bad.

    Super User
    August 1, 2025

    Please don't hijack old threads - start a new one, describing your HW and SW, expected behaviour and how observed one departs from it, and attach readout values from registers of relevant peripherals.

    JW