📄 idma.c
字号:
#include "bm8024.h"
#include "idma.h"
#include "ppc860cpm.h"
#include "ppc860siu.h"
volatile U32 immrValue;
U32 txBdIndex=0;
#define TXBD_INDEX_INCREASE(index) index = ((index + 1) % NO_IDMA_BD_TX)
#define BDRX_OFFSET 0x2c00
#define BDTX_OFFSET 0x2c30
/*
* get immr register value
*/
U32 ImmrGet(void)
{
unsigned long immr;
asm( "mfspr %0,638": "=r"(immr) : );
immr &= 0xFFFF0000;
return immr;
}
/*
* the entry of CPM's IDMA initialization.
*/
void IDMA_Init(void)
{
U32 i,bd_offset;
IDMA_PARAM *idmaBase;
IDMA_BD *pIBD;
immrValue = ImmrGet();
/* set up port B pin 22, 23 as DACK , direction: output*/
*PBPAR(immrValue) |= (PORTB_BIT23 | PORTB_BIT22);
*PBDIR(immrValue) |= (PORTB_BIT23 | PORTB_BIT22);
/* configure RISC controller configuration register*/
*RCCR(immrValue) |= (RCCR_DR1M_LEVEL | RCCR_DR0M_LEVEL) | (0x02<<4); /* fix the MPC850 bug */
/* initialization IDMA1 buffer descriptor, not finished*/
bd_offset = BDRX_OFFSET;
pIBD = (IDMA_BD *)(immrValue + bd_offset); /*start of the dual-port RAM address for IDMA1 BD*/
idmaBase = (IDMA_PARAM *)(immrValue + DPRAM_IDMA1_PARAM); /*3CC0*/
idmaBase->ibase = (U16)bd_offset;
idmaBase->dcmr = (DCMR_SIZE_WORD | DCMR_SD_RP_WM | DCMR_SC_SINGLE); /*read from peripheral , write to memory*/
/* to ensure the CPM is ideal now.*/
while(*CPCR(immrValue) & 0x0001)
{
/* wait for previous command complete */
}
*CPCR(immrValue) = 0x0511; /* initial IDMA1 channel */
for(i=0; i<NO_IDMA_BD_RX; i++) /* NO_IDMA_BD_RX = 0x01 */
{
pIBD[i].status = 0x0000;
pIBD[i].dfcr = SOURCE_FUNC_CODE;
pIBD[i].sfcr = DEST_FUNC_CODE;
pIBD[i].len = 0;
pIBD[i].sBuffer = 0;
pIBD[i].dBuffer = 0;
}
pIBD[NO_IDMA_BD_RX-1].status |= BD_WRAP_BIT;
*IDMR1(immrValue) = (IDSRx_DONE | IDSRx_OB);
*IDSR1(immrValue) = (IDSRx_DONE | IDSRx_OB | IDSRx_AD);
/* initialization IDMA2 buffer descriptor */
bd_offset = BDTX_OFFSET;
pIBD = (IDMA_BD *)(immrValue + bd_offset); /*start of the dual-port RAM address for IDMA2 BD*/
idmaBase = (IDMA_PARAM *)(immrValue + DPRAM_IDMA2_PARAM); /*3DC0*/
idmaBase->ibase = (U16)bd_offset;
idmaBase->dcmr = (DCMR_SIZE_WORD | DCMR_SD_RM_WP | DCMR_SC_DUAL);
/* issue command via CPCR to initialize IDMA parameters */
while(*CPCR(immrValue) & 0x0001)
{
/* wait for previous command complete */
}
*CPCR(immrValue) = 0x0551; /* initial IDMA2 channel */
for(i=0; i<NO_IDMA_BD_TX; i++) /*NO_IDMA_BD = 0x08 */
{
pIBD[i].status = 0x0000;
pIBD[i].dfcr = SOURCE_FUNC_CODE;
pIBD[i].sfcr = DEST_FUNC_CODE;
pIBD[i].len = 0;
pIBD[i].sBuffer = 0;
pIBD[i].dBuffer = 0;
}
pIBD[NO_IDMA_BD_TX-1].status |= BD_WRAP_BIT;
*IDMR2(immrValue) = (IDSRx_DONE | IDSRx_OB);
*IDSR2(immrValue) = (IDSRx_DONE | IDSRx_OB | IDSRx_AD);
/*
set up port C pin 14, 15 as DREQ0, DREQ1
*/
*PCPAR(immrValue) &= ~(PORTC_BIT14 | PORTC_BIT15);
*PCDIR(immrValue) &= ~(PORTC_BIT14 | PORTC_BIT15);
*PCSO(immrValue) |= (PORTC_BIT14 | PORTC_BIT15);
}
int setupWriteIDMA(U8 *sBuffer, U32 len ,U32 lastBufferFlag)
{
IDMA_PARAM *idmaBase;
IDMA_BD *pIBD;
/* Wait for DMA channel*/
if (lastBufferFlag)
semTake (acdDmaRdySem, WAIT_FOREVER);
idmaBase = (IDMA_PARAM *)(immrValue + DPRAM_IDMA2_PARAM);
pIBD = (IDMA_BD *)(immrValue + idmaBase->ibase);
if (pIBD[txBdIndex].status & BD_READY_BIT)
return IDMA_BUSY;
if (len%4)
len = 4*(len/4+1);
pIBD[txBdIndex].status |= BD_READY_BIT;
if (lastBufferFlag)
pIBD[txBdIndex].status |= BD_LAST_BIT;
pIBD[txBdIndex].len = len;
pIBD[txBdIndex].sBuffer = sBuffer;
TXBD_INDEX_INCREASE(txBdIndex);
return IDMA_OK;
}
void setupReadIDMA(U8 *dBuffer, U32 len)
{
IDMA_BD *pIBD;
IDMA_PARAM *idmaBase;
U8 status;
/* Wait for DMA channel*/
semTake (acdDmaRdySem, WAIT_FOREVER);
/* len must be 4 aligned */
if (len%4)
len = 4*(len/4 + 1);
status = *IDSR1(immrValue);
*IDSR1(immrValue) = status; /**clear the IDSR bits by writing ones**/
/*select IDMA1 channel*/
idmaBase = (IDMA_PARAM *)(immrValue + DPRAM_IDMA1_PARAM) ; /*3cc0*/
idmaBase->dcmr = (DCMR_SIZE_WORD | DCMR_SD_RP_WM | DCMR_SC_SINGLE);
pIBD = (IDMA_BD *)(immrValue + idmaBase->ibptr);
pIBD[0].status |= 0x8800;
pIBD[0].len = len;
pIBD[0].dBuffer = dBuffer;
}
U32 checkIDMADone(U32 channel)
{
U32 count =0;
volatile U32 status_idma;
while(count++< MAX_RETRY)
{
if(channel == CHANNEL_IDMA1)
status_idma = *IDSR1(immrValue);
else
status_idma = *IDSR2(immrValue);
if (status_idma & 0x02)
{
/* Release for DMA channel*/
semGive(acdDmaRdySem);
return ACD_SUCCESS;
}
}
/* Time out */
semGive(acdDmaRdySem);
stopReadIDMA(channel);
return ACD_ERROR;
}
void stopReadIDMA(U32 channel)
{
/* issue command via CPCR to initialize IDMA parameters*/
while(*CPCR(immrValue) & 0x0001)
{
/* wait for previous command complete*/
}
if(channel == CHANNEL_IDMA1)
*CPCR(immrValue) = 0x0B11; /* stop IDAM1 channel*/
else
*CPCR(immrValue) = 0x0B51;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -