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

📄 dma.c

📁 NXP LPC3000系列 wince BSP包
💻 C
字号:
//*********************************************************************
//* 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. 
//*
//* Copyright NXP Semiconductors
//*********************************************************************
//
// dma.c
//
// Core DMA handler
//

#include <bsp.h>
#include "lpc32xx_dmac.h"
#include "dma.h"

//------------------------------------------------------------------------------
//
// pDMARegs
//
// Pointer to DMA registers
//
static DMAC_REGS_T *pDMARegs;

//------------------------------------------------------------------------------
//
// dmach_to_intr
//
// Array that maps DMA channel value to it's INTR value
//
const DWORD dmach_to_intr[DMAC_CHANNELS_MAX] = {
	OAL_INTR_DMACH_0, OAL_INTR_DMACH_1, OAL_INTR_DMACH_2, OAL_INTR_DMACH_3};

//------------------------------------------------------------------------------
	//
// dmach_enab_cnt
//
// Number of enabled channels, used for master DMA clock control
//
static int dmach_enab_cnt;

//------------------------------------------------------------------------------
//
// dma_init
//
// Initialize DMA controller
//
void dma_init(void)
{
	INT32 idx;

	// Save base address of DMA controller registers
	pDMARegs = (DMAC_REGS_T *) OALPAtoVA((UINT32) DMA_BASE, FALSE);

	// Enable clock to DMA controller
	clkpwr_clk_en_dis(CLKPWR_DMA_CLK, 1);

	// Make sure DMA controller and all channels are disabled.
	// Controller is in little-endian mode. Disable sync signals
	pDMARegs->config = 0;
	pDMARegs->sync = 0;

	// Clear interrupt and error statuses
	pDMARegs->int_tc_clear = 0xFF;
	pDMARegs->raw_tc_stat = 0xFF;

	// All DMA channels are initially disabled
	for (idx = 0; idx < DMAC_CHANNELS_MAX; idx++)
	{
		pDMARegs->dma_chan [idx].control = 0;
		pDMARegs->dma_chan [idx].config_ch = 0;
	}

	// Disable clock to DMA controller
	clkpwr_clk_en_dis(CLKPWR_DMA_CLK, 0);

	// No channels are enabled
	dmach_enab_cnt = 0;
}

//------------------------------------------------------------------------------
//
// dma_channel_enable
//
// Enable a DMA channel
//
void dma_channel_enable(INT32 channel) 
{
	clkpwr_clk_en_dis(CLKPWR_DMA_CLK, 1);

	if (dmach_enab_cnt == 0)
	{
		// Enable DMA controller
		pDMARegs->config = DMAC_CTRL_ENABLE;
	}

	// Increment used channel count
	dmach_enab_cnt++;

	// Clear channel
	pDMARegs->dma_chan [channel].control = 0;
	pDMARegs->dma_chan [channel].config_ch = 0;
}

//------------------------------------------------------------------------------
//
// dma_channel_disable
//
// Disable a DMA channel
//
void dma_channel_disable(INT32 channel)
{
	pDMARegs->dma_chan [channel].control = 0;
	pDMARegs->dma_chan [channel].config_ch = 0;

	// Decrement used channel count and disable DMA clock if no
	// channels are used
	dmach_enab_cnt++;
	if (dmach_enab_cnt == 0)
	{
		// Disable clock to DMA controller
		pDMARegs->config = 0;
		clkpwr_clk_en_dis(CLKPWR_DMA_CLK, 0);
	}
}

//------------------------------------------------------------------------------
//
// dma_get_int_ch
//
// Get OALINTR value for DMA channel that is requesting interrupt
//
BOOL dma_get_int_ch(DWORD *irq)
{
	DWORD dmapirq;
	INT32 chan = 0;
	BOOL chint = TRUE;

	dmapirq = pDMARegs->int_stat;
	while ((chan < 8) && (chint == TRUE))
	{
		// Find interrupting channel
		if (((1 << chan) & dmapirq) != 0)
		{
			chint = FALSE;
		}
		else
		{
			chan++;
		}
	}

	// Return mapped OALINTR value if channel is good
	if (chan < DMAC_CHANNELS_MAX)
	{
		// DMA channel needs service
		chint = TRUE;
		*irq = dmach_to_intr[chan];
	}
	else if (chan < 8)
	{
		// Disable the offending channel
		dma_channel_disable(chan);
	}

	return chint;
}

//------------------------------------------------------------------------------
//
// OALDMAGetCh
//
// Enable the selected DMA channel and return the mapped OALINTR value for
// the channel.
//
BOOL OALDMAGetCh(
    UINT32 code, VOID* pInpBuffer, UINT32 inpSize, VOID* pOutBuffer,
    UINT32 outSize, UINT32 *pOutSize)
{
	DWORD ch;
	BOOL rc = FALSE;

    OALMSG(OAL_FUNC, (L"+OALDMAGetCh(...)\r\n"));

    if ((pInpBuffer != NULL) && (pOutBuffer != NULL) &&
		(inpSize == sizeof(DWORD)) &&
		(outSize == sizeof(DWORD)))
	{
        if (code == IOCTL_LPC32XX_DMACHGET)
		{
            // Enable DMA channel and return mapped OALINTR value
			ch = * (DWORD *) pInpBuffer;
			if (ch < DMAC_CHANNELS_MAX)
			{
				dma_channel_enable(ch);
				* (DWORD *) pOutBuffer = dmach_to_intr [ch];
				rc = TRUE;
			}
		}
    }

    OALMSG(OAL_FUNC, (L"-OALDMAGetCh(...), rc=%d\r\n", rc));
    return rc;
}

//------------------------------------------------------------------------------
//
// OALDMAFreeCh
//
// Free the selected DMA channel
//
BOOL OALDMAFreeCh(
    UINT32 code, VOID* pInpBuffer, UINT32 inpSize, VOID* pOutBuffer,
    UINT32 outSize, UINT32 *pOutSize)
{
	DWORD ch;
	BOOL rc = FALSE;

    OALMSG(OAL_FUNC, (L"+OALDMAFreeCh(...)\r\n"));

    if ((pInpBuffer != NULL) && (inpSize == sizeof(DWORD)))
	{
        if (code == IOCTL_LPC32XX_DMACHFREE)
		{
            // Disable DMA channel
			ch = * (DWORD *) pInpBuffer;
			if (ch < DMAC_CHANNELS_MAX)
			{
				dma_channel_disable(ch);
				rc = TRUE;
			}
		}
    }

    OALMSG(OAL_FUNC, (L"-OALDMAFreeCh(...), rc=%d\r\n", rc));
    return rc;
}

⌨️ 快捷键说明

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