LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gpdma_17xx_40xx.c
Go to the documentation of this file.
1 /*
2  * @brief LPC17xx/40xx 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 */
40 #if defined(CHIP_LPC177X_8X) || defined(CHIP_LPC407X_8X)
41 /* Optimized Peripheral Source and Destination burst size (177x_8x,407x_8x) */
42 static const uint8_t GPDMA_LUTPerBurst[] = {
43  0, /* Reserved */
44  GPDMA_BSIZE_8, /* SD Card */
45  GPDMA_BSIZE_4, /* SSP0 Tx */
46  GPDMA_BSIZE_4, /* SSP0 Rx */
47  GPDMA_BSIZE_4, /* SSP1 Tx */
48  GPDMA_BSIZE_4, /* SSP1 Rx */
49  GPDMA_BSIZE_4, /* SSP2 Tx */
50  GPDMA_BSIZE_4, /* SSP2 Rx */
51  GPDMA_BSIZE_1, /* ADC */
52  GPDMA_BSIZE_1, /* DAC */
53  GPDMA_BSIZE_1, /* UART0 Tx */
54  GPDMA_BSIZE_1, /* UART0 Rx */
55  GPDMA_BSIZE_1, /* UART1 Tx */
56  GPDMA_BSIZE_1, /* UART1 Rx */
57  GPDMA_BSIZE_1, /* UART2 Tx */
58  GPDMA_BSIZE_1, /* UART2 Rx */
59  GPDMA_BSIZE_1, /* MAT0.0 */
60  GPDMA_BSIZE_1, /* MAT0.1 */
61  GPDMA_BSIZE_1, /* MAT1.0 */
62  GPDMA_BSIZE_1, /* MAT1.1 */
63  GPDMA_BSIZE_1, /* MAT2.0 */
64  GPDMA_BSIZE_1, /* MAT2.1 */
65  GPDMA_BSIZE_32, /* I2S channel 0 */
66  GPDMA_BSIZE_32, /* I2S channel 1 */
67  0, /* Reserved */
68  0, /* Reserved */
69  GPDMA_BSIZE_1, /* UART3 Tx */
70  GPDMA_BSIZE_1, /* UART3 Rx */
71  GPDMA_BSIZE_1, /* UART4 Tx */
72  GPDMA_BSIZE_1, /* UART4 Rx */
73  GPDMA_BSIZE_1, /* MAT3.0 */
74  GPDMA_BSIZE_1, /* MAT3.1 */
75 };
76 
77 /* Optimized Peripheral Source and Destination transfer width (177x_8x,407x_8x) */
78 static const uint8_t GPDMA_LUTPerWid[] = {
79  0, /* Reserved */
80  GPDMA_WIDTH_WORD, /* SD Card */
81  GPDMA_WIDTH_BYTE, /* SSP0 Tx */
82  GPDMA_WIDTH_BYTE, /* SSP0 Rx */
83  GPDMA_WIDTH_BYTE, /* SSP1 Tx */
84  GPDMA_WIDTH_BYTE, /* SSP1 Rx */
85  GPDMA_WIDTH_BYTE, /* SSP2 Tx */
86  GPDMA_WIDTH_BYTE, /* SSP2 Rx */
87  GPDMA_WIDTH_WORD, /* ADC */
88  GPDMA_WIDTH_HALFWORD, /* DAC */
89  GPDMA_WIDTH_BYTE, /* UART0 Tx */
90  GPDMA_WIDTH_BYTE, /* UART0 Rx */
91  GPDMA_WIDTH_BYTE, /* UART1 Tx */
92  GPDMA_WIDTH_BYTE, /* UART1 Rx */
93  GPDMA_WIDTH_BYTE, /* UART2 Tx */
94  GPDMA_WIDTH_BYTE, /* UART2 Rx */
95  GPDMA_WIDTH_WORD, /* MAT0.0 */
96  GPDMA_WIDTH_WORD, /* MAT0.1 */
97  GPDMA_WIDTH_WORD, /* MAT1.0 */
98  GPDMA_WIDTH_WORD, /* MAT1.1 */
99  GPDMA_WIDTH_WORD, /* MAT2.0 */
100  GPDMA_WIDTH_WORD, /* MAT2.1 */
101  GPDMA_WIDTH_WORD, /* I2S channel 0 */
102  GPDMA_WIDTH_WORD, /* I2S channel 1 */
103  0, /* Reserved */
104  0, /* Reserved */
105  GPDMA_WIDTH_BYTE, /* UART3 Tx */
106  GPDMA_WIDTH_BYTE, /* UART3 Rx */
107  GPDMA_WIDTH_BYTE, /* UART4 Tx */
108  GPDMA_WIDTH_BYTE, /* UART4 Rx */
109  GPDMA_WIDTH_WORD, /* MAT3.0 */
110  GPDMA_WIDTH_WORD, /* MAT3.1 */
111 };
112 
113 /* Lookup Table of Connection Type matched with (177x_8x,407x_8x) Peripheral Data (FIFO) register base address */
114 volatile static const void *GPDMA_LUTPerAddr[] = {
115  0, /* Reserved */
116  (&LPC_SDC->FIFO), /* SD Card */
117  (&LPC_SSP0->DR), /* SSP0 Tx */
118  (&LPC_SSP0->DR), /* SSP0 Rx */
119  (&LPC_SSP1->DR), /* SSP1 Tx */
120  (&LPC_SSP1->DR), /* SSP1 Rx */
121  (&LPC_SSP2->DR), /* SSP2 Tx */
122  (&LPC_SSP2->DR), /* SSP2 Rx */
123  (&LPC_ADC->GDR), /* ADC */
124  (&LPC_DAC->CR), /* DAC */
125  (&LPC_UART0-> /*RBTHDLR.*/ THR), /* UART0 Tx */
126  (&LPC_UART0-> /*RBTHDLR.*/ RBR), /* UART0 Rx */
127  (&LPC_UART1-> /*RBTHDLR.*/ THR), /* UART1 Tx */
128  (&LPC_UART1-> /*RBTHDLR.*/ RBR), /* UART1 Rx */
129  (&LPC_UART2-> /*RBTHDLR.*/ THR), /* UART2 Tx */
130  (&LPC_UART2-> /*RBTHDLR.*/ RBR), /* UART2 Rx */
131  (&LPC_TIMER0->MR[0]), /* MAT0.0 */
132  (&LPC_TIMER0->MR[1]), /* MAT0.1 */
133  (&LPC_TIMER1->MR[0]), /* MAT1.0 */
134  (&LPC_TIMER1->MR[1]), /* MAT1.1 */
135  (&LPC_TIMER2->MR[0]), /* MAT2.0 */
136  (&LPC_TIMER2->MR[1]), /* MAT2.1 */
137  (&LPC_I2S->TXFIFO), /* I2S Tx */
138  (&LPC_I2S->RXFIFO), /* I2S Rx */
139  0, /* Reverse */
140  0, /* Reverse */
141  (&LPC_UART3-> /*RBTHDLR.*/ THR), /* UART3 Tx */
142  (&LPC_UART3-> /*RBTHDLR.*/ RBR), /* UART3 Rx */
143  (&LPC_UART4-> /*RBTHDLR.*/ THR), /* UART4 Tx */
144  (&LPC_UART4-> /*RBTHDLR.*/ RBR), /* UART4 Rx */
145  (&LPC_TIMER3->MR[0]), /* MAT3.0 */
146  (&LPC_TIMER3->MR[1]) /* MAT3.1 */
147 };
148 #elif defined(CHIP_LPC175X_6X)
149 const uint8_t GPDMA_LUTPerBurst[] = {
150  GPDMA_BSIZE_4, // SSP0 Tx
151  GPDMA_BSIZE_4, // SSP0 Rx
152  GPDMA_BSIZE_4, // SSP1 Tx
153  GPDMA_BSIZE_4, // SSP1 Rx
154  GPDMA_BSIZE_1, // ADC
155  GPDMA_BSIZE_32, // I2S channel 0
156  GPDMA_BSIZE_32, // I2S channel 1
157  GPDMA_BSIZE_1, // DAC
158  GPDMA_BSIZE_1, // UART0 Tx
159  GPDMA_BSIZE_1, // UART0 Rx
160  GPDMA_BSIZE_1, // UART1 Tx
161  GPDMA_BSIZE_1, // UART1 Rx
162  GPDMA_BSIZE_1, // UART2 Tx
163  GPDMA_BSIZE_1, // UART2 Rx
164  GPDMA_BSIZE_1, // UART3 Tx
165  GPDMA_BSIZE_1, // UART3 Rx
166  GPDMA_BSIZE_1, // MAT0.0
167  GPDMA_BSIZE_1, // MAT0.1
168  GPDMA_BSIZE_1, // MAT1.0
169  GPDMA_BSIZE_1, // MAT1.1
170  GPDMA_BSIZE_1, // MAT2.0
171  GPDMA_BSIZE_1, // MAT2.1
172  GPDMA_BSIZE_1, // MAT3.0
173  GPDMA_BSIZE_1 // MAT3.1
174 };
175 
179 const uint8_t GPDMA_LUTPerWid[] = {
180  GPDMA_WIDTH_BYTE, // SSP0 Tx
181  GPDMA_WIDTH_BYTE, // SSP0 Rx
182  GPDMA_WIDTH_BYTE, // SSP1 Tx
183  GPDMA_WIDTH_BYTE, // SSP1 Rx
184  GPDMA_WIDTH_WORD, // ADC
185  GPDMA_WIDTH_WORD, // I2S channel 0
186  GPDMA_WIDTH_WORD, // I2S channel 1
187  GPDMA_WIDTH_HALFWORD, // DAC
188  GPDMA_WIDTH_BYTE, // UART0 Tx
189  GPDMA_WIDTH_BYTE, // UART0 Rx
190  GPDMA_WIDTH_BYTE, // UART1 Tx
191  GPDMA_WIDTH_BYTE, // UART1 Rx
192  GPDMA_WIDTH_BYTE, // UART2 Tx
193  GPDMA_WIDTH_BYTE, // UART2 Rx
194  GPDMA_WIDTH_BYTE, // UART3 Tx
195  GPDMA_WIDTH_BYTE, // UART3 Rx
196  GPDMA_WIDTH_WORD, // MAT0.0
197  GPDMA_WIDTH_WORD, // MAT0.1
198  GPDMA_WIDTH_WORD, // MAT1.0
199  GPDMA_WIDTH_WORD, // MAT1.1
200  GPDMA_WIDTH_WORD, // MAT2.0
201  GPDMA_WIDTH_WORD, // MAT2.1
202  GPDMA_WIDTH_WORD, // MAT3.0
203  GPDMA_WIDTH_WORD // MAT3.1
204 };
205 
206 
210 volatile const void *GPDMA_LUTPerAddr[] = {
211  (&LPC_SSP0->DR), // SSP0 Tx
212  (&LPC_SSP0->DR), // SSP0 Rx
213  (&LPC_SSP1->DR), // SSP1 Tx
214  (&LPC_SSP1->DR), // SSP1 Rx
215  (&LPC_ADC->GDR), // ADC
216  (&LPC_I2S->TXFIFO), // I2S Tx
217  (&LPC_I2S->RXFIFO), // I2S Rx
218  (&LPC_DAC->CR), // DAC
219  (&LPC_UART0->/*RBTHDLR.*/THR), // UART0 Tx
220  (&LPC_UART0->/*RBTHDLR.*/RBR), // UART0 Rx
221  (&LPC_UART1->/*RBTHDLR.*/THR), // UART1 Tx
222  (&LPC_UART1->/*RBTHDLR.*/RBR), // UART1 Rx
223  (&LPC_UART2->/*RBTHDLR.*/THR), // UART2 Tx
224  (&LPC_UART2->/*RBTHDLR.*/RBR), // UART2 Rx
225  (&LPC_UART3->/*RBTHDLR.*/THR), // UART3 Tx
226  (&LPC_UART3->/*RBTHDLR.*/RBR), // UART3 Rx
227  (&LPC_TIMER0->MR[0]), // MAT0.0
228  (&LPC_TIMER0->MR[1]), // MAT0.1
229  (&LPC_TIMER1->MR[0]), // MAT1.0
230  (&LPC_TIMER1->MR[1]), // MAT1.1
231  (&LPC_TIMER2->MR[0]), // MAT2.0
232  (&LPC_TIMER2->MR[1]), // MAT2.1
233  (&LPC_TIMER3->MR[0]), // MAT3.0
234  (&LPC_TIMER3->MR[1]) // MAT3.1
235 
236 };
237 #endif
238 /*****************************************************************************
239  * Public types/enumerations/variables
240  ****************************************************************************/
241 
242 /*****************************************************************************
243  * Private functions
244  ****************************************************************************/
245 
246 /* Control which set of peripherals is connected to the DMA controller */
247 static uint8_t DMAMUX_Config(uint32_t gpdma_peripheral_connection_number)
248 {
249 #if defined(CHIP_LPC175X_6X)
250  if (gpdma_peripheral_connection_number > 15) {
251  LPC_SYSCTL->DMAREQSEL |= (1 << (gpdma_peripheral_connection_number - 16));
252  return gpdma_peripheral_connection_number - 8;
253  }
254  else {
255  if(gpdma_peripheral_connection_number>7)
256  LPC_SYSCTL->DMAREQSEL &= ~(1 << (gpdma_peripheral_connection_number-8));
257  return gpdma_peripheral_connection_number;
258  }
259 #elif defined(CHIP_LPC177X_8X) || defined(CHIP_LPC407X_8X)
260  if (gpdma_peripheral_connection_number > 15) {
261  LPC_SYSCTL->DMAREQSEL |= (1 << (gpdma_peripheral_connection_number - 16));
262  return gpdma_peripheral_connection_number - 16;
263  }
264  else {
265  LPC_SYSCTL->DMAREQSEL &= ~(1 << (gpdma_peripheral_connection_number));
266  return gpdma_peripheral_connection_number;
267  }
268 #endif
269 }
270 
271 /*****************************************************************************
272  * Public functions
273  ****************************************************************************/
274 
275 /* Initialize the GPDMA */
277 {
278  uint8_t i;
279 
280  /* Enable GPDMA master clock */
282 
283  IP_GPDMA_Init(pGPDMA);
284 
285  /* Reset all channels are free */
286  for (i = 0; i < GPDMA_NUMBER_CHANNELS; i++) {
287  ChannelHandlerArray[i].ChannelStatus = DISABLE;
288  }
289 }
290 
291 /* Shutdown the GPDMA */
293 {
295 }
296 
297 /* Stop a stream DMA transfer */
299  uint8_t ChannelNum)
300 {
301  IP_GPDMA_ChannelCmd(pGPDMA, (ChannelNum), DISABLE);
302  if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INTTC, ChannelNum)) {
303  /* Clear terminate counter Interrupt pending */
304  Chip_GPDMA_ClearIntPending(pGPDMA, GPDMA_STATCLR_INTTC, ChannelNum);
305  }
306  if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INTERR, ChannelNum)) {
307  /* Clear terminate counter Interrupt pending */
309  }
310  ChannelHandlerArray[ChannelNum].ChannelStatus = DISABLE;
311 }
312 
313 /* The GPDMA stream interrupt status checking */
315  uint8_t ChannelNum)
316 {
317 
318  if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INT, ChannelNum)) {
319  /* Check counter terminal status */
320  if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INTTC, ChannelNum)) {
321  /* Clear terminate counter Interrupt pending */
322  Chip_GPDMA_ClearIntPending(pGPDMA, GPDMA_STATCLR_INTTC, ChannelNum);
323  return SUCCESS;
324  }
325  /* Check error terminal status */
326  if (Chip_GPDMA_IntGetStatus(pGPDMA, GPDMA_STAT_INTERR, ChannelNum)) {
327  /* Clear error counter Interrupt pending */
328 
330  return ERROR;
331  }
332  }
333  return ERROR;
334 }
335 
337  GPDMA_Channel_CFG_T *GPDMACfg,
338  uint8_t ChannelNum,
339  uint32_t src,
340  uint32_t dst,
341  uint32_t Size,
342  IP_GPDMA_FLOW_CONTROL_T TransferType)
343 {
344  int rval = -1;
345  GPDMACfg->ChannelNum = ChannelNum;
346  GPDMACfg->TransferType = TransferType;
347  GPDMACfg->TransferSize = Size;
348 
349  switch (TransferType) {
351  GPDMACfg->SrcAddr = (uint32_t) src;
352  GPDMACfg->DstAddr = (uint32_t) dst;
353  rval = 3;
354  GPDMACfg->TransferWidth = GPDMA_WIDTH_WORD;
355  GPDMACfg->TransferSize = Size / 4;
356  break;
357 
360  GPDMACfg->SrcAddr = (uint32_t) src;
361  rval = 1;
362  GPDMACfg->DstAddr = (uint32_t) GPDMA_LUTPerAddr[dst];
363  break;
364 
367  GPDMACfg->SrcAddr = (uint32_t) GPDMA_LUTPerAddr[src];
368  GPDMACfg->DstAddr = (uint32_t) dst;
369  rval = 2;
370  break;
371 
375  GPDMACfg->SrcAddr = (uint32_t) GPDMA_LUTPerAddr[src];
376  GPDMACfg->DstAddr = (uint32_t) GPDMA_LUTPerAddr[dst];
377  rval = 0;
378  break;
379 
380  default:
381  break;
382  }
383  return rval;
384 }
385 
386 /* Do a DMA transfer M2M, M2P,P2M or P2P */
388  uint8_t ChannelNum,
389  uint32_t src,
390  uint32_t dst,
391  IP_GPDMA_FLOW_CONTROL_T TransferType,
392  uint32_t Size)
393 {
394  GPDMA_Channel_CFG_T GPDMACfg;
395  uint8_t SrcPeripheral = 0, DstPeripheral = 0;
396  uint32_t cwrd;
397  int ret;
398 
399  ret = Chip_DMA_InitChannelCfg(pGPDMA, &GPDMACfg, ChannelNum, src, dst, Size, TransferType);
400  if (ret < 0) {
401  return ERROR;
402  }
403 
404  /* Adjust src/dst index if they are memory */
405  if (ret & 1) {
406  src = 0;
407  }
408  else {
409  SrcPeripheral = DMAMUX_Config(src);
410  }
411 
412  if (ret & 2) {
413  dst = 0;
414  }
415  else {
416  DstPeripheral = DMAMUX_Config(dst);
417  }
418 
419  cwrd = IP_GPDMA_MakeCtrlWord(&GPDMACfg,
420  (uint32_t) GPDMA_LUTPerBurst[src],
421  (uint32_t) GPDMA_LUTPerBurst[dst],
422  (uint32_t) GPDMA_LUTPerWid[src],
423  (uint32_t) GPDMA_LUTPerWid[dst]);
424  if (IP_GPDMA_Setup(pGPDMA, &GPDMACfg, cwrd, 0, SrcPeripheral, DstPeripheral) == ERROR) {
425  return ERROR;
426  }
427 
428  /* Start the Channel */
429  IP_GPDMA_ChannelCmd(pGPDMA, ChannelNum, ENABLE);
430  return SUCCESS;
431 }
432 
435  uint32_t src,
436  uint32_t dst,
437  uint32_t Size,
438  IP_GPDMA_FLOW_CONTROL_T TransferType,
439  const DMA_TransferDescriptor_t *NextDescriptor)
440 {
441  int ret;
442  GPDMA_Channel_CFG_T GPDMACfg;
443 
444  ret = Chip_DMA_InitChannelCfg(pGPDMA, &GPDMACfg, 0, src, dst, Size, TransferType);
445  if (ret < 0) {
446  return ERROR;
447  }
448 
449  /* Adjust src/dst index if they are memory */
450  if (ret & 1) {
451  src = 0;
452  }
453 
454  if (ret & 2) {
455  dst = 0;
456  }
457 
458  DMADescriptor->src = GPDMACfg.SrcAddr;
459  DMADescriptor->dst = GPDMACfg.DstAddr;
460  DMADescriptor->lli = (uint32_t) NextDescriptor;
461  DMADescriptor->ctrl = IP_GPDMA_MakeCtrlWord(&GPDMACfg,
462  (uint32_t) GPDMA_LUTPerBurst[src],
463  (uint32_t) GPDMA_LUTPerBurst[dst],
464  (uint32_t) GPDMA_LUTPerWid[src],
465  (uint32_t) GPDMA_LUTPerWid[dst]);
466 
467  /* By default set interrupt only for last transfer */
468  if (NextDescriptor) {
469  DMADescriptor->ctrl &= ~GPDMA_DMACCxControl_I;
470  }
471 
472  return SUCCESS;
473 }
474 
475 /* Do a DMA scatter-gather transfer M2M, M2P,P2M or P2P using DMA descriptors */
477  uint8_t ChannelNum,
479  IP_GPDMA_FLOW_CONTROL_T TransferType)
480 {
481  const DMA_TransferDescriptor_t *dsc = DMADescriptor;
482  GPDMA_Channel_CFG_T GPDMACfg;
483  uint8_t SrcPeripheral = 0, DstPeripheral = 0;
484  uint32_t src = DMADescriptor->src, dst = DMADescriptor->dst;
485  int ret;
486 
487  ret = Chip_DMA_InitChannelCfg(pGPDMA, &GPDMACfg, ChannelNum, src, dst, 0, TransferType);
488  if (ret < 0) {
489  return ERROR;
490  }
491 
492  /* Adjust src/dst index if they are memory */
493  if (ret & 1) {
494  src = 0;
495  }
496  else {
497  SrcPeripheral = DMAMUX_Config(src);
498  }
499 
500  if (ret & 2) {
501  dst = 0;
502  }
503  else {
504  DstPeripheral = DMAMUX_Config(dst);
505  }
506 
507  if (IP_GPDMA_Setup(pGPDMA, &GPDMACfg, dsc->ctrl, dsc->lli, SrcPeripheral, DstPeripheral) == ERROR) {
508  return ERROR;
509  }
510 
511  /* Start the Channel */
512  IP_GPDMA_ChannelCmd(pGPDMA, ChannelNum, ENABLE);
513  return SUCCESS;
514 }
515 
516 /* Get a free GPDMA channel for one DMA connection */
518  uint32_t PeripheralConnection_ID)
519 {
520  uint8_t temp = 0;
521  for (temp = 0; temp < GPDMA_NUMBER_CHANNELS; temp++) {
523  temp) && (ChannelHandlerArray[temp].ChannelStatus == DISABLE)) {
524  ChannelHandlerArray[temp].ChannelStatus = ENABLE;
525  return temp;
526  }
527  }
528  return 0;
529 }