10.22.2008

如何將public code 移到platform下

 

如何將\PUBLIC\COMMON\OAK\DRIVERS下的檔移到\PLATFORM\COMMON\SRC\SOC\pxa310_mrvl_v1下build



  1. 建一個BSP_ 開頭的目錄在\PLATFORM\COMMON\SRC\SOC\pxa310_mrvl_v1下


  2. 將檔案copy到上述的目錄


  3. 從你要改的檔的source 找出TARGETNAME


  4. 用3的name 去search PUBLIC, PLATFORM 下的sources



    1. -> 如果PUBLIC 下有就要再去找用的sources是不是有另外別人用(用這一個的sources 再跑一次3,4 steps)


    2. -> 如果PLATFORM 下有就要改它的sources 去link 到你會產生的lib而不是public的


    3. -> 如果兩個都沒有, 去search PUBLIC\COMMON\CESYSGEN\makefile, 如果有…表示wince 有用到這個lib



      1. 在project root 下, 下sysgen_captuer <targetname>, 會產生一個或多個sources.xxxx, 選source.<targetname>


      2. create a DLL floador 在(上層1), 將1 copy 進去rename 成sources


      3. 改(上層3的source) targetname = bsp_xxxxx


      4. 改includes 或cpp 想辦法讓它build 過

 

 





在sources 裡

RELEASETYPE=PLATFORM -> 意思是lib 會產生在PLATFORM\COMMON\SRC\SOC\PXA310_MRVL_V1\LIB\ARMV4I\RETIAL\下

不加的話 會是預設的…可能會在PUBLIC..WPC...下

9.12.2008

Fix the following problems by 9/19

 

Problems:

1. USB's Hi Speed is not passed in eye diag.

2. current to battery is not enough.

3. D+ signal is wrong action. D+ should be low(0V) before and after connecting PC.

 

 





JOB STATUS:

* understand USB client's code architecture -> trace the USB device initial

* need complete environment to trace code -> wait PinHu for EVT1.2 board

* 3319Vendor said i have to put 50 to 04 register.. follow the table 5.1

9/12* Understand USB OTG -> what's status D+/D- ?

 

* confirm 3319 can be a switcher to change D+/D- line

    when RESETB=0(low active) and V1.8 = on... the 3319 is a switch. D+/D- -> SPKR_R/M / SPKR_L

*9/22

the cable cannot be longer than 2 M between device(client) to PC(Host) while testing Eye Diagnostic.

-> I added the code that makes a bigger eye, but it's still fail.

-> test active syc is ok?t

-> Check in code





 

3319

* Pin VDD3.3 should bypass a 2.2uF capacitor -> de capacitor is bigger than 2.2u which is okay.

* NXT[P->L]: indicates when the current byte has been accepted by the PHY.

* DIR[P->L]: Hi-> PHY to Link, Lo-> Link to PHY. Hi-> PHY cannot accept data from Link

* STP[L->P]: one clock cycle to stop the data stream

* CLKOUT[P->L]: 60MHz, ULPI signals are driven synchronous to the rising edge of this clock.

* VDD1.8: shoulde bypass 0.1uF

* GPIO9_2 to reset 3319d

* QUAL_SEL AND SUB_SEL??

 

* ULPI TxdCMD: sent command to 3319

 

* RxCMD:






Code present:

*ZyUSBOTG_ULPI:Init @(platformzylonite_mhlvsrcdriversotg_ulpiusbotg_ulpi.cpp)

    OTGCable, USBCLK, BUSMonitor 都繼承 ZyUSBOTG_ULPI

 

*UfnPdd_init()WINAPI @(platformcommonsrcsocpxa310_mvl_v1usb20fn.Usb20fn.cpp)

    CreateUSB20Device @(platformzylonite_mhlvsrcdriversusb20fnZylonite_usb20fn.cpp)

 


* what is status before plug in cable, and after?

* how is it programmed in code?

* every status maps to what signaling?

Set OTG status flow:
UfnMdd_Start() @publiccommonoakdriversusbfncontrollermddUfnmdd.cpp ->

USBOTG::IOControl(IOCTL_BUS_USBOTG_USBFN_ACTIVE) @publiccommonoakdriversusbotgmddUsbotg.cpp ->

USBOTG::OTGUSBFNNotfyActive() @publiccommonoakdriversusbotgmddUsbotg.cpp ->

USBOTG::EventNotficication() @publiccommonoakdriversusbotgmddUsbotg.cpp ->

USBOTG::EnterState() @publiccommonoakdriversusbotgmddUsbotg.cpp ->
ZyUSBOTG_ULPI::NewStateAction() @platformzylonite_mhlvsrdriverotg_upliUsbotg_lupi.cpp





SPEC
*what's Device A&B? -> A = Host, need to offer Vbus , B = peripheral


*Device detection:  D+ and D- signals have 15Kohm pull-down resistors at port end (hub end), FS devices have 1.5Kohm pull-up resistor on D+ (no resistor on D-), LS devices have 1.5Kohm pull-up resistor on D- (no resistor on D+) HS devices have 45ohm pull-down resistor on both D+ and D-.
No device attached:  D+ and D- float to 0V if not driven 

FS device attached:  D+ floats to 4.54V and D- floats to 0V if not driven


LS device attached:  D+ floats to 0V and D- floats to 4.54V if not driven




*pull-down resistance


    when A/B-device is idle or acting as Host, D+ -> pull low (R 14.25k -24.8k)     D- -> pull low (R 14.25k -24.8k)


    when A/B-device is acting as a peripheral, D+ disable pull-down(floating) and D-> pull-down, A prevent B-device's D- floating if the B-device becomes unplugged and B is the same that of A-device.


    During the interval of packet transmission, A/B-device is allowed to disable D+ and D- pull-down resistor 




*pull-up resistance


    A/B-device is operating as Peripheral, D+ -> pull-up


    During the interval of packet transmission, A/B-device is allowed to disable D+ pull-up resistor





*if one side is not OTG device, how does the protocol go?




*What's J, K state?

J state -> idle state -> D+>D-(differential 1) for FS, D+<D-(differential 0) for LS
K state -> D+<D-(differential 0) for FS, D+>D-(differential 1) for LS

*What's Session Request Protocol(SRP)?

