Linux驱动开发-02字符设备驱动开发初步

 一、驱动开发的前期准备

在进入驱动开发之前,需要烧写UBoot、内核、设备树,做一些前期的准备工作,确保我们开发板上的内核版本和Ubuntu上是一致的才能进行正式开发

 1.U-Boot

2.内核版本

 3.使用TFTP挂载的内核和设备树

二、Linux驱动开发与裸机开发的区别

Linux驱动开发和裸机开发的区别主要体现在以下几个方面:

  1. 开发环境
    • Linux驱动开发:在带有Linux操作系统的环境下进行,开发者利用Linux提供的各种驱动框架和API进行开发。这通常意味着开发者需要熟悉Linux内核的工作原理和相关的系统调用。
    • 裸机开发:在没有操作系统支持的环境中直接运行程序,开发者需要直接操作硬件的底层细节,包括寄存器、中断等。裸机开发常见于嵌入式系统、实时控制系统等对系统性能和资源使用有极高要求的场景。
  2. 开发技术
    • Linux驱动开发:主要使用C语言进行开发,并可能使用汇编语言进行某些特定的优化。开发者需要熟悉Linux内核编程和相关的驱动框架,如字符设备驱动、块设备驱动、网络设备驱动等。
    • 裸机开发:可能涉及汇编语言、C语言或更低级别的编程语言,因为需要直接操作硬件的底层细节。开发者需要深入了解硬件的工作原理和如何与之交互。
  3. 开发流程
    • Linux驱动开发:通常包括需求分析、设计、编码、测试等阶段。开发者需要编写符合Linux内核规范的代码,并通过系统调用或设备文件与应用程序进行交互。
    • 裸机开发:开发流程可能更为复杂,因为需要直接操作硬件。这通常包括编写启动代码、初始化硬件、配置中断、编写外设驱动程序等步骤。
  4. 关注点
    • Linux驱动开发:主要关注如何在Linux操作系统下实现对硬件设备的控制和管理,以及与操作系统的交互。
    • 裸机开发:主要关注如何直接操作硬件,实现底层的功能和性能优化。
  5. 可移植性和复用性
    • Linux驱动开发:由于是基于Linux操作系统的,因此驱动程序的可移植性和复用性通常较好。Linux支持多种硬件平台和架构,开发者可以编写通用的驱动程序以支持不同的硬件。
    • 裸机开发:由于直接操作硬件,因此可移植性和复用性通常较差。不同的硬件平台和架构可能需要完全不同的驱动程序。
  6. 调试和测试
    • Linux驱动开发:可以利用Linux提供的各种调试工具和技术进行调试和测试,如GDB、KDB等。此外,由于是在操作系统环境下进行开发,因此可以利用操作系统的功能进行辅助调试和测试。
    • 裸机开发:调试和测试通常更为复杂和困难,因为需要直接操作硬件。开发者可能需要使用专门的调试工具和技术,如JTAG调试器、逻辑分析仪等。

总结来说,Linux驱动开发和裸机开发在开发环境、技术、流程、关注点、可移植性和复用性、调试和测试等方面都存在显著的区别。选择哪种开发方式取决于具体的应用场景和需求

驱动最终表现就是/dev/xxx文件,对文件的读写、打开关闭;现在新的内核支持设备树,这个一个.dts文件,此文件描述了板子的设备信息

驱动加载成功以后会在“/dev”目录下生成一个相应的文件,应用程序通过对这个名为“/dev/xxx”(xxx 是具体的驱动文件名字)的文件进行相应的操作即可实现对硬件的操作

 2.1 驱动设备的分类

字符设备驱动:字符设备就是一个一个字节,按照字节流进行读写操作的设备,读写数据是分先后顺序的

块设备驱动:所谓的块设备驱动就是存储器设备的驱动,比如 EMMC、 NAND、 SD卡和 U盘等存储设备,因为这些存储设备的特点是以存储块为基础,因此叫做块设备。网络设备驱动就更好理

网络设备驱动:就是网络驱动,不管是有线的还是无线的,都属于网络设备驱动的范畴。一个设备可以

一个设备可以属于多种设备驱动类型,比如 USB WIFI,其使用 USB接口,所以属于字符设备,但是其又能上网,所以也属于网络设备驱动。

三、Linux驱动开发的VScode的环境搭建

1.禁止鼠标中键复制与创建驱动文件夹

//禁止鼠标中键复制
alientek@ubuntu16:~/linux/IMX6ULL/Linux_Drivers/1_chrdevbase$ xmodmap -e "pointer = 1 25 3 4 5 6 7 2"
Warning: Only changing the first 8 of 16 buttons.
alientek@ubuntu16:~/linux/IMX6ULL/Linux_Drivers/1_chrdevbase$ pwd
/home/alientek/linux/IMX6ULL/Linux_Drivers/1_chrdevbase
alientek@ubuntu16:~/linux/IMX6ULL/Linux_Drivers/1_chrdevbase$ ls
chrdevbase.c  chrdevbase.code-workspace
///home/alientek/linux/IMX6ULL/Linux_Drivers/1_chrdevbase在该路径下,新建第一个驱动的文件夹,编写代码

 2.将创建的驱动文件夹,添加到Ubuntu的vscode中

 3.将我们的内核源码路径添加到c_cpp_properties.json和Makefile

 (1)c_cpp_properties.json文件

{"configurations": [{"name": "Linux","includePath": ["${workspaceFolder}/**","/home/alientek/alpha/alientek-zzk/kernel-chao/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek/include", "/home/alientek/alpha/alientek-zzk/kernel-chao/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek/arch/arm/include", "/home/alientek/alpha/alientek-zzk/kernel-chao/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek/arch/arm/include/generated/"],"defines": [],"compilerPath": "/usr/bin/clang","cStandard": "c11","cppStandard": "c++17","intelliSenseMode": "clang-x64"}],"version": 4
}

  (2)Makefile文件

KERNELDIR := /home/alientek/alpha/alientek-zzk/kernel-chao/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek
//KERNELDIR表示开发板所使用的 Linux内核源码目录,使用绝对路径CURRENT_PATH := $(shell pwd)
//CURRENT_PATH表示当前路径,直接通过运行“ pwd”命令来获取当前所处路
径。obj-m := chrdevbase.o
//obj-m表示将 chrdevbase.c这个文件 编译为 chrdevbase.ko模块。build: kernel_modules
//表示我们编译的是模块kernel_modules:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
//编译时,先把目录切换到源码中,因为使用了源码的一些函数;编译完成后再把目录切换到当前目录,需要把编译生成的文件放在当前目录下,Linux内核中我们已经指定好交叉编译器了clean:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

 3.先清理(make clean)再编译(make)

alientek@ubuntu16:~/linux/IMX6ULL/Linux_Drivers/1_chrdevbase$ make clean
make -C /home/alientek/alpha/alientek-zzk/kernel-chao/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek M=/home/alientek/linux/IMX6ULL/Linux_Drivers/1_chrdevbase clean
make[1]: Entering directory '/home/alientek/alpha/alientek-zzk/kernel-chao/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek'CLEAN   /home/alientek/linux/IMX6ULL/Linux_Drivers/1_chrdevbase/.tmp_versionsCLEAN   /home/alientek/linux/IMX6ULL/Linux_Drivers/1_chrdevbase/Module.symvers
make[1]: Leaving directory '/home/alientek/alpha/alientek-zzk/kernel-chao/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek'
alientek@ubuntu16:~/linux/IMX6ULL/Linux_Drivers/1_chrdevbase$ make
make -C /home/alientek/alpha/alientek-zzk/kernel-chao/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek M=/home/alientek/linux/IMX6ULL/Linux_Drivers/1_chrdevbase modules
make[1]: Entering directory '/home/alientek/alpha/alientek-zzk/kernel-chao/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek'CC [M]  /home/alientek/linux/IMX6ULL/Linux_Drivers/1_chrdevbase/chrdevbase.oBuilding modules, stage 2.MODPOST 1 modulesCC      /home/alientek/linux/IMX6ULL/Linux_Drivers/1_chrdevbase/chrdevbase.mod.oLD [M]  /home/alientek/linux/IMX6ULL/Linux_Drivers/1_chrdevbase/chrdevbase.ko
make[1]: Leaving directory '/home/alientek/alpha/alientek-zzk/kernel-chao/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek'
alientek@ubuntu16:~/linux/IMX6ULL/Linux_Drivers/1_chrdevbase$ ls
chrdevbase.c  chrdevbase.code-workspace  chrdevbase.ko  chrdevbase.mod.c  chrdevbase.mod.o  chrdevbase.o  Makefile  modules.order  Module.symvers
alientek@ubuntu16:~/linux/IMX6ULL/Linux_Drivers/1_chrdevbase$ 

 4.先清理(make clean)再编译(make)

 四、驱动模块加载与卸载

