cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103 and ADC & DMA using latest Firmware Package 1.8.0

VYare
Associate II

Sup! I've tried to revive my old HAL-based project written a while ago for FW 1.6.1, fixing some minor bugs. Unfortunately, i removed old package long time ago, so i installed latest version 1.8.0. And my code isn't working anymore. After calling to 'HAL_ADC_Stop_DMA', the hdma->State has bit 'HAL_ADC_STATE_ERROR_DMA' set and all further conversions are screwed. After first conversion, HAL_ADC_ConvCpltCallback is never called again, only half transfer and error callbacks are called. The code sample:

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
	UNUSED(hadc);
	bConvInProgress = 0;
}
 
 
void joystickCalibrationMidPoint(p_joystick_calibration_data_t joy) {
...
    HAL_ADC_Start_DMA(&hadc1, (uint32_t*) dacBuffer, AdcNumChannels);
    while (bConvInProgress == 1) {
        HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);
    };
    HAL_ADC_Stop_DMA(&hadc1);
...
}

Since i didn't changed anything ADC/DMA related in my code yet, there is definitely something wrong with a new firmware package.

I've noticed HAL_ADC_Stop_DMA calls HAL_DMA_Abort internally, which expects the hdma->State to be HAL_DMA_STATE_BUSY for some reason, but the State is HAL_DMA_STATE_READY in my case.

Old stm32f1xx_hal_dma.c:

HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
{
  HAL_StatusTypeDef status = HAL_OK;
 
  /* Disable DMA IT */
  __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
    
  /* Disable the channel */
  __HAL_DMA_DISABLE(hdma);
    
  /* Clear all flags */
  hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex);
 
  /* Change the DMA state */
  hdma->State = HAL_DMA_STATE_READY;
 
  /* Process Unlocked */
  __HAL_UNLOCK(hdma);      
  
  return status; 
}

Latest version of stm32f1xx_hal_dma.c:

HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
{
  HAL_StatusTypeDef status = HAL_OK;
  
  if(hdma->State != HAL_DMA_STATE_BUSY)
  {
    /* no transfer ongoing */
    hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
 
    /* Process Unlocked */
    __HAL_UNLOCK(hdma);
 
    return HAL_ERROR;
  }
  else
 
  {
    /* Disable DMA IT */
    __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
      
    /* Disable the channel */
    __HAL_DMA_DISABLE(hdma);
      
    /* Clear all flags */
    hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex);
  }
  /* Change the DMA state */
  hdma->State = HAL_DMA_STATE_READY;
 
  /* Process Unlocked */
  __HAL_UNLOCK(hdma);      
  
  return status; 
}

So, i commented out this check, and now my code works fine. Is there an actual bug in the latest FW package or am I doing something wrong?

2 REPLIES 2
Gianluca Costa
Associate II

I found the same issue and I think that there is a bug in the last HAL version.

The issue is the line:

 if(hdma->State != HAL_DMA_STATE_BUSY)

In the HAL_DMA_Abort function. I suppose that the real "if" condition must be:

  if(hdma->State == HAL_DMA_STATE_BUSY)

with this change my code work fine.

This (My) solution is not correct!