The wait in mci_WaitForEvent will delay all card transactions.

Dependencies:   FATFileSystem

Fork of EALib by EmbeddedArtists AB

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers gpdma.cpp Source File

gpdma.cpp

00001 
00002 /******************************************************************************
00003  * Includes
00004  *****************************************************************************/
00005 
00006 #include "gpdma.h"
00007 
00008 /******************************************************************************
00009  * Defines and typedefs
00010  *****************************************************************************/
00011 
00012 #define NUM_GPDMA_CHANNELS  8
00013 
00014 #define GPDMACH(__x) ((LPC_GPDMACH_TypeDef*)(LPC_GPDMACH0_BASE + (0x20 * (__x))))
00015 
00016 #define CH_MASK(__ch)  (((1UL << (__ch)) & 0xFF))
00017 
00018 /**
00019  * @brief GPDMA request connections
00020  */
00021 #define GPDMA_CONN_MEMORY           ((0UL))
00022 #define GPDMA_CONN_SDC              ((1UL))      /*!< SD card */
00023 
00024 /**
00025  * @brief Macro defines for DMA channel control registers
00026  */
00027 #define GPDMA_DMACCxControl_TransferSize(n) (((n & 0xFFF) << 0))  /*!< Transfer size*/
00028 #define GPDMA_DMACCxControl_SBSize(n)       (((n & 0x07) << 12))  /*!< Source burst size*/
00029 #define GPDMA_DMACCxControl_DBSize(n)       (((n & 0x07) << 15))  /*!< Destination burst size*/
00030 #define GPDMA_DMACCxControl_SWidth(n)       (((n & 0x07) << 18))  /*!< Source transfer width*/
00031 #define GPDMA_DMACCxControl_DWidth(n)       (((n & 0x07) << 21))  /*!< Destination transfer width*/
00032 #define GPDMA_DMACCxControl_SI              ((1UL << 26))      /*!< Source increment*/
00033 #define GPDMA_DMACCxControl_DI              ((1UL << 27))      /*!< Destination increment*/
00034 #define GPDMA_DMACCxControl_SrcTransUseAHBMaster1   0
00035 #define GPDMA_DMACCxControl_DestTransUseAHBMaster1  0
00036 #define GPDMA_DMACCxControl_Prot1           ((1UL << 28))      /*!< Indicates that the access is in user mode or privileged mode*/
00037 #define GPDMA_DMACCxControl_Prot2           ((1UL << 29))      /*!< Indicates that the access is bufferable or not bufferable*/
00038 #define GPDMA_DMACCxControl_Prot3           ((1UL << 30))      /*!< Indicates that the access is cacheable or not cacheable*/
00039 #define GPDMA_DMACCxControl_I               ((1UL << 31))      /*!< Terminal count interrupt enable bit */
00040 
00041 /**
00042  * @brief GPDMA Burst size in Source and Destination definitions
00043  */
00044 #define GPDMA_BSIZE_1   ((0UL))  /*!< Burst size = 1 */
00045 #define GPDMA_BSIZE_4   ((1UL))  /*!< Burst size = 4 */
00046 #define GPDMA_BSIZE_8   ((2UL))  /*!< Burst size = 8 */
00047 #define GPDMA_BSIZE_16  ((3UL))  /*!< Burst size = 16 */
00048 #define GPDMA_BSIZE_32  ((4UL))  /*!< Burst size = 32 */
00049 #define GPDMA_BSIZE_64  ((5UL))  /*!< Burst size = 64 */
00050 #define GPDMA_BSIZE_128 ((6UL))  /*!< Burst size = 128 */
00051 #define GPDMA_BSIZE_256 ((7UL))  /*!< Burst size = 256 */
00052 
00053 /**
00054  * @brief Width in Source transfer width and Destination transfer width definitions
00055  */
00056 #define GPDMA_WIDTH_BYTE        ((0UL))  /*!< Width = 1 byte */
00057 #define GPDMA_WIDTH_HALFWORD    ((1UL))  /*!< Width = 2 bytes */
00058 #define GPDMA_WIDTH_WORD        ((2UL))  /*!< Width = 4 bytes */
00059 
00060 /**
00061  * @brief Macro defines for DMA Configuration register
00062  */
00063 #define GPDMA_DMACConfig_E              ((0x01))  /*!< DMA Controller enable*/
00064 #define GPDMA_DMACConfig_M              ((0x02))  /*!< AHB Master endianness configuration*/
00065 #define GPDMA_DMACConfig_BITMASK        ((0x03))
00066 
00067 /**
00068  * @brief Macro defines for DMA Channel Configuration registers
00069  */
00070 #define GPDMA_DMACCxConfig_E                    ((1UL << 0))      /*!< DMA control enable*/
00071 #define GPDMA_DMACCxConfig_SrcPeripheral(n)     (((n & 0x1F) << 1))    /*!< Source peripheral*/
00072 #define GPDMA_DMACCxConfig_DestPeripheral(n)    (((n & 0x1F) << 6))    /*!< Destination peripheral*/
00073 #define GPDMA_DMACCxConfig_TransferType(n)      (((n & 0x7) << 11))    /*!< This value indicates the type of transfer*/
00074 #define GPDMA_DMACCxConfig_IE                   ((1UL << 14))      /*!< Interrupt error mask*/
00075 #define GPDMA_DMACCxConfig_ITC                  ((1UL << 15))      /*!< Terminal count interrupt mask*/
00076 #define GPDMA_DMACCxConfig_L                    ((1UL << 16))      /*!< Lock*/
00077 #define GPDMA_DMACCxConfig_A                    ((1UL << 17))      /*!< Active*/
00078 #define GPDMA_DMACCxConfig_H                    ((1UL << 18))      /*!< Halt*/
00079 
00080 /**
00081  * @brief GPDMA structure using for DMA configuration
00082  */
00083 typedef struct {
00084   uint32_t ChannelNum;  /*!< DMA channel number, should be in
00085                *  range from 0 to 7.
00086                *  Note: DMA channel 0 has the highest priority
00087                *  and DMA channel 7 the lowest priority.
00088                */
00089   uint32_t TransferSize;  /*!< Length/Size of transfer */
00090   uint32_t TransferWidth;  /*!< Transfer width - used for TransferType is GPDMA_TRANSFERTYPE_M2M only */
00091   uint32_t SrcAddr;    /*!< Physical Source Address, used in case TransferType is chosen as
00092                *   GPDMA_TRANSFERTYPE_M2M or GPDMA_TRANSFERTYPE_M2P */
00093   uint32_t DstAddr;    /*!< Physical Destination Address, used in case TransferType is chosen as
00094                *   GPDMA_TRANSFERTYPE_M2M or GPDMA_TRANSFERTYPE_P2M */
00095   uint32_t TransferType;  /*!< Transfer Type, should be one of the following:
00096                * - GPDMA_TRANSFERTYPE_M2M: Memory to memory - DMA control
00097                * - GPDMA_TRANSFERTYPE_M2P: Memory to peripheral - DMA control
00098                * - GPDMA_TRANSFERTYPE_P2M: Peripheral to memory - DMA control
00099                * - GPDMA_TRANSFERTYPE_P2P: Source peripheral to destination peripheral - DMA control
00100                */
00101 } GPDMA_Channel_CFG_T;
00102 
00103 /******************************************************************************
00104  * External global variables
00105  *****************************************************************************/
00106 
00107 /******************************************************************************
00108  * Local variables
00109  *****************************************************************************/
00110 
00111 static bool used_channels[NUM_GPDMA_CHANNELS];
00112 
00113 /******************************************************************************
00114  * Local Functions
00115  *****************************************************************************/
00116 
00117 static void gpdma_transfer(GPDMA_Channel_CFG_T* cfg,
00118                            uint32_t CtrlWord,
00119                            uint32_t LinkListItem,
00120                            uint8_t SrcPeripheral,
00121                            uint8_t DstPeripheral)
00122 {
00123   /* Get Channel pointer */
00124   LPC_GPDMACH_TypeDef* pCh = GPDMACH(cfg->ChannelNum);
00125 
00126   /* Reset the Interrupt status */
00127   LPC_GPDMA->IntTCClear = CH_MASK(cfg->ChannelNum);
00128   LPC_GPDMA->IntErrClr = CH_MASK(cfg->ChannelNum);
00129 
00130   /* Assign Linker List Item value */
00131   pCh->CLLI = LinkListItem;
00132 
00133   /* Enable DMA channels, little endian */
00134   LPC_GPDMA->Config = GPDMA_DMACConfig_E;
00135   while (!(LPC_GPDMA->Config & GPDMA_DMACConfig_E)) {}
00136 
00137   pCh->CSrcAddr = cfg->SrcAddr;
00138   pCh->CDestAddr = cfg->DstAddr;
00139 
00140   /* Configure DMA Channel, enable Error Counter and Terminate counter */
00141   pCh->CConfig = GPDMA_DMACCxConfig_IE
00142            | GPDMA_DMACCxConfig_ITC
00143            | GPDMA_DMACCxConfig_TransferType((uint32_t) cfg->TransferType)
00144            | GPDMA_DMACCxConfig_SrcPeripheral(SrcPeripheral)
00145            | GPDMA_DMACCxConfig_DestPeripheral(DstPeripheral);
00146 
00147   pCh->CControl = CtrlWord;
00148 
00149   /* Start the Channel */
00150   pCh->CConfig |= GPDMA_DMACCxConfig_E;
00151 }
00152 
00153 /******************************************************************************
00154  * Public Functions
00155  *****************************************************************************/
00156 
00157 void gpdma_init()
00158 {
00159   uint8_t i;
00160 
00161   /* Enable GPDMA master clock */
00162   LPC_SC->PCONP |= (1<<29);
00163 
00164   /* Reset all channel configuration register */
00165   for (i = 0; i < NUM_GPDMA_CHANNELS; i++) {
00166     GPDMACH(i)->CConfig = 0;
00167   }
00168 
00169   /* Clear all DMA interrupt and error flag */
00170   LPC_GPDMA->IntTCClear = 0xFF;
00171   LPC_GPDMA->IntErrClr  = 0xFF;
00172 
00173   /* Reset all channels are free */
00174   for (int i = 0; i < NUM_GPDMA_CHANNELS; i++)
00175   {
00176     used_channels[i] = false;
00177   }
00178 }
00179 
00180 void gpdma_deinit()
00181 {
00182   /* Disable GPDMA master clock */
00183   LPC_SC->PCONP &= ~(1<<29);
00184 }
00185 
00186 void gpdma_stop(uint8_t ChannelNum)
00187 {
00188   if (ChannelNum >= NUM_GPDMA_CHANNELS) {
00189     return;
00190   }
00191 
00192   /* Disable channel */
00193   GPDMACH(ChannelNum)->CConfig &= ~GPDMA_DMACCxConfig_E;
00194 
00195   /* check terminal count interrupt request status for DMA */
00196   if (LPC_GPDMA->IntTCStat & CH_MASK(ChannelNum)) {
00197     /* Clear terminate counter Interrupt pending */
00198     LPC_GPDMA->IntTCClear = CH_MASK(ChannelNum);
00199   }
00200 
00201   /* check status of the error interrupt for DMA channels */
00202   if (LPC_GPDMA->IntErrStat & CH_MASK(ChannelNum)) {
00203     /* clear the error interrupt request */
00204     LPC_GPDMA->IntErrClr = CH_MASK(ChannelNum);
00205   }
00206 
00207   used_channels[ChannelNum] = false;
00208 }
00209 
00210 bool gpdma_interrupt(uint8_t ChannelNum)
00211 {
00212   /* check status of DMA channel interrupts */
00213   if (LPC_GPDMA->IntStat & CH_MASK(ChannelNum)) {
00214     /* Check counter terminal status */
00215     if (LPC_GPDMA->IntTCStat & CH_MASK(ChannelNum)) {
00216       /* Clear terminate counter Interrupt pending */
00217       LPC_GPDMA->IntTCClear = CH_MASK(ChannelNum);
00218       return true;
00219     }
00220     /* Check error terminal status */
00221     if (LPC_GPDMA->IntErrStat & CH_MASK(ChannelNum)) {
00222       /* Clear error counter Interrupt pending */
00223       LPC_GPDMA->IntErrClr = CH_MASK(ChannelNum);
00224       return false;
00225     }
00226   }
00227   return false;
00228 }
00229 
00230 bool gpdma_getFreeChannel(uint8_t* pCh)
00231 {
00232   for (int i = 0; i < NUM_GPDMA_CHANNELS; i++)
00233   {
00234     if ((!used_channels[i]) && ((LPC_GPDMA->EnbldChns & CH_MASK(i)) == 0))
00235     {
00236       used_channels[i] = true;
00237       *pCh = i;
00238       return true;
00239     }
00240   }
00241   return false;
00242 }
00243 
00244 bool gpdma_transfer_to_mci(uint8_t ChannelNum,
00245                            uint32_t src,
00246                            uint32_t Size)
00247 {
00248   GPDMA_Channel_CFG_T cfg;
00249   cfg.ChannelNum = ChannelNum;
00250   cfg.TransferType = GPDMA_TRANSFERTYPE_M2P_CONTROLLER_PERIPHERAL;
00251   cfg.TransferSize = Size;
00252   cfg.TransferWidth = 0;
00253   cfg.SrcAddr = src;
00254   cfg.DstAddr = (uint32_t) (&LPC_MCI->FIFO);
00255 
00256   uint32_t ctrl_word =
00257       GPDMA_DMACCxControl_TransferSize((uint32_t) cfg.TransferSize)
00258           | GPDMA_DMACCxControl_SBSize(GPDMA_BSIZE_8)
00259           | GPDMA_DMACCxControl_DBSize(GPDMA_BSIZE_8)
00260           | GPDMA_DMACCxControl_SWidth(GPDMA_WIDTH_WORD)
00261           | GPDMA_DMACCxControl_DWidth(GPDMA_WIDTH_WORD)
00262           | GPDMA_DMACCxControl_DestTransUseAHBMaster1
00263           | GPDMA_DMACCxControl_SI
00264           | GPDMA_DMACCxControl_I;
00265 
00266   if (LPC_GPDMA->EnbldChns & CH_MASK(ChannelNum)) {
00267     /* This channel is enabled, return ERROR, need to release this channel first */
00268     return false;
00269   }
00270 
00271   /* Select SD card interface in the DMA MUX*/
00272   LPC_SC->DMAREQSEL &= ~(1 << 1);
00273 
00274   gpdma_transfer(&cfg, ctrl_word, 0, GPDMA_CONN_MEMORY, GPDMA_CONN_SDC);
00275   return true;
00276 }
00277 
00278 bool gpdma_transfer_from_mci(uint8_t ChannelNum,
00279                              uint32_t dst,
00280                              uint32_t Size)
00281 {
00282   GPDMA_Channel_CFG_T cfg;
00283   cfg.ChannelNum = ChannelNum;
00284   cfg.TransferType = GPDMA_TRANSFERTYPE_P2M_CONTROLLER_PERIPHERAL;
00285   cfg.TransferSize = Size;
00286   cfg.TransferWidth = 0;
00287   cfg.SrcAddr = (uint32_t) (&LPC_MCI->FIFO);
00288   cfg.DstAddr = dst;
00289 
00290   uint32_t ctrl_word =
00291       GPDMA_DMACCxControl_TransferSize((uint32_t) cfg.TransferSize)
00292           | GPDMA_DMACCxControl_SBSize(GPDMA_BSIZE_8)
00293           | GPDMA_DMACCxControl_DBSize(GPDMA_BSIZE_8)
00294           | GPDMA_DMACCxControl_SWidth(GPDMA_WIDTH_WORD)
00295           | GPDMA_DMACCxControl_DWidth(GPDMA_WIDTH_WORD)
00296           | GPDMA_DMACCxControl_SrcTransUseAHBMaster1
00297           | GPDMA_DMACCxControl_DI
00298           | GPDMA_DMACCxControl_I;
00299 
00300   if (LPC_GPDMA->EnbldChns & CH_MASK(ChannelNum)) {
00301     /* This channel is enabled, return ERROR, need to release this channel first */
00302     return false;
00303   }
00304 
00305   /* Select SD card interface in the DMA MUX*/
00306   LPC_SC->DMAREQSEL &= ~(1 << 1);
00307 
00308   gpdma_transfer(&cfg, ctrl_word, 0, GPDMA_CONN_SDC, GPDMA_CONN_MEMORY);
00309   return true;
00310 }
00311 
00312