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