教学文库网 - 权威文档分享云平台
您的当前位置:首页 > 文库大全 > 小学教育 >

Android GPIO LED 驱动与HAL分析

来源:网络收集 时间:2026-08-24
导读: 前言: 以一个GPIO控制的GPIO LED为例,描述Android系统中,如何完成一个最简单的从软件控制硬件的示例: 如何完成一个最简单的驱动程序控制某个GPIO引脚 如何在Android系统中建立这个驱动程序对应的HAL 如何使上层应用程序通过HAL来控制驱动程序 1 总体结构

前言:

以一个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字,全部文档内容请下载后查看。喜欢就下载吧 ……

Android GPIO LED 驱动与HAL分析.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.jiaowen.net/wenku/42162.html(转载请注明文章来源)
Copyright © 2020-2025 教文网 版权所有
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:78024566 邮箱:78024566@qq.com
苏ICP备19068818号-2
Top
× 游客快捷下载通道(下载后可以自由复制和排版)
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
注:下载文档有可能出现无法下载或内容有问题,请联系客服协助您处理。
× 常见问题(客服时间:周一到周五 9:30-18:00)