comm.c
来自「S3C24A0的完整BSP包,对开发此芯片的开发者很有用.」· C语言 代码 · 共 1,352 行 · 第 1/3 页
C
1,352 行
bytesAtATime = MIN(S24A0UART_FIFO_SIZE -32, (NumberOfBytes ));
// bytesAtATime = MIN(8, (NumberOfBytes ));
}
else {
bytesAtATime = 1;
}
#endif
bytesAtATime = 1;
cp = pTxBuffer = &(portInfo->writeBuf[thisDev->portInfo.writeBufPos]);
/*
* Wait for ready-to-send.
*/
#if 0
i=0;
do {
rFifoStat = INREG(UFSTAT);
TxFifoCnt = ((rFifoStat & SER24A0_TX_FIFOCNT_MASK) >> 8);
} while ((TxFifoCnt ) && (++i < maxLoops));
if (TxFifoCnt){
RETAILMSG(1,(TEXT("TxFifoCnt break")));
break;
}
for (i = 0; i < bytesAtATime; i++){
c = *pTxBuffer++;
(g_pComm1Reg->UTXH) =c;
RETAILMSG(1,(TEXT(" %x"),c));
}
#else
bytesAtATime = 1;
c= *pTxBuffer++;
(g_pComm1Reg->UTXH) =c;
for ( i = 0; i < 600000; i++ ) {
tmpreg = INREG(UTRSTAT);
if ( tmpreg & 0x4 ) break;
}
if ( i == 600000 )
{
RETAILMSG (1, (TEXT("SL_TxInt : Error : i = %d \r\n"), i));
break;
}
#endif
// DBGOUT((TEXT("TxFifo clear")));
/*
* Send the next byte or FIFO-volume of bytes.
*/
#if 0
#endif
thisDev->portInfo.writeBufPos+= bytesAtATime;
#if 0
for (i = 0; i < bytesAtATime; i++){
RETAILMSG(1,(TEXT(" %x"),*cp++));
if(i%16 == 15)
RETAILMSG(1,(TEXT("\r\n")));
}
#endif
// DBGOUT((TEXT(" dONE")));
}
#if 0
i = 0;
do {
rFifoStat = INREG(UFSTAT);
TxFifoCnt = ((rFifoStat & SER24A0_TX_FIFOCNT_MASK) >> 8);
} while ((TxFifoCnt ) && (++i < maxLoops));
if (TxFifoCnt){
RETAILMSG(1,(TEXT("TxFifoCnt break %d"),TxFifoCnt));
g_pComm1Reg->UFCON |= (1<<2);
}
#endif
// RETAILMSG(1,(TEXT("TxFifoCnt break LoopCount %d\r\n"),i));
// g_pComm1Reg->UFCON |= (1<<2);
g_pComm1Reg->UFCON |= 3;
/*
* The return value will indicate whether we've sent the entire frame.
*/
#if 1
if (thisDev->portInfo.writeBufPos >= thisDev->portInfo.writeBufLen){
// CLEARREG(UCON , (3<<2)); //Disable tx
if (thisDev->setSpeedAfterCurrentSendPacket){
/*
* We'll be changing speeds after this packet,
* so poll until the packet bytes have been completely sent out the FIFO.
* After the 16550 says that it is empty, there may still be one remaining
* byte in the FIFO, so flush it out by sending one more BOF.
*/
DBGOUT((TEXT(" Sending one extr bof")));
(g_pComm1Reg->UTXH) = SLOW_IR_EXTRA_BOF;
i = 0;
do {
rFifoStat = INREG(UFSTAT);
TxFifoCnt = ((rFifoStat & SER24A0_TX_FIFOCNT_MASK) >> 8);
} while ((TxFifoCnt ) && (++i < maxLoops));
}
result = TRUE;
}
else {
result = FALSE;
}
#endif
DBGOUT((TEXT("StepSendFSM wrote %d bytes (%s):"), (UINT)(thisDev->portInfo.writeBufPos-startPos), (PUCHAR)(result ? "DONE" : "not done")));
return result;
}
/*
*************************************************************************
* StepReceiveFSM
*************************************************************************
*
*
* Step the receive fsm to read in a piece of an IR frame;
* strip the BOFs and EOF, and eliminate escape sequences.
* Return TRUE only after an entire frame has been read in.
*
*/
BOOLEAN StepReceiveFSM(IrDevice *thisDev)
{
UINT rawBufPos, rawBytesRead;
BOOLEAN result;
UCHAR thisch;
PLIST_ENTRY pListEntry;
while ((thisDev->portInfo.rcvState != STATE_SAW_EOF) && (thisDev->portInfo.readBufPos <= MAX_RCV_DATA_SIZE)){
if (thisDev->portInfo.rcvState == STATE_CLEANUP){
/*
* We returned a complete packet last time, but we had read some
* extra bytes, which we stored into the rawBuf after returning
* the previous complete buffer to the user.
* So instead of calling DoRcvDirect in this first execution of this loop,
* we just use these previously-read bytes.
* (This is typically only 1 or 2 bytes).
*/
rawBytesRead = thisDev->portInfo.readBufPos;
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->portInfo.readBufPos = 0;
}
else {
rawBytesRead = DoRcvDirect(thisDev, thisDev->portInfo.rawBuf, S24A0UART_FIFO_SIZE);
if (rawBytesRead == (UINT)-1){
/*
* Receive error occurred. Go back to INIT state.
*/
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->portInfo.readBufPos = 0;
continue;
}
else if (rawBytesRead == 0){
/*
* No more receive bytes. Break out.
*/
break;
}
}
/*
* Let the receive state machine process this group of characters
* we got from the FIFO.
*
* NOTE: We have to loop once more after getting MAX_RCV_DATA_SIZE
* bytes so that we can see the 'EOF'; hence <= and not <.
*/
for (rawBufPos = 0;
((thisDev->portInfo.rcvState != STATE_SAW_EOF) &&
(rawBufPos < rawBytesRead) &&
(thisDev->portInfo.readBufPos <= MAX_RCV_DATA_SIZE));
rawBufPos++){
thisch = thisDev->portInfo.rawBuf[rawBufPos];
switch (thisDev->portInfo.rcvState){
case STATE_INIT:
switch (thisch){
case SLOW_IR_BOF:
thisDev->portInfo.rcvState = STATE_GOT_BOF;
break;
case SLOW_IR_EOF:
case SLOW_IR_ESC:
default:
/*
* This is meaningless noise. Scan past it.
*/
break;
}
break;
case STATE_GOT_BOF:
switch (thisch){
case SLOW_IR_BOF:
break;
case SLOW_IR_EOF:
/*
* Garbage
*/
DBGERR((TEXT("EOF in absorbing-BOFs state in DoRcv")));
thisDev->portInfo.rcvState = STATE_INIT;
break;
case SLOW_IR_ESC:
/*
* Start of data.
* Our first data byte happens to be an ESC sequence.
*/
thisDev->portInfo.readBufPos = 0;
thisDev->portInfo.rcvState = STATE_ESC_SEQUENCE;
break;
default:
thisDev->portInfo.readBuf[0] = thisch;
thisDev->portInfo.readBufPos = 1;
thisDev->portInfo.rcvState = STATE_ACCEPTING;
break;
}
break;
case STATE_ACCEPTING:
switch (thisch){
case SLOW_IR_BOF:
/*
* Meaningless noise, ignore
*/
DBGWARN((TEXT("WARNING: BOF during accepting state in DoRcv")));
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->portInfo.readBufPos = 0;
break;
case SLOW_IR_EOF:
if (thisDev->portInfo.readBufPos <
IR_ADDR_SIZE+IR_CONTROL_SIZE+SLOW_IR_FCS_SIZE){
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->portInfo.readBufPos = 0;
}
else {
thisDev->portInfo.rcvState = STATE_SAW_EOF;
}
break;
case SLOW_IR_ESC:
thisDev->portInfo.rcvState = STATE_ESC_SEQUENCE;
break;
default:
thisDev->portInfo.readBuf[thisDev->portInfo.readBufPos++] = thisch;
break;
}
break;
case STATE_ESC_SEQUENCE:
switch (thisch){
case SLOW_IR_EOF:
case SLOW_IR_BOF:
case SLOW_IR_ESC:
/*
* ESC + {EOF|BOF|ESC} is an abort sequence
*/
DBGERR((TEXT("DoRcv - abort sequence; ")
TEXT("ABORTING IR PACKET: (got following ")
TEXT("packet + ESC,%xh)"),
(UINT)thisch));
DBGPRINTBUF(thisDev->portInfo.readBuf, thisDev->portInfo.readBufPos);
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->portInfo.readBufPos = 0;
break;
case SLOW_IR_EOF^SLOW_IR_ESC_COMP:
case SLOW_IR_BOF^SLOW_IR_ESC_COMP:
case SLOW_IR_ESC^SLOW_IR_ESC_COMP:
thisDev->portInfo.readBuf[thisDev->portInfo.readBufPos++] = thisch ^ SLOW_IR_ESC_COMP;
thisDev->portInfo.rcvState = STATE_ACCEPTING;
break;
default:
DBGERR((TEXT("Unnecessary escape sequence: (got following packet + ESC,%xh"), (UINT)thisch));
DBGPRINTBUF(thisDev->portInfo.readBuf, thisDev->portInfo.readBufPos);
thisDev->portInfo.readBuf[thisDev->portInfo.readBufPos++] = thisch ^ SLOW_IR_ESC_COMP;
thisDev->portInfo.rcvState = STATE_ACCEPTING;
break;
}
break;
case STATE_SAW_EOF:
default:
DBGERR((TEXT("Illegal state in DoRcv")));
thisDev->portInfo.readBufPos = 0;
thisDev->portInfo.rcvState = STATE_INIT;
return 0;
}
}
}
/*
* Set result and do any post-cleanup.
*/
switch (thisDev->portInfo.rcvState){
case STATE_SAW_EOF:
/*
* We've read in the entire packet.
* Queue it and return TRUE.
*/
DBGOUT((TEXT(" *** DoRcv returning with COMPLETE packet, read %d bytes ***"),
thisDev->portInfo.readBufPos));
ASSERT(!IsListEmpty(&thisDev->rcvBufBuf));
#if COMM_DEBUG
{
int i;
RETAILMSG(1,(TEXT("Rx")));
for (i=0;i<thisDev->portInfo.readBufPos;i++) {
RETAILMSG(1,(TEXT("%2x "),thisDev->portInfo.readBuf[i]));
}
RETAILMSG(1,(TEXT("\r\n")));
}
#endif
QueueReceivePacket(thisDev, thisDev->portInfo.readBuf, thisDev->portInfo.readBufPos, FALSE);
// The protocol has our buffer. Get a new one.
pListEntry = RemoveHeadList(&thisDev->rcvBufBuf);
thisDev->portInfo.readBuf = LIST_ENTRY_TO_RCV_BUF(pListEntry);
result = TRUE;
if (rawBufPos < rawBytesRead){
/*
* We have some more unprocessed bytes in the raw buffer.
* Move these to the beginning of the raw buffer
* go to the CLEANUP state, which indicates that these
* bytes be used up during the next call.
* (This is typically only 1 or 2 bytes).
* Note: We can't just leave these in the raw buffer because
* we might be supporting connections to multiple COM ports.
*/
memcpy(thisDev->portInfo.rawBuf, &thisDev->portInfo.rawBuf[rawBufPos], rawBytesRead-rawBufPos);
thisDev->portInfo.readBufPos = rawBytesRead-rawBufPos;
thisDev->portInfo.rcvState = STATE_CLEANUP;
}
else {
thisDev->portInfo.rcvState = STATE_INIT;
}
break;
default:
if (thisDev->portInfo.readBufPos > MAX_RCV_DATA_SIZE){
DBGERR((TEXT("Overrun in DoRcv : read %d=%xh bytes:"),
thisDev->portInfo.readBufPos, thisDev->portInfo.readBufPos));
DBGPRINTBUF(thisDev->portInfo.readBuf, thisDev->portInfo.readBufPos);
thisDev->portInfo.readBufPos = 0;
thisDev->portInfo.rcvState = STATE_INIT;
}
else {
DBGOUT((TEXT("DoRcv returning with partial packet, read %d bytes"),
thisDev->portInfo.readBufPos));
}
result = FALSE;
break;
}
return result;
}
/*
*************************************************************************
* COM_ISR
*************************************************************************
*
*
*/
VOID COM_ISR(IrDevice *thisDev, BOOLEAN *claimingInterrupt, BOOLEAN *requireDeferredCallback)
{
comPortInfo *portInfo = &thisDev->portInfo;
ULONG IntPndVal=0;
ULONG IntSubPndVal=0;
DEBUGFIR(1,(_T("COM_ISR Called\r\n")));
try {
IntPndVal = *(portInfo->UART_INTSRCPND);
IntSubPndVal = *(portInfo->UART_INTSUBSRCPND);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
RETAILMSG(1, (TEXT("ACCESS VIOLATION ERROR \r\n")));
IntPndVal = SER24A0_INT_INVALID; // simulate no interrupt
}
ClearSubINTPnd(portInfo, portInfo->bTxINT | portInfo->bRxINT | portInfo->bErrINT);
ClearINTPnd(portInfo, portInfo->bINT);
DEBUGFIR(1,(_T("COM_ISR Intsrc pnd %x subsrcpnd %x \r\n"),IntPndVal,IntSubPndVal));
if ( (IntPndVal & (portInfo->bINT)) == 0 ){
DEBUGFIR(1,(_T("COM_ISR No interrupt pending at all..\r\n")));
/*
* This is NOT our interrupt.
* Set carry bit to pass the interrupt to the next driver in the chain.
*/
*claimingInterrupt = *requireDeferredCallback = FALSE;
}
else
{
/*
* This is our interrupt
*/
/*
* In some odd situations, we can get interrupt bits that don't
* get cleared; we don't want to loop forever in this case, so keep a counter.
*/
UINT loops = 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?