Linux驱动
进阶嵌入式的boy
最近打算考一下软考证书,有兴趣一起学习可以联系我
展开
-
驱动:11.4 内核中自带的按键驱动程序分析
1 platform_driver 的实现drivers/input/keyboard/nxp_io_key.c nxp_key_probe(){ input = input_allocate_device(); input->name = "Nexell Keypad"; input->evbit[0] = BIT_MASK(EV_KEY) input->evbit[0] |= BIT_MASK(EV_REP);原创 2020-06-23 09:42:08 · 306 阅读 · 0 评论 -
驱动:11.2 总线驱动模型
为了统一芯片设备驱动框架内核中设计了一套1.总线struct bus_type{ const char *name;}bus_registervoid bus_unregister(struct bus_type *bus);ls /sys/bus/2.设备struct device{ struct bus_type *bus; //该设备挂在那条总线上 ...}int device_register(struct device *dev);void device_unre原创 2020-06-22 11:54:35 · 136 阅读 · 0 评论 -
驱动:11.3 platform总线
1.总线driver/base/platform.cbus_register(platform_bus_type);2.设备struct platform_device{ //platform_device.h 派生类 const char *name; struct device dev; // 基类 u32 num_resoutces; //资源个数 struct resource *resoutce; //资源信息的地址 ...}int platform_dev原创 2020-06-22 11:53:32 · 184 阅读 · 0 评论 -
驱动:11.1 找出内核中自带的按键驱动程序
移植课:配置是如何影响编译过程的驱动课:将内核中自带按键驱动程序裁剪掉help中有下图中的信息变量:CONFIG_KEYBOARD_NXP_KEYDefined at drivers/input/keyboard/Kconfig:583此文件中对应了该变量相应的.o文件便可找到对应的.c文件按键驱动: drivers/input/keyboard/nxp_io_key.c为什么看起来我们写的驱动程序和内核写的驱动程序区别很大呢?请看下一节...原创 2020-06-22 10:02:42 · 177 阅读 · 0 评论 -
驱动:10.2 input子系统
1)按键键值标准化的问题 2)按键键值缓冲区的问题 它本质上应该是一个循环缓冲队列 用户进程对该缓冲区执行读操作 中断处理过程要对该缓冲区执行写操作 它属于共享资源,如何解决竞态? 建议尝试编程 3) 按键按住不放 按下保存了键值后 开启一个新的定时器 该定时器隔一段时间就向按键缓冲区存储一个键值 ... 当释放按键动作产生时停止该定时器 建议尝试1.什么是input子系统它是内核中的一部分代码Linux中随着支持的硬件设.原创 2020-06-20 23:42:37 · 220 阅读 · 0 评论 -
驱动:9.3 mmap
内存管理:是将物理内存映射到3-4G内核空间使得可以在内核空间操作物理内存ioremap:是将IO设备映射到3-4G内核空间使得可以在你和空间操作特殊功能寄存器mmap:是将物理内存/特殊功能寄存器映射到0-3G的用户空间使得在用户空间可以直接控制硬件int mmap(struct file *file, struct vm_area_struct *vma)void *mmap(void *addr, size_t length, int prot, int flags, int fd, o原创 2020-06-19 17:39:52 · 170 阅读 · 0 评论 -
驱动:9.2 ioremap
将特殊功能寄存器物理地址进行映射通过映射之后的虚拟地址访问特殊功能寄存器统一编址:将内存和外设(特殊功能寄存器) 使用同一套地址编号去编址,称作统一编址 ARM处理器 访问内存 ldr/str 访问外设 ldr/str独立编址:将内存和外设(特殊功能寄存器) 各自使用一套独立的编号去编址,称作独立编址 X86处理器 访问内存 mov 访问外设 in / outlinux内核中将使用统一编址的外设称为I/O内存 独立原创 2020-06-19 14:56:44 · 192 阅读 · 0 评论 -
驱动:9.1 内存管理
人家如何管理的我们怎么使用呢1、需要掌握的基本概念1)内核管理内存是以物理内存页为基本单位,通常一个物理内存页为4KB内核会为每个物理内存页创建一个struct page类型的对象struct page{ atomic_t _count;//记录该物理内存页被引用的次数 为0 代表空闲页}2)内核管理内存时对所有的内存并不是一视同仁 低端内存:<896M(可调)的内存,采用静态的映射方式 虚拟地址 -0xc0000000+物理偏移 例如物理地址为0x40000原创 2020-06-19 14:08:51 · 154 阅读 · 0 评论 -
驱动:8.3设备的非阻塞方式访问
应用程序:fd = open("/dev/mybuttons",O_RDONLY); //阻塞方式fd = open("/dev/mybuttons",O_RDNLY|O_NONBLOCK);//非阻塞方式驱动程序:也需要支持非阻塞方式代码示例:#include <linux/init.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/cdev.h>#incl原创 2020-06-17 17:34:20 · 148 阅读 · 0 评论 -
驱动:8.2按键去抖
使用定时器或底半部延时工作队列按下去抖的-代码示例:#include <linux/init.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/cdev.h>#include <linux/device.h>#include <linux/interrupt.h>#include <linux/uaccess.h>#include原创 2020-06-17 16:41:37 · 173 阅读 · 0 评论 -
驱动:8.1设备的阻塞方式访问
用户空间:recv/acceptfd = open("/dev/mybuttons",…);read(fd,buf,len);//有数据读,无数据等待驱动程序:要是实现设备的阻塞方式操作,要使用内核中的等待队列机制等待队列的核心数据结构:struct __wait_queue_head { spinlock_t lock; struct list_head task_list;};typedef struct __wait_queue_head wait_queue_head_t;原创 2020-06-17 15:08:58 · 208 阅读 · 0 评论 -
驱动:7.1内核中的竞态与并发
1.基本概念竞态,竞争的状态 竞争共享资源共享资源 硬件(串口 LCD 声卡 。。。) 多线程可见的全局变量,多线程编程实现的生产者消费者模型中的仓库 进程之间使用的共享内存临界区,访问共享资源系统中产生竞态的原因: 1)SMP(对称多处理器) 2)任务和任务之间的抢占 3)任务和中断服务之间的抢占 4)中断服务程序和中断服务程序之间的抢占练习:希望按键能够实现独占式访问#include <linux/init.h>#include <linux/modu原创 2020-06-16 12:00:05 · 175 阅读 · 0 评论 -
驱动:6 内核定时器
系统时钟中断:选取一个硬件定时器,对该硬件定时器作出相应的初始化,使得该定时器产生周期性的系统时钟中断setup_irq(info->irqno, &timer_event_irqaction);timer_event_handler:会调用tick_periodic更新墙上时间计算当前线程的时间片是否耗尽如果耗尽重新执行任务调度jiffies++;…HZ:它是一个宏它对规定了每秒钟产生的系统时钟中断次数当前所使用的系统 HZ=1000tick:系统滴答时钟节拍tic原创 2020-06-15 17:58:51 · 104 阅读 · 0 评论 -
驱动:5.2中断处理函数的特点及底半部登记方式
函数的可重入性问题:判断一个函数是否具有可重入性的标准,就是函数是否使用了全局变量如果使用了全局变量,那么它就不具有可重入性1.中断处理函数的特点:1)短而有效率(很快直接结束)中断处理函数中不应该调用那些执行速度比较慢 比较耗时子函数2)Linux中断处理函数中,不能调用引起阻塞或者睡眠的函数copy_to_user / copy_from_user / msleep3)Linux系统中中断处理函数运行于中断上下文,使用独立的栈空间,该栈空间通常为1个物理内存页(4KB)意味着中断处理函原创 2020-06-13 21:11:54 · 956 阅读 · 0 评论 -
驱动:5.1Linux系统中关于按键中断异常处理
1.回顾裸板中按键中断异常是如何处理的中断触发要做的三级配置—>中断源级------>配置中断的检测模式------>中断使能—>中断控制器------>中断的优先级------>中断使能------>中断信号可以发往核------>中断是以IRQ/FIQ上报—>ARMcore级------>中断使能异常产生后硬件自动做的4件事—>1)备份CPRS—>2)修改CPRS—>3)保存返回地址到LR—&g原创 2020-06-13 11:47:41 · 366 阅读 · 0 评论 -
驱动:4.4设备文件的自动创建
设备文件自动创建:设备插上后自动生成对应的设备文件1.实现设备文件自动创建的条件1)根文件系统中必须存在可执行 mdev2)配置热插拔事件对应的处理方式vi /etc/init.d/rcSecho /sbin/mdev >/proc/sys/kernel/hotplug热拔插事件定义:狭义上,U盘的插入和拔出广义上,/sys目录下文件的变化3)挂载了procfs 和sysfs 虚拟设备vi /etc/fstabproc /proc proc defaults原创 2020-06-13 08:53:04 · 238 阅读 · 0 评论 -
驱动:3.3ioctl
用户空间:使用ioctl可以用来设置、获取设备的工作属性参数ioctl(fd,cmd);ioctl(fd,cmd,&arg);内核空间:.unlocked_ioctl = led_ioctl 为成员变量函数指针赋值实验步骤:vi led_drv.c#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <sys/ioctl.h>#define LED_原创 2020-06-12 16:07:36 · 153 阅读 · 0 评论 -
驱动:3.2内核空间和用户空间的数据交互
write(fd,buf,len)//调用内核中的磁盘驱动程序将用户空间buf中的数据写入到磁盘设备read(fd,buf,len)//调用内核中的磁盘驱动程序将磁盘中的数据写入到用户空间的buf原则:1)用户空间代码不能访问内核空间数据2)内核空间代码也不直接访问用户空间数据访问前先做权限检查 再找做读写操作内核中提供的间接访问用户空间数据的API:#include <linux/uaccess.h>unsigned long __must_check copy_to_us原创 2020-06-12 14:51:51 · 274 阅读 · 0 评论 -
驱动 :3.1内核态控制led
电路原理图:控制LED1,就是控制cpu上的GPIOC12管脚cpu datasheet:GPIOC12配置输出模式控制输出高/低电平GPIOCALTFN0GPIOCOUTENBGPIOCOUT内核态控制GPIO管脚有两种方式:1)类似裸板中直接通过特殊功能寄存器控制2)通过GPIO库函数(本质就是将操作特殊功能寄存器的过程封装起来了)这里我们使用第二种方式Linux系统中使用GPIO库函数的标准套路(gpio_left.c):1)申请GPIO管脚int gpio_requ原创 2020-06-12 11:20:01 · 200 阅读 · 0 评论 -
驱动 2.3 字符设备驱动编程框架
Linux内核绝大部分代码是由c语言实现的但是Linux内核中大量运用了面向对象的编程思想c语言实现面向对象主要依靠struct在内核中实现一个字符设备(例如LED 键盘 鼠标 触摸屏…)的驱动程序其本质就是实例化一个struct cdev类型的对象 并注册到内核中去即可struct cdev { //字符设备驱动框架的核心数据结构 ... const struct file_operations *ops; dev_t dev;};1.设备号本质就是一个32bit的无符号数据设原创 2020-06-11 00:03:31 · 125 阅读 · 0 评论 -
驱动 2.2系统调用
面试题:谈谈对系统调用的理解uc系统调用函数:open read write lseek socket bind listen accept recv fork …1.系统调用的作用 保证用户空间以安全的方式访问内核中的函数2.系统调用是如何实现的 当产生系统调用时 用户空间受限会向特定寄存器中填入一个编号 然后执行一个特殊的指令,该指令的执行会导致内核收到一个软中断异常 软中断异常后,会跳转到异常向量表执行软中断处理代码 软中断处理代码根据填入寄存器的编号 在内核中找到对应的函数,并原创 2020-06-10 12:19:54 · 172 阅读 · 0 评论 -
驱动:2.1模块参数
用户态编程:./a.out xxx yyy zzz内核态编程insmod xx.ko 参数1 参数2 参数3 。。。。。。为了达到以上效果 内核中提供了两个宏module param(name,type,perm)作用:将一个变量声明为模块参数name,变量名称(要把那个变量声明为模块参数)type,变量的类型支持的类型 int short long bool charp//char *perm,权限module_param_array(name,type,ptr,perm)作用原创 2020-06-10 10:45:06 · 163 阅读 · 0 评论 -
驱动:1.2驱动的生成
vi makefileobj-m += hello.oKERNEL = ../../linux/kernelall: make -C $(KERNEL) M=$(PWD)modulesclean: make -C $(KERNEL) M=$(PWD)clean 1 obj-m += hello.o 2 KERNEL = ../../../linux/kernel 3 4 all: 5 make -C $(KERNE...原创 2020-06-09 17:06:31 · 327 阅读 · 0 评论 -
驱动:1.1搭建开发环境
驱动课开发环境 -> kernel:编译通过的内核源码 板子通过tftp方式加载启动内核 -> rootfs:根文件系统数据 板子启动后nfs挂载根文件系统:/home/tarena/driver/rootfs...原创 2020-06-09 11:33:54 · 118 阅读 · 0 评论