驱动(RK3588S)第六课时:linux2.6的使用与GPIO子系统的使用

目录

  • 一、Linux2.6 字符设备驱动编写框架
    • 1、合成一个完整的设备号函数
    • 2、从完整的设备号里提取主设备号
    • 3、动态申请设备号
    • 4、静态申请设备号
    • 5、释放申请的设备号
    • 6、Linux2.6 字符设备驱动的核心结构体
    • 7、初始化核心结构体
    • 8、向内核去申请 linux2.6 字符设备
    • 9、释放申请的设备
    • 10、创建一个类,去管理你注册的设备 /sys/class/name
    • 11、自动创建设备节点
    • 12、销毁类
    • 13、销毁设备节点,节点位于 /dev/name
  • 二、GPIO子系统的使用
    • 1、申请你要使用 gpio 口的资源
    • 2、释放gpio口资源
    • 3、配置 gpio 口的工作模式为输出
    • 4、配置 gpio 口的工作模式为输入
    • 5、配置 gpio 口的工作模式为输入
    • 6、 设置 gpio 的电平状态
  • 三、代码实现

一、Linux2.6 字符设备驱动编写框架

Linux2.6 他是咱们字符设备驱动编写的第二种方法,这种方法要比杂项的复杂,过程和函数是比较多的,他最大的优点就在于他的资源很多 — 设备号,而杂项设备号是非常有限的,也就是 0 — 255 因为主设备号是固定是 10 。但是Linux2.6 他使用一个 32 位的数字表示设备号,这个设备号里包含了主设备号和次设备号,32 位他做一个划分,前 12 位是主设备号,后 20 位是次设备
号,因此他的设备号的取值范围是比较大的。主设备号的范围:2^12 次设备号的范围:2^20, 他使用主设备号和次设备号合成了一个完整的设备号。

1、合成一个完整的设备号函数

函数头文件:#include <linux/cdev.h>
函数参数:
ma: — 主设备号
mi: ---- 次设备号
函数返回值:合成之后的完整的设备号
函数功能:合成一个完整的设备号
函数原型:MKDEV(ma,mi)

2、从完整的设备号里提取主设备号

函数头文件:#include <linux/cdev.h>
函数参数:dev :设备号
函数返回值:提取的主设备,提取的次设备
函数功能:从完整的设备号里提取主设备号
函数原型:MAJOR(dev)
MINOR(dev)

3、动态申请设备号

**函数头文件:#include <linux/fs.h>
函数参数:dev:保存申请成功的设备号
baseminor:次设备号起始值
count:连续申请次设备号的数量
name:设备的名字 — 无所谓
函数返回值:成功返回 0 失败负数
函数功能:动态申请设备号
函数原型:int alloc_chrdev_region(
dev_t dev,
unsigned baseminor,
unsigned count,
const char name)

4、静态申请设备号

*函数功能:静态申请设备号
函数原型:int register_chrdev_region(
dev_t from,
unsigned count,
const char name)
函数头文件:同上
函数参数:from:是你自己提前使用 MKDEV 函数合成一个完整的设备号
count:申请的次设备号的数量
name:设备的名字 — 无所谓
函数返回值:成功返回 0 失败负数

5、释放申请的设备号

函数功能:释放申请的设备号
函数原型:void unregister_chrdev_region(
dev_t from,
unsigned count)
函数头文件:同上
函数参数:from:设备号
count:申请的次设备号的数量
函数返回值:无

6、Linux2.6 字符设备驱动的核心结构体

**这个结构体一般只需要咱们定义一个结构体变量即可。
struct cdev {
struct kobject kobj;
struct module owner;//代表这个模块 THIS_MODULE
const struct file_operations ops;//操作设备集合的方法
struct list_head list;
dev_t dev;//设备号
unsigned int count;//次设备号的数量
} __randomize_layout;

7、初始化核心结构体

**函数功能:初始化核心结构体
函数原型:void cdev_init(
struct cdev cdev,
const struct file_operations fops)
函数头文件:#include<linux/cdev.h>
函数参数:cdev:定义的核心结构体
fops:定义操作设备方法集合的结构体变量
函数返回值:无

