WINCE6.0+S3C2443的RTC初始化及存在的問題

1.系統啓動過程中RTC初始化

WINCE6.0中,我們知道是通過OALIoCtlHalInitRTC()函數來設置RTC的時間的,但是如何調用到這個函數的呢?我們就從NKStartup()函數開始,但系統從nboot開始是如何執行到NKStartup()函數的呢?我後面會抽空寫關於ebootnk的啓動過程中有涉及。

SystemStartupFunc函數中,通過下面語句來創建一個內核線程RunApps

hTh = CreateKernelThread (RunApps,0,THREAD_RT_PRIORITY_NORMAL,0);

接着就執行線程RunApps。在線程RunApps中,通過下面語句:

 hFilesys = (HMODULE) NKLoadLibraryEx (L"filesys.dll", MAKELONG (LOAD_LIBRARY_IN_KERNEL, LLIB_NO_PAGING), NULL);

來加載filesys.dll,接着通過下面語句:

hTh = CreateKernelThread ((LPTHREAD_START_ROUTINE)pfnMain, hFilesys, THREAD_RT_PRIORITY_NORMAL, 0);

來創建filesys.dll的線程WinMain(),這個線程在/WINCE600/PRIVATE/TEST/BASEOS/FILESYS/GENFILE/genfile.cpp中定義,這樣就接着執行這個線程。

Filesys.dll的主要工作是初始化文件系統、對象存儲、註冊表、CEDB數據庫、設備通知以及其它一些工作:

Filesys.dll檢測是冷啓動還是熱啓動

如果是冷啓動,對象儲存內存將被初始化並映射給Filesys.dll;對於熱啓動,不用初始化而直接映射給Filesys.dll

Filesys.dllnandflash中加載OEMcertification DLL

如果必須他能夠必須是冷啓動,Filesys.dll調用OAL函數pNotifyForceCleanboot

對於冷啓動,Filesys.dll調用OEMIoControl函數,I/O控制代碼爲IOCTL_HAL_INIT_RTC,也就是初始化RT

Filesys.dll還有很多的動作,再這裏就不介紹了,我們接下來看看OEMIoControl函數是如何一層層調用到OALIoCtlHalInitRTC的呢?接着往下看。

OEMIoControl():在/WINCE600/PLATFORM/COMMON/SRC/COMMON/IOCTL/ioctl.c下面定義

從上圖可以知道OEMIoControl函數通過傳遞進來的code來和數組g_oalIoCtlTable中的code成員比較,找到吻合的code後便跳出這個for循環,然後往下執行。而數組g_oalIoCtlTable是在/Src/Oal/Oallib/ioctl.c下定義,如下圖

接着看ioctl_tab.h的內容

到這裏我們還是沒有直觀看到IOCTL_HAL_INIT_RTC,接着往下看oal_ioctl_tab.h的內容:

在上圖的第31行可以看到IOCTL_HAL_INIT_RTC,那麼對應於IOCTL_HAL_INIT_RTC的處理函數是如何得到執行的呢?上面提到,OEMIoControl函數通過傳遞進來的code找到數組g_oalIoCtlTable中吻合的code後,通過下面的處理

會記下i的值,也就是IOCTL_HAL_INIT_RTC所在數組g_oalIoCtlTable的索引值,接着看OEMIoControl函數下面的處理

這段代碼就是根據上面確定的i的值,來執行對應的handler,在這裏就是調用OALIoCtlHalInitRTC()函數

2.RTC初始化存在的問題

從上面可知,系統啓動過程是通過調用函數OALIoCtlHalInitRTC()來初始化RTC的,這個函數體如下

從這個函數體可知是通過調用OEMSetRealTime()來設置RTC的,g_oalRtcResetTime的定義如下:

SYSTEMTIME g_oalRtcResetTime = {2010, 8, 5, 27, 12, 0, 0, 0};

因爲我們的系統每次關機後重啓都是冷啓動,所以每次啓動之後都會調用到OALIoCtlHalInitRTC函數,從而不管你之前設置的時間是多少,都會重新初始化爲g_oalRtcResetTime中的時間。我把上圖的第98行替換爲下面的函數就可以解決了這個問題:

3.BOOL OEMSetRealTime(LPSYSTEMTIME pTime) 

OEMGetRealTime()用來獲得當前的時間。WinCE啓動以後,默認情況下,WinCE會每隔一段時間調用OEMGetRealTime()函數來獲得系統的時間,這種方式被稱爲hardware mode。WinCE還有另一種獲得系統時間的方法,被稱爲software mode,就是通過調用GetTickCount()函數跟蹤系統的timetick的變化來累加時間。如果要用software mode,那麼需要在註冊表中做如下的設置:
HKEY_LOCAL_MACHINE/Platform/"SoftRTC" = 1
我來談談我的看法,一般都要使用hardware mode,這樣獲得的系統時間比較準。software mode獲得系統時間不會很準的。

4.BOOL OEMGetRealTime(SYSTEMTIME *pTime)

OEMGetRealTime()用來獲得當前的時間。WinCE啓動以後,默認情況下,WinCE會每隔一段時間調用OEMGetRealTime()函數來獲得系統的時間,這種方式被稱爲hardware mode。WinCE還有另一種獲得系統時間的方法,被稱爲software mode,就是通過調用GetTickCount()函數跟蹤系統的timetick的變化來累加時間。如果要用software mode,那麼需要在註冊表中做如下的設置:
HKEY_LOCAL_MACHINE/Platform/"SoftRTC" = 1
我來談談我的看法,一般都要使用hardware mode,這樣獲得的系統時間比較準。software mode獲得系統時間不會很準的。

5.BOOL OEMSetRealTime(LPSYSTEMTIME pTime) 

OEMSetRealTime()用來設置當前的時間。當WinCE啓動以後,我們會在界面的右下角看到時間顯示,我們可以直接在WinCE的界面裏面設置時間,這個時候,系統就會調用OEMSetRealTime()把你設置的時間寫到RTC模塊裏面。

6.LPSYSTEMTIME

LPSYSTEMTIME實際上是一個指向SYSTEMTIME結構的指針,關於SYSTEMTIME,定義如下:

typedef struct _SYSTEMTIME

    {

    WORD wYear;

    WORD wMonth;

    WORD wDayOfWeek;

    WORD wDay;

    WORD wHour;

    WORD wMinute;

    WORD wSecond;

    WORD wMilliseconds;

    } SYSTEMTIME;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章