📄 s3c6400_dma_controller.c
字号:
#include <windows.h>
#include <CEDDK.h>
#include <bsp_cfg.h>
#include <oal_intr.h>
#include <s3c6400.h>
#include "s3c6400_dma_controller_macro.h"
#include "s3c6400_dma_controller.h"
#ifdef REMOVE_BEFORE_RELEASE
#define DMA_MSG(x)
#define DMA_INF(x)
#define DMA_ERR(x) RETAILMSG(TRUE, x)
#else
//#define DMA_MSG(x) RETAILMSG(TRUE, x)
#define DMA_MSG(x)
#define DMA_INF(x) RETAILMSG(TRUE, x)
//#define DMA_INF(x)
#define DMA_ERR(x) RETAILMSG(TRUE, x)
//#define DMA_ERR(x)
#endif
#define DMA_MUTEX TEXT("S3C6400_DMA_Mutex")
static volatile S3C6400_DMAC_REG *g_pDMAC0Reg = NULL;
static volatile S3C6400_DMAC_REG *g_pDMAC1Reg = NULL;
static volatile S3C6400_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 = (S3C6400_DMAC_REG *)pDMAC0Reg;
g_pDMAC1Reg = (S3C6400_DMAC_REG *)pDMAC1Reg;
g_pSysConReg = (S3C6400_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 S3C6400_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 CleanUp;
}
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_HSI_TX:
case DMA_HSI_RX:
case DMA_MEM:
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:
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 = (S3C6400_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 = (S3C6400_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
}
// 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 S3C6400_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 = (S3C6400_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 S3C6400_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_HSI_TX:
pCtxt->SrcAHBM = AHB_M1; // Memory
pCtxt->DstAHBM = AHB_M2; // Peripheral
pCtxt->SrcPeri = 0; // Memory (Don't Care)
pCtxt->DstPeri = DMAC0_HSI_TX; // SPI0_TX
pCtxt->FlowCtrl = MEM_TO_PERI; // Memory -> Peripheral
break;
case DMA_HSI_RX:
pCtxt->SrcAHBM = AHB_M2; // Peripheral
pCtxt->DstAHBM = AHB_M1; // Memory
pCtxt->SrcPeri = DMAC0_HSI_RX; // HSI_RX
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -