• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 74, 文章 - 0, 評(píng)論 - 26, 引用 - 0
            數(shù)據(jù)加載中……

            wince6.0移植之oal 轉(zhuǎn)

            [克隆BSP]

            Clone一個(gè)BSP.

            WinCE6.0安裝armv4i架構(gòu)后,里面提供了一個(gè)名字為DeviceEmulatorBSP. 這個(gè)BSPs3c2410BSP.我的是s3c2440a,就克隆這個(gè)吧.

             


            [移植OAL]

            WinCE5.0OAL是編譯成為一個(gè)靜態(tài)庫oal.lib,然后與內(nèi)核nk.lib靜態(tài)編譯成kernel.exe,也就是nk.exe. WinCE6.0OALkernel中剝離出來單獨(dú)編譯成為oal.exe,內(nèi)核則編譯成了Kernel.dll. 分離的代價(jià)是不能再直接使用相互的資源了,即相互間的全局變量和函數(shù)不能直接訪問了. OEMGLOBAL NKGLOBAL2個(gè)結(jié)構(gòu)體充當(dāng)了OALKernel的接口橋梁. 分離的好處是更方便內(nèi)核獨(dú)立升級(jí)(嗯哼~ 這在將來會(huì)發(fā)生么?設(shè)備的架構(gòu)可是千差萬別的.我想替內(nèi)核升級(jí)最有可能的還是OEMs,不是MS),不過另外一個(gè)好處是接口更清晰了,內(nèi)核會(huì)需要哪些OEM函數(shù)顯得更直觀明了.

            內(nèi)核的啟動(dòng)和原來略有不同了,簡單回顧WinCE5.0的內(nèi)核啟動(dòng)過程:

            [NK.exe=Kern.exe]

            StartUp()                      [ OAL入口點(diǎn)]

                 KernelStart()                  [ kernel入口點(diǎn)]

                          ArmInit()

                                     OEMInitDebugSerial()

                             OEMInit()

                       KernelInit()

                           HeapInit()

                           InitMemoryPool()

                           ProcInit()

                           SchedInit()

                         FirstSchedule()                             

             

             
             

             

             

             

             

             

             

             

             

             

             

             

             


            下面是WinCE6.0的內(nèi)核啟動(dòng)過程:

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             


            OAL不能調(diào)用內(nèi)核的KernelStart()函數(shù)了, 所以自己要實(shí)現(xiàn)一個(gè)KernelStart() (nkldr.lib替我們完成了這個(gè), nkldr.lib鏈接到OAL),調(diào)用nkldr.lib中的KernelStart().然后執(zhí)行的ARMInit()函數(shù)有一個(gè)很重要的任務(wù),它將位于OALOEMinitGlobals()函數(shù)指針賦值到Kdata, 后面內(nèi)核需要這個(gè)指針.接下來根據(jù)Kdata找到并跳轉(zhuǎn)到內(nèi)核kernel.dll的入口點(diǎn)NKStartup().

            Kernel.dll開始執(zhí)行NKStartUp(),首先要把和OAL的橋梁打通.也就是把內(nèi)核的NKGlobal數(shù)據(jù)結(jié)構(gòu)指針交給OAL,并且獲得OALOEMGlobal的數(shù)據(jù)結(jié)構(gòu)指針. 怎么實(shí)現(xiàn)的? 內(nèi)核根據(jù)Kdata找到OAL中一個(gè)函數(shù)OEMInitGlobals()  還記得嗎,前面說到OALARMInit()曾經(jīng)鄭重的把OEMInitGlobals函數(shù)指針賦值給了Kdata,就是為了這一天... 然后,NKGlobal指針作為參數(shù)執(zhí)行這個(gè)函數(shù), 這個(gè)函數(shù)返回OALOEMGlobal的指針.(嗯哼~ OAL要實(shí)現(xiàn)OEMInitGlobals(), oemmain.lib替我們完成了這個(gè),oemmain.lib鏈接到OAL).

            這個(gè)Kdata是個(gè)什么玩意? 它是內(nèi)核數(shù)據(jù)結(jié)構(gòu), 簡單理解成共享內(nèi)存好了, oal kernel都可訪問到.再往后沒啥好說了,內(nèi)核可以訪問OAL,痛快的調(diào)用OEM函數(shù),和以前WinCE5.0差不多. 最后調(diào)用KernelStart(),這回這個(gè)函數(shù)可是在內(nèi)核里面了,WinCE6.0起來了……

            這個(gè)流程和WinCE5.0有點(diǎn)點(diǎn)差別.都是因?yàn)?/span>OALkernel分離了.

            [編譯OAL]

            空談了這么久,來做實(shí)質(zhì)性的工作吧,開始編譯WinCE6.0OAL. 微軟希望它的設(shè)計(jì)使得移植OAL時(shí)候盡可能少工作量,所以oal.exe2個(gè)步驟來實(shí)現(xiàn).第一步:編譯oal.lib.第二步:編譯oal.exe. 第一步的oal.lib可以就是原來版本的,你拷貝原來的oal目錄代碼到OALLIB目錄編譯一個(gè)oal.lib.關(guān)鍵是第二步,原來在WinCE5.0時(shí)候,oal.lib+nk.lib編譯成了kern.exe,然后改名成nk.exe.現(xiàn)在,要把oal+nkstub.lib,編譯成oal.exe.nk.lib也不是說不要就可以直接不要的.在編譯oal.lib時(shí)候可是大量使用了nk.lib的東東. 你不會(huì)想全文重新改變函數(shù)和變量的調(diào)用形式吧? ok,nkstub.lib鏈接上.這么一來, OALEXE目錄下的SOURCES文件里面,4個(gè)庫被添加進(jìn)來.

              TARGETLIBS= oal.lib oemmain.lib nkldr.lib nkstub.lib ……(路徑省略)

            Nkldr.liboemmain.lib是干嗎的?回溯前面的啟動(dòng)過程吧. nkldr.lib提供了KernelStart()的實(shí)現(xiàn), oemmain.lib提供了OEMInitGlobals()的實(shí)現(xiàn).當(dāng)然還有更多的,不羅列了.

            [定制OAL]

            沒有oal.lib咋辦?做一個(gè)吧……前面提到OALKernel分離,使得接口更加明顯了,kernel到底需要OEMs提供哪些函數(shù),可以參照著oemglobal.h文件里面OEMGLOBAL結(jié)構(gòu)體來完成.并且在oemglobal.c里面對這個(gè)結(jié)構(gòu)體初始化.這個(gè)文件位于oemmain.lib.發(fā)揚(yáng)愚公移山的精神,我來抽絲撥繭一下,下面根據(jù)我的2440來分析最重要的必須的幾個(gè)接口:

            [Init相關(guān)接口]

            要提供OEMInit(), OEMInitDebugSerial(),

            OEMInit()函數(shù),建立一個(gè)init.c,然后實(shí)現(xiàn)這個(gè)函數(shù).

            OEMInitDebugSerial()放到下面debug.c中實(shí)現(xiàn).

            [Debug相關(guān)接口]

            OEMWriteDebugString

            OEMInitDebugSerial

            OEMWriteDebugByte

            OEMReadDebugByte

            OEMWriteDebugLED

            PQOALoal_other.lib提供了OEMWriteDebugString(),

            OALLIB下創(chuàng)建debug.c ,然后實(shí)現(xiàn)OEMInitDebugSerial, OEMWriteDebugByte, OEMReadDebugByte, OEMWriteDebugLED4個(gè)函數(shù).

            [Cache相關(guān)接口]

            需要提供OEMCacheRangeFlush, 根據(jù)自己的架構(gòu)去已有的PQOAL找吧,我的是oal_cache_arm920t.lib

            [Time相關(guān)接口]

            需要提供

            InitClock

            OEMGetRealTime

            OEMSetRealTime

            OEMSetAlarmTime

            OEMQueryPerfCounter

            OEMQueryPerfFreq

            OEMGetTickCount

             

            InitClock,這個(gè)功能已經(jīng)廢除了, 相關(guān)功能被移到OEMPowerOff.所以可以實(shí)現(xiàn)一個(gè)空函數(shù),在初始化OemGlobal時(shí)候,把這個(gè)指針賦值RetuanFalse()函數(shù)也是一樣的效果.OEMGetRealTime ,OEMSetRealTime是設(shè)置讀取rtc的日期功能.OEMSetAlarmTime是設(shè)置rtc的報(bào)警時(shí)刻,找到oal_rtc_s3c2440a.lib

            OEMQueryPerfCounter,OEMQueryPerfFreq是提供更高精度時(shí)間的查詢,

            OEMGetTickCount返回當(dāng)前CurMSec,系統(tǒng)運(yùn)行了多少毫秒.oal_time.lib中已經(jīng)有實(shí)現(xiàn).特別強(qiáng)調(diào)的是,這個(gè)函數(shù)在WinCE5.0里面是SC_GetTickCount.需要把名字改了.這個(gè)是OAL的一個(gè)區(qū)別.

            [Scheduler相關(guān)接口]

                   OEMIdle, OEMNotifyThreadExit, OEMNotifyIntrOccurs, OEMUpdateReschedTime, 一個(gè)變量DefaultThreadQuantum.

            [power相關(guān)接口]

            OEMPowerOff, 這個(gè)還要說啥, 掛起時(shí)候會(huì)執(zhí)行這個(gè)函數(shù). PQOALoal_power_s3c2440a.lib已經(jīng)幫忙實(shí)現(xiàn)了最基礎(chǔ)的工作,會(huì)調(diào)用BSPPowerOff來完成平臺(tái)相關(guān)的動(dòng)作,建立一個(gè)文件power.c來實(shí)現(xiàn)這個(gè)BSPPowerOff.

                                       

            [DRAM相關(guān)接口]

                   OEMGetExtensionDRAM, OEMEnumExtensionDRAM, CalcFSPages, 變量MainMemoryEndAddress

            這組函數(shù)詢問擴(kuò)展RAM的情況,如果OEMEnumExtensionDRAM函數(shù)提供了, 就執(zhí)行這個(gè)函數(shù),否則執(zhí)行OEMGetExtensionDRAM, CalcFSPages計(jì)算pages, 這個(gè)功能內(nèi)核自己實(shí)現(xiàn)了,已經(jīng)不要了,指向一個(gè)空函數(shù)即可.

            [interrupt相關(guān)接口]

            OEMInterruptEnable, OEMInterruptDisable, OEMInterruptDone,

            OEMIniterruptMask,OEMInterruptHandler

                   基本工作PQOAL已經(jīng)做好了,PQOAL下面幾個(gè)接口完成平臺(tái)相關(guān)工作,BSPIntrInit, BSPIntrRequestIrq, BSPINtrEnableIrq, BSPIntrDisableIrq, BSPIntrDoneIrq, BSPIntrActiveIrq.最后一個(gè)OEMInterruptHandler就是系統(tǒng)ISR, 將物理irq轉(zhuǎn)換成邏輯中斷SYSINTR_XXX.

            [other ]

                   OEMIoControl .PQOAL里面已經(jīng)實(shí)現(xiàn)了這個(gè)功能.如果OEMs要添加新的控制命令, 建立一個(gè)ioctl.c,定義一個(gè)全局?jǐn)?shù)組g_oalIoCtlTable, 然后往數(shù)組里面填入命令字和對應(yīng)命令執(zhí)行的函數(shù)的名稱.這個(gè)對應(yīng)命令的執(zhí)行函數(shù)當(dāng)然要自己實(shí)現(xiàn)了. 驅(qū)動(dòng)或者應(yīng)用使用KernelIOControl這個(gè)api時(shí)候,相應(yīng)命令的函數(shù)就會(huì)執(zhí)行.

            [總結(jié)]

            1.WinCE6.0不只是將OALkernel分離.還將kitl也分離成為了kitl.dll. 所以,OAL也不能直接使用kitl的資源. 首先把kitl.ckitl相關(guān)代碼從OAL里面給放到kitl目錄去.然后在OEMInit中不能調(diào)用OALKitlStart(),KITLIoctl(IOCTL_KITL_STARTUP, NULL, 0, NULL, 0, NULL);這一句來替代.

            2.OAL需要使用的數(shù)據(jù)結(jié)構(gòu)定義,和外部函數(shù)聲明都在頭文件nkexport.h.可以在oal.hinclude這個(gè)nkexport.h頭文件.

                   3. PQOALoal_log庫有了變化,如果使用了這個(gè)庫的要注意,它不在使用g_oalLogMask這個(gè)全局變量了.

            4. timertimer_dvs目錄下的watchdog.c文件和nkexport.h中重復(fù)定義了pfnOEMRefreshWatchDog,dwOemWatchDogPeriod.一個(gè)解決辦法是去掉watchdog.c.反正也可以不使用這個(gè)接口.默認(rèn)傳過去的是空接口ReturnFalse()

            5. 編譯smflash.dll出錯(cuò),需要fal.lib一起編譯成為smflash.dll. fal的源代碼位于private\winceos\driver\msflash\src.這個(gè)fal.lib.好像和以前的不一樣.從錯(cuò)誤信息中觀察,好像多出來2個(gè)接口.fmd.cpp里面增加這2個(gè)接口:

            LPVOID FMDHOOK_HookInterface(PFMDInterface pInterface)

            { return (LPVOID) pInterface;}

            Void FMDHOOK_UnhookInterface(LPVOID pContext, FMDInterface *pInterface){}

            至此, 在給oal加上一個(gè)啟動(dòng)代碼startup.s. 一個(gè)oal.lib就完成了.

            posted on 2008-11-12 10:19 井泉 閱讀(1053) 評(píng)論(0)  編輯 收藏 引用


            只有注冊用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            精品亚洲综合久久中文字幕| 久久无码人妻一区二区三区午夜 | 久久综合久久性久99毛片| 久久久久九国产精品| 伊人久久综合精品无码AV专区| 日韩精品无码久久久久久| 国产99久久精品一区二区| 日日狠狠久久偷偷色综合0| 久久国产欧美日韩精品| 久久免费大片| 国产精品岛国久久久久| 国内精品久久久久影院亚洲| 丰满少妇人妻久久久久久| 亚洲国产成人久久精品99 | 亚洲精品成人网久久久久久| 久久国产免费观看精品3| 久久人人爽人人爽人人片AV麻豆 | 国产成人精品久久一区二区三区av| 久久国产精品无| 国产精品成人无码久久久久久| 色偷偷久久一区二区三区| 久久笫一福利免费导航| 久久99精品国产麻豆婷婷| 久久国产免费观看精品3| 久久精品国产99久久久古代| 精品人妻伦九区久久AAA片69| 99久久免费国产特黄| 亚洲中文字幕无码久久精品1| 欧美久久久久久精选9999| 国产精品久久久99| 久久噜噜电影你懂的| 99999久久久久久亚洲| 亚洲欧美日韩中文久久| 久久综合久久美利坚合众国| 伊人 久久 精品| 久久亚洲AV无码精品色午夜麻豆 | 久久综合九色综合精品| 国产精品美女久久久| 国产成人精品白浆久久69| 久久久婷婷五月亚洲97号色| 久久这里只有精品18|