小徐的记事本
这个作者很懒,什么都没留下…
展开
-
虚拟网卡驱动代码精读
【代码】虚拟网卡驱动代码精读。原创 2023-08-01 15:32:38 · 245 阅读 · 0 评论 -
网络设备驱动
1.网络设备:主要是负责收发网络的数据包,它将上层协议传递下来的数据包以特定的媒介访问控制方式进行发送, 并将接收到的数据包传递给上层协议。网络接口是Linux第三类标准设备。2.网络设备和块设备类似,在内核的特定数据结构中注册自己。3.当发生网络数据交换时,网络设备驱动程序注册的方法将被内核调用。4.网络设备不会在/dev下存在一个设备入口,它使用保留的内部设备名。在linux下一切皆文件,是标准化接口的一种抽象手段,由于历史原因,网络编程的套接字接口标准早于linux。原创 2023-06-10 11:12:07 · 161 阅读 · 0 评论 -
块设备驱动
系统中能够随机访问固定大小(1block 512byte)数据片的设备被称之为块设备。块设备文件一般都是以安装文件系统的方式使用,这也是块设备通常的访问方式。块设备的方式访问方式是随机的。块设备中最小的可寻址单位是扇区,扇区大小一般是2的整数倍。最常见的大小是512字节。块是文件系统的一种抽象,只能基于块来访问文件系统。物理磁盘寻址是按照扇区的级别进行的,内核访问的所有磁盘操作又都是按照块进行的。扇区是设备的最小可寻址单位,所以块不能比扇区还小,只能数倍与扇区大小。原创 2023-06-10 11:11:54 · 281 阅读 · 0 评论 -
摄像头驱动补充
原创 2023-06-10 11:10:44 · 75 阅读 · 0 评论 -
V4l2应用程序实验
3.检测内核中是否添加了摄像头的设备树,在发fsmp1a-linux-5.4.31/arch/arm/boot/dts目录下如下两个文件为。7.由于图片中没有添加头和尾部信息,所有得到的图片只有数据信息,可以通过YUVviewPlus.exe来显示图片信息。在实验过程中的"$"后的操作在主机上,"#"后的操作在开发板上。4.接上摄像头设备,启动linux内核,检测是否存在摄像头节点。5.将摄像头的应用程序交叉编译后拷贝到rootfs目录执行。1.将内核中的虚拟摄像头驱动从内核中选配掉,默认是选中的。原创 2023-06-10 11:08:25 · 111 阅读 · 0 评论 -
摄像头V4L2驱动框架
编译之后arm-linux-gnueabihf-gcc ov5640_camera_app.c -o ov5640_camera_app,将上述的代码配置到内核之后,重新编译内核 make uImage LOADADDR=0xc2000000 -j4。上述的命令在开发板的终端执行完之后,得到了picturex.yuv但是这个图片不能直接打开,需要配置的驱动的代码DCMI(摄像头控制器),V4L2的核心,ov5640到内核中。因为没有按照图片的格式来存储,这个文件中存储的是图像的原始数据,如果想查看需。原创 2023-06-10 11:07:20 · 301 阅读 · 0 评论 -
摄像头驱动硬件介绍
一、OV5640简介OV5640是OV(OmniVision)公司推出的一款CMOS图像传感器,实际感光阵列为:2592 x 1944(即500w像素),该传感器内部集成了图像处理的电路,包括自动曝光控制(AEC)、自动白平衡( AWB) 等。同时该传感器支持LED补光、 MIPI(移动产业处理器接口,多用于手机等)输出接口和DVP(数字视频并行,在设计HDMI显示时,就用的这个)输出接口选择、 ISP(图像信号处理)以及自动聚焦控制(VCM)等功能。原创 2023-06-10 11:07:48 · 1090 阅读 · 0 评论 -
Linux内核中内存分配
在datasheet中能够查到的地址称之为物理地址,实际设备的操作地址;将程序进行反汇编之后,其中能够看到的地址称之为逻辑地址;在操作系统程序员能够操作的地址称之为虚拟地址;段式管理:x86架构,分段管理。页式管理:arm架构,页式管理。原创 2023-06-09 11:01:54 · 91 阅读 · 0 评论 -
spi总线驱动
CPOL=0,CPHA=0:此时空闲态时,SCLK处于低电平,数据采样是在第1个边沿,CPOL=0,CPHA=1:此时空闲态时,SCLK处于低电平,数据发送是在第1个边沿,CPOL=1,CPHA=0:此时空闲态时,SCLK处于高电平,数据采集是在第1个边沿,CPOL=1,CPHA=1:此时空闲态时,SCLK处于高电平,数据发送是在第1个边沿,也就是 SCLK由低电平到高电平的跳变,所以数据采样是在上升沿,数据发送。也就是 SCLK由低电平到高电平的跳变,所以数据采样是在下降沿,数据发送。原创 2023-06-09 11:01:27 · 116 阅读 · 0 评论 -
i2c总线驱动
start:起始信号:当scl为高电平的时候,sda 从高到低跳变。 stop:停止信号:当scl为高电平的时候,sda 从低到高跳变。 100K(低速) 400K(全速) 3.4M(1Mhz)(高速) ack :应答信号:在第九个时钟周期的时候sda上是低电平。 Nack:非应答 :在第九个时钟周期的时候sda上是高电平。 i2c是一个半双工,同步,串行,具备应答机制的总线协议。注:如下链接是解释7-8-10bit位从机地址寻址过程。有多少个起始信号就有多少个消息,消息的长度以字节来表示。原创 2023-06-09 11:02:40 · 100 阅读 · 0 评论 -
platform总线驱动
platform运用分离的思想,将设备信息和设备驱动分离,分离后借助总线模型device bus driver完成匹配的过程。匹配成功之后执行驱动中的probe函数,在probe中操作硬件即可,如果两者分离执行驱动中的remove。bus就完成匹配的工作(bus是内核实现的)原创 2023-06-09 11:02:08 · 306 阅读 · 0 评论 -
中断底半部机制
什么是中断底半部,为什么需要中断底半部?中断顶半部不能做延时,耗时,甚至休眠的操作,也就是说在中断顶半部中只能做简短的、紧急的、不耗时的操作。但是有的时候又希望在中断到来的时候做尽可能多的操作,所以两者就产生了矛盾,内核为了解决这一矛盾引入了中断底半部的机制。也就是在中断底半部中,可以做不紧急的,耗时的操作。中断底半部的机制分为软中断、tasklet、工作队列。eg:在网卡中断到来的时候,想要在中断处理函数中接收网络数据包,这个过程就是耗时的操作,所以内核将这一操作放在中中断底半部机制中(软中断)。原创 2023-06-09 10:59:58 · 189 阅读 · 0 评论 -
Linux内核定时器
jiffies的频率可以通过make menuconfig进行选配,选配之后在.config中保存着。在使用定时器的时候可以通过jiffies来获取当前的时间,jiffies内核时钟节拍数,在ubuntu内核上定时器每增加1代表走4ms。从内核启动这一刻起,内核时钟节拍数就一直在增加。在开发板内核上定时器每增加1代表走10ms。实例2:使用定时器完成按键中断消抖工作。实例1:(控制6盏灯亮灭闪烁)定时器每加1代表走多长时间。原创 2023-06-09 11:01:10 · 177 阅读 · 0 评论 -
Linux内核中断子系统
interrupts=<中断类型 中断号 触发方式>;触发方式:1上升沿 2下降沿 4高电平 8低电平。触发方式:1上升沿 2下降沿 4高电平 8低电平。中断类型:SGI PPI<1> SPI<0>interrupts=<中断号 触发方式>;设置PC跳转到对应的位置执行。按下开发版的k1、k2、k3。将cpsr保存到spsr中。2.3如果有必要就禁止中断。2.1设置到ARM的状态。中断的cells是3。中断的cells是2。原创 2023-06-09 10:58:58 · 183 阅读 · 0 评论 -
gpio子系统
实现开发板上的6盏灯流水显示(基于gpio子系统和字符设备驱动完成),6盏灯的设备树按照如下格式编写。原创 2023-06-09 10:58:29 · 77 阅读 · 0 评论 -
设备树的介绍
设备树(Device Tree)是种描述硬件的数据结构,在操作系统(os)引导阶段进行设备初始化的时候,数据结构中的硬件信息被检测并传递给操作系统内核设备树官网详解设备树固定含义键值对的详解(V0.3)原创 2023-06-09 10:57:24 · 102 阅读 · 0 评论 -
IO模型的介绍
在同一个APP应用程序中如果想要同时监听多个硬件的数据,此时就需要将这些需要监听的文件描述符放到文件描述符的集合中,然后使用select/poll/epoll来监听这些文件描述符,如果所有的文件描述符对应的硬件数据都没有准备好进程休眠,如果有一个或者多个硬件数据准备好了select/poll/epoll就会被返回,然后从返回的文件描述符中间数据读取到用户空间即可。注:epoll_ctl 支持管道,FIFO,套接字,POSIX消息队列,终端,设备等,但是就是不支持普通文件或目录的fd。原创 2023-06-09 10:59:38 · 73 阅读 · 0 评论 -
串口输入控制灯的亮灭
在串口工具输入led1off -------->硬件LED1熄灭。在串口工具输入led2off -------->硬件LED2熄灭。在串口工具输入led3off -------->硬件LED3熄灭。在串口工具输入led1on -------->硬件LED1点亮。在串口工具输入led2on -------->硬件LED2点亮。在串口工具输入led3on -------->硬件LED3点亮。实验要求:串口输入对应的命令,通过对应的命令,控制硬件工作。原创 2023-06-08 08:13:56 · 920 阅读 · 0 评论 -
选择并发控制机制的原则
1.不允许睡眠的上下文需要采用忙等待类,可以睡眠的上下文可以采用阻塞类。在异常上下文中访问的竞争资源一定采用忙等待类。2 . 临界区操作较长的应用建议采用阻塞类,临界区很短的操作建议采用忙等待类。3 . 中断屏蔽仅在有与中断上下文共享资源时使用。4 . 共享资源仅是一个简单整型量时用原子变量。原创 2023-06-08 08:15:07 · 55 阅读 · 0 评论 -
互斥锁:基于阻塞的互斥机制
a.初始化 struct mutex my_mutex;c.释放互斥体 void mutex_unlock(struct mutex *lock);b.获取互斥体 void mutex_lock(struct mutex *lock);适用场合:任务上下文之间且临界区执行时间较长时的互斥问题。./too /dev/oncedev(第二个终端窗口)会发现第二个终端无法打开设备。1 . 定义对应类型的变量。2 . 初始化对应变量。原创 2023-06-08 08:14:36 · 69 阅读 · 0 评论 -
自旋锁:基于忙等待的并发控制机制
c.获得自旋锁 spin_lock(spinlock_t *);//成功获得自旋锁立即返回,否则自旋在那里直到该自旋锁的保持者释放。b.初始化自旋锁 spin_lock_init(spinlock_t *);spin_lock_init(&lock)后才能正常使用spinlock。d.释放自旋锁 spin_unlock(spinlock_t *);./too /dev/oncedev(第二个终端窗口)a.定义自旋锁 spinlock_t lock;原创 2023-06-08 08:14:09 · 72 阅读 · 0 评论 -
信号量:基于阻塞的并发控制机制
b.初始化信号量 void sema_init(struct semaphore *sem, int val);c.获得信号量P int down(struct semaphore *sem);d.释放信号量V void up(struct semaphore *sem);适用场合:任务上下文之间且临界区执行时间较长时的互斥或同步问题。./too /dev/oncedev(第二个终端窗口)原创 2023-06-08 08:12:04 · 127 阅读 · 0 评论 -
原子变量的介绍
/改变addr的第nr位为1。//测试addr的第nr位是否为1。//设置原子量的值为i。//设置addr的第nr位为1。./too /dev/oncedev(第二个终端窗口)原创 2023-06-08 08:13:13 · 342 阅读 · 0 评论 -
Linux内核中并发和竞态的解决方法
当一个进程获取到自旋锁之后,另外一个进程也想获取这把锁,此时后一个进程处于自旋状态,自旋状态是需要消耗cpu资源的,自旋过程是一个忙等过程,自旋锁又叫忙等锁。当一个进程获取到信号量的时候,此时另外一个进程也想获取这个信号量,后一个进程处于休眠状态。当一个进程获取到互斥体的时候,此时另外一个进程也想获取这个互斥体,此时后一个进程会稍微等一会在进入休眠状态。对于互斥体保护的临界区非常小的时候互斥体的效率高于信号量。原创 2023-06-08 08:10:32 · 86 阅读 · 0 评论 -
中断屏蔽的介绍
适用场合:中断上下文与某任务共享资源时,或多个不同优先级的中断上下文间共享资源时。临界区 //临界区代码不能占用太长时间,需要很快完成。一种同步机制的辅助手段。原创 2023-06-08 08:10:07 · 82 阅读 · 0 评论 -
上下文和并发场合
竞态:多任务并行执行时,如果在一个时刻同时操作同一个资源,会引起资源的错乱,这种错乱情形被称为竞态。为了解决竞态,需要提供一种控制机制,来避免在同一时刻使用共享资源,这种机制被称为并发控制机制。b. 应用进程或线程运行在内核空间(通过调用syscall来间接使用内核空间)执行流:有开始有结束总体顺序执行的一段代码 又称上下文。2 . 异常上下文:不可阻塞 中断上下文。共享资源:可能会被多个任务同时使用的资源。a. 应用进程或线程运行在用户空间。//并发控制机制初始化为不可用。c. 内核线程始终在内核空间。原创 2023-06-08 08:09:29 · 61 阅读 · 0 评论 -
设备号——内核中同类设备的区分
如果已知一个设备的主次设备号,应用层指定好设备文件名,那么可以用mknod命令在/dev目录创建代表这个设备的文件,即此。应用程序打开一个设备文件时,通过设备号来查找定位内核中管理的设备。1 . 主设备号:占高12位,用来表示驱动程序相同的一类设备。2 . 次设备号:占低20位,用来表示被操作的哪个具体设备。原创 2023-06-08 08:09:00 · 229 阅读 · 0 评论 -
字符设备驱动内部实现
inode的功能:1.只要一个文件存在,在文件系统中就会有一个inode结构体来描述这个文件2.inode就是用来描述文件信息的一个结构体3.如果这个文件是设备文件,它会唯一关联一个设备的驱动4.并且在调用open函数的使用inode会作为参数传递给驱动的open函数echo 1 > /dev/myled0 //LED1亮(open write close)echo 0 > /dev/myled0 //LED1灭。原创 2023-06-07 08:28:27 · 66 阅读 · 0 评论 -
自动创建设备节点
define A do{...}while(0)和#define A ({...})都能应用于多语句宏定义,前者没有返回值,后者有返回值,其返回值取决后者的最后一条语句。错误码指针的判断方法是借助地址区间完成的,在linux内核中最顶端的4K位置是预留出来的,用来判断错误码的,如果cls在内核最顶端的4K的位置它就是错误,否则就不是错误。udev(mdev)(2.6内核之后)devfs(2.4内核)创建节点的逻辑在内核空间。原创 2023-06-07 08:27:58 · 76 阅读 · 0 评论 -
ioctl函数的实例
linux内核开发者想让设备的控制和数据的读写分开来做,对数据的读写通过read/write完成,对设备的控制通过ioctl函数完成。例如串口驱动,在进行数据收发前需要设置波特率,数据位,停止位等这些操作可以通过ioctl完成,设置好上述的工作方式后通过read/write完成数据的读写。ioctl:用户设备的控制,比如摄像头,摄像头在拍摄照片的时候可以通过ioctl完成本次图片大小的设置,再比如lcd上的背光灯亮度也可以通过ioctl函数来控制。-I:include,头文件路径。-l:link,链接库。原创 2023-06-07 08:29:08 · 193 阅读 · 0 评论 -
用户空间和内核空间数据传输
内核空间不能够直接通过指针在操作用户空间的内存,如果内核正在通过指针操作内存,此时进程结束,内核就会崩溃。正确的做法是在内核空间开辟自己可以操作的内存,将用户空间的数据拷贝到内核空间之后,内核操作自己的这块内存即可,即使进程意外结束,内核也不会崩溃,这种做法的安全性是要比前者的高的。驱动在Ubuntu上执行:make/驱动在开发板上执行:make ARCH=arm。原创 2023-06-07 08:25:50 · 415 阅读 · 0 评论 -
字符设备驱动
dmesg ====>申请到的主设备号是235。lsmod====>查看驱动是否安装。原创 2023-06-07 08:25:23 · 66 阅读 · 0 评论 -
内核模块导出符号表
在内核中有的模块都是运行在同一个3-4G的内核空间的,模块和模块间就可以进行函数的直接调用,在调用前只需要将被调用函数的符号表导出即可。在demoA模块中有一个add函数,在demoB模块中想调用demoA模块中的add函数,此时只需要让demoB模块拿到demoA模块中add函数的地址即可。这个过程就使用导出符号表完成。原创 2023-06-07 08:24:01 · 306 阅读 · 0 评论 -
linux内核模块传参
2.char *-charp在传递字符串的时候不能有空格,否则获取的是空格前的字符串,若想要在dmesg打印信息中的字符串中包括空格,空格用下划线‘_’代替。可以通过modinfo hello.ko查看MODULE_PARM_DESC信息。1.char-byte不能传递字符,而是传递的整数值。1.使用内核模块传参传递字符和字符串。3.在传参的时候最大权限是0664。用户:rw 组:rw 其他:w。②通过sysfs目录下的文件修改。即无操作权限,不能超过0664。2.使用内核模块传参传递数组。原创 2023-06-07 08:23:32 · 207 阅读 · 0 评论 -
驱动的多文件编译
在执行当前的Makefile的时候,要变异生成hello.o,默认会在当前目录下找hello.c,但是当前目录并没有hello.c文件,所以Makefile就会在当前文件找hello的依赖关系,通过这依赖关系找到对应的.c文件,并把他们编译产生hello.o,然后编译器会把这个hello.o最终生成hello.ko。原创 2023-06-07 08:21:28 · 153 阅读 · 0 评论 -
内核模块中打印语句的使用
linux内核中一共有8种打印级别,可以用来过滤打印信息,数值越小级别越高。只要消息的默认级别大于终端的级别,消息就可以主动在终端回显。ctrl+alt+fn+[F2-F6] 进入虚拟终端。sudo dmesg -c 先回显后清除打印信息。ctrl+atl+fn+F1 退出虚拟终端。printk(打印级别 "打印信息");sudo dmesg -C 清除打印信息。printk("打印信息");dmesg 查看驱动的打印信息。注:默认消息级别修改。原创 2023-06-07 08:20:45 · 344 阅读 · 0 评论 -
Linux内核模块
步骤如下:(将内核软连接到家目录下:ln -s /home/linux/kernel/linux-5.10.61-new/linux-5.10.61 ~/linux-5.10.61)⑧进入~/kernerl/linux-stm32mp-5.10.10-r0/linux-5.10.10/drivers/char。⑪回到~/kernerl/linux-stm32mp-5.10.10-r0/linux-5.10.10/drivers/char。①进入~/linux-5.10.10/drivers/char。原创 2023-06-06 08:56:43 · 69 阅读 · 0 评论 -
Ubuntu上ctag的使用
从__init、__exit、module__init、module__exit、MODULE_LICENSE入手。如果没有打开文件:vi -t 函数/变量名。追代码:ctrl+]原创 2023-06-06 08:56:16 · 337 阅读 · 0 评论 -
驱动的种类
块设备驱动:按照block(512字节)来访问,可以顺序访问也可以无序方法的设备。网络设备驱动:结合网络协议栈,操作网卡硬件实现数据收发的代码(没有设备节点)驱动一共分为三种:字符设备驱动,块设备驱动,网络设备驱动。字符设备驱动:按照字节流来访问,只能顺序方法的设备。原创 2023-06-06 08:57:26 · 166 阅读 · 0 评论 -
什么是驱动?
广义上:软件控制硬件工作的代码就是驱动。原创 2023-06-06 08:55:22 · 138 阅读 · 0 评论