linux驱动:6ull(3)自动分配设备号来创建led驱动
在 linux驱动:6ull(2)的文章代码上进行更改
步骤:
- 创建入口函数和出口函数
- 定义一个设备结构体和创建一个led设备
- 在入口函数init中添加初始化led的gpio
- 在入口函数init中添加自动分配设备号来创建led字符设备
- 在出口函数中取消led的gpio映射、注销设备号和销毁字符设备
- 在写操作函数中读取应用传入的参数,判断参数控制灯,写对应的寄存器
- 写一个读写驱动的代码测试
- 测试
- modprobe newchrled.ko
- cat /proc/devices 来查看分配出来的主设备号
- mknod /dev/newchrled c xxx 0 一般是不需要 这一步,因为已经自动创建了
- /a.out /dev/newchrled 0
- /a.out /dev/newchrled 1
- rmmod newchrled.ko
代码:
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>#include <linux/device.h>
#include <linux/cdev.h>#define NEWCHRLED_CNT 1 /* 设备号个数 */
#define NEWCHRLED_NAME "newchrled" /* 名字 */
#define LEDOFF 0 /* 关灯 */
#define LEDON 1 /* 开灯 *//* 寄存器物理地址 */
#define CCM_CCGR1_BASE (0X020C406C)
#define SW_MUX_GPIO1_IO03_BASE (0X020E0068)
#define SW_PAD_GPIO1_IO03_BASE (0X020E02F4)
#define GPIO1_DR_BASE (0X0209C000)
#define GPIO1_GDIR_BASE (0X0209C004)/* newchrled设备结构体 */
struct newchrled_dev{dev_t devid; /* 设备号 */struct cdev cdev; /* cdev */struct class *class; /* 类 */struct device *device; /* 设备 */int major; /* 主设备号 */int minor; /* 次设备号 */
};struct newchrled_dev newchrled; /* led设备 *//* 映射后的寄存器虚拟地址指针 */
static void __iomem *IMX6U_CCM_CCGR1;
static void __iomem *SW_MUX_GPIO1_IO03;
static void __iomem *SW_PAD_GPIO1_IO03;
static void __iomem *GPIO1_DR;
static void __iomem *GPIO1_GDIR;// LED打开/关闭
void led_switch(u8 sta)
{u32 val = 0;if(sta == LEDON) {val = readl(GPIO1_DR);val &= ~(1 << 3); writel(val, GPIO1_DR);}else if(sta == LEDOFF) {val = readl(GPIO1_DR);val|= (1 << 3); writel(val, GPIO1_DR);}
}// 打开设备
static int led_open(struct inode *inode, struct file *filp)
{filp->private_data = &newchrled; /* 设置私有数据 */return 0;
}// 从设备读取数据
static ssize_t led_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{return 0;
}// 向设备写数据
static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{int retvalue;unsigned char databuf[1];unsigned char ledstat;retvalue = copy_from_user(databuf, buf, cnt);if(retvalue < 0) {printk("kernel write failed!\r\n");return -EFAULT;}ledstat = databuf[0]; /* 获取状态值 */if(ledstat == LEDON) { led_switch(LEDON); /* 打开LED灯 */} else if(ledstat == LEDOFF) {led_switch(LEDOFF); /* 关闭LED灯 */}return 0;
}// 关闭/释放设备
static int led_release(struct inode *inode, struct file *filp)
{return 0;
}/* 设备操作函数 */
static struct file_operations led_fops = {.owner = THIS_MODULE,.open = led_open,.read = led_read,.write = led_write,.release = led_release,
};static int __init led_init(void)
{int retvalue = 0;u32 val = 0;/* 初始化LED */// 1、寄存器地址映射 IMX6U_CCM_CCGR1 = ioremap(CCM_CCGR1_BASE, 4);SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_GPIO1_IO03_BASE, 4);SW_PAD_GPIO1_IO03 = ioremap(SW_PAD_GPIO1_IO03_BASE, 4);GPIO1_DR = ioremap(GPIO1_DR_BASE, 4);GPIO1_GDIR = ioremap(GPIO1_GDIR_BASE, 4);// 2、使能GPIO1时钟 val = readl(IMX6U_CCM_CCGR1);val &= ~(3 << 26); /* 清楚以前的设置 */val |= (3 << 26); /* 设置新值 */writel(val, IMX6U_CCM_CCGR1);// 3、设置GPIO1_IO03的复用功能writel(5, SW_MUX_GPIO1_IO03);/*寄存器SW_PAD_GPIO1_IO03设置IO属性*bit 16:0 HYS关闭*bit [15:14]: 00 默认下拉*bit [13]: 0 kepper功能*bit [12]: 1 pull/keeper使能*bit [11]: 0 关闭开路输出*bit [7:6]: 10 速度100Mhz*bit [5:3]: 110 R0/6驱动能力*bit [0]: 0 低转换率*/writel(0x10B0, SW_PAD_GPIO1_IO03);// 4、设置GPIO1_IO03为输出功能 val = readl(GPIO1_GDIR);val &= ~(1 << 3); /* 清除以前的设置 */val |= (1 << 3); /* 设置为输出 */writel(val, GPIO1_GDIR);/* 5、默认关闭LED */val = readl(GPIO1_DR);val |= (1 << 3); writel(val, GPIO1_DR);/* 6、注册字符设备驱动 *//* 7、创建设备号 */if (newchrled.major) { /* 定义了设备号 */newchrled.devid = MKDEV(newchrled.major, 0);register_chrdev_region(newchrled.devid, NEWCHRLED_CNT, NEWCHRLED_NAME);} else { /* 没有定义设备号 */alloc_chrdev_region(&newchrled.devid, 0, NEWCHRLED_CNT, NEWCHRLED_NAME); /* 申请设备号 */newchrled.major = MAJOR(newchrled.devid); /* 获取分配号的主设备号 */newchrled.minor = MINOR(newchrled.devid); /* 获取分配号的次设备号 */}printk("newcheled major=%d,minor=%d\r\n",newchrled.major, newchrled.minor); /* 8、初始化cdev 也就是添加文件操作集到 cdev*/newchrled.cdev.owner = THIS_MODULE; // 将 cdev 结构的 owner 字段设置为当前模块,确保模块在使用期间不会被卸载cdev_init(&newchrled.cdev, &newchrled_fops);/* 9、将初始化好的 cdev 结构添加到内核中,使其成为系统中有效的字符设备*/// cdev_add 函数将 cdev 与设备号 (newchrled.devid) 以及设备数量 (NEWCHRLED_CNT) 关联起来cdev_add(&newchrled.cdev, newchrled.devid, NEWCHRLED_CNT);/* 10、使用 class_create 函数创建一个设备类 */// 设备类用于在 /sys/class/ 下创建相应的目录结构,便于用户空间识别和管理设备newchrled.class = class_create(THIS_MODULE, NEWCHRLED_NAME);if (IS_ERR(newchrled.class)) {return PTR_ERR(newchrled.class);}/* 11、使用 device_create 在 /dev 目录下创建设备节点 *//*newchrled.class:设备所属的类 NULL:父设备newchrled.devid:设备号 NULL:设备的私有数据NEWCHRLED_NAME:设备名称 /dev/NEWCHRLED_NAME*/newchrled.device = device_create(newchrled.class, NULL, newchrled.devid, NULL, NEWCHRLED_NAME);if (IS_ERR(newchrled.device)) {return PTR_ERR(newchrled.device);}
}static void __exit led_exit(void)
{/* 取消映射 */iounmap(IMX6U_CCM_CCGR1);iounmap(SW_MUX_GPIO1_IO03);iounmap(SW_PAD_GPIO1_IO03);iounmap(GPIO1_DR);iounmap(GPIO1_GDIR);/* 注销字符设备驱动 */// 删除cdevcdev_del(&newchrled.cdev);// 注销字符设备号unregister_chrdev(LED_MAJOR, LED_NAME);// 销毁设备节点device_destroy(newchrled.class, newchrled.devid);// 销毁设备类class_destroy(newchrled.class);
}module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
相关文章:
linux驱动:6ull(3)自动分配设备号来创建led驱动
在 linux驱动:6ull(2)的文章代码上进行更改 步骤: 创建入口函数和出口函数定义一个设备结构体和创建一个led设备在入口函数init中添加初始化led的gpio在入口函数init中添加自动分配设备号来创建led字符设备在出口函数中取消led的…...

