1 /**************************************************************************//**
2 * @file pdma.c
3 * @version V3.00
4 * @brief M2351 series PDMA driver source file
5 *
6 * @copyright SPDX-License-Identifier: Apache-2.0
7 * @copyright Copyright (C) 2017-2020 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9 #include "NuMicro.h"
10
11
12 static uint8_t au8ChSelect[PDMA_CH_MAX];
13
14 /** @addtogroup Standard_Driver Standard Driver
15 @{
16 */
17
18 /** @addtogroup PDMA_Driver PDMA Driver
19 @{
20 */
21
22
23 /** @addtogroup PDMA_EXPORTED_FUNCTIONS PDMA Exported Functions
24 @{
25 */
26
27 /**
28 * @brief PDMA Open
29 *
30 * @param[in] pdma The pointer of the specified PDMA module
31 * @param[in] u32Mask Channel enable bits.
32 *
33 * @return None
34 *
35 * @details This function enable the PDMA channels.
36 */
PDMA_Open(PDMA_T * pdma,uint32_t u32Mask)37 void PDMA_Open(PDMA_T *pdma, uint32_t u32Mask)
38 {
39 uint32_t i;
40
41 for(i = 0UL; i < (int)PDMA_CH_MAX; i++)
42 {
43 if((1 << i) & u32Mask)
44 {
45 (pdma)->DSCT[i].CTL = 0UL;
46 au8ChSelect[i] = (uint8_t)PDMA_MEM;
47 }
48 }
49
50 (pdma)->CHCTL |= u32Mask;
51 }
52
53 /**
54 * @brief PDMA Close
55 *
56 * @param[in] pdma The pointer of the specified PDMA module
57 *
58 * @return None
59 *
60 * @details This function disable all PDMA channels.
61 */
PDMA_Close(PDMA_T * pdma)62 void PDMA_Close(PDMA_T *pdma)
63 {
64 (pdma)->CHCTL = 0UL;
65 }
66
67 /**
68 * @brief Set PDMA Transfer Count
69 *
70 * @param[in] pdma The pointer of the specified PDMA module
71 * @param[in] u32Ch The selected channel
72 * @param[in] u32Width Data width. Valid values are
73 * - \ref PDMA_WIDTH_8
74 * - \ref PDMA_WIDTH_16
75 * - \ref PDMA_WIDTH_32
76 * @param[in] u32TransCount Transfer count
77 *
78 * @return None
79 *
80 * @details This function set the selected channel data width and transfer count.
81 */
PDMA_SetTransferCnt(PDMA_T * pdma,uint32_t u32Ch,uint32_t u32Width,uint32_t u32TransCount)82 void PDMA_SetTransferCnt(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32Width, uint32_t u32TransCount)
83 {
84 (pdma)->DSCT[u32Ch].CTL &= ~(PDMA_DSCT_CTL_TXCNT_Msk | PDMA_DSCT_CTL_TXWIDTH_Msk);
85 (pdma)->DSCT[u32Ch].CTL |= (u32Width | ((u32TransCount - 1UL) << PDMA_DSCT_CTL_TXCNT_Pos));
86 }
87
88 /**
89 * @brief Set PDMA Stride Mode
90 *
91 * @param[in] pdma The pointer of the specified PDMA module
92 * @param[in] u32Ch The selected channel
93 * @param[in] u32DestLen Destination stride count
94 * @param[in] u32SrcLen Source stride count
95 * @param[in] u32TransCount Transfer count
96 *
97 * @return None
98 *
99 * @details This function set the selected stride mode.
100 */
PDMA_SetStride(PDMA_T * pdma,uint32_t u32Ch,uint32_t u32DestLen,uint32_t u32SrcLen,uint32_t u32TransCount)101 void PDMA_SetStride(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32DestLen, uint32_t u32SrcLen, uint32_t u32TransCount)
102 {
103 (pdma)->DSCT[u32Ch].CTL |= PDMA_DSCT_CTL_STRIDEEN_Msk;
104 (pdma)->STRIDE[u32Ch].ASOCR = (u32DestLen << 16) | u32SrcLen;
105 (pdma)->STRIDE[u32Ch].STCR = u32TransCount;
106 }
107
108 /**
109 * @brief Set PDMA Transfer Address
110 *
111 * @param[in] pdma The pointer of the specified PDMA module
112 * @param[in] u32Ch The selected channel
113 * @param[in] u32SrcAddr Source address
114 * @param[in] u32SrcCtrl Source control attribute. Valid values are
115 * - \ref PDMA_SAR_INC
116 * - \ref PDMA_SAR_FIX
117 * @param[in] u32DstAddr destination address
118 * @param[in] u32DstCtrl destination control attribute. Valid values are
119 * - \ref PDMA_DAR_INC
120 * - \ref PDMA_DAR_FIX
121 *
122 * @return None
123 *
124 * @details This function set the selected channel source/destination address and attribute.
125 */
PDMA_SetTransferAddr(PDMA_T * pdma,uint32_t u32Ch,uint32_t u32SrcAddr,uint32_t u32SrcCtrl,uint32_t u32DstAddr,uint32_t u32DstCtrl)126 void PDMA_SetTransferAddr(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32SrcAddr, uint32_t u32SrcCtrl, uint32_t u32DstAddr, uint32_t u32DstCtrl)
127 {
128 (pdma)->DSCT[u32Ch].SA = u32SrcAddr;
129 (pdma)->DSCT[u32Ch].DA = u32DstAddr;
130 (pdma)->DSCT[u32Ch].CTL &= ~(PDMA_DSCT_CTL_SAINC_Msk | PDMA_DSCT_CTL_DAINC_Msk);
131 (pdma)->DSCT[u32Ch].CTL |= (u32SrcCtrl | u32DstCtrl);
132 }
133
134 /**
135 * @brief Set PDMA Transfer Mode
136 *
137 * @param[in] pdma The pointer of the specified PDMA module
138 * @param[in] u32Ch The selected channel
139 * @param[in] u32Peripheral The selected peripheral. Valid values are
140 * - \ref PDMA_MEM
141 * - \ref PDMA_USB_TX
142 * - \ref PDMA_USB_RX
143 * - \ref PDMA_UART0_TX
144 * - \ref PDMA_UART0_RX
145 * - \ref PDMA_UART1_TX
146 * - \ref PDMA_UART1_RX
147 * - \ref PDMA_UART2_TX
148 * - \ref PDMA_UART2_RX
149 * - \ref PDMA_UART3_TX
150 * - \ref PDMA_UART3_RX
151 * - \ref PDMA_UART4_TX
152 * - \ref PDMA_UART4_RX
153 * - \ref PDMA_UART5_TX
154 * - \ref PDMA_UART5_RX
155 * - \ref PDMA_USCI0_TX
156 * - \ref PDMA_USCI0_RX
157 * - \ref PDMA_USCI1_TX
158 * - \ref PDMA_USCI1_RX
159 * - \ref PDMA_QSPI0_TX
160 * - \ref PDMA_QSPI0_RX
161 * - \ref PDMA_SPI0_TX
162 * - \ref PDMA_SPI0_RX
163 * - \ref PDMA_SPI1_TX
164 * - \ref PDMA_SPI1_RX
165 * - \ref PDMA_SPI2_TX
166 * - \ref PDMA_SPI2_RX
167 * - \ref PDMA_SPI3_TX
168 * - \ref PDMA_SPI3_RX
169 * - \ref PDMA_EPWM0_P1_RX
170 * - \ref PDMA_EPWM0_P2_RX
171 * - \ref PDMA_EPWM0_P3_RX
172 * - \ref PDMA_EPWM1_P1_RX
173 * - \ref PDMA_EPWM1_P2_RX
174 * - \ref PDMA_EPWM1_P3_RX
175 * - \ref PDMA_I2C0_TX
176 * - \ref PDMA_I2C0_RX
177 * - \ref PDMA_I2C1_TX
178 * - \ref PDMA_I2C1_RX
179 * - \ref PDMA_I2C2_TX
180 * - \ref PDMA_I2C2_RX
181 * - \ref PDMA_I2S0_TX
182 * - \ref PDMA_I2S0_RX
183 * - \ref PDMA_TMR0
184 * - \ref PDMA_TMR1
185 * - \ref PDMA_TMR2
186 * - \ref PDMA_TMR3
187 * - \ref PDMA_ADC_RX
188 * - \ref PDMA_DAC0_TX
189 * - \ref PDMA_DAC1_TX
190 * @param[in] u32ScatterEn Scatter-gather mode enable
191 * @param[in] u32DescAddr Scatter-gather descriptor address
192 *
193 * @return None
194 *
195 * @details This function set the selected channel transfer mode. Include peripheral setting.
196 */
PDMA_SetTransferMode(PDMA_T * pdma,uint32_t u32Ch,uint32_t u32Peripheral,uint32_t u32ScatterEn,uint32_t u32DescAddr)197 void PDMA_SetTransferMode(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32Peripheral, uint32_t u32ScatterEn, uint32_t u32DescAddr)
198 {
199 au8ChSelect[u32Ch] = (uint8_t)u32Peripheral;
200 switch(u32Ch)
201 {
202 case 0UL:
203 (pdma)->REQSEL0_3 = ((pdma)->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC0_Msk) | u32Peripheral;
204 break;
205 case 1UL:
206 (pdma)->REQSEL0_3 = ((pdma)->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC1_Msk) | (u32Peripheral << PDMA_REQSEL0_3_REQSRC1_Pos);
207 break;
208 case 2UL:
209 (pdma)->REQSEL0_3 = ((pdma)->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC2_Msk) | (u32Peripheral << PDMA_REQSEL0_3_REQSRC2_Pos);
210 break;
211 case 3UL:
212 (pdma)->REQSEL0_3 = ((pdma)->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC3_Msk) | (u32Peripheral << PDMA_REQSEL0_3_REQSRC3_Pos);
213 break;
214 case 4UL:
215 (pdma)->REQSEL4_7 = ((pdma)->REQSEL4_7 & ~PDMA_REQSEL4_7_REQSRC4_Msk) | u32Peripheral;
216 break;
217 case 5UL:
218 (pdma)->REQSEL4_7 = ((pdma)->REQSEL4_7 & ~PDMA_REQSEL4_7_REQSRC5_Msk) | (u32Peripheral << PDMA_REQSEL4_7_REQSRC5_Pos);
219 break;
220 case 6UL:
221 (pdma)->REQSEL4_7 = ((pdma)->REQSEL4_7 & ~PDMA_REQSEL4_7_REQSRC6_Msk) | (u32Peripheral << PDMA_REQSEL4_7_REQSRC6_Pos);
222 break;
223 case 7UL:
224 (pdma)->REQSEL4_7 = ((pdma)->REQSEL4_7 & ~PDMA_REQSEL4_7_REQSRC7_Msk) | (u32Peripheral << PDMA_REQSEL4_7_REQSRC7_Pos);
225 break;
226 default:
227 break;
228 }
229
230 if(u32ScatterEn)
231 {
232 (pdma)->DSCT[u32Ch].CTL = ((pdma)->DSCT[u32Ch].CTL & ~PDMA_DSCT_CTL_OPMODE_Msk) | PDMA_OP_SCATTER;
233 (pdma)->DSCT[u32Ch].NEXT = u32DescAddr - ((pdma)->SCATBA);
234 }
235 else
236 {
237 (pdma)->DSCT[u32Ch].CTL = ((pdma)->DSCT[u32Ch].CTL & ~PDMA_DSCT_CTL_OPMODE_Msk) | PDMA_OP_BASIC;
238 }
239 }
240
241 /**
242 * @brief Set PDMA Burst Type and Size
243 *
244 * @param[in] pdma The pointer of the specified PDMA module
245 * @param[in] u32Ch The selected channel
246 * @param[in] u32BurstType Burst mode or single mode. Valid values are
247 * - \ref PDMA_REQ_SINGLE
248 * - \ref PDMA_REQ_BURST
249 * @param[in] u32BurstSize Set the size of burst mode. Valid values are
250 * - \ref PDMA_BURST_128
251 * - \ref PDMA_BURST_64
252 * - \ref PDMA_BURST_32
253 * - \ref PDMA_BURST_16
254 * - \ref PDMA_BURST_8
255 * - \ref PDMA_BURST_4
256 * - \ref PDMA_BURST_2
257 * - \ref PDMA_BURST_1
258 *
259 * @return None
260 *
261 * @details This function set the selected channel burst type and size.
262 */
PDMA_SetBurstType(PDMA_T * pdma,uint32_t u32Ch,uint32_t u32BurstType,uint32_t u32BurstSize)263 void PDMA_SetBurstType(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32BurstType, uint32_t u32BurstSize)
264 {
265 (pdma)->DSCT[u32Ch].CTL &= ~(PDMA_DSCT_CTL_TXTYPE_Msk | PDMA_DSCT_CTL_BURSIZE_Msk);
266 (pdma)->DSCT[u32Ch].CTL |= (u32BurstType | u32BurstSize);
267 }
268
269 /**
270 * @brief Enable timeout function
271 *
272 * @param[in] pdma The pointer of the specified PDMA module
273 * @param[in] u32Mask Channel enable bits.
274 *
275 * @return None
276 *
277 * @details This function enable timeout function of the selected channel(s).
278 This function is only supported in channel 0 and channel 1.
279 */
PDMA_EnableTimeout(PDMA_T * pdma,uint32_t u32Mask)280 void PDMA_EnableTimeout(PDMA_T *pdma, uint32_t u32Mask)
281 {
282 (pdma)->TOUTEN |= u32Mask;
283 }
284
285 /**
286 * @brief Disable timeout function
287 *
288 * @param[in] pdma The pointer of the specified PDMA module
289 * @param[in] u32Mask Channel enable bits.
290 *
291 * @return None
292 *
293 * @details This function disable timeout function of the selected channel(s).
294 This function is only supported in channel 0 and channel 1.
295 */
PDMA_DisableTimeout(PDMA_T * pdma,uint32_t u32Mask)296 void PDMA_DisableTimeout(PDMA_T *pdma, uint32_t u32Mask)
297 {
298 (pdma)->TOUTEN &= ~u32Mask;
299 }
300
301 /**
302 * @brief Set PDMA Timeout Count
303 *
304 * @param[in] pdma The pointer of the specified PDMA module
305 * @param[in] u32Ch The selected channel
306 * @param[in] u32OnOff Enable/disable timeout function
307 * @param[in] u32TimeOutCnt Timeout count
308 *
309 * @return None
310 *
311 * @details This function set the timeout count.
312 This function is only supported in channel 0 and channel 1.
313 */
PDMA_SetTimeOut(PDMA_T * pdma,uint32_t u32Ch,uint32_t u32OnOff,uint32_t u32TimeOutCnt)314 void PDMA_SetTimeOut(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32OnOff, uint32_t u32TimeOutCnt)
315 {
316 switch(u32Ch)
317 {
318 case 0UL:
319 (pdma)->TOC0_1 = ((pdma)->TOC0_1 & ~PDMA_TOC0_1_TOC0_Msk) | u32TimeOutCnt;
320 break;
321 case 1UL:
322 (pdma)->TOC0_1 = ((pdma)->TOC0_1 & ~PDMA_TOC0_1_TOC1_Msk) | (u32TimeOutCnt << PDMA_TOC0_1_TOC1_Pos);
323 break;
324
325 default:
326 break;
327 }
328 if(u32OnOff)
329 {
330 (pdma)->TOUTEN |= (1UL << u32Ch);
331 }
332 else
333 {
334 (pdma)->TOUTEN &= ~(1UL << u32Ch);
335 }
336 }
337
338 /**
339 * @brief Trigger PDMA
340 *
341 * @param[in] pdma The pointer of the specified PDMA module
342 * @param[in] u32Ch The selected channel
343 *
344 * @return None
345 *
346 * @details This function trigger the selected channel.
347 */
PDMA_Trigger(PDMA_T * pdma,uint32_t u32Ch)348 void PDMA_Trigger(PDMA_T *pdma, uint32_t u32Ch)
349 {
350 if(au8ChSelect[u32Ch] == PDMA_MEM)
351 {
352 (pdma)->SWREQ = (1UL << u32Ch);
353 }
354 }
355
356 /**
357 * @brief Enable Interrupt
358 *
359 * @param[in] pdma The pointer of the specified PDMA module
360 * @param[in] u32Ch The selected channel
361 * @param[in] u32Mask The Interrupt Type. Valid values are
362 * - \ref PDMA_INT_TRANS_DONE
363 * - \ref PDMA_INT_TABLE
364 * - \ref PDMA_INT_TIMEOUT
365 * - \ref PDMA_INT_ALIGN
366 *
367 * @return None
368 *
369 * @details This function enable the selected channel interrupt.
370 PDMA_INT_TIMEOUT is only supported in channel 0 and channel 1.
371 */
PDMA_EnableInt(PDMA_T * pdma,uint32_t u32Ch,uint32_t u32Mask)372 void PDMA_EnableInt(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32Mask)
373 {
374 switch(u32Mask)
375 {
376 case PDMA_INT_TRANS_DONE:
377 case PDMA_INT_ALIGN:
378 (pdma)->INTEN |= (1UL << u32Ch);
379 break;
380 case PDMA_INT_TABLE:
381 (pdma)->DSCT[u32Ch].CTL &= ~PDMA_DSCT_CTL_TBINTDIS_Msk;
382 break;
383 case PDMA_INT_TIMEOUT:
384 (pdma)->TOUTIEN |= (1UL << u32Ch);
385 break;
386
387 default:
388 break;
389 }
390 }
391
392 /**
393 * @brief Disable Interrupt
394 *
395 * @param[in] pdma The pointer of the specified PDMA module
396 * @param[in] u32Ch The selected channel
397 * @param[in] u32Mask The Interrupt Type. Valid values are
398 * - \ref PDMA_INT_TRANS_DONE
399 * - \ref PDMA_INT_TABLE
400 * - \ref PDMA_INT_TIMEOUT
401 * - \ref PDMA_INT_ALIGN
402 *
403 * @return None
404 *
405 * @details This function disable the selected channel interrupt.
406 PDMA_INT_TIMEOUT is only supported in channel 0 and channel 1.
407 The transfer done interrupt is disabled when table empty interrupt is disabled(PDMA_INT_TEMPTY).
408 */
PDMA_DisableInt(PDMA_T * pdma,uint32_t u32Ch,uint32_t u32Mask)409 void PDMA_DisableInt(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32Mask)
410 {
411 switch(u32Mask)
412 {
413 case PDMA_INT_TRANS_DONE:
414 case PDMA_INT_ALIGN:
415 (pdma)->INTEN &= ~(1UL << u32Ch);
416 break;
417 case PDMA_INT_TABLE:
418 (pdma)->DSCT[u32Ch].CTL |= PDMA_DSCT_CTL_TBINTDIS_Msk;
419 break;
420 case PDMA_INT_TIMEOUT:
421 (pdma)->TOUTIEN &= ~(1UL << u32Ch);
422 break;
423
424 default:
425 break;
426 }
427 }
428
429 /*@}*/ /* end of group PDMA_EXPORTED_FUNCTIONS */
430
431 /*@}*/ /* end of group PDMA_Driver */
432
433 /*@}*/ /* end of group Standard_Driver */
434
435