当前位置: 首页 > news >正文

LINUX2.6设备注册与GPIO相关的API

LINUX2.6设备注册与GPIO相关的API

linux2.6 设备注册和杂项设备注册的区别

杂项设备的特点

这种设备注册方法相对来说比较简单

杂项设备的主设备号固定为 10

次设备号 0-255

杂项设备注册成功之后会在/dev 目录下生成设备文件

linux2.6 设备注册的特点

linux2.6 设备注册相对比较复杂

这种设备注册方法比较流行

设备注册完成之后不会生成设备文件

主设备号和次设备号都是没有限制的

主设备号范围

0-2^12

次设备号

0-2^20

linux2.6 设备注册设备号存在的问题

由于主设备号和次设备号都是没有限制的

如果直接的指定主设备号和次设备号会造成

设备号冲突的问题

为了解决设备号存在的问题,在使用设备号的时候

一般不直接指定 而是借助于内核提供的函数来来向内核申请

linux2.6 的设备号的申请

函数的功能

向内核申请一个设备号

函数的头文件

linux/fs.h

函数的原型

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)

函数的参数

dev_t *dev, 用来存放申请到的设备号的缓冲区

unsigned baseminor, 次设备号起始的位置

unsigned count, 要申请的设备号的个数

const char *name 设备号的名字 /proc/devices 文件里

函数的返回值

成功返回 0

失败返回 -1

linux2.6 设备注册相关的 API

cdev_init函数的功能

初始化一个 linux2.6 的核心结构体

函数的头文件

linux/cdev.h

函数的原型

void cdev_init(struct cdev *cdev, const struct file_operations *fops)

函数的参数

struct cdev *cdev, linux2.6 的核心结构体

const struct file_operations *fops 操作集合结构体

函数的返回值

cdev_add函数的功能

向内核注册一个 linux2.6 的核心结构体

函数的头文件

linux/cdev.h

函数的原型

int cdev_add(struct cdev *p, dev_t dev, unsigned count)

函数的参数

struct cdev *p, linux2.6 的核心结构体指针

dev_t dev, 设备号

unsigned count 要注册的 linux2.6 的设备的个数 1

函数的返回值

成功返回 0

失败返回 -1

cdev_del函数的功能

取消 linux2.6 的设备的注册

函数的头文件

linux/cdev.h

函数的原型

void cdev_del(struct cdev *p)

函数的参数

struct cdev *p:linux2.6 的核心结构体

函数的返回值

自动生成设备文件

通过验证可知 linux2.6 设备注册成功以后不会自动的生成设备文件,不能生成设备文件就会导致别的程序无法使用这个驱动,为了解决这个问题,就需要搞定驱动对应的设备文件,生成设备文件的方法主要有两种

手动生成

需要在终端执行命令

在执行命令之前需要了解主设备号和次设备号

执行如下指令

mknod /dev/myled c 234 0

借助于内核提供的 api 来实现自动的生成设备文件

在自动生成设备文件的时候需要使用一个类结构体,这个类结构体申请需要借助于内核提供的函数

class_create函数的功能

创建一个类结构体

函数的头文件

linux/device.h

函数的原型

struct class * class_create(struct module *owner, const char *name)

函数的参数

struct module *owner, 模块

const char *name 类结构体的名字

函数的返回值

成功返回 类结构体的指针

失败返回 NULL

ps:

类结构体是可以复用的

class_destroy函数的功能

销毁类结构体

函数的头文件

linux/device.h

函数的原型

void class_destroy(struct class *cls)

函数的参数

struct class *cls:类结构体的指针

函数的返回值

device_create函数的功能

自动生成设备文件

函数的头文件

linux/device.h

函数的原型

struct device *device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...)

函数的参数

struct class *class, 类结构体指针

struct device *parent, 父节点的信息 NULL

dev_t devt, 设备号

void *drvdata, 私有数据 NULL

const char *fmt, … 设备名 会出现在/dev 目录下

函数的返回值

成功返回 设备的结构体指针

失败返回 NULL

device_destroy函数的功能

销毁设备文件

函数的头文件

linux/device.h

函数的原型

void device_destroy(struct class *class, dev_t devt)

函数的参数

struct class *class, 类结构体指针

dev_t devt 设备号

函数的返回值

linux2.6 设备注册的总结

注册的流程

申请设备号

初始化 linux2.6 的核心结构体

向内核注册一个 linux2.6 的核心结构体

创建类结构体

使用类结构体创建设备文件

取消注册的流程

销毁设备

销毁类结构体

取消 linux2.6 的设备注册

实例

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>dev_t mydev;
struct cdev mycdev;
struct file_operations myfops;
struct class * myclass=NULL;
struct device * mydevice=NULL;int myopen (struct inode *inode, struct file * file)
{printk("打开\n");return 0;
}
int myclose (struct inode *inode, struct file * file)
{printk("关闭\n");return 0;
}static int __init myled_init(void)
{//1申请设备号alloc_chrdev_region(&mydev, 0, 1, "myled");printk("设备号:%d\n",mydev);printk("主设备号:%d\n",(mydev >> 20));printk("次设备号:%d\n",(mydev)&0xFFFFF);//2初始化linux2.6核心结构体myfops.owner = THIS_MODULE;myfops.open = myopen;myfops.release = myclose;cdev_init(&mycdev, &myfops);//3向内核注册linux2.6核心结构体cdev_add(&mycdev, mydev, 1);//创建类结构体myclass=class_create(THIS_MODULE,"myled");//创建设备mydevice=device_create(myclass, NULL,mydev,NULL, "myled");return 0;
}static void __exit myled_exit(void)
{//销毁设备文件device_destroy(myclass, mydev);//取消类结构体class_destroy(myclass);//取消Linux2.6的注册cdev_del(&mycdev);
}module_init(myled_init);
module_exit(myled_exit);
MODULE_LICENSE("GPL");

应用层

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int fd;
int main()
{while(1){fd=open("/dev/myled",O_RDWR);sleep(1);close(fd);sleep(1);}return 0;
}

gpio 子系统相关的 API

gpio函数

gpio_request函数的功能

申请一个 GPIO 口

函数的头文件

linux/gpio.h

函数的原型

int gpio_request(unsigned gpio, const char *label);

函数的参数

unsigned gpio, gpio 口引脚的编号

const char *label 标签

函数的返回值

成功返回 0

失败返回 -1

gpio_direction_output函数的功能

设置 gpio 口的工作模式为输出

函数的头文件

linux/gpio.h

函数的原型

int gpio_direction_output(unsigned gpio, int value)

函数的参数

unsigned gpio, gpio 口引脚的编号

int value 默认的输出的值 一般是有效电平取反

函数的返回值

成功返回 0

失败返回 -1

gpio_direction_input函数的功能

设置 gpio 口引脚的工作模式为输入

函数的头文件

linux/gpio.h

函数的原型

int gpio_direction_input(unsigned gpio)

函数的参数

unsigned gpio:gpio 口引脚的编号

函数的返回值

成功返回 0

失败返回 -1

gpio_set_value函数的功能

设置 gpio 口引脚的值

函数的头文件

linux/gpio.h

函数的原型

void gpio_set_value(unsigned gpio, int value)

函数的参数

unsigned gpio, gpio 口引脚的编号

int value 要设置的值

函数的返回值

gpio_get_value函数的功能

获取 gpio 口引脚的值

函数的头文件

linux/gpio.h

函数的原型

int gpio_get_value(unsigned gpio)

函数的参数

unsigned gpio:gpio 引脚的编号

函数的返回值

成功返回 引脚值

实例

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/gpio.h>dev_t mydev;
struct cdev mycdev;
struct file_operations myfops;
struct class * myclass=NULL;
struct device * mydevice=NULL;int myopen (struct inode *inode, struct file * file)
{
//GPIO1_A4 1*32+A-A +4printk("打开\n");gpio_set_value(21, 1);gpio_set_value(22, 1);gpio_set_value(36, 1);return 0;
}
int myclose (struct inode *inode, struct file * file)
{printk("关闭\n");gpio_set_value(21, 0);gpio_set_value(22, 0);gpio_set_value(36, 0);return 0;
}static int __init myled_init(void)
{gpio_request(21, "led21");gpio_request(22, "led22");gpio_request(36, "beep");gpio_direction_output(21, 0);gpio_direction_output(22, 0);gpio_direction_output(36, 0);//1申请设备号alloc_chrdev_region(&mydev, 0, 1, "myled");printk("设备号:%d\n",mydev);printk("主设备号:%d\n",(mydev >> 20));printk("次设备号:%d\n",(mydev)&0xFFFFF);//2初始化linux2.6核心结构体myfops.owner = THIS_MODULE;myfops.open = myopen;myfops.release = myclose;cdev_init(&mycdev, &myfops);//3向内核注册linux2.6核心结构体cdev_add(&mycdev, mydev, 1);//创建类结构体myclass=class_create(THIS_MODULE,"myled");//创建设备mydevice=device_create(myclass, NULL,mydev,NULL, "myled");return 0;
}static void __exit myled_exit(void)
{//销毁设备文件device_destroy(myclass, mydev);//取消类结构体class_destroy(myclass);//取消Linux2.6的注册cdev_del(&mycdev);
}module_init(myled_init);
module_exit(myled_exit);
MODULE_LICENSE("GPL");
http://www.lryc.cn/news/578444.html

相关文章:

  • FFmpeg 中./configure的解析
  • Linux基本命令篇 —— bc命令
  • 微软服务器安全问题
  • 【蓝牙】Linux Qt4查看已经配对的蓝牙信息
  • MCP 协议使用核心讲解
  • HDMI2.1 FRL流控 概览
  • 基于OPUS-MT模型的中译英程序实现
  • swing音频输入
  • Vue 安装使用教程
  • 【机器学习深度学习】模型微调的基本概念与流程
  • 动手实践:如何提取Python代码中的字符串变量的值
  • QA - RAG智能问答系统中的文档切片与实现原理
  • 深入金融与多模态场景实战:金融文档分块技术与案例汇总
  • 打造可观测的 iOS CICD 流程:调试、追踪与质量保障全记录
  • python下划线开头函数总结
  • 服务器安装 ros2时遇到底层库依赖冲突的问题
  • Crystaldiskinfo查询的硬盘参数信息
  • 2.3.1 Nginx Web服务器安全加固
  • 基于Pandas和FineBI的昆明职位数据分析与可视化实现(四)- 职位数据可视化(FineBI)
  • 【开源项目】一款真正可修改视频MD5工具视频质量不损失
  • Python 数据分析:numpy,抽提,布尔索引2。
  • github代码中遇到的问题-解决方案
  • 【C++】备忘录模式
  • mini-electron使用方法
  • 时空数据挖掘五大革新方向详解篇!
  • 多探头分布式雷达测流系统解决方案概述
  • HakcMyVM-Arroutada
  • 软考中级【网络工程师】第6版教材 第1章 计算机网络概述
  • CompletableFuture源码分析
  • Android 网络全栈攻略(四)—— TCPIP 协议族与 HTTPS 协议