Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Continuous ADC with DMA on NUCLEO-F446RE board not working #89046

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
AdrianSuliga opened this issue Apr 24, 2025 · 1 comment
Closed

Continuous ADC with DMA on NUCLEO-F446RE board not working #89046

AdrianSuliga opened this issue Apr 24, 2025 · 1 comment
Assignees
Labels
area: ADC Analog-to-Digital Converter (ADC) bug The issue is a bug, or the PR is fixing a bug platform: STM32 ST Micro STM32 priority: low Low impact/importance bug

Comments

@AdrianSuliga
Copy link

Describe the bug
I was working on migrating Nucleo F4446RE from FreeRTOS + HAL to ZephyrRTOS and got stuck on setting up continuous ADC + DMA read. Whenever ADC finishes sampling I want DMA to write this new data to a given buffer. What I am seeing instead is just one read being completed.

To Reproduce
My setup:

&adc1 {
    #address-cells = <1>;
    #size-cells = <0>;
    status = "okay";
    st,adc-prescaler = <8>;
    pinctrl-0 = <&adc1_in4_pa4>;
    pinctrl-names = "default";
    channel@4 {
        reg = <0x4>;
        zephyr,gain = "ADC_GAIN_1";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,resolution = <12>;
    };
};

&dma1 {
    status = "disabled";
};

&dma2 {
    status = "okay";
};
CONFIG_ADC=y
CONFIG_ADC_STM32=y
CONFIG_ADC_ASYNC=y

CONFIG_DMA=y
CONFIG_DMA_STM32=y
static const struct device *adc1_dev = DEVICE_DT_GET(DT_NODELABEL(adc1));
static const struct device *dma_dev = DEVICE_DT_GET(DT_NODELABEL(dma2));

static struct dma_config dma_cfg = {0};
static struct dma_block_config dma_block_cfg = {0};

volatile uint16_t adc_buffer;

// Lack of this callback caused usage fault and crash
void dma_callback(const struct device *dev, void *user_data, uint32_t channel, int status)
{

}

void task_adc_meas(void)
{
    int ret = 0;
    k_msleep(2000);
    
    static const struct adc_channel_cfg channel_cfg = {
        .gain = ADC_GAIN_1,
        .reference = ADC_REF_INTERNAL,
        .acquisition_time = ADC_ACQ_TIME_DEFAULT,
        .channel_id = ADC_CHANNEL_4,
    };
    
    ret = adc_channel_setup(adc1_dev, &channel_cfg);
    if (ret != 0) {
        LOG_ERR("COULD NOT SET UP CHANNEL %d", ret);
        return;
    }
    
    dma_cfg.channel_direction = PERIPHERAL_TO_MEMORY;
    dma_cfg.source_data_size = 2;
    dma_cfg.dest_data_size = 2;
    dma_cfg.source_burst_length = 1;
    dma_cfg.dest_burst_length = 1;
    dma_cfg.block_count = 1;
    dma_cfg.head_block = &dma_block_cfg;
    dma_cfg.cyclic = true;
    dma_cfg.dma_callback = dma_callback;

    dma_block_cfg.source_address = (uint32_t)&ADC1->DR;
    dma_block_cfg.dest_address = (uint32_t)&adc_buffer;
    dma_block_cfg.block_size = sizeof(adc_buffer);  
    
    ret = dma_config(dma_dev, 0, &dma_cfg);
    if (ret < 0) {
        LOG_ERR("Could not setup dma %d", ret);
        return;
    }
    
    ret = dma_start(dma_dev, 0);
    if (ret < 0) {
        LOG_ERR("Could not start dma %d", ret);
        return;
    }
    
    ADC1->CR2 |= ADC_CR2_CONT;  
    ADC1->CR2 |= ADC_CR2_DMA;   
    ADC1->CR2 |= ADC_CR2_DDS;   
    ADC1->CR2 |= ADC_CR2_ADON;  
    ADC1->CR2 |= ADC_CR2_SWSTART; 
    
    while (true) { // I should see different values with time
        LOG_INF("ADC1: %d", adc_buffer);
        k_msleep(1000);
    }
}

Expected behavior
With time I expected to see different values being logged into terminal

Environment

  • OS: Linux Mint 22
  • Toolchain: Zephyr SDK 0.17.0
  • Version 4.0.0
@AdrianSuliga AdrianSuliga added the bug The issue is a bug, or the PR is fixing a bug label Apr 24, 2025
@kartben kartben added platform: STM32 ST Micro STM32 area: ADC Analog-to-Digital Converter (ADC) labels Apr 24, 2025
@erwango erwango added the priority: low Low impact/importance bug label Apr 25, 2025
@gautierg-st
Copy link
Collaborator

Unfortunately, continuous sampling on Zephyr is currently not supported for STM32 driver. I don't think there is even the possibility to enable the option using the Zephyr API.
I'm not sure of the behavior of your code, using a mix of driver function and direct call is risky. The driver may rewrite some registers in the interrupts resulting in strange behavior.

As a partial workaround, you could use extra_samplings to sample up to 65536 values at a time. You'll still have to relaunch a read sequence every now and then, but it is at least much less frequent. You can see examples of how it is used in tests/drivers/adc/adc_api/src/test_adc.c

@zephyrproject-rtos zephyrproject-rtos locked and limited conversation to collaborators Apr 28, 2025
@erwango erwango converted this issue into discussion #89175 Apr 28, 2025

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
area: ADC Analog-to-Digital Converter (ADC) bug The issue is a bug, or the PR is fixing a bug platform: STM32 ST Micro STM32 priority: low Low impact/importance bug
Projects
None yet
Development

No branches or pull requests

4 participants