当前位置:首页 > 单片机 > 单片机
[导读]到了神秘的LCD驱动了,信息还真有点胆怯,但是还是不得不走下去。对刚刚学习的linux驱动坐一下总结,毕竟是Linux内核当中的东东,而且是那么的繁琐。做一总结,等用笔记把学过东西几下来,这样就不会忘了。哈哈!那就

到了神秘的LCD驱动了,信息还真有点胆怯,但是还是不得不走下去。对刚刚学习的linux驱动坐一下总结,毕竟是Linux内核当中的东东,而且是那么的繁琐。做一总结,等用笔记把学过东西几下来,这样就不会忘了。哈哈!

那就开始!!!

在编写裸机LCD程序的时候,首先就是硬件初始化操作。有一个寄存器当中存放了帧缓冲的起始地址。这个参数是非常重要的。当配置好硬件后,帧缓冲中的数据能够脱离CPU不停地将真缓冲当中的数据写入到LCD屏。如果我们要现实一个图片的话只需要将图片数据放到帧缓冲当中,这样就非常的方便了。

在linux当中,把整个LCD驱动分为两层:LCD帧缓冲区层和LCD硬件驱动层。LCD帧缓冲区层其实就是将内核中的一部分空间当作一个字符型设备,通过操作字符型设备的接口函数就可以操作这段帧缓冲区。而LCD硬件驱动层是对LCD硬件的初始化,LCD控制器在硬件驱动层被看作一个平台设备。

LCD帧缓冲区层对应的文件是fbmem.c,LCD硬件驱动层对应的文件是S32440fb.c。


从最底层开始说吧,那当然是LCD硬件驱动层了。


LCD硬件驱动层(S32440fb.c):

前面提到了LCD控制器在LCD硬件驱动层被当看作是一个平台设备,没有定义字符设备所以不可能通过应用层来访问硬件。

既然是平台设备,那么我们就按照平台设备的执行流程来分析。

首先来看一下,在S32440fb.c文件中定义的平台设备驱动变量。如下:

staticstructplatform_drivers3c2410fb_driver={

.probe =s3c2410fb_probe,

.remove =s3c2410fb_remove,

.suspend =s3c2410fb_suspend,

.resume =s3c2410fb_resume,

.driver ={

.name ="s3c2410-lcd",

.owner =THIS_MODULE,

},

};

后面两个是功耗操作函数,而第一函数才是最重要的呀!因为平台设备驱动在向平台总线注册时如果与挂接在该总线上的设备之一与该平台设备驱动的匹配(文件名或者ID,通常时文件名),那么就会指向探测函数s3c2410fb_probe(为什么会执行,在平台设备总结文章中),探测函数只有一个语句即调用s3c24xxfb_probe函数,这两个函数的参数是一样的

该参数是对应的与之匹配的平台设备结构体,此设备在devs.c中定义,定义代码如下

staticu64s3c_device_lcd_dmamask=0xffffffffUL;


structplatform_devices3c_device_lcd={

.name ="s3c2410-lcd",

.id =-1,

.num_resources =ARRAY_SIZE(s3c_lcd_resource),

.resource =s3c_lcd_resource,

.dev={

.dma_mask =&s3c_device_lcd_dmamask,

.coherent_dma_mask =0xffffffffUL

}

};

s3c_lcd_resource是LCD驱动所使用到的资源,源的定义如下:

staticstructresources3c_lcd_resource[]={

[0]={

.start=S3C24XX_PA_LCD,

.end=S3C24XX_PA_LCD+S3C24XX_SZ_LCD-1,

.flags=IORESOURCE_MEM,

},

[1]={

.start=IRQ_LCD,

.end=IRQ_LCD,

.flags=IORESOURCE_IRQ,

}


};

第一个元素为配置LCD寄存器时所用的寄存器的空间,第二个参数是在LCD硬件驱动中用到了LCD中断,虽然定义了当时没有真正的用到。

进入s3c24xxfb_prob函数,里面有一句代码mach_info=pdev->dev.platform_data;platform_data虽然在定义的时候没有赋值,但是在进入smdk2440_machine_init函数时,第一个语句调用了s3c24xx_fb_set_platdata函数,此函数的作用就是将smdk2440_fb_info变量赋值给s3c_device_lcd.dev.platform_data(具体请看源码),smdk2440_fb_info的定义如下:

staticstructs3c2410fb_mach_infosmdk2440_fb_info__initdata={

.displays =&smdk2440_lcd_cfg,

.num_displays =1,

.default_display=0,



.gpccon =0xaaaaaaaa,

.gpccon_mask =0xffffffff,

.gpcup =0x0000ffff,

.gpcup_mask =0xffffffff,


.gpdcon =0xaaaaaaaa,

.gpdcon_mask =0xffffffff,

.gpdup =0x0000ffff,

.gpdup_mask =0xffffffff,


.lpcsel =0x00,

};



