ARM--$2$驱动模块

news2024/12/24 8:55:51

目录

1.驱动模块(驱动程序的框架)

2.内核中的打印函数(编写第一个驱动程序)

Source Insight 使用:

打印函数编写

分析

3.驱动的多文件编译

4.模块传递参数

安装好驱动之后如何传参?

 多驱动之间调用(导出符号表)

具体过程

5.字符设备驱动

字符设备驱动的注册

总结归纳

具体过程


1.驱动模块(驱动程序的框架)

入口(安装):资源的申请

出口(卸载):资源的释放

许可证:GPL

#include <linux/init.h>
#include <linux/module.h>
//声明   //static 是为了防止别人的驱动和你重名 
static int __init hello_init(void)    //入口
{

}
static void __exit hello_exit(void)   //出口
{

}
//告诉内核驱动的入口
module_init(hello_init);
//告诉内核驱动的出口
module_exit(hello_exit);
MODULE_LICENSE("GPL");    //许可证

Makefile

KERNELDIR:= /lib/modules/$(shell uname -r)/build/  //ubuntu 内核目录
#KERNELDIR:= /home/linux/kernel/kernel-3.4.39/    //开发板内核目录
PWD:=$(shell pwd)
all: 
    make -C $(KERNELDIR) M=$(PWD) modules
clean:
    make -C $(KERNELDIR) M=$(PWD) clean
obj-m:=hello.o 	

具体过程:

vi Makefile

 ls

 

 

 

 

 更改

 

 

 

 

 vi hello.c

make

 

 

 

 SI3US-361500-17409

2.内核中的打印函数(编写第一个驱动程序)

Source Insight 使用:

 

 

 

 

 

 

 

打印函数编写

分析

--------------------------------------打印级别--------------------------------------
#define KERN_EMERG	"<0>"	/* system is unusable			*/
#define KERN_ALERT	"<1>"	/* action must be taken immediately	*/
#define KERN_CRIT	"<2>"	/* critical conditions			*/
#define KERN_ERR	"<3>"	/* error conditions			*/
#define KERN_WARNING	"<4>"	/* warning conditions			*/
#define KERN_NOTICE	"<5>"	/* normal but significant condition	*/
#define KERN_INFO	"<6>"	/* informational			*/
#define KERN_DEBUG	"<7>"	/* debug-level messages			*/
y@y-virtual-machine:~/linux6818/demo$ cat /proc/sys/kernel/printk
   4              4	                 1	            7     

