----------我先找到SD卡检测中断相关的函数
- ///////////////////////////////////////////////////////////////////////////////
- // CSDIOControllerBase::CardDetectThread - thread for card insert/removal detection
- // Input:
- // Output:
- //
- // Return: thread exit code
- ///////////////////////////////////////////////////////////////////////////////
- DWORD CSDIOControllerBase::CardDetectThread()
- {
- BOOL bSlotStateChanged = FALSE;
- DWORD dwWaitResult = WAIT_TIMEOUT;
- if( m_nCardDetectIstThreadPriority != 0xffffffff && !CeSetThreadPriority( GetCurrentThread(), m_nCardDetectIstThreadPriority ) )
- {
- DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCDriver:CardDetectThread(): warning, failed to set CEThreadPriority /r/n")));
- }
- for(;;)
- {
- //----- 1. Wait for the next insertion/removal interrupt -----
- dwWaitResult = WaitForSingleObject(m_hCardInsertInterruptEvent, m_dwPollingTimeout);
- if(m_bDriverShutdown)
- {
- DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCardDetectIstThread: Thread Exiting/r/n")));
- return FALSE;
- }
- // Test if a card is present
- if( IsCardPresent() == m_bDevicePresent )
- {
- bSlotStateChanged = FALSE;
- }
- else
- {
- bSlotStateChanged = TRUE;
- }
- if( bSlotStateChanged || m_bReinsertTheCard )
- {
- m_bReinsertTheCard = FALSE;
- // If a card is inserted, unload the driver...
- if(m_bDevicePresent == TRUE)
- {
- m_fCardInTheSlot = FALSE;
- // indicate the slot change
- SDHCDIndicateSlotStateChange(m_pHCContext, 0, DeviceEjected);
- m_bDevicePresent = FALSE;
- Stop_SDI_Clock();
- }
- if(IsCardPresent())
- {
- m_fCardInTheSlot = TRUE;
- m_bDevicePresent = TRUE;
- //----- 5. Reset the clock to the ID rate -----
- vm_pSDIReg->SDICON |= LITTLE_ENDIAN_BYTE_ORDER; // Windows CE is always Little Endian.
- vm_pSDIReg->SDIFSTA |= FIFO_RESET; // Reset the FIFO
- vm_pSDIReg->SDIBSIZE = BYTES_PER_SECTOR;
- vm_pSDIReg->SDIDTIMER = MAX_DATABUSY_TIMEOUT; // Data/busy timeout
- SetClockRate(SD_DEFAULT_CARD_ID_CLOCK_RATE);
- // give the card enough time for initialization
- Start_SDI_Clock();
- Wait_80_SDI_Clock_Cycles();
- //----- 6. Inform the bus handler that this is the first command sent -----
- m_bSendInitClocks = TRUE;
- //----- 7. Indicate the slot change -----
- SDHCDIndicateSlotStateChange(m_pHCContext, 0, DeviceInserted);
- }
- } // if
- } // for
- return TRUE;
- }
对于WaitForSingleObject这个函数,我以前不怎么了解,现在来看一下PB帮助文档,来揭开中断的谜团。
This function returns when the specified object is in the signaled state or when the time-out interval elapses.
DWORD WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds );
Parameters
- hHandle
- [in] Handle to the object. For a list of the object types whose handles can be specified, see the Remarks section.
- dwMilliseconds
- [in] Specifies the time-out interval, in milliseconds. The function returns if the interval elapses, even if the object's state is nonsignaled. If dwMilliseconds is zero, the function tests the object's state and returns immediately. If dwMilliseconds is INFINITE, the function's time-out interval never elapses.
Return Values
If the function succeeds, the return value indicates the event that caused the function to return. The following table shows the possible return values.
Value | Description |
---|---|
WAIT_OBJECT_0 | The state of the specified object is signaled. |
WAIT_TIMEOUT | The time-out interval elapsed, and the object's state is nonsignaled. |
WAIT_FAILED indicates failure. Waiting on an invalid handle causes WaitForSingleObject to return WAIT_FAILED.
To get extended error information, call GetLastError.
Remarks
Windows CE 1.0 through 2.12 do not support waiting for semaphores, change notification objects, input, and timers. Windows CE 3.0 and later support waiting for semaphores.
For Windows CE 1.0 and 1.01, this function cannot wait on process or thread handles.
The WaitForSingleObject function checks the current state of the specified object. If the object's state is nonsignaled, the calling thread enters an efficient wait state. The thread consumes very little processor time while waiting for the object state to become signaled or the time-out interval to elapse.
The time-out value needs to be a positive number between zero and 0x7FFFFFFF. The maximum time-out value not equal to infinity is 0x7FFFFFFF. The infinite time-out value is 0xFFFFFFFF. Any time-out value between 0x7FFFFFFF and 0xFFFFFFFF — that is, values from 0x80000000 through 0xFFFFFFFE — is equivalent to 0x7FFFFFFF. If you need a bigger time-out value than the maximum of 0x7FFFFFFF, use the value for infinity (0xFFFFFFFF).
Before returning, a wait function modifies the state of some types of synchronization objects. Modification occurs only for the object whose signaled state caused the function to return. For example, the count of a semaphore object is decreased by one.
The WaitForSingleObject function can wait for the following objects:
- Event
- Mutex
- Semaphore
- Process
- Thread
Use caution when calling the wait functions and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. A thread that uses a wait function with no time-out interval may cause the system to become deadlocked. For example, the Dynamic Data Exchange (DDE) protocol and the COM function CoInitialize both indirectly create windows that can cause a deadlock. Therefore, if you have a thread that creates windows, use or , rather than WaitForSingleObject.
Requirements
OS Versions: Windows CE 1.0 and later.
Header: Winbase.h.
Link Library: Coredll.lib.
- WaitForSingleObject的用法
- DWORD WaitForSingleObject(
- HANDLE hHandle,
- DWORD dwMilliseconds
- );
- 参数hHandle是一个事件的句柄,第二个参数dwMilliseconds是时间间隔。如果时间是有信号状态返回WAIT_OBJECT_0,如果时间超过dwMilliseconds值但时间事件还是无信号状态则返回WAIT_TIMEOUT。
- hHandle可以是下列对象的句柄:
- Change notification
- Console input
- Event
- Job
- Memory resource notification
- Mutex
- Process
- Semaphore
- Thread
- Waitable timer
- WaitForSingleObject函数用来检测hHandle事件的信号状态,当函数的执行时间超过dwMilliseconds就返回,但如果参数dwMilliseconds为INFINITE时函数将直到相应时间事件变成有信号状态才返回,否则就一直等待下去,直到WaitForSingleObject有返回直才执行后面的代码。在这里举个例子:
- 先创建一个全局Event对象g_event:
- CEvent g_event;
- 在程序中可以通过调用CEvent::SetEvent设置事件为有信号状态。
- 下面是一个线程函数MyThreadPro()
- UINT CFlushDlg::MyThreadProc( LPVOID pParam )
- {
- WaitForSingleObject(g_event,INFINITE);
- For(;;)
- {
- ………….
- }
- return 0;
- }
- 在这个线程函数中只有设置g_event为有信号状态时才执行下面的for循环,因为g_event是全局变量,所以我们可以在别的线程中通过g_event. SetEvent控制这个线程。
- 还有一种用法就是我们可以通过WaitForSingleObject函数来间隔的执行一个线程函数的函数体
- UINT CFlushDlg::MyThreadProc( LPVOID pParam )
- {
- while(WaitForSingleObject(g_event,MT_INTERVAL)!=WAIT_OBJECT_0)
- {
- ………………
- }
- return 0;
- }
- 在这个线程函数中可以可以通过设置MT_INTERVAL来控制这个线程的函数体多久执行一次,当事件为无信号状态时函数体隔MT_INTERVAL执行一次,当设置事件为有信号状态时,线程就执行完毕了。
线程怎么和中断绑定的呢?请看下面代码
- SD_API_STATUS CSDIOControllerBase::Initialize()
- {
- ................
- //----- 10. Setup the IST for handling SDIO data transfer interrupts -----
- m_hSDIOInterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
- if(NULL == m_hSDIOInterruptEvent)
- {
- status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
- goto INIT_ERROR;
- }
- // initialize the card insertion interrupt event
- if(!InterruptInitialize (m_dwSDIOSysIntr, m_hSDIOInterruptEvent,
- NULL, 0))
- {
- status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
- goto INIT_ERROR;
- }
- m_hSDIOInterruptThread = CreateThread(NULL, 0,
- (LPTHREAD_START_ROUTINE)SD_IOInterruptIstThread,
- this, 0, &threadID);
- if(NULL == m_hSDIOInterruptThread)
- {
- status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
- goto INIT_ERROR;
- }
- ...........
- }
那么OAL里面的中断又是怎么样和这里的m_dwSDIOSysIntr绑定的呢?再看下面的代码
- // convert the SDI hardware IRQ into a logical SYSINTR value
- if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &m_dwSDIOIrq, sizeof(DWORD), &m_dwSDIOSysIntr, sizeof(DWORD), NULL))
- {
- // invalid SDIO SYSINTR value!
- DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("invalid SDIO SYSINTR value!/r/n")));
- m_dwSDIOSysIntr = SYSINTR_UNDEFINED;
- fRetVal = FALSE;
- goto FUNCTION_EXIT;
- }
现在,我有一些疑惑,在这里,我并没有看见有中断相关的一些代码,但是三星的三个SD卡DLL为什么会固定了中断呢?
难道他们的DLL有所不同?在DLL限定了中断?
原来,这份三星代码的中断是由注册表设定的,请看下面代码
- // read registry settings
- // read the SDIO SYSINTR value
- m_dwSDIOIrq = regDevice.ValueDW( SDIO_IRQ_TEXT, 0xffffffff );
- if( m_dwSDIOIrq == 0xffffffff )
- {
- // invalid SDIO IRQ value!
- DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("invalid SDIO IRQ value!/r/n")));
- fRetVal = FALSE;
- goto FUNCTION_EXIT;
- }
下面的宏定义就是和注册表配合的,中断之类的东西都是在注册表中配置。
#define DMA_CHANNEL_TEXT TEXT("DMAChannel")
#define DMA_IRQ_TEXT TEXT("DMAIrq")
#define DMA_IST_PRIORITY_TEXT TEXT("DMA_IST_Priority")
#define SDIO_IRQ_TEXT TEXT("SDIOIrq")----------在SD卡的注册表部分肯定可以找到。
#define SDIO_IST_PRIORITY_TEXT TEXT("SDIO_IST_Priority")
#define POLLING_TIMEOUT_TEXT TEXT("PollingTimeout")
#define CARD_DETECT_THREAD_PRIORITY_TEXT TEXT("CardDetect_Thread_Priority")
#define HANDLE_BUSY_FINISH_ON_COMMAND38_TEXT TEXT("HandleBusyFinishOnCommand38")
#define DMA_TRANSFER_TIMEOUT_FACTOR_TEXT TEXT("DmaTransferTimeoutFactor")
#define DMA_TRANSFER_TIMEOUT_CONSTANT_TEXT TEXT("DmaTransferTimeoutConstant")