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

            正文:

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

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

            1.首先是這個(gè)結(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). 真見(jiàn)鬼, 感覺(jué)應(yīng)該和上面的LogicalLoc作用調(diào)過(guò)來(lái)看著比較順吧?
            ??DWORD? Pin;??//Ethernet才用的東東
            ?}
            ?union
            ?{
            ??struct
            ??{
            ???UINT32? baudRate;?//不用解釋了
            ???UINT32? dataBits;
            ???UINT32? stopBits;
            ???UINT32? parity;
            ??}
            ??struct
            ??{
            ???UINT16? mac[3];?//這個(gè)也不用解釋了
            ???UINT32? ipAddress;
            ???UINT32? ipMask;
            ???UINT32? ipRoute
            ??}
            ?}
            }
            2. pszDeviceID.? 感覺(jué)這名字就是起了好玩, 賦成Walzer應(yīng)該比較拽,不過(guò)還是保留原來(lái)賦的AMOISOFT好了, 免得被打.
            3. 全局變量OAL_KITL_DEVICE g_kitlDevices. 這個(gè)東東在kitl.c開(kāi)頭包含的kitl_cfg.h中被賦值,? 最主要就是修改g_kitlDevices.pDriver.? 這個(gè)pDrvier指向一個(gè)函數(shù)指針列表的結(jié)構(gòu)體,該列表定義了用做kitl模塊的初始化、讀寫(xiě)、中斷、流控制等函數(shù)。 g_kitlDevices本身是個(gè)二維數(shù)組, 可以定義許多設(shè)備用做kitl時(shí)提供的參數(shù)設(shè)置, 后面會(huì)用一個(gè)for來(lái)循環(huán)判斷pKITLArgs的參數(shù)和g_kilDevices里面哪個(gè)一維數(shù)組成員相匹配.

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

            三.BOOL OALKitlInit( deviceId, pArgs, pDevice)??? [platform\common\src\common\kitl\kitl.c]
            ??? 這個(gè)函數(shù)先把輸入的參量全部用OALMSG打印出來(lái),這個(gè)不管。
            ??? 重要的是引入了g_kitlState全局變量,開(kāi)頭一句
            ??? g_kitlState.pDevice = OALKitlFindDevice(&pArgs->devLoc, pDevice) 這個(gè)就是上面所說(shuō)的從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,不給面子。不過(guò)是private里面的東東,可遠(yuǎn)觀而不可褻玩焉~~
            ??? 這個(gè)函數(shù)干了三件事:
            1. 裝載了三個(gè)全局的函數(shù)指針
            2. 用NewClient注冊(cè)了三個(gè)KITL客戶端:
            ??? KITL_SVCNAME_DBGMSG?? //debug message, Debug信息發(fā)布通道
            ??? KITL_SVCNAME_PPSH? //PPshell, 文本控制臺(tái)界面
            ??? KITL_SVCNAME_KDBG //kernel debug, 內(nèi)核調(diào)試界面

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

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

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

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

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

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

            七.BOOL OALKitlSerialInit(LPSTR deviceId, OAL_KITL_DEVICE *pDevice, OAL_KITL_ARGS *pArgs, KITLTRANSPORT *pKitl)
            ??? [platform\common\src\common\kitl\kitlserial.c]
            ??? 我自己往這個(gè)kitlserial.c文件里寫(xiě)了六個(gè)函數(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等都沒(méi)有, 所以FlowControl自然也應(yīng)該是STUB了
            ??? void KitlSerialEnableInt(void)?? //stub, use polling
            ??? void KitlSerialDisableInt(void)? //stub, use polling
            ??? 否則前面的g_kitlDevices里面沒(méi)有相應(yīng)的硬件抽象層來(lái)填充.
            ??? 上面的SerialRecv, Encode, Decode等就意思都很明顯了,不用多說(shuō). OK現(xiàn)在已經(jīng)走到最底層了, 文章也可以結(jié)束了.

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

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

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

            評(píng)論

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

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

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

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

            導(dǎo)航

            統(tǒng)計(jì)

            公告

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

            常用鏈接

            留言簿(37)

            隨筆分類(104)

            隨筆檔案(101)

            文章分類(51)

            文章檔案(53)

            wince牛人

            搜索

            積分與排名

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            久久国产精品偷99| 久久久久久久免费视频| 91超碰碰碰碰久久久久久综合| 久久国产精品无码HDAV| 思思久久99热只有频精品66| 久久久久久久97| 国内精品九九久久久精品| 久久乐国产精品亚洲综合| 日本精品久久久久中文字幕8 | 久久国产免费观看精品| 久久亚洲美女精品国产精品| 国产91久久综合| 国产成年无码久久久久毛片| 伊人久久大香线焦综合四虎| 久久99热这里只有精品国产| 久久99九九国产免费看小说| www亚洲欲色成人久久精品| 久久这里只有精品久久| 亚洲AV日韩AV永久无码久久| 久久国产精品一区| 久久九九久精品国产免费直播| 久久国产精品99久久久久久老狼| 欧美国产成人久久精品| 51久久夜色精品国产| 久久国产亚洲高清观看| 99久久精品毛片免费播放| 中文字幕久久久久人妻| 国产V综合V亚洲欧美久久| 97久久精品人人做人人爽| 久久精品国产黑森林| 亚洲日本久久久午夜精品| 久久婷婷五月综合国产尤物app | 国内精品久久久久伊人av| 99久久精品久久久久久清纯| 久久久久亚洲?V成人无码| 99久久99久久精品国产| 777午夜精品久久av蜜臀| 69久久精品无码一区二区| 国产精品成人无码久久久久久| 亚洲精品乱码久久久久久久久久久久 | 亚洲欧美日韩中文久久|