cancel
Showing results for 
Search instead for 
Did you mean: 

HPDMA with ADC with STM32 MCU(H7S3L8)

prometheans152
Associate II

Hi,

 

I tried to set up and use HPDMA with ADC on my Nucleo-H7S3L8,

but I have some questions about how to use it.

  1. I could not find documentation on using HPDMA with STM32 MCU, only for GPDMA.
  2. I found an HPDMA example for the Nucleo-H7S3L8 (ADC_SingleConversion_TriggerSW_HPDMA), but I don't get the logic. Why are both HAL_ADC_Start_DMA() and HAL_ADC_Start() used together? Normally, you'd just use HAL_ADC_Start_DMA(), right?
    prometheans152_0-1720659795732.png

     

  3. Continuing from my previous question, if I want to modify this example to support multiple channels, Continuous Conversion Mode, and DMA circular mode, how should I do it?
    I tried modifying the ADC parameters to Continuous Conversion Mode and DMA circular mode, but it still only runs once.
    Then I tried enabling Circular Mode in HPDMA, but it gets stuck at HAL_ADC_Start_DMA.

  4. If possible, could you teach me how to modify it for multiple channels? I'm not sure whether to use End of single conversion or End of sequence of conversion. I have 9 channels.
    I'm also not sure how to configure it with DMA.

Attached is the ADC_SingleConversion_TriggerSW_HPDMA example.

1 ACCEPTED SOLUTION

Accepted Solutions

Hi @CMYL 

 

Your code for regular DMA cannot be used with GPDMA and HPDMA.

I successfully ran Continuous Conversion Mode and DMA Circular Mode after enabling HPDMA and ADC in CubeMX.

Based on my debugging experience, the following points are key (though they might not be entirely correct).

  1. Enable M7 APPLI MPU
    prometheans152_1-1723169003787.png

     

  2. Enable HPDMA and configure
    prometheans152_0-1723168942991.png
  3. Link data to HPDMA channel node and enable HPDMA clock(By the way, I don't know why CubeMX didn't enable the HPDMA clock for me. Is this a bug?)
    prometheans152_2-1723169146951.pngprometheans152_3-1723169157238.png
    prometheans152_4-1723169172160.png

     

My method is not a very good one; I found your GPDMA tutorial.
https://rristm.github.io/tomas_materials_v2/RRISTM/stm32u5_workshop/master

 

I followed the link-list setup in the tutorial, but it didn't work.One important reason is that the U5 only has one project, while the H7S3 has two: BOOT and APPLI.Maybe you should release an HPDMA tutorial for the H7S3.

View solution in original post

7 REPLIES 7
CMYL
ST Employee

Hello @prometheans152,

 

I agree with you HAL_ADC_Start is not mandatory we need only HAL_ADC_Start_DMA().

To configure the ADC in DMA Circular mode along with Continuous Conversion mode for 9 ADC channels, follow these steps:

  1. Initialize the ADC:

    • Set the ContinuousConvMode to ENABLE.
    • Set the ConversionDataManagement to ADC_CONVERSIONDATA_DMA_CIRCULAR.
    • Configure the number of conversions to 9 and set up the channels.
  2. Configure the DMA:

    • Ensure the DMA is set to circular mode to handle continuous data transfer.
  3. Start the ADC with DMA:

    • Use the HAL_ADC_Start_DMA function to start the ADC in DMA mode.

Here is a sample code snippet to illustrate the configuration:

#include "main.h"

ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;

#define ADC_CONVERTED_DATA_BUFFER_SIZE 9

uint32_t aADCxConvertedData[ADC_CONVERTED_DATA_BUFFER_SIZE];

