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