2020-04-21 01:19 AM
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:
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