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