久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

wince串口線程,、中斷等相關(guān)學(xué)習(xí)(作者:wogoyixikexie@gliet)

 lhzstudio 2012-05-16

    前面發(fā)了好幾篇wince串口的學(xué)習(xí)的文章,,由于是學(xué)習(xí)性質(zhì)的,,弄的比較亂,,還請網(wǎng)友們原諒,。以前只是搞懂了大體框架,,對這個中斷線程等底層的東西還沒有了解,現(xiàn)在來來學(xué)習(xí)一下,。

 
  1. VOID
  2. SerialEventHandler(PHW_INDEP_INFO       pSerialHead)
  3. {
  4.     PHW_VTBL            pFuncTbl = pSerialHead->pHWObj->pFuncTbl;
  5.     PVOID               pHWHead = pSerialHead->pHWHead;
  6.     ULONG               CharIndex;
  7.     ULONG               RoomLeft = 0;
  8.     ULONG               TotalLeft = 0;
  9.     INTERRUPT_TYPE      it = INTR_NONE;
  10.     BOOL                RxDataAvail = FALSE;
  11.     DEBUGMSG (ZONE_THREAD, (TEXT("+SerialEventHandler, pHead 0x%X/r/n"),
  12.                             pSerialHead));
  13.     if ( pSerialHead->KillRxThread ||
  14.          !pSerialHead->hSerialEvent ) {
  15.         DEBUGMSG (ZONE_THREAD, (TEXT("Exitting thread/r/n")));
  16.         SetEvent(pSerialHead->hKillDispatchThread);
  17.         ExitThread(0);
  18.     }
  19. // NOTE - This one is a little tricky.  If the only owner is a monitoring task
  20. // then I don't have an owner for read/write, yet I might be in this routine
  21. // due to a change in line status.  Lets just do the best we can and increment
  22. // the count for the access owner if available.
  23.     if ( pSerialHead->pAccessOwner )
  24.         COM_INC_USAGE_CNT(pSerialHead->pAccessOwner);
  25.     while ( 1 ) {
  26.         if ( !(it = pFuncTbl->HWGetIntrType(pHWHead)) ) {
  27.             DEBUGMSG (ZONE_THREAD,
  28.                       (TEXT("SerialEventHandler, No Interrupt./r/n")));
  29.             break;
  30.         }
  31.         DEBUGMSG (ZONE_THREAD,
  32.                   (TEXT("SerialEventHandler, Interrupts 0x%X/r/n"), it));
  33.         if ( it & INTR_RX ) {
  34.             // It's read data event. Optimize the read by reading chunks
  35.             // if the user has not specified using xflow control
  36.             // or event/error/eof characters. Ack the receive,
  37.             // unmask the interrupt, get the current data pointer
  38.             // and see if data is available.
  39.             // Note: We have to copy RxRead and RxWrite index to local in order to make it atomic.
  40.             register DWORD RxWIndex=RxWrite(pSerialHead), RxRIndex=RxRead(pSerialHead);
  41.             DEBUGMSG (ZONE_THREAD|ZONE_READ , (TEXT("Rx Event/r/n")));
  42.             if ( RxRIndex == 0 ) {
  43.                 // have to leave one byte free.
  44.                 RoomLeft = RxLength(pSerialHead) - RxWIndex - 1;
  45.             } else {
  46.                 RoomLeft = RxLength(pSerialHead) - RxWIndex;
  47.             }
  48.             if ( RxRIndex > RxWIndex ) {
  49.                 RoomLeft = RxRIndex - RxWIndex - 1;
  50.             }
  51.             if ( RoomLeft ) {
  52.                 pSerialHead->DroppedBytesPDD +=
  53.                 pFuncTbl->HWRxIntrHandler(pHWHead,
  54.                                           RxBuffWrite(pSerialHead),
  55.                                           &RoomLeft);
  56.             } else {
  57.                 BYTE    TempBuf[16];
  58.                 RoomLeft = 16;
  59.                 pFuncTbl->HWRxIntrHandler(pHWHead,
  60.                                           TempBuf,
  61.                                           &RoomLeft);
  62.                 pSerialHead->DroppedBytesMDD += RoomLeft;
  63.                 DEBUGMSG (ZONE_WARN|ZONE_READ, (TEXT("Tossed %d bytes/r/n"),
  64.                                                 RoomLeft));
  65.                 RoomLeft = 0;
  66.             }
  67.             DEBUGMSG (ZONE_READ ,
  68.                       (TEXT("After HWGetBytes, Fifo(R=%d,W=%d,BA=%d,L=%d) ByteRead=%d/r/n"),
  69.                        RxRead(pSerialHead), RxWrite(pSerialHead),
  70.                        RxBytesAvail(pSerialHead), RxLength(pSerialHead),
  71.                        RoomLeft));
  72.             // If flow control enabled then we need to scan for XON/XOFF
  73.             // characters
  74.             if ( pSerialHead->XFlow ) {
  75.                 for ( CharIndex=0; CharIndex < RoomLeft; ) {
  76.                     if ( RxBuffWrite(pSerialHead)[CharIndex] ==
  77.                          pSerialHead->DCB.XoffChar ) {
  78.                         DEBUGMSG (ZONE_FLOW, (TEXT("Received XOFF/r/n")));
  79.                         pSerialHead->StopXmit = 1;
  80.                         memmove (RxBuffWrite(pSerialHead)+CharIndex,
  81.                                  RxBuffWrite(pSerialHead)+CharIndex+1,
  82.                                  RoomLeft - CharIndex);
  83.                         RoomLeft--;
  84.                         continue;
  85.                     } else if ( RxBuffWrite(pSerialHead)[CharIndex] ==
  86.                                 pSerialHead->DCB.XonChar ) {
  87.                         pSerialHead->StopXmit = 0;
  88.                         DEBUGMSG (ZONE_FLOW, (TEXT("Received XON/r/n")));
  89.                         memmove (RxBuffWrite(pSerialHead)+CharIndex,
  90.                                  RxBuffWrite(pSerialHead)+CharIndex+1,
  91.                                  RoomLeft - CharIndex);
  92.                         RoomLeft--;
  93.                         // We disabled TX on XOFF, so now we need to start sending
  94.                         // again. Easiest way is to pretend we saw a TX interrupt
  95.                         it |= INTR_TX;
  96.                         continue;
  97.                     }
  98.                     CharIndex++;
  99.                 }
  100.             }
  101.             pSerialHead->RxBytes += RoomLeft;
  102.             RxWrite(pSerialHead) = 
  103.                 (RxWrite(pSerialHead)+RoomLeft<RxLength(pSerialHead)? RxWrite(pSerialHead)+RoomLeft: RxWrite(pSerialHead)+RoomLeft-RxLength(pSerialHead));
  104.             if ( RoomLeft ) {
  105.                 RxDataAvail = TRUE;
  106.             }
  107.             /* Support DTR_CONTROL_HANDSHAKE/RTS_CONTROL_HANDSHAKE
  108.              * signal is cleared when the input buffer is more than 3/4 full.
  109.              */
  110.             if ( (pSerialHead->DCB.fDtrControl == DTR_CONTROL_HANDSHAKE) &
  111.                  (!pSerialHead->DtrFlow) && 
  112.                  (4*RxBytesAvail(pSerialHead) > (3*RxLength(pSerialHead))) ) {
  113.                 DEBUGMSG (ZONE_READ|ZONE_FLOW,
  114.                           (TEXT("DTR_CONTROL_HANDSHAKE Clearing DTR/r/n")));
  115.                 pSerialHead->DtrFlow = 1;
  116.                 pFuncTbl->HWClearDTR(pHWHead);
  117.             }
  118.             if ( (pSerialHead->DCB.fRtsControl == RTS_CONTROL_HANDSHAKE) &
  119.                  (!pSerialHead->RtsFlow) &
  120.                  (4*RxBytesAvail(pSerialHead) > (3*RxLength(pSerialHead))) ) {
  121.                 DEBUGMSG (ZONE_READ|ZONE_FLOW,
  122.                           (TEXT("RTS_CONTROL_HANDSHAKE Clearing RTS/r/n")));
  123.                 pSerialHead->RtsFlow = 1;
  124.                 pFuncTbl->HWClearRTS(pHWHead);
  125.             }
  126.             /* If Xon/Xoff flow control is desired. check the limit against
  127.              * the remaining room and act accordingly.
  128.              */
  129.             if ( pSerialHead->DCB.fInX && !(pSerialHead->SentXoff) &
  130.                  ( pSerialHead->DCB.XoffLim >=
  131.                    (RxLength(pSerialHead) - RxBytesAvail(pSerialHead))) ) {
  132.                 DEBUGMSG (ZONE_FLOW, (TEXT("Sending XOFF/r/n")));
  133.                 pFuncTbl->HWXmitComChar(pHWHead, pSerialHead->DCB.XoffChar);
  134.                 pSerialHead->SentXoff = 1;
  135.                 if ( !pSerialHead->DCB.fTXContinueOnXoff ) {
  136.                     pSerialHead->StopXmit = 1;
  137.                 }
  138.             }
  139.         }
  140.         //-與中斷相關(guān)的操作
  141.         if ( it & INTR_TX ) {
  142.             DEBUGMSG (ZONE_THREAD|ZONE_WRITE , (TEXT("Tx Event/r/n")));
  143.             DoTxData( pSerialHead );//收到發(fā)送中斷后發(fā)送數(shù)據(jù)
  144.         }
  145.         if ( (it & INTR_MODEM) ) {
  146.             DEBUGMSG (ZONE_THREAD, (TEXT("Other Event, it:%x/r/n"), it));
  147.             /* Call low level status clean up code.
  148.              */
  149.             pFuncTbl->HWModemIntrHandler(pHWHead);//這個函數(shù)會對應(yīng)下層函數(shù)實現(xiàn)
  150.         }
  151.         if ( it & INTR_LINE ) {
  152.             DEBUGMSG (ZONE_THREAD, (TEXT("Line Event, it:%x/r/n"), it));
  153.             /* Call low level line status clean up code.
  154.              * Then unmask the interrupt
  155.              */
  156.             pFuncTbl->HWLineIntrHandler(pHWHead);//這個是干什么的?
  157.         }
  158.     }
  159.     // We kept this till the end to optimize the above loop
  160.     if ( RxDataAvail ) {
  161.         // Signal COM_Read that bytes are available.
  162.         SetEvent(pSerialHead->hReadEvent);
  163.         EvaluateEventFlag(pSerialHead, EV_RXCHAR);
  164.     }
  165.     DEBUGMSG (ZONE_THREAD ,
  166.               (TEXT("-SerialEventHandler, Fifo(R=%d,W=%d,L=%d)/r/n"),
  167.                RxRead(pSerialHead), RxWrite(pSerialHead),
  168.                RxLength(pSerialHead)));
  169.     if ( pSerialHead->pAccessOwner )
  170.         COM_DEC_USAGE_CNT(pSerialHead->pAccessOwner);
  171.     return;
  172. }

                         

    從這個SerialEventHandler的實現(xiàn)代碼來看,,這個SerialEventHandler幾乎包括了所有串口功能的操作。把讀寫線程等都集成在一起了,。通過判斷中斷類型來執(zhí)行不同的函數(shù),。

   SerialEventHandler函數(shù)被兩個地方調(diào)用

   一、在49行處調(diào)用,,

 

        SerialDispatchThread函數(shù)是等待線程啟動的作用,,微軟的代碼還是寫的比較清晰的,,來看看SerialDispatchThread函數(shù)在哪里調(diào)用了,。

再來看這個StartDispatchThread被誰調(diào)用了

(1)COM_Init調(diào)用了

  if ( pSerialHead->pHWObj->BindFlags & THREAD_AT_INIT ) {
        // Hook the interrupt and start the associated thread.
        if ( ! StartDispatchThread( pSerialHead ) ) {
            // Failed on InterruptInitialize or CreateThread.  Bail.
            COM_Deinit(pSerialHead);
            return(NULL);       
        }

    }

(2)COM_Open調(diào)用了

 if ( pSerialHead->pHWObj->BindFlags & THREAD_AT_OPEN ) {
            DEBUGMSG(ZONE_INIT|ZONE_OPEN,
                     (TEXT("COM_Open: Starting DispatchThread x%X/n/r"),
                      pOpenHead));
            // Hook the interrupt and start the associated thread.
            if ( ! StartDispatchThread( pSerialHead ) ) {
                // Failed on InterruptInitialize or CreateThread.  Bail.
                DEBUGMSG(ZONE_INIT|ZONE_OPEN,
                         (TEXT("COM_Open: Failed StartDispatchThread x%X/n/r"),
                          pOpenHead));
                goto OpenFail;
            }
        }

 

 

二,、NotifyPDDInterrupt調(diào)用了SerialEventHandler函數(shù)

