📄 dma.c
字号:
return ERR_BADINPUT;
/*Set registers to correct channel*/
addrDMAByc0_1 = (nChannel == DMA_Channel0 ? DMA0BYC0_1 : DMA1BYC0_1);
addrDMAByc2 = (nChannel == DMA_Channel0 ? DMA0BYC2 : DMA1BYC2);
_SetEXRegByte(DMACLRBP, 0x0); /* Clear the byte pointer flip-flop */
/* Write count, bits 0-7 */
_SetEXRegByte(addrDMAByc0_1, (BYTE) ( lCount & 0xFF));
/* Write count, bits 8-15 */
_SetEXRegByte(addrDMAByc0_1, (BYTE) ((lCount >> 8) & 0xFF));
/* Write count, bits 16-23 */
_SetEXRegByte(addrDMAByc2, (BYTE) ((lCount >> 16) & 0xFF));
return ERR_NONE;
}
/*******************************************************************************
FUNCTION: void InitDMA()
DESCRIPTION:
This function enables the DMA and initializes settings independent of the
two channels:
bus arbitration--set to no rotation, external bus master request(HOLD)
assigned to lowest priority level
EOP# sampling--set to asynch. (no effect when DMA is used with internal
peripherals)
DRQn sampling--set to synch. (no effect when DMA is used with internal
peripherals)
PARAMETERS: (none)
RETURN: (none)
SYNTAX/USAGE:
InitDMA(); //Initialize DMA peripheral
ASSUMPTIONS:
REAL/PROTECTED MODE:
*******************************************************************************/
void InitDMA(void)
{
_SetEXRegByte(DMACLR, 0x0); /*Resets DMA peripheral*/
_SetEXRegByte(DMACMD1, 0x0); /*DMACMD1[7:5]=0: reserved*/
/*DMACMD1[4]=0: disable priority rotation enable*/
/*DMACMD1[2]=0: enable channel's 0 and 1*/
/*DMACMD1[1:0]=0: reserved*/
_SetEXRegByte(DMACMD2, 0x8); /*DMACMD2[7:4]=0: reserved*/
/*DMACMD2[3:2]=2: assign HOLD to the lowest*/
/* priority level*/
/*DMACMD2[1]=0: EOP# samples input async.*/
/*DMACMD2[0]=0: DRQn samples input async.*/
}
/*******************************************************************************
FUNCTION: void InitDMA1ForSSIXmitterToMem()
DESCRIPTION:
This function prepares DMA channel 1 for transfers between the async.
serial port transmitter (channel 0) and memory. After calling this
function, a DMA transfer can be initiated by setting the Target address,
setting the transfer count, and clearing the hardware request mask
for this DMA channel.
PARAMETERS: (none)
RETURN: (none)
SYNTAX/USAGE:
static char lpsz[]="Hello World";
InitDMA(); //Initialize DMA peripheral
InitDMA1ForSerialXmitter(); //Initialize DMA channel 1
.
.
.
SetDMATargMemAddr(DMA_Channel1, lpsz); //Set target memory address
//Set transfer count
SetDMAXferCount(DMA_Channel1, strlen(lpsz) );
EnableDMAHWRequests(DMA_Channel1); //Begin transfer at SIO request
ASSUMPTIONS:
InitDMA() has been called to enable the peripheral.
REAL/PROTECTED MODE:
*******************************************************************************/
void InitDMA1ForSerialXmitter(void)
{
BYTE regDMACfg;
BYTE regDMAIE;
BYTE regDMAOvfE;
DisableDMAHWRequests(DMA_Channel1); /*Disable channel 1 Hardware requests*/
regDMACfg = (_GetEXRegByte(DMACFG) & 0x0F) | 0xA0;
_SetEXRegByte(DMACFG, regDMACfg); /*DMACFG[7]=1: mask DMA Acknowledge for channel 1*/
/*DMACFG[6:4]=3: set channel request to SIO*/
/* channel 0's transmit buffer empty signal*/
/*DMAMSK[3:0]=unmodified: channel 0 settings*/
_SetEXRegByte(DMAMOD1, 0x9); /*DMAMOD1[7:6]=0: set to demand data-xfer mode*/
/*DMAMOD1[5]=0: increment target*/
/*DMAMOD1[4]=0: disable autoinitialize buffer-xfer*/
/* mode*/
/*DMAMOD1[3:2]=2: data is xfer'd from targ. to req.*/
/*DMAMOD1[1]=0: reserved*/
/*DMAMOD1[0]=1: selections for bits 7-2 affect */
/* channel 1*/
_SetEXRegByte(DMAMOD2, 0xD1); /*DMAMOD2[7]=1: Select 2-cycle data xfer*/
/*DMAMOD2[6]=1: Requestor is in I/O space*/
/*DMAMOD2[5]=0: Target is in memory space*/
/*DMAMOD2[4]=1: Requestor is held constant thru xfer*/
/*DMAMOD2[3]=x: Req. Inc/Dec...see DMAMOD2[4]*/
/*DMAMOD2[2]=0: Target address is modified...see*/
/* DMAMOD1[5]*/
/*DMAMOD2[1]=0: reserved*/
/*DMAMOD2[0]=1: selections for bits 7-2 affect */
/* channel 1*/
_SetEXRegByte(DMABSR, 0x51); /*DMABSR[7]=0: reserved*/
/*DMABSR[6]=1: sets req.'s bus size to 8-bit*/
/*DMABSR[5]=0: reserved*/
/*DMABSR[4]=1: sets targ.'s bus size to 8-bit*/
/*DMABSR[3:2]=0: reserved*/
/*DMABSR[0]=1: selections for bits 7-2 affect */
/* channel 1*/
_SetEXRegByte(DMACHR, 0x1); /*DMACHR[7:3]=0: reserved*/
/*DMACHR[2]=0: disable chaining buffer-xfer mode*/
/*DMACHR[1]=0: reserved*/
/*DMACHR[0]=1: selections for bits 7-2 affect */
/* channel 1*/
regDMAIE = _GetEXRegByte(DMAIEN) & 0xFD;
_SetEXRegByte(DMAIEN, regDMAIE); /*DMAIE[7:2]=untouched: reserved*/
/*DMAIE[1]=0: masks channel 1's transfer complete*/
/* signal from interrupt controller*/
/*DMAIE[0]=untouched: channel 0 setting*/
regDMAOvfE = _GetEXRegByte(DMAOVFE) | 0xC;
_SetEXRegByte(DMAOVFE, regDMAOvfE); /*DMAOVFE[7:4]=untouched: reserved*/
/*DMAOVFE[3]=1: all bits of channel 1 req. address */
/* are inc/dec (see DMAMOD[4])*/
/*DMAOVFE[2]=1: all bits of channel 1 targ. address*/
/* are inc/dec*/
/*DMAOVFE[1:0]=untouched: channel 0 settings*/
SetDMAReqIOAddr(DMA_Channel1, TBR0); /*Sets Req. I/O address to Serial Receiver*/
}
/*******************************************************************************
FUNCTION: void interrupt far DMAInterrupt(void)
DESCRIPTION:
This function is called by the DMA unit when it either completes a
transfer or (in chaining xfer mode) when a new requester, target, and
byte count should be written to the device.
PARAMETERS: (none)
RETURN: (none)
SYNTAX/USAGE:
regDMAIE = _GetEXRegByte(DMAIEN) | 0x2; //Enable tc interrupt for channel 0
_SetEXRegByte(DMAIEN, regDMAIE);
//Set interrupt routine
SetIRQVector(DMAInterrupt, 12, INTERRUPT_ISR);
Enable8259Interrupt(0, IR4); //Enable slave IR4, DMA interrupt
NonSpecificEOI(); //Clear all interrupts
ASSUMPTIONS:
REAL/PROTECTED MODE:
*******************************************************************************/
void interrupt far DMAInterrupt(void)
{
WORD regDMAIS;
regDMAIS = _GetEXRegByte(DMAIS); /*Get interrupt status register*/
if (regDMAIS & 0x10)
{ /*Transfer Complete, channel 0*/
_SetEXRegByte(DMACLRTC, 0x00); /*Clear transfer complete signal*/
}
if (regDMAIS & 0x20)
{ /*Transfer Complete, channel 1*/
_SetEXRegByte(DMACLRTC, 0x00); /*Clear transfer complete signal*/
}
if (regDMAIS & 0x1)
{ /*Chaining Interrupt, channel 0*/
}
if (regDMAIS & 0x2)
{ /*Chaining Interrupt, channel 1*/
}
NonSpecificEOI(); /*Send End-Of-Interrupt Signal to Master/Slave*/
}
/* APB_BLOCK_END */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -