| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gpdma_18xx_43xx.c
Go to the documentation of this file.
1 /*
2 * @brief LPC18xx/43xx DMA driver
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2012
6 * All rights reserved.
7 *
8 * @par
9 * Software that is described herein is for illustrative purposes only
10 * which provides customers with programming information regarding the
11 * LPC products. This software is supplied "AS IS" without any warranties of
12 * any kind, and NXP Semiconductors and its licensor disclaim any and
13 * all warranties, express or implied, including all implied warranties of
14 * merchantability, fitness for a particular purpose and non-infringement of
15 * intellectual property rights. NXP Semiconductors assumes no responsibility
16 * or liability for the use of the software, conveys no license or rights under any
17 * patent, copyright, mask work right, or any other intellectual property rights in
18 * or to any products. NXP Semiconductors reserves the right to make changes
19 * in the software without notification. NXP Semiconductors also makes no
20 * representation or warranty that such application will be suitable for the
21 * specified use without further testing or modification.
22 *
23 * @par
24 * Permission to use, copy, modify, and distribute this software and its
25 * documentation is hereby granted, under NXP Semiconductors' and its
26 * licensor's relevant copyrights in the software, without fee, provided that it
27 * is used in conjunction with NXP Semiconductors microcontrollers. This
28 * copyright, permission, and disclaimer notice must appear in all copies of
29 * this code.
30 */
31
32 #include "chip.h"
33
34 /*****************************************************************************
35 * Private types/enumerations/variables
36 ****************************************************************************/
37
38 /* Channel array to monitor free channel */
39 static DMA_ChannelHandle_t ChannelHandlerArray[GPDMA_NUMBER_CHANNELS];
40
41 /* Optimized Peripheral Source and Destination burst size (18xx,43xx) */
42 static const uint8_t GPDMA_LUTPerBurst[] = {
43 GPDMA_BSIZE_4, /* MEMORY */
44 GPDMA_BSIZE_1, /* MAT0.0 */
45 GPDMA_BSIZE_1, /* UART0 Tx */
46 GPDMA_BSIZE_1, /* MAT0.1 */
47 GPDMA_BSIZE_1, /* UART0 Rx */
48 GPDMA_BSIZE_1, /* MAT1.0 */
49 GPDMA_BSIZE_1, /* UART1 Tx */
50 GPDMA_BSIZE_1, /* MAT1.1 */
51 GPDMA_BSIZE_1, /* UART1 Rx */
52 GPDMA_BSIZE_1, /* MAT2.0 */
53 GPDMA_BSIZE_1, /* UART2 Tx */
54 GPDMA_BSIZE_1, /* MAT2.1 */
55 GPDMA_BSIZE_1, /* UART2 Rx */
56 GPDMA_BSIZE_1, /* MAT3.0 */
57 GPDMA_BSIZE_1, /* UART3 Tx */
58 0, /* SCT timer channel 0*/
59 GPDMA_BSIZE_1, /* MAT3.1 */
60 GPDMA_BSIZE_1, /* UART3 Rx */
61 0, /* SCT timer channel 1*/
62 GPDMA_BSIZE_4, /* SSP0 Rx */
63 GPDMA_BSIZE_32, /* I2S channel 0 */
64 GPDMA_BSIZE_4, /* SSP0 Tx */
65 GPDMA_BSIZE_32, /* I2S channel 1 */
66 GPDMA_BSIZE_4, /* SSP1 Rx */
67 GPDMA_BSIZE_4, /* SSP1 Tx */
68 GPDMA_BSIZE_4, /* ADC 0 */
69 GPDMA_BSIZE_4, /* ADC 1 */
70 GPDMA_BSIZE_1, /* DAC */
71 GPDMA_BSIZE_32, /* I2S channel 0 */
72 GPDMA_BSIZE_32 /* I2S channel 0 */
73 };
74
75 /* Optimized Peripheral Source and Destination transfer width (18xx,43xx) */
76 static const uint8_t GPDMA_LUTPerWid[] = {
77 GPDMA_WIDTH_WORD, /* MEMORY */
78 GPDMA_WIDTH_WORD, /* MAT0.0 */
79 GPDMA_WIDTH_BYTE, /* UART0 Tx */
80 GPDMA_WIDTH_WORD, /* MAT0.1 */
81 GPDMA_WIDTH_BYTE, /* UART0 Rx */
82 GPDMA_WIDTH_WORD, /* MAT1.0 */
83 GPDMA_WIDTH_BYTE, /* UART1 Tx */
84 GPDMA_WIDTH_WORD, /* MAT1.1 */
85 GPDMA_WIDTH_BYTE, /* UART1 Rx */
86 GPDMA_WIDTH_WORD, /* MAT2.0 */
87 GPDMA_WIDTH_BYTE, /* UART2 Tx */
88 GPDMA_WIDTH_WORD, /* MAT2.1 */
89 GPDMA_WIDTH_BYTE, /* UART2 Rx */
90 GPDMA_WIDTH_WORD, /* MAT3.0 */
91 GPDMA_WIDTH_BYTE, /* UART3 Tx */
92 0, /* SCT timer channel 0*/
93 GPDMA_WIDTH_WORD, /* MAT3.1 */
94 GPDMA_WIDTH_BYTE, /* UART3 Rx */
95 0, /* SCT timer channel 1*/
96 GPDMA_WIDTH_BYTE, /* SSP0 Rx */
97 GPDMA_WIDTH_WORD, /* I2S channel 0 */
98 GPDMA_WIDTH_BYTE, /* SSP0 Tx */
99 GPDMA_WIDTH_WORD, /* I2S channel 1 */
100 GPDMA_WIDTH_BYTE, /* SSP1 Rx */
101 GPDMA_WIDTH_BYTE, /* SSP1 Tx */
102 GPDMA_WIDTH_WORD, /* ADC 0 */
103 GPDMA_WIDTH_WORD, /* ADC 1 */
104 GPDMA_WIDTH_WORD, /* DAC */
105 GPDMA_WIDTH_WORD, /* I2S channel 0 */
106 GPDMA_WIDTH_WORD/* I2S channel 0 */
107 };
108
109 /* Lookup Table of Connection Type matched with (18xx,43xx) Peripheral Data (FIFO) register base address */
110 volatile static const void *GPDMA_LUTPerAddr[] = {
111 NULL, /* MEMORY */
112 (&LPC_TIMER0->MR), /* MAT0.0 */
113 (&LPC_USART0-> /*RBTHDLR.*/ THR), /* UART0 Tx */
114 ((uint32_t *) &LPC_TIMER0->MR + 1), /* MAT0.1 */
115 (&LPC_USART0-> /*RBTHDLR.*/ RBR), /* UART0 Rx */
116 (&LPC_TIMER1->MR), /* MAT1.0 */
117 (&LPC_UART1-> /*RBTHDLR.*/ THR),/* UART1 Tx */
118 ((uint32_t *) &LPC_TIMER1->MR + 1), /* MAT1.1 */
119 (&LPC_UART1-> /*RBTHDLR.*/ RBR),/* UART1 Rx */
120 (&LPC_TIMER2->MR), /* MAT2.0 */
121 (&LPC_USART2-> /*RBTHDLR.*/ THR), /* UART2 Tx */
122 ((uint32_t *) &LPC_TIMER2->MR + 1), /* MAT2.1 */
123 (&LPC_USART2-> /*RBTHDLR.*/ RBR), /* UART2 Rx */
124 (&LPC_TIMER3->MR), /* MAT3.0 */
125 (&LPC_USART3-> /*RBTHDLR.*/ THR), /* UART3 Tx */
126 0, /* SCT timer channel 0*/
127 ((uint32_t *) &LPC_TIMER3->MR + 1), /* MAT3.1 */
128 (&LPC_USART3-> /*RBTHDLR.*/ RBR), /* UART3 Rx */
129 0, /* SCT timer channel 1*/
130 (&LPC_SSP0->DR), /* SSP0 Rx */
131 (&LPC_I2S0->TXFIFO), /* I2S channel 0 */
132 (&LPC_SSP0->DR), /* SSP0 Tx */
133 (&LPC_I2S0->RXFIFO), /* I2S channel 1 */
134 (&LPC_SSP1->DR), /* SSP1 Rx */
135 (&LPC_SSP1->DR), /* SSP1 Tx */
136 (&LPC_ADC0->GDR), /* ADC 0 */
137 (&LPC_ADC1->GDR), /* ADC 1 */
138 (&LPC_DAC->CR), /* DAC */
139 (&LPC_I2S0->TXFIFO), /* I2S channel 0 */
140 (&LPC_I2S0->RXFIFO) /* I2S channel 0 */
141 };
142
143 /*****************************************************************************
144 * Public types/enumerations/variables
145 ****************************************************************************/
146
147 /*****************************************************************************
148 * Private functions
149 ****************************************************************************/
150
151 /* Control which set of peripherals is connected to the DMA controller */
152 static uint8_t DMAMUX_Config(uint32_t gpdma_peripheral_connection_number)
153 {
154 uint8_t function, channel;
155
156 switch (gpdma_peripheral_connection_number) {
157 case GPDMA_CONN_MAT0_0:
158 function = 0;
159 channel = 1;
160 break;
161
162 case GPDMA_CONN_UART0_Tx:
163 function = 1;
164 channel = 1;
165 break;
166
167 case GPDMA_CONN_MAT0_1:
168 function = 0;
169 channel = 2;
170 break;
171
172 case GPDMA_CONN_UART0_Rx:
173 function = 1;
174 channel = 2;
175 break;
176
177 case GPDMA_CONN_MAT1_0:
178 function = 0;
179 channel = 3;
180 break;
181
182 case GPDMA_CONN_UART1_Tx:
183 function = 1;
184 channel = 3;
185 break;
186
187 case GPDMA_CONN_MAT1_1:
188 function = 0;
189 channel = 4;
190 break;
191
192 case GPDMA_CONN_UART1_Rx:
193 function = 1;
194 channel = 4;
195 break;
196
197 case GPDMA_CONN_MAT2_0:
198 function = 0;
199 channel = 5;
200 break;
201
202 case GPDMA_CONN_UART2_Tx:
203 function = 1;
204 channel = 5;
205 break;
206
207 case GPDMA_CONN_MAT2_1:
208 function = 0;
209 channel = 6;
210 break;
211
212 case GPDMA_CONN_UART2_Rx:
213 function = 1;
214 channel = 6;
215 break;
216
217 case GPDMA_CONN_MAT3_0:
218 function = 0;
219 channel = 7;
220 break;
221
222 case GPDMA_CONN_UART3_Tx:
223 function = 1;
224 channel = 7;
225 break;
226
227 case GPDMA_CONN_SCT_0:
228 function = 2;
229 channel = 7;
230 break;
231
232 case GPDMA_CONN_MAT3_1:
233 function = 0;
234 channel = 8;
235 break;
236
237 case GPDMA_CONN_UART3_Rx:
238 function = 1;
239 channel = 8;
240 break;
241
242 case GPDMA_CONN_SCT_1:
243 function = 2;
244 channel = 8;
245 break;
246
247 case GPDMA_CONN_SSP0_Rx:
248 function = 0;
249 channel = 9;
250 break;
251
252 case GPDMA_CONN_I2S_Tx_Channel_0:
253 case GPDMA_CONN_I2S_Rx_Channel_0:
254 function = 1;
255 channel = 9;
256 break;
257
258 case GPDMA_CONN_SSP0_Tx:
259 function = 0;
260 channel = 10;
261 break;
262
263 case GPDMA_CONN_I2S_Tx_Channel_1:
264 case GPDMA_CONN_I2S_Rx_Channel_1:
265 function = 1;
266 channel = 10;
267 break;
268
269 case GPDMA_CONN_SSP1_Rx:
270 function = 0;
271 channel = 11;
272 break;
273
274 case GPDMA_CONN_SSP1_Tx:
275 function = 0;
276 channel = 12;
277 break;
278
279 case GPDMA_CONN_ADC_0:
280 function = 0;
281 channel = 13;
282 break;
283
284 case GPDMA_CONN_ADC_1:
285 function = 0;
286 channel = 14;
287 break;
288
289 case GPDMA_CONN_DAC:
290 function = 0;
291 channel = 15;
292 break;
293
294 default:
295 function = 3;
296 channel = 15;
297 break;
298 }
299 /* Set select function to dmamux register */
300 if (0 != gpdma_peripheral_connection_number) {
301 uint32_t temp;
302 temp = LPC_CREG->DMAMUX & (~(0x03 << (2 * channel)));
303 LPC_CREG->DMAMUX = temp | (function << (2 * channel));
304 }
305 return channel;
306 }
307
308 /*****************************************************************************
309 * Public functions
310 ****************************************************************************/
311
312 /* Initialize the GPDMA */
313 void Chip_GPDMA_Init(LPC_GPDMA_T *pGPDMA)
314 {
315 uint8_t i;
316
317 Chip_Clock_EnableOpts(CLK_MX_DMA, true, true, 1);
318 IP_GPDMA_Init(pGPDMA);
319 /* Reset all channels are free */
320 for (i = 0; i < GPDMA_NUMBER_CHANNELS; i++) {
321 ChannelHandlerArray[i].ChannelStatus = DISABLE;
322 }
323 }
324
325 /* Shutdown the GPDMA */
326 void Chip_GPDMA_DeInit(LPC_GPDMA_T *pGPDMA)
327 {
328 Chip_Clock_Disable(CLK_MX_DMA);
329 }
330
331 /* Stop a stream DMA transfer */
332 void Chip_DMA_Stop(LPC_GPDMA_T *pGPDMA,
333 uint8_t ChannelNum)
334 {
335 IP_GPDMA_ChannelCmd(pGPDMA, (ChannelNum), DISABLE);
336 if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INTTC, ChannelNum)) {
337 /* Clear terminate counter Interrupt pending */
338 Chip_GPDMA_ClearIntPending(pGPDMA, GPDMA_STATCLR_INTTC, ChannelNum);
339 }
340 if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INTERR, ChannelNum)) {
341 /* Clear terminate counter Interrupt pending */
342 Chip_GPDMA_ClearIntPending(pGPDMA, GPDMA_STATCLR_INTERR, ChannelNum);
343 }
344 ChannelHandlerArray[ChannelNum].ChannelStatus = DISABLE;
345 }
346
347 /* The GPDMA stream interrupt status checking */
348 Status Chip_DMA_Interrupt(LPC_GPDMA_T *pGPDMA,
349 uint8_t ChannelNum)
350 {
351
352 if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INT, ChannelNum)) {
353 /* Check counter terminal status */
354 if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INTTC, ChannelNum)) {
355 /* Clear terminate counter Interrupt pending */
356 Chip_GPDMA_ClearIntPending(pGPDMA, GPDMA_STATCLR_INTTC, ChannelNum);
357 return SUCCESS;
358 }
359 /* Check error terminal status */
360 if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INTERR, ChannelNum)) {
361 /* Clear error counter Interrupt pending */
362
363 Chip_GPDMA_ClearIntPending(pGPDMA, GPDMA_STATCLR_INTERR, ChannelNum);
364 return ERROR;
365 }
366 }
367 return ERROR;
368 }
369
370 int Chip_DMA_InitChannelCfg(LPC_GPDMA_T *pGPDMA,
371 GPDMA_Channel_CFG_T *GPDMACfg,
372 uint8_t ChannelNum,
373 uint32_t src,
374 uint32_t dst,
375 uint32_t Size,
376 IP_GPDMA_FLOW_CONTROL_T TransferType)
377 {
378 int rval = -1;
379 GPDMACfg->ChannelNum = ChannelNum;
380 GPDMACfg->TransferType = TransferType;
381 GPDMACfg->TransferSize = Size;
382
383 switch (TransferType) {
384 case GPDMA_TRANSFERTYPE_M2M_CONTROLLER_DMA:
385 GPDMACfg->SrcAddr = (uint32_t) src;
386 GPDMACfg->DstAddr = (uint32_t) dst;
387 rval = 3;
388 GPDMACfg->TransferWidth = GPDMA_WIDTH_WORD;
389 GPDMACfg->TransferSize = Size / 4;
390 break;
391
392 case GPDMA_TRANSFERTYPE_M2P_CONTROLLER_DMA:
393 case GPDMA_TRANSFERTYPE_M2P_CONTROLLER_PERIPHERAL:
394 GPDMACfg->SrcAddr = (uint32_t) src;
395 rval = 1;
396 GPDMACfg->DstAddr = (uint32_t) GPDMA_LUTPerAddr[dst];
397 break;
398
399 case GPDMA_TRANSFERTYPE_P2M_CONTROLLER_DMA:
400 case GPDMA_TRANSFERTYPE_P2M_CONTROLLER_PERIPHERAL:
401 GPDMACfg->SrcAddr = (uint32_t) GPDMA_LUTPerAddr[src];
402 GPDMACfg->DstAddr = (uint32_t) dst;
403 rval = 2;
404 break;
405
406 case GPDMA_TRANSFERTYPE_P2P_CONTROLLER_DMA:
407 case GPDMA_TRANSFERTYPE_P2P_CONTROLLER_DestPERIPHERAL:
408 case GPDMA_TRANSFERTYPE_P2P_CONTROLLER_SrcPERIPHERAL:
409 GPDMACfg->SrcAddr = (uint32_t) GPDMA_LUTPerAddr[src];
410 GPDMACfg->DstAddr = (uint32_t) GPDMA_LUTPerAddr[dst];
411 rval = 0;
412 break;
413
414 default:
415 break;
416 }
417 return rval;
418 }
419
420 /* Do a DMA transfer M2M, M2P,P2M or P2P */
421 Status Chip_DMA_Transfer(LPC_GPDMA_T *pGPDMA,
422 uint8_t ChannelNum,
423 uint32_t src,
424 uint32_t dst,
425 IP_GPDMA_FLOW_CONTROL_T TransferType,
426 uint32_t Size)
427 {
428 GPDMA_Channel_CFG_T GPDMACfg;
429 uint8_t SrcPeripheral = 0, DstPeripheral = 0;
430 uint32_t cwrd;
431 int ret;
432
433 ret = Chip_DMA_InitChannelCfg(pGPDMA, &GPDMACfg, ChannelNum, src, dst, Size, TransferType);
434 if (ret < 0) {
435 return ERROR;
436 }
437
438 /* Adjust src/dst index if they are memory */
439 if (ret & 1) {
440 src = 0;
441 }
442 else {
443 SrcPeripheral = DMAMUX_Config(src);
444 }
445
446 if (ret & 2) {
447 dst = 0;
448 }
449 else {
450 DstPeripheral = DMAMUX_Config(dst);
451 }
452
453 cwrd = IP_GPDMA_MakeCtrlWord(&GPDMACfg,
454 (uint32_t) GPDMA_LUTPerBurst[src],
455 (uint32_t) GPDMA_LUTPerBurst[dst],
456 (uint32_t) GPDMA_LUTPerWid[src],
457 (uint32_t) GPDMA_LUTPerWid[dst]);
458 if (IP_GPDMA_Setup(pGPDMA, &GPDMACfg, cwrd, 0, SrcPeripheral, DstPeripheral) == ERROR) {
459 return ERROR;
460 }
461
462 /* Start the Channel */
463 IP_GPDMA_ChannelCmd(pGPDMA, ChannelNum, ENABLE);
464 return SUCCESS;
465 }
466
467 Status Chip_DMA_PrepareDescriptor(LPC_GPDMA_T *pGPDMA,
468 DMA_TransferDescriptor_t *DMADescriptor,
469 uint32_t src,
470 uint32_t dst,
471 uint32_t Size,
472 IP_GPDMA_FLOW_CONTROL_T TransferType,
473 const DMA_TransferDescriptor_t *NextDescriptor)
474 {
475 int ret;
476 GPDMA_Channel_CFG_T GPDMACfg;
477
478 ret = Chip_DMA_InitChannelCfg(pGPDMA, &GPDMACfg, 0, src, dst, Size, TransferType);
479 if (ret < 0) {
480 return ERROR;
481 }
482
483 /* Adjust src/dst index if they are memory */
484 if (ret & 1) {
485 src = 0;
486 }
487
488 if (ret & 2) {
489 dst = 0;
490 }
491
492 DMADescriptor->src = GPDMACfg.SrcAddr;
493 DMADescriptor->dst = GPDMACfg.DstAddr;
494 DMADescriptor->lli = (uint32_t) NextDescriptor;
495 DMADescriptor->ctrl = IP_GPDMA_MakeCtrlWord(&GPDMACfg,
496 (uint32_t) GPDMA_LUTPerBurst[src],
497 (uint32_t) GPDMA_LUTPerBurst[dst],
498 (uint32_t) GPDMA_LUTPerWid[src],
499 (uint32_t) GPDMA_LUTPerWid[dst]);
500
501 /* By default set interrupt only for last transfer */
502 if (NextDescriptor) {
503 DMADescriptor->ctrl &= ~GPDMA_DMACCxControl_I;
504 }
505
506 return SUCCESS;
507 }
508
509 /* Do a DMA scatter-gather transfer M2M, M2P,P2M or P2P using DMA descriptors */
510 Status Chip_DMA_SGTransfer(LPC_GPDMA_T *pGPDMA,
511 uint8_t ChannelNum,
512 const DMA_TransferDescriptor_t *DMADescriptor,
513 IP_GPDMA_FLOW_CONTROL_T TransferType)
514 {
515 const DMA_TransferDescriptor_t *dsc = DMADescriptor;
516 GPDMA_Channel_CFG_T GPDMACfg;
517 uint8_t SrcPeripheral = 0, DstPeripheral = 0;
518 uint32_t src = DMADescriptor->src, dst = DMADescriptor->dst;
519 int ret;
520
521 ret = Chip_DMA_InitChannelCfg(pGPDMA, &GPDMACfg, ChannelNum, src, dst, 0, TransferType);
522 if (ret < 0) {
523 return ERROR;
524 }
525
526 /* Adjust src/dst index if they are memory */
527 if (ret & 1) {
528 src = 0;
529 }
530 else {
531 SrcPeripheral = DMAMUX_Config(src);
532 }
533
534 if (ret & 2) {
535 dst = 0;
536 }
537 else {
538 DstPeripheral = DMAMUX_Config(dst);
539 }
540
541 if (IP_GPDMA_Setup(pGPDMA, &GPDMACfg, dsc->ctrl, dsc->lli, SrcPeripheral, DstPeripheral) == ERROR) {
542 return ERROR;
543 }
544
545 /* Start the Channel */
546 IP_GPDMA_ChannelCmd(pGPDMA, ChannelNum, ENABLE);
547 return SUCCESS;
548 }
549
550 /* Get a free GPDMA channel for one DMA connection */
551 uint8_t Chip_DMA_GetFreeChannel(LPC_GPDMA_T *pGPDMA,
552 uint32_t PeripheralConnection_ID)
553 {
554 uint8_t temp = 0;
555 for (temp = 0; temp < GPDMA_NUMBER_CHANNELS; temp++) {
556 if (!Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_ENABLED_CH,
557 temp) && (ChannelHandlerArray[temp].ChannelStatus == DISABLE)) {
558 ChannelHandlerArray[temp].ChannelStatus = ENABLE;
559 return temp;
560 }
561 }
562 return 0;
563 }