Memory to Memory DMA demo from CMSIS example. This demo execute 1000 times of 32 word memory to memory DMA (copy), and also measures number of dummy loop execution during DMA cylcles. Line 56 of "DMA_M2M.c" can change DMA source. where; 1)static : source is SRAM 2)const : source is Flash ROM

Dependencies:   mbed

CMSIS_Lib/lpc17xx_gpdma.c

Committer:
todotani
Date:
2010-11-14
Revision:
0:692bf16d1455

File content as of revision 0:692bf16d1455:

/***********************************************************************//**
 * @file        lpc17xx_gpdma.c
 * @brief        Contains all functions support for GPDMA firmware library on LPC17xx
 * @version        2.0
 * @date        21. May. 2010
 * @author        NXP MCU SW Application Team
 **************************************************************************
 * Software that is described herein is for illustrative purposes only
 * which provides customers with programming information regarding the
 * products. This software is supplied "AS IS" without any warranties.
 * NXP Semiconductors assumes no responsibility or liability for the
 * use of the software, conveys no license or title under any patent,
 * copyright, or mask work right to the product. NXP Semiconductors
 * reserves the right to make changes in the software without
 * notification. NXP Semiconductors also make no representation or
 * warranty that such application will be suitable for the specified
 * use without further testing or modification.
 **********************************************************************/

/* Peripheral group ----------------------------------------------------------- */
/** @addtogroup GPDMA
 * @{
 */

/* Includes ------------------------------------------------------------------- */
#include "lpc17xx_gpdma.h"
#include "lpc17xx_clkpwr.h"

/* If this source file built with example, the LPC17xx FW library configuration
 * file in each example directory ("lpc17xx_libcfg.h") must be included,
 * otherwise the default FW library configuration file must be included instead
 */
#include "lpc17xx_libcfg.h"

#ifdef _GPDMA


/* Private Variables ---------------------------------------------------------- */
/** @defgroup GPDMA_Private_Variables GPDMA Private Variables
 * @{
 */

/**
 * @brief Lookup Table of Connection Type matched with
 * Peripheral Data (FIFO) register base address
 */
