linux驱动初探之杂项设备(控制两个GPIO口)
关键字:linux驱动、杂项设备、GPIO
此驱动程序控制了外接的两个二极管,二极管是低电平有效。
上一篇博客中已经介绍了linux驱动程序的编写流程,这篇博客算是前一篇的提高篇,也是下一篇博客(JNI)的底层程序
一样的在平台文件中配置设备信息
#ifdef CONFIG_HELLO_CTL
struct platform_device s3c_device_hello_ctl = {
.name = "jni",
.id = -,
};
#endif
#ifdef CONFIG_HELLO_CTL
&s3c_device_hello_ctl,
#endif
在编写驱动程序之前要确定需要控制哪个GPIO接口,同时要保证该GPIO口没有被其他程序占用,若被占用则需要取消编译那个驱动程序。
经过查找开发板原理图准备使用CAM_VSYNC和CAM_HREF两个端口

这两个端口对应于平台文件的EXYNOS4212_GPIO(1)与EXYNOS4212_GPIO(2)两个脚,也就是说只要控制这两个脚,就是控制了硬件上的两个脚。

使用杂项设备编写驱动会比字符类设备简单,因为杂项设备的主设备号规定了为10,他能够挂255个从设备号。
同样的,从init函数开始:
static void jni_exit(void){
printk("jni_exit ...\n");
platform_driver_unregister(&jni_driver);
}
static int jni_init(void){
int err;
printk("jni_init start...\n");
err = platform_driver_register(&jni_driver);
printk("state is %d\n",err);
return ;
}
module_init(jni_init);
module_exit(jni_exit);
通过platform_driver进行注册,然后申明一个platform_driver结构体,在这里要注意!!这里的.name与我们刚开始时在平台文件中的.name必须要一致,否则会注册失败!也就是说内核会自动进行匹配
struct platform_driver jni_driver = {
.probe = jni_probe,
.remove = jni_remove,
.shutdown = jni_shutdown,
.suspend = jni_suspend,
.resume = jni_resume,
.driver = {
.name = "jni",
.owner = THIS_MODULE,
}
};
如果匹配成功,那么会进入驱动的probe函数中,所以一般初始化操作都写在了probe函数中,而不像字符类设备是写在init函数中!
static int jni_probe(struct platform_device *pdv){
int ret,i;
printk("jni_probe start..\n");
for(i=; i<GPIO_NUM; i++)
{
ret = gpio_request(led_gpios[i], "LED");
if (ret < ) {
printk("%s: request GPIO %d for LED failed, ret = %d\n", DEVICE_NAME,i, ret);
}
else{
printk("%s: request GPIO %d for LED success, ret = %d\n", DEVICE_NAME,i, ret);
s3c_gpio_cfgpin(led_gpios[i], S3C_GPIO_OUTPUT);
gpio_set_value(led_gpios[i], );
//gpio_free(led_gpios[i]);
}
}
ret = misc_register(&jni_dev);
if(ret<)
{
printk("jni:register device failed!\n");
goto exit;
}
return ;
exit:
misc_deregister(&jni_dev);
return ret;
}
static int jni_remove(struct platform_device *pdv){
//int i;
printk("jni_remove...\n");
misc_deregister(&jni_dev);
return ;
}
static void jni_shutdown(struct platform_device *pdv){
return ;
}
static int jni_suspend(struct platform_device *pdv,pm_message_t pmt){
return ;
}
static int jni_resume(struct platform_device *pdv){
return ;
}
在probe函数中会请求gpio口,即gpio_request,如果请求失败,那肯定是某个驱动占用了该gpio口,需要手动取消。
然后设置为输出。最后调用杂项设备注册函数misc_register进行注册。
static struct miscdevice jni_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &jni_ops,
};
这里终于出现久违的fops函数了,也就是驱动操作函数。
static struct file_operations jni_ops = {
.owner = THIS_MODULE,
.open = jni_open,
.release = jni_release,
.unlocked_ioctl = jni_ioctl,
};
这里的函数接口就是为上层应用提供啦。
static long jni_ioctl( struct file *files, unsigned int cmd, unsigned long arg){
int ret;
printk("Hello JNI and cmd is %d,arg is %d\n",cmd,arg);
switch(cmd)
{
case :
case :
if (arg > ) {
return -EINVAL;
}
gpio_set_value(led_gpios[arg], cmd);
break;
default:
return -EINVAL;
}
return ;
}
static int jni_release(struct inode *inode, struct file *file){
printk("jni release\n");
return ;
}
static int jni_open(struct inode *inode, struct file *file){
printk("jni open\n");
return nonseekable_open(inode,file);
}
最后附上完整的驱动代码
#include <linux/init.h>
#include <linux/module.h> /*驱动注册的头文件,platform结构体和驱动注册与注销*/
#include <linux/platform_device.h> /*杂项设备头文件*/
#include <linux/miscdevice.h> /*设备节点头文件*/
#include <linux/fs.h> /*Linux中申请GPIO的头文件*/
#include <linux/gpio.h>
/*三星平台的GPIO配置函数头文件*/
/*三星平台EXYNOS系列平台,GPIO配置参数宏定义头文件*/
#include <plat/gpio-cfg.h>
#include <mach/gpio.h>
/*三星平台4412平台,GPIO宏定义头文件*/
#include <mach/gpio-exynos4.h> #include <linux/delay.h> //设备节点
#define DEVICE_NAME "jni"
//匹配项
#define DRIVER_NAME "jni" MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("PNGCUI"); static int led_gpios[] = {
EXYNOS4212_GPJ0(),EXYNOS4212_GPJ0(),
}; #define GPIO_NUM ARRAY_SIZE(led_gpios) static long jni_ioctl( struct file *files, unsigned int cmd, unsigned long arg){
int ret;
printk("Hello JNI and cmd is %d,arg is %d\n",cmd,arg); switch(cmd)
{
case :
case :
if (arg > ) {
return -EINVAL;
}
gpio_set_value(led_gpios[arg], cmd); break; default:
return -EINVAL;
} return ;
} static int jni_release(struct inode *inode, struct file *file){ printk("jni release\n"); return ;
} static int jni_open(struct inode *inode, struct file *file){ printk("jni open\n"); return nonseekable_open(inode,file);
} static struct file_operations jni_ops = {
.owner = THIS_MODULE,
.open = jni_open,
.release = jni_release,
.unlocked_ioctl = jni_ioctl,
}; static struct miscdevice jni_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &jni_ops,
}; static int jni_probe(struct platform_device *pdv){
int ret,i;
printk("jni_probe start..\n"); for(i=; i<GPIO_NUM; i++)
{
ret = gpio_request(led_gpios[i], "LED");
if (ret < ) {
printk("%s: request GPIO %d for LED failed, ret = %d\n", DEVICE_NAME,i, ret);
}
else{
printk("%s: request GPIO %d for LED success, ret = %d\n", DEVICE_NAME,i, ret);
s3c_gpio_cfgpin(led_gpios[i], S3C_GPIO_OUTPUT);
gpio_set_value(led_gpios[i], );
//gpio_free(led_gpios[i]);
}
} ret = misc_register(&jni_dev);
if(ret<)
{
printk("jni:register device failed!\n");
goto exit;
} return ; exit:
misc_deregister(&jni_dev);
return ret;
} static int jni_remove(struct platform_device *pdv){
//int i;
printk("jni_remove...\n"); misc_deregister(&jni_dev); return ;
} static void jni_shutdown(struct platform_device *pdv){ return ;
} static int jni_suspend(struct platform_device *pdv,pm_message_t pmt){ return ;
} static int jni_resume(struct platform_device *pdv){ return ;
} struct platform_driver jni_driver = {
.probe = jni_probe,
.remove = jni_remove,
.shutdown = jni_shutdown,
.suspend = jni_suspend,
.resume = jni_resume,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
}
}; static void jni_exit(void){ printk("jni_exit ...\n"); platform_driver_unregister(&jni_driver); } static int jni_init(void){ int err; printk("jni_init start...\n"); err = platform_driver_register(&jni_driver); printk("state is %d\n",err); return ;
} module_init(jni_init);
module_exit(jni_exit);
linux驱动初探之杂项设备(控制两个GPIO口)的更多相关文章
- Linux驱动设计——字符杂项设备
杂项设备 linux里面的misc杂项设备是主设备号为10的驱动设备,misc设备其实也就是特殊的字符设备,可自动生成设备节点. 定义头文件<linux/miscdevice.h> 杂 ...
- Linux 驱动框架---cdev字符设备驱动和misc杂项设备驱动
字符设备 Linux中设备常见分类是字符设备,块设备.网络设备,其中字符设备也是Linux驱动中最常用的设备类型.因此开发Linux设备驱动肯定是要先学习一下字符设备的抽象的.在内核中使用struct ...
- linux驱动开发之块设备学习笔记
我的博客主要用来存放我的学习笔记,如有侵权,请与我练习,我会立刻删除.学习参考:http://www.cnblogs.com/yuanfang/archive/2010/12/24/1916231.h ...
- linux驱动初探之字符驱动
关键字:字符驱动.动态生成设备节点.helloworld linux驱动编程,个人觉得第一件事就是配置好平台文件,这里以字符设备,也就是传说中的helloworld为例~ 此驱动程序基于linux3. ...
- 迅为4412开发板Linux驱动教程——总线_设备_驱动注册流程详解
本文转自:http://www.topeetboard.com 视频下载地址: 驱动注册:http://pan.baidu.com/s/1i34HcDB 设备注册:http://pan.baidu.c ...
- 迅为4412开发板Linux驱动教程——总线_设备_驱动注冊流程具体解释
视频下载地址: 驱动注冊:http://pan.baidu.com/s/1i34HcDB 设备注冊:http://pan.baidu.com/s/1kTlGkcR 总线_设备_驱动注冊流程具体解释 • ...
- Linux驱动技术(五) _设备阻塞/非阻塞读写
等待队列是内核中实现进程调度的一个十分重要的数据结构,其任务是维护一个链表,链表中每一个节点都是一个PCB(进程控制块),内核会将PCB挂在等待队列中的所有进程都调度为睡眠状态,直到某个唤醒的条件发生 ...
- Linux驱动技术(五) _设备阻塞/非阻塞读写【转】
转自:http://www.cnblogs.com/xiaojiang1025/p/6377925.html 等待队列是内核中实现进程调度的一个十分重要的数据结构,其任务是维护一个链表,链表中每一个节 ...
- 【linux驱动分析】misc设备驱动
misc设备驱动.又称混杂设备驱动. misc设备驱动共享一个设备驱动号MISC_MAJOR.它在include\linux\major.h中定义: #define MISC_MAJO ...
随机推荐
- 《奥威Power-BI智能分析报告制作方法 》精彩回顾
上次课我们简单介绍了奥威Power-BI的智能分析报告,并展示了报告与图表相结合的应用场景.图文分析报表的意义不只在于美观,更重要的是固定框架下的灵活性和追根究底的动态分析,有着很强的实用性.上节课 ...
- selenium and win32api
I:Web 测试 selenium-2.45.0 python 2.7.8 win32api http://sourceforge.net/projects/pywin32/files/pywin32 ...
- 笔记本自带 WiFi 功能
在寝室,动网速基本崩溃.平时打电话什么的都得到阳台,有时候还听不清声音.对于学校的环境,我不说什么了. 笔记本可以上网,那就要满足手机等移动电子设备上网的上网需求. WiFi 热点就显得尤为重要了. ...
- 使用NPOI导入导出标准的Excel
关于NPOI NPOI是POI项目的.NET版本,是由@Tony Qu(http://tonyqus.cnblogs.com/)等大侠基于POI开发的,可以从http://npoi.codeplex. ...
- Plextor 浦科特M7VC性能
浦科特一出TLC的SSD,立刻就受到了人们的关注,网上铺天盖地的评测.看了评测感觉不错,于是买了一块来用. 自己测试,似乎和网上的结果差异挺大的. 这是我自己测试的结果.(测试平台为:I7-5820K ...
- Apple开发者账号简介
苹果对开发者主要分为3类:个人.组织(公司.企业).教育机构.即: 1.个人(Individual) 2.组织(Organizations) 组织类又分为2个小类: (1)公司(Company) (2 ...
- jQuery 选择器 (基础恶补之三)+Ajax
jQuery load() 方法 jQuery load() 方法是简单但强大的 AJAX 方法. load() 方法从服务器加载数据,并把返回的数据放入被选元素中. 语法: $(selector). ...
- osip状态机分析
转载于:http://blog.csdn.net/lbc2100/article/details/48342889 OSIP的核心是系统状态机,在不同情况下,系统处于不同的状态,在某一状态下当系统发生 ...
- 用NULL布局为什么不能显示
import javax.swing.JComboBox;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing. ...
- Unity碰撞器触发关系测试
本文刚体有关的内容不再赘述,主要测试碰撞器和触发器的消息关系. 刚体在这篇有测试:U3D刚体测试1-刚体非刚体物体非Kinematic等之间的碰撞关系 碰撞器测试结果: 1.A对象为Collider, ...