LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 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 */
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 
254  function = 1;
255  channel = 9;
256  break;
257 
258  case GPDMA_CONN_SSP0_Tx:
259  function = 0;
260  channel = 10;
261  break;
262 
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 */
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 */
327 {
329 }
330 
331 /* Stop a stream DMA transfer */
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 */
343  }
344  ChannelHandlerArray[ChannelNum].ChannelStatus = DISABLE;
345 }
346 
347 /* The GPDMA stream interrupt status checking */
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 
364  return ERROR;
365  }
366  }
367  return ERROR;
368 }
369 
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) {
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 
394  GPDMACfg->SrcAddr = (uint32_t) src;
395  rval = 1;
396  GPDMACfg->DstAddr = (uint32_t) GPDMA_LUTPerAddr[dst];
397  break;
398 
401  GPDMACfg->SrcAddr = (uint32_t) GPDMA_LUTPerAddr[src];
402  GPDMACfg->DstAddr = (uint32_t) dst;
403  rval = 2;
404  break;
405 
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 */
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,
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 
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,
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 */
511  uint8_t ChannelNum,
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 */
552  uint32_t PeripheralConnection_ID)
553 {
554  uint8_t temp = 0;
555  for (temp = 0; temp < GPDMA_NUMBER_CHANNELS; temp++) {
557  temp) && (ChannelHandlerArray[temp].ChannelStatus == DISABLE)) {
558  ChannelHandlerArray[temp].ChannelStatus = ENABLE;
559  return temp;
560  }
561  }
562  return 0;
563 }