📄 lh7a400_dma_driver.c
字号:
/***********************************************************************
* $Workfile: LH7A400_DMA_driver.c $
* $Revision: 1.0 $
* $Author: SuryanG $
* $Date: Sep 10 2002 14:55:20 $
*
* Project: LH7A400
*
* Description:
* This file contains function definitions for the LH7A400 DMA
* controller driver
*
* ! ! ! P R E L I M I N A R Y ! ! !
*
* Revision History:
* $Log: //smaicnt2/pvcs/VM/CHIPS/archives/LH7A400/DMA/Drivers/LH7A400_DMA_driver.c-arc $
*
* Rev 1.0 Sep 10 2002 14:55:20 SuryanG
* Initial revision.
*
*
*
***********************************************************************
*
* Copyright (c) 2002 Sharp Microelectronics of the Americas
*
* All rights reserved
*
* SHARP MICROELECTRONICS OF THE AMERICAS MAKES NO REPRESENTATION
* OR WARRANTIES WITH RESPECT TO THE PERFORMANCE OF THIS SOFTWARE,
* AND SPECIFICALLY DISCLAIMS ANY RESPONSIBILITY FOR ANY DAMAGES,
* SPECIAL OR CONSEQUENTIAL, CONNECTED WITH THE USE OF THIS SOFTWARE.
*
* SHARP MICROELECTRONICS OF THE AMERICAS PROVIDES THIS SOFTWARE SOLELY
* FOR THE PURPOSE OF SOFTWARE DEVELOPMENT INCORPORATING THE USE OF A
* SHARP MICROCONTROLLER OR SYSTEM-ON-CHIP PRODUCT. USE OF THIS SOURCE
* FILE IMPLIES ACCEPTANCE OF THESE CONDITIONS.
*
**********************************************************************/
#include "LH7A400_dma_driver.h"
#include "SMA_priority_driver.h"
#include "LH7A400_csc_driver.h"
#include "LH7A400_int_driver.h"
#include "LH7A400_cp15_driver.h"
#define DMAINTR_PRIORITY (21) /* make sure this doesn't conflict
with other priorities (how?) */
#define N_DMA_INT_SOURCES (10)
#define N_DMA_CHANNELS (10)
#define DMA_AAC_OFFSET (4)
static void (*dma_int_handlers[N_DMA_INT_SOURCES+1])(void);
static INT_8 dma_priorities[N_DMA_INT_SOURCES + 1];
static INT_8 dma_priority_encode0[_BIT(8)];
static INT_8 dma_priority_encode1[_BIT(N_DMA_INT_SOURCES - 8)];
static UNS_32 dma_int_status;
static PRIORITY_DATA prio =
{
N_DMA_INT_SOURCES,
dma_priorities,
dma_priority_encode0,
dma_priority_encode1,
0,
0,
dma_int_handlers
};
static UNS_32 initialized = 0;
static DMACHANNELREGS *dmach;
/***********************************************************************
*
* Function: dma_null_handler
*
* Purpose:
* Disable the interrupt source if it is unhandled.
*
* Processing:
* This function is called by the DMA interrupt handler if the
* DMA has an active, unmasked, unhandled interrupt. It
* disables the unhandled interrupt.
*
* Parameters: none
*
* Outputs: nothing
*
* Returns: nothing
*
* Notes: None
*
**********************************************************************/
static void dma_null_handler(void)
{
INT_32 i;
for(i = 0; i < N_DMA_INT_SOURCES; i++)
{
if(dma_int_status & _BIT(i))
{
dma_interrupt_disable((INT_8)i);
}
}
}
/***********************************************************************
*
* Function: dma_irq_handler
*
* Purpose:
* Dispatches the appropriate dma handler
*
* Processing:
* call the MAKE_DISPATCHER macro
*
* Parameters: none
*
* Outputs: nothing
*
* Returns: nothing
*
* Notes: None
*
**********************************************************************/
static void dma_irq_handler(void)
{
MAKE_DISPATCHER16( (dma_int_status = DMAC->dma_global_int),
dma_int_handlers,
dma_priority_encode)
}
/***********************************************************************
*
* Function: dma_install_int_handler
*
* Purpose:
* Install an interrupt handler function that will be called by the
* DMA interrupt handler function
*
* Processing:
* Use priority_driver functions
*
* Parameters:
* source: The number for the interrupt source. can be one of
* DMAC_USBTXINT_BIT
* DMAC_USBRXINT_BIT
* DMAC_MMCTXINT_BIT
* DMAC_MMCRXINT_BIT
* DMAC_AACRX0INT_BIT
* DMAC_AACTX0INT_BIT
* DMAC_AACRX1INT_BIT
* DMAC_AACTX1INT_BIT
* DMAC_AACRX2INT_BIT
* DMAC_AACTX2INT_BIT
* priority: The priority number for the source.
* 0 <= priority < N_DMA_INT_SOURCES
* hp: A pointer to the handler function.
*
* Outputs: Arrays in the prio structure set up for the handler
*
* Returns:
* priority if successful, N_DMA_INT_SOURCES if not.
*
* Notes: None
*
**********************************************************************/
INT_8 dma_install_int_handler(INT_8 source,
INT_8 priority,
void (*hp)(void))
{
return priority_install_handler(&prio, source, priority, hp,
dma_null_handler);
}
/***********************************************************************
*
* Function: dma_remove_int_handler
*
* Purpose:
* Install an interrupt handler function that will be called by the
* DMA interrupt handler function
*
* Processing:
* Use priority_driver functions
*
* Parameters: The number for the interrupt source. can be one of
* DMAC_USBTXINT_BIT
* DMAC_USBRXINT_BIT
* DMAC_MMCTXINT_BIT
* DMAC_MMCRXINT_BIT
* DMAC_AACRX0INT_BIT
* DMAC_AACTX0INT_BIT
* DMAC_AACRX1INT_BIT
* DMAC_AACTX1INT_BIT
* DMAC_AACRX2INT_BIT
* DMAC_AACTX2INT_BIT
*
* Outputs: None
*
* Returns:
* priority if successful, N_DMA_INT_SOURCES if not.
*
* Notes: None
*
**********************************************************************/
INT_8 dma_remove_int_handler(INT_8 source)
{
return priority_remove_handler(&prio,
priority_get_priority(&prio, source),
dma_null_handler);
}
/***********************************************************************
*
* Function: dma_init
*
* Purpose:
*
*
* Processing:
*
* Parameters: None
*
* Outputs: None
*
* Returns:
*
* Notes: None
*
**********************************************************************/
INT_32 dma_init(void)
{
INT_32 retval, i;
if(!initialized)
{
int_init_irq_handler(0);
retval = int_install_irq_handler(INTC_DMAINTR_BIT,
DMAINTR_PRIORITY,
dma_irq_handler);
if(retval == INTC_N_IRQ_HANDLERS)
{
return (_ERROR);
}
priority_init_driver(&prio, dma_null_handler);
int_enable_interrupt(INTC_DMAINTR);
/* set up pointer to dma channel registers structure */
dmach = &(DMAC->usbrx);
/* disable all dma channels */
for (i = 0; i < N_DMA_CHANNELS; i++)
{
csc_disable_dma((dma_channel_t) i);
}
initialized = 1;
}
return (_NO_ERROR);
}
/***********************************************************************
*
* Function: dma_interrupt_enable
*
* Purpose:
*
*
* Processing:
*
* Parameters: None
*
* Outputs: None
*
* Returns:
*
* Notes: None
*
**********************************************************************/
INT_32 dma_interrupt_enable(INT_8 ch)
{
if(ch < 0 || ch > (N_DMA_INT_SOURCES - 1))
{
return (_ERROR);
}
if (ch > DMA_MMC_TX)
{
ch += DMA_AAC_OFFSET;
}
dmach[ch].control |= DMAC_STALL | DMAC_NFB | DMAC_CHERROR;
return(_NO_ERROR);
}
/***********************************************************************
*
* Function: dma_interrupt_disable
*
* Purpose:
*
*
* Processing:
*
* Parameters: None
*
* Outputs: None
*
* Returns:
*
* Notes: None
*
**********************************************************************/
INT_32 dma_interrupt_disable(INT_8 ch)
{
if(ch < 0 || ch > (N_DMA_INT_SOURCES - 1))
{
return (_ERROR);
}
if (ch > DMA_MMC_TX)
{
ch += DMA_AAC_OFFSET;
}
dmach[ch].control &= ~(DMAC_STALL | DMAC_NFB | DMAC_CHERROR);
return(_NO_ERROR);
}
/***********************************************************************
*
* Function: dma_start
*
* Purpose:
*
*
* Processing:
*
* Parameters: None
*
* Outputs: None
*
* Returns:
*
* Notes: None
*
**********************************************************************/
INT_32 dma_start(INT_8 ch,
UNS_32 start_addr,
UNS_32 nbytes)
{
UNS_32 base0, base1, maxcnt0, maxcnt1;
if (ch < 0 || ch > (N_DMA_INT_SOURCES - 1))
{
return (_ERROR);
}
if (ch > DMA_MMC_TX)
{
ch += DMA_AAC_OFFSET;
}
base0 = LH7A400_cp15_map_virtual_to_physical((void *)start_addr);
if (nbytes > USHRT_MAX)
{
maxcnt0 = USHRT_MAX;
maxcnt1 = nbytes - USHRT_MAX;
base1 = LH7A400_cp15_map_virtual_to_physical((void *)
(start_addr + (sizeof(UNS_32)*USHRT_MAX)));
}
else
{
maxcnt0 = nbytes;
maxcnt1 = 0;
base1 = 0;
}
dma_interrupt_enable(ch - DMA_AAC_OFFSET);
dmach[ch].maxcnt0 = maxcnt0;
dmach[ch].control |= DMAC_ENABLE;
dmach[ch].base0 = base0;
return(_NO_ERROR);
}
/***********************************************************************
*
* Function: dma_next_buffer
*
* Purpose:
*
*
* Processing:
*
* Parameters: None
*
* Outputs: None
*
* Returns:
*
* Notes: None
*
**********************************************************************/
INT_32 dma_next_buffer(INT_8 ch,
UNS_32 base1,
UNS_16 maxcnt1)
{
if (ch < 0 || ch > (N_DMA_INT_SOURCES - 1))
{
return (_ERROR);
}
if (ch > DMA_MMC_TX)
{
ch += DMA_AAC_OFFSET;
}
dmach[ch].maxcnt1 = maxcnt1;
/* enable DMA channel before writing to the base address register */
dmach[ch].control |= DMAC_ENABLE;
dmach[ch].base1 = LH7A400_cp15_map_virtual_to_physical((void *)base1);
return(_NO_ERROR);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -