10-S3C2440驱动学习(四)嵌入式linux-LCD驱动程序

最新更新时间:2023-02-14来源: eefocus关键字:S3C2440  linux 手机看文章 扫描二维码
随时随地手机看文章

核心层的代码以fbmem.c为主,核心层包括许多与具体硬件无关的代码,并且提供了API给用户空间。用户空间使用系统调用,系统调用会使用相应的API函数,最后会调用驱动层实现功能。最终操作到硬件,对于不同的设备,驱动层的代码将有所不同。



一、LCD内核驱动实现分析


内核中包含了LCD驱动程序S3c2410fb.c,通过platform平台驱动框架实现,参考其现在自己写。


字符设备驱动编写往往包括,那么LCD也不例外:

应用程序open的时候,会调用fbmem里面file_operation的open,这个open里面会调用硬件注册进来的结构体的一些函数和属性。


1、fbmem.c分析(内核写好的LCD驱动框架,里面实现一些接口,硬件平台来使用)


(1)入口函数fbmem_init;


fbmem_init(void)

{

create_proc_read_entry("fb", 0, NULL, fbmem_read_proc, NULL);

 

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

printk("unable to get major %d for fb devsn", FB_MAJOR);

 

fb_class = class_create(THIS_MODULE, "graphics");

if (IS_ERR(fb_class)) {

printk(KERN_WARNING "Unable to create fb class; errno = %ldn", PTR_ERR(fb_class));

fb_class = NULL;

}

return 0;

}


fbmem_init里面注册字符设备,其主设备号为29.并且创建了类class_create,但是没创建设备节点


fbmem_init--》register_chrdev--》#define FB_MAJOR             29

(2)假设


app: open("/dev/fb0", ...)   主设备号: 29, 次设备号: 0  //应用程序打开 /dev/fb0,主设备号29 次设备号0



--------------------------------------------------------------


kernel:


        fb_open    


             int fbidx = iminor(inode);                                // 会调用到fb_open ,里面得到次设备号,


             struct fb_info *info = =registered_fb[0];         //fb_info 这个结构体等于registered_fb数组里面的此设备号检索出来,fb_info 有open的话会调用其open函数




app: read()                                                                 //应用程序read的时候


---------------------------------------------------------------


kernel:


              fb_read             //最终调用到内核的fb_read函数 


                     intfbidx = iminor(inode);                                 //得到次设备号0


                     struct   fb_info *info = registered_fb[fbidx];    //在registered_fb数组里得到一个fb_info 结构体


                     if(info->fbops->fb_read)


                            returninfo->fbops->fb_read(info, buf, count, ppos);          //有读函数就调用


                     src= (u32 __iomem *) (info->screen_base + p);                      //没有从screen_base显存基地址读


                     dst= buffer;


                     *dst++= fb_readl(src++);


                     copy_to_user(buf,buffer, c)                                                     //copy_to_user返回给应用程序


因此:


open read都依赖fb_info结构体,从registered_fb数组中得到fb_info结构体。也就是说内核中主设备号为29的设备可能有很多,open的时候根据次设备号从registered_fb数组得到一个fb_info。registered_fb数组是硬件注册来完成初始化的。


(3)registered_fb在哪里被设置?

搜索后发现在:


register_framebuffer(Fbmem.c (driversvideo))



register_framebuffer(struct fb_info*fb_info)


{undefined


       registered_fb[i]= fb_info;


}


S3c2410fb.c里面有使用register_framebuffer。register_framebuffer是供给硬件设备驱动里面掉用。框图如下

到此已经可以很清晰看出LCD的框架。首先内核帮助我们实现了一个主设备号为29的设备,此时只创建了类,并没有在类下创建设备节点。当我们的下层硬件驱动掉用注册函数的时候,会初始化registered_fb结构体,并创建设备节点。此时应用程序可以来打开一个设备节点了,比如open("/dev/fb0", ...),最终会调用到fbmem核心层提供的open函数,这个open函数中根据次设备号,在registered_fb数组中取出硬件注册进来的结构体,调用里面的open函数,或者使用一些属性。这样内核可以方便管理类似的设备了。


注意fbmem核心层和platform_device是无关的,内核注册了fbmem,并且实现了一个platform_device完成初始化,S3c2410fb入口函数,注册平台设备,由于系统中有同名设备,所以.probe= s3c2410fb_probe会被调用,这个probe函数中实现向上fbmem核心层进行注册。


(4)内核已经帮我们实现好了LCD驱动框架的一部分,以及供硬件驱动掉用的接口函数,怎么写LCD硬件部分的驱动程序呢?根据S3c2410fb.c总结以下几部:


(上层fbmem内核已经写好,并完成上层驱动注册。我们要做的是写出硬件部分的函数,来初始化registered_fb)


1. 分配一个fb_info结构体: 怎么分配:framebuffer_alloc

2. 设置fb_info里面的相关参数

3. 注册:register_framebuffer

4. 硬件相关的设置

(5)参考S3c2410fb.c来分析如何写硬件部分的驱动程序。


内核中是通过平台总线驱动来实现的,现在我们独立出LCD驱动来编写。


module_init(s3c2410fb_init);


int __devinit s3c2410fb_init(void)


{undefined


       returnplatform_driver_register(&s3c2410fb_driver);


}


static struct platform_drivers3c2410fb_driver = {undefined


       .probe           = s3c2410fb_probe,


       .remove         = s3c2410fb_remove,


       .suspend = s3c2410fb_suspend,


       .resume         = s3c2410fb_resume,


       .driver            = {undefined


              .name     = "s3c2410-lcd",


              .owner    = THIS_MODULE,


       },


};


static int __init s3c2410fb_probe(structplatform_device *pdev)


{undefined


       structs3c2410fb_info *info;


       structfb_info    *fbinfo;


       fbinfo= framebuffer_alloc(sizeof(struct s3c2410fb_info), &pdev->dev);.


设置fbinfo。。。


       ret= register_framebuffer(fbinfo);


}


s3c2410fb_probe –>register_framebuffer(fbinfo);


fbmem.c系统实现并抽象出来的,使用的时候依赖于底层框架实现,如s3c2410fb_probe里面的内容决定了LCD的具体操作。


(6)设置了LCD的一些信息,现在设置一些硬件的相关配置。如LCD寄存器配置等。

(7)以下引脚为触摸屏的:

(8)设置内容保包括:


每来一个时钟VCLK,打出一个像素点的颜色,染色由VD1-VD23的值决定。


水平垂直同步型号HSYNC VSYNC


显存:存着颜色像素,从里面取出值,打到LCD上。


VM有效的时候打出颜色,无效的时候只是移动不打出颜色

因此,需要设置哪些:


(1)设置LCD控制器


VCLK:发出合适时钟,看LCD手册


(2)分配显存,把地址告诉LCD控制器,告诉颜色格式,一个像素多少字节表示。


内存中分配显存,存储着要显示到屏幕上的像素值,通过从显存中取值,一个一个显示到LCD上。


(3)配置相关引脚为LCD管角。

因此LCD驱动程序涉及到的要点就是以上内容,和常见的字符设备驱动程序,并没有很大差别。


二、自己写LCD驱动程序过程


(1)参考内核自带的LCD驱动程序S3c2410fb.c (driversvideo):

(2)复制参考的头文件,写入口函数,出口函数,协议

(3)需要做哪些事情:



1. 分配一个fb_info结构体: 怎么分配:framebuffer_alloc

2. 设置fb_info里面的相关参数

3. 硬件相关的设置

4. 注册:register_framebuffer

       /* 1分配一个fb_info */

       s3c_lcd= framebuffer_alloc(0, NULL);


。。。


       /* 4注册 */


       register_framebuffer(s3c_lcd);


(4)设置fb_info里面的相关参数

        /*设置 */


        /* 1设置固定的参数 */


/* 2设置可变的参数 */


/* 3设置操作函数 */


/* 4其他的设置 */


(5)几个重要的结构体--fb_info结构体



struct fb_info {

int node;/*  序号索引值,/dev/fb0,/dev/fb1  其中0,1 就是从这里获得的*/

int flags;

struct fb_var_screeninfo var; /* Current var *//* 可变参数,很重要 */

struct fb_fix_screeninfo fix; /* Current fix *//* 固定参数,很重要 */

struct fb_monspecs monspecs; /* Current Monitor specs */

struct work_struct queue; /* Framebuffer event queue */

struct fb_pixmap pixmap; /* Image hardware mapper */

struct fb_pixmap sprite; /* Cursor hardware mapper */

struct fb_cmap cmap; /* Current cmap */

struct list_head modelist;      /* mode list */

struct fb_videomode *mode; /* current mode */

 

#ifdef CONFIG_FB_BACKLIGHT

/* assigned backlight device */

/* set before framebuffer registration, 

   remove after unregister */

struct backlight_device *bl_dev;

/* Backlight level curve */

struct mutex bl_curve_mutex;

u8 bl_curve[FB_BACKLIGHT_LEVELS];

#endif

#ifdef CONFIG_FB_DEFERRED_IO

struct delayed_work deferred_work;

struct fb_deferred_io *fbdefio;

#endif

struct fb_ops *fbops;/* 固定参数,很重要 */

struct device *device; /* This is the parent */

struct device *dev; /* This is this fb device */

int class_flag;                    /* private sysfs flags */

#ifdef CONFIG_FB_TILEBLITTING

struct fb_tile_ops *tileops;    /* Tile Blitting */

#endif

char __iomem *screen_base; /* Virtual address *//* "显存“的基地址 */

unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */  /* ”显存“的大小 */ 

void *pseudo_palette; /* Fake palette of 16 colors */ /* 16位假的调色板 */ 

#define FBINFO_STATE_RUNNING 0

#define FBINFO_STATE_SUSPENDED 1

u32 state; /* Hardware state i.e suspend */

void *fbcon_par;                /* fbcon use-only private area */

/* From here on everything is device dependent */

void *par; /* 这个用来存放私有数据 */

};


fb_fix_screeninfo fix结构体

struct fb_fix_screeninfo {

char id[16]; /* identification string eg "TT Builtin" */

unsigned long smem_start; /* Start of frame buffer mem */

/* (physical address) */

__u32 smem_len; /* Length of frame buffer mem */

__u32 type; /* see FB_TYPE_* */

__u32 type_aux; /* Interleave for interleaved Planes */

__u32 visual; /* see FB_VISUAL_* */ 

__u16 xpanstep; /* zero if no hardware panning  */

__u16 ypanstep; /* zero if no hardware panning  */

__u16 ywrapstep; /* zero if no hardware ywrap    */

__u32 line_length; /* length of a line in bytes    */

unsigned long mmio_start; /* Start of Memory Mapped I/O   */

/* (physical address) */

__u32 mmio_len; /* Length of Memory Mapped I/O  */

__u32 accel; /* Indicate to driver which */

/*  specific chip/card we have */

__u16 reserved[3]; /* Reserved for future compatibility */

};


fb_var_screeninfo var结构体

struct fb_var_screeninfo {

__u32 xres; /* visible resolution */

__u32 yres;

__u32 xres_virtual; /* virtual resolution */

__u32 yres_virtual;

__u32 xoffset; /* offset from virtual to visible */

__u32 yoffset; /* resolution */

 

__u32 bits_per_pixel; /* guess what */

__u32 grayscale; /* != 0 Graylevels instead of colors */

 

struct fb_bitfield red; /* bitfield in fb mem if true color, */

[1] [2] [3]
关键字:S3C2440  linux 编辑:什么鱼 引用地址:10-S3C2440驱动学习(四)嵌入式linux-LCD驱动程序

上一篇:11-S3C2440驱动学习(五)嵌入式linux-网络设备驱动(一)虚拟网卡驱动程序
下一篇:09-S3C2440驱动学习(三)嵌入式linux-platform平台总线驱动程序及分离分层构建驱动框架

推荐阅读

我在ARM板上写的第一个驱动程序
摘要:搞嵌入式有两个方向,一个是嵌入式软件开发(MCU方向),另一个是嵌入式软件开发(Linux方向)。其中,MCU方向基本是裸机开发和RTOS开发,而Linux开发方向又分为驱动开发和应用开发。相较于驱动开发,应用开发相对简单一些,因为搞驱动你要和Linux内核打交道。而我们普通的单片机开发就是应用开发,和Linux开发没多大区别,单片机你去调别人写好的库,Linux应用你也是调别人的驱动程序。很多人学习的路线是:单片机到RTOS,再到Linux,这个路线其实是非常好,循序渐进。因为你学了单片机,所以你对RTOS的学习会很容易理解,单片机+RTOS在市面上也可以找到一个很好的工作。因为你学了RTOS,你会发现Linux驱动开发其实
发表于 2023-03-27
当STM32遇到Linux = STM32MP1
STM32MP1系列是ST今年2月重磅推出的最新多核微处理器产品(MPU),集成两颗主频 650MHz 的 Arm® Cortex-A7 应用处理器内核和一颗运行频率209MHz 的高性能 Arm® Cortex-M4 微控制器内核。这一灵活的异构计算架构在充分满足多种应用的灵活性需求的同时,又实现了最佳性能和低功耗特性。Cortex-A7 内核支持开源操作系统 (Linux/Android),Cortex-M4 内核完美沿用现有的 STM32 MCU 生态系统,有助于开发者轻松实现各类开发应用。同时,STM32MP1嵌入了3D图形处理器(GPU),以支持人机界面(HMI)显示器;兼备高能效实时控制和高功能集成度,有助于简化工业制造
发表于 2023-03-07
Linux 6.2 内核已正式发布,广泛支持苹果 M1 系列芯片
Linux 创始人 Linus Torvalds 现发布了稳定的 Linux 6.2 内核更新,带来了一些新的驱动程序、新功能等等,并且还有一些硬件支持和安全性改进。这是 Linux 2023 年的第一个主要内核版本更新。Linux 6.3 合并窗口今日已正式开启,Linus 称其 “已经有 30 多个拉取请求在排队”。经过两个多月的努力,Linux 内核 6.2 终于引入了 IPv6 堆栈的保护性负载平衡 (PLB),支持英特尔“异步退出通知”机制,新的 x86 FineIBT 控制流完整性机制,以及进一步改进新的 Rust 基础设施。硬件方面,Linux 6.2 提升了 Intel 锐炫显卡 (DG2 / Alchemist)
发表于 2023-02-21
Cache,为STM32L5提速助力(二)
TrustZone下使用ICACHEKey message
发表于 2023-02-09
基于S3C44BOX处理器和Linux操作系统实现物流PDA无线终端的设计
科学技术的进步带来了物流业的巨大变化,从机械化向自动化、智能化发展。我国物流业起步较晚,目前还处于人工管理或半自动管理状态,效率不高。随着物流业的发展,仓储规模不断扩大,货物种 类不断增多,带来一系列连锁反应,导致传统的物流业日渐吃力。嵌入式扩展技术的发展可为物流MA控制领域提供强大灵活的解决方案。本文研究方案将嵌入式扩展技术系统应用于物流控制领域,采用嵌入式处理器以及丰富的外围扩展接口,配以液晶触摸屏,实现了人机交互。结合条码采集器,实现实时采集数据信息,通过无线传输实时连接服务器数据库;实时盘点货物、出入库;实时查询信息及时调度;还具有存储语音数据、简便快捷、避免人为错误、精简人力、管理库存、缩短繁杂程序、节省时间、提高服务质量
发表于 2023-02-07
基于S3C44BOX处理器和<font color='red'>Linux</font>操作系统实现物流PDA无线终端的设计
U-boot在S3C2440上的移植详解(四)
一、移植环境主 机:VMWare--Fedora 9开发板:Mini2440--64MB Nand,Kernel:2.6.30.4编译器:arm-linux-gcc-4.3.2.tgzu-boot:u-boot-2009.08.tar.bz2二、移植步骤在这一篇中,我们首先让开发板对CS8900或者DM9000X网卡的支持,然后再分析实现u-boot怎样来引导Linux内核启动。因为测试u-boot引导内核我们要用到网络下载功能。7)u-boot对CS8900或者DM9000X网卡的支持。u-boot-2009.08版本已经对CS8900和DM9000X网卡有比较完善的代码支持(代码在drivers/net/目录下),而且在S3C2
发表于 2023-02-07
U-boot在<font color='red'>S3C2440</font>上的移植详解(四)

推荐帖子

[转] 了解麦克风灵敏度
灵敏度,即模拟输出电压或数字输出值与输入压力之比,对任何麦克风来说都是一项关键指标。在输入已知的情况下,从声域单元到电域单元的映射决定麦克风输出信号的幅度。本文将探讨模拟麦克风与数字麦克风在灵敏度规格方面的差异,如何根据具体应用选择灵敏度最佳的麦克风,同时还会讨论为什么增加一位(或更多)数字增益可以增强麦克风信号。模拟与数字 麦克风灵敏度一般在94dB的声压级(SPL)(或者1帕(Pa)压力)下,用1kHz正弦波进行测量。麦克风在该输入激励下的模拟或数字输出信号幅度即是衡量麦克风灵敏度。
dontium ADI参考电路
【GD32E503评测】芯片内部接口测试
兆易创新(GigaDevice)的GD32E503V-EVAL开发板核心芯片选用的是GD32E503VET6。在GD32E503V-EVAL开发板进行测试前需要对核心芯片架构熟悉及上手。 GD32E503VET6是一款基于ARMCortex-M33核的32位一般用途的微控制器。Cortex®-M33处理器是32位处理器,具有低中断延迟和低调试成本。Cortex®-M33处理器具有集成和高级的特点。适用于需要高性能、低功耗微控制器的市场产品。处理器基于ARMv8体系结构,支持功
superstar_gu 国产芯片交流
运放的问题
初学运放,不明白这个是什么原理?运放的问题
eadi 模拟电子
【AT-START-F403A测评】第4篇 F403A 内部FLASH参数比较及测试
本帖最后由常见泽1于2020-10-2115:52编辑 FLASH闪存测试AT这款芯片的闪存,看手册里高达1024K的内存,共使用了两片闪存,前512KB容量在第一片闪存(BanK1)中,其余容量在Bank2中。一页是2KB介绍完之后我们直接跳到存储器特性测试在很多应用中对擦除和写的时间是有要求的,我们大概看一下STM3和M4的存储器特性103RC的可以看出来103的擦除时间和电流都是比较小的407的407的擦除时间略长一些128K擦
常见泽1 国产芯片交流
eboot编译的问题
单独编译EBOOT,听说好像要设置什么环境变量,怎么设? 我看HELP里有: SetWINCEREL=1 是这个么?还有人说:wince.bat/myproject1.bat 怎么设呀?谢谢。。eboot编译的问题
282767310 嵌入式系统
请教大神,RC吸收电路中其中的电阻破了,有什么办法简易快速测试出来
在生产过程中,突然发现一款机子的吸收电路中的吸收电阻破了或者掉了,测试纹波什么的都是正常的,发现空载切满载的时候会有滋滋的电流声,请教大神还有什么办法可以快速挑出来?(机子是已经装了壳子的) 请教大神,RC吸收电路中其中的电阻破了,有什么办法简易快速测试出来
HUhu00 电源技术
小广播
设计资源 培训 开发板 精华推荐

何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2023 EEWORLD.com.cn, Inc. All rights reserved