GM_T 0039《密码模块安全检测要求》题目
单项选择题 根据GM/T 0039《密码模块安全检测要求》,送检单位的密码模块应包括()密码主管角色。 A.一个 B.两个 C.至少一个 D.至少两个 正确答案:C 多项选择题 根据GM/T 0039《密码模块安全检测要求》,关于非入侵式安全,以下属于安全三级密码模块要求的是()。 …...

第四届电气工程与控制科学
重要信息 官网:www.ic2ecs.com 时间:2024年12月27-29日 简介 第四届电气工程与控制科学定于2024年12月27-29日在中国南京召开。主要围绕“电气工程“、”控制科学“、”机械工程“、”自动化”等主题展开,旨在为从电…...

LabVIEW在电液比例控制与伺服控制中的应用
LabVIEW作为一种图形化编程环境,广泛应用于各类控制系统中,包括电液比例控制和伺服控制领域。在这些高精度、高动态要求的控制系统中,LabVIEW的优势尤为突出。以下从多个角度探讨其应用与优势: 1. 灵活的控制架构 LabVIEW为电…...

植物大战僵尸杂交版v3.0.2最新版本(附下载链接)
B站游戏作者潜艇伟伟迷于12月21日更新了植物大战僵尸杂交版3.0.2版本!!!,有b站账户的记得要给作者三连关注一下呀! 不多废话下载链接放上: 夸克网盘链接::https://pan.quark.cn/s/5c…...
车辆重识别代码笔记12.19
1、resnet_ibn_a和resnet网络的区别 ResNet-IBN-A 是在 ResNet 基础上进行了一些改进的变种,具体来说,它引入了 Instance Batch Normalization (IBN) 的概念,这在某些任务中(如图像识别、迁移学习等)有显著的性能提升。…...