B-device request A-device to provide Vbus to B-device by using SRP.


*What's Host Negotiation protocol(HNP)?


  1. A-device sends a SetFeature(b_hnp_enable) command.
  2. A-device suspend bus.
  3. B-device signals a disconnect to the A-device.(if B-device want to use bus)
  4. A-device interrupts this disconnect.(if A-device enable to switch)
  5. A-device turns on pull-up resistor on D+.

     A) A-device finishes using bus and stops all bus activity, (i.e. suspends the bus).
     A) A-device 用完bus 然後停止所有的bus 的運作,(例如suspends the bus)

    B) B-device detects that bus is idle for more than TA_AIDL_BDIS min and begins HNP by turning off pull-up on D+. This allows the bus to discharge to the SE0 state. If the bus was operating in HS mode, the B-device will first enter the full-speed mode and turn on its D+ pull-up resistor for at least TB_FS_BDIS min before turning off its pull up to start the HNP sequence.
    B) B-device 偵測到bus idle 超過 TA-AIDL_BDIS  min 之後開始 HNP , 透過關掉 D+的pull-up。 這麼做可以讓bus 進入 SE0 state(D+ and D- go low). 如果 bus 正在運作在 HS mode, B-device 會先進入 FS mode 並開啟 D+ pull-up 阻抗至少 TB_FS_BDIS min ,在關掉pull-up 阻抗去開始NHP程序之前.  

    Note: After B-device enters the FS mode and turns on its pull-up resistor; it waits to see if the data line goes high. If the data line does not go high within TWTRSTHS (from Table 7-14 in USB 2.0 specification [USB2.0]), then the B-device shall start its HS chirp. Otherwise, if the D+ line does go high for at least TB_FS_BDIS min, then the B-device may start HNP.
    注意: 在B-device 進入 FS mode 並開啟 pull-up 阻抗之後; 它會等並看看是否資料線是hi. 如果資料線沒有go high 至少 TWTRSTHS(在USB 2.0 的Table 7-14有提到), B-device 可能會開始它的 HS chirp。否則,如果D+ line 有go high 至少 TB_FS_BDIS min, 則B-device 開始 NHP.
 
    C) The A-device detects the SE0 on the bus and recognizes this as a request from the B-device to become Host. The A-device responds by turning on its D+ pull-up within TA_BDIS_ACON max of first detecting the SE0 on the bus.
    C) A-device 偵測到 SE0 並了解這個是 B-device 要變成 Host 的要求。A-device 回應,透過開啟 D+ pull-up 要在第一次偵測到 SE0 的 TA_BDIS_ACON 的最大值之間。

    D) After waiting long enough to insure that the D+ line cannot be high due to the residual effect of the B-device pull-up, (see Section 5.1.9), the B-device sees that the D+ line is high and D- line is low, (i.e. J state). This indicates that the A-device has recognized the HNP request from the B-device. At this point, the B-device becomes Host and asserts bus reset to start using the bus. The B-device must assert the bus reset (SE0) within TB_ACON_BSE0 max of the time that the A-device turns on its pull-up.
    D) 在等待一段長時間來確定 D+ 線不會是 hi 之後(由於B-device pull-up 的殘餘的影響 Section 5.1.9) ,  B-device 會看到D+>D-(例如 J State)。這說明了A-device 已經辦識到 HNP 的要求來自B-device。在這個時候, B-device 變成 Host 並reset bus 來開始使用bus. B-device 必須告知 bus reset (SE0) 在 TB_ACON_BES0的最大值之間, 這個時間是A-device 開啟它的pull-up 的時候。

    E) When the B-device completes using the bus, it stops all bus activity. (Optionally, the B-device may turn on its D+ pull-up when a FS idle condition is detected on the bus.)
    E) 當B-device  用完bus 時, 它停止所有bus 上的運作(B-device 可能會開啟 D+ pull-up 當偵測到 FS idle 在bus 上)

    F) A-device detects lack of bus activity for more than TA_BIDL_ADIS min and turns off its D+ pull-up. Alternatively, if the A-device has no further need to communicate with the B-device, the A-device may turn off VBUS and end the session.
    F) A-device 偵測到busy 沒有活動超過 TA_BIDL_ADIS min 然後就關掉 D+ pull-up. 如果A-device 沒有更進一步的需要來跟B-device 溝通的話,A-device 關掉Vbus 然後結束 session.

    G) B-device turns on its pull-up.
    G) B-device 開啟 pull-up.

    H) After waiting long enough to insure that the D+ line cannot be high due to the residual effect of the A-device pull-up, (see Section 5.1.9), the A-device sees that the D+ line is high (and D- line is low)indicating that the B-device is signaling a connect and is ready to respond as a Peripheral. At this point, the A-device becomes Host and asserts bus reset to start using the bus.
    H) 在等待一段長時間來確定 D+ 線不會是 hi 之後(由於A-device pull-up 的殘餘的影響 Section 5.1.9) ,  A-device 會看到D+ -> hi, (D- -> low)。這說明了B-device 正在連接並且準備好回應如同一個 Peripheral. 在這個時候, A-device 變成 Host 並reset bus 來開始使用bus.





 

9.10.2008

ACPI

Advanced Configuration & Power Interface

9.01.2008

The Great Office War

The Great Office War


這個Video說明了幾件事
1)商場如戰場
2)公司內鬥,最後就成兩敗俱傷

很好笑的video

8.25.2008

Windows Embedded CE 6.0 是如何啟動的?


As writer said, the most interesting thing in Embedded system is how the Kernel start. This article gives us insights into kernel and start process.
Hopefully, I can understand this artical more by translating into Chinese.



Windows Embedded CE 6.0 是如何啟動的?

posted by Kurt Kennett, Senior Development Lead, Windows CE OS Core


作業系統程式,如同我的其中一個同事最近才了解的,就只是一個"程式"而已。它沒有存在任何魔法或高深的知識。事實上,一個作業系統程式跟其它程式比起來也只是有較好的結構及設計而已。當你再懷疑時,它就已經是了。愈來愈多的人需要了解及維護一套能支援除錯的作業系統程式的核心。這些人藉由不斷的進步及換工作去尋找新的挑戰來持續學習這樣的核心程式。但這些人當中,如果只有一個人了解作業系統的運作方式,那將是多麼大的風險。

