
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
Revision 38:420cdc281467, committed 2015-04-15
- 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
--- 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