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