diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-25 10:43:38 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-25 14:31:28 +0200 |
commit | e945b049dc650ee2270740585a2c6d14bd925279 (patch) | |
tree | ccd1f3cd6bc9bd44435b25918fc4e934a6aff6a4 /bsps/arm/lpc176x/start/dma.c | |
parent | bsp/lpc24xx: Move source files to bsps (diff) | |
download | rtems-e945b049dc650ee2270740585a2c6d14bd925279.tar.bz2 |
bsp/lpc176x: Move source files to bsps
This patch is a part of the BSP source reorganization.
Update #3285.
Diffstat (limited to 'bsps/arm/lpc176x/start/dma.c')
-rw-r--r-- | bsps/arm/lpc176x/start/dma.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/bsps/arm/lpc176x/start/dma.c b/bsps/arm/lpc176x/start/dma.c new file mode 100644 index 0000000000..10c7701484 --- /dev/null +++ b/bsps/arm/lpc176x/start/dma.c @@ -0,0 +1,117 @@ +/** + * @file + * + * @ingroup lpc176x_dma + * + * @brief Direct memory access (DMA) support. + */ + +/* + * Copyright (c) 2008-2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/endian.h> +#include <bsp/dma.h> +#include <bsp/io.h> + +/** + * @brief Table that indicates if a channel is currently occupied. + */ +static bool lpc176x_dma_channel_occupation[ GPDMA_CH_NUMBER ]; + +void lpc176x_dma_initialize( void ) +{ + /* Enable module power */ + lpc176x_module_enable( LPC176X_MODULE_GPDMA, LPC176X_MODULE_PCLK_DEFAULT ); + + /* Disable module */ + GPDMA_CONFIG = 0u; + + /* Reset registers */ + GPDMA_SOFT_SREQ = 0u; + GPDMA_SOFT_BREQ = 0u; + GPDMA_SOFT_LSREQ = 0u; + GPDMA_SOFT_LBREQ = 0u; + GPDMA_SYNC = 0u; + GPDMA_CH0_CFG = 0u; + GPDMA_CH1_CFG = 0u; + + /* Enable module */ +#if BYTE_ORDER == LITTLE_ENDIAN + GPDMA_CONFIG = GPDMA_CONFIG_EN; +#else + GPDMA_CONFIG = GPDMA_CONFIG_EN | GPDMA_CONFIG_MODE; +#endif +} + +rtems_status_code lpc176x_dma_channel_obtain( const unsigned channel ) +{ + rtems_status_code status_code = RTEMS_INVALID_ID; + + if ( channel < GPDMA_CH_NUMBER ) { + rtems_interrupt_level level = 0u; + bool occupation = true; + + rtems_interrupt_disable( level ); + occupation = lpc176x_dma_channel_occupation[ channel ]; + lpc176x_dma_channel_occupation[ channel ] = true; + rtems_interrupt_enable( level ); + + status_code = occupation ? RTEMS_RESOURCE_IN_USE : RTEMS_SUCCESSFUL; + } + + /* else implies that the channel is not valid. Also, + there is nothing to do. */ + + return status_code; +} + +void lpc176x_dma_channel_release( const unsigned channel ) +{ + if ( channel < GPDMA_CH_NUMBER ) { + lpc176x_dma_channel_occupation[ channel ] = false; + } + + /* else implies that the channel is not valid. Also, + there is nothing to do. */ +} + +void lpc176x_dma_channel_disable( + const unsigned channel, + const bool force +) +{ + if ( channel < GPDMA_CH_NUMBER ) { + volatile lpc176x_dma_channel *ch = GPDMA_CH_BASE_ADDR( channel ); + uint32_t cfg = ch->cfg; + + if ( !force ) { + /* Halt */ + ch->cfg |= GPDMA_CH_CFG_HALT; + + /* Wait for inactive */ + do { + cfg = ch->cfg; + } while ( ( cfg & GPDMA_CH_CFG_ACTIVE ) != 0u ); + } + + /* else implies that the channel is not to be forced. Also, + there is nothing to do. */ + + /* Disable */ + ch->cfg &= ~GPDMA_CH_CFG_EN; + } + + /* else implies that the channel is not valid. Also, + there is nothing to do. */ +} |