//NotifyPDDInterrupt在PDD和中間層被調(diào)用了
BOOL CSerialPDD::NotifyPDDInterrupt(INTERRUPT_TYPE interruptType)
{
    m_InterruptLock.Lock();
    // The interrupt is define as Bit event.
    m_dwInterruptFlag |= (DWORD)interruptType;
    m_InterruptLock.Unlock();
    if (IsPowerResumed ( )) {
        if (m_lOpenCount) { // If application is opened.
            EventCallback( EV_POWER );
        }
        else {
            if (GetModemStatus() & MS_RLSD_ON)
                CeEventHasOccurred (NOTIFICATION_EVENT_RS232_DETECTED, NULL);
        }
    }
    SerialEventHandler(m_pMdd);
    return TRUE;
}
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 現(xiàn)在來看看這個中斷到底怎么回事,,感覺和4.2的區(qū)別太大了。

 ———————————————————————————————————————————————

我找了好久,,終于找到PDD線程相關(guān)的地方,,這里值得注意的是C++語言的構(gòu)造函數(shù)和析構(gòu)函數(shù)的作用,在第一次

建類對象的時候會調(diào)用構(gòu)造函數(shù)(構(gòu)造函數(shù)可以用來初始化對象),,而清除類對象的時候調(diào)用析構(gòu)函數(shù)(如果不懂

C++的,,比如我,找了好久才知道在析構(gòu)函數(shù)關(guān)閉了串口線程句柄,,慚愧,。)

