十七、字符类 GPIOS
一、驱动代码(char_driver_leds.c)
/*包含初始化宏定义的头文件,代码中的module_init和module_exit在此文件中*/
#include <linux/init.h>
/*包含初始化加载模块的头文件,代码中的MODULE_LICENSE在此头文件中*/
#include <linux/module.h>
/*定义module_param module_param_array的头文件*/
#include <linux/moduleparam.h>
/*定义module_param module_param_array中perm的头文件*/
#include <linux/stat.h>
/*三个字符设备函数*/
#include <linux/fs.h>
/*MKDEV转换设备号数据类型的宏定义*/
#include <linux/kdev_t.h>
/*定义字符设备的结构体*/
#include <linux/cdev.h>
/*分配内存空间函数头文件*/
#include <linux/slab.h>
/*包含函数device_create 结构体class等头文件*/
#include <linux/device.h>/*自定义头文件*/
#include "char_driver_leds.h"/*Linux中申请GPIO的头文件*/
#include <linux/gpio.h>
/*三星平台的GPIO配置函数头文件*/
/*三星平台EXYNOS系列平台,GPIO配置参数宏定义头文件*/
#include <plat/gpio-cfg.h>
/*三星平台4412平台,GPIO宏定义头文件*/
#include <mach/gpio-exynos4.h>MODULE_LICENSE("Dual BSD/GPL");
/*声明是开源的,没有内核版本限制*/
MODULE_AUTHOR("iTOPEET_dz");
/*声明作者*/static int led_gpios[] = {EXYNOS4_GPL2(0),EXYNOS4_GPK1(1),
};
#define LED_NUM ARRAY_SIZE(led_gpios)int numdev_major = DEV_MAJOR;
int numdev_minor = DEV_MINOR;/*输入主设备号*/
module_param(numdev_major,int,S_IRUSR);
/*输入次设备号*/
module_param(numdev_minor,int,S_IRUSR);static struct class *myclass;
struct reg_dev *my_devices;/*打开操作*/
static int chardevnode_open(struct inode *inode, struct file *file){printk(KERN_EMERG "chardevnode_open is success!\n");return 0;
}
/*关闭操作*/
static int chardevnode_release(struct inode *inode, struct file *file){printk(KERN_EMERG "chardevnode_release is success!\n");return 0;
}
/*IO操作*/
static long chardevnode_ioctl(struct file *file, unsigned int cmd, unsigned long arg){switch(cmd){case 0:case 1:if (arg > LED_NUM) {return -EINVAL;}gpio_set_value(led_gpios[arg], cmd);break;default:return -EINVAL;}printk(KERN_EMERG "chardevnode_ioctl is success! cmd is %d,arg is %d \n",cmd,arg);return 0;
}ssize_t chardevnode_read(struct file *file, char __user *buf, size_t count, loff_t *f_ops){return 0;
}ssize_t chardevnode_write(struct file *file, const char __user *buf, size_t count, loff_t *f_ops){return 0;
}loff_t chardevnode_llseek(struct file *file, loff_t offset, int ence){return 0;
}
struct file_operations my_fops = {.owner = THIS_MODULE,.open = chardevnode_open,.release = chardevnode_release,.unlocked_ioctl = chardevnode_ioctl,.read = chardevnode_read,.write = chardevnode_write,.llseek = chardevnode_llseek,
};/*设备注册到系统*/
static void reg_init_cdev(struct reg_dev *dev,int index){int err;int devno = MKDEV(numdev_major,numdev_minor+index);/*数据初始化*/cdev_init(&dev->cdev,&my_fops);dev->cdev.owner = THIS_MODULE;dev->cdev.ops = &my_fops;/*注册到系统*/err = cdev_add(&dev->cdev,devno,1);if(err){printk(KERN_EMERG "cdev_add %d is fail! %d\n",index,err);}else{printk(KERN_EMERG "cdev_add %d is success!\n",numdev_minor+index);}
}static int gpio_init(void){int i=0,ret;for(i=0;i<LED_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);return -1;}else{s3c_gpio_cfgpin(led_gpios[i], S3C_GPIO_OUTPUT);gpio_set_value(led_gpios[i], 1); }}return 0;
}static int scdev_init(void)
{int ret = 0,i;dev_t num_dev;printk(KERN_EMERG "numdev_major is %d!\n",numdev_major);printk(KERN_EMERG "numdev_minor is %d!\n",numdev_minor);if(numdev_major){num_dev = MKDEV(numdev_major,numdev_minor);ret = register_chrdev_region(num_dev,DEVICE_MINOR_NUM,DEVICE_NAME);}else{/*动态注册设备号*/ret = alloc_chrdev_region(&num_dev,numdev_minor,DEVICE_MINOR_NUM,DEVICE_NAME);/*获得主设备号*/numdev_major = MAJOR(num_dev);printk(KERN_EMERG "adev_region req %d !\n",numdev_major);}if(ret<0){printk(KERN_EMERG "register_chrdev_region req %d is failed!\n",numdev_major); }myclass = class_create(THIS_MODULE,DEVICE_NAME);my_devices = kmalloc(DEVICE_MINOR_NUM * sizeof(struct reg_dev),GFP_KERNEL);if(!my_devices){ret = -ENOMEM;goto fail;}memset(my_devices,0,DEVICE_MINOR_NUM * sizeof(struct reg_dev));/*设备初始化*/for(i=0;i<DEVICE_MINOR_NUM;i++){my_devices[i].data = kmalloc(REGDEV_SIZE,GFP_KERNEL);memset(my_devices[i].data,0,REGDEV_SIZE);/*设备注册到系统*/reg_init_cdev(&my_devices[i],i);/*创建设备节点*/device_create(myclass,NULL,MKDEV(numdev_major,numdev_minor+i),NULL,DEVICE_NAME"%d",i);}ret = gpio_init();if(ret){printk(KERN_EMERG "gpio_init failed!\n");} printk(KERN_EMERG "scdev_init!\n");/*打印信息,KERN_EMERG表示紧急信息*/return 0;fail:/*注销设备号*/unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);printk(KERN_EMERG "kmalloc is fail!\n");return ret;
}static void scdev_exit(void)
{int i;printk(KERN_EMERG "scdev_exit!\n");/*除去字符设备*/for(i=0;i<DEVICE_MINOR_NUM;i++){cdev_del(&(my_devices[i].cdev));/*摧毁设备节点函数d*/device_destroy(myclass,MKDEV(numdev_major,numdev_minor+i));}/*释放设备class*/class_destroy(myclass);/*释放内存*/kfree(my_devices);/*释放GPIO*/for(i=0;i<LED_NUM;i++){gpio_free(led_gpios[i]);}unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);
}module_init(scdev_init);
/*初始化函数*/
module_exit(scdev_exit);
/*卸载函数*/
char_driver_leds.h
#ifndef _CHAR_DRIVER_LEDS_H_
#define _CHAR_DRIVER_LEDS_H_#ifndef DEVICE_NAME
#define DEVICE_NAME "chardevnode"
#endif#ifndef DEVICE_MINOR_NUM
#define DEVICE_MINOR_NUM 2
#endif#ifndef DEV_MAJOR
#define DEV_MAJOR 0
#endif#ifndef DEV_MINOR
#define DEV_MINOR 0
#endif#ifndef REGDEV_SIZE
#define REGDEV_SIZE 3000
#endifstruct reg_dev
{char *data;unsigned long size;struct cdev cdev;
};
#endif
二、Makefile
#!/bin/bash
#通知编译器我们要编译模块的哪些源码
#这里是编译itop4412_hello.c这个文件编译成中间文件mini_linux_module.o
obj-m += char_driver_leds.o #源码目录变量,这里用户需要根据实际情况选择路径
#作者是将Linux的源码拷贝到目录/home/topeet/android4.0下并解压的
KDIR := /home/topeet/android4.0/iTop4412_Kernel_3.0#当前目录变量
PWD ?= $(shell pwd)#make命名默认寻找第一个目标
#make -C就是指调用执行的路径
#$(KDIR)Linux源码目录,作者这里指的是/home/topeet/android4.0/iTop4412_Kernel_3.0
#$(PWD)当前目录变量
#modules要执行的操作
all:make -C $(KDIR) M=$(PWD) modules#make clean执行的操作是删除后缀为o的文件
clean:rm -rf *.mod.c *.o *.order *.ko *.mod.o *.symvers
三、应用程序(invoke_char_gpios.c)
编译:arm-none-linux-gnueabi-gcc -o invoke_char_gpios invoke_char_gpios.c - static
#include <stdio.h>#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>/*argv[1] is cmd , argv[2] is io_arg*/
int main(int argc , char **argv){int fd;char *lednode = "/dev/chardevnode0";/*O_RDWR只读打开,O_NDELAY非阻塞方式*/ if((fd = open(lednode,O_RDWR|O_NDELAY))<0){printf("APP open %s failed!\n",lednode);}else{printf("APP open %s success!\n",lednode);ioctl(fd,atoi(argv[1]),atoi(argv[2]));printf("APP ioctl %s ,cmd is %s! io_arg is %s!\n",lednode,argv[1],argv[2]);}close(fd);
}
四、运行效果
十七、字符类 GPIOS相关推荐
- 4412 字符类设备的设备号
一.静态申请字符类设备号 字符类设备函数在文件"include/linux/fs.h"中 内核提供了三个函数来注册一组字符设备编号,这三个函数分别是 register_chrdev ...
- java 正则 u2E80_java正则表达式中的POSIX 字符类和Unicode 块和类别的类介绍
假如现在有一个需求,要你用java语言来匹配出一个文本里面的所有(英文半角)标点符号,你会怎么写呢?我想大多数人应该是把这些符号都罗列出来, 如: !"#$%&'()*+,-./:; ...
- 十五、linux 注册字符类设备和生成节点
一. 注册字符类设备 • 分配内存空间函数kmalloc – 分配连续的虚拟地址,用于小内存分配.在include/linux/slab.h文件中. – 参数1:申请的 ...
- 快速解决正则----模糊匹配、字符类、量词
主体概要 正则表达式是什么 是匹配模式.要么匹配字符.要么匹配位置 内容 掌握字符类和量词就能解决大部分常见正则问题 关键内容:字符组.量词.贪婪.惰性.模糊.横向.纵向.分支.位置 重要的基础 ...
- linux grep -11,11个高级Linux字符类和括号表达式的grep命令
你是否曾经在你需要的一种局面搜索字符串,文字或图案的文件里面呢? 如果是,那么grep工具来在这样的情况下派上用场. grep的是为其匹配一个正则表达式搜索行纯文本数据的命令行实用程序. 如果您将分词 ...
- shell中的常用通配符,字符类
因为 shell 频繁 地使用文件名,shell 提供了特殊字符来帮助你快速指定一组文件名.这些特殊字符叫做通配符. 通配符 意义 * 匹配任意多个字符(包括零个或一个) ? 匹配任意 ...
- Java字符类isLowerCase()方法与示例
字符类isLowerCase()方法 (Character class isLowerCase() method) isLowerCase() method is available in java. ...
- Linux驱动(14)--字符类设备与驱动
字符类设备 1. 静态申请字符类设备号 1.1 所需函数与头文件 1.2 源码与注释 1.3 运行结果 2. 动态申请字符类设备号 2.1 所需函数与头文件 2.2 源码与注释 2.3 运行结果 3. ...
- java字符类型的返回值,Java字符类isWhitespace()方法及示例
Character 类isWhitespace()法isWhitespace()方法在java.lang包中可用. isWhitespace()方法用于检查给定的char值是否为空格,但是它包含空格中 ...
最新文章
- 单例测试模式中【饿汉式】与【懒汉式】的区别
- gabor小波matlab,用matlab实现gabor小波对图片的纹理特征提取【转】
- 中文任务全面超越BERT:百度正式发布NLP预训练模型ERNIE(附项目地址)
- redmine 插件开发非官方指南
- 微软宣布将于08年发布Centro服务器软件
- [Wap]command和selectionList冲突的分析
- 进度条(python 实现)
- hibernate脏数据_Hibernate性能提示:脏收集效果
- 请教哪里有M4A格式解码器
- 计算机网络ppt_计算机网络--女娲补天
- 自己编译操作系统,安装systemtap
- gimp中文版教程_GIMP中文教程.pdf
- 《剑指offer》Java版全系列题解(2021版,持续更新!)
- 财智V6.0(完美破解序列号特别版)
- 毕业生Markdown简历模板
- SpringMVC、Struts1和Struts2区别
- 神经网络学习小记录64——Pytorch 图像处理中注意力机制的解析与代码详解
- Unity鼠标光标使用学习
- 51单片机农历转换公历c语言算法,用51单片机实现公历与农历星期的转换
- 求最长递增子序列个数——C++
热门文章
- 【Nutch2.2.1基础教程之2.1】集成Nutch/Hbase/Solr构建搜索引擎之一:安装及运行【单机环境】...
- 微信公众帐号开发教程第1篇-引言(转)
- prototype.js常用函数及其用法
- python spider code
- UA OPTI512R 傅立叶光学导论23 透镜成像系统的物理光学模型
- UA MATH565C 随机微分方程V Markov Family的算子
- Win32 API 获取其他程序剪贴板内容
- Android之NDK开发学习总结
- SQL错误提示档案(3):SQL Server连接中的四个最常见错误
- java学习记录--ThreadLocal使用案例