cancel
Showing results for 
Search instead for 
Did you mean: 

DMA DAC STM32F405RGT6 underrun

Godzilla
Visitor

We have STM32F405RGT6 and we want to implement DAC through DMA.
We used an example for STM32F429ZI-Nucleo
Here is an actual code where we have an underrun the error and we need help to clarify reason and find a solution, thanks!:

 

 

 

#include "main.h"
#include "usb_device.h"
#include "math.h"

#define SAWTOOTH_MAX 4095  // Максимальне значення DAC (12-біт)
#define DAC_BUFFER_SIZE 100
#define PI 3.1415926
uint16_t sawtooth_value = 0;  // Значення пилкоподібного сигналу
uint16_t dac_buffer[DAC_BUFFER_SIZE];
void Generate_SineWave() {
    for (int i = 0; i < DAC_BUFFER_SIZE; i++) {
        dac_buffer[i] = (uint16_t)(((sin(i * 2 * PI / DAC_BUFFER_SIZE) + 1) * (4096 / 2)));
    }
}

#define VDDA_APPLI                       ((uint32_t)3300)
                                              */
#define DIGITAL_SCALE_12BITS             (__LL_DAC_DIGITAL_SCALE(LL_DAC_RESOLUTION_12B))

#define WAVEFORM_AMPLITUDE          (VDDA_APPLI)
#define WAVEFORM_FREQUENCY          ((uint32_t)1000)
#define WAVEFORM_SAMPLES_SIZE       (sizeof (WaveformSine_12bits_32samples) / sizeof (uint16_t))                             
 #define WAVEFORM_TIMER_FREQUENCY                (WAVEFORM_FREQUENCY * WAVEFORM_SAMPLE_SIZE)
  #define WAVEFORM_TIMER_FREQUENCY_RANGE_MIN      ((uint32_t)    1)
  #define WAVEFORM_TIMER_PRESCALER_MAX_VALUE      ((uint32_t)0xFFFF-1)

#define __WAVEFORM_AMPLITUDE_SCALING(__DATA_12BITS__)                                     \
  (__DATA_12BITS__                                                                        \
   * __LL_DAC_CALC_VOLTAGE_TO_DATA(VDDA_APPLI, WAVEFORM_AMPLITUDE, LL_DAC_RESOLUTION_12B) \
   / __LL_DAC_DIGITAL_SCALE(LL_DAC_RESOLUTION_12B)                                        \
  )

const uint16_t WaveformSine_12bits_32samples[] =
{
__WAVEFORM_AMPLITUDE_SCALING(2048),
__WAVEFORM_AMPLITUDE_SCALING(2447),
__WAVEFORM_AMPLITUDE_SCALING(2831),
__WAVEFORM_AMPLITUDE_SCALING(3185),
__WAVEFORM_AMPLITUDE_SCALING(3495),
__WAVEFORM_AMPLITUDE_SCALING(3750),
__WAVEFORM_AMPLITUDE_SCALING(3939),
__WAVEFORM_AMPLITUDE_SCALING(4056),
__WAVEFORM_AMPLITUDE_SCALING(4095),
__WAVEFORM_AMPLITUDE_SCALING(4056),
__WAVEFORM_AMPLITUDE_SCALING(3939),
__WAVEFORM_AMPLITUDE_SCALING(3750),
__WAVEFORM_AMPLITUDE_SCALING(3495),
__WAVEFORM_AMPLITUDE_SCALING(3185),
__WAVEFORM_AMPLITUDE_SCALING(2831),
__WAVEFORM_AMPLITUDE_SCALING(2447),
__WAVEFORM_AMPLITUDE_SCALING(2048),
__WAVEFORM_AMPLITUDE_SCALING(1649),
__WAVEFORM_AMPLITUDE_SCALING(1265),
__WAVEFORM_AMPLITUDE_SCALING(911),
__WAVEFORM_AMPLITUDE_SCALING(601),
__WAVEFORM_AMPLITUDE_SCALING(346),
__WAVEFORM_AMPLITUDE_SCALING(157),
__WAVEFORM_AMPLITUDE_SCALING(40),
__WAVEFORM_AMPLITUDE_SCALING(0),
__WAVEFORM_AMPLITUDE_SCALING(40),
__WAVEFORM_AMPLITUDE_SCALING(157),
__WAVEFORM_AMPLITUDE_SCALING(346),
__WAVEFORM_AMPLITUDE_SCALING(601),
__WAVEFORM_AMPLITUDE_SCALING(911),
__WAVEFORM_AMPLITUDE_SCALING(1265),
__WAVEFORM_AMPLITUDE_SCALING(1649)
};

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_DAC_Init(void);
static void MX_TIM6_Init(void);
void     LED_Init(void);
void     Configure_DMA(void);
void     Configure_TIM_TimeBase_DAC_trigger(void);
void     Configure_DAC(void);
void     Activate_DAC(void);
void     LED_Blinking(uint32_t Period);
void	Debug_GPIO_Init(void);
void Debug_LED_Blink(uint32_t count, uint32_t period);
void Debug_Check_Timers(void);
void Debug_Check_DMA(void);
void Debug_Check_DAC(void);