Linux驱动有两种运行方式,第一种就是将驱动编译进 Linux内核中,这样当 Linux内核启动的时候就会自动运行驱动程序。第二种就是将驱动编译成模块 (Linux下模块扩展名为 .ko),在Linux内核启动以后使用“ insmod”命令加载驱动模块。

 1.将我们在vscode中编译出来的文件拷贝到制作好的根文件目录下

alientek@ubuntu16:~/linux/IMX6ULL/Linux_Drivers/1_chrdevbase$ sudo cp chrdevbase.ko /home/alientek/linux/nfs/rootfs/lib/modules/4.1.15 -f

 2.modprobe来加载模块

insmod命令不能解决模块的依赖关系,modprobe会分析模块的依赖关系,然后会将所有的依赖模块都加载到内核中,我们使用modprobe来加载模块;

modprobe命令默认会去/lib/modules/<kernel-version>目录中查找模块,比如本书使用的 Linux kernel的版本号为 4.1.15因此 modprobe命令默认会到 /lib/modules/4.1.15这个目录中查找相应的驱动模块,一般自己制作的根文件系统中是不会有这个目录的,所以需要自己手 动创建。

 对于一个新的模块使用modprobe加载的时候需要先调用一下depmod命令;驱动模块加载成功以后可以使用lsmod查看一下;卸载模块使用rmmod命令

  2.lsmod查看当前驱动模块是否有我们刚刚加载的模块

  3.rmmod查看当前驱动模块

 

 

 4.执行命令

/lib/modules/4.1.15 # modprobe chrdevbase.ko
chrdevbase: module license 'unspecified' taints kernel.
Disabling lock debugging due to kernel taint
module_init!
/lib/modules/4.1.15 # lsmod
Module                  Size  Used by    Tainted: P
chrdevbase               664  0
/lib/modules/4.1.15 # rmmod chrdevbase.ko
module_exit!
/lib/modules/4.1.15 # lsmod
Module                  Size  Used by    Tainted: P
/lib/modules/4.1.15 # ls
8188eu.ko              ft5x06.ko              libcomposite.ko
8189fs.ko              g_audio.ko             modules.alias
8192cu.ko              g_mass_storage.ko      modules.dep
8821cu.ko              gpioled.ko             modules.symbols
adcApp                 ledAPP                 usb_f_mass_storage.ko
chrdevbase.ko          ledApp                 usb_f_uac1.ko
/lib/modules/4.1.15 # lsmod
Module                  Size  Used by    Tainted: P
/lib/modules/4.1.15 # modprobe chrdevbase.ko
module_init!
/lib/modules/4.1.15 # lsmod
Module                  Size  Used by    Tainted: P
chrdevbase               664  0
/lib/modules/4.1.15 # rmmod chrdevbase.ko
module_exit!
/lib/modules/4.1.15 # lsmod
Module                  Size  Used by    Tainted: P

5.在Ubuntu上的根文件系统中同步可以看到文件

alientek@ubuntu16:~/linux/nfs/rootfs/lib/modules/4.1.15$ pwd
/home/alientek/linux/nfs/rootfs/lib/modules/4.1.15
alientek@ubuntu16:~/linux/nfs/rootfs/lib/modules/4.1.15$ ls
8188eu.ko  chrdevbase.ko      ledApp           modules.symbols
8189fs.ko  ft5x06.ko          ledAPP           usb_f_mass_storage.ko
8192cu.ko  g_audio.ko         libcomposite.ko  usb_f_uac1.ko
8821cu.ko  g_mass_storage.ko  modules.alias
adcApp     gpioled.ko         modules.dep
alientek@ubuntu16:~/linux/nfs/rootfs/lib/modules/4.1.15$ ls
8188eu.ko  chrdevbase.ko      ledApp           modules.symbols
8189fs.ko  ft5x06.ko          ledAPP           usb_f_mass_storage.ko
8192cu.ko  g_audio.ko         libcomposite.ko  usb_f_uac1.ko
8821cu.ko  g_mass_storage.ko  modules.alias
adcApp     gpioled.ko         modules.dep

 我们的第一个驱动模块加载与卸载编译完成

 五、代码

chrdevbase.c

#include <linux/module.h>
#include <linux/init.h>//printk函数头文件
static int __init chrdevbase_init(void)
{printk("module_init!\r\n");return 0;
}static void __exit chrdevbase_exit(void)
{//没有返回值printk("module_exit!\r\n");
}
/*
模块的入口与出口
*/
module_init(chrdevbase_init);
module_exit(chrdevbase_exit);
/*
模块的一些许可证信息
*/MODULE_AUTHOR("Chao");//作者是谁
MODULE_LICENSE("GPL");//开源协议

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

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

相关文章

记一次elementui时间线的实现

实现效果 点击展开&#xff0c;每次累加五条数据进行展示 实现思路 起始本质上就是一个分页查询&#xff0c;只不过按新的形式展示&#xff0c;然后也不统计总数&#xff0c;每次只展示固定的5条数据点击加载更多&#xff0c;就展示下一页&#xff0c;页的页数进行1&#xff…

ONLYOFFICE 文档 8.1 发布:重塑文档处理

官网链接&#xff1a;ONLYOFFICE官网 一、PDF编辑器功能强大&#xff1a;创造跟随想象 在追求无界办公与高效创作的今天&#xff0c;ONLYOFFICE再次引领风潮&#xff0c;正式发布了其桌面编辑器的最新版本——ONLYOFFICE桌面编辑器8.1。这一版本不仅巩固了其作为顶级办公套件…

python3使用ast.parse详解

使用ast库分析python3脚本, 并对脚本进行一些处理, 比如注释pirnt语句 一.基础知识 官方网址连接 ast — Abstract Syntax Trees ast库可以方便的分析python代码结构, 并做一些处理, 很适合对大量脚本文件做批量处理, 比如把print语句全部注释等. 直观的打印出代码结构 impo…

简述Java项目中VO,BO,PO,DO,DTO之类的文件概念、易混点

VO&#xff0c;BO&#xff0c;PO&#xff0c;DO&#xff0c;DTO 概念易混点一&#xff1a;VO和DTO- 让我们通过一个实例来阐释DTO和VO的概念及其应用差异&#xff1a;小结&#xff1a;VO专注于展示&#xff0c;而DTO则用于数据的传输和业务逻辑的处理。 二&#xff1a;BO和PO小…

公益培训|半导体与集成电路项目制培训项目

关于我们 硬蛋产业学院&#xff0c;基于硬蛋创新(http://00400.HK)在芯片产业的资源和技术优势&#xff0c;引进全球领先的芯片应用技术&#xff0c;为国内培养芯片应用技术人才&#xff0c;助力芯片应用产业发展。 硬蛋产业学院在国家各主管部门、广东省、深圳市及社会各界的大…

AI 激发算力需求暴增,施耐德电气解码智算中心发展

随着全球碳达峰目标的持续推进&#xff0c;各行各业都在加速绿色转型的步伐&#xff0c;尤其是高耗能产业更是备受关注。人工智能行业以其迅猛的发展速度令人瞩目&#xff0c;它所带来的不仅是算力需求的飙升&#xff0c;更是日益凸显的能耗问题。 目前&#xff0c;人工智能预…

AVI 是什么格式,AVI 格式用什么播放器打开?

AVI 是什么格式&#xff1f;提到 AVI 格式想必大家多数会想到在 DVD 横行的年代&#xff0c;光盘中所包含的媒体视频格式多是以 AVI 格式存储。AVI 是一个非常通用的容器格式&#xff0c;支持多种视频和音频编解码器。这意味着从DVD中提取视频内容时&#xff0c;可以通过转码为…

发电机保护屏产品介绍,组成

发电机保护屏产品介绍&#xff0c;组成 发电机保护屏是用于保护发电机组的电气装置。它根据发电机的类型和实际运行要求&#xff0c;将多种保护装置组合在一起&#xff0c;形成一个保护屏柜。发电机保护测控屏是指把发电机类保护装置集中在安装在一个控制柜里&#xff0c;主要用…

Java程序递归及mybatis递归查询

之前项目组有个需求&#xff0c;定时同步机构的信息。已知三方接口由于返回数据量很大&#xff0c;所以最后需要三方提供一个可根据机构编号获取当前机构及子机构信息的接口。而不是一次性返回全部机构信息&#xff01; 由于这次需求也用到了递归&#xff0c;所以记录下&#…

Python自动化操作:简单、有趣、高效!解放你的工作流程!

今天跟大家分享一套自动化操作流程解决方案&#xff0c;基于Python语言&#xff0c;涉及pyautogui、pyperclip、pythoncom、win32com依赖包。安装命令为&#xff1a; pip install pyautoguipip install pyperclippip install pythoncompip install win32compyautogui 是一个自…

病理性不对称引导的渐进学习用于急性缺血性脑卒中梗死分割| 文献速递-先进深度学习疾病诊断

Title 题目 Pathological Asymmetry-Guided Progressive Learning for Acute Ischemic Stroke Infarct Segmentation 病理性不对称引导的渐进学习用于急性缺血性脑卒中梗死分割 01 文献速递介绍 中风已经成为第二大致命疾病&#xff0c;大约70%的中风是缺血性的。众所周知…

如何提高网页加载速度?

如何以闪电般的速度加载网站&#xff1f; 看看这 8 个提升前端性能的技巧&#xff1a; 01 压缩 在传输之前压缩文件可以减少其大小&#xff0c;减少需要传输的数据量&#xff0c;从而加快加载时间。 实现方法&#xff1a; Gzip/Brotli 压缩: 配置你的 web 服务器&#xff08…

[Linux] 历史根源

UNIX系统&#xff1a; 1969年&#xff0c;由贝尔实验室的K.Thompson和D.M.Ritchie为PDP-7机器编写的一个分时操作系统&#xff0c; 最初使用汇编语言编写&#xff0c; 后来1972年C语言出世以后&#xff0c;二人由使用C写了UNIX3&#xff0c; 此后UNIX大为流行开来 UNIX流派树&a…

华为交换机的堆叠-Stack配置(基于业务口普通线缆的堆叠配置)

不想看原理请跳过一、二、三、四&#xff0c; 直接到配置五&#xff0c;干完活有时间在慢慢看原理。 一、什么是堆叠-Stack 指将多台交换机通过堆叠线缆连接在一起&#xff0c;逻辑上变成一台交换设备&#xff0c;作为一个整体参与数据转发。即&#xff1a;1 1 一 二、堆叠…

如何通过待办工具提升个人效率 减轻压力提升效率的待办app

在快节奏的现代社会中&#xff0c;工作任务繁重&#xff0c;人们的压力日益增大。为了减轻压力并提升工作效率&#xff0c;我们急需找到一种有效的方法来管理日常任务。幸运的是&#xff0c;随着科技的进步&#xff0c;各种新兴工具应运而生&#xff0c;为我们提供了便捷的解决…

qt报错:“QtRunWork”任务返回了 false,但未记录错误。

qt报错&#xff1a;“QtRunWork”任务返回了 false&#xff0c;但未记录错误。 说明情况一 说明 这个报错可能的原因有很多&#xff0c;这里只写一种&#xff0c;以后遇到再进行补充。 情况一 如果 Q_OBJECT 宏未正确处理&#xff0c;通常会出现类似的错误。 要使用信号与槽…

3.优化算法之二分查找1

二分查找简介 1.特点 最简单最恶心&#xff0c;细节最多&#xff0c;最容易写出死循环的算法 2.学习中的侧重点 1&#xff09;算法原理 数组有序的情况 2&#xff09; 模板 不要死记硬背 ->理解之后再记忆 1.朴素的二分模板 2.查找左边界的二分模板 3.查找右边界的二分模板 …

24年了 直播带货的未来如何?

32 个国家在取消电商&#xff0c; 那我国的电商呢&#xff0c;首先电商是不会被取缔的。直播电商会被严格的控制&#xff0c;比如有一家饼店&#xff0c;它线下的销售是 3000 万&#xff0c;线上抖音的销售是 5, 000 万。 这一类型小而精又专业的品牌企业&#xff0c;未来在抖…

Sensei for Mac:一键清理,系统如新!

Sensei for Mac是一款高效且易于使用的系统优化清理工具。它能够深入Mac系统内部&#xff0c;智能识别并清理无用的缓存文件、临时文件、垃圾邮件等&#xff0c;从而释放磁盘空间&#xff0c;提升系统性能。无论是日常使用还是长时间工作后&#xff0c;Sensei都能帮助你的Mac恢…

鸿蒙 HarmonyOS NEXT星河版APP应用开发阶段三-热门组件使用及案例

一、样式和结果重用 介绍 /* Extend:扩展组件&#xff08;样式、事件&#xff09; Styles: 抽取通用数据、事件 Builder:自定义构建函数&#xff08;结构、样式、事件&#xff09; */Extend /* 作用&#xff1a;扩展组件&#xff08;样式、事件&#xff09; 场景&#xff1a;…