1 /**************************************************************************//**
2  * @file     pdma.c
3  * @version  V3.00
4  * @brief    M2354 series PDMA driver source file
5  *
6  * @copyright SPDX-License-Identifier: Apache-2.0
7  * @copyright Copyright (C) 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 Repeat
110   *
111  * @param[in]   pdma                The pointer of the specified PDMA module
112  * @param[in]   u32Ch               The selected channel
113  * @param[in]   u32DestInterval     Destination address interval count
114  * @param[in]   u32SrcInterval      Source address interval count
115  * @param[in]   u32RepeatCount      Repeat count
116  *
117  * @return      None
118  *
119  * @details     This function set the selected repeat.
120  */
PDMA_SetRepeat(PDMA_T * pdma,uint32_t u32Ch,uint32_t u32DestInterval,uint32_t u32SrcInterval,uint32_t u32RepeatCount)121 void PDMA_SetRepeat(PDMA_T * pdma, uint32_t u32Ch, uint32_t u32DestInterval, uint32_t u32SrcInterval, uint32_t u32RepeatCount)
122 {
123     pdma->DSCT[u32Ch].CTL |= PDMA_DSCT_CTL_STRIDEEN_Msk;
124     pdma->REPEAT[u32Ch].AICTL = ((u32DestInterval) << 16) | (u32SrcInterval);
125     pdma->REPEAT[u32Ch].RCNT = u32RepeatCount;
126 }
127 
128 /**
129  * @brief       Set PDMA Transfer Address
130  *
131  * @param[in]   pdma            The pointer of the specified PDMA module
132  * @param[in]   u32Ch           The selected channel
133  * @param[in]   u32SrcAddr      Source address
134  * @param[in]   u32SrcCtrl      Source control attribute. Valid values are
135  *                - \ref PDMA_SAR_INC
136  *                - \ref PDMA_SAR_FIX
137  * @param[in]   u32DstAddr      destination address
138  * @param[in]   u32DstCtrl      destination control attribute. Valid values are
139  *                - \ref PDMA_DAR_INC
140  *                - \ref PDMA_DAR_FIX
141  *
142  * @return      None
143  *
144  * @details     This function set the selected channel source/destination address and attribute.
145  */
PDMA_SetTransferAddr(PDMA_T * pdma,uint32_t u32Ch,uint32_t u32SrcAddr,uint32_t u32SrcCtrl,uint32_t u32DstAddr,uint32_t u32DstCtrl)146 void PDMA_SetTransferAddr(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32SrcAddr, uint32_t u32SrcCtrl, uint32_t u32DstAddr, uint32_t u32DstCtrl)
147 {
148     (pdma)->DSCT[u32Ch].SA = u32SrcAddr;
149     (pdma)->DSCT[u32Ch].DA = u32DstAddr;
150     (pdma)->DSCT[u32Ch].CTL &= ~(PDMA_DSCT_CTL_SAINC_Msk | PDMA_DSCT_CTL_DAINC_Msk);
151     (pdma)->DSCT[u32Ch].CTL |= (u32SrcCtrl | u32DstCtrl);
152 }
153 
154 /**
155  * @brief       Set PDMA Transfer Mode
156  *
157  * @param[in]   pdma            The pointer of the specified PDMA module
158  * @param[in]   u32Ch           The selected channel
159  * @param[in]   u32Peripheral   The selected peripheral. Valid values are
160  *                - \ref PDMA_MEM
161  *                - \ref PDMA_USB_TX
162  *                - \ref PDMA_USB_RX
163  *                - \ref PDMA_UART0_TX
164  *                - \ref PDMA_UART0_RX
165  *                - \ref PDMA_UART1_TX
166  *                - \ref PDMA_UART1_RX
167  *                - \ref PDMA_UART2_TX
168  *                - \ref PDMA_UART2_RX
169  *                - \ref PDMA_UART3_TX
170  *                - \ref PDMA_UART3_RX
171  *                - \ref PDMA_UART4_TX
172  *                - \ref PDMA_UART4_RX
173  *                - \ref PDMA_UART5_TX
174  *                - \ref PDMA_UART5_RX
175  *                - \ref PDMA_USCI0_TX
176  *                - \ref PDMA_USCI0_RX
177  *                - \ref PDMA_USCI1_TX
178  *                - \ref PDMA_USCI1_RX
179  *                - \ref PDMA_QSPI0_TX
180  *                - \ref PDMA_QSPI0_RX
181  *                - \ref PDMA_SPI0_TX
182  *                - \ref PDMA_SPI0_RX
183  *                - \ref PDMA_SPI1_TX
184  *                - \ref PDMA_SPI1_RX
185  *                - \ref PDMA_SPI2_TX
186  *                - \ref PDMA_SPI2_RX
187  *                - \ref PDMA_SPI3_TX
188  *                - \ref PDMA_SPI3_RX
189  *                - \ref PDMA_EPWM0_P1_RX
190  *                - \ref PDMA_EPWM0_P2_RX
191  *                - \ref PDMA_EPWM0_P3_RX
192  *                - \ref PDMA_EPWM1_P1_RX
193  *                - \ref PDMA_EPWM1_P2_RX
194  *                - \ref PDMA_EPWM1_P3_RX
195  *                - \ref PDMA_I2C0_TX
196  *                - \ref PDMA_I2C0_RX
197  *                - \ref PDMA_I2C1_TX
198  *                - \ref PDMA_I2C1_RX
199  *                - \ref PDMA_I2C2_TX
200  *                - \ref PDMA_I2C2_RX
201  *                - \ref PDMA_I2S0_TX
202  *                - \ref PDMA_I2S0_RX
203  *                - \ref PDMA_TMR0
204  *                - \ref PDMA_TMR1
205  *                - \ref PDMA_TMR2
206  *                - \ref PDMA_TMR3
207  *                - \ref PDMA_ADC_RX
208  *                - \ref PDMA_DAC0_TX
209  *                - \ref PDMA_DAC1_TX
210  *                - \ref PDMA_EPWM0_CH0_TX
211  *                - \ref PDMA_EPWM0_CH1_TX
212  *                - \ref PDMA_EPWM0_CH2_TX
213  *                - \ref PDMA_EPWM0_CH3_TX
214  *                - \ref PDMA_EPWM0_CH4_TX
215  *                - \ref PDMA_EPWM0_CH5_TX
216  *                - \ref PDMA_EPWM1_CH0_TX
217  *                - \ref PDMA_EPWM1_CH1_TX
218  *                - \ref PDMA_EPWM1_CH2_TX
219  *                - \ref PDMA_EPWM1_CH3_TX
220  *                - \ref PDMA_EPWM1_CH4_TX
221  *                - \ref PDMA_EPWM1_CH5_TX
222  * @param[in]   u32ScatterEn    Scatter-gather mode enable
223  * @param[in]   u32DescAddr     Scatter-gather descriptor address
224  *
225  * @return      None
226  *
227  * @details     This function set the selected channel transfer mode. Include peripheral setting.
228  */
PDMA_SetTransferMode(PDMA_T * pdma,uint32_t u32Ch,uint32_t u32Peripheral,uint32_t u32ScatterEn,uint32_t u32DescAddr)229 void PDMA_SetTransferMode(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32Peripheral, uint32_t u32ScatterEn, uint32_t u32DescAddr)
230 {
231     au8ChSelect[u32Ch] = (uint8_t)u32Peripheral;
232     switch(u32Ch)
233     {
234         case 0UL:
235             (pdma)->REQSEL0_3 = ((pdma)->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC0_Msk) | u32Peripheral;
236             break;
237         case 1UL:
238             (pdma)->REQSEL0_3 = ((pdma)->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC1_Msk) | (u32Peripheral << PDMA_REQSEL0_3_REQSRC1_Pos);
239             break;
240         case 2UL:
241             (pdma)->REQSEL0_3 = ((pdma)->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC2_Msk) | (u32Peripheral << PDMA_REQSEL0_3_REQSRC2_Pos);
242             break;
243         case 3UL:
244             (pdma)->REQSEL0_3 = ((pdma)->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC3_Msk) | (u32Peripheral << PDMA_REQSEL0_3_REQSRC3_Pos);
245             break;
246         case 4UL:
247             (pdma)->REQSEL4_7 = ((pdma)->REQSEL4_7 & ~PDMA_REQSEL4_7_REQSRC4_Msk) | u32Peripheral;
248             break;
249         case 5UL:
250             (pdma)->REQSEL4_7 = ((pdma)->REQSEL4_7 & ~PDMA_REQSEL4_7_REQSRC5_Msk) | (u32Peripheral << PDMA_REQSEL4_7_REQSRC5_Pos);
251             break;
252         case 6UL:
253             (pdma)->REQSEL4_7 = ((pdma)->REQSEL4_7 & ~PDMA_REQSEL4_7_REQSRC6_Msk) | (u32Peripheral << PDMA_REQSEL4_7_REQSRC6_Pos);
254             break;
255         case 7UL:
256             (pdma)->REQSEL4_7 = ((pdma)->REQSEL4_7 & ~PDMA_REQSEL4_7_REQSRC7_Msk) | (u32Peripheral << PDMA_REQSEL4_7_REQSRC7_Pos);
257             break;
258         default:
259             break;
260     }
261 
262     if(u32ScatterEn)
263     {
264         (pdma)->DSCT[u32Ch].CTL = ((pdma)->DSCT[u32Ch].CTL & ~PDMA_DSCT_CTL_OPMODE_Msk) | PDMA_OP_SCATTER;
265         (pdma)->DSCT[u32Ch].NEXT = u32DescAddr - ((pdma)->SCATBA);
266     }
267     else
268     {
269         (pdma)->DSCT[u32Ch].CTL = ((pdma)->DSCT[u32Ch].CTL & ~PDMA_DSCT_CTL_OPMODE_Msk) | PDMA_OP_BASIC;
270     }
271 }
272 
273 /**
274  * @brief       Set PDMA Burst Type and Size
275  *
276  * @param[in]   pdma            The pointer of the specified PDMA module
277  * @param[in]   u32Ch           The selected channel
278  * @param[in]   u32BurstType    Burst mode or single mode. Valid values are
279  *                - \ref PDMA_REQ_SINGLE
280  *                - \ref PDMA_REQ_BURST
281  * @param[in]   u32BurstSize    Set the size of burst mode. Valid values are
282  *                - \ref PDMA_BURST_128
283  *                - \ref PDMA_BURST_64
284  *                - \ref PDMA_BURST_32
285  *                - \ref PDMA_BURST_16
286  *                - \ref PDMA_BURST_8
287  *                - \ref PDMA_BURST_4
288  *                - \ref PDMA_BURST_2
289  *                - \ref PDMA_BURST_1
290  *
291  * @return      None
292  *
293  * @details     This function set the selected channel burst type and size.
294  */
PDMA_SetBurstType(PDMA_T * pdma,uint32_t u32Ch,uint32_t u32BurstType,uint32_t u32BurstSize)295 void PDMA_SetBurstType(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32BurstType, uint32_t u32BurstSize)
296 {
297     (pdma)->DSCT[u32Ch].CTL &= ~(PDMA_DSCT_CTL_TXTYPE_Msk | PDMA_DSCT_CTL_BURSIZE_Msk);
298     (pdma)->DSCT[u32Ch].CTL |= (u32BurstType | u32BurstSize);
299 }
300 
301 /**
302  * @brief       Enable timeout function
303  *
304  * @param[in]   pdma            The pointer of the specified PDMA module
305  * @param[in]   u32Mask         Channel enable bits.
306  *
307  * @return      None
308  *
309  * @details     This function enable timeout function of the selected channel(s).
310  * @note        This function is only supported in channel 0 and channel 1.
311  */
PDMA_EnableTimeout(PDMA_T * pdma,uint32_t u32Mask)312 void PDMA_EnableTimeout(PDMA_T *pdma, uint32_t u32Mask)
313 {
314     (pdma)->TOUTEN |= u32Mask;
315 }
316 
317 /**
318  * @brief       Disable timeout function
319  *
320  * @param[in]   pdma            The pointer of the specified PDMA module
321  * @param[in]   u32Mask         Channel enable bits.
322  *
323  * @return      None
324  *
325  * @details     This function disable timeout function of the selected channel(s).
326  * @note        This function is only supported in channel 0 and channel 1.
327  */
PDMA_DisableTimeout(PDMA_T * pdma,uint32_t u32Mask)328 void PDMA_DisableTimeout(PDMA_T *pdma, uint32_t u32Mask)
329 {
330     (pdma)->TOUTEN &= ~u32Mask;
331 }
332 
333 /**
334  * @brief       Set PDMA Timeout Count
335  *
336  * @param[in]   pdma            The pointer of the specified PDMA module
337  * @param[in]   u32Ch           The selected channel
338  * @param[in]   u32OnOff        Enable/disable timeout function
339  * @param[in]   u32TimeOutCnt   Timeout count
340  *
341  * @return      None
342  *
343  * @details     This function set the timeout count.
344  * @note        This function is only supported in channel 0 and channel 1.
345  */
PDMA_SetTimeOut(PDMA_T * pdma,uint32_t u32Ch,uint32_t u32OnOff,uint32_t u32TimeOutCnt)346 void PDMA_SetTimeOut(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32OnOff, uint32_t u32TimeOutCnt)
347 {
348     switch(u32Ch)
349     {
350         case 0UL:
351             (pdma)->TOC0_1 = ((pdma)->TOC0_1 & ~PDMA_TOC0_1_TOC0_Msk) | u32TimeOutCnt;
352             break;
353         case 1UL:
354             (pdma)->TOC0_1 = ((pdma)->TOC0_1 & ~PDMA_TOC0_1_TOC1_Msk) | (u32TimeOutCnt << PDMA_TOC0_1_TOC1_Pos);
355             break;
356 
357         default:
358             break;
359     }
360     if(u32OnOff)
361     {
362         (pdma)->TOUTEN |= (1UL << u32Ch);
363     }
364     else
365     {
366         (pdma)->TOUTEN &= ~(1UL << u32Ch);
367     }
368 }
369 
370 /**
371  * @brief       Trigger PDMA
372  *
373  * @param[in]   pdma            The pointer of the specified PDMA module
374  * @param[in]   u32Ch           The selected channel
375  *
376  * @return      None
377  *
378  * @details     This function trigger the selected channel.
379  */
PDMA_Trigger(PDMA_T * pdma,uint32_t u32Ch)380 void PDMA_Trigger(PDMA_T *pdma, uint32_t u32Ch)
381 {
382     if(au8ChSelect[u32Ch] == PDMA_MEM)
383     {
384         (pdma)->SWREQ = (1UL << u32Ch);
385     }
386 }
387 
388 /**
389  * @brief       Enable Interrupt
390  *
391  * @param[in]   pdma            The pointer of the specified PDMA module
392  * @param[in]   u32Ch           The selected channel
393  * @param[in]   u32Mask         The Interrupt Type. Valid values are
394  *                - \ref PDMA_INT_TRANS_DONE
395  *                - \ref PDMA_INT_TABLE
396  *                - \ref PDMA_INT_TIMEOUT
397  *                - \ref PDMA_INT_ALIGN
398  *
399  * @return      None
400  *
401  * @details     This function enable the selected channel interrupt.
402  * @note        PDMA_INT_TIMEOUT is only supported in channel 0 and channel 1.
403  */
PDMA_EnableInt(PDMA_T * pdma,uint32_t u32Ch,uint32_t u32Mask)404 void PDMA_EnableInt(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32Mask)
405 {
406     switch(u32Mask)
407     {
408         case PDMA_INT_TRANS_DONE:
409         case PDMA_INT_ALIGN:
410             (pdma)->INTEN |= (1UL << u32Ch);
411             break;
412         case PDMA_INT_TABLE:
413             (pdma)->DSCT[u32Ch].CTL &= ~PDMA_DSCT_CTL_TBINTDIS_Msk;
414             break;
415         case PDMA_INT_TIMEOUT:
416             (pdma)->TOUTIEN |= (1UL << u32Ch);
417             break;
418 
419         default:
420             break;
421     }
422 }
423 
424 /**
425  * @brief       Disable Interrupt
426  *
427  * @param[in]   pdma            The pointer of the specified PDMA module
428  * @param[in]   u32Ch           The selected channel
429  * @param[in]   u32Mask         The Interrupt Type. Valid values are
430  *                - \ref PDMA_INT_TRANS_DONE
431  *                - \ref PDMA_INT_TABLE
432  *                - \ref PDMA_INT_TIMEOUT
433  *                - \ref PDMA_INT_ALIGN
434  *
435  * @return      None
436  *
437  * @details     This function disable the selected channel interrupt.
438  * @note        PDMA_INT_TIMEOUT is only supported in channel 0 and channel 1.
439  * @note        The transfer done interrupt is disabled when table empty interrupt is disabled(PDMA_INT_TEMPTY).
440  */
PDMA_DisableInt(PDMA_T * pdma,uint32_t u32Ch,uint32_t u32Mask)441 void PDMA_DisableInt(PDMA_T *pdma, uint32_t u32Ch, uint32_t u32Mask)
442 {
443     switch(u32Mask)
444     {
445         case PDMA_INT_TRANS_DONE:
446         case PDMA_INT_ALIGN:
447             (pdma)->INTEN &= ~(1UL << u32Ch);
448             break;
449         case PDMA_INT_TABLE:
450             (pdma)->DSCT[u32Ch].CTL |= PDMA_DSCT_CTL_TBINTDIS_Msk;
451             break;
452         case PDMA_INT_TIMEOUT:
453             (pdma)->TOUTIEN &= ~(1UL << u32Ch);
454             break;
455 
456         default:
457             break;
458     }
459 }
460 
461 /**@}*/ /* end of group PDMA_EXPORTED_FUNCTIONS */
462 
463 /**@}*/ /* end of group PDMA_Driver */
464 
465 /**@}*/ /* end of group Standard_Driver */
466