在工作上,我追過作業系統的流程,其中最有趣的部份是它如何啟動。雖然初始化在設計裡是最後一步(最不重要?),但同時卻也揭開,使用原理的最根本的基礎。試想一個平台要啟動,從一開始什麼都沒有,就只有一棵能執行指令(有時甚至連記憶體也沒能使用)的CPU,到能夠將一個平台從原點帶到完全功能的系統,一個不只是只會利用硬體的系統,而還要能夠讓硬體之間有個共通協定的系統。

在這篇文章我要仔細的討論Winodows CE 6.0 kernel是如何啟動的,以及Microsoft 的 kernel 與 OEM 的程式之間的關係。透過這樣的了解,希望有更多的人有個較好的 IDEA,Microsoft "如何"及"為什麼"這樣設計。

一開始,讓我們快速的複習一下 operation system software 是如何被建立的。Microsoft tool chain 發行了.EXE 以及/或者 .DLL 程式檔。這兩個檔案格式都是"Portable Executable"或叫做"PE"格式。他們在許多方面幾乎是一樣的:
  • 他們都是Common Object File Format(COFF) 格式
  • 他們都有輸入表格及輸出表格(EXE的輸出表格通常是空白的)
  • 他們都有個entry pointer(就是程式從哪執行),它是被定義在他們的headers裡

至於opperation system kernel program,也沒有什麼特別的,就是被標準的 compler 加一些很少的 definitions 所 compile 出來的。它的.EXE(叫做NK.EXE)也沒有連接任何 external library 或 DLL -實際上它也不能。當它開始執行時沒有任何東西在系統裡,就此而言甚至連所謂的系統也沒有。因為 EXE 是已知的格式(PE COFF), 所以你可以從它檔案的開頭裡找到它的entry point。意思就是說我們知道CPU's instruction pointer 會設在哪裡,程式會從哪裡開始執行。

PE 檔還有一個額外的特性就是它可以被安置以至於它能"execute in place"。意思就是說如果 file data 被放在特定的 virtual address,那麼檔案裡的 program code 的部份不需做任何改變就能知道其它code 和data 的正確位址。舉例來說,假設 Microsoft linker program 將 Kernel program 放在 virtual address 0x80000000,然後將它與 code (function entry point) 的關聯也放在 EXE file ,那麼其它的code 就可以透過address(定址?)跳到這一個code。如果 function foo()是在位址0x80001000 然後裡面的一條 code call function bar() 在位址 0x80005000 ,那麼就會有個從 foo() call 到 0x80005000 的h指令,直接存在程式碼裡。虛線只是代表 function code 的開始和結束。


















如果Kernel 的EXE 程式不能放在0x80000000 而且必須要被移,那 bar() function 就要跟著移,而且在 foo() 的呼叫指令也必需被改變去呼叫到正確的新位址。否則它會呼叫到錯的地方:

你可見上面的例子,如果 kernel EXE 檔被設計放在位址 0x80000000 但卻被載入在位址 0x8050000,那麼程式裡的指令就會不正確。

當一個 EXE 或 DLL 程式檔在被載入到對應的實際載入位址時需要做一些改變,這樣的改變的程序就叫做 "fixed up" 。(改變的)記錄會被放在一個標準的、允許程式檔被 fixed up 的 EXE 檔裡。然而,直到 fixup 程序完成,EXE 檔的 function 位址會一直是錯的。為了避免這樣的情況,Windows CE kernel EXE 檔會事先 fixed up 好,然後才載入到特定的位址。有個程式叫做 ROMIMAGE ,當它再 build operation system image file (NK.BIN)時,實際上就對 kernel EXE 及一些被使用的 DLLs 做事前的處理並將它們 fix up。


概要重述一下,我們有個已經 fixed-up 的 EXE 檔叫到 NK.EXE,它包含了一部份的 operating system kernel。這個EXE有個 entry point 定義在裡面,就像每一個其它 COFF EXE DLL 一樣。在執行的一開始,系統的 bootloader 會image file 放到正確的位址,並找到這個 EXE entry point,然後跳到那裡執行。bootloader 是另一個部份,我們將不在這討論,況且每個 bootloader 在不同的平台上也不盡相同。在這篇文章裡,我們簡單的假設 bootloader OS image 檔放在記憶體裡的特定的位址。從下面我們可以看到,bootloader image 裡可以找到 NK.EXE 檔並找到它的 entry point




NK.EXE 只是Windows Embedded CE 6.0 kernel的一部份- 它包含了OEM Adaptation Layer (OAL) 和一些永不變的程式來啟動系統。 Operating system kernel (kernel.dll) 的主要的部份做了所有的process, threadmemory的功能。這個 DLL 是已經被 ROMIMAGE “fixed up” 過的,並放在記憶體裡特定的 virtual memory。所以意思是說,至少有兩個可執行的檔,我們需要知道它們的位址及 entry point這個 Entry point 是被存在 EXE/DLL 檔裡,所以我們可以找的到,但我們怎麼知道 EXE DLL 檔在 image 裡的位址呢?

Windows CE images 有一個很重要的結構,叫做 “Table Of Contents”, 或 TOC,它是由 ROMIMAGE 建立並放在 image 檔裡。TOC 包含了operating system image 檔的 pointers 及 metadata。然後在靠近 image 檔一開始的地方,放個 marker - "CECE" (0x44424442)。在這個 maker 之後就是TOC的位址。如此 bootloader 或其它程式可以找到關於這個 image 的資訊。除了透過 marker 可以知道 TOC 的位址外,OAL 還必需定義一個公用的 symbol 叫做 'pTOC' (依照 'C' 命名規則),當 ROMIMAGE 再準備 image 檔時,它會找 pTOC 並填入 TOC 的 virtual address。在編譯時,NK.EXE 的 pTOC 變數必須是 0xFFFFFFFF。當 ROMIMAGE 再準備 NK.BIN OS system imgae 時,ROMIMAGE 會做下列事 (除了其它工作以外):

  1. 載入 NK.EXE 並 fix it up
  2. 建立 TOC 並在 image 檔裡找個位址放(當 os image 被載入時,是在 virtual memory裡)
  3. 在 NK.EXE 裡找 'pTOC' 變數並確定值為 0xFFFFFFFF。
  4. 將TOC的位址值(2)設給pTOC


