📄 hdlc100init.c
字号:
// not first buffer in frame /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// U32 * fptr; // pointer to first buffer int flen; // fptr = (U32 *) ((U32) HDLCRxUserFirst[cn] | NonCache); if(fptr == ((U32 *) -1)) { Print("\nHDLC Rx Internal error"); return(0); } if(fptr >= end) { fptr = start; } // rotate to queue begin *fptr |= ((status & 0xFFFF) << 16); flen = *fptr & 0xFFFF; *fptr = (*fptr & 0xFFFF0000) | (len & 0xFFFF); len -= flen; if((status & HDLCRxBD_L) != 0) {// last buffer => clear pointer to first /////////////////////////////////////// HDLCRxUserFirst[cn] = (U32 *) -1; // clear first pointer } }// source address ////////////////////////////////////////////////////////////// data = ((U32 *) buf); wlen = (len + 3) / 4; if(ptr >= end) { ptr = start; } // rotate to queue start while(wlen-- > 0) { *ptr++ = *data++; // if(ptr >= end) { ptr = start; } // rotate to queue start dcnt += 1; // bytes is writen } HDLCRxUserCount[cn]+= dcnt; // bytes in queue HDLCRxUserWrite[cn] = ptr; // reset write position return(1);}#endif // USER_AREA#ifdef USER_AREAint HDLCRecv(int cn, U32 * status, U8 * buf, int * size){ U32 intbit; U32 * data; U32 * start; // queue start address U32 * end; // queue end address U32 * ptr; // read pointer int len; // data length, bytes int wlen; // int wsize; // int dcnt = 0; Disable_Int(nGLOBAL_INT); if(HDLCRxUserCount[cn] < 1) { Enable_Int(nGLOBAL_INT); return(0); } start = (U32 *) ((U32) HDLCRxUserArea[cn] | NonCache); // queue start pointer ptr = (U32 *) ((U32) HDLCRxUserRead[cn] | NonCache); // queue read pointer end = start + HDLC_USER_AREA_SIZE; // queue end pointer if(ptr >= end) { ptr = start; } *status = (*ptr >> 16) & 0xFFFF; // read status if((*status & HDLCRxBD_L) == 0) {// last bit not set => wait Rx last buffer ///////////////////////////////////// Enable_Int(nGLOBAL_INT); return(0); } len = *ptr & 0xFFFF; // read length if(++ptr >= end) { ptr = start; } // rotate read pointer to queue start// read words from queue /////////////////////////////////////////////////////// dcnt = 1; // readed header data = (U32 *) buf; wlen = len >> 2; // frame length, full words wsize = *size >> 2; // buffer size, full words while(wlen-- > 0) { if(wsize-- > 0) { *data++ = *ptr; // }// dcnt++; // readed words from queue ptr++; // move pointer if(ptr >= end) { ptr = start; } // rotate read pointer to queue start } if((len & 0x3) != 0) { wlen = len & 0xFFFFFFFC; // dst pos wsize = *ptr; // read word from queue if(++ptr >= end) { ptr = start; } // rotate read pointer to start dcnt++; // readed words // while(wlen < len) { if(wlen >= *size) { break; } *(buf + wlen++) = (U8) wsize & 0xFF; wsize >>= 8; } } *size = len; // frame length HDLCRxUserCount[cn]-= dcnt; // words in queue HDLCRxUserRead[cn] = ptr; // reset read pointer Enable_Int(nGLOBAL_INT); return(1);}#elseint HDLCRecv(int cn, U32 * status, U8 * buf, int * size){ sHDLCBD * bd; // current Rx BD U32 stat; // BD status int cnt; // BD count int num; // BD number int flen; // total length int len; // length U32 * dst; // destination address U32 * src; // source address int wlen; // length, words int pos; // destination position if(cn < 0 || cn > 1 || status == 0 || buf == 0 || size == 0) { // invalid channel number, data buffer return(-1); // or data length ... } cnt = gHDLCRxCount[cn]; // Rx BD count if(cnt == 0) { // no Rx data return(0); } else if(cnt < 0) { Print("\nHDLCRecv internal error. Rx BD count < 0"); return(-1); } bd = (sHDLCBD *) gHDLCRxStart[cn]; for(num = 0; num < cnt; ++num) { if(bd == 0) { // Null terminating List Print("\nHDLCRecv error, BD == 0"); return(-1); } if((bd->BufferDataPtr & HDLCRxBD_DMA)) { // owner DMA return(0); // }// read status & check last BD in frame bit stat = (bd->StatusLength >> 16) & 0xffff; if((stat & HDLCRxBD_L) != 0 || (num > 0 && (stat & HDLCRxBD_F))) { // last BD in frame, or ommit last BD break; // } bd = bd->Next; } if(num >= cnt) { // no last BD in frame return(0); }// bd = (sHDLCBD *) gHDLCRxStart[cn]; // start buffer descriptor *status = 0; // frame status flen = 0; // frame length pos = 0; // destination buffer position for(num = 0; num < cnt; ++num) { int tmp; if(bd->BufferDataPtr & HDLCRxBD_DMA) { // owner DMA Print("\nHDLCRecv internal error. Unexpected DMA bit."); return(0); }// read BD status, data length stat = (bd->StatusLength >> 16) &0xffff; len = (bd->StatusLength & 0xFFFF); if(num > 0 && (stat & HDLCRxBD_F)) { // find first BD, ommit last BD break; } *status |= stat; // frame status// tmp = flen; flen = len; // total length len -= tmp; if(len < 0) { Print("\nHDLCRecv internal error. Length < 0"); return(-1); } // wlen = (len >> 2); dst = (U32 *)(buf + pos); src = (U32 *) bd->BufferDataPtr; while(wlen-- > 0) { pos += 4; if(pos <= *size) { *dst++ = *src++; } } if((len & 0x3) != 0) { U8 * bsrc; wlen = len & 0xFFFFFFFC; bsrc = (U8 *) bd->BufferDataPtr + wlen; while(wlen++ < len) { if(pos < *size) { *(buf + pos) = *bsrc++; } pos++; } } bd->Reserved = 0; // clear BD reserved field bd->StatusLength = 0; // clear status & length field bd->BufferDataPtr |= HDLCRxBD_DMA; // owner DMA bd = bd->Next; // move to next descriptor if((stat & HDLCRxBD_L)) { // last BD in frame break; } }// save frame length *size = flen; Disable_Int(nGLOBAL_INT); // disable global int gHDLCRxCount[cn]-= (num + 1); // decrement Rx BD count gHDLCRxStart[cn] = (U32) bd; // move start BD // enable DMA Rx, may be cleared if ovner of current Rx decriptor is CPU HCON(cn) |= HCON_DRxEN; // enable DMA Rx Enable_Int(nGLOBAL_INT); // enable global int return(1);}#endif // USER_AREA#ifdef HDLC_RX_ISR_DEBUG#define HDLCRx_isr_debug(ch) put_byte(ch)#else#define HDLCRx_isr_debug(ch)#endif // HDLC_RX_ISR_DEBUGvoid HDLCRx_isr(int cn){ U32 stat; // HDLC channel status U32 clear; // cleared bits stat = HSTAT(cn); // read HDLC status register clear = 0; // start cleared bits #ifdef HDLC_RX_ISR_DEBUG HDLCRxStatus[cn].RxISR++;#endif // HDLC_RX_ISR_DEBUG HDLCRx_isr_debug('R'); if(stat & HSTAT_DRxFD) {////////////////////////////////////////////////////////////////////////////////// [24] DMA Rx frame done every received frame (DRxFD) ///////////////////////////////////////////////////////////////////////////////////////////////////////// sHDLCBD * bd; U32 status; U32 len; int i; HDLCRx_isr_debug('D'); clear |= HSTAT_DRxFD; // clear DMA Rx frame done bit HDLCRxStatus[cn].DRxFD++; // DMA Rx frame done statistics bd = (sHDLCBD *) gHDLCRxEnd[cn]; // end buffer descriptor for(i = 0; i < HDLC_MAX_RX_DES; ++i) { if((bd->BufferDataPtr & HDLCRxBD_DMA) != 0) {// descriptor owner DMA (not CPU) => break ///////////////////////////////////// break; } if((U32)bd == HDMARXPTR(cn)) { break; } status = (bd->StatusLength >> 16) &0xffff; // read status len = bd->StatusLength & 0xffff; // read length if( status & ( HDLCRxBD_CD | // CD lost HDLCRxBD_CRC | // CRC error HDLCRxBD_NO | // Non octet alignment HDLCRxBD_OV | // Overun HDLCRxBD_DTM | // DPLL two miss occurs HDLCRxBD_ABT | // received frame abborted HDLCRxBD_FLV // frame length violation ) ) {// Rx frame error ////////////////////////////////////////////////////////////// if((status & HDLCRxBD_CRC) != 0) { HDLCRxStatus[cn].RxCRCE++; // Rx CRC Error } if((status & HDLCRxBD_NO) != 0) { HDLCRxStatus[cn].RxNO++; // Rx Non Octet } if((status & HDLCRxBD_OV) != 0) { HDLCRxStatus[cn].RxOV++; // Rx Overrun } if((status & HDLCRxBD_ABT) != 0) { HDLCRxStatus[cn].RxABT++; // Rx Abort } if((status & HDLCRxBD_FLV) != 0) { HDLCRxStatus[cn].RxFV++; // Rx Frame Valid } if((status & HDLCRxBD_DTM) != 0) { HDLCDPLLStatus[cn].DPLLTM++; } } // save Rx buffer (not frame) ////////////////////////////////////////////////// #ifdef USER_AREA GetRxBDData(cn, bd->BufferDataPtr, status, len); // clear BD fields and move to next BD ///////////////////////////////////////// bd->Reserved = 0; // clear BD reserved field bd->StatusLength = 0; // clear status & length field bd->BufferDataPtr |= HDLCRxBD_DMA; // owner DMA#else gHDLCRxCount[cn]++;#endif // USER_AREA bd = bd->Next; // to next BD } gHDLCRxEnd[cn] = (U32) bd; // set end Rx BD gHDLCRxDone = (0x1 << cn); // set Rx done channel bit }// [9] Rx FIFO available (RxFA) //////////////////////////////////////////////// if(stat & HSTAT_RxFA) { HDLCRxStatus[cn].RxFA++; // Rx FIFO Avail clear |= HSTAT_RxFA; // clear Rx FIFO Available bit HDLCRx_isr_debug('A'); }// [11] Rx flag detected (RxFD) //////////////////////////////////////////////// if(stat & HSTAT_RxFD) { U32 hinten; HDLCRxStatus[cn].RxFD++; // Rx Flag Detect statistics clear |= HSTAT_RxFD; // clear Rx Flag detect bit hinten = HINTEN(cn); if(hinten & HINTEN_RxFDIE) {/* clear flag detect int enable set idle detect int enable */ HINTEN(cn) = ((hinten &
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -