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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers <title>GPDMA.h Source File</title>

GPDMA.h

00001 /*
00002  *  Copyright 2015 Embedded Artists AB
00003  *
00004  *  Licensed under the Apache License, Version 2.0 (the "License");
00005  *  you may not use this file except in compliance with the License.
00006  *  You may obtain a copy of the License at
00007  *
00008  *    http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  *  Unless required by applicable law or agreed to in writing, software
00011  *  distributed under the License is distributed on an "AS IS" BASIS,
00012  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *  See the License for the specific language governing permissions and
00014  *  limitations under the License.
00015  */
00016 
00017 #ifndef GPDMA_H
00018 #define GPDMA_H
00019 
00020 #include "mbed.h"
00021 #include "rtos.h"
00022 
00023 /**
00024  * @brief GPDMA request connections
00025  */
00026 #define GPDMA_CONN_MEMORY           ((0UL))
00027 #define GPDMA_CONN_SDC              ((1UL))      /*!< SD card */
00028 
00029 /**
00030  * @brief Macro defines for DMA channel control registers
00031  */
00032 #define GPDMA_DMACCxControl_TransferSize(n) (((n & 0xFFF) << 0))  /*!< Transfer size*/
00033 #define GPDMA_DMACCxControl_SBSize(n)       (((n & 0x07) << 12))  /*!< Source burst size*/
00034 #define GPDMA_DMACCxControl_DBSize(n)       (((n & 0x07) << 15))  /*!< Destination burst size*/
00035 #define GPDMA_DMACCxControl_SWidth(n)       (((n & 0x07) << 18))  /*!< Source transfer width*/
00036 #define GPDMA_DMACCxControl_DWidth(n)       (((n & 0x07) << 21))  /*!< Destination transfer width*/
00037 #define GPDMA_DMACCxControl_SI              ((1UL << 26))      /*!< Source increment*/
00038 #define GPDMA_DMACCxControl_DI              ((1UL << 27))      /*!< Destination increment*/
00039 #define GPDMA_DMACCxControl_SrcTransUseAHBMaster1   0
00040 #define GPDMA_DMACCxControl_DestTransUseAHBMaster1  0
00041 #define GPDMA_DMACCxControl_Prot1           ((1UL << 28))      /*!< Indicates that the access is in user mode or privileged mode*/
00042 #define GPDMA_DMACCxControl_Prot2           ((1UL << 29))      /*!< Indicates that the access is bufferable or not bufferable*/
00043 #define GPDMA_DMACCxControl_Prot3           ((1UL << 30))      /*!< Indicates that the access is cacheable or not cacheable*/
00044 #define GPDMA_DMACCxControl_I               ((1UL << 31))      /*!< Terminal count interrupt enable bit */
00045 
00046 /**
00047  * @brief GPDMA Burst size in Source and Destination definitions
00048  */
00049 #define GPDMA_BSIZE_1   ((0UL))  /*!< Burst size = 1 */
00050 #define GPDMA_BSIZE_4   ((1UL))  /*!< Burst size = 4 */
00051 #define GPDMA_BSIZE_8   ((2UL))  /*!< Burst size = 8 */
00052 #define GPDMA_BSIZE_16  ((3UL))  /*!< Burst size = 16 */
00053 #define GPDMA_BSIZE_32  ((4UL))  /*!< Burst size = 32 */
00054 #define GPDMA_BSIZE_64  ((5UL))  /*!< Burst size = 64 */
00055 #define GPDMA_BSIZE_128 ((6UL))  /*!< Burst size = 128 */
00056 #define GPDMA_BSIZE_256 ((7UL))  /*!< Burst size = 256 */
00057 
00058 /**
00059  * @brief Width in Source transfer width and Destination transfer width definitions
00060  */
00061 #define GPDMA_WIDTH_BYTE        ((0UL))  /*!< Width = 1 byte */
00062 #define GPDMA_WIDTH_HALFWORD    ((1UL))  /*!< Width = 2 bytes */
00063 #define GPDMA_WIDTH_WORD        ((2UL))  /*!< Width = 4 bytes */
00064 
00065 /**
00066  * @brief Macro defines for DMA Configuration register
00067  */
00068 #define GPDMA_DMACConfig_E              ((0x01))  /*!< DMA Controller enable*/
00069 #define GPDMA_DMACConfig_M              ((0x02))  /*!< AHB Master endianness configuration*/
00070 #define GPDMA_DMACConfig_BITMASK        ((0x03))
00071 
00072 /**
00073  * @brief Macro defines for DMA Channel Configuration registers
00074  */
00075 #define GPDMA_DMACCxConfig_E                    ((1UL << 0))      /*!< DMA control enable*/
00076 #define GPDMA_DMACCxConfig_SrcPeripheral(n)     (((n & 0x1F) << 1))    /*!< Source peripheral*/
00077 #define GPDMA_DMACCxConfig_DestPeripheral(n)    (((n & 0x1F) << 6))    /*!< Destination peripheral*/
00078 #define GPDMA_DMACCxConfig_TransferType(n)      (((n & 0x7) << 11))    /*!< This value indicates the type of transfer*/
00079 #define GPDMA_DMACCxConfig_IE                   ((1UL << 14))      /*!< Interrupt error mask*/
00080 #define GPDMA_DMACCxConfig_ITC                  ((1UL << 15))      /*!< Terminal count interrupt mask*/
00081 #define GPDMA_DMACCxConfig_L                    ((1UL << 16))      /*!< Lock*/
00082 #define GPDMA_DMACCxConfig_A                    ((1UL << 17))      /*!< Active*/
00083 #define GPDMA_DMACCxConfig_H                    ((1UL << 18))      /*!< Halt*/
00084 
00085 /**
00086  * @brief GPDMA Linker List Item structure type definition
00087  */
00088 typedef struct {
00089     uint32_t SrcAddr;    /**< Source Address */
00090     uint32_t DstAddr;    /**< Destination address */
00091     uint32_t NextLLI;    /**< Next LLI address, otherwise set to '0' */
00092     uint32_t Control;    /**< GPDMA Control of this LLI */
00093 } GPDMA_LLI_Type;
00094 
00095 /**
00096  * Wrapper for the General Purpose DMA controller.
00097  *
00098  * The GPDMA class allows multiple users of DMA to claim one or more
00099  * of the eight available DMA channels and to register handlers for the
00100  * interrupts. This centralized control is needed as there are eight
00101  * channels but only one DMA IRQ.
00102  *
00103  * By having to request a channel to use it is possible to avoid having
00104  * hardcoded DMA channel number in the code
00105  *
00106  * An example of use:
00107  *
00108  * @code
00109  * void handler() {
00110  *   _eventSuccess = LPC_GPDMA->IntTCStat & (1<<ch);
00111  *   LPC_GPDMA->IntTCClear = (1<<ch);
00112  * }
00113  *
00114  * void foo() {
00115  *    GPDMA* dma = &GPDMA::instance();
00116  *    dma->init();
00117  *
00118  *    DMAChannels ch = dma->acquireChannel(handler)
00119  *    if (ch == DMACh_Unavailable) {
00120  *      // handle error
00121  *    }
00122  *
00123  *    // prepare the channel data (see e.g. gpdma_transfer_from_mci() in MCIFileSystem)
00124  *    ...
00125  *
00126  *    // start the transfer
00127  *    dma->transfer(&cfg, ctrl_word, 0, GPDMA_CONN_SDC, GPDMA_CONN_MEMORY);
00128  *
00129  *    // wait for transfer to complete (e.g. by handler() setting a flag)
00130  *    ...
00131  *
00132  *    // return the channel now that it is no longer needed
00133  *    dma->releaseChannel(ch);
00134  * }
00135  * @endcode
00136  */
00137 class GPDMA {
00138 public:
00139     enum DMAChannels {
00140         DMACh0,   /* DMA channel 0 has the highest priority */
00141         DMACh1,
00142         DMACh2,
00143         DMACh3,
00144         DMACh4,
00145         DMACh5,
00146         DMACh6,
00147         DMACh7,   /* DMA channel 7 has the lowest priority */
00148         NumDMAChannels,
00149         DMACh_Unavailable = NumDMAChannels,
00150     };
00151     enum FlowControl {
00152         FlowControl_M2M_Ctrl_DMA,         /* Memory to memory - DMA control */
00153         FlowControl_M2P_Ctrl_DMA,         /* Memory to peripheral - DMA control */
00154         FlowControl_P2M_Ctrl_DMA,         /* Peripheral to memory - DMA control */
00155         FlowControl_P2P_Ctrl_DMA,         /* Source peripheral to destination peripheral - DMA control */
00156         FlowControl_P2P_Ctrl_DestPeriph,  /* Source peripheral to destination peripheral - destination peripheral control */
00157         FlowControl_M2P_Ctrl_Periph,      /* Memory to peripheral - peripheral control */
00158         FlowControl_P2M_Ctrl_Periph,      /* Peripheral to memory - peripheral control */
00159         FlowControl_P2P_Ctrl_SrcPeriph,   /* Source peripheral to destination peripheral - source peripheral control */
00160     };
00161     typedef struct {
00162         DMAChannels ChannelNum;
00163         uint32_t    TransferSize;  /* Length/Size of transfer */
00164         uint32_t    TransferWidth; /* Transfer width - used only for M2M */
00165         uint32_t    SrcAddr;       /* Physical Source Address, only for M2M and M2P */
00166         uint32_t    DstAddr;       /* Physical Destination Address, only for M2M and P2M */
00167         FlowControl TransferType;
00168     } GPDMA_Channel_CFG_T;
00169 
00170     /** Get the only instance of the GPDMA
00171      *
00172      *  @returns The Registry
00173      */
00174     static GPDMA& instance()
00175     {
00176         static GPDMA singleton;
00177         return singleton;
00178     }
00179 
00180     /** Initializes the GPDMA
00181      *
00182      *  Safe to call even with multiple DMA users
00183      */
00184     void init();
00185 
00186     /** Shuts down the GPDMA
00187      *
00188      *  Call will be ignored if there are any acquired channels
00189      */
00190     void deinit();
00191 
00192     /** Get a free GPDMA channel for one DMA connection
00193      *
00194      *  The function will start to look for the suggested channel.
00195      *  If it is in use then the next, higher, channel number will
00196      *  be tested. The default is set to use DMACh3 which has
00197      *  medium priority.
00198      *
00199      *  To acquire a channel with the highest available priority
00200      *  call this function with DMACh0 as parameter.
00201      *
00202      *  @param func       the interrupt callback function
00203      *  @param suggested  the first channel to look for
00204      *
00205      *  @returns
00206      *       DMACh0 to DMACh7 on success
00207      *       DMACh_Unavailable if there are no channels available
00208      */
00209     DMAChannels acquireChannel(void (*irqfunc)(void), DMAChannels suggested = DMACh3);
00210 
00211     /** Release a previously acquired channel
00212      *
00213      *  @param ch  the DMA channel to release
00214      */
00215     void releaseChannel(DMAChannels ch);
00216 
00217     /** Returns the raw registers for the GPDMA channel for direct manipulation
00218      *
00219      *  @param ch    the DMA channel
00220      *
00221      *  @returns
00222      *       The registers on success
00223      *       NULL if the channel is invalid
00224      */
00225     LPC_GPDMACH_TypeDef* getDirectRegisters(DMAChannels ch);
00226 
00227     // Internal use only. Called by the IRQ handler
00228     void processInterrupt();
00229 
00230     /** Does the actual DMA transfer
00231      *
00232      *  @param cfg           the DMA configuration
00233      *  @param CtrlWord      data for the DMA channel's CONTROL register
00234      *  @param LinkListItem  address to the linked list or 0 if not used
00235      *  @param SrcPeripheral source of the transfer (GPDMA_CONN_MEMORY or GPDMA_CONN_SDC)
00236      *  @param DstPeripheral destination of the transfer (GPDMA_CONN_MEMORY or GPDMA_CONN_SDC)
00237      *
00238      *  @returns
00239      *       True on success, false on failure
00240      */
00241     bool transfer(GPDMA_Channel_CFG_T* cfg,
00242                   uint32_t CtrlWord,
00243                   uint32_t LinkListItem,
00244                   uint8_t SrcPeripheral,
00245                   uint8_t DstPeripheral);
00246 
00247     void stopTransfer(DMAChannels ch);
00248 
00249 private:
00250     typedef struct {
00251         bool inUse;
00252         void (*func)(void);
00253     } channelData_t;
00254 
00255     Mutex _mutex;
00256     channelData_t _chData[NumDMAChannels];
00257     int _usedChannels;
00258     bool _initialized;
00259 
00260     explicit GPDMA();
00261     // hide copy constructor
00262     GPDMA(const GPDMA&);
00263     // hide assign operator
00264     GPDMA& operator=(const GPDMA&);
00265     ~GPDMA();
00266 };
00267 
00268 #endif