#ifdef __IAR_SYSTEMS_ICC__
volatile const void *GPDMA_LUTPerAddr[] = {
        (&LPC_SSP0->DR),                // SSP0 Tx
        (&LPC_SSP0->DR),                // SSP0 Rx
        (&LPC_SSP1->DR),                // SSP1 Tx
        (&LPC_SSP1->DR),                // SSP1 Rx
        (&LPC_ADC->ADGDR),            // ADC
        (&LPC_I2S->I2STXFIFO),         // I2S Tx
        (&LPC_I2S->I2SRXFIFO),         // I2S Rx
        (&LPC_DAC->DACR),                // DAC
        (&LPC_UART0->/*RBTHDLR.*/THR),    // UART0 Tx
        (&LPC_UART0->/*RBTHDLR.*/RBR),    // UART0 Rx
        (&LPC_UART1->/*RBTHDLR.*/THR),    // UART1 Tx
        (&LPC_UART1->/*RBTHDLR.*/RBR),    // UART1 Rx
        (&LPC_UART2->/*RBTHDLR.*/THR),    // UART2 Tx
        (&LPC_UART2->/*RBTHDLR.*/RBR),    // UART2 Rx
        (&LPC_UART3->/*RBTHDLR.*/THR),    // UART3 Tx
        (&LPC_UART3->/*RBTHDLR.*/RBR),    // UART3 Rx
        (&LPC_TIM0->MR0),                // MAT0.0
        (&LPC_TIM0->MR1),                // MAT0.1
        (&LPC_TIM1->MR0),                // MAT1.0
        (&LPC_TIM1->MR1),                // MAT1.1
        (&LPC_TIM2->MR0),                // MAT2.0
        (&LPC_TIM2->MR1),                // MAT2.1
        (&LPC_TIM3->MR0),                // MAT3.0
        (&LPC_TIM3->MR1),                // MAT3.1
};
#else
const uint32_t GPDMA_LUTPerAddr[] = {
        ((uint32_t)&LPC_SSP0->DR),                // SSP0 Tx
        ((uint32_t)&LPC_SSP0->DR),                // SSP0 Rx
        ((uint32_t)&LPC_SSP1->DR),                // SSP1 Tx
        ((uint32_t)&LPC_SSP1->DR),                // SSP1 Rx
        ((uint32_t)&LPC_ADC->ADGDR),            // ADC
        ((uint32_t)&LPC_I2S->I2STXFIFO),         // I2S Tx
        ((uint32_t)&LPC_I2S->I2SRXFIFO),         // I2S Rx
        ((uint32_t)&LPC_DAC->DACR),                // DAC
        ((uint32_t)&LPC_UART0->/*RBTHDLR.*/THR),    // UART0 Tx
        ((uint32_t)&LPC_UART0->/*RBTHDLR.*/RBR),    // UART0 Rx
        ((uint32_t)&LPC_UART1->/*RBTHDLR.*/THR),    // UART1 Tx
        ((uint32_t)&LPC_UART1->/*RBTHDLR.*/RBR),    // UART1 Rx
        ((uint32_t)&LPC_UART2->/*RBTHDLR.*/THR),    // UART2 Tx
        ((uint32_t)&LPC_UART2->/*RBTHDLR.*/RBR),    // UART2 Rx
        ((uint32_t)&LPC_UART3->/*RBTHDLR.*/THR),    // UART3 Tx
        ((uint32_t)&LPC_UART3->/*RBTHDLR.*/RBR),    // UART3 Rx
        ((uint32_t)&LPC_TIM0->MR0),                // MAT0.0
        ((uint32_t)&LPC_TIM0->MR1),                // MAT0.1
        ((uint32_t)&LPC_TIM1->MR0),                // MAT1.0
        ((uint32_t)&LPC_TIM1->MR1),                // MAT1.1
        ((uint32_t)&LPC_TIM2->MR0),                // MAT2.0
        ((uint32_t)&LPC_TIM2->MR1),                // MAT2.1
        ((uint32_t)&LPC_TIM3->MR0),                // MAT3.0
        ((uint32_t)&LPC_TIM3->MR1),                // MAT3.1
};
#endif
/**
 * @brief Lookup Table of GPDMA Channel Number matched with
 * GPDMA channel pointer
 */
const LPC_GPDMACH_TypeDef *pGPDMACh[8] = {
        LPC_GPDMACH0,    // GPDMA Channel 0
        LPC_GPDMACH1,    // GPDMA Channel 1
        LPC_GPDMACH2,    // GPDMA Channel 2
        LPC_GPDMACH3,    // GPDMA Channel 3
        LPC_GPDMACH4,    // GPDMA Channel 4
        LPC_GPDMACH5,    // GPDMA Channel 5
        LPC_GPDMACH6,    // GPDMA Channel 6
        LPC_GPDMACH7,    // GPDMA Channel 7
};
/**
 * @brief Optimized Peripheral Source and Destination burst size
 */
const uint8_t GPDMA_LUTPerBurst[] = {
        GPDMA_BSIZE_4,                // SSP0 Tx
        GPDMA_BSIZE_4,                // SSP0 Rx
        GPDMA_BSIZE_4,                // SSP1 Tx
        GPDMA_BSIZE_4,                // SSP1 Rx
        GPDMA_BSIZE_4,                // ADC
        GPDMA_BSIZE_32,             // I2S channel 0
        GPDMA_BSIZE_32,             // I2S channel 1
        GPDMA_BSIZE_1,                // DAC
        GPDMA_BSIZE_1,                // UART0 Tx
        GPDMA_BSIZE_1,                // UART0 Rx
        GPDMA_BSIZE_1,                // UART1 Tx
        GPDMA_BSIZE_1,                // UART1 Rx
        GPDMA_BSIZE_1,                // UART2 Tx
        GPDMA_BSIZE_1,                // UART2 Rx
        GPDMA_BSIZE_1,                // UART3 Tx
        GPDMA_BSIZE_1,                // UART3 Rx
        GPDMA_BSIZE_1,                // MAT0.0
        GPDMA_BSIZE_1,                // MAT0.1
        GPDMA_BSIZE_1,                // MAT1.0
        GPDMA_BSIZE_1,                // MAT1.1
        GPDMA_BSIZE_1,                // MAT2.0
        GPDMA_BSIZE_1,                // MAT2.1
        GPDMA_BSIZE_1,                // MAT3.0
        GPDMA_BSIZE_1,                // MAT3.1
};
/**
 * @brief Optimized Peripheral Source and Destination transfer width
 */
