wince串口线程、中断等相关学习(作者:wogoyixikexie@gliet)

来源:互联网 发布:免费的vpn软件 编辑:程序博客网 时间:2024/05/18 00:19
前面发了好几篇wince串口的学习的文章,由于是学习性质的,弄的比较乱,还请网友们原谅。以前只是搞懂了大体框架,对这个中断线程等底层的东西还没有了解,现在来来学习一下。# VOID# SerialEventHandler(PHW_INDEP_INFO pSerialHead)# {# PHW_VTBL pFuncTbl = pSerialHead->pHWObj->pFuncTbl;# PVOID pHWHead = pSerialHead->pHWHead;# ULONG CharIndex;# ULONG RoomLeft = 0;# ULONG TotalLeft = 0;# INTERRUPT_TYPE it = INTR_NONE;# BOOL RxDataAvail = FALSE;## DEBUGMSG (ZONE_THREAD, (TEXT("+SerialEventHandler, pHead 0x%X/r/n"),# pSerialHead));## if ( pSerialHead->KillRxThread ||# !pSerialHead->hSerialEvent ) {# DEBUGMSG (ZONE_THREAD, (TEXT("Exitting thread/r/n")));# SetEvent(pSerialHead->hKillDispatchThread);# ExitThread(0);# }## // NOTE - This one is a little tricky. If the only owner is a monitoring task# // then I don't have an owner for read/write, yet I might be in this routine# // due to a change in line status. Lets just do the best we can and increment# // the count for the access owner if available.# if ( pSerialHead->pAccessOwner )# COM_INC_USAGE_CNT(pSerialHead->pAccessOwner);## while ( 1 ) {## if ( !(it = pFuncTbl->HWGetIntrType(pHWHead)) ) {# DEBUGMSG (ZONE_THREAD,# (TEXT("SerialEventHandler, No Interrupt./r/n")));# break;# }## DEBUGMSG (ZONE_THREAD,# (TEXT("SerialEventHandler, Interrupts 0x%X/r/n"), it));# if ( it & INTR_RX ) {# // It's read data event. Optimize the read by reading chunks# // if the user has not specified using xflow control# // or event/error/eof characters. Ack the receive,# // unmask the interrupt, get the current data pointer# // and see if data is available.# // Note: We have to copy RxRead and RxWrite index to local in order to make it atomic.# register DWORD RxWIndex=RxWrite(pSerialHead), RxRIndex=RxRead(pSerialHead);## DEBUGMSG (ZONE_THREAD|ZONE_READ , (TEXT("Rx Event/r/n")));## if ( RxRIndex == 0 ) {# // have to leave one byte free.# RoomLeft = RxLength(pSerialHead) - RxWIndex - 1;# } else {# RoomLeft = RxLength(pSerialHead) - RxWIndex;# }# if ( RxRIndex > RxWIndex ) {# RoomLeft = RxRIndex - RxWIndex - 1;# }# if ( RoomLeft ) {# pSerialHead->DroppedBytesPDD +=# pFuncTbl->HWRxIntrHandler(pHWHead,# RxBuffWrite(pSerialHead),# &RoomLeft);# } else {# BYTE TempBuf[16];# RoomLeft = 16;# pFuncTbl->HWRxIntrHandler(pHWHead,# TempBuf,# &RoomLeft);## pSerialHead->DroppedBytesMDD += RoomLeft;# DEBUGMSG (ZONE_WARN|ZONE_READ, (TEXT("Tossed %d bytes/r/n"),# RoomLeft));# RoomLeft = 0;# }## DEBUGMSG (ZONE_READ ,# (TEXT("After HWGetBytes, Fifo(R=%d,W=%d,BA=%d,L=%d) ByteRead=%d/r/n"),# RxRead(pSerialHead), RxWrite(pSerialHead),# RxBytesAvail(pSerialHead), RxLength(pSerialHead),# RoomLeft));### // If flow control enabled then we need to scan for XON/XOFF# // characters# if ( pSerialHead->XFlow ) {# for ( CharIndex=0; CharIndex < RoomLeft; ) {# if ( RxBuffWrite(pSerialHead)[CharIndex] ==# pSerialHead->DCB.XoffChar ) {# DEBUGMSG (ZONE_FLOW, (TEXT("Received XOFF/r/n")));## pSerialHead->StopXmit = 1;# memmove (RxBuffWrite(pSerialHead)+CharIndex,# RxBuffWrite(pSerialHead)+CharIndex+1,# RoomLeft - CharIndex);# RoomLeft--;# continue;# } else if ( RxBuffWrite(pSerialHead)[CharIndex] ==# pSerialHead->DCB.XonChar ) {# pSerialHead->StopXmit = 0;# DEBUGMSG (ZONE_FLOW, (TEXT("Received XON/r/n")));# memmove (RxBuffWrite(pSerialHead)+CharIndex,# RxBuffWrite(pSerialHead)+CharIndex+1,# RoomLeft - CharIndex);# RoomLeft--;# // We disabled TX on XOFF, so now we need to start sending# // again. Easiest way is to pretend we saw a TX interrupt# it |= INTR_TX;# continue;# }# CharIndex++;# }# }## pSerialHead->RxBytes += RoomLeft;# RxWrite(pSerialHead) = # (RxWrite(pSerialHead)+RoomLeftDCB.fDtrControl == DTR_CONTROL_HANDSHAKE) &# (!pSerialHead->DtrFlow) && # (4*RxBytesAvail(pSerialHead) > (3*RxLength(pSerialHead))) ) {# DEBUGMSG (ZONE_READ|ZONE_FLOW,# (TEXT("DTR_CONTROL_HANDSHAKE Clearing DTR/r/n")));# pSerialHead->DtrFlow = 1;# pFuncTbl->HWClearDTR(pHWHead);# }# if ( (pSerialHead->DCB.fRtsControl == RTS_CONTROL_HANDSHAKE) &# (!pSerialHead->RtsFlow) &# (4*RxBytesAvail(pSerialHead) > (3*RxLength(pSerialHead))) ) {# DEBUGMSG (ZONE_READ|ZONE_FLOW,# (TEXT("RTS_CONTROL_HANDSHAKE Clearing RTS/r/n")));# pSerialHead->RtsFlow = 1;# pFuncTbl->HWClearRTS(pHWHead);# }## /* If Xon/Xoff flow control is desired. check the limit against# * the remaining room and act accordingly.# */# if ( pSerialHead->DCB.fInX && !(pSerialHead->SentXoff) &# ( pSerialHead->DCB.XoffLim >=# (RxLength(pSerialHead) - RxBytesAvail(pSerialHead))) ) {# DEBUGMSG (ZONE_FLOW, (TEXT("Sending XOFF/r/n")));# pFuncTbl->HWXmitComChar(pHWHead, pSerialHead->DCB.XoffChar);## pSerialHead->SentXoff = 1;# if ( !pSerialHead->DCB.fTXContinueOnXoff ) {# pSerialHead->StopXmit = 1;# }# }# }# //-与中断相关的操作## if ( it & INTR_TX ) {# DEBUGMSG (ZONE_THREAD|ZONE_WRITE , (TEXT("Tx Event/r/n")));# DoTxData( pSerialHead );//收到发送中断后发送数据# }## if ( (it & INTR_MODEM) ) {# DEBUGMSG (ZONE_THREAD, (TEXT("Other Event, it:%x/r/n"), it));## /* Call low level status clean up code.# */# pFuncTbl->HWModemIntrHandler(pHWHead);//这个函数会对应下层函数实现# }## if ( it & INTR_LINE ) {# DEBUGMSG (ZONE_THREAD, (TEXT("Line Event, it:%x/r/n"), it));## /* Call low level line status clean up code.# * Then unmask the interrupt# */# pFuncTbl->HWLineIntrHandler(pHWHead);//这个是干什么的?# }# }## // We kept this till the end to optimize the above loop# if ( RxDataAvail ) {# // Signal COM_Read that bytes are available.# SetEvent(pSerialHead->hReadEvent);# EvaluateEventFlag(pSerialHead, EV_RXCHAR);# }## DEBUGMSG (ZONE_THREAD ,# (TEXT("-SerialEventHandler, Fifo(R=%d,W=%d,L=%d)/r/n"),# RxRead(pSerialHead), RxWrite(pSerialHead),# RxLength(pSerialHead)));## if ( pSerialHead->pAccessOwner )# COM_DEC_USAGE_CNT(pSerialHead->pAccessOwner);# return;# } 从这个SerialEventHandler的实现代码来看,这个SerialEventHandler几乎包括了所有串口功能的操作。把读写线程等都集成在一起了。通过判断中断类型来执行不同的函数。
原创粉丝点击