三 实验过程与结果
1. Linux 源代码的修改
首先修改arch/arm/mach-smdk2410.c文件,加入以下代码。
static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = {
.regs = {
.lcdcon1 = S3C2410_LCDCON1_TFT16BPP |
S3C2410_LCDCON1_TFT |
S3C2410_LCDCON1_CLKVAL(7),
.lcdcon2 = S3C2410_LCDCON2_VBPD(4) |
S3C2410_LCDCON2_LINEVAL(319) |
S3C2410_LCDCON2_VFPD(1) |
S3C2410_LCDCON2_VSPW(1),
.lcdcon3 = S3C2410_LCDCON3_HBPD(26) |
S3C2410_LCDCON3_HOZVAL(239) |
S3C2410_LCDCON3_HFPD(30),
.lcdcon4 = S3C2410_LCDCON4_HSPW(13) |
S3C2410_LCDCON4_MVAL(13),
.lcdcon5 = S3C2410_LCDCON5_FRM565 |
S3C2410_LCDCON5_INVVLINE |
S3C2410_LCDCON5_INVVFRAME |
S3C2410_LCDCON5_PWREN |
S3C2410_LCDCON5_HWSWP,
},
.lpcsel = ((0xCE6) & ~7) | 1<<4,
.width = 240,
.height = 320,
.xres = {
.min = 240,
.max = 240,
.defval = 240,
},
.yres = {
.min = 320,
.max = 320,
.defval = 320,
},
.bpp = {
.min = 16,
.max = 16,
.defval = 16,
},
};
在函数smdk2410_machine_init()函数中加入LCD的初始化代码,见下
static void __init smdk2410_machine_init(void){
s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);
smdk_machine_init();
}
2.编译内核,产生zImage文件,放入tftp目录下。
3.在nfs的dev目录下建立FrameBuffer的设备节点,使用命令:
mknod fb0 c 29 0
4.启动开发板,加载内核和文件系统。
5.编写LCD的应用程序,程序见附录。
6.采用arm-linux-gcc 编译应用程序,产生可执行文件,放入nfs目录中。
7.在开发板上运行编译好的可执行文件,便可。
8.下图是BMP位图显示程序,在S3C2410上的运行结果。
四 实验心得体会
1. LCD驱动的主要问题是没有LCD屏的文档,我们找不到它的那些参数值,后来只能参照Linux源码里面的其他LCD屏的参数进行实验。
2. 在驱动差错的过程中,我们采用跟踪打印的方法进行调试。刚开始的时候,内核打印出一行找不到LCD设备。我们定位到输出这行提示的代码处,进行反向跟踪。发现传给函数的设备指针为空,于是往上排查,终于发现源代码中没有定义LCD的设备信息。于是驱动问题也就顺利解决了。
3. 原来一直以为,只要LCD驱动工作正常了,内核起来的时候,液晶屏会显示出Logo。当时搞了很久一直没有,还以为是驱动的问题。后来随便写了一个LCD应用程序,竟然能用。
4. 在调试过程应用程序中发现,在读取文件头的时候,如果直接定义一个bitmapfileheader为它动态分配内存:
*bmph=(bitmapfileheader*)malloc(sizeof(bitmapfileheader));
然后用fread((char*)bmph,sizeof(bitmapfileheader),1,f)把文件头一次性读出来,读出来的文件头是错误的,经过调试发现原因是bitmapfileheader这个结构体中的type属性原本应该占2字节,但是被编译器在分配内存的时候进行了内存对齐的优化,给他分配了4个字节的空间,造成读文件的错误。因此在编程中要特别注意内存对齐的影响。
typedef struct
{
WORD type;(被优化)
DWORD bfsize;
DWORD reserved;
DWORD offbits;
} bitmapfileheader;
5. 在嵌入式应用程序的移植过程中,我们原来认为ARM和PC机大小尾顺序是不同的,因此在应用程序中,也对这个差别进行了处理。当时,在调试过程中发现,PC机程序可以直接移植到ARM上,不需要任何改动。但是我们的程序,的确存在会产生大小尾问题代码(在使用fread()读入时)。这究竟是为什么?有人说,ARM是可以设置大小尾顺序的。后来这个问题也没有深究下去。
五 参考文献
(1)嵌入式系统设计与应用开发:郑灵翔. 北京:北京航天航空大学出版社 2006