const uint8_t GPDMA_LUTPerWid[] = {
        GPDMA_WIDTH_BYTE,                // SSP0 Tx
        GPDMA_WIDTH_BYTE,                // SSP0 Rx
        GPDMA_WIDTH_BYTE,                // SSP1 Tx
        GPDMA_WIDTH_BYTE,                // SSP1 Rx
        GPDMA_WIDTH_WORD,                // ADC
        GPDMA_WIDTH_WORD,                 // I2S channel 0
        GPDMA_WIDTH_WORD,                 // I2S channel 1
        GPDMA_WIDTH_BYTE,                // DAC
        GPDMA_WIDTH_BYTE,                // UART0 Tx
        GPDMA_WIDTH_BYTE,                // UART0 Rx
        GPDMA_WIDTH_BYTE,                // UART1 Tx
        GPDMA_WIDTH_BYTE,                // UART1 Rx
        GPDMA_WIDTH_BYTE,                // UART2 Tx
        GPDMA_WIDTH_BYTE,                // UART2 Rx
        GPDMA_WIDTH_BYTE,                // UART3 Tx
        GPDMA_WIDTH_BYTE,                // UART3 Rx
        GPDMA_WIDTH_WORD,                // MAT0.0
        GPDMA_WIDTH_WORD,                // MAT0.1
        GPDMA_WIDTH_WORD,                // MAT1.0
        GPDMA_WIDTH_WORD,                // MAT1.1
        GPDMA_WIDTH_WORD,                // MAT2.0
        GPDMA_WIDTH_WORD,                // MAT2.1
        GPDMA_WIDTH_WORD,                // MAT3.0
        GPDMA_WIDTH_WORD,                // MAT3.1
};

/**
 * @}
 */

/* Public Functions ----------------------------------------------------------- */
/** @addtogroup GPDMA_Public_Functions
 * @{
 */

/********************************************************************//**
 * @brief         Initialize GPDMA controller
 * @param         None
 * @return         None
 *********************************************************************/
void GPDMA_Init(void)
{
    /* Enable GPDMA clock */
    CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCGPDMA, ENABLE);

    // Reset all channel configuration register
    LPC_GPDMACH0->DMACCConfig = 0;
    LPC_GPDMACH1->DMACCConfig = 0;
    LPC_GPDMACH2->DMACCConfig = 0;
    LPC_GPDMACH3->DMACCConfig = 0;
    LPC_GPDMACH4->DMACCConfig = 0;
    LPC_GPDMACH5->DMACCConfig = 0;
    LPC_GPDMACH6->DMACCConfig = 0;
    LPC_GPDMACH7->DMACCConfig = 0;

    /* Clear all DMA interrupt and error flag */
    LPC_GPDMA->DMACIntTCClear = 0xFF;
    LPC_GPDMA->DMACIntErrClr = 0xFF;
}

/********************************************************************//**
 * @brief         Setup GPDMA channel peripheral according to the specified
 *               parameters in the GPDMAChannelConfig.
 * @param[in]    GPDMAChannelConfig Pointer to a GPDMA_CH_CFG_Type
 *                                     structure that contains the configuration
 *                                     information for the specified GPDMA channel peripheral.
 * @return        ERROR if selected channel is enabled before
 *                 or SUCCESS if channel is configured successfully
 *********************************************************************/
