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