8、向内核去申请 linux2.6 字符设备

*函数功能:向内核去申请 linux2.6 字符设备
函数原型:int cdev_add(
struct cdev p,
dev_t dev,
unsigned count)
函数头文件:#include<linux/cdev.h>
函数参数:p:定义的核心结构体
dev:设备号
count:次设备号的数量
函数返回值:成功返回 0 失败负数

9、释放申请的设备

*函数功能:释放申请的设备
函数原型:void cdev_del(struct cdev p)
函数头文件:#include<linux/cdev.h>
函数参数:p:定义的核心结构体
函数返回值:无

10、创建一个类,去管理你注册的设备 /sys/class/name

**函数功能:创建一个类,去管理你注册的设备
函数原型:struct class * class_create(
struct module owner,
const char name)
函数头文件:#include<linux/device.h>
函数参数:owner:他是一个固定的值 THIS_MODULE
name:创建类的名字
函数返回值:成功返回指向 struct class 失败 NULL

11、自动创建设备节点

**函数功能:自动创建设备节点
函数原型:struct device *device_create(
struct class *class,
struct device *parent,
dev_t devt,
void drvdata,
const char fmt,…)
函数头文件:#include<linux/device.h>
函数参数:class:创建的类
parent:父设备 — 写 NULL
devt:设备号
drvdata:内核的私有数据 — 写 NULL
fmt:他一般就是你创建的设备节点的名字
函数返回值:成功返回一个指向 struct device 失败 NULL

12、销毁类

*函数功能:销毁类
函数原型:void class_destroy(struct class cls)
函数头文件:#include<linux/device.h>
函数参数:cls:就是定义的类的变量名
函数返回值:无

13、销毁设备节点,节点位于 /dev/name

*函数功能:销毁设备节点 /dev/name
函数原型:void device_destroy(struct class class,dev_t devt)
函数头文件:#include<linux/device.h>
函数参数:class:定义的类名
devt:设备号

二、GPIO子系统的使用

所谓的 gpio 子系统值的就是使用内核封装好的函数对设备进行操作,这里一般操
作设备都是通过 gpio 口,因此咱们需要掌握操作 gpio 口函数。在使用 GPIO 口区操作硬件的时候,你需要先申请注册才能使用当前的 gpio 口的资源。我以下检测是灯,高电平亮,低电平不亮。
下面演示 GPIO1_D0 pin 脚计算方法:
bank = 1; //GPIO1_D0 => 1, bank ∈ [0,4]
group = 3; //GPIO1_D0 => 3, group ∈ {(A=0), (B=1), (C=2), (D=3)}
X = 0; //GPIO1_D0 => 0, X ∈ [0,7]
number = group * 8 + X = 3 * 8 + 0 = 24
pin = bank*32 + number= 1 * 32 + 24 = 56;
最后要得到的是pin

1、申请你要使用 gpio 口的资源

*函数功能:申请你要使用 gpio 口的资源
函数原型: int gpio_request(unsigned gpio, const char label)
函数头文件:#include <linux/gpio.h>
函数参数:gpio:这里就是你要申请注册的 gpio 口的编号
label:标签 — 一般没有太大作用,就是标识
函数返回值:成功返回 0 失败负数

2、释放gpio口资源

函数功能: 释放 gpio 口资源
函数原型: void gpio_free(unsigned gpio)
函数头文件: #include <linux/gpio.h>
函数参数:gpio:gpio:这里就是你要申请注册的 gpio 口的编号
函数返回值:无

3、配置 gpio 口的工作模式为输出

函数功能:配置 gpio 口的工作模式为输出
函数原型: int gpio_direction_output(unsigned gpio, int value)
函数头文件:#include <linux/gpio.h>
函数参数:gpio:这里就是你要申请注册的 gpio 口的编号
value:默认给的值 — 一般就是 0 或者是 1 代表高低电平
函数返回值:成功返回 0 失败负数

4、配置 gpio 口的工作模式为输入