Status GPDMA_Setup(GPDMA_Channel_CFG_Type *GPDMAChannelConfig)
{
    LPC_GPDMACH_TypeDef *pDMAch;
    uint32_t tmp1, tmp2;

    if (LPC_GPDMA->DMACEnbldChns & (GPDMA_DMACEnbldChns_Ch(GPDMAChannelConfig->ChannelNum))) {
        // This channel is enabled, return ERROR, need to release this channel first
        return ERROR;
    }

    // Get Channel pointer
    pDMAch = (LPC_GPDMACH_TypeDef *) pGPDMACh[GPDMAChannelConfig->ChannelNum];

    // Reset the Interrupt status
    LPC_GPDMA->DMACIntTCClear = GPDMA_DMACIntTCClear_Ch(GPDMAChannelConfig->ChannelNum);
    LPC_GPDMA->DMACIntErrClr = GPDMA_DMACIntErrClr_Ch(GPDMAChannelConfig->ChannelNum);

    // Clear DMA configure
    pDMAch->DMACCControl = 0x00;
    pDMAch->DMACCConfig = 0x00;

    /* Assign Linker List Item value */
    pDMAch->DMACCLLI = GPDMAChannelConfig->DMALLI;

    /* Set value to Channel Control Registers */
    switch (GPDMAChannelConfig->TransferType)
    {
    // Memory to memory
    case GPDMA_TRANSFERTYPE_M2M:
        // Assign physical source and destination address
        pDMAch->DMACCSrcAddr = GPDMAChannelConfig->SrcMemAddr;
        pDMAch->DMACCDestAddr = GPDMAChannelConfig->DstMemAddr;
        pDMAch->DMACCControl
                = GPDMA_DMACCxControl_TransferSize(GPDMAChannelConfig->TransferSize) \
                        | GPDMA_DMACCxControl_SBSize(GPDMA_BSIZE_32) \
                        | GPDMA_DMACCxControl_DBSize(GPDMA_BSIZE_32) \
                        | GPDMA_DMACCxControl_SWidth(GPDMAChannelConfig->TransferWidth) \
                        | GPDMA_DMACCxControl_DWidth(GPDMAChannelConfig->TransferWidth) \
                        | GPDMA_DMACCxControl_SI \
                        | GPDMA_DMACCxControl_DI \
                        | GPDMA_DMACCxControl_I;
        break;
    // Memory to peripheral
    case GPDMA_TRANSFERTYPE_M2P:
        // Assign physical source
        pDMAch->DMACCSrcAddr = GPDMAChannelConfig->SrcMemAddr;
        // Assign peripheral destination address
        pDMAch->DMACCDestAddr = (uint32_t)GPDMA_LUTPerAddr[GPDMAChannelConfig->DstConn];
        pDMAch->DMACCControl
                = GPDMA_DMACCxControl_TransferSize((uint32_t)GPDMAChannelConfig->TransferSize) \
                        | GPDMA_DMACCxControl_SBSize((uint32_t)GPDMA_LUTPerBurst[GPDMAChannelConfig->DstConn]) \
                        | GPDMA_DMACCxControl_DBSize((uint32_t)GPDMA_LUTPerBurst[GPDMAChannelConfig->DstConn]) \
                        | GPDMA_DMACCxControl_SWidth((uint32_t)GPDMA_LUTPerWid[GPDMAChannelConfig->DstConn]) \
                        | GPDMA_DMACCxControl_DWidth((uint32_t)GPDMA_LUTPerWid[GPDMAChannelConfig->DstConn]) \
                        | GPDMA_DMACCxControl_SI \
                        | GPDMA_DMACCxControl_I;
        break;
    // Peripheral to memory
    case GPDMA_TRANSFERTYPE_P2M:
        // Assign peripheral source address
        pDMAch->DMACCSrcAddr = (uint32_t)GPDMA_LUTPerAddr[GPDMAChannelConfig->SrcConn];
        // Assign memory destination address
        pDMAch->DMACCDestAddr = GPDMAChannelConfig->DstMemAddr;
        pDMAch->DMACCControl
                = GPDMA_DMACCxControl_TransferSize((uint32_t)GPDMAChannelConfig->TransferSize) \
                        | GPDMA_DMACCxControl_SBSize((uint32_t)GPDMA_LUTPerBurst[GPDMAChannelConfig->SrcConn]) \
                        | GPDMA_DMACCxControl_DBSize((uint32_t)GPDMA_LUTPerBurst[GPDMAChannelConfig->SrcConn]) \
                        | GPDMA_DMACCxControl_SWidth((uint32_t)GPDMA_LUTPerWid[GPDMAChannelConfig->SrcConn]) \
                        | GPDMA_DMACCxControl_DWidth((uint32_t)GPDMA_LUTPerWid[GPDMAChannelConfig->SrcConn]) \
                        | GPDMA_DMACCxControl_DI \
                        | GPDMA_DMACCxControl_I;
        break;
    // Peripheral to peripheral
    case GPDMA_TRANSFERTYPE_P2P:
        // Assign peripheral source address
        pDMAch->DMACCSrcAddr = (uint32_t)GPDMA_LUTPerAddr[GPDMAChannelConfig->SrcConn];
        // Assign peripheral destination address
        pDMAch->DMACCDestAddr = (uint32_t)GPDMA_LUTPerAddr[GPDMAChannelConfig->DstConn];
        pDMAch->DMACCControl
                = GPDMA_DMACCxControl_TransferSize((uint32_t)GPDMAChannelConfig->TransferSize) \
                        | GPDMA_DMACCxControl_SBSize((uint32_t)GPDMA_LUTPerBurst[GPDMAChannelConfig->SrcConn]) \
                        | GPDMA_DMACCxControl_DBSize((uint32_t)GPDMA_LUTPerBurst[GPDMAChannelConfig->DstConn]) \
                        | GPDMA_DMACCxControl_SWidth((uint32_t)GPDMA_LUTPerWid[GPDMAChannelConfig->SrcConn]) \
                        | GPDMA_DMACCxControl_DWidth((uint32_t)GPDMA_LUTPerWid[GPDMAChannelConfig->DstConn]) \
                        | GPDMA_DMACCxControl_I;
        break;
    // Do not support any more transfer type, return ERROR
    default:
        return ERROR;
    }

    /* Re-Configure DMA Request Select for source peripheral */
    if (GPDMAChannelConfig->SrcConn > 15)
    {
        DMAREQSEL |= (1<<(GPDMAChannelConfig->SrcConn - 16));
    } else {
        DMAREQSEL &= ~(1<<(GPDMAChannelConfig->SrcConn - 8));
    }

    /* Re-Configure DMA Request Select for Destination peripheral */
    if (GPDMAChannelConfig->DstConn > 15)
    {
        DMAREQSEL |= (1<<(GPDMAChannelConfig->DstConn - 16));
    } else {
        DMAREQSEL &= ~(1<<(GPDMAChannelConfig->DstConn - 8));
    }

    /* Enable DMA channels, little endian */
    LPC_GPDMA->DMACConfig = GPDMA_DMACConfig_E;
    while (!(LPC_GPDMA->DMACConfig & GPDMA_DMACConfig_E));

    // Calculate absolute value for Connection number
    tmp1 = GPDMAChannelConfig->SrcConn;
    tmp1 = ((tmp1 > 15) ? (tmp1 - 8) : tmp1);
    tmp2 = GPDMAChannelConfig->DstConn;
    tmp2 = ((tmp2 > 15) ? (tmp2 - 8) : tmp2);

    // Configure DMA Channel, enable Error Counter and Terminate counter
    pDMAch->DMACCConfig = GPDMA_DMACCxConfig_IE | GPDMA_DMACCxConfig_ITC /*| GPDMA_DMACCxConfig_E*/ \
        | GPDMA_DMACCxConfig_TransferType((uint32_t)GPDMAChannelConfig->TransferType) \
        | GPDMA_DMACCxConfig_SrcPeripheral(tmp1) \
        | GPDMA_DMACCxConfig_DestPeripheral(tmp2);

    return SUCCESS;
}


