cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with ADC DMA One Shot Mode

TBaue.1
Associate

Hi folks,

i'm using a STM32H750 MCU for analog data acquisition.

I've implemented a simple UART Command interface to trigger a measurement with a given number of samples. This Interface works fine (checked it with the debugger).

Now the Problem: only the first measurement after Reset seems to work. My structure to take a measurement of x samples is setup as follows:

  • UART RX Interrupt checkes incomming command and triggers the measurement
  • ADC_Start (only aimed, waiting for ext. interrupt via GPIO)
  • HAL_DMA_START
  • GPIO Gets triggered
  • ...idle... (sampling in progress, DMA shifts the data)
  • DMA-Transfer-Complete IT fires and calls "USR_sampling_done" function
  • ADC_Stop and transfer of samples via UART

When sending the next measure command, nothing happens. With the Debugger i've found out, that the HAL_DMA_Start function does not "reinit" the DMA. It returns from "__HAL_LOCK()" (Line 24) since the DMA Instance seems to still be locked. What is the Problem here? I thought that the DMA_IRQ_Handler takes care of clearing all the IT-Flags and "frees" the DMA Instance. I further checked the HAL functions for DMA and could not found any function that manually stops odr reinit the DMA.

Now some code for better understanding:

/**
  * @brief  Starts the DMA Transfer.
  * @param  hdma      : pointer to a DMA_HandleTypeDef structure that contains
  *                     the configuration information for the specified DMA Stream.
  * @param  SrcAddress: The source memory Buffer address
  * @param  DstAddress: The destination memory Buffer address
  * @param  DataLength: The length of data to be transferred from source to destination
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
{
  HAL_StatusTypeDef status = HAL_OK;
 
  /* Check the parameters */
  assert_param(IS_DMA_BUFFER_SIZE(DataLength));
 
  /* Check the DMA peripheral handle */
  if(hdma == NULL)
  {
    return HAL_ERROR;
  }
 
  /* Process locked */
  __HAL_LOCK(hdma);
 
  if(HAL_DMA_STATE_READY == hdma->State)
  {
    /* Change DMA peripheral state */
    hdma->State = HAL_DMA_STATE_BUSY;
 
    /* Initialize the error code */
    hdma->ErrorCode = HAL_DMA_ERROR_NONE;
 
    /* Disable the peripheral */
    __HAL_DMA_DISABLE(hdma);
 
    /* Configure the source, destination address and the data length */
    DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
 
    /* Enable the Peripheral */
    __HAL_DMA_ENABLE(hdma);
  }
  else
  {
    /* Process unlocked */
    __HAL_UNLOCK(hdma);
 
    /* Set the error code to busy */
    hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
 
    /* Return error status */
    status = HAL_ERROR;
  }
  return status;
}

void USR_sampling_done()
{
	uint16_t i = 0;
	uint16_t nos = usr_ctrl_inst.num_of_samples/2;
	uint32_t *pSample;
	uint16_t helper = 0;
	pSample = &samples[0];
 
 
	HAL_ADC_Stop(&hadc1);
	HAL_GPIO_WritePin(PLL_TRIG_PORT, PLL_TRIG_PIN, GPIO_PIN_RESET);
 
	while (i < nos)
	{
		helper = *pSample & 0xFFFF;
		USR_printf_val(helper);
		helper = *pSample >> 16;
		USR_printf_val(helper);
		pSample++;
		i++;
	}
 
}
/* Start single Measurement */
		  if(usr_ctrl_inst._f_ctrl & _F_MEAS_TRIG)
		  {
			  usr_ctrl_inst._f_ctrl &= ~(_F_MEAS_TRIG);
			  /* Aim the ADC and the DMA for Conversion of given number of samples */
			  HAL_DMA_Start(&hdma_adc1, (uint32_t)&(hadc1.Instance->DR), (uint32_t)&samples[0], usr_ctrl_inst.num_of_samples );
			  HAL_ADC_Start(&hadc1);
			  /* One Shot the ADC after short Delay (which not necessary) */
			  HAL_Delay(500);
			  HAL_GPIO_WritePin(PLL_TRIG_PORT, PLL_TRIG_PIN, GPIO_PIN_SET);
		  }
/**
  * @brief This function handles DMA1 stream0 global interrupt.
  */
void DMA1_Stream0_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Stream0_IRQn 0 */
 
  /* USER CODE END DMA1_Stream0_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_adc1);
  /* USER CODE BEGIN DMA1_Stream0_IRQn 1 */
  USR_sampling_done();
  /* USER CODE END DMA1_Stream0_IRQn 1 */
}

Thanks in advance, and let me know if something is missing 🙂

Regards!

Tony

0 REPLIES 0