2025-05-30 1:24 AM
I like to use the CubeMx 6.14.1 generated code (up2date firmware packages) to use DAC 1+2 with GPDMA in circular mode (Standard-Request-Mode)
The 1st thing that makes me wonder: Although I selected "Standard Request Mode" in CubeMX a configuration for Linked-ListMode is generated. Nevertheless this seems to work with ADC.
On DAC Channels 1+2 I get a Data-Transfer-Error although I can't figure out a CubeMX missconfiguration for now.
See my attached .ioc File for Reference.
Expectation: CubeMx generated Standard Request code when selecting this in the GUI.
Expectation: DAC generates HAL_DAC_CH1_COMPLETE instead of HAL_DAC_CH1_ERROR with DTE bit set.
DMA-Start-Code:
HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, (uint32_t*)output_buffer[0], SAMPLE_BLOCK_SIZE * 2, DAC_ALIGN_12B_R);
HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_2, (uint32_t*)output_buffer[1], SAMPLE_BLOCK_SIZE * 2, DAC_ALIGN_12B_R);
with output_buffer being a global:
int16_t output_buffer[3][2*SAMPLE_BLOCK_SIZE];
Maybe one may give me a hint what I've been done wrong.
FYI: Same application code runs on a STM32G4 cubemx, so I suppose it's due to a CubeMX missconfiguration or a CubeMX errata.
Thanks in advance. Best Regards
Pascal Speck
Solved! Go to Solution.
2025-06-03 6:58 AM
I now found the solution in:
https://community.st.com/t5/stm32-mcus-products/stm32u599-dac-doesn-t-work-in-dma-mode/m-p/685089
Unfortunately my first search didn't bring this article up.
AGAIN for all with similar problems: Destination data width mus be "WORD" ( not "HalfWord" as on other derivates )
2025-05-30 9:34 AM
Hello @stst9180,
What's the Linked-ListMode configuration that is generated?
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-06-01 11:14 PM - edited 2025-06-02 3:37 AM
Here U R:
/* DAC1 init function */
void MX_DAC1_Init(void)
{
/* USER CODE BEGIN DAC1_Init 0 */
/* USER CODE END DAC1_Init 0 */
DAC_ChannelConfTypeDef sConfig = {0};
DAC_AutonomousModeConfTypeDef sAutonomousMode = {0};
/* USER CODE BEGIN DAC1_Init 1 */
/* USER CODE END DAC1_Init 1 */
/** DAC Initialization
*/
hdac1.Instance = DAC1;
if (HAL_DAC_Init(&hdac1) != HAL_OK)
{
Error_Handler();
}
/** DAC channel OUT1 config
*/
sConfig.DAC_HighFrequency = DAC_HIGH_FREQUENCY_INTERFACE_MODE_DISABLE;
sConfig.DAC_DMADoubleDataMode = DISABLE;
sConfig.DAC_SignedFormat = DISABLE;
sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;
sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE;
sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_EXTERNAL;
sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY;
if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/** Configure Autonomous Mode
*/
sAutonomousMode.AutonomousModeState = DAC_AUTONOMOUS_MODE_DISABLE;
if (HAL_DACEx_SetConfigAutonomousMode(&hdac1, &sAutonomousMode) != HAL_OK)
{
Error_Handler();
}
/** DAC channel OUT2 config
*/
if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN DAC1_Init 2 */
/* USER CODE END DAC1_Init 2 */
}
void HAL_DAC_MspInit(DAC_HandleTypeDef* dacHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
DMA_NodeConfTypeDef NodeConfig= {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
if(dacHandle->Instance==DAC1)
{
/* USER CODE BEGIN DAC1_MspInit 0 */
/* USER CODE END DAC1_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADCDAC|RCC_PERIPHCLK_DAC1;
PeriphClkInit.AdcDacClockSelection = RCC_ADCDACCLKSOURCE_HSI;
PeriphClkInit.Dac1ClockSelection = RCC_DAC1CLKSOURCE_LSI;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
/* 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 = GPIO_PIN_4|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* DAC1 DMA Init */
/* GPDMA1_REQUEST_DAC1_CH2 Init */
NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
NodeConfig.Init.Request = GPDMA1_REQUEST_DAC1_CH2;
NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
NodeConfig.Init.Direction = DMA_MEMORY_TO_PERIPH;
NodeConfig.Init.SrcInc = DMA_SINC_INCREMENTED;
NodeConfig.Init.DestInc = DMA_DINC_FIXED;
NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_HALFWORD;
NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_HALFWORD;
NodeConfig.Init.SrcBurstLength = 1;
NodeConfig.Init.DestBurstLength = 1;
NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT1|DMA_DEST_ALLOCATED_PORT0;
NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
NodeConfig.Init.Mode = DMA_NORMAL;
NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
if (HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel4) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel4, NULL, &Node_GPDMA1_Channel4) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel4) != HAL_OK)
{
Error_Handler();
}
handle_GPDMA1_Channel4.Instance = GPDMA1_Channel4;
handle_GPDMA1_Channel4.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
handle_GPDMA1_Channel4.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
handle_GPDMA1_Channel4.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT1;
handle_GPDMA1_Channel4.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_GPDMA1_Channel4.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel4) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel4, &List_GPDMA1_Channel4) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(dacHandle, DMA_Handle2, handle_GPDMA1_Channel4);
if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel4, DMA_CHANNEL_NPRIV) != HAL_OK)
{
Error_Handler();
}
/* GPDMA1_REQUEST_DAC1_CH1 Init */
NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
NodeConfig.Init.Request = GPDMA1_REQUEST_DAC1_CH1;
NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
NodeConfig.Init.Direction = DMA_MEMORY_TO_PERIPH;
NodeConfig.Init.SrcInc = DMA_SINC_INCREMENTED;
NodeConfig.Init.DestInc = DMA_DINC_FIXED;
NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_HALFWORD;
NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_HALFWORD;
NodeConfig.Init.SrcBurstLength = 1;
NodeConfig.Init.DestBurstLength = 1;
NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT1|DMA_DEST_ALLOCATED_PORT0;
NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
NodeConfig.Init.Mode = DMA_NORMAL;
NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
if (HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel3) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel3, NULL, &Node_GPDMA1_Channel3) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel3) != HAL_OK)
{
Error_Handler();
}
handle_GPDMA1_Channel3.Instance = GPDMA1_Channel3;
handle_GPDMA1_Channel3.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
handle_GPDMA1_Channel3.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
handle_GPDMA1_Channel3.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT1;
handle_GPDMA1_Channel3.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_GPDMA1_Channel3.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel3) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel3, &List_GPDMA1_Channel3) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(dacHandle, DMA_Handle1, handle_GPDMA1_Channel3);
if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel3, DMA_CHANNEL_NPRIV) != HAL_OK)
{
Error_Handler();
}
/* DAC1 interrupt Init */
HAL_NVIC_SetPriority(DAC1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DAC1_IRQn);
/* USER CODE BEGIN DAC1_MspInit 1 */
/* USER CODE END DAC1_MspInit 1 */
}
}
I don't know if it helps guessing what's happening:
When I debug the Core while bein in the Transfer-Error-Interrupt, the C3SAR is in the range but at position 10 ( 5 half-word-transfers). So it seems that there were some bytes transferred. C3DAR is also correct with 0x46021808.
I just tried in different directions: Enabling / Disabling caches, Trying different burst-sizes, but the error just arises.
2025-06-03 6:58 AM
I now found the solution in:
https://community.st.com/t5/stm32-mcus-products/stm32u599-dac-doesn-t-work-in-dma-mode/m-p/685089
Unfortunately my first search didn't bring this article up.
AGAIN for all with similar problems: Destination data width mus be "WORD" ( not "HalfWord" as on other derivates )