int main(void)
{

  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
//  MX_DMA_Init();
//  MX_USB_DEVICE_Init();
//  MX_DAC_Init();
//  MX_TIM6_Init();
  Generate_SineWave();

    LED_Init();

    Configure_DMA();

    Configure_TIM_TimeBase_DAC_trigger();

    Configure_DAC();

    Activate_DAC();                      

  while (1)
  {
  }
}

void LED_Init(void)
{
  LED1_GPIO_CLK_ENABLE();

  LL_GPIO_SetPinMode(LED1_GPIO_PORT, LED1_PIN, LL_GPIO_MODE_OUTPUT);
  //LL_GPIO_SetPinOutputType(LED1_GPIO_PORT, LED1_PIN, LL_GPIO_OUTPUT_PUSHPULL);
  //LL_GPIO_SetPinSpeed(LED1_GPIO_PORT, LED1_PIN, LL_GPIO_SPEED_FREQ_LOW);
  //LL_GPIO_SetPinPull(LED1_GPIO_PORT, LED1_PIN, LL_GPIO_PULL_NO);
}


void Configure_DMA(void)
{
  NVIC_SetPriority(DMA1_Stream5_IRQn, 1); /* DMA IRQ lower priority than DAC IRQ */
  NVIC_EnableIRQ(DMA1_Stream5_IRQn);

  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);

  LL_DMA_SetChannelSelection(DMA1, LL_DMA_STREAM_5, LL_DMA_CHANNEL_7);
  LL_DMA_ConfigTransfer(DMA1, LL_DMA_MODE_CIRCULAR);

  LL_DMA_ConfigAddresses(DMA1,
                         LL_DMA_STREAM_5,
						 (uint32_t)&WaveformSine_12bits_32samples,
                         LL_DAC_DMA_GetRegAddr(DAC1, LL_DAC_CHANNEL_1, LL_DAC_DMA_REG_DATA_12BITS_RIGHT_ALIGNED),
                         LL_DMA_DIRECTION_MEMORY_TO_PERIPH);

  LL_DMA_SetDataLength(DMA1,
                       LL_DMA_STREAM_5,
					   WAVEFORM_SAMPLES_SIZE);

  LL_DMA_EnableIT_TE(DMA1,
                     LL_DMA_STREAM_5);

  LL_DMA_EnableStream(DMA1,
                       LL_DMA_STREAM_5);
}

