📄 dma.c
字号:
break;
case DMA_CON_MASTER_UART1TX:
UART_TrxHandler_VFIFO(&UARTPort[uart_port1]);
break;
case DMA_CON_MASTER_UART2RX:
UART_RecHandler_VFIFO(&UARTPort[uart_port2]);
break;
case DMA_CON_MASTER_UART2TX:
UART_TrxHandler_VFIFO(&UARTPort[uart_port2]);
break;
case DMA_CON_MASTER_UART3RX:
UART_RecHandler_VFIFO(&UARTPort[uart_port3]);
break;
case DMA_CON_MASTER_UART3TX:
UART_TrxHandler_VFIFO(&UARTPort[uart_port3]);
break;
}
DMA_ACKI(index);
}
}
#endif //__DMA_UART_VIRTUAL_FIFO__
IRQClearInt(IRQ_DMA_CODE);
IRQUnmask(IRQ_DMA_CODE);
}
void DMA_LISR(void)
{
IRQMask(IRQ_DMA_CODE);
drv_active_hisr(DRV_DMA_HISR_ID);
}
void DMA_Ini(void)
{
kal_uint8 index;
for (index = 0; index < DMA_MAX_CHANNEL; index++)
DMA_Owner[index] = DMA_IDLE;
DRV_Reg(DRVPDN_CON0) &= ~DRVPDN_CON0_DMA;
IRQ_Register_LISR(IRQ_DMA_CODE, DMA_LISR, "DMA handler");
DRV_Register_HISR(DRV_DMA_HISR_ID, DMA_HISR);
IRQSensitivity(IRQ_DMA_CODE,LEVEL_SENSITIVE);
IRQUnmask(IRQ_DMA_CODE);
}
kal_bool DMA_memcpy(const void *src, const void *dst, kal_uint32 length)
{
kal_uint8 handle=0xff;
DMA_INPUT input;
DMA_SWCOPYMENU menu;
if (length > 0xffff)
return KAL_FALSE;
handle = DMA_FullSize_GetChannel(DMA_SW);
ASSERT(handle!=0xff);
if (handle != 0xff)
{
menu.srcaddr = (kal_uint32)src;
menu.dstaddr = (kal_uint32)dst;
input.type = DMA_SWCOPY;
input.menu = &menu;
input.callback = NULL;
if ((menu.srcaddr|menu.dstaddr|input.count) & 0x01)
{
input.size = DMA_BYTE;
input.count = length;
}
else if ((menu.srcaddr|menu.dstaddr|input.count) & 0x02)
{
input.size = DMA_SHORT;
input.count = length/2;
}
else
{
input.size = DMA_LONG;
input.count = length/4;
}
DMA_FullSize_Config(handle,&input,KAL_TRUE);
DMA_WaitUntilRdy(handle);
return KAL_TRUE;
}
else
{
return KAL_FALSE;
}
}
/*
* This function is used to set the DMA Global Bandwidth Limiter.
* All DMA channels' bandwidth limit will be updated.
*/
DMA_GBL_HANDLE DMA_SetGBL(DMA_GBL_CLASS dma_gbl_class)
{
kal_uint8 is_update;
kal_uint32 _savedMask;
kal_uint8 limiter;
kal_uint16 i;
if (dma_gbl_class > DMA_MAX_GBL_CLASS)
return (DMA_GBL_HANDLE)DMA_INVALID_GBL_HANDLE;
is_update = 0;
_savedMask = SaveAndSetIRQMask();
if (dma_gbl_class != 0)
dma_gbl_count[dma_gbl_class - 1]++;
if (dma_gbl_class > dma_gbl_class_g) {
dma_gbl_class_g = dma_gbl_class;
is_update = 1;
}
RestoreIRQMask(_savedMask);
if (is_update == 1) {
/* need to set DMA bandwidth limit */
limiter = dma_gbl_class_to_grade[dma_gbl_class];
#ifdef MT6218B
for (i = 2; i <= DMA_MAX_CHANNEL; i++)
#else /* MT6218B */
for (i = 1; i <= DMA_MAX_CHANNEL; i++)
#endif /* MT6218B */
DRV_WriteReg8(DMA_LIMITER(i), limiter);
#if ( defined(MT6218B) || defined(MT6217) )
lcd_dma_slow_down(dma_gbl_class);
#endif
}
return (DMA_GBL_HANDLE)dma_gbl_class;
}
/*
* This function is used to restore the DMA Global Bandwidth Limiter.
* All DMA channels' limiter will be updated.
*/
void DMA_RestoreGBL(DMA_GBL_HANDLE dma_gbl_handle)
{
DMA_GBL_CLASS dma_gbl_class;
kal_uint8 is_update, max;
kal_int16 i;
kal_uint32 _savedMask;
kal_uint8 limiter;
if (dma_gbl_handle == DMA_INVALID_GBL_HANDLE)
return ;
dma_gbl_class = (DMA_GBL_CLASS)dma_gbl_handle;
if (dma_gbl_class > DMA_MAX_GBL_CLASS)
return ;
is_update = 0;
/* update DMA GBL */
_savedMask = SaveAndSetIRQMask();
if (dma_gbl_class != 0)
dma_gbl_count[dma_gbl_class - 1]--;
max = 0;
/* get the current max of available DMA gbl */
for (i = DMA_MAX_GBL_CLASS - 1; i >= 0; i--) {
if (dma_gbl_count[i] > 0) {
max = i + 1;
break;
}
}
if (max != dma_gbl_class_g) {
dma_gbl_class_g = max;
is_update = 1;
}
RestoreIRQMask(_savedMask);
if (is_update == 0)
return ;
else {
/* need to set DMA bandwidth limit */
limiter = dma_gbl_class_to_grade[dma_gbl_class];
#ifdef MT6218B
for (i = 2; i <= DMA_MAX_CHANNEL; i++)
#else
for (i = 1; i <= DMA_MAX_CHANNEL; i++)
#endif
DRV_WriteReg8(DMA_LIMITER(i), limiter);
#if ( defined(MT6218B) || defined(MT6217) )
lcd_dma_slow_down(dma_gbl_class);
#endif
}
}
#endif /* MT6205 || MT6208 || MT6205B || FPGA */
#ifdef MT6218B
/*
* FUNCTION
* dma_ch1_init
*
* DESCRIPTION
* This function is used to initialize DMA channel 1.
*
* CALLS
*
* PARAMETERS
* None
*
* RETURNS
* None
*
* GLOBALS AFFECTED
*/
void dma_ch1_init(kal_uint32 dstaddr, kal_uint16 len, kal_uint8 limiter)
{
DRV_WriteReg32(DMA_DST(1), dstaddr);
DRV_WriteReg32(DMA_COUNT(1), (kal_uint32)len);
DRV_WriteReg32(DMA_CON(1), 0 | DMA_CON_SIZE_BYTE | DMA_CON_SINC);
DRV_WriteReg32(DMA_LIMITER(1),limiter);
}
/*
* This function is used to start DMA channel 1 for transfer.
*/
void dma_ch1_start(kal_uint32 srcaddr)
{
DMA_Stop_Now(1);
DMA_ACKI(1);
DRV_WriteReg32(DMA_SRC(1), srcaddr);
DMA_Start(1);
}
/*
* This function is used to stop transfer of DMA channel 1.
*/
void dma_ch1_stop()
{
DMA_Stop_Now(1);
DMA_ACKI(1);
}
#endif /* MT6218B */
static kal_uint32 dma_slowdown_handle;
static kal_uint32 dma_slowdown_mask;
kal_uint8 dma_slowdown_get_handle(void)
{
ASSERT(dma_slowdown_handle<32);
return dma_slowdown_handle++;
}
void dma_slowdown(kal_uint8 handle)
{
kal_uint32 _savedMask;
_savedMask = SaveAndSetIRQMask();
if (dma_slowdown_mask == 0)
{
che_slowdown();
/*
* Original lcd_dma_slow_down(void) internally uses 0x3F as command
* latency. Here we pass "4" to new lcd_dma_slow_down(level) such that
* the command latency is longer than before.
*/
#if defined(MT6218B) || defined(MT6217)
{
kal_uint8 index;
lcd_dma_slow_down(DMA_GBL_CLASS4);
#ifdef MT6218B
/* nop */
#else /* MT6218B */
DRV_WriteReg32(DMA_LIMITER(1),0xff);
#endif /* MT6218B */
DRV_WriteReg32(DMA_LIMITER(2),0xff);
DRV_WriteReg32(DMA_LIMITER(3),0xff);
for(index = 4; index <= DMA_MAX_CHANNEL; index++)
{
DRV_WriteReg32(DMA_LIMITER(index),0xc8);
}
}
#elif defined(MT6208) || defined(MT6205B) /* MT6218B || MT6217 */
lcd_dma_slow_down(4);
#endif /* MT6218B || MT6217 */
}
dma_slowdown_mask |= (1 << handle);
RestoreIRQMask(_savedMask);
}
/*
* FUNCTION
* dma_recover
*
* DESCRIPTION
* Recover DMA limiter
*
* CALLS
*
* PARAMETERS
* None
*
* RETURNS
* None
*
* GLOBALS AFFECTED
*/
void dma_recover(kal_uint8 handle)
{
kal_uint32 _savedMask;
_savedMask = SaveAndSetIRQMask();
dma_slowdown_mask &= ~(1 << handle);
if (dma_slowdown_mask == 0)
{
che_recover();
#if defined(MT6208) || defined(MT6205B) || defined(MT6218B) || defined(MT6217)
lcd_dma_recovery();
#endif /* MT6208 || MT6205B || MT6218B || MT6217 */
#if defined(MT6218B) || defined(MT6217)
{
kal_uint8 index;
kal_uint8 limiter;
limiter = dma_gbl_class_to_grade[dma_gbl_class_g];
#ifdef MT6218B
for(index = 2; index <= DMA_MAX_CHANNEL; index++)
{
#else /* MT6218B */
for(index = 1; index <= DMA_MAX_CHANNEL; index++)
{
#endif /* MT6218B */
DRV_WriteReg32(DMA_LIMITER(index), limiter);
}
}
#endif /* MT6218B || MT6217 */
}
RestoreIRQMask(_savedMask);
}
/*
* FUNCTION
* dma_recover_all
*
* DESCRIPTION
* Recover all DMA limiter
*
* CALLS
*
* PARAMETERS
* None
*
* RETURNS
* None
*
* GLOBALS AFFECTED
*/
void dma_recover_all()
{
kal_uint32 _savedMask;
kal_uint8 index;
#if !defined(MT6205B) && !defined(MT6208)
kal_uint8 limiter;
#endif
_savedMask = SaveAndSetIRQMask();
#if defined(MT6205B) || defined(MT6218B) || defined(MT6217)
lcd_dma_recovery();
#endif
#if !defined(MT6205B) && !defined(MT6208)
limiter = dma_gbl_class_to_grade[dma_gbl_class_g];
#ifdef MT6218B
for(index = 2; index <= DMA_MAX_CHANNEL; index++) {
#else /* MT6218B */
for(index = 1; index <= DMA_MAX_CHANNEL; index++) {
#endif /* MT6218B */
DRV_WriteReg32(DMA_LIMITER(index), limiter);
}
#endif
RestoreIRQMask(_savedMask);
}
#ifdef __DMA_UART_VIRTUAL_FIFO__
/*
* FUNCTION
* DMA_Vfifo_init
*
* DESCRIPTION
* DMA virtual FIFO
*
* CALLS
*
* PARAMETERS
* None
*
* RETURNS
* None
*
* GLOBALS AFFECTED
*/
void DMA_Vfifo_init(void)
{
kal_uint32 dma_con = 0;
if(UART_VFIFO_support[uart_port1])
{
// DMA10 for UART1 RX, DMA12 for UART1 TX
dma_con = (DMA_CON_MASTER_UART1RX << 20)|DMA_CON_DIR|DMA_CON_DRQ|DMA_CON_ITEN;
//DRV_WriteReg32(DMA_CON(VDMA_UART1RX_CH),dma_con);
DRV_WriteReg32(DMA_CON(UARTPort[uart_port1].Rx_DMA_Ch),dma_con);
dma_con = 0;
dma_con = (DMA_CON_MASTER_UART1TX << 20)|DMA_CON_DRQ;
//DRV_WriteReg32(DMA_CON(VDMA_UART1TX_CH),dma_con);
DRV_WriteReg32(DMA_CON(UARTPort[uart_port1].Tx_DMA_Ch),dma_con);
}
if(UART_VFIFO_support[uart_port2])
{
// DMA11 for UART2 Rx, DMA13 for UART2 TX
dma_con = (DMA_CON_MASTER_UART2RX << 20)|DMA_CON_DIR|DMA_CON_DRQ|DMA_CON_ITEN;
//DRV_WriteReg32(DMA_CON(VDMA_UART2RX_CH),dma_con);
DRV_WriteReg32(DMA_CON(UARTPort[uart_port2].Rx_DMA_Ch),dma_con);
dma_con = 0;
dma_con = (DMA_CON_MASTER_UART2TX << 20)|DMA_CON_DRQ;
//DRV_WriteReg32(DMA_CON(VDMA_UART2RX_CH),dma_con);
DRV_WriteReg32(DMA_CON(UARTPort[uart_port2].Tx_DMA_Ch),dma_con);
}
if(UART_VFIFO_support[uart_port3])
{
// DMA13 for UART3 Rx, DMA14 for UART3 TX
dma_con = (DMA_CON_MASTER_UART3RX << 20)|DMA_CON_DIR|DMA_CON_DRQ|DMA_CON_ITEN;
//DRV_WriteReg32(DMA_CON(VDMA_UART3RX_CH),dma_con);
DRV_WriteReg32(DMA_CON(UARTPort[uart_port3].Rx_DMA_Ch),dma_con);
dma_con = 0;
dma_con = (DMA_CON_MASTER_UART3TX << 20)|DMA_CON_DRQ;
//DRV_WriteReg32(DMA_CON(VDMA_UART3TX_CH),dma_con);
DRV_WriteReg32(DMA_CON(UARTPort[uart_port3].Tx_DMA_Ch),dma_con);
}
}
/*
* FUNCTION
* DMA_Vfifo_SetAdrs
*
* DESCRIPTION
* DMA virtual FIFO set address
*
* CALLS
*
* PARAMETERS
* None
*
* RETURNS
* None
*
* GLOBALS AFFECTED
*/
void DMA_Vfifo_SetAdrs(kal_uint32 adrs, kal_uint32 len, DMA_VFIFO_UART ch, kal_bool IsTx )
{
DRV_WriteReg32(DMA_PGMADDR(ch), adrs);
DRV_WriteReg32(DMA_FFSIZE(ch), len);
DRV_WriteReg32(DMA_ALTLEN(ch), DMA_VIFOF_ALERT_LENGTH); //maximum of alert threshold will effect the flow control
DRV_Reg(DMA_COUNT(ch)) = (IsTx)?DMA_TX_TRIGGER_LEVEL(len):DMA_RX_TRIGGER_LEVEL(len); // set trigger level for DMA interrupt
}
/*
* FUNCTION
* DMA_Vfifo_Flush
*
* DESCRIPTION
* Flushing DMA virtual FIFO
*
* CALLS
*
* PARAMETERS
* None
*
* RETURNS
* None
*
* GLOBALS AFFECTED
*/
void DMA_Vfifo_Flush(DMA_VFIFO_UART ch)
{
DMA_Stop(ch);
DMA_Start(ch);
}
#endif //__DMA_UART_VIRTUAL_FIFO__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -