• linux设备驱动归纳总结(十二):简单的数码相框【转】


    本文转载自:http://blog.chinaunix.net/uid-25014876-id-116926.html

    linux设备驱动归纳总结(十二):简单的数码相框

    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    其实代码很简单,实现lcd驱动,使lcd能够显示图片,当按下按键后切换图片。

    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    先要说明一下几处地方:

    1、代码中显示的图片都是*.bin文件(显示模式是使用16位数据来表示一个像素的颜色——5:6:5),将jpg文件转为*.bin文件的工具在我上传的mkimage目录中。转换图片的尺寸在fb.h中指定,我的图片是480*272,所以:

    #define X 480

    #define Y 272

    转换的命令也很简单:

    ./mkimage src_file dis_file

    源代码都上传了,自己摸索,源码面前没有秘密。 mkimage.rar   

    2、我的lcd480*272,即使是同样的尺寸的lcd,因为接线的不一样,我也不能保证能够驱动成功。但是,显示器的不同也只需要修改lcd配置函数就可以了。

    接下来介绍一下我编写时的顺序。

    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    一、实现lcd的基本操作:12th_lcd/1st

    代码具体做了以下几件事:

    1、定义了一个结构体:struct _lcd_t

    2、实现了lcd即基本操作,包括:

    配置lcds3c_lcd_config(struct _lcd_t *lcd)

    启动lcds3c_lcd_enabe(struct _lcd_t *lcd)

    关闭lcds3c_lcd_disable(struct _lcd_t *lcd)

    3、封装了lcd设备的初始化和注销函数:

    init_lcd_device(struct _lcd_t *lcd)

    destory_lcd_device(struct _lcd_t *lcd)

    其中有一个我在之前的总结中没有介绍的知识点——DMA编程,简单的理解就会调用一个函数,函数给你返回两个地址,一个是虚拟地址,一个是对应的物理地址。只要你的程序往虚拟地址中读写数据,实际就会往物理地址写数据。主要的特点就是:数据的传输不需要经过处理器,而是2440中的DMA负责传输。具体的以后有机会再补充。

    其实就是一个函数:

    void *dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)

    注意:如果显示屏不一样的话,就要修改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处的内核代码:

    1arch/arm/mach-s3c2440/mach-mini2440.c

    250 static struct platform_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 };

    2arch/arm/plat-s3c24xx/devs.c

    405 static struct resource s3c_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

    423 struct platform_device s3c_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

    430 EXPORT_SYMBOL(s3c_device_lcd_xb);

    3arch/arm/plat-s3c/include/plat/devs.h

    5 extern struct platform_device s3c_device_lcd_xb;

    大致知识点:

    ·linux设备驱动归纳总结(九):1.platform设备驱动

    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    六、实现字符设备操作mmap12th_lcd/6th

    这个知识点我还没总结,大体上就是在应用程序中调用mmap,驱动就会把一块实际的内存地址映射到应用层,并返回一个地址给用户操作。

    具体就是在字符设备中添加mmap操作。详细请看代码,我就不详细介绍了,可以看《LDD3P418

    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    七、为驱动添加信号量:12th_lcd/7th

    其实这一步在这里可以说是多于的,在非抢占单处理器的情况下根本不需要添加防止并发和竞态的机制,我这里也只是仅仅加上,当是复习。

    大致知识点:

    ·linux设备驱动归纳总结(四):5.SMP下的竞态和并发

    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    八、完善代码:12th_lcd_8th

    之前为了代码看起来短小一点,我没有在代码中添加错误操作,如申请中断号失败时的操作。这里稍稍修改了一下,添加了一下错误检查的代码。

    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

  • 相关阅读:
    Java Spring Boot VS .NetCore (十) Java Interceptor vs .NetCore Interceptor
    Java Spring Boot VS .NetCore (九) Spring Security vs .NetCore Security
    IdentityServer4 And AspNetCore.Identity Get AccessToken 问题
    Java Spring Boot VS .NetCore (八) Java 注解 vs .NetCore Attribute
    Java Spring Boot VS .NetCore (七) 配置文件
    Java Spring Boot VS .NetCore (六) UI thymeleaf vs cshtml
    Java Spring Boot VS .NetCore (五)MyBatis vs EFCore
    Java Spring Boot VS .NetCore (四)数据库操作 Spring Data JPA vs EFCore
    Java Spring Boot VS .NetCore (三)Ioc容器处理
    Java Spring Boot VS .NetCore (二)实现一个过滤器Filter
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/6252300.html
Copyright © 2020-2023  润新知