WinCE的LCD驱动程序编写指南
转载自:http://blog.chinaunix.net/u1/58373/showart_459285.html
本文以 1024*768 分辨率的 TFT_16BPP 真彩 LCD 为例 , 说明在 WIN CE 4.2 中驱动程序的修改事项,目标板的微处理器是 S3C2410A 。
该LCD的时序图如下图所示:
Note : LCD 时序的参数和时钟相位因不同 LCD 而异 , 请参考相应 LCD 的 datasheet.
在 WIN CE 4.2 中修改 LCD 驱动程序有五个相关文件 , 分别是:
1. …/WINCE420/PLATFORM/SMDK2410/INC/s2410.h
2. …/WINCE420/PLATFORM/SMDK2410/KERNEL/HAL/cfw.c
3. …/WINCE420/PLATFORM/SMDK2410/DRIVERS/DISPLAY/S3C2410LCD/s3c2410disp.cpp
4. …/WINCE420/PLATFORM/SMDK2410/FILES/config.bib
5. …/ WINCE420/PLATFORM/SMDK2410/FILES/platform.reg
1. …/WINCE420/PLATFORM/SMDK2410/INC/s2410.h
2. …/WINCE420/PLATFORM/SMDK2410/KERNEL/HAL/cfw.c
3. …/WINCE420/PLATFORM/SMDK2410/DRIVERS/DISPLAY/S3C2410LCD/s3c2410disp.cpp
4. …/WINCE420/PLATFORM/SMDK2410/FILES/config.bib
5. …/ WINCE420/PLATFORM/SMDK2410/FILES/platform.reg
1. s2410.h
…/WINCE420/PLATFORM/SMDK2410/INC/s2410.h
主要有 LCD 控制器的寄存器定义、 LCD 控制器的工作时序定义、分辨率的定义等等。红色部分为修改后的内容:
#define LCDTYPE TFT16BPP
#define LCD_TYPE TFTxxx_xxx
#define SCR_XSIZE_TFT (1280 )
#define SCR_YSIZE_TFT (960 )
#define LCD_XSIZE_TFT (1024 )
#define LCD_YSIZE_TFT (768 )
#define VBPD ((2-1 )&0xff)
#define VFPD ((2-1 )&0xff)
#define VSPW ((2-1 ) &0x3f)
#define HBPD ((16-1 )&0x7f)
#define HFPD ((200-1 )&0xff)
#define HSPW ((16-1 )&0xff)
#define CLKVAL_TFT (1 ) // 这个值的定义在 LCD 初始化函数中并不用到 , 而是直接用数值表示。
2. cfw.c
…/WINCE420/PLATFORM/SMDK2410/KERNEL/HAL/cfw.c
红色部分为修改后的内容:
static void InitDisplay()
{
********
s2410LCD->rLCDCON1=(1 <<8)|(MVAL_USED<<7)|(3 <<5)|(12 <<1)|0 ;
// CLKVAL_TFT = 1 , HCLK = 100MHz -> VCLK = 25MHz
// TFT LCD panel
//16 bpp for TFT
s2410LCD->rLCDCON2=(VBPD<<24)|(LINEVAL_TFT<<14)|(VFPD<<6)|(VSPW);
s2410LCD->rLCDCON3=(HBPD<<19)|(HOZVAL_TFT<<8)|(HFPD);
s2410LCD->rLCDCON4=(MVAL<<8)|(HSPW);
s2410LCD->rLCDCON5=
(1 <<11)|(0 <<10)|(0 <<9)|(0 <<8)|(0 <<7)|(0 <<6)|(0 <<3)|(0 <<1)|(1 <<0);
// 5:6:5 Format
//The video data is fetched at VCLK falling edge
//VLINE/HSYNC pulse polarity-Normal
//VFRAME/VSYNC pulse polarity-Normal
//VD (video data) pulse polarity-Normal
//VDEN signal polarity-Normal
//Disable PWREN signal
//Byte swap Disable
//Half-Word swap Enable
********
}
…/WINCE420/PLATFORM/SMDK2410/INC/s2410.h
主要有 LCD 控制器的寄存器定义、 LCD 控制器的工作时序定义、分辨率的定义等等。红色部分为修改后的内容:
#define LCDTYPE TFT16BPP
#define LCD_TYPE TFTxxx_xxx
#define SCR_XSIZE_TFT (1280 )
#define SCR_YSIZE_TFT (960 )
#define LCD_XSIZE_TFT (1024 )
#define LCD_YSIZE_TFT (768 )
#define VBPD ((2-1 )&0xff)
#define VFPD ((2-1 )&0xff)
#define VSPW ((2-1 ) &0x3f)
#define HBPD ((16-1 )&0x7f)
#define HFPD ((200-1 )&0xff)
#define HSPW ((16-1 )&0xff)
#define CLKVAL_TFT (1 ) // 这个值的定义在 LCD 初始化函数中并不用到 , 而是直接用数值表示。
2. cfw.c
…/WINCE420/PLATFORM/SMDK2410/KERNEL/HAL/cfw.c
红色部分为修改后的内容:
static void InitDisplay()
{
********
s2410LCD->rLCDCON1=(1 <<8)|(MVAL_USED<<7)|(3 <<5)|(12 <<1)|0 ;
// CLKVAL_TFT = 1 , HCLK = 100MHz -> VCLK = 25MHz
// TFT LCD panel
//16 bpp for TFT
s2410LCD->rLCDCON2=(VBPD<<24)|(LINEVAL_TFT<<14)|(VFPD<<6)|(VSPW);
s2410LCD->rLCDCON3=(HBPD<<19)|(HOZVAL_TFT<<8)|(HFPD);
s2410LCD->rLCDCON4=(MVAL<<8)|(HSPW);
s2410LCD->rLCDCON5=
(1 <<11)|(0 <<10)|(0 <<9)|(0 <<8)|(0 <<7)|(0 <<6)|(0 <<3)|(0 <<1)|(1 <<0);
// 5:6:5 Format
//The video data is fetched at VCLK falling edge
//VLINE/HSYNC pulse polarity-Normal
//VFRAME/VSYNC pulse polarity-Normal
//VD (video data) pulse polarity-Normal
//VDEN signal polarity-Normal
//Disable PWREN signal
//Byte swap Disable
//Half-Word swap Enable
********
}
3. s3c2410disp.cpp
…/WINCE420/PLATFORM/SMDK2410/DRIVERS/DISPLAY/S3C2410LCD/s3c2410disp.cpp
红色部分为修改后的内容:
WORD TempBuffer[1025 ][768 ];
S3C2410DISP::S3C2410DISP (void)
{
********
m_nScreenWidth = 1024 ;
m_nScreenHeight = 768 ;
*********
}
到此修改工作基本完成,但还要一个问题: 1024*768 分辨率占用的显示缓冲区大小是: 1024*768*2 = 1536 K Bytes, 因此要确认所分配的内存空间够不够 , 是在 config.bib 文件中定义的。如果以前定义的足够大 , 后面的步骤可以省略了。
4. config.bib
…/WINCE420/PLATFORM/SMDK2410/FILES/config.bib
#define NKNAME NK
#define NKSTART 8C200000
#define NKLEN 01D00000
#define RAMSTART 8E000000
#define RAMLEN 01F00000
$(NKNAME) $(NKSTART) $(NKLEN) RAMIMAGE
RAM $(RAMSTART) $(RAMLEN) RAM
AUD_DMA 8c002000 00002000 RESERVED
DRV_GLB 8c010000 00010000 RESERVED
DBGSER_DMA 8c022000 00002000 RESERVED
SER_DMA 8c024000 00002000 RESERVED
IR_DMA 8c026000 00002000 RESERVED
SD_DMA 8c028000 00008000 RESERVED
EDBG 8c030000 00020000 RESERVED
CPXIPCHAIN 8c050000 00008000 RESERVED
SLEEP_BUFF 8c058000 00004000 RESERVED
DISPLAY 8c100000 00100000 RESERVED
DISPLAY项就是显示缓冲区的内存空间定义 , 8c100000 是开始地址 , 00100000 是大小。可以看出原先只定义了 1M Bytes 的内存空间给 LCD 显示缓冲区 ; 而 1024*768 需要 1536 K Bytes 的内存空间 , 因此需要修改这里的定义。但是一旦修改到 config.bib 文件的内容 , 将会涉及到很多地方的修改工作 , 过程比较繁琐。所幸的是我的目标板 DISPLAY 前面还有 0x8C100000-(0x8C058000+0x00004000) = 656K Bytes 未分配的内存空间 , 因此做如下修改:
AUD_DMA 8c002000 00002000 RESERVED
DRV_GLB 8c010000 00010000 RESERVED
DBGSER_DMA 8c022000 00002000 RESERVED
SER_DMA 8c024000 00002000 RESERVED
IR_DMA 8c026000 00002000 RESERVED
SD_DMA 8c028000 00008000 RESERVED
EDBG 8c030000 00020000 RESERVED
CPXIPCHAIN 8c050000 00008000 RESERVED
SLEEP_BUFF 8c058000 00004000 RESERVED
;DISPLAY 8c100000 00100000 RESERVED
DISPLAY 8c 060000 001a 0000 RESERVED
5. 在( 4 )中修改了 DISPLAY 显示缓冲区的开始地址 , 因此要在“ s2410.h ”中做相应的修改:
…/WINCE420/PLATFORM/SMDK2410/INC/s2410.h
#define DMA_BUFFER_BASE 0xAC000000
#define DMA_PHYSICAL_BASE 0x30000000
//#define FRAMEBUF_BASE (DMA_BUFFER_BASE + 0x00100000)
//#define FRAMEBUF_DMA_BASE (DMA_PHYSICAL_BASE + 0x00100000)
#define FRAMEBUF_BASE (DMA_BUFFER_BASE + 0x00060000 )
#define FRAMEBUF_DMA_BASE (DMA_PHYSICAL_BASE + 0x00060000 )
6. 在( 4 )中修改了 DISPLAY 显示缓冲区的大小 , 因此要在“ s3c2410disp.cpp ”中做相应的修改:
…/WINCE420/PLATFORM/SMDK2410/DRIVERS/DISPLAY/S3C2410LCD/s3c2410disp.cpp
红色部分为修改后的内容:
void S3C2410DISP::InitializeHardware (void)
{
*********
m_VirtualFrameBuffer = (DWORD)VirtualAlloc(0, (0x1A0000 ), MEM_RESERVE, PAGE_NOACCESS);
if (m_VirtualFrameBuffer == NULL)
{
RETAILMSG(0,(TEXT("m_VirtualFrameBuffer is not allocated/n/r")));
return;
}
else if (!VirtualCopy((PVOID)m_VirtualFrameBuffer, (PVOID)gdwLCDVirtualFrameBase, (0x1A0000 ), PAGE_READWRITE | PAGE_NOCACHE))
{
RETAILMSG(0, (TEXT("m_VirtualFrameBuffer is not mapped/n/r")));
VirtualFree((PVOID)m_VirtualFrameBuffer, 0, MEM_RELEASE);
return;
}
*********
}
7. 在( 4 )中修改了 DISPLAY 显示缓冲区的开始地址 , 还要对注册表文件“ platform.reg ”做相应的修改:
…/ WINCE420/PLATFORM/SMDK2410/FILES/platform.reg
[HKEY_LOCAL_MACHINE/Drivers/Display/S3C2410/CONFIG]
"DisplayDll"="s3c2410disp.dll"
;"LCDVirtualFrameBase"=dword:ac100000
;"LCDPhysicalFrameBase"=dword:30100000
"LCDVirtualFrameBase"=dword:ac060000
"LCDPhysicalFrameBase"=dword:30060000
完!