函数功能: 配置 gpio 口的工作模式为输入
函数原型: int gpio_direction_input(unsigned gpio)
函数头文件:#include <linux/gpio.h>
函数参数:gpio:这里就是你要申请注册的 gpio 口的编号
函数返回值:成功返回 0 失败负数
这里配置的 gpio 口模式为输入和输出那么这里的输入和输出是针对于 CPU 来说的。

5、配置 gpio 口的工作模式为输入

函数功能:获取这个 gpio 口引脚上的电平的状态
函数原型: int gpio_get_value(unsigned gpio)
函数头文件:#include <linux/gpio.h>
函数参数:gpio:这里就是你要申请注册的 gpio 口的编号
函数返回值:返回获取的电平的状态 — 高电平或者是低电平 1/0

6、 设置 gpio 的电平状态

函数功能: 设置 gpio 的电平状态
函数原型: void gpio_set_value(unsigned gpio, int value)
函数头文件:#include <linux/gpio.h>
函数参数:gpio:这里就是你要申请注册的 gpio 口的编号
value:你要设置的电平的状态 — 高电平 1 低电平 0
函数返回值:无

三、代码实现

linux26.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/gpio.h>
dev_t dev;
struct cdev mydev;
struct class *myclass=NULL;
int gpio_value = 0;
int myled_open (struct inode *inode, struct file *fp)
{gpio_set_value(21,1);printk("myled open ok\n");printk("myled open 正确打开\n");return 0;
}int myled_close (struct inode *inode, struct file *fp)
{gpio_set_value(21,0);printk("myled close ok\n");printk("myled close 关闭正确\n");return 0;
}
struct file_operations myfops={.open = myled_open,.release = myled_close,};
static int __init myled_init(void)
{	int all;gpio_value=gpio_request(21, "led5");printk("gpio_value:%d\n",gpio_value);if(gpio_value==0){printk("申请成功\n");}gpio_direction_output(21, 1);all=alloc_chrdev_region(&dev,0, 1,"led");if(all<0){printk("alloc_chrdev_region error\n");printk("动态创建失败\n");return -1;}printk("主设备号:%d\n",MAJOR(dev));printk("次设备号:%d\n",MINOR(dev));cdev_init(&mydev,&myfops);cdev_add(&mydev,dev,1);myclass=class_create(THIS_MODULE,"class_led");if(myclass == NULL){printk("class_create error\n");printk("class_create 类创建失败\n");return -1;}device_create(myclass,NULL,dev,NULL,"myled");return 0;
}
static void __exit myled_exit(void)
{device_destroy(myclass,dev);class_destroy(myclass);cdev_del(&mydev);unregister_chrdev_region(dev,1);gpio_free(21);
}module_init(myled_init);
module_exit(myled_exit);
MODULE_LICENSE("GPL");