//構(gòu)造函數(shù),當(dāng)創(chuàng)建對象的時候會自動調(diào)用

CPdd2440Uart::CPdd2440Uart (LPTSTR lpActivePath, PVOID pMdd, PHWOBJ pHwObj )
:   CSerialPDD(lpActivePath,pMdd, pHwObj)
,   m_ActiveReg(HKEY_LOCAL_MACHINE,lpActivePath)
,   CMiniThread (0, TRUE)  
{
    m_pReg2440Uart = NULL;
    m_pINTregs = NULL;
    m_dwIntShift = 0;
    m_dwSysIntr = MAXDWORD;
    m_hISTEvent = NULL;
    m_dwDevIndex = 0;
    m_pRegVirtualAddr = NULL;
    m_XmitFlushDone =  CreateEvent(0, FALSE, FALSE, NULL);
    m_XmitFifoEnable = FALSE;
    m_dwWaterMark = 8 ;
}

//析構(gòu)函數(shù),,當(dāng)清除類對象的時候會自動調(diào)用
CPdd2440Uart::~CPdd2440Uart()
{
    InitModem(FALSE);
    if (m_hISTEvent) {
        m_bTerminated=TRUE;
        ThreadStart();
        SetEvent(m_hISTEvent);
        ThreadTerminated(1000);
        InterruptDisable( m_dwSysIntr );   //禁止中斷      
        CloseHandle(m_hISTEvent);//關(guān)閉串口線程句柄

    };
    if (m_pReg2440Uart)
        delete m_pReg2440Uart;
    if (m_XmitFlushDone)
        CloseHandle(m_XmitFlushDone);
    if (m_pRegVirtualAddr != NULL) {
        MmUnmapIoSpace((PVOID)m_pRegVirtualAddr,0UL);//釋放虛擬內(nèi)存
    }
    if (m_pINTregs!=NULL) {
        MmUnmapIoSpace((PVOID)m_pINTregs,0UL));//釋放虛擬內(nèi)存

    }
       
}

