cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G030 ADC DMA Not Working

shohanur00
Visitor

Hi all,

I am using STM32G030F6P6 and trying to read ADC channel 11 and channel 16 using DMA.

  • ADC works correctly in polling and interrupt mode.

  • When I enable DMA, the ADC values in the buffer remain 0 all the time.

  • DMA does not trigger at EOC, and DMA transfer never happens.

I have been trying for 1 week, and I cannot understand what is wrong.


What I have done:

  • Configured ADC correctly (calibration, sequence, sampling time, etc.)

  • Configured DMA correctly (channel, source/destination, size, circular mode)

  • Enabled ADC DMA request (DMAEN)

  • Enabled DMAMUX (for STM32G0 series)

But still no data is transferred and buffer remains 0.

 

#include  "stm32g030xx.h"
#include  "gpio.h"

volatile uint32_t adc_value[2] = {0},adc_buff = 0, adc_index = 0;

void delay_ms(uint32_t ms)
{
    SysTick->LOAD = 64000 - 1;   // 64MHz ? 1ms
    SysTick->VAL  = 0;
    SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
                    SysTick_CTRL_ENABLE_Msk;

    for(uint32_t i = 0; i < ms; i++)
    {
        while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
    }
}

void RCC_Clock_Config(void){
//Clock Config
RCC->CR &= ~RCC_CR_PLLON;
while(RCC->CR & RCC_CR_PLLRDY);
RCC->PLLCFGR &= ~RCC_PLLCFGR_PLLSRC;   // Clear both PLLSRC bits
RCC->PLLCFGR |=  RCC_PLLCFGR_PLLSRC_1; // 10b ? HSI16
RCC->PLLCFGR &= ~RCC_PLLCFGR_PLLM;
RCC->PLLCFGR |= RCC_PLLCFGR_PLLM_0;
RCC->PLLCFGR &= ~RCC_PLLCFGR_PLLN;
RCC->PLLCFGR |= (16U << RCC_PLLCFGR_PLLN_Pos);
RCC->PLLCFGR &= ~RCC_PLLCFGR_PLLR;
RCC->PLLCFGR |= (1U << RCC_PLLCFGR_PLLR_Pos);
RCC->CR |= RCC_CR_PLLON;
while(!(RCC->CR & RCC_CR_PLLRDY)); 
RCC->PLLCFGR |= RCC_PLLCFGR_PLLREN;

FLASH->ACR &= ~FLASH_ACR_LATENCY;
FLASH->ACR |= FLASH_ACR_LATENCY_2;  // 48–64 MHz ? 2 WS

RCC->CFGR &= ~RCC_CFGR_SW;
RCC->CFGR |= (2 << RCC_CFGR_SW_Pos);
while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != 0x2);
}

void UART2_Init(void){
RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
GPIO_Init(GPIOA,2,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_NOPULL,GPIO_SPEED_HIGH);
GPIOA->AFR[0] &= ~GPIO_AFRL_AFSEL2_Msk;
GPIOA->AFR[0] |= (1U << GPIO_AFRL_AFSEL2_Pos);
RCC->APBENR1 |= RCC_APBENR1_USART2EN;
USART2->CR1 = 0;
USART2->BRR = 556; // 115200 baud @ 64MHz
USART2->CR1 |= USART_CR1_UE;
USART2->CR1 |= USART_CR1_TE;
}

void UART2_Send_Byte(uint8_t c){
while(!(USART2->ISR & USART_ISR_TXE_TXFNF));
    USART2->TDR = c;
while(!(USART2->ISR & USART_ISR_TC)); // wait transmission complete
}

void UART2_Send_Number(int32_t num)
{
    char buf[12];   // enough for -2147483648
    int i = 0;

    if(num == 0){
        UART2_Send_Byte('0');
        return;
    }

    if(num < 0){
        UART2_Send_Byte('-');
        num = -num;
    }

    while(num > 0){
        buf[i++] = (num % 10) + '0';
        num /= 10;
    }

    while(i--){
        UART2_Send_Byte(buf[i]);
    }
}

void ADC_Init(void){
RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
GPIO_Init(GPIOA,10,GPIO_MODE_ANALOG,GPIO_OTYPE_PP,GPIO_NOPULL,GPIO_SPEED_LOW); //ADC Channel 16
RCC->IOPENR |= RCC_IOPENR_GPIOBEN;
GPIO_Init(GPIOB,7,GPIO_MODE_ANALOG,GPIO_OTYPE_PP,GPIO_NOPULL,GPIO_SPEED_LOW);  //ADC Channel 11
RCC->APBENR2 |= RCC_APBENR2_ADCEN;

ADC1->CR &= ~ADC_CR_ADEN;
while(ADC1->CR & ADC_CR_ADEN);

ADC1->CR |= ADC_CR_ADVREGEN;
for(volatile int i=0;i<30000;i++);
ADC1->CR |= ADC_CR_ADCAL;
while(ADC1->CR & ADC_CR_ADCAL);

ADC1->CFGR1 = 0;
ADC1->CFGR1 |= ADC_CFGR1_CONT;
ADC1->CFGR1 |= ADC_CFGR1_CHSELRMOD;

ADC1->CFGR1 |= ADC_CFGR1_DMAEN;
ADC1->CFGR1 |= ADC_CFGR1_DMACFG;
//ADC1->CFGR1 |= ADC_CFGR1_CHSELRMOD;
ADC1->CFGR1 |= ADC_CFGR1_OVRMOD; // overwrite old data
ADC1->SMPR &= ~ ADC_SMPR_SMP1_Msk;
ADC1->SMPR |= (7U << ADC_SMPR_SMP1_Pos);
//ADC->CCR &= ~ADC_CCR_TSEN;   // ?? this is the missing piece

/*ADC1->IER |= ADC_IER_EOCIE;
NVIC_SetPriority(ADC1_IRQn, 0);
NVIC_EnableIRQ(ADC1_IRQn);
__enable_irq();*/

ADC1->CHSELR = ADC_CHSELR_CHSEL11 | ADC_CHSELR_CHSEL16;

ADC1->CR |= ADC_CR_ADEN;
while (!(ADC1->ISR & ADC_ISR_ADRDY)); // ADC ready
//ADC1->CR |= ADC_CR_ADSTART;
}

