New Light on ADC DMA Problems

Using ST Nucleo F401 with STM32Cube, I coded up a simple ‘blinky’ with ADC and DMA running round reading 4 analogue channels, squirreling away readings in a ram buffer in the background. All very good.

Porting to Mbed Studio, OS 6.11 bare metal - nothing works. Commenting out stuff to get at least ‘blinky’ working again, attention focussed on Cube generated function MX_DMA_Init, and I discovered commenting out the line:
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
not only restored ‘blinky’ but got the ADC DMA system working again as well! How can this be ?

While I’m happy at this apparent breakthrough, I would be happier by far to gain some understanding of the underlying reasons.

One problem remains of course - not enabling the interrupts means the
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc) {
and
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
functions don’t get called. These are needed.
I can see buffer contents change, just the interrupts to sort now, any help gratefully appreciated!

Files copied from Cube -
main.cpp
main.h
stm32f4xx_hal_msp.c
stm32f4xx_hal.h

Hello Jon,

Open the stm32F4xx_it.c file in your program (created by the STM32CubeIDE) and comment out the IRQ handlers starting
from void HardFault_Handler(void)
to void SysTick_Handler(void),
implemented also by the Mbed system software.

You can find an example of ADC DMA for the NUCLEO_F103RB target here.
The ADC DMA works along with the interrupts as expected. The main function calls the MX_DMA_Init(); implemented as follows:

/**
  * Enable DMA controller clock
  */
static void MX_DMA_Init()
{
    /* DMA controller clock enable */
    __HAL_RCC_DMA1_CLK_ENABLE();

    /* DMA interrupt init */
    /* DMA1_Channel1_IRQn interrupt configuration */
    HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}

The ADC DMA is started by the TIM1 callback ISR:

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef* htim)
{
    if (htim->Instance == TIM3) {
        if (ledIsOn && !adcDmaStarted) {
            pulseCount = 1;
            adcDataCount = 0;
            HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&adcData[adcDataCount++], 1);
            adcDmaStarted = true;
        }
    }
}

and

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (htim->Instance == TIM1) {
        if (adcDmaStarted && (adcDataCount < DATA_LEN)) {
            if (++pulseCount == 1) {
                HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&adcData[adcDataCount++], 1);
            }
            if (pulseCount == 4) {
                pulseCount = 0;
            }
        }
    }
}

The completion of the ADC DMA is indicated for the main fuction by setting a flag by the HAL_ADC_ConvCpltCallback ISR as follows:

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    adcDataAvailable = true;
}

To make programs work properly in some cases (it’s not clear for me when and why) the Mbed OS compiler requires to add a "platform.callback-nontrivial": true entry to the mbed_app.json file.
For example:

{
    "target_overrides": {
        "*": {
            "platform.callback-nontrivial": true
        }
    }
}

Many thanks Zoltan,
Commented out the functions you mentioned, compiled ok and now it runs. As far as I can see, I now have the code working in an identical way using STMCube generated code or Mbed Studio generated code.
This is excellent !!
I have several projects I can now revisit in which I hope to use this. Many times over the years I have cursed the run-time wasted using the AnalogIn API, and thought there must be a better way.
Also added the “platform.callback-nontrivial”: true line to mbed_app.json. Although it didn’t seem to be needed, I guess it won’t do any harm ! Thanks again
Regards
Jon