Linux驱动:s3c2440 lcd 驱动分析--终结篇

发布者:superstar11最新更新时间:2022-11-16 来源: zhihu关键字:Linux驱动  s3c2440  lcd 手机看文章 扫描二维码
随时随地手机看文章

一,前言

s3c2440 lcd 驱动分析,涉及到的内容有,LCD图像显示原理、s3c2440的LCD控制器的操作、LCD驱动使用平台总线-设备-驱动模型的实例、LCD相关参数的设置、fb字符设备驱动实例、framebuffer的注册和管理、以及一次LCD显示的完整过程分析。


二,LCD原理和硬件分析

2.1 LCD原理解析

SDRAM:在SDRAM中申请了一块连续的内存作为LCD显示数据的存储,叫做显存(framebuffer)。

LCD控制器:LCD控制器通过硬件电路和LCD屏连接。

LCD屏:作为一个外设通过硬件电路和MCU(引脚配置为LCD引脚)连接。

图像在LCD屏上显示,可以看成是LCD控制器先从显存中取出一帧图像数据,然后输入到LCD屏上。480272的屏,所显示的一帧有480272个像素点、272行、480列。对于每一行的像素点,LCD控制器有一个VCLK信号控制,每来一个VCLK,显示的像素点就向右移动一个,当移动到这一行中的最后一个像素点时,LCD控制器有一个HSYNC信号,控制像素点跳到下一行的第一个像素显示。对于一帧图像(也叫一场),即当像素点移动到最后一行的最后一个位置显示完后,LCD控制器有一个VSYNC信号,控制像素点重新移动到第一行的第一个像素显示下一帧图像。


2.2 硬件电路

2.2.1 LCD背光电路

开启LCD显示,需要使能KEYBOARD(一般EN表示高电平有效,EN上面画一横表示低电平有效)开启背光。

背光开关通过主控,GPB0引脚设置

2.2.2 LCD屏

VLINE:HSYNC信号输出引脚(由LCD控制器操作)

VFRAME:VSYNC信号输出引脚(由LCD控制器操作)

VCLK:VCLK信号输出引脚(由LCD控制器操作)

VD3~VD7:RGB(565)中B数据输出引脚

VD10~VD15:RGB(565)中G数据输出引脚

VD19~VD23:RGB(565)中R数据输出引脚

TS*:供ts触摸屏连接

2.2.3 S3c2440主控

涉及 GPG、GPD、GPC引脚。

VM:LCD控制器使能引脚(由LCD控制器的寄存器配置),开启LCD显示需要配置相关寄存器的相应位使能。 LCD_PWREN:LCD电源使能引脚(由LCD控制器的寄存器配置),开启LCD显示需要配置相关寄存器的相应位使能。

三,LCD应用平台总线-设备-驱动模型

3.1 lcd 设备的加载和注册

MACHINE_START(S3C2440, "SMDK2440")

/* Maintainer: Ben Dooks */

.phys_io    = S3C2410_PA_UART,

.io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,

.boot_params    = S3C2410_SDRAM_PA + 0x100,


.init_irq   = s3c24xx_init_irq,

.map_io     = smdk2440_map_io,

.init_machine   = smdk2440_machine_init,

.timer      = &s3c24xx_timer,

MACHINE_END

将上面的宏展开


static const struct machine_desc __mach_desc_SMDK2440

 __attribute_used__

 __attribute__((__section__(".arch.info.init"))) = {

 .nr = MACH_TYPE_SMDK2410, /* architecture number */

 .name = "SMDK2440", /* architecture name */

 /* Maintainer: Jonas Dietsche */

 .phys_io = S3C2410_PA_UART, /* start of physical io */

 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,

 .boot_params = S3C2410_SDRAM_PA + 0x100, /* tagged list */

 .map_io = smdk2440_map_io, /* IO mapping function */

 .init_irq = s3c24xx_init_irq,

 .init_machine = smdk2440_machine_init,

 .timer = &s3c24xx_timer,

}

MACHINE_START主要是定义了"struct machine_desc"的类型,放在 section(".arch.info.init"),是初始化数据,Kernel 起来之后将被丢弃。

各个成员函数在不同时期被调用:

1.init_machine 在 arch/arm/kernel/setup.c 中被 customize_machine 调用,放在 arch_initcall() 段里面,会自动按顺序被调用。

2. init_irq在start_kernel() -> init_IRQ() -> init_arch_irq() 被调用

3. map_io 在 setup_arch() -> paging_init() -> devicemaps_init()被调用 其他主要都在 setup_arch() 中用到。

系统初始化时,会调用smdk2440_machine_init


static void __init smdk2440_machine_init(void)

{

    // 这里设置LCD的参数,和驱动分离。这样要修改LCD时,驱动层程序可以不需要改动,只需修改设备层参数就行了,方便移植。

    s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);


    // 将smdk2440_devices数组中的设备注册到平台总线

    platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));

    smdk_machine_init();

}


// smdk2440_devices数组

static struct platform_device *smdk2440_devices[] __initdata = {

    &s3c_device_usb,

    &s3c_device_lcd,

    &s3c_device_wdt,

    &s3c_device_i2c,

    &s3c_device_iis,

    &s3c2440_device_sdi,

};


// lcd设备

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

    }

};


// 设置lcd设备参数 smdk2440_lcd_cfg。各参数含义后面在probe分析时解析

/* 480x272 */ 

static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = {

    .regs   = {

        .lcdcon1 =  S3C2410_LCDCON1_TFT16BPP |

                S3C2410_LCDCON1_TFT |

                  S3C2410_LCDCON1_CLKVAL(0x04),


        .lcdcon2 =  S3C2410_LCDCON2_VBPD(1) |

                S3C2410_LCDCON2_LINEVAL(271) |

                S3C2410_LCDCON2_VFPD(1) |

                S3C2410_LCDCON2_VSPW(9),


        .lcdcon3 =  S3C2410_LCDCON3_HBPD(1) |

                S3C2410_LCDCON3_HOZVAL(479) |

                S3C2410_LCDCON3_HFPD(1),


        .lcdcon4 =  S3C2410_LCDCON4_HSPW(40),


        .lcdcon5    = S3C2410_LCDCON5_FRM565 |

                  S3C2410_LCDCON5_INVVLINE |

                  S3C2410_LCDCON5_INVVFRAME |

                  S3C2410_LCDCON5_PWREN |

                  S3C2410_LCDCON5_HWSWP,

    },


    .gpccon      =  0xaaaaaaaa,

    .gpccon_mask    = 0xffffffff,

    .gpcup       =  0xffffffff,

    .gpcup_mask = 0xffffffff,


    .gpdcon      =  0xaaaaaaaa,

    .gpdcon_mask    = 0xffffffff,

    .gpdup       =  0xffffffff,

    .gpdup_mask = 0xffffffff,


    .fixed_syncs =  1,

    .type        =  S3C2410_LCDCON1_TFT, 

    .width      = 480,

    .height     = 272,


    .xres       = {

        .min    = 480,

        .max    = 480,

        .defval = 480,

    },


    .yres       = {

        .max    =   272,

        .min    =   272,

        .defval =   272,

    },


    .bpp    = {

        .min    =   16,

        .max    =   16,

        .defval =   16,

    },

};

调用platform_device_register注册平台设备


int platform_add_devices(struct platform_device **devs, int num)

{

    int i, ret = 0;


    for (i = 0; i < num; i++) {

        ret = platform_device_register(devs[i]);

        if (ret) {

            while (--i >= 0)

                platform_device_unregister(devs[i]);

            break;

        }

    }


    return ret;

}

3.2 lcd 驱动的加载和注册

3.2.1 编译进内核,加载驱动

编译内核设置,make menuconfig

-> Device Drivers

  -> Graphics support

    <*> Support for frame buffer devices

