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