一、驱动代码(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相关推荐

  1. 4412 字符类设备的设备号

    一.静态申请字符类设备号 字符类设备函数在文件"include/linux/fs.h"中 内核提供了三个函数来注册一组字符设备编号,这三个函数分别是 register_chrdev ...

  2. java 正则 u2E80_java正则表达式中的POSIX 字符类和Unicode 块和类别的类介绍

    假如现在有一个需求,要你用java语言来匹配出一个文本里面的所有(英文半角)标点符号,你会怎么写呢?我想大多数人应该是把这些符号都罗列出来, 如: !"#$%&'()*+,-./:; ...

  3. 十五、linux 注册字符类设备和生成节点

    一. 注册字符类设备 • 分配内存空间函数kmalloc         – 分配连续的虚拟地址,用于小内存分配.在include/linux/slab.h文件中.         – 参数1:申请的 ...

  4. 快速解决正则----模糊匹配、字符类、量词

    主体概要 正则表达式是什么 是匹配模式.要么匹配字符.要么匹配位置 内容 掌握字符类和量词就能解决大部分常见正则问题 关键内容:字符组.量词.贪婪.惰性.模糊.横向.纵向.分支.位置 重要的基础   ...

  5. linux grep -11,11个高级Linux字符类和括号表达式的grep命令

    你是否曾经在你需要的一种局面搜索字符串,文字或图案的文件里面呢? 如果是,那么grep工具来在这样的情况下派上用场. grep的是为其匹配一个正则表达式搜索行纯文本数据的命令行实用程序. 如果您将分词 ...

  6. shell中的常用通配符,字符类

    因为 shell 频繁 地使用文件名,shell 提供了特殊字符来帮助你快速指定一组文件名.这些特殊字符叫做通配符. 通配符         意义 * 匹配任意多个字符(包括零个或一个) ? 匹配任意 ...

  7. Java字符类isLowerCase()方法与示例

    字符类isLowerCase()方法 (Character class isLowerCase() method) isLowerCase() method is available in java. ...

  8. Linux驱动(14)--字符类设备与驱动

    字符类设备 1. 静态申请字符类设备号 1.1 所需函数与头文件 1.2 源码与注释 1.3 运行结果 2. 动态申请字符类设备号 2.1 所需函数与头文件 2.2 源码与注释 2.3 运行结果 3. ...

  9. java字符类型的返回值,Java字符类isWhitespace()方法及示例

    Character 类isWhitespace()法isWhitespace()方法在java.lang包中可用. isWhitespace()方法用于检查给定的char值是否为空格,但是它包含空格中 ...

最新文章

  1. 单例测试模式中【饿汉式】与【懒汉式】的区别
  2. gabor小波matlab,用matlab实现gabor小波对图片的纹理特征提取【转】
  3. 中文任务全面超越BERT:百度正式发布NLP预训练模型ERNIE(附项目地址)
  4. redmine 插件开发非官方指南
  5. 微软宣布将于08年发布Centro服务器软件
  6. [Wap]command和selectionList冲突的分析
  7. 进度条(python 实现)
  8. hibernate脏数据_Hibernate性能提示:脏收集效果
  9. 请教哪里有M4A格式解码器
  10. 计算机网络ppt_计算机网络--女娲补天
  11. 自己编译操作系统,安装systemtap
  12. gimp中文版教程_GIMP中文教程.pdf
  13. 《剑指offer》Java版全系列题解(2021版,持续更新!)
  14. 财智V6.0(完美破解序列号特别版)
  15. 毕业生Markdown简历模板
  16. SpringMVC、Struts1和Struts2区别
  17. 神经网络学习小记录64——Pytorch 图像处理中注意力机制的解析与代码详解
  18. Unity鼠标光标使用学习
  19. 51单片机农历转换公历c语言算法,用51单片机实现公历与农历星期的转换
  20. 求最长递增子序列个数——C++

热门文章

  1. 【Nutch2.2.1基础教程之2.1】集成Nutch/Hbase/Solr构建搜索引擎之一:安装及运行【单机环境】...
  2. 微信公众帐号开发教程第1篇-引言(转)
  3. prototype.js常用函数及其用法
  4. python spider code
  5. UA OPTI512R 傅立叶光学导论23 透镜成像系统的物理光学模型
  6. UA MATH565C 随机微分方程V Markov Family的算子
  7. Win32 API 获取其他程序剪贴板内容
  8. Android之NDK开发学习总结
  9. SQL错误提示档案(3):SQL Server连接中的四个最常见错误
  10. java学习记录--ThreadLocal使用案例