2016-07-22 07:40 AM
I'm having a problem where I can't seem to use the DMA to read ADC values without a perpetual overrun error.
I'm trying to configure the part such that a - conversion sequence is started by software. - DMA stores the sequence results in ram - Everything stops and waits for the next software trigger.What I see is - The first conversion sequence is started by software - The first conversion sequence completes successfully - Every subsequent attempt to start a sequence results in immediate overruns.I'm using a STM32L476G-DISCOVERY board. I've setup the adc conversions on some pins that were used to read input from a joystick.I used CubeMX (v4.15.1) to generate this init code using the v1.5.1 HAL firmware package:void MX_ADC1_Init(void){ ADC_MultiModeTypeDef multimode; ADC_ChannelConfTypeDef sConfig; /**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_ENABLE; hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV; hadc1.Init.LowPowerAutoWait = DISABLE; hadc1.Init.ContinuousConvMode = ENABLE; hadc1.Init.NbrOfConversion = 5; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.DMAContinuousRequests = DISABLE; hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED; hadc1.Init.OversamplingMode = DISABLE; if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } /**Configure the ADC multi-mode */ multimode.Mode = ADC_MODE_INDEPENDENT; if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK) { Error_Handler(); } /**Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_5; sConfig.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(); } /**Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_6; sConfig.Rank = 2; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } /**Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_7; sConfig.Rank = 3; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } /**Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_8; sConfig.Rank = 4; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } /**Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_10; sConfig.Rank = 5; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); }}void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle){ GPIO_InitTypeDef GPIO_InitStruct; if(adcHandle->Instance==ADC1) { /* USER CODE BEGIN ADC1_MspInit 0 */ /* USER CODE END ADC1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_ADC_CLK_ENABLE(); /**ADC1 GPIO Configuration PA0 ------> ADC1_IN5 PA1 ------> ADC1_IN6 PA2 ------> ADC1_IN7 PA3 ------> ADC1_IN8 PA5 ------> ADC1_IN10 */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 |GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* Peripheral DMA init*/ hdma_adc1.Instance = DMA1_Channel1; hdma_adc1.Init.Request = DMA_REQUEST_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_NORMAL; hdma_adc1.Init.Priority = DMA_PRIORITY_VERY_HIGH; if (HAL_DMA_Init(&hdma_adc1) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1); /* Peripheral interrupt init */ HAL_NVIC_SetPriority(ADC1_2_IRQn, 5, 0); HAL_NVIC_EnableIRQ(ADC1_2_IRQn); /* USER CODE BEGIN ADC1_MspInit 1 */ /* USER CODE END ADC1_MspInit 1 */ }}The calling code to start ADCs. You can see I've tried a few of the HAL calls to start things off. The MultiModeStart_DMA call was in the generated code so I assume this one is more correct?HAL_ADC_Start_DMA(m_bAdc, (uint32_t*)m_pRxBuffer, m_nRxSize);//HAL_ADCEx_MultiModeStart_DMA(m_bAdc, (uint32_t*)m_pRxBuffer, m_nRxSize);//HAL_ADC_Start_IT(m_bAdc);ISR callbacks. extern ''C'' void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){ static int togCnt2 = 0; if (togCnt2 % 2) HAL_GPIO_WritePin(LD_G_GPIO_Port, LD_G_Pin, GPIO_PIN_SET); else HAL_GPIO_WritePin(LD_G_GPIO_Port, LD_G_Pin, GPIO_PIN_RESET); togCnt2++; AdcTask* pTask = (AdcTask*)hadc->pReceiverObject; pTask->processFrame(hadc->Instance->DR);}extern ''C'' void HAL_ADC_ErrorCallback(ADC_HandleTypeDef* hadc){ //TODO: Reset the ADC to get things going again? __asm(''NOP'');}Thanks in advance for any help on the issue.Seth