/*********************************************************************//**
 * @brief        Enable/Disable DMA channel
 * @param[in]    channelNum    GPDMA channel, should be in range from 0 to 7
 * @param[in]    NewState    New State of this command, should be:
 *                     - ENABLE.
 *                     - DISABLE.
 * @return        None
 **********************************************************************/
void GPDMA_ChannelCmd(uint8_t channelNum, FunctionalState NewState)
{
    LPC_GPDMACH_TypeDef *pDMAch;

    // Get Channel pointer
    pDMAch = (LPC_GPDMACH_TypeDef *) pGPDMACh[channelNum];

    if (NewState == ENABLE) {
        pDMAch->DMACCConfig |= GPDMA_DMACCxConfig_E;
    } else {
        pDMAch->DMACCConfig &= ~GPDMA_DMACCxConfig_E;
    }
}
/*********************************************************************//**
 * @brief        Check if corresponding channel does have an active interrupt
 *                 request or not
 * @param[in]    type        type of status, should be:
 *                     - GPDMA_STAT_INT:         GPDMA Interrupt Status
 *                     - GPDMA_STAT_INTTC:     GPDMA Interrupt Terminal Count Request Status
 *                     - GPDMA_STAT_INTERR:    GPDMA Interrupt Error Status
 *                     - GPDMA_STAT_RAWINTTC:    GPDMA Raw Interrupt Terminal Count Status
 *                     - GPDMA_STAT_RAWINTERR:    GPDMA Raw Error Interrupt Status
 *                     - GPDMA_STAT_ENABLED_CH:GPDMA Enabled Channel Status
 * @param[in]    channel        GPDMA channel, should be in range from 0 to 7
 * @return        IntStatus    status of DMA channel interrupt after masking
 *                 Should be:
 *                     - SET: the corresponding channel has no active interrupt request
 *                     - RESET: the corresponding channel does have an active interrupt request
 **********************************************************************/
