📄 hdlcinit.c
字号:
if ( ((U32)(CRxBDPtr->BufferDataPtr) & BOwnership_DMA) ) {
// Step 4. Clear Ownership bit for DMA
DataBuffer = (U32)(CRxBDPtr->BufferDataPtr & BOwnership_CPU ) ;
// Step 5. Setup Rx DMA and Data buffer
if ( Dev->HDLC_Rx_Mode == MODE_DMA ) {
HDMARXBCNT(channel) = 0x0 ;
HDMARXMA(channel) = DataBuffer ;
HDMARXCNT(channel) = sizeof(sHDLCFrame) ;
HDMA_Rx_Enable(channel) ;
}
else {
ModeInt_RxDataBuffer[channel] = (U32 *)DataBuffer ;
ModeInt_RxDataSize[channel] = 0 ;
}
// Step 6. Receive enable
HDLC_Rx_Enable(channel) ;
return 1 ;
}
else return 0 ; // buffer full state, so can't use this buffer before get used
}
/*
* Function : SendHdlcFrame
* Description : Send HDLC frame
*/
int SendHdlcFrame(U32 channel, U8 *Data, int Size)
{
sBufferDescriptor *CTxBDPtr ;
HDLC_Device_Entry *Dev ;
U32 *DataBufferPtr ;
U8 *DataBuffer ;
// Step 1. Get device entry pointer
Dev = (HDLC_Device_Entry *)&HDLC_Dev[channel] ;
// Step 2. Get transmit buffer descriptor pointer
CTxBDPtr = (sBufferDescriptor *)pCTxBDPtr[channel] ;
// Step 3. Get data buffer pointer
DataBufferPtr = (U32 *)CTxBDPtr->BufferDataPtr ;
DataBuffer = (U8 *)CTxBDPtr->BufferDataPtr ;
// Step 4. Check DMA ownership, if setted to 1 then exit send frame
if ( ((U32)CTxBDPtr->BufferDataPtr & BOwnership_DMA) ) return 0 ;
// Step 5. Copy Tx frame data to frame buffer
CTxBDPtr->LengthField = Size ;
memcpy ((U8 *)DataBuffer,(U8 *)Data,Size);
#if 0
// debug message
Print("\r++< Tx=>BDP:%x, BD:%x, L:%d ", \
CTxBDPtr, CTxBDPtr->BufferDataPtr,Size) ;
#endif
// Step 6. Change ownership to DMA
CTxBDPtr->BufferDataPtr |= BOwnership_DMA;
// Step 7. Change current buffer descriptor pointer
pCTxBDPtr[channel] = (U32)CTxBDPtr->NextBufferDescriptor ;
// Step 8. Set HDLC transmit DMA or Transmit buffer
if ( Dev->HDLC_Tx_Mode == MODE_DMA ) {
// Setup HDLC transmit DMA
HDMA_Tx_init(channel,(U32)DataBufferPtr,Size) ;
HDMA_Tx_Enable(channel);
}
else {
// Setup transmit buffer and size to transmit
ModeInt_TxDataBuffer[channel] = (U8 *)DataBuffer ;
ModeInt_TxDataSize[channel] = Size ;
// Enable Transmit FIFO avaliable interrupt
HINTEN(channel) |= TxFAIE ;
}
return 1 ;
}
/*
* Function : WriteDataToFifo
* Description : Write frame data to HDLC Tx FIFO
* This function is used only interrupt mode transmit
*/
int WriteDataToFifo(U32 channel)
{
int i, j ;
U32 *Data ;
U8 *data ;
for (i=0 ; i<4 ; i++) {
if ( ModeInt_TxDataSize[channel] > 4 ) {
// Read data buffer pointer to transmit
Data = (U32 *)ModeInt_TxDataBuffer[channel] ;
// Write Tx frame data to FIFO
HTXFIFOC(channel) = *Data ;
// increase data pointer
ModeInt_TxDataBuffer[channel] += 4 ;
// decrement word
ModeInt_TxDataSize[channel] -= 4 ;
}
else {
// excuted when left transmit byte is 4 or under 4 byte
// Disable Transmit FIFO avaliable interrupt
HINTEN(channel) &= ~TxFAIE ;
if (ModeInt_TxDataSize[channel] == 4 ) {
// if lefted transmit data is 1 word, then write
// word data to HTXFIFOT register
Data = (U32 *)ModeInt_TxDataBuffer[channel] ;
HTXFIFOT(channel) = *Data ;
ModeInt_TxDataSize[channel] -= 4 ; // decrement word
} else {
// Get byte data pointer
data = (U8 *)ModeInt_TxDataBuffer[channel] ;
HDLCTXFIFOT = (U8 *)&HTXFIFOT(channel) ;
HDLCTXFIFOC = (U8 *)&HTXFIFOC(channel) ;
// process under 4 byte data
for ( j=0 ; j<4; j++) {
ModeInt_TxDataSize[channel] -- ;// decrement byte
if (ModeInt_TxDataSize[channel] > 0) {
*HDLCTXFIFOC = *data++ ;
}
else {
// end of frame data
*HDLCTXFIFOT = *data++ ;
break ;
}
}
}
return 0 ; // return end of frame transfer
}
}
return 1 ; // return not end of frame transfer
}
/*
* Function : ReadDataFromFifo
* Description : Read frame data from HDLC Rx FIFO
* This function is only used when interrupt mode receive
*/
int ReadDataFromFifo(U32 channel, U32 bcnt)
{
int i, cnt ;
cnt = (int)(((bcnt&~3)+4)/4) ;
ModeInt_RxDataSize[channel] += (bcnt+1) ;
for (i=0 ; i<cnt ; i++)
*ModeInt_RxDataBuffer[channel]++ = HRXFIFO(channel) ;
return 1 ;
}
/*
* Function : HDLCA_Isr
* Description : HDLC Interrupt service routine for channel A
*/
void HDLCA_isr(void)
{
sBufferDescriptor *CRxBDPtr, *CTxBDPtr ;
HDLC_Device_Entry *Dev ;
U32 RxLength, TxLength ;
U32 channel = HDLCA ;
U32 IntHdlcStatus ;
// 1. Get device entry pointer
Dev = (HDLC_Device_Entry *)&HDLC_Dev[channel] ;
// 2. Save current HDLC status
IntHdlcStatus = HSTAT(channel) ;
// 3. Process HDMA receive operation
// This routine is used when HDLC DMA mode receive operation
if ( IntHdlcStatus & ( DRxSTOP | DRxABT) ) {
if ( IntHdlcStatus & DRxSTOP ) {
gHdlcRxStatus[channel].DMARxStop++ ;
HSTAT(channel) |= DRxSTOP ;
}
else if ( IntHdlcStatus & DRxABT ) {
gHdlcRxStatus[channel].DMARxABT++ ;
HSTAT(channel) |= DRxABT ;
}
// Step 1. Get current receive buffer descriptor point
CRxBDPtr = (sBufferDescriptor *)gCRxBDPtr[channel];
// Step 2. Clear owner to CPU
CRxBDPtr->BufferDataPtr &= BOwnership_CPU ;
// Step 3. Get length and status
CRxBDPtr->LengthField = RxLength = HDMARXBCNT(channel) ;
CRxBDPtr->StatusField = IntHdlcStatus ;
// Step 4. Get Next buffer descriptor
gCRxBDPtr[channel] = (U32)CRxBDPtr->NextBufferDescriptor ;
// Step 5. Initialize HDLC DMA for receive
HDLC_Rx_init(channel) ;
}
// 4. Process HDLC receive operation
// This routine is used when HDLC interrupt mode receive operation
if (Dev->HDLC_Rx_Mode == MODE_INTERRUPT) {
if (IntHdlcStatus & (RxFA | RxFV | RxFERR) ) {
if (IntHdlcStatus & RxFA)
gHdlcRxStatus[channel].RxFIFOAvalable++ ;
if (IntHdlcStatus & (RxFV | RxFERR) ) {
if (IntHdlcStatus & RxFV)
gHdlcRxStatus[channel].RxLastFrameValid++ ;
if ( IntHdlcStatus & RxFERR )
gHdlcRxStatus[channel].RxFrameError++ ;
// Step 1. Read received data from HDLC receive FIFO entry
ReadDataFromFifo(channel,(HSTAT(channel)&0xF)) ;
// Step 2. Get current receive buffer descriptor point
CRxBDPtr = (sBufferDescriptor *)gCRxBDPtr[channel];
// Step 3. Clear owner to CPU
CRxBDPtr->BufferDataPtr &= BOwnership_CPU ;
// Step 4. Get length and status
CRxBDPtr->LengthField = RxLength =
ModeInt_RxDataSize[channel] ;
CRxBDPtr->StatusField = IntHdlcStatus ;
// Step 5. Get Next buffer descriptor
gCRxBDPtr[channel] = (U32)CRxBDPtr->NextBufferDescriptor ;
// Step 6. Initialize HDLC DMA for receive
HDLC_Rx_init(channel) ;
} else
// Read received data from HDLC receive FIFO entry
ReadDataFromFifo(channel, 15) ;
}
}
// 5. Save HDLC receive status
if ( IntHdlcStatus & ( RxOV|RxABT|RxAERR|RxFAP|RxFD|RxDCD|RxSDCD|RxIDLE) ) {
// HDLC Rx OverRun Error
if ( IntHdlcStatus & RxOV ) {
gHdlcRxStatus[channel].RxOverrun++ ;
HSTAT(channel) |= RxOV ;
// check all descriptor is used, then enable HDMA Rx
if ( gCRxBDPtr[channel] == pCRxBDPtr[channel] )
HDLC_Rx_init(channel) ;
}
if ( IntHdlcStatus & RxABT ) {
gHdlcRxStatus[channel].RxAbort++ ;
HSTAT(channel) |= RxABT ;
HDLC_Rx_init(channel) ;
}
if ( IntHdlcStatus & RxAERR )
gHdlcRxStatus[channel].RxAddressError++ ;
if (IntHdlcStatus & RxFAP)
gHdlcRxStatus[channel].RxFIFOAddrPresent++ ;
if (IntHdlcStatus & RxFD) {
gHdlcRxStatus[channel].RxFlagDetected++ ;
HSTAT(channel) |= RxFD ;
}
if (IntHdlcStatus & RxDCD)
gHdlcRxStatus[channel].RxLevelOfDCD++ ;
if (IntHdlcStatus & RxSDCD) {
gHdlcRxStatus[channel].RxTransitionOfDCD++ ;
HSTAT(channel) |= RxSDCD ;
}
if (IntHdlcStatus & RxIDLE) {
gHdlcRxStatus[channel].RxIdle++ ;
HSTAT(channel) |= RxIDLE ;
}
}
// 6. HDLC Transmit DMA mode Complete
if ( IntHdlcStatus & (DTxSTOP | DTxABT) ) {
if ( IntHdlcStatus & DTxSTOP ) {
gHdlcTxStatus[channel].DMATxStop++ ;
HSTAT(channel) |= DTxSTOP ;
}
if ( IntHdlcStatus & DTxABT ) {
gHdlcTxStatus[channel].DMATxABT++ ;
HSTAT(channel) |= DTxABT ;
}
do {
// Step 1. Get current transmit buffer descriptor pointer
// and length
CTxBDPtr = (sBufferDescriptor *)gCTxBDPtr[channel];
TxLength = CTxBDPtr->LengthField ;
// Step 2. Clear Length and Status field
CTxBDPtr->LengthField = (U32)0x0;
CTxBDPtr->StatusField = (U32)0x0;
// Step 3. Get Next buffer descriptor
gCTxBDPtr[channel] = (U32)CTxBDPtr->NextBufferDescriptor ;
// Step 4. Clear DMA owner to CPU
CTxBDPtr->BufferDataPtr &= BOwnership_CPU ;
} while (pCTxBDPtr[channel] == gCTxBDPtr[channel]) ;
}
// 7. HDLC Transmit Interrupt mode
if (Dev->HDLC_Tx_Mode == MODE_INTERRUPT) {
if (IntHdlcStatus & TxFA) {
gHdlcTxStatus[channel].TxFIFOAvailable++ ;
if ( ModeInt_TxDataSize[channel] > 0)
// Step 1. write 4 word frame data to FIFO
if ( !WriteDataToFifo(channel) ) {
// Step 2. Get current receive buffer descriptor point
CTxBDPtr = (sBufferDescriptor *)gCTxBDPtr[channel];
TxLength = CTxBDPtr->LengthField ;
// Step 3. Clear length and status field
CTxBDPtr->LengthField = (U32)0x0;
CTxBDPtr->StatusField = (U32)0x0;
// Step 4. Get Next buffer descriptor
gCTxBDPtr[channel] =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -