2011年9月26日 星期一

我工作兩年來得到的東西

2011年9月5日 星期一

[筆記] Windows CE 硬體中斷處理

這裡只講 IST, 不是 ISR, 而實際上我覺的 IST 稍稍好用一點, 雖然它比較不即時.

構成硬體中斷通知總共須要四樣東西, 產生步驟大概是這樣:
1.硬體的中斷向量值, 這個要 chip design vendor 提供. 這裡稱 A.
2.CreateEvent 產生的 Event handle, 這裡稱 B.
3.KernelIoControl 用 IOCTL_HAL_REQUEST_SYSINTR, 這裡是傳入 A, 產生 C.
4.InterruptInitialize function 傳入 C 和 B, 到這裡才算是把中斷跟事件連接起來.
5.用 CreateThread 產生一個 IST (Interrupt Service Thread) (稱為D) 去等那個 C.

example. IRQ_GPIO2_PIN20 這個是 BSP 裡提供的一個定義值, 也就是 A.

static DWORD WINAPI ThreadHDS(LPVOID lpParam);

HANDLE hHND = CreateEvent(0, 0, 0, 0); //這個是B.
HANDLE hThread = 0; //要被產生的 D.
DWORD dwSysIntr = 0; //要被產生的 C.

if(hHND && hHND!=INVALID_HANDLE_VALUE)
{
DWORD dwIRQ = IRQ_GPIO2_PIN20;

if(KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwIRQ, sizeof(dwIRQ), &dwSysIntr, sizeof(DWORD), 0))
{ //這裡開始把中斷向量掛上去, 在 dwIRQ 裡傳回一個系統裡的對應代號.
if(InterruptInitialize(dwSysIntr, hHND, NULL, 0))
{ //當這個中斷進來後, 就去 SetEvent(hHND).
//開一個 thread (D) 下去等那個 event (
hThrea =
CreateThread( 0,
0,
(LPTHREAD_START_ROUTINE)ThreadHDS
hHND, //在這裡只傳入被產生的那個 handle.
0,
&dwThreadID
);
}
}
}

static DWORD WINAPI ThreadHDS(LPVOID lpParam)
{
HANDLE hHND = (HANDLE)hHND; //HANDLE 本身是 void* 所以可以這樣玩..

while(WaitForSingleObject(hHND, INFINITE) != WAIT_FAILED)
{ //以下是如果有等到事件觸發時才會有的動作.
Sleep(100);
//這邊就可以再塞 SendMessage 這類的東西把事件傳給 MFC 的 AP 使用.
}
return 0;
}

WaitForMultipleObject 我沒有實驗成功, 有人說 CE 底下這個 function 不 work, 等哪天試出來時再丟上來修改範例...

2011年9月4日 星期日

同樣是看電影...

有兩個國家, 各自拍兩部電影, 然後去問這兩個這兩個國家的人, 他們會不會去看自己國家的電影.. 一個人說: "我們自己國產的片子拍的這麼爛, 我為什麼要去看?? 我寧可去看____國出的電影!!" 一個人說: "這部片看起來不錯, 我會去看". 如果你追問他說 "可是這部片聽說影評很差耶??, 他還是會說 "不用阻止我, 我會去看國產的電影".

這兩個國家, 約莫25年前時, 前一個國家的電影在東南亞圈還撐起一片天, 但是這個國家的人很媚外, 始終會認為外國電影才是好. 另一個國家完全的默默無聞, 這個國家的國民, 看自己家的電影, 即使踩到地雷片, 看的幹不絕口, 下一次看電影仍然會選擇國片. 25年後, 那個默默耕云的國家把電影外銷給那個 25 年前電影很丘的國家.

也許市場淘汰機制是促使產業進步的動力之一, 但這些自以為良禽擇木而棲的人始終沒有想過, 國內這些產業蕭條了, 這些人失業了, 這些人失業後也就沒有收入來支撐這些所謂高知識份子的產物, 循環下去沒有多久, 這些高知識份子也失業了, 不一樣的是後者這些人始終對著自己人指著鼻子罵: "景氣就是被你們這些人搞差的" ....

某個也曾被看不起的東南亞半島國, 現在全球 DRAM 跟 Flash 都是他們在掌控, 有人有想過背後真正的原因是什麼嗎... ?

我不想明講說哪個國家是哪個, 哪個人是哪個, 我只希望大家能團結一點, 敵人最想看到的就是一個國家的人, 內鬥內行外鬥外行.


2011年9月2日 星期五

Windows CE 的 debug console

一般來講, Windows CE (或 mobile 或 phone, ...) 都會用到一個 UART port 當 debug console, 因為最少 e-boot 裡會用到 debug console, 進 OS 後也會在 debug console 裡秀一些錯誤訊息.

OK, 有人提議說把這個 debug console 拿掉, 還原回一般 UART 的功能. 怎麼做咧? 一開始想到的就是改掉整個 BSP 裡對 OALMSG, DEBUGMSG, RETAILMSG 的定義, 我的 BSP 裡是被轉向到 printf_exp 這個東西, 但我找不到 printf_exp 的進入點在哪裡...

於是我轉而去改另一樣東西, 也就是 e-boot 跟 kernel 在啟始時都會啟始的 debug console, 這個 function 一般是 "OEMDebugInit" (BOOL OEMDebugInit(void)), 在 blcommon.c 中 BootloadertMain 裡會呼叫它, 如果都追不到這些 function name 也沒關係, 因為這些都還不算重點, 我覺的重點在 "OALLogSetZones" 這個 function 上, 用 ultraedit 搜尋 BSP 裡有沒有地方用上, 有用上就是了.

一般 BSP 會用 OALLogSetZones(initialOALLogZones); 的方式向系統告知有 debug console 可用, 如果可以的話, 在這之前做點要不要 debug console 的判斷, 來打開或關掉 (移作它用) 它吧.

後記:
OALLogSetZones 設定的是要輸出哪些 debug message, 設 0 就是不輸出任何訊息, 而 console debug message 的實作是 call 兩個東西:
int OEMReadDebugByte();
VOID OEMWriteDebugByte(UINT8 ch);
(ps.它本來就沒有佔用任何 COM 的 file header)
要在這裡直接攔掉 debug console 的操作.

至於要不要把 output console message 轉向到 IPU, input 指去 keyboard array, 那又是另一段工程了....

2011/11/15 update:
這樣做還有另一個副作用, 就是進 suspend 會死當, 不過這種情況要滿足兩種條件:
1.UART1 為 debug port, 而且 OALLogSetZones() 設定時不為 0 (message enable)
2.UART1 設定可以被 OS 使用.

這樣在進 suspend 時, UART1 也當然會 power-off, 但當 power-off 時, debug message 也就跟著送不出去, 然後系統就 hang 住.

可以靠修改 code 解這個問題.
------------------
\\WINCE600\PLATFORM\COMMON\src\soc\COMMON_FSL_V2_PDK1_7\SERIAL\serial.c
extern DWORD initialOALLogZones;
static BOOL SerPowerOff(PVOID pContext)
{
PUART_INFO pHWHead = (PUART_INFO)pContext;
if(pHWHead->HwAddr == 0x43f90000L && initialOALLogZones != 0) return TRUE;
...
}
------------------
在這兩個 sources 檔案的 link 裡加上 "$(_PLATCOMMONLIB)\$(_CPUDEPPATH)\oal_log.lib":
\\WINCE600\PLATFORM\COMMON\src\soc\COMMON_FSL_V2_PDK1_7\SERIAL\sources
\\WINCE600\PLATFORM\iMX35-3DS-PDK1_7\src\DRIVERS\SERIAL\sources