A board support package for the LPC4088 Display Module.

Dependencies:   DM_HttpServer DM_USBHost

Dependents:   lpc4088_displaymodule_emwin lpc4088_displaymodule_demo_sphere sampleGUI sampleEmptyGUI ... more

Fork of DMSupport by EmbeddedArtists AB

Files at this revision

API Documentation at this revision

Comitter:
embeddedartists
Date:
Wed Apr 15 09:41:56 2015 +0200
Parent:
37:07659b5d90ce
Child:
39:e1cb4dd9bfeb
Commit message:
- Added a new class GPDMA to allow multiple users of DMA
- Modified the MCI file system to use the new GPDMA class
- Updated ethernet/rtos/mbed/usbdevice library versions

Changed in this revision

EthernetInterface.lib Show annotated file Show diff for this revision Revisions of this file
FileSystems/MCIFileSystem.cpp Show annotated file Show diff for this revision Revisions of this file
FileSystems/MCIFileSystem.h Show annotated file Show diff for this revision Revisions of this file
FileSystems/gpdma.cpp Show diff for this revision Revisions of this file
FileSystems/gpdma.h Show diff for this revision Revisions of this file
GPDMA.cpp Show annotated file Show diff for this revision Revisions of this file
GPDMA.h Show annotated file Show diff for this revision Revisions of this file
USBDevice.lib Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
mbed-src.lib Show annotated file Show diff for this revision Revisions of this file
--- a/EthernetInterface.lib	Mon Mar 23 13:45:16 2015 +0000
+++ b/EthernetInterface.lib	Wed Apr 15 09:41:56 2015 +0200
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/EthernetInterface/#65b0d840274c
+http://mbed.org/users/mbed_official/code/EthernetInterface/#2fc406e2553f
--- a/FileSystems/MCIFileSystem.cpp	Mon Mar 23 13:45:16 2015 +0000
+++ b/FileSystems/MCIFileSystem.cpp	Wed Apr 15 09:41:56 2015 +0200
@@ -23,7 +23,6 @@
 #include "rtos.h"
 
 #include "diskio.h" //STA_* defines
-#include "gpdma.h"
 
 /******************************************************************************
  * Defines and typedefs
@@ -642,9 +641,6 @@
     LPC_SC->RSTCON0 = (1<<28);
     LPC_SC->RSTCON0 &= ~(1<<28);
 
-    /* Initialize GPDMA controller */
-    gpdma_init();
-
     /* Initialize SDC peripheral */
     LPC_SC->PCONP |= SYSCTL_CLOCK_SDC;
 
@@ -685,8 +681,8 @@
     NVIC_SetVector(MCI_IRQn, (uint32_t) mymciirq);
     NVIC_EnableIRQ(MCI_IRQn);
 