接下来应该注意一下 fbinfo->fbops =&s3c2410fb_ops;此语句代码。Fbinfo的fbops指向了一个操作在LCD硬件驱动层的一些硬件操作函数,然后再看ret=register_framebuffer(fbinfo); 这中间很多的语句就是对fbinfo中的成赋值,在此不具体分析。register_framebuffer函数不是在该文件中定义的,而是在LCD帧缓冲区层的fbmem.c当中定义,是由有LCD硬件驱动层使用的。它是LCD硬件驱动层和LCD帧缓冲区层的信息交流的通道,这个函数将fbops指针变量传给了LCD帧缓冲区,那么LCD帧缓冲区就可以通过此指针来访问LCD硬件驱动层中的操作函数了。稍后我们在LCD帧缓冲区层的实现代码fbmem.c中详细讲解。





LCD帧缓冲区层(fbmem.c):

LCD帧缓冲区实际上就是把内存当中的一段帧缓冲区抽象成了以字符设备。既然是字符设备,那么在模块初始化函数当中就执行注册字符设备函数,代码如下:

staticint__init

fbmem_init(void)

{

proc_create("fb",0,NULL,&fb_proc_fops);


if(register_chrdev(FB_MAJOR,"fb",&fb_fops))

printk("unabletogetmajor%dforfbdevsn",FB_MAJOR);


fb_class=class_create(THIS_MODULE,"graphics");

if(IS_ERR(fb_class)){

printk(KERN_WARNING"Unabletocreatefbclass;errno=%ldn",PTR_ERR(fb_class));

fb_class=NULL;

}

return0;

}

设备的名字为"fb",主设备号是固定的,在/linux/Major被宏定义为29,系统启动后就已经固定了。后面的代码是用于创建结点的,在此不对其进行分析。

注册设备就好了,当然在字符设备当中还有一个文件结构体定义如下:

staticconststructfile_operationsfb_fops={

.owner= THIS_MODULE,

.read= fb_read,

.write= fb_write,

.unlocked_ioctl=fb_ioctl,

#ifdefCONFIG_COMPAT

.compat_ioctl=fb_compat_ioctl,

#endif

.mmap= fb_mmap,

.open= fb_open,

.release= fb_release,

#ifdefHAVE_ARCH_FB_UNMAPPED_AREA

.get_unmapped_area=get_fb_unmapped_area,

#endif

#ifdefCONFIG_FB_DEFERRED_IO

.fsync= fb_deferred_io_fsync,

#endif

};


在应用程序中若相对帧缓冲操作,那么必须先打开对应的结点,则对应要执行的函数当然是fb_open了。那就从fb_open开始分析吧!

进入fb_open函数,我们就就几个核心代码吧!

info=registered_fb[fbidx];这个语句是获得代表帧缓冲区的信息(信息存放在结构体当中)只要有帧缓冲区注册那么就会依次放到registered_fb这个数组(具体怎么被赋值到数组,稍后再注册函数中分析),这样就获得了一个帧缓冲区的信息了。

然后再看这段代码

file->private_data=info;

if(info->fbops->fb_open){

res=info->fbops->fb_open(info,1);

if(res)

module_put(info->fbops->owner);

}

看到了其中的res=info->fbops->fb_open(info,1);语句了吗?就是通过fbinfo指针的文件操作函数来访问LCD硬件驱动层的打开函数的吧!LCD帧缓冲驱动层的程序通过fbinfo中fops指针的变量来访问LCD硬件驱动层的东东。到此打开函数就执行完了。分析此函数的目的不仅是操作帧缓冲区必须先打开文件,还是为了显示出LCD帧缓冲区层怎样来访问LCD硬件驱动层的。



好了,接下来分析LCD帧缓冲区层和LCD硬件驱动层沟通的桥梁函数

现在进入register_framebuffer函数吧!

registered_fb[i]=fb_info;

看到这句代码就知道了上面提到registered_fb为什么会用到了吧!在registered_fb数组中存放着每一个注册代表帧缓冲区信息的结构体指针(structfb_info*)。也许你会有疑问那i的值是多少呐?那怎么就网上看,就看到了如下代码:

for(i=0;i

if(!registered_fb[i])

break;

对registered_fb指针数组遍历,发现为空后就退出,然后注册的帧缓冲区指针就存放到这里,那么就可以实现当注册多个时依次在registered_fb数组中存放了。


如果你要移植到一个开发板上,要改的东西也很少,linux的LCD驱动设计的时候就是可以方便移植的。若硬件差别不大,你只需要更改几个结构体初始化数据,很方便的。



对于LCD的驱动就先讲到这里吧!以为后来用。


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