void Configure_TIM_TimeBase_DAC_trigger(void)
{
  uint32_t timer_clock_frequency = 0;             /* Timer clock frequency */
  uint32_t timer_prescaler = 0;                   /* Time base prescaler to have timebase aligned on minimum frequency possible */
  uint32_t timer_reload = 0;                      /* Timer reload value in function of timer prescaler to achieve time base period */

  if (LL_RCC_GetAPB1Prescaler() == LL_RCC_APB1_DIV_1)
  {
    timer_clock_frequency = __LL_RCC_CALC_PCLK1_FREQ(SystemCoreClock, LL_RCC_GetAPB1Prescaler());
  }
  else
  {
    timer_clock_frequency = (__LL_RCC_CALC_PCLK1_FREQ(SystemCoreClock, LL_RCC_GetAPB1Prescaler()) * 2);
  }

  timer_prescaler = ((timer_clock_frequency / (WAVEFORM_TIMER_PRESCALER_MAX_VALUE * WAVEFORM_TIMER_FREQUENCY_RANGE_MIN)) +1);
  timer_reload = (timer_clock_frequency / (timer_prescaler * WAVEFORM_TIMER_FREQUENCY));

  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM6);

  LL_TIM_SetPrescaler(TIM6, (timer_prescaler - 1));

  LL_TIM_SetAutoReload(TIM6, (timer_reload - 1));//83

  LL_TIM_SetCounterMode(TIM6, LL_TIM_COUNTERMODE_UP);

  LL_TIM_SetTriggerOutput(TIM6, LL_TIM_TRGO_UPDATE);

  LL_TIM_EnableCounter(TIM6);
}

void Configure_DAC(void)
{
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);

  LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_4, LL_GPIO_MODE_ANALOG);

  NVIC_SetPriority(TIM6_DAC_IRQn, 0);
  NVIC_EnableIRQ(TIM6_DAC_IRQn);

  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_DAC1);

  // LL_DAC_SetMode(DAC1, LL_DAC_CHANNEL_1, LL_DAC_MODE_NORMAL_OPERATION);

  LL_DAC_SetTriggerSource(DAC1, LL_DAC_CHANNEL_1, LL_DAC_TRIG_EXT_TIM6_TRGO);

  //LL_DAC_SetOutputBuffer(DAC1, LL_DAC_CHANNEL_1, LL_DAC_OUTPUT_BUFFER_ENABLE);

  LL_DAC_EnableDMAReq(DAC1, LL_DAC_CHANNEL_1);

  LL_DAC_EnableIT_DMAUDR1(DAC1);
}

void Activate_DAC(void)
{
  __IO uint32_t wait_loop_index = 0;

  LL_DAC_Enable(DAC1, LL_DAC_CHANNEL_1);

  HAL_Delay(1000);

  wait_loop_index = ((LL_DAC_DELAY_STARTUP_VOLTAGE_SETTLING_US * (SystemCoreClock / (100000 * 2))) / 10);
  while(wait_loop_index != 0)
  {
    wait_loop_index--;
  }

  LL_DAC_EnableTrigger(DAC1, LL_DAC_CHANNEL_1);
}

void SystemClock_Config(void)
{
  LL_FLASH_SetLatency(LL_FLASH_LATENCY_5);
  while(LL_FLASH_GetLatency()!= LL_FLASH_LATENCY_5)
  {
  }
  LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
  LL_RCC_HSE_Enable();

  while(LL_RCC_HSE_IsReady() != 1)
  {

  }
  LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_4, 168, LL_RCC_PLLP_DIV_2);
  LL_RCC_PLL_ConfigDomain_48M(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_4, 168, LL_RCC_PLLQ_DIV_7);
  LL_RCC_PLL_Enable();

  while(LL_RCC_PLL_IsReady() != 1)
  {

  }
  while (LL_PWR_IsActiveFlag_VOS() == 0)
  {
  }
  LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
  LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_4);
  LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_2);
  LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);

  while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
  {

  }
  LL_SetSystemCoreClock(168000000);

  if (HAL_InitTick (TICK_INT_PRIORITY) != HAL_OK)
  {
    Error_Handler();
  }
}

