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