1 /**
2   **********************************************************************************************************************
3   * @file    stm32wbaxx_hal_dma_ex.c
4   * @author  MCD Application Team
5   * @brief   DMA Extension HAL module driver
6   *          This file provides firmware functions to manage the following functionalities of the DMA extension
7   *          peripheral:
8   *           + Linked-List Initialization and De-Initialization Functions
9   *           + Linked-List I/O Operation Functions
10   *           + Linked-List Management Functions
11   *           + Data Handling, Repeated Block and Trigger Configuration Functions
12   *           + Suspend and Resume Operation Functions
13   *           + FIFO Status Function
14   *
15   **********************************************************************************************************************
16   * @attention
17   *
18   * Copyright (c) 2022 STMicroelectronics.
19   * All rights reserved.
20   *
21   * This software is licensed under terms that can be found in the LICENSE file
22   * in the root directory of this software component.
23   * If no LICENSE file comes with this software, it is provided AS-IS.
24   *
25   **********************************************************************************************************************
26   @verbatim
27   ======================================================================================================================
28                                  ##### How to use this driver #####
29   ======================================================================================================================
30     [..]
31       Alternatively to the normal programming mode, a DMA channel can be programmed by a list of transfers, known as
32       linked-list (list of Node items). Each node is defined by its data structure.
33       Each node specifies a standalone DMA channel.
34       When enabled, the DMA channel fetch the first linked-list node from SRAM (known as head node). When executed, the
35       next linked list node will be fetched and executed. This operation is repeated until the end of the whole
36       linked-list queue. Optionally, the linked-list can be linear where the last linked-list queue node is not linked
37       to another queue node or circular where the last linked-list node is linked to any linked-list queue node.
38 
39           (+) Linear linked-list:
40               The DMA channel fetch and execute all DMA linked-list queue from first node (head node) to last node
41               (tail node) ones. When the last node is completed, the DMA channel remains in idle state and another
42               transfer can be lunched.
43 
44           (+) Circular linked-list:
45               The DMA channel fetch and execute all DMA linked-list queue from first node (head node) to last node (tail
46               node). When last node is executed, the DMA channel fetches the first circular node another time and repeat
47               the same sequence in an infinite loop (Circular transfer). To stop the DMA channel, an abort operation is
48               required. This linked-list mode replaces the legacy circular transfers.
49 
50     [..]
51       In order to reduce linked-list queue executing time and power consumption, the DMA channel supports executing the
52       dynamic linked-list format. In fact, the DMA supports the execution of 2 types of linked-list formats : static and
53       dynamic.
54 
55           (+) Static linked-list:
56               The static linked-list format refers to the full linked-list node where all DMA channel parameters are
57               fetched and executed independently of the redundancy of information.
58 
59           (+) Dynamic linked-list:
60               The dynamic linked-list format refer to the customized linked-list node where only DMA channel necessary
61               parameters are fetched and executed (Example: data size = 20 on previous node, and data size = 20 on the
62               current node => No need to update it).
63 
64       For linked-list transfers, the DMA channel can execute the linked-list queue node by node. This feature is named
65       link step mode. When activated, enabling the DMA channel first time allows to fetch the head node from memory
66       then it stops. Then, another DMA channel enable is needed to execute the node. After that, keeping enabling the
67       DMA channel is needed to execute each node until the end of linked-list queue. When the linked-list queue is
68       circular, enabling the DMA channel in an infinite loop is required to keep the DMA channel running. This feature
69       is useful for debug purpose or asynchronously executing queue nodes.
70 
71     [..]
72       Each DMA channel transfer (normal or linked-list), is highly configurable according to DMA channel instance
73       integrated in devices. These configuration can be :
74 
75           (+) Repeated block configuration :
76               If the feature is supported, the DMA channel can performs a repeated block transfers. Named also 2
77               dimension addressing transfers, this feature can transfer n iteration of programmed block transfer (Block
78               transfer is the legacy data size). Additional to the repeat count of a block, DMA channel addresses can
79               jump after at burst and block level. The jump length is a programmable parameter defined by DMA user.
80                (++) Jump at burst level :
81                     The DMA channel keep an empty area, between each 2 consecutive bursts transmitted.
82                (++) Jump at block level :
83                     The DMA channel keep an empty area, between each 2 consecutive blocks transmitted.
84 
85           (+) Trigger :
86               The DMA channel transfers can be conditioned by hardware signals edges (rising or falling) named hardware
87               triggers. Trigger condition can be applied at :
88                (++) Single/Burst level :
89                     Each single/burst data transmission is conditioned by a signal trigger hit.
90                (++) Block level :
91                     Each block data transmission is conditioned by a signal trigger hit.
92                (++) Node level :
93                     Each node execution is conditioned by a signal trigger hit.
94               The DMA channel can report a trigger overrun when detects more than 2 trigger signal edges before
95               executing the current transfer.
96 
97           (+) Data handling :
98               The data handling feature is a FIFO capability that can be :
99                 (++) Padding pattern :
100                      Padding selected pattern (zero padding or sign extension) when the source data width is smaller
101                      than the destination data width at single level.
102                 (++) Truncation :
103                      Truncate section from the source data single when the source data width is bigger than the
104                      destination data width.
105                 (++) Pack/Unpack :
106                      Pack a set of data when source data width is smaller than the destination data width.
107                      Unpack a set of data when source data width is bigger than the destination data width.
108                 (++) Exchange :
109                      Exchange data at byte and half-word on the destination and at byte level on the source.
110 
111     [..]
112       Each DMA channel transfer (normal or linked-list) when it is active, can be suspended and resumed at run time
113       application. When trying to suspend an ongoing transfer, the DMA channel isn't suspended instantly but complete
114       the current ongoing single/burst then it stops.
115       When the DMA channel is suspended, the current transfer can be resumed instantly.
116 
117     [..]
118       The DMA channel that supports FIFO, can report in real time the number of beats remains on destination (Output)
119       FIFO level.
120 
121     *** Linked-List Initialization and De-Initialization operation ***
122     ==================================================================
123     [..]
124       Differently from normal transfers, DMA channel initialization and de-initialization need less parameters as the
125       remaining transfer parameters are defined by linked-list nodes.
126 
127           (+) Use HAL_DMAEx_List_Init() to initialize a DMA channel in linked-list mode according to programmed fields.
128               When called, the DMA channel will be ready to execute linked-list queues.
129 
130           (+) Use HAL_DMAEx_List_DeInit() to de-initialize a DMA channel in linked-list mode.
131               When called, the DMA channel will be in reset. It is mandatory to reinitialize it for next transfer.
132 
133     *** Linked-List I/O Operation ***
134     =================================
135     [..]
136           (+) Use HAL_DMAEx_List_Start() to start a DMA transfer in linked-list mode after the configuration of
137               linked-list queue base address and offset in polling mode (Blocking mode).
138 
139           (+) Use HAL_DMAEx_List_Start_IT() to start a DMA transfer in linked-list mode after the configuration of
140               linked-list queue base address and offset in interrupt mode (Non-blocking mode).
141 
142     *** Linked-List Management ***
143     ==============================
144     [..]
145       The linked-list management is a software processing independently of DMA channel hardware. It allows to reset,
146       build, create, insert, remove, replace, circularize, convert both nodes and queue in order to perform DMA
147       channel transfers in linked-list mode.
148       Linked-list APIs and types are adapted to reduce memory footprint.
149 
150     *** Linked-list nodes building ***
151     [..]
152       At node level, the operations that can be done are building a new linked-list node or get a linked-list node
153       information from a built node. The linked-list nodes have two forms according to 2 dimensions addressing
154       capability. The linear addressing nodes contains the information of all DMA channel features except the 2
155       dimension addressing features and the 2 dimensions addressing nodes contain the information of all available
156       features.
157 
158           (+) Use HAL_DMAEx_List_BuildNode() to build the DMA linked-list node according to the specified parameters.
159               Build operation allow to convert the specified parameter in values known by the DMA channel and place them
160               in memory.
161               Placing DMA linked-list in SRAM must be done in accordance to product specification to ensure that the
162               link access port can access to the specified SRAM.
163               (++) The DMA linked-list node parameter address should be 32bit aligned and should not exceed the 64 KByte
164               addressable space.
165 
166           (+) Use HAL_DMAEx_List_GetNodeConfig() to get the specified configuration parameter on building node.
167               This API can be used when need to change few parameter to build new node.
168 
169     *** Inserting nodes to linked-list queue ***
170     [..]
171       In order to build a sequence of DMA transaction with different configuration, we need to insert built node at
172       linked-list queue (node present an elementary DMA transaction) in linked-list queue on any position to have the
173       full flexibility of ordering nodes or extend the sequence of queue transactions.
174 
175           (+) Use HAL_DMAEx_List_InsertNode() to insert new built node in any queue position of linked-list queue
176               according to selecting previous node. When calling this API with previous node parameter is NULL, the
177               inserted node will be placed at the head of the linked-list queue.
178               (++) This API must be used after HAL_DMAEx_List_BuildNode() otherwise an error will be returned.
179               (++) This API must be called for static queues format.
180               (++) This API shall be avoided when adding new node at the head or the tail of queue (overhead of
181                    footprint and performance : use HAL_DMAEx_List_InsertNode_Head() or HAL_DMAEx_List_InsertNode_Tail()
182                    instead).
183 
184           (+) Use HAL_DMAEx_List_InsertNode_Head() to insert new built node at the head of linked-list queue. The head
185               node will not be overwritten but will be the second queue node.
186               (++) This API must be used after HAL_DMAEx_List_BuildNode() otherwise an error will be returned.
187               (++) This API must be called for static queues format.
188 
189           (+) Use HAL_DMAEx_List_InsertNode_Tail() to insert new built node at the tail of linked-list queue. The tail
190               node will not be overwritten but will be the penultimate queue node.
191               (++) This API must be used after HAL_DMAEx_List_BuildNode() otherwise an error will be returned.
192               (++) This API must be called for static queues format.
193 
194     *** Removing nodes from linked-list queue ***
195     [..]
196       There is some cases when removing a node from linked-list queue is needed (need to remove an elementary DMA
197       transaction). Removing node allows to unlink a node from DMA linked-list queue (NOT DELETED), so the removed node
198       can be reused for another queue or to be added to the same queue without need to rebuild it in next step.
199 
200           (+) Use HAL_DMAEx_List_RemoveNode() to remove any yet built and inserted node from linked-list queue according
201               to selected node.
202               (++) This API must be called for static queues format.
203               (++) This API shall be avoided when removing the head or the tail of linked-list queue (overhead of
204                    footprint and performance : use HAL_DMAEx_List_RemoveNode_Head() or HAL_DMAEx_List_RemoveNode_Tail()
205                    instead).
206 
207           (+) Use HAL_DMAEx_List_RemoveNode_Head() to remove the head node from linked-list queue.
208               (++) This API must be called for static queues format.
209 
210           (+) Use HAL_DMAEx_List_RemoveNode_Tail() to remove the tail node from linked-list queue.
211               (++) This API must be called for static queues format.
212 
213     *** Replacing nodes on linked-list queue ***
214     [..]
215       There is some cases when replacing a node from linked-list queue is needed (need to replace an elementary DMA
216       transfer, by another one that have not the same configuration). Replacing node allows to unlink the node to be
217       replaced from DMA linked-list queue (NOT DELETED) and link instead a new node. So the replaced node can be reused
218       for another queue or to be added to the same queue without need to rebuild it in next step and the new node cannot
219       be reused except when remove it or replaced in next step.
220 
221           (+) Use HAL_DMAEx_List_ReplaceNode() to replace any yet built and inserted node on linked-list queue according
222               to selected node.
223               (++) This API must be called for static queues format.
224               (++) This API shall be avoided when replacing the head or the tail linked-list queue (overhead of
225                    footprint and performance : use HAL_DMAEx_List_ReplaceNode_Head() or
226                    HAL_DMAEx_List_ReplaceNode_Tail() instead).
227 
228           (+) Use HAL_DMAEx_List_ReplaceNode_Head() to replace the head node of linked-list queue.
229               (++) This API must be called for static queues format.
230 
231           (+) Use HAL_DMAEx_List_ReplaceNode_Tail() to replace the tail node from linked-list queue.
232               (++) This API must be called for static queues format.
233 
234     *** Reset linked-list queue ***
235     [..]
236       After finishing using a linked-list queue, it can be reset and cleared and it's content nodes will be
237       unlinked (NOT DELETED) and reused on another queue.
238 
239           (+) Use HAL_DMAEx_List_ResetQ() to reset a linked-list queue and unlink all it's content nodes.
240               (++) This API must be called for ready state queues.
241               (++) This API must be called for static queues format.
242 
243     *** Inserting linked-list queue ***
244     [..]
245       To ensure the flexibility of building linked-list queue by their targeted functionalities (Example: 3 nodes for
246       action 1 and 5 nodes for action 2), it is possible to build a queue for action 1 that contains action 1 nodes and
247       a queue for action 2 that contains action 2 nodes then concatenating the 2 queues. So, there are some cases where
248       the management of linked-list at queue granularity is needed.
249 
250           (+) Use HAL_DMAEx_List_InsertQ() to insert source linked-list queue to a destination linked-list queue
251               according to selecting previous node.
252               (++) This API must be called for static queues format.
253               (++) This API shall be avoided when inserting source linked-list queue at the head or the tail of
254                    destination queue (overhead of footprint and performance : use HAL_DMAEx_List_InsertQ_Head() or
255                    HAL_DMAEx_List_InsertQ_Tail() instead).
256 
257           (+) Use HAL_DMAEx_List_InsertQ_Head() to insert a source linked-list queue at the head of linked-list
258               destination queue.
259               (++) This API must be called for static queues format.
260 
261           (+) Use HAL_DMAEx_List_InsertQ_Tail() to insert a source linked-list queue at the tail of linked-list
262               destination queue.
263               (++) This API must be called for static queues format.
264 
265     *** Circularizing linked-list queue ***
266     [..]
267       In order to perform tasks in infinite loop with DMA channel, it is possible to circularize the linked-list queues.
268       Circularizing queue allows to link last linked-list queue node to any previous node of the same queue (This node
269       is named first circular queue). When the first circular node is the head node, all linked-list queue nodes will be
270       executed in infinite loop. When the first circular node is not the head nodes, all precedent nodes are executed
271       once and all remaining nodes are executed in an infinite loop.
272 
273           (+) Use HAL_DMAEx_List_SetCircularModeConfig() to circularize the linked-list queue according to first
274               circular node selected.
275               (++) This API must be called for static queues format.
276               (++) This API shall be avoided when first circular node is the head linked-list queue node (overhead of
277                    footprint and performance : use HAL_DMAEx_List_SetCircularMode() instead).
278 
279           (+) Use HAL_DMAEx_List_SetCircularMode() to circularize the linked-list queue with linking last queue node
280               with first queue node.
281               (++) This API must be called for static queues format.
282 
283           (+) Use HAL_DMAEx_List_ClearCircularMode() to clear any linked-list queue circular configuration.
284               (++) This API must be called for static queues format.
285 
286 
287     *** Converting linked-list queue ***
288     [..]
289       To have the best DMA channel linked-list queue execution, it is recommended to convert yet build linked-list queue
290       to dynamic format (Static is the default format). When linked-list queue becomes dynamic, all queue nodes are
291       optimized and only changed parameters will be updated between nodes. So, the DMA will fetch only changes
292       parameters instead of the whole node.
293 
294           (+) Use HAL_DMAEx_List_ConvertQToDynamic() to convert a linked-list queue to dynamic format.
295               (++) This API must be called for ready state queues.
296               (++) This API must be called for static queues format.
297               (++) This API must be called as the last API before starting the DMA channel in linked-list mode.
298 
299           (+) Use HAL_DMAEx_List_ConvertQToStatic() to convert a linked-list queue to static format.
300               (++) This API must be called for ready state queues.
301               (++) This API must be called for dynamic queues format.
302               (++) This API must be called as the first API after the full execution of linked-list queue when the
303                    execution mode is linear (not circular) if it is dynamic and a linked-list queue management is
304                    needed.
305               (++) This API must be called as the first API after the aborting the execution of the current linked-list
306                    queue when the execution mode is linear (not circular) if it is dynamic and a linked-list queue
307                    management is needed.
308 
309     [..]
310       When converting a circular queue to dynamic format and when the first circular node is the last queue node, it is
311       recommended to duplicate the last circular node in order to ensure the full optimization when calling
312       HAL_DMAEx_List_ConvertQToDynamic() API. In this case, updated information are only addresses which allow to reduce
313       4 words of update for linear nodes per node execution and 6 words update for 2 dimensions addressing nodes per
314       node execution.
315 
316 
317     *** Linking linked-list queue to DMA channel ***
318     [..]
319       In order to have the possibility of the creation of an infinity queues (limited by available memory size), the
320       building of linked-list queue is fully independent from DMA channels. It is possible to build all needed queues if
321       their size is less then available memory at startup time, then linking each time when needed a linked-list queue
322       to an idle DMA channel.
323 
324           (+) Use HAL_DMAEx_List_LinkQ() to link a ready linked-list queue to ready DMA channel.
325               (++) This API supports the two format of linked-list (Static and dynamic).
326               (++) This API must be called for ready state queues and DMA channels.
327 
328           (+) Use HAL_DMAEx_List_ConvertQToStatic() to unlink a ready linked-list queue to ready DMA channel.
329               (++) This API supports the two format of linked-list (Static and dynamic).
330               (++) This API must be called for ready state queues and DMA channels.
331 
332     *** User sequence ***
333     [..]
334       To use cleanly the DMA linked-list library, ensure to apply the following call sequences :
335 
336           (+) Linear transfer :
337               Linked-list queue building
338               (++) HAL_DMAEx_List_BuildNode()
339               (++) HAL_DMAEx_List_InsertNode_Tail()
340                               .
341                               .
342                               .
343               (++) HAL_DMAEx_List_BuildNode()
344               (++) HAL_DMAEx_List_InsertNode_Tail()
345               (++) HAL_DMAEx_List_ConvertQToDynamic()
346               Linked-list queue execution
347               (++) HAL_DMAEx_List_Init()
348               (++) HAL_DMAEx_List_LinkQ()
349               (++) HAL_DMAEx_List_Start() / HAL_DMAEx_List_Start_IT()
350               (++) HAL_DMAEx_List_UnLinkQ()
351               (++) HAL_DMAEx_List_DeInit()
352 
353           (+) Circular transfer :
354               Linked-list queue building
355               (++) HAL_DMAEx_List_BuildNode()
356               (++) HAL_DMAEx_List_InsertNode_Tail()
357                               .
358                               .
359                               .
360               (++) HAL_DMAEx_List_BuildNode()
361               (++) HAL_DMAEx_List_InsertNode_Tail()
362               (++) HAL_DMAEx_List_SetCircularModeConfig() / HAL_DMAEx_List_SetCircularMode()
363               (++) HAL_DMAEx_List_ConvertQToDynamic()
364               Linked-list queue execution
365               (++) HAL_DMAEx_List_Init()
366               (++) HAL_DMAEx_List_LinkQ()
367               (++) HAL_DMAEx_List_Start() / HAL_DMAEx_List_Start_IT()
368               (++) HAL_DMA_Abort() / HAL_DMA_Abort_IT()
369               (++) HAL_DMAEx_List_UnLinkQ()
370               (++) HAL_DMAEx_List_DeInit()
371 
372 
373     *** Data Handling ***
374     =====================
375     [..]
376       In order to avoid some CPU data processing in several cases, the DMA channel provides some features related to
377       FIFO capabilities titled data handling.
378                 (++) Padding pattern
379                      Padding selected pattern (zero padding or sign extension) when the source data width is smaller
380                      than the destination data width at single level.
381                      Zero padding       (Source : 0xABAB ------> Destination : 0xABAB0000)
382                      Sign bit extension (Source : 0x0ABA ------> Destination : 0x00000ABA)
383                                         (Source : 0xFABA ------> Destination : 0xFFFFFABA)
384                 (++) Truncation :
385                      Truncate section from the source data single when the source data width is bigger than the
386                      destination data width.
387                      Left truncation  (Source : 0xABABCDCD ------> Destination : 0xCDCD)
388                      Right truncation (Source : 0xABABCDCD ------> Destination : 0xABAB)
389                 (++) Pack/Unpack :
390                      Pack a set of data when source data width is smaller than the destination data width.
391                      Unpack a set of data when source data width is bigger than the destination data width.
392                      Pack   (Source : 0xAB, 0xCD ------> Destination : 0xABCD)
393                      UnPack (Source : 0xABCD     ------> Destination : 0xAB, 0xCD)
394                 (++) Exchange :
395                      Exchange data at byte and half-word on the destination and at byte level on the source.
396                      Considering source and destination are both word type. Exchange operation can be as follows.
397                      In examples below, one exchange setting is enabled at a time.
398                      Source byte exchange only (Source : 0xAB12CD34 ------> Destination : 0xABCD1234)
399                      Destination byte exchange only (Source : 0xAB12CD34 ------> Destination : 0x12AB34CD)
400                      Destination half-word exchange only (Source : 0xAB12CD34 ------> Destination : 0xCD34AB12)
401 
402           (+) Use HAL_DMAEx_ConfigDataHandling() to configure data handling features. Previous elementary explained
403               can be combined according to application needs.
404               (++) This API is complementary of normal transfers.
405               (++) This API must not be called for linked-list transfers as data handling information are configured at
406                    node level.
407 
408     *** User sequence ***
409     [..]
410       To configure cleanly the DMA channel data handling, ensure to apply the following call sequence :
411 
412           (+) Linear transfer :
413               (++) HAL_DMA_Init()
414               (++) HAL_DMAEx_ConfigDataHandling()
415               (++) HAL_DMA_Start()
416 
417     *** Trigger Configuration ***
418     =============================
419     [..]
420       When application needs that DMA transfers are conditioned by internal or external events, the trigger feature can
421       do that. Trigger signals are a set of device signal that are linked to DMA trigger inputs that allows to start the
422       DMA transfers.
423       To setup a trigger transfers, three DMA channel parameters are needed:
424 
425           (+) Trigger mode
426               This parameter specifies the trig level.
427                (++) Block level
428                (++) Repeated block level
429                (++) Node level
430                (++) Single / Burst level
431 
432           (+) Trigger polarity
433               This parameter specifies the DMA trigger sensitivity (Rising or falling).
434 
435           (+) Trigger selection
436               This parameter specifies the DMA trigger hardware signal.
437 
438           (+) Use HAL_DMAEx_ConfigTrigger() to configure trigger feature.
439               (++) This API is complementary to normal transfers APIs.
440               (++) This API must not be called for linked-list transfers as trigger information are configured at
441                    node level.
442 
443     *** User sequence ***
444     [..]
445       To configure cleanly the DMA channel trigger, ensure to apply the following call sequence :
446           (+) Linear transfer :
447               (++) HAL_DMA_Init()
448               (++) HAL_DMAEx_ConfigTrigger()
449               (++) HAL_DMA_Start()
450 
451     *** Suspend and resume operation ***
452     ====================================
453     [..]
454       There are several cases when needs to suspend a DMA current transfer (Example: liberate bandwidth for more
455       priority DMA channel transfer). Suspending DMA channel (same as abort) is available in polling (blocking mode) and
456       interrupt (non-blocking mode) modes. When suspended, a DMA channel can be instantly resumed.
457 
458           (+) Use HAL_DMAEx_Suspend() to suspend an ongoing DMA channel transfer in polling mode (Blocking mode).
459 
460           (+) Use HAL_DMAEx_Suspend_IT() to suspend an ongoing DMA channel transfer in interrupt mode (Non-blocking
461               mode).
462 
463           (+) Use HAL_DMAEx_Resume() to resume a suspended DMA channel transfer execution.
464 
465     *** FIFO status ***
466     ===================
467     [..]
468       In several cases, the information of FIFO level is useful to inform at application level how to process remaining
469       data. When not empty, the DMA channel FIFO cannot be flashed only by reset.
470 
471           (+) Use HAL_DMAEx_GetFifoLevel() to get the DMA channel FIFO level (available beats in FIFO).
472 
473     @endverbatim
474   **********************************************************************************************************************
475   */
476 
477 /* Includes ----------------------------------------------------------------------------------------------------------*/
478 #include "stm32wbaxx_hal.h"
479 
480 /** @addtogroup STM32WBAxx_HAL_Driver
481   * @{
482   */
483 
484 /** @defgroup DMAEx DMAEx
485   * @brief DMA Extended HAL module driver
486   * @{
487   */
488 
489 #ifdef HAL_DMA_MODULE_ENABLED
490 
491 /* Private types -----------------------------------------------------------------------------------------------------*/
492 /* Private variables -------------------------------------------------------------------------------------------------*/
493 /* Private Constants -------------------------------------------------------------------------------------------------*/
494 /* Private macros ----------------------------------------------------------------------------------------------------*/
495 /* Private function prototypes ---------------------------------------------------------------------------------------*/
496 static void DMA_List_Init(DMA_HandleTypeDef const *const hdma);
497 static void DMA_List_BuildNode(DMA_NodeConfTypeDef const *const pNodeConfig,
498                                DMA_NodeTypeDef *const pNode);
499 static void DMA_List_GetNodeConfig(DMA_NodeConfTypeDef *const pNodeConfig,
500                                    DMA_NodeTypeDef const *const pNode);
501 static uint32_t DMA_List_CheckNodesBaseAddresses(DMA_NodeTypeDef const *const pNode1,
502                                                  DMA_NodeTypeDef const *const pNode2,
503                                                  DMA_NodeTypeDef const *const pNode3);
504 static uint32_t DMA_List_CheckNodesTypes(DMA_NodeTypeDef const *const pNode1,
505                                          DMA_NodeTypeDef const *const pNode2,
506                                          DMA_NodeTypeDef const *const pNode3);
507 static void DMA_List_GetCLLRNodeInfo(DMA_NodeTypeDef const *const pNode,
508                                      uint32_t *const cllr_mask,
509                                      uint32_t *const cllr_offset);
510 static uint32_t DMA_List_FindNode(DMA_QListTypeDef const *const pQList,
511                                   DMA_NodeTypeDef const *const pNode,
512                                   DMA_NodeInQInfoTypeDef *const NodeInfo);
513 static void DMA_List_ResetQueueNodes(DMA_QListTypeDef const *const pQList,
514                                      DMA_NodeInQInfoTypeDef const *const NodeInfo);
515 static void DMA_List_FillNode(DMA_NodeTypeDef const *const pSrcNode,
516                               DMA_NodeTypeDef *const pDestNode);
517 static void DMA_List_ConvertNodeToDynamic(uint32_t ContextNodeAddr,
518                                           uint32_t CurrentNodeAddr,
519                                           uint32_t RegisterNumber);
520 static void DMA_List_ConvertNodeToStatic(uint32_t ContextNodeAddr,
521                                          uint32_t CurrentNodeAddr,
522                                          uint32_t RegisterNumber);
523 static void DMA_List_UpdateDynamicQueueNodesCLLR(DMA_QListTypeDef const *const pQList,
524                                                  uint32_t LastNode_IsCircular);
525 static void DMA_List_UpdateStaticQueueNodesCLLR(DMA_QListTypeDef const *const pQList,
526                                                 uint32_t operation);
527 static void DMA_List_FormatNode(DMA_NodeTypeDef *const pNode,
528                                 uint32_t RegisterIdx,
529                                 uint32_t RegisterNumber,
530                                 uint32_t Format);
531 static void DMA_List_ClearUnusedFields(DMA_NodeTypeDef *const pNode,
532                                        uint32_t FirstUnusedField);
533 static void DMA_List_CleanQueue(DMA_QListTypeDef *const pQList);
534 
535 /* Exported functions ------------------------------------------------------------------------------------------------*/
536 
537 /** @addtogroup DMAEx_Exported_Functions
538   * @{
539   */
540 
541 /** @addtogroup DMAEx_Exported_Functions_Group1
542   *
543 @verbatim
544   ======================================================================================================================
545                  ##### Linked-List Initialization and De-Initialization Functions #####
546   ======================================================================================================================
547     [..]
548       This section provides functions allowing to initialize and de-initialize the DMA channel in linked-list mode.
549     [..]
550       (+) The HAL_DMAEx_List_Init() function follows the DMA channel linked-list mode configuration procedures as
551           described in reference manual.
552       (+) The HAL_DMAEx_List_DeInit() function allows to de-initialize the DMA channel in linked-list mode.
553 
554 @endverbatim
555   * @{
556   */
557 
558 /**
559   * @brief  Initialize the DMA channel in linked-list mode according to the specified parameters in the
560   *         DMA_InitLinkedListTypeDef and create the associated handle.
561   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
562   *                specified DMA Channel.
563   * @retval HAL status.
564   */
HAL_DMAEx_List_Init(DMA_HandleTypeDef * const hdma)565 HAL_StatusTypeDef HAL_DMAEx_List_Init(DMA_HandleTypeDef *const hdma)
566 {
567   /* Get tick number */
568   uint32_t tickstart = HAL_GetTick();
569 
570   /* Check the DMA channel handle parameter */
571   if (hdma == NULL)
572   {
573     return HAL_ERROR;
574   }
575 
576   /* Check the parameters */
577   assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
578   assert_param(IS_DMA_PRIORITY(hdma->InitLinkedList.Priority));
579   assert_param(IS_DMA_LINK_STEP_MODE(hdma->InitLinkedList.LinkStepMode));
580   assert_param(IS_DMA_TCEM_LINKEDLIST_EVENT_MODE(hdma->InitLinkedList.TransferEventMode));
581   assert_param(IS_DMA_LINKEDLIST_MODE(hdma->InitLinkedList.LinkedListMode));
582   /* Check DMA channel instance */
583   if (IS_GPDMA_INSTANCE(hdma->Instance) != 0U)
584   {
585     assert_param(IS_DMA_LINK_ALLOCATED_PORT(hdma->InitLinkedList.LinkAllocatedPort));
586   }
587 
588   /* Allocate lock resource */
589   __HAL_UNLOCK(hdma);
590 
591   /* Change DMA peripheral state */
592   hdma->State = HAL_DMA_STATE_BUSY;
593 
594   /* Disable the DMA channel */
595   __HAL_DMA_DISABLE(hdma);
596 
597   /* Check if the DMA channel is effectively disabled */
598   while ((hdma->Instance->CCR & DMA_CCR_EN) != 0U)
599   {
600     /* Check for the Timeout */
601     if ((HAL_GetTick() - tickstart) > HAL_TIMEOUT_DMA_ABORT)
602     {
603       /* Update error code */
604       hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
605 
606       /* Change the DMA state */
607       hdma->State = HAL_DMA_STATE_ERROR;
608 
609       return HAL_ERROR;
610     }
611   }
612 
613   /* Initialize the DMA channel registers */
614   DMA_List_Init(hdma);
615 
616   /* Update DMA channel operation mode */
617   hdma->Mode = hdma->InitLinkedList.LinkedListMode;
618 
619   /* Update the DMA channel error code */
620   hdma->ErrorCode = HAL_DMA_ERROR_NONE;
621 
622   /* Update the DMA channel state */
623   hdma->State = HAL_DMA_STATE_READY;
624 
625   return HAL_OK;
626 }
627 
628 /**
629   * @brief  DeInitialize the DMA channel when it is configured in linked-list mode.
630   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
631   *                specified DMA Channel.
632   * @retval HAL status.
633   */
HAL_DMAEx_List_DeInit(DMA_HandleTypeDef * const hdma)634 HAL_StatusTypeDef HAL_DMAEx_List_DeInit(DMA_HandleTypeDef *const hdma)
635 {
636 #if defined (DMA_PRIVCFGR_PRIV0)
637   /* Get DMA instance */
638   DMA_TypeDef *p_dma_instance;
639 #endif /* DMA_PRIVCFGR_PRIV0 */
640   /* Get tick number */
641   uint32_t tickstart = HAL_GetTick();
642 
643   /* Check the DMA peripheral handle parameter */
644   if (hdma == NULL)
645   {
646     return HAL_ERROR;
647   }
648 
649   /* Check the parameters */
650   assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
651 
652 #if defined (DMA_PRIVCFGR_PRIV0)
653   /* Get DMA instance */
654   p_dma_instance = GET_DMA_INSTANCE(hdma);
655 #endif /* DMA_PRIVCFGR_PRIV0 */
656   /* Disable the selected DMA Channel */
657   __HAL_DMA_DISABLE(hdma);
658 
659   /* Check if the DMA channel is effectively disabled */
660   while ((hdma->Instance->CCR & DMA_CCR_EN) != 0U)
661   {
662     /* Check for the Timeout */
663     if ((HAL_GetTick() - tickstart) > HAL_TIMEOUT_DMA_ABORT)
664     {
665       /* Update error code */
666       hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
667 
668       /* Change the DMA state */
669       hdma->State = HAL_DMA_STATE_ERROR;
670 
671       return HAL_ERROR;
672     }
673   }
674 
675   /* Reset DMA Channel registers */
676   hdma->Instance->CCR   = 0U;
677   hdma->Instance->CLBAR = 0U;
678   hdma->Instance->CTR1  = 0U;
679   hdma->Instance->CTR2  = 0U;
680   hdma->Instance->CBR1  = 0U;
681   hdma->Instance->CSAR  = 0U;
682   hdma->Instance->CDAR  = 0U;
683   hdma->Instance->CLLR  = 0U;
684 
685 #if defined (DMA_PRIVCFGR_PRIV0)
686   /* Clear privilege attribute */
687   CLEAR_BIT(p_dma_instance->PRIVCFGR, (1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU)));
688 #endif /* DMA_PRIVCFGR_PRIV0 */
689 
690 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
691   /* Clear secure attribute */
692   CLEAR_BIT(p_dma_instance->SECCFGR, (1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU)));
693 #endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
694 
695   /* Clear all flags */
696   __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC | DMA_FLAG_HT | DMA_FLAG_DTE | DMA_FLAG_ULE | DMA_FLAG_USE | DMA_FLAG_SUSP |
697                               DMA_FLAG_TO));
698 
699   /* Clean all callbacks */
700   hdma->XferCpltCallback     = NULL;
701   hdma->XferHalfCpltCallback = NULL;
702   hdma->XferErrorCallback    = NULL;
703   hdma->XferAbortCallback    = NULL;
704   hdma->XferSuspendCallback  = NULL;
705 
706   /* Check the linked-list queue */
707   if (hdma->LinkedListQueue != NULL)
708   {
709     /* Update the queue state and error code */
710     hdma->LinkedListQueue->State     = HAL_DMA_QUEUE_STATE_READY;
711     hdma->LinkedListQueue->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
712 
713     /* Clean DMA queue */
714     hdma->LinkedListQueue = NULL;
715   }
716 
717   /* Clean DMA parent */
718   if (hdma->Parent != NULL)
719   {
720     hdma->Parent = NULL;
721   }
722 
723   /* Update DMA channel operation mode */
724   hdma->Mode = DMA_NORMAL;
725 
726   /* Update the DMA channel error code */
727   hdma->ErrorCode = HAL_DMA_ERROR_NONE;
728 
729   /* Update the DMA channel state */
730   hdma->State = HAL_DMA_STATE_RESET;
731 
732   /* Release Lock */
733   __HAL_UNLOCK(hdma);
734 
735   return HAL_OK;
736 }
737 /**
738   * @}
739   */
740 
741 /** @addtogroup DMAEx_Exported_Functions_Group2
742   *
743 @verbatim
744   ======================================================================================================================
745                          ##### Linked-List IO Operation Functions #####
746   ======================================================================================================================
747     [..]
748       This section provides functions allowing to :
749       (+) Configure to start DMA transfer in linked-list mode.
750 
751     [..]
752       (+) The HAL_DMAEx_List_Start() function allows to start the DMA channel transfer in linked-list mode (Blocking
753           mode).
754       (+) The HAL_DMAEx_List_Start_IT() function allows to start the DMA channel transfer in linked-list mode
755           (Non-blocking mode).
756               (++) It is mandatory to register a linked-list queue to be executed by a DMA channel before starting
757                    transfer otherwise a HAL_ERROR will be returned.
758 
759 @endverbatim
760   * @{
761   */
762 
763 /**
764   * @brief  Start the DMA channel transfer in linked-list mode (Blocking mode).
765   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
766   *                specified DMA Channel.
767   * @retval HAL status.
768   */
HAL_DMAEx_List_Start(DMA_HandleTypeDef * const hdma)769 HAL_StatusTypeDef HAL_DMAEx_List_Start(DMA_HandleTypeDef *const hdma)
770 {
771   HAL_DMA_StateTypeDef dma_state;
772   uint32_t ccr_value;
773   uint32_t cllr_mask;
774 
775   /* Check the DMA peripheral handle and the linked-list queue parameters */
776   if ((hdma == NULL) || (hdma->LinkedListQueue == NULL))
777   {
778     return HAL_ERROR;
779   }
780 
781   /* Check DMA channel state */
782   dma_state = hdma->State;
783   ccr_value = hdma->Instance->CCR & DMA_CCR_LSM;
784   if ((dma_state == HAL_DMA_STATE_READY) || ((dma_state == HAL_DMA_STATE_BUSY) && (ccr_value != 0U)))
785   {
786     /* Check DMA channel state is ready */
787     if (hdma->State == HAL_DMA_STATE_READY)
788     {
789       /* Process locked */
790       __HAL_LOCK(hdma);
791 
792       /* Update the DMA channel and the queue states */
793       hdma->State                  = HAL_DMA_STATE_BUSY;
794       hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_BUSY;
795 
796       /* Update the DMA channel and the queue error codes */
797       hdma->ErrorCode                  = HAL_DMA_ERROR_NONE;
798       hdma->LinkedListQueue->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
799 
800       /* Get CLLR register mask and offset */
801       DMA_List_GetCLLRNodeInfo(hdma->LinkedListQueue->Head, &cllr_mask, NULL);
802 
803       /* Update DMA registers for linked-list transfer */
804       hdma->Instance->CLBAR = ((uint32_t)hdma->LinkedListQueue->Head & DMA_CLBAR_LBA);
805       hdma->Instance->CLLR  = ((uint32_t)hdma->LinkedListQueue->Head & DMA_CLLR_LA) | cllr_mask;
806     }
807 
808     /* Enable DMA channel */
809     __HAL_DMA_ENABLE(hdma);
810   }
811   else
812   {
813     /* Update the DMA channel error code */
814     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
815 
816     /* Process unlocked */
817     __HAL_UNLOCK(hdma);
818 
819     return HAL_ERROR;
820   }
821 
822   return HAL_OK;
823 }
824 
825 /**
826   * @brief  Starts the DMA channel transfer in linked-list mode with interrupts enabled (Non-blocking mode).
827   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
828   *                specified DMA Channel.
829   * @retval HAL status.
830   */
HAL_DMAEx_List_Start_IT(DMA_HandleTypeDef * const hdma)831 HAL_StatusTypeDef HAL_DMAEx_List_Start_IT(DMA_HandleTypeDef *const hdma)
832 {
833   HAL_DMA_StateTypeDef dma_state;
834   uint32_t ccr_value;
835   uint32_t cllr_mask;
836 
837   /* Check the DMA peripheral handle and the linked-list queue parameters */
838   if ((hdma == NULL) || (hdma->LinkedListQueue == NULL))
839   {
840     return HAL_ERROR;
841   }
842 
843   /* Check DMA channel state */
844   dma_state = hdma->State;
845   ccr_value = hdma->Instance->CCR & DMA_CCR_LSM;
846   if ((dma_state == HAL_DMA_STATE_READY) || ((dma_state == HAL_DMA_STATE_BUSY) && (ccr_value != 0U)))
847   {
848     /* Check DMA channel state is ready */
849     if (hdma->State == HAL_DMA_STATE_READY)
850     {
851       /* Process locked */
852       __HAL_LOCK(hdma);
853 
854       /* Update the DMA channel and the queue states */
855       hdma->State                  = HAL_DMA_STATE_BUSY;
856       hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_BUSY;
857 
858       /* Update the DMA channel and the queue error codes */
859       hdma->ErrorCode                  = HAL_DMA_ERROR_NONE;
860       hdma->LinkedListQueue->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
861 
862       /* Enable common interrupts: Transfer Complete and Transfer Errors ITs */
863       __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_DTE | DMA_IT_ULE | DMA_IT_USE | DMA_IT_TO));
864 
865       /* Check half transfer complete callback */
866       if (hdma->XferHalfCpltCallback != NULL)
867       {
868         /* If half transfer complete callback is set, enable the corresponding IT */
869         __HAL_DMA_ENABLE_IT(hdma, DMA_IT_HT);
870       }
871 
872       /* Check suspend callback */
873       if (hdma->XferSuspendCallback != NULL)
874       {
875         /* If transfer suspend callback is set, enable the corresponding IT */
876         __HAL_DMA_ENABLE_IT(hdma, DMA_IT_SUSP);
877       }
878 
879       /* Get CLLR register mask and offset */
880       DMA_List_GetCLLRNodeInfo(hdma->LinkedListQueue->Head, &cllr_mask, NULL);
881 
882       /* Update DMA registers for linked-list transfer */
883       hdma->Instance->CLBAR = ((uint32_t)hdma->LinkedListQueue->Head & DMA_CLBAR_LBA);
884       hdma->Instance->CLLR  = ((uint32_t)hdma->LinkedListQueue->Head & DMA_CLLR_LA) | cllr_mask;
885     }
886 
887     /* Enable DMA channel */
888     __HAL_DMA_ENABLE(hdma);
889   }
890   else
891   {
892     /* Change the error code */
893     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
894 
895     /* Process unlocked */
896     __HAL_UNLOCK(hdma);
897 
898     return HAL_ERROR;
899   }
900 
901   return HAL_OK;
902 }
903 /**
904   * @}
905   */
906 
907 /** @addtogroup DMAEx_Exported_Functions_Group3
908   *
909 @verbatim
910   ======================================================================================================================
911                          ##### Linked-List Management Functions #####
912   ======================================================================================================================
913     [..]
914       This section provides functions allowing to :
915       (+) Build linked-list node.
916       (+) Get linked-list node configuration.
917       (+) Insert node to linked-list queue in any queue position.
918       (+) Remove any node from linked-list queue.
919       (+) Replace any node from linked-list queue.
920       (+) Reset linked-list queue.
921       (+) Insert linked-list queue in any queue position.
922       (+) Set circular mode configuration to linked-list queue.
923       (+) Clear circular mode configuration from linked-list queue.
924       (+) Convert static linked-list queue to dynamic format.
925       (+) Convert dynamic linked-list queue to static format.
926       (+) Link linked-list queue to DMA channel.
927       (+) Unlink linked-list queue from DMA channel.
928 
929     [..]
930       (+) The HAL_DMAEx_List_BuildNode() function allows to build linked-list node.
931           Node type can be :
932               (++) 2 dimensions addressing node.
933               (++) Linear addressing node.
934 
935       (+) The HAL_DMAEx_List_GetNodeConfig() function allows to get the linked-list node configuration from built node.
936 
937       (+) The HAL_DMAEx_List_InsertNode() function allows to insert built linked-list node to static linked-list queue
938           according to selected position.
939 
940       (+) The HAL_DMAEx_List_InsertNode_Head() and HAL_DMAEx_List_InsertNode_Tail() functions allow to insert built
941           linked-list node to the head (respectively the tail) of static linked-list queue.
942 
943       (+) The HAL_DMAEx_List_RemoveNode() function allows to remove selected built linked-list node from static
944           linked-list queue.
945 
946       (+) The HAL_DMAEx_List_RemoveNode_Head() and HAL_DMAEx_List_RemoveNode_Tail() functions allow to remove the head
947           (respectively the tail) built linked-list node from static linked-list queue.
948 
949       (+) The HAL_DMAEx_List_ReplaceNode() function allows to replace selected built linked-list node from static
950           linked-list queue.
951 
952       (+) The HAL_DMAEx_List_ReplaceNode_Head() and HAL_DMAEx_List_ReplaceNode_Tail() functions allow to replace the
953           head (respectively the tail) built linked-list node of static linked-list queue.
954 
955       (+) The HAL_DMAEx_List_ResetQ() function allows to reset static linked-list queue and unlink all built linked-list
956           nodes.
957 
958       (+) The HAL_DMAEx_List_InsertQ() function allows to insert static linked-list source queue to static linked-list
959           destination queue according to selected position.
960 
961       (+) The HAL_DMAEx_List_InsertQ_Head() and HAL_DMAEx_List_InsertQ_Tail() functions allow to insert static
962           linked-list source queue to the head (respectively the tail) of static linked-list destination queue.
963 
964       (+) The HAL_DMAEx_List_SetCircularModeConfig() function allows to link the last static linked-list queue node to
965           the selected first circular node.
966 
967       (+) The HAL_DMAEx_List_SetCircularMode() function allows to link the last static linked-list queue node to the
968           first static linked-list queue node.
969 
970       (+) The HAL_DMAEx_List_ClearCircularMode() function allows to unlink the last static linked-list queue node from
971           any first circular node position.
972 
973       (+) The HAL_DMAEx_List_ConvertQToDynamic() function allows to convert the static linked-list queue to dynamic
974           format. (Optimized queue execution)
975 
976       (+) The HAL_DMAEx_List_ConvertQToStatic() function allows to convert the dynamic linked-list queue to static
977           format. (Not optimized queue execution)
978 
979       (+) The HAL_DMAEx_List_LinkQ() function allows to link the (Dynamic / Static) linked-list queue to DMA channel to
980           be executed.
981 
982       (+) The HAL_DMAEx_List_UnLinkQ() function allows to unlink the (Dynamic / Static) linked-list queue from DMA
983           channel when execution is completed.
984 
985 @endverbatim
986   * @{
987   */
988 
989 /**
990   * @brief  Build a DMA channel node according to the specified parameters in the DMA_NodeConfTypeDef.
991   * @param  pNodeConfig : Pointer to a DMA_NodeConfTypeDef structure that contains the configuration information for the
992   *                       specified DMA linked-list Node.
993   * @param  pNode       : Pointer to a DMA_NodeTypeDef structure that contains linked-list node registers
994   *                       configurations.
995   * @note   The DMA linked-list node parameter address should be 32bit aligned and should not exceed the 64 KByte
996   *         addressable space.
997   * @retval HAL status.
998   */
HAL_DMAEx_List_BuildNode(DMA_NodeConfTypeDef const * const pNodeConfig,DMA_NodeTypeDef * const pNode)999 HAL_StatusTypeDef HAL_DMAEx_List_BuildNode(DMA_NodeConfTypeDef const *const pNodeConfig,
1000                                            DMA_NodeTypeDef *const pNode)
1001 {
1002   /* Check the node configuration and physical node parameters */
1003   if ((pNodeConfig == NULL) || (pNode == NULL))
1004   {
1005     return HAL_ERROR;
1006   }
1007 
1008   /* Check node type parameter */
1009   assert_param(IS_DMA_NODE_TYPE(pNodeConfig->NodeType));
1010 
1011   /* Check DMA channel basic transfer parameters */
1012   assert_param(IS_DMA_SOURCE_INC(pNodeConfig->Init.SrcInc));
1013   assert_param(IS_DMA_DESTINATION_INC(pNodeConfig->Init.DestInc));
1014   assert_param(IS_DMA_SOURCE_DATA_WIDTH(pNodeConfig->Init.SrcDataWidth));
1015   assert_param(IS_DMA_DESTINATION_DATA_WIDTH(pNodeConfig->Init.DestDataWidth));
1016   assert_param(IS_DMA_DATA_ALIGNMENT(pNodeConfig->DataHandlingConfig.DataAlignment));
1017   assert_param(IS_DMA_REQUEST(pNodeConfig->Init.Request));
1018   assert_param(IS_DMA_DIRECTION(pNodeConfig->Init.Direction));
1019   assert_param(IS_DMA_TCEM_EVENT_MODE(pNodeConfig->Init.TransferEventMode));
1020   assert_param(IS_DMA_BLOCK_HW_REQUEST(pNodeConfig->Init.BlkHWRequest));
1021   assert_param(IS_DMA_MODE(pNodeConfig->Init.Mode));
1022 
1023   /* Check DMA channel parameters */
1024   if ((pNodeConfig->NodeType & DMA_CHANNEL_TYPE_GPDMA) == DMA_CHANNEL_TYPE_GPDMA)
1025   {
1026     assert_param(IS_DMA_BURST_LENGTH(pNodeConfig->Init.SrcBurstLength));
1027     assert_param(IS_DMA_BURST_LENGTH(pNodeConfig->Init.DestBurstLength));
1028     assert_param(IS_DMA_DATA_EXCHANGE(pNodeConfig->DataHandlingConfig.DataExchange));
1029     assert_param(IS_DMA_TRANSFER_ALLOCATED_PORT(pNodeConfig->Init.TransferAllocatedPort));
1030   }
1031 
1032   /* Check DMA channel trigger parameters */
1033   assert_param(IS_DMA_TRIGGER_POLARITY(pNodeConfig->TriggerConfig.TriggerPolarity));
1034   if (pNodeConfig->TriggerConfig.TriggerPolarity != DMA_TRIG_POLARITY_MASKED)
1035   {
1036     assert_param(IS_DMA_TRIGGER_MODE(pNodeConfig->TriggerConfig.TriggerMode));
1037     assert_param(IS_DMA_TRIGGER_SELECTION(pNodeConfig->TriggerConfig.TriggerSelection));
1038   }
1039 
1040   /* Check DMA channel security and privilege attributes parameters */
1041 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
1042   assert_param(IS_DMA_ATTRIBUTES(pNodeConfig->SrcSecure));
1043   assert_param(IS_DMA_ATTRIBUTES(pNodeConfig->DestSecure));
1044 #endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
1045 
1046   /* Build the DMA channel node */
1047   DMA_List_BuildNode(pNodeConfig, pNode);
1048 
1049   return HAL_OK;
1050 }
1051 
1052 /**
1053   * @brief  Get a DMA channel node configuration.
1054   * @param  pNodeConfig : Pointer to a DMA_NodeConfTypeDef structure that contains the configuration information for the
1055   *                       specified DMA linked-list Node.
1056   * @param  pNode       : Pointer to a DMA_NodeTypeDef structure that contains linked-list node registers
1057   *                       configurations.
1058   * @retval HAL status.
1059   */
HAL_DMAEx_List_GetNodeConfig(DMA_NodeConfTypeDef * const pNodeConfig,DMA_NodeTypeDef const * const pNode)1060 HAL_StatusTypeDef HAL_DMAEx_List_GetNodeConfig(DMA_NodeConfTypeDef *const pNodeConfig,
1061                                                DMA_NodeTypeDef const *const pNode)
1062 {
1063   /* Check the node configuration and physical node parameters */
1064   if ((pNodeConfig == NULL) || (pNode == NULL))
1065   {
1066     return HAL_ERROR;
1067   }
1068 
1069   /* Get the DMA channel node configuration */
1070   DMA_List_GetNodeConfig(pNodeConfig, pNode);
1071 
1072   return HAL_OK;
1073 }
1074 
1075 /**
1076   * @brief  Insert new node in any queue position of linked-list queue according to selecting previous node.
1077   * @param  pQList    : Pointer to a DMA_QListTypeDef structure that contains queue information.
1078   * @param  pPrevNode : Pointer to a DMA_NodeTypeDef structure that contains linked-list previous node registers
1079   *                     configurations.
1080   * @param  pNewNode  : Pointer to a DMA_NodeTypeDef structure that contains linked-list new node registers
1081   *                     configurations.
1082   * @retval HAL status.
1083   */
HAL_DMAEx_List_InsertNode(DMA_QListTypeDef * const pQList,DMA_NodeTypeDef * const pPrevNode,DMA_NodeTypeDef * const pNewNode)1084 HAL_StatusTypeDef HAL_DMAEx_List_InsertNode(DMA_QListTypeDef *const pQList,
1085                                             DMA_NodeTypeDef *const pPrevNode,
1086                                             DMA_NodeTypeDef *const pNewNode)
1087 {
1088   uint32_t cllr_mask;
1089   uint32_t cllr_offset;
1090   DMA_NodeInQInfoTypeDef node_info;
1091 
1092   /* Check the queue and the new node parameters */
1093   if ((pQList == NULL) || (pNewNode == NULL))
1094   {
1095     return HAL_ERROR;
1096   }
1097 
1098   /* Check queue type */
1099   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1100   {
1101     /* Update the queue error code */
1102     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1103 
1104     return HAL_ERROR;
1105   }
1106 
1107   /* Check nodes base addresses */
1108   if (DMA_List_CheckNodesBaseAddresses(pQList->Head, pPrevNode, pNewNode) != 0U)
1109   {
1110     /* Update the queue error code */
1111     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
1112 
1113     return HAL_ERROR;
1114   }
1115 
1116   /* Check nodes types compatibility */
1117   if (DMA_List_CheckNodesTypes(pQList->Head, pPrevNode, pNewNode) != 0U)
1118   {
1119     /* Update the queue error code */
1120     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1121 
1122     return HAL_ERROR;
1123   }
1124 
1125   /* Update the queue state */
1126   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
1127 
1128   /* Update the queue error code */
1129   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1130 
1131   /* Get CLLR register mask and offset */
1132   DMA_List_GetCLLRNodeInfo(pNewNode, &cllr_mask, &cllr_offset);
1133 
1134   /* Empty queue */
1135   if (pQList->Head == NULL)
1136   {
1137     /* Add only new node to queue */
1138     if (pPrevNode == NULL)
1139     {
1140       pQList->Head       = pNewNode;
1141       pQList->NodeNumber = 1U;
1142     }
1143     /* Add previous node then new node to queue */
1144     else
1145     {
1146       pQList->Head                          = pPrevNode;
1147       pPrevNode->LinkRegisters[cllr_offset] = ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1148       pQList->NodeNumber                    = 2U;
1149     }
1150   }
1151   /* Not empty queue */
1152   else
1153   {
1154     /* Add new node at the head of queue */
1155     if (pPrevNode == NULL)
1156     {
1157       pNewNode->LinkRegisters[cllr_offset] = ((uint32_t)pQList->Head & DMA_CLLR_LA) | cllr_mask;
1158       pQList->Head                         = pNewNode;
1159     }
1160     /* Add new node according to selected position */
1161     else
1162     {
1163       /* Find node and get its position in selected queue */
1164       node_info.cllr_offset = cllr_offset;
1165       if (DMA_List_FindNode(pQList, pPrevNode, &node_info) == 0U)
1166       {
1167         /* Selected node is the last queue node */
1168         if (node_info.currentnode_pos == pQList->NodeNumber)
1169         {
1170           /* Check if queue is circular */
1171           if (pQList->FirstCircularNode != NULL)
1172           {
1173             pNewNode->LinkRegisters[cllr_offset] = ((uint32_t)pQList->FirstCircularNode & DMA_CLLR_LA) | cllr_mask;
1174           }
1175 
1176           pPrevNode->LinkRegisters[cllr_offset] = ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1177         }
1178         /* Selected node is not the last queue node */
1179         else
1180         {
1181           pNewNode->LinkRegisters[cllr_offset] = pPrevNode->LinkRegisters[cllr_offset];
1182           pPrevNode->LinkRegisters[cllr_offset] = ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1183         }
1184       }
1185       else
1186       {
1187         /* Update the queue error code */
1188         pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NOTFOUND;
1189 
1190         return HAL_ERROR;
1191       }
1192     }
1193 
1194     /* Increment queue node number */
1195     pQList->NodeNumber++;
1196   }
1197 
1198   /* Update the queue error code */
1199   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1200 
1201   /* Update the queue state */
1202   pQList->State = HAL_DMA_QUEUE_STATE_READY;
1203 
1204   return HAL_OK;
1205 }
1206 
1207 /**
1208   * @brief  Insert new node at the head of linked-list queue.
1209   * @param  pQList    : Pointer to a DMA_QListTypeDef structure that contains queue information.
1210   * @param  pNewNode  : Pointer to a DMA_NodeTypeDef structure that contains linked-list new node registers
1211   *                     configurations.
1212   * @retval HAL status.
1213   */
HAL_DMAEx_List_InsertNode_Head(DMA_QListTypeDef * const pQList,DMA_NodeTypeDef * const pNewNode)1214 HAL_StatusTypeDef HAL_DMAEx_List_InsertNode_Head(DMA_QListTypeDef *const pQList,
1215                                                  DMA_NodeTypeDef *const pNewNode)
1216 {
1217   uint32_t cllr_mask;
1218   uint32_t cllr_offset;
1219 
1220   /* Check the queue and the new node parameters */
1221   if ((pQList == NULL) || (pNewNode == NULL))
1222   {
1223     return HAL_ERROR;
1224   }
1225 
1226   /* Check queue type */
1227   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1228   {
1229     /* Update the queue error code */
1230     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1231 
1232     return HAL_ERROR;
1233   }
1234 
1235   /* Check nodes base addresses */
1236   if (DMA_List_CheckNodesBaseAddresses(pQList->Head, pNewNode, NULL) != 0U)
1237   {
1238     /* Update the queue error code */
1239     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
1240 
1241     return HAL_ERROR;
1242   }
1243 
1244   /* Check nodes types compatibility */
1245   if (DMA_List_CheckNodesTypes(pQList->Head, pNewNode, NULL) != 0U)
1246   {
1247     /* Update the queue error code */
1248     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1249 
1250     return HAL_ERROR;
1251   }
1252 
1253   /* Update the queue state */
1254   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
1255 
1256   /* Update the queue error code */
1257   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1258 
1259   /* Empty queue */
1260   if (pQList->Head == NULL)
1261   {
1262     pQList->Head = pNewNode;
1263   }
1264   /* Not empty queue */
1265   else
1266   {
1267     /* Get CLLR register mask and offset */
1268     DMA_List_GetCLLRNodeInfo(pNewNode, &cllr_mask, &cllr_offset);
1269 
1270     pNewNode->LinkRegisters[cllr_offset] = ((uint32_t)pQList->Head & DMA_CLLR_LA) | cllr_mask;
1271     pQList->Head                         = pNewNode;
1272   }
1273 
1274   /* Increment queue node number */
1275   pQList->NodeNumber++;
1276 
1277   /* Update the queue error code */
1278   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1279 
1280   /* Update the queue state */
1281   pQList->State = HAL_DMA_QUEUE_STATE_READY;
1282 
1283   return HAL_OK;
1284 }
1285 
1286 /**
1287   * @brief  Insert new node at the tail of linked-list queue.
1288   * @param  pQList    : Pointer to a DMA_QListTypeDef structure that contains queue information.
1289   * @param  pNewNode  : Pointer to a DMA_NodeTypeDef structure that contains linked-list new node registers
1290   *                     configurations.
1291   * @retval HAL status.
1292   */
HAL_DMAEx_List_InsertNode_Tail(DMA_QListTypeDef * const pQList,DMA_NodeTypeDef * const pNewNode)1293 HAL_StatusTypeDef HAL_DMAEx_List_InsertNode_Tail(DMA_QListTypeDef *const pQList,
1294                                                  DMA_NodeTypeDef *const pNewNode)
1295 {
1296   uint32_t cllr_mask;
1297   uint32_t cllr_offset;
1298   DMA_NodeInQInfoTypeDef node_info;
1299 
1300   /* Check the queue and the new node parameters */
1301   if ((pQList == NULL) || (pNewNode == NULL))
1302   {
1303     return HAL_ERROR;
1304   }
1305 
1306   /* Check queue type */
1307   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1308   {
1309     /* Update the queue error code */
1310     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1311 
1312     return HAL_ERROR;
1313   }
1314 
1315   /* Check nodes base addresses */
1316   if (DMA_List_CheckNodesBaseAddresses(pQList->Head, pNewNode, NULL) != 0U)
1317   {
1318     /* Update the queue error code */
1319     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
1320 
1321     return HAL_ERROR;
1322   }
1323 
1324   /* Check nodes types compatibility */
1325   if (DMA_List_CheckNodesTypes(pQList->Head, pNewNode, NULL) != 0U)
1326   {
1327     /* Update the queue error code */
1328     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1329 
1330     return HAL_ERROR;
1331   }
1332 
1333   /* Empty queue */
1334   if (pQList->Head == NULL)
1335   {
1336     pQList->Head = pNewNode;
1337   }
1338   /* Not empty queue */
1339   else
1340   {
1341     /* Get CLLR register mask and offset */
1342     DMA_List_GetCLLRNodeInfo(pNewNode, &cllr_mask, &cllr_offset);
1343 
1344     /* Find node and get its position in selected queue */
1345     node_info.cllr_offset = cllr_offset;
1346     (void)DMA_List_FindNode(pQList, NULL, &node_info);
1347 
1348     /* Check if queue is circular */
1349     if (pQList->FirstCircularNode != NULL)
1350     {
1351       pNewNode->LinkRegisters[cllr_offset] = ((uint32_t)pQList->FirstCircularNode & DMA_CLLR_LA) | cllr_mask;
1352     }
1353 
1354     ((DMA_NodeTypeDef *)node_info.currentnode_addr)->LinkRegisters[cllr_offset] =
1355       ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1356   }
1357 
1358   /* Increment queue node number */
1359   pQList->NodeNumber++;
1360 
1361   /* Update the queue error code */
1362   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1363 
1364   /* Update the queue state */
1365   pQList->State = HAL_DMA_QUEUE_STATE_READY;
1366 
1367   /* Prevent MISRA-C2012-Rule-2.2_b */
1368   UNUSED(node_info);
1369 
1370   return HAL_OK;
1371 }
1372 
1373 /**
1374   * @brief  Remove node from any linked-list queue position.
1375   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
1376   * @param  pNode  : Pointer to a DMA_NodeTypeDef structure that contains linked-list previous node registers
1377   *                  configurations.
1378   * @retval HAL status.
1379   */
HAL_DMAEx_List_RemoveNode(DMA_QListTypeDef * const pQList,DMA_NodeTypeDef * const pNode)1380 HAL_StatusTypeDef HAL_DMAEx_List_RemoveNode(DMA_QListTypeDef *const pQList,
1381                                             DMA_NodeTypeDef *const pNode)
1382 {
1383   uint32_t previousnode_addr;
1384   uint32_t cllr_offset;
1385   DMA_NodeInQInfoTypeDef node_info;
1386 
1387   /* Check the queue and the node parameters */
1388   if ((pQList == NULL) || (pNode == NULL))
1389   {
1390     return HAL_ERROR;
1391   }
1392 
1393   /* Check the queue */
1394   if (pQList->Head == NULL)
1395   {
1396     /* Update the queue error code */
1397     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
1398 
1399     return HAL_ERROR;
1400   }
1401 
1402   /* Check queue type */
1403   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1404   {
1405     /* Update the queue error code */
1406     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1407 
1408     return HAL_ERROR;
1409   }
1410 
1411   /* Update the queue state */
1412   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
1413 
1414   /* Update the queue error code */
1415   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1416 
1417   /* Get CLLR register mask and offset */
1418   DMA_List_GetCLLRNodeInfo(pNode, NULL, &cllr_offset);
1419 
1420   /* Find node and get its position in selected queue */
1421   node_info.cllr_offset = cllr_offset;
1422   if (DMA_List_FindNode(pQList, pNode, &node_info) == 0U)
1423   {
1424     /* Removed node is the head node */
1425     if (node_info.currentnode_pos == 1U)
1426     {
1427       /* Check if first circular node queue is the first node */
1428       if (pQList->FirstCircularNode == ((DMA_NodeTypeDef *)node_info.currentnode_addr))
1429       {
1430         /* Find last queue node */
1431         (void)DMA_List_FindNode(pQList, NULL, &node_info);
1432 
1433         /* Clear last node link */
1434         ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
1435 
1436         /* Clear first circular node */
1437         pQList->FirstCircularNode = NULL;
1438       }
1439 
1440       /* Update the queue head node */
1441       pQList->Head = (DMA_NodeTypeDef *)(((uint32_t)pQList->Head & DMA_CLBAR_LBA) +
1442                                          (pNode->LinkRegisters[cllr_offset] & DMA_CLLR_LA));
1443       /* Unlink node to be removed */
1444       pNode->LinkRegisters[cllr_offset] = 0U;
1445     }
1446     /* Removed node is the last node */
1447     else if (node_info.currentnode_pos == pQList->NodeNumber)
1448     {
1449       /* Clear CLLR for previous node */
1450       ((DMA_NodeTypeDef *)(node_info.previousnode_addr))->LinkRegisters[cllr_offset] = 0U;
1451 
1452       /* Clear CLLR for last node */
1453       ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
1454 
1455       /* Clear first circular node */
1456       pQList->FirstCircularNode = NULL;
1457     }
1458     /* Removed node is in the middle */
1459     else
1460     {
1461       /* Store previous node address to be updated later */
1462       previousnode_addr = node_info.previousnode_addr;
1463 
1464       /* Check if first circular node queue is the current node */
1465       if (pQList->FirstCircularNode == ((DMA_NodeTypeDef *)node_info.currentnode_addr))
1466       {
1467         /* Find last queue node */
1468         (void)DMA_List_FindNode(pQList, NULL, &node_info);
1469 
1470         /* Clear last node link */
1471         ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
1472 
1473         /* Clear first circular node */
1474         pQList->FirstCircularNode = NULL;
1475       }
1476 
1477       /* Link previous node */
1478       ((DMA_NodeTypeDef *)(previousnode_addr))->LinkRegisters[cllr_offset] = pNode->LinkRegisters[cllr_offset];
1479 
1480       /* Unlink node to be removed */
1481       pNode->LinkRegisters[cllr_offset] = 0U;
1482     }
1483 
1484     /* Decrement node number */
1485     pQList->NodeNumber--;
1486   }
1487   else
1488   {
1489     /* Update the queue error code */
1490     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NOTFOUND;
1491 
1492     return HAL_ERROR;
1493   }
1494 
1495   /* Check if queue is empty */
1496   if (pQList->NodeNumber == 0U)
1497   {
1498     /* Clean empty queue parameter */
1499     DMA_List_CleanQueue(pQList);
1500   }
1501   else
1502   {
1503     /* Update the queue error code */
1504     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1505 
1506     /* Update the queue state */
1507     pQList->State = HAL_DMA_QUEUE_STATE_READY;
1508   }
1509 
1510   /* Prevent MISRA-C2012-Rule-2.2_b */
1511   UNUSED(node_info);
1512 
1513   return HAL_OK;
1514 }
1515 
1516 /**
1517   * @brief  Remove the head node from linked-list queue.
1518   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
1519   * @retval HAL status.
1520   */
HAL_DMAEx_List_RemoveNode_Head(DMA_QListTypeDef * const pQList)1521 HAL_StatusTypeDef HAL_DMAEx_List_RemoveNode_Head(DMA_QListTypeDef *const pQList)
1522 {
1523   uint32_t cllr_offset;
1524   uint32_t current_addr;
1525   DMA_NodeInQInfoTypeDef node_info;
1526 
1527   /* Check the queue parameter */
1528   if (pQList == NULL)
1529   {
1530     return HAL_ERROR;
1531   }
1532 
1533   /* Check the queue */
1534   if (pQList->Head == NULL)
1535   {
1536     /* Update the queue error code */
1537     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
1538 
1539     return HAL_ERROR;
1540   }
1541 
1542   /* Check queue type */
1543   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1544   {
1545     /* Update the queue error code */
1546     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1547 
1548     return HAL_ERROR;
1549   }
1550 
1551   /* Update the queue state */
1552   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
1553 
1554   /* Update the queue error code */
1555   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1556 
1557   /* Get CLLR register mask and offset */
1558   DMA_List_GetCLLRNodeInfo(pQList->Head, NULL, &cllr_offset);
1559 
1560   /* Queue contains only one node */
1561   if (pQList->NodeNumber == 1U)
1562   {
1563     pQList->Head->LinkRegisters[cllr_offset] = 0U;
1564     pQList->FirstCircularNode = 0U;
1565     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1566   }
1567   /* Queue contains more then one node */
1568   else
1569   {
1570     /* Check if first circular node queue is the first node */
1571     if (pQList->FirstCircularNode == pQList->Head)
1572     {
1573       /* Find last queue node */
1574       node_info.cllr_offset = cllr_offset;
1575       (void)DMA_List_FindNode(pQList, NULL, &node_info);
1576 
1577       /* Clear last node link */
1578       ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
1579 
1580       /* Clear first circular node */
1581       pQList->FirstCircularNode = NULL;
1582     }
1583 
1584     current_addr = pQList->Head->LinkRegisters[cllr_offset] & DMA_CLLR_LA;
1585     pQList->Head->LinkRegisters[cllr_offset] = 0U;
1586     pQList->Head = ((DMA_NodeTypeDef *)(current_addr + ((uint32_t)pQList->Head & DMA_CLBAR_LBA)));
1587   }
1588 
1589   /* Decrement node number */
1590   pQList->NodeNumber--;
1591 
1592   /* Check if queue is empty */
1593   if (pQList->NodeNumber == 0U)
1594   {
1595     /* Clean empty queue parameter */
1596     DMA_List_CleanQueue(pQList);
1597   }
1598   else
1599   {
1600     /* Update the queue error code */
1601     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1602 
1603     /* Update the queue state */
1604     pQList->State = HAL_DMA_QUEUE_STATE_READY;
1605   }
1606 
1607   /* Prevent MISRA-C2012-Rule-2.2_b */
1608   UNUSED(node_info);
1609 
1610   return HAL_OK;
1611 }
1612 
1613 /**
1614   * @brief  Remove the tail node from linked-list queue.
1615   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
1616   * @retval HAL status.
1617   */
HAL_DMAEx_List_RemoveNode_Tail(DMA_QListTypeDef * const pQList)1618 HAL_StatusTypeDef HAL_DMAEx_List_RemoveNode_Tail(DMA_QListTypeDef *const pQList)
1619 {
1620   uint32_t cllr_offset;
1621   DMA_NodeInQInfoTypeDef node_info;
1622 
1623   /* Check the queue parameter */
1624   if (pQList == NULL)
1625   {
1626     return HAL_ERROR;
1627   }
1628 
1629   /* Check the queue */
1630   if (pQList->Head == NULL)
1631   {
1632     /* Update the queue error code */
1633     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
1634 
1635     return HAL_ERROR;
1636   }
1637 
1638   /* Check queue type */
1639   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1640   {
1641     /* Update the queue error code */
1642     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1643 
1644     return HAL_ERROR;
1645   }
1646 
1647   /* Update the queue state */
1648   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
1649 
1650   /* Update the queue error code */
1651   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1652 
1653   /* Get CLLR register mask and offset */
1654   DMA_List_GetCLLRNodeInfo(pQList->Head, NULL, &cllr_offset);
1655 
1656   /* Queue contains only one node */
1657   if (pQList->NodeNumber == 1U)
1658   {
1659     pQList->Head->LinkRegisters[cllr_offset] = 0U;
1660     pQList->FirstCircularNode = 0U;
1661     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1662   }
1663   /* Queue contains more then one node */
1664   else
1665   {
1666     /* Find node and get its position in selected queue */
1667     node_info.cllr_offset = cllr_offset;
1668     (void)DMA_List_FindNode(pQList, NULL, &node_info);
1669 
1670     /* Clear CLLR for previous node */
1671     ((DMA_NodeTypeDef *)(node_info.previousnode_addr))->LinkRegisters[cllr_offset] = 0U;
1672 
1673     /* Clear CLLR for last node */
1674     ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
1675 
1676     /* Clear first circular node */
1677     pQList->FirstCircularNode = NULL;
1678   }
1679 
1680   /* Decrement node number */
1681   pQList->NodeNumber--;
1682 
1683   /* Check if queue is empty */
1684   if (pQList->NodeNumber == 0U)
1685   {
1686     /* Clean empty queue parameter */
1687     DMA_List_CleanQueue(pQList);
1688   }
1689   else
1690   {
1691     /* Update the queue error code */
1692     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1693 
1694     /* Update the queue state */
1695     pQList->State = HAL_DMA_QUEUE_STATE_READY;
1696   }
1697 
1698   /* Prevent MISRA-C2012-Rule-2.2_b */
1699   UNUSED(node_info);
1700 
1701   return HAL_OK;
1702 }
1703 
1704 /**
1705   * @brief  Replace node in linked-list queue.
1706   * @param  pQList   : Pointer to a DMA_QListTypeDef structure that contains queue information.
1707   * @param  pOldNode : Pointer to a DMA_NodeTypeDef structure that contains linked-list old node registers
1708   *                    configurations.
1709   * @param  pNewNode : Pointer to a DMA_NodeTypeDef structure that contains linked-list new node registers
1710   *                    configurations.
1711   * @retval HAL status.
1712   */
HAL_DMAEx_List_ReplaceNode(DMA_QListTypeDef * const pQList,DMA_NodeTypeDef * const pOldNode,DMA_NodeTypeDef * const pNewNode)1713 HAL_StatusTypeDef HAL_DMAEx_List_ReplaceNode(DMA_QListTypeDef *const pQList,
1714                                              DMA_NodeTypeDef *const pOldNode,
1715                                              DMA_NodeTypeDef *const pNewNode)
1716 {
1717   uint32_t cllr_mask;
1718   uint32_t cllr_offset;
1719   DMA_NodeInQInfoTypeDef node_info;
1720 
1721   /* Check the queue and the nodes parameters */
1722   if ((pQList == NULL) || (pOldNode == NULL) || (pNewNode == NULL))
1723   {
1724     return HAL_ERROR;
1725   }
1726 
1727   /* Check the queue */
1728   if (pQList->Head == NULL)
1729   {
1730     /* Update the queue error code */
1731     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
1732 
1733     return HAL_ERROR;
1734   }
1735 
1736   /* Check queue type */
1737   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1738   {
1739     /* Update the queue error code */
1740     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1741 
1742     return HAL_ERROR;
1743   }
1744 
1745   /* Check nodes base addresses */
1746   if (DMA_List_CheckNodesBaseAddresses(pQList->Head, pOldNode, pNewNode) != 0U)
1747   {
1748     /* Update the queue error code */
1749     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
1750 
1751     return HAL_ERROR;
1752   }
1753 
1754   /* Check nodes types compatibility */
1755   if (DMA_List_CheckNodesTypes(pQList->Head, pOldNode, pNewNode) != 0U)
1756   {
1757     /* Update the queue error code */
1758     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1759 
1760     return HAL_ERROR;
1761   }
1762 
1763   /* Update the queue state */
1764   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
1765 
1766   /* Update the queue error code */
1767   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1768 
1769   /* Get CLLR register mask and offset */
1770   DMA_List_GetCLLRNodeInfo(pNewNode, &cllr_mask, &cllr_offset);
1771 
1772   /* Find node and get its position in selected queue */
1773   node_info.cllr_offset = cllr_offset;
1774   if (DMA_List_FindNode(pQList, pOldNode, &node_info) == 0U)
1775   {
1776     /* Replaced node is the head node */
1777     if (node_info.currentnode_pos == 1U)
1778     {
1779       pNewNode->LinkRegisters[cllr_offset] =
1780         ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset];
1781       pQList->Head = pNewNode;
1782       ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
1783 
1784       /* Check if first circular node queue is the first node */
1785       if (pQList->FirstCircularNode == ((DMA_NodeTypeDef *)node_info.currentnode_addr))
1786       {
1787         /* Find last queue node */
1788         (void)DMA_List_FindNode(pQList, NULL, &node_info);
1789 
1790         /* Clear last node link */
1791         ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
1792           ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1793 
1794         /* Set new node as first circular node */
1795         pQList->FirstCircularNode = pNewNode;
1796       }
1797     }
1798     /* Replaced node is the last */
1799     else if (node_info.currentnode_pos == pQList->NodeNumber)
1800     {
1801       ((DMA_NodeTypeDef *)(node_info.previousnode_addr))->LinkRegisters[cllr_offset] =
1802         ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1803       ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
1804 
1805       /* Check if first circular node queue is the last node */
1806       if (pQList->FirstCircularNode == ((DMA_NodeTypeDef *)(node_info.currentnode_addr)))
1807       {
1808         /* Link first circular node to new node */
1809         pNewNode->LinkRegisters[cllr_offset] = ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1810 
1811         /* Set new node as first circular node */
1812         pQList->FirstCircularNode = pNewNode;
1813       }
1814       /* Check if first circular node queue is not the last node */
1815       else if (pQList->FirstCircularNode != NULL)
1816       {
1817         /* Link first circular node to new node */
1818         pNewNode->LinkRegisters[cllr_offset] = ((uint32_t)pQList->FirstCircularNode & DMA_CLLR_LA) | cllr_mask;
1819       }
1820       else
1821       {
1822         /* Prevent MISRA-C2012-Rule-15.7 */
1823       }
1824     }
1825     /* Replaced node is in the middle */
1826     else
1827     {
1828       ((DMA_NodeTypeDef *)(node_info.previousnode_addr))->LinkRegisters[cllr_offset] =
1829         ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1830       pNewNode->LinkRegisters[cllr_offset] =
1831         ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset];
1832       ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
1833 
1834       /* Check if first circular node queue is the current node */
1835       if (pQList->FirstCircularNode == ((DMA_NodeTypeDef *)(node_info.currentnode_addr)))
1836       {
1837         /* Find last node and get its position in selected queue */
1838         (void)DMA_List_FindNode(pQList, NULL, &node_info);
1839 
1840         /* Link last queue node to new node */
1841         ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
1842           ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1843 
1844         /* Set new node as first circular node */
1845         pQList->FirstCircularNode = pNewNode;
1846       }
1847     }
1848   }
1849   else
1850   {
1851     /* Update the queue error code */
1852     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NOTFOUND;
1853 
1854     return HAL_ERROR;
1855   }
1856 
1857   /* Update the queue error code */
1858   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1859 
1860   /* Update the queue state */
1861   pQList->State = HAL_DMA_QUEUE_STATE_READY;
1862 
1863   /* Prevent MISRA-C2012-Rule-2.2_b */
1864   UNUSED(node_info);
1865 
1866   return HAL_OK;
1867 }
1868 
1869 /**
1870   * @brief  Replace the head node of linked-list queue.
1871   * @param  pQList   : Pointer to a DMA_QListTypeDef structure that contains queue information.
1872   * @param  pNewNode : Pointer to a DMA_NodeTypeDef structure that contains linked-list new node registers
1873   *                    configurations.
1874   * @retval HAL status.
1875   */
HAL_DMAEx_List_ReplaceNode_Head(DMA_QListTypeDef * const pQList,DMA_NodeTypeDef * const pNewNode)1876 HAL_StatusTypeDef HAL_DMAEx_List_ReplaceNode_Head(DMA_QListTypeDef *const pQList,
1877                                                   DMA_NodeTypeDef *const pNewNode)
1878 {
1879   uint32_t cllr_offset;
1880   uint32_t cllr_mask;
1881   DMA_NodeInQInfoTypeDef node_info;
1882 
1883   /* Check the queue and the new node parameters */
1884   if ((pQList == NULL) || (pNewNode == NULL))
1885   {
1886     return HAL_ERROR;
1887   }
1888 
1889   /* Check the queue */
1890   if (pQList->Head == NULL)
1891   {
1892     /* Update the queue error code */
1893     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
1894 
1895     return HAL_ERROR;
1896   }
1897 
1898   /* Check queue type */
1899   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1900   {
1901     /* Update the queue error code */
1902     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1903 
1904     return HAL_ERROR;
1905   }
1906 
1907   /* Check nodes base addresses */
1908   if (DMA_List_CheckNodesBaseAddresses(pQList->Head, pNewNode, NULL) != 0U)
1909   {
1910     /* Update the queue error code */
1911     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
1912 
1913     return HAL_ERROR;
1914   }
1915 
1916   /* Check nodes types compatibility */
1917   if (DMA_List_CheckNodesTypes(pQList->Head, pNewNode, NULL) != 0U)
1918   {
1919     /* Update the queue error code */
1920     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1921 
1922     return HAL_ERROR;
1923   }
1924 
1925   /* Update the queue state */
1926   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
1927 
1928   /* Update the queue error code */
1929   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1930 
1931   /* Get CLLR register mask and offset */
1932   DMA_List_GetCLLRNodeInfo(pNewNode, &cllr_mask, &cllr_offset);
1933 
1934   /* Check if first circular node queue is the first node */
1935   if (pQList->FirstCircularNode == pQList->Head)
1936   {
1937     /* Find last queue node */
1938     node_info.cllr_offset = cllr_offset;
1939     (void)DMA_List_FindNode(pQList, NULL, &node_info);
1940 
1941     /* Clear last node link */
1942     ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
1943       ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1944 
1945     /* Set new node as first circular node */
1946     pQList->FirstCircularNode = pNewNode;
1947   }
1948 
1949   /* Replace head node */
1950   pNewNode->LinkRegisters[cllr_offset] = pQList->Head->LinkRegisters[cllr_offset];
1951   pQList->Head->LinkRegisters[cllr_offset] = 0U;
1952   pQList->Head = pNewNode;
1953 
1954   /* Update the queue error code */
1955   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1956 
1957   /* Update the queue state */
1958   pQList->State = HAL_DMA_QUEUE_STATE_READY;
1959 
1960   /* Prevent MISRA-C2012-Rule-2.2_b */
1961   UNUSED(node_info);
1962 
1963   return HAL_OK;
1964 }
1965 
1966 /**
1967   * @brief  Replace the tail node of linked-list queue.
1968   * @param  pQList   : Pointer to a DMA_QListTypeDef structure that contains queue information.
1969   * @param  pNewNode : Pointer to a DMA_NodeTypeDef structure that contains linked-list new node registers
1970   *                    configurations.
1971   * @retval HAL status.
1972   */
HAL_DMAEx_List_ReplaceNode_Tail(DMA_QListTypeDef * const pQList,DMA_NodeTypeDef * const pNewNode)1973 HAL_StatusTypeDef HAL_DMAEx_List_ReplaceNode_Tail(DMA_QListTypeDef *const pQList,
1974                                                   DMA_NodeTypeDef *const pNewNode)
1975 {
1976   uint32_t cllr_mask;
1977   uint32_t cllr_offset;
1978   DMA_NodeInQInfoTypeDef node_info;
1979 
1980   /* Check the queue and the new node parameters */
1981   if ((pQList == NULL) || (pNewNode == NULL))
1982   {
1983     return HAL_ERROR;
1984   }
1985 
1986   /* Check the queue */
1987   if (pQList->Head == NULL)
1988   {
1989     /* Update the queue error code */
1990     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
1991 
1992     return HAL_ERROR;
1993   }
1994 
1995   /* Check queue type */
1996   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1997   {
1998     /* Update the queue error code */
1999     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2000 
2001     return HAL_ERROR;
2002   }
2003 
2004   /* Update the queue state */
2005   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2006 
2007   /* Update the queue error code */
2008   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2009 
2010   /* Get CLLR register mask and offset */
2011   DMA_List_GetCLLRNodeInfo(pNewNode, &cllr_mask, &cllr_offset);
2012 
2013   /* Find last node and get its position in selected queue */
2014   node_info.cllr_offset = cllr_offset;
2015   (void)DMA_List_FindNode(pQList, NULL, &node_info);
2016 
2017   /* Link previous node to new node */
2018   ((DMA_NodeTypeDef *)(node_info.previousnode_addr))->LinkRegisters[cllr_offset] =
2019     ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
2020 
2021   /* Clear CLLR for current node */
2022   ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
2023 
2024   /* Check if first circular node queue is the last node */
2025   if (pQList->FirstCircularNode == ((DMA_NodeTypeDef *)(node_info.currentnode_addr)))
2026   {
2027     /* Link first circular node to new node */
2028     pNewNode->LinkRegisters[cllr_offset] = ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
2029 
2030     /* Set new node as first circular node */
2031     pQList->FirstCircularNode = pNewNode;
2032   }
2033   /* Check if first circular node queue is not the last node */
2034   else if (pQList->FirstCircularNode != NULL)
2035   {
2036     /* Link first circular node to new node */
2037     pNewNode->LinkRegisters[cllr_offset] = ((uint32_t)pQList->FirstCircularNode & DMA_CLLR_LA) | cllr_mask;
2038   }
2039   else
2040   {
2041     /* Prevent MISRA-C2012-Rule-15.7 */
2042   }
2043 
2044   /* Check if queue contains one node */
2045   if (pQList->NodeNumber == 1U)
2046   {
2047     pQList->Head = pNewNode;
2048   }
2049 
2050   /* Update the queue error code */
2051   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2052 
2053   /* Update the queue state */
2054   pQList->State = HAL_DMA_QUEUE_STATE_READY;
2055 
2056   return HAL_OK;
2057 }
2058 
2059 /**
2060   * @brief  Reset the linked-list queue and unlink queue nodes.
2061   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
2062   * @retval HAL status.
2063   */
HAL_DMAEx_List_ResetQ(DMA_QListTypeDef * const pQList)2064 HAL_StatusTypeDef HAL_DMAEx_List_ResetQ(DMA_QListTypeDef *const pQList)
2065 {
2066   uint32_t cllr_offset;
2067   DMA_NodeInQInfoTypeDef node_info;
2068 
2069   /* Check the queue parameter */
2070   if (pQList == NULL)
2071   {
2072     return HAL_ERROR;
2073   }
2074 
2075   /* Check queue state */
2076   if (pQList->State == HAL_DMA_QUEUE_STATE_BUSY)
2077   {
2078     /* Update the queue error code */
2079     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_BUSY;
2080 
2081     return HAL_ERROR;
2082   }
2083 
2084   /* Check queue type */
2085   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
2086   {
2087     /* Update the queue error code */
2088     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2089 
2090     return HAL_ERROR;
2091   }
2092 
2093   /* Update the queue state */
2094   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2095 
2096   /* Update the queue error code */
2097   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2098 
2099   /* Check the queue */
2100   if (pQList->Head != NULL)
2101   {
2102     /* Get CLLR register mask and offset */
2103     DMA_List_GetCLLRNodeInfo(pQList->Head, NULL, &cllr_offset);
2104 
2105     /* Reset selected queue nodes */
2106     node_info.cllr_offset = cllr_offset;
2107     DMA_List_ResetQueueNodes(pQList, &node_info);
2108   }
2109 
2110   /* Reset head node address */
2111   pQList->Head = NULL;
2112 
2113   /* Reset node number */
2114   pQList->NodeNumber = 0U;
2115 
2116   /* Reset first circular node */
2117   pQList->FirstCircularNode = NULL;
2118 
2119   /* Update the queue error code */
2120   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2121 
2122   /* Update the queue state */
2123   pQList->State = HAL_DMA_QUEUE_STATE_RESET;
2124 
2125   return HAL_OK;
2126 }
2127 
2128 /**
2129   * @brief  Insert a source linked-list queue to a destination linked-list queue according to selecting previous node.
2130   * @param  pSrcQList  : Pointer to a DMA_QListTypeDef structure that contains source queue information.
2131   * @param  pPrevNode  : Pointer to a DMA_NodeTypeDef structure that contains linked-list previous node registers
2132   *                      configurations.
2133   * @param  pDestQList : Pointer to a DMA_QListTypeDef structure that contains destination queue information.
2134   * @retval HAL status.
2135   */
HAL_DMAEx_List_InsertQ(DMA_QListTypeDef * const pSrcQList,DMA_NodeTypeDef const * const pPrevNode,DMA_QListTypeDef * const pDestQList)2136 HAL_StatusTypeDef HAL_DMAEx_List_InsertQ(DMA_QListTypeDef *const pSrcQList,
2137                                          DMA_NodeTypeDef const *const pPrevNode,
2138                                          DMA_QListTypeDef *const pDestQList)
2139 {
2140   uint32_t cllr_mask;
2141   uint32_t cllr_offset;
2142   DMA_NodeInQInfoTypeDef src_q_node_info;
2143   DMA_NodeInQInfoTypeDef dest_q_node_info;
2144 
2145   /* Check the source and destination queues and the previous node parameters */
2146   if ((pSrcQList == NULL) || (pDestQList == NULL))
2147   {
2148     return HAL_ERROR;
2149   }
2150 
2151   /* Check the source queue */
2152   if (pSrcQList->Head == NULL)
2153   {
2154     /* Update the queue error code */
2155     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
2156 
2157     return HAL_ERROR;
2158   }
2159 
2160   /* Check the source queue type */
2161   if (pSrcQList->Type == QUEUE_TYPE_DYNAMIC)
2162   {
2163     /* Update the queue error code */
2164     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2165 
2166     return HAL_ERROR;
2167   }
2168 
2169   /* Check the destination queue type */
2170   if (pDestQList->Type == QUEUE_TYPE_DYNAMIC)
2171   {
2172     /* Update the queue error code */
2173     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2174 
2175     return HAL_ERROR;
2176   }
2177 
2178   /* Check the source queue circularity */
2179   if (pSrcQList->FirstCircularNode != NULL)
2180   {
2181     /* Update the source queue error code */
2182     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2183 
2184     return HAL_ERROR;
2185   }
2186 
2187   /* Check nodes base addresses */
2188   if (DMA_List_CheckNodesBaseAddresses(pSrcQList->Head, pPrevNode, pDestQList->Head) != 0U)
2189   {
2190     /* Update the source queue error code */
2191     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
2192 
2193     /* Update the destination queue error code */
2194     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
2195 
2196     return HAL_ERROR;
2197   }
2198 
2199   /* Check nodes types compatibility */
2200   if (DMA_List_CheckNodesTypes(pSrcQList->Head, pPrevNode, pDestQList->Head) != 0U)
2201   {
2202     /* Update the source queue error code */
2203     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2204 
2205     /* Update the destination queue error code */
2206     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2207 
2208     return HAL_ERROR;
2209   }
2210 
2211   /* Update the source queue state */
2212   pSrcQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2213 
2214   /* Update the source queue error code */
2215   pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2216 
2217   /* Update the destination queue state */
2218   pDestQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2219 
2220   /* Update the destination queue error code */
2221   pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2222 
2223   /* Get CLLR register mask and offset */
2224   DMA_List_GetCLLRNodeInfo(pSrcQList->Head, &cllr_mask, &cllr_offset);
2225 
2226   /* Empty destination queue */
2227   if (pDestQList->Head == NULL)
2228   {
2229     pDestQList->Head       = pSrcQList->Head;
2230     pDestQList->NodeNumber = pSrcQList->NodeNumber;
2231   }
2232   /* Not empty destination queue */
2233   else
2234   {
2235     /* Previous node is empty */
2236     if (pPrevNode == NULL)
2237     {
2238       /* Find node and get its position in selected queue */
2239       src_q_node_info.cllr_offset = cllr_offset;
2240       (void)DMA_List_FindNode(pSrcQList, NULL, &src_q_node_info);
2241 
2242       /* Check if first circular node queue is the first node */
2243       if (pDestQList->FirstCircularNode == pDestQList->Head)
2244       {
2245         /* Find node and get its position in selected queue */
2246         dest_q_node_info.cllr_offset = cllr_offset;
2247         (void)DMA_List_FindNode(pDestQList, NULL, &dest_q_node_info);
2248 
2249         /* Link destination queue tail node to new first circular node */
2250         ((DMA_NodeTypeDef *)dest_q_node_info.currentnode_addr)->LinkRegisters[cllr_offset] =
2251           ((uint32_t)pSrcQList->Head & DMA_CLLR_LA) | cllr_mask;
2252 
2253         /* Set the head node of source queue as the first circular node */
2254         pDestQList->FirstCircularNode = pSrcQList->Head;
2255       }
2256 
2257       /* Link the last node of source queue to the fist node of destination queue */
2258       ((DMA_NodeTypeDef *)(src_q_node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
2259         ((uint32_t)pDestQList->Head & DMA_CLLR_LA) | cllr_mask;
2260       pDestQList->Head        = pSrcQList->Head;
2261       pDestQList->NodeNumber += pSrcQList->NodeNumber;
2262     }
2263     /* Previous node is not empty */
2264     else
2265     {
2266       /* Find node and get its position in selected queue */
2267       dest_q_node_info.cllr_offset = cllr_offset;
2268       if (DMA_List_FindNode(pDestQList, pPrevNode, &dest_q_node_info) == 0U)
2269       {
2270         /* Selected node is the last destination queue node */
2271         if (dest_q_node_info.currentnode_pos == pDestQList->NodeNumber)
2272         {
2273           /* Link the first node of source queue to the last node of destination queue */
2274           ((DMA_NodeTypeDef *)(dest_q_node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
2275             ((uint32_t)pSrcQList->Head & DMA_CLLR_LA) | cllr_mask;
2276           pDestQList->NodeNumber += pSrcQList->NodeNumber;
2277 
2278           /* Check if first circular node queue is not empty */
2279           if (pDestQList->FirstCircularNode != NULL)
2280           {
2281             /* Find node and get its position in selected queue */
2282             src_q_node_info.cllr_offset = cllr_offset;
2283             (void)DMA_List_FindNode(pSrcQList, NULL, &src_q_node_info);
2284 
2285             /* Find first circular node */
2286             (void)DMA_List_FindNode(pDestQList, pDestQList->FirstCircularNode, &dest_q_node_info);
2287 
2288             /* Link last source queue node to first destination queue */
2289             ((DMA_NodeTypeDef *)src_q_node_info.currentnode_addr)->LinkRegisters[cllr_offset] =
2290               (dest_q_node_info.currentnode_addr & DMA_CLLR_LA) | cllr_mask;
2291           }
2292         }
2293         /* Selected node is not the last destination queue node */
2294         else
2295         {
2296           /* Link the first node of source queue to the previous node of destination queue */
2297           ((DMA_NodeTypeDef *)(dest_q_node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
2298             ((uint32_t)pSrcQList->Head & DMA_CLLR_LA) | cllr_mask;
2299 
2300           /* Find node and get its position in selected queue */
2301           src_q_node_info.cllr_offset = cllr_offset;
2302           (void)DMA_List_FindNode(pSrcQList, NULL, &src_q_node_info);
2303 
2304           /* Link the last node of source queue to the next node of destination queue */
2305           ((DMA_NodeTypeDef *)(src_q_node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
2306             (dest_q_node_info.nextnode_addr & DMA_CLLR_LA) | cllr_mask;
2307 
2308           /* Update queues counter */
2309           pDestQList->NodeNumber += pSrcQList->NodeNumber;
2310         }
2311       }
2312       else
2313       {
2314         /* Update the destination queue error code */
2315         pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NOTFOUND;
2316 
2317         return HAL_ERROR;
2318       }
2319     }
2320   }
2321 
2322   /* Clean the source queue variable as it is obsolete */
2323   DMA_List_CleanQueue(pSrcQList);
2324 
2325   /* Update the destination queue error code */
2326   pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2327 
2328   /* Update the destination queue state */
2329   pDestQList->State = HAL_DMA_QUEUE_STATE_READY;
2330 
2331   /* Prevent MISRA-C2012-Rule-2.2_b */
2332   UNUSED(src_q_node_info);
2333   UNUSED(dest_q_node_info);
2334 
2335   return HAL_OK;
2336 }
2337 
2338 /**
2339   * @brief  Insert a source linked-list queue at the head of destination queue.
2340   * @param  pSrcQList  : Pointer to a DMA_QListTypeDef structure that contains source queue information.
2341   * @param  pDestQList : Pointer to a DMA_QListTypeDef structure that contains destination queue information.
2342   * @retval HAL status.
2343   */
HAL_DMAEx_List_InsertQ_Head(DMA_QListTypeDef * const pSrcQList,DMA_QListTypeDef * const pDestQList)2344 HAL_StatusTypeDef HAL_DMAEx_List_InsertQ_Head(DMA_QListTypeDef *const pSrcQList,
2345                                               DMA_QListTypeDef *const pDestQList)
2346 {
2347   uint32_t cllr_mask;
2348   uint32_t cllr_offset;
2349   DMA_NodeInQInfoTypeDef src_q_node_info;
2350   DMA_NodeInQInfoTypeDef dest_q_node_info;
2351 
2352   /* Check the source and destination queues and the previous node parameters */
2353   if ((pSrcQList == NULL) || (pDestQList == NULL))
2354   {
2355     return HAL_ERROR;
2356   }
2357 
2358   /* Check the source queue */
2359   if (pSrcQList->Head == NULL)
2360   {
2361     /* Update the queue error code */
2362     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
2363 
2364     return HAL_ERROR;
2365   }
2366 
2367   /* Check the source queue type */
2368   if (pSrcQList->Type == QUEUE_TYPE_DYNAMIC)
2369   {
2370     /* Update the queue error code */
2371     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2372 
2373     return HAL_ERROR;
2374   }
2375 
2376   /* Check the destination queue type */
2377   if (pDestQList->Type == QUEUE_TYPE_DYNAMIC)
2378   {
2379     /* Update the queue error code */
2380     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2381 
2382     return HAL_ERROR;
2383   }
2384 
2385   /* Check nodes base addresses */
2386   if (DMA_List_CheckNodesBaseAddresses(pSrcQList->Head, pDestQList->Head, NULL) != 0U)
2387   {
2388     /* Update the source queue error code */
2389     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
2390 
2391     /* Update the destination queue error code */
2392     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
2393 
2394     return HAL_ERROR;
2395   }
2396 
2397   /* Check nodes types compatibility */
2398   if (DMA_List_CheckNodesTypes(pSrcQList->Head, pDestQList->Head, NULL) != 0U)
2399   {
2400     /* Update the source queue error code */
2401     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2402 
2403     /* Update the destination queue error code */
2404     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2405 
2406     return HAL_ERROR;
2407   }
2408 
2409   /* Update the source queue state */
2410   pSrcQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2411 
2412   /* Update the source queue error code */
2413   pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2414 
2415   /* Update the destination queue state */
2416   pDestQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2417 
2418   /* Update the destination queue error code */
2419   pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2420 
2421   /* Get CLLR register mask and offset */
2422   DMA_List_GetCLLRNodeInfo(pSrcQList->Head, &cllr_mask, &cllr_offset);
2423 
2424   /* Empty destination queue */
2425   if (pDestQList->Head == NULL)
2426   {
2427     pDestQList->Head       = pSrcQList->Head;
2428     pDestQList->NodeNumber = pSrcQList->NodeNumber;
2429   }
2430   /* Not empty destination queue */
2431   else
2432   {
2433     /* Find node and get its position in selected queue */
2434     src_q_node_info.cllr_offset = cllr_offset;
2435     (void)DMA_List_FindNode(pSrcQList, NULL, &src_q_node_info);
2436 
2437     /* Check if first circular node queue is the first node */
2438     if (pDestQList->FirstCircularNode == pDestQList->Head)
2439     {
2440       /* Find node and get its position in selected queue */
2441       dest_q_node_info.cllr_offset = cllr_offset;
2442       (void)DMA_List_FindNode(pDestQList, NULL, &dest_q_node_info);
2443 
2444       /* Link destination queue tail node to new first circular node */
2445       ((DMA_NodeTypeDef *)dest_q_node_info.currentnode_addr)->LinkRegisters[cllr_offset] =
2446         ((uint32_t)pSrcQList->Head & DMA_CLLR_LA) | cllr_mask;
2447 
2448       /* Set the head node of source queue as the first circular node */
2449       pDestQList->FirstCircularNode = pSrcQList->Head;
2450     }
2451 
2452     /* Link the last node of source queue to the fist node of destination queue */
2453     ((DMA_NodeTypeDef *)(src_q_node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
2454       ((uint32_t)pDestQList->Head & DMA_CLLR_LA) | cllr_mask;
2455     pDestQList->Head        = pSrcQList->Head;
2456     pDestQList->NodeNumber += pSrcQList->NodeNumber;
2457   }
2458 
2459   /* Clean the source queue variable as it is obsolete */
2460   DMA_List_CleanQueue(pSrcQList);
2461 
2462   /* Update the destination queue error code */
2463   pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2464 
2465   /* Update the destination queue state */
2466   pDestQList->State = HAL_DMA_QUEUE_STATE_READY;
2467 
2468   /* Prevent MISRA-C2012-Rule-2.2_b */
2469   UNUSED(src_q_node_info);
2470   UNUSED(dest_q_node_info);
2471 
2472   return HAL_OK;
2473 }
2474 
2475 /**
2476   * @brief  Insert a source linked-list queue at the tail of destination queue.
2477   * @param  pSrcQList  : Pointer to a DMA_QListTypeDef structure that contains source queue information.
2478   * @param  pDestQList : Pointer to a DMA_QListTypeDef structure that contains destination queue information.
2479   * @retval HAL status.
2480   */
HAL_DMAEx_List_InsertQ_Tail(DMA_QListTypeDef * const pSrcQList,DMA_QListTypeDef * const pDestQList)2481 HAL_StatusTypeDef HAL_DMAEx_List_InsertQ_Tail(DMA_QListTypeDef *const pSrcQList,
2482                                               DMA_QListTypeDef *const pDestQList)
2483 {
2484   uint32_t cllr_mask;
2485   uint32_t cllr_offset;
2486   DMA_NodeInQInfoTypeDef src_q_node_info;
2487   DMA_NodeInQInfoTypeDef dest_q_node_info;
2488 
2489   /* Check the source and destination queues and the previous node parameters */
2490   if ((pSrcQList == NULL) || (pDestQList == NULL))
2491   {
2492     return HAL_ERROR;
2493   }
2494 
2495   /* Check the source queue */
2496   if (pSrcQList->Head == NULL)
2497   {
2498     /* Update the queue error code */
2499     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
2500 
2501     return HAL_ERROR;
2502   }
2503 
2504   /* Check the source queue type */
2505   if (pSrcQList->Type == QUEUE_TYPE_DYNAMIC)
2506   {
2507     /* Update the queue error code */
2508     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2509 
2510     return HAL_ERROR;
2511   }
2512 
2513   /* Check the destination queue type */
2514   if (pDestQList->Type == QUEUE_TYPE_DYNAMIC)
2515   {
2516     /* Update the queue error code */
2517     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2518 
2519     return HAL_ERROR;
2520   }
2521 
2522   /* Check nodes base addresses */
2523   if (DMA_List_CheckNodesBaseAddresses(pSrcQList->Head, pDestQList->Head, NULL) != 0U)
2524   {
2525     /* Update the source queue error code */
2526     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
2527 
2528     /* Update the destination queue error code */
2529     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
2530 
2531     return HAL_ERROR;
2532   }
2533 
2534   /* Check nodes types compatibility */
2535   if (DMA_List_CheckNodesTypes(pSrcQList->Head, pDestQList->Head, NULL) != 0U)
2536   {
2537     /* Update the source queue error code */
2538     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2539 
2540     /* Update the destination queue error code */
2541     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2542 
2543     return HAL_ERROR;
2544   }
2545 
2546   /* Update the source queue state */
2547   pSrcQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2548 
2549   /* Update the source queue error code */
2550   pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2551 
2552   /* Update the destination queue state */
2553   pDestQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2554 
2555   /* Update the destination queue error code */
2556   pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2557 
2558   /* Get CLLR register mask and offset */
2559   DMA_List_GetCLLRNodeInfo(pSrcQList->Head, &cllr_mask, &cllr_offset);
2560 
2561   /* Empty destination queue */
2562   if (pDestQList->Head == NULL)
2563   {
2564     pDestQList->Head       = pSrcQList->Head;
2565     pDestQList->NodeNumber = pSrcQList->NodeNumber;
2566   }
2567   /* Not empty destination queue */
2568   else
2569   {
2570     /* Find node and get its position in selected queue */
2571     dest_q_node_info.cllr_offset = cllr_offset;
2572     (void)DMA_List_FindNode(pDestQList, NULL, &dest_q_node_info);
2573 
2574     /* Update source queue last node CLLR to link it with destination first node */
2575     ((DMA_NodeTypeDef *)(dest_q_node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
2576       ((uint32_t)pSrcQList->Head & DMA_CLLR_LA) | cllr_mask;
2577     pDestQList->NodeNumber += pSrcQList->NodeNumber;
2578 
2579     /* Check if first circular node queue is not empty */
2580     if (pDestQList->FirstCircularNode != NULL)
2581     {
2582       /* Find node and get its position in selected queue */
2583       src_q_node_info.cllr_offset = cllr_offset;
2584       (void)DMA_List_FindNode(pSrcQList, NULL, &src_q_node_info);
2585 
2586       /* Find first circular node */
2587       (void)DMA_List_FindNode(pDestQList, pDestQList->FirstCircularNode, &dest_q_node_info);
2588 
2589       /* Link last source queue node to first destination queue */
2590       ((DMA_NodeTypeDef *)src_q_node_info.currentnode_addr)->LinkRegisters[cllr_offset] =
2591         (dest_q_node_info.currentnode_addr & DMA_CLLR_LA) | cllr_mask;
2592     }
2593   }
2594 
2595   /* Clean the source queue variable as it is obsolete */
2596   DMA_List_CleanQueue(pSrcQList);
2597 
2598   /* Update the destination queue error code */
2599   pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2600 
2601   /* Update the destination queue state */
2602   pDestQList->State = HAL_DMA_QUEUE_STATE_READY;
2603 
2604   /* Prevent MISRA-C2012-Rule-2.2_b */
2605   UNUSED(src_q_node_info);
2606 
2607   return HAL_OK;
2608 }
2609 
2610 /**
2611   * @brief  Set circular mode configuration for linked-list queue.
2612   * @param  pQList             : Pointer to a DMA_QListTypeDef structure that contains queue information.
2613   * @param  pFirstCircularNode : Pointer to a DMA_NodeTypeDef structure that contains linked-list first circular node
2614   *                              registers configurations.
2615   * @retval HAL status.
2616   */
HAL_DMAEx_List_SetCircularModeConfig(DMA_QListTypeDef * const pQList,DMA_NodeTypeDef * const pFirstCircularNode)2617 HAL_StatusTypeDef HAL_DMAEx_List_SetCircularModeConfig(DMA_QListTypeDef *const pQList,
2618                                                        DMA_NodeTypeDef *const pFirstCircularNode)
2619 {
2620   uint32_t cllr_mask;
2621   uint32_t cllr_offset;
2622   DMA_NodeInQInfoTypeDef node_info;
2623 
2624   /* Check the queue and the first circular node parameters */
2625   if ((pQList == NULL) || (pFirstCircularNode == NULL))
2626   {
2627     return HAL_ERROR;
2628   }
2629 
2630   /* Check the queue */
2631   if (pQList->Head == NULL)
2632   {
2633     /* Update the queue error code */
2634     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
2635 
2636     return HAL_ERROR;
2637   }
2638 
2639   /* Check queue circular mode */
2640   if (pQList->FirstCircularNode != NULL)
2641   {
2642     if (pQList->FirstCircularNode == pFirstCircularNode)
2643     {
2644       return HAL_OK;
2645     }
2646     else
2647     {
2648       /* Update the queue error code */
2649       pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2650 
2651       return HAL_ERROR;
2652     }
2653   }
2654 
2655   /* Check queue type */
2656   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
2657   {
2658     /* Update the queue error code */
2659     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2660 
2661     return HAL_ERROR;
2662   }
2663 
2664   /* Update the queue state */
2665   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2666 
2667   /* Update the queue error code */
2668   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2669 
2670   /* Get CLLR register mask and offset */
2671   DMA_List_GetCLLRNodeInfo(pFirstCircularNode, &cllr_mask, &cllr_offset);
2672 
2673   /* Find the first circular node and get its position in selected queue */
2674   node_info.cllr_offset = cllr_offset;
2675   if (DMA_List_FindNode(pQList, pFirstCircularNode, &node_info) == 0U)
2676   {
2677     /* Find the last queue node and get its position in selected queue */
2678     (void)DMA_List_FindNode(pQList, NULL, &node_info);
2679 
2680     /* Set circular mode */
2681     ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
2682       ((uint32_t)pFirstCircularNode & DMA_CLLR_LA) | cllr_mask;
2683 
2684     /* Update first circular node in queue */
2685     pQList->FirstCircularNode = pFirstCircularNode;
2686   }
2687   else
2688   {
2689     /* Update the queue error code */
2690     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NOTFOUND;
2691 
2692     return HAL_ERROR;
2693   }
2694 
2695   /* Update the queue error code */
2696   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2697 
2698   /* Update the queue state */
2699   pQList->State = HAL_DMA_QUEUE_STATE_READY;
2700 
2701   /* Prevent MISRA-C2012-Rule-2.2_b */
2702   UNUSED(node_info);
2703 
2704   return HAL_OK;
2705 }
2706 
2707 /**
2708   * @brief  Set circular mode for linked-list queue.
2709   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
2710   * @retval HAL status.
2711   */
HAL_DMAEx_List_SetCircularMode(DMA_QListTypeDef * const pQList)2712 HAL_StatusTypeDef HAL_DMAEx_List_SetCircularMode(DMA_QListTypeDef *const pQList)
2713 {
2714   uint32_t cllr_mask;
2715   uint32_t cllr_offset;
2716   DMA_NodeInQInfoTypeDef node_info;
2717 
2718   /* Check the queue parameter */
2719   if (pQList == NULL)
2720   {
2721     return HAL_ERROR;
2722   }
2723 
2724   /* Check the queue */
2725   if (pQList->Head == NULL)
2726   {
2727     /* Update the queue error code */
2728     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
2729 
2730     return HAL_ERROR;
2731   }
2732 
2733   /* Check queue circular mode */
2734   if (pQList->FirstCircularNode != NULL)
2735   {
2736     if (pQList->FirstCircularNode == pQList->Head)
2737     {
2738       return HAL_OK;
2739     }
2740     else
2741     {
2742       /* Update the queue error code */
2743       pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2744 
2745       return HAL_ERROR;
2746     }
2747   }
2748 
2749   /* Check queue type */
2750   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
2751   {
2752     /* Update the queue error code */
2753     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2754 
2755     return HAL_ERROR;
2756   }
2757 
2758   /* Update the queue state */
2759   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2760 
2761   /* Update the queue error code */
2762   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2763 
2764   /* Get CLLR register mask and offset */
2765   DMA_List_GetCLLRNodeInfo(pQList->Head, &cllr_mask, &cllr_offset);
2766 
2767   /* Find the last queue node and get its position in selected queue */
2768   node_info.cllr_offset = cllr_offset;
2769   (void)DMA_List_FindNode(pQList, NULL, &node_info);
2770 
2771   /* Set circular mode */
2772   ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
2773     ((uint32_t)pQList->Head & DMA_CLLR_LA) | cllr_mask;
2774 
2775   /* Update linked-list circular state */
2776   pQList->FirstCircularNode = pQList->Head;
2777 
2778   /* Update the queue error code */
2779   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2780 
2781   /* Update the queue state */
2782   pQList->State = HAL_DMA_QUEUE_STATE_READY;
2783 
2784   /* Prevent MISRA-C2012-Rule-2.2_b */
2785   UNUSED(node_info);
2786 
2787   return HAL_OK;
2788 }
2789 
2790 /**
2791   * @brief  Clear circular mode for linked-list queue.
2792   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
2793   * @retval HAL status.
2794   */
HAL_DMAEx_List_ClearCircularMode(DMA_QListTypeDef * const pQList)2795 HAL_StatusTypeDef HAL_DMAEx_List_ClearCircularMode(DMA_QListTypeDef *const pQList)
2796 {
2797   uint32_t cllr_offset;
2798   DMA_NodeInQInfoTypeDef node_info;
2799 
2800   /* Check the queue parameter */
2801   if (pQList == NULL)
2802   {
2803     return HAL_ERROR;
2804   }
2805 
2806   /* Check the queue */
2807   if (pQList->Head == NULL)
2808   {
2809     /* Update the queue error code */
2810     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
2811 
2812     return HAL_ERROR;
2813   }
2814 
2815   /* Check queue circular mode */
2816   if (pQList->FirstCircularNode == NULL)
2817   {
2818     return HAL_OK;
2819   }
2820 
2821   /* Check queue type */
2822   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
2823   {
2824     /* Update the queue error code */
2825     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2826 
2827     return HAL_ERROR;
2828   }
2829 
2830   /* Update the queue state */
2831   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2832 
2833   /* Update the queue error code */
2834   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2835 
2836   /* Get CLLR register offset */
2837   DMA_List_GetCLLRNodeInfo(pQList->Head, NULL, &cllr_offset);
2838 
2839   /* Find the last queue node and get its position in selected queue */
2840   node_info.cllr_offset = cllr_offset;
2841   (void)DMA_List_FindNode(pQList, NULL, &node_info);
2842 
2843   /* Clear circular mode */
2844   ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
2845 
2846   /* Update linked-list circular configuration */
2847   pQList->FirstCircularNode = NULL;
2848 
2849   /* Update the queue error code */
2850   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2851 
2852   /* Update the queue state */
2853   pQList->State = HAL_DMA_QUEUE_STATE_READY;
2854 
2855   /* Prevent MISRA-C2012-Rule-2.2_b */
2856   UNUSED(node_info);
2857 
2858   return HAL_OK;
2859 }
2860 
2861 /**
2862   * @brief  Convert a linked-list queue to dynamic (Optimized DMA queue execution).
2863   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
2864   * @retval HAL status.
2865   */
HAL_DMAEx_List_ConvertQToDynamic(DMA_QListTypeDef * const pQList)2866 HAL_StatusTypeDef HAL_DMAEx_List_ConvertQToDynamic(DMA_QListTypeDef *const pQList)
2867 {
2868   uint32_t cllr_offset;
2869   uint32_t currentnode_addr;
2870   DMA_NodeTypeDef context_node;
2871   DMA_NodeInQInfoTypeDef node_info;
2872 
2873   /* Check the queue parameter */
2874   if (pQList == NULL)
2875   {
2876     return HAL_ERROR;
2877   }
2878 
2879   /* Check the queue */
2880   if (pQList->Head == NULL)
2881   {
2882     /* Update the queue error code */
2883     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
2884 
2885     return HAL_ERROR;
2886   }
2887 
2888   /* Check if queue is dynamic */
2889   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
2890   {
2891     return HAL_OK;
2892   }
2893 
2894   /* Update the queue state */
2895   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2896 
2897   /* Update the queue error code */
2898   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2899 
2900   /* Get CLLR register mask and offset */
2901   DMA_List_GetCLLRNodeInfo(pQList->Head, NULL, &cllr_offset);
2902 
2903   /* Check queue circularity */
2904   if (pQList->FirstCircularNode != 0U)
2905   {
2906     /* Find the last queue node and get its position in selected queue */
2907     node_info.cllr_offset = cllr_offset;
2908     (void)DMA_List_FindNode(pQList, NULL, &node_info);
2909   }
2910 
2911   /* Set current node address */
2912   currentnode_addr = (uint32_t)pQList->Head;
2913 
2914   /* Store register value */
2915   DMA_List_FillNode(pQList->Head, &context_node);
2916 
2917   /* Convert all nodes to dyncamic (Bypass head node) */
2918   for (uint32_t node_count = 1U; node_count < pQList->NodeNumber; node_count++)
2919   {
2920     /* Update node address */
2921     MODIFY_REG(currentnode_addr, DMA_CLLR_LA, (context_node.LinkRegisters[cllr_offset] & DMA_CLLR_LA));
2922 
2923     /* Bypass the first circular node when first circular node isn't the last queue node */
2924     if (((uint32_t)pQList->FirstCircularNode != 0U)                         &&
2925         ((uint32_t)pQList->FirstCircularNode != node_info.currentnode_addr) &&
2926         ((uint32_t)pQList->FirstCircularNode == currentnode_addr))
2927     {
2928       /* Copy first circular node to context node */
2929       DMA_List_FillNode(pQList->FirstCircularNode, &context_node);
2930     }
2931     else
2932     {
2933       /* Convert current node to dynamic */
2934       DMA_List_ConvertNodeToDynamic((uint32_t)&context_node, currentnode_addr, (cllr_offset + 1U));
2935     }
2936   }
2937 
2938   /* Check if first circular node is the last node queue */
2939   if (((uint32_t)pQList->FirstCircularNode != 0U) &&
2940       ((uint32_t)pQList->FirstCircularNode != node_info.currentnode_addr))
2941   {
2942     /* Update all queue nodes CLLR */
2943     DMA_List_UpdateDynamicQueueNodesCLLR(pQList, LASTNODE_ISNOT_CIRCULAR);
2944   }
2945   else
2946   {
2947     /* Update all queue nodes CLLR */
2948     DMA_List_UpdateDynamicQueueNodesCLLR(pQList, LASTNODE_IS_CIRCULAR);
2949   }
2950 
2951   /* Set queue type */
2952   pQList->Type = QUEUE_TYPE_DYNAMIC;
2953 
2954   /* Update the queue error code */
2955   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2956 
2957   /* Update the queue state */
2958   pQList->State = HAL_DMA_QUEUE_STATE_READY;
2959 
2960   return HAL_OK;
2961 }
2962 
2963 /**
2964   * @brief  Convert a linked-list queue to static (Not optimized DMA queue execution).
2965   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
2966   * @retval HAL status.
2967   */
HAL_DMAEx_List_ConvertQToStatic(DMA_QListTypeDef * const pQList)2968 HAL_StatusTypeDef HAL_DMAEx_List_ConvertQToStatic(DMA_QListTypeDef *const pQList)
2969 {
2970   uint32_t cllr_offset;
2971   uint32_t currentnode_addr;
2972   DMA_NodeTypeDef context_node;
2973 
2974   /* Check the queue parameter */
2975   if (pQList == NULL)
2976   {
2977     return HAL_ERROR;
2978   }
2979 
2980   /* Check the queue */
2981   if (pQList->Head == NULL)
2982   {
2983     /* Update the queue error code */
2984     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
2985 
2986     return HAL_ERROR;
2987   }
2988 
2989   /* Check if queue is static */
2990   if (pQList->Type == QUEUE_TYPE_STATIC)
2991   {
2992     return HAL_OK;
2993   }
2994 
2995   /* Set current node address */
2996   currentnode_addr = (uint32_t)pQList->Head;
2997 
2998   /* Update the queue state */
2999   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
3000 
3001   /* Update the queue error code */
3002   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
3003 
3004   /* Get CLLR register mask and offset */
3005   DMA_List_GetCLLRNodeInfo(pQList->Head, NULL, &cllr_offset);
3006 
3007   /* Set all CLLR queue nodes to their default positions */
3008   DMA_List_UpdateStaticQueueNodesCLLR(pQList, UPDATE_CLLR_POSITION);
3009 
3010   /* Convert all nodes to static (Bypass head node) */
3011   for (uint32_t node_count = 1U; node_count < pQList->NodeNumber; node_count++)
3012   {
3013     /* Update context node register values */
3014     DMA_List_FillNode((DMA_NodeTypeDef *)currentnode_addr, &context_node);
3015 
3016     /* Update node address */
3017     MODIFY_REG(currentnode_addr, DMA_CLLR_LA, (context_node.LinkRegisters[cllr_offset] & DMA_CLLR_LA));
3018 
3019     /* Convert current node to static */
3020     DMA_List_ConvertNodeToStatic((uint32_t)&context_node, currentnode_addr, (cllr_offset + 1U));
3021   }
3022 
3023   /* Set all CLLR queue nodes to their default values */
3024   DMA_List_UpdateStaticQueueNodesCLLR(pQList, UPDATE_CLLR_VALUE);
3025 
3026   /* Set queue type */
3027   pQList->Type = QUEUE_TYPE_STATIC;
3028 
3029   /* Update the queue error code */
3030   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
3031 
3032   /* Update the queue state */
3033   pQList->State = HAL_DMA_QUEUE_STATE_READY;
3034 
3035   return HAL_OK;
3036 }
3037 
3038 /**
3039   * @brief  Link linked-list queue to a DMA channel.
3040   * @param  hdma   : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
3041   *                  specified DMA Channel.
3042   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
3043   * @retval HAL status.
3044   */
HAL_DMAEx_List_LinkQ(DMA_HandleTypeDef * const hdma,DMA_QListTypeDef * const pQList)3045 HAL_StatusTypeDef HAL_DMAEx_List_LinkQ(DMA_HandleTypeDef *const hdma,
3046                                        DMA_QListTypeDef *const pQList)
3047 {
3048   HAL_DMA_StateTypeDef state;
3049 
3050   /* Check the DMA channel handle and the queue parameters */
3051   if ((hdma == NULL) || (pQList == NULL))
3052   {
3053     return HAL_ERROR;
3054   }
3055 
3056   /* Get DMA state */
3057   state = hdma->State;
3058 
3059   /* Check DMA channel state */
3060   if ((hdma->State == HAL_DMA_STATE_BUSY) || (state == HAL_DMA_STATE_SUSPEND))
3061   {
3062     /* Update the DMA channel error code */
3063     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
3064 
3065     /* Process unlocked */
3066     __HAL_UNLOCK(hdma);
3067 
3068     return HAL_ERROR;
3069   }
3070 
3071   /* Check queue state */
3072   if (pQList->State == HAL_DMA_QUEUE_STATE_BUSY)
3073   {
3074     /* Update the queue error code */
3075     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_BUSY;
3076 
3077     return HAL_ERROR;
3078   }
3079 
3080   /* Check circularity compatibility */
3081   if (hdma->Mode == DMA_LINKEDLIST_CIRCULAR)
3082   {
3083     /* Check first circular node */
3084     if (pQList->FirstCircularNode == NULL)
3085     {
3086       /* Update the queue error code */
3087       pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
3088 
3089       return HAL_ERROR;
3090     }
3091   }
3092   else
3093   {
3094     /* Check first circular node */
3095     if (pQList->FirstCircularNode != NULL)
3096     {
3097       /* Update the queue error code */
3098       pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
3099 
3100       return HAL_ERROR;
3101     }
3102   }
3103 
3104   /* Register queue to DMA handle */
3105   hdma->LinkedListQueue = pQList;
3106 
3107   return HAL_OK;
3108 }
3109 
3110 /**
3111   * @brief  Unlink linked-list queue from a DMA channel.
3112   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
3113   *                specified DMA Channel.
3114   * @retval HAL status.
3115   */
HAL_DMAEx_List_UnLinkQ(DMA_HandleTypeDef * const hdma)3116 HAL_StatusTypeDef HAL_DMAEx_List_UnLinkQ(DMA_HandleTypeDef *const hdma)
3117 {
3118   HAL_DMA_StateTypeDef state;
3119 
3120   /* Check the DMA channel parameter */
3121   if (hdma == NULL)
3122   {
3123     return HAL_ERROR;
3124   }
3125 
3126   /* Get DMA state */
3127   state = hdma->State;
3128 
3129   /* Check DMA channel state */
3130   if ((hdma->State == HAL_DMA_STATE_BUSY) || (state == HAL_DMA_STATE_SUSPEND))
3131   {
3132     /* Update the DMA channel error code */
3133     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
3134 
3135     /* Process unlocked */
3136     __HAL_UNLOCK(hdma);
3137 
3138     return HAL_ERROR;
3139   }
3140 
3141   /* Clear queue information from DMA channel handle */
3142   hdma->LinkedListQueue = NULL;
3143 
3144   return HAL_OK;
3145 }
3146 /**
3147   * @}
3148   */
3149 
3150 /** @addtogroup DMAEx_Exported_Functions_Group4
3151   *
3152 @verbatim
3153   ======================================================================================================================
3154              ##### Data handling, repeated block and trigger configuration functions #####
3155   ======================================================================================================================
3156     [..]
3157       This section provides functions allowing to :
3158       (+) Configure DMA channel data handling.
3159       (+) Configure DMA channel repeated block.
3160       (+) Configure DMA channel trigger.
3161 
3162     [..]
3163       (+) The HAL_DMAEx_ConfigDataHandling() function allows to configure DMA channel data handling.
3164               (++) GPDMA data handling : byte-based reordering, packing/unpacking, padding/truncation, sign extension
3165                                          and left/right alignment.
3166 
3167       (+) The HAL_DMAEx_ConfigTrigger() function allows to configure DMA channel HW triggers.
3168 
3169 @endverbatim
3170   * @{
3171   */
3172 
3173 /**
3174   * @brief  Configure the DMA channel data handling according to the specified parameters in the
3175   *         DMA_DataHandlingConfTypeDef.
3176   * @param  hdma                : Pointer to a DMA_HandleTypeDef structure that contains the configuration information
3177   *                               for the specified DMA Channel.
3178   * @param  pConfigDataHandling : Pointer to a DMA_DataHandlingConfTypeDef structure that contains the data handling
3179   *                               configuration.
3180   * @retval HAL status.
3181   */
HAL_DMAEx_ConfigDataHandling(DMA_HandleTypeDef * const hdma,DMA_DataHandlingConfTypeDef const * const pConfigDataHandling)3182 HAL_StatusTypeDef HAL_DMAEx_ConfigDataHandling(DMA_HandleTypeDef *const hdma,
3183                                                DMA_DataHandlingConfTypeDef const *const pConfigDataHandling)
3184 {
3185   /* Check the DMA peripheral handle and data handling parameters */
3186   if ((hdma == NULL) || (pConfigDataHandling == NULL))
3187   {
3188     return HAL_ERROR;
3189   }
3190 
3191   /* Check the parameters */
3192   assert_param(IS_DMA_DATA_ALIGNMENT(pConfigDataHandling->DataAlignment));
3193   assert_param(IS_DMA_DATA_EXCHANGE(pConfigDataHandling->DataExchange));
3194 
3195   /* Check DMA channel state */
3196   if (hdma->State == HAL_DMA_STATE_READY)
3197   {
3198     MODIFY_REG(hdma->Instance->CTR1, (DMA_CTR1_DHX | DMA_CTR1_DBX | DMA_CTR1_SBX | DMA_CTR1_PAM),
3199                (pConfigDataHandling->DataAlignment | pConfigDataHandling->DataExchange));
3200 
3201   }
3202   else
3203   {
3204     /* Update the DMA channel error code */
3205     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
3206 
3207     /* Process unlocked */
3208     __HAL_UNLOCK(hdma);
3209 
3210     return HAL_ERROR;
3211   }
3212 
3213   return HAL_OK;
3214 }
3215 
3216 /**
3217   * @brief  Configure the DMA channel trigger according to the specified parameters in the DMA_TriggerConfTypeDef.
3218   * @param  hdma           : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for
3219   *                          the specified DMA Channel.
3220   * @param  pConfigTrigger : Pointer to a DMA_TriggerConfTypeDef structure that contains the trigger configuration.
3221   * @retval HAL status.
3222   */
HAL_DMAEx_ConfigTrigger(DMA_HandleTypeDef * const hdma,DMA_TriggerConfTypeDef const * const pConfigTrigger)3223 HAL_StatusTypeDef HAL_DMAEx_ConfigTrigger(DMA_HandleTypeDef *const hdma,
3224                                           DMA_TriggerConfTypeDef const *const pConfigTrigger)
3225 {
3226   /* Check the DMA peripheral handle and trigger parameters */
3227   if ((hdma == NULL) || (pConfigTrigger == NULL))
3228   {
3229     return HAL_ERROR;
3230   }
3231 
3232   /* Check the parameters */
3233   assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
3234   assert_param(IS_DMA_TRIGGER_POLARITY(pConfigTrigger->TriggerPolarity));
3235   assert_param(IS_DMA_TRIGGER_MODE(pConfigTrigger->TriggerMode));
3236   assert_param(IS_DMA_TRIGGER_SELECTION(pConfigTrigger->TriggerSelection));
3237 
3238   /* Check DMA channel state */
3239   if (hdma->State == HAL_DMA_STATE_READY)
3240   {
3241     MODIFY_REG(hdma->Instance->CTR2, (DMA_CTR2_TRIGPOL | DMA_CTR2_TRIGSEL | DMA_CTR2_TRIGM),
3242                (pConfigTrigger->TriggerPolarity | pConfigTrigger->TriggerMode |
3243                 (pConfigTrigger->TriggerSelection << DMA_CTR2_TRIGSEL_Pos)));
3244   }
3245   else
3246   {
3247     /* Update the DMA channel error code */
3248     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
3249 
3250     /* Process unlocked */
3251     __HAL_UNLOCK(hdma);
3252 
3253     return HAL_ERROR;
3254   }
3255 
3256   return HAL_OK;
3257 }
3258 
3259 /**
3260   * @}
3261   */
3262 
3263 /** @addtogroup DMAEx_Exported_Functions_Group5
3264   *
3265 @verbatim
3266   ======================================================================================================================
3267                          ##### Suspend and resume operation functions #####
3268   ======================================================================================================================
3269     [..]
3270       This section provides functions allowing to :
3271       (+) Suspend any ongoing DMA channel transfer.
3272       (+) Resume any suspended DMA channel transfer.
3273 
3274     [..]
3275       (+) The HAL_DMAEx_Suspend() function allows to suspend any ongoing DMA channel transfer in polling mode (Blocking
3276           mode).
3277 
3278       (+) The HAL_DMAEx_Suspend_IT() function allows to suspend any ongoing DMA channel transfer in interrupt mode
3279          (Non-blocking mode).
3280 
3281       (+) The HAL_DMAEx_Resume() function allows to resume any suspended DMA channel transfer.
3282 
3283 @endverbatim
3284   * @{
3285   */
3286 
3287 /**
3288   * @brief  Suspend any ongoing DMA channel transfer in polling mode (Blocking mode).
3289   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
3290   *                specified DMA channel.
3291   * @note   After suspending a DMA channel, a check for wait until the DMA channel is effectively suspended is added. If
3292   *         a channel is suspended while a data transfer is ongoing, the current data will be transferred and the
3293   *         channel will be effectively suspended only after the transfer of this single/burst data is finished.
3294   * @retval HAL status.
3295   */
HAL_DMAEx_Suspend(DMA_HandleTypeDef * const hdma)3296 HAL_StatusTypeDef HAL_DMAEx_Suspend(DMA_HandleTypeDef *const hdma)
3297 {
3298   /* Get tick number */
3299   uint32_t tickstart = HAL_GetTick();
3300 
3301   /* Check the DMA peripheral handle */
3302   if (hdma == NULL)
3303   {
3304     return HAL_ERROR;
3305   }
3306 
3307   /* Check DMA channel state */
3308   if (hdma->State != HAL_DMA_STATE_BUSY)
3309   {
3310     /* Update the DMA channel error code */
3311     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
3312 
3313     /* Process unlocked */
3314     __HAL_UNLOCK(hdma);
3315 
3316     return HAL_ERROR;
3317   }
3318   else
3319   {
3320     /* Suspend the channel */
3321     hdma->Instance->CCR |= DMA_CCR_SUSP;
3322 
3323     /* Check if the DMA channel is suspended */
3324     while ((hdma->Instance->CSR & DMA_CSR_SUSPF) == 0U)
3325     {
3326       /* Check for the timeout */
3327       if ((HAL_GetTick() - tickstart) > HAL_TIMEOUT_DMA_ABORT)
3328       {
3329         /* Update the DMA channel error code */
3330         hdma->ErrorCode |= HAL_DMA_ERROR_TIMEOUT;
3331 
3332         /* Update the DMA channel state */
3333         hdma->State = HAL_DMA_STATE_ERROR;
3334 
3335         /* Process Unlocked */
3336         __HAL_UNLOCK(hdma);
3337 
3338         return HAL_ERROR;
3339       }
3340     }
3341 
3342     /* Update the DMA channel state */
3343     hdma->State = HAL_DMA_STATE_SUSPEND;
3344   }
3345 
3346   return HAL_OK;
3347 }
3348 
3349 /**
3350   * @brief  Suspend any ongoing DMA channel transfer in polling mode (Non-blocking mode).
3351   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
3352   *                specified DMA Channel.
3353   * @retval HAL status.
3354   */
HAL_DMAEx_Suspend_IT(DMA_HandleTypeDef * const hdma)3355 HAL_StatusTypeDef HAL_DMAEx_Suspend_IT(DMA_HandleTypeDef *const hdma)
3356 {
3357   /* Check the DMA peripheral handle parameter */
3358   if (hdma == NULL)
3359   {
3360     return HAL_ERROR;
3361   }
3362 
3363   /* Check DMA channel state */
3364   if (hdma->State != HAL_DMA_STATE_BUSY)
3365   {
3366     /* Update the DMA channel error code */
3367     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
3368 
3369     /* Process unlocked */
3370     __HAL_UNLOCK(hdma);
3371 
3372     return HAL_ERROR;
3373   }
3374   else
3375   {
3376     /* Suspend the DMA channel and activate suspend interrupt */
3377     hdma->Instance->CCR |= (DMA_CCR_SUSP | DMA_CCR_SUSPIE);
3378   }
3379 
3380   return HAL_OK;
3381 }
3382 
3383 /**
3384   * @brief  Resume any suspended DMA channel transfer.
3385   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
3386   *                specified DMA Channel.
3387   * @retval HAL status.
3388   */
HAL_DMAEx_Resume(DMA_HandleTypeDef * const hdma)3389 HAL_StatusTypeDef HAL_DMAEx_Resume(DMA_HandleTypeDef *const hdma)
3390 {
3391   /* Check the DMA peripheral handle parameter */
3392   if (hdma == NULL)
3393   {
3394     return HAL_ERROR;
3395   }
3396 
3397   /* Check DMA channel state */
3398   if (hdma->State != HAL_DMA_STATE_SUSPEND)
3399   {
3400     /* Update the DMA channel error code */
3401     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
3402 
3403     /* Process unlocked */
3404     __HAL_UNLOCK(hdma);
3405 
3406     return HAL_ERROR;
3407   }
3408   else
3409   {
3410     /* Resume the DMA channel */
3411     hdma->Instance->CCR &= (~DMA_CCR_SUSP);
3412 
3413     /* Clear the suspend flag */
3414     hdma->Instance->CFCR |= DMA_CFCR_SUSPF;
3415 
3416     /* Update the DMA channel state */
3417     hdma->State = HAL_DMA_STATE_BUSY;
3418   }
3419 
3420   return HAL_OK;
3421 }
3422 /**
3423   * @}
3424   */
3425 
3426 /** @addtogroup DMAEx_Exported_Functions_Group6
3427   *
3428 @verbatim
3429   ======================================================================================================================
3430                                ##### Fifo status function #####
3431   ======================================================================================================================
3432     [..]
3433       This section provides function allowing to get DMA channel FIFO level.
3434 
3435     [..]
3436       (+) The HAL_DMAEx_GetFifoLevel() function allows to return the number of available write beats in the FIFO, in
3437           units of the programmed destination data.
3438               (++) This API is available only for DMA channels that supports FIFO.
3439 
3440 @endverbatim
3441   * @{
3442   */
3443 
3444 /**
3445   * @brief  Get and returns the DMA channel FIFO level.
3446   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
3447   *                specified DMA Channel.
3448   * @retval Returns the number of available beats in FIFO.
3449   */
HAL_DMAEx_GetFifoLevel(DMA_HandleTypeDef const * const hdma)3450 uint32_t HAL_DMAEx_GetFifoLevel(DMA_HandleTypeDef const *const hdma)
3451 {
3452   return ((hdma->Instance->CSR & DMA_CSR_FIFOL) >> DMA_CSR_FIFOL_Pos);
3453 }
3454 
3455 /**
3456   * @}
3457   */
3458 
3459 /**
3460   * @}
3461   */
3462 
3463 /* Private functions -------------------------------------------------------------------------------------------------*/
3464 /** @defgroup DMAEx_Private_Functions DMAEx Private Functions
3465   * @brief    DMAEx Private Functions
3466   * @{
3467   */
3468 
3469 /**
3470   * @brief  Initialize the DMA handle according to the specified parameters in the DMA_InitTypeDef.
3471   * @param  hdma : pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
3472   *                specified DMA Channel.
3473   * @retval None.
3474   */
DMA_List_Init(DMA_HandleTypeDef const * const hdma)3475 static void DMA_List_Init(DMA_HandleTypeDef const *const hdma)
3476 {
3477   uint32_t tmpreg;
3478 
3479   /* Prepare DMA Channel Control Register (CCR) value */
3480   tmpreg = hdma->InitLinkedList.Priority | hdma->InitLinkedList.LinkStepMode;
3481 
3482   /* Check DMA channel instance */
3483   if (IS_GPDMA_INSTANCE(hdma->Instance) != 0U)
3484   {
3485     tmpreg |= hdma->InitLinkedList.LinkAllocatedPort;
3486   }
3487 
3488   /* Write DMA Channel Control Register (CCR) */
3489   MODIFY_REG(hdma->Instance->CCR, DMA_CCR_PRIO | DMA_CCR_LAP | DMA_CCR_LSM, tmpreg);
3490 
3491   /* Write DMA Channel Control Register (CTR1) */
3492   WRITE_REG(hdma->Instance->CTR1, 0U);
3493 
3494   /* Write DMA Channel Control Register (CTR2) */
3495   WRITE_REG(hdma->Instance->CTR2, hdma->InitLinkedList.TransferEventMode);
3496 
3497   /* Write DMA Channel Control Register (CBR1) */
3498   WRITE_REG(hdma->Instance->CBR1, 0U);
3499 
3500   /* Write DMA Channel Control Register (CSAR) */
3501   WRITE_REG(hdma->Instance->CSAR, 0U);
3502 
3503   /* Write DMA Channel Control Register (CDAR) */
3504   WRITE_REG(hdma->Instance->CDAR, 0U);
3505 
3506   /* Write DMA Channel linked-list address register (CLLR) */
3507   WRITE_REG(hdma->Instance->CLLR, 0U);
3508 }
3509 
3510 /**
3511   * @brief  Build a DMA channel node according to the specified parameters in the DMA_NodeConfTypeDef.
3512   * @param  pNodeConfig : Pointer to a DMA_NodeConfTypeDef structure that contains the configuration information for the
3513   *                       specified DMA linked-list Node.
3514   * @param  pNode       : Pointer to a DMA_NodeTypeDef structure that contains linked-list node registers
3515   *                       configurations.
3516   * @retval None.
3517   */
DMA_List_BuildNode(DMA_NodeConfTypeDef const * const pNodeConfig,DMA_NodeTypeDef * const pNode)3518 static void DMA_List_BuildNode(DMA_NodeConfTypeDef const *const pNodeConfig,
3519                                DMA_NodeTypeDef *const pNode)
3520 {
3521   /* Update CTR1 register value ***************************************************************************************/
3522   /* Prepare DMA channel transfer register (CTR1) value */
3523   pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET] = pNodeConfig->Init.DestInc                     |
3524                                                    pNodeConfig->Init.DestDataWidth               |
3525                                                    pNodeConfig->DataHandlingConfig.DataAlignment |
3526                                                    pNodeConfig->Init.SrcInc                      |
3527                                                    pNodeConfig->Init.SrcDataWidth;
3528 
3529 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
3530   /* set source channel security attribute */
3531   if (pNodeConfig->SrcSecure == DMA_CHANNEL_SRC_SEC)
3532   {
3533     pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET] |= DMA_CTR1_SSEC;
3534   }
3535 
3536   /* set destination channel security attribute */
3537   if (pNodeConfig->DestSecure == DMA_CHANNEL_DEST_SEC)
3538   {
3539     pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET] |= DMA_CTR1_DSEC;
3540   }
3541 #endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
3542 
3543   /* Add parameters related to DMA configuration */
3544   if ((pNodeConfig->NodeType & DMA_CHANNEL_TYPE_GPDMA) == DMA_CHANNEL_TYPE_GPDMA)
3545   {
3546     /* Prepare DMA channel transfer register (CTR1) value */
3547     pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET] |=
3548       (pNodeConfig->Init.TransferAllocatedPort | pNodeConfig->DataHandlingConfig.DataExchange |
3549        (((pNodeConfig->Init.DestBurstLength - 1U) << DMA_CTR1_DBL_1_Pos) & DMA_CTR1_DBL_1)    |
3550        (((pNodeConfig->Init.SrcBurstLength - 1U) << DMA_CTR1_SBL_1_Pos) & DMA_CTR1_SBL_1));
3551   }
3552   /*********************************************************************************** CTR1 register value is updated */
3553 
3554 
3555   /* Update CTR2 register value ***************************************************************************************/
3556   /* Prepare DMA channel transfer register 2 (CTR2) value */
3557   pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET] = pNodeConfig->Init.TransferEventMode |
3558                                                    (pNodeConfig->Init.Request & (DMA_CTR2_REQSEL | DMA_CTR2_SWREQ));
3559 
3560   /* Check for memory to peripheral transfer */
3561   if ((pNodeConfig->Init.Direction) == DMA_MEMORY_TO_PERIPH)
3562   {
3563     if ((pNodeConfig->NodeType & DMA_CHANNEL_TYPE_GPDMA) == DMA_CHANNEL_TYPE_GPDMA)
3564     {
3565       pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET] |= DMA_CTR2_DREQ;
3566     }
3567   }
3568   /* Memory to memory transfer */
3569   else if ((pNodeConfig->Init.Direction) == DMA_MEMORY_TO_MEMORY)
3570   {
3571     pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET] |= DMA_CTR2_SWREQ;
3572   }
3573   else
3574   {
3575     /* Prevent MISRA-C2012-Rule-15.7 */
3576   }
3577 
3578   /* Check if trigger feature is active */
3579   if (pNodeConfig->TriggerConfig.TriggerPolarity != DMA_TRIG_POLARITY_MASKED)
3580   {
3581     /* Prepare DMA channel transfer register 2 (CTR2) value */
3582     pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET] |=
3583       pNodeConfig->TriggerConfig.TriggerMode | pNodeConfig->TriggerConfig.TriggerPolarity |
3584       ((pNodeConfig->TriggerConfig.TriggerSelection << DMA_CTR2_TRIGSEL_Pos) & DMA_CTR2_TRIGSEL);
3585   }
3586   /*********************************************************************************** CTR2 register value is updated */
3587 
3588 
3589   /* Update CBR1 register value ***************************************************************************************/
3590   /* Prepare DMA channel block register 1 (CBR1) value */
3591   pNode->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] = (pNodeConfig->DataSize & DMA_CBR1_BNDT);
3592 
3593   /*********************************************************************************** CBR1 register value is updated */
3594 
3595 
3596   /* Update CSAR register value ***************************************************************************************/
3597   pNode->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET] = pNodeConfig->SrcAddress;
3598   /*********************************************************************************** CSAR register value is updated */
3599 
3600 
3601   /* Update CDAR register value ***************************************************************************************/
3602   pNode->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = pNodeConfig->DstAddress;
3603   /*********************************************************************************** CDAR register value is updated */
3604 
3605   /* Update CLLR register value *************************************************************************************/
3606   /* Reset CLLR Register value : channel linked-list address register offset */
3607   pNode->LinkRegisters[NODE_CLLR_LINEAR_DEFAULT_OFFSET] = 0U;
3608   /********************************************************************************* CLLR register value is cleared */
3609 
3610   /* Update node information value ************************************************************************************/
3611   /* Set node information */
3612   pNode->NodeInfo = pNodeConfig->NodeType;
3613   pNode->NodeInfo |= (NODE_CLLR_LINEAR_DEFAULT_OFFSET << NODE_CLLR_IDX_POS);
3614   /******************************************************************************** Node information value is updated */
3615 }
3616 
3617 /**
3618   * @brief  Get a DMA channel node configuration.
3619   * @param  pNodeConfig : Pointer to a DMA_NodeConfTypeDef structure that contains the configuration information for the
3620   *                       specified DMA linked-list Node.
3621   * @param  pNode       : Pointer to a DMA_NodeTypeDef structure that contains linked-list node registers
3622   *                       configurations.
3623   * @retval None.
3624   */
DMA_List_GetNodeConfig(DMA_NodeConfTypeDef * const pNodeConfig,DMA_NodeTypeDef const * const pNode)3625 static void DMA_List_GetNodeConfig(DMA_NodeConfTypeDef *const pNodeConfig,
3626                                    DMA_NodeTypeDef const *const pNode)
3627 {
3628 
3629   /* Get node information *********************************************************************************************/
3630   pNodeConfig->NodeType = (pNode->NodeInfo & NODE_TYPE_MASK);
3631   /*************************************************************************************** Node type value is updated */
3632 
3633 
3634   /* Get CTR1 fields values *******************************************************************************************/
3635   pNodeConfig->Init.SrcInc                      = pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET]   & DMA_CTR1_SINC;
3636   pNodeConfig->Init.DestInc                     = pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET]   & DMA_CTR1_DINC;
3637   pNodeConfig->Init.SrcDataWidth                = pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET]   & DMA_CTR1_SDW_LOG2;
3638   pNodeConfig->Init.DestDataWidth               = pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET]   & DMA_CTR1_DDW_LOG2;
3639   pNodeConfig->Init.SrcBurstLength              = ((pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET] &
3640                                                     DMA_CTR1_SBL_1) >> DMA_CTR1_SBL_1_Pos) + 1U;
3641   pNodeConfig->Init.DestBurstLength             = ((pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET] &
3642                                                     DMA_CTR1_DBL_1) >> DMA_CTR1_DBL_1_Pos) + 1U;
3643   pNodeConfig->Init.TransferAllocatedPort       = pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET]   &
3644                                                   (DMA_CTR1_SAP | DMA_CTR1_DAP);
3645   pNodeConfig->DataHandlingConfig.DataExchange  = pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET]   &
3646                                                   (DMA_CTR1_SBX | DMA_CTR1_DBX | DMA_CTR1_DHX);
3647 
3648   pNodeConfig->DataHandlingConfig.DataAlignment = pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET]   & DMA_CTR1_PAM;
3649 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
3650   if ((pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET] & DMA_CTR1_SSEC) != 0U)
3651   {
3652     pNodeConfig->SrcSecure = DMA_CHANNEL_SRC_SEC;
3653   }
3654   else
3655   {
3656     pNodeConfig->SrcSecure = DMA_CHANNEL_SRC_NSEC;
3657   }
3658 
3659   if ((pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET] & DMA_CTR1_DSEC) != 0U)
3660   {
3661     pNodeConfig->DestSecure = DMA_CHANNEL_DEST_SEC;
3662   }
3663   else
3664   {
3665     pNodeConfig->DestSecure = DMA_CHANNEL_DEST_NSEC;
3666   }
3667 #endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
3668   /*********************************************************************************** CTR1 fields values are updated */
3669 
3670 
3671   /* Get CTR2 fields values *******************************************************************************************/
3672   if ((pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET] & DMA_CTR2_SWREQ) != 0U)
3673   {
3674     pNodeConfig->Init.Request   = DMA_REQUEST_SW;
3675     pNodeConfig->Init.Direction = DMA_MEMORY_TO_MEMORY;
3676   }
3677   else
3678   {
3679     pNodeConfig->Init.Request   = pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET] & DMA_CTR2_REQSEL;
3680 
3681     if ((pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET] & DMA_CTR2_DREQ) != 0U)
3682     {
3683       pNodeConfig->Init.Direction = DMA_MEMORY_TO_PERIPH;
3684     }
3685     else
3686     {
3687       pNodeConfig->Init.Direction = DMA_PERIPH_TO_MEMORY;
3688     }
3689   }
3690 
3691   pNodeConfig->Init.BlkHWRequest              = (pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET] & DMA_CTR2_BREQ);
3692   pNodeConfig->TriggerConfig.TriggerMode      = pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET]  & DMA_CTR2_TRIGM;
3693   pNodeConfig->TriggerConfig.TriggerPolarity  = pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET]  & DMA_CTR2_TRIGPOL;
3694   pNodeConfig->TriggerConfig.TriggerSelection = (pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET] &
3695                                                  DMA_CTR2_TRIGSEL) >> DMA_CTR2_TRIGSEL_Pos;
3696   pNodeConfig->Init.TransferEventMode         = pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET]  & DMA_CTR2_TCEM;
3697   /*********************************************************************************** CTR2 fields values are updated */
3698 
3699 
3700   /* Get CBR1 fields **************************************************************************************************/
3701   pNodeConfig->DataSize = pNode->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] & DMA_CBR1_BNDT;
3702 
3703   /*********************************************************************************** CBR1 fields values are updated */
3704 
3705 
3706   /* Get CSAR field ***************************************************************************************************/
3707   pNodeConfig->SrcAddress = pNode->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET];
3708   /************************************************************************************** CSAR field value is updated */
3709 
3710 
3711   /* Get CDAR field ***************************************************************************************************/
3712   pNodeConfig->DstAddress = pNode->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET];
3713   /************************************************************************************** CDAR field value is updated */
3714 
3715 }
3716 
3717 /**
3718   * @brief  Check nodes base addresses compatibility.
3719   * @param  pNode1 : Pointer to a DMA_NodeTypeDef structure that contains linked-list node 1 registers configurations.
3720   * @param  pNode2 : Pointer to a DMA_NodeTypeDef structure that contains linked-list node 2 registers configurations.
3721   * @param  pNode3 : Pointer to a DMA_NodeTypeDef structure that contains linked-list node 3 registers configurations.
3722   * @retval Return 0 when nodes addresses are compatible, 1 otherwise.
3723   */
DMA_List_CheckNodesBaseAddresses(DMA_NodeTypeDef const * const pNode1,DMA_NodeTypeDef const * const pNode2,DMA_NodeTypeDef const * const pNode3)3724 static uint32_t DMA_List_CheckNodesBaseAddresses(DMA_NodeTypeDef const *const pNode1,
3725                                                  DMA_NodeTypeDef const *const pNode2,
3726                                                  DMA_NodeTypeDef const *const pNode3)
3727 {
3728   uint32_t temp = (((uint32_t)pNode1 | (uint32_t)pNode2 | (uint32_t)pNode3) & DMA_CLBAR_LBA);
3729   uint32_t ref  = 0U;
3730 
3731   /* Check node 1 address */
3732   if ((uint32_t)pNode1 != 0U)
3733   {
3734     ref = (uint32_t)pNode1;
3735   }
3736   /* Check node 2 address */
3737   else if ((uint32_t)pNode2 != 0U)
3738   {
3739     ref = (uint32_t)pNode2;
3740   }
3741   /* Check node 3 address */
3742   else if ((uint32_t)pNode3 != 0U)
3743   {
3744     ref = (uint32_t)pNode3;
3745   }
3746   else
3747   {
3748     /* Prevent MISRA-C2012-Rule-15.7 */
3749   }
3750 
3751   /* Check addresses compatibility */
3752   if (temp != ((uint32_t)ref & DMA_CLBAR_LBA))
3753   {
3754     return 1U;
3755   }
3756 
3757   return 0U;
3758 }
3759 
3760 /**
3761   * @brief  Check nodes types compatibility.
3762   * @param  pNode1 : Pointer to a DMA_NodeTypeDef structure that contains linked-list node 1 registers configurations.
3763   * @param  pNode2 : Pointer to a DMA_NodeTypeDef structure that contains linked-list node 2 registers configurations.
3764   * @param  pNode3 : Pointer to a DMA_NodeTypeDef structure that contains linked-list node 3 registers configurations.
3765   * @retval Return 0 when nodes types are compatible, otherwise nodes types are not compatible.
3766   */
DMA_List_CheckNodesTypes(DMA_NodeTypeDef const * const pNode1,DMA_NodeTypeDef const * const pNode2,DMA_NodeTypeDef const * const pNode3)3767 static uint32_t DMA_List_CheckNodesTypes(DMA_NodeTypeDef const *const pNode1,
3768                                          DMA_NodeTypeDef const *const pNode2,
3769                                          DMA_NodeTypeDef const *const pNode3)
3770 {
3771   uint32_t ref = 0U;
3772 
3773   /* Check node 1 parameter */
3774   if (pNode1 != NULL)
3775   {
3776     ref = pNode1->NodeInfo & NODE_TYPE_MASK;
3777   }
3778   /* Check node 2 parameter */
3779   else if (pNode2 != NULL)
3780   {
3781     ref = pNode2->NodeInfo & NODE_TYPE_MASK;
3782   }
3783   /* Check node 3 parameter */
3784   else if (pNode3 != NULL)
3785   {
3786     ref = pNode3->NodeInfo & NODE_TYPE_MASK;
3787   }
3788   else
3789   {
3790     /* Prevent MISRA-C2012-Rule-15.7 */
3791   }
3792 
3793   /* Check node 2 parameter */
3794   if (pNode2 != NULL)
3795   {
3796     /* Check node type compatibility */
3797     if (ref != (pNode2->NodeInfo & NODE_TYPE_MASK))
3798     {
3799       return 2U;
3800     }
3801   }
3802 
3803   /* Check node 3 parameter */
3804   if (pNode3 != NULL)
3805   {
3806     /* Check node type compatibility */
3807     if (ref != (pNode3->NodeInfo & NODE_TYPE_MASK))
3808     {
3809       return 3U;
3810     }
3811   }
3812 
3813   return 0U;
3814 }
3815 
3816 /**
3817   * @brief  Check nodes types compatibility.
3818   * @param  pNode       : Pointer to a DMA_NodeTypeDef structure that contains linked-list node registers
3819   *                       configurations.
3820   * @param  cllr_mask   : Pointer to CLLR register mask value.
3821   * @param  cllr_offset : Pointer to CLLR register offset value.
3822   * @retval None.
3823   */
DMA_List_GetCLLRNodeInfo(DMA_NodeTypeDef const * const pNode,uint32_t * const cllr_mask,uint32_t * const cllr_offset)3824 static void DMA_List_GetCLLRNodeInfo(DMA_NodeTypeDef const *const pNode,
3825                                      uint32_t *const cllr_mask,
3826                                      uint32_t *const cllr_offset)
3827 {
3828   /* Prevent unused argument(s) compilation warning */
3829   UNUSED(pNode);
3830 
3831   /* Update CLLR register mask value */
3832   if (cllr_mask != NULL)
3833   {
3834     *cllr_mask = DMA_CLLR_UT1 | DMA_CLLR_UT2 | DMA_CLLR_UB1 | DMA_CLLR_USA | DMA_CLLR_UDA | DMA_CLLR_ULL;
3835   }
3836 
3837   /* Update CLLR register offset */
3838   if (cllr_offset != NULL)
3839   {
3840     *cllr_offset = NODE_CLLR_LINEAR_DEFAULT_OFFSET;
3841   }
3842 }
3843 
3844 /**
3845   * @brief  Find node in queue.
3846   * @param  pQList   : Pointer to a DMA_QListTypeDef structure that contains queue information.
3847   * @param  pNode    : Pointer to a DMA_NodeTypeDef structure that contains linked-list node registers configurations.
3848   * @param  NodeInfo : Pointer to a DMA_NodeInQInfoTypeDef structure that contains node linked to queue information.
3849   * @retval Return 0 when node is found in selected queue, otherwise node is not found.
3850   */
DMA_List_FindNode(DMA_QListTypeDef const * const pQList,DMA_NodeTypeDef const * const pNode,DMA_NodeInQInfoTypeDef * const NodeInfo)3851 static uint32_t DMA_List_FindNode(DMA_QListTypeDef const *const pQList,
3852                                   DMA_NodeTypeDef const *const pNode,
3853                                   DMA_NodeInQInfoTypeDef *const NodeInfo)
3854 {
3855   uint32_t node_idx = 0U;
3856   uint32_t currentnode_address  = 0U;
3857   uint32_t previousnode_address  = 0U;
3858   uint32_t cllr_offset = NodeInfo->cllr_offset;
3859 
3860   /* Find last node in queue */
3861   if (pNode ==  NULL)
3862   {
3863     /* Check that previous node is linked to the selected queue */
3864     while (node_idx < pQList->NodeNumber)
3865     {
3866       /* Get head node address */
3867       if (node_idx == 0U)
3868       {
3869         currentnode_address = (uint32_t)pQList->Head & DMA_CLLR_LA;
3870       }
3871       /* Calculate nodes addresses */
3872       else
3873       {
3874         previousnode_address = currentnode_address;
3875         currentnode_address =
3876           ((DMA_NodeTypeDef *)(currentnode_address +
3877                                ((uint32_t)pQList->Head & DMA_CLBAR_LBA)))->LinkRegisters[cllr_offset] & DMA_CLLR_LA;
3878       }
3879 
3880       /* Increment node index */
3881       node_idx++;
3882     }
3883   }
3884   /* Find selected node node in queue */
3885   else
3886   {
3887     /* Check that previous node is linked to the selected queue */
3888     while ((node_idx < pQList->NodeNumber) && (currentnode_address != ((uint32_t)pNode & DMA_CLLR_LA)))
3889     {
3890       /* Get head node address */
3891       if (node_idx == 0U)
3892       {
3893         currentnode_address = (uint32_t)pQList->Head & DMA_CLLR_LA;
3894       }
3895       /* Calculate nodes addresses */
3896       else
3897       {
3898         previousnode_address = currentnode_address;
3899         currentnode_address =
3900           ((DMA_NodeTypeDef *)(currentnode_address +
3901                                ((uint32_t)pQList->Head & DMA_CLBAR_LBA)))->LinkRegisters[cllr_offset] & DMA_CLLR_LA;
3902       }
3903 
3904       /* Increment node index */
3905       node_idx++;
3906     }
3907   }
3908 
3909   /* Check stored address */
3910   if (pNode != NULL)
3911   {
3912     if (currentnode_address != ((uint32_t)pNode & DMA_CLLR_LA))
3913     {
3914       return 1U;
3915     }
3916   }
3917 
3918   /* Update current node position */
3919   NodeInfo->currentnode_pos = node_idx;
3920 
3921   /* Update previous node address */
3922   NodeInfo->previousnode_addr = previousnode_address | ((uint32_t)pQList->Head & DMA_CLBAR_LBA);
3923 
3924   /* Update current node address */
3925   NodeInfo->currentnode_addr = currentnode_address | ((uint32_t)pQList->Head & DMA_CLBAR_LBA);
3926 
3927   /* Update next node address */
3928   if (((DMA_NodeTypeDef *)NodeInfo->currentnode_addr)->LinkRegisters[cllr_offset] != 0U)
3929   {
3930     NodeInfo->nextnode_addr = (((DMA_NodeTypeDef *)NodeInfo->currentnode_addr)->LinkRegisters[cllr_offset] &
3931                                DMA_CLLR_LA) | ((uint32_t)pQList->Head & DMA_CLBAR_LBA);
3932   }
3933 
3934   return 0U;
3935 }
3936 
3937 /**
3938   * @brief  Reset queue nodes.
3939   * @param  pQList   : Pointer to a DMA_QListTypeDef structure that contains queue information.
3940   * @param  NodeInfo : Pointer to a DMA_NodeInQInfoTypeDef structure that contains node linked to queue information.
3941   * @retval None.
3942   */
DMA_List_ResetQueueNodes(DMA_QListTypeDef const * const pQList,DMA_NodeInQInfoTypeDef const * const NodeInfo)3943 static void DMA_List_ResetQueueNodes(DMA_QListTypeDef const *const pQList,
3944                                      DMA_NodeInQInfoTypeDef const *const NodeInfo)
3945 {
3946   uint32_t node_idx = 0U;
3947   uint32_t currentnode_address  = 0U;
3948   uint32_t previousnode_address;
3949   uint32_t cllr_offset = NodeInfo->cllr_offset;
3950 
3951   /* Check that previous node is linked to the selected queue */
3952   while (node_idx < pQList->NodeNumber)
3953   {
3954     /* Get head node address */
3955     if (node_idx == 0U)
3956     {
3957       previousnode_address = (uint32_t)pQList->Head & DMA_CLLR_LA;
3958       currentnode_address  = (pQList->Head->LinkRegisters[cllr_offset] & DMA_CLLR_LA);
3959     }
3960     /* Calculate nodes addresses */
3961     else
3962     {
3963       previousnode_address = currentnode_address;
3964       currentnode_address =
3965         ((DMA_NodeTypeDef *)(currentnode_address +
3966                              ((uint32_t)pQList->Head & DMA_CLBAR_LBA)))->LinkRegisters[cllr_offset] & DMA_CLLR_LA;
3967     }
3968 
3969     /* Reset node */
3970     ((DMA_NodeTypeDef *)(previousnode_address +
3971                          ((uint32_t)pQList->Head & DMA_CLBAR_LBA)))->LinkRegisters[cllr_offset] = 0U;
3972 
3973     /* Increment node index */
3974     node_idx++;
3975   }
3976 }
3977 
3978 /**
3979   * @brief  Fill source node registers values by destination nodes registers values.
3980   * @param  pSrcNode  : Pointer to a DMA_NodeTypeDef structure that contains linked-list source node registers
3981   *                     configurations.
3982   * @param  pDestNode : Pointer to a DMA_NodeTypeDef structure that contains linked-list destination node registers
3983   *                     configurations.
3984   * @retval None.
3985   */
DMA_List_FillNode(DMA_NodeTypeDef const * const pSrcNode,DMA_NodeTypeDef * const pDestNode)3986 static void DMA_List_FillNode(DMA_NodeTypeDef const *const pSrcNode,
3987                               DMA_NodeTypeDef *const pDestNode)
3988 {
3989   /* Repeat for all register nodes */
3990   for (uint32_t reg_idx = 0U; reg_idx < NODE_MAXIMUM_SIZE; reg_idx++)
3991   {
3992     pDestNode->LinkRegisters[reg_idx] = pSrcNode->LinkRegisters[reg_idx];
3993   }
3994 
3995   /* Fill node information */
3996   pDestNode->NodeInfo = pSrcNode->NodeInfo;
3997 }
3998 
3999 /**
4000   * @brief  Convert node to dynamic.
4001   * @param  ContextNodeAddr : The context node address.
4002   * @param  CurrentNodeAddr : The current node address to be converted.
4003   * @param  RegisterNumber  : The register number to be converted.
4004   * @retval None.
4005   */
DMA_List_ConvertNodeToDynamic(uint32_t ContextNodeAddr,uint32_t CurrentNodeAddr,uint32_t RegisterNumber)4006 static void DMA_List_ConvertNodeToDynamic(uint32_t ContextNodeAddr,
4007                                           uint32_t CurrentNodeAddr,
4008                                           uint32_t RegisterNumber)
4009 {
4010   uint32_t currentnode_reg_counter = 0U;
4011   uint32_t contextnode_reg_counter = 0U;
4012   uint32_t cllr_idx = RegisterNumber - 1U;
4013   DMA_NodeTypeDef *context_node = (DMA_NodeTypeDef *)ContextNodeAddr;
4014   DMA_NodeTypeDef *current_node = (DMA_NodeTypeDef *)CurrentNodeAddr;
4015   uint32_t update_link[NODE_MAXIMUM_SIZE] = {DMA_CLLR_UT1, DMA_CLLR_UT2, DMA_CLLR_UB1, DMA_CLLR_USA,
4016                                              DMA_CLLR_UDA, DMA_CLLR_ULL
4017                                             };
4018 
4019   /* Update ULL position according to register number */
4020   update_link[cllr_idx] = update_link[NODE_MAXIMUM_SIZE - 1U];
4021 
4022   /* Repeat for all node registers */
4023   while (contextnode_reg_counter != RegisterNumber)
4024   {
4025     /* Check if register values are equal (exception for CSAR, CDAR and CLLR registers) */
4026     if ((context_node->LinkRegisters[contextnode_reg_counter]  ==
4027          current_node->LinkRegisters[currentnode_reg_counter]) &&
4028         (contextnode_reg_counter != NODE_CSAR_DEFAULT_OFFSET)  &&
4029         (contextnode_reg_counter != NODE_CDAR_DEFAULT_OFFSET)  &&
4030         (contextnode_reg_counter != (RegisterNumber - 1U)))
4031     {
4032       /* Format the node according to unused registers */
4033       DMA_List_FormatNode(current_node, currentnode_reg_counter, RegisterNumber, NODE_DYNAMIC_FORMAT);
4034 
4035       /* Update CLLR index */
4036       cllr_idx --;
4037 
4038       /* Update CLLR fields */
4039       current_node->LinkRegisters[cllr_idx] &= ~update_link[contextnode_reg_counter];
4040     }
4041     else
4042     {
4043       /* Update context node register fields with new values */
4044       context_node->LinkRegisters[contextnode_reg_counter] = current_node->LinkRegisters[currentnode_reg_counter];
4045 
4046       /* Update CLLR fields */
4047       current_node->LinkRegisters[cllr_idx] |= update_link[contextnode_reg_counter];
4048 
4049       /* Increment current node number register counter */
4050       currentnode_reg_counter++;
4051     }
4052 
4053     /* Increment context node number register counter */
4054     contextnode_reg_counter++;
4055   }
4056 
4057   /* Update node information */
4058   MODIFY_REG(current_node->NodeInfo, NODE_CLLR_IDX, ((currentnode_reg_counter - 1U) << NODE_CLLR_IDX_POS));
4059 
4060   /* Clear unused node fields */
4061   DMA_List_ClearUnusedFields(current_node, currentnode_reg_counter);
4062 }
4063 
4064 /**
4065   * @brief  Convert node to static.
4066   * @param  ContextNodeAddr : The context node address.
4067   * @param  CurrentNodeAddr : The current node address to be converted.
4068   * @param  RegisterNumber  : The register number to be converted.
4069   * @retval None.
4070   */
DMA_List_ConvertNodeToStatic(uint32_t ContextNodeAddr,uint32_t CurrentNodeAddr,uint32_t RegisterNumber)4071 static void DMA_List_ConvertNodeToStatic(uint32_t ContextNodeAddr,
4072                                          uint32_t CurrentNodeAddr,
4073                                          uint32_t RegisterNumber)
4074 {
4075   uint32_t contextnode_reg_counter = 0U;
4076   uint32_t cllr_idx;
4077   uint32_t cllr_mask;
4078   const DMA_NodeTypeDef *context_node = (DMA_NodeTypeDef *)ContextNodeAddr;
4079   DMA_NodeTypeDef *current_node = (DMA_NodeTypeDef *)CurrentNodeAddr;
4080   uint32_t update_link[NODE_MAXIMUM_SIZE] = {DMA_CLLR_UT1, DMA_CLLR_UT2, DMA_CLLR_UB1, DMA_CLLR_USA,
4081                                              DMA_CLLR_UDA, DMA_CLLR_ULL
4082                                             };
4083 
4084   /* Update ULL position according to register number */
4085   update_link[RegisterNumber - 1U] = update_link[NODE_MAXIMUM_SIZE - 1U];
4086 
4087   /* Get context node CLLR information */
4088   cllr_idx  = (context_node->NodeInfo & NODE_CLLR_IDX) >> NODE_CLLR_IDX_POS;
4089   cllr_mask = context_node->LinkRegisters[cllr_idx];
4090 
4091   /* Repeat for all node registers */
4092   while (contextnode_reg_counter != RegisterNumber)
4093   {
4094     /* Check if node field is dynamic */
4095     if ((cllr_mask & update_link[contextnode_reg_counter]) == 0U)
4096     {
4097       /* Format the node according to unused registers */
4098       DMA_List_FormatNode(current_node, contextnode_reg_counter, RegisterNumber, NODE_STATIC_FORMAT);
4099 
4100       /* Update node field */
4101       current_node->LinkRegisters[contextnode_reg_counter] = context_node->LinkRegisters[contextnode_reg_counter];
4102     }
4103 
4104     /* Increment context node number register counter */
4105     contextnode_reg_counter++;
4106   }
4107 
4108   /* Update node information */
4109   MODIFY_REG(current_node->NodeInfo, NODE_CLLR_IDX, ((RegisterNumber - 1U) << NODE_CLLR_IDX_POS));
4110 }
4111 
4112 /**
4113   * @brief  Format the node according to unused registers.
4114   * @param  pNode           : Pointer to a DMA_NodeTypeDef structure that contains linked-list node registers
4115   *                           configurations.
4116   * @param  RegisterIdx     : The first register index to be formatted.
4117   * @param  RegisterNumber  : The number of node registers.
4118   * @param  Format          : The format type.
4119   * @retval None.
4120   */
DMA_List_FormatNode(DMA_NodeTypeDef * const pNode,uint32_t RegisterIdx,uint32_t RegisterNumber,uint32_t Format)4121 static void DMA_List_FormatNode(DMA_NodeTypeDef *const pNode,
4122                                 uint32_t RegisterIdx,
4123                                 uint32_t RegisterNumber,
4124                                 uint32_t Format)
4125 {
4126   if (Format == NODE_DYNAMIC_FORMAT)
4127   {
4128     /* Repeat for all registers to be formatted */
4129     for (uint32_t reg_idx = RegisterIdx; reg_idx < (RegisterNumber - 1U); reg_idx++)
4130     {
4131       pNode->LinkRegisters[reg_idx] = pNode->LinkRegisters[reg_idx + 1U];
4132     }
4133   }
4134   else
4135   {
4136     /* Repeat for all registers to be formatted */
4137     for (uint32_t reg_idx = (RegisterNumber - 2U); reg_idx > RegisterIdx; reg_idx--)
4138     {
4139       pNode->LinkRegisters[reg_idx] = pNode->LinkRegisters[reg_idx - 1U];
4140     }
4141   }
4142 }
4143 
4144 /**
4145   * @brief  Clear unused register fields.
4146   * @param  pNode            : Pointer to a DMA_NodeTypeDef structure that contains linked-list node registers
4147   *                            configurations.
4148   * @param  FirstUnusedField : The first unused field to be cleared.
4149   * @retval None.
4150   */
DMA_List_ClearUnusedFields(DMA_NodeTypeDef * const pNode,uint32_t FirstUnusedField)4151 static void DMA_List_ClearUnusedFields(DMA_NodeTypeDef *const pNode,
4152                                        uint32_t FirstUnusedField)
4153 {
4154   /* Repeat for all unused fields */
4155   for (uint32_t reg_idx = FirstUnusedField; reg_idx < NODE_MAXIMUM_SIZE; reg_idx++)
4156   {
4157     pNode->LinkRegisters[reg_idx] = 0U;
4158   }
4159 }
4160 
4161 /**
4162   * @brief  Update CLLR for all dynamic queue nodes.
4163   * @param  pQList :              Pointer to a DMA_QListTypeDef structure that contains queue information.
4164   * @param  LastNode_IsCircular : The first circular node is the last queue node or not.
4165   * @retval None.
4166   */
DMA_List_UpdateDynamicQueueNodesCLLR(DMA_QListTypeDef const * const pQList,uint32_t LastNode_IsCircular)4167 static void DMA_List_UpdateDynamicQueueNodesCLLR(DMA_QListTypeDef const *const pQList,
4168                                                  uint32_t LastNode_IsCircular)
4169 {
4170   uint32_t previous_cllr_offset;
4171   uint32_t current_cllr_offset = 0U;
4172   uint32_t previousnode_addr;
4173   uint32_t currentnode_addr = (uint32_t)pQList->Head;
4174   uint32_t cllr_mask;
4175   uint32_t node_idx = 0U;
4176 
4177   /*  Repeat for all register nodes */
4178   while (node_idx < pQList->NodeNumber)
4179   {
4180     /* Get head node address */
4181     if (node_idx == 0U)
4182     {
4183       /* Get current node information */
4184       current_cllr_offset = (((DMA_NodeTypeDef *)currentnode_addr)->NodeInfo & NODE_CLLR_IDX) >> NODE_CLLR_IDX_POS;
4185     }
4186     /* Calculate nodes addresses */
4187     else
4188     {
4189       /* Get previous node information */
4190       previousnode_addr = currentnode_addr;
4191       previous_cllr_offset = current_cllr_offset;
4192 
4193       /* Get current node information */
4194       currentnode_addr = (((DMA_NodeTypeDef *)(previousnode_addr))->LinkRegisters[previous_cllr_offset] & DMA_CLLR_LA) +
4195                          ((uint32_t)pQList->Head & DMA_CLBAR_LBA);
4196       current_cllr_offset = (((DMA_NodeTypeDef *)currentnode_addr)->NodeInfo & NODE_CLLR_IDX) >> NODE_CLLR_IDX_POS;
4197 
4198       /* Calculate CLLR register value to be updated */
4199       cllr_mask = (((DMA_NodeTypeDef *)currentnode_addr)->LinkRegisters[current_cllr_offset] & ~DMA_CLLR_LA) |
4200                   (((DMA_NodeTypeDef *)(previousnode_addr))->LinkRegisters[previous_cllr_offset] & DMA_CLLR_LA);
4201 
4202       /* Set new CLLR value to previous node */
4203       ((DMA_NodeTypeDef *)(previousnode_addr))->LinkRegisters[previous_cllr_offset] = cllr_mask;
4204     }
4205 
4206     /* Increment node index */
4207     node_idx++;
4208   }
4209 
4210   /* Check queue circularity */
4211   if (pQList->FirstCircularNode != 0U)
4212   {
4213     /* First circular queue is not last queue node */
4214     if (LastNode_IsCircular == 0U)
4215     {
4216       /* Get CLLR node information */
4217       DMA_List_GetCLLRNodeInfo(((DMA_NodeTypeDef *)currentnode_addr), &cllr_mask, NULL);
4218 
4219       /* Update CLLR register for last circular node */
4220       ((DMA_NodeTypeDef *)currentnode_addr)->LinkRegisters[current_cllr_offset] =
4221         ((uint32_t)pQList->Head & DMA_CLLR_LA) | cllr_mask;
4222     }
4223     /* First circular queue is last queue node */
4224     else
4225     {
4226       /* Disable CLLR updating */
4227       ((DMA_NodeTypeDef *)currentnode_addr)->LinkRegisters[current_cllr_offset] &= ~DMA_CLLR_ULL;
4228     }
4229   }
4230   else
4231   {
4232     /* Clear CLLR register for last node */
4233     ((DMA_NodeTypeDef *)currentnode_addr)->LinkRegisters[current_cllr_offset] = 0U;
4234   }
4235 }
4236 
4237 /**
4238   * @brief  Update CLLR for all static queue nodes.
4239   * @param  pQList    : Pointer to a DMA_QListTypeDef structure that contains queue information.
4240   * @param  operation : The operation type.
4241   * @retval None.
4242   */
DMA_List_UpdateStaticQueueNodesCLLR(DMA_QListTypeDef const * const pQList,uint32_t operation)4243 static void DMA_List_UpdateStaticQueueNodesCLLR(DMA_QListTypeDef const *const pQList,
4244                                                 uint32_t operation)
4245 {
4246   uint32_t currentnode_addr = (uint32_t)pQList->Head;
4247   uint32_t current_cllr_offset = ((uint32_t)pQList->Head->NodeInfo & NODE_CLLR_IDX) >> NODE_CLLR_IDX_POS;
4248   uint32_t cllr_default_offset;
4249   uint32_t cllr_default_mask;
4250   uint32_t cllr_mask;
4251   uint32_t node_idx = 0U;
4252 
4253   /* Get CLLR node information */
4254   DMA_List_GetCLLRNodeInfo(pQList->Head, &cllr_default_mask, &cllr_default_offset);
4255 
4256   /*  Repeat for all register nodes (Bypass last queue node) */
4257   while (node_idx < pQList->NodeNumber)
4258   {
4259     if (operation == UPDATE_CLLR_POSITION)
4260     {
4261       /* Get CLLR value */
4262       cllr_mask = ((DMA_NodeTypeDef *)currentnode_addr)->LinkRegisters[current_cllr_offset];
4263     }
4264     else
4265     {
4266       /* Calculate CLLR value */
4267       cllr_mask = (((DMA_NodeTypeDef *)currentnode_addr)->LinkRegisters[current_cllr_offset] & DMA_CLLR_LA) |
4268                   cllr_default_mask;
4269     }
4270 
4271     /* Set new CLLR value to default position */
4272     if ((node_idx == (pQList->NodeNumber - 1U)) && (pQList->FirstCircularNode == NULL))
4273     {
4274       ((DMA_NodeTypeDef *)(currentnode_addr))->LinkRegisters[cllr_default_offset] = 0U;
4275     }
4276     else
4277     {
4278       ((DMA_NodeTypeDef *)(currentnode_addr))->LinkRegisters[cllr_default_offset] = cllr_mask;
4279     }
4280 
4281     /* Update current node address with next node address */
4282     currentnode_addr = (currentnode_addr & DMA_CLBAR_LBA) | (cllr_mask & DMA_CLLR_LA);
4283 
4284     /* Update current CLLR offset with next CLLR offset */
4285     current_cllr_offset = (((DMA_NodeTypeDef *)currentnode_addr)->NodeInfo & NODE_CLLR_IDX) >> NODE_CLLR_IDX_POS;
4286 
4287     /* Increment node index */
4288     node_idx++;
4289   }
4290 }
4291 
4292 /**
4293   * @brief  Clean linked-list queue variable.
4294   * @param  pQList    : Pointer to a DMA_QListTypeDef structure that contains queue information.
4295   * @retval None.
4296   */
DMA_List_CleanQueue(DMA_QListTypeDef * const pQList)4297 static void DMA_List_CleanQueue(DMA_QListTypeDef *const pQList)
4298 {
4299   /* Clear head node */
4300   pQList->Head = NULL;
4301 
4302   /* Clear first circular queue node */
4303   pQList->FirstCircularNode = NULL;
4304 
4305   /* Reset node number */
4306   pQList->NodeNumber = 0U;
4307 
4308   /* Reset queue state */
4309   pQList->State = HAL_DMA_QUEUE_STATE_RESET;
4310 
4311   /* Reset queue error code */
4312   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
4313 
4314   /* Reset queue type */
4315   pQList->Type = QUEUE_TYPE_STATIC;
4316 }
4317 /**
4318   * @}
4319   */
4320 
4321 #endif /* HAL_DMA_MODULE_ENABLED */
4322 /**
4323   * @}
4324   */
4325 
4326 /**
4327   * @}
4328   */
4329