這個方式,當 NK.EXE 開始時它會參考這個變數來知道 TOC 在哪裡。透過使用TOC,程式可以找到 operating system image 的其它部份。



ROMIMAGE 使用配置檔 .BIB檔來知道image和RAM 應該放哪裡。在 CONFIG.BIB 裡有兩個重要的部份- RAMIMAGE 及 RAM。這裡有個範例來自 DEvice Emulator's CONFIG.BIB:

NK 0x80070000 0x02000000 RAMIMAGE

RAM 0x82070000 0x01E7F000 RAM

這些 entryies 告訴 ROMIMAGE 要做什麼。它會知道將 OS image 檔放在 0x80070000,以及可以從0x82070000 開始 讀/寫 memory。依照這個資訊,它可以將一些 modules 像是 NK.EXE 和 KERNEL.DLL 放進virtual memory, 然後產生一個TOC並且將TOC 放入image裡。 為了幫助kernel 啟動,TOC 也包含 RAM 位址的資訊。更詳細的資訊有關 image 檔如何放在memory裡,顯示如下:



為了實際讓 operating system 運作起來,bootloader 需要:

1.將image檔放到記憶體裡正確的位址

2.找 "CECE" marker

3.使用 TOC pointer,就是在找到TOC之後

4.在TOC裡找"NK.EXE" 檔的起始點

5. 掃描這個EXE檔的entry point(它是標準的PE格式檔)

6.跳到與這個entry point 相符合的位址


自NK.EXE 啟動之後,有一些有趣的事發生。一般來說,NK.EXE 有一些自有的工作需要做:
  1. 設定 virtual memory並且啟動它
  2. 收集一些資訊,這些資訊是 KERNEL.DLL 會用來跑系統的資訊
  3. 使用 pTOC 來找 TOC 以知道 KERNEL.DLL 在 operatinhg system image 的哪裡
  4. 找 KERNEL.DLL 的 entry point
  5. 在呼叫他自己的entry 時把在搜集到的重要資訊(2)給 KNERNEL.DLL


我們會仔細的走過一遍這些動作來更了解他們。有一些啟動程序在不同的CPU有不同的方式。舉例來說,ARM CPU 和 X86 CPU就有不同的vitual memory management 硬體和映設結講。然而,為了唯持一致性,一般的程序還是會被maintained。 無論何時,可能的話我會試著針對架構說明任何的運作。



當NK.EXE啟動時,有一些系統的準備事項:
  1. 所有的 caches disabled
  2. RAMIMAGE 和 RAM 的區域的 entry ,就是在 CONFIG.BIB 檔明確說到的 ,是可定址和讀取的在實際位址
  3. Virtual memory是在預先定義的狀態(CPU 基本上是執行在 physical address 模式)
另一個預先處理的事情在NK.EXE啟動前會被滿足的,或是在NK.EXE一開始執行就被完成的,就是
4.RAM 應該可寫,不用任何設定(例如,memory controller 的設定)


這些假設允許 NK.EXE 的啟動程式碼去帶起任何必要的特定系統,而不用擔心什麼已做什麼還沒做。上面的第三點也許反直覺,但由於Kernel 必需要很自給自足的執行,要依靠bootloader來設定virtual memory再它啟動之前是無義意的。



Kernel 在physical address mode下開始執行指令時,NK.EXE的第一個動作就是去計算OEMAddressTable symbol 的 physical address。它是一個表格由 kernel 所建立的,kernel 定義靜態(不會改變)的virtual memory的預設區域。 NK.EXE 知道:
  1. 在virtual memory裡,它有自己的位置(它將會執行指令的地方)
  2. 在physical memory裡,它有自己的位置(它正在執行指令的地方)
  3. OEMAddressTable 的 virtual address (當 ROMIMAGE 建立 NK.EXE 並隨後 fixed up 所決定的位置)
透過下列的資訊,一個簡單的計算可告訴 Kernel OEMAddressTable 的 physical addreaa
NK::PhysicalBase + (NK::Virtual OEMAddressTable – NK::Virtual Base) è NK Physical OEMAddressTable

The OEMAddressTable has triads of DWORDS making up a line in a table, with the following format:

<region virtual start> <region physical start> <region size in MB>

<region virtual start> <region physical start> <region size in MB>

...

從這個表格找到的資訊,可以讓 NK.EXE 為 Memory Management Unit (MMU) 設定 virtual memory mapping tables,好讓 MMU 來執行它自己的功能。virtual memory mapping tables 存放著 MMU-formated mapping tables,這些 tables 在不同平台上都不太相同 - OEMAddressTable 是一個很簡單的格式以至於適用於各種架構。使用OEMAddressTAble 裡的資料,Virtual memory 可以被設定及啟動,然後 NK.EXE 轉換到它可以執行程式的 virtual address上。
有一件事要注意的就是,在這個時間點任何在 RAM 的東西都還不能用(這個 RAM 是需要事先被初始化的(被填為0或其它已知的值))。這個RAM在一開始仍然是乾靜的,可以放入任何東西。初始值(就是在image檔裡(NK.EXE的 .data 部份及其它模組))被使用前,必須要從 image 裡 copy 到實體 RAM 的位址. 不過 NK.exe 怎麼知道什麼東西要 copy 或要放到 virtual RAM 的哪裡? 答案就是TOC。
TOC 不只是列出在 image 裡所有模組的起始位址, 它也描述了 RAM 及每一個模組可讀寫的位址,以至於 Kernel 可以依照這些資訊來工作。OS imaeg 的一部份叫做"copy entries",需要被 copy 到 RAM 去。在NK.EXE 可以存取(讀/寫)它自己的變數之前,它需要 copy "copy entries" 到 RAM 裡。這裡就有個問題, pTOC 也是個變數,不是嘛?那 NK.EXE 如何知道 pTOC 在哪裡如果 NK.EXE 還沒設定好?答案就是,pTOC 是一個唯讀的變數,只有 ROMIMAGE 寫它當 image 被建立時。 pTOC 儲存的地方不是在 RAM 且在它的值被使用之前也不需要被 copy 。在 NK.EXE 裡,透過 pTOC ,負責 copy 所有的 "copy entries"到RAM 的 function 叫做 "KernelReloacate()"。它是一個簡單的程序,就是參照一個結構的表格然後將一塊 virtual memory copy 到另一個地方。一但這一些都完成了, NK.EXE 的變數就可以被讀寫,就像其它程式一樣。

在這個時候,我們有個就像其它程式一樣的運作中的程式。它能執行指令,可以呼叫 functions,也可以讀寫記憶體位址。沒有 threads, processes, 也沒有 operating system constructs,但所有的東西被放在已知的地方且也可以被存取來讓我們去做較高階系統的啟動程式。Virtual memory 允許巨大的彈性(什麼彈性?為什麼要有physical adddress 和 virtual address 之分?)。Windos CE 保留一些 virtual memory 的區域,來作為它在 OS kernel 裡私自使用。在 virtual memory 高位址區有保留有幾塊 4k 的pages,大概從 0xFFFE0000 往上開始。Kernel 映射一些 physcial memory 在這個區域來儲存它的 'global' 動態資料。有些則給特定結構的 MMU 的 memory mapping table 使用。另一些則保留給 Kernel-mode 和中斷堆疊。最重要的是,至少有一個 4k pages 是特別保留作為 'Kernel Data Page'。這個 page 包含大量的資料欄位,這些欄位是 kernel 的一個版本特有的。NK.EXE 設定位址並直接地初始這個 page 的內容。
NK.EXE 儲存了三個重要的值在這個結構裡:
  1. 備份 pTOC
  2. OEMAddressTable 位址。
  3. OEMInitGlobals() function 的位址
前兩點放在 Kernel Data Page 好讓任何知道這個 page 位址的程式都能知道有什麼東西在 OS image 裡並知道 virtual memory 的基本 layout。最後一點的資訊會被特別用到,當控制權轉到 KERNEL.DLL 時, NK.EXE 的內容還可以被使用。一般來說,這塊 virtual memory 保留區看起來像這樣:

此時 kernel data page 已經被初始化並且 virutal memory 也在動作中,接著我們就可以跳到 Microsoft KERNEL.DLL 的可執行的 entry point 裡(entry point 指的是程式碼的第一行?) 別忘了,我可以在 image 裡找到 KERNEL.DLL 透過使用 TOC,然後我們也可以掃出 module 的 entry point 。 雖然 NK.EXE 之前就知道它將會將 kernel data page 放到 virtual memory 的哪裡,但 KERNEL.DLL 卻不能自己認為 kernel data page 的位址在哪就在哪。因此,我們就需要把 kernel data page 的 virtual addres 傳給 KERNEL.DLL 的 entry point(怎麼傳?)。雖然 Microsoft 程式可以 callback NK.EXE function 的位址,但 NK.EXE 程式從不會有完整的控制權。
在 jump 之後,我們 現在就開始執行 Microsoft kernel code。 Microsoft kernel code 的 entry point 會被給予 Kernel Data Page 的位址,然後透過 TOC 的欄位,就可以知道任何有關 OS image 的資訊。Kernel 做了一些他自己的的設定,也設定一些它自己要用的重要資料欄位在 Kernel Data Page裡。

KERNEL.DLL 有個靜態的 functions 和 data 的 table,叫做 "NKGlobals" (簡單地被建立在 DLL裡,如同一個靜態資料結構一樣)。因為 ROMIMAGE 已將 KERNEL.DLL fixed up 使它執行在特定的 virtual address,所以當 KERNEL.DLL 程式開跑時 NKGlobals 的 function pointers 會是正確的。有一些在這個 structure 裡的 functions 像是 SetLastError() 和 NKwvsprintfW(),這些 rounine function 是充許NK.EXE 呼叫它們的。然而,有一件重要的事需要知道的就是,在這個時間點, NK.EXE 不知道這些 functions 在 KERNEL.DLL 的哪裡 - NK.EXE 仍然需要被告知這些 functions 和 data 是放在 KERNEL.DLL 裡面的哪裡。
KERNEL.DLL 將 "NKGlobals" 的位址傳回給 NK.EXE 透過一個 function call 到 OEMInitGlobals()裡,而 OEMInitGlobals() 的位址是留在 Kernel Data Page裡的。所以在基本上,function call 的圖看起來像這樣:

就上面顯示的, OEMInitGlobals() function 儲存了 NKGlobals 結構的指標 ,這個結構是屬於 KERNEL.DLL 的結構。在它儲存了這個指標之後, NK.EXE 可以用它來找到 KERNEL.DLL 裡充許被呼叫的 function 的位址。OEMInitGlobals (通過 function 傳回值) 也傳回一個指標到它自己的結構,叫做 "OEMGlobals"。這個結構對 kernel 來說是很重要的,尤其是當 kernel 要能夠存取整個 NK.EXE 裡平台特有的功能時。
KERNEL.DLL 被建構成可以跑在任何特定結構(X86, ARM, etc)的處理器。而NK.EXE 是特定系列(像 SXCALE 或 OMAP 處理器)的結構及支援這個結構的平台的抽象化 (abstraction)。OEMGlobals 結構包含了一些 function poniters 及 data 就像 NKGlobals。它的一些成員包含下列:
  • PFN_InitDebugSerial(), PFN_WriteDebugByte(), PFN_ReadDebugByte()
  • PFN_SetRealTime(), PFN_GetRealTime(), PFN_SetAlarmTime()
  • PFN_Ioctl()

這些 function 的指標都指到 OEM 關連的 functions 像是 OEMInitDebugSerial 及 OEMIoctl,這些 function 都存在 NK.EXE 裡。許多其它 functions 也會被列出來,好讓 KERNEL.DLL 可以做一些必需要做的事情,針對某種特定的平台。這些 functions 也會用很明顯的名字寫在 MSDN 裡。