//---------至于更進一步分析,,明天做個比較完整的總結(jié)吧,看來年前的時間都用來學(xué)C++比較合適

 

————————————上面都是比較亂,,現(xiàn)在總結(jié)一下一個正常的線程架構(gòu)——————————————

首先是創(chuàng)建線程 pSerialHead->hSerialEvent = CreateEvent(0,FALSE,FALSE,NULL);

InterruptInitialize(pSerialHead->pHWObj->dwIntID,//這個中斷和PDD的中斷以及相關(guān)線程到底有什么不同,?
                              pSerialHead->hSerialEvent,
                              NULL,
                              0) )

 SetEvent(pSerialHead->hSerialEvent);

WaitReturn = WaitForSingleObject(pSerialHead->hSerialEvent, INFINITE);

SerialEventHandler(pSerialHead);//開始執(zhí)行串口線程

CloseHandle(pSerialHead->hSerialEvent);//關(guān)閉線程句柄

—————————————————————————————————————————————————

WaitForSingleObject函數(shù)用來檢測hHandle事件的信號狀態(tài),當(dāng)函數(shù)的執(zhí)行時間超過dwMilliseconds就返回,,但如果參數(shù)dwMilliseconds為INFINITE時函數(shù)將直到相應(yīng)時間事件變成有信號狀態(tài)才返回,,否則就一直等待下去,直到WaitForSingleObject有返回直才執(zhí)行后面的代碼,。在這里舉個例子:

先創(chuàng)建一個全局Event對象g_event:
CEvent g_event;
在程序中可以通過調(diào)用CEvent::SetEvent設(shè)置事件為有信號狀態(tài),。

在驅(qū)動程序中,因為線程往往和硬件中斷相關(guān),,中斷產(chǎn)生就執(zhí)行線程,,中斷關(guān)閉就不執(zhí)行線程,所以串口提供了

兩種執(zhí)行線程的方法(1)產(chǎn)生中斷.(2)SetEvent(線程句柄)

—————————————————————————————————————————————————

MDD中的中斷是怎么回事?

在SerialEventHandler函數(shù)中調(diào)用了HWGetIntrType函數(shù)(其實是調(diào)用了轉(zhuǎn)換函數(shù)表的SerGetInterruptType函數(shù))

INTERRUPT_TYPE
SerGetInterruptType(
                   PVOID pHead      // Pointer to hardware head
                   )
{
    CSerialPDD * pSerialPDD  = ( CSerialPDD * )pHead;
    INTERRUPT_TYPE interrupts=INTR_NONE;
    DEBUGMSG (ZONE_EVENTS,(TEXT("+SerGetInterruptType 0x%X/r/n"), pHead));
    if (pSerialPDD)
        interrupts= pSerialPDD->GetInterruptType();
    DEBUGMSG (ZONE_EVENTS,(TEXT("-SerGetInterruptType (0x%X) return %X/r/n"), pHead, interrupts));
    return interrupts;
}

——————————

INTERRUPT_TYPE CSerialPDD::GetInterruptType()
{
    m_InterruptLock.Lock();
    // The interrupt is define as Bit event.
    INTERRUPT_TYPE lIntrFlagRet= (INTERRUPT_TYPE )m_dwInterruptFlag;
    m_dwInterruptFlag = INTR_NONE;
    m_InterruptLock.Unlock();
    return lIntrFlagRet;
}

