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