终端的级别   消息的默认级别   终端的最大级别   终端的最小级别  
#define console_loglevel (console_printk[0])
#define default_message_loglevel (console_printk[1])
#define minimum_console_loglevel (console_printk[2])
#define default_console_loglevel (console_printk[3])
--------------------------------打印函数---------------------------------------------
printk(KERN_ERR "BFS-fs: %s(): " format, __func__, ## args)
功能:消息打印
参数:
   第一个参数:打印的级别
   第二个参数:打印的内容
   第三个参数:和printf一样,需要打印的参数

 ubuntu级别

#include <linux/init.h>
#include <linux/module.h>
#include <linux/printk.h>
static int __init hello_init(void)//入口
{
  printk(KERN_ERR "hello word\n");
  return 0;
}
static void __exit hello_exit(void)//出口
{
  printk(KERN_ERR "baibai\n");
}
module_init(hello_init);//告诉内核驱动的入口
module_exit(hello_exit);//告诉内核驱动的出口
MODULE_LICENSE("GPL");

PM:

ctrl+F5 (进入虚拟控制台)ctrl+F7(退出虚拟控制台)-》有的退出是F2
sudo insmod  hello.ko(安装驱动)sudo rmmod  hello(卸载驱动)
 dmesg (查看消息的回显)  dmesg -c  (查看回显并清空)dmesg -C  (清空回显)
cat /prod/sys/kernel/printk 
(查看ubuntu终端显示级别 消息默认级别 消息最大级别  消息最小级别)
su root echo 4 3 1 7 > /proc/sys/kernel/printk
(修改ubuntu终端显示级别 消息默认级别 消息最大级别  消息最小级别)
echo 4 3 1 7 > /proc/sys/kernel/printk
(修改开发板)
= 赋值 需要等待其他文件全部执行完,才执行调用的 
:= 立即赋值
+= 附加赋值
?= 询问变量之前是否被赋值过 如果赋值过,本次赋值不成立,否则成立

3.驱动的多文件编译

hello.c  add.c
	 Makefile
	 obj-m:=demo.o
	 demo-y+=hello.o add.o
	最终生成demo.ko文件	

 vi makefile

增添完后 make

然后make clean

4.模块传递参数

module_param(name, type, perm) 

功能:接收命令行传递的参数

参数:

name: 变量的名字  type:变量的类型  perm:权限 0664 0775 
#include <linux/init.h>
#include <linux/module.h>
int a=10;
module_param(a,int,0664);                   
static int __init hello_init(void)
{
 printk("sum= %d\n",a);
 return 0;
}
static void __exit hello_exit(void)
{
 printk(KERN_ERR"bai");                
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

传递两个参数程序

int a=10;
module_param(a,int,0664);    
int b=10;
module_param(b,int,0664);    

问:安装时怎么区分a和b的作用,自己写的知道那如果移植其他厂商的呢比如LCD屏

使用modinfo hello.ko查看,且需要程序里使用如下函数进行配置

MODULE_PARM_DESC(_parm, desc)
功能:对变量的功能进行描述
参数:
	@_parm:变量
	@desc :描述字段
int a=10;
module_param(a,int,0664);
MODULE_PARM_DESC(a,"light");
short b=123;
module_param(b,short,0664);
MODULE_PARM_DESC(b,"clour");
char c='c';
 module_param(c,byte,0664);
 MODULE_PARM_DESC(c,"light_c");
 char *d=null;
 module_param(d,charp,0664);
  MODULE_PARM_DESC(d,"clour");
 static int __init hello_init(void)
{ 
    printk("sum= %d\n",a);
    printk("sum= %d\n",b);
    printk("sum= %c\n",c);
    printk("sum= %s\n",d);                                                                                                                                                                                 
return 0;
}
static void __exit hello_exit(void)
 {
  printk(KERN_ERR"bai");
}
 module_init(hello_init);
 module_exit(hello_exit);
 MODULE_LICENSE("GPL");

vi hello.c

`` 

int a=10;

int b=0;

module_param(a, int, 0664) ;

module_param(b, int, 0664) ;

MODULE_PARM_dESC(a,"light");

MODULE_PARM_dESC(b,"color");

sudo insmod hello.ko a=20

make

modinfo hello.ko

sudo insomd hello.ko a=30 b=24

sudo dmesg -c

数组传参:

module_param_array(name,type,nump,perm)
功能:接收命令行传递的数组
参数:
name:数组名 type :数组类型  nump:参数的个数,变量的地址 perm 权限
int ww[10]={0}; 
int num;
module_param_array(ww,int,&num,0664)
static int __init hello_init(void)
{
    int i;
    for(i=0;i<num;i++)
    {
     printk("ww[%d]=%d\n",i,ww[i]);
    }
}

sudo insmod hello.ko ww=1,2,3,4,5

具体过程:

 

 

 

 

 make

sudo insmod hello.ko ww=1,2,3,4,5

安装好驱动之后如何传参?

1.lsmod查看驱动名字

2.找路径 /sys/module/驱动模块的名字/parameters

3.修改 -》su root -》echo 需要改为多少>需要修改的参数名

4.cat 需要修改的参数名(查看是否修改成功)

 多驱动之间调用(导出符号表)

假如有两个驱动模块,modul1和modu2 。这两个是可以调用的

cp  ../day1/module  .  -a    拷贝module到当前目录下

makdir export   mv module/  export/ 

mv module/   A 重命名moudule为A

cp A B -a  拷贝一份并命名为B

#include <linux/intt.h>
#include <linux/module.h>
int add(int a,int b)
{
 return (a+b);
}
EXPORT_SYMBOL_GPL(add);//导出符号表
static int __init hello_init(void)
{
 return 0;
}
staic int __exit hello_exit(void)
{
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

进入B,mv hello.c demo.c改下名字

然后vi打开

extern int add(int a,int b);
static int __init hello_init(void)
{
    printk("sum = %d\n",add(10,345));
}

编译

  make  

 发现报错,提示add没有定义

 所以在执行之前把A里面大M开头文件复制到当前目录下   

mv  cp  ../A/Module.symvers

然后再make

安装:

 先安装提供者 sudo insmod hello.ko

 再安装调用者 sudo insmod  demo.ko

查看信息:dmesg

卸载:

先卸载 demo.ko  再卸载 hello.ko

具体过程

cp -r /

 

 

vi add.c

 

 make

 

 

 vi hello.c

 

5.字符设备驱动

APP层    ---- 读写操作 ----→

                                     open打开一个文件 --→{ open=hello、read=buf、write=ubuf、close=hello}

内核层    ---- 读写文件 ----→

   |

   v

硬件层    ---- GPIO输出 ----→     LED灯    

字符设备驱动的注册

   int register_chrdev(unsigned int major, const char *name,const struct file_operations *fops)

功能:注册一个字符设备驱动

参数:

@major:主设备号  

  :如果你填写的值大于0,它认为这个就是主设备号

  :如果你填写的值为0,操作系统给你分配一个主设备号   

@name :名字    cat /proc/devices 查看设备名和主设备号

@fops :操作方法结构体

返回值:major>0 ,成功返回0,失败返回错误码(负数) (vi -t EIO 可以查看错误码)

major=0,成功主设备号,失败返回错误码(负数)      

void unregister_chrdev(unsigned int major, const char *name)

功能:注销一个字符设备驱动

参数:

@major:主设备号

@name:名字

返回值:无

总结归纳:

字符设备驱动:

 1、注册驱动register_chrdev(unsigned int major, const char *name,const struct file_operations *fops)

major=0  自动分配设备号  name:驱动的名字   fops:结构体

 2、声明结构体-》注册驱动时第三个参数

 3、open、read、write、release-》按照内核的格式自己写的

 4、把自己写的这些函数->给到结构体里-》.open .read .write .release

 5、注销设备驱动

具体过程:

 开始注册,起一个变量

 

 

 

 

 1.注册驱动 register_chrdev

    major=0 (自动分配设备号)  name:驱动名字  fops:结构体

2.声明结构体-》注册驱动时第三个参数

3.open、read、write、release-》按照内核的格式自己写的

4.把自己写的函数给到结构体里-》.open .read .write .release

5.注销设备驱动

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

js内存管理与闭包

JavaScript内存管理 ◼ 不管什么样的编程语言&#xff0c;在代码的执行过程中都是需要给它分配内存的&#xff0c;不同的是某些编程语言需要我们自己手动的管理内存&#xff0c; 某些编程语言会可以自动帮助我们管理内存&#xff1a; ◼ 不管以什么样的方式来管理内存&#xf…

扩展系统功能——装饰模式(二)

装饰模式概述 装饰模式可以在不改变一个对象本身功能的基础上给对象增加额外的新行为&#xff0c;在现实生活中&#xff0c;这种情况也到处存在&#xff0c;例如一张照片&#xff0c;我们可以不改变照片本身&#xff0c;给它增加一个相框&#xff0c;使得它具有防潮的功能&…

安装Unity Hub和Unity Editor

1、首先下载UnityHub的安装包&#xff1a; https://unity.com/cn/download 开始您的创意项目并下载 Unity Hub | Unity 2、运行安装包 3、运行Unity Hub 第一次运行Unity Hub会默认弹出登录Unity提示&#xff0c;正常登录就可以了&#xff0c;登录后会在浏览器提示打开 Unity…

nginx+lua(openresty) 安装及使用(一)

前言 OpenResty —— 通过 Lua 扩展 NGINX 实现的可伸缩的 Web 平台。 OpenResty&#xff08;也称为 ngx_openresty&#xff09;是一个基于 Nginx 与 Lua 的高性能 Web 平台&#xff0c;其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超…

全志V3S嵌入式驱动开发(lcd屏幕驱动)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 对于一些设备&#xff0c;人们是希望从屏幕上面获取结果信息的&#xff0c;这样也显得更直观一些。另外&#xff0c;也有一些设备&#xff0c;它本…

阿里云OSS实现图片上传(后端接口)

文章目录 1、阿里云oss服务开通2、java操作阿里云oss&#xff0c;上传文件到阿里云oss1. 创建操作阿里云oss许可证2. 安装SDK3.修改配置文件4.创建常量类&#xff0c;读取配置文件中的内容5、OssController6、OssService7、OssServiceImpl8、改进1. 多次上传相同名称文件&#…

Segment Anything学习小结

论文地址&#xff1a;Segment Anything 项目地址&#xff1a;https://github.com/facebookresearch/segment-anything 在线Demo&#xff1a; https://segment-anything.com/demo 前言 近日&#xff0c;MetaAI团队开源了一个用于分割的10亿个masks&#xff0c;1100w张图片数…

测试新手如何晋升为月入过万的软件测试工程师?“我“的测试之路不简单...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 测试工程师这个岗…

记一次binlog恢复Mysql某张表数据的过程

1、备份数据库&#xff0c;非常重要 2、要用户不能操作&#xff08;如果不能停止&#xff0c;可以新建一个库&#xff0c;所有的binlog执行操作在新库执行&#xff09;。 3、登录服务器&#xff1b; 4、获取Mysql数据路径 cat /etc/my.cnf.d/mysql-server.cnf5、进入当前目录…

【SpinalHDL快速入门】4.2、基本类型之Bits

文章目录 1.1、描述1.2、声明1.3、运算符1.3.1、逻辑运算&#xff08;Logic&#xff09;1.3.2、比较&#xff08;Comparison&#xff09;1.3.3、类型转换&#xff08;Type cast&#xff09;1.3.4、部分赋值/提取操作符&#xff08;Bit extraction&#xff09;1.3.5、杂项&#…

Redis的使用规范小建议

Redis 核心技术与实战 笔记 作者&#xff1a; 蒋德钧 毕竟&#xff0c;高性能和节省内存&#xff0c;是我们的两个目标&#xff0c;只有规范地使用Redis&#xff0c;才能真正实现这两个目标。如果说之前的内容教会了你怎么用&#xff0c;那么今天的内容&#xff0c;就是帮助你用…

ChatGPT的学习过程【分析ChatGPT原理】+如何高效使用GPT

ChatGPT的学习过程【分析ChatGPT原理】如何高效使用GPT 此处借鉴&#xff1a;台湾大学李宏毅老师的讲解 资料&#xff1a;pan.baidu.com/s/1Jk1phne3ArfOERYNTPL12Q?pwd1111 GPTGenerative Pre-trained Transformer生成式预训练转换模型 ChatGPT共有四个学习阶段 学习文字接龙…

Java性能权威指南-总结7

Java性能权威指南-总结7 垃圾收集算法理解Throughput收集器堆大小的自适应调整和静态调整理解CMS收集器 垃圾收集算法 理解Throughput收集器 Throughput收集器有两个基本的操作&#xff1b;其一是回收新生代的垃圾&#xff0c;其二是回收老年代的垃圾。 下图展示了堆在新生代…

Python配置MySQL数据库使用

创建配置文件 config.ini [MySQL] host 172.xxx.xxx.xxx port 3306 user root password ****** db bgp_routing charset utf8创建读取配置文件 readConfig.py import configparser from pathlib import Pathclass ReadConfig():def __init__(self):configDir Path.cwd…

【学习日记2023.6.6】之 Linux环境下部署Java项目

文章目录 5. 项目部署5.1 手动部署项目5.2 基于Shell脚本自动部署5.2.1 介绍5.2.2 推送代码到远程5.2.3 Git操作5.2.4 Maven安装5.2.5 Shell脚本准备5.2.6 Linux权限5.2.7 授权并执行脚本5.2.8 设置静态IP 5. 项目部署 开发的项目绝大部分情况下都需要部署在Linux系统中。下面通…

springboot+vue多维的知识分类管理系统

随着国内市场经济这几十年来的蓬勃发展&#xff0c;突然遇到了从国外传入国内的互联网技术&#xff0c;互联网产业从开始的群众不信任&#xff0c;到现在的离不开&#xff0c;中间经历了很多挫折。本次开发的多维分类的知识管理系统有管理员和用户两个角色。管理员可以管理用户…

Dozzle-解决通过命令方式查看Docker 日志的神器

对于程序员们来说&#xff0c;Docker 一定是不陌生了。Docker 为我们的工作带来的巨大的便利&#xff0c;你可以使用它快速部署和扩展应用程序&#xff0c;并保证隔离性和可移植性&#xff0c;使应用程序在容器内独立运行&#xff0c;而且可以轻松地在不同的主机和操作系统上移…

bpmn是什么?bpmn.js的简单使用

文章目录 一、bpmn.js是什么&#xff1f;二、使用步骤1.引入bpmn2.使用bpmn3.引入bpmn-左侧工具栏4.引入bpmn-左侧工具栏5.引入bpmn数据导出6.数据导出为svg格式7.监听modeler并绑定事件7.监听element点击……8.自定义左侧工具栏图标9.自定义左侧工具栏完整效果 总结 一、bpmn.…

推动体系建设 助推融合发展|2023 开放原子全球开源峰会软件物料清单(SBOM)分论坛即将启幕

软件物料清单对于普通人而言可能很陌生&#xff0c;而对于从业者而言&#xff0c;软件物料清单是以 “开源” 为核心&#xff0c;通过有效识别和记录软件组成成分及相互依赖关系&#xff0c;保障软件全生命周期各环节要素的可控制、可预测、可管理。 由开放原子开源基金会主办…

云原生Docker网络管理和数据卷

Docker网络 Docker 网络实现原理 Docker使用Linux桥接&#xff0c;在宿主机虚拟一个Docker容器网桥(docker0)&#xff0c; Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址&#xff0c;称为Container-IP&#xff0c; 同时Docker网桥是每个容器的默认网关。 …