• <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>

            milkyway的窩

            最初想法的誕生地

             

            解讀WINCE 5.0 KITL代碼流程

            作者:Walzer
            日期:2005.3.19

            摘要:KITL是PLATFORM BUILDER中的一個亮點,提供了和本地調(diào)試類似的斷點、變量跟蹤、內(nèi)存查看等手段,如果沒有KITL,嵌入式調(diào)試應(yīng)該只能用串口打印消息來看了,工作效率大大下降。本文以實現(xiàn)最簡單的SERIAL KITL為目的,就其實現(xiàn)代碼進行跟蹤調(diào)試,這些代碼跨越了WINCE的PLATFORM、PUBLIC、PRIVATE三大主要目錄,有些煩瑣,不過只要能調(diào)通,一切工作和彎路都是值得的。我把調(diào)試經(jīng)驗和個人理解寫下來,希望能幫助別人少走彎路。如果文章中有理解失當(dāng)?shù)牡胤剑埐涣哔n教。

            正文:

            一.void OEMInit()? [platform\project\src\kernel\oal\init.c]
            ??? 首先從OEMInit()函數(shù)看起。。在依次初始化Branch-Target Buffer、KERNEL函數(shù)、初始化中斷、TIMER之后,就輪到KITL了。調(diào)用了這個函數(shù)OALKitlStart()。此時有個編譯的分支,如果是RELEASE版本,那么在kernel\kern\stubs.c里面的OALKitlStart()函數(shù)是個STUB,只是return TRUE; 如果是DEBUG版本,那就進到kernel\oal\kitl.c里面的OALKitlStart().

            二.BOOL OALKitlStart()? [platform\myproject\src\kernel\oal]
            ??? 在OALKitlStart()里面,首先試圖從0xA00FF00處讀取bootloader里面留下的kitl參量,如果讀不到東西則使用該函數(shù)里的默認配置。由于原來用了ethernet同時作為download和kitl途徑,所以在InitSpecifiedEthDevice函數(shù)里給pKitlArgs結(jié)構(gòu)體賦值了。現(xiàn)在想把兩者劃分清楚,首先就把讀取bootloader里面的kitl參量一句干掉,強迫使用我們在下面的默認配置。主要就是填充三個參量

            1.首先是這個結(jié)構(gòu)體
            OAL_KITL_ARGS pKITLArgs
            {
            ?UINT32 flags;? //設(shè)好ENABLED標(biāo)志,按需要設(shè)POLL標(biāo)志,但注意一定不要設(shè)PASSIVE標(biāo)志
            ?DEVICE_LOCATION? devLoc;
            ?{
            ??DWORD? IfcType;??//不論ether還是serial,都是internal type =0;
            ??DWORD? BusNumber;?// =0
            ??DWORD? LogicalLoc;?//物理地址
            ??PVOID???? PhysicalLoc;?//留做后面=OALPAtoVA(LogicalLoc, FALSE). 真見鬼, 感覺應(yīng)該和上面的LogicalLoc作用調(diào)過來看著比較順吧?
            ??DWORD? Pin;??//Ethernet才用的東東
            ?}
            ?union
            ?{
            ??struct
            ??{
            ???UINT32? baudRate;?//不用解釋了
            ???UINT32? dataBits;
            ???UINT32? stopBits;
            ???UINT32? parity;
            ??}
            ??struct
            ??{
            ???UINT16? mac[3];?//這個也不用解釋了
            ???UINT32? ipAddress;
            ???UINT32? ipMask;
            ???UINT32? ipRoute
            ??}
            ?}
            }
            2. pszDeviceID.? 感覺這名字就是起了好玩, 賦成Walzer應(yīng)該比較拽,不過還是保留原來賦的AMOISOFT好了, 免得被打.
            3. 全局變量OAL_KITL_DEVICE g_kitlDevices. 這個東東在kitl.c開頭包含的kitl_cfg.h中被賦值,? 最主要就是修改g_kitlDevices.pDriver.? 這個pDrvier指向一個函數(shù)指針列表的結(jié)構(gòu)體,該列表定義了用做kitl模塊的初始化、讀寫、中斷、流控制等函數(shù)。 g_kitlDevices本身是個二維數(shù)組, 可以定義許多設(shè)備用做kitl時提供的參數(shù)設(shè)置, 后面會用一個for來循環(huán)判斷pKITLArgs的參數(shù)和g_kilDevices里面哪個一維數(shù)組成員相匹配.

            這三個參量填充好以后,就可以進到OALKitlInit(pszDeviceID, pKITLArgs, g_kitlDevices)里面了.

            三.BOOL OALKitlInit( deviceId, pArgs, pDevice)??? [platform\common\src\common\kitl\kitl.c]
            ??? 這個函數(shù)先把輸入的參量全部用OALMSG打印出來,這個不管。
            ??? 重要的是引入了g_kitlState全局變量,開頭一句
            ??? g_kitlState.pDevice = OALKitlFindDevice(&pArgs->devLoc, pDevice) 這個就是上面所說的從g_kitlDevices里可用設(shè)備列表里循環(huán)判斷,找到選用的設(shè)備的匹配函數(shù)指針。
            ??? 接著把輸入?yún)⒘縟evicdId和前面填充好的OAL_KITL_ARGS結(jié)構(gòu)COPY到g_kitlState里面
            ??? 然后就可以調(diào)用KItlInit(TRUE)了,如果前面在FLAG里面設(shè)了PASSSIVE標(biāo)志,現(xiàn)在就是KitlInit(FALSE)了,嘿嘿爽到了吧。

            四.BOOL KitlInit(BOOL fStartKitl)??? [private\winceos\coreos\nk\kitl\ethdbg.c]
            ??? 太猥瑣了,我要用串口,它居然叫ethdbg.c,不給面子。不過是private里面的東東,可遠觀而不可褻玩焉~~
            ??? 這個函數(shù)干了三件事:
            1. 裝載了三個全局的函數(shù)指針
            2. 用NewClient注冊了三個KITL客戶端:
            ??? KITL_SVCNAME_DBGMSG?? //debug message, Debug信息發(fā)布通道
            ??? KITL_SVCNAME_PPSH? //PPshell, 文本控制臺界面
            ??? KITL_SVCNAME_KDBG //kernel debug, 內(nèi)核調(diào)試界面

            3.由fStartKitl來決定是否啟動StartKitl()函數(shù). (這里順便提一下,按照匈牙利命名法, BOOL變量前面加個b, 但MS的做法我覺得很合理, BOOL變量就是個FLAG嘛, 前面加個f, 把小b留著給BYTE類型用.)

            五.static BOOL StartKitl(BOOL fInit)??? [private\winceos\coreos\nk\kitl\ethdbg.c]
            ??? 這又是prviate里面的東東。最痛苦的地方開始了。這函數(shù)及其子函數(shù)將第一次調(diào)用OEM自己寫的KITL模塊初始化、讀寫程序。是騾子是馬,拉出來溜溜就知道啦~
            ??? 按順序看下來,首先判斷輸入?yún)⒘渴欠褚獑覭ITL,并且如果KITLGlobalState里面被打上KITL_ST_DESKTOP_CONNECTED標(biāo)記的話,那下面的步驟就全免了。當(dāng)然我們是第一次運行到這里,若這么就跳出的話,俺就馬加爵了。

            ??? 第一步:
            ??? 干的第一件正事就是調(diào)用OEMKitlInit(&Kitl). 這個后面詳述. 繼續(xù)把這個函數(shù)看完.
            ??? OEMKitlInit初始化KITL的硬件抽象層后并把相關(guān)指針數(shù)據(jù)填充給全局變量KITLTRANSPORT Kitl (有沒有搞錯,為什么不叫g(shù)_kitl), 這些工作做完就返回了
            ???? StartKitl收貨后把Kitl結(jié)構(gòu)整個檢查一遍,保證沒錯后, 馬上買單, 把全局變量KITLGlobalState打上個KITL_ST_KITLSTARTED標(biāo)記. 這才算KITL啟動的第一步OK了.

            ??? 第二步:
            ??? 接下來就是KITLConnectToDesktop(), 進這個函數(shù)后就是第一次使用了前面KITL傳輸介質(zhì)硬件抽象層里的讀寫函數(shù)了, 這時候就需要調(diào)試了. 這個ConnectToDesktop大致就是先Send了一個kITL.....的frame過去,然后polling等待PC端的response, 那邊再發(fā)個kITL.....的frame過來, 搞得跟地下黨打暗號似的, 其實也沒什么玄乎的,就是普通的數(shù)據(jù)包前面加個KTIL專用的HEADER而已. 這個CONNECT成功后,KITLGlobalState里面就加個KITL_ST_DESKTOP_CONNECTED標(biāo)記了.

            ??? 第三步:
            ??? set up kernel function pointers, 也沒什么,就三個函數(shù)指針, 賦完后就KITL_ST_ADAPTER_INITIALIZED了. 其實這個KITLGolbalSate的總共有7個標(biāo)志,分別是
            KITL_STARTED,? (OK)
            DESKTOP_CONNECTED,?? (OK)
            TIMER_INIT, (?)
            INT_ENABLED,? (POLLING)
            IST_STARTED,? (POLLING)
            MULTITHREADED,?? (?)
            ADAPTER_INITIALIZED. (OK)
            后面括號里打上OK是到這里已經(jīng)完成的, 打問號的我還不太清楚什么作用, INT和IST兩項,我們用的POLLING所以肯定是不需要了.

            ??? 第四步:
            ??? 調(diào)用SetKernelCommDev設(shè)置kernel通過何種介質(zhì)傳送DBGMSG, PPSH和KDBG.
            ??? OHYEAH, 我的SERIAL KITL就夭折在這里. 進到SerKernelCommDev(service, CommDevice)函數(shù)里看, 它只認CommDevice=KERNEL_COMM_ETHER的情況,而屏蔽了與ETHER并列的SERIAL和PARALLER,直接return FALSE, 下面的事情都不用干了. 而在MS提供的WinCE Documantation里面,這個SetKernelCommDev函數(shù)的說明上寫著"This function is obsolete and should not be used". 若想改嘛,這個是在private里面的還動它不得. NND, 感覺被MS raped了.
            ???? 如果使用ETHER在這里成功的話, 下面還有兩個函數(shù)NKForceCleanBoot()和KITLInitializeInterrupt()走過去, 這KITL初始化就全部結(jié)束了. 我估計KITLGolbalSate里面的INIT_ENABLED和IST_STARTED就是在這個函數(shù)過程中被標(biāo)記上的.
            ????
            ???
            六.BOOL OEMKitlInit(PKITLTRANSPORT pKitl)??? [platform\common\src\common\kitl\kitl.c]
            ??? 前面提到StartKItl起來后,首要的就是調(diào)用OEMKitlInit. 這個函數(shù)在WinCE4.2和5.0里差別很大, 4.2里的做法是??? if (!InitEther (pKitl) && !InitParallelSerial (pKitl)), 把ETHER, SERIAL, PARALLEL都初始化了一遍,碰運氣看哪個用得上,而5.0里是進來后就一個很明顯的分支劇情,由g_kitlState.pDevice->type來決定是調(diào)用OALKitlEthInit還是OALKitlSerialInit. 典型的種族歧視, 居然沒有OALKitlParallelinit. 還好我們用的是SERIAL.
            ??? 這里有個選擇編譯的地方,就是#ifdef KITL_ETHER和#ifdef KITL_SERIAL, 具體定義的地方是該目錄下的sources文件里面一行 CDEFINES=$(CDEFINES) -DKITL_SERIAL -DKITL_ETHER, 猥瑣啊找了半天. 其實我覺得既然有if結(jié)構(gòu)來選了,那么選擇編譯也是可有可無的了.
            ??? 好,下面就進到OALKItlSerialInit()里面.

            七.BOOL OALKitlSerialInit(LPSTR deviceId, OAL_KITL_DEVICE *pDevice, OAL_KITL_ARGS *pArgs, KITLTRANSPORT *pKitl)
            ??? [platform\common\src\common\kitl\kitlserial.c]
            ??? 我自己往這個kitlserial.c文件里寫了六個函數(shù).
            ??? BOOL KitlSerialInit(KITL_SERIAL_INTFO *pSerInfo)
            ??? UINT16 KitlSerialWriteData(UINT8 *pch, UINT16 length)
            ??? UINT16 KitlSerialReadData(UINT8 *pch, UINT16 length)
            ??? void KitlSerialFlowControl? //stub, 我所用的FFUART只有TXD和RXD兩根線, RTS等都沒有, 所以FlowControl自然也應(yīng)該是STUB了
            ??? void KitlSerialEnableInt(void)?? //stub, use polling
            ??? void KitlSerialDisableInt(void)? //stub, use polling
            ??? 否則前面的g_kitlDevices里面沒有相應(yīng)的硬件抽象層來填充.
            ??? 上面的SerialRecv, Encode, Decode等就意思都很明顯了,不用多說. OK現(xiàn)在已經(jīng)走到最底層了, 文章也可以結(jié)束了.

            八、記錄一下調(diào)試經(jīng)驗
            ??? 雖然這是我第三次調(diào)串口了,由于沒總結(jié)前面的經(jīng)驗,還是耗了兩天才到private里面夭折的地方。實際上應(yīng)該一天就能走到了。問題出在
            1. 第一天調(diào)試器根本用不上手。調(diào)試器軟件、PB不斷死翹,經(jīng)常重啟軟件甚至重啟電腦,第一天有3/4以上的時間耗在這些問題上, 不斷重啟。
            2. 在UART初始化函數(shù)的最后,居然忘記了在interrupt controller register里面enable uart unit, 這么烏龍的事。
            3. KitlSerialFlowControl的問題. 寫的時候照搬了X86下的函數(shù), 沒想明白到底要Control什么. 調(diào)試時死在這里后,? 一開始把指向這個函數(shù)的指針設(shè)置成NULL, 但這樣PRIVATE里面有些要IF判斷的函數(shù)就進不去了. 后來換成STUB就OK了.
            4. receive函數(shù)里面, 在收每個BYTE之前先去判斷了Line Status Register里面的Data Ready bit, 如果該為零, 則返回失敗. 但這里是有問題的,具體也沒太想明白, 反正在調(diào)試debug serial的時候就把這個判斷從MS提供的源碼里頭刪去了,現(xiàn)在做KITL serial時又手癢加進去, 果然還是不行. 這可能是MS或INTEL的一處BUG, 但按照INTEL CPU MANUL UPDATE里面給的讀流程, 一開始只判斷LSR里面的ERROR, 沒有判斷DR位就開始讀第一個BYTE了. 讀過后再判斷如果DR位為1,則繼續(xù)讀下一BYTE.
            5. 在receive函數(shù)里加通過debugger加break point, 結(jié)果receive buffer register里面的數(shù)據(jù)被debugger掃描去以后,就變零了,CPU上卻什么都收不到, 這事情耗了大半個下午,最后還是Jeffery發(fā)現(xiàn)的這個問題.

            參考文章:
            KITL解析 by Nasiry? (http://nasiry.cnblogs.com/archive/2004/09/22/45473.html)

            posted on 2007-01-16 10:00 milkyway 閱讀(1981) 評論(1)  編輯 收藏 引用 所屬分類: wince(別人的文章技巧總結(jié))

            評論

            # re: 解讀WINCE 5.0 KITL代碼流程 2007-01-16 10:02 相思酸中有甜

            BOOTLOADER和KITL是兩碼事, 兩者的執(zhí)行順序應(yīng)該是,
            1. 板上跑的BOOTLOADER出了個菜單, 選擇LAUNCH或者DOWNLOAD.
            2. 如果選擇了D, 那么BOOTLOADER會SEND BOOTME給PB
            3. 然后PB響應(yīng)了下載NK.BIN文件到板子上
            4. 下載完畢后BOOTLOADER由自身代碼決定,跳轉(zhuǎn)到RAM或FLASH里的一個指定地址開始執(zhí)行(必須是這個NK.BIN的起始地址)
            5. NK.BIN里面包含了KITL初始化的代碼,這個KITL初始化去連接PB的KITL.

            如果選擇了L,那么就是跳過第2,3步,直接到第4步,跳轉(zhuǎn)到FLASH里的地址開始執(zhí)行.

            也就是說,DOWNLOAD或LAUNCH是由BOOTLOADEER(比如EBOOT.BIN)決定的, 而KITL連接是由NK.BIN決定的. LAUNCH后,就直接跳轉(zhuǎn)到FLASH里燒好的NK.BIN開始地址執(zhí)行. 在這之后, NK.BIN里是否帶有KITL初始化代碼決定了PB這邊能否和板子的KITL連起來.
              回復(fù)  更多評論   

            導(dǎo)航

            統(tǒng)計

            公告

            隨筆皆原創(chuàng),文章乃轉(zhuǎn)載. 歡迎留言!

            常用鏈接

            留言簿(37)

            隨筆分類(104)

            隨筆檔案(101)

            文章分類(51)

            文章檔案(53)

            wince牛人

            搜索

            積分與排名

            最新評論

            閱讀排行榜

            評論排行榜

            91视频国产91久久久| 国产色综合久久无码有码| 青青热久久综合网伊人| 国产成人AV综合久久| 久久久国产精华液| 久久久久免费看成人影片| 国产精品伊人久久伊人电影| 伊人久久国产免费观看视频| 久久久国产乱子伦精品作者| 久久久久亚洲AV无码专区桃色 | 77777亚洲午夜久久多人| 亚洲精品无码久久千人斩| 国产精品丝袜久久久久久不卡| 亚洲精品无码久久千人斩| 欧美日韩精品久久久久| 久久99精品国产一区二区三区| 久久久久久精品久久久久| 久久99精品久久久久久水蜜桃| 久久国产乱子伦免费精品| 日本亚洲色大成网站WWW久久| 久久精品无码一区二区三区| 亚洲综合伊人久久综合| 久久婷婷午色综合夜啪| 欧美与黑人午夜性猛交久久久| 久久狠狠色狠狠色综合| 99久久婷婷国产综合亚洲| 久久久久久夜精品精品免费啦| 亚洲精品乱码久久久久久| 噜噜噜色噜噜噜久久| 久久性生大片免费观看性| 久久人人爽人人爽AV片| 久久久久亚洲AV成人网人人软件| 99久久久久| 欧美日韩精品久久久久| 亚州日韩精品专区久久久| 久久精品中文字幕有码| 久久免费视频一区| 国产精品99久久久精品无码| 97精品伊人久久大香线蕉| 久久天天婷婷五月俺也去| 国产香蕉久久精品综合网|