app.c

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char *argv[])
{int fd = 0;if(argc < 2){printf("请输入正确的参数\n");return -1;}while(1){fd = open(argv[1],O_RDWR); // --- 底层的open函数sleep(5);close(fd);//底层的closesleep(5);}return 0;
}

Makefile

obj-m += linux26.o #最终生成模块的名字就是 led.ko      KDIR:=/home/stephen/RK3588S/kernel  #他就是你现在rk3588s里内核的路径 CROSS_COMPILE_FLAG=/home/stephen/RK3588S/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-#这是你的交叉编译器路径 --- 这里你也要替换成你自己的交叉编译工具的路径
all:make -C $(KDIR) M=$(PWD) modules ARCH=arm64 CROSS_COMPILE=$(CROSS_COMPILE_FLAG)aarch64-none-linux-gnu-gcc app.c -o app#调用内核层 Makefile 编译目标为 modules->模块 文件在当前路径# 架构  ARCH=arm64 
clean:rm -f  *.o *.mod.o *.mod.c *.symvers *.markers *.order app  *.mod

编译之后将app和linux.ko推送金开发板中。
在这里插入图片描述
开发板中的现象:
在这里插入图片描述
灯现象:
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/416084.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

哈希 详解

目录 1. “哈希”是什么&#xff1f; 2. 哈希冲突 3. 哈希函数 3.1 设计原则 3.2 常见哈希函数 4. 解决哈希冲突的两种常见方法 4.1 闭散列 4.2 开散列 4.3 散列表的扩容问题 5. 哈希表的实现 并 封装模拟实现unordered系列容器 6. 哈希的应用 6.1 位图 -- bitset …

【js逆向专题】2.浏览器调试技巧

小节目标: 熟悉 开发者工具的使用熟悉 代码断点的方式熟悉 网页debugger实现方式 一. 浏览器开发者工具 1. element元素面板 展示浏览器渲染之后的页面 2. network网络面板 浏览器请求的数据都会加载在网络面板 3. console控制台面板 可以在控制台调试你对应的代码 4.…

3000字带你了解SD提示词用法,一点就通,小白轻松上手(附提示词生成器)(1.4 SD提示词运用)

提示词是什么 提示词是我们向AI模型发出的指令。正确的提示词能让AI准确反馈所需的输出&#xff0c;而优质的提示词则能使AI生成的内容更优质、更符合你的期望。这与编写程序代码颇为相似&#xff0c;准确的代码逻辑是程序正常运行的前提&#xff0c;而优秀的代码则能减少运行…

Vue基础概述

Vue框架概述 什么是Vue框架 Vue是一种流行的渐进式JavaScript框架&#xff0c;用于构建Web用户界面。它具有易学、轻量级、灵活性强、高效率等特点&#xff0c;并且可以与其他库和项目集成。是目前最流行的前端框架之一.框架的两种用法: 多页面应用: 在html页面中引入vue.js框…

全倒装共阴节能COB超微小间距LED显示屏主导新型显示技术

COB&#xff08;Chip on Board&#xff09;技术最早发源于上世纪60年代&#xff0c;是将LED芯片直接封装在PCB电路板上&#xff0c;并用特种树脂做整体覆盖。COB实现“点” 光源到“面” 光源的转换。点间距有P0.3、P0.4、P0.5、P0.6、P0.7、P0.9、P1.25、P1.538、P1.5625、P1.…

NanoPC-T6安装redriod笔记

这里主要用于自己对安装过程的记录&#xff0c;中间可能记录比较粗糙。 重新编译内核 参考链接&#xff1a;【环境搭建】基于linux的NanoPC-T6_LTS系统固件编译环境搭建 基于docker构建编译环境 docker run -it \ --privilegedtrue --cap-addALL \ --name nanopc_t6_lts_en…

ESP32!Thonny+MicroPython+ESP32开发环境搭建!!

准备工具&#xff1a; ThonnyMicroPythonESP32 一.Thonny安装 下载地址&#xff1a;Thonny, Python IDE for beginnershttps://thonny.org/ 二.下载esp32环境——根据型号下载 下载地址&#xff1a;MicroPython - Python for microcontrollershttps://micropython.org/dow…

Spring Boot 多数据源配置(JPA)

目录 前言 前置环境 pom yml Entity Dao Config Controller 演示 前言 一般一个系统至少有一个数据源&#xff0c;用来持久化业务数据以及查询。单个数据源的系统很常见&#xff0c;在 Spring Boot 框架下配置也很简单。在约定大于配置这个思想下&#xff0c;只需要在…

vue 中计算属性可以接收参数

代码中的value就是接收的参数 计算属性要接收参数要写在返回的时候 computed: {isButtonDisabled() {return (value) > {const num parseInt(value);return isNaN(num) || num < 0}},},//计算属性aaa(){return (value) >{写逻辑return 返回值}} 使用 <el-butto…

Python OpenCV 深入理解(二)

引言 OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个用于计算机视觉的开源软件库。它提供了大量的图像处理和机器视觉功能&#xff0c;支持多种编程语言&#xff0c;其中Python接口因其易用性和快速原型设计能力而受到广泛欢迎。本文将详细介绍如何…

基于OMS构建OceanBase容灾双活架构的实践

在实际生产环境中&#xff0c;对于关键业务&#xff0c;往往会有容灾双活的需求。除了OceanBase提供的主备库能力&#xff0c;通过官方工具OMS也可以实现容灾双活架构。目前&#xff0c;通过OMS实现的双活架构仅支持OceanBase数据库之间的数据同步。 要通过OMS实现双活架构&am…

合宙LuatOS开发板Core_Air780EP使用说明

Core-Air780EP 开发板是合宙通信推出的基于 Air780EP 模组所开发的&#xff0c; 包含电源&#xff0c;SIM卡&#xff0c;USB&#xff0c;天线&#xff0c;音频等必要功能的最小硬件系统。 以方便用户在设计前期对 Air780EP模块进行性能评估&#xff0c;功能调试&#xff0c;软…

快速学习GO语言总结

干货分享&#xff0c;感谢您的阅读&#xff01;备注&#xff1a;本博客将自己初步学习GO的总结进行分享&#xff0c;希望大家通过本博客可以在短时间内快速掌握GO的基本程序编码能力&#xff0c;如有错误请留言指正&#xff0c;谢谢&#xff01; 一、初步了解Go语言 &#xf…

基于约束大于规范的想法,封装缓存组件

架构&#xff1f;何谓架构&#xff1f;好像并没有一个准确的概念。以前我觉得架构就是搭出一套完美的框架&#xff0c;可以让其他开发人员减少不必要的代码开发量&#xff1b;可以完美地实现高内聚低耦合的准则;可以尽可能地实现用最少的硬件资源&#xff0c;实现最高的程序效率…

职业院校如何建设人工智能实训室

随着人工智能&#xff08;AI&#xff09;技术的快速发展&#xff0c;越来越多的职业院校开始意识到培养具备AI技能的人才的重要性。为了让学生能够在实践中学习&#xff0c;职业院校需要建立能够支持实际操作的人工智能实训室。本文将探讨职业院校应该如何规划和建设一个高效且…

大模型产品经理学习路线,2024最新,从零基础入门到精通,非常详细收藏我这一篇

随着人工智能技术的发展&#xff0c;尤其是大模型&#xff08;Large Model&#xff09;的兴起&#xff0c;越来越多的企业开始重视这一领域的投入。作为大模型产品经理&#xff0c;你需要具备一系列跨学科的知识和技能&#xff0c;以便有效地推动产品的开发、优化和市场化。以下…

《Cloud Native Data Center Networking》(云原生数据中心网络设计)读书笔记 -- 09部署OSPF

本章的目的是帮助网络工程师确定网络的理想 OSPF 配置。本章将回答以下问题 应何时在数据中使用OSPF ?配置 OSPF 的关键设计原则是什么?OSPFv2 和 OSPFv3 之间有什么区别&#xff0c;应如何使用?如何在路由协议栈中配置 OSPF ?如何在服务器上配置 OSPF&#xff0c;例如为容…

Electron 项目实战 03: 实现一个截图功能

实现效果 实现思路 创建两个window&#xff0c;一个叫mainWindow&#xff0c;一个叫cutWindowmainWindow&#xff1a;主界面用来展示截图结果cutWindow&#xff1a;截图窗口&#xff0c;加载截图页面和截图交互逻辑mainWindow 页面点击截图&#xff0c;让cutWIndow 来实现具体…

‌智慧公厕:城市文明的智慧新篇章‌@卓振思众

在日新月异的城市化进程中&#xff0c;公共设施的智能化升级已成为不可逆转的趋势。其中&#xff0c;智慧公厕作为城市智慧化建设的重要组成部分&#xff0c;正悄然改变着我们的生活。智慧公厕&#xff0c;这一融合了物联网、大数据、云计算等现代信息技术的创新产物&#xff0…

Django Admin管理后台导入CSV

修改管理模型&#xff0c;代码如下&#xff1a; class CsvImportForm(forms.Form):csv_file forms.FileField() admin.register(Hero) class HeroAdmin(admin.ModelAdmin, ExportCsvMixin):...change_list_template "entities/heroes_changelist.html"def get_url…