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 + -
显示快捷键?