基于ARM的平板电脑的底层硬件驱动设计说明
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
摘要
推出平板的目的是为了弥补手机和笔记本电脑之间的这块空白区域,就是为人们提供一款和手机一样携带方便、操作简单,但比手机视觉效果更好,并能像笔记本电脑一样可以快速流畅的上网、观看视频和玩游戏的产品。
软件方面,除苹果自己有自己的IOS外,不管是国还是国外厂商,由于google的开源,基本都选择了 andriod操作系统作为开发平台。
Android是一个基于linux核的操作系统,在一款产品的开发过程中,硬件驱动程序的开发和调试是一项艰巨的任务,驱动程序的质量直接影响产品的性能和稳定性,所以对平板上驱动程序的研究和设计具有实际工程意义。
此次设计针对平板电脑中常用的几个硬件驱动进行了研究和设计,如LCD驱动,PWM背光驱动,按键驱动等。
旨在熟悉驱动设计流程,掌握驱动设计的一般方法。
关键字:平板电脑,Android,linux,硬件驱动
ABSTRACT
The purpose of the launch of the tablet is in order tomake upthepiece ofblank areabetweenmobile phones and laptopcomputersfor people tooffer a device as easy as mobile phoneto carry,simpletooperate, butbetterthanthemobilephonevisual effects, andthesameas the laptopcan quickly accesstotheInternet, watching videos and playing games. On the software side, in addition to Apple's ownIOS, whether domestic orforeign manufacturers, because of googleopened the android source code, basicallychoosetheandriodoperating systemas thedevelopment platform. Android isaLinuxkernel-based operating system, in the process of a productdevelopment, developing and debugginghardware driversisanarduous task, thequalityofthedriverdirectly impact on productperformance and stability, So theresearch and designofthedriverontheTablet PChasapractical engineeringsignificance. This paper will research and design a fewhardware drivers that commonly used in the Tablet PC, suchasLCD drivers, PWMbacklight driver, key drivers and so on. The purposeofthisdesignis tofamiliarto the driverdesign process and graspthegeneral approachtodriverdesign.
Keywords: tablet pc, android, linux, hardware drivers
目录
第一章引言5
1.1 ARM处理器介绍5
1.2 android 操作系统介绍6
1.3 平板电脑驱动开发概述7
第二章软硬件平台介绍和启动过程分析9 2.1 硬件平台介绍9
2.2 软件平台介绍9
2.3 启动过程分析10
第三章 LCD驱动设计与实现13
3.1 显示控制器与显示器硬件配置13
3.1.1 S5PV210 显示控制器13
3.1.2 三星9.7寸IPS屏LTN097XL0213 3.1.3 显示模块硬件连接方式14
3.2 android下的LCD驱动15
3.2.1 LCD 硬件时序参数设置15
3.2.2 LCD硬件设备注册16
3.2.3 frambuffer驱动注册18
第四章 PWM背光驱动设计与实现19
4.1 PWM背光控制器硬件连接19
4.2 linux核PWM驱动19
4.2.1 PWM背光设备注册19
4.2.2 PWM背光驱动注册20
4.3 PWM 背光在android HAL 层移植22 4.3.1 什么是硬件抽象层22
4.3.2 HAL的实现机制23
4.3.3 pwm背光的HAL层实现24
第五章接键驱动设计与实现27
5.1 接键硬件以与功能要求27
5.2核空间按键驱动设计和实现27
5.2 android对按键的重映射32
第六章振动电机驱动设计与实现35
6.1功能要求以与硬件连接35
6.2核空间振动电机驱动设计与实现35
6.2.1 什么是timed GPIO35
6.2.2 振动电机的Timed GPIO驱动实现36
6.3振动电机驱动HAL层的实现40
第七章 WM8976声道自动切换设计与实现43
7.1功能要求以与硬件43
7.2核空间声道自动切换设计与实现44
7.2.1什么是switch IO44
7.2.1switch IO 耳机插拔检测驱动设计与实现44 7.2.2wm8976声道切换控制实现48
总结51
参考文献52
致53
外文资料原文54
译文58
第一章引言
2010年1月份苹果公司发布了iPad平板电脑,从此为IT行业带来了一个全新的产业。
iPad定位是介于智能手机和笔记本电脑之间的产品,提供浏览互联网、收发电子、观看电子书、播放音频或视频等功能。
从产品定位我们可以看出,苹果公司推出iPad的目的是为了弥补手机和笔记本电脑之间的这块空白区域,就是为人们提供一款和手机一样携带方便、操作简单,但比手机视觉效果更好,并能像笔记本电脑一样可以快速流畅的上网、观看视频和玩游戏的产品。
iPad 的推出,可以说开启了后PC时代,其火爆的销量让以前其他众多处于观望的厂商也迅速杀入的这块市场。
得益于集成电路的高速发展,以前需要很多电路才可以完成的功能现在都被高度整合到了SOC之中(片上系统)。
所以和PC相比,平板电脑可以把体积做得更小。
功耗做得更底。
从硬件和软件的角度来讲,最关键的分别是SOC和操作系统。
在SOC这一块,国外主要被高通、三星、TI、NVIDIA这些厂商所占据。
这些厂商做出来的SOC集成度高,功能强劲,CPU主频现一般在1G-1.5G左右。
基本已经过渡到双核时代。
终端制造厂商做出来的平板终端主要面向高端消费市场。
在国,几家面向移动多媒体终端的IC设计公司也推出了性能优异的SOC芯片。
如:全志,瑞芯微,君正,晶晨半导体等。
这些厂商的推出的SOC集成度也较高。
主频从800MHZ-1.2GHZ,均为单核处理器。
整体上比国外大厂要低一个档次。
但是,用这些厂商做出来的平板方案成本很低,更复合中国消费者的消费习惯。
所以市场也非常的广阔。
在软件方面。
除苹果自己有自己的IOS外,不管是国还是国外厂商,由于google的开源,基本都选择了 andriod操作系统作为开发平台。
所以在这个平台上的软件资源非常丰富。
对于方案设计商和终端制造商,只要具备一定的开发实力,都可以以这个平台做出差异化地方案。
1.1 ARM处理器介绍
ARM是Advanced RISC Machines的缩写,即可以认为是一个公司的名字,也可以认为是对一类微处理器的通称,还可以认为是种技术的名字。
目前,ARM公司专门从事基于RISC技术芯片的设计开发,作为知识产权供应商,ARM 的商业模式主要涉与 IP 的设计和许可,而非生产和销售实际的半导体芯片。
他们向合作伙伴(包括世界领先的半导体公司和系统公司)授予 IP 许可证。
这些合作伙伴可利用 ARM 的 IP 设计创造和生产片上系统设计,但需要
向 ARM 支付原始 IP 的许可费用并为每块生产的芯片或晶片交纳版税。
除了处理器 IP 外,他们还提供了一系列工具、物理和系统 IP 来优化片上系统设计.
图1-1 ARM 产品线:提供领先的设计、实现和应用正因为 ARM 的 IP 多种多样以与支持基于 ARM 的解决方案的芯片和软件体系十分庞大,全球领先的原始设备制造商 (OEM) 都在广泛使用 ARM 技术,应用领域涉与手机、数字机顶盒以与汽车制动系统和网络路由器。
当今,全球 95% 以上的手机以与超过四分之一的电子设备都在使用 ARM 技术。
在平板领域,国外厂商基本青一色的使用了ARM的核或者具有ARM ISA的处理器。
在国,除群正自主研发基于MIPS ISA的xburst架构CPU以外。
其他厂商都采用了ARM cortex A8或cortex A9核,在此基础上再加入厂商自己的外设如USB,LCDC,HDMI,audio codec,video codec等,形成具有自主特色的SOC。
1.2 android 操作系统介绍
Android最早是由google在2007年发布的一款操作系统,Android是一种以Linux为基础的开放源代码操作系统,主要使用于便携设备。
Android操作系统最初由Andy Rubin开发,最初主要支持手机。
2005年由Google收购注资,并组建开放手机联盟开发改良,逐渐扩展到平板电脑与其他领域上。
自2007年发布以来,Android已经经历了数个版本的更新,市面上采用该系统的移动设备数量也在飞速增长。
目前市面上实用的比较多的版本为android2.3, 代号为饼。
Google最新的版本为4.0,代号为冰欺凌治。
根据google的官方统计,就目前的市场占有率来看,2.3版本为市场占有市场份额最多的anroid版本。
约占了整个android 的63.9%。
在该平台上软件资源也是最丰富的。
图1-2 Anroid设备中各版本占有率
1.3 平板电脑驱动开发概述
驱动程序是一种实现硬件具体功能的软件。
做驱动程序开发不仅仅要明白操作系统为我们提供的驱动模型,常用的数据结构。
而且要理解我们所操作的硬件。
明白硬件的工作原理。
所以驱动程序的开发工作非常具有挑战性。
在现在市长上销售的平板中,大多数在硬件平台上,选用ARM处理器,软件平台上选用android(苹果有自家的IOS),所以,平板电脑上的驱动开发可以说是在ARM平台上的android驱动开发,由于android是linux核,所以android下有很多为标准的linux 驱动,如串口驱动, framebuffer驱动,touch panel驱动等。
但android 也有自己的专有驱动。
具体如下:
1.Android Binder: 基于OpenBinder框架的一个驱动,用于提供Android 平台的进程间通信功能。
2.Android电源管理(PM): 一个基于标准liunx电源管理系统的轻量级Android电源管理驱动,针对嵌入式设备做了很多优化。
3.低存管理器(Low Memory Killer): 根据系统运行的需要杀死进程以释放需要的存。
4.匿名共享存(Asheme): 为进程间提供大量共享存,同时为核提供回收和管理这个存的机制。
5.Android PMEM(physical): PMEME用于向用户空间提供连续的物理存区域。
6.Android Logger: 一个轻量级的日志设备,用于抓取Android系统的各种日志。
7 / 59
7.Android Alarm: 提供了一个定时器,用于把设备从睡眠状态唤醒,同时它还提供了一个即使在设备睡眠时也会运行的时钟基准。
B Gadget: 驱动一个基于标准liunx usb gadget 驱动框架的设备驱动,Android的USB驱动是基于gadget框架。
9.Android ram Console: 为了提供调试功能,Android允许将调试日志信息写入一个被称为RAM Console的设备里,它是一个基于RAM的Buffer.
10.Android timed deivce: 提供了对设备进行定时控制功能,目前支持vibrator 和LED设备.
11.Yaffs2文件系统: Android采用Yaffs2作为MTD nand flash文件系统。
同时,同标准的linux相比,android驱动开发中,为我们提出了一个新的概念HAL(Hardware Abstract Layer硬件抽象层). 是Google因应厂商希望不公开源码的要求下,所推出的新观念。
HAL运行在用户空间,这样,驱动程序就可以不受GPL的限制,不用公开源代码。
他们的硬件规格和驱动代码就可以很好的保护驱动。
这对很多设备制造商来说,是一种良好的自我保护。
在android移植中,HAL也是需要驱动人员去开发的一部分。
针对我们的自己搭建的硬件平台,在本文中将重点阐述如下驱动的移植和开发:
1.三星9.7英寸IPS显示面板显示驱动设计。
2.显示面板PWM背光驱动程序设计。
3.平板电脑上按键驱动设计。
4.振动电机驱动设计。
5.WM8976 codec研究,配合硬件实现耳机插入检测,着重解决外放喇叭和耳机声道自动切换问题。
第二章软硬件平台介绍和启动过程分析
2.1 硬件平台介绍
在硬件平台上选用三星蜂鸟ARM处理器s5pv210.其具有如下特性:CortexTM-A8架构
32KB I/D缓存,512KB二级缓存
64位多总线架构
●支持MPEG4,H.263,H.264 1080P30fps编解码以与MPEG4
●1080P30fps解码
JPEG解码高达80Mpixels/s
2D,3D高性能加速
HDMI,TV OUT
根据应用需求,我们板载如下硬件:
1.三星K4T1G084QE 512MB DDR
2.
2.9.7寸IPS显示屏,分辨率为1024*768.
3.9.7寸10点电容触摸屏。
采用goodix GT8105芯片组.
4.HDMI高清输出接口.
5.OV2655 200W像素前置摄像头.
6.WM8976 audio codec,自带AB类功放.
7.Kionix KXTF9-2050 加速度传感器.
8.Atheros AR6102 WIFI.
9.7400MA 锂电池,并设计了充电电路.
10.振动电机.
2.2 软件平台介绍
在软件开发上选用 xboot作为启动引导bootloader。
xboot是由九鼎展创科技自主开发的开源bootloader。
具有如下特性:
支持多操作系统选择启动,默认系统可自定义;
支持开机LOGO;
支持shell命令行脚本解析;
源码架构清晰易懂,无需繁琐的宏定义;
添加程序简单,类似linux驱动加载;
完全免费开源工程,无须license;
支持打包核,调试更加出色;
支持打包文件系统,boot,kernel,ramdisk只需一个文件;
Android采用目前兼容性最好的android2.3。
核采用linux2.6.37.整个开发过程在ubuntu10.10下完成.
2.3 启动过程分析
系统启动过程是一个代码从闪存到存,初始化必须的硬件并为操作系统的运行做好前期准备的过程。
本系统中启动代码由三部分组成:IROM,一级bootloader,二级bootloader。
其中IROM由CPU自身硬件实现,一级和二级bootloader由xboot实现.每一个阶段的特点为:
●iROM代码:包含小而简单的代码,是独立于平台和存储在部存储器
●一级引导装载程序:包含小而简单的代码,这是独立于平台和存储在外部存
储设备。
●二级引导装载程序:包含复杂的代码,这是特定于平台和存储在外部存储设
备。
S5PV210带64K ROM 和96K SRAM。
部的64KB ROM和部96KB SRAM的地区都可以用于引导。
可通过外部引脚设置选择从不同的设备启动.
图2-1 启动引导过程
具体启动过程如下:
IROM代码被放置在部的64KB ROM。
它初始化基本系统功能,如时钟,堆栈和堆。
该IROM从一个特定的外部引导设备复制一级bootloader到部96KB的SRAM。
引导设备的选择由工作模式(OM)引脚确定。
在一级bootloader中主要完成如下功能:
1.关闭看门狗
2.设置CPU到管理模式
3.关MMU
4.初始化系统时钟
5.初始化DRAM控制器
6.锁定系统电源状态
7.跳转到二级bootloader
其中在锁定系统电源这个步骤是为了用户开机的实现。
在硬件上系统有如下开机电路:
11 / 59
图2-2 硬件开机电路
整个供电电路中,首先按住SW12,即POWER键,MOS管Q5的栅级由高电平变为低电平,MOS管导通,DCDC芯片MP1482的使能脚被拉高,5V电压产生。
随后,3.3V的DC-DC电源芯片由于5V电源已近输入也会开始工作,产生3.3V电压,给整个板卡供电,程序开始运行。
在bootloader中将网络标号为PWR_LOCK 的GPIO口拉高,注意这时5V供电部分的三极管Q6导通,MOS管Q5维持导通,至此,可以松开POWER按键整个电源已经置锁。
在二级bootloader中主要完成如下功能:
1.初始化本阶段用到的外设
2.拷贝核镜像和根文件系统到DRAM中
3.设置启动参数
4.调用核.
第三章 LCD驱动设计与实现
3.1 显示控制器与显示器硬件配置
3.1.1 S5PV210 显示控制器
S5PV210自带显示控制器,它可以将总线上图像数据和系统存中的视屏缓冲区里的数据传输到外部LCD接口上。
外部的LCD接口支持三种类型:RGB接口,间接I80接口,和YUV接口。
显示控制器具有五个叠加图形窗口,支持多种颜色模式,256级alpha混合,色键,XY位置控制,软滚动,可变窗口大小. 同时支持各种颜色格式,如RGB(1 BPP~24 BPP)和YCbCr4:4:4.可通过软件配置以支持在屏幕上的水平和垂直像素,数据接口数据线的宽度,接口时序,和刷新率的不同要求.
显示控制器传输视频数据,并产生必要的控制信号,如,RGB_VSYNC,RGB_HSYNC,RGB_VCLK,RGB_VDEN和SYS_CS0,SYS_CS1,SYS_WE。
除了产生控制信号,显示控制器包含视频数据的数据端口。
其结构框图如下:
3-1 S5PV210显示控制器结构框图
3.1.2 三星9.7寸IPS屏LTN097XL02
LTN097X02是一个完整的具有LED背光系统的彩色有源矩阵液晶显示器。
矩阵采用的a-Si薄膜晶体管作为有源元件。
它是一种透射型显示操作系统。
这块TFT-LCD具有9.7英寸XGA主动显示区域分辨率(1024×768像素)。
每个像素被分为红,绿,蓝子像素。
每个子像素具有6级灰度信号,一共呈现出262,144种颜色。
LTN097XL02采用了LVDS接口,以使整个模块达到低功耗,高速,低EMI 要求。
基于这些特点他非常适合作为平板电脑显示器。
其整个模块框图如下:
图3-2 LTN097XL02部结构框图
3.1.3 显示模块硬件连接方式
由于S5PV210的显示控制器不支持LVDS接口,所以外接电路需要实现RGB 到LVDS的转换电路。
选用DOESTEK DTC34LM85A作为LVDS发送器,完成RGB接口到LVDS接口的时序转换其硬件电路如下:
图3-3 RGB接口转LVDS接口电路
特别值得注意的是,芯片具有一个PDN引脚,该引脚为低电平时,整个芯片进入低功耗模式,芯片停止工作,整个IC的从3.3V吸收的电流从大约35mA降到10uA,可大大降低功耗。
因此把此引脚连入到CPU上的GPIO,通过驱动控制以达到控制显示模块挂起时的低功耗的目的。
3.2 android下的LCD驱动
三星公司把LCD的驱动程序在核中以platform driver的形式注册。
针对不同的LCD dvice,需要补充实现不同的platform dvice。
注册后,驱动程序根据注册的硬件信息来配置和初始化显示控制器。
以达到硬件上的时序要求,同时伴随注册的为LCD的操作方法,如LCD gpio配置,打开背光,关闭背光,LCD复位等操作。
3.2.1 LCD 硬件时序参数设置
图3-4 RGB接口驱动时序
上图给出了LCD屏的典型时序,时序图中的VCLK,HSYNC和VYSNC分别为像素时种信号,行同步信号,帧同步信号,VDEN为数据有效标志,VD为图像的数据信号。
作为帧同步信号的VSYNC,每发出一个脉冲,都意味着新的一屏数据开始发送,上一屏数据结束和下一屏数据开始中间的时间为场消隐(field blanking)。
而作为行同步信号的HSYNC,每发出一个脉冲都表明新的一行图像数据开始发送。
在一行数据结束和下一行数据开始之间的时间为行消隐(line blanking)。
在帧同步和行同步之前和之后都必须留下消隐时间。
场消隐时间=VFPD+1+VSPW+1+VBPD+1;
其中VFPD为场消隐前沿,VSPW为场消隐脉冲宽度,VBPD为场消隐后沿。
15 / 59
行消隐时间= HFPD+1+HSPW+1+HBPD+1;
其中HFPD为行消隐前沿,HSPW为行消隐脉冲宽度,HBPD为行消隐后沿。
图3-5 LTN097XL02硬件时序参数
其参数可通过LTN097XL02硬件手册得到。
如上图所示。
3.2.2 LCD硬件设备注册
在系统初始化过程中,调用static void __init smdkv210_machine_init(void)函数,在其中注册frambuffer的platform device:
platform_device_register(&s3c_device_fb);
然后为frambuffer设置平台数据:
s3cfb_set_platdata(<N097xl02_data);
其中LTN097xl02定义为:
static struct s3c_platform_fb LTN097xl02_fb_data __initdata = { .hw_ver = 0x62,
.nr_wins = 5,
.default_win = CONFIG_FB_S3C_DEFAULT_WINDOW,
.swap = FB_SWAP_WORD | FB_SWAP_HWORD,
.lcd = & LTN097lx02,
.cfg_gpio = LTN097lx02_cfg_gpio,
.backlight_on = LTN097lx02_backlight_on,
.backlight_onoff = LTN097lx02_backlight_off,
.reset_lcd = LTN097lx02_reset_lcd,
};
其中ek070tn93定义为:
static struct s3cfb_lcd LTN097lx02 = {
.width = 1024,
.height = 768,
.bpp = 32,
.freq = 60,
.timing = {
.h_fp = 260,
.h_bp = 480,
.h_sw = 10,
.v_fp = 22,
.v_fpe = 1,
.v_bp = 18,
.v_bpe = 1,
.v_sw = 7,
},
.polarity = {
.rise_vclk = 0,
.inv_hsync = 1,
.inv_vsync = 1,
.inv_vden = 0,
},
};
17 / 59
这个结构体中决定了lcd显示分辨率,显示帧率,以与色深。
.timing域就决定了LCD的硬件时序参数。
.polarity域决定了LCD控制性号的有效电平为高有效还是低有效。
3.2.3 frambuffer驱动注册
由于显示控制器已经集成在三星的SOC中作为一个独立的硬件模块布存在,因此LCD驱动包含了平台驱动。
这样在frambuffer设备注册的过程中只需要注册平台驱动。
当找到匹配的平台设备时,在探测函数中完成了如下4个工作:(1)申请fb_info结构体存空间,初始化FBI结构体中固定和可变的屏幕参数。
(2)根据注册的LCD dvice传递的硬件信息,完成显示控制器的初始化。
(3)申请frambuffer设备显示缓冲空间。
(4)注册frambuffer设备。
注册的frambuffer设备将在用户空间生成相应的节点,操作系统调用相应的操作节点,以达到操作LCD硬件的目的。
第四章 PWM背光驱动设计与实现
4.1 PWM背光控制器硬件连接
图4-1 PWM背光驱动电路
在硬件上采用MPS MP3202升压恒流IC,CPU 发出受软件控制的PWM信号。
经过R64,C34滤波后改变参考直流DC电势,以达到调节背光的目的。
CPU通过一个GPIO控制MP3202 EN端,从而控制背光的打开和关闭。
4.2 linux核PWM驱动
4.2.1 PWM背光设备注册
由于S5PV210自带PWM控制器,所以PWM设备在核被抽象为一个平台设备。
我们使用PWM_TOUT0作为背光驱动设备。
在mach-smdkv210.c中定义PWM背光设备为:
static struct platform_device smdk_backlight_device = { .name = "pwm-backlight",
.id = -1,
.dev = {
.parent = &s3c_device_timer[0].dev,
.platform_data = &smdk_backlight_data,
},
};
其中.name定义了背光设备的名字 .platform_data成员指向了此背光设备的平台数据,其定义为:
static struct platform_pwm_backlight_data smdk_backlight_data = { .pwm_id = 0,
.max_brightness = 255,
.dft_brightness = 255,
.pwm_period_ns = 78770*4,
};此结构体中比较重要的两个成员为 max_brightness:最大亮度值。
由于android 平台上规定PWM背光亮度围为0~255.所以设置最大亮度值为255。
pwm_period_ns决定了pwm的周期:
Tpwm=78770*4=315080 (ns)。
故PWM的输出频率为:Fpwm=1/Tpwm=3.17(KHz)。
定义的PWM设备通过platform_device_register(&smdk_backlight_device)函数调用注册为一个平台设备。
4.2.2 PWM背光驱动注册
由于PWM背光设备被实现为一个平台设备,则需要与之对应的平台驱动来驱动该设备。
此驱动在核代码/driver/video/backlight/Pwm_bl.c中实现。
在模块加载过程中先执行模块初始化函数:
static int __init pwm_backlight_init(void)
{
return platform_driver_register(&pwm_backlight_driver);
}
在初始化中完成对PWM背光平台驱动的注册。
其中pwm_back_light_driver定义为:
static struct platform_driver pwm_backlight_driver = {
.driver = {
.name = "pwm-backlight",
.owner = THIS_MODULE,
},
.probe = pwm_backlight_probe,
.remove = pwm_backlight_remove,
.suspend = pwm_backlight_suspend,
.resume = pwm_backlight_resume,
};
在此结构体中实现了平台驱动的几个方法:探测硬件是否存在的probe方法,移除驱动的remove方法, 睡眠挂起的suspend方法和恢复的resume方法。
当此驱动加载时,通过匹配驱动名和设备名来遍历系统中是否存在相应的设备,如匹配成功,则调用pwm_backlight_probe函数,在此函数中完成的操作为:
图4-2 pwm_backlight_probe函数执行流程
其中注册背光设备到backlight类的实现为:
backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
&pwm_backlight_ops, &props);
其中dev_name(&pdev->dev)为注册设备的名字。
最终被解析为“pwm-backlight”, pwm_backlight_ops参数的定义为:
static const struct backlight_ops pwm_backlight_ops = {
.update_status = pwm_backlight_update_status,
.get_brightness = pwm_backlight_get_brightness,
21 / 59
};
pwm_backlight_update_status为用户空间对相应节点的写操作实现的核空间的回调函数,pwm_backlight_get_brightness向用户空间反回当前的PWM背光亮度.
整个探测过程结束后,在sys文件系统下,生成
/sys/class/backlight/pwm-backlight/brightness节点,用户空间通过写这个节点来实现背光亮度的调节。
4.3 PWM 背光在android HAL 层移植
4.3.1 什么是硬件抽象层
Android HAL是google应厂商希望不公开源代码的要求所推出的一个概念。
它能以封闭源码的形式提供硬件驱动模块。
其目的是把Android Framwork与Linux Kernel隔开,让Android不至于过度依赖Linux Kernel,以达成Kernel Independent的概念,也让Android Framwork的开发能在不考虑驱动程序的前提下进行。
HAL提供了简单的设备驱动程序接口,应用程序使用设备驱动程序与底层硬件进行通信。
另外,HAL应用程序接口和ANSIC标准库结合在一起,用户可以使用C语言库函数来访问Android文件系统。
其在android中的位置如下图所示:
图4-3 android软件框架图
从上图可以看到,HAL位于Linux Kernel与Libraries和Android Runtime 之间,也就是说,HAL是底层硬件设备驱动程序提供给Application Framwork 的一个接口,它将直接和底层的设备驱动程序挂接。
因此当我们需要将Android 移植到具体硬件时,或者给Android添加硬件支持时,都需要对Android的HAL 层进行移植或实现。
4.3.2 HAL的实现机制
4.3.2.1 通过库模块实现
早期的 Android HAL通过库模块实现,在“hardware/libhardware_ legacy”目录中实现,它需要将HAL实现为一个*.so的共享库,然后在Runtime 过函数直接调用HAL Module来操作驱动程序。
其调用流程如下图所示:
图4-4 Android HAL通过库实现的调用流程
由于采用了直接调用方式,可被多个进程使用,但会被映射到多个进程空间,从而造成资源浪费,同时需要考虑代码能否安全重入的问题。
4.3.2.1 通过HAL stub方式实现
HAL stub方式是Android改进后的方式,引入了桩(stub)的概念,stub 虽然仍是以 *.so库的形式存在,但 HAL 已经将 *.so 库隐藏起来了。
Stub 向 HAL 提供操作函数(operations),而 runtime 则是向 HAL 取得特定模块(stub)的操作函数,再回调这些操作函数。
和以库模块方式实现的不同就在于:HAL stub是通过回调函数间接的调用操作。
这就说明HAL中包含了各种各样的stub,Runtime只需要通过不同的类型(moduleID)就可以取得不同设备驱动的操作。
其调用流程如下图所示:
23 / 59
图4-5 Android HAL通过stub方式实现的调用流程
实际上,这种方式也将Android在不同的硬件中的移植工作进行了简化,统一了访问硬件的接口,不同的硬件只需要按照规则实践这些接口即可。
4.3.3 pwm背光的HAL层实现
由于HAL层是以模块的方式被加载,所以HAL 层的实现也可以看成是一个硬块的实现。
在device\samsung\proprietary\liblight下建立lights.c和Android.mk文件.其中Android.mk文件容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := lights.c
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
通过这个makefile,在整个android编译时就会生成相应的共享库,由于我们的目标平台为smdkv210。
所以最后生成lights.smdkv210.so,并放到目标平台上lib/hw/目录下。
在lights.c中实现如下模块结构:
const struct hw_module_t HAL_MODULE_INFO_SYM = {
.tag = HARDWARE_MODULE_TAG,
.version_major = 1,
.version_minor = 0,
.id = LIGHTS_HARDWARE_MODULE_ID,
.name = "lights Module",
.author = "Google, Inc.",
.methods = &lights_module_methods,
};
hw_module_t结构体的methods成员是一个指向hw_module_methods_t结构体的一个指针,hw_module_methods_t结构体定义如下:
typedef struct hw_module_methods_t {
int (*open)(const struct hw_module_t* module, const char* id,struct hw_device_t** device);
} hw_module_methods_t;
据此我们定义一个hw_module_methods_t类型的参数lights_module_methods如下:
static struct hw_module_methods_t lights_module_methods = { .open = open_lights,
};
其中open_lights实现流程如下:
25 / 59
图4-6 open_light函数实现流程
首先设置了背光回调函数,以在需要对背光操作的时候回调这个函数。
初始化一个线程互斥锁用于保护在回调调光函数对节点的写操作。
然后分配light_device_t结构体。
可看出在open_light函数中主要完成用light_device_t这个结构体去初始化device 这个二重指针。
并向其中传入了对背光操作的回调函数,其原型为:
static int set_light_backlight(struct light_device_t *dev,
struct light_state_t const *state)
{
int err = 0;
int brightness = rgb_to_brightness(state);//rgb到亮度转换
pthread_mutex_lock(&g_lock);//写线程加锁
err = write_int(LCD_FILE, brightness);//写亮度值到驱动节点
pthread_mutex_unlock(&g_lock);//写线程解锁
return err;
}
其中LCD_FILE定义:
char const *const LCD_FILE = "/sys/class/backlight/pwm-backlight/brightness";
可以看出,LCD_FILE为linux核空间向用户空间提供的驱动节点。
调用
write_int(LCD_FILE, brightness)函数完成对这个驱动节点的写操作,以达到调节背光的目的.
第五章接键驱动设计与实现
5.1 接键硬件以与功能要求
在本设计中,根据一般用户需求,在硬件板卡做了如下6个按键:
1.Power 键,实现长按开机,长按关机,短按睡眠;
2.volume up键, 实现音频声音的增大;
3.volume down键,实现音频声音的减少;
4.Home键,实现android下主界面的返回;
5.菜单键,实现短按弹出选择菜单;
6.返回键,实现返回到上一个界面;
其中每个按键到s5pv210的一个IO上,其对应关系如下:
图5-1功能按键和硬件IO的对应关系
5.2核空间按键驱动设计和实现
在按键驱动设计中,我们把按键设备抽象为一个平台设备,相应的驱动程序也作为一个平台设备驱动给出。
其模块初始化代码如下:
static int __init s3c_button_init(void)
{ //注册按键平台设备
platform_device_register(&s3c_device_button);
//注册按键平台驱动
return platform_driver_register(&s3c_button_device_driver);。