linux内核网络分层概述
在开发应用时,我们使用 socket 实现网络数据的收发。以tcp为例,server端通过 socket, bind, listen来创建服务端,然后通过 accept接收客户端连接;客户端通过 socket和 connect系统调用来创建客户端。用于数据收发的系统调用包括 s…...

H3C交换机配置 telnet 服务
使用一个交换机做成 telnet 服务, telnet 可以使用指定端口开启三层交换机, 用于与 pc 互通, 也可以使用自带的 vlan1 设置 ip 然后达到互通, 因为华三的交换机端口默认是 access 口, 默认带 vlan1 , 直接设置 vlan1 的 ip 也就可以实现互通 实现互通 互通的两种方式 设置 vl…...
江苏计算机专转本 技能Mysql知识点总结(二)
三、SQL数据操纵语言(增删改查) 1.insert 语句(增) INSERT INTO 表名 (列1, 列2, 列3) VALUES (值1, 值2, 值3); 2.Delete 语句(删) //1. DELETE FROM 表名 WHERE 条件;//2. truncate table 表名; …...

边缘智能网关助力打造建筑智慧消防物联网
随着经济社会的快速发展,为了满足民众生产、生活、消费需求,高层建筑、大型综合连体建筑持续兴建,各类火灾风险和事故也越发增加。得益于物联网的普及应用,消防监测和管理迎来数字化、智慧化转型升级。 针对各类高层、大型建筑消防…...

学习Cookie 提升
目录 Cookie 的覆盖 Cookie下的path 特点 设置Cookie 路径 实例 Cookie的最大存活时间 设置Cookie 存活时间 实例 Cookie 和session的区别 和联系 Cookie 的覆盖 当 key相同 和只要path的上级目录的路径相同,就可以被替换掉 value 值 如下图…...
OpenAI 发布会 9 天技术总结
OPEN AI 发布会总结 OpenAI 发布会 12 天技术总结Day 1: 开幕与愿景主要内容:体验方式: Day 2: GPT-4 及其突破性进展主要内容:体验方式: Day 3: GPT-4 在编程领域的突破 - Codex & Copilot主要内容:体验方式&…...
免费注册.news域名一年(今日有效)
时间紧迫,就不上图了,需要的尽快。 网址:https://www.namecheap.com/ 优惠码:FREEDOM24...

解决JIRA、Confluence用户自动注销、反复登录的问题
一、问题描述:当工作从从confluence里面打开jira的时候,在回到confluence时候,就自动退出了,需要账号密码登录重复登录,使人十分厌恶。 二、原因分析: 访问 JIRA、Confluence 或任何其他具有相同域或 IP 上…...
Oracle创建逻辑目录
Oracle 在执行逻辑备份及还原时,需要用到逻辑目录。 本文就来简单介绍一下逻辑目录相关的操作,希望对大家有所帮助。 1.登录到Oracle数据库 使用具有足够权限的数据库用户登录到Oracle数据库。通常,这需要是管理员账号,如SYS…...

【AIGC-ChatGPT进阶副业提示词】星际占卜师:探索星象能量的艺术【限时免费阅读,一天之后自动进入进阶课程】
引言 在这个数字化的时代,我们创造了一个独特的角色 —— 星际占卜师。这不仅是一个简单的运势预测工具,更是一个融合了玄学、预言和能量解读的智能向导。通过精心设计的系统提示词和独特的画境生成机制,星际占卜师能够为用户带来沉浸式的占…...

泷羽sec-shell编程(9)
shell(9) 声明! 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他…...
【Vue-4小时速通01-ES6】
1.var和let的区别 1.1作用域与有效范围 var 在函数或全局作用域中声明变量,无论在块级作用域内外都可以访问。 var 即使在块级作用域外部访问,仍然能获取到结果。 let 在块级作用域内声明变量,仅在其所在的作用域中有效。 let 如果在作用域…...

基于STM32的智能仓储环境监测的Proteus仿真
文章目录 一、智能仓储环境监测1.题目要求2.思路3.电路仿真3.1 未仿真时3.2 开始仿真,显示屏显示Init后,正常显示温度湿度光照烟雾数值3.3 切换温度阈值界面,用阈值加减设置温度min和温度max阈值3.4 调整温度数值,触发风扇/加热3.…...
logback日志控制台打印与写入文件
1.创建logback-spring.xml文件放入resource下 <?xml version"1.0" encoding"UTF-8"?> <configuration><property name"LOG_CONTEXT_NAME" value"log"/><!--定义日志文件的存储地址 勿在 LogBack 的配置中使用…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...