uint16_t ADC_Read(void){
    //ADC1->CR |= ADC_CR_ADSTART;
    while(!(ADC1->ISR & ADC_ISR_EOC));

    return ADC1->DR;
}

void DMA_Init(void){
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
DMA1_Channel1->CCR = 0;
DMA1_Channel1->CCR |= (3 << DMA_CCR_PL_Pos);  //Priority set very High
DMA1_Channel1->CCR |= (1 << DMA_CCR_MSIZE_Pos); // 16 bits
DMA1_Channel1->CCR |= (1 << DMA_CCR_PSIZE_Pos);
DMA1_Channel1->CCR &= ~DMA_CCR_DIR; 
DMA1_Channel1->CCR |= DMA_CCR_CIRC; //Circularly porbe
DMA1_Channel1->CCR |= DMA_CCR_MINC;

DMA1_Channel1->CPAR = (uint32_t) &(ADC1->DR);
DMA1_Channel1->CMAR = (uint32_t)adc_value;
DMA1_Channel1->CNDTR = 2;
//DMA1_Channel1->CCR |= DMA_CCR_EN;
}

int main(void){
//Clock Config
RCC_Clock_Config();
//GPIO
//__enable_irq();
RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
GPIO_Init(GPIOA,4,GPIO_MODE_OUTPUT,GPIO_OTYPE_PP,GPIO_NOPULL,GPIO_SPEED_LOW);
//ADC
UART2_Init();
DMA_Init();
ADC_Init();
DMA1_Channel1->CCR |= DMA_CCR_EN;   // enable DMA channel
ADC1->CR |= ADC_CR_ADSTART;         // start ADC conversions

while(1){
int16_t adc = adc_buff;
int16_t T = 0;

UART2_Send_Number(adc_value[0]& 0xFFFF);
UART2_Send_Byte('\n');
UART2_Send_Byte('\r');
UART2_Send_Number(adc_value[1]& 0xFFFF);
UART2_Send_Byte('\n');
UART2_Send_Byte('\r');
GPIO_TogglePin(GPIOA,4);
delay_ms(100);
}
}

void ADC1_IRQHandler(void)
{
    if (ADC1->ISR & ADC_ISR_EOC)
    {
        uint16_t val = ADC1->DR;   // MUST read DR to clear EOC

        adc_value[adc_index] = val;

        adc_index++;
        if (adc_index >= 2)
            adc_index = 0;
    }
}
 

Problem:

The DMA never transfers data and the buffer remains 0.

Even though ADC conversion is running and EOC flag is set, DMA is not triggered.


Request:

Please help me identify what is missing or wrong in my configuration.

What should I check?


Thank you.

 

Edited to apply source code formatting - please see How to insert source code for future reference.

9 REPLIES 9
Andrew Neil
Super User

Welcome to the forum.

Please see How to write your question to maximize your chances to find a solution for best results

In particular, please give details of your hardware setup, and your software tools.

 

Have you tried the examples provided by ST ?

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

I am using STM32G030F6P6 with Keil uVision. I am programming in bare-metal (no HAL/CubeMX). I did not use any ST example. I configured the ADC and DMA manually based on the datasheet, and I also tried using code generated with ChatGPT, but the DMA still does not work.


@shohanur00 wrote:

I am using STM32G030F6P6

That's just the STM32 chip - what about the external hardware?

See point 2 & 3 of How to write your question to maximize your chances to find a solution 

 

PS:

 


@shohanur00 wrote:

I did not use any ST example.


Would be worth trying.

 


@shohanur00 wrote:

 I also tried using code generated with ChatGPT, .


Have you tried Sidekick - ST's AI agent specifically trained for STM32?

How to use STM32 Sidekick

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
shohanur00
Visitor

I have use 2 ant sensor at PA10 and PB7, I have read ntc sensor value with polling and interrupt method , Thats works fine , but DMA method not working . 

I have use 2 ant sensor at PA10 and PB7, I have read ntc sensor value with polling and interrupt method , Thats works fine , but DMA method not working . 

I have use 2 ntc sensor at PA10 and PB7, I have read ntc sensor value with polling and interrupt method , Thats works fine , but DMA method not working . 

I haven't use sidekick

TDK
Super User

I suggest getting the working examples up and running. If you really want to use bare metal, compare register values on the working examples vs your code.

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

Where I will get bare metal example?

Start a project in CubeMX - choose to base it on an example from the list.

You still haven't said what board you're using but, if it's an ST board, there will be examples specifically for it ...

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.