cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_DAC_Start_DMA stops on start calling HAL_DAC_ErrorCallbackCh1

RPere.4
Associate II
if (HAL_DAC_Start(&hdac4, DAC_CHANNEL_1))
  {
  /* DAC conversion start error */
  Error_Handler();
  }
 
 if (HAL_OPAMP_Start(&hopamp4) != HAL_OK)
  {
  /* OPAMP  start error */
   Error_Handler();
  }
 
  HAL_TIM_Base_Start(&htim7);
//   while(1)
//  	 HAL_DAC_SetValue(&hdac4, DAC_CHANNEL_1, DAC_ALIGN_12B_R, Dacbuffers[0][0]);
  if (HAL_DAC_Start_DMA(&hdac4, DAC_CHANNEL_1,(uint32_t *) Dacbuffers[0], DAC_BUFFER_SIZE, DAC_ALIGN_12B_R) != HAL_OK)
  {
  /* DAC conversion start error */
  Error_Handler();
  }

Project is Cubemx generated. Everything works fine without DMA and i get result on DAC output. Trying to start DMA immediately stops with calling HAL_DAC_ErrorCallbackCh1. What can be the reason for this?

Cubemx generated code

DAC_HandleTypeDef hdac4;
DMA_HandleTypeDef hdma_dac4_ch1;
 
/* DAC4 init function */
void MX_DAC4_Init(void)
{
  DAC_ChannelConfTypeDef sConfig = {0};
 
  /** DAC Initialization 
  */
  hdac4.Instance = DAC4;
  if (HAL_DAC_Init(&hdac4) != HAL_OK)
  {
    Error_Handler();
  }
  /** DAC channel OUT1 config 
  */
  sConfig.DAC_HighFrequency = DAC_HIGH_FREQUENCY_INTERFACE_MODE_AUTOMATIC;
  sConfig.DAC_DMADoubleDataMode = DISABLE;
  sConfig.DAC_SignedFormat = DISABLE;
  sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;
  sConfig.DAC_Trigger = DAC_TRIGGER_T7_TRGO;
  sConfig.DAC_Trigger2 = DAC_TRIGGER_NONE;
  sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE;
  sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_ENABLE;
  sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY;
  if (HAL_DAC_ConfigChannel(&hdac4, &sConfig, DAC_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
 
}
 
void HAL_DAC_MspInit(DAC_HandleTypeDef* dacHandle)
{
 
  if(dacHandle->Instance==DAC4)
  {
  /* USER CODE BEGIN DAC4_MspInit 0 */
 
  /* USER CODE END DAC4_MspInit 0 */
    /* DAC4 clock enable */
    __HAL_RCC_DAC4_CLK_ENABLE();
  
    /* DAC4 DMA Init */
    /* DAC4_CH1 Init */
    hdma_dac4_ch1.Instance = DMA2_Channel1;
    hdma_dac4_ch1.Init.Request = DMA_REQUEST_DAC4_CHANNEL1;
    hdma_dac4_ch1.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_dac4_ch1.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_dac4_ch1.Init.MemInc = DMA_MINC_ENABLE;
    hdma_dac4_ch1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_dac4_ch1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_dac4_ch1.Init.Mode = DMA_CIRCULAR;
    hdma_dac4_ch1.Init.Priority = DMA_PRIORITY_VERY_HIGH;
    if (HAL_DMA_Init(&hdma_dac4_ch1) != HAL_OK)
    {
      Error_Handler();
    }
 
    __HAL_LINKDMA(dacHandle,DMA_Handle1,hdma_dac4_ch1);
 
  /* USER CODE BEGIN DAC4_MspInit 1 */
 
  /* USER CODE END DAC4_MspInit 1 */
  }
}

1 ACCEPTED SOLUTION

Accepted Solutions

Yes I've found the answer. You need to select destination size as 32 bit despite your source is 16 bit. DMA will do unpacking for you so

hdma_dac4_ch1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; // must be replaced with DMA_PDATAALIGN_WORD

hdma_dac4_ch1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;

Not sure if your case is the same though....

View solution in original post

7 REPLIES 7
Sirac
Associate III

Hi,

do you initialise DMA before ?

This is not righ => (uint32_t *) Dacbuffers[0]

Remplace by simply (uint32_t *) Dacbuffers, or at least (uint32_t *) &Dacbuffers[0]

Sorry to confuse you

Dacbuffers[2][DAC_BUFFER_SIZE] Supposed to be double buffer

What do you mean by initialization. Typically cubemex do this for you (second snippet)

Sirac
Associate III

OK for Dacbuffers[2][DAC_BUFFER_SIZE]

Yes normally CubeMx generate for you a function call MX_DMA_Init() witch enable Irq and clk, but as I can't see this on your code I ask.

Do you configure the pin as analog.

You can try to you place breakpoint on DAC Irq and follow until HAL_DAC_ErrorCallbackCh1 to see what's going wrong.

Sure it is generated

void MX_DMA_Init(void) 
{
 
  /* DMA controller clock enable */
  __HAL_RCC_DMAMUX1_CLK_ENABLE();
  __HAL_RCC_DMA2_CLK_ENABLE();
  __HAL_RCC_DMA1_CLK_ENABLE();
 
  /* DMA interrupt init */
  /* DMA1_Channel1_IRQn interrupt configuration */
  NVIC_SetPriority(DMA1_Channel1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0));
  NVIC_EnableIRQ(DMA1_Channel1_IRQn);
  /* DMA1_Channel2_IRQn interrupt configuration */
  NVIC_SetPriority(DMA1_Channel2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0));
  NVIC_EnableIRQ(DMA1_Channel2_IRQn);
  /* DMA1_Channel3_IRQn interrupt configuration */
  NVIC_SetPriority(DMA1_Channel3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0));
  NVIC_EnableIRQ(DMA1_Channel3_IRQn);
  /* DMA1_Channel4_IRQn interrupt configuration */
  NVIC_SetPriority(DMA1_Channel4_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0));
  NVIC_EnableIRQ(DMA1_Channel4_IRQn);
  /* DMA2_Channel1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Channel1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA2_Channel1_IRQn);
 
}

Pin is configured correctly. It is high speed DAC and output is through built-in op-amp as follower. See CUBEMX file attached.

And everything is working including DAC output without dma.

I'm curious if you found and answer. I have pretty much the same problem. I notice the DMAUDRx bit gets set immediately after I turn on the timer associated with the DAC channel. Which means the data is triggered too fast. For my application it is way under 1Msps.

Yes I've found the answer. You need to select destination size as 32 bit despite your source is 16 bit. DMA will do unpacking for you so

hdma_dac4_ch1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; // must be replaced with DMA_PDATAALIGN_WORD

hdma_dac4_ch1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;

Not sure if your case is the same though....

Yes that was the issue. Thanks! ​