现在的位置: 首页 > 综合 > 正文

移植SD卡驱动。

2013年07月29日 ⁄ 综合 ⁄ 共 9810字 ⁄ 字号 评论关闭

gsymichael      2008年10月27日 09点49分14秒 说:
你发给我的这个BSP应该是没有什么问题的,你只需要把这个SDHC的整个文件夹放到你的BSP下面就可以了。
但是还需要有些地方需要改动,主要是集中在注册表部分。注册表你打开这个BSP的Platform.reg可以看到SD部分的注册表信息很多,你接合代码与你的硬件修改注册表的内容。

你原来的那个什么SDSDC.dll肯定是给改过的,而且注册表信息很少,估计也是卖板子的人怕别人抄袭才这样做的。你现在有了这个BSP直接可以修改了,想怎么改就怎么改,有源码就是这么爽。

gsymichael      2008年10月27日 09点54分12秒 说:
我不推荐用反汇编的方法去做,因为意义不大。而且以后能用到的机会几乎是微乎其微。
我建议你好好学习一下底层的实现代码,这个对于了解SD卡驱动也是很有意义的。
gooogleman      2008年10月27日 10点13分19秒 说:
好的,我试试。
gooogleman      2008年10月27日 10点15分40秒 说:
这个改动不小,因为我的BSP是从4.2升级而来的,现在这个SDHC是标准的5.0,所以那些什么名字,文件夹全部不同,我看见有些头文件名字很大不同。估计要费一番心思了。
gsymichael      2008年10月27日 10点25分34秒 说:
就是把头文件对应一下。修改一下注册表。
gooogleman      2008年10月27日 10点27分18秒 说:
先试试先,谢谢。

----------我先找到SD卡检测中断相关的函数

 

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //  CSDIOControllerBase::CardDetectThread - thread for card insert/removal detection
  3. //  Input:  
  4. //  Output: 
  5. //
  6. //  Return: thread exit code
  7. ///////////////////////////////////////////////////////////////////////////////
  8. DWORD CSDIOControllerBase::CardDetectThread()
  9. {
  10.     BOOL  bSlotStateChanged = FALSE;
  11.     DWORD dwWaitResult  = WAIT_TIMEOUT;
  12.     if( m_nCardDetectIstThreadPriority != 0xffffffff && !CeSetThreadPriority( GetCurrentThread(), m_nCardDetectIstThreadPriority ) )
  13.     {
  14.         DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCDriver:CardDetectThread(): warning, failed to set CEThreadPriority /r/n")));
  15.     }
  16.     for(;;)
  17.     {
  18.         //----- 1. Wait for the next insertion/removal interrupt -----
  19.         dwWaitResult = WaitForSingleObject(m_hCardInsertInterruptEvent, m_dwPollingTimeout);
  20.         
  21.         if(m_bDriverShutdown) 
  22.         {
  23.             DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCardDetectIstThread: Thread Exiting/r/n")));
  24.             return FALSE;
  25.         }
  26.         // Test if a card is present
  27.         if( IsCardPresent() == m_bDevicePresent )
  28.         {
  29.             bSlotStateChanged = FALSE;
  30.         }
  31.         else
  32.         {
  33.             bSlotStateChanged = TRUE;
  34.         }
  35.         if( bSlotStateChanged || m_bReinsertTheCard )
  36.         {
  37.             m_bReinsertTheCard = FALSE;
  38.             // If a card is inserted, unload the driver...
  39.             if(m_bDevicePresent == TRUE)
  40.             {
  41.                 m_fCardInTheSlot = FALSE;
  42.                 // indicate the slot change 
  43.                 SDHCDIndicateSlotStateChange(m_pHCContext, 0, DeviceEjected); 
  44.                 m_bDevicePresent = FALSE;
  45.                 Stop_SDI_Clock();
  46.             }
  47.             if(IsCardPresent())
  48.             {
  49.                 m_fCardInTheSlot = TRUE;
  50.                 m_bDevicePresent = TRUE;
  51.                 //----- 5. Reset the clock to the ID rate -----
  52.                 vm_pSDIReg->SDICON     |= LITTLE_ENDIAN_BYTE_ORDER;    // Windows CE is always Little Endian.
  53.                 vm_pSDIReg->SDIFSTA     |= FIFO_RESET;                  // Reset the FIFO
  54.                 vm_pSDIReg->SDIBSIZE    = BYTES_PER_SECTOR; 
  55.                 vm_pSDIReg->SDIDTIMER   = MAX_DATABUSY_TIMEOUT;        // Data/busy timeout
  56.                 SetClockRate(SD_DEFAULT_CARD_ID_CLOCK_RATE);
  57.                 // give the card enough time for initialization
  58.                 Start_SDI_Clock();
  59.                 Wait_80_SDI_Clock_Cycles();
  60.                 //----- 6. Inform the bus handler that this is the first command sent -----
  61.                 m_bSendInitClocks = TRUE;
  62.                 //----- 7. Indicate the slot change -----
  63.                 SDHCDIndicateSlotStateChange(m_pHCContext, 0, DeviceInserted);
  64.             }
  65.         } // if
  66.     } // for
  67.     return TRUE;
  68. }

 

对于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.

  1. WaitForSingleObject的用法
  2. DWORD WaitForSingleObject(
  3.   HANDLE hHandle,
  4.   DWORD dwMilliseconds
  5. );
  6. 参数hHandle是一个事件的句柄,第二个参数dwMilliseconds是时间间隔。如果时间是有信号状态返回WAIT_OBJECT_0,如果时间超过dwMilliseconds值但时间事件还是无信号状态则返回WAIT_TIMEOUT。
  7. hHandle可以是下列对象的句柄:
  8.     Change notification 
  9. Console input 
  10. Event 
  11. Job 
  12. Memory resource notification 
  13. Mutex 
  14. Process 
  15. Semaphore 
  16. Thread 
  17. Waitable timer 
  18. WaitForSingleObject函数用来检测hHandle事件的信号状态,当函数的执行时间超过dwMilliseconds就返回,但如果参数dwMilliseconds为INFINITE时函数将直到相应时间事件变成有信号状态才返回,否则就一直等待下去,直到WaitForSingleObject有返回直才执行后面的代码。在这里举个例子:
  19. 先创建一个全局Event对象g_event:
  20.     CEvent g_event;
  21. 在程序中可以通过调用CEvent::SetEvent设置事件为有信号状态。
  22. 下面是一个线程函数MyThreadPro()
  23. UINT CFlushDlg::MyThreadProc( LPVOID pParam ) 
  24.      WaitForSingleObject(g_event,INFINITE); 
  25.      For(;;) 
  26.         { 
  27.          …………. 
  28.         } 
  29.      return 0; 
  30. 在这个线程函数中只有设置g_event为有信号状态时才执行下面的for循环,因为g_event是全局变量,所以我们可以在别的线程中通过g_event. SetEvent控制这个线程。
  31. 还有一种用法就是我们可以通过WaitForSingleObject函数来间隔的执行一个线程函数的函数体
  32.      UINT CFlushDlg::MyThreadProc( LPVOID pParam ) 
  33.      while(WaitForSingleObject(g_event,MT_INTERVAL)!=WAIT_OBJECT_0) 
  34.      { 
  35.          ……………… 
  36.      } 
  37.      return 0; 
  38. 在这个线程函数中可以可以通过设置MT_INTERVAL来控制这个线程的函数体多久执行一次,当事件为无信号状态时函数体隔MT_INTERVAL执行一次,当设置事件为有信号状态时,线程就执行完毕了。

线程怎么和中断绑定的呢?请看下面代码

  1. SD_API_STATUS CSDIOControllerBase::Initialize()
  2. {
  3.    ................
  4.    //----- 10. Setup the IST for handling SDIO data transfer interrupts -----
  5.     m_hSDIOInterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
  6.     
  7.     if(NULL == m_hSDIOInterruptEvent) 
  8.     {
  9.         status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
  10.         goto INIT_ERROR;
  11.     }
  12.     // initialize the card insertion interrupt event
  13.     if(!InterruptInitialize (m_dwSDIOSysIntr, m_hSDIOInterruptEvent,
  14.                              NULL, 0)) 
  15.     {
  16.         status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
  17.         goto INIT_ERROR;
  18.     }
  19.     m_hSDIOInterruptThread = CreateThread(NULL, 0,
  20.                                           (LPTHREAD_START_ROUTINE)SD_IOInterruptIstThread,
  21.                                           this, 0, &threadID);
  22.     
  23.     if(NULL == m_hSDIOInterruptThread) 
  24.     {
  25.         status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
  26.         goto INIT_ERROR;
  27.     }
  28.   ...........
  29. }

那么OAL里面的中断又是怎么样和这里的m_dwSDIOSysIntr绑定的呢?再看下面的代码

  1.  // convert the SDI hardware IRQ into a logical SYSINTR value
  2.     if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &m_dwSDIOIrq, sizeof(DWORD), &m_dwSDIOSysIntr, sizeof(DWORD), NULL))
  3.     {
  4.         // invalid SDIO SYSINTR value!
  5.         DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("invalid SDIO SYSINTR value!/r/n")));
  6.         m_dwSDIOSysIntr = SYSINTR_UNDEFINED;
  7.         fRetVal = FALSE;
  8.         goto FUNCTION_EXIT;
  9.     } 

现在,我有一些疑惑,在这里,我并没有看见有中断相关的一些代码,但是三星的三个SD卡DLL为什么会固定了中断呢?

难道他们的DLL有所不同?在DLL限定了中断?

原来,这份三星代码的中断是由注册表设定的,请看下面代码

  1.  // read registry settings
  2.     // read the SDIO SYSINTR value
  3.     m_dwSDIOIrq = regDevice.ValueDW( SDIO_IRQ_TEXT, 0xffffffff );
  4.     if( m_dwSDIOIrq == 0xffffffff )
  5.     {
  6.         // invalid SDIO IRQ value!
  7.         DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("invalid SDIO IRQ value!/r/n")));
  8.         fRetVal = FALSE;
  9.         goto FUNCTION_EXIT;
  10.     }

下面的宏定义就是和注册表配合的,中断之类的东西都是在注册表中配置。

#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")

 

抱歉!评论已关闭.