2011年12月11日 星期日

[心得] intel 跟 microsoft 的差別..

intel 努力把機器的速度從石器時代提升到文明時代,
microsoft 努力把機器的速度從文明時代拉回到石器時代.

2011年11月29日 星期二

沒有標題

ARM_VFPv2_R0P0_00BET0.zip 請不要問我這是什麼東西..
我只是很討厭 ARM 沒事情就亂改 link.
https://skydrive.live.com/?cid=ea95177ed13eeda8&sc=documents&uc=1&id=EA95177ED13EEDA8%21342

2011年11月23日 星期三

FAT 12/16/32 檔案讀寫機

修改自這個東西
因為這個會不時去讀 FAT, 往往會因為相對位址跳太遠造成 cache miss, 我就寫了一個 LRU cache 外掛給它用, 讓它即使是回去讀 FAT 都可以在 cache memory 裡找到資料. 檔案:
https://skydrive.live.com/?cid=ea95177ed13eeda8&sc=documents&uc=1&id=EA95177ED13EEDA8%21342#

原本這個軟體就是寫給 SD/MMC 卡用的, 還是需要自行將 raw data 讀寫 function 掛上去, 掛的方法可以參考 hostemu.h, hostemu.c 中的寫法.

會特別去找這個東西, 是因為 eboot 中 aruba board bsp 中的 FAT 讀檔機讀 FAT32 會不明原因死當, 有個自己可以掌握的 code 以後也可以方便 porting 到 MCU 之類的東西上..

2011年11月14日 星期一

CE 6.0 HIVE

很久以前解掉的, 留一下筆記.
除了網路上找的到的設定以外, environment 裡加上兩個很重要的參數:

PRJ_ENABLE_FSREGHIVE=1
PRJ_BOOTDEVICE_MSFLASH=1

這兩個的相關設定被擺在

C:\WINCE600\PUBLIC\COMMON\OAK\FILES\common.reg

裡, 而 PRJ_BOOTDEVICE_MSFLASH 這個跟用什麼 storage 存 HIVE 有關係.

2011年11月11日 星期五

i.MX35 e-boot splash

這個 driver 是別人從 i.MX31 IPU driver 中的 SDC.C 裡改出來的, 我再給它改成 i.MX35 使用, main function 是 OALDisplaySplashScreen().

改到 i.MX35要更動的東西, 我現在只剩下記得:
1.DISP3 pin (DISP0~2 是 ADC 用的非 SDC 用的).
2.CCM 中 IPU clock 對應的啟動 bits 要打開, i.MX35 上是 CCM[1] bit 18,19.
3.DMA address, i.MX35 我把它指到 image_cfg.h 中 IPU_PA_START, i.MX31 跟 i.MX35 的 frame buffer 地點似乎都不一樣, 寫圖片載入器時記得加載到 OALPAtoUA(IMAGE_BOOT_DISPLAY_RAM_START) 去.

這裡預設的圖片格式是 RGB565 而非 windows 的 ARGB1555, 寫轉換程式時要梢加注意.

兩個要自行 implement.
1.LCD power GPIO pin, 這個要記得給它 enable 而且打開.
2.圖片載入. 這個可能從外面讀進來, 可能從 image 裡解壓縮出來, 不一定, 看使用者高興.

檔案下載:
https://skydrive.live.com/?cid=ea95177ed13eeda8&sc=documents&uc=1&id=EA95177ED13EEDA8%21342#

source code:

#pragma warning(disable: 4100 4115 4201 4204 4214 4702)
#include
#include
#include "loader.h"
// Defines
#define FLOW_ARM 0
#define SDC_DMA_CHANNEL IPU_DMA_CHA_DMASDC_0_LSH // background
//#define SDC_DMA_CHANNEL IPU_DMA_CHA_DMASDC_1_LSH // background

// #define IMAGE_BOOT_DISPLAY_RAM_START IMAGE_WINCE_IPU_RAM_PA_START
// #define IMAGE_BOOT_DISPLAY_RAM_SIZE IMAGE_WINCE_IPU_RAM_SIZE

BOOL OALDisplaySplashScreen(void);
void DumpIMA(PCSP_IPU_REGS pIPU, int ch);

// i.MX35 Registers
static PCSP_CCM_REGS g_pCCM = 0;
static PCSP_IOMUX_REGS g_pIOMUX = 0;
static PCSP_IPU_REGS g_pIPU = 0;
extern BOOL NANDLoadLogoPicture(VOID);

// Init the IPU DMA module
static void SetupIDMAC(int width, int height, int bpp, int nFlip, const int channel)
{ //setup IDMAC Channel Parameter Memory.
UINT32 bpp_code, npb_code, sat_code, bam_code, ofs[4], wid[4];

//=================================
// Configure First 132 bit word
//=================================
// Default access type to 32-bit
sat_code = 2;
bam_code = nFlip ? 1 : 0;
npb_code = 0;

switch (bpp)
{
case 32:
bpp_code = 0;
npb_code = 8 - 1;
ofs[0] = 0;
ofs[1] = 8;
ofs[2] = 16;
ofs[3] = 24;
wid[0] = 8 - 1;
wid[1] = 8 - 1;
wid[2] = 8 - 1;
wid[3] = 8 - 1;
break;

case 24:
bpp_code = 1;
npb_code = 10 - 1;
sat_code = 0;
ofs[0] = 0;
ofs[1] = 8;
ofs[2] = 16;
ofs[3] = 0;
wid[0] = 8 - 1;
wid[1] = 8 - 1;
wid[2] = 8 - 1;
wid[3] = 0;
break;

case 16:
bpp_code = 2;
npb_code = 16 - 1;
ofs[0] = 0;
ofs[1] = 5;
ofs[2] = 11;
ofs[3] = 0;
wid[0] = 5 - 1;
wid[1] = 6 - 1;
wid[2] = 5 - 1;
wid[3] = 0;
break;

case 8:
bpp_code = 3;
npb_code = 32 - 1;
ofs[0] = 0;
ofs[1] = 0;
ofs[2] = 0;
ofs[3] = 0;
wid[0] = 8 - 1;
wid[1] = 0;
wid[2] = 0;
wid[3] = 0;
break;

case 4:
bpp_code = 4;
npb_code = 32 - 1;
ofs[0] = 0;
ofs[1] = 0;
ofs[2] = 0;
ofs[3] = 0;
wid[0] = 4 - 1;
wid[1] = 0;
wid[2] = 0;
wid[3] = 0;
break;

case 1:
bpp_code = 5;
npb_code = 64 - 1;
ofs[0] = 0;
ofs[1] = 0;
ofs[2] = 0;
ofs[3] = 0;
wid[0] = 1 - 1;
wid[1] = 0;
wid[2] = 0;
wid[3] = 0;
break;

default:
bpp_code = 7;
// TODO: Should report error here. bpp_code is reserved.
break;
}

// Set IPU_IMA_ADDR (IPU Internal Memory Access Address)
OUTREG32(&g_pIPU->IPU_IMA_ADDR,
CSP_BITFVAL( IPU_IPU_IMA_ADDR_MEM_NU, IPU_IMA_ADDR_MEM_NU_CPM) |
CSP_BITFVAL( IPU_IPU_IMA_ADDR_ROW_NU, (2 * channel )) | // channel is 14
CSP_BITFVAL( IPU_IPU_IMA_ADDR_WORD_NU, 0));

//...0th 32 bit word
// XV [9:0], YV [19:10], XB [31:20]
OUTREG32(&g_pIPU->IPU_IMA_DATA,
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_XV, 0) | // 0
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_YV, 0) | // 10
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_XB, 0)); // 20

//...1st 32 bit word
// YB [11:0], SCE [12], RESERVED [13], NSB [14], LNPB [20:15], SX [30:21],
// SY~ [31]
// - Set NSB
OUTREG32(&g_pIPU->IPU_IMA_DATA,
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_YB, 0) | // 32-32
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_SCE, 0) | // 44-32
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_NSB, 1) | // 46-32
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_LNPB, 0) | // 47-32
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_SX, 0) | // 53-32
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_LOW_SY, 0)); // 63-32

//...2nd 32 bit word
// ~SY [8:0], NS [18:9], SM [28:10] SDX~ [31:29]
OUTREG32(&g_pIPU->IPU_IMA_DATA,
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_HIGH_SY, 0) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_NS, 0) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_SM, 0) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_LOW_SDX, 0));

//...3rd 32 bit word
// ~SDX [1:0], SDY [6:2], SDRX [7], SDRY [8], SCRQ [9], RESERVED [11:10]
// - FW [23:12], FH~ [31:24]
// - Set FW & FH
OUTREG32(&g_pIPU->IPU_IMA_DATA,
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_HIGH_SDX, 0) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_SDY, 0) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_SDRX, 0) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_SDRY, 0) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_SCRQ, 0) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_FW, (width - 1)) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_LOW_FH, (height - 1)));

//...4th 32 bit word
// ~FH [3:0]
// NOTE: this takes care of the upper four bits in the FH field
OUTREG32(&g_pIPU->IPU_IMA_DATA, ((height - 1) >> 8));

//=================================
// Configure Second 132 bit word
//=================================
if(channel == IPU_DMA_CHA_DMASDC_0_LSH || channel == IPU_DMA_CHA_DMASDC_1_LSH)
{
// Set IPU IPU_IMA_ADDR (IPU Internal Memory Access Address)
// MEM_NU = 0x0001 (CPM)
// ROW_NU = 2*N + 1 (N is channel number)
// WORD_NU = 0
OALMSG(1, (TEXT("SDC DMA addr 0x%08x\r\n"), IMAGE_BOOT_DISPLAY_RAM_START));

OUTREG32(&g_pIPU->IPU_IMA_ADDR,
CSP_BITFVAL( IPU_IPU_IMA_ADDR_MEM_NU, IPU_IMA_ADDR_MEM_NU_CPM) |
CSP_BITFVAL( IPU_IPU_IMA_ADDR_ROW_NU, (2 * channel + 1)) |
CSP_BITFVAL( IPU_IPU_IMA_ADDR_WORD_NU, 0));

//...parameters for YUV/RGB interleaved - 2nd 132 bit word

//...0th 32 bit word
// EBA0 [31:0], double buffer page 0
// Set buffer #1 to physical frame buffer address
// 在這裡設定 double buffer page 0 起始位置, 必需是絕對位址.
OUTREG32(&g_pIPU->IPU_IMA_DATA, IMAGE_BOOT_DISPLAY_RAM_START);

//...1st 32 bit word
// EBA1 [31:0], double buffer page 1
OUTREG32(&g_pIPU->IPU_IMA_DATA, 0);
}
else
{
//..skip over EBA0 and EBA1 for the viewfinder mode
//.. Set IPU_IMA_ADDR (IPU Internal Memory Access Address)
//EBA0 與 EBA1 不設定, ADDR_WORD_NU = 2 表從第二個 dword 開始設定.
OUTREG32(&g_pIPU->IPU_IMA_ADDR,
CSP_BITFVAL( IPU_IPU_IMA_ADDR_MEM_NU, IPU_IMA_ADDR_MEM_NU_CPM) |
CSP_BITFVAL( IPU_IPU_IMA_ADDR_ROW_NU, (2 * channel + 1)) |
CSP_BITFVAL( IPU_IPU_IMA_ADDR_WORD_NU, 2));
}

//...2nd 32 bit word
// - BPP [2:0], SL [16:3], PFS [19:17], BAM [24:20], NPB [30:25],
// - RESERVED [31]
// - Set BPP to 24bpp (1)
// - Set SL (Scaling Factor) to bytes_pp * width
// - Set PFS (Packing) to RGB (%100)
OUTREG32(&g_pIPU->IPU_IMA_DATA,
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_BPP, bpp_code) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_SL, ((width * bpp / 8) - 1)) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_PFS, 0x4) | //0x4 是 RGB
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_BAM, bam_code) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_NPB, npb_code));

//...3rd 32 bit word
// SAT [1:0], SCC [2], OFS0 [7:3], 0FS1 [12:8], OFS2 [17:13], OFS3 [22:18]
// - WID0 [25:23], WID1 [28:26], WID2 [31:29]
OUTREG32(&g_pIPU->IPU_IMA_DATA,
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_SAT, sat_code) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_SCC, 0) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_OFS0, ofs[0]) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_OFS1, ofs[1]) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_OFS2, ofs[2]) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_OFS3, ofs[3]) |

CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_WID0, wid[0]) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_WID1, wid[1]) |
CSP_BITFVAL( IPU_IPU_IMA_DATA_PARAM_WID2, wid[2]));

//...4th 32 bit word
// WID3 [2:0], DEC_SEL [3],
// Set WID3 (7 - 8 bit size), Color component 3 width (Alpha)
OUTREG32(&g_pIPU->IPU_IMA_DATA,
CSP_BITFVAL(IPU_IPU_IMA_DATA_PARAM_WID3, wid[3]));
}

static void EnableSDC2(void)
{
g_pIOMUX = (PCSP_IOMUX_REGS)OALPAtoUA(CSP_BASE_REG_PA_IOMUXC);
g_pIPU = (PCSP_IPU_REGS)OALPAtoUA(CSP_BASE_REG_PA_IPU);
g_pCCM = (PCSP_CCM_REGS)OALPAtoUA(CSP_BASE_REG_PA_CCM);

// Configure IOMUX to request IPU SDC pins
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD0, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD1, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD2, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD3, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD4, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD5, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD6, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD7, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD8, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD9, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD10, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD11, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD12, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD13, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD14, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD15, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD16, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD17, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD18, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD19, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD20, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD21, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD22, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_LD23, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_D3_VSYNC, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_D3_HSYNC, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_D3_FPSHIFT, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_D3_DRDY, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_D3_REV, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);//
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_D3_CLS, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);//
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_D3_SPL, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);//
OAL_IOMUX_SET_MUX(g_pIOMUX, DDK_IOMUX_PIN_CONTRAST, DDK_IOMUX_PIN_MUXMODE_ALT0, DDK_IOMUX_PIN_SION_REGULAR);

// Enable DI and SDC
SETREG32(&g_pIPU->IPU_CONF,
CSP_BITFVAL( IPU_IPU_CONF_DI_EN, IPU_IPU_CONF_DI_EN_ENABLE) |
CSP_BITFVAL( IPU_IPU_CONF_SDC_EN, IPU_IPU_CONF_SDC_EN_ENABLE));

// Enable DMA SDC Channel 0
INSREG32BF(&g_pIPU->IDMAC_CHA_EN,
IPU_DMA_CHA_DMASDC_0, IPU_ENABLE);

// Enable SDC background
// Set BG_EN = 1 (Background is enabled)
INSREG32BF(&g_pIPU->SDC_COM_CONF,
IPU_SDC_COM_CONF_BG_EN, IPU_ENABLE);

// Set DMA SDC Channel 0 as ready
INSREG32BF(&g_pIPU->IPU_CHA_BUF0_RDY,
IPU_DMA_CHA_DMASDC_0, IPU_DMA_CHA_READY);
}

static void InitializeSDC2(void)
{
UINT32 g_IPUCLK = 0x7ed6b40;
UINT32 m_PixelClock = 0, m_PixelDivider;
INT WIDTH = 320; //以下參數比照 driver 中 sdc.c 的修改值.
INT HEIGHT = 240;
INT VSYNCWIDTH = 1;
INT VSTARTWIDTH = 17;
INT VENDWIDTH = 4;
INT HSYNCWIDTH = 1;
INT HSTARTWIDTH = 67;
INT HENDWIDTH = 20;

// map registers
g_pIOMUX = (PCSP_IOMUX_REGS)OALPAtoUA(CSP_BASE_REG_PA_IOMUXC);
g_pIPU = (PCSP_IPU_REGS)OALPAtoUA(CSP_BASE_REG_PA_IPU);
g_pCCM = (PCSP_CCM_REGS)OALPAtoUA(CSP_BASE_REG_PA_CCM);

// Enable clock to IPU -- bits 18-19 of CGR1
// Read in current value, "or" it with bits 22-23, write the value back to the register
OUTREG32( &g_pCCM->CGR[1], INREG32(&g_pCCM->CGR[1]) | 0xc0000 );

//----- General configuration
//step 1
// Set little endian
INSREG32BF(&g_pIPU->IPU_CONF, IPU_IPU_CONF_PXL_ENDIAN, IPU_LITTLE_ENDIAN);

//----- Display interface configuration
//step 2
//... SDC_COM_CONF
OUTREG32( &g_pIPU->SDC_COM_CONF,
//.. SDC mode, TFT color
CSP_BITFVAL(IPU_SDC_COM_CONF_SDC_MODE, IPU_SDC_MODE_TFT_COLOR) |
//.. sharp pannel enable
CSP_BITFVAL(IPU_SDC_COM_CONF_SHARP, 0x0) |
//.. dual mode disable, only smart lcd supports dual mode
CSP_BITFVAL(IPU_SDC_COM_CONF_DUAL_MODE, 0));
//step 3, setup panel
//... SDC_HOR_CONF
OUTREG32( &g_pIPU->SDC_HOR_CONF,
//.. display width for tearing and Vsync calculation
// Screen width minus 1. Specifies the number of pixel clock periods between
// the last HSYNC and the new HSYNC.
CSP_BITFVAL(IPU_SDC_HOR_CONF_SCREEN_WIDTH, (WIDTH + HSTARTWIDTH + HENDWIDTH )) | //nathan
//.. horizontal synchronization pulse, actually hsync pulse width is 1
CSP_BITFVAL(IPU_SDC_HOR_CONF_H_SYNC_WIDTH, HSYNCWIDTH - 1));

//... SDC_VER_CONF
OUTREG32( &g_pIPU->SDC_VER_CONF,
//..line/pixel resolution
CSP_BITFVAL(IPU_SDC_VER_CONF_V_SYNC_WIDTH_L, 0x1) |
//..display height for tearing and Vsync calculation
CSP_BITFVAL(IPU_SDC_VER_CONF_SCREEN_HEIGHT, (HEIGHT + VSTARTWIDTH + VENDWIDTH)) | //nathan
//..vsync size, vsync width is 1
CSP_BITFVAL(IPU_SDC_VER_CONF_V_SYNC_WIDTH, VSYNCWIDTH));

//step 4
OUTREG32(&g_pIPU->DI_DISP_IF_CONF,
//..data mask for display 3
CSP_BITFVAL( IPU_DI_DISP_IF_CONF_DISP3_DATAMSK, 0x0) | //0
// select interface display clock for display 3
CSP_BITFVAL( IPU_DI_DISP_IF_CONF_DISP3_CLK_SEL, 0) |
// display clock idle enable
CSP_BITFVAL( IPU_DI_DISP_IF_CONF_DISP3_CLK_IDLE, 0)); // 0x1

OUTREG32(&g_pIPU->DI_DISP_SIG_POL,
//..1: inverse data polarity
CSP_BITFVAL( IPU_DI_DISP_SIG_POL_D3_DATA_POL, 0) |
//..display interface clock polarity
CSP_BITFVAL( IPU_DI_DISP_SIG_POL_D3_CLK_POL, 0) |
//..1: active high horizontal signal polarity
CSP_BITFVAL( IPU_DI_DISP_SIG_POL_D3_HSYNC_POL, 1) |
//..1: active high vertical signal polarity
CSP_BITFVAL( IPU_DI_DISP_SIG_POL_D3_VSYNC_POL, 1) |
// output enable polarity
CSP_BITFVAL( IPU_DI_DISP_SIG_POL_D3_DRDY_SHARP_POL, 1));
//step 5
// HSP_CLK = 133 MHz
//
// DI_CLK = HSP_CLK * HSP_CLOCK_PER = 133 MHz
// ==> HSP_CLOCK_PER = 1
// these are 7 bit fields iiiffff
// where i = integer part and f = fractional part of the value
OUTREG32(&g_pIPU->DI_HSP_CLK_PER,
CSP_BITFVAL( IPU_DI_HSP_CLK_PER_HSP_CLK_PERIOD_1, 1 << 4) |
CSP_BITFVAL( IPU_DI_HSP_CLK_PER_HSP_CLK_PERIOD_2, 1 << 4));
m_PixelClock = ( WIDTH + HSTARTWIDTH + HSYNCWIDTH + HENDWIDTH) * ( HEIGHT + VSTARTWIDTH + VSYNCWIDTH + VENDWIDTH) * 60;

g_IPUCLK = 0x7ed6b40;
m_PixelDivider = (g_IPUCLK << 4) / m_PixelClock; // g_IPUClk is 0x3F6B5A0

if (m_PixelDivider < 0x40) // Divider less than 4
{
DEBUGMSG(SDC_ERROR,
(TEXT("InitPanel() - Pixel clock divider less than 1\r\n")));
m_PixelDivider = 0x40;
}

OUTREG32(&g_pIPU->DI_DISP3_TIME_CONF,
//..write strobe end
CSP_BITFVAL( IPU_DI_DISP3_TIME_CONF_DISP3_IF_CLK_DOWN_WR, (m_PixelDivider / 8) - 1) |
//.. period
CSP_BITFVAL( IPU_DI_DISP3_TIME_CONF_DISP3_IF_CLK_PER_WR, m_PixelDivider));

//step 6
//... DI_DISP_ACC_CC
INSREG32BF(&g_pIPU->DI_DISP_ACC_CC,
// Display clock cycles number minus 1 for output/input one data word. This
// bit describe in which clock displayed bit is masked.
IPU_DI_DISP_ACC_CC_DISP3_IF_CLK_CNT_D, 0);

//step 7
//... DI_DISP3_B0_MAP
OUTREG32(&g_pIPU->DI_DISP3_B0_MAP,
// set0; data offset
CSP_BITFVAL( IPU_DI_DISP3_B0_MAP_M30_OFFS0, 0x5) |
CSP_BITFVAL( IPU_DI_DISP3_B0_MAP_M30_OFFS1, 0) |
CSP_BITFVAL( IPU_DI_DISP3_B0_MAP_M30_OFFS2, 0) |
// set0; data maping
// mask LSB
CSP_BITFVAL( IPU_DI_DISP3_B0_MAP_M30_M0, 3) |
// mask LSB
CSP_BITFVAL( IPU_DI_DISP3_B0_MAP_M30_M1, 3) |
// Enable LSB in the first clock cycle
CSP_BITFVAL( IPU_DI_DISP3_B0_MAP_M30_M2, 0) |
// enable LSB in the first clock cycle
CSP_BITFVAL( IPU_DI_DISP3_B0_MAP_M30_M3, 0) |
// enable LSB in the first clock cycle
CSP_BITFVAL( IPU_DI_DISP3_B0_MAP_M30_M4, 0) |
// enable LSB in the first clock cycle
CSP_BITFVAL( IPU_DI_DISP3_B0_MAP_M30_M5, 0) |
// enable LSB in the first clock cycle
CSP_BITFVAL( IPU_DI_DISP3_B0_MAP_M30_M6, 0) |
// enable LSB in the first clock cycle
CSP_BITFVAL( IPU_DI_DISP3_B0_MAP_M30_M7, 0));

//... DI_DISP3_B1_MAP
OUTREG32(&g_pIPU->DI_DISP3_B1_MAP,
// set1; data offset
CSP_BITFVAL( IPU_DI_DISP3_B1_MAP_M31_OFFS0, 0xb) |
CSP_BITFVAL( IPU_DI_DISP3_B1_MAP_M31_OFFS1, 0) |
CSP_BITFVAL( IPU_DI_DISP3_B1_MAP_M31_OFFS2, 0) |
// set1; data maping
CSP_BITFVAL( IPU_DI_DISP3_B1_MAP_M31_M0, 3) |
CSP_BITFVAL( IPU_DI_DISP3_B1_MAP_M31_M1, 3) |
CSP_BITFVAL( IPU_DI_DISP3_B1_MAP_M31_M2, 0) |
CSP_BITFVAL( IPU_DI_DISP3_B1_MAP_M31_M3, 0) |
CSP_BITFVAL( IPU_DI_DISP3_B1_MAP_M31_M4, 0) |
CSP_BITFVAL( IPU_DI_DISP3_B1_MAP_M31_M5, 0) |
CSP_BITFVAL( IPU_DI_DISP3_B1_MAP_M31_M6, 0) |
CSP_BITFVAL( IPU_DI_DISP3_B1_MAP_M31_M7, 0));

//... DI_DISP3_B2_MAP
OUTREG32(&g_pIPU->DI_DISP3_B2_MAP,
// set2; data offset
CSP_BITFVAL( IPU_DI_DISP3_B2_MAP_M32_OFFS0, 0x11) |
CSP_BITFVAL( IPU_DI_DISP3_B2_MAP_M32_OFFS1, 0) |
CSP_BITFVAL( IPU_DI_DISP3_B2_MAP_M32_OFFS2, 0) |
// set2; data maping
CSP_BITFVAL( IPU_DI_DISP3_B2_MAP_M32_M0, 3) |
CSP_BITFVAL( IPU_DI_DISP3_B2_MAP_M32_M1, 3) |
CSP_BITFVAL( IPU_DI_DISP3_B2_MAP_M32_M2, 0) |
CSP_BITFVAL( IPU_DI_DISP3_B2_MAP_M32_M3, 0) |
CSP_BITFVAL( IPU_DI_DISP3_B2_MAP_M32_M4, 0) |
CSP_BITFVAL( IPU_DI_DISP3_B2_MAP_M32_M5, 0) |
CSP_BITFVAL( IPU_DI_DISP3_B2_MAP_M32_M6, 0) |
CSP_BITFVAL( IPU_DI_DISP3_B2_MAP_M32_M7, 0));

//step 8
//----- SDC Configuration
//Select graphic window to be on foreground or background.
// background selected
INSREG32BF(&g_pIPU->SDC_COM_CONF,
IPU_SDC_COM_CONF_GWSEL, IPU_SDC_COM_CONF_GWSEL_BG);
// Graphic window alpha mode. Select the use of alpha to be global or local.
// global alpha selcted
// INSREG32BF(&g_pIPU->SDC_COM_CONF,
// IPU_SDC_COM_CONF_SDC_GLB_LOC_A, 1);
//disable alpha channel, 這部份是參考 u-boot 2011.09 的版本.
OUTREG32(&g_pIPU->SDC_GRAPH_WIND_CTRL, INREG32(&g_pIPU->SDC_GRAPH_WIND_CTRL) & 0x00ffffffL);
{
UINT32 reg;

reg = INREG32(&g_pIPU->SDC_COM_CONF);
//Graphic window alpha mode is global (1).
reg |= 0x40L;
//Graphic window select. Graphic window is background (0).
reg &= ~0x20L;
//Graphic window color keying enable, Disable color keying of graphic window (0)
reg &= ~0x80L;
OUTREG32(&g_pIPU->SDC_COM_CONF, reg);
}

OUTREG32(&g_pIPU->SDC_BG_POS,
CSP_BITFVAL( IPU_SDC_BG_POS_BGXP, HSTARTWIDTH) | //nathan
CSP_BITFVAL( IPU_SDC_BG_POS_BGYP, VSTARTWIDTH)); //nathan

OUTREG32(&g_pIPU->SDC_FG_POS,
CSP_BITFVAL( IPU_SDC_FG_POS_FGXP, HSTARTWIDTH+1) | //nathan
CSP_BITFVAL( IPU_SDC_FG_POS_FGYP, VSTARTWIDTH)); //nathan

//step 9
//----- IDMAC Configuration
// Set no double-buffer, use single buffer
INSREG32BF(&g_pIPU->IPU_CHA_DB_MODE_SEL, IPU_DMA_CHA_DMASDC_0, IPU_SIG_BUF); //14
INSREG32BF(&g_pIPU->IPU_CHA_DB_MODE_SEL, IPU_DMA_CHA_DMASDC_1, IPU_SIG_BUF); //15

// Set buffer 0 as current buffer (non double buffered)
// for chanel DMASDC_0, current buffer is buffer 0
INSREG32BF(&g_pIPU->IPU_CHA_CUR_BUF, IPU_DMA_CHA_DMASDC_0, IPU_SIG_BUF);
// for chanel DMASDC_1, current buffer is buffer 0 too.
INSREG32BF(&g_pIPU->IPU_CHA_CUR_BUF, IPU_DMA_CHA_DMASDC_1, IPU_SIG_BUF);
// Set high priority for DMA SDC Channel 0
INSREG32BF(&g_pIPU->IDMAC_CHA_PRI,
IPU_DMA_CHA_DMASDC_0, 1);

// Set high priority for DMA SDC Channel 1
INSREG32BF(&g_pIPU->IDMAC_CHA_PRI,
IPU_DMA_CHA_DMASDC_1, 1); //original is 1.
// Set high priority for DMA SDC Channel 1
// INSREG32BF(&g_pIPU->IDMAC_CHA_PRI,
// IPU_DMA_CHA_DMASDC_3, 1);

// Set max for consecutive bursts for each channel
INSREG32BF(&g_pIPU->IDMAC_CONF,
IPU_IDMAC_CONF_SRCNT, 7);

// Select source of SDC channel as ARM
// SDC background channel 0 source select as MCU(arm).
// SDC foreground channel 1 source select as MCU(arm).
OUTREG32(&g_pIPU->IPU_FS_DISP_FLOW,
CSP_BITFVAL( IPU_IPU_FS_DISP_FLOW_SDC0_SRC_SEL, FLOW_ARM) |
CSP_BITFVAL( IPU_IPU_FS_DISP_FLOW_SDC1_SRC_SEL, FLOW_ARM));

// Turn contrast fully on
OUTREG32(&g_pIPU->SDC_CUR_BLINK_PWM_CTRL,
// Source select. Selects the input clock source for the PWM counter. The
// PWM output frequency is equal to the frequency of the input clock divided by 256.
// source select as pixel clock
CSP_BITFVAL( IPU_SDC_CUR_BLINK_PWM_CTRL_SCR, 1) |
// Contrast control is on.
CSP_BITFVAL( IPU_SDC_CUR_BLINK_PWM_CTRL_CC_EN, 1) |
//
CSP_BITFVAL( IPU_SDC_CUR_BLINK_PWM_CTRL_PWM, 0xffL));

SetupIDMAC(320, 240, 16, FALSE, IPU_DMA_CHA_DMASDC_0_LSH); // SDC_DMA_CHANNEL is 14
}

BOOL OALDisplaySplashScreen(void)
{
InitializeSDC2();
//NANDLoadLogoPicture();
EnableSDC2();
OALMSG(1, (TEXT("-DisplaySplashScreen(%d)\r\n"), success));

return TRUE;
}

2011年10月17日 星期一

Windows CE 多語系切換

這裡要講的是一個以上非英語系的切換. 首先感謝 http://johnny0627.blogspot.com/2011/02/wince.html 這篇裡講到如何實作英語與法語間的切換實作. 不過在下用的 BSP 上有一個問題是, 在 rebuild driver 時會順路把這些 MUI 的 .exe 跟 .dll 清掉, 為了解決這個問題, 我把方法重寫一下. 基本上根本作法跟這篇寫的一樣, 只是有幾個重點:

1.build 時設定非英語語系當主要語系, 否則 "user interface language" 裡不給你選.

2.這裡假設我們要簡中, 英文, 日文這三個語系, 就在 build -> open release directory in build window 裡下指令建立 MUI 所需的檔案: createmui 0409 0411 0804. (1.前面沒有 0x, MSDN 寫說前面要接 0x 如 0x409, 這樣反而會找不到檔案. 2.中間是空格, 有人說是逗點 ',' 我試過後者似乎也可以用) 建立一大票 .exe 跟 .dll, 還有 multiui.bib

3.如引用文章所說, 把 multiui.bib 中 k.core 開頭的敘述都拿掉.

4.參考 BSP 裡擺檔案的路徑與擺法, 如我的 BSP 擺 \windows 是 "$(_FLATRELEASEDIR)\", 那麼就把 bulti.bib 裡的路徑加個... 例如說是 "_mui", 改成 "$(_FLATRELEASEDIR)\_mui\" 這樣.

5.把剛剛建好, 擺在 release 目錄裡的那群 .exe .dll (目錄為 mui) copy 到
(_$platfrom)\FILES\_mui (此時後面的 _mui 就是 4. 講的例子) 裡.

6.這時再修改 (_$platfrom)\FILES\platfrom.bib 中的檔案清單, 把 multiui.bib 中已修改過路徑的內容貼到尾端.

這時整個 BSP 不管怎麼建, 這些檔案都會在, 而且不會因為重 build 就消失, 還要再回 console 裡再下一次指令.

如果沒有成功的話, 可以檢查看看檔案有沒有被綁進去. 首先隨便開一個 folder 如 my document, 選到 "view -> option" 這裡, 如圖:

可以看到這三個item

把勾選全拿掉後

在 windows 目錄下查看是不是有 .0409 這類的檔案:

檔案有確實綁進去的話, 控制臺底下的語言控制選項才會出現.

[筆記] Windows CE eboot 裡自己加選單

我改的是 FreeScale 的 BSP, 因為 eboot 選單會隨著每種 BSP 的不同而自訂出不一樣的功能, FreeScale i.MX35 裡的是在:
C:\WINCE600\PLATFORM\iMX35-3DS-PDK1_7\SRC\BOOTLOADER\EBOOT\menu.c
中, 語法大概是這樣:

BOOL BLrescure_cmd(BLMENU_ITEM *pMenu);

#define MENUrescure { L'A', L"rescure from SD", BLrescure_cmd, 0, 0, 0 }
#define SocMenu MENUrescure, Null_Menu
#define MainMenu { CommonMenu, SocMenu }
// Local Variables
static BLMENU_ITEM g_menu[] = MainMenu;

基本上 g_menu 裡擺的全是 BOOL (BLMENU_ITEM*) 的 function pointer, 而擺進去的 function 就自己在外面另開 .c 去 implement 就可以, 只是要留意一下各家 BSP 對 BLmenu() 的處理手法都不太一樣, 隨著 return 值的不同, 有的還可以跳回選單, 有的就直接跳去開機.

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

2011年8月24日 星期三

Windows CE 的 kernelIoControl


這些是 KernelIoControl 中 FILE_DEVICE_HAL 用的 control code, 號碼是十進位, 這些是從 FreeScale 的 BSP 裡挖出來的, 還不是全部的 Control Code..

CTL_CODE(FILE_DEVICE_HAL, xx, METHOD_BUFFERED, FILE_ANY_ACCESS)

xx:
01 HAL_GET_DEVICE_INFO
03 HAL_GET_IP_ADDR
04 HAL_RADIO_CNTRL
05 HAL_DDK_CALL
06 EDBG_REGISTER_CLIENT
07 EDBG_DEREGISTER_CLIENT
08 EDBG_REGISTER_DFLT_CLIENT
09 EDBG_SEND
10 EDBG_RECV
11 EDBG_SET_DEBUG
78 KITL_STARTUP
79 KITL_INTRINIT
80 KITL_IS_KDBG_REGISTERED

// KITL PowerOn/Off ioctl, *lpInBuf = 0 for off, 1 for on.
81 KITL_POWER_CALL
12 SET_KERNEL_COMM_DEV
13 HAL_GET_UUID
14 HAL_INIT_RTC
15 HAL_REBOOT
16 HAL_HALT
17 SET_KERNEL_DEV_PORT
18 HAL_TRANSLATE_IRQ
19 HAL_GET_RIO_INFO
20 HAL_ILTIMING
21 HAL_GET_DEVICEID
22 HAL_PROFILE
23 HAL_SET_DEVICE_INFO
24 QUERY_PHYSICALMEM
25 PROCESSOR_INFORMATION
35 HAL_GETREGSECUREKEYS
36 HAL_REQUEST_IRQ
38 HAL_REQUEST_SYSINTR
54 HAL_RELEASE_SYSINTR
// IOCTL to get KITL transport info
37 KITL_GET_INFO
40 HAL_ENABLE_WAKE
41 HAL_DISABLE_WAKE
42 HAL_GET_WAKE_SOURCE
61 HAL_PRESUSPEND
// IOCTL to tell OEM to initialize registry on boot
44 HAL_INITREGISTRY

// IOCTL to give OEM a more full-featured init when the kernel is ready to go
// and before any apps are started
45 HAL_POSTINIT

// IOCTL to ask OEM whether to force clean registry hive
49 HAL_GET_HIVE_CLEAN_FLAG

// IOCTL to ask OEM the reason for power on
50 HAL_GET_POWERONREASON

// IOCTL to get random hardware seed
52 HAL_GET_RANDOM_SEED

// IOCTL to ask OEM for a RAM region to put the registry hive into
53 GET_HIVE_RAM_REGION

// IOCTL to tell OEM to save the RAM region where the registry hive is stored
55 SAVE_HIVE_RAM_REGION

// IOCTL to write XIP section.
46 HAL_WRITE_XIP
47 HAL_XIPCHAIN

// IOCTL for authenticate device
60 HAL_AUTHENTICATE_DEVICE

// IOCTL for WHQL testing (used to check whether hardware is in a jumpered test mode)
56 WHQL_TEST_MODE

// IOCTL for retrieving location and size of bootloader in flash
57 HAL_GET_BOOTLOADER_PARAMS

// IOCTL for retrieving the signed state of an OS image
58 HAL_GET_IMAGE_SIGNED_STATE

// IOCTL to query for a default display resolution.
63 HAL_QUERY_DISPLAYSETTINGS

// IOCTL to query device for device-specific information
64 HAL_QUERY_DEVICE_SETTINGS

// IOCTL to allow the HAL to override the extension region
65 HAL_GET_BIN_CHAIN

// IOCTL to retrieve cache information
66 HAL_GET_CACHE_INFO

// IOCTL to control OEM-specified profiler
67 HAL_OEM_PROFILER

// IOCTL to allow the networking component interrupts to use one SYSINTR_NETWORK_SHARED
68 HAL_SYSINTR_NETWORK_SHARED

// IOCTL to allow OEM specify MAC address for RNDIS
69 HAL_GET_RNDIS_MACADDR

// IOCTL to allow OEM's to specify if a partition is to be formated before being mounted.
70 HAL_QUERY_FORMAT_PARTITION

// IOCTL used by halflat display driver
71 HAL_DDI

// This IOCTL enables/disables update mode. It's used when updating system images and it sets/clears a flag in
// an OEM-defined location that's interpreted by the initial program loader (IPL) at boot time. Based on the
// flag, the IPL will either boot the OS image or it'll load the update loader which starts the update process.
//
// The IOCTL takes a single boolean input parameter: TRUE == update mode and FALSE == normal OS
//
77 HAL_UPDATE_MODE

// IOCTL used by kernel to query page pool parameters from the OAL
// The IOCTL takes no input parameters but returns an NKPoolParameters struct as output.
82 HAL_GET_POOL_PARAMETERS

////////////////////////////////////////////////////////////////////////////////
// VBridge support in kernel, used by VMini (Null miniport driver).
//
26 VBRIDGE_GET_TX_PACKET
27 VBRIDGE_GET_TX_PACKET_COMPLETE
28 VBRIDGE_GET_RX_PACKET
29 VBRIDGE_GET_RX_PACKET_COMPLETE
30 VBRIDGE_GET_ETHERNET_MAC
31 VBRIDGE_ADD_MAC
32 VBRIDGE_SHARED_ETHERNET
33 VBRIDGE_CURRENT_PACKET_FILTER
34 VBRIDGE_802_3_MULTICAST_LIST
39 VBRIDGE_WILD_CARD

//
// These are only handled in vbridge.lib
//

42 VBRIDGE_WILD_CARD_RESET_BUFFER
43 VBRIDGE_WILD_CARD_VB_INITIALIZED
// Ioctl to retrieve OutputDebugString
48 EDBG_GET_OUTPUT_DEBUG_FN
51 EDBG_IS_STARTED
// IOCTL to retrieve hardware-generated entropy
62 HAL_GET_HWENTROPY

例如呼叫已經被串接好的 RTC_init 就像這樣:
SYSTEMTIME tTIME = { 0 };
KernelIoControl(CTL_CODE(FILE_DEVICE_HAL, 14, METHOD_BUFFERED, FILE_ANY_ACCESS), &tTIME, sizeof(SYSTEMTIME), NULL, 0, NULL);

至於串接到 OEM function 這個是在 WinCE 裡被定義好的, 能不能改我就不確定了..
{WINCE_ROOT}\\PLATFORM\\COMMON\\SRC\\INC\\oal_ioctl_tab.h :

{ IOCTL_HAL_INIT_RTC, 0, OALIoCtlHalInitRTC },

2011年8月12日 星期五

嗯, 真的, why so serious?

我現在不會想那麼好心跟客戶打招呼, 我只是想告訴客戶, 前面有水雷, 不要過去.

2011年8月5日 星期五

Windows CE 輸入法...

先寫在這做筆記, 我不確定完全正確...
在做 windows CE 的東西時, 只要碰上非英語語系界面時都會碰上這個問題:

ERROR: C:\WINCE600\public\common\oak\drivers\keybd\LAYMGR\.\LayMgr.cpp line 1600: MapVirtualKey: No input language installed
ERROR: C:\WINCE600\public\common\oak\drivers\keybd\LAYMGR\.\LayMgr.cpp line 1411: KeybdDriverVKeyToUnicode: No input language installed

google 半天的結果當然是無解.. (google 能找到答案的問題本來就不叫問題..), 如 debug console 所說, 這是欠輸入法, 但只講對 1/5, 實際上這除了欠輸入法以外, 還欠 keyboard layout. 而更奇怪的是, CE 上 keyboard layout 竟然是用輸入法所用的代號..

以下假設是日文環境, 輸入法用 IME 3.1, BSP會這樣設定:
[HKEY_CURRENT_USER\Keyboard Layout\Preload]
@="00000411"
[HKEY_CURRENT_USER\Keyboard Layout\Preload\1]
@="00000411"

這個在 \wince600\PUBLIC\COMMON\OAK\DRIVERS\KEYBD\LAYMGR.reg 裡, 而被 BSP 用的 platform.reg include 進來:

[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Layouts\00000411]
"Layout File"="kbdmouse.dll"
"Layout Text"="Japanese"
"PS2_AT"="kbdmouse.dll"

但實際上這樣做有幾個問題在於
1.實際上沒有一個輸入法叫 00000411, 這是國家代碼, 當然不會是輸入法代碼..
2.IME 3.1 的輸入法代號叫 e001, 所以在 laymgr.cpp 中尋找的是 e0010411....
3.這個 e0010411 會在以上的 Preload 裡尋找, 如果沒有的話, 表示預設就沒有它..
4.這個 e0010411 也會 在 Layouts 裡尋找, 如果沒有, 就沒有對應表..

這個問題源自於 laymgr.cpp GetDefaultInputMethodName()中的一行
_tcsicmp( szTempInputMethodName, szTempDefaultInputMethodName)
(line 2963 at wince 6.0 R3 patch 2011-06-30) 中的判斷, 傳進去的是輸入法代碼 + 國碼一起比較, 也就所以為什麼英語語系 (00000409) 都沒有問題, 因為英語語系沒有輸入法, 前面都是0, 所以不會有找不到的問題.
(實際上我會建議在 laymgr.cpp 中安插自己的 debug message 把輸入法的代號 dump 出來, 以利日後 registery 值的建立.)

也就是說, 如果是用日文語系+IME的話, laymgr 會去找一個叫 "日文語系+IME" 的鍵盤, 實際上當然是不會有這種東西, 但我們要在 registery 裡造個假的去騙過檢查...

所以我現在用的設定是這樣子, 平臺是 FreeScale i.MX35

i.MX35 用的 platform registery key 在:
C:\WINCE600\PLATFORM\iMX35-3DS-PDK1_7\FILES\platform.reg
修改幾個:
; #include "$(DRIVERS_DIR)\keybd\LayMgr.reg" ;<= mark 掉
因為全域變數不一定 100% work, 所以被 include 進去的東西
往往會被設定成預設的 0409 而非想要的其它語系.

在最後面加上:
[HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\KEYBD]
"DriverName"="kbdmouse.dll" ;這是預設 driver.
[HKEY_CURRENT_USER\Keyboard Layout\Preload]
@="e0010411" ;預設使用的輸入法
[HKEY_CURRENT_USER\Keyboard Layout\Preload\1]
@="00000409" ;有這三個可以備選
[HKEY_CURRENT_USER\Keyboard Layout\Preload\2]
@="e0010411"
[HKEY_CURRENT_USER\Keyboard Layout\Preload\3]
@="00000411" ;這個是被列給 keyboard layout 用的.
[HKEY_LOCAL_MACHINE\Security\Policies]
@="00000411" ;這個不確定幹麻的.
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Layouts\00000409]
"Layout File"="kbdmouse.dll" ;其實這裡指的都是對應表.
"Layout Text"="US"
"PS2_AT"="kbdmouse.dll"
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Layouts\e0010411]
"Layout File"="KbdNopJpn1.dll" ;JPN IBM layout 是 jpn1, NEC 是 jpn2.
"Layout Text"="Japanese"
"PS2_AT"="KbdNopJpn1.dll"
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Layouts\00000411]
"Layout File"="KbdNopJpn1.dll" ;這裡也要再設定一個.
"Layout Text"="Japanese"

其中指定用 kbdnopjpn1.dll 的主要原因, 是因為它有 export PS2AT_00000411 跟 IL_00000411 兩個 function 出來, 這個是 CE 一拿到就會有已經建好的東西, 其它像法文鍵盤等, 就要參考網路上的文章 (也是被找到最多的文章..)

開機進 CE 裡後, 還要先把輸入法切回英數再切回 IME 才可以兩個都載入進來.

ps. OS component 中, international->locale_specific_support->Japanese->Keyboard 確定要選. 而 NOP-en., NOP keyboard/mouse japan2 這兩個其實一定要選, 才會有 kbdnopjpn1.dll 被包進 kernel image 中, 圖中是因為 BSP 還啥的影響不能全選:


不過仍有繞路走的解法. 在 sysgen 時, 會幾乎把所有不管你有用到沒用到的 .DLL 全部編譯, 先盡可能浪費你所有的時間後, 然後再看要不要加進來... 也就是說, 編好後, 用搜尋是可以搜尋的到這些 .DLL 檔案的. 把這些 .DLL 檔案抓出來後, 可以用內建檔案的玩法給它內建在 kernel image 裡.
也就是修改 platform.bib, 加上
KbdNopJpn1.dll $(_FLATRELEASEDIR)\KbdNopJpn1.dll NK U
這樣在執行時, 會擺在 \\windows\\ 下, 輸入法檔案是可以找的到的.

先這樣, 這還不是很好的解法...