Skip to main content
VNado.1
Associate III
December 21, 2020
Question

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

  • December 21, 2020
  • 3 replies
  • 1076 views

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);
 }
}

This topic has been closed for replies.

3 replies

VNado.1
VNado.1Author
Associate III
December 22, 2020

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?

waclawek.jan
Super User
December 22, 2020

> 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

VNado.1
VNado.1Author
Associate III
December 22, 2020

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.

waclawek.jan
Super User
December 23, 2020

I said, read out.

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

JW