一旦 OEMInitGlobals() 跑完,KERNEL.DLL 就會有所有它需要的東西來執行 architecture-generic 和 platform-specific 程序。它知道記憶體在哪以及知道記憶體如何虛擬地排列,還有每一個模組在記憶體的位址。NK.EXE 也有它可呼叫的 function 指標。基本上,這兩個程式碼模組已經執行了一個人工的'交握'了(透過執行很簡單的人工動態連結的方式達到)。
到目前為止,NK.EXE 和 KERNEL.DLL 執行及被執行,都沒有透過任何 processes 或 theads, 也沒有透過任何 kernel services running。為了要帶起系統其它的部份,KERNEL.DLL 還必需做下列三件事:
  1. Architecture-specific 設定
  2. Architecture-neutral 設定
  3. Platform-specific 設定 (特定 CPU 和 BSP 的初始化)
Architecture-specific 設定會先被完成,透過呼叫一個 KERNEL.DLL 的 function,叫做 <architecture>Setup。在 ARM 平台,它會叫做 ARMSetup()。在 X86 平台,它會叫做 X86Setup()。Architecture-specific 程式碼做了很多事,但它們都執行在單線程內容裡且沒有任何 processes 在跑。下列這些動作會被執行,但不只侷限這些:
  • 設定 hard required page table 及保留 VM 給 kernel page tables
  • 在 Page Tables 裡更新 cache 的資訊
  • 清除 Transition Lookaside Buffer (TLB)
  • 設定 architecture-specific 匯流排及元件 (相關的 chips,處理器等)
另一件事,architecture-specific 程式碼會做的就是設定 Interlocked API code,好讓 NK.EXE 知道它在哪,然後能夠呼叫它。這其實只是小小的一部份,但我會仔細的解譯它是因為它是 OS 很重要的一部份。
甚至在最基本的階段,Windows CE 也需要在不同的 threads of execution 中做協調 - 甚至一些跑在 Kernel 裡的,以及跑在 specific procees 領域外的。 有個機制很有效率的做這些事,就是 Interlocked API。這個 API 由一些有用的 functions 所組成的,其中最重要的一個 function 是 InterlockedCompareExchage()。這個 function 的目的是:
  1. 將 memory (M) 的值,寫到暫存器(R)裡
  2. 比較 (R) 和另一個有同樣值的暫存器 (R2)
  3. 如果 (R) 和 (R2) 不相等,則離開
  4. 將另一個暫存器 (R3)值,寫到 memory (M) 的位址
這四個步驟意謂著是要原子地執行的(什麼是原子執行?不能被中斷?),因為它們是從兩個不同 threads 間的協調準則而來的。那表示,(1) 到 (4) 指令間是不能被中斷的。唯一的方法保證不被中斷,就是確保 interrupt 是 disabled 的,特別是一些在現今處理器上,硬體直接就是無支援這麼做的地方,更要這麼做。在此拋出一個問題,由於 user-mode processes 沒有足夠的權利去 disable interrupts,並且這麼做也是很沒效率(每次兩個 treads 要互相協調動作時就要做一個 system call 去 disable interrupts)。
所以為了更有效率,在整個系統裡,有個獨一的地方可以執行 InterlockedCompareExchange() ,就是將上面四個程式碼放到 Kernel Data Page 的一個眾所皆知的地方。然後 NK.EXE 和 KERNEL.Dll (及任何有Kernel Data Page maped 的 process) 都可以呼叫這個程式碼,且指令都存在同一個地方。如此這個 API 就是個可重新開始跑的 API。這是什麼意思? 為什麼我們這麼做?
在作業系統裡,Thread switch會發生有下列三個理由:
  • 執行的 threads 有個特別地要求
  • thread 的 time-slice 到期 (由 timer interrupt event 來通知) 然後換另一個 thread 開始跑
  • 另一種中斷發生,這個中斷需要執行高優先權的 thread

第二部份的兩個 cases 幾乎是一樣的- 當 interrupt 發生時,最終就會造成 thread switch。一旦 interrupt 發生在(1) 到 (4) 之間並有可能把 thread 給 switch out 掉,那這四個步驟(我們需要將它原子化的步驟(又來了什麼是原子化))就不能讓一些 thread run 在 (2) 到 (3) 之間,舉例來說。為了要確保指令 (1) 到 (4) 能原子執行(atomic again!!)每一次都有個中斷 來簡單的檢查邊界,來看看是否 CPU 正在執行 (1) 到 (4) 之間(這是什麼樣的中斷?每一次是指每執行一個指令?)。如果中斷發生在當 CPU 執行在(1)之前(4)之後時,就將目前 thread 的指令指標 reset 到指令 (1),如此這個運作也就糾正回來了。而為了讓 interrupt 的程式碼能夠檢查是否 CPU 是在執行指令(1)到(4)之間,程式碼一定要放在唯一大家都知道的地方。這個地方就是在 Kernel Data Page 裡。
一旦 Interlocked API 程式碼 copy 到 Kernel Data Page,NK.EXE 就知道它在哪以及當 multiple threads 發生時 NK.EXE 也可以跟 KERNEL.DLL 互相協調透過 Interlocked API。
回到我們的主題,KERNEL.DLL 啟動的下一步就是 architectue-neutral 設定。Architectural-neutral 的其中一件事就是去看,是否 OS image (包含 KITL.DLL的 image) 允許跟 OS kernel 的debugging 溝通。KITL 代表的就是 "Kernel Independent Transport Layer"。這是一個基本的機制,透個這個機制將資料封包,特別對Windows CE 系統的封包,在 device of kernel 和桌上電腦的Platform Builder 之間傳遞。通常,一部份的 KITL 會被 implement 在 NK.EXE,這些 KITL code 就是單純地對傳輸及資料封包的傳輸的編碼而己。Board Support Package (BSP) 不需要知道任何有關 device 和 電腦之間傳遞的資料- 只要幫忙傳送和接受能夠正確就好了。KITL 封包的傳輸機制包含(但不只限制這些) RS2323 Serial,Ethernet,和 USB。KITL 完整的描述超過這篇 BLOG 文章的範圍。其它在 architecture-neutral 設定的動作包含:
  1. 初始化 Kernel Debug Output (透過呼叫 OEMInitDEbugSerial(),這個 function point 是在 OEMGlobals structer)
  2. 丟個message("Windows CE Kernel Version xxxx") 到 debug output
  3. 從變數選項選擇 kernel processor type

