ADC DMA values are refreshed only if other DMA peripheral are working
Hi everyone!
I've got something strange with my ADCs (working on STM32H743).
Everything was working until I realized that both of my ADC values are refreshed only if use other DMA peripheral. For example, it seems that sending SPI refresh the ADC, otherwise values stay the same.
You can have a look at my code :
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
GPIO_InitTypeDef GPIO_InitStruct = { 0 };
if(hadc->Instance == ADC2)
{
/* Initializes the peripherals clock */
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = { 0 };
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_CLKP;
if(HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) __DEBUG_BKPT();
/* Peripheral clock enable */
__HAL_RCC_ADC12_CLK_ENABLE();
__ADC12_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
hdma_adc2.Instance = DMA1_Stream3;
hdma_adc2.Init.Request = DMA_REQUEST_ADC2;
hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc2.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc2.Init.Mode = DMA_CIRCULAR;
hdma_adc2.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma_adc2.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_adc2.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_adc2.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_adc2.Init.PeriphBurst = DMA_PBURST_SINGLE;
if(HAL_DMA_Init(&hdma_adc2) != HAL_OK) __DEBUG_BKPT();
__HAL_LINKDMA(hadc, DMA_Handle, hdma_adc2);
HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
}
}__IO uint16_t VOLTAGE_DMA[2];
void adc::Init()
{
/* ADC 2 (PB0 + PB1) */
hadc2.Instance = ADC2;
hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc2.Init.Resolution = ADC_RESOLUTION_16B;
hadc2.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc2.Init.LowPowerAutoWait = DISABLE;
hadc2.Init.ContinuousConvMode = ENABLE;
hadc2.Init.NbrOfConversion = 2;
hadc2.Init.DiscontinuousConvMode = DISABLE;
//hadc2.Init.NbrOfDiscConversion = 1;
hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc2.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
hadc2.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc2.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
hadc2.Init.OversamplingMode = DISABLE;
if(HAL_ADC_Init(&hadc2) != HAL_OK) __DEBUG_BKPT();
/* ADC_CV_IN_1 */
ADC_ChannelConfTypeDef sConfig;
sConfig.Channel = ADC_CHANNEL_9;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_387CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
sConfig.OffsetSignedSaturation = DISABLE;
if(HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK) __DEBUG_BKPT();
/* ADC_CV_IN_2 */
sConfig.Channel = ADC_CHANNEL_5;
sConfig.Rank = ADC_REGULAR_RANK_2;
if(HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK) __DEBUG_BKPT();
if(HAL_ADC_Start_DMA(&hadc2, const_cast<uint32_t*>(reinterpret_cast<volatile uint32_t*>(VOLTAGE_DMA)), 2) != HAL_OK) __DEBUG_BKPT();
}void DMA1_Stream0_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_spi1_tx); // SPI1
}
void DMA1_Stream1_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_spi2_tx); // SPI2
}
void DMA1_Stream2_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_spi4_tx); // SPI4
}
void DMA1_Stream3_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_adc2); // ADC
}The values VOLTAGE_DMA[0] and VOLTAGE_DMA[1] should be always scanned and auto-refreshed, but they are updated only when I use an other DMA peripheral (SPI1, SP2, SP4).
As you can see, these other DMA peripheral also uses DMA1.
Do you have an idea of what can be wrong in my code?
Thanks a lot for your help!
Jean