STM32Cube Linked List generation issue
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-10-30 9: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.
- Labels:
-
STM32U5 series
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-10-31 3: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.
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-10-31 3: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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-10-31 5:58 AM - edited ‎2023-10-31 7:20 AM
Hello @fsorin,
Can you please provide your IOC file.
Thanks.
Mahmoud
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-10-31 7: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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-11-02 9: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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-11-06 6: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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-11-06 8: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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-11-06 9: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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎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...