linux-2.6.22.6/.config CONFIG_FB_S3C2410=y linux-2.6.22.6/drivers/video/Makefile obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o


然后make uImage,将s3c2410fb驱动编译进内核,系统启动便会加载,即调用驱动的s3c2410fb_init函数。

int __devinit s3c2410fb_init(void)

{

    // 注册到平台总线驱动

    return platform_driver_register(&s3c2410fb_driver);

}

3.3 lcd 设备和驱动的匹配

3.3.1 lcd设备注册时的匹配

platform_device_register ->

    platform_device_add ->

        device_add ->

            bus_attach_device ->

                device_attach -> 

                    bus_for_each_drv -> // 从平台总线的的驱动链表中,取出每一项驱动进行匹配

                        __device_attach ->

                            driver_probe_device ->

                                if (drv->bus->match && !drv->bus->match(dev, drv)) 此总线类型为平台总线,其存在match函数,即调用platform_match进行匹配


// 平台总线                            

struct bus_type platform_bus_type = {

    .name       = "platform",

    .dev_attrs  = platform_dev_attrs,

    .match      = platform_match,

    .uevent     = platform_uevent,

    .suspend    = platform_suspend,

    .suspend_late   = platform_suspend_late,

    .resume_early   = platform_resume_early,

    .resume     = platform_resume,

};              


static int platform_match(struct device * dev, struct device_driver * drv)

{

    struct platform_device *pdev = container_of(dev, struct platform_device, dev);


    // 平台总线匹配设备和驱动的名称

    return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);

}


// lcd 设备   name = "s3c2410-lcd"

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

[1] [2] [3] [4]
关键字:Linux驱动  s3c2440  lcd 引用地址:Linux驱动:s3c2440 lcd 驱动分析--终结篇

上一篇:Linux驱动:s3c2440 lcd 驱动分析
下一篇:Linux驱动:s3c2410/s3c2440 ts驱动分析 之二

推荐阅读最新更新时间:2024-11-18 12:50

