⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c6410_dma_controller.c

📁 6410BSP3
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <windows.h>
#include <CEDDK.h>
#include <bsp_cfg.h>
#include <oal_intr.h>
#include <s3c6410.h>
#include "s3c6410_dma_controller_macro.h"
#include "s3c6410_dma_controller.h"

#define DMA_MSG(x)
#define DMA_INF(x)
#define DMA_ERR(x)    RETAILMSG(TRUE, x)

#define DMA_MUTEX    TEXT("S3C6410_DMA_Mutex")

static volatile S3C6410_DMAC_REG *g_pDMAC0Reg = NULL;
static volatile S3C6410_DMAC_REG *g_pDMAC1Reg = NULL;
static volatile S3C6410_SYSCON_REG *g_pSysConReg = NULL;
static HANDLE g_hMutex = NULL;

DMA_ERROR DMA_initialize_register_address(void *pDMAC0Reg, void *pDMAC1Reg, void *pSysConReg)
{
    DMA_ERROR error = DMA_SUCCESS;

    DMA_MSG((_T("[DMA]++DMA_initialize_register_address(0x%08x, 0x%08x, 0x%08x)\n\r"), pDMAC0Reg, pDMAC1Reg, pSysConReg));

    if (pDMAC0Reg == NULL || pDMAC1Reg == NULL || pSysConReg == NULL)
    {
        DMA_ERR((_T("[DMA:ERR] DMA_initialize_register_address() : NULL pointer parameter\n\r")));
        error = DMA_ERROR_NULL_PARAMETER;
    }
    else
    {
        g_pDMAC0Reg = (S3C6410_DMAC_REG *)pDMAC0Reg;
        g_pDMAC1Reg = (S3C6410_DMAC_REG *)pDMAC1Reg;
        g_pSysConReg = (S3C6410_SYSCON_REG *)pSysConReg;
        DMA_INF((_T("[DMA:INF] g_pDMAC0Reg = 0x%08x\n\r"), g_pDMAC0Reg));
        DMA_INF((_T("[DMA:INF] g_pDMAC1Reg = 0x%08x\n\r"), g_pDMAC1Reg));
        DMA_INF((_T("[DMA:INF] g_pSysConReg = 0x%08x\n\r"), g_pSysConReg));

        g_pSysConReg->SDMA_SEL = 0xcfffffff;    // All DMA is set to Normal DMA except Security TX, RX
        DMA_INF((_T("[DMA:INF] All DMA Source is set to Normal DMA\n\r")));
    }

    if (g_hMutex == NULL)
    {
        g_hMutex = CreateMutex(NULL, FALSE, DMA_MUTEX);
        if (g_hMutex == NULL)
        {
            DMA_ERR((_T("[DMA:ERR] DMA_initialize_register_address() : CreateMutex() Failed\n\r")));
            error = DMA_ERROR_NOT_INITIALIZED;
        }
    }

    DMA_MSG((_T("[DMA]--DMA_initialize_register_address() : %d\n\r"), error));

    return error;
}

BOOL DMA_request_channel(DMA_CH_CONTEXT *pCtxt, DMA_SOURCE DMASrc)
{
    volatile S3C6410_DMA_CH_REG *pDMACHReg;
    BOOL bRet = TRUE;
    int i;

    DMA_MSG((_T("[DMA]++DMA_request_channel(%d)\n\r"), DMASrc));

    pCtxt->DMASrc = DMASrc;

    if (g_pDMAC0Reg == NULL || g_pDMAC1Reg == NULL)
    {
        DMA_ERR((_T("[DMA:ERR] DMA Register Address is Not initialized\n\r")));
        bRet = FALSE;
        goto CleanUp2;
    }

    switch(DMASrc)
    {
    case DMA_UART0_TX:
    case DMA_UART0_RX:
    case DMA_UART1_TX:
    case DMA_UART1_RX:
    case DMA_UART2_TX:
    case DMA_UART2_RX:
    case DMA_UART3_TX:
    case DMA_UART3_RX:
    case DMA_PCM0_TX:
    case DMA_PCM0_RX:
    case DMA_I2S0_TX:
    case DMA_I2S0_RX:
    case DMA_SPI0_TX:
    case DMA_SPI0_RX:

    case DMA_I2S_V40_TX:
    case DMA_I2S_V40_RX:

    case DMA_MEM:
    case DMA_FIMG:
        pCtxt->Controller = DMAC0;
        break;
    case DMA_PCM1_TX:
    case DMA_PCM1_RX:
    case DMA_I2S1_TX:
    case DMA_I2S1_RX:
    case DMA_SPI1_TX:
    case DMA_SPI1_RX:
    case DMA_AC97_PCMOUT:
    case DMA_AC97_PCMIN:
    case DMA_AC97_MICIN:
    case DMA_PWM:
    case DMA_IRDA:
    case DMA_EXTERNAL:
    case DMA_SSS:
        pCtxt->Controller = DMAC1;
        break;
    default:
        DMA_ERR((_T("[DMA:ERR] DMA_request_channel() : Unknown DMA Source [%d]\n\r"), DMASrc));
        bRet = FALSE;
        goto CleanUp;
        break;
    }

    // Lock DMA Access
    DMA_lock();

    // Enable DMAC HCLK
    g_pSysConReg->HCLK_GATE |= (1<<12);    // DMAC0 HCLK Pass
    g_pSysConReg->HCLK_GATE |= (1<<13);    // DMAC1 HCLK Pass

    if (pCtxt->Controller == DMAC0)    // Find available channel in DMAC0
    {
        for (i=0; i<8; i++)
        {
            if (i == 3) continue;    // for OneNAND DMA channel

            pDMACHReg = (S3C6410_DMA_CH_REG *)((ULONG)g_pDMAC0Reg + DMA_CH_REG_OFFSET + i*DMA_CH_REG_SIZE);

            if (!(pDMACHReg->Control0 & TCINT_ENABLE))    // Check channel in use with TC Int Enable Bit !!!
            {
                pDMACHReg->Control0 |= TCINT_ENABLE;    // Set TC Int Enable Bit to reserve this channel!!!
                break;
            }
        }

        if (i < 8)        // there is available channel
        {
            DMA_INF((_T("[DMA:INF] DMA_request_channel() : Ch[%d] in DMAC0 is Available for DMASrc[%d]\n\r"), i, DMASrc));
            pCtxt->Channel = (DMAC_CH)i;
            pCtxt->dwIRQ = IRQ_DMA0_CH0+i;
            pCtxt->pCHReg = (void *)pDMACHReg;
            pCtxt->bValid = TRUE;
            DMA_dmac0_enable();
        }
        else if (DMASrc == DMA_MEM)    // DMA MEM2MEM can use channel in DMAC1
        {
            pCtxt->Controller = DMAC1;
        }
        else            // there is no available channel
        {
            DMA_ERR((_T("[DMA:ERR] DMA_request_channel() : No Available Channel in DMAC0 for DMASrc[%d]\n\r"), DMASrc));
            bRet = FALSE;
            goto CleanUp;
        }
    }

    if (pCtxt->Controller == DMAC1)    // Find available channel in DMAC1
    {
        for (i=0; i<8; i++)
        {
            if (i == 3) continue;    // for OneNAND DMA channel

            pDMACHReg = (S3C6410_DMA_CH_REG *)((ULONG)g_pDMAC1Reg + DMA_CH_REG_OFFSET + i*DMA_CH_REG_SIZE);

            if (!(pDMACHReg->Control0 & TCINT_ENABLE))    // Check channel in use with TC Int Enable Bit !!!
            {
                pDMACHReg->Control0 |= TCINT_ENABLE;    // Set TC Int Enable Bit to reserve this channel!!!
                break;
            }
        }

        if (i < 8)        // there is available channel
        {
            DMA_INF((_T("[DMA:INF] DMA_request_channel() : Ch[%d] in DMAC1 is Available for DMASrc[%d]\n\r"), i, DMASrc));
            pCtxt->Channel = (DMAC_CH)i;
            pCtxt->dwIRQ = IRQ_DMA1_CH0+i;
            pCtxt->pCHReg = (void *)pDMACHReg;
            pCtxt->bValid = TRUE;
            DMA_dmac1_enable();
        }
        else            // there is no available channel
        {
            DMA_ERR((_T("[DMA:ERR] DMA_request_channel() : No Available Channel in DMAC1 for DMASrc[%d]\n\r"), DMASrc));
            bRet = FALSE;
            goto CleanUp;
        }
    }

CleanUp:

    // Disable DMAC HCLK when No channel is allocated
    if (!(g_pDMAC0Reg->DMACConfiguration & DMAC_ENABLE))
    {
        g_pSysConReg->HCLK_GATE &= ~(1<<12);    // DMAC0 HCLK Mask
    }

    if (!(g_pDMAC1Reg->DMACConfiguration & DMAC_ENABLE))
    {
        g_pSysConReg->HCLK_GATE &= ~(1<<13);    // DMAC1 HCLK Mask
    }
CleanUp2:
    // Unlock DMA Access
    DMA_unlock();

    if (bRet == FALSE)        // Request is denied
    {
        // Clear DMA Channel Context
        memset((void *)pCtxt, 0x0, sizeof(DMA_CH_CONTEXT));
    }

    DMA_MSG((_T("[DMA]--DMA_request_channel() : %d\n\r"), bRet));

    return bRet;
}