——


BOOL CSerialPDD::NotifyPDDInterrupt(INTERRUPT_TYPE interruptType)
{
    m_InterruptLock.Lock();
    // The interrupt is define as Bit event.
    m_dwInterruptFlag |= (DWORD)interruptType;
    m_InterruptLock.Unlock();
    if (IsPowerResumed ( )) {
        if (m_lOpenCount) { // If application is opened.
            EventCallback( EV_POWER );
        }
        else {
            if (GetModemStatus() & MS_RLSD_ON)
                CeEventHasOccurred (NOTIFICATION_EVENT_RS232_DETECTED, NULL);
        }
    }
    SerialEventHandler(m_pMdd);
    return TRUE;
}

——看看這個NotifyPDDInterrupt被誰調(diào)用了就知道怎么回事了,。

 在PDD層的ThreadRun函數(shù)調(diào)用了NotifyPDDInterrupt函數(shù)

DWORD CPdd2440Uart::ThreadRun()
{
    while ( m_hISTEvent!=NULL && !IsTerminated()) {
        if (WaitForSingleObject( m_hISTEvent,m_dwISTTimeout)==WAIT_OBJECT_0) {
            m_HardwareLock.Lock();   
            while (!IsTerminated() ) {
                DWORD dwData = (GetInterruptStatus() & (S2440UART_INT_RXD|S2440UART_INT_TXD|S2440UART_INT_ERR));
                DWORD dwMask = (GetIntrruptMask() & (S2440UART_INT_RXD|S2440UART_INT_TXD|S2440UART_INT_ERR));
                 DEBUGMSG(ZONE_THREAD,
                      (TEXT(" CPdd2440Uart::ThreadRun INT=%x, MASK =%x/r/n"),dwData,dwMask));
                dwMask &= dwData;
                if (dwMask) {
                    DEBUGMSG(ZONE_THREAD,
                      (TEXT(" CPdd2440Uart::ThreadRun Active INT=%x/r/n"),dwMask));
                    DWORD interrupts=INTR_MODEM; // Always check Modem when we have change. It may work at polling mode.
                    if ((dwMask & S2440UART_INT_RXD)!=0)
                        interrupts |= INTR_RX;
                    if ((dwMask & S2440UART_INT_TXD)!=0)
                        interrupts |= INTR_TX;
                    if ((dwMask & S2440UART_INT_ERR)!=0)
                        interrupts |= INTR_LINE|INTR_RX;
                    NotifyPDDInterrupt((INTERRUPT_TYPE)interrupts);
                    ClearInterrupt(dwData);

                }
                else
                    break;
            }
            m_HardwareLock.Unlock();  
            InterruptDone(m_dwSysIntr);
        }
        else { // Polling Modem.
            NotifyPDDInterrupt(INTR_MODEM);
            DEBUGMSG(ZONE_THREAD,(TEXT(" CPdd2440Uart::ThreadRun timeout INT=%x,MASK=%d/r/n"),m_pINTregs->SUBSRCPND,m_pINTregs->INTSUBMSK));
#ifdef DEBUG
            if ( ZONE_THREAD )
                m_pReg2440Uart->DumpRegister();
#endif
        }
    }
    return 1;
}
——————————————————————————————————————————

這個有點奇怪,這個是硬件中斷相關(guān)的東西,,但是在MMD層有個中斷實在讓人費解

InterruptInitialize(pSerialHead->pHWObj->dwIntID,//這個中斷和PDD的中斷以及相關(guān)線程到底有什么不同,?
                              pSerialHead->hSerialEvent,
                              NULL,
                              0) )

在中間層的SerInit函數(shù)有

//為什么會這樣做呢,中斷和
  //DeviceArrayIndex()注冊表扯上關(guān)系?
        DWORD dwIndex= pHWObj->dwIntID;
        pHWObj->dwIntID = 0;

 ——————————————————————

找到了

 

// GetSerialObj : The purpose of this function is to allow multiple PDDs to be
// linked with a single MDD creating a multiport driver.  In such a driver, the
// MDD must be able to determine the correct vtbl and associated parameters for
// each PDD.  Immediately prior to calling HWInit, the MDD calls GetSerialObject
// to get the correct function pointers and parameters.
//
extern "C" PHWOBJ
GetSerialObject(
               DWORD DeviceArrayIndex
               )
{
    PHWOBJ pSerObj;

    // Unlike many other serial samples, we do not have a statically allocated
    // array of HWObjs.  Instead, we allocate a new HWObj for each instance
    // of the driver.  The MDD will always call GetSerialObj/HWInit/HWDeinit in
    // that order, so we can do the alloc here and do any subsequent free in
    // HWDeInit.
    // Allocate space for the HWOBJ.
    pSerObj=(PHWOBJ)LocalAlloc( LPTR ,sizeof(HWOBJ) );
    if ( !pSerObj )
        return (NULL);

    // Fill in the HWObj structure that we just allocated.

    pSerObj->BindFlags = THREAD_IN_PDD;     // PDD create thread when device is first attached.
    pSerObj->dwIntID = DeviceArrayIndex;   // Only it is useful when set set THREAD_AT_MDD. We use this to transfer DeviceArrayIndex
    pSerObj->pFuncTbl = (HW_VTBL *) &IoVTbl; // Return pointer to appropriate functions

    // Now return this structure to the MDD.
    return (pSerObj);
}

 

果然是注冊表中的DeviceArrayIndex值就是dwIntID ,,不過我始終對前面的線程綁定dwIntID 有點不解

//中斷綁定串口線程SerialEventHandler,,這個dwIntID并不是什么硬件中斷,這樣調(diào)用怎么能成功,?
//而是注冊表中的DeviceArrayIndex的值why?
    if ( !InterruptInitialize(pSerialHead->pHWObj->dwIntID,
                              pSerialHead->hSerialEvent,
                              NULL,
                              0)
)

——————————————————————————————

按照道理,,上面是這個所謂的“中斷”(dwIntID )綁定了句柄為hSerialEvent的線程。只要dwIntID 有硬件動作

才會啟動句柄為hSerialEvent的線程,。但是這個中斷是假的,,不知道微軟是怎么弄的,搞定這個,,串口的架構(gòu)基本是算完成了,。

——————引用何宗健老師的回答

InterruptInitialize函數(shù)要調(diào)用成功,必須要求目前的event沒有對象正在等待,。因此,,如果你先創(chuàng)建了線程,并且已經(jīng)執(zhí)行了WaitForSingleObject一句的話,,肯定就不能滿足這個要求了,。

 

  其實InterruptInitialize函數(shù)在WinCE里面是有完整源代碼的,在/WINCE600/PRIVATE/WINCEOS/COREOS/NK/KERNEL/intrapi.c中,,你可以順藤摸瓜,,看看它是如何把中斷跟event連上的。

 

 

     中斷是硬件與軟件打交道的重要方法,,因此,,大多數(shù)驅(qū)動程序都涉及到對中斷的處理,本文就驅(qū)動程序的開發(fā)人員以及BSP的開發(fā)人員的角度,,來談?wù)刉indows CE中中斷的處理過程,。

