2023-10-30 09:51 AM
Hi all,
I'm using STM32Cube IDE (version 1.13.1, build 17479_20230728_0839 ) to manage my company project based on a STM32U5 MCU.
More specifically, I'm using linked list feature (for playing audio with SAI + DMA transfer) and I have noticed what appears to me as a bug in auto-generated code.
Basically, I have created through CubeMx one list named SAIQueue, with one node named NodeTx and the auto-generated initialization code is the following:
/**
* @brief DMA Linked-list SAIQueue configuration
* @PAram None
* @retval None
*/
HAL_StatusTypeDef MX_SAIQueue_Config(void)
{
HAL_StatusTypeDef ret = HAL_OK;
/* DMA node configuration declaration */
DMA_NodeConfTypeDef pNodeConfig;
/* Set node configuration ################################################*/
pNodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
pNodeConfig.Init.Request = GPDMA1_REQUEST_SAI1_B;
pNodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
pNodeConfig.Init.Direction = DMA_MEMORY_TO_PERIPH;
pNodeConfig.Init.SrcInc = DMA_SINC_INCREMENTED;
pNodeConfig.Init.DestInc = DMA_DINC_FIXED;
pNodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_HALFWORD;
pNodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_HALFWORD;
pNodeConfig.Init.SrcBurstLength = 1;
pNodeConfig.Init.DestBurstLength = 1;
pNodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
pNodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
pNodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
pNodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
pNodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
pNodeConfig.SrcAddress = 0;
pNodeConfig.DstAddress = 0;
pNodeConfig.DataSize = 0;
/* Build NodeTx Node */
ret |= HAL_DMAEx_List_BuildNode(&pNodeConfig, &NodeTx);
/* Insert NodeTx to Queue */
ret |= HAL_DMAEx_List_InsertNode_Tail(&SAIQueue, &NodeTx);
ret |= HAL_DMAEx_List_SetCircularMode(&SAIQueue);
return ret;
}
If I run this code without modification, I encounter an assert failure in HAL_DMAEx_List_BuildNode (line 1069 of file stm32u5xx_hal_dma_ex.c):
assert_param(IS_DMA_MODE(pNodeConfig->Init.Mode));
This is fixed by adding the following missing line in "pNodeConfig" structure initialization:
pNodeConfig.Init.Mode = DMA_NORMAL;
Obviously, if I do any modification on the ioc file and relaunch code generation, this line is deleted and the issue is back.
Am I missing something on the UI to generate this line properly? Should this be fixed?
Thanks in advance for any insights.
2023-10-31 03:07 AM
Hello @fsorin,
First let me thank you for posting and welcome to ST Community.
I would like to know where you added this line of code:
pNodeConfig.Init.Mode = DMA_NORMAL
Thanks.
Mahmoud.
2023-10-31 03:20 AM
Hello @Mahmoud Ben Romdhane,
Thank you for your quick reply.
I have added this line after all the "pNodeConfig.Init.x" in the auto-generated code, meaning between line 24 and 25 on the code I posted, which basically become the following one:
/**
* @brief DMA Linked-list SAIQueue configuration
* @param None
* @retval None
*/
HAL_StatusTypeDef MX_SAIQueue_Config(void)
{
HAL_StatusTypeDef ret = HAL_OK;
/* DMA node configuration declaration */
DMA_NodeConfTypeDef pNodeConfig;
/* Set node configuration ################################################*/
pNodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
pNodeConfig.Init.Request = GPDMA1_REQUEST_SAI1_B;
pNodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
pNodeConfig.Init.Direction = DMA_MEMORY_TO_PERIPH;
pNodeConfig.Init.SrcInc = DMA_SINC_INCREMENTED;
pNodeConfig.Init.DestInc = DMA_DINC_FIXED;
pNodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_HALFWORD;
pNodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_HALFWORD;
pNodeConfig.Init.SrcBurstLength = 1;
pNodeConfig.Init.DestBurstLength = 1;
pNodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
pNodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
pNodeConfig.Init.Mode = DMA_NORMAL;
pNodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
pNodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
pNodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
pNodeConfig.SrcAddress = 0;
pNodeConfig.DstAddress = 0;
pNodeConfig.DataSize = 0;
/* Build NodeTx Node */
ret |= HAL_DMAEx_List_BuildNode(&pNodeConfig, &NodeTx);
/* Insert NodeTx to Queue */
ret |= HAL_DMAEx_List_InsertNode_Tail(&SAIQueue, &NodeTx);
ret |= HAL_DMAEx_List_SetCircularMode(&SAIQueue);
return ret;
}
Best regards
2023-10-31 05:58 AM - edited 2023-10-31 07:20 AM
2023-10-31 07:39 AM
Hello @Mahmoud Ben Romdhane,
Here is the ioc file. Please note that I only renamed it and changed project name for confidentiality purpose. I also renamed it as .txt because uploading was refused otherwise for some reason.
Best regards
2023-11-02 09:26 AM
Regardless of this specific project, I was looking for the explanation of why the structure field "Mode" (pNodeConfig.Init.Mode here) was left uninitialized by the auto-generated code.
If there is something to be modified in MX configuration I would be glad to know what, but it appears to me that it's just missing. I am guessing that the assumption is made that its value will be zero, which is the value of "DMA_NORMAL", the only accepted value by "assert_param(IS_DMA_MODE(pNodeConfig->Init.Mode))", but it can in fact takes any random number, as it is uninitialized.
Could not this line be integrated on a next release, as initializing every parameter to a known value is considered as best practice?
Thank you for considering this.
Best regards
2023-11-06 06:54 AM
same problem on H563/nucleo-H563zi cube generated code never gets dma working. not in standard or in list-mode.
using list-mode on GPDMA1 and insert line
pNodeConfig.Init.Mode = DMA_NORMAL;
it starts working in a magical way. Quite an outstanding achievement.
2023-11-06 08:55 AM
Hello @AScha.3,
I'm glad that I helped you solve your issue.
This is still a workaround though, and will be lost after the next auto-generation. Let's hope for a real fix from ST team on this one!
2023-11-06 09:57 AM - edited 2023-11-06 10:03 AM
you made my day ! :)
and no, not lost always: because the cube generated code didnt work in any way, i tried to copy from git example
and make it my way, in a function. so in cube its just set to list mode, GPDMA1 ch 7 .
then in main: (is really "main_task" in Azure rtos -- just for fun (to test it) )
define:
DMA_NodeTypeDef NodeTx;
DMA_QListTypeDef SAIQueue;
/* USER CODE END PV */
/* Associate the DMA handle */
__HAL_LINKDMA(&hsai_BlockA2, hdmatx, handle_GPDMA1_Channel7);
MX_SAIQueue_Config();
HAL_DMAEx_List_SetCircularMode(&SAIQueue);
/* Link SAI queue to DMA channel */
HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel7, &SAIQueue);
// start dma
fresult = HAL_SAI_Transmit_DMA(&hsai_BlockA2,(uint8_t *)playbuf, sizeof(playbuf))/4);
and the config..:
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
HAL_StatusTypeDef MX_SAIQueue_Config(void)
{
HAL_StatusTypeDef ret = HAL_OK;
/* DMA node configuration declaration */
DMA_NodeConfTypeDef pNodeConfig;
/* Set node configuration ################################################*/
pNodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
pNodeConfig.Init.Request = GPDMA1_REQUEST_SAI2_A;
pNodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
pNodeConfig.Init.Direction = DMA_MEMORY_TO_PERIPH;
pNodeConfig.Init.SrcInc = DMA_SINC_INCREMENTED;
pNodeConfig.Init.DestInc = DMA_DINC_FIXED;
pNodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
pNodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
pNodeConfig.Init.SrcBurstLength = 1;
pNodeConfig.Init.DestBurstLength = 1;
pNodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
pNodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
pNodeConfig.Init.Mode = DMA_NORMAL; // new ??!!!
pNodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
pNodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
pNodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
pNodeConfig.SrcAddress = 0;
pNodeConfig.DstAddress = 0;
pNodeConfig.DataSize = 0;
/* Build NodeTx Node */
ret |= HAL_DMAEx_List_BuildNode(&pNodeConfig, &NodeTx);
/* Insert NodeTx to Queue */
ret |= HAL_DMAEx_List_InsertNode_Tail(&SAIQueue, &NodeTx);
return ret;
}
and nothing removed!
2023-11-07 12:43 AM
Ok so basically you don't generate the linked list code from Cube anymore, but manually implement it in user code section. I guess I will end up doing the same thing but it would be great if the auto-generated code managed that properly...