BOOL DMA_release_channel(DMA_CH_CONTEXT *pCtxt)
{
    volatile S3C6410_DMA_CH_REG *pDMACHReg;
    BOOL bRet = TRUE;

    DMA_MSG((_T("[DMA]++DMA_release_channel() : Ch%d in DMAC%d, \n\r"), pCtxt->Channel, pCtxt->Controller));

    if (pCtxt->bValid == FALSE)
    {
        DMA_ERR((_T("[DMA:ERR] DMA_release_channel() : Invalid DMA_CH_CONTEXT\n\r")));
        bRet = FALSE;
        goto CleanUp;
    }

    // Stop DMA Channel
    DMA_channel_stop(pCtxt);

    // Lock DMA Access
    DMA_lock();

    pDMACHReg = (S3C6410_DMA_CH_REG *)pCtxt->pCHReg;
    pDMACHReg->Control0 &= ~TCINT_ENABLE;        // Clear TC Int Enable Bit to release this channel!!!

    if (pCtxt->Controller == DMAC0)        // Release channel in DMAC0
    {
        DMA_dmac0_disable();
    }
    else if (pCtxt->Controller == DMAC1)    // Release channel in DMAC1
    {
        DMA_dmac1_disable();
    }

    // Unlock DMA Access
    DMA_unlock();

CleanUp:

    // Release LLI buffer
    DMA_free_LLI_context(pCtxt);

    // Clear DMA Channel Context
    memset((void *)pCtxt, 0x0, sizeof(DMA_CH_CONTEXT));

    DMA_MSG((_T("[DMA]--DMA_release_channel() : %d\n\r"), bRet));

    return bRet;
}