void ADC_Init(void)
{
    // Initialize the ADC handle
    hadc1.Instance = ADC1;
    hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
    hadc1.Init.Resolution = ADC_RESOLUTION_12B;
    hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE; // Enable scan mode for multiple channels
    hadc1.Init.ContinuousConvMode = ENABLE; // Enable continuous conversion mode
    hadc1.Init.DiscontinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc1.Init.NbrOfConversion = 9; // Number of conversions
    hadc1.Init.DMAContinuousRequests = ENABLE;
    hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
    hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR; // Set DMA circular mode

    if (HAL_ADC_Init(&hadc1) != HAL_OK)
    {
        // Initialization Error
        Error_Handler();
    }

    // Configure the ADC channels
    ADC_ChannelConfTypeDef sConfig = {0};
    for (uint32_t i = 0; i < 9; i++)
    {
        sConfig.Channel = ADC_CHANNEL_0 + i; // Assuming channels 0 to 8
        sConfig.Rank = ADC_REGULAR_RANK_1 + i;
        sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
        if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
        {
            // Channel Configuration Error
            Error_Handler();
        }
    }
}

void DMA_Init(void)
{
    // Initialize the DMA handle
    __HAL_RCC_DMA1_CLK_ENABLE();

    hdma_adc1.Instance = DMA1_Channel1;
    hdma_adc1.Init.Request = DMA_REQUEST_ADC1;
    hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
    hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_adc1.Init.Mode = DMA_CIRCULAR; // Set DMA to circular mode
    hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;

    if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
    {
        // Initialization Error
        Error_Handler();
    }

    __HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1);
}

void Start_ADC_DMA(void)
{
    if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *)aADCxConvertedData, ADC_CONVERTED_DATA_BUFFER_SIZE) != HAL_OK)
    {
        // Start Error
        Error_Handler();
    }
}

int main(void)
{
    HAL_Init();
    SystemClock_Config();

    ADC_Init();
    DMA_Init();
    Start_ADC_DMA();

    while (1)
    {
        // Main loop
    }
}

Hi @CMYL 

 

Your code for regular DMA cannot be used with GPDMA and HPDMA.

I successfully ran Continuous Conversion Mode and DMA Circular Mode after enabling HPDMA and ADC in CubeMX.

Based on my debugging experience, the following points are key (though they might not be entirely correct).

  1. Enable M7 APPLI MPU
    prometheans152_1-1723169003787.png

     

  2. Enable HPDMA and configure
    prometheans152_0-1723168942991.png
  3. Link data to HPDMA channel node and enable HPDMA clock(By the way, I don't know why CubeMX didn't enable the HPDMA clock for me. Is this a bug?)
    prometheans152_2-1723169146951.pngprometheans152_3-1723169157238.png
    prometheans152_4-1723169172160.png

     

My method is not a very good one; I found your GPDMA tutorial.
https://rristm.github.io/tomas_materials_v2/RRISTM/stm32u5_workshop/master

 

I followed the link-list setup in the tutorial, but it didn't work.One important reason is that the U5 only has one project, while the H7S3 has two: BOOT and APPLI.Maybe you should release an HPDMA tutorial for the H7S3.

Hello @prometheans152 

Sorry, I didn't pay attention that GPDMA/HPDMA is used. The H7S/R series has only GPDMA versus DMA in H7xx series. 

Let me notice the difference in circular mode programming between GPDMA/HPDMA (General Purpose DMA) and DMA (Direct Memory Access).

  • GPDMA: When using GPDMA in circular mode, it is essentially linked-list with one node configuration. This means that even if you select "Standard Request mode," the configuration will still involve linked-list.
  • DMA: Traditional DMA does not inherently require linked-list configuration for circular mode. It can operate in circular mode without the need for linked-list setup (as linked list is not supported).

Thanks for giving the solution :)

I highlight the workshop reference for community on STM32U5 GPDMA / LPBAM / ULP modes: https://rristm.github.io/tomas_materials_v2/RRISTM/stm32u5_workshop/master

 

Best regards,

 

Hi @CMYL 

I think there are many deficiencies in your information about the H7S3 HPDMA.

The main points are as follows:

  1. Regarding the HPDMA tutorial, there are no documents available. Although it can be said that HPDMA is the same as GPDMA, there is no explanation provided that clarifies they are the same.
  2. The dual project design of the H7S3 leads to a different coding experience compared to previous ones. As a result, online tutorials or articles may not be reliable references.This results in HPDMA not being usable based on experience with U5 or H5.
  3. The examples are incomplete and contain errors.

I believe your intention to introduce new technology is good, but could you please ensure everything is well-prepared before launching? This isn't the video game industry, where release debugging is acceptable.

CMYL
ST Employee

Hello @prometheans152 

Sorry I missed a last comment in my last message above: " I'm working on a project for Continuous Conversion Mode and DMA Circular Mode based on HPDMA, I will share it with you". 

Note that for H7S series you need to focus on Appli project and use the boot project as provided by CubeMx for the Nucleo-H7S. Otherwise, I will share with you also the Howto for running and debugging your usecase. 

For your third comment: ( 3. The examples are incomplete and contain errors.)

  • Could you please share with me the examples that are not running and what examples are incomplete !! 

Otherwise, all the official documentations required to launch the product are available (STM32H7R7/7S7 - PDF Documentation:( RM0477, ANs, datasheets and ES ....  HPDMA for example is detailed in chapter 13 of RM0477.

 

Best regards

 

 

CMYL
ST Employee

Hi @prometheans152 

I deeply reviewed your questions. Here the answers to questions 1 and 2.

(I keep the answers to 3 and 4 in the next prompt window.)

  1. I could not find documentation on using HPDMA with STM32 MCU, only for GPDMA:Answer: HPDMA is detailed into the RM0477, chap 13.
  2. I found an HPDMA example for the Nucleo-H7S3L8 (ADC_SingleConversion_TriggerSW_HPDMA), but I don't get the logic. 
    • Normally, you'd just use HAL_ADC_Start_DMA(), right?
    • ==> Answer:Your are right HAL_ADC_Start_DMA() and HAL_ADC_Start() can't be used together unless in your configuration of ADC you choose single conversion.
    • Why are both HAL_ADC_Start_DMA() and HAL_ADC_Start() used together in the example ? 
    • ==> Answer: This is related to the use case choice of ADC and HPDMA configurations as given by the readme file. The ADC peripheral performs a single ADC conversion on a channel at each "software start" as the ADCcontinuous mode is disabled and ADC start conversion is done by SW. In this case the ADC will convert one value then STOPs, then the DMA will not receive any request and remains waiting. That's why we need to restart the ADC by SW after each transfer until we reach the number of HPDMA transfers. The call to HAL_ADC_Start() will not be necessary if continuous conversion mode is enabled.

 

  //hadc1.Init.ContinuousConvMode = DISABLE; // --> ENABLE
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;

 

 Thanks

Hi,

For the following questions 3 and 4 below:

  1. Question 3: Continuing from my previous question, if I want to modify this example to support multiple channels, Continuous Conversion Mode, and DMA circular mode, how should I do it?
    I tried modifying the ADC parameters to Continuous Conversion Mode and DMA circular mode, but it still only runs once.
    Then I tried enabling Circular Mode in HPDMA, but it gets stuck at HAL_ADC_Start_DMA.
  2. Question 4: If possible, could you teach me how to modify it for multiple channels? I'm not sure whether to use End of single conversion or End of sequence of conversion. I have 9 channels.
    I'm also not sure how to configure it with DMA.

Answers:

- Please find my Step -by-Step demo in the attached document ADC_DMA_circular_usingSTM32CubeMx.pdf

- For the setting of STM32CubeIDE to avoid loading the boot binary each time you want to debug see attached document H7S_CubeIDE_config_Howto - Copy.pdf

- The whole project is attached ADC1_HPDMA_CircularMode.zip

Best Regards,

Younes