xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
虽然代码很简单,实现lcd驱动,使lcd才能显示图片,当按下按钮后切换图片。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
先要说明一下几处地方:
1、代码中显示的图片都是*.bin文件(显示模式是使用16位数据来表示一个象素的颜色——5:6:5),将jpg文件转为*.bin文件的工具在我上传的mkimage目录中。转换图片的规格在fb.h食指定,我的图片是480*272,所以:
#defineX480
#defineY272
转换的命令也很简单:
./mkimagesrc_filedis_file
源代码都上传了,自己摸索,源码面前没有秘密。
mkimage.rar
2、我的lcd是480*272,虽然是同样的规格的lcd,由于接线的不一样,我也不能保证就能驱动成功。并且,显示器的不同也只须要更改lcd配置函数就可以了。
接出来介绍一下我编撰时的次序。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
一、实现lcd的基本操作:12th_lcd/1st
代码具体做了以下几件事:
1、定义了一个结构体:struct_lcd_t
2、实现了lcd即基本操作,包括:
配置lcd:s3c_lcd_config(struct_lcd_t*lcd)
启动lcd:s3c_lcd_enabe(struct_lcd_t*lcd)
关掉lcd:s3c_lcd_disable(struct_lcd_t*lcd)
3、封装了lcd设备的初始化和注销函数:
init_lcd_device(struct_lcd_t*lcd)
destory_lcd_device(struct_lcd_t*lcd)
其中有一个我在之前的总结中没有介绍的知识点——DMA编程,简单的理解都会调用一个函数,函数给你返回两个地址linux lcd驱动模块linux格式化命令,一个是虚拟地址,一个是对应的数学地址。只要你的程序往虚拟地址中读写数据,实际都会往化学地址写数据。主要的特征就是:数据的传输不须要经过处理器,而是2440中的DMA负责传输。具体的之后有机会再补充。
虽然就是一个函数:
void*dma_alloc_writecombine(structdevice*dev,size_tsize,dma_addr_t*handle,gfp_tgfp)
注意:假如显示屏不一样的话,就要更改s3c_lcd_config上面的代码。
装载模块时,会调用test_lcd函数测试是否成功,该函数会让屏幕全红。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
二、实现字符型设备:12th_lcd/2nd
第二个代码在原先的基础上注册了杂设备,而且实现了write操作,当在应用层将图片数据讲到设备文件/dev/test_lcd中,都会将图片显示下来。
大致知识点:
·linux设备驱动归纳总结(三):2open.close.read.write
·linux设备驱动归纳总结(十):1.udev&misc
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
三、实现图片切换:12th_lcd/3rd
第三个代码要实现的功能是:当键盘按下时,应用层切换新的图片传给lcd。
这儿要添加两个东西:
1、添加中断,当键盘按下时执行中断处理函数。
2、添加字符设备的异步通知机制,在中断处理函数发送讯号到应用层,应用程序接到讯号后更换图片。
大致知识点:
·linux设备驱动归纳总结(六):1.中断的实现
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
四、实现键盘去抖:12th_lcd/4th
在前面的程序,假如硬件本身不好的话,按下一次的键盘可能形成多次的中断,所以键盘去抖很有必要。实现很简单,就是添加一个定时器。
大致知识点:
·linux设备驱动归纳总结(七):2.内核定时器
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
五、实现静态平台类驱动:12th_lcd/5th
虽然就是在原先的程序上加上平台类驱动的注册,之后更改3处的内核代码:
1、arch/arm/mach-s3c2440/mach-mini2440.c
250staticstructplatform_device*mini2440_devices[]__initdata={
251&s3c_device_usb,
252&s3c_device_rtc,
253&s3c_device_lcd,
254&s3c_device_wdt,
255&s3c_device_led,
256&s3c_device_wdt_xb,
257&s3c_device_lcd_xb,//这是新添加的
258&s3c_device_i2c0,
259&s3c_device_iis,
260&s3c_device_dm9k,
261&net_device_cs8900,
262&s3c24xx_uda134x,
263};
2、arch/arm/plat-s3c24xx/devs.c
405staticstructresources3c_lcd_xb_resource[]={
406[0]={
407.start=0x4d000000,
408.end=0x4d0000ff,
409.flags=IORESOURCE_MEM,
410},
411[1]={
412.start=0x56000000,
413.end=0x560000ff,
414.flags=IORESOURCE_MEM,
415},
416[2]={
417.start=IRQ_EINT1,
418.end=IRQ_EINT1,
419.flags=IORESOURCE_IRQ,
420}
421};
422
423structplatform_devices3c_device_lcd_xb={
424.name="s3c_lcd_xb",
425.id=-1,
426.num_resources=ARRAY_SIZE(s3c_lcd_xb_resource),
427.resource=s3c_lcd_xb_resource,
428};
429
430EXPORT_SYMBOL(s3c_device_lcd_xb);
3、arch/arm/plat-s3c/include/plat/devs.h
5externstructplatform_devices3c_device_lcd_xb;
大致知识点:
·linux设备驱动归纳总结(九):1.platform设备驱动
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
六、实现字符设备操作mmap:12th_lcd/6th
这个知识点我还没总结,大体上就是在应用程序中调用mmaplinux lcd驱动模块,驱动都会把一块实际的显存地址映射到应用层,并返回一个地址给用户操作。
具体就是在字符设备中添加mmap操作。详尽请看代码,我就不详尽介绍了,可以看《LDD3》P418。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
七、为驱动添加讯号量:12th_lcd/7th
虽然这一步在这儿可以说是少于的linux命令行,在非占据单处理器的情况下根本不须要添加避免并发和竞态的机制,我这儿也只是仅仅加上,当是备考。
大致知识点:
·linux设备驱动归纳总结(四):5.SMP下的竞态和并发
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
八、完善代码:12th_lcd_8th
之前为了代码看上去短小一点,我没有在代码中添加错误操作,如申请中断号失败时的操作。这儿稍微更改了一下,添加了一下错误检测的代码。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
源代码:
12th_lcd_1.rar
12th_lcd_2.rar