當 architecture-neutral 部份已經完成時,我們可以開始做 platform-specific 設定。這個程式碼是在 NK.EXE 因為它是 OEM 和 board 特有的。透過呼叫 OEMInit() 來初始化這個部份,它的 function pointer 是在 OEMGlobals 的結構裡。 OEMInit 做了 board-specific 初始化,並且也做了另一個重要的事 - 啟動 KITL。
如果 KITL 是被建立在 NK.EXE,那麼它就能從 NK.EXE 直接被存取。如果 KITL 是在 DLL 裡,那麼這個 DLL 在 architecture-neutral 設定的一開始就會被載入到 kernel。無論哪一個,OEMInit() function 都會呼叫 Kernel IO control 來宣告 KITL 應該要被啟動。基本上,無論 KITL.DLL 是否被找到與否,kernel 都知道要做什麼。
回到 OEMInit(),kernel 已經準備好開始讓 processes 和 thread 跑起來。它也同步它的cashe,然後進入 processor architecture's service mode (如果它還沒跑進去的話)。然後做所有的一次性初始化,在不用到現行的thread。這些動作包含:
  1. 列舉可用的記憶體(選擇性的呼叫 OEMEnumExtensionDRAM())
  2. 初始化 kernel 裡不可缺的部份(這個部份有使用 Interlocked API, 它的設定在上面有討論過)
  3. 初始化 heap 結構
  4. 初始化 process 和 thread tracking 結構
  5. 完成任何動作在 multi-threading 開啟之前

在所有的 single-threaded 初始化都完成之後,kernel 就準備好安排第一個 thread 。這個第一個 thread 叫做 "SystemStartupFunc()",它是在 KERNEL.DLL 裡。為了開始 thread,kernel 會表明沒有任何現行的 thread 會被交換,設定第一個 thread 如同唯一 可跑的 thread,然後呼叫進 thread scheduler 的程式碼。這個 scheduler 程式碼管所有可用的 threads 並選擇下一個 thread 執行。在 starup 的這個時間點,我們只有一個由手動設定的 thread 在跑,就是那個被 switch 的thread。
經由沖刷 system cache , SystemStartupFunc() 開始執行,然後做一些事情(使 "current" thread 可執行的事情)。這些動作包含:
  1. 初始化系統 loader
  2. 初始化 paging pool
  3. 初始化系統 logging
  4. 初始化系統 debugger

SystemStartupFunc() 會再呼叫一個 OEM function 在它完成初始化之前 - 透過在 OEMGlobals 的 function pointer 及參數 "OEM_HAL_POSTINIT",它會呼叫 OEMIoctl() 。這告訴 NK.EXE,所有的 system startup 已完成,並且我們準備 schedule threads 和 processes。
在呼叫OEMIoctl()之後,SystemStartupFunc() 初始化了 system message queue, 以及所有的 watchdogs,然後建立並開始 power manager、file system 的 threads。因此,作業系統剩餘的高階部份開始在這執行。SystemStartupFunc() 的最後一個動作是建立另一個 thread ,叫"RunAppsAtStartup()"。這個 function 會建立第一個 user processes。
此時,kernel、power manager、以及 file system 都執行起來了,然後那些在 system registry 有描述的 applications 也可以開始執行起來了。

這篇說明了 windows embedded CE 6.0 如何啟動的文章就到這結束。Windows CE 的內部很有趣的,同是它也是有很好的結構在裡面,藉由上面描述的 startup process 能夠讓你洞悉最重要的 system components。在未來我希望能發表其它文章有關 system registry, file system, device and power managers 的內部構造。



8.19.2008


A visit with Microsoft Research: A look at tomorrow’s health solutions today


在Chanel 10 ,報導了三個有趣的 Microsoft Research
第一個 project 是電腦看人類的人際關系:
當兩個人比較接近或是他們的動作傾向是一夥,在銀幕上就會將兩個人連成一線。電腦也可以知道現在誰看著誰之類的。
(透過這個東西分析之後,是不是就可以很容易知道誰跟誰是一國的?哪裡形成一個小圈圈?但電腦知道這個資訊有什麼用呢?)

第二個 project 就人怎麼看電腦:
透過個sencer 可以知道人的眼睛都底是看銀幕的那裡。

第三個就是 Surface: 不過是用投影的,所以也就可以用任何的地方當Surface。而且也可放實體鍵盤。當需要多人討論時,是不會錯的工具。

8.18.2008

Why do people pay for it?
The application, "Where To?" published by taptaptap, is selling on AppStore.
From 7/11 to 8/2, it's been sold 24,094 pieces by costing USD$2.99.
I'm not excited when I know the functionality of this application. The same functions is already on the most of GPS Handheld device.
So, why do people pay for it? Because of lots of iPhone in market? Because of Apple's type?
If I design an App on WM, can I earn that much?



8.10.2008

acheive 90% above in new version SPEC of FA Diagnostic Application before 9/18
  • 16/22 -> 72% driver ready to test

System part:

處理器&記憶體模組(Tommy):
ask about the items (Jession) -> ask Tommy, can we do it? and confirm Tommy liu -> need to add code
SDRAM:
waiting for PE(tommy, liu) demo
電話模組:
know how to test (Jession) -> 之星 handle it -> ready 2 test -> he can't test w/o SIM card, don't sure how to get IMEI
typedef struct simlocalinfo_tag {
DWORD cbSize;
DWORD dwParams;
DWORD dwLAC;
DWORD dwCellId;
TCHAR lpszNumName[MAXLEN_OPERATOR_NUMERIC];
TCHAR lpszIMEI[MAXLEN_IMEI];
BYTE rgbNMR[MAXLEN_NMR];
BYTE rgbBCCH[MAXLEN_BCCH * MAXNUM_BCCH];
DWORD dwNumBCCH;
} SIMLOCALINFO, *LPSIMLOCALINFO;
??
lpszIMEI[MAXLEN_IMEI]
Indicates International Mobile Equipment Identifier (IMEI) of the phone.
充電電源 (清偉):
know how to test (Jession) -> Kerror have to modify his driver and provide API to AP -> 清偉 give me deviceIOControl call or GetACLineStatus() and GetBatteryLifePercent() @BQ24070.c
照相機模組 (Vision, Ivan):
pending -> the same as 869, there is a AP for camera test, ready 2 test
Scan (政揚):
only 1D -> request sample code to 之星 -> offer a AP path for Diag lanuch -> wait FA to test
藍芽模組(柏豪):
ready to test, wait for AP
無線網路模組 (柏豪):
know how to test (Jession) -> as the old one, ready to test
電流測試 (Sammy):
know how to test (Jession) -> there is a tool for PC to test ,and is supposed to done already, ready to test
RTC (Jassion):
know how to test (Jession) -> the driver is not ready yet, wait for driver -> wait for gigi(shanghi)'s code for 869 -> add code form 869, ready to test
重置:doing nothing in driver

