Issues getting DMA to autotrigger (and related issues with ADC/DMA)
Hello!
I'm working with an STM32WB55 development board and I'm trying to take data fairly quickly (every 25 us) so I'm trying to work with the DMA to collect data. Right now, I'm not even collecting actual ADC data, just toggling a GPIO point to get timing figured out.
Anyway, found some good examples at DeepBlueEmbedded and have been poking at a few of them trying to get it to do what I want. The problem I'm coming across is I can't seem to get the DMA to autotrigger so i keep having to manually call the
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
// Conversion Complete & DMA Transfer Complete As Well
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_12);
// Starting DMA takes about 30 us
HAL_ADC_Start_DMA(&hadc1, &AD_RES, 1);
}The problem is the HAL_ADC_START_DMA command takes somewhere between 15-30 us to run and, by the time this is finished, the code calls it again and I have no cpu time to run the main part of my program outside of the ADC. If I remove the line though, it triggers once and then never starts up again (which makes sense if it's not auto triggering). figure I likely have this setup incorrectly but I can't seem to see the source of the issue.
Below is my ADC and DMA setup. I must be missing something really obvious:
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.NbrOfDiscConversion = 1;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_6;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */
}static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMAMUX1_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 6, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}Now, all this said, I do have a timer setup to run every 25 us, and I think it makes sense to use that long term, but I thought getting it auto triggering makes the most sense.
I am using the *.ioc file to generate code so, if it's easier to take screenshots of the GUI, let me know and I can do that.
I think I'm pretty close but I just can't seem to get there. Was reading through all the settings in the stm32wbxx_hal_adc.h file and the stm32wbxx_hal_dma.h files (which give pretty good descriptions). I must be missing something.
Anyway, if anyone can point me to where I'm going wrong or what I'm missing, it would be greatly appreciated. Thanks a lot!