如果一個驅(qū)動程序要處理一個中斷,那么驅(qū)動程序需要首先建立一個事件,,可以使用CreateEvent函數(shù),,然后調(diào)用InterruptInitialize將該事件與中斷號綁定,這一步就會使能該中斷,,OAL中的OEMInerrupteEnable就會被調(diào)用,,如果該函數(shù)不返回true的話,,InterruptInitialize就會失敗。然后驅(qū)動程序中的IST就可以使用WaitForSingleObject函數(shù)來等待中斷的發(fā)生,。

      當(dāng)一個硬件中斷發(fā)生之后,,操作系統(tǒng)陷入異常,中斷向量指示進入CE的異常處理程序,,該異常處理程序然后調(diào)用OAL的OEMInterruptHandler函數(shù),,該函數(shù)檢測硬件之后,將硬件中斷轉(zhuǎn)換為軟件的中斷號,,返回給系統(tǒng),。該中斷號就是上面提到的InterruptInitialize中使用的那個中斷號。系統(tǒng)得到該中斷號之后,,就會找到該中斷號對應(yīng)的事件,,并喚醒等待相應(yīng)事件的線程(IST),然后IST就可以在用戶態(tài)進行中斷處理,。處理完成之后,,IST需要調(diào)用InterruptDone來告訴操作系統(tǒng)中斷處理結(jié)束,操作系統(tǒng)再次調(diào)用OAL中的OEMInterruptDone函數(shù),,最后完成中斷的處理。

在上面的描述中,,驅(qū)動程序需要使用的是InterruptInitialize,,WaitForSingleObject和InterruptDone三個函數(shù),而BSP開發(fā)者需要主要考慮的是OEMInerrupteEnable,,OEMInterruptHandler,,OEMInterruptDone三個函數(shù)。當(dāng)然,,這是上面提到的一些函數(shù),,實際上BSP開發(fā)者在中斷部分還需要考慮Init以及Disable等等函數(shù),這里就不再討論了,。

——對于這個問題我還是無法解釋,,怎么想也不會使用這種注冊表的一些參數(shù)來啊,要徹底明白,,只能看看InterruptInitialize源碼到底是怎么回事了,。

————————————————————

wogoyixikexie@gliet 說:
WaitReturn = WaitForSingleObject(pSerialHead->hSerialEvent, INFINITE);

        SerialEventHandler(pSerialHead);//開始執(zhí)行串口線程
CSDN-廣州天河wince6.0 說:

wogoyixikexie@gliet 說:
要有信號來才會執(zhí)行這個線程,可是我發(fā)現(xiàn)這個
SetEvent(pSerialHead->hSerialEvent);
在StopDispatchThread函數(shù)里面,,而StopDispatchThread是被COM_Deinit函數(shù)調(diào)用的
wogoyixikexie@gliet 說:
那么這樣導(dǎo)致了關(guān)閉驅(qū)動的時候才執(zhí)行上面那個串口發(fā)送接收相關(guān)的線程SerialEventHandler
wogoyixikexie@gliet 說:
我看后實在不解,,不過它是能正常工作的
wogoyixikexie@gliet 說:
我想求個讓人信服的理由
加密助手 說:
--- 系統(tǒng)提示: 以下會話未被加密 ---
CSDN-廣州天河wince6.0 說:
兩個事件是不一樣的吧
wogoyixikexie@gliet 說:
一樣的
wogoyixikexie@gliet 說:
這個線程句柄就是用來控制線程是否執(zhí)行的
wogoyixikexie@gliet 說:
如果沒有信號,就等待
CSDN-廣州天河wince6.0 說:
WaitReturn = WaitForSingleObject(pSerialHead->hSerialEvent, INFINITE);
是在那個函數(shù)中
CSDN-廣州天河wince6.0 說:
threadrun(_)?
wogoyixikexie@gliet 說:
SerialDispatchThread
wogoyixikexie@gliet 說:
這個是MDD的線程
wogoyixikexie@gliet 說:
PDD的線程是和硬件中斷相關(guān)的
wogoyixikexie@gliet 說:
真是神了,,這樣使用注冊表一個配置產(chǎn)生了一個線程
加密助手 說:
--- 系統(tǒng)提示: 以下會話未被加密 ---
CSDN-廣州天河wince6.0 說:
不太清楚它為什么要這樣子做
wogoyixikexie@gliet 說:
呵呵,,先放一下了,,以后再補充了。
CSDN-廣州天河wince6.0 說:
好像這個線程一直都是阻塞的

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多