source: rtems/c/src/lib/libbsp/arm/lpc176x/misc/dma-copy.c @ d4edbdbc

4.115
Last change on this file since d4edbdbc was d4edbdbc, checked in by Sebastian Huber <sebastian.huber@…>, on Mar 20, 2015 at 1:09:26 PM

Replace www.rtems.com with www.rtems.org

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup lpc176x_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/lpc176x.h>
23#include <bsp/dma.h>
24#include <bsp/irq.h>
25
26static rtems_id lpc176x_dma_sema_table[ GPDMA_CH_NUMBER ];
27static bool     lpc176x_dma_status_table[ GPDMA_CH_NUMBER ];
28
29static void lpc176x_dma_copy_handler( void *arg )
30{
31  /* Get interrupt status */
32  uint32_t tc = GPDMA_INT_TCSTAT;
33  uint32_t err = GPDMA_INT_ERR_STAT;
34
35  /* Clear interrupt status */
36  GPDMA_INT_TCCLR = tc;
37  GPDMA_INT_ERR_CLR = err;
38
39  if ( ( tc & GPDMA_STATUS_CH_0 ) != 0 ) {
40    rtems_semaphore_release( lpc176x_dma_sema_table[ 0 ] );
41  }
42
43  /* else implies that the channel is not the 0. Also,
44     there is nothing to do. */
45
46  lpc176x_dma_status_table[ 0 ] = ( err & GPDMA_STATUS_CH_0 ) == 0;
47
48  if ( ( tc & GPDMA_STATUS_CH_1 ) != 0 ) {
49    rtems_semaphore_release( lpc176x_dma_sema_table[ 1 ] );
50  }
51
52  /* else implies that the channel is not the 1. Also,
53     there is nothing to do. */
54
55  lpc176x_dma_status_table[ 1 ] = ( err & GPDMA_STATUS_CH_1 ) == 0;
56}
57
58rtems_status_code lpc176x_dma_copy_initialize( void )
59{
60  rtems_status_code status_code = RTEMS_SUCCESSFUL;
61  rtems_id          id0 = RTEMS_ID_NONE;
62  rtems_id          id1 = RTEMS_ID_NONE;
63
64  /* Create semaphore for channel 0 */
65  status_code = rtems_semaphore_create( rtems_build_name( 'D', 'M', 'A', '0' ),
66    0,
67    RTEMS_LOCAL | RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE,
68    0,
69    &id0 );
70
71  if ( status_code != RTEMS_SUCCESSFUL ) {
72    return status_code;
73  }
74
75  /* else implies that the semaphore to the channel 0 was created succefully.
76     Also, there is nothing to do. */
77
78  /* Create semaphore for channel 1 */
79  status_code = rtems_semaphore_create( rtems_build_name( 'D', 'M', 'A', '1' ),
80    0,
81    RTEMS_LOCAL | RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE,
82    0,
83    &id1 );
84
85  if ( status_code != RTEMS_SUCCESSFUL ) {
86    rtems_semaphore_delete( id0 );
87
88    return status_code;
89  }
90
91  /* else implies that the semaphore to the channel 1 was created succefully.
92     Also, there is nothing to do. */
93
94  /* Install DMA interrupt handler */
95  status_code = rtems_interrupt_handler_install( LPC176X_IRQ_DMA,
96    "DMA copy",
97    RTEMS_INTERRUPT_UNIQUE,
98    lpc176x_dma_copy_handler,
99    NULL );
100
101  if ( status_code != RTEMS_SUCCESSFUL ) {
102    rtems_semaphore_delete( id0 );
103    rtems_semaphore_delete( id1 );
104
105    return status_code;
106  }
107
108  /* else implies that the interrupt handler was installed succefully. Also,
109     there is nothing to do. */
110
111  /* Initialize global data */
112  lpc176x_dma_sema_table[ 0 ] = id0;
113  lpc176x_dma_sema_table[ 1 ] = id1;
114
115  return RTEMS_SUCCESSFUL;
116}
117
118rtems_status_code lpc176x_dma_copy_release( void )
119{
120  rtems_status_code status_code = RTEMS_SUCCESSFUL;
121  rtems_status_code status_code_aux = RTEMS_SUCCESSFUL;
122
123  status_code = rtems_interrupt_handler_remove( LPC176X_IRQ_DMA,
124    lpc176x_dma_copy_handler,
125    NULL );
126
127  if ( status_code != RTEMS_SUCCESSFUL ) {
128    status_code_aux = status_code;
129  }
130
131  /* else implies that the interrupt handler was removed succefully. Also,
132     there is nothing to do. */
133
134  status_code = rtems_semaphore_delete( lpc176x_dma_sema_table[ 0 ] );
135
136  if ( status_code != RTEMS_SUCCESSFUL ) {
137    status_code_aux = status_code;
138  }
139
140  /* else implies that the semaphore to the channel 0 was deleted succefully.
141     Also, there is nothing to do. */
142
143  status_code = rtems_semaphore_delete( lpc176x_dma_sema_table[ 1 ] );
144
145  if ( status_code != RTEMS_SUCCESSFUL ) {
146    status_code_aux = status_code;
147  }
148
149  /* else implies that the semaphore to the channel 1 was deleted succefully.
150     Also, there is nothing to do. */
151
152  return status_code_aux;
153}
154
155rtems_status_code lpc176x_dma_copy(
156  unsigned          channel,
157  const void *const dest,
158  const void *const src,
159  size_t            n,
160  const size_t      width
161)
162{
163  rtems_status_code             status_code = RTEMS_SUCCESSFUL;
164  volatile lpc176x_dma_channel *e = GPDMA_CH_BASE_ADDR( channel );
165  uint32_t                      w = GPDMA_CH_CTRL_W_8;
166
167  switch ( width ) {
168    case 4:
169      w = GPDMA_CH_CTRL_W_32;
170      break;
171    case 2:
172      w = GPDMA_CH_CTRL_W_16;
173      break;
174  }
175
176  n = n >> w;
177
178  if ( n > 0 && n < 4096 ) {
179    e->desc.src = (uint32_t) src;
180    e->desc.dest = (uint32_t) dest;
181    e->desc.lli = 0;
182    e->desc.ctrl = SET_GPDMA_CH_CTRL_TSZ( 0, n ) |
183                   SET_GPDMA_CH_CTRL_SBSZ( 0, GPDMA_CH_CTRL_BSZ_1 ) |
184                   SET_GPDMA_CH_CTRL_DBSZ( 0, GPDMA_CH_CTRL_BSZ_1 ) |
185                   SET_GPDMA_CH_CTRL_SW( 0, w ) |
186                   SET_GPDMA_CH_CTRL_DW( 0, w ) |
187                   GPDMA_CH_CTRL_ITC |
188                   GPDMA_CH_CTRL_SI |
189                   GPDMA_CH_CTRL_DI;
190    e->cfg = SET_GPDMA_CH_CFG_FLOW( 0, GPDMA_CH_CFG_FLOW_MEM_TO_MEM_DMA ) |
191             GPDMA_CH_CFG_IE |
192             GPDMA_CH_CFG_ITC |
193             GPDMA_CH_CFG_EN;
194  } else {
195    status_code = RTEMS_INVALID_SIZE;
196  }
197
198  return status_code;
199}
200
201rtems_status_code lpc176x_dma_copy_wait( const unsigned channel )
202{
203  rtems_status_code status_code = RTEMS_SUCCESSFUL;
204
205  status_code = rtems_semaphore_obtain( lpc176x_dma_sema_table[ channel ],
206    RTEMS_WAIT,
207    RTEMS_NO_TIMEOUT );
208
209  if ( status_code != RTEMS_SUCCESSFUL ) {
210    return status_code;
211  }
212
213  /* else implies that the semaphore was obtained succefully. Also,
214     there is nothing to do. */
215
216  status_code = lpc176x_dma_status_table[ channel ]
217                ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR;
218
219  return status_code;
220}
Note: See TracBrowser for help on using the repository browser.