1 /**
2   ******************************************************************************
3   * @file    stm32u0xx_ll_dma.c
4   * @author  GPM Application Team
5   * @brief   DMA LL module driver.
6   ******************************************************************************
7   * @attention
8   *
9   * Copyright (c) 2023 STMicroelectronics.
10   * All rights reserved.
11   *
12   * This software is licensed under terms that can be found in the LICENSE file
13   * in the root directory of this software component.
14   * If no LICENSE file comes with this software, it is provided AS-IS.
15   *
16   ******************************************************************************
17   */
18 #if defined(USE_FULL_LL_DRIVER)
19 
20 /* Includes ------------------------------------------------------------------*/
21 #include "stm32u0xx_ll_dma.h"
22 #include "stm32u0xx_ll_bus.h"
23 #ifdef  USE_FULL_ASSERT
24 #include "stm32_assert.h"
25 #else
26 #define assert_param(expr) ((void)0U)
27 #endif /* USE_FULL_ASSERT */
28 
29 /** @addtogroup STM32U0xx_LL_Driver
30   * @{
31   */
32 
33 #if defined (DMA1) || defined (DMA2)
34 
35 /** @defgroup DMA_LL DMA
36   * @{
37   */
38 
39 /* Private types -------------------------------------------------------------*/
40 /* Private variables ---------------------------------------------------------*/
41 /* Private constants ---------------------------------------------------------*/
42 /* Private macros ------------------------------------------------------------*/
43 /** @addtogroup DMA_LL_Private_Macros
44   * @{
45   */
46 #define IS_LL_DMA_DIRECTION(__VALUE__)          (((__VALUE__) == LL_DMA_DIRECTION_PERIPH_TO_MEMORY) || \
47                                                  ((__VALUE__) == LL_DMA_DIRECTION_MEMORY_TO_PERIPH) || \
48                                                  ((__VALUE__) == LL_DMA_DIRECTION_MEMORY_TO_MEMORY))
49 
50 #define IS_LL_DMA_MODE(__VALUE__)               (((__VALUE__) == LL_DMA_MODE_NORMAL) || \
51                                                  ((__VALUE__) == LL_DMA_MODE_CIRCULAR))
52 
53 #define IS_LL_DMA_PERIPHINCMODE(__VALUE__)      (((__VALUE__) == LL_DMA_PERIPH_INCREMENT) || \
54                                                  ((__VALUE__) == LL_DMA_PERIPH_NOINCREMENT))
55 
56 #define IS_LL_DMA_MEMORYINCMODE(__VALUE__)      (((__VALUE__) == LL_DMA_MEMORY_INCREMENT) || \
57                                                  ((__VALUE__) == LL_DMA_MEMORY_NOINCREMENT))
58 
59 #define IS_LL_DMA_PERIPHDATASIZE(__VALUE__)     (((__VALUE__) == LL_DMA_PDATAALIGN_BYTE)      || \
60                                                  ((__VALUE__) == LL_DMA_PDATAALIGN_HALFWORD)  || \
61                                                  ((__VALUE__) == LL_DMA_PDATAALIGN_WORD))
62 
63 #define IS_LL_DMA_MEMORYDATASIZE(__VALUE__)     (((__VALUE__) == LL_DMA_MDATAALIGN_BYTE)      || \
64                                                  ((__VALUE__) == LL_DMA_MDATAALIGN_HALFWORD)  || \
65                                                  ((__VALUE__) == LL_DMA_MDATAALIGN_WORD))
66 
67 #define IS_LL_DMA_NBDATA(__VALUE__)             ((__VALUE__)  <= 0x0000FFFFU)
68 
69 #define IS_LL_DMA_PERIPHREQUEST(__VALUE__)      ((__VALUE__) <= LL_DMAMUX_MAX_REQ)
70 
71 #define IS_LL_DMA_PRIORITY(__VALUE__)           (((__VALUE__) == LL_DMA_PRIORITY_LOW)    || \
72                                                  ((__VALUE__) == LL_DMA_PRIORITY_MEDIUM) || \
73                                                  ((__VALUE__) == LL_DMA_PRIORITY_HIGH)   || \
74                                                  ((__VALUE__) == LL_DMA_PRIORITY_VERYHIGH))
75 
76 #if defined(DMA2)
77 #define IS_LL_DMA_ALL_CHANNEL_INSTANCE(INSTANCE, CHANNEL)  ((((INSTANCE) == DMA1) && \
78                                                              (((CHANNEL) == LL_DMA_CHANNEL_1) || \
79                                                               ((CHANNEL) == LL_DMA_CHANNEL_2) || \
80                                                               ((CHANNEL) == LL_DMA_CHANNEL_3) || \
81                                                               ((CHANNEL) == LL_DMA_CHANNEL_4) || \
82                                                               ((CHANNEL) == LL_DMA_CHANNEL_5) || \
83                                                               ((CHANNEL) == LL_DMA_CHANNEL_6) || \
84                                                               ((CHANNEL) == LL_DMA_CHANNEL_7))) || \
85                                                             (((INSTANCE) == DMA2) && \
86                                                              (((CHANNEL) == LL_DMA_CHANNEL_1) || \
87                                                               ((CHANNEL) == LL_DMA_CHANNEL_2) || \
88                                                               ((CHANNEL) == LL_DMA_CHANNEL_3) || \
89                                                               ((CHANNEL) == LL_DMA_CHANNEL_4) || \
90                                                               ((CHANNEL) == LL_DMA_CHANNEL_5))))
91 #else /* DMA1 */
92 #define IS_LL_DMA_ALL_CHANNEL_INSTANCE(INSTANCE, CHANNEL)  ((((INSTANCE) == DMA1) && \
93                                                              (((CHANNEL) == LL_DMA_CHANNEL_1) || \
94                                                               ((CHANNEL) == LL_DMA_CHANNEL_2) || \
95                                                               ((CHANNEL) == LL_DMA_CHANNEL_3) || \
96                                                               ((CHANNEL) == LL_DMA_CHANNEL_4) || \
97                                                               ((CHANNEL) == LL_DMA_CHANNEL_5) || \
98                                                               ((CHANNEL) == LL_DMA_CHANNEL_6) || \
99                                                               ((CHANNEL) == LL_DMA_CHANNEL_7))))
100 #endif /* DMA2 */
101 /**
102   * @}
103   */
104 
105 /* Private function prototypes -----------------------------------------------*/
106 
107 /* Exported functions --------------------------------------------------------*/
108 /** @addtogroup DMA_LL_Exported_Functions
109   * @{
110   */
111 
112 /** @addtogroup DMA_LL_EF_Init
113   * @{
114   */
115 
116 /**
117   * @brief  De-initialize the DMA registers to their default reset values.
118   * @param  DMAx DMAx Instance
119   * @param  Channel This parameter can be one of the following values:
120   *         @arg @ref LL_DMA_CHANNEL_1
121   *         @arg @ref LL_DMA_CHANNEL_2
122   *         @arg @ref LL_DMA_CHANNEL_3
123   *         @arg @ref LL_DMA_CHANNEL_4
124   *         @arg @ref LL_DMA_CHANNEL_5
125   *         @arg @ref LL_DMA_CHANNEL_6
126   *         @arg @ref LL_DMA_CHANNEL_7
127   *         @arg @ref LL_DMA_CHANNEL_ALL
128   * @retval An ErrorStatus enumeration value:
129   *          - SUCCESS: DMA registers are de-initialized
130   *          - ERROR: DMA registers are not de-initialized
131   */
LL_DMA_DeInit(DMA_TypeDef * DMAx,uint32_t Channel)132 ErrorStatus LL_DMA_DeInit(DMA_TypeDef *DMAx, uint32_t Channel)
133 {
134   ErrorStatus status = SUCCESS;
135 
136   /* Check the DMA Instance DMAx and Channel parameters*/
137   assert_param(IS_LL_DMA_ALL_CHANNEL_INSTANCE(DMAx, Channel) || (Channel == LL_DMA_CHANNEL_ALL));
138 
139   if (Channel == LL_DMA_CHANNEL_ALL)
140   {
141     if (DMAx == DMA1)
142     {
143       /* Force reset of DMA clock */
144       LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_DMA1);
145 
146       /* Release reset of DMA clock */
147       LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_DMA1);
148     }
149 #if defined(DMA2)
150     else if (DMAx == DMA2)
151     {
152       /* Force reset of DMA clock */
153       LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_DMA2);
154 
155       /* Release reset of DMA clock */
156       LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_DMA2);
157     }
158 #endif /* DMA2 */
159     else
160     {
161       status = ERROR;
162     }
163   }
164   else
165   {
166     DMA_Channel_TypeDef *tmp;
167 
168     tmp = (DMA_Channel_TypeDef *)(__LL_DMA_GET_CHANNEL_INSTANCE(DMAx, Channel));
169 
170     /* Disable the selected DMAx_Channely */
171     CLEAR_BIT(tmp->CCR, DMA_CCR_EN);
172 
173     /* Reset DMAx_Channely control register */
174     WRITE_REG(tmp->CCR, 0U);
175 
176     /* Reset DMAx_Channely remaining bytes register */
177     WRITE_REG(tmp->CNDTR, 0U);
178 
179     /* Reset DMAx_Channely peripheral address register */
180     WRITE_REG(tmp->CPAR, 0U);
181 
182     /* Reset DMAx_Channely memory address register */
183     WRITE_REG(tmp->CMAR, 0U);
184 
185     /* Reset Request register field for DMAx Channel */
186     LL_DMA_SetPeriphRequest(DMAx, Channel, LL_DMAMUX_REQ_MEM2MEM);
187 
188     if (Channel == LL_DMA_CHANNEL_1)
189     {
190       /* Reset interrupt pending bits for DMAx Channel1 */
191       LL_DMA_ClearFlag_GI1(DMAx);
192     }
193     else if (Channel == LL_DMA_CHANNEL_2)
194     {
195       /* Reset interrupt pending bits for DMAx Channel2 */
196       LL_DMA_ClearFlag_GI2(DMAx);
197     }
198     else if (Channel == LL_DMA_CHANNEL_3)
199     {
200       /* Reset interrupt pending bits for DMAx Channel3 */
201       LL_DMA_ClearFlag_GI3(DMAx);
202     }
203     else if (Channel == LL_DMA_CHANNEL_4)
204     {
205       /* Reset interrupt pending bits for DMAx Channel4 */
206       LL_DMA_ClearFlag_GI4(DMAx);
207     }
208     else if (Channel == LL_DMA_CHANNEL_5)
209     {
210       /* Reset interrupt pending bits for DMAx Channel5 */
211       LL_DMA_ClearFlag_GI5(DMAx);
212     }
213     else if (Channel == LL_DMA_CHANNEL_6)
214     {
215       /* Reset interrupt pending bits for DMAx Channel6 */
216       LL_DMA_ClearFlag_GI6(DMAx);
217     }
218     else if (Channel == LL_DMA_CHANNEL_7)
219     {
220       /* Reset interrupt pending bits for DMAx Channel7 */
221       LL_DMA_ClearFlag_GI7(DMAx);
222     }
223     else
224     {
225       status = ERROR;
226     }
227   }
228 
229   return status;
230 }
231 
232 /**
233   * @brief  Initialize the DMA registers according to the specified parameters in DMA_InitStruct.
234   * @note   To convert DMAx_Channely Instance to DMAx Instance and Channely, use helper macros :
235   *         @arg @ref __LL_DMA_GET_INSTANCE
236   *         @arg @ref __LL_DMA_GET_CHANNEL
237   * @param  DMAx DMAx Instance
238   * @param  Channel This parameter can be one of the following values:
239   *         @arg @ref LL_DMA_CHANNEL_1
240   *         @arg @ref LL_DMA_CHANNEL_2
241   *         @arg @ref LL_DMA_CHANNEL_3
242   *         @arg @ref LL_DMA_CHANNEL_4
243   *         @arg @ref LL_DMA_CHANNEL_5
244   *         @arg @ref LL_DMA_CHANNEL_6
245   *         @arg @ref LL_DMA_CHANNEL_7
246   * @param  DMA_InitStruct pointer to a @ref LL_DMA_InitTypeDef structure.
247   * @retval An ErrorStatus enumeration value:
248   *          - SUCCESS: DMA registers are initialized
249   *          - ERROR: Not applicable
250   */
LL_DMA_Init(DMA_TypeDef * DMAx,uint32_t Channel,LL_DMA_InitTypeDef * DMA_InitStruct)251 ErrorStatus LL_DMA_Init(DMA_TypeDef *DMAx, uint32_t Channel, LL_DMA_InitTypeDef *DMA_InitStruct)
252 {
253   /* Check the DMA Instance DMAx and Channel parameters*/
254   assert_param(IS_LL_DMA_ALL_CHANNEL_INSTANCE(DMAx, Channel));
255 
256   /* Check the DMA parameters from DMA_InitStruct */
257   assert_param(IS_LL_DMA_DIRECTION(DMA_InitStruct->Direction));
258   assert_param(IS_LL_DMA_MODE(DMA_InitStruct->Mode));
259   assert_param(IS_LL_DMA_PERIPHINCMODE(DMA_InitStruct->PeriphOrM2MSrcIncMode));
260   assert_param(IS_LL_DMA_MEMORYINCMODE(DMA_InitStruct->MemoryOrM2MDstIncMode));
261   assert_param(IS_LL_DMA_PERIPHDATASIZE(DMA_InitStruct->PeriphOrM2MSrcDataSize));
262   assert_param(IS_LL_DMA_MEMORYDATASIZE(DMA_InitStruct->MemoryOrM2MDstDataSize));
263   assert_param(IS_LL_DMA_NBDATA(DMA_InitStruct->NbData));
264   assert_param(IS_LL_DMA_PERIPHREQUEST(DMA_InitStruct->PeriphRequest));
265   assert_param(IS_LL_DMA_PRIORITY(DMA_InitStruct->Priority));
266 
267   /*---------------------------- DMAx CCR Configuration ------------------------
268    * Configure DMAx_Channely: data transfer direction, data transfer mode,
269    *                          peripheral and memory increment mode,
270    *                          data size alignment and  priority level with parameters :
271    * - Direction:      DMA_CCR_DIR and DMA_CCR_MEM2MEM bits
272    * - Mode:           DMA_CCR_CIRC bit
273    * - PeriphOrM2MSrcIncMode:  DMA_CCR_PINC bit
274    * - MemoryOrM2MDstIncMode:  DMA_CCR_MINC bit
275    * - PeriphOrM2MSrcDataSize: DMA_CCR_PSIZE[1:0] bits
276    * - MemoryOrM2MDstDataSize: DMA_CCR_MSIZE[1:0] bits
277    * - Priority:               DMA_CCR_PL[1:0] bits
278    */
279   LL_DMA_ConfigTransfer(DMAx, Channel, DMA_InitStruct->Direction              | \
280                         DMA_InitStruct->Mode                   | \
281                         DMA_InitStruct->PeriphOrM2MSrcIncMode  | \
282                         DMA_InitStruct->MemoryOrM2MDstIncMode  | \
283                         DMA_InitStruct->PeriphOrM2MSrcDataSize | \
284                         DMA_InitStruct->MemoryOrM2MDstDataSize | \
285                         DMA_InitStruct->Priority);
286 
287   /*-------------------------- DMAx CMAR Configuration -------------------------
288    * Configure the memory or destination base address with parameter :
289    * - MemoryOrM2MDstAddress: DMA_CMAR_MA[31:0] bits
290    */
291   LL_DMA_SetMemoryAddress(DMAx, Channel, DMA_InitStruct->MemoryOrM2MDstAddress);
292 
293   /*-------------------------- DMAx CPAR Configuration -------------------------
294    * Configure the peripheral or source base address with parameter :
295    * - PeriphOrM2MSrcAddress: DMA_CPAR_PA[31:0] bits
296    */
297   LL_DMA_SetPeriphAddress(DMAx, Channel, DMA_InitStruct->PeriphOrM2MSrcAddress);
298 
299   /*--------------------------- DMAx CNDTR Configuration -----------------------
300    * Configure the peripheral base address with parameter :
301    * - NbData: DMA_CNDTR_NDT[15:0] bits
302    */
303   LL_DMA_SetDataLength(DMAx, Channel, DMA_InitStruct->NbData);
304 
305   /*--------------------------- DMAMUXx CCR Configuration ----------------------
306    * Configure the DMA request for DMA Channels on DMAMUX Channel x with parameter :
307    * - PeriphRequest: DMA_CxCR[7:0] bits
308    */
309   LL_DMA_SetPeriphRequest(DMAx, Channel, DMA_InitStruct->PeriphRequest);
310 
311   return SUCCESS;
312 }
313 
314 /**
315   * @brief  Set each @ref LL_DMA_InitTypeDef field to default value.
316   * @param  DMA_InitStruct Pointer to a @ref LL_DMA_InitTypeDef structure.
317   * @retval None
318   */
LL_DMA_StructInit(LL_DMA_InitTypeDef * DMA_InitStruct)319 void LL_DMA_StructInit(LL_DMA_InitTypeDef *DMA_InitStruct)
320 {
321   /* Set DMA_InitStruct fields to default values */
322   DMA_InitStruct->PeriphOrM2MSrcAddress  = 0x00000000U;
323   DMA_InitStruct->MemoryOrM2MDstAddress  = 0x00000000U;
324   DMA_InitStruct->Direction              = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
325   DMA_InitStruct->Mode                   = LL_DMA_MODE_NORMAL;
326   DMA_InitStruct->PeriphOrM2MSrcIncMode  = LL_DMA_PERIPH_NOINCREMENT;
327   DMA_InitStruct->MemoryOrM2MDstIncMode  = LL_DMA_MEMORY_NOINCREMENT;
328   DMA_InitStruct->PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE;
329   DMA_InitStruct->MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE;
330   DMA_InitStruct->NbData                 = 0x00000000U;
331   DMA_InitStruct->PeriphRequest          = LL_DMAMUX_REQ_MEM2MEM;
332   DMA_InitStruct->Priority               = LL_DMA_PRIORITY_LOW;
333 }
334 
335 /**
336   * @}
337   */
338 
339 /**
340   * @}
341   */
342 
343 /**
344   * @}
345   */
346 
347 #endif /* DMA1 || DMA2 */
348 
349 /**
350   * @}
351   */
352 
353 #endif /* USE_FULL_LL_DRIVER */
354