个人总结日记:ltv350三星LCD并行接口接2440处理器的linux驱动程序移植
2014-12-23 20:42
856 查看
ltv350三星LCD并行接口接2440处理器的linux驱动程序移植
总体上分三步:
1> framebuffer_alloc函数分配一个fb_info类型的结构体
该结构体用于填充描述使用的液晶参数,比如像 像素类型,是否有硬件加速,
长宽,每个像素的位数,调色板等。
其中主要填充fix与var这两个成员结构体变量,这两个结构体在应用程序中
可以通过ioctl函数的命令字 FBIOGET_VSCREENINFO与FBIOGET_FSCREENINFO
获取这两个结构体。
填充一个结构体fb_ops类型的变量,并让fb_info结构体成员指针fbops指向该
变量。fb_ops需要完成如下设置:
.owner
= THIS_MODULE,
.fb_setcolreg = live2440_setcolreg,
.fb_fillrect
= cfb_fillrect,
.fb_copyarea
= cfb_copyarea,
.fb_imageblit
= cfb_imageblit,
fb_setcolreg用于根据红绿蓝三基色的分量合成颜色到调色板数组中
fb_fillrect fb_copyarea fb_imageblit三个函数用于无显存硬件加器的系统
完成显示数据的填充和复制,使用这三个函数时需要配置相应.c文件编译成模块
或编译进内核。
通过dma_alloc_writecombine函数调协dma方式内存数据到LCD显示总线的数据
传输开始地址及传输长度,并返回传输的内存地址的物理地址及虚拟地址
2>设置lcd控制器及其相关的引脚
主要是设置lcdcon1--lcdcon5 lcdaddr1--lcdaddr3及LCD控制所使用的GPIO引脚
的复用功能:GPC,GPD,GPG。其中数据总线与地址总线使用GPC GPD,GPG的引脚4
作为LCD屏的电源控制引脚。
3>注册frame buffer结构体到内核
调用内核函数register_framebuffer把分配的fb_info结构体注册到内核中。
内核中分配了一个长度为32的fb_info类型的数组指针,每注册一个fb_info就把
其放入到数组中,并把数组的下标做为fb设置的序号给设备使用。然后创建设备
文件/dev/fbx,由于fbmem.c的初始化函数中已经完成了fb主设备的注册,其已经
提供了fb设备的 read write ioctl函数,这部分不需要为其进行其实设置
至此整个lcd驱动程序的基本结构就完成了,需要需要写成platform平台驱动的结
构,只需要按其结构修改,并把以上三部分的代码写到其probe函数中。
本来比较简单的程序,调试了几个周才算是完成也是比较纠结,期间也是相当的烦躁
曾经有过放弃的念头(之前移植uboot时也有过类似经历:
默认的nfcont的12位Soft lock是打开的,禁止写nand,但可以读nand,初始化时需要
清0该位,同时清0ECC相关位)。
遇到问题如下:
a>
编译后能直接insmod,但是使用echo nihao > /dev/tty1 或
cat xx.file > /dev/fb0 屏幕无反应。
发现/dev/下有fb0与fb1两个设备文件,将上面命令中的tty1换成tty2,fb0换成fb1
依然没有反应。
<a解决方法:发现源代码中已经存在文件s3c2410fb.c,make menuconfig修改源码
配置项,把S3C2410FB配置成M,编译内核make uImage,编译模块make modules。
b>然后insmod cfb(三个cfb模块)*.ko和insmod lcd.ko出现段错误,而这时插入
源码中的s3c2410fb.ko一切正常。
<b这地方卡了好久,曾经一路查看和打印内核源代码,发现程序在console_lock()
中调用down_console_sem()请求信号量前能打印出信息,之后的信息没有打印出
来就段错误了,曾经怀疑是busybox的insmod命令代码错误(用的busybox比较新)
后来看了源码感觉不是它的问题。后来又挂成最新的3.18.0的内核还是同样死在
请求console的信息量时段错误。于是最后又回归到检查自己的源码的路子上。
最后发现是在设置 fix.line_length 的参数填写成240*2,填成了列的长度,修改之。
遇到这样的错误其实首先应该去自己的代码中去仔细检查,找出错误,而不是先
怀疑别人的代码,kernel,busybox这都是很多编写使用的代码一般发行的版本不会
有大错误;浪费了大量的时间,当然其间也阅读也一些相关的代码也算是一点收获吧。
c>insmod lcd.ko后,注册成功但是屏幕还是没有反应
<c打印出lcdcon1-lcdaddr1寄存器值查看是否正确,发现打印出的值全是0,怀疑是
lcd控制器的时钟没有打开,阅读源码中s3c2410fb.c的probe函数中有clk_get相关
函数调用,于是在初始化LCD控制器前加入
clk_get(NULL, "lcd")与clk_prepare_enable(lcd_clk)
使能控制器时钟.默认地内核会关闭不使用的外设的时钟,以降低功率.
之间还有过一次,设置lcdaddr2时与0x1fffff进行位与运算时少写了一个f,造成屏幕
不停地在闪烁,像时小时候的黑白电视机在没有台时显示的波纹一样。
d>操作fb0和tty1设备文件,屏幕有反应能显示。在使用16位显示时,通过
echo nihao > /dev/tty1 能看到屏幕上显示出了nihao但是很不清楚,
在使用24位色显示时就只能看到屏幕上显示出一个黑块,该问题没能解决。
应用程序可以通过ioctl获取屏幕的参数,通过mmap系统调用将屏幕的显存映射到
内存空间中,通过向映射的内存空间写入颜色的值使屏幕点亮。
<d通过在屏幕的四周画线,观察能否在屏幕上看到来校正驱动程序参数。
通过阅读屏幕的手册参数来设置lcdcon1-lcdcon5就能校正使显示正常。
e>在全屏显示纯色时,屏幕左上角大约有一个7*7像素的黑格在闪
使用echo nihao > /dev/tty1命令后,发现黑格向下移动
<e这可能是内核默认的支持lcd console功能导致,make menuconfig修改内核配置
去除该功能
至此LCD驱动程序移植完毕
驱动程序编码调试成功后静态编译进内核
考虑到编写的驱动程序只是自己使用,就不再为其分类放到内核相应的目录树下,而是
在drivers目录下新建立文件夹live2440_platform,然后把.c文件放到该文件夹下,并
新建Kconfig与Makefile文件,Kconfig与Makefile的写法比较简单可参靠内核源码目录
下的其他文件填充编写。完成后修改drivers目录下的Kconfig,在endmenu前加入
source "drivers/live2440_platform/Kconfig"
修改drivers/Makefile文件
在最后一行加入
或 写死obj-y += live2440_platform/
obj-$(CONFIG_LIVE2440_PLATFORM) += live2440_platform/
只有修改了drivers/Makefile后编译时make才会进入live2440_platform去执行它下面
的Makefile,否则及时通过make menuconfig配置上选项也不会将其编译进内核
最后附上LCD控制器的参数设置:
S3C2440,400MHz--Fclk 100MHz--Hclk 50MHz--Pclk
live2440_lcd_ctrl->lcdcon1 = (5<<8)|(3<<5)|(0xD<<1);
live2440_lcd_ctrl->lcdcon2 = (11<<24)|(239<<14)|(4<<6)|(7<<0);
live2440_lcd_ctrl->lcdcon3 = (8<<19)|(319<<8)|(4<<0);
live2440_lcd_ctrl->lcdcon4 = 7;
live2440_lcd_ctrl->lcdcon5 = (1<<11)|(1<<9)|(1<<8);
live2440_lcd_ctrl->lcdsaddr1 = (live2440_fbinfo->fix.smem_start>>1)&(0x3fffffff);
live2440_lcd_ctrl->lcdsaddr2 = ((live2440_fbinfo->fix.smem_start+live2440_fbinfo->fix.smem_len)>>1)&0x1fffff;
live2440_lcd_ctrl->lcdsaddr3 = 320*32/16;
live2440_lcd_ctrl->lcdcon5 |= (1<<3);
live2440_lcd_ctrl->lcdcon1 |= (1<<0);
总体上分三步:
1> framebuffer_alloc函数分配一个fb_info类型的结构体
该结构体用于填充描述使用的液晶参数,比如像 像素类型,是否有硬件加速,
长宽,每个像素的位数,调色板等。
其中主要填充fix与var这两个成员结构体变量,这两个结构体在应用程序中
可以通过ioctl函数的命令字 FBIOGET_VSCREENINFO与FBIOGET_FSCREENINFO
获取这两个结构体。
填充一个结构体fb_ops类型的变量,并让fb_info结构体成员指针fbops指向该
变量。fb_ops需要完成如下设置:
.owner
= THIS_MODULE,
.fb_setcolreg = live2440_setcolreg,
.fb_fillrect
= cfb_fillrect,
.fb_copyarea
= cfb_copyarea,
.fb_imageblit
= cfb_imageblit,
fb_setcolreg用于根据红绿蓝三基色的分量合成颜色到调色板数组中
fb_fillrect fb_copyarea fb_imageblit三个函数用于无显存硬件加器的系统
完成显示数据的填充和复制,使用这三个函数时需要配置相应.c文件编译成模块
或编译进内核。
通过dma_alloc_writecombine函数调协dma方式内存数据到LCD显示总线的数据
传输开始地址及传输长度,并返回传输的内存地址的物理地址及虚拟地址
2>设置lcd控制器及其相关的引脚
主要是设置lcdcon1--lcdcon5 lcdaddr1--lcdaddr3及LCD控制所使用的GPIO引脚
的复用功能:GPC,GPD,GPG。其中数据总线与地址总线使用GPC GPD,GPG的引脚4
作为LCD屏的电源控制引脚。
3>注册frame buffer结构体到内核
调用内核函数register_framebuffer把分配的fb_info结构体注册到内核中。
内核中分配了一个长度为32的fb_info类型的数组指针,每注册一个fb_info就把
其放入到数组中,并把数组的下标做为fb设置的序号给设备使用。然后创建设备
文件/dev/fbx,由于fbmem.c的初始化函数中已经完成了fb主设备的注册,其已经
提供了fb设备的 read write ioctl函数,这部分不需要为其进行其实设置
至此整个lcd驱动程序的基本结构就完成了,需要需要写成platform平台驱动的结
构,只需要按其结构修改,并把以上三部分的代码写到其probe函数中。
本来比较简单的程序,调试了几个周才算是完成也是比较纠结,期间也是相当的烦躁
曾经有过放弃的念头(之前移植uboot时也有过类似经历:
默认的nfcont的12位Soft lock是打开的,禁止写nand,但可以读nand,初始化时需要
清0该位,同时清0ECC相关位)。
遇到问题如下:
a>
编译后能直接insmod,但是使用echo nihao > /dev/tty1 或
cat xx.file > /dev/fb0 屏幕无反应。
发现/dev/下有fb0与fb1两个设备文件,将上面命令中的tty1换成tty2,fb0换成fb1
依然没有反应。
<a解决方法:发现源代码中已经存在文件s3c2410fb.c,make menuconfig修改源码
配置项,把S3C2410FB配置成M,编译内核make uImage,编译模块make modules。
b>然后insmod cfb(三个cfb模块)*.ko和insmod lcd.ko出现段错误,而这时插入
源码中的s3c2410fb.ko一切正常。
<b这地方卡了好久,曾经一路查看和打印内核源代码,发现程序在console_lock()
中调用down_console_sem()请求信号量前能打印出信息,之后的信息没有打印出
来就段错误了,曾经怀疑是busybox的insmod命令代码错误(用的busybox比较新)
后来看了源码感觉不是它的问题。后来又挂成最新的3.18.0的内核还是同样死在
请求console的信息量时段错误。于是最后又回归到检查自己的源码的路子上。
最后发现是在设置 fix.line_length 的参数填写成240*2,填成了列的长度,修改之。
遇到这样的错误其实首先应该去自己的代码中去仔细检查,找出错误,而不是先
怀疑别人的代码,kernel,busybox这都是很多编写使用的代码一般发行的版本不会
有大错误;浪费了大量的时间,当然其间也阅读也一些相关的代码也算是一点收获吧。
c>insmod lcd.ko后,注册成功但是屏幕还是没有反应
<c打印出lcdcon1-lcdaddr1寄存器值查看是否正确,发现打印出的值全是0,怀疑是
lcd控制器的时钟没有打开,阅读源码中s3c2410fb.c的probe函数中有clk_get相关
函数调用,于是在初始化LCD控制器前加入
clk_get(NULL, "lcd")与clk_prepare_enable(lcd_clk)
使能控制器时钟.默认地内核会关闭不使用的外设的时钟,以降低功率.
之间还有过一次,设置lcdaddr2时与0x1fffff进行位与运算时少写了一个f,造成屏幕
不停地在闪烁,像时小时候的黑白电视机在没有台时显示的波纹一样。
d>操作fb0和tty1设备文件,屏幕有反应能显示。在使用16位显示时,通过
echo nihao > /dev/tty1 能看到屏幕上显示出了nihao但是很不清楚,
在使用24位色显示时就只能看到屏幕上显示出一个黑块,该问题没能解决。
应用程序可以通过ioctl获取屏幕的参数,通过mmap系统调用将屏幕的显存映射到
内存空间中,通过向映射的内存空间写入颜色的值使屏幕点亮。
<d通过在屏幕的四周画线,观察能否在屏幕上看到来校正驱动程序参数。
通过阅读屏幕的手册参数来设置lcdcon1-lcdcon5就能校正使显示正常。
e>在全屏显示纯色时,屏幕左上角大约有一个7*7像素的黑格在闪
使用echo nihao > /dev/tty1命令后,发现黑格向下移动
<e这可能是内核默认的支持lcd console功能导致,make menuconfig修改内核配置
去除该功能
至此LCD驱动程序移植完毕
驱动程序编码调试成功后静态编译进内核
考虑到编写的驱动程序只是自己使用,就不再为其分类放到内核相应的目录树下,而是
在drivers目录下新建立文件夹live2440_platform,然后把.c文件放到该文件夹下,并
新建Kconfig与Makefile文件,Kconfig与Makefile的写法比较简单可参靠内核源码目录
下的其他文件填充编写。完成后修改drivers目录下的Kconfig,在endmenu前加入
source "drivers/live2440_platform/Kconfig"
修改drivers/Makefile文件
在最后一行加入
或 写死obj-y += live2440_platform/
obj-$(CONFIG_LIVE2440_PLATFORM) += live2440_platform/
只有修改了drivers/Makefile后编译时make才会进入live2440_platform去执行它下面
的Makefile,否则及时通过make menuconfig配置上选项也不会将其编译进内核
最后附上LCD控制器的参数设置:
S3C2440,400MHz--Fclk 100MHz--Hclk 50MHz--Pclk
live2440_lcd_ctrl->lcdcon1 = (5<<8)|(3<<5)|(0xD<<1);
live2440_lcd_ctrl->lcdcon2 = (11<<24)|(239<<14)|(4<<6)|(7<<0);
live2440_lcd_ctrl->lcdcon3 = (8<<19)|(319<<8)|(4<<0);
live2440_lcd_ctrl->lcdcon4 = 7;
live2440_lcd_ctrl->lcdcon5 = (1<<11)|(1<<9)|(1<<8);
live2440_lcd_ctrl->lcdsaddr1 = (live2440_fbinfo->fix.smem_start>>1)&(0x3fffffff);
live2440_lcd_ctrl->lcdsaddr2 = ((live2440_fbinfo->fix.smem_start+live2440_fbinfo->fix.smem_len)>>1)&0x1fffff;
live2440_lcd_ctrl->lcdsaddr3 = 320*32/16;
live2440_lcd_ctrl->lcdcon5 |= (1<<3);
live2440_lcd_ctrl->lcdcon1 |= (1<<0);
相关文章推荐
- 【移植驱动到Linux3.4.2内核之二】LCD,触摸屏,按键,USB等驱动程序的移植心得总结
- LCD驱动程序往2.6.11内核的移植总结
- #嵌入式Linux最小系统移植# 对uboot移植和裁剪的一点点个人思考和总结
- LCD驱动设计与分析 --GQ2440+LTV350QV_F04 + LINUX2.6.22内核
- linux之lcd驱动程序总结
- linux-2.6.22.6中LCD驱动到FL2440-I移植
- S3C2440 Linux驱动移植——LCD
- [ARM-LINUX]移植2.6.31.12内核到立宇泰ARMSYS2440开发板之LCD驱动+触摸屏驱动
- 移植linux的范例(芯片在linux中是没有的)--我们一般移植对象都是内核中已存在的处理器如2410 2440 6410等。
- 向嵌入式Linux移植实时设备驱动程序
- 关于2410上LCD移植方面的几点总结(含触摸屏)——转载
- 个人学习Linux知识总结第1/4页
- 在S3C2410的6寸LCD驱动在linux2.6上的移植
- 关于2410上LCD移植方面的几点总结(含触摸屏)
- 个人对Linux下的QQ聊天工具的总结
- 怎样写 Linux LCD 驱动程序
- Linux-2.4.x 在 s3c44b0上的移植总结
- S3C2410 LCD 驱动程序移植及GUI程序编写
- 解决了2440液晶LCD在内核linux2.6.26.3上的一个问题
- Linux-2.6.x在S3C44B0X上的移植总结