static void MX_DAC_Init(void)
{

  LL_DAC_InitTypeDef DAC_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_DAC1);

  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);

  GPIO_InitStruct.Pin = LL_GPIO_PIN_4;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  LL_DMA_SetChannelSelection(DMA1, LL_DMA_STREAM_5, LL_DMA_CHANNEL_7);

  LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_STREAM_5, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);

  LL_DMA_SetStreamPriorityLevel(DMA1, LL_DMA_STREAM_5, LL_DMA_PRIORITY_VERYHIGH);

  LL_DMA_SetMode(DMA1, LL_DMA_STREAM_5, LL_DMA_MODE_CIRCULAR);

  LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_STREAM_5, LL_DMA_PERIPH_NOINCREMENT);

  LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_STREAM_5, LL_DMA_MEMORY_INCREMENT);

  LL_DMA_SetPeriphSize(DMA1, LL_DMA_STREAM_5, LL_DMA_PDATAALIGN_WORD);

  LL_DMA_SetMemorySize(DMA1, LL_DMA_STREAM_5, LL_DMA_MDATAALIGN_WORD);

  LL_DMA_EnableFifoMode(DMA1, LL_DMA_STREAM_5);

  LL_DMA_SetFIFOThreshold(DMA1, LL_DMA_STREAM_5, LL_DMA_FIFOTHRESHOLD_FULL);

  LL_DMA_SetMemoryBurstxfer(DMA1, LL_DMA_STREAM_5, LL_DMA_MBURST_SINGLE);

  LL_DMA_SetPeriphBurstxfer(DMA1, LL_DMA_STREAM_5, LL_DMA_PBURST_SINGLE);

  NVIC_SetPriority(TIM6_DAC_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(TIM6_DAC_IRQn);

  DAC_InitStruct.TriggerSource = LL_DAC_TRIG_EXT_TIM6_TRGO;
  DAC_InitStruct.WaveAutoGeneration = LL_DAC_WAVE_AUTO_GENERATION_NONE;
  DAC_InitStruct.OutputBuffer = LL_DAC_OUTPUT_BUFFER_ENABLE;
  LL_DAC_Init(DAC, LL_DAC_CHANNEL_1, &DAC_InitStruct);
}

static void MX_TIM6_Init(void)
{
  LL_TIM_InitTypeDef TIM_InitStruct = {0};

  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM6);

  NVIC_SetPriority(TIM6_DAC_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(TIM6_DAC_IRQn);

  TIM_InitStruct.Prescaler = 0;
  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  TIM_InitStruct.Autoreload = 1;
  LL_TIM_Init(TIM6, &TIM_InitStruct);
  LL_TIM_DisableARRPreload(TIM6);
  LL_TIM_SetTriggerOutput(TIM6, LL_TIM_TRGO_RESET);
  LL_TIM_DisableMasterSlaveMode(TIM6);
}

static void MX_DMA_Init(void)
{
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);

  NVIC_SetPriority(DMA1_Stream5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(DMA1_Stream5_IRQn);

}

static void MX_GPIO_Init(void)
{
  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOH);
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB);

  LL_GPIO_ResetOutputPin(LED_GPIO_Port, LED_Pin);

  GPIO_InitStruct.Pin = LED_Pin;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  LL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);
}

void DacDmaTransferError_Callback()
{
  LED_Blinking(LED_BLINK_ERROR);
}

void DacUnderrunError_Callback(void)
{
  LL_DAC_DisableIT_DMAUDR1(DAC1);

  LED_Blinking(LED_BLINK_ERROR);
}

void LED_Blinking(uint32_t Period)
{
  LL_GPIO_SetOutputPin(LED1_GPIO_PORT, LED1_PIN);

  while (1)
  {
    LL_GPIO_TogglePin(LED1_GPIO_PORT, LED1_PIN);
    LL_mDelay(Period);
  }
}


void Debug_LED_Blink(uint32_t count, uint32_t period)
{
    for (uint32_t i = 0; i < count; i++)
    {
        LL_GPIO_TogglePin(GPIOB, LL_GPIO_PIN_2);
        LL_mDelay(period);
    }
}

void Debug_Check_Timers(void)
{
    if (!LL_TIM_IsEnabledCounter(TIM6))
    {
        Debug_LED_Blink(3, 200);
    }
}

void Debug_Check_DMA(void)
{
    if (!LL_DMA_IsEnabledStream(DMA1, LL_DMA_STREAM_5))
    {
        Debug_LED_Blink(2, 500);
    }
}

void Debug_Check_DAC(void)
{
    if (!LL_DAC_IsEnabled(DAC1, LL_DAC_CHANNEL_1))
    {
        Debug_LED_Blink(5, 100);
    }
}

void Error_Handler(void)
{
  __disable_irq();
  while (1)
  {
  }
}

#ifdef  USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{

}
#endif /* USE_FULL_ASSERT */

 

 

 

 

stm32f4xx_it.c:

 

 

 

 

#include "main.h"
#include "stm32f4xx_it.h"

extern PCD_HandleTypeDef hpcd_USB_OTG_FS;

void NMI_Handler(void)
{
   while (1)
  {
  }
}

void HardFault_Handler(void)
{
  while (1)
  {

  }
}

void MemManage_Handler(void)
{
  while (1)
  {

  }
}

void BusFault_Handler(void)
{
  while (1)
  {

  }
}

void UsageFault_Handler(void)
{
  while (1)
  {

  }
}

void SVC_Handler(void)
{

}

void DebugMon_Handler(void)
{

}

void PendSV_Handler(void)
{

}

void SysTick_Handler(void)
{
  HAL_IncTick();
}

void DMA1_Stream5_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Stream5_IRQn 0 */
	/* Check whether DMA transfer error caused the DMA interruption */
		  if(LL_DMA_IsActiveFlag_TE7(DMA1) == 1)
		  {
		    /* Clear flag DMA transfer error */
		    LL_DMA_ClearFlag_TE7(DMA1);

		    /* Call interruption treatment function */
		    DacDmaTransferError_Callback();
		  }
  /* USER CODE END DMA1_Stream5_IRQn 0 */
}

void TIM6_DAC_IRQHandler(void)
{
//	if (LL_TIM_IsActiveFlag_UPDATE(TIM6)) {
//	    Debug_LED_Blink(100, 100);
//	    LL_TIM_ClearFlag_UPDATE(TIM6);
//	}

  /* USER CODE BEGIN TIM6_DAC_IRQn 0 */
	/* Check whether DAC channel1 underrun caused the DAC interruption */
	  if(LL_DAC_IsActiveFlag_DMAUDR1(DAC1) != 0)
	  {
		  if (LL_DMA_GetDataLength(DMA1, LL_DMA_STREAM_5) == 0)
		  {
		      Debug_LED_Blink(3, 200); // Blinks 3 times if DMA is not transferring data
		  }

		  if (!LL_TIM_IsEnabledCounter(TIM6)) {
		      Debug_LED_Blink(4, 300); 
		  }


		  if (LL_TIM_GetCounter(TIM6) == 0)
		  {
		      Debug_LED_Blink(4, 300); // Blinks 4 times if TIM6 is not counting
		  }

		  if (!LL_DAC_IsEnabled(DAC1, LL_DAC_CHANNEL_1))
		  {
		      Debug_LED_Blink(5, 100); // Blinks 5 times if DAC is not enabled
		  }

		  if (LL_DMA_GetDataLength(DMA1, LL_DMA_STREAM_5) == 0)
		  {
		      Debug_LED_Blink(3, 200); // DMA not transferring
		  }


		  Debug_Check_Timers();
		  Debug_Check_DMA();
		  Debug_Check_DAC();

	    /* Clear flag DAC channel1 underrun */
	    LL_DAC_ClearFlag_DMAUDR1(DAC1);

	    /* Call interruption treatment function */
	    DacUnderrunError_Callback();
	  }
  /* USER CODE END TIM6_DAC_IRQn 0 */
  /* USER CODE BEGIN TIM6_DAC_IRQn 1 */

  /* USER CODE END TIM6_DAC_IRQn 1 */
}

void OTG_FS_IRQHandler(void)
{
  HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);
}

 

 

 

 



1 REPLY 1
Godzilla
Visitor

Godzilla_0-1741805530500.png