cancel
Showing results for 
Search instead for 
Did you mean: 

Trying to integrate the waveplayer from stm32137 example in L4+ MCU. However, the loop updating the DMA buffer only enters DMATxComplete on 3 occasions?

VNado.1
Associate III

Here's the essence of what I have at the moment. I wonder why it does not enter DMATxComplete, I have tried with 128 and 30 buffer sizes...

//****** dac.c **********//
 
DAC_HandleTypeDef hdac1;
DMA_HandleTypeDef hdma_dac_ch1;
DMA_HandleTypeDef hdma_dac_ch2;
 
/* DAC1 init function */
void MX_DAC1_Init(void)
{
  DAC_ChannelConfTypeDef sConfig;
 
    /**DAC Initialization
    */
  hdac1.Instance = DAC1;
  if (HAL_DAC_Init(&hdac1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
    /**DAC channel OUT1 config
    */
  sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;
  sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
  sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
  sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE;
  sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY;
  sConfig.DAC_HighFrequency = DAC_HIGH_FREQUENCY_INTERFACE_MODE_ABOVE_80MHZ;
 
  if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
    /**DAC channel OUT2 config
    */
  sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;
  sConfig.DAC_Trigger = DAC_TRIGGER_T7_TRGO; //T7
  sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
  sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE;
  sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY;
  sConfig.DAC_HighFrequency = DAC_HIGH_FREQUENCY_INTERFACE_MODE_ABOVE_80MHZ;
 
  if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
}
 
void HAL_DAC_MspInit(DAC_HandleTypeDef* dacHandle)
{
 
  GPIO_InitTypeDef GPIO_InitStruct;
  if(dacHandle->Instance==DAC1)
  {
  /* USER CODE BEGIN DAC1_MspInit 0 */
 
  /* USER CODE END DAC1_MspInit 0 */
    /* DAC1 clock enable */
    __HAL_RCC_DAC1_CLK_ENABLE();
 
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**DAC1 GPIO Configuration
    PA4     ------> DAC1_OUT1
    PA5     ------> DAC1_OUT2
    */
    GPIO_InitStruct.Pin = DAC_OUT1_Pin | DAC_OUT2_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
    /* DAC1 DMA Init */
    /* DAC_CH2 Init */
    hdma_dac_ch2.Instance = DMA2_Channel5;
    hdma_dac_ch2.Init.Request = DMA_REQUEST_DAC1_CH2; //DMA_REQUEST_3;
    hdma_dac_ch2.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_dac_ch2.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_dac_ch2.Init.MemInc = DMA_MINC_ENABLE;
    hdma_dac_ch2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_dac_ch2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_dac_ch2.Init.Mode = DMA_CIRCULAR;
    hdma_dac_ch2.Init.Priority = DMA_PRIORITY_HIGH;
    if (HAL_DMA_Init(&hdma_dac_ch2) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
 
    __HAL_LINKDMA(dacHandle,DMA_Handle2,hdma_dac_ch2);
 
    /* DAC_CH1 Init */
    hdma_dac_ch1.Instance = DMA1_Channel3;
    hdma_dac_ch1.Init.Request = DMA_REQUEST_DAC1_CH1; //DMA_REQUEST_6;
    hdma_dac_ch1.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_dac_ch1.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_dac_ch1.Init.MemInc = DMA_MINC_ENABLE;
    hdma_dac_ch1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_dac_ch1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_dac_ch1.Init.Mode = DMA_NORMAL;
    hdma_dac_ch1.Init.Priority = DMA_PRIORITY_HIGH;
    if (HAL_DMA_Init(&hdma_dac_ch1) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
 
    __HAL_LINKDMA(dacHandle,DMA_Handle1,hdma_dac_ch1);
 
  /* USER CODE BEGIN DAC1_MspInit 1 */
 
    /* Enable Transfer Complete on channel 3 */
    //DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);
 
  /* USER CODE END DAC1_MspInit 1 */
  }
}
 
void Audio_MAL_Play(uint32_t * signal, uint32_t size)
{
      if(HAL_DAC_Stop_DMA(&hdac1, DAC_CHANNEL_1) != HAL_OK)
      {
          Error_Handler();
      }
 
 
      if(HAL_TIM_Base_Stop(&htim6) != HAL_OK)
      {
          Error_Handler();
      }
 
      /* Disable DMA1 Channel3 */
      //HAL_DMA_Abort(DMA1_Channel3);
 
 
  /* Enable DMA1 Channel3 */
  //HAL_DMA_Start(DMA1_Channel3);
 
  if (HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, signal, size, DAC_ALIGN_12B_R) != HAL_OK) // 12B_L or 12B_R?
  {
	  /* Start DMA Error */
      Error_Handler();
  }
 
  // Set the timer period to the default
  htim6.Instance->ARR = ARR_FILE; // replace with htim7?
 
  if(HAL_TIM_Base_Start(&htim6) != HAL_OK) // replace with htim7
  {
	  Error_Handler();
  }
}
 
 
 
void start_DAC_us(uint32_t * signal, uint32_t size)
{
 
 
	if (HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, signal, size, DAC_ALIGN_12B_R) != HAL_OK) // 12B_L or 12B_R?
	  {
		  /* Start DMA Error */
	      Error_Handler();
	  }
 
	// Only playback Sine Wave on DAC Channel 2, DAC Channel 1 will playback AudioTrack
    if (HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_2, signal, size, DAC_ALIGN_12B_R) != HAL_OK) // input a second signal for DAC channel 2
    {
        /* Start DMA Error */
        Error_Handler();
    }
 
    // Set the timer period to the default
    htim7.Instance->ARR = ARR_SIN; //Channel2 - Sine Wave
 
    if(HAL_TIM_Base_Start(&htim7) != HAL_OK) // replace with htim7
    {
        Error_Handler();
    }
 
    // Set the timer period to the default
      htim6.Instance->ARR = ARR_FILE; //Channel1 - Audio File
 
      if(HAL_TIM_Base_Start(&htim6) != HAL_OK)
      {
    	  Error_Handler();
      }
}
 
//****** In function.c **********//
 
start_DAC_us( (uint32_t *)Sine12bit, SIZE_LUT); 
 
 
 
				
Audio_MAL_Play((uint32_t*)Sine12bit, SIZE_LUT);
 
 
 
	BufferSelection = 2;
 
				do
				{
 
 
					if(BufferRead != 0)
					{
						/* Play sine test */
//						Audio_MAL_Play( (uint32_t *)Sine12bit, SIZE_LUT);
//						BufferRead = 0;
 
					    if(BufferSelection == 2)
					    {
					      /* Play buffer 2 */
					      Audio_MAL_Play((uint32_t*)Sine12bit, SIZE_LUT);   
 
					      BufferRead = 0;
					    }
					    else if (BufferSelection == 1)
					    {
					    	/* Play buffer 1 */
					    	Audio_MAL_Play((uint32_t*)Sine12bit, SIZE_LUT);
 
					      BufferRead = 0;
					    }
 
 
					 }
 
 
				}while((FlagBits & FLAG_TOGGLE_US));
 
-----------------------------------------------------------------------------------
 
void WavePlayer_DMATxComplete_IRQHandler(void)
{
   if(__HAL_DMA_GET_FLAG(&hdma_dac_ch1,DMA_FLAG_TC3))
  {
    if(BufferSelection == 2)
    {
      BufferSelection = 1;
      BufferRead = 1;
    }
    else
    {
      BufferSelection = 2;
      BufferRead = 1;
    }
    __HAL_DMA_CLEAR_FLAG(&hdma_dac_ch1,DMA_FLAG_TC3);
  }
}

4 REPLIES 4
VNado.1
Associate III

When I set DMA for DAC_Ch1 as a circular buffer it enters WavePlayer_DMATxComplete_IRQHandler constantly. However, when I set the DMA as a "normal" buffer, it only enters it at the beginning. It is supposed to do reset BufferRead = 1, since it does not enter the function it gets stuck without any output at the DAC.

I have added the following code to init the DMA NVIC for interrupts, without further success:

void WavePlayer_Init(void)
{
  /********************************* DMA Config *******************************/
  /* DMA1 clock enable (to be used with DAC) */
  RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN; //Enable DMA1 Clock //RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  /* DMA channel3 Configuration is managed by Audio_MAL_Play() function */
 
  HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
 
  /* Enable Transfer Complete on channel 3 */
  __HAL_DMA_ENABLE_IT(&hdma_dac_ch1,DMA_IT_TC);
}

How can I debug this? How can I know where the DMA Tx complete fails?

> When I set DMA for DAC_Ch1 as a circular buffer it enters WavePlayer_DMATxComplete_IRQHandler constantly.

> However, when I set the DMA as a "normal" buffer, it only enters it at the beginning.

Quite likely, DAC underruns. Read out and check the DMA and DAC registers content, focus on status bits in both.

JW

Where can I find the DMA and DAC registers content? I have looked in HAL_DMA_Start_IT() and I am not sure I know where to focus.

I said, read out.

The easiest way is to use the register view in debugger.

JW