单片机——压力传感器LCD
主程序 #include reg51.h #include intrins.h #include absacc.h #include math.h #define uchar unsigned char #define uint unsigned int #define BUSY 0x80 //常量定义 #define DATAPORT P0 //ADC0832的引脚 sbit ADCS =P3^5; //ADC0832 chip seclect sbit ADDI =P3^7; //ADC0832 k in sbit ADDO =P3^7; //ADC0832 k out sbi
[单片机]
单片机——压力传感器<font color='red'>LCD</font>
AVR M16实验之九 LCD12864
/********************************************************************** * 文件名称: main.c * 程序作者: kidcao1987 * 程序版本: V1.0 * 功能描述: 接好LCD12864,用在LCD12864上显示,这里建议再外接上电源。 CEPARK-M16开发板 12864液晶测试 程序设计: 曹佃生!! www.cepark.com * 编译器:WinAVR-20090313 * 芯片:ATmega16,外部11.0592MHZ晶振 * 技术支持:http://bbs.cepark.com **********************
[单片机]
基于FPGA的LCD%26amp;VGA控制器设计
摘要:介绍了基于FPGA的图形式LCD%26;amp;VGA控制器的设计,详细讨论了用VHDL设计行场扫描时序的方法,这种设计方法稍作改动便可产生任意行场扫描时序,具有很好的可重用性。该控制器已成功地在某型飞机座舱图形显示系统中使用。 关键词:仪表装置 LCD VHDL FPGA VGA 飞机座舱图形显示系统已发展到第六代,即采用有源矩阵彩色液晶显示器AMLCD(Active Matrix Liquid Crystal Display)。当前高分辨率的军用AMLCD显示模块还只能依靠进口,且控制电路板须安装在该显示模块提供的机箱内。这种安装方式对AMLCD控制电路板的尺寸要求高,要求尽可能减少所设计电路板的尺寸。在笔者设计的
[半导体设计/制造]
Linux I2C驱动详解
本文基于mini2440开发板,Linux版本号是:linux-2.6.32.2 一.IIC总线device 硬件信息 #define S3C2410_PA_IIC (0x54000000) static struct resource s3c_i2c_resource = { = { .start = S3C_PA_IIC, .end = S3C_PA_IIC + SZ_4K - 1, .flags = IORESOURCE_MEM, }, = { .start = IRQ_IIC, .end = IRQ_IIC, .flags = IORESOURCE_IRQ,
[单片机]
<font color='red'>Linux</font> I2C<font color='red'>驱动</font>详解
S3C2440的UART详解
1、UART原理简介 在介绍2440的UART控制器之前,我们首先来了解一下UART的原理 UART:Universal Asynchronous Receiver/Transmitter(通用异步收发送器),用来传输串行数据,发送数据时,CPU将并行数据写入UART,UART按照一定格式在TxD线上串行发出;接收数据时,UART检测到RxD线上的信号,将串行收集放到缓冲区中,CPU即可读取UART获得的这些数据。 UART最精简的连线形式只有3根线,TXD用于发送,RXD用于接收,GND用于提供参考电平。UART之间以帧作为数据传输单位,帧由具有完整意义的若干位组成,它包含开始位、数据位、校验位和停止位。发送数据之前,互相通信
[单片机]
<font color='red'>S3C2440</font>的UART详解
基于S3C2440的Ethercat实现
  1 引言   工业以太网由于低成本、易于组网和具有相当高的数据传输速率、资源共享能力强以及易于Internet连接等特点,以太网(Ethernet)指的是由Xerox公司创建并由Xerox、Intel和DEC公司联合开发的基带局域网规范,是当今现有局域网采用的最通用的通信协议标准。以太网络使用CSMA/CD(载波监听多路访问及冲突检测)技术,并以10M/S的速率运行在多种类型的电缆上。以太网与IEEE802·3系列标准相类似。以太网最早由Xerox(施乐)公司创建,在1980年,DEC、lntel和Xerox三家公司联合开发成为一个标准。以太网是应用最为广泛的局域网,包括标准的以太网(10Mbit/s)、快速以太网(100Mb
[单片机]
基于<font color='red'>S3C2440</font>的Ethercat实现
五 ARM9(S3C2440)的实时时钟(RTC)-理论知识及程序实例讲解
在一个嵌入式系统中,实时时钟单元可以提供可靠的时钟,包括时、分、秒和年、月、日。即使系统处于关机状态下,它也能够正常工作(通常采用后备电池供电,能够可靠工作十年),其外围也不需要太多的辅助电路,只需要一个高精度的晶振。 它具有以下特点: 时钟数据采用BCD编码或二进制表示; 能够对闰年的年、月、日进行自动处理; 具有告警功能,当系统处于关机状态时,能产生告警中断; 具有独立的电源输入; 提供毫秒级的时钟中断,该中断可用于嵌入式操作系统的内核时钟。 实时时钟特殊功能寄存器 实时时钟控制(RTCCON)寄存器 RTCCON 寄存器由4 位组成,如控制BCD 寄存器读/写使能的RTCEN、CLKS
[单片机]
盛群推出大点数具I2C接口的LCD驱动IC
盛群的HT16C2X系列为I2C接口、RAM mapping的LCD控制暨驱动IC,此系列以先进设计技术降低IC耗电、提升抗噪声及ESD防护能力。全系列包含HT16C22/HT16C22G、HT16C23/HT16C23G、HT16C24/HT16C24G等。HT16C22已成功获得单相电表客户的认可及采用,HT16C23及HT16C24适合于点数需求较大的三相电表的应用。 此系列内建显示内存及RC振荡电路;工作电压宽广:2.4V~5.5V;提供2种图框扫瞄频率:80Hz or 160Hz;可由外挂电阻调整VLCD电压,也提供内建可由指令调整16阶的VLCD电压;提供全屏闪烁功能、有三种频率可选。透过I2C接口及多项内置
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved