STM32F4 ADC + DMA - mbed crashes

Hello,
I am new with mbed OS so perhaps I am doing something wrong.
Anyway, I use a Nucleo-F411RE board, and mbed OS 6.3. One of my first trials was to make the ADC work using the DMA; which eventually I managed to get to work by putting together pieces of code from left and right.

So, I wanted to configure the ADC to scan 4 channels, and perform for example 4x reads of each channel, which I can average and then use. I also wanted to use the DMA to store those 16x measured values in a buffer. To start the ADC, I call HAL_ADC_Start_DMA(…) which causes mbed OS to crash (error mentions something about invalid mutex access in ISR… which I am not directly using so I assume this is part of the mbed OS itself). However, if I add the HAL_ADC_Stop(…) inside the HAL_ADC_ConvCpltCallback callback method, then everything works fine. Also, the values inside the buffer are correct.

I use the code below:

static void MX_DMA_Init(void) {
    __HAL_RCC_DMA2_CLK_ENABLE();
    HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}
static void MX_ADC1_Init(void) {
    ADC_ChannelConfTypeDef sConfig = {0};
    hadc1.Instance = ADC1;
    hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
    hadc1.Init.Resolution = ADC_RESOLUTION_12B;
    hadc1.Init.ScanConvMode = ENABLE;
    hadc1.Init.ContinuousConvMode = ENABLE;
    hadc1.Init.DiscontinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConvEdge = ADC_ETERNALTRIGCONVEDGE_NONE;//ADC_EXTERNALTRIGCONVEDGE_RISING;
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;//ADC_EXTERNALTRIGCONV_T3_TRGO;
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc1.Init.NbrOfConversion = 4;
    hadc1.Init.NbrOfDiscConversion = 0;
    hadc1.Init.DMAContinuousRequests = ENABLE;
    hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
    if (HAL_ADC_Init(&hadc1) != HAL_OK) {
        printf("\n[FATAL] - HAL_ADC_Init failed\n");
    }
    sConfig.Channel = ADC_CHANNEL_10;
    sConfig.Rank = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
    sConfig.Offset = 0;
    if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
        printf("\n[FATAL] - HAL_ADC_ConfigChannel failed\n");
    }
    sConfig.Channel = ADC_CHANNEL_11;
    sConfig.Rank = 2;
    if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
        printf("\n[FATAL] - HAL_ADC_ConfigChannel failed\n");
    }
    sConfig.Channel = ADC_CHANNEL_12;
    sConfig.Rank = 3;
    if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
        printf("\n[FATAL] - HAL_ADC_ConfigChannel failed\n");
    }
    sConfig.Channel = ADC_CHANNEL_13;
    sConfig.Rank = 4;
    if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
      printf("\n[FATAL] - HAL_ADC_ConfigChannel failed\n");
    }
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if (hadc->Instance == ADC1) {
        __HAL_RCC_ADC1_CLK_ENABLE();
        __HAL_RCC_GPIOC_CLK_ENABLE();
        /**ADC1 GPIO Configuration
        PC0     ------> ADC1_IN10
        PC1     ------> ADC1_IN11
        PC2     ------> ADC1_IN12
        PC3     ------> ADC1_IN13
        */
       GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
        hdma_adc1.Instance = DMA2_Stream0;
        hdma_adc1.Init.Channel = DMA_CHANNEL_0;
        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;
        hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
        hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
        hdma_adc1.Init.MemBurst = DMA_MBURST_SINGLE;
        hdma_adc1.Init.PeriphBurst = DMA_PBURST_SINGLE;
          if (HAL_DMA_Init(&hdma_adc1) != HAL_OK) {
            while(1);
        }
        __HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);
    }
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) {
    if(hadc->Instance == ADC1) {
        __HAL_RCC_ADC1_CLK_DISABLE();
        /**ADC1 GPIO Configuration
        PC0     ------> ADC1_IN10
        PC1     ------> ADC1_IN11
        PC2     ------> ADC1_IN12
        PC3     ------> ADC1_IN13
        */
        HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
        HAL_DMA_DeInit(hadc->DMA_Handle);
    }
}
extern "C" void DMA2_Stream0_IRQHandler(void) {
  HAL_DMA_IRQHandler(&hdma_adc1);
}
#define ADCINPUTS           4
#define ADCSAMPLES          4
#define SAMPLEBUFFERSIZE    (ADCINPUTS * ADCSAMPLES)
__IO uint16_t _buffer[SAMPLEBUFFERSIZE];
uint16_t _adcinputs[ADCINPUTS];

extern "C" void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {
    HAL_ADC_Stop_DMA(&hadc1);   // <--- must be present or mbed crashes ?
    for (int i = 0; i < ADCINPUTS; i++) {
        uint32_t value;
        value =  _buffer[ADCINPUTS * 0 + i];
        value += _buffer[ADCINPUTS * 1 + i];
        value += _buffer[ADCINPUTS * 2 + i];
        value += _buffer[ADCINPUTS * 3 + i];
        value >>= 2;   // make sure ADCINPUTS is pow of 2; 4 in this case
        _adcinputs[i] = (uint16_t)value;
    }
}

Now, I have 2x questions;

  1. Why is it that the mbed OS seems to crash if I do not call the HAL_ADC_Stop_DMA(…) inside the HAL_ADC_ConvCpltCallback callback ? Is that because the callback is triggered way too often … ?

  2. If I wanted to configure a TIM to trigger the same ADC conversions let’s say every 100ms. Is it possible to have the buffer filled with 4x samples of the 4x channels and then call the HAL_ADC_DMA_Stop(…) in the HAL_ADC_ConvCpltCallback callback and repeat that every 100ms? How is the setup aware of the buffer and how many bytes to read … ?

Hope my questions/setup/code are clear.
BR,
S