-    NVIC_SetVector(DMA_IRQn, (uint32_t) mydmairq);
-    NVIC_EnableIRQ(DMA_IRQn);
+    /* Initialize GPDMA controller */
+    _eventDmaChannel = GPDMA::instance().acquireChannel(mydmairq);
 }
 
 int MCIFileSystem::disk_initialize() {
@@ -788,15 +784,72 @@
 
 void MCIFileSystem::mci_DMAIRQHandler()
 {
-  _eventSuccess = gpdma_interrupt(_eventDmaChannel);
+  _eventSuccess = LPC_GPDMA->IntTCStat & (1<<_eventDmaChannel);
   _eventReceived = true;
-  NVIC_DisableIRQ(DMA_IRQn);
+  LPC_GPDMA->IntTCClear = (1<<_eventDmaChannel);
+  LPC_GPDMA->IntErrClr = (1<<_eventDmaChannel);
 }
 
 /******************************************************************************
  * Private Functions
  *****************************************************************************/
 
+static bool gpdma_transfer_to_mci(GPDMA::DMAChannels ChannelNum,
+                                  uint32_t src,
+                                  uint32_t Size)
+{
+  GPDMA::GPDMA_Channel_CFG_T cfg;
+  cfg.ChannelNum = ChannelNum;
+  cfg.TransferType = GPDMA::FlowControl_M2P_Ctrl_Periph;
+  cfg.TransferSize = Size;
+  cfg.TransferWidth = 0;
+  cfg.SrcAddr = src;
+  cfg.DstAddr = (uint32_t) (&LPC_MCI->FIFO);
+
+  uint32_t ctrl_word =
+      GPDMA_DMACCxControl_TransferSize((uint32_t) cfg.TransferSize)
+          | GPDMA_DMACCxControl_SBSize(GPDMA_BSIZE_8)
+          | GPDMA_DMACCxControl_DBSize(GPDMA_BSIZE_8)
+          | GPDMA_DMACCxControl_SWidth(GPDMA_WIDTH_WORD)
+          | GPDMA_DMACCxControl_DWidth(GPDMA_WIDTH_WORD)
+          | GPDMA_DMACCxControl_DestTransUseAHBMaster1
+          | GPDMA_DMACCxControl_SI
+          | GPDMA_DMACCxControl_I;
+
+  /* Select SD card interface in the DMA MUX*/
+  LPC_SC->DMAREQSEL &= ~(1 << 1);
+
+  return GPDMA::instance().transfer(&cfg, ctrl_word, 0, GPDMA_CONN_MEMORY, GPDMA_CONN_SDC);
+}
+
+static bool gpdma_transfer_from_mci(GPDMA::DMAChannels ChannelNum,
+                             uint32_t dst,
+                             uint32_t Size)
+{
+  GPDMA::GPDMA_Channel_CFG_T cfg;
+  cfg.ChannelNum = ChannelNum;
+  cfg.TransferType = GPDMA::FlowControl_P2M_Ctrl_Periph;
+  cfg.TransferSize = Size;
+  cfg.TransferWidth = 0;
+  cfg.SrcAddr = (uint32_t) (&LPC_MCI->FIFO);
+  cfg.DstAddr = dst;
+
+  uint32_t ctrl_word =
+      GPDMA_DMACCxControl_TransferSize((uint32_t) cfg.TransferSize)
+          | GPDMA_DMACCxControl_SBSize(GPDMA_BSIZE_8)
+          | GPDMA_DMACCxControl_DBSize(GPDMA_BSIZE_8)
+          | GPDMA_DMACCxControl_SWidth(GPDMA_WIDTH_WORD)
+          | GPDMA_DMACCxControl_DWidth(GPDMA_WIDTH_WORD)
+          | GPDMA_DMACCxControl_SrcTransUseAHBMaster1
+          | GPDMA_DMACCxControl_DI
+          | GPDMA_DMACCxControl_I;
+
+  /* Select SD card interface in the DMA MUX*/
+  LPC_SC->DMAREQSEL &= ~(1 << 1);
+
+  return GPDMA::instance().transfer(&cfg, ctrl_word, 0, GPDMA_CONN_SDC, GPDMA_CONN_MEMORY);
+}
+
 bool MCIFileSystem::cardInserted() const
 {
     // If no card detect pin is given, then assume that a card is inserted.
@@ -968,7 +1021,6 @@
 MCIFileSystem::ReturnCode MCIFileSystem::mci_ReadBlocks(void *buffer, int32_t startBlock, int32_t blockNum)
 {
   ReturnCode Ret = SDC_RET_FAILED;
-  uint8_t dmaChannel;
   int32_t ByteNum = blockNum *  MMC_SECTOR_SIZE;
 
   do
@@ -988,9 +1040,8 @@
     LPC_MCI->MASK0 = SDC_MASK0_DATA | SDC_MASK0_RXDATAERR;
 
     /* DMA Setup */
-    gpdma_getFreeChannel(&dmaChannel);
-    gpdma_transfer_from_mci(dmaChannel, (uint32_t)buffer, ByteNum);
-    mci_SetupEventWakeup(dmaChannel);
+    mci_SetupEventWakeup();
+    gpdma_transfer_from_mci(_eventDmaChannel, (uint32_t)buffer, ByteNum);
 
     /* set transfer information */
     mci_SetDataTransfer(blockNum, true, DATA_TIMER_VALUE_R);
@@ -1005,7 +1056,7 @@
       Ret = SDC_RET_FAILED;
     }
 
-    gpdma_stop(dmaChannel);
+    GPDMA::instance().stopTransfer(_eventDmaChannel);
 
     if ((blockNum > 1) || (mci_GetCardState() == SDMMC_DATA_ST)) {
       /* Send Stop transmission command */
@@ -1023,7 +1074,6 @@
 MCIFileSystem::ReturnCode MCIFileSystem::mci_WriteBlocks(void *buffer, int32_t startBlock, int32_t blockNum)
 {
   ReturnCode Ret = SDC_RET_FAILED;
-  uint8_t dmaChannel;
   
   do
   {
@@ -1050,9 +1100,8 @@
     LPC_MCI->MASK0 = SDC_MASK0_DATA | SDC_MASK0_TXDATAERR;
 
     /* DMA Setup */
-    gpdma_getFreeChannel(&dmaChannel);
-    gpdma_transfer_to_mci(dmaChannel, (uint32_t)buffer, blockNum*MMC_SECTOR_SIZE);
-    mci_SetupEventWakeup(dmaChannel);
+    mci_SetupEventWakeup();
+    gpdma_transfer_to_mci(_eventDmaChannel, (uint32_t)buffer, blockNum*MMC_SECTOR_SIZE);
 
     /* set transfer information */
     mci_SetDataTransfer(blockNum, false, DATA_TIMER_VALUE_W);
@@ -1061,7 +1110,6 @@
     if (mci_WaitForEvent() != 0) {
       Ret = SDC_RET_FAILED;
     }
-    gpdma_stop(dmaChannel);
 
     if ((blockNum > 1) || (mci_GetCardState() == SDMMC_RCV_ST)) {
       /* Send Stop transmission command */
@@ -1728,16 +1776,12 @@
   }
 }
 
-void MCIFileSystem::mci_SetupEventWakeup(uint8_t dmaChannel)
+void MCIFileSystem::mci_SetupEventWakeup()
 {
   /* Wait for IRQ - for an RTOS, you would pend on an event here with a IRQ based wakeup. */
-  NVIC_ClearPendingIRQ(DMA_IRQn);
 
-  _eventDmaChannel = dmaChannel;
   _eventReceived = false;
   _eventSuccess = false;
-
-  NVIC_EnableIRQ(DMA_IRQn);
 }
 
 uint32_t MCIFileSystem::mci_WaitForEvent() const
--- a/FileSystems/MCIFileSystem.h	Mon Mar 23 13:45:16 2015 +0000
+++ b/FileSystems/MCIFileSystem.h	Wed Apr 15 09:41:56 2015 +0200
@@ -19,6 +19,7 @@
 
 #include "mbed.h"
 #include "FATFileSystem.h"
+#include "GPDMA.h"
 
 /** Access the filesystem on an SD Card using MCI
  *
@@ -185,7 +186,7 @@
     void        mci_ReadFIFO(uint32_t *pDst, bool bFirstHalf) const;
     void        mci_WriteFIFO(uint32_t *pSrc, bool bFirstHalf) const;
                 
-    void        mci_SetupEventWakeup(uint8_t dmaChannel);
+    void        mci_SetupEventWakeup();
     uint32_t    mci_WaitForEvent() const;
 
     ReturnCode _readBlocks(uint32_t card_type, uint32_t startBlock, uint32_t blockNum) const;
@@ -197,7 +198,7 @@
 
     DigitalIn* _cardDetect;
 
-    uint8_t _eventDmaChannel;    /*!< DMA Channel used for transfer data */
+    GPDMA::DMAChannels _eventDmaChannel;    /*!< DMA Channel used for transfer data */
     volatile bool _eventReceived;
     volatile bool _eventSuccess;
 };
--- a/FileSystems/gpdma.cpp	Mon Mar 23 13:45:16 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,325 +0,0 @@
-/*
- *  Copyright 2014 Embedded Artists AB
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-/******************************************************************************
- * Includes
- *****************************************************************************/
-
-#include "gpdma.h"
-
-/******************************************************************************
- * Defines and typedefs
- *****************************************************************************/
-
-#define NUM_GPDMA_CHANNELS  8
-
-#define GPDMACH(__x) ((LPC_GPDMACH_TypeDef*)(LPC_GPDMACH0_BASE + (0x20 * (__x))))
-
-#define CH_MASK(__ch)  (((1UL << (__ch)) & 0xFF))
-
-/**
- * @brief GPDMA request connections
- */
-#define GPDMA_CONN_MEMORY           ((0UL))
-#define GPDMA_CONN_SDC              ((1UL))      /*!< SD card */
-
-/**
- * @brief Macro defines for DMA channel control registers
- */
-#define GPDMA_DMACCxControl_TransferSize(n) (((n & 0xFFF) << 0))  /*!< Transfer size*/
-#define GPDMA_DMACCxControl_SBSize(n)       (((n & 0x07) << 12))  /*!< Source burst size*/
-#define GPDMA_DMACCxControl_DBSize(n)       (((n & 0x07) << 15))  /*!< Destination burst size*/
-#define GPDMA_DMACCxControl_SWidth(n)       (((n & 0x07) << 18))  /*!< Source transfer width*/
-#define GPDMA_DMACCxControl_DWidth(n)       (((n & 0x07) << 21))  /*!< Destination transfer width*/
-#define GPDMA_DMACCxControl_SI              ((1UL << 26))      /*!< Source increment*/
-#define GPDMA_DMACCxControl_DI              ((1UL << 27))      /*!< Destination increment*/
-#define GPDMA_DMACCxControl_SrcTransUseAHBMaster1   0
-#define GPDMA_DMACCxControl_DestTransUseAHBMaster1  0
-#define GPDMA_DMACCxControl_Prot1           ((1UL << 28))      /*!< Indicates that the access is in user mode or privileged mode*/
-#define GPDMA_DMACCxControl_Prot2           ((1UL << 29))      /*!< Indicates that the access is bufferable or not bufferable*/
-#define GPDMA_DMACCxControl_Prot3           ((1UL << 30))      /*!< Indicates that the access is cacheable or not cacheable*/
-#define GPDMA_DMACCxControl_I               ((1UL << 31))      /*!< Terminal count interrupt enable bit */
-
-/**
- * @brief GPDMA Burst size in Source and Destination definitions
- */
-#define GPDMA_BSIZE_1   ((0UL))  /*!< Burst size = 1 */
-#define GPDMA_BSIZE_4   ((1UL))  /*!< Burst size = 4 */
-#define GPDMA_BSIZE_8   ((2UL))  /*!< Burst size = 8 */
-#define GPDMA_BSIZE_16  ((3UL))  /*!< Burst size = 16 */
-#define GPDMA_BSIZE_32  ((4UL))  /*!< Burst size = 32 */
-#define GPDMA_BSIZE_64  ((5UL))  /*!< Burst size = 64 */
-#define GPDMA_BSIZE_128 ((6UL))  /*!< Burst size = 128 */
-#define GPDMA_BSIZE_256 ((7UL))  /*!< Burst size = 256 */
-
-/**
- * @brief Width in Source transfer width and Destination transfer width definitions
- */
-#define GPDMA_WIDTH_BYTE        ((0UL))  /*!< Width = 1 byte */
-#define GPDMA_WIDTH_HALFWORD    ((1UL))  /*!< Width = 2 bytes */
-#define GPDMA_WIDTH_WORD        ((2UL))  /*!< Width = 4 bytes */
-
-/**
- * @brief Macro defines for DMA Configuration register
- */
-#define GPDMA_DMACConfig_E              ((0x01))  /*!< DMA Controller enable*/
-#define GPDMA_DMACConfig_M              ((0x02))  /*!< AHB Master endianness configuration*/
-#define GPDMA_DMACConfig_BITMASK        ((0x03))
-
-/**
- * @brief Macro defines for DMA Channel Configuration registers
- */
-#define GPDMA_DMACCxConfig_E                    ((1UL << 0))      /*!< DMA control enable*/
-#define GPDMA_DMACCxConfig_SrcPeripheral(n)     (((n & 0x1F) << 1))    /*!< Source peripheral*/
-#define GPDMA_DMACCxConfig_DestPeripheral(n)    (((n & 0x1F) << 6))    /*!< Destination peripheral*/
-#define GPDMA_DMACCxConfig_TransferType(n)      (((n & 0x7) << 11))    /*!< This value indicates the type of transfer*/
-#define GPDMA_DMACCxConfig_IE                   ((1UL << 14))      /*!< Interrupt error mask*/
-#define GPDMA_DMACCxConfig_ITC                  ((1UL << 15))      /*!< Terminal count interrupt mask*/
-#define GPDMA_DMACCxConfig_L                    ((1UL << 16))      /*!< Lock*/
-#define GPDMA_DMACCxConfig_A                    ((1UL << 17))      /*!< Active*/
-#define GPDMA_DMACCxConfig_H                    ((1UL << 18))      /*!< Halt*/
-
-/**
- * @brief GPDMA structure using for DMA configuration
- */
-typedef struct {
-  uint32_t ChannelNum;  /*!< DMA channel number, should be in
-               *  range from 0 to 7.
-               *  Note: DMA channel 0 has the highest priority
-               *  and DMA channel 7 the lowest priority.
-               */
-  uint32_t TransferSize;  /*!< Length/Size of transfer */
-  uint32_t TransferWidth;  /*!< Transfer width - used for TransferType is GPDMA_TRANSFERTYPE_M2M only */
-  uint32_t SrcAddr;    /*!< Physical Source Address, used in case TransferType is chosen as
-               *   GPDMA_TRANSFERTYPE_M2M or GPDMA_TRANSFERTYPE_M2P */
-  uint32_t DstAddr;    /*!< Physical Destination Address, used in case TransferType is chosen as
-               *   GPDMA_TRANSFERTYPE_M2M or GPDMA_TRANSFERTYPE_P2M */
-  uint32_t TransferType;  /*!< Transfer Type, should be one of the following:
-               * - GPDMA_TRANSFERTYPE_M2M: Memory to memory - DMA control
-               * - GPDMA_TRANSFERTYPE_M2P: Memory to peripheral - DMA control
-               * - GPDMA_TRANSFERTYPE_P2M: Peripheral to memory - DMA control
-               * - GPDMA_TRANSFERTYPE_P2P: Source peripheral to destination peripheral - DMA control
-               */
-} GPDMA_Channel_CFG_T;
-
-/******************************************************************************
- * External global variables
- *****************************************************************************/
-
-/******************************************************************************
- * Local variables
- *****************************************************************************/
-
-static bool used_channels[NUM_GPDMA_CHANNELS];
-
-/******************************************************************************
- * Local Functions
- *****************************************************************************/
-
-static void gpdma_transfer(GPDMA_Channel_CFG_T* cfg,
-                           uint32_t CtrlWord,
-                           uint32_t LinkListItem,
-                           uint8_t SrcPeripheral,
-                           uint8_t DstPeripheral)
-{
-  /* Get Channel pointer */
-  LPC_GPDMACH_TypeDef* pCh = GPDMACH(cfg->ChannelNum);
-
-  /* Reset the Interrupt status */
-  LPC_GPDMA->IntTCClear = CH_MASK(cfg->ChannelNum);
-  LPC_GPDMA->IntErrClr = CH_MASK(cfg->ChannelNum);
-
-  /* Assign Linker List Item value */
-  pCh->CLLI = LinkListItem;
-
-  /* Enable DMA channels, little endian */
-  LPC_GPDMA->Config = GPDMA_DMACConfig_E;
-  while (!(LPC_GPDMA->Config & GPDMA_DMACConfig_E)) {}
-
-  pCh->CSrcAddr = cfg->SrcAddr;
-  pCh->CDestAddr = cfg->DstAddr;
-
-  /* Configure DMA Channel, enable Error Counter and Terminate counter */
-  pCh->CConfig = GPDMA_DMACCxConfig_IE
-           | GPDMA_DMACCxConfig_ITC
-           | GPDMA_DMACCxConfig_TransferType((uint32_t) cfg->TransferType)
-           | GPDMA_DMACCxConfig_SrcPeripheral(SrcPeripheral)
-           | GPDMA_DMACCxConfig_DestPeripheral(DstPeripheral);
-
-  pCh->CControl = CtrlWord;
-
-  /* Start the Channel */
-  pCh->CConfig |= GPDMA_DMACCxConfig_E;
-}
-
-/******************************************************************************
- * Public Functions
- *****************************************************************************/
-
-void gpdma_init()
-{
-  uint8_t i;
-
-  /* Enable GPDMA master clock */
-  LPC_SC->PCONP |= (1<<29);
-
-  /* Reset all channel configuration register */
-  for (i = 0; i < NUM_GPDMA_CHANNELS; i++) {
-    GPDMACH(i)->CConfig = 0;
-  }
-
-  /* Clear all DMA interrupt and error flag */
-  LPC_GPDMA->IntTCClear = 0xFF;
-  LPC_GPDMA->IntErrClr  = 0xFF;
-
-  /* Reset all channels are free */
-  for (int i = 0; i < NUM_GPDMA_CHANNELS; i++)
-  {
-    used_channels[i] = false;
-  }
-}
-
-void gpdma_deinit()
-{
-  /* Disable GPDMA master clock */
-  LPC_SC->PCONP &= ~(1<<29);
-}
-
-void gpdma_stop(uint8_t ChannelNum)
-{
-  if (ChannelNum >= NUM_GPDMA_CHANNELS) {
-    return;
-  }
-
-  /* Disable channel */
-  GPDMACH(ChannelNum)->CConfig &= ~GPDMA_DMACCxConfig_E;
-
-  /* check terminal count interrupt request status for DMA */
-  if (LPC_GPDMA->IntTCStat & CH_MASK(ChannelNum)) {
-    /* Clear terminate counter Interrupt pending */
-    LPC_GPDMA->IntTCClear = CH_MASK(ChannelNum);
-  }
-
-  /* check status of the error interrupt for DMA channels */
-  if (LPC_GPDMA->IntErrStat & CH_MASK(ChannelNum)) {
-    /* clear the error interrupt request */
-    LPC_GPDMA->IntErrClr = CH_MASK(ChannelNum);
-  }
-
-  used_channels[ChannelNum] = false;
-}
-
-bool gpdma_interrupt(uint8_t ChannelNum)
-{
-  /* check status of DMA channel interrupts */
-  if (LPC_GPDMA->IntStat & CH_MASK(ChannelNum)) {
-    /* Check counter terminal status */
-    if (LPC_GPDMA->IntTCStat & CH_MASK(ChannelNum)) {
-      /* Clear terminate counter Interrupt pending */
-      LPC_GPDMA->IntTCClear = CH_MASK(ChannelNum);
-      return true;
-    }
-    /* Check error terminal status */
-    if (LPC_GPDMA->IntErrStat & CH_MASK(ChannelNum)) {
-      /* Clear error counter Interrupt pending */
-      LPC_GPDMA->IntErrClr = CH_MASK(ChannelNum);
-      return false;
-    }
-  }
-  return false;
-}
-
-bool gpdma_getFreeChannel(uint8_t* pCh)
-{
-  for (int i = 0; i < NUM_GPDMA_CHANNELS; i++)
-  {
-    if ((!used_channels[i]) && ((LPC_GPDMA->EnbldChns & CH_MASK(i)) == 0))
-    {
-      used_channels[i] = true;
-      *pCh = i;
-      return true;
-    }
-  }
-  return false;
-}
-
-bool gpdma_transfer_to_mci(uint8_t ChannelNum,
-                           uint32_t src,
-                           uint32_t Size)
-{
-  GPDMA_Channel_CFG_T cfg;
-  cfg.ChannelNum = ChannelNum;
-  cfg.TransferType = GPDMA_TRANSFERTYPE_M2P_CONTROLLER_PERIPHERAL;
-  cfg.TransferSize = Size;
-  cfg.TransferWidth = 0;
-  cfg.SrcAddr = src;
-  cfg.DstAddr = (uint32_t) (&LPC_MCI->FIFO);
-
-  uint32_t ctrl_word =
-      GPDMA_DMACCxControl_TransferSize((uint32_t) cfg.TransferSize)
-          | GPDMA_DMACCxControl_SBSize(GPDMA_BSIZE_8)
-          | GPDMA_DMACCxControl_DBSize(GPDMA_BSIZE_8)
-          | GPDMA_DMACCxControl_SWidth(GPDMA_WIDTH_WORD)
-          | GPDMA_DMACCxControl_DWidth(GPDMA_WIDTH_WORD)
-          | GPDMA_DMACCxControl_DestTransUseAHBMaster1
-          | GPDMA_DMACCxControl_SI
-          | GPDMA_DMACCxControl_I;
-
-  if (LPC_GPDMA->EnbldChns & CH_MASK(ChannelNum)) {
-    /* This channel is enabled, return ERROR, need to release this channel first */
-    return false;
-  }
-
-  /* Select SD card interface in the DMA MUX*/
-  LPC_SC->DMAREQSEL &= ~(1 << 1);
-
-  gpdma_transfer(&cfg, ctrl_word, 0, GPDMA_CONN_MEMORY, GPDMA_CONN_SDC);
-  return true;
-}
-
-bool gpdma_transfer_from_mci(uint8_t ChannelNum,
-                             uint32_t dst,
-                             uint32_t Size)
-{
-  GPDMA_Channel_CFG_T cfg;
-  cfg.ChannelNum = ChannelNum;
-  cfg.TransferType = GPDMA_TRANSFERTYPE_P2M_CONTROLLER_PERIPHERAL;
-  cfg.TransferSize = Size;
-  cfg.TransferWidth = 0;
-  cfg.SrcAddr = (uint32_t) (&LPC_MCI->FIFO);
-  cfg.DstAddr = dst;
-
-  uint32_t ctrl_word =
-      GPDMA_DMACCxControl_TransferSize((uint32_t) cfg.TransferSize)
-          | GPDMA_DMACCxControl_SBSize(GPDMA_BSIZE_8)
-          | GPDMA_DMACCxControl_DBSize(GPDMA_BSIZE_8)
-          | GPDMA_DMACCxControl_SWidth(GPDMA_WIDTH_WORD)
-          | GPDMA_DMACCxControl_DWidth(GPDMA_WIDTH_WORD)
-          | GPDMA_DMACCxControl_SrcTransUseAHBMaster1
-          | GPDMA_DMACCxControl_DI
-          | GPDMA_DMACCxControl_I;
-
-  if (LPC_GPDMA->EnbldChns & CH_MASK(ChannelNum)) {
-    /* This channel is enabled, return ERROR, need to release this channel first */
-    return false;
-  }
-
-  /* Select SD card interface in the DMA MUX*/
-  LPC_SC->DMAREQSEL &= ~(1 << 1);
-
-  gpdma_transfer(&cfg, ctrl_word, 0, GPDMA_CONN_SDC, GPDMA_CONN_MEMORY);
-  return true;
-}
--- a/FileSystems/gpdma.h	Mon Mar 23 13:45:16 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- *  Copyright 2014 Embedded Artists AB
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-#ifndef GPDMA_H
-#define GPDMA_H
-
-#include "platform.h"
-
-#define GPDMA_CONN_SDC              ((1UL))      /*!< SD card */
-
-typedef enum
-{
-  GPDMA_TRANSFERTYPE_M2M_CONTROLLER_DMA,             /* Memory to memory - DMA control */
-  GPDMA_TRANSFERTYPE_M2P_CONTROLLER_DMA,             /* Memory to peripheral - DMA control */
-  GPDMA_TRANSFERTYPE_P2M_CONTROLLER_DMA,             /* Peripheral to memory - DMA control */
-  GPDMA_TRANSFERTYPE_P2P_CONTROLLER_DMA,             /* Source peripheral to destination peripheral - DMA control */
-  GPDMA_TRANSFERTYPE_P2P_CONTROLLER_DestPERIPHERAL,  /* Source peripheral to destination peripheral - destination peripheral control */
-  GPDMA_TRANSFERTYPE_M2P_CONTROLLER_PERIPHERAL,      /* Memory to peripheral - peripheral control */
-  GPDMA_TRANSFERTYPE_P2M_CONTROLLER_PERIPHERAL,      /* Peripheral to memory - peripheral control */
-  GPDMA_TRANSFERTYPE_P2P_CONTROLLER_SrcPERIPHERAL,  /* Source peripheral to destination peripheral - source peripheral control */
-} gpdma_flowControl_t;
-
-/**
- * @brief  Initialize the GPDMA
- * @param  pGPDMA  : The base of GPDMA on the chip
- * @return  Nothing
- */
-void gpdma_init();
-
-/**
- * @brief  Shutdown the GPDMA
- * @param  pGPDMA  : The base of GPDMA on the chip
- * @return  Nothing
- */
-void gpdma_deinit();
-
-/**
- * @brief  Stop a stream DMA transfer
- * @param  ChannelNum  : Channel Number to be closed
- * @return  Nothing
- */
-void gpdma_stop(uint8_t ChannelNum);
-
-/**
- * @brief  The GPDMA stream interrupt status checking
- * @param  ChannelNum  : Channel Number to be checked on interruption
- * @return  Status:
- *              - true  : DMA transfer success
- *              - false  : DMA transfer failed
- */
-bool gpdma_interrupt(uint8_t ChannelNum);
-
-/**
- * @brief  Get a free GPDMA channel for one DMA connection
- * @param  pCh  : Assigned channel number (only valid if success)
- * @return  Status:
- *              - true  : Found a free DMA channel
- *              - false  : No free DMA channels, pCh value is undefined
- */
-bool gpdma_getFreeChannel(uint8_t* pCh);
-
-/**
- * @brief  Do a DMA transfer M2M, M2P,P2M or P2P
- * @param  ChannelNum  : Channel used for transfer
- * @param  src      : Address of Memory or PeripheralConnection_ID which is the source
- * @param  dst      : Address of Memory or PeripheralConnection_ID which is the destination
- * @param  TransferType: Select the transfer controller and the type of transfer. Should be:
- *                               - GPDMA_TRANSFERTYPE_M2M_CONTROLLER_DMA
- *                               - GPDMA_TRANSFERTYPE_M2P_CONTROLLER_DMA
- *                               - GPDMA_TRANSFERTYPE_P2M_CONTROLLER_DMA
- *                               - GPDMA_TRANSFERTYPE_P2P_CONTROLLER_DMA
- *                               - GPDMA_TRANSFERTYPE_P2P_CONTROLLER_DestPERIPHERAL
- *                               - GPDMA_TRANSFERTYPE_M2P_CONTROLLER_PERIPHERAL
- *                               - GPDMA_TRANSFERTYPE_P2M_CONTROLLER_PERIPHERAL
- *                               - GPDMA_TRANSFERTYPE_P2P_CONTROLLER_SrcPERIPHERAL
- * @param  Size    : The number of DMA transfers
- * @return  False on error, true on success
- */
-//bool gpdma_transfer(uint8_t ChannelNum,
-//                    uint32_t src,
-//                    uint32_t dst,
-//                    gpdma_flowControl_t TransferType,
-//                    uint32_t Size);
-
-bool gpdma_transfer_to_mci(uint8_t ChannelNum,
-                           uint32_t src,
-                           uint32_t Size);
-bool gpdma_transfer_from_mci(uint8_t ChannelNum,
-                             uint32_t dst,
-                             uint32_t Size);
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GPDMA.cpp	Wed Apr 15 09:41:56 2015 +0200
@@ -0,0 +1,238 @@
+/*
+ *  Copyright 2015 Embedded Artists AB
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include "mbed.h"
+#include "DMBoard.h"
+#include "GPDMA.h"
+
+
+/******************************************************************************
+ * Defines and typedefs
+ *****************************************************************************/
+
+#define GPDMACH(__x) ((LPC_GPDMACH_TypeDef*)(LPC_GPDMACH0_BASE + (0x20 * (__x))))
+
+#define CH_MASK(__ch)  (((1UL << (__ch)) & 0xFF))
+
+#define GPDMA_ALL_CH_MASK  (0xff)
+
+/******************************************************************************
+ * Local variables
+ *****************************************************************************/
+
+/******************************************************************************
+ * Private Class
+ *****************************************************************************/
+
+/******************************************************************************
+ * DMA Interrupt Functon
+ *****************************************************************************/
+
+static void mydmairq()
+{
+  GPDMA::instance().processInterrupt();
+}
+
+/******************************************************************************
+ * Private Functions
+ *****************************************************************************/
+
+/******************************************************************************
+ * Public Functions
+ *****************************************************************************/
+
+GPDMA::GPDMA() : _usedChannels(0), _initialized(false)
+{
+  for (int i = 0; i < NumDMAChannels; i++) {
+    _chData[i].inUse = false;
+    _chData[i].func = NULL;
+  }
+
+  /* Redirect all DMA IRQs to the local mydmairq() function */
+  NVIC_SetVector(DMA_IRQn, (uint32_t) mydmairq);
+}
+
+GPDMA::~GPDMA()
+{
+}
+
+void GPDMA::init()
+{
+  _mutex.lock();
+  if (!_initialized) {
+    /* Enable GPDMA master clock */
+    LPC_SC->PCONP |= (1<<29);
+
+    /* Reset all channel configuration register */
+    for (int i = 0; i < NumDMAChannels; i++) {
+      GPDMACH(i)->CConfig = 0;
+    }
+
+    /* Clear all DMA interrupt and error flag */
+    LPC_GPDMA->IntTCClear = 0xFF;
+    LPC_GPDMA->IntErrClr  = 0xFF;
+
+    /* Reset all channel datas */
+    for (int i = 0; i < NumDMAChannels; i++) {
+      _chData[i].inUse = false;
+      _chData[i].func = NULL;
+    }
+
+    _initialized = true;
+  }
+  _mutex.unlock();
+}
+
+void GPDMA::deinit()
+{
+  _mutex.lock();
+  if (_usedChannels == 0) {
+    /* Disable the real interrupt */
+    NVIC_DisableIRQ(DMA_IRQn);
+
+    /* Clear all DMA interrupt and error flag */
+    LPC_GPDMA->IntTCClear = 0xFF;
+    LPC_GPDMA->IntErrClr  = 0xFF;
+
+    /* Disable GPDMA master clock */
+    LPC_SC->PCONP &= ~(1<<29);
+
+    _initialized = false;
+  }
+  _mutex.unlock();
+}
+
+GPDMA::DMAChannels GPDMA::acquireChannel(void (*irqfunc)(void), DMAChannels suggested)
+{
+  DMAChannels result = DMACh_Unavailable;
+  _mutex.lock();
+  if (!_initialized) {
+    init();
+  }
+  for (int i = suggested; i < NumDMAChannels; i++) {
+    if ((!_chData[i].inUse) && ((LPC_GPDMA->EnbldChns & CH_MASK(i)) == 0)) {
+      _chData[i].inUse = true;
+      _chData[i].func = irqfunc;
+      result = (DMAChannels)i;
+      _usedChannels++;
+      break;
+    }
+  }
+
+  _mutex.unlock();
+  return result;
+}
+
+void GPDMA::releaseChannel(DMAChannels ch)
+{
+  _mutex.lock();
+  if (ch < NumDMAChannels) {
+    stopTransfer(ch);
+    if (_chData[ch].inUse) {
+      _usedChannels--;
+    }
+    _chData[ch].inUse = false;
+    _chData[ch].func = NULL;
+  }
+  _mutex.unlock();
+}
+
+LPC_GPDMACH_TypeDef* GPDMA::getDirectRegisters(DMAChannels ch)
+{
+  if (ch < NumDMAChannels) {
+    return GPDMACH(ch);
+  } else {
+    return NULL;
+  }
+}
+
+void GPDMA::processInterrupt()
+{
+  /* check status of DMA channel interrupts */
+  uint32_t intstat = LPC_GPDMA->IntStat;
+
+  for (int i = 0; i < NumDMAChannels; i++) {
+    uint32_t mask = CH_MASK(i);
+    if (intstat & mask) {
+      if (_chData[i].func != NULL) {
+        /* Notify registered subscriber */
+        _chData[i].func();//GPDMACH(i), (tcstat&mask)!=0, (errstat&mask)!=0);
+      }
+    }
+  }
+
+  if ((LPC_GPDMA->EnbldChns & GPDMA_ALL_CH_MASK) == 0) {
+    /* No more enabled DMA channels, so turn of DMA IRQ */
+    //NVIC_DisableIRQ(DMA_IRQn);
+  }
+}
+
+bool GPDMA::transfer(GPDMA_Channel_CFG_T* cfg, uint32_t CtrlWord,
+                     uint32_t LinkListItem, uint8_t SrcPeripheral,
+                     uint8_t DstPeripheral)
+{
+  if (LPC_GPDMA->EnbldChns & CH_MASK(cfg->ChannelNum)) {
+    /* This channel is enabled, return ERROR, need to release this channel first */
+    return false;
+  }
+
+  /* Get Channel pointer */
+  LPC_GPDMACH_TypeDef* pCh = GPDMACH(cfg->ChannelNum);
+
+  /* Reset the Interrupt status */
+  LPC_GPDMA->IntTCClear = CH_MASK(cfg->ChannelNum);
+  LPC_GPDMA->IntErrClr = CH_MASK(cfg->ChannelNum);
+
+  /* Clear configuration */
+  pCh->CControl = 0x00;
+  pCh->CConfig = 0x00;
+
+  /* Assign Linker List Item value */
+  pCh->CLLI = LinkListItem;
+
+  pCh->CSrcAddr = cfg->SrcAddr;
+  pCh->CDestAddr = cfg->DstAddr;
+  pCh->CControl = CtrlWord;
+
+  /* Enable DMA channels, little endian */
+  LPC_GPDMA->Config = GPDMA_DMACConfig_E;
+  while (!(LPC_GPDMA->Config & GPDMA_DMACConfig_E)) {}
+
+  /* Configure DMA Channel, enable Error Counter and Terminate counter */
+  pCh->CConfig = GPDMA_DMACCxConfig_IE
+               | GPDMA_DMACCxConfig_ITC
+               | GPDMA_DMACCxConfig_TransferType((uint32_t) cfg->TransferType)
+               | GPDMA_DMACCxConfig_SrcPeripheral(SrcPeripheral)
+               | GPDMA_DMACCxConfig_DestPeripheral(DstPeripheral);
+
+  /* Enable the interrupts */
+  NVIC_EnableIRQ(DMA_IRQn);
+
+  /* Start the Channel */
+  pCh->CConfig |= GPDMA_DMACCxConfig_E;
+
+  return true;
+}
+
+void GPDMA::stopTransfer(DMAChannels ch)
+{
+  /* Disable channel */
+  GPDMACH(ch)->CConfig &= ~GPDMA_DMACCxConfig_E;
+
+  /* Clear pending interrupts */
+  LPC_GPDMA->IntTCClear = CH_MASK(ch);
+  LPC_GPDMA->IntErrClr = CH_MASK(ch);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GPDMA.h	Wed Apr 15 09:41:56 2015 +0200
@@ -0,0 +1,268 @@
+/*
+ *  Copyright 2015 Embedded Artists AB
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef GPDMA_H
+#define GPDMA_H
+
+#include "mbed.h"
+#include "rtos.h"
+
+/**
+ * @brief GPDMA request connections
+ */
+#define GPDMA_CONN_MEMORY           ((0UL))
+#define GPDMA_CONN_SDC              ((1UL))      /*!< SD card */
+
+/**
+ * @brief Macro defines for DMA channel control registers
+ */
+#define GPDMA_DMACCxControl_TransferSize(n) (((n & 0xFFF) << 0))  /*!< Transfer size*/
+#define GPDMA_DMACCxControl_SBSize(n)       (((n & 0x07) << 12))  /*!< Source burst size*/
+#define GPDMA_DMACCxControl_DBSize(n)       (((n & 0x07) << 15))  /*!< Destination burst size*/
+#define GPDMA_DMACCxControl_SWidth(n)       (((n & 0x07) << 18))  /*!< Source transfer width*/
+#define GPDMA_DMACCxControl_DWidth(n)       (((n & 0x07) << 21))  /*!< Destination transfer width*/
+#define GPDMA_DMACCxControl_SI              ((1UL << 26))      /*!< Source increment*/
+#define GPDMA_DMACCxControl_DI              ((1UL << 27))      /*!< Destination increment*/
+#define GPDMA_DMACCxControl_SrcTransUseAHBMaster1   0
+#define GPDMA_DMACCxControl_DestTransUseAHBMaster1  0
+#define GPDMA_DMACCxControl_Prot1           ((1UL << 28))      /*!< Indicates that the access is in user mode or privileged mode*/
+#define GPDMA_DMACCxControl_Prot2           ((1UL << 29))      /*!< Indicates that the access is bufferable or not bufferable*/
+#define GPDMA_DMACCxControl_Prot3           ((1UL << 30))      /*!< Indicates that the access is cacheable or not cacheable*/
+#define GPDMA_DMACCxControl_I               ((1UL << 31))      /*!< Terminal count interrupt enable bit */
+
+/**
+ * @brief GPDMA Burst size in Source and Destination definitions
+ */
+#define GPDMA_BSIZE_1   ((0UL))  /*!< Burst size = 1 */
+#define GPDMA_BSIZE_4   ((1UL))  /*!< Burst size = 4 */
+#define GPDMA_BSIZE_8   ((2UL))  /*!< Burst size = 8 */
+#define GPDMA_BSIZE_16  ((3UL))  /*!< Burst size = 16 */
+#define GPDMA_BSIZE_32  ((4UL))  /*!< Burst size = 32 */
+#define GPDMA_BSIZE_64  ((5UL))  /*!< Burst size = 64 */
+#define GPDMA_BSIZE_128 ((6UL))  /*!< Burst size = 128 */
+#define GPDMA_BSIZE_256 ((7UL))  /*!< Burst size = 256 */
+
+/**
+ * @brief Width in Source transfer width and Destination transfer width definitions
+ */
+#define GPDMA_WIDTH_BYTE        ((0UL))  /*!< Width = 1 byte */
+#define GPDMA_WIDTH_HALFWORD    ((1UL))  /*!< Width = 2 bytes */
+#define GPDMA_WIDTH_WORD        ((2UL))  /*!< Width = 4 bytes */
+
+/**
+ * @brief Macro defines for DMA Configuration register
+ */
+#define GPDMA_DMACConfig_E              ((0x01))  /*!< DMA Controller enable*/
+#define GPDMA_DMACConfig_M              ((0x02))  /*!< AHB Master endianness configuration*/
+#define GPDMA_DMACConfig_BITMASK        ((0x03))
+
+/**
+ * @brief Macro defines for DMA Channel Configuration registers
+ */
+#define GPDMA_DMACCxConfig_E                    ((1UL << 0))      /*!< DMA control enable*/
+#define GPDMA_DMACCxConfig_SrcPeripheral(n)     (((n & 0x1F) << 1))    /*!< Source peripheral*/
+#define GPDMA_DMACCxConfig_DestPeripheral(n)    (((n & 0x1F) << 6))    /*!< Destination peripheral*/
+#define GPDMA_DMACCxConfig_TransferType(n)      (((n & 0x7) << 11))    /*!< This value indicates the type of transfer*/
+#define GPDMA_DMACCxConfig_IE                   ((1UL << 14))      /*!< Interrupt error mask*/
+#define GPDMA_DMACCxConfig_ITC                  ((1UL << 15))      /*!< Terminal count interrupt mask*/
+#define GPDMA_DMACCxConfig_L                    ((1UL << 16))      /*!< Lock*/
+#define GPDMA_DMACCxConfig_A                    ((1UL << 17))      /*!< Active*/
+#define GPDMA_DMACCxConfig_H                    ((1UL << 18))      /*!< Halt*/
+
+/**
+ * @brief GPDMA Linker List Item structure type definition
+ */
+typedef struct {
+    uint32_t SrcAddr;    /**< Source Address */
+    uint32_t DstAddr;    /**< Destination address */
+    uint32_t NextLLI;    /**< Next LLI address, otherwise set to '0' */
+    uint32_t Control;    /**< GPDMA Control of this LLI */
+} GPDMA_LLI_Type;
+
+/**
+ * Wrapper for the General Purpose DMA controller.
+ *
+ * The GPDMA class allows multiple users of DMA to claim one or more
+ * of the eight available DMA channels and to register handlers for the
+ * interrupts. This centralized control is needed as there are eight
+ * channels but only one DMA IRQ.
+ *
+ * By having to request a channel to use it is possible to avoid having
+ * hardcoded DMA channel number in the code
+ *
+ * An example of use:
+ *
+ * @code
+ * void handler() {
+ *   _eventSuccess = LPC_GPDMA->IntTCStat & (1<<ch);
+ *   LPC_GPDMA->IntTCClear = (1<<ch);
+ * }
+ *
+ * void foo() {
+ *    GPDMA* dma = &GPDMA::instance();
+ *    dma->init();
+ *
+ *    DMAChannels ch = dma->acquireChannel(handler)
+ *    if (ch == DMACh_Unavailable) {
+ *      // handle error
+ *    }
+ *
+ *    // prepare the channel data (see e.g. gpdma_transfer_from_mci() in MCIFileSystem)
+ *    ...
+ *
+ *    // start the transfer
+ *    dma->transfer(&cfg, ctrl_word, 0, GPDMA_CONN_SDC, GPDMA_CONN_MEMORY);
+ *
+ *    // wait for transfer to complete (e.g. by handler() setting a flag)
+ *    ...
+ *
+ *    // return the channel now that it is no longer needed
+ *    dma->releaseChannel(ch);
+ * }
+ * @endcode
+ */
+class GPDMA {
+public:
+    enum DMAChannels {
+        DMACh0,   /* DMA channel 0 has the highest priority */
+        DMACh1,
+        DMACh2,
+        DMACh3,
+        DMACh4,
+        DMACh5,
+        DMACh6,
+        DMACh7,   /* DMA channel 7 has the lowest priority */
+        NumDMAChannels,
+        DMACh_Unavailable = NumDMAChannels,
+    };
+    enum FlowControl {
+        FlowControl_M2M_Ctrl_DMA,         /* Memory to memory - DMA control */
+        FlowControl_M2P_Ctrl_DMA,         /* Memory to peripheral - DMA control */
+        FlowControl_P2M_Ctrl_DMA,         /* Peripheral to memory - DMA control */
+        FlowControl_P2P_Ctrl_DMA,         /* Source peripheral to destination peripheral - DMA control */
+        FlowControl_P2P_Ctrl_DestPeriph,  /* Source peripheral to destination peripheral - destination peripheral control */
+        FlowControl_M2P_Ctrl_Periph,      /* Memory to peripheral - peripheral control */
+        FlowControl_P2M_Ctrl_Periph,      /* Peripheral to memory - peripheral control */
+        FlowControl_P2P_Ctrl_SrcPeriph,   /* Source peripheral to destination peripheral - source peripheral control */
+    };
+    typedef struct {
+        DMAChannels ChannelNum;
+        uint32_t    TransferSize;  /* Length/Size of transfer */
+        uint32_t    TransferWidth; /* Transfer width - used only for M2M */
+        uint32_t    SrcAddr;       /* Physical Source Address, only for M2M and M2P */
+        uint32_t    DstAddr;       /* Physical Destination Address, only for M2M and P2M */
+        FlowControl TransferType;
+    } GPDMA_Channel_CFG_T;
+
+    /** Get the only instance of the GPDMA
+     *
+     *  @returns The Registry
+     */
+    static GPDMA& instance()
+    {
+        static GPDMA singleton;
+        return singleton;
+    }
+
+    /** Initializes the GPDMA
+     *
+     *  Safe to call even with multiple DMA users
+     */
+    void init();
+
+    /** Shuts down the GPDMA
+     *
+     *  Call will be ignored if there are any acquired channels
+     */
+    void deinit();
+
+    /** Get a free GPDMA channel for one DMA connection
+     *
+     *  The function will start to look for the suggested channel.
+     *  If it is in use then the next, higher, channel number will
+     *  be tested. The default is set to use DMACh3 which has
+     *  medium priority.
+     *
+     *  To acquire a channel with the highest available priority
+     *  call this function with DMACh0 as parameter.
+     *
+     *  @param func       the interrupt callback function
+     *  @param suggested  the first channel to look for
+     *
+     *  @returns
+     *       DMACh0 to DMACh7 on success
+     *       DMACh_Unavailable if there are no channels available
+     */
+    DMAChannels acquireChannel(void (*irqfunc)(void), DMAChannels suggested = DMACh3);
+
+    /** Release a previously acquired channel
+     *
+     *  @param ch  the DMA channel to release
+     */
+    void releaseChannel(DMAChannels ch);
+
+    /** Returns the raw registers for the GPDMA channel for direct manipulation
+     *
+     *  @param ch    the DMA channel
+     *
+     *  @returns
+     *       The registers on success
+     *       NULL if the channel is invalid
+     */
+    LPC_GPDMACH_TypeDef* getDirectRegisters(DMAChannels ch);
+
+    // Internal use only. Called by the IRQ handler
+    void processInterrupt();
+
+    /** Does the actual DMA transfer
+     *
+     *  @param cfg           the DMA configuration
+     *  @param CtrlWord      data for the DMA channel's CONTROL register
+     *  @param LinkListItem  address to the linked list or 0 if not used
+     *  @param SrcPeripheral source of the transfer (GPDMA_CONN_MEMORY or GPDMA_CONN_SDC)
+     *  @param DstPeripheral destination of the transfer (GPDMA_CONN_MEMORY or GPDMA_CONN_SDC)
+     *
+     *  @returns
+     *       True on success, false on failure
+     */
+    bool transfer(GPDMA_Channel_CFG_T* cfg,
+                  uint32_t CtrlWord,
+                  uint32_t LinkListItem,
+                  uint8_t SrcPeripheral,
+                  uint8_t DstPeripheral);
+
+    void stopTransfer(DMAChannels ch);
+
+private:
+    typedef struct {
+        bool inUse;
+        void (*func)(void);
+    } channelData_t;
+
+    Mutex _mutex;
+    channelData_t _chData[NumDMAChannels];
+    int _usedChannels;
+    bool _initialized;
+
+    explicit GPDMA();
+    // hide copy constructor
+    GPDMA(const GPDMA&);
+    // hide assign operator
+    GPDMA& operator=(const GPDMA&);
+    ~GPDMA();
+};
+
+#endif
--- a/USBDevice.lib	Mon Mar 23 13:45:16 2015 +0000
+++ b/USBDevice.lib	Wed Apr 15 09:41:56 2015 +0200
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/USBDevice/#0ca6eeb54b97
+http://mbed.org/users/mbed_official/code/USBDevice/#0f216c4e75e5
--- a/mbed-rtos.lib	Mon Mar 23 13:45:16 2015 +0000
+++ b/mbed-rtos.lib	Wed Apr 15 09:41:56 2015 +0200
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed-rtos/#83e169389a69
+http://mbed.org/users/mbed_official/code/mbed-rtos/#d3d0e710b443
--- a/mbed-src.lib	Mon Mar 23 13:45:16 2015 +0000
+++ b/mbed-src.lib	Wed Apr 15 09:41:56 2015 +0200
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed-src/#5831be29b0ad
+http://mbed.org/users/mbed_official/code/mbed-src/#f0fe52f5109e