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 /* defined (DMA_PRIVCFGR_PRIV0) */
640 
641   /* Get tick number */
642   uint32_t tickstart = HAL_GetTick();
643 
644   /* Check the DMA peripheral handle parameter */
645   if (hdma == NULL)
646   {
647     return HAL_ERROR;
648   }
649 
650   /* Check the parameters */
651   assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
652 
653 #if defined (DMA_PRIVCFGR_PRIV0)
654   /* Get DMA instance */
655   p_dma_instance = GET_DMA_INSTANCE(hdma);
656 #endif /* defined (DMA_PRIVCFGR_PRIV0) */
657 
658   /* Disable the selected DMA Channel */
659   __HAL_DMA_DISABLE(hdma);
660 
661   /* Check if the DMA channel is effectively disabled */
662   while ((hdma->Instance->CCR & DMA_CCR_EN) != 0U)
663   {
664     /* Check for the Timeout */
665     if ((HAL_GetTick() - tickstart) > HAL_TIMEOUT_DMA_ABORT)
666     {
667       /* Update error code */
668       hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
669 
670       /* Change the DMA state */
671       hdma->State = HAL_DMA_STATE_ERROR;
672 
673       return HAL_ERROR;
674     }
675   }
676 
677   /* Reset DMA Channel registers */
678   hdma->Instance->CCR   = 0U;
679   hdma->Instance->CLBAR = 0U;
680   hdma->Instance->CTR1  = 0U;
681   hdma->Instance->CTR2  = 0U;
682   hdma->Instance->CBR1  = 0U;
683   hdma->Instance->CSAR  = 0U;
684   hdma->Instance->CDAR  = 0U;
685   hdma->Instance->CLLR  = 0U;
686 
687 #if defined (DMA_PRIVCFGR_PRIV0)
688   /* Clear privilege attribute */
689   CLEAR_BIT(p_dma_instance->PRIVCFGR, (1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU)));
690 #endif /* defined (DMA_PRIVCFGR_PRIV0) */
691 
692 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
693   /* Clear secure attribute */
694   CLEAR_BIT(p_dma_instance->SECCFGR, (1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU)));
695 #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
696 
697   /* Clear all flags */
698   __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC | DMA_FLAG_HT | DMA_FLAG_DTE | DMA_FLAG_ULE | DMA_FLAG_USE | DMA_FLAG_SUSP |
699                               DMA_FLAG_TO));
700 
701   /* Clean all callbacks */
702   hdma->XferCpltCallback     = NULL;
703   hdma->XferHalfCpltCallback = NULL;
704   hdma->XferErrorCallback    = NULL;
705   hdma->XferAbortCallback    = NULL;
706   hdma->XferSuspendCallback  = NULL;
707 
708   /* Check the linked-list queue */
709   if (hdma->LinkedListQueue != NULL)
710   {
711     /* Update the queue state and error code */
712     hdma->LinkedListQueue->State     = HAL_DMA_QUEUE_STATE_READY;
713     hdma->LinkedListQueue->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
714 
715     /* Clean DMA queue */
716     hdma->LinkedListQueue = NULL;
717   }
718 
719   /* Clean DMA parent */
720   if (hdma->Parent != NULL)
721   {
722     hdma->Parent = NULL;
723   }
724 
725   /* Update DMA channel operation mode */
726   hdma->Mode = DMA_NORMAL;
727 
728   /* Update the DMA channel error code */
729   hdma->ErrorCode = HAL_DMA_ERROR_NONE;
730 
731   /* Update the DMA channel state */
732   hdma->State = HAL_DMA_STATE_RESET;
733 
734   /* Release Lock */
735   __HAL_UNLOCK(hdma);
736 
737   return HAL_OK;
738 }
739 /**
740   * @}
741   */
742 
743 /** @addtogroup DMAEx_Exported_Functions_Group2
744   *
745 @verbatim
746   ======================================================================================================================
747                          ##### Linked-List IO Operation Functions #####
748   ======================================================================================================================
749     [..]
750       This section provides functions allowing to :
751       (+) Configure to start DMA transfer in linked-list mode.
752 
753     [..]
754       (+) The HAL_DMAEx_List_Start() function allows to start the DMA channel transfer in linked-list mode (Blocking
755           mode).
756       (+) The HAL_DMAEx_List_Start_IT() function allows to start the DMA channel transfer in linked-list mode
757           (Non-blocking mode).
758               (++) It is mandatory to register a linked-list queue to be executed by a DMA channel before starting
759                    transfer otherwise a HAL_ERROR will be returned.
760 
761 @endverbatim
762   * @{
763   */
764 
765 /**
766   * @brief  Start the DMA channel transfer in linked-list mode (Blocking mode).
767   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
768   *                specified DMA Channel.
769   * @retval HAL status.
770   */
HAL_DMAEx_List_Start(DMA_HandleTypeDef * const hdma)771 HAL_StatusTypeDef HAL_DMAEx_List_Start(DMA_HandleTypeDef *const hdma)
772 {
773   HAL_DMA_StateTypeDef dma_state;
774   uint32_t ccr_value;
775   uint32_t cllr_mask;
776 
777   /* Check the DMA peripheral handle and the linked-list queue parameters */
778   if ((hdma == NULL) || (hdma->LinkedListQueue == NULL))
779   {
780     return HAL_ERROR;
781   }
782 
783   /* Check DMA channel state */
784   dma_state = hdma->State;
785   ccr_value = hdma->Instance->CCR & DMA_CCR_LSM;
786   if ((dma_state == HAL_DMA_STATE_READY) || ((dma_state == HAL_DMA_STATE_BUSY) && (ccr_value != 0U)))
787   {
788     /* Check DMA channel state is ready */
789     if (hdma->State == HAL_DMA_STATE_READY)
790     {
791       /* Process locked */
792       __HAL_LOCK(hdma);
793 
794       /* Update the DMA channel and the queue states */
795       hdma->State                  = HAL_DMA_STATE_BUSY;
796       hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_BUSY;
797 
798       /* Update the DMA channel and the queue error codes */
799       hdma->ErrorCode                  = HAL_DMA_ERROR_NONE;
800       hdma->LinkedListQueue->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
801 
802       /* Get CLLR register mask and offset */
803       DMA_List_GetCLLRNodeInfo(hdma->LinkedListQueue->Head, &cllr_mask, NULL);
804 
805       /* Update DMA registers for linked-list transfer */
806       hdma->Instance->CLBAR = ((uint32_t)hdma->LinkedListQueue->Head & DMA_CLBAR_LBA);
807       hdma->Instance->CLLR  = ((uint32_t)hdma->LinkedListQueue->Head & DMA_CLLR_LA) | cllr_mask;
808     }
809 
810     /* Enable DMA channel */
811     __HAL_DMA_ENABLE(hdma);
812   }
813   else
814   {
815     /* Update the DMA channel error code */
816     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
817 
818     /* Process unlocked */
819     __HAL_UNLOCK(hdma);
820 
821     return HAL_ERROR;
822   }
823 
824   return HAL_OK;
825 }
826 
827 /**
828   * @brief  Starts the DMA channel transfer in linked-list mode with interrupts enabled (Non-blocking mode).
829   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
830   *                specified DMA Channel.
831   * @retval HAL status.
832   */
HAL_DMAEx_List_Start_IT(DMA_HandleTypeDef * const hdma)833 HAL_StatusTypeDef HAL_DMAEx_List_Start_IT(DMA_HandleTypeDef *const hdma)
834 {
835   HAL_DMA_StateTypeDef dma_state;
836   uint32_t ccr_value;
837   uint32_t cllr_mask;
838 
839   /* Check the DMA peripheral handle and the linked-list queue parameters */
840   if ((hdma == NULL) || (hdma->LinkedListQueue == NULL))
841   {
842     return HAL_ERROR;
843   }
844 
845   /* Check DMA channel state */
846   dma_state = hdma->State;
847   ccr_value = hdma->Instance->CCR & DMA_CCR_LSM;
848   if ((dma_state == HAL_DMA_STATE_READY) || ((dma_state == HAL_DMA_STATE_BUSY) && (ccr_value != 0U)))
849   {
850     /* Check DMA channel state is ready */
851     if (hdma->State == HAL_DMA_STATE_READY)
852     {
853       /* Process locked */
854       __HAL_LOCK(hdma);
855 
856       /* Update the DMA channel and the queue states */
857       hdma->State                  = HAL_DMA_STATE_BUSY;
858       hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_BUSY;
859 
860       /* Update the DMA channel and the queue error codes */
861       hdma->ErrorCode                  = HAL_DMA_ERROR_NONE;
862       hdma->LinkedListQueue->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
863 
864       /* Enable common interrupts: Transfer Complete and Transfer Errors ITs */
865       __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_DTE | DMA_IT_ULE | DMA_IT_USE | DMA_IT_TO));
866 
867       /* Check half transfer complete callback */
868       if (hdma->XferHalfCpltCallback != NULL)
869       {
870         /* If half transfer complete callback is set, enable the corresponding IT */
871         __HAL_DMA_ENABLE_IT(hdma, DMA_IT_HT);
872       }
873 
874       /* Check suspend callback */
875       if (hdma->XferSuspendCallback != NULL)
876       {
877         /* If transfer suspend callback is set, enable the corresponding IT */
878         __HAL_DMA_ENABLE_IT(hdma, DMA_IT_SUSP);
879       }
880 
881       /* Get CLLR register mask and offset */
882       DMA_List_GetCLLRNodeInfo(hdma->LinkedListQueue->Head, &cllr_mask, NULL);
883 
884       /* Update DMA registers for linked-list transfer */
885       hdma->Instance->CLBAR = ((uint32_t)hdma->LinkedListQueue->Head & DMA_CLBAR_LBA);
886       hdma->Instance->CLLR  = ((uint32_t)hdma->LinkedListQueue->Head & DMA_CLLR_LA) | cllr_mask;
887     }
888 
889     /* Enable DMA channel */
890     __HAL_DMA_ENABLE(hdma);
891   }
892   else
893   {
894     /* Change the error code */
895     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
896 
897     /* Process unlocked */
898     __HAL_UNLOCK(hdma);
899 
900     return HAL_ERROR;
901   }
902 
903   return HAL_OK;
904 }
905 /**
906   * @}
907   */
908 
909 /** @addtogroup DMAEx_Exported_Functions_Group3
910   *
911 @verbatim
912   ======================================================================================================================
913                          ##### Linked-List Management Functions #####
914   ======================================================================================================================
915     [..]
916       This section provides functions allowing to :
917       (+) Build linked-list node.
918       (+) Get linked-list node configuration.
919       (+) Insert node to linked-list queue in any queue position.
920       (+) Remove any node from linked-list queue.
921       (+) Replace any node from linked-list queue.
922       (+) Reset linked-list queue.
923       (+) Insert linked-list queue in any queue position.
924       (+) Set circular mode configuration to linked-list queue.
925       (+) Clear circular mode configuration from linked-list queue.
926       (+) Convert static linked-list queue to dynamic format.
927       (+) Convert dynamic linked-list queue to static format.
928       (+) Link linked-list queue to DMA channel.
929       (+) Unlink linked-list queue from DMA channel.
930 
931     [..]
932       (+) The HAL_DMAEx_List_BuildNode() function allows to build linked-list node.
933           Node type can be :
934               (++) 2 dimensions addressing node.
935               (++) Linear addressing node.
936 
937       (+) The HAL_DMAEx_List_GetNodeConfig() function allows to get the linked-list node configuration from built node.
938 
939       (+) The HAL_DMAEx_List_InsertNode() function allows to insert built linked-list node to static linked-list queue
940           according to selected position.
941 
942       (+) The HAL_DMAEx_List_InsertNode_Head() and HAL_DMAEx_List_InsertNode_Tail() functions allow to insert built
943           linked-list node to the head (respectively the tail) of static linked-list queue.
944 
945       (+) The HAL_DMAEx_List_RemoveNode() function allows to remove selected built linked-list node from static
946           linked-list queue.
947 
948       (+) The HAL_DMAEx_List_RemoveNode_Head() and HAL_DMAEx_List_RemoveNode_Tail() functions allow to remove the head
949           (respectively the tail) built linked-list node from static linked-list queue.
950 
951       (+) The HAL_DMAEx_List_ReplaceNode() function allows to replace selected built linked-list node from static
952           linked-list queue.
953 
954       (+) The HAL_DMAEx_List_ReplaceNode_Head() and HAL_DMAEx_List_ReplaceNode_Tail() functions allow to replace the
955           head (respectively the tail) built linked-list node of static linked-list queue.
956 
957       (+) The HAL_DMAEx_List_ResetQ() function allows to reset static linked-list queue and unlink all built linked-list
958           nodes.
959 
960       (+) The HAL_DMAEx_List_InsertQ() function allows to insert static linked-list source queue to static linked-list
961           destination queue according to selected position.
962 
963       (+) The HAL_DMAEx_List_InsertQ_Head() and HAL_DMAEx_List_InsertQ_Tail() functions allow to insert static
964           linked-list source queue to the head (respectively the tail) of static linked-list destination queue.
965 
966       (+) The HAL_DMAEx_List_SetCircularModeConfig() function allows to link the last static linked-list queue node to
967           the selected first circular node.
968 
969       (+) The HAL_DMAEx_List_SetCircularMode() function allows to link the last static linked-list queue node to the
970           first static linked-list queue node.
971 
972       (+) The HAL_DMAEx_List_ClearCircularMode() function allows to unlink the last static linked-list queue node from
973           any first circular node position.
974 
975       (+) The HAL_DMAEx_List_ConvertQToDynamic() function allows to convert the static linked-list queue to dynamic
976           format. (Optimized queue execution)
977 
978       (+) The HAL_DMAEx_List_ConvertQToStatic() function allows to convert the dynamic linked-list queue to static
979           format. (Not optimized queue execution)
980 
981       (+) The HAL_DMAEx_List_LinkQ() function allows to link the (Dynamic / Static) linked-list queue to DMA channel to
982           be executed.
983 
984       (+) The HAL_DMAEx_List_UnLinkQ() function allows to unlink the (Dynamic / Static) linked-list queue from DMA
985           channel when execution is completed.
986 
987 @endverbatim
988   * @{
989   */
990 
991 /**
992   * @brief  Build a DMA channel node according to the specified parameters in the DMA_NodeConfTypeDef.
993   * @param  pNodeConfig : Pointer to a DMA_NodeConfTypeDef structure that contains the configuration information for the
994   *                       specified DMA linked-list Node.
995   * @param  pNode       : Pointer to a DMA_NodeTypeDef structure that contains linked-list node registers
996   *                       configurations.
997   * @note   The DMA linked-list node parameter address should be 32bit aligned and should not exceed the 64 KByte
998   *         addressable space.
999   * @retval HAL status.
1000   */
HAL_DMAEx_List_BuildNode(DMA_NodeConfTypeDef const * const pNodeConfig,DMA_NodeTypeDef * const pNode)1001 HAL_StatusTypeDef HAL_DMAEx_List_BuildNode(DMA_NodeConfTypeDef const *const pNodeConfig,
1002                                            DMA_NodeTypeDef *const pNode)
1003 {
1004   /* Check the node configuration and physical node parameters */
1005   if ((pNodeConfig == NULL) || (pNode == NULL))
1006   {
1007     return HAL_ERROR;
1008   }
1009 
1010   /* Check node type parameter */
1011   assert_param(IS_DMA_NODE_TYPE(pNodeConfig->NodeType));
1012 
1013   /* Check DMA channel basic transfer parameters */
1014   assert_param(IS_DMA_SOURCE_INC(pNodeConfig->Init.SrcInc));
1015   assert_param(IS_DMA_DESTINATION_INC(pNodeConfig->Init.DestInc));
1016   assert_param(IS_DMA_SOURCE_DATA_WIDTH(pNodeConfig->Init.SrcDataWidth));
1017   assert_param(IS_DMA_DESTINATION_DATA_WIDTH(pNodeConfig->Init.DestDataWidth));
1018   assert_param(IS_DMA_DATA_ALIGNMENT(pNodeConfig->DataHandlingConfig.DataAlignment));
1019   assert_param(IS_DMA_REQUEST(pNodeConfig->Init.Request));
1020   assert_param(IS_DMA_DIRECTION(pNodeConfig->Init.Direction));
1021   assert_param(IS_DMA_TCEM_EVENT_MODE(pNodeConfig->Init.TransferEventMode));
1022   assert_param(IS_DMA_BLOCK_HW_REQUEST(pNodeConfig->Init.BlkHWRequest));
1023   assert_param(IS_DMA_MODE(pNodeConfig->Init.Mode));
1024 
1025   /* Check DMA channel parameters */
1026   if ((pNodeConfig->NodeType & DMA_CHANNEL_TYPE_GPDMA) == DMA_CHANNEL_TYPE_GPDMA)
1027   {
1028     assert_param(IS_DMA_BURST_LENGTH(pNodeConfig->Init.SrcBurstLength));
1029     assert_param(IS_DMA_BURST_LENGTH(pNodeConfig->Init.DestBurstLength));
1030     assert_param(IS_DMA_DATA_EXCHANGE(pNodeConfig->DataHandlingConfig.DataExchange));
1031     assert_param(IS_DMA_TRANSFER_ALLOCATED_PORT(pNodeConfig->Init.TransferAllocatedPort));
1032   }
1033 
1034   /* Check DMA channel trigger parameters */
1035   assert_param(IS_DMA_TRIGGER_POLARITY(pNodeConfig->TriggerConfig.TriggerPolarity));
1036   if (pNodeConfig->TriggerConfig.TriggerPolarity != DMA_TRIG_POLARITY_MASKED)
1037   {
1038     assert_param(IS_DMA_TRIGGER_MODE(pNodeConfig->TriggerConfig.TriggerMode));
1039     assert_param(IS_DMA_TRIGGER_SELECTION(pNodeConfig->TriggerConfig.TriggerSelection));
1040   }
1041 
1042   /* Check DMA channel security and privilege attributes parameters */
1043 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
1044   assert_param(IS_DMA_ATTRIBUTES(pNodeConfig->SrcSecure));
1045   assert_param(IS_DMA_ATTRIBUTES(pNodeConfig->DestSecure));
1046 #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
1047 
1048   /* Build the DMA channel node */
1049   DMA_List_BuildNode(pNodeConfig, pNode);
1050 
1051   return HAL_OK;
1052 }
1053 
1054 /**
1055   * @brief  Get a DMA channel node configuration.
1056   * @param  pNodeConfig : Pointer to a DMA_NodeConfTypeDef structure that contains the configuration information for the
1057   *                       specified DMA linked-list Node.
1058   * @param  pNode       : Pointer to a DMA_NodeTypeDef structure that contains linked-list node registers
1059   *                       configurations.
1060   * @retval HAL status.
1061   */
HAL_DMAEx_List_GetNodeConfig(DMA_NodeConfTypeDef * const pNodeConfig,DMA_NodeTypeDef const * const pNode)1062 HAL_StatusTypeDef HAL_DMAEx_List_GetNodeConfig(DMA_NodeConfTypeDef *const pNodeConfig,
1063                                                DMA_NodeTypeDef const *const pNode)
1064 {
1065   /* Check the node configuration and physical node parameters */
1066   if ((pNodeConfig == NULL) || (pNode == NULL))
1067   {
1068     return HAL_ERROR;
1069   }
1070 
1071   /* Get the DMA channel node configuration */
1072   DMA_List_GetNodeConfig(pNodeConfig, pNode);
1073 
1074   return HAL_OK;
1075 }
1076 
1077 /**
1078   * @brief  Insert new node in any queue position of linked-list queue according to selecting previous node.
1079   * @param  pQList    : Pointer to a DMA_QListTypeDef structure that contains queue information.
1080   * @param  pPrevNode : Pointer to a DMA_NodeTypeDef structure that contains linked-list previous node registers
1081   *                     configurations.
1082   * @param  pNewNode  : Pointer to a DMA_NodeTypeDef structure that contains linked-list new node registers
1083   *                     configurations.
1084   * @retval HAL status.
1085   */
HAL_DMAEx_List_InsertNode(DMA_QListTypeDef * const pQList,DMA_NodeTypeDef * const pPrevNode,DMA_NodeTypeDef * const pNewNode)1086 HAL_StatusTypeDef HAL_DMAEx_List_InsertNode(DMA_QListTypeDef *const pQList,
1087                                             DMA_NodeTypeDef *const pPrevNode,
1088                                             DMA_NodeTypeDef *const pNewNode)
1089 {
1090   uint32_t cllr_mask;
1091   uint32_t cllr_offset;
1092   DMA_NodeInQInfoTypeDef node_info;
1093 
1094   /* Check the queue and the new node parameters */
1095   if ((pQList == NULL) || (pNewNode == NULL))
1096   {
1097     return HAL_ERROR;
1098   }
1099 
1100   /* Check queue type */
1101   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1102   {
1103     /* Update the queue error code */
1104     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1105 
1106     return HAL_ERROR;
1107   }
1108 
1109   /* Check nodes base addresses */
1110   if (DMA_List_CheckNodesBaseAddresses(pQList->Head, pPrevNode, pNewNode) != 0U)
1111   {
1112     /* Update the queue error code */
1113     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
1114 
1115     return HAL_ERROR;
1116   }
1117 
1118   /* Check nodes types compatibility */
1119   if (DMA_List_CheckNodesTypes(pQList->Head, pPrevNode, pNewNode) != 0U)
1120   {
1121     /* Update the queue error code */
1122     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1123 
1124     return HAL_ERROR;
1125   }
1126 
1127   /* Update the queue state */
1128   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
1129 
1130   /* Update the queue error code */
1131   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1132 
1133   /* Get CLLR register mask and offset */
1134   DMA_List_GetCLLRNodeInfo(pNewNode, &cllr_mask, &cllr_offset);
1135 
1136   /* Empty queue */
1137   if (pQList->Head == NULL)
1138   {
1139     /* Add only new node to queue */
1140     if (pPrevNode == NULL)
1141     {
1142       pQList->Head       = pNewNode;
1143       pQList->NodeNumber = 1U;
1144     }
1145     /* Add previous node then new node to queue */
1146     else
1147     {
1148       pQList->Head                          = pPrevNode;
1149       pPrevNode->LinkRegisters[cllr_offset] = ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1150       pQList->NodeNumber                    = 2U;
1151     }
1152   }
1153   /* Not empty queue */
1154   else
1155   {
1156     /* Add new node at the head of queue */
1157     if (pPrevNode == NULL)
1158     {
1159       pNewNode->LinkRegisters[cllr_offset] = ((uint32_t)pQList->Head & DMA_CLLR_LA) | cllr_mask;
1160       pQList->Head                         = pNewNode;
1161     }
1162     /* Add new node according to selected position */
1163     else
1164     {
1165       /* Find node and get its position in selected queue */
1166       node_info.cllr_offset = cllr_offset;
1167       if (DMA_List_FindNode(pQList, pPrevNode, &node_info) == 0U)
1168       {
1169         /* Selected node is the last queue node */
1170         if (node_info.currentnode_pos == pQList->NodeNumber)
1171         {
1172           /* Check if queue is circular */
1173           if (pQList->FirstCircularNode != NULL)
1174           {
1175             pNewNode->LinkRegisters[cllr_offset] = ((uint32_t)pQList->FirstCircularNode & DMA_CLLR_LA) | cllr_mask;
1176           }
1177 
1178           pPrevNode->LinkRegisters[cllr_offset] = ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1179         }
1180         /* Selected node is not the last queue node */
1181         else
1182         {
1183           pNewNode->LinkRegisters[cllr_offset] = pPrevNode->LinkRegisters[cllr_offset];
1184           pPrevNode->LinkRegisters[cllr_offset] = ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1185         }
1186       }
1187       else
1188       {
1189         /* Update the queue error code */
1190         pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NOTFOUND;
1191 
1192         return HAL_ERROR;
1193       }
1194     }
1195 
1196     /* Increment queue node number */
1197     pQList->NodeNumber++;
1198   }
1199 
1200   /* Update the queue error code */
1201   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1202 
1203   /* Update the queue state */
1204   pQList->State = HAL_DMA_QUEUE_STATE_READY;
1205 
1206   return HAL_OK;
1207 }
1208 
1209 /**
1210   * @brief  Insert new node at the head of linked-list queue.
1211   * @param  pQList    : Pointer to a DMA_QListTypeDef structure that contains queue information.
1212   * @param  pNewNode  : Pointer to a DMA_NodeTypeDef structure that contains linked-list new node registers
1213   *                     configurations.
1214   * @retval HAL status.
1215   */
HAL_DMAEx_List_InsertNode_Head(DMA_QListTypeDef * const pQList,DMA_NodeTypeDef * const pNewNode)1216 HAL_StatusTypeDef HAL_DMAEx_List_InsertNode_Head(DMA_QListTypeDef *const pQList,
1217                                                  DMA_NodeTypeDef *const pNewNode)
1218 {
1219   uint32_t cllr_mask;
1220   uint32_t cllr_offset;
1221 
1222   /* Check the queue and the new node parameters */
1223   if ((pQList == NULL) || (pNewNode == NULL))
1224   {
1225     return HAL_ERROR;
1226   }
1227 
1228   /* Check queue type */
1229   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1230   {
1231     /* Update the queue error code */
1232     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1233 
1234     return HAL_ERROR;
1235   }
1236 
1237   /* Check nodes base addresses */
1238   if (DMA_List_CheckNodesBaseAddresses(pQList->Head, pNewNode, NULL) != 0U)
1239   {
1240     /* Update the queue error code */
1241     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
1242 
1243     return HAL_ERROR;
1244   }
1245 
1246   /* Check nodes types compatibility */
1247   if (DMA_List_CheckNodesTypes(pQList->Head, pNewNode, NULL) != 0U)
1248   {
1249     /* Update the queue error code */
1250     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1251 
1252     return HAL_ERROR;
1253   }
1254 
1255   /* Update the queue state */
1256   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
1257 
1258   /* Update the queue error code */
1259   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1260 
1261   /* Empty queue */
1262   if (pQList->Head == NULL)
1263   {
1264     pQList->Head = pNewNode;
1265   }
1266   /* Not empty queue */
1267   else
1268   {
1269     /* Get CLLR register mask and offset */
1270     DMA_List_GetCLLRNodeInfo(pNewNode, &cllr_mask, &cllr_offset);
1271 
1272     pNewNode->LinkRegisters[cllr_offset] = ((uint32_t)pQList->Head & DMA_CLLR_LA) | cllr_mask;
1273     pQList->Head                         = pNewNode;
1274   }
1275 
1276   /* Increment queue node number */
1277   pQList->NodeNumber++;
1278 
1279   /* Update the queue error code */
1280   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1281 
1282   /* Update the queue state */
1283   pQList->State = HAL_DMA_QUEUE_STATE_READY;
1284 
1285   return HAL_OK;
1286 }
1287 
1288 /**
1289   * @brief  Insert new node at the tail of linked-list queue.
1290   * @param  pQList    : Pointer to a DMA_QListTypeDef structure that contains queue information.
1291   * @param  pNewNode  : Pointer to a DMA_NodeTypeDef structure that contains linked-list new node registers
1292   *                     configurations.
1293   * @retval HAL status.
1294   */
HAL_DMAEx_List_InsertNode_Tail(DMA_QListTypeDef * const pQList,DMA_NodeTypeDef * const pNewNode)1295 HAL_StatusTypeDef HAL_DMAEx_List_InsertNode_Tail(DMA_QListTypeDef *const pQList,
1296                                                  DMA_NodeTypeDef *const pNewNode)
1297 {
1298   uint32_t cllr_mask;
1299   uint32_t cllr_offset;
1300   DMA_NodeInQInfoTypeDef node_info;
1301 
1302   /* Check the queue and the new node parameters */
1303   if ((pQList == NULL) || (pNewNode == NULL))
1304   {
1305     return HAL_ERROR;
1306   }
1307 
1308   /* Check queue type */
1309   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1310   {
1311     /* Update the queue error code */
1312     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1313 
1314     return HAL_ERROR;
1315   }
1316 
1317   /* Check nodes base addresses */
1318   if (DMA_List_CheckNodesBaseAddresses(pQList->Head, pNewNode, NULL) != 0U)
1319   {
1320     /* Update the queue error code */
1321     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
1322 
1323     return HAL_ERROR;
1324   }
1325 
1326   /* Check nodes types compatibility */
1327   if (DMA_List_CheckNodesTypes(pQList->Head, pNewNode, NULL) != 0U)
1328   {
1329     /* Update the queue error code */
1330     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1331 
1332     return HAL_ERROR;
1333   }
1334 
1335   /* Empty queue */
1336   if (pQList->Head == NULL)
1337   {
1338     pQList->Head = pNewNode;
1339   }
1340   /* Not empty queue */
1341   else
1342   {
1343     /* Get CLLR register mask and offset */
1344     DMA_List_GetCLLRNodeInfo(pNewNode, &cllr_mask, &cllr_offset);
1345 
1346     /* Find node and get its position in selected queue */
1347     node_info.cllr_offset = cllr_offset;
1348     (void)DMA_List_FindNode(pQList, NULL, &node_info);
1349 
1350     /* Check if queue is circular */
1351     if (pQList->FirstCircularNode != NULL)
1352     {
1353       pNewNode->LinkRegisters[cllr_offset] = ((uint32_t)pQList->FirstCircularNode & DMA_CLLR_LA) | cllr_mask;
1354     }
1355 
1356     ((DMA_NodeTypeDef *)node_info.currentnode_addr)->LinkRegisters[cllr_offset] =
1357       ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1358   }
1359 
1360   /* Increment queue node number */
1361   pQList->NodeNumber++;
1362 
1363   /* Update the queue error code */
1364   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1365 
1366   /* Update the queue state */
1367   pQList->State = HAL_DMA_QUEUE_STATE_READY;
1368 
1369   /* Prevent MISRA-C2012-Rule-2.2_b */
1370   UNUSED(node_info);
1371 
1372   return HAL_OK;
1373 }
1374 
1375 /**
1376   * @brief  Remove node from any linked-list queue position.
1377   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
1378   * @param  pNode  : Pointer to a DMA_NodeTypeDef structure that contains linked-list previous node registers
1379   *                  configurations.
1380   * @retval HAL status.
1381   */
HAL_DMAEx_List_RemoveNode(DMA_QListTypeDef * const pQList,DMA_NodeTypeDef * const pNode)1382 HAL_StatusTypeDef HAL_DMAEx_List_RemoveNode(DMA_QListTypeDef *const pQList,
1383                                             DMA_NodeTypeDef *const pNode)
1384 {
1385   uint32_t previousnode_addr;
1386   uint32_t cllr_offset;
1387   DMA_NodeInQInfoTypeDef node_info;
1388 
1389   /* Check the queue and the node parameters */
1390   if ((pQList == NULL) || (pNode == NULL))
1391   {
1392     return HAL_ERROR;
1393   }
1394 
1395   /* Check the queue */
1396   if (pQList->Head == NULL)
1397   {
1398     /* Update the queue error code */
1399     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
1400 
1401     return HAL_ERROR;
1402   }
1403 
1404   /* Check queue type */
1405   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1406   {
1407     /* Update the queue error code */
1408     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1409 
1410     return HAL_ERROR;
1411   }
1412 
1413   /* Update the queue state */
1414   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
1415 
1416   /* Update the queue error code */
1417   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1418 
1419   /* Get CLLR register mask and offset */
1420   DMA_List_GetCLLRNodeInfo(pNode, NULL, &cllr_offset);
1421 
1422   /* Find node and get its position in selected queue */
1423   node_info.cllr_offset = cllr_offset;
1424   if (DMA_List_FindNode(pQList, pNode, &node_info) == 0U)
1425   {
1426     /* Removed node is the head node */
1427     if (node_info.currentnode_pos == 1U)
1428     {
1429       /* Check if first circular node queue is the first node */
1430       if (pQList->FirstCircularNode == ((DMA_NodeTypeDef *)node_info.currentnode_addr))
1431       {
1432         /* Find last queue node */
1433         (void)DMA_List_FindNode(pQList, NULL, &node_info);
1434 
1435         /* Clear last node link */
1436         ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
1437 
1438         /* Clear first circular node */
1439         pQList->FirstCircularNode = NULL;
1440       }
1441 
1442       /* Update the queue head node */
1443       pQList->Head = (DMA_NodeTypeDef *)(((uint32_t)pQList->Head & DMA_CLBAR_LBA) +
1444                                          (pNode->LinkRegisters[cllr_offset] & DMA_CLLR_LA));
1445       /* Unlink node to be removed */
1446       pNode->LinkRegisters[cllr_offset] = 0U;
1447     }
1448     /* Removed node is the last node */
1449     else if (node_info.currentnode_pos == pQList->NodeNumber)
1450     {
1451       /* Clear CLLR for previous node */
1452       ((DMA_NodeTypeDef *)(node_info.previousnode_addr))->LinkRegisters[cllr_offset] = 0U;
1453 
1454       /* Clear CLLR for last node */
1455       ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
1456 
1457       /* Clear first circular node */
1458       pQList->FirstCircularNode = NULL;
1459     }
1460     /* Removed node is in the middle */
1461     else
1462     {
1463       /* Store previous node address to be updated later */
1464       previousnode_addr = node_info.previousnode_addr;
1465 
1466       /* Check if first circular node queue is the current node */
1467       if (pQList->FirstCircularNode == ((DMA_NodeTypeDef *)node_info.currentnode_addr))
1468       {
1469         /* Find last queue node */
1470         (void)DMA_List_FindNode(pQList, NULL, &node_info);
1471 
1472         /* Clear last node link */
1473         ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
1474 
1475         /* Clear first circular node */
1476         pQList->FirstCircularNode = NULL;
1477       }
1478 
1479       /* Link previous node */
1480       ((DMA_NodeTypeDef *)(previousnode_addr))->LinkRegisters[cllr_offset] = pNode->LinkRegisters[cllr_offset];
1481 
1482       /* Unlink node to be removed */
1483       pNode->LinkRegisters[cllr_offset] = 0U;
1484     }
1485 
1486     /* Decrement node number */
1487     pQList->NodeNumber--;
1488   }
1489   else
1490   {
1491     /* Update the queue error code */
1492     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NOTFOUND;
1493 
1494     return HAL_ERROR;
1495   }
1496 
1497   /* Check if queue is empty */
1498   if (pQList->NodeNumber == 0U)
1499   {
1500     /* Clean empty queue parameter */
1501     DMA_List_CleanQueue(pQList);
1502   }
1503   else
1504   {
1505     /* Update the queue error code */
1506     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1507 
1508     /* Update the queue state */
1509     pQList->State = HAL_DMA_QUEUE_STATE_READY;
1510   }
1511 
1512   /* Prevent MISRA-C2012-Rule-2.2_b */
1513   UNUSED(node_info);
1514 
1515   return HAL_OK;
1516 }
1517 
1518 /**
1519   * @brief  Remove the head node from linked-list queue.
1520   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
1521   * @retval HAL status.
1522   */
HAL_DMAEx_List_RemoveNode_Head(DMA_QListTypeDef * const pQList)1523 HAL_StatusTypeDef HAL_DMAEx_List_RemoveNode_Head(DMA_QListTypeDef *const pQList)
1524 {
1525   uint32_t cllr_offset;
1526   uint32_t current_addr;
1527   DMA_NodeInQInfoTypeDef node_info;
1528 
1529   /* Check the queue parameter */
1530   if (pQList == NULL)
1531   {
1532     return HAL_ERROR;
1533   }
1534 
1535   /* Check the queue */
1536   if (pQList->Head == NULL)
1537   {
1538     /* Update the queue error code */
1539     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
1540 
1541     return HAL_ERROR;
1542   }
1543 
1544   /* Check queue type */
1545   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1546   {
1547     /* Update the queue error code */
1548     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1549 
1550     return HAL_ERROR;
1551   }
1552 
1553   /* Update the queue state */
1554   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
1555 
1556   /* Update the queue error code */
1557   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1558 
1559   /* Get CLLR register mask and offset */
1560   DMA_List_GetCLLRNodeInfo(pQList->Head, NULL, &cllr_offset);
1561 
1562   /* Queue contains only one node */
1563   if (pQList->NodeNumber == 1U)
1564   {
1565     pQList->Head->LinkRegisters[cllr_offset] = 0U;
1566     pQList->FirstCircularNode = 0U;
1567     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1568   }
1569   /* Queue contains more then one node */
1570   else
1571   {
1572     /* Check if first circular node queue is the first node */
1573     if (pQList->FirstCircularNode == pQList->Head)
1574     {
1575       /* Find last queue node */
1576       node_info.cllr_offset = cllr_offset;
1577       (void)DMA_List_FindNode(pQList, NULL, &node_info);
1578 
1579       /* Clear last node link */
1580       ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
1581 
1582       /* Clear first circular node */
1583       pQList->FirstCircularNode = NULL;
1584     }
1585 
1586     current_addr = pQList->Head->LinkRegisters[cllr_offset] & DMA_CLLR_LA;
1587     pQList->Head->LinkRegisters[cllr_offset] = 0U;
1588     pQList->Head = ((DMA_NodeTypeDef *)(current_addr + ((uint32_t)pQList->Head & DMA_CLBAR_LBA)));
1589   }
1590 
1591   /* Decrement node number */
1592   pQList->NodeNumber--;
1593 
1594   /* Check if queue is empty */
1595   if (pQList->NodeNumber == 0U)
1596   {
1597     /* Clean empty queue parameter */
1598     DMA_List_CleanQueue(pQList);
1599   }
1600   else
1601   {
1602     /* Update the queue error code */
1603     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1604 
1605     /* Update the queue state */
1606     pQList->State = HAL_DMA_QUEUE_STATE_READY;
1607   }
1608 
1609   /* Prevent MISRA-C2012-Rule-2.2_b */
1610   UNUSED(node_info);
1611 
1612   return HAL_OK;
1613 }
1614 
1615 /**
1616   * @brief  Remove the tail node from linked-list queue.
1617   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
1618   * @retval HAL status.
1619   */
HAL_DMAEx_List_RemoveNode_Tail(DMA_QListTypeDef * const pQList)1620 HAL_StatusTypeDef HAL_DMAEx_List_RemoveNode_Tail(DMA_QListTypeDef *const pQList)
1621 {
1622   uint32_t cllr_offset;
1623   DMA_NodeInQInfoTypeDef node_info;
1624 
1625   /* Check the queue parameter */
1626   if (pQList == NULL)
1627   {
1628     return HAL_ERROR;
1629   }
1630 
1631   /* Check the queue */
1632   if (pQList->Head == NULL)
1633   {
1634     /* Update the queue error code */
1635     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
1636 
1637     return HAL_ERROR;
1638   }
1639 
1640   /* Check queue type */
1641   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1642   {
1643     /* Update the queue error code */
1644     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1645 
1646     return HAL_ERROR;
1647   }
1648 
1649   /* Update the queue state */
1650   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
1651 
1652   /* Update the queue error code */
1653   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1654 
1655   /* Get CLLR register mask and offset */
1656   DMA_List_GetCLLRNodeInfo(pQList->Head, NULL, &cllr_offset);
1657 
1658   /* Queue contains only one node */
1659   if (pQList->NodeNumber == 1U)
1660   {
1661     pQList->Head->LinkRegisters[cllr_offset] = 0U;
1662     pQList->FirstCircularNode = 0U;
1663     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1664   }
1665   /* Queue contains more then one node */
1666   else
1667   {
1668     /* Find node and get its position in selected queue */
1669     node_info.cllr_offset = cllr_offset;
1670     (void)DMA_List_FindNode(pQList, NULL, &node_info);
1671 
1672     /* Clear CLLR for previous node */
1673     ((DMA_NodeTypeDef *)(node_info.previousnode_addr))->LinkRegisters[cllr_offset] = 0U;
1674 
1675     /* Clear CLLR for last node */
1676     ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
1677 
1678     /* Clear first circular node */
1679     pQList->FirstCircularNode = NULL;
1680   }
1681 
1682   /* Decrement node number */
1683   pQList->NodeNumber--;
1684 
1685   /* Check if queue is empty */
1686   if (pQList->NodeNumber == 0U)
1687   {
1688     /* Clean empty queue parameter */
1689     DMA_List_CleanQueue(pQList);
1690   }
1691   else
1692   {
1693     /* Update the queue error code */
1694     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1695 
1696     /* Update the queue state */
1697     pQList->State = HAL_DMA_QUEUE_STATE_READY;
1698   }
1699 
1700   /* Prevent MISRA-C2012-Rule-2.2_b */
1701   UNUSED(node_info);
1702 
1703   return HAL_OK;
1704 }
1705 
1706 /**
1707   * @brief  Replace node in linked-list queue.
1708   * @param  pQList   : Pointer to a DMA_QListTypeDef structure that contains queue information.
1709   * @param  pOldNode : Pointer to a DMA_NodeTypeDef structure that contains linked-list old node registers
1710   *                    configurations.
1711   * @param  pNewNode : Pointer to a DMA_NodeTypeDef structure that contains linked-list new node registers
1712   *                    configurations.
1713   * @retval HAL status.
1714   */
HAL_DMAEx_List_ReplaceNode(DMA_QListTypeDef * const pQList,DMA_NodeTypeDef * const pOldNode,DMA_NodeTypeDef * const pNewNode)1715 HAL_StatusTypeDef HAL_DMAEx_List_ReplaceNode(DMA_QListTypeDef *const pQList,
1716                                              DMA_NodeTypeDef *const pOldNode,
1717                                              DMA_NodeTypeDef *const pNewNode)
1718 {
1719   uint32_t cllr_mask;
1720   uint32_t cllr_offset;
1721   DMA_NodeInQInfoTypeDef node_info;
1722 
1723   /* Check the queue and the nodes parameters */
1724   if ((pQList == NULL) || (pOldNode == NULL) || (pNewNode == NULL))
1725   {
1726     return HAL_ERROR;
1727   }
1728 
1729   /* Check the queue */
1730   if (pQList->Head == NULL)
1731   {
1732     /* Update the queue error code */
1733     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
1734 
1735     return HAL_ERROR;
1736   }
1737 
1738   /* Check queue type */
1739   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1740   {
1741     /* Update the queue error code */
1742     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1743 
1744     return HAL_ERROR;
1745   }
1746 
1747   /* Check nodes base addresses */
1748   if (DMA_List_CheckNodesBaseAddresses(pQList->Head, pOldNode, pNewNode) != 0U)
1749   {
1750     /* Update the queue error code */
1751     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
1752 
1753     return HAL_ERROR;
1754   }
1755 
1756   /* Check nodes types compatibility */
1757   if (DMA_List_CheckNodesTypes(pQList->Head, pOldNode, pNewNode) != 0U)
1758   {
1759     /* Update the queue error code */
1760     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1761 
1762     return HAL_ERROR;
1763   }
1764 
1765   /* Update the queue state */
1766   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
1767 
1768   /* Update the queue error code */
1769   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1770 
1771   /* Get CLLR register mask and offset */
1772   DMA_List_GetCLLRNodeInfo(pNewNode, &cllr_mask, &cllr_offset);
1773 
1774   /* Find node and get its position in selected queue */
1775   node_info.cllr_offset = cllr_offset;
1776   if (DMA_List_FindNode(pQList, pOldNode, &node_info) == 0U)
1777   {
1778     /* Replaced node is the head node */
1779     if (node_info.currentnode_pos == 1U)
1780     {
1781       pNewNode->LinkRegisters[cllr_offset] =
1782         ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset];
1783       pQList->Head = pNewNode;
1784       ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
1785 
1786       /* Check if first circular node queue is the first node */
1787       if (pQList->FirstCircularNode == ((DMA_NodeTypeDef *)node_info.currentnode_addr))
1788       {
1789         /* Find last queue node */
1790         (void)DMA_List_FindNode(pQList, NULL, &node_info);
1791 
1792         /* Clear last node link */
1793         ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
1794           ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1795 
1796         /* Set new node as first circular node */
1797         pQList->FirstCircularNode = pNewNode;
1798       }
1799     }
1800     /* Replaced node is the last */
1801     else if (node_info.currentnode_pos == pQList->NodeNumber)
1802     {
1803       ((DMA_NodeTypeDef *)(node_info.previousnode_addr))->LinkRegisters[cllr_offset] =
1804         ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1805       ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
1806 
1807       /* Check if first circular node queue is the last node */
1808       if (pQList->FirstCircularNode == ((DMA_NodeTypeDef *)(node_info.currentnode_addr)))
1809       {
1810         /* Link first circular node to new node */
1811         pNewNode->LinkRegisters[cllr_offset] = ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1812 
1813         /* Set new node as first circular node */
1814         pQList->FirstCircularNode = pNewNode;
1815       }
1816       /* Check if first circular node queue is not the last node */
1817       else if (pQList->FirstCircularNode != NULL)
1818       {
1819         /* Link first circular node to new node */
1820         pNewNode->LinkRegisters[cllr_offset] = ((uint32_t)pQList->FirstCircularNode & DMA_CLLR_LA) | cllr_mask;
1821       }
1822       else
1823       {
1824         /* Prevent MISRA-C2012-Rule-15.7 */
1825       }
1826     }
1827     /* Replaced node is in the middle */
1828     else
1829     {
1830       ((DMA_NodeTypeDef *)(node_info.previousnode_addr))->LinkRegisters[cllr_offset] =
1831         ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1832       pNewNode->LinkRegisters[cllr_offset] =
1833         ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset];
1834       ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
1835 
1836       /* Check if first circular node queue is the current node */
1837       if (pQList->FirstCircularNode == ((DMA_NodeTypeDef *)(node_info.currentnode_addr)))
1838       {
1839         /* Find last node and get its position in selected queue */
1840         (void)DMA_List_FindNode(pQList, NULL, &node_info);
1841 
1842         /* Link last queue node to new node */
1843         ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
1844           ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1845 
1846         /* Set new node as first circular node */
1847         pQList->FirstCircularNode = pNewNode;
1848       }
1849     }
1850   }
1851   else
1852   {
1853     /* Update the queue error code */
1854     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NOTFOUND;
1855 
1856     return HAL_ERROR;
1857   }
1858 
1859   /* Update the queue error code */
1860   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1861 
1862   /* Update the queue state */
1863   pQList->State = HAL_DMA_QUEUE_STATE_READY;
1864 
1865   /* Prevent MISRA-C2012-Rule-2.2_b */
1866   UNUSED(node_info);
1867 
1868   return HAL_OK;
1869 }
1870 
1871 /**
1872   * @brief  Replace the head node of linked-list queue.
1873   * @param  pQList   : Pointer to a DMA_QListTypeDef structure that contains queue information.
1874   * @param  pNewNode : Pointer to a DMA_NodeTypeDef structure that contains linked-list new node registers
1875   *                    configurations.
1876   * @retval HAL status.
1877   */
HAL_DMAEx_List_ReplaceNode_Head(DMA_QListTypeDef * const pQList,DMA_NodeTypeDef * const pNewNode)1878 HAL_StatusTypeDef HAL_DMAEx_List_ReplaceNode_Head(DMA_QListTypeDef *const pQList,
1879                                                   DMA_NodeTypeDef *const pNewNode)
1880 {
1881   uint32_t cllr_offset;
1882   uint32_t cllr_mask;
1883   DMA_NodeInQInfoTypeDef node_info;
1884 
1885   /* Check the queue and the new node parameters */
1886   if ((pQList == NULL) || (pNewNode == NULL))
1887   {
1888     return HAL_ERROR;
1889   }
1890 
1891   /* Check the queue */
1892   if (pQList->Head == NULL)
1893   {
1894     /* Update the queue error code */
1895     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
1896 
1897     return HAL_ERROR;
1898   }
1899 
1900   /* Check queue type */
1901   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1902   {
1903     /* Update the queue error code */
1904     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1905 
1906     return HAL_ERROR;
1907   }
1908 
1909   /* Check nodes base addresses */
1910   if (DMA_List_CheckNodesBaseAddresses(pQList->Head, pNewNode, NULL) != 0U)
1911   {
1912     /* Update the queue error code */
1913     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
1914 
1915     return HAL_ERROR;
1916   }
1917 
1918   /* Check nodes types compatibility */
1919   if (DMA_List_CheckNodesTypes(pQList->Head, pNewNode, NULL) != 0U)
1920   {
1921     /* Update the queue error code */
1922     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
1923 
1924     return HAL_ERROR;
1925   }
1926 
1927   /* Update the queue state */
1928   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
1929 
1930   /* Update the queue error code */
1931   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1932 
1933   /* Get CLLR register mask and offset */
1934   DMA_List_GetCLLRNodeInfo(pNewNode, &cllr_mask, &cllr_offset);
1935 
1936   /* Check if first circular node queue is the first node */
1937   if (pQList->FirstCircularNode == pQList->Head)
1938   {
1939     /* Find last queue node */
1940     node_info.cllr_offset = cllr_offset;
1941     (void)DMA_List_FindNode(pQList, NULL, &node_info);
1942 
1943     /* Clear last node link */
1944     ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
1945       ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
1946 
1947     /* Set new node as first circular node */
1948     pQList->FirstCircularNode = pNewNode;
1949   }
1950 
1951   /* Replace head node */
1952   pNewNode->LinkRegisters[cllr_offset] = pQList->Head->LinkRegisters[cllr_offset];
1953   pQList->Head->LinkRegisters[cllr_offset] = 0U;
1954   pQList->Head = pNewNode;
1955 
1956   /* Update the queue error code */
1957   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
1958 
1959   /* Update the queue state */
1960   pQList->State = HAL_DMA_QUEUE_STATE_READY;
1961 
1962   /* Prevent MISRA-C2012-Rule-2.2_b */
1963   UNUSED(node_info);
1964 
1965   return HAL_OK;
1966 }
1967 
1968 /**
1969   * @brief  Replace the tail node of linked-list queue.
1970   * @param  pQList   : Pointer to a DMA_QListTypeDef structure that contains queue information.
1971   * @param  pNewNode : Pointer to a DMA_NodeTypeDef structure that contains linked-list new node registers
1972   *                    configurations.
1973   * @retval HAL status.
1974   */
HAL_DMAEx_List_ReplaceNode_Tail(DMA_QListTypeDef * const pQList,DMA_NodeTypeDef * const pNewNode)1975 HAL_StatusTypeDef HAL_DMAEx_List_ReplaceNode_Tail(DMA_QListTypeDef *const pQList,
1976                                                   DMA_NodeTypeDef *const pNewNode)
1977 {
1978   uint32_t cllr_mask;
1979   uint32_t cllr_offset;
1980   DMA_NodeInQInfoTypeDef node_info;
1981 
1982   /* Check the queue and the new node parameters */
1983   if ((pQList == NULL) || (pNewNode == NULL))
1984   {
1985     return HAL_ERROR;
1986   }
1987 
1988   /* Check the queue */
1989   if (pQList->Head == NULL)
1990   {
1991     /* Update the queue error code */
1992     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
1993 
1994     return HAL_ERROR;
1995   }
1996 
1997   /* Check queue type */
1998   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
1999   {
2000     /* Update the queue error code */
2001     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2002 
2003     return HAL_ERROR;
2004   }
2005 
2006   /* Update the queue state */
2007   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2008 
2009   /* Update the queue error code */
2010   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2011 
2012   /* Get CLLR register mask and offset */
2013   DMA_List_GetCLLRNodeInfo(pNewNode, &cllr_mask, &cllr_offset);
2014 
2015   /* Find last node and get its position in selected queue */
2016   node_info.cllr_offset = cllr_offset;
2017   (void)DMA_List_FindNode(pQList, NULL, &node_info);
2018 
2019   /* Link previous node to new node */
2020   ((DMA_NodeTypeDef *)(node_info.previousnode_addr))->LinkRegisters[cllr_offset] =
2021     ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
2022 
2023   /* Clear CLLR for current node */
2024   ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
2025 
2026   /* Check if first circular node queue is the last node */
2027   if (pQList->FirstCircularNode == ((DMA_NodeTypeDef *)(node_info.currentnode_addr)))
2028   {
2029     /* Link first circular node to new node */
2030     pNewNode->LinkRegisters[cllr_offset] = ((uint32_t)pNewNode & DMA_CLLR_LA) | cllr_mask;
2031 
2032     /* Set new node as first circular node */
2033     pQList->FirstCircularNode = pNewNode;
2034   }
2035   /* Check if first circular node queue is not the last node */
2036   else if (pQList->FirstCircularNode != NULL)
2037   {
2038     /* Link first circular node to new node */
2039     pNewNode->LinkRegisters[cllr_offset] = ((uint32_t)pQList->FirstCircularNode & DMA_CLLR_LA) | cllr_mask;
2040   }
2041   else
2042   {
2043     /* Prevent MISRA-C2012-Rule-15.7 */
2044   }
2045 
2046   /* Check if queue contains one node */
2047   if (pQList->NodeNumber == 1U)
2048   {
2049     pQList->Head = pNewNode;
2050   }
2051 
2052   /* Update the queue error code */
2053   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2054 
2055   /* Update the queue state */
2056   pQList->State = HAL_DMA_QUEUE_STATE_READY;
2057 
2058   return HAL_OK;
2059 }
2060 
2061 /**
2062   * @brief  Reset the linked-list queue and unlink queue nodes.
2063   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
2064   * @retval HAL status.
2065   */
HAL_DMAEx_List_ResetQ(DMA_QListTypeDef * const pQList)2066 HAL_StatusTypeDef HAL_DMAEx_List_ResetQ(DMA_QListTypeDef *const pQList)
2067 {
2068   uint32_t cllr_offset;
2069   DMA_NodeInQInfoTypeDef node_info;
2070 
2071   /* Check the queue parameter */
2072   if (pQList == NULL)
2073   {
2074     return HAL_ERROR;
2075   }
2076 
2077   /* Check queue state */
2078   if (pQList->State == HAL_DMA_QUEUE_STATE_BUSY)
2079   {
2080     /* Update the queue error code */
2081     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_BUSY;
2082 
2083     return HAL_ERROR;
2084   }
2085 
2086   /* Check queue type */
2087   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
2088   {
2089     /* Update the queue error code */
2090     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2091 
2092     return HAL_ERROR;
2093   }
2094 
2095   /* Update the queue state */
2096   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2097 
2098   /* Update the queue error code */
2099   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2100 
2101   /* Check the queue */
2102   if (pQList->Head != NULL)
2103   {
2104     /* Get CLLR register mask and offset */
2105     DMA_List_GetCLLRNodeInfo(pQList->Head, NULL, &cllr_offset);
2106 
2107     /* Reset selected queue nodes */
2108     node_info.cllr_offset = cllr_offset;
2109     DMA_List_ResetQueueNodes(pQList, &node_info);
2110   }
2111 
2112   /* Reset head node address */
2113   pQList->Head = NULL;
2114 
2115   /* Reset node number */
2116   pQList->NodeNumber = 0U;
2117 
2118   /* Reset first circular node */
2119   pQList->FirstCircularNode = NULL;
2120 
2121   /* Update the queue error code */
2122   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2123 
2124   /* Update the queue state */
2125   pQList->State = HAL_DMA_QUEUE_STATE_RESET;
2126 
2127   return HAL_OK;
2128 }
2129 
2130 /**
2131   * @brief  Insert a source linked-list queue to a destination linked-list queue according to selecting previous node.
2132   * @param  pSrcQList  : Pointer to a DMA_QListTypeDef structure that contains source queue information.
2133   * @param  pPrevNode  : Pointer to a DMA_NodeTypeDef structure that contains linked-list previous node registers
2134   *                      configurations.
2135   * @param  pDestQList : Pointer to a DMA_QListTypeDef structure that contains destination queue information.
2136   * @retval HAL status.
2137   */
HAL_DMAEx_List_InsertQ(DMA_QListTypeDef * const pSrcQList,DMA_NodeTypeDef const * const pPrevNode,DMA_QListTypeDef * const pDestQList)2138 HAL_StatusTypeDef HAL_DMAEx_List_InsertQ(DMA_QListTypeDef *const pSrcQList,
2139                                          DMA_NodeTypeDef const *const pPrevNode,
2140                                          DMA_QListTypeDef *const pDestQList)
2141 {
2142   uint32_t cllr_mask;
2143   uint32_t cllr_offset;
2144   DMA_NodeInQInfoTypeDef src_q_node_info;
2145   DMA_NodeInQInfoTypeDef dest_q_node_info;
2146 
2147   /* Check the source and destination queues and the previous node parameters */
2148   if ((pSrcQList == NULL) || (pDestQList == NULL))
2149   {
2150     return HAL_ERROR;
2151   }
2152 
2153   /* Check the source queue */
2154   if (pSrcQList->Head == NULL)
2155   {
2156     /* Update the queue error code */
2157     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
2158 
2159     return HAL_ERROR;
2160   }
2161 
2162   /* Check the source queue type */
2163   if (pSrcQList->Type == QUEUE_TYPE_DYNAMIC)
2164   {
2165     /* Update the queue error code */
2166     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2167 
2168     return HAL_ERROR;
2169   }
2170 
2171   /* Check the destination queue type */
2172   if (pDestQList->Type == QUEUE_TYPE_DYNAMIC)
2173   {
2174     /* Update the queue error code */
2175     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2176 
2177     return HAL_ERROR;
2178   }
2179 
2180   /* Check the source queue circularity */
2181   if (pSrcQList->FirstCircularNode != NULL)
2182   {
2183     /* Update the source queue error code */
2184     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2185 
2186     return HAL_ERROR;
2187   }
2188 
2189   /* Check nodes base addresses */
2190   if (DMA_List_CheckNodesBaseAddresses(pSrcQList->Head, pPrevNode, pDestQList->Head) != 0U)
2191   {
2192     /* Update the source queue error code */
2193     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
2194 
2195     /* Update the destination queue error code */
2196     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
2197 
2198     return HAL_ERROR;
2199   }
2200 
2201   /* Check nodes types compatibility */
2202   if (DMA_List_CheckNodesTypes(pSrcQList->Head, pPrevNode, pDestQList->Head) != 0U)
2203   {
2204     /* Update the source queue error code */
2205     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2206 
2207     /* Update the destination queue error code */
2208     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2209 
2210     return HAL_ERROR;
2211   }
2212 
2213   /* Update the source queue state */
2214   pSrcQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2215 
2216   /* Update the source queue error code */
2217   pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2218 
2219   /* Update the destination queue state */
2220   pDestQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2221 
2222   /* Update the destination queue error code */
2223   pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2224 
2225   /* Get CLLR register mask and offset */
2226   DMA_List_GetCLLRNodeInfo(pSrcQList->Head, &cllr_mask, &cllr_offset);
2227 
2228   /* Empty destination queue */
2229   if (pDestQList->Head == NULL)
2230   {
2231     pDestQList->Head       = pSrcQList->Head;
2232     pDestQList->NodeNumber = pSrcQList->NodeNumber;
2233   }
2234   /* Not empty destination queue */
2235   else
2236   {
2237     /* Previous node is empty */
2238     if (pPrevNode == NULL)
2239     {
2240       /* Find node and get its position in selected queue */
2241       src_q_node_info.cllr_offset = cllr_offset;
2242       (void)DMA_List_FindNode(pSrcQList, NULL, &src_q_node_info);
2243 
2244       /* Check if first circular node queue is the first node */
2245       if (pDestQList->FirstCircularNode == pDestQList->Head)
2246       {
2247         /* Find node and get its position in selected queue */
2248         dest_q_node_info.cllr_offset = cllr_offset;
2249         (void)DMA_List_FindNode(pDestQList, NULL, &dest_q_node_info);
2250 
2251         /* Link destination queue tail node to new first circular node */
2252         ((DMA_NodeTypeDef *)dest_q_node_info.currentnode_addr)->LinkRegisters[cllr_offset] =
2253           ((uint32_t)pSrcQList->Head & DMA_CLLR_LA) | cllr_mask;
2254 
2255         /* Set the head node of source queue as the first circular node */
2256         pDestQList->FirstCircularNode = pSrcQList->Head;
2257       }
2258 
2259       /* Link the last node of source queue to the fist node of destination queue */
2260       ((DMA_NodeTypeDef *)(src_q_node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
2261         ((uint32_t)pDestQList->Head & DMA_CLLR_LA) | cllr_mask;
2262       pDestQList->Head        = pSrcQList->Head;
2263       pDestQList->NodeNumber += pSrcQList->NodeNumber;
2264     }
2265     /* Previous node is not empty */
2266     else
2267     {
2268       /* Find node and get its position in selected queue */
2269       dest_q_node_info.cllr_offset = cllr_offset;
2270       if (DMA_List_FindNode(pDestQList, pPrevNode, &dest_q_node_info) == 0U)
2271       {
2272         /* Selected node is the last destination queue node */
2273         if (dest_q_node_info.currentnode_pos == pDestQList->NodeNumber)
2274         {
2275           /* Link the first node of source queue to the last node of destination queue */
2276           ((DMA_NodeTypeDef *)(dest_q_node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
2277             ((uint32_t)pSrcQList->Head & DMA_CLLR_LA) | cllr_mask;
2278           pDestQList->NodeNumber += pSrcQList->NodeNumber;
2279 
2280           /* Check if first circular node queue is not empty */
2281           if (pDestQList->FirstCircularNode != NULL)
2282           {
2283             /* Find node and get its position in selected queue */
2284             src_q_node_info.cllr_offset = cllr_offset;
2285             (void)DMA_List_FindNode(pSrcQList, NULL, &src_q_node_info);
2286 
2287             /* Find first circular node */
2288             (void)DMA_List_FindNode(pDestQList, pDestQList->FirstCircularNode, &dest_q_node_info);
2289 
2290             /* Link last source queue node to first destination queue */
2291             ((DMA_NodeTypeDef *)src_q_node_info.currentnode_addr)->LinkRegisters[cllr_offset] =
2292               (dest_q_node_info.currentnode_addr & DMA_CLLR_LA) | cllr_mask;
2293           }
2294         }
2295         /* Selected node is not the last destination queue node */
2296         else
2297         {
2298           /* Link the first node of source queue to the previous node of destination queue */
2299           ((DMA_NodeTypeDef *)(dest_q_node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
2300             ((uint32_t)pSrcQList->Head & DMA_CLLR_LA) | cllr_mask;
2301 
2302           /* Find node and get its position in selected queue */
2303           src_q_node_info.cllr_offset = cllr_offset;
2304           (void)DMA_List_FindNode(pSrcQList, NULL, &src_q_node_info);
2305 
2306           /* Link the last node of source queue to the next node of destination queue */
2307           ((DMA_NodeTypeDef *)(src_q_node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
2308             (dest_q_node_info.nextnode_addr & DMA_CLLR_LA) | cllr_mask;
2309 
2310           /* Update queues counter */
2311           pDestQList->NodeNumber += pSrcQList->NodeNumber;
2312         }
2313       }
2314       else
2315       {
2316         /* Update the destination queue error code */
2317         pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NOTFOUND;
2318 
2319         return HAL_ERROR;
2320       }
2321     }
2322   }
2323 
2324   /* Clean the source queue variable as it is obsolete */
2325   DMA_List_CleanQueue(pSrcQList);
2326 
2327   /* Update the destination queue error code */
2328   pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2329 
2330   /* Update the destination queue state */
2331   pDestQList->State = HAL_DMA_QUEUE_STATE_READY;
2332 
2333   /* Prevent MISRA-C2012-Rule-2.2_b */
2334   UNUSED(src_q_node_info);
2335   UNUSED(dest_q_node_info);
2336 
2337   return HAL_OK;
2338 }
2339 
2340 /**
2341   * @brief  Insert a source linked-list queue at the head of destination queue.
2342   * @param  pSrcQList  : Pointer to a DMA_QListTypeDef structure that contains source queue information.
2343   * @param  pDestQList : Pointer to a DMA_QListTypeDef structure that contains destination queue information.
2344   * @retval HAL status.
2345   */
HAL_DMAEx_List_InsertQ_Head(DMA_QListTypeDef * const pSrcQList,DMA_QListTypeDef * const pDestQList)2346 HAL_StatusTypeDef HAL_DMAEx_List_InsertQ_Head(DMA_QListTypeDef *const pSrcQList,
2347                                               DMA_QListTypeDef *const pDestQList)
2348 {
2349   uint32_t cllr_mask;
2350   uint32_t cllr_offset;
2351   DMA_NodeInQInfoTypeDef src_q_node_info;
2352   DMA_NodeInQInfoTypeDef dest_q_node_info;
2353 
2354   /* Check the source and destination queues and the previous node parameters */
2355   if ((pSrcQList == NULL) || (pDestQList == NULL))
2356   {
2357     return HAL_ERROR;
2358   }
2359 
2360   /* Check the source queue */
2361   if (pSrcQList->Head == NULL)
2362   {
2363     /* Update the queue error code */
2364     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
2365 
2366     return HAL_ERROR;
2367   }
2368 
2369   /* Check the source queue type */
2370   if (pSrcQList->Type == QUEUE_TYPE_DYNAMIC)
2371   {
2372     /* Update the queue error code */
2373     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2374 
2375     return HAL_ERROR;
2376   }
2377 
2378   /* Check the destination queue type */
2379   if (pDestQList->Type == QUEUE_TYPE_DYNAMIC)
2380   {
2381     /* Update the queue error code */
2382     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2383 
2384     return HAL_ERROR;
2385   }
2386 
2387   /* Check nodes base addresses */
2388   if (DMA_List_CheckNodesBaseAddresses(pSrcQList->Head, pDestQList->Head, NULL) != 0U)
2389   {
2390     /* Update the source queue error code */
2391     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
2392 
2393     /* Update the destination queue error code */
2394     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
2395 
2396     return HAL_ERROR;
2397   }
2398 
2399   /* Check nodes types compatibility */
2400   if (DMA_List_CheckNodesTypes(pSrcQList->Head, pDestQList->Head, NULL) != 0U)
2401   {
2402     /* Update the source queue error code */
2403     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2404 
2405     /* Update the destination queue error code */
2406     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2407 
2408     return HAL_ERROR;
2409   }
2410 
2411   /* Update the source queue state */
2412   pSrcQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2413 
2414   /* Update the source queue error code */
2415   pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2416 
2417   /* Update the destination queue state */
2418   pDestQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2419 
2420   /* Update the destination queue error code */
2421   pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2422 
2423   /* Get CLLR register mask and offset */
2424   DMA_List_GetCLLRNodeInfo(pSrcQList->Head, &cllr_mask, &cllr_offset);
2425 
2426   /* Empty destination queue */
2427   if (pDestQList->Head == NULL)
2428   {
2429     pDestQList->Head       = pSrcQList->Head;
2430     pDestQList->NodeNumber = pSrcQList->NodeNumber;
2431   }
2432   /* Not empty destination queue */
2433   else
2434   {
2435     /* Find node and get its position in selected queue */
2436     src_q_node_info.cllr_offset = cllr_offset;
2437     (void)DMA_List_FindNode(pSrcQList, NULL, &src_q_node_info);
2438 
2439     /* Check if first circular node queue is the first node */
2440     if (pDestQList->FirstCircularNode == pDestQList->Head)
2441     {
2442       /* Find node and get its position in selected queue */
2443       dest_q_node_info.cllr_offset = cllr_offset;
2444       (void)DMA_List_FindNode(pDestQList, NULL, &dest_q_node_info);
2445 
2446       /* Link destination queue tail node to new first circular node */
2447       ((DMA_NodeTypeDef *)dest_q_node_info.currentnode_addr)->LinkRegisters[cllr_offset] =
2448         ((uint32_t)pSrcQList->Head & DMA_CLLR_LA) | cllr_mask;
2449 
2450       /* Set the head node of source queue as the first circular node */
2451       pDestQList->FirstCircularNode = pSrcQList->Head;
2452     }
2453 
2454     /* Link the last node of source queue to the fist node of destination queue */
2455     ((DMA_NodeTypeDef *)(src_q_node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
2456       ((uint32_t)pDestQList->Head & DMA_CLLR_LA) | cllr_mask;
2457     pDestQList->Head        = pSrcQList->Head;
2458     pDestQList->NodeNumber += pSrcQList->NodeNumber;
2459   }
2460 
2461   /* Clean the source queue variable as it is obsolete */
2462   DMA_List_CleanQueue(pSrcQList);
2463 
2464   /* Update the destination queue error code */
2465   pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2466 
2467   /* Update the destination queue state */
2468   pDestQList->State = HAL_DMA_QUEUE_STATE_READY;
2469 
2470   /* Prevent MISRA-C2012-Rule-2.2_b */
2471   UNUSED(src_q_node_info);
2472   UNUSED(dest_q_node_info);
2473 
2474   return HAL_OK;
2475 }
2476 
2477 /**
2478   * @brief  Insert a source linked-list queue at the tail of destination queue.
2479   * @param  pSrcQList  : Pointer to a DMA_QListTypeDef structure that contains source queue information.
2480   * @param  pDestQList : Pointer to a DMA_QListTypeDef structure that contains destination queue information.
2481   * @retval HAL status.
2482   */
HAL_DMAEx_List_InsertQ_Tail(DMA_QListTypeDef * const pSrcQList,DMA_QListTypeDef * const pDestQList)2483 HAL_StatusTypeDef HAL_DMAEx_List_InsertQ_Tail(DMA_QListTypeDef *const pSrcQList,
2484                                               DMA_QListTypeDef *const pDestQList)
2485 {
2486   uint32_t cllr_mask;
2487   uint32_t cllr_offset;
2488   DMA_NodeInQInfoTypeDef src_q_node_info;
2489   DMA_NodeInQInfoTypeDef dest_q_node_info;
2490 
2491   /* Check the source and destination queues and the previous node parameters */
2492   if ((pSrcQList == NULL) || (pDestQList == NULL))
2493   {
2494     return HAL_ERROR;
2495   }
2496 
2497   /* Check the source queue */
2498   if (pSrcQList->Head == NULL)
2499   {
2500     /* Update the queue error code */
2501     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
2502 
2503     return HAL_ERROR;
2504   }
2505 
2506   /* Check the source queue type */
2507   if (pSrcQList->Type == QUEUE_TYPE_DYNAMIC)
2508   {
2509     /* Update the queue error code */
2510     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2511 
2512     return HAL_ERROR;
2513   }
2514 
2515   /* Check the destination queue type */
2516   if (pDestQList->Type == QUEUE_TYPE_DYNAMIC)
2517   {
2518     /* Update the queue error code */
2519     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2520 
2521     return HAL_ERROR;
2522   }
2523 
2524   /* Check nodes base addresses */
2525   if (DMA_List_CheckNodesBaseAddresses(pSrcQList->Head, pDestQList->Head, NULL) != 0U)
2526   {
2527     /* Update the source queue error code */
2528     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
2529 
2530     /* Update the destination queue error code */
2531     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_OUTOFRANGE;
2532 
2533     return HAL_ERROR;
2534   }
2535 
2536   /* Check nodes types compatibility */
2537   if (DMA_List_CheckNodesTypes(pSrcQList->Head, pDestQList->Head, NULL) != 0U)
2538   {
2539     /* Update the source queue error code */
2540     pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2541 
2542     /* Update the destination queue error code */
2543     pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2544 
2545     return HAL_ERROR;
2546   }
2547 
2548   /* Update the source queue state */
2549   pSrcQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2550 
2551   /* Update the source queue error code */
2552   pSrcQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2553 
2554   /* Update the destination queue state */
2555   pDestQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2556 
2557   /* Update the destination queue error code */
2558   pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2559 
2560   /* Get CLLR register mask and offset */
2561   DMA_List_GetCLLRNodeInfo(pSrcQList->Head, &cllr_mask, &cllr_offset);
2562 
2563   /* Empty destination queue */
2564   if (pDestQList->Head == NULL)
2565   {
2566     pDestQList->Head       = pSrcQList->Head;
2567     pDestQList->NodeNumber = pSrcQList->NodeNumber;
2568   }
2569   /* Not empty destination queue */
2570   else
2571   {
2572     /* Find node and get its position in selected queue */
2573     dest_q_node_info.cllr_offset = cllr_offset;
2574     (void)DMA_List_FindNode(pDestQList, NULL, &dest_q_node_info);
2575 
2576     /* Update source queue last node CLLR to link it with destination first node */
2577     ((DMA_NodeTypeDef *)(dest_q_node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
2578       ((uint32_t)pSrcQList->Head & DMA_CLLR_LA) | cllr_mask;
2579     pDestQList->NodeNumber += pSrcQList->NodeNumber;
2580 
2581     /* Check if first circular node queue is not empty */
2582     if (pDestQList->FirstCircularNode != NULL)
2583     {
2584       /* Find node and get its position in selected queue */
2585       src_q_node_info.cllr_offset = cllr_offset;
2586       (void)DMA_List_FindNode(pSrcQList, NULL, &src_q_node_info);
2587 
2588       /* Find first circular node */
2589       (void)DMA_List_FindNode(pDestQList, pDestQList->FirstCircularNode, &dest_q_node_info);
2590 
2591       /* Link last source queue node to first destination queue */
2592       ((DMA_NodeTypeDef *)src_q_node_info.currentnode_addr)->LinkRegisters[cllr_offset] =
2593         (dest_q_node_info.currentnode_addr & DMA_CLLR_LA) | cllr_mask;
2594     }
2595   }
2596 
2597   /* Clean the source queue variable as it is obsolete */
2598   DMA_List_CleanQueue(pSrcQList);
2599 
2600   /* Update the destination queue error code */
2601   pDestQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2602 
2603   /* Update the destination queue state */
2604   pDestQList->State = HAL_DMA_QUEUE_STATE_READY;
2605 
2606   /* Prevent MISRA-C2012-Rule-2.2_b */
2607   UNUSED(src_q_node_info);
2608 
2609   return HAL_OK;
2610 }
2611 
2612 /**
2613   * @brief  Set circular mode configuration for linked-list queue.
2614   * @param  pQList             : Pointer to a DMA_QListTypeDef structure that contains queue information.
2615   * @param  pFirstCircularNode : Pointer to a DMA_NodeTypeDef structure that contains linked-list first circular node
2616   *                              registers configurations.
2617   * @retval HAL status.
2618   */
HAL_DMAEx_List_SetCircularModeConfig(DMA_QListTypeDef * const pQList,DMA_NodeTypeDef * const pFirstCircularNode)2619 HAL_StatusTypeDef HAL_DMAEx_List_SetCircularModeConfig(DMA_QListTypeDef *const pQList,
2620                                                        DMA_NodeTypeDef *const pFirstCircularNode)
2621 {
2622   uint32_t cllr_mask;
2623   uint32_t cllr_offset;
2624   DMA_NodeInQInfoTypeDef node_info;
2625 
2626   /* Check the queue and the first circular node parameters */
2627   if ((pQList == NULL) || (pFirstCircularNode == NULL))
2628   {
2629     return HAL_ERROR;
2630   }
2631 
2632   /* Check the queue */
2633   if (pQList->Head == NULL)
2634   {
2635     /* Update the queue error code */
2636     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
2637 
2638     return HAL_ERROR;
2639   }
2640 
2641   /* Check queue circular mode */
2642   if (pQList->FirstCircularNode != NULL)
2643   {
2644     if (pQList->FirstCircularNode == pFirstCircularNode)
2645     {
2646       return HAL_OK;
2647     }
2648     else
2649     {
2650       /* Update the queue error code */
2651       pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2652 
2653       return HAL_ERROR;
2654     }
2655   }
2656 
2657   /* Check queue type */
2658   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
2659   {
2660     /* Update the queue error code */
2661     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2662 
2663     return HAL_ERROR;
2664   }
2665 
2666   /* Update the queue state */
2667   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2668 
2669   /* Update the queue error code */
2670   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2671 
2672   /* Get CLLR register mask and offset */
2673   DMA_List_GetCLLRNodeInfo(pFirstCircularNode, &cllr_mask, &cllr_offset);
2674 
2675   /* Find the first circular node and get its position in selected queue */
2676   node_info.cllr_offset = cllr_offset;
2677   if (DMA_List_FindNode(pQList, pFirstCircularNode, &node_info) == 0U)
2678   {
2679     /* Find the last queue node and get its position in selected queue */
2680     (void)DMA_List_FindNode(pQList, NULL, &node_info);
2681 
2682     /* Set circular mode */
2683     ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
2684       ((uint32_t)pFirstCircularNode & DMA_CLLR_LA) | cllr_mask;
2685 
2686     /* Update first circular node in queue */
2687     pQList->FirstCircularNode = pFirstCircularNode;
2688   }
2689   else
2690   {
2691     /* Update the queue error code */
2692     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NOTFOUND;
2693 
2694     return HAL_ERROR;
2695   }
2696 
2697   /* Update the queue error code */
2698   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2699 
2700   /* Update the queue state */
2701   pQList->State = HAL_DMA_QUEUE_STATE_READY;
2702 
2703   /* Prevent MISRA-C2012-Rule-2.2_b */
2704   UNUSED(node_info);
2705 
2706   return HAL_OK;
2707 }
2708 
2709 /**
2710   * @brief  Set circular mode for linked-list queue.
2711   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
2712   * @retval HAL status.
2713   */
HAL_DMAEx_List_SetCircularMode(DMA_QListTypeDef * const pQList)2714 HAL_StatusTypeDef HAL_DMAEx_List_SetCircularMode(DMA_QListTypeDef *const pQList)
2715 {
2716   uint32_t cllr_mask;
2717   uint32_t cllr_offset;
2718   DMA_NodeInQInfoTypeDef node_info;
2719 
2720   /* Check the queue parameter */
2721   if (pQList == NULL)
2722   {
2723     return HAL_ERROR;
2724   }
2725 
2726   /* Check the queue */
2727   if (pQList->Head == NULL)
2728   {
2729     /* Update the queue error code */
2730     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
2731 
2732     return HAL_ERROR;
2733   }
2734 
2735   /* Check queue circular mode */
2736   if (pQList->FirstCircularNode != NULL)
2737   {
2738     if (pQList->FirstCircularNode == pQList->Head)
2739     {
2740       return HAL_OK;
2741     }
2742     else
2743     {
2744       /* Update the queue error code */
2745       pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2746 
2747       return HAL_ERROR;
2748     }
2749   }
2750 
2751   /* Check queue type */
2752   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
2753   {
2754     /* Update the queue error code */
2755     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2756 
2757     return HAL_ERROR;
2758   }
2759 
2760   /* Update the queue state */
2761   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2762 
2763   /* Update the queue error code */
2764   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2765 
2766   /* Get CLLR register mask and offset */
2767   DMA_List_GetCLLRNodeInfo(pQList->Head, &cllr_mask, &cllr_offset);
2768 
2769   /* Find the last queue node and get its position in selected queue */
2770   node_info.cllr_offset = cllr_offset;
2771   (void)DMA_List_FindNode(pQList, NULL, &node_info);
2772 
2773   /* Set circular mode */
2774   ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] =
2775     ((uint32_t)pQList->Head & DMA_CLLR_LA) | cllr_mask;
2776 
2777   /* Update linked-list circular state */
2778   pQList->FirstCircularNode = pQList->Head;
2779 
2780   /* Update the queue error code */
2781   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2782 
2783   /* Update the queue state */
2784   pQList->State = HAL_DMA_QUEUE_STATE_READY;
2785 
2786   /* Prevent MISRA-C2012-Rule-2.2_b */
2787   UNUSED(node_info);
2788 
2789   return HAL_OK;
2790 }
2791 
2792 /**
2793   * @brief  Clear circular mode for linked-list queue.
2794   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
2795   * @retval HAL status.
2796   */
HAL_DMAEx_List_ClearCircularMode(DMA_QListTypeDef * const pQList)2797 HAL_StatusTypeDef HAL_DMAEx_List_ClearCircularMode(DMA_QListTypeDef *const pQList)
2798 {
2799   uint32_t cllr_offset;
2800   DMA_NodeInQInfoTypeDef node_info;
2801 
2802   /* Check the queue parameter */
2803   if (pQList == NULL)
2804   {
2805     return HAL_ERROR;
2806   }
2807 
2808   /* Check the queue */
2809   if (pQList->Head == NULL)
2810   {
2811     /* Update the queue error code */
2812     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
2813 
2814     return HAL_ERROR;
2815   }
2816 
2817   /* Check queue circular mode */
2818   if (pQList->FirstCircularNode == NULL)
2819   {
2820     return HAL_OK;
2821   }
2822 
2823   /* Check queue type */
2824   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
2825   {
2826     /* Update the queue error code */
2827     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
2828 
2829     return HAL_ERROR;
2830   }
2831 
2832   /* Update the queue state */
2833   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2834 
2835   /* Update the queue error code */
2836   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2837 
2838   /* Get CLLR register offset */
2839   DMA_List_GetCLLRNodeInfo(pQList->Head, NULL, &cllr_offset);
2840 
2841   /* Find the last queue node and get its position in selected queue */
2842   node_info.cllr_offset = cllr_offset;
2843   (void)DMA_List_FindNode(pQList, NULL, &node_info);
2844 
2845   /* Clear circular mode */
2846   ((DMA_NodeTypeDef *)(node_info.currentnode_addr))->LinkRegisters[cllr_offset] = 0U;
2847 
2848   /* Update linked-list circular configuration */
2849   pQList->FirstCircularNode = NULL;
2850 
2851   /* Update the queue error code */
2852   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2853 
2854   /* Update the queue state */
2855   pQList->State = HAL_DMA_QUEUE_STATE_READY;
2856 
2857   /* Prevent MISRA-C2012-Rule-2.2_b */
2858   UNUSED(node_info);
2859 
2860   return HAL_OK;
2861 }
2862 
2863 /**
2864   * @brief  Convert a linked-list queue to dynamic (Optimized DMA queue execution).
2865   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
2866   * @retval HAL status.
2867   */
HAL_DMAEx_List_ConvertQToDynamic(DMA_QListTypeDef * const pQList)2868 HAL_StatusTypeDef HAL_DMAEx_List_ConvertQToDynamic(DMA_QListTypeDef *const pQList)
2869 {
2870   uint32_t cllr_offset;
2871   uint32_t currentnode_addr;
2872   DMA_NodeTypeDef context_node;
2873   DMA_NodeInQInfoTypeDef node_info;
2874 
2875   /* Check the queue parameter */
2876   if (pQList == NULL)
2877   {
2878     return HAL_ERROR;
2879   }
2880 
2881   /* Check the queue */
2882   if (pQList->Head == NULL)
2883   {
2884     /* Update the queue error code */
2885     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
2886 
2887     return HAL_ERROR;
2888   }
2889 
2890   /* Check if queue is dynamic */
2891   if (pQList->Type == QUEUE_TYPE_DYNAMIC)
2892   {
2893     return HAL_OK;
2894   }
2895 
2896   /* Update the queue state */
2897   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
2898 
2899   /* Update the queue error code */
2900   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2901 
2902   /* Get CLLR register mask and offset */
2903   DMA_List_GetCLLRNodeInfo(pQList->Head, NULL, &cllr_offset);
2904 
2905   /* Check queue circularity */
2906   if (pQList->FirstCircularNode != 0U)
2907   {
2908     /* Find the last queue node and get its position in selected queue */
2909     node_info.cllr_offset = cllr_offset;
2910     (void)DMA_List_FindNode(pQList, NULL, &node_info);
2911   }
2912 
2913   /* Set current node address */
2914   currentnode_addr = (uint32_t)pQList->Head;
2915 
2916   /* Store register value */
2917   DMA_List_FillNode(pQList->Head, &context_node);
2918 
2919   /* Convert all nodes to dyncamic (Bypass head node) */
2920   for (uint32_t node_count = 1U; node_count < pQList->NodeNumber; node_count++)
2921   {
2922     /* Update node address */
2923     MODIFY_REG(currentnode_addr, DMA_CLLR_LA, (context_node.LinkRegisters[cllr_offset] & DMA_CLLR_LA));
2924 
2925     /* Bypass the first circular node when first circular node isn't the last queue node */
2926     if (((uint32_t)pQList->FirstCircularNode != 0U)                         &&
2927         ((uint32_t)pQList->FirstCircularNode != node_info.currentnode_addr) &&
2928         ((uint32_t)pQList->FirstCircularNode == currentnode_addr))
2929     {
2930       /* Copy first circular node to context node */
2931       DMA_List_FillNode(pQList->FirstCircularNode, &context_node);
2932     }
2933     else
2934     {
2935       /* Convert current node to dynamic */
2936       DMA_List_ConvertNodeToDynamic((uint32_t)&context_node, currentnode_addr, (cllr_offset + 1U));
2937     }
2938   }
2939 
2940   /* Check if first circular node is the last node queue */
2941   if (((uint32_t)pQList->FirstCircularNode != 0U) &&
2942       ((uint32_t)pQList->FirstCircularNode != node_info.currentnode_addr))
2943   {
2944     /* Update all queue nodes CLLR */
2945     DMA_List_UpdateDynamicQueueNodesCLLR(pQList, LASTNODE_ISNOT_CIRCULAR);
2946   }
2947   else
2948   {
2949     /* Update all queue nodes CLLR */
2950     DMA_List_UpdateDynamicQueueNodesCLLR(pQList, LASTNODE_IS_CIRCULAR);
2951   }
2952 
2953   /* Set queue type */
2954   pQList->Type = QUEUE_TYPE_DYNAMIC;
2955 
2956   /* Update the queue error code */
2957   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
2958 
2959   /* Update the queue state */
2960   pQList->State = HAL_DMA_QUEUE_STATE_READY;
2961 
2962   return HAL_OK;
2963 }
2964 
2965 /**
2966   * @brief  Convert a linked-list queue to static (Not optimized DMA queue execution).
2967   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
2968   * @retval HAL status.
2969   */
HAL_DMAEx_List_ConvertQToStatic(DMA_QListTypeDef * const pQList)2970 HAL_StatusTypeDef HAL_DMAEx_List_ConvertQToStatic(DMA_QListTypeDef *const pQList)
2971 {
2972   uint32_t cllr_offset;
2973   uint32_t currentnode_addr;
2974   DMA_NodeTypeDef context_node;
2975 
2976   /* Check the queue parameter */
2977   if (pQList == NULL)
2978   {
2979     return HAL_ERROR;
2980   }
2981 
2982   /* Check the queue */
2983   if (pQList->Head == NULL)
2984   {
2985     /* Update the queue error code */
2986     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_EMPTY;
2987 
2988     return HAL_ERROR;
2989   }
2990 
2991   /* Check if queue is static */
2992   if (pQList->Type == QUEUE_TYPE_STATIC)
2993   {
2994     return HAL_OK;
2995   }
2996 
2997   /* Set current node address */
2998   currentnode_addr = (uint32_t)pQList->Head;
2999 
3000   /* Update the queue state */
3001   pQList->State = HAL_DMA_QUEUE_STATE_BUSY;
3002 
3003   /* Update the queue error code */
3004   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
3005 
3006   /* Get CLLR register mask and offset */
3007   DMA_List_GetCLLRNodeInfo(pQList->Head, NULL, &cllr_offset);
3008 
3009   /* Set all CLLR queue nodes to their default positions */
3010   DMA_List_UpdateStaticQueueNodesCLLR(pQList, UPDATE_CLLR_POSITION);
3011 
3012   /* Convert all nodes to static (Bypass head node) */
3013   for (uint32_t node_count = 1U; node_count < pQList->NodeNumber; node_count++)
3014   {
3015     /* Update context node register values */
3016     DMA_List_FillNode((DMA_NodeTypeDef *)currentnode_addr, &context_node);
3017 
3018     /* Update node address */
3019     MODIFY_REG(currentnode_addr, DMA_CLLR_LA, (context_node.LinkRegisters[cllr_offset] & DMA_CLLR_LA));
3020 
3021     /* Convert current node to static */
3022     DMA_List_ConvertNodeToStatic((uint32_t)&context_node, currentnode_addr, (cllr_offset + 1U));
3023   }
3024 
3025   /* Set all CLLR queue nodes to their default values */
3026   DMA_List_UpdateStaticQueueNodesCLLR(pQList, UPDATE_CLLR_VALUE);
3027 
3028   /* Set queue type */
3029   pQList->Type = QUEUE_TYPE_STATIC;
3030 
3031   /* Update the queue error code */
3032   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
3033 
3034   /* Update the queue state */
3035   pQList->State = HAL_DMA_QUEUE_STATE_READY;
3036 
3037   return HAL_OK;
3038 }
3039 
3040 /**
3041   * @brief  Link linked-list queue to a DMA channel.
3042   * @param  hdma   : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
3043   *                  specified DMA Channel.
3044   * @param  pQList : Pointer to a DMA_QListTypeDef structure that contains queue information.
3045   * @retval HAL status.
3046   */
HAL_DMAEx_List_LinkQ(DMA_HandleTypeDef * const hdma,DMA_QListTypeDef * const pQList)3047 HAL_StatusTypeDef HAL_DMAEx_List_LinkQ(DMA_HandleTypeDef *const hdma,
3048                                        DMA_QListTypeDef *const pQList)
3049 {
3050   HAL_DMA_StateTypeDef state;
3051 
3052   /* Check the DMA channel handle and the queue parameters */
3053   if ((hdma == NULL) || (pQList == NULL))
3054   {
3055     return HAL_ERROR;
3056   }
3057 
3058   /* Get DMA state */
3059   state = hdma->State;
3060 
3061   /* Check DMA channel state */
3062   if ((hdma->State == HAL_DMA_STATE_BUSY) || (state == HAL_DMA_STATE_SUSPEND))
3063   {
3064     /* Update the DMA channel error code */
3065     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
3066 
3067     /* Process unlocked */
3068     __HAL_UNLOCK(hdma);
3069 
3070     return HAL_ERROR;
3071   }
3072 
3073   /* Check queue state */
3074   if (pQList->State == HAL_DMA_QUEUE_STATE_BUSY)
3075   {
3076     /* Update the queue error code */
3077     pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_BUSY;
3078 
3079     return HAL_ERROR;
3080   }
3081 
3082   /* Check circularity compatibility */
3083   if (hdma->Mode == DMA_LINKEDLIST_CIRCULAR)
3084   {
3085     /* Check first circular node */
3086     if (pQList->FirstCircularNode == NULL)
3087     {
3088       /* Update the queue error code */
3089       pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
3090 
3091       return HAL_ERROR;
3092     }
3093   }
3094   else
3095   {
3096     /* Check first circular node */
3097     if (pQList->FirstCircularNode != NULL)
3098     {
3099       /* Update the queue error code */
3100       pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_INVALIDTYPE;
3101 
3102       return HAL_ERROR;
3103     }
3104   }
3105 
3106   /* Register queue to DMA handle */
3107   hdma->LinkedListQueue = pQList;
3108 
3109   return HAL_OK;
3110 }
3111 
3112 /**
3113   * @brief  Unlink linked-list queue from a DMA channel.
3114   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
3115   *                specified DMA Channel.
3116   * @retval HAL status.
3117   */
HAL_DMAEx_List_UnLinkQ(DMA_HandleTypeDef * const hdma)3118 HAL_StatusTypeDef HAL_DMAEx_List_UnLinkQ(DMA_HandleTypeDef *const hdma)
3119 {
3120   HAL_DMA_StateTypeDef state;
3121 
3122   /* Check the DMA channel parameter */
3123   if (hdma == NULL)
3124   {
3125     return HAL_ERROR;
3126   }
3127 
3128   /* Get DMA state */
3129   state = hdma->State;
3130 
3131   /* Check DMA channel state */
3132   if ((hdma->State == HAL_DMA_STATE_BUSY) || (state == HAL_DMA_STATE_SUSPEND))
3133   {
3134     /* Update the DMA channel error code */
3135     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
3136 
3137     /* Process unlocked */
3138     __HAL_UNLOCK(hdma);
3139 
3140     return HAL_ERROR;
3141   }
3142 
3143   /* Clear queue information from DMA channel handle */
3144   hdma->LinkedListQueue = NULL;
3145 
3146   return HAL_OK;
3147 }
3148 /**
3149   * @}
3150   */
3151 
3152 /** @addtogroup DMAEx_Exported_Functions_Group4
3153   *
3154 @verbatim
3155   ======================================================================================================================
3156              ##### Data handling, repeated block and trigger configuration functions #####
3157   ======================================================================================================================
3158     [..]
3159       This section provides functions allowing to :
3160       (+) Configure DMA channel data handling.
3161       (+) Configure DMA channel repeated block.
3162       (+) Configure DMA channel trigger.
3163 
3164     [..]
3165       (+) The HAL_DMAEx_ConfigDataHandling() function allows to configure DMA channel data handling.
3166               (++) GPDMA data handling : byte-based reordering, packing/unpacking, padding/truncation, sign extension
3167                                          and left/right alignment.
3168 
3169       (+) The HAL_DMAEx_ConfigTrigger() function allows to configure DMA channel HW triggers.
3170 
3171 @endverbatim
3172   * @{
3173   */
3174 
3175 /**
3176   * @brief  Configure the DMA channel data handling according to the specified parameters in the
3177   *         DMA_DataHandlingConfTypeDef.
3178   * @param  hdma                : Pointer to a DMA_HandleTypeDef structure that contains the configuration information
3179   *                               for the specified DMA Channel.
3180   * @param  pConfigDataHandling : Pointer to a DMA_DataHandlingConfTypeDef structure that contains the data handling
3181   *                               configuration.
3182   * @retval HAL status.
3183   */
HAL_DMAEx_ConfigDataHandling(DMA_HandleTypeDef * const hdma,DMA_DataHandlingConfTypeDef const * const pConfigDataHandling)3184 HAL_StatusTypeDef HAL_DMAEx_ConfigDataHandling(DMA_HandleTypeDef *const hdma,
3185                                                DMA_DataHandlingConfTypeDef const *const pConfigDataHandling)
3186 {
3187   /* Check the DMA peripheral handle and data handling parameters */
3188   if ((hdma == NULL) || (pConfigDataHandling == NULL))
3189   {
3190     return HAL_ERROR;
3191   }
3192 
3193   /* Check the parameters */
3194   assert_param(IS_DMA_DATA_ALIGNMENT(pConfigDataHandling->DataAlignment));
3195   assert_param(IS_DMA_DATA_EXCHANGE(pConfigDataHandling->DataExchange));
3196 
3197   /* Check DMA channel state */
3198   if (hdma->State == HAL_DMA_STATE_READY)
3199   {
3200     MODIFY_REG(hdma->Instance->CTR1, (DMA_CTR1_DHX | DMA_CTR1_DBX | DMA_CTR1_SBX | DMA_CTR1_PAM),
3201                (pConfigDataHandling->DataAlignment | pConfigDataHandling->DataExchange));
3202   }
3203   else
3204   {
3205     /* Update the DMA channel error code */
3206     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
3207 
3208     /* Process unlocked */
3209     __HAL_UNLOCK(hdma);
3210 
3211     return HAL_ERROR;
3212   }
3213 
3214   return HAL_OK;
3215 }
3216 
3217 /**
3218   * @brief  Configure the DMA channel trigger according to the specified parameters in the DMA_TriggerConfTypeDef.
3219   * @param  hdma           : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for
3220   *                          the specified DMA Channel.
3221   * @param  pConfigTrigger : Pointer to a DMA_TriggerConfTypeDef structure that contains the trigger configuration.
3222   * @retval HAL status.
3223   */
HAL_DMAEx_ConfigTrigger(DMA_HandleTypeDef * const hdma,DMA_TriggerConfTypeDef const * const pConfigTrigger)3224 HAL_StatusTypeDef HAL_DMAEx_ConfigTrigger(DMA_HandleTypeDef *const hdma,
3225                                           DMA_TriggerConfTypeDef const *const pConfigTrigger)
3226 {
3227   /* Check the DMA peripheral handle and trigger parameters */
3228   if ((hdma == NULL) || (pConfigTrigger == NULL))
3229   {
3230     return HAL_ERROR;
3231   }
3232 
3233   /* Check the parameters */
3234   assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
3235   assert_param(IS_DMA_TRIGGER_POLARITY(pConfigTrigger->TriggerPolarity));
3236   assert_param(IS_DMA_TRIGGER_MODE(pConfigTrigger->TriggerMode));
3237   assert_param(IS_DMA_TRIGGER_SELECTION(pConfigTrigger->TriggerSelection));
3238 
3239   /* Check DMA channel state */
3240   if (hdma->State == HAL_DMA_STATE_READY)
3241   {
3242     MODIFY_REG(hdma->Instance->CTR2, (DMA_CTR2_TRIGPOL | DMA_CTR2_TRIGSEL | DMA_CTR2_TRIGM),
3243                (pConfigTrigger->TriggerPolarity | pConfigTrigger->TriggerMode |
3244                 (pConfigTrigger->TriggerSelection << DMA_CTR2_TRIGSEL_Pos)));
3245   }
3246   else
3247   {
3248     /* Update the DMA channel error code */
3249     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
3250 
3251     /* Process unlocked */
3252     __HAL_UNLOCK(hdma);
3253 
3254     return HAL_ERROR;
3255   }
3256 
3257   return HAL_OK;
3258 }
3259 
3260 /**
3261   * @}
3262   */
3263 
3264 /** @addtogroup DMAEx_Exported_Functions_Group5
3265   *
3266 @verbatim
3267   ======================================================================================================================
3268                          ##### Suspend and resume operation functions #####
3269   ======================================================================================================================
3270     [..]
3271       This section provides functions allowing to :
3272       (+) Suspend any ongoing DMA channel transfer.
3273       (+) Resume any suspended DMA channel transfer.
3274 
3275     [..]
3276       (+) The HAL_DMAEx_Suspend() function allows to suspend any ongoing DMA channel transfer in polling mode (Blocking
3277           mode).
3278 
3279       (+) The HAL_DMAEx_Suspend_IT() function allows to suspend any ongoing DMA channel transfer in interrupt mode
3280          (Non-blocking mode).
3281 
3282       (+) The HAL_DMAEx_Resume() function allows to resume any suspended DMA channel transfer.
3283 
3284 @endverbatim
3285   * @{
3286   */
3287 
3288 /**
3289   * @brief  Suspend any ongoing DMA channel transfer in polling mode (Blocking mode).
3290   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
3291   *                specified DMA channel.
3292   * @note   After suspending a DMA channel, a check for wait until the DMA channel is effectively suspended is added. If
3293   *         a channel is suspended while a data transfer is ongoing, the current data will be transferred and the
3294   *         channel will be effectively suspended only after the transfer of this single/burst data is finished.
3295   * @retval HAL status.
3296   */
HAL_DMAEx_Suspend(DMA_HandleTypeDef * const hdma)3297 HAL_StatusTypeDef HAL_DMAEx_Suspend(DMA_HandleTypeDef *const hdma)
3298 {
3299   /* Get tick number */
3300   uint32_t tickstart = HAL_GetTick();
3301 
3302   /* Check the DMA peripheral handle */
3303   if (hdma == NULL)
3304   {
3305     return HAL_ERROR;
3306   }
3307 
3308   /* Check DMA channel state */
3309   if (hdma->State != HAL_DMA_STATE_BUSY)
3310   {
3311     /* Update the DMA channel error code */
3312     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
3313 
3314     /* Process unlocked */
3315     __HAL_UNLOCK(hdma);
3316 
3317     return HAL_ERROR;
3318   }
3319   else
3320   {
3321     /* Suspend the channel */
3322     hdma->Instance->CCR |= DMA_CCR_SUSP;
3323 
3324     /* Check if the DMA channel is suspended */
3325     while ((hdma->Instance->CSR & DMA_CSR_SUSPF) == 0U)
3326     {
3327       /* Check for the timeout */
3328       if ((HAL_GetTick() - tickstart) > HAL_TIMEOUT_DMA_ABORT)
3329       {
3330         /* Update the DMA channel error code */
3331         hdma->ErrorCode |= HAL_DMA_ERROR_TIMEOUT;
3332 
3333         /* Update the DMA channel state */
3334         hdma->State = HAL_DMA_STATE_ERROR;
3335 
3336         /* Process Unlocked */
3337         __HAL_UNLOCK(hdma);
3338 
3339         return HAL_ERROR;
3340       }
3341     }
3342 
3343     /* Update the DMA channel state */
3344     hdma->State = HAL_DMA_STATE_SUSPEND;
3345   }
3346 
3347   return HAL_OK;
3348 }
3349 
3350 /**
3351   * @brief  Suspend any ongoing DMA channel transfer in polling mode (Non-blocking mode).
3352   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
3353   *                specified DMA Channel.
3354   * @retval HAL status.
3355   */
HAL_DMAEx_Suspend_IT(DMA_HandleTypeDef * const hdma)3356 HAL_StatusTypeDef HAL_DMAEx_Suspend_IT(DMA_HandleTypeDef *const hdma)
3357 {
3358   /* Check the DMA peripheral handle parameter */
3359   if (hdma == NULL)
3360   {
3361     return HAL_ERROR;
3362   }
3363 
3364   /* Check DMA channel state */
3365   if (hdma->State != HAL_DMA_STATE_BUSY)
3366   {
3367     /* Update the DMA channel error code */
3368     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
3369 
3370     /* Process unlocked */
3371     __HAL_UNLOCK(hdma);
3372 
3373     return HAL_ERROR;
3374   }
3375   else
3376   {
3377     /* Suspend the DMA channel and activate suspend interrupt */
3378     hdma->Instance->CCR |= (DMA_CCR_SUSP | DMA_CCR_SUSPIE);
3379   }
3380 
3381   return HAL_OK;
3382 }
3383 
3384 /**
3385   * @brief  Resume any suspended DMA channel transfer.
3386   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
3387   *                specified DMA Channel.
3388   * @retval HAL status.
3389   */
HAL_DMAEx_Resume(DMA_HandleTypeDef * const hdma)3390 HAL_StatusTypeDef HAL_DMAEx_Resume(DMA_HandleTypeDef *const hdma)
3391 {
3392   /* Check the DMA peripheral handle parameter */
3393   if (hdma == NULL)
3394   {
3395     return HAL_ERROR;
3396   }
3397 
3398   /* Check DMA channel state */
3399   if (hdma->State != HAL_DMA_STATE_SUSPEND)
3400   {
3401     /* Update the DMA channel error code */
3402     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
3403 
3404     /* Process unlocked */
3405     __HAL_UNLOCK(hdma);
3406 
3407     return HAL_ERROR;
3408   }
3409   else
3410   {
3411     /* Resume the DMA channel */
3412     hdma->Instance->CCR &= (~DMA_CCR_SUSP);
3413 
3414     /* Clear the suspend flag */
3415     hdma->Instance->CFCR |= DMA_CFCR_SUSPF;
3416 
3417     /* Update the DMA channel state */
3418     hdma->State = HAL_DMA_STATE_BUSY;
3419   }
3420 
3421   return HAL_OK;
3422 }
3423 /**
3424   * @}
3425   */
3426 
3427 /** @addtogroup DMAEx_Exported_Functions_Group6
3428   *
3429 @verbatim
3430   ======================================================================================================================
3431                                ##### Fifo status function #####
3432   ======================================================================================================================
3433     [..]
3434       This section provides function allowing to get DMA channel FIFO level.
3435 
3436     [..]
3437       (+) The HAL_DMAEx_GetFifoLevel() function allows to return the number of available write beats in the FIFO, in
3438           units of the programmed destination data.
3439               (++) This API is available only for DMA channels that supports FIFO.
3440 
3441 @endverbatim
3442   * @{
3443   */
3444 
3445 /**
3446   * @brief  Get and returns the DMA channel FIFO level.
3447   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
3448   *                specified DMA Channel.
3449   * @retval Returns the number of available beats in FIFO.
3450   */
HAL_DMAEx_GetFifoLevel(DMA_HandleTypeDef const * const hdma)3451 uint32_t HAL_DMAEx_GetFifoLevel(DMA_HandleTypeDef const *const hdma)
3452 {
3453   return ((hdma->Instance->CSR & DMA_CSR_FIFOL) >> DMA_CSR_FIFOL_Pos);
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 /* defined (__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     /* Check for GPDMA */
3564     if ((pNodeConfig->NodeType & DMA_CHANNEL_TYPE_GPDMA) == DMA_CHANNEL_TYPE_GPDMA)
3565     {
3566       pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET] |= DMA_CTR2_DREQ;
3567     }
3568   }
3569   /* Memory to memory transfer */
3570   else if ((pNodeConfig->Init.Direction) == DMA_MEMORY_TO_MEMORY)
3571   {
3572     pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET] |= DMA_CTR2_SWREQ;
3573   }
3574   else
3575   {
3576     /* Prevent MISRA-C2012-Rule-15.7 */
3577   }
3578 
3579   /* Check if trigger feature is active */
3580   if (pNodeConfig->TriggerConfig.TriggerPolarity != DMA_TRIG_POLARITY_MASKED)
3581   {
3582     /* Prepare DMA channel transfer register 2 (CTR2) value */
3583     pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET] |=
3584       pNodeConfig->TriggerConfig.TriggerMode | pNodeConfig->TriggerConfig.TriggerPolarity |
3585       ((pNodeConfig->TriggerConfig.TriggerSelection << DMA_CTR2_TRIGSEL_Pos) & DMA_CTR2_TRIGSEL);
3586   }
3587   /*********************************************************************************** CTR2 register value is updated */
3588 
3589 
3590   /* Update CBR1 register value ***************************************************************************************/
3591   /* Prepare DMA channel block register 1 (CBR1) value */
3592   pNode->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] = (pNodeConfig->DataSize & DMA_CBR1_BNDT);
3593 
3594   /*********************************************************************************** CBR1 register value is updated */
3595 
3596 
3597   /* Update CSAR register value ***************************************************************************************/
3598   pNode->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET] = pNodeConfig->SrcAddress;
3599   /*********************************************************************************** CSAR register value is updated */
3600 
3601 
3602   /* Update CDAR register value ***************************************************************************************/
3603   pNode->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = pNodeConfig->DstAddress;
3604   /*********************************************************************************** CDAR register value is updated */
3605 
3606 
3607   /* Update node information value ************************************************************************************/
3608   /* Set node information */
3609   pNode->NodeInfo = pNodeConfig->NodeType;
3610   pNode->NodeInfo |= (NODE_CLLR_LINEAR_DEFAULT_OFFSET << NODE_CLLR_IDX_POS);
3611   /******************************************************************************** Node information value is updated */
3612 }
3613 
3614 /**
3615   * @brief  Get a DMA channel node configuration.
3616   * @param  pNodeConfig : Pointer to a DMA_NodeConfTypeDef structure that contains the configuration information for the
3617   *                       specified DMA linked-list Node.
3618   * @param  pNode       : Pointer to a DMA_NodeTypeDef structure that contains linked-list node registers
3619   *                       configurations.
3620   * @retval None.
3621   */
DMA_List_GetNodeConfig(DMA_NodeConfTypeDef * const pNodeConfig,DMA_NodeTypeDef const * const pNode)3622 static void DMA_List_GetNodeConfig(DMA_NodeConfTypeDef *const pNodeConfig,
3623                                    DMA_NodeTypeDef const *const pNode)
3624 {
3625 
3626   /* Get node information *********************************************************************************************/
3627   pNodeConfig->NodeType = (pNode->NodeInfo & NODE_TYPE_MASK);
3628   /*************************************************************************************** Node type value is updated */
3629 
3630 
3631   /* Get CTR1 fields values *******************************************************************************************/
3632   pNodeConfig->Init.SrcInc                      = pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET]   & DMA_CTR1_SINC;
3633   pNodeConfig->Init.DestInc                     = pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET]   & DMA_CTR1_DINC;
3634   pNodeConfig->Init.SrcDataWidth                = pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET]   & DMA_CTR1_SDW_LOG2;
3635   pNodeConfig->Init.DestDataWidth               = pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET]   & DMA_CTR1_DDW_LOG2;
3636   pNodeConfig->Init.SrcBurstLength              = ((pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET] &
3637                                                     DMA_CTR1_SBL_1) >> DMA_CTR1_SBL_1_Pos) + 1U;
3638   pNodeConfig->Init.DestBurstLength             = ((pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET] &
3639                                                     DMA_CTR1_DBL_1) >> DMA_CTR1_DBL_1_Pos) + 1U;
3640   pNodeConfig->Init.TransferAllocatedPort       = pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET]   &
3641                                                   (DMA_CTR1_SAP | DMA_CTR1_DAP);
3642   pNodeConfig->DataHandlingConfig.DataExchange  = pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET]   &
3643                                                   (DMA_CTR1_SBX | DMA_CTR1_DBX | DMA_CTR1_DHX);
3644   pNodeConfig->DataHandlingConfig.DataAlignment = pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET]   & DMA_CTR1_PAM;
3645 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
3646   if ((pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET] & DMA_CTR1_SSEC) != 0U)
3647   {
3648     pNodeConfig->SrcSecure = DMA_CHANNEL_SRC_SEC;
3649   }
3650   else
3651   {
3652     pNodeConfig->SrcSecure = DMA_CHANNEL_SRC_NSEC;
3653   }
3654 
3655   if ((pNode->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET] & DMA_CTR1_DSEC) != 0U)
3656   {
3657     pNodeConfig->DestSecure = DMA_CHANNEL_DEST_SEC;
3658   }
3659   else
3660   {
3661     pNodeConfig->DestSecure = DMA_CHANNEL_DEST_NSEC;
3662   }
3663 #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
3664   /*********************************************************************************** CTR1 fields values are updated */
3665 
3666 
3667   /* Get CTR2 fields values *******************************************************************************************/
3668   if ((pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET] & DMA_CTR2_SWREQ) != 0U)
3669   {
3670     pNodeConfig->Init.Request   = DMA_REQUEST_SW;
3671     pNodeConfig->Init.Direction = DMA_MEMORY_TO_MEMORY;
3672   }
3673   else
3674   {
3675     pNodeConfig->Init.Request   = pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET] & DMA_CTR2_REQSEL;
3676 
3677     if ((pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET] & DMA_CTR2_DREQ) != 0U)
3678     {
3679       pNodeConfig->Init.Direction = DMA_MEMORY_TO_PERIPH;
3680     }
3681     else
3682     {
3683       pNodeConfig->Init.Direction = DMA_PERIPH_TO_MEMORY;
3684     }
3685   }
3686 
3687   pNodeConfig->Init.BlkHWRequest              = (pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET] & DMA_CTR2_BREQ);
3688   pNodeConfig->TriggerConfig.TriggerMode      = pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET]  & DMA_CTR2_TRIGM;
3689   pNodeConfig->TriggerConfig.TriggerPolarity  = pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET]  & DMA_CTR2_TRIGPOL;
3690   pNodeConfig->TriggerConfig.TriggerSelection = (pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET] &
3691                                                  DMA_CTR2_TRIGSEL) >> DMA_CTR2_TRIGSEL_Pos;
3692   pNodeConfig->Init.TransferEventMode         = pNode->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET]  & DMA_CTR2_TCEM;
3693   /*********************************************************************************** CTR2 fields values are updated */
3694 
3695 
3696   /* Get CBR1 fields **************************************************************************************************/
3697   pNodeConfig->DataSize = pNode->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] & DMA_CBR1_BNDT;
3698 
3699   /*********************************************************************************** CBR1 fields values are updated */
3700 
3701 
3702   /* Get CSAR field ***************************************************************************************************/
3703   pNodeConfig->SrcAddress = pNode->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET];
3704   /************************************************************************************** CSAR field value is updated */
3705 
3706 
3707   /* Get CDAR field ***************************************************************************************************/
3708   pNodeConfig->DstAddress = pNode->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET];
3709   /************************************************************************************** CDAR field value is updated */
3710 
3711 }
3712 
3713 /**
3714   * @brief  Check nodes base addresses compatibility.
3715   * @param  pNode1 : Pointer to a DMA_NodeTypeDef structure that contains linked-list node 1 registers configurations.
3716   * @param  pNode2 : Pointer to a DMA_NodeTypeDef structure that contains linked-list node 2 registers configurations.
3717   * @param  pNode3 : Pointer to a DMA_NodeTypeDef structure that contains linked-list node 3 registers configurations.
3718   * @retval Return 0 when nodes addresses are compatible, 1 otherwise.
3719   */
DMA_List_CheckNodesBaseAddresses(DMA_NodeTypeDef const * const pNode1,DMA_NodeTypeDef const * const pNode2,DMA_NodeTypeDef const * const pNode3)3720 static uint32_t DMA_List_CheckNodesBaseAddresses(DMA_NodeTypeDef const *const pNode1,
3721                                                  DMA_NodeTypeDef const *const pNode2,
3722                                                  DMA_NodeTypeDef const *const pNode3)
3723 {
3724   uint32_t temp = (((uint32_t)pNode1 | (uint32_t)pNode2 | (uint32_t)pNode3) & DMA_CLBAR_LBA);
3725   uint32_t ref  = 0U;
3726 
3727   /* Check node 1 address */
3728   if ((uint32_t)pNode1 != 0U)
3729   {
3730     ref = (uint32_t)pNode1;
3731   }
3732   /* Check node 2 address */
3733   else if ((uint32_t)pNode2 != 0U)
3734   {
3735     ref = (uint32_t)pNode2;
3736   }
3737   /* Check node 3 address */
3738   else if ((uint32_t)pNode3 != 0U)
3739   {
3740     ref = (uint32_t)pNode3;
3741   }
3742   else
3743   {
3744     /* Prevent MISRA-C2012-Rule-15.7 */
3745   }
3746 
3747   /* Check addresses compatibility */
3748   if (temp != ((uint32_t)ref & DMA_CLBAR_LBA))
3749   {
3750     return 1U;
3751   }
3752 
3753   return 0U;
3754 }
3755 
3756 /**
3757   * @brief  Check nodes types compatibility.
3758   * @param  pNode1 : Pointer to a DMA_NodeTypeDef structure that contains linked-list node 1 registers configurations.
3759   * @param  pNode2 : Pointer to a DMA_NodeTypeDef structure that contains linked-list node 2 registers configurations.
3760   * @param  pNode3 : Pointer to a DMA_NodeTypeDef structure that contains linked-list node 3 registers configurations.
3761   * @retval Return 0 when nodes types are compatible, otherwise nodes types are not compatible.
3762   */
DMA_List_CheckNodesTypes(DMA_NodeTypeDef const * const pNode1,DMA_NodeTypeDef const * const pNode2,DMA_NodeTypeDef const * const pNode3)3763 static uint32_t DMA_List_CheckNodesTypes(DMA_NodeTypeDef const *const pNode1,
3764                                          DMA_NodeTypeDef const *const pNode2,
3765                                          DMA_NodeTypeDef const *const pNode3)
3766 {
3767   uint32_t ref = 0U;
3768 
3769   /* Check node 1 parameter */
3770   if (pNode1 != NULL)
3771   {
3772     ref = pNode1->NodeInfo & NODE_TYPE_MASK;
3773   }
3774   /* Check node 2 parameter */
3775   else if (pNode2 != NULL)
3776   {
3777     ref = pNode2->NodeInfo & NODE_TYPE_MASK;
3778   }
3779   /* Check node 3 parameter */
3780   else if (pNode3 != NULL)
3781   {
3782     ref = pNode3->NodeInfo & NODE_TYPE_MASK;
3783   }
3784   else
3785   {
3786     /* Prevent MISRA-C2012-Rule-15.7 */
3787   }
3788 
3789   /* Check node 2 parameter */
3790   if (pNode2 != NULL)
3791   {
3792     /* Check node type compatibility */
3793     if (ref != (pNode2->NodeInfo & NODE_TYPE_MASK))
3794     {
3795       return 2U;
3796     }
3797   }
3798 
3799   /* Check node 3 parameter */
3800   if (pNode3 != NULL)
3801   {
3802     /* Check node type compatibility */
3803     if (ref != (pNode3->NodeInfo & NODE_TYPE_MASK))
3804     {
3805       return 3U;
3806     }
3807   }
3808 
3809   return 0U;
3810 }
3811 
3812 /**
3813   * @brief  Check nodes types compatibility.
3814   * @param  pNode       : Pointer to a DMA_NodeTypeDef structure that contains linked-list node registers
3815   *                       configurations.
3816   * @param  cllr_mask   : Pointer to CLLR register mask value.
3817   * @param  cllr_offset : Pointer to CLLR register offset value.
3818   * @retval None.
3819   */
DMA_List_GetCLLRNodeInfo(DMA_NodeTypeDef const * const pNode,uint32_t * const cllr_mask,uint32_t * const cllr_offset)3820 static void DMA_List_GetCLLRNodeInfo(DMA_NodeTypeDef const *const pNode,
3821                                      uint32_t *const cllr_mask,
3822                                      uint32_t *const cllr_offset)
3823 {
3824   /* Prevent unused argument(s) compilation warning */
3825   UNUSED(pNode);
3826 
3827   /* Update CLLR register mask value */
3828   if (cllr_mask != NULL)
3829   {
3830     *cllr_mask = DMA_CLLR_UT1 | DMA_CLLR_UT2 | DMA_CLLR_UB1 | DMA_CLLR_USA | DMA_CLLR_UDA | DMA_CLLR_ULL;
3831   }
3832 
3833   /* Update CLLR register offset */
3834   if (cllr_offset != NULL)
3835   {
3836     *cllr_offset = NODE_CLLR_LINEAR_DEFAULT_OFFSET;
3837   }
3838 }
3839 
3840 /**
3841   * @brief  Find node in queue.
3842   * @param  pQList   : Pointer to a DMA_QListTypeDef structure that contains queue information.
3843   * @param  pNode    : Pointer to a DMA_NodeTypeDef structure that contains linked-list node registers configurations.
3844   * @param  NodeInfo : Pointer to a DMA_NodeInQInfoTypeDef structure that contains node linked to queue information.
3845   * @retval Return 0 when node is found in selected queue, otherwise node is not found.
3846   */
DMA_List_FindNode(DMA_QListTypeDef const * const pQList,DMA_NodeTypeDef const * const pNode,DMA_NodeInQInfoTypeDef * const NodeInfo)3847 static uint32_t DMA_List_FindNode(DMA_QListTypeDef const *const pQList,
3848                                   DMA_NodeTypeDef const *const pNode,
3849                                   DMA_NodeInQInfoTypeDef *const NodeInfo)
3850 {
3851   uint32_t node_idx = 0U;
3852   uint32_t currentnode_address  = 0U;
3853   uint32_t previousnode_address  = 0U;
3854   uint32_t cllr_offset = NodeInfo->cllr_offset;
3855 
3856   /* Find last node in queue */
3857   if (pNode ==  NULL)
3858   {
3859     /* Check that previous node is linked to the selected queue */
3860     while (node_idx < pQList->NodeNumber)
3861     {
3862       /* Get head node address */
3863       if (node_idx == 0U)
3864       {
3865         currentnode_address = (uint32_t)pQList->Head & DMA_CLLR_LA;
3866       }
3867       /* Calculate nodes addresses */
3868       else
3869       {
3870         previousnode_address = currentnode_address;
3871         currentnode_address =
3872           ((DMA_NodeTypeDef *)(currentnode_address +
3873                                ((uint32_t)pQList->Head & DMA_CLBAR_LBA)))->LinkRegisters[cllr_offset] & DMA_CLLR_LA;
3874       }
3875 
3876       /* Increment node index */
3877       node_idx++;
3878     }
3879   }
3880   /* Find selected node node in queue */
3881   else
3882   {
3883     /* Check that previous node is linked to the selected queue */
3884     while ((node_idx < pQList->NodeNumber) && (currentnode_address != ((uint32_t)pNode & DMA_CLLR_LA)))
3885     {
3886       /* Get head node address */
3887       if (node_idx == 0U)
3888       {
3889         currentnode_address = (uint32_t)pQList->Head & DMA_CLLR_LA;
3890       }
3891       /* Calculate nodes addresses */
3892       else
3893       {
3894         previousnode_address = currentnode_address;
3895         currentnode_address =
3896           ((DMA_NodeTypeDef *)(currentnode_address +
3897                                ((uint32_t)pQList->Head & DMA_CLBAR_LBA)))->LinkRegisters[cllr_offset] & DMA_CLLR_LA;
3898       }
3899 
3900       /* Increment node index */
3901       node_idx++;
3902     }
3903   }
3904 
3905   /* Check stored address */
3906   if (pNode != NULL)
3907   {
3908     if (currentnode_address != ((uint32_t)pNode & DMA_CLLR_LA))
3909     {
3910       return 1U;
3911     }
3912   }
3913 
3914   /* Update current node position */
3915   NodeInfo->currentnode_pos = node_idx;
3916 
3917   /* Update previous node address */
3918   NodeInfo->previousnode_addr = previousnode_address | ((uint32_t)pQList->Head & DMA_CLBAR_LBA);
3919 
3920   /* Update current node address */
3921   NodeInfo->currentnode_addr = currentnode_address | ((uint32_t)pQList->Head & DMA_CLBAR_LBA);
3922 
3923   /* Update next node address */
3924   if (((DMA_NodeTypeDef *)NodeInfo->currentnode_addr)->LinkRegisters[cllr_offset] != 0U)
3925   {
3926     NodeInfo->nextnode_addr = (((DMA_NodeTypeDef *)NodeInfo->currentnode_addr)->LinkRegisters[cllr_offset] &
3927                                DMA_CLLR_LA) | ((uint32_t)pQList->Head & DMA_CLBAR_LBA);
3928   }
3929 
3930   return 0U;
3931 }
3932 
3933 /**
3934   * @brief  Reset queue nodes.
3935   * @param  pQList   : Pointer to a DMA_QListTypeDef structure that contains queue information.
3936   * @param  NodeInfo : Pointer to a DMA_NodeInQInfoTypeDef structure that contains node linked to queue information.
3937   * @retval None.
3938   */
DMA_List_ResetQueueNodes(DMA_QListTypeDef const * const pQList,DMA_NodeInQInfoTypeDef const * const NodeInfo)3939 static void DMA_List_ResetQueueNodes(DMA_QListTypeDef const *const pQList,
3940                                      DMA_NodeInQInfoTypeDef const *const NodeInfo)
3941 {
3942   uint32_t node_idx = 0U;
3943   uint32_t currentnode_address  = 0U;
3944   uint32_t previousnode_address;
3945   uint32_t cllr_offset = NodeInfo->cllr_offset;
3946 
3947   /* Check that previous node is linked to the selected queue */
3948   while (node_idx < pQList->NodeNumber)
3949   {
3950     /* Get head node address */
3951     if (node_idx == 0U)
3952     {
3953       previousnode_address = (uint32_t)pQList->Head & DMA_CLLR_LA;
3954       currentnode_address  = (pQList->Head->LinkRegisters[cllr_offset] & DMA_CLLR_LA);
3955     }
3956     /* Calculate nodes addresses */
3957     else
3958     {
3959       previousnode_address = currentnode_address;
3960       currentnode_address =
3961         ((DMA_NodeTypeDef *)(currentnode_address +
3962                              ((uint32_t)pQList->Head & DMA_CLBAR_LBA)))->LinkRegisters[cllr_offset] & DMA_CLLR_LA;
3963     }
3964 
3965     /* Reset node */
3966     ((DMA_NodeTypeDef *)(previousnode_address +
3967                          ((uint32_t)pQList->Head & DMA_CLBAR_LBA)))->LinkRegisters[cllr_offset] = 0U;
3968 
3969     /* Increment node index */
3970     node_idx++;
3971   }
3972 }
3973 
3974 /**
3975   * @brief  Fill source node registers values by destination nodes registers values.
3976   * @param  pSrcNode  : Pointer to a DMA_NodeTypeDef structure that contains linked-list source node registers
3977   *                     configurations.
3978   * @param  pDestNode : Pointer to a DMA_NodeTypeDef structure that contains linked-list destination node registers
3979   *                     configurations.
3980   * @retval None.
3981   */
DMA_List_FillNode(DMA_NodeTypeDef const * const pSrcNode,DMA_NodeTypeDef * const pDestNode)3982 static void DMA_List_FillNode(DMA_NodeTypeDef const *const pSrcNode,
3983                               DMA_NodeTypeDef *const pDestNode)
3984 {
3985   /* Repeat for all register nodes */
3986   for (uint32_t reg_idx = 0U; reg_idx < NODE_MAXIMUM_SIZE; reg_idx++)
3987   {
3988     pDestNode->LinkRegisters[reg_idx] = pSrcNode->LinkRegisters[reg_idx];
3989   }
3990 
3991   /* Fill node information */
3992   pDestNode->NodeInfo = pSrcNode->NodeInfo;
3993 }
3994 
3995 /**
3996   * @brief  Convert node to dynamic.
3997   * @param  ContextNodeAddr : The context node address.
3998   * @param  CurrentNodeAddr : The current node address to be converted.
3999   * @param  RegisterNumber  : The register number to be converted.
4000   * @retval None.
4001   */
DMA_List_ConvertNodeToDynamic(uint32_t ContextNodeAddr,uint32_t CurrentNodeAddr,uint32_t RegisterNumber)4002 static void DMA_List_ConvertNodeToDynamic(uint32_t ContextNodeAddr,
4003                                           uint32_t CurrentNodeAddr,
4004                                           uint32_t RegisterNumber)
4005 {
4006   uint32_t currentnode_reg_counter = 0U;
4007   uint32_t contextnode_reg_counter = 0U;
4008   uint32_t cllr_idx = RegisterNumber - 1U;
4009   DMA_NodeTypeDef *context_node = (DMA_NodeTypeDef *)ContextNodeAddr;
4010   DMA_NodeTypeDef *current_node = (DMA_NodeTypeDef *)CurrentNodeAddr;
4011   uint32_t update_link[NODE_MAXIMUM_SIZE] = {DMA_CLLR_UT1, DMA_CLLR_UT2, DMA_CLLR_UB1, DMA_CLLR_USA,
4012                                              DMA_CLLR_UDA, DMA_CLLR_ULL
4013                                             };
4014 
4015   /* Update ULL position according to register number */
4016   update_link[cllr_idx] = update_link[NODE_MAXIMUM_SIZE - 1U];
4017 
4018   /* Repeat for all node registers */
4019   while (contextnode_reg_counter != RegisterNumber)
4020   {
4021     /* Check if register values are equal (exception for CSAR, CDAR and CLLR registers) */
4022     if ((context_node->LinkRegisters[contextnode_reg_counter]  ==
4023          current_node->LinkRegisters[currentnode_reg_counter]) &&
4024         (contextnode_reg_counter != NODE_CSAR_DEFAULT_OFFSET)  &&
4025         (contextnode_reg_counter != NODE_CDAR_DEFAULT_OFFSET)  &&
4026         (contextnode_reg_counter != (RegisterNumber - 1U)))
4027     {
4028       /* Format the node according to unused registers */
4029       DMA_List_FormatNode(current_node, currentnode_reg_counter, RegisterNumber, NODE_DYNAMIC_FORMAT);
4030 
4031       /* Update CLLR index */
4032       cllr_idx --;
4033 
4034       /* Update CLLR fields */
4035       current_node->LinkRegisters[cllr_idx] &= ~update_link[contextnode_reg_counter];
4036     }
4037     else
4038     {
4039       /* Update context node register fields with new values */
4040       context_node->LinkRegisters[contextnode_reg_counter] = current_node->LinkRegisters[currentnode_reg_counter];
4041 
4042       /* Update CLLR fields */
4043       current_node->LinkRegisters[cllr_idx] |= update_link[contextnode_reg_counter];
4044 
4045       /* Increment current node number register counter */
4046       currentnode_reg_counter++;
4047     }
4048 
4049     /* Increment context node number register counter */
4050     contextnode_reg_counter++;
4051   }
4052 
4053   /* Update node information */
4054   MODIFY_REG(current_node->NodeInfo, NODE_CLLR_IDX, ((currentnode_reg_counter - 1U) << NODE_CLLR_IDX_POS));
4055 
4056   /* Clear unused node fields */
4057   DMA_List_ClearUnusedFields(current_node, currentnode_reg_counter);
4058 }
4059 
4060 /**
4061   * @brief  Convert node to static.
4062   * @param  ContextNodeAddr : The context node address.
4063   * @param  CurrentNodeAddr : The current node address to be converted.
4064   * @param  RegisterNumber  : The register number to be converted.
4065   * @retval None.
4066   */
DMA_List_ConvertNodeToStatic(uint32_t ContextNodeAddr,uint32_t CurrentNodeAddr,uint32_t RegisterNumber)4067 static void DMA_List_ConvertNodeToStatic(uint32_t ContextNodeAddr,
4068                                          uint32_t CurrentNodeAddr,
4069                                          uint32_t RegisterNumber)
4070 {
4071   uint32_t contextnode_reg_counter = 0U;
4072   uint32_t cllr_idx;
4073   uint32_t cllr_mask;
4074   DMA_NodeTypeDef *context_node = (DMA_NodeTypeDef *)ContextNodeAddr;
4075   DMA_NodeTypeDef *current_node = (DMA_NodeTypeDef *)CurrentNodeAddr;
4076   uint32_t update_link[NODE_MAXIMUM_SIZE] = {DMA_CLLR_UT1, DMA_CLLR_UT2, DMA_CLLR_UB1, DMA_CLLR_USA,
4077                                              DMA_CLLR_UDA, DMA_CLLR_ULL
4078                                             };
4079 
4080   /* Update ULL position according to register number */
4081   update_link[RegisterNumber - 1U] = update_link[NODE_MAXIMUM_SIZE - 1U];
4082 
4083   /* Get context node CLLR information */
4084   cllr_idx  = (context_node->NodeInfo & NODE_CLLR_IDX) >> NODE_CLLR_IDX_POS;
4085   cllr_mask = context_node->LinkRegisters[cllr_idx];
4086 
4087   /* Repeat for all node registers */
4088   while (contextnode_reg_counter != RegisterNumber)
4089   {
4090     /* Check if node field is dynamic */
4091     if ((cllr_mask & update_link[contextnode_reg_counter]) == 0U)
4092     {
4093       /* Format the node according to unused registers */
4094       DMA_List_FormatNode(current_node, contextnode_reg_counter, RegisterNumber, NODE_STATIC_FORMAT);
4095 
4096       /* Update node field */
4097       current_node->LinkRegisters[contextnode_reg_counter] = context_node->LinkRegisters[contextnode_reg_counter];
4098     }
4099 
4100     /* Increment context node number register counter */
4101     contextnode_reg_counter++;
4102   }
4103 
4104   /* Update node information */
4105   MODIFY_REG(current_node->NodeInfo, NODE_CLLR_IDX, ((RegisterNumber - 1U) << NODE_CLLR_IDX_POS));
4106 }
4107 
4108 /**
4109   * @brief  Format the node according to unused registers.
4110   * @param  pNode           : Pointer to a DMA_NodeTypeDef structure that contains linked-list node registers
4111   *                           configurations.
4112   * @param  RegisterIdx     : The first register index to be formatted.
4113   * @param  RegisterNumber  : The number of node registers.
4114   * @param  Format          : The format type.
4115   * @retval None.
4116   */
DMA_List_FormatNode(DMA_NodeTypeDef * const pNode,uint32_t RegisterIdx,uint32_t RegisterNumber,uint32_t Format)4117 static void DMA_List_FormatNode(DMA_NodeTypeDef *const pNode,
4118                                 uint32_t RegisterIdx,
4119                                 uint32_t RegisterNumber,
4120                                 uint32_t Format)
4121 {
4122   if (Format == NODE_DYNAMIC_FORMAT)
4123   {
4124     /* Repeat for all registers to be formatted */
4125     for (uint32_t reg_idx = RegisterIdx; reg_idx < (RegisterNumber - 1U); reg_idx++)
4126     {
4127       pNode->LinkRegisters[reg_idx] = pNode->LinkRegisters[reg_idx + 1U];
4128     }
4129   }
4130   else
4131   {
4132     /* Repeat for all registers to be formatted */
4133     for (uint32_t reg_idx = (RegisterNumber - 2U); reg_idx > RegisterIdx; reg_idx--)
4134     {
4135       pNode->LinkRegisters[reg_idx] = pNode->LinkRegisters[reg_idx - 1U];
4136     }
4137   }
4138 }
4139 
4140 /**
4141   * @brief  Clear unused register fields.
4142   * @param  pNode            : Pointer to a DMA_NodeTypeDef structure that contains linked-list node registers
4143   *                            configurations.
4144   * @param  FirstUnusedField : The first unused field to be cleared.
4145   * @retval None.
4146   */
DMA_List_ClearUnusedFields(DMA_NodeTypeDef * const pNode,uint32_t FirstUnusedField)4147 static void DMA_List_ClearUnusedFields(DMA_NodeTypeDef *const pNode,
4148                                        uint32_t FirstUnusedField)
4149 {
4150   /* Repeat for all unused fields */
4151   for (uint32_t reg_idx = FirstUnusedField; reg_idx < NODE_MAXIMUM_SIZE; reg_idx++)
4152   {
4153     pNode->LinkRegisters[reg_idx] = 0U;
4154   }
4155 }
4156 
4157 /**
4158   * @brief  Update CLLR for all dynamic queue nodes.
4159   * @param  pQList :              Pointer to a DMA_QListTypeDef structure that contains queue information.
4160   * @param  LastNode_IsCircular : The first circular node is the last queue node or not.
4161   * @retval None.
4162   */
DMA_List_UpdateDynamicQueueNodesCLLR(DMA_QListTypeDef const * const pQList,uint32_t LastNode_IsCircular)4163 static void DMA_List_UpdateDynamicQueueNodesCLLR(DMA_QListTypeDef const *const pQList,
4164                                                  uint32_t LastNode_IsCircular)
4165 {
4166   uint32_t previous_cllr_offset;
4167   uint32_t current_cllr_offset = 0U;
4168   uint32_t previousnode_addr;
4169   uint32_t currentnode_addr = (uint32_t)pQList->Head;
4170   uint32_t cllr_mask;
4171   uint32_t node_idx = 0U;
4172 
4173   /*  Repeat for all register nodes */
4174   while (node_idx < pQList->NodeNumber)
4175   {
4176     /* Get head node address */
4177     if (node_idx == 0U)
4178     {
4179       /* Get current node information */
4180       current_cllr_offset = (((DMA_NodeTypeDef *)currentnode_addr)->NodeInfo & NODE_CLLR_IDX) >> NODE_CLLR_IDX_POS;
4181     }
4182     /* Calculate nodes addresses */
4183     else
4184     {
4185       /* Get previous node information */
4186       previousnode_addr = currentnode_addr;
4187       previous_cllr_offset = current_cllr_offset;
4188 
4189       /* Get current node information */
4190       currentnode_addr = (((DMA_NodeTypeDef *)(previousnode_addr))->LinkRegisters[previous_cllr_offset] & DMA_CLLR_LA) +
4191                          ((uint32_t)pQList->Head & DMA_CLBAR_LBA);
4192       current_cllr_offset = (((DMA_NodeTypeDef *)currentnode_addr)->NodeInfo & NODE_CLLR_IDX) >> NODE_CLLR_IDX_POS;
4193 
4194       /* Calculate CLLR register value to be updated */
4195       cllr_mask = (((DMA_NodeTypeDef *)currentnode_addr)->LinkRegisters[current_cllr_offset] & ~DMA_CLLR_LA) |
4196                   (((DMA_NodeTypeDef *)(previousnode_addr))->LinkRegisters[previous_cllr_offset] & DMA_CLLR_LA);
4197 
4198       /* Set new CLLR value to previous node */
4199       ((DMA_NodeTypeDef *)(previousnode_addr))->LinkRegisters[previous_cllr_offset] = cllr_mask;
4200     }
4201 
4202     /* Increment node index */
4203     node_idx++;
4204   }
4205 
4206   /* Check queue circularity */
4207   if (pQList->FirstCircularNode != 0U)
4208   {
4209     /* First circular queue is not last queue node */
4210     if (LastNode_IsCircular == 0U)
4211     {
4212       /* Get CLLR node information */
4213       DMA_List_GetCLLRNodeInfo(((DMA_NodeTypeDef *)currentnode_addr), &cllr_mask, NULL);
4214 
4215       /* Update CLLR register for last circular node */
4216       ((DMA_NodeTypeDef *)currentnode_addr)->LinkRegisters[current_cllr_offset] =
4217         ((uint32_t)pQList->Head & DMA_CLLR_LA) | cllr_mask;
4218     }
4219     /* First circular queue is last queue node */
4220     else
4221     {
4222       /* Disable CLLR updating */
4223       ((DMA_NodeTypeDef *)currentnode_addr)->LinkRegisters[current_cllr_offset] &= ~DMA_CLLR_ULL;
4224     }
4225   }
4226   else
4227   {
4228     /* Clear CLLR register for last node */
4229     ((DMA_NodeTypeDef *)currentnode_addr)->LinkRegisters[current_cllr_offset] = 0U;
4230   }
4231 }
4232 
4233 /**
4234   * @brief  Update CLLR for all static queue nodes.
4235   * @param  pQList    : Pointer to a DMA_QListTypeDef structure that contains queue information.
4236   * @param  operation : The operation type.
4237   * @retval None.
4238   */
DMA_List_UpdateStaticQueueNodesCLLR(DMA_QListTypeDef const * const pQList,uint32_t operation)4239 static void DMA_List_UpdateStaticQueueNodesCLLR(DMA_QListTypeDef const *const pQList,
4240                                                 uint32_t operation)
4241 {
4242   uint32_t currentnode_addr = (uint32_t)pQList->Head;
4243   uint32_t current_cllr_offset = ((uint32_t)pQList->Head->NodeInfo & NODE_CLLR_IDX) >> NODE_CLLR_IDX_POS;
4244   uint32_t cllr_default_offset;
4245   uint32_t cllr_default_mask;
4246   uint32_t cllr_mask;
4247   uint32_t node_idx = 0U;
4248 
4249   /* Get CLLR node information */
4250   DMA_List_GetCLLRNodeInfo(pQList->Head, &cllr_default_mask, &cllr_default_offset);
4251 
4252   /*  Repeat for all register nodes (Bypass last queue node) */
4253   while (node_idx < pQList->NodeNumber)
4254   {
4255     if (operation == UPDATE_CLLR_POSITION)
4256     {
4257       /* Get CLLR value */
4258       cllr_mask = ((DMA_NodeTypeDef *)currentnode_addr)->LinkRegisters[current_cllr_offset];
4259     }
4260     else
4261     {
4262       /* Calculate CLLR value */
4263       cllr_mask = (((DMA_NodeTypeDef *)currentnode_addr)->LinkRegisters[current_cllr_offset] & DMA_CLLR_LA) |
4264                   cllr_default_mask;
4265     }
4266 
4267     /* Set new CLLR value to default position */
4268     if ((node_idx == (pQList->NodeNumber - 1U)) && (pQList->FirstCircularNode == NULL))
4269     {
4270       ((DMA_NodeTypeDef *)(currentnode_addr))->LinkRegisters[cllr_default_offset] = 0U;
4271     }
4272     else
4273     {
4274       ((DMA_NodeTypeDef *)(currentnode_addr))->LinkRegisters[cllr_default_offset] = cllr_mask;
4275     }
4276 
4277     /* Update current node address with next node address */
4278     currentnode_addr = (currentnode_addr & DMA_CLBAR_LBA) | (cllr_mask & DMA_CLLR_LA);
4279 
4280     /* Update current CLLR offset with next CLLR offset */
4281     current_cllr_offset = (((DMA_NodeTypeDef *)currentnode_addr)->NodeInfo & NODE_CLLR_IDX) >> NODE_CLLR_IDX_POS;
4282 
4283     /* Increment node index */
4284     node_idx++;
4285   }
4286 }
4287 
4288 /**
4289   * @brief  Clean linked-list queue variable.
4290   * @param  pQList    : Pointer to a DMA_QListTypeDef structure that contains queue information.
4291   * @retval None.
4292   */
DMA_List_CleanQueue(DMA_QListTypeDef * const pQList)4293 static void DMA_List_CleanQueue(DMA_QListTypeDef *const pQList)
4294 {
4295   /* Clear head node */
4296   pQList->Head = NULL;
4297 
4298   /* Clear first circular queue node */
4299   pQList->FirstCircularNode = NULL;
4300 
4301   /* Reset node number */
4302   pQList->NodeNumber = 0U;
4303 
4304   /* Reset queue state */
4305   pQList->State = HAL_DMA_QUEUE_STATE_RESET;
4306 
4307   /* Reset queue error code */
4308   pQList->ErrorCode = HAL_DMA_QUEUE_ERROR_NONE;
4309 
4310   /* Reset queue type */
4311   pQList->Type = QUEUE_TYPE_STATIC;
4312 }
4313 /**
4314   * @}
4315   */
4316 
4317 #endif /* HAL_DMA_MODULE_ENABLED */
4318 /**
4319   * @}
4320   */
4321 
4322 /**
4323   * @}
4324   */
4325