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 ...
随机推荐
- 使用Mod_JK链接Apache和Tomcat
There are many potential problems associated with the default configuration of mod_jk. Let's say it ...
- Python开发【杂货铺】:五个知识点搞定作用域
1.块级作用域 想想此时运行下面的程序会有输出吗?执行会成功吗? #块级作用域 if 1 == 1: name = "lzl" print(name) for i in range ...
- Nginx基础整理
目录结构如下: Nginx基础知识 Nginx HTTP服务器的特色及优点 Nginx的主要企业功能 Nginx作为web服务器的主要应用场景包括: Nginx的安装 安装环境 快速安装命令集合 各个 ...
- cocoa pods报错The dependency `Reveal-iOS-SDK` is not used in any concrete target.
Podfile错误写法,会报错The dependency `Reveal-iOS-SDK` is not used in any concrete target. platform:ios,'7.0 ...
- Communication 交流
1:请不要立马抗拒别人的观点,先沉默下来思考,在做出回应. 2:在与别人交流的时候,请尽量先让别人同意你的观点,找到共同点,让别人回答 "是";
- 夺命雷公狗-----React---8--react官方提供的组建实现双向绑定
首先要引入她.. <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...
- WEB三层架构与MVC
web三层架构是指: >用户接口层(UI Layer) >业务逻辑层(Bussiness Layer) >持久化层 关于业务逻辑和用户接口 在早期的web开发中,因为业务比较简单,并 ...
- Spark实战3:Maven_Java_HelloWorld
Spark独立开发应用( Java语言) 1 创建SimpleApp.java文件: /* SimpleApp.java */ import org.apache.spark.api.java.*; ...
- python脚本利用windows计划定时执行
- JSON 格式说明
一维json { "sn" : "CS20160918095444121640", "suitstypes_id" : "47&q ...