仿wordpress模板教程,西安seo优化顾问,百度下载官方下载安装,网站建设前途目录
ARM裸机代码和驱动的区别
Linux系统组成
内核五大功能
设备驱动分类
内核类型
驱动模块
驱动模块示例
Makefile配置
命令
编码辅助工具
内核中的打印函数
printk 函数
修改打印级别
编辑
打印级别含义 驱动多文件编译
示例 模块传递参数
命令行传递参数…目录
ARM裸机代码和驱动的区别
Linux系统组成
内核五大功能
设备驱动分类
内核类型
驱动模块
驱动模块示例
Makefile配置
命令
编码辅助工具
内核中的打印函数
printk 函数
修改打印级别
编辑
打印级别含义 驱动多文件编译
示例 模块传递参数
命令行传递参数
支持的数据类型
module_param 函数
MODULE_PARM_DESC 函数
示例
module_param_array 函数
字符设备驱动
Linux系统中一切皆文件
字符设备驱动步骤
字符设备驱动的注册
编辑
字符设备驱动的注销 以下是本人学习时的一些笔记对初入门的驱动可能会有一些帮助希望可以帮到大家~ ARM裸机代码和驱动的区别
共同点
都能够操作硬件。
不同点
裸机编程是直接用C语言给寄存器写值。驱动编程遵循一定的框架和规范通过往寄存器写值来控制硬件。裸机代码独立编译和执行而驱动依赖于内核进行编译和执行。裸机程序一次只能执行一个任务而驱动可以支持并发执行多个任务。裸机程序只需一个main函数即可而驱动需要遵循内核的框架和流程。 Linux系统组成
用户空间0-3G每个进程独占0-3G的虚拟地址空间。 内核空间3-4G所有进程共享3-4G的虚拟地址空间。系统调用应用程序通过系统调用软中断SWI与内核交互。 内核五大功能
进程管理负责进程的创建、销毁和调度。文件管理通过文件系统如ext2/ext3/ext4/YAFFS/JFFS等来管理文件。网络管理通过网络协议栈如OSI/TCP/IP处理数据包的封装和拆解。内存管理负责用户空间和内核空间内存的分配和回收。设备管理管理设备驱动如字符设备、块设备和网络设备。
设备驱动分类
字符设备驱动如LED、鼠标、键盘、LCD、触摸屏等。 按照字节为单位访问支持顺序访问。创建设备文件通过open, read, write, close等操作访问。块设备驱动如摄像头、U盘、eMMC等。 按照块通常是512字节访问支持顺序和随机访问。创建设备文件通过open, read, write, close等操作访问。网络设备驱动如网卡。 按照网络数据包进行收发。
内核类型
宏内核将主要功能集成在一个内核中。 优点运行效率高。缺点任何一个部分出错都可能导致整个内核崩溃。示例Ubuntu, Android微内核只包含最基本的功能其他功能通过服务的形式在用户空间实现。 优点更高的稳定性和安全性。缺点相对较低的运行效率。示例HarmonyOS, QNX
驱动模块
三要素入口、出口、许可证。入口资源的申请。出口资源的释放。许可证通常使用GPL许可。 __init可以不指定及可以不写但是正常是写的 驱动模块示例
#include linux/init.h
#include linux/module.h//__init将hello_init放到.init.text段中
static int __init hello_init(void) {// 初始化函数return 0;
}//__exit将hello_exit放到.exit.text段中
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/
PWD : $(shell pwd)all:make -C $(KERNELDIR) M$(PWD) modulesclean:make -C $(KERNELDIR) M$(PWD) cleanobj-m hello.o
命令
安装驱动模块sudo insmod hello.ko卸载驱动模块sudo rmmod hello 查看已加载的模块lsmod查看内核消息dmesg清空内核消息sudo dmesg -C 或 sudo dmesg -c持续查看内核消息sudo dmesg -w 编码辅助工具
创建索引文件ctags -R在vi中跳转至标签ctrl ] 和 ctrl t Ubuntu内核所对应的内核路径 内核中的打印函数 printk 函数 函数原型 printk(打印级别 内容) 示例 printk(KERN_ERR Fail%d, a);
printk(KERN_ERR %s:%s:%d\n, __FILE__, __func__, __LINE__);
printk(%s:%s:%d\n, __FILE__, __func__, __LINE__); 查看内核打印级别 vi -t KERN_ERR 内核打印级别定义 #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 */ 打印级别范围 从 0 到 70 为最高级别7 为最低级别。 修改打印级别 查看当前打印级别 cat /proc/sys/kernel/printk 打印级别的含义 第一个数字终端的级别。第二个数字消息的默认级别。第三个数字终端的最大级别。第四个数字终端的最小级别。 修改系统默认的级别 su root
echo 4 3 1 7 /proc/sys/kernel/printk 添加修改级别命令 echo 4 3 1 7 /proc/sys/kernel/printk 打印级别含义 终端的级别只有当消息的级别大于或等于终端级别时消息才会在终端上显示。消息的默认级别如果没有特别指定消息将采用此级别。终端的最大级别终端可以显示的最高级别。 安装驱动和卸载驱动时消息会打印。 驱动多文件编译 示例 文件列表 hello.cadd.c Makefile obj-m : demo.o
demo-y hello.o add.o 说明 -y 作用将 hello.o 和 add.o 文件合并到 demo.o 中。最终生成demo.ko 文件。 模块传递参数 命令行传递参数 命令示例 sudo insmod demo.ko hello world 支持的数据类型 标准类型 byte, short, ushort, int, uint, long, ulongcharp: 字符串指针bool: 布尔值接受 0/1, y/n, Y/Ninvbool: 布尔值接受 0/1, y/n, Y/N但意义相反N 表示真 module_param 函数 函数原型 module_param(name, type, perm); 参数 name: 变量的名字。type: 变量的类型。perm: 权限如 0664, 0775。 MODULE_PARM_DESC 函数 函数原型 MODULE_PARM_DESC(_parm, desc); 参数 _parm: 变量。desc: 描述字段。 示例 命令行参数 sudo insmod hello.ko a20 b30 c65 phello_world 注意事项 传递字符时使用 ASCII 码值。传递字符串时不能包含空格。 module_param_array 函数 函数原型 module_param_array(name, type, nump, perm); 参数 name: 数组名。type: 数组的类型。nump: 参数的个数变量的地址。perm: 权限。 练习 1.byte类型如何使用 (传递参数用ascii) 2.如何给一个指针传递一个字符串 命令行参数 sudo insmod hello.ko a121 b10 c65 phello ww1,2,3,4,5 传参成功~ 字符设备驱动 Linux系统中一切皆文件 应用层 fd open(led驱动的文件, O_RDWR);
read(fd);
write(fd);
close(fd); 内核层 驱动文件led_driver.c驱动函数 driver_open();
driver_read();
driver_write();
driver_close(); 结构体定义 struct file_operations {int (*open)(struct inode *, struct file *);ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);int (*release)(struct inode *, struct file *);
; 设备号 32位无符号数字 高12位主设备号用于区分设备类别。低20位次设备号用于区分同一类别中的不同设备。 硬件层 LED、UART、ADC、PWM 等设备。 字符设备驱动步骤 注册字符设备驱动 - 得到一个字符设备驱动的框架并获得设备号。确定操作的硬件设备 - 如 LED 灯初始化灯。初始化灯 - 建立灯实际物理地址和虚拟地址之间的映射。用户空间与内核空间数据交互 - 当用户使用时驱动会被真正运行涉及数据交互。在应用层创建设备文件设备节点。 字符设备驱动的注册 函数原型 int register_chrdev(unsigned int major, const char *name,const struct file_operations *fops); 参数 major主设备号。 如果填写的值大于0它认为这个就是主设备号。如果填写的值为0操作系统会分配一个主设备号。name设备名称。fops操作方法结构体。 返回值 major 0成功返回0失败返回错误码负数。major 0成功返回分配的主设备号失败返回错误码负数。 查看设备信息 cat /proc/devices 字符设备驱动的注销 函数原型 void unregister_chrdev(unsigned int major, const char *name); 参数 major主设备号。name设备名称。 返回值无。 就分享到这希望可以帮到你吧~