70天 Linux(韦东山驱动基础))
小甲鱼T
这个作者很懒,什么都没留下…
展开
-
4.3_内核目录里编译驱动
1、如下图,如果划红线部分为y,表示把后面这个驱动程序编进内核里面去,成为内核映像的一部分。如果为m,就不会编译进内核映像里,将会称为一个ko文件。3、怎么使变量和文件产生联系通过,编辑内核里面的Makefile。有些驱动程序要么编译进内核,要么编译成模块,可通过对之前的变量进行设置。内核目录的源码第一可以编译成.ko,第二可以编译进内核的映像文件里。3、配置内核成功后,编译有问题的话,一般是没有设置ARCH.2、布尔变量只有两个取值,要么“y”,要么“N”4、如果配置成m,make modules。转载 2022-11-18 17:50:50 · 129 阅读 · 0 评论 -
4.2_在内核目录外编译模块
上面图片make - C的“C”是指Changeddir。1、KERN_DIR的目录有问题;二、Makefile讲解。2、没有设置工具链;转载 2022-11-18 17:49:13 · 107 阅读 · 0 评论 -
4.1_LED驱动程序分析
这个“__user”是一个空的宏,那为什么要放一个空的宏在这里呢?起到提示用户的作用,表明这个buf是由用户传进来的,内核里面不可以直接访问这个buf。通过使用copy_from_user,将buf拷贝进val。转载 2022-11-18 17:47:57 · 66 阅读 · 0 评论 -
3.5_答疑
链接不是将各类.o文件放入内存,而是将.o文件打包到一起,并对用到的函数、变量等分别分配地址,然后生成一个文件。如下图所示,在a.o、b.o中定义全局变量int a 、int b,在main.o中定义函数f1,链接时,会将这些文件都分配一个地址,然后放到文件中。单片机只有main函数,链接的时候是哪个地址,烧写的时候就在哪个地址。对于多任务系统,同一个函数可能多次同时运行,所以得有多个位置,这些位置不是事先确定的,所以链接的时候用的虚拟地址,运行的时候用的物理地址。转载 2022-11-18 17:46:35 · 53 阅读 · 0 评论 -
3.4_class_create和device_create
驱动和应用联系:通过两个函数“copy_to_user”和“copy_from_user”2、驱动程序辅助信息(自动创建类和节点)驱动和硬件联系:虚拟地址等。1、驱动和其他的数据传输。转载 2022-11-18 17:45:41 · 165 阅读 · 0 评论 -
3.3_为什么需要虚拟地址
而在Linux芯片中,内存很大,加入几个程序同时运行如果没有内存映射,会使用新的地址去访问f1,会很麻烦,如下图所示。先介绍链接地址,在单片机系统中,每个函数在RAM/Flash中都有一个确定的地址,运行时对地址进行链接。转载 2022-11-18 17:44:15 · 215 阅读 · 0 评论 -
3.2_地址片选与虚拟地址的引用
如下图所示,在cpu与外设之间,有一个内存控制器,CPU将address的范围发送给内存控制器,然后内存控制器根据地址范围将对应的CSx设置为0,从而控制对应的外设。在单片机上用的是物理地址直接控制对应的外设,单片机CPU上有内存,称为SOC:system on chip。Linux芯片的硬件如下(注意Linux芯片有的有ARM,有的没有。问题: 如下图所示,为什么打印的值不同,而打印的地址相同?要解释这个问题,就要引用虚拟地址的概念。在MPU中,引用了虚拟地址的概念。转载 2022-11-06 21:48:18 · 170 阅读 · 0 评论 -
3.1_驱动辅助信息及地址空间概念
如下图所示,驱动和应用之间通过“copy_to_user”和“copy_from_user”进行数据传输。通过ioremap,将物理地址映射为虚拟地址。3、软件层 argc 和 argv讲解。2、驱动和硬件之间怎么进行数据传输?1、 驱动和软件怎么进行数据传输?转载 2022-11-06 21:46:55 · 60 阅读 · 0 评论 -
2.4_数据交互
open文件的时候,这个必须是一个节点,主设备号很重要,根据主设备号找到chrdevs[]中对应的那一项,进而找到对应的结构体。因为这个write函数是要提供给应用层去调用的,调用的时候要求这个函数的返回值是读取到数据的长度,这是系统调用接口函数的规定。3、Linux中echo本质是打开设备节点,然后写数据,cat本质是打开设备节点,然后读数据。1、如下图,为什么write函数的返回值要和copy_from_user中的那个长度一样。4、软件程序中,open怎么寻找驱动程序的?转载 2022-11-06 17:12:27 · 793 阅读 · 0 评论 -
2.2_入口出口细讲
入口函数在驱动装载之后就再也用不到了,所以可以在装载之后进行销毁,因此可以加上__init。如果驱动程序编进内核,就无法卸载,就无需出口,出口函数就无意义。加上__exit,就可以卸载了。1、在驱动程序中,打印用printk,在应用程序中,打印用printf。printk的信息先会存入kerBuf中,可以调用dmesg进行查看。3、任何一个驱动的入口函数都是init_module。4、驱动程序入口函数加__init的作用。5、驱动程序出口函数加__exit的作用。2、内核里的信息,用dmesg。转载 2022-11-06 17:09:59 · 113 阅读 · 0 评论 -
2.1_字符设备驱动回顾与数据流程
注:注册的本质就是将file_operation结构体放入数组chrdevs[]中。2、怎么写驱动程序套路。转载 2022-11-06 17:06:53 · 42 阅读 · 0 评论 -
1.4_深入答疑
在一个驱动程序中,一个函数的的入口函数是固定的,如下图示,调用init_module就相当于调用了hello_init。如果不使用module-init(hello_init)这个宏的话,可以把他注释,然后将入口函数命名为init_module。module-init(hello_init)将hello_init函数定义为一个入口函数,然后通过注册函数register_chrdev将设备号放入chardevs[]里面。以LED灯为例,主设备号表示灯这个驱动,次设备号表示不同的灯。2、次设备号起什么作用?转载 2022-11-06 17:05:38 · 80 阅读 · 0 评论 -
1.3_字符设备驱动程序框架
先确定是什么文件(类别),在确定主次设备号。要想解决怎么写驱动的问题,就先要找到驱动?转载 2022-11-06 16:59:57 · 41 阅读 · 0 评论 -
1.2_Linux应用程序与驱动程序的接口
硬件事件产生的就是硬件中断,软件事件产生的就是软件中断。SWI是硬件中断吗?怎么区分软硬件中断?驱动 = 框架 + 硬件操作。APP调用驱动流程图。转载 2022-11-06 16:58:09 · 75 阅读 · 0 评论 -
1.1_单片机程序与Linux程序的分层
(4)、根据R分辨原因,如R = val1,调用sys_open函数,R = val2,调用sys_read等。在里面首先会判断文件名,然后在找到对应的驱动,调用drv_open。1、为了效率更高,Linux开了一个后门,如下图划线所示,以后访问addr = mmap()的时候就相当于访问了指定的硬件地址,但是也得通过驱动程序。(2)、在某个寄存器R中设置某个值,并产生SWI异常;(1)、应用层在glib.c库中调用open函数;(3)、CPU调用内核中SWI异常处理函数;转载 2022-11-06 16:51:37 · 132 阅读 · 0 评论