Interface part: 8/18(Zhi-Xing)
信號燈:
ready 4 test, wait 4 AP
螢幕顯示:
ready 4 test, wait 4 AP
背光:
ready 4 test, wait 4 AP
觸控螢幕:
ready 4 test, wait 4 AP
閃光燈:
ask PM to confirm this function -> there is a flash light in EDA, how to drive it (vison or Bear) -> Bear add a iocontrol in cammera, wait him back to TW -> 2 ways to turn on Flash light:1. commend 2. GPIO.. haven't decide to use which one yet
按鍵/ 鍵盤:
ready 4 test, wait 4 AP
震動:
ready 4 test, wait 4 AP
喇叭/耳機:
confirm it's work in driver -> driver seems no ready, who's in charge of?(Vincent)
錄放音:
confirm to AP
IR 測試:
ready 4 test, wait 4 AP
Micro SD測試:
to confirm how to test R/W/E action (who?) -> just check detect MicroSD is okay, ready 2 test

Handy.DVT 9/26, SA/FA 10/24
EDA.DVT 10/9, SA/FA 11/6
I should give my test inviorment to ShangHai. So, they have golden sample.

7.30.2008

Promblem:
The developing board cannot find the Ethernet contgroller LAN91C11 on debug board, so they cannot connect each other.

Solution:
The CPLD code have to burn again.

what's happen to CPLD?
what changes CPLD's code?
While I'm modifying the file, this file was changed already on Source Safe.

How can I do?

one way can do, to merge code before check in.

If my code base is too old from the code on Source Safe. How can I make sure that the code I merage won't affect to other people's, which causes complileing error.
  1. to update my code base
    1. get the lasest code on Source Safe and make sure it can be builded through the end
    2. merge my code which im developoing to the new code base and make sure it can be builded through the end
  2. check out the code what I want to merge
  3. merge 2 to my new code base and make sure it can be builded throough the end
  4. check in
Problem:
the developing board cannot connect to JTEG for burning EBOOT.

Solution:
Take off back up battery, then it's working again (why? relate to PowerManager IC?)
but it still can't connect to EBOOT ( no messages from Terminal).

7.22.2008

Build code hanging

to Build All the code, the builder stoped and poped the results as below:

"Microsoft (R) Program Maintenance Utility Version Test Version
Copyright
(C) Microsoft Corporation. All rights reserved.

Windows CE Version
(Release) (Built on Mar 1 2004 21:46:39)
makefile.def: Invoked with
predefined settings:
TARGETNAME: dummy
TARGETTYPE: dummy
RELEASETYPE:
TARGETLIBS:
SOURCELIBS:
makefile.def: Including
D:\WM612_AKU1.2_19958\public\common\oak\misc\Sources.default
makefile.def:
BUILDROOT is D:\WM612_AKU1.2_19958\public\ossvcs\cesysgen
0 Please add
_COMMONPUBROOT and __PROJROOT to your tree's cesysgen\sources file.
makefile.def: Including .\sources.
makefile.def: Including
D:\WM612_AKU1.2_19958\public\common\oak\misc\Sources.CE
makefile.def:
Including D:\WM612_AKU1.2_19958public\wpc\oak\misc\makefile.inc
Directory:
D:\WM612_AKU1.2_19958\PUBLIC\OSSVCS\CESYSGEN
TARGETNAME: dummy
RELEASETYPE is not defined. Using DEFAULT.
makefile.def: Including
D:\WM612_AKU1.2_19958\public\common\oak\misc\sources.ReleaseType_DEFAULT
輸入錯誤: 副檔名".js" 沒有對應的 Script 引擎。
NMAKE : fatal error U1077: 'cscript' :
return code '0x1'
Stop."

the problem is cuased from UltraEdit. It sets the Script file for UltraEdit using and change the seting of builder.

Solution is from Sammy.

Understanding Makefile is useful.

Image Update Device Side Features

*When started IPL(Initial Program Loader)->(check) Switch/Button & falg ->kenel image (normal boot) OR ->ULDR(Update Loader)

*Normal boot kernel starts&loads OS components to located in the kernel partition to point(OS can read from the system partition) At this point: nothing is located in the kernel partition until the run-time image is booted.

*Device update IPL knows where the master boot record(MBR). active partition is stored in the MBR. IPL loads the contents of active partition(kernel partition) to RAM(NAND,NOR), or jumps to startup address if the artition is NOR XIP kernel.


*during an update to the kernel partition to system partitionpackage mechanism donwloads (update packages) to (device's persistent user store)

UpdateBin

  1. checks signature on the packages,
  2. validates the package contents,
  3. verifies versions,
  4. sets a flash update flag(update is available)
  5. rebbots the system. at reboot, IPL notes the flag and invokes ULDR.

*when ULDR is booted and runing from RAM, ULDR searches the validated packages in the user store (contains file system drivers).

begins update process one package at a time package information is recorded in the file system for useing by Update Validator on future updates. the update progress is tracked to allow for roll-forward updates in case a power failure occurs during the update.


*when all package contents have been applied and complete, the package can be removed from the user store or marked as completed. the flash update flag is cleared the device is rebooted.

Image Download Application

*provides the following functionality:
1. downloading the new disk image to device replacing the existing disk image.
2. downloading packages to the device in the Update Loader context. packages can be applied to the image by the ULDR.

*when a device boots, IPL jumps to the ULDR
the primary run-time image(pressing a switch/ software flag is set(packages need to be applied).

*when IPL jumps to the ULDR, ULDR run an update application to apply the available updates to the image , reboot the device, and updating the image

*because Image Download Application can downlade packages in the ULDR context, it is useful for the development enviroment or for failsafe image recovery.

*because the Impage Update model replaces the old boot loader model,