IntStatus GPDMA_IntGetStatus(GPDMA_Status_Type type, uint8_t channel)
{
    CHECK_PARAM(PARAM_GPDMA_STAT(type));
    CHECK_PARAM(PARAM_GPDMA_CHANNEL(channel));

    switch (type)
    {
    case GPDMA_STAT_INT: //check status of DMA channel interrupts
        if (LPC_GPDMA->DMACIntStat & (GPDMA_DMACIntStat_Ch(channel)))
            return SET;
        return RESET;
    case GPDMA_STAT_INTTC: // check terminal count interrupt request status for DMA
        if (LPC_GPDMA->DMACIntTCStat & GPDMA_DMACIntTCStat_Ch(channel))
            return SET;
        return RESET;
    case GPDMA_STAT_INTERR: //check interrupt status for DMA channels
        if (LPC_GPDMA->DMACIntErrStat & GPDMA_DMACIntTCClear_Ch(channel))
            return SET;
        return RESET;
    case GPDMA_STAT_RAWINTTC: //check status of the terminal count interrupt for DMA channels
        if (LPC_GPDMA->DMACRawIntErrStat & GPDMA_DMACRawIntTCStat_Ch(channel))
            return SET;
        return RESET;
    case GPDMA_STAT_RAWINTERR: //check status of the error interrupt for DMA channels
        if (LPC_GPDMA->DMACRawIntTCStat & GPDMA_DMACRawIntErrStat_Ch(channel))
            return SET;
        return RESET;
    default: //check enable status for DMA channels
        if (LPC_GPDMA->DMACEnbldChns & GPDMA_DMACEnbldChns_Ch(channel))
            return SET;
        return RESET;
    }
}

/*********************************************************************//**
 * @brief        Clear one or more interrupt requests on DMA channels
 * @param[in]    type        type of interrupt request, should be:
 *                     - GPDMA_STATCLR_INTTC:     GPDMA Interrupt Terminal Count Request Clear
 *                     - GPDMA_STATCLR_INTERR: GPDMA Interrupt Error Clear
 * @param[in]    channel        GPDMA channel, should be in range from 0 to 7
 * @return        None
 **********************************************************************/
void GPDMA_ClearIntPending(GPDMA_StateClear_Type type, uint8_t channel)
{
    CHECK_PARAM(PARAM_GPDMA_STATCLR(type));
    CHECK_PARAM(PARAM_GPDMA_CHANNEL(channel));

    if (type == GPDMA_STATCLR_INTTC) // clears the terminal count interrupt request on DMA channel
        LPC_GPDMA->DMACIntTCClear = GPDMA_DMACIntTCClear_Ch(channel);
    else // clear the error interrupt request
        LPC_GPDMA->DMACIntErrClr = GPDMA_DMACIntErrClr_Ch(channel);
}

/**
 * @}
 */

#endif /* _GPDMA */

/**
 * @}
 */

/* --------------------------------- End Of File ------------------------------ */