Android GPIO LED 驱动与HAL分析
前言:
以一个GPIO控制的GPIO LED为例,描述Android系统中,如何完成一个最简单的从软件控制硬件的示例:
如何完成一个最简单的驱动程序控制某个GPIO引脚
如何在Android系统中建立这个驱动程序对应的HAL
如何使上层应用程序通过HAL来控制驱动程序
1 总体结构
modkoid工程提供了一个LedTest示例程序,是台湾的Jollen用于培训的。
原始工程下载方法:
#svn checkout
本文所使用的代码基于硬件(s5pc100开发板)做了部分修改。
HAL在Android系统中的位置
2
驱动程序
本部分共两个文件。一个是led_drv.ko,这是驱动程序;另一个是:main,这个实际上main.c生成的测试程序。它可以通过ioctl来控制驱动程序,测试驱动程序是否达到目标。
3.1 驱动程序初始化和退出
static int simple_major = 250;//默认的设备号码,如果为0则尝试自动分配 ……
/*
* Set up the cdev structure for a device.
*/
static void simple_setup_cdev(struct cdev *dev, int minor,
struct file_operations *fops)//自编的函数,注册字符设备
{
int err, devno = MKDEV(simple_major, minor);//建立设备号 cdev_init(dev, fops);//初始化设备结构体struct cdev *dev dev->owner = THIS_MODULE; dev->ops = fops;//关联fops err = cdev_add (dev, devno, 1);//注册一个字符设备 /* Fail gracefully if need be */ if (err)//注册失败处理
printk (KERN_NOTICE "Error %d adding simple%d", err, minor); 3
}
/*
* Our various sub-devices.
*/
/* Device 0 uses remap_pfn_range */
static struct file_operations simple_remap_ops = { //定义设备的fops
.owner = THIS_MODULE,
.open = simple_open,
.release = simple_release,
.read = simple_read,
.write = simple_write,
.ioctl = simple_ioctl,
};
/*
* We export two simple devices. There's no need for us to maintain any
* special housekeeping info, so we just deal with raw cdevs.
*/
static struct cdev SimpleDevs;
/*
* Module housekeeping.
*/
static struct class *my_class;
static int simple_init(void)
{
int result;
dev_t dev = MKDEV(simple_major, 0);//将设备号转化为dev_t的结构
/* Figure out our device number. */
if (simple_major)
result = register_chrdev_region(dev, 1, "simple");//尝试申请主设备号 else {
result = alloc_chrdev_region(&dev, 0, 1, "simple");//请求自动分配主设备号,起始值是0,总共分配1个,设备名simple
simple_major = MAJOR(dev);//将分配成功的设备号保存在simple_major变量中
}
if (result < 0) {//分配主设备号失败
printk(KERN_WARNING "simple: unable to get major %d\n", simple_major);
return result;
}
if (simple_major == 0)//将返回值记录为主设备号。需要么?
simple_major = result;
/* Now set up two cdevs. */
simple_setup_cdev(&SimpleDevs, 0, &simple_remap_ops);//调用自编的函数注册字符设备,有Bug没有返回注册是否成功。
printk("simple device installed, with major %d\n", simple_major);//Bug:打印前应该检查注册是否成功?
my_class= class_create(THIS_MODULE, "simple");//建立一个叫simple的内核class,目的是下一步创建设备节点文件
device_create(my_class, NULL, MKDEV(simple_major, 0),
NULL, "led");//创建设备节点文件
return 0;
}
static void simple_cleanup(void)
{
cdev_del(&SimpleDevs);//删除字符设备
unregister_chrdev_region(MKDEV(simple_major, 0), 1);//注销主设备号
device_destroy(my_class,MKDEV(simple_major,0));//删除设备节点
printk("simple device uninstalled\n");
}
module_init(simple_init);
module_exit(simple_cleanup);
3.2 驱动程序Open and release 函数
//寄存器地址,见CPU手册70页
#define pGPG3CON 0xE03001C0
#define pGPG3DAT 0xE03001C4
//寄存器操作指针
static void *vGPG3CON , *vGPG3DAT;
#define GPG3CON (*(volatile unsigned int *) vGPG3CON)
#define GPG3DAT (*(volatile unsigned int *) vGPG3DAT)
…
static int simple_major = 250;//默认的主设备号
module_param(simple_major, int, 0);//向内核申明一个参数,可以在insmod的时候传递给驱动程序
MODULE_AUTHOR("farsight");
MODULE_LICENSE("Dual BSD/GPL");
* Open the device; in fact, there's nothing to do here.
*/
int simple_open (struct inode *inode, struct file *filp)
{
vGPG3CON=ioremap(pGPG3CON,0x10);//io remap地址pGPG3CON到变量 vGPG3DAT=vGPG3CON+0x04;//计算vGPG3DAT寄存器的地址
GPG3CON=0x1111;//使用宏设定寄存器初始值
GPG3DAT=0xff; //使用宏设定寄存器初始值
return 0;
}
ssize_t simple_read(struct file *file, char __user *buff, size_t count, loff_t *offp) {
return 0;
}
ssize_t simple_write(struct file *file, const char __user *buff, size_t count, loff_t *offp)
{
return 0;
}
……
static int simple_release(struct inode *node, struct file *file)
{
return 0;
}
3.3 驱动程序ioctl函数
…
//ioctl命令值,LED ON ,LED OFF
#define LED_ON 0x4800
#define LED_OFF 0x4801
…
void led_off( void )
{
GPG3DAT=GPG3DAT|(1<<2);//通过宏设定寄存器的值,置1
//printk("stop led\n");
}
void led_on( void )
{
GPG3DAT=GPG3DAT&(~(1<<2)); //通过宏设定寄存器的值,置0
//printk("start led\n");
}
static int simple_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
switch ( cmd )
{
case LED_ON://判断命令
{
led_on();//执行命令 break; } case LED_OFF: { led_off(); break; } default: { break; } } return 0;
3.4 } 驱动测试程序main.c
/*
* main.c : test dem …… 此处隐藏:3703字,全部文档内容请下载后查看。喜欢就下载吧 ……
相关推荐:
- [小学教育]四年级综合实践活动课《衣物的洗涤》教
- [小学教育]2014半年工作总结怎么写
- [小学教育]20世纪外国文学专题综合试题及答案
- [小学教育]TS_1循环使用催化丙烯环氧化反应研究
- [小学教育]最实用的考勤签到表(上下班签到表)
- [小学教育]气候与生态建筑——以新疆民居为例
- [小学教育]二人以上股东有限责任公司章程参考样本
- [小学教育]2014届第一轮复习资料4.1,3美好生活的
- [小学教育]土方开挖、降水方案
- [小学教育]手绘儿童绘本《秋天的图画》(蜡笔)
- [小学教育]2002级硕士研究生卫生统计学考试试题
- [小学教育]环保装备重点发展目录
- [小学教育]金蝶K3合并报表培训教材
- [小学教育]岩浆岩试题及参考答案
- [小学教育]知之深爱之切学习心得
- [小学教育]第十二章 蛋白质的生物合成
- [小学教育]Chapter 2-3 Solid structure and basi
- [小学教育]市政道路雨季专项施工方案
- [小学教育]中国海洋大学2012-2013学年第二学期天
- [小学教育]教育心理学第3章-学习迁移
- 浅谈深化国企改革中加强党管企业
- 2006年中国病理生理学会学术活动安排
- 设计投标工作大纲
- 基于ARP的网络攻击与防御
- 2016届湖北省七市(州)教科研协作体高三
- Google_学术搜索及其检索技巧
- 2019-2020学年七年级地理下册6.3美洲教
- 城市道路可研报告
- 【名师指津】2012高考英语 写作基础技
- 6级知识点培训北京师范大学《幼儿智趣
- 注册会计师会计知识点:金融资产
- 新安装 500 kV 变压器介损分析与判断
- PS2模拟器PCSX2设置及使用教程.
- 医院药事管理与药剂科管理组织机构
- {PPT背景素材}丹巴的醉人美景,免费,一
- NAS网络存储应用解决方案
- 青海省西宁市六年级上学期数学期末考试
- 测量管理体系手册依据ISO10012:2003
- 洞子小学培养骨干教师工作计划
- 浅谈《牛津初中英语》的教材特点及教学




