source: rtems/c/src/lib/libbsp/arm/lpc24xx/misc/dma-copy.c @ c499856

4.115
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 4.1 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup lpc24xx_dma
5 *
6 * @brief Direct memory access (DMA) support.
7 */
8
9/*
10 * Copyright (c) 2008, 2009
11 * embedded brains GmbH
12 * Obere Lagerstr. 30
13 * D-82178 Puchheim
14 * Germany
15 * <rtems@embedded-brains.de>
16 *
17 * The license and distribution terms for this file may be
18 * found in the file LICENSE in this distribution or at
19 * http://www.rtems.org/license/LICENSE.
20 */
21
22#include <bsp/lpc24xx.h>
23#include <bsp/dma.h>
24#include <bsp/irq.h>
25
26static rtems_id lpc24xx_dma_sema_table [GPDMA_CH_NUMBER];
27
28static bool lpc24xx_dma_status_table [GPDMA_CH_NUMBER];
29
30static void lpc24xx_dma_copy_handler(void *arg)
31{
32  /* Get interrupt status */
33  uint32_t tc = GPDMA_INT_TCSTAT;
34  uint32_t err = GPDMA_INT_ERR_STAT;
35
36  /* Clear interrupt status */
37  GPDMA_INT_TCCLR = tc;
38  GPDMA_INT_ERR_CLR = err;
39
40  /* Check channel 0 */
41  if ((tc & GPDMA_STATUS_CH_0) != 0) {
42    rtems_semaphore_release(lpc24xx_dma_sema_table [0]);
43  }
44  lpc24xx_dma_status_table [0] = (err & GPDMA_STATUS_CH_0) == 0;
45
46  /* Check channel 1 */
47  if ((tc & GPDMA_STATUS_CH_1) != 0) {
48    rtems_semaphore_release(lpc24xx_dma_sema_table [1]);
49  }
50  lpc24xx_dma_status_table [1] = (err & GPDMA_STATUS_CH_1) == 0;
51}
52
53rtems_status_code lpc24xx_dma_copy_initialize(void)
54{
55  rtems_status_code sc = RTEMS_SUCCESSFUL;
56  rtems_id id0 = RTEMS_ID_NONE;
57  rtems_id id1 = RTEMS_ID_NONE;
58
59  /* Create semaphore for channel 0 */
60  sc = rtems_semaphore_create(
61    rtems_build_name('D', 'M', 'A', '0'),
62    0,
63    RTEMS_LOCAL | RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE,
64    0,
65    &id0
66  );
67  if (sc != RTEMS_SUCCESSFUL) {
68    return sc;
69  }
70
71  /* Create semaphore for channel 1 */
72  sc = rtems_semaphore_create(
73    rtems_build_name('D', 'M', 'A', '1'),
74    0,
75    RTEMS_LOCAL | RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE,
76    0,
77    &id1
78  );
79  if (sc != RTEMS_SUCCESSFUL) {
80    rtems_semaphore_delete(id0);
81
82    return sc;
83  }
84
85  /* Install DMA interrupt handler */
86  sc = rtems_interrupt_handler_install(
87    LPC24XX_IRQ_DMA,
88    "DMA copy",
89    RTEMS_INTERRUPT_UNIQUE,
90    lpc24xx_dma_copy_handler,
91    NULL
92  );
93  if (sc != RTEMS_SUCCESSFUL) {
94    rtems_semaphore_delete(id0);
95    rtems_semaphore_delete(id1);
96
97    return sc;
98  }
99
100  /* Initialize global data */
101  lpc24xx_dma_sema_table [0] = id0;
102  lpc24xx_dma_sema_table [1] = id1;
103
104  return RTEMS_SUCCESSFUL;
105}
106
107rtems_status_code lpc24xx_dma_copy_release(void)
108{
109  rtems_status_code sc = RTEMS_SUCCESSFUL;
110  rtems_status_code rsc = RTEMS_SUCCESSFUL;
111
112  sc = rtems_interrupt_handler_remove(
113    LPC24XX_IRQ_DMA,
114    lpc24xx_dma_copy_handler,
115    NULL
116  );
117  if (sc != RTEMS_SUCCESSFUL) {
118    rsc = sc;
119  }
120
121  sc = rtems_semaphore_delete(lpc24xx_dma_sema_table [0]);
122  if (sc != RTEMS_SUCCESSFUL) {
123    rsc = sc;
124  }
125
126  sc = rtems_semaphore_delete(lpc24xx_dma_sema_table [1]);
127  if (sc != RTEMS_SUCCESSFUL) {
128    rsc = sc;
129  }
130
131  return rsc;
132}
133
134rtems_status_code lpc24xx_dma_copy(
135  unsigned channel,
136  void *dest,
137  const void *src,
138  size_t n,
139  size_t width
140)
141{
142  volatile lpc24xx_dma_channel *e = GPDMA_CH_BASE_ADDR(channel);
143  uint32_t w = GPDMA_CH_CTRL_W_8;
144
145  switch (width) {
146    case 4:
147      w = GPDMA_CH_CTRL_W_32;
148      break;
149    case 2:
150      w = GPDMA_CH_CTRL_W_16;
151      break;
152  }
153
154  n = n >> w;
155
156  if (n > 0U && n < 4096U) {
157    e->desc.src = (uint32_t) src;
158    e->desc.dest = (uint32_t) dest;
159    e->desc.lli = 0;
160    e->desc.ctrl = SET_GPDMA_CH_CTRL_TSZ(0, n)
161      | SET_GPDMA_CH_CTRL_SBSZ(0, GPDMA_CH_CTRL_BSZ_1)
162      | SET_GPDMA_CH_CTRL_DBSZ(0, GPDMA_CH_CTRL_BSZ_1)
163      | SET_GPDMA_CH_CTRL_SW(0, w)
164      | SET_GPDMA_CH_CTRL_DW(0, w)
165      | GPDMA_CH_CTRL_ITC
166      | GPDMA_CH_CTRL_SI
167      | GPDMA_CH_CTRL_DI;
168    e->cfg = SET_GPDMA_CH_CFG_FLOW(0, GPDMA_CH_CFG_FLOW_MEM_TO_MEM_DMA)
169      | GPDMA_CH_CFG_IE
170      | GPDMA_CH_CFG_ITC
171      | GPDMA_CH_CFG_EN;
172  } else {
173    return RTEMS_INVALID_SIZE;
174  }
175
176  return RTEMS_SUCCESSFUL;
177}
178
179rtems_status_code lpc24xx_dma_copy_wait(unsigned channel)
180{
181  rtems_status_code sc = RTEMS_SUCCESSFUL;
182
183  sc = rtems_semaphore_obtain(
184    lpc24xx_dma_sema_table [channel],
185    RTEMS_WAIT,
186    RTEMS_NO_TIMEOUT
187  );
188  if (sc != RTEMS_SUCCESSFUL) {
189    return sc;
190  }
191
192  return lpc24xx_dma_status_table [channel]
193    ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR;
194}
Note: See TracBrowser for help on using the repository browser.