DMA_ERROR DMA_initialize_channel(DMA_CH_CONTEXT *pCtxt, BOOL bSync)
{
    volatile S3C6410_DMA_CH_REG *pDMACHReg;
    DMA_ERROR error = DMA_SUCCESS;

    DMA_MSG((_T("[DMA]++DMA_initialize_channel() : Ch%d in DMAC%d (bSync:%d)\n\r"), pCtxt->Channel, pCtxt->Controller, bSync));

    if (pCtxt->bValid == FALSE)
    {
        DMA_ERR((_T("[DMA:ERR] DMA_initialize_channel() : Invalid DMA_CH_CONTEXT\n\r")));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }

    pCtxt->LLICount = 0;
    pCtxt->LLIAHBM = AHB_M1;

    switch(pCtxt->DMASrc)
    {
    //-------------------
    // DMA Source in DMC0
    //-------------------
    case DMA_UART0_TX:
        pCtxt->SrcAHBM = AHB_M1;            // Memory
        pCtxt->DstAHBM = AHB_M2;            // Peripheral
        pCtxt->SrcPeri = 0;                    // Memory (Don't Care)
        pCtxt->DstPeri = DMAC0_UART0_TX;        // UART0_TX
        pCtxt->FlowCtrl = MEM_TO_PERI;        // Memory -> Peripheral
        break;
    case DMA_UART0_RX:
        pCtxt->SrcAHBM = AHB_M2;            // Peripheral
        pCtxt->DstAHBM = AHB_M1;            // Memory
        pCtxt->SrcPeri = DMAC0_UART0_RX;        // UART0_RX
        pCtxt->DstPeri = 0;                    // Memory (Don't Care)
        pCtxt->FlowCtrl = PERI_TO_MEM;        // Peripheral -> Memory
        break;
    case DMA_UART1_TX:
        pCtxt->SrcAHBM = AHB_M1;            // Memory
        pCtxt->DstAHBM = AHB_M2;            // Peripheral
        pCtxt->SrcPeri = 0;                    // Memory (Don't Care)
        pCtxt->DstPeri = DMAC0_UART1_TX;        // UART1_TX
        pCtxt->FlowCtrl = MEM_TO_PERI;        // Memory -> Peripheral
        break;
    case DMA_UART1_RX:
        pCtxt->SrcAHBM = AHB_M2;            // Peripheral
        pCtxt->DstAHBM = AHB_M1;            // Memory
        pCtxt->SrcPeri = DMAC0_UART1_RX;        // UART1_RX
        pCtxt->DstPeri = 0;                    // Memory (Don't Care)
        pCtxt->FlowCtrl = PERI_TO_MEM;        // Peripheral -> Memory
        break;
    case DMA_UART2_TX:
        pCtxt->SrcAHBM = AHB_M1;            // Memory
        pCtxt->DstAHBM = AHB_M2;            // Peripheral
        pCtxt->SrcPeri = 0;                    // Memory (Don't Care)
        pCtxt->DstPeri = DMAC0_UART2_TX;        // UART2_TX
        pCtxt->FlowCtrl = MEM_TO_PERI;        // Memory -> Peripheral
        break;
    case DMA_UART2_RX:
        pCtxt->SrcAHBM = AHB_M2;            // Peripheral
        pCtxt->DstAHBM = AHB_M1;            // Memory
        pCtxt->SrcPeri = DMAC0_UART2_RX;        // UART2_RX
        pCtxt->DstPeri = 0;                    // Memory (Don't Care)
        pCtxt->FlowCtrl = PERI_TO_MEM;        // Peripheral -> Memory
        break;
    case DMA_UART3_TX:
        pCtxt->SrcAHBM = AHB_M1;            // Memory
        pCtxt->DstAHBM = AHB_M2;            // Peripheral
        pCtxt->SrcPeri = 0;                    // Memory (Don't Care)
        pCtxt->DstPeri = DMAC0_UART3_TX;        // UART3_TX
        pCtxt->FlowCtrl = MEM_TO_PERI;        // Memory -> Peripheral
        break;
    case DMA_UART3_RX:
        pCtxt->SrcAHBM = AHB_M2;            // Peripheral
        pCtxt->DstAHBM = AHB_M1;            // Memory
        pCtxt->SrcPeri = DMAC0_UART3_RX;        // UART3_RX
        pCtxt->DstPeri = 0;                    // Memory (Don't Care)
        pCtxt->FlowCtrl = PERI_TO_MEM;        // Peripheral -> Memory
        break;
    case DMA_PCM0_TX:
        pCtxt->SrcAHBM = AHB_M1;            // Memory
        pCtxt->DstAHBM = AHB_M2;            // Peripheral
        pCtxt->SrcPeri = 0;                    // Memory (Don't Care)
        pCtxt->DstPeri = DMAC0_PCM0_TX;        // PCM0_TX
        pCtxt->FlowCtrl = MEM_TO_PERI;        // Memory -> Peripheral
        break;
    case DMA_PCM0_RX:
        pCtxt->SrcAHBM = AHB_M2;            // Peripheral
        pCtxt->DstAHBM = AHB_M1;            // Memory
        pCtxt->SrcPeri = DMAC0_PCM0_RX;        // PCM0_RX
        pCtxt->DstPeri = 0;                    // Memory (Don't Care)
        pCtxt->FlowCtrl = PERI_TO_MEM;        // Peripheral -> Memory
        break;
    case DMA_I2S0_TX:
        pCtxt->SrcAHBM = AHB_M1;            // Memory
        pCtxt->DstAHBM = AHB_M2;            // Peripheral
        pCtxt->SrcPeri = 0;                    // Memory (Don't Care)
        pCtxt->DstPeri = DMAC0_I2S0_TX;        // I2S0_TX
        pCtxt->FlowCtrl = MEM_TO_PERI;        // Memory -> Peripheral
        break;
    case DMA_I2S0_RX:
        pCtxt->SrcAHBM = AHB_M2;            // Peripheral
        pCtxt->DstAHBM = AHB_M1;            // Memory
        pCtxt->SrcPeri = DMAC0_I2S0_RX;        // I2S0_RX
        pCtxt->DstPeri = 0;                    // Memory (Don't Care)
        pCtxt->FlowCtrl = PERI_TO_MEM;        // Peripheral -> Memory
        break;
    case DMA_SPI0_TX:
        pCtxt->SrcAHBM = AHB_M1;            // Memory
        pCtxt->DstAHBM = AHB_M2;            // Peripheral
        pCtxt->SrcPeri = 0;                    // Memory (Don't Care)
        pCtxt->DstPeri = DMAC0_SPI0_TX;        // SPI0_TX
        pCtxt->FlowCtrl = MEM_TO_PERI;        // Memory -> Peripheral
        break;
    case DMA_SPI0_RX:
        pCtxt->SrcAHBM = AHB_M2;            // Peripheral
        pCtxt->DstAHBM = AHB_M1;            // Memory
        pCtxt->SrcPeri = DMAC0_SPI0_RX;        // SPI0_RX
        pCtxt->DstPeri = 0;                    // Memory (Don't Care)
        pCtxt->FlowCtrl = PERI_TO_MEM;        // Peripheral -> Memory
        break;
    case DMA_I2S_V40_TX:
        pCtxt->SrcAHBM = AHB_M1;            // Memory
        pCtxt->DstAHBM = AHB_M2;            // Peripheral
        pCtxt->SrcPeri = 0;                    // Memory (Don't Care)
        pCtxt->DstPeri = DMAC0_I2S_V40_TX;    // I2S_V40_TX
        pCtxt->FlowCtrl = MEM_TO_PERI;        // Memory -> Peripheral
        break;
    case DMA_I2S_V40_RX:
        pCtxt->SrcAHBM = AHB_M2;            // Peripheral
        pCtxt->DstAHBM = AHB_M1;            // Memory
        pCtxt->SrcPeri = DMAC0_I2S_V40_RX;    // I2S_V40_RX
        pCtxt->DstPeri = 0;                    // Memory (Don't Care)
        pCtxt->FlowCtrl = PERI_TO_MEM;        // Peripheral -> Memory
        break;
    
    //-------------------
    // DMA Source in DMC1

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -