
大学期间Linux驱动与应用开发学习
文章平均质量分 88
Linux YYDS
苦梨甜
嵌入式全栈ing
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
pinctrl_desc结构体注册
首先,pinctrl_register_one_pin 函数用于注册单个引脚,它分配内存并初始化引脚描述符,然后将其插入到引脚描述符树中。其次,pinctrl_register_pins 函数用于注册一组引脚,它遍历引脚描述符数组并调用 pinctrl_register_one_pin 函数来逐个注册引脚。接着,函数会注册所有的引脚,调用 pinctrl_register_pins 函数进行引脚的注册。如果注册过程中发生错误,则会打印错误信息,释放已注册的引脚描述符,并跳转到错误处理标签 out_err。原创 2023-08-07 12:59:35 · 657 阅读 · 0 评论 -
中断控制器(GIC)
上篇大概讲了一下ARM的异常处理,但是处理器是如何知道是哪一种异常或中断的呢?这就需要中断控制器了。原创 2022-11-19 14:43:54 · 1865 阅读 · 0 评论 -
应用层open->软中断指令->底层驱动xxx_open
驱动程序中实现file_operations中的open函数,在应用层中使用open来调用到内核中实现的file_operations中的open函数,那么如何实现的呢?原创 2022-12-02 21:40:09 · 531 阅读 · 0 评论 -
自旋锁
设计自旋锁的最初目的是在多处理器系统中提供对共享数据的保护,其背后的核心思想是:设置一个在多处理器之间共享的全局变量锁v,并定义当V=I时为上锁状态,V=0为解锁状态·如果处理器A上的代码要进入临界区.它要先读取V的值,判断其是否为0,如果V不等于0表明有其他处理器上的代码正在对共享数据进行访问,此时处理器A进入忙等待即自旋状态,如果V=O表明当前没有其他处理器上的代码进入临界区,此时处理器A可以访问该资源,它先把V置1(自旋锁的上锁状态).然后进入临界区,访问完毕离开临界区时将V置0(自旋锁的解锁状态)原创 2023-02-08 16:09:59 · 801 阅读 · 0 评论 -
第二十六章 linux-i2c子系统一
12C(lnter—lntegrated Circuit),PHILIPS公司丿发的两线式半双工同步串行总线,具有接口线少,控制方式简单,通信速率较高等优点。i2C为电平触发方式(数据先发高位,再发低位)SDA线上的数据必须在SCL的高电平周期保持稳定。i2C是一个多主机的总线,每个设备既可以当主控器或被控器,又可作为发送器或接收器,一条总线上可以有多个主机,但同一时刻只允许一个主机工作。每个支持i2c总线的设备,它都会有一个可以代表自己的地址。半双工:不能同时收发数据,数据发时不能接收,比如i2c。原创 2022-12-13 20:39:45 · 293 阅读 · 0 评论 -
用户空间与内核空间通信方式
get_user和put_user相对于copy_from_user和copy_to_user,这两个函数主要用来完成一些简单类型变量(char、int、long等)的拷贝任务,对于一些复合类型的变量,如数据结构或者数组类型,get_user和put_user函数则无法胜任:函数内部将对ptr所指向的对象长度进行检查,大部分平台只支持长度为1,2,4的变量。get_user将用户空间ptr指向的数据拷贝到内核空间的变量x中,函数如果成功则返回0,否则返回-EFAULT。原创 2023-03-06 22:04:56 · 457 阅读 · 0 评论 -
互斥锁mutex
如果在程序执行期间要初始化一个mutex变量,则可以使用mutex_init宏。原创 2023-03-05 14:26:02 · 944 阅读 · 0 评论 -
按键消抖的两种方法--中断延迟工作与定时器
按键由于物理特性,按下瞬间会多次置为 1/0,俗称抖动。所以我们需要给一个合理的延时,来判断是否按下按钮,为了实现这个延时我们可以使用中断延迟工作和定时器来实现,下面是具体实现的方法。原创 2023-03-23 19:02:07 · 2261 阅读 · 1 评论 -
总线驱动---IIC驱动
Linux的I2C体系结构分为3个组成部分。(1)I2C核心I2C核心提供了I2C总线驱动和设备驱动的注册、注销方法,I2C通信方法(即Algorithm)上层的与具体适配器无关的代码以及探测设备、检测设备地址的上层代码等,如图15.1所示。(2)I2C总线驱动I2C总线驱动是对I2C硬件体系结构中适配器端的实现,适配器可由CPU控制,甚至可以直接集成在CPU内部。I2C总线驱动主要包含I2C适配器数据结构i2c_adapter、I2C适配器的Algorithm数据结构i2c_algorithm和原创 2023-04-04 15:22:28 · 1794 阅读 · 0 评论 -
内核模块
modprobe在识别出目标模块所依赖的模块之后,在内核中也会使用insmod,在用户空间对模块的处理也是基于insmod。因为模块使用了持久编译到内核中的函数,在模块本身编译时无法确定这些函数的地址,所以的要在这里处里未定义的引用。内核中驻留的每一个模块,都分配了该结构的一个实例。模块使用ELF二进制恪式,模块中包含了几个额外的段,普通的程序或库中不会出现。处理未解决的引用,为与内核的剩余部分协作,模块必须使用内核提供的函数。当然,前提是该模块的代码不再使用,并且其他模块也不再使用该模块导出的函数。原创 2022-12-03 12:59:15 · 1111 阅读 · 0 评论 -
ov2640子设备视频操作详细分析
如果 mf->code 是 MEDIA_BUS_FMT_RGB565_2X8_BE 或 MEDIA_BUS_FMT_RGB565_2X8_LE,则选择 SRGB 颜色空间;flags 表示总线配置的标志,包括 V4L2_MBUS_PCLK_SAMPLE_RISING、V4L2_MBUS_MASTER、V4L2_MBUS_VSYNC_ACTIVE_HIGH、V4L2_MBUS_HSYNC_ACTIVE_HIGH 和 V4L2_MBUS_DATA_ACTIVE_HIGH。原创 2023-05-23 09:23:41 · 1991 阅读 · 0 评论 -
uboot移植到IMX6ULL平台详细过程
I.MX6UL/ULL 内部有个以太网 MAC 外设,也就是 ENET,需要外接一个 PHY 芯片来实现网络通信功能,也就是内部 MAC+外部 PHY 芯片的方案。大家可能听过 DM9000 这个网络芯片,在一些没有内部 MAC 的 CPU 中,比如三星的 2440, 4412 等,就会采用 DM9000 来实现联网功能。DM9000 提供了一个类似 SRAM 的访问接口,主控 CPU 通过这个接口即可与DM9000 进行通信, DM9000 就是一个 MAC+PHY 芯片。原创 2023-04-07 15:23:09 · 1374 阅读 · 0 评论 -
platform设备驱动
编写字符设备驱动基本上都要实现以下内容:1.实现入口函数xxx_init()和卸载函数xxx_exit()2.申请设备号register_chrdev(与内核有关)3.注册字符设备驱动cdev_alloc cdev_init cdev_add(与内核有关)4.利用udev/mdev机制创建设备文件(节点),class_create,device_create(与内核有关)5.硬件部分初始化io资源映射ioremap,内核提供gpio库函数(与硬件相关)原创 2022-11-11 19:34:20 · 674 阅读 · 0 评论 -
IMX6ULL平台I2C数据结构分析
在 i.MX 平台的 I2C 驱动中,存在多个相关的结构体,它们之间的联系和在内核中的作用如下:struct i2c_client:表示一个 I2C 从设备的结构体,用于描述从设备的信息。它包含了从设备的地址、名称、适配器等信息,并提供与从设备进行通信和交互的接口。struct i2c_adapter:表示一个 I2C 控制器适配器的结构体,用于管理 I2C 控制器的相关信息。它提供了控制器的配置、数据传输和中断处理等功能。原创 2023-05-24 12:54:35 · 1298 阅读 · 0 评论 -
模块的加载过程三
这种情况下simplify_symbols函数会调用resolve_symbol函数来处理该未定义符号,后者会调用find_symbol函数去查找该符号(详细的查找过程见本章前面的"find_symbol函数”部分),如果找到了,就把它在内存中的实际地址赋值给st_valueo如此,经过simplify_symbols函数的调用之后,内核模块符号表中的所有符号就都有了正确的st_value值,也即都有了正确的内存地址。这是个很严重的问题。如此,内核模块导出符号的地址在系统执行完重定位之后被更新为正确的值。原创 2022-12-19 21:33:52 · 1122 阅读 · 0 评论 -
字符设备的编写二
上一篇文章介绍了一下字符设备编写的步骤,仅此而已,想要真正掌握字符设备编写,需要对其包含的数据结构有所掌握,这才是重要的。字符设备就暂时学习到这,后面将继续为大家分享。原创 2022-10-31 13:55:20 · 152 阅读 · 0 评论 -
platform_get_resource=NULL内核源码分析
of_translateone返回1of_translate_address回OFBAD_ADDRofaddresstoresource返回EINVALofaddresstoresource返回EINVAL所以numreg为0,通过代码的分折,当有ranges属性的时,但是属性值为0,则不对地址进行转,所以在设备节点中添加ranges属性即可。原创 2023-05-11 20:34:39 · 1538 阅读 · 0 评论 -
休眠与唤醒
当应用程序必须等待某个时间发生,比如必须等待按键被按下时,可以使用“休眠-唤醒”机制,这一机制近似于,你是个早起困难户,想要早起,必须等待闹钟响了,才会起床。原创 2022-11-05 21:14:35 · 2780 阅读 · 0 评论 -
Linux开发环境配置详细过程--正点原子阿尔法开发板
编辑->虚拟网络编辑器设置->更改设置->添加网络VMnet0并设置为桥接模式->保存后还原默认设置。上述设置后Ubuntu中会有两个网卡的信息,一个用来让Ubuntu上网,另一个用于为开发板提供网络。配置ens38网卡信息与前面虚拟网络编辑器中NAT模式的网卡信息在同一子网下。编辑虚拟机设置->添加->网络适配器->设置添加的网络适配器为NAT模式。设置开发板为sd卡启动,上电启动uboot,进入uboot命令模式。如图所示,网卡ens38让虚拟机上网,ens33为开发板提供网络。重新加载网络配置文件。原创 2023-03-06 21:46:03 · 2666 阅读 · 0 评论 -
device_node转换成platform_device
设备树替换了平台总线模型当中对硬件资源描述的device部分。所以设备树也是对硬件资源进行描述的文件。在平台总线模型中,device部分是用platform_device结构体来描述硬件资源的。所以内核最终会将内核认识的device_node树转换platform_device。但是并不是所有的节点都会被转换成platform_device,只有满足要求的才会转换成platform_device,原创 2023-05-11 20:32:03 · 948 阅读 · 0 评论 -
顺序锁seqlock
在此基础上sequence提供的另外一个信息是写入过程有没有结束,这是用sequence的最低位来完成的,如果sequence & 0为0表明写入过程己经结束,否则表明写入过程正在进行·接下来会在读取者的seqlock作数中看到sequence的这两种用途。读取者在开始读取前读取该sequence,在读取后再重读该值,如果与之前读取到的值不一致,则说明本次读取作过程中发生了数据更新,读取操作无效,因此要求写入者在开始写入的时候要更新sequence的值。写入者与写入者之间并不需要sequence。原创 2023-03-10 19:50:29 · 704 阅读 · 0 评论 -
设备树二
后缀名一般为dts和dts主,可以被include,甚至可以include那些c语言的头文件dtsi主一般写soc共性部分,而dts—般写目标单板特性部分,所以一般dts包含并重写部分dtsi注释用/* */,注意#开头的不是注释分号是段落块之间的分隔符,{}和[]是段落块的封装符号,和c语言语言类似/dts-v1/节点,表示dts的版本号,目前都是vl/{}是根节点root node,理论上只应该有一个根节点,有说法dtc会合并所有root node为同一个。原创 2022-12-16 20:44:54 · 1825 阅读 · 3 评论 -
并发与竞争
并发会造成多个程序同时访问一个共享资源,这时候由并发同时访问一个共享资源而产生的问题就是竞争。比如A和B要打电话,但是公共电话只有一部。A和B要打电话就是并行,谁先打电话就是竞争,所以电话就是共享资源。Linux是一个多任务的操作系统,并发和竞争在Linux中常的常见。所以在编写Linux驱动的过程中就要考虑并发与竞争。否则在访问共享资源的时候容易出问题,而这些问题往往小容易排查,很难定位。原创 2023-02-07 20:20:50 · 581 阅读 · 0 评论 -
驱动编译进Linux内核
每个选项都必须指定类型,类型包括bool,tristate,string,hex,int最常见的是bool,tristate,string这二个。选项的状态有[ ],< >,()三种表示状态,其中[ ]表示有俩种状态,只能设置成选中或者不选中,< >表示有三种状态,可以设置成选中,不选中,和编译成模块。config文件和.config文件都是Linux内核的配置文件,config文件位于Linux内核源码的arch/$(ARCH)/configs目录下,是Linux系统默认的配置文件。这俩个是成对出现的。原创 2023-03-29 17:16:21 · 1466 阅读 · 0 评论 -
模块的加载过程四
sys_init_module第二部分由load_module返回的do_init_module实现。原创 2022-12-20 16:10:46 · 1018 阅读 · 0 评论 -
CMOS摄像头驱动分析
初始化name字段,格式为"driver_name adapter_id-addr",其中driver_name是i2c_client的driver name,adapter_id是i2c_adapter的ID,addr是i2c_client的地址。如果控件类型是菜单(V4L2_CTRL_TYPE_MENU)、整数菜单(V4L2_CTRL_TYPE_INTEGER_MENU)或者复合类型(V4L2_CTRL_COMPOUND_TYPES),则设置处理器的错误信息为EINVAL,并返回空指针。原创 2023-05-23 09:16:26 · 1323 阅读 · 0 评论 -
UVC调用过程部分细节分析
VideoStreaming Interface用于获得视频数据,也可以用来选择fromat/frame(VS可能有多种format, 一个format支持多种frame, frame用来表示分辨率等信息)// 获取视频流格式,等数据,uvc_ioctl_reqbufs->uvc_request_buffers->vb2_reqbuf->__reqbufs分配缓冲区。video->streaming->type 应该是在设备被枚举时分析描述符时设置的。应是设备被枚举时设置的,也就是分析它的描述符时设置的。原创 2023-05-22 13:45:24 · 1301 阅读 · 0 评论 -
Linux性能监控与调优工具
除了保证程序的正确性以外, 在项目开发中往往还关心性能和稳定性。这时候, 我们往往要对内核、应用程序或整个系统进行性能优化。在性能优化中常用的手段如下。原创 2023-05-09 13:11:49 · 908 阅读 · 0 评论 -
模块的加载过程二
总体上,each_symbol_section函数可以分成两个部分:第一部分是在内核导出的符号表中查找对应的符号,如果找到,就通过返回该符号的信息,否则,再进行第二部分的查找:第2部分是在系统中己加载的模块(系统中所有己成功加载的模块都以链表的形式保存在一个全局变量modules中)的导出符号表中查找对应的符号,如果找到就通过返回该符号的信息,否则函数返回false。函数在全局链表modules中遍历所有己加载的内核模块,对其中的每一模块都构造一个新的arr数组,然后在其中查找特定的符号。原创 2022-12-18 15:59:56 · 667 阅读 · 0 评论 -
字符设备的编写一
字符设备是Linux驱动中三大设备之一,字符(char)设备是个能够像字节流(类似文件)一样被访问的设备,由字符设备驱动程序来实现这种特性。字符设备驱动程序通常至少要实现open、close、read和write的系统调用。字符终端(/dev/console)和串口(/dev/ttyS0以及类似备)就是两个字符设备,它们能很好的说明“流”这种抽象概念。字符设备可以通过文件节点来访问,比如/dev/tty1和/dev/lp0等。原创 2022-10-31 13:17:52 · 626 阅读 · 0 评论 -
usb摄像头驱动打印信息
后面将根据打印的信息来分析摄像头相关的驱动。分析一下这些打印信息。原创 2023-05-18 19:10:56 · 1135 阅读 · 0 评论 -
串口,IIC,SPI,USB等总线叙述
之后, 每次传输的数据也是1字节, 从MSB开始传输。PCI-E(PCI Express)是Intel公司提出的新一代的总线接口,PCI Express采用了目前业内流行的点对点串行连接,比起PCI以及更早的计算机总线的共享并行架构,每个设备都有自己的专用连接,采用串行方式传输数据,不需要向整个总线请求带宽,并可以把数据传输率提高到一个很高的频率,达到PCI所不能提供的高带宽。如下图所示, 在SPI总线的传输中, SS信号是低电平有效的, 当我们要与某外设通信的时候, 需要将该外设上的SS线置低。原创 2023-03-25 22:37:31 · 2105 阅读 · 0 评论 -
字符设备驱动编程②(cdev结构)
我们接着讲,我们使用正点原子提供的字符设备驱动的模板来进行讲解。相信大家应该都已经知道代码的意思,我们来分析函数之间的调用关系。/* 注册字符设备驱动 *//* 1 、创建设备号 */ if(newchrled.major) {/* 定义了设备号 */} else {/* 没有定义设备号 *//* 申请设备号 *//* 获取分配号的主设备号 */原创 2022-11-14 20:32:21 · 376 阅读 · 0 评论 -
总线系统
内核支持大量总线,可能涉及多种硬件平台,也有可能只涉及一种平台。在Linux支持的大多数体系结构上都使用了PCI总线。我还会讨论广泛使用、系统无关的USB总线,该总线用于外设。现代总线系统在布局和结构的细节上可能有所不同,但也有许多共同之处,内核的数据结构即反映了这个事实。结构中的许多成员用于所有的总线(以及相关设备的数据结构中)。在内核版本2.6开发期间,一个通用驱动程序模型(设备模型,device model)并入内该,以防止不必要的复制。所有总线共有的屈性封装到特殊的、可以用通用方法处理的数据结构中,原创 2022-12-03 17:06:02 · 828 阅读 · 0 评论 -
sysfs文件系统与kobject
kernfs_mount_ns函数用来产生sysfs文件系统的超级块,其内部调用的最主要的函数是kernfs_fill_super,后者再经过一系列的函数调用链进入到kernfs_init_inode函数,这里之所以重点强调这个函数,是因为在接下来谈到内核对象的属性问题时会看到用户空间和内核对象的沟通问题,这种文件接口形式的交互发生在内核空间和用户空间,所以我们需要知道这条沟通的通道是如何建立起来的。运行上面的代码后,可在/sys/pa_obj/cld_obj目录下看到一名为"cldatt"的属性文件。原创 2022-12-05 20:39:01 · 609 阅读 · 0 评论 -
设备树一
设备树是采用树形结构来描述板子上的设备信息的文件,每个设备都是一个节点,叫做设备节点,每个节点都通过一些属性信息来描述节点信息,属性就是键—值对。节点是由一堆的属性组成,节点都是具体的设备,不同的设备需要的属性不同,用户可以自定义属性。除了用户自定义属性,有很多属性是标准属性, Linux 下的很多外设驱动都会使用这些标准属性。原创 2022-11-07 22:43:52 · 844 阅读 · 0 评论 -
makefile实现创建目录和复制.ko文件
如果已经创建了对应项目的目录就不需要·make file了。原创 2022-10-31 14:54:38 · 2041 阅读 · 0 评论 -
编译进内核的驱动是如何工作的
打开内核源码下的顶层Makefile,驱动编译进内核KBUILD_AFLAGS_KERNEL决定驱动编译成模块KBUILD_AFLAGS_MODULE决定所以这里时驱动编译成模块即。原创 2023-03-29 17:41:36 · 435 阅读 · 0 评论 -
dump_stack分析函数调用关系实例及其实现
在内核态使用的都是 svc mode 的堆栈,那如何把不同线程的堆栈分开呢,实际上内核针对不同线程会分配不同的堆栈地址,而堆栈地址都被存在 task_struct中,这样每次线程调度时就可以把相应的地址设置给 SP 寄存器,由此实现不同内核线程堆栈的切换。kstack_end 是判断是否到达栈底的函数,一个线程堆栈大小为 THREAD_SIZE,SP 寄存器存储的是栈顶,由此可以找到对应的栈底,如果没有到堆栈底部,则每次持续打印出相关的函数调用列表。所以可知使用的是finit_module。原创 2023-05-08 15:08:48 · 1366 阅读 · 0 评论 -
内核是如何运行ko文件的--系统调用
系统调用是操作系统扌是供给编程人员的接囗,当编程人员写程序时,因为上层应用不能直接操作硬件,所以就要利用系统调用接囗来请求操作系统的照务,如访问硬件。系统调用是和CPU架进行绑定的。和内核版本也有关系。回到init_module和finit_module这俩个系统调用就是应用程序调用系统调用,内核就会执行运行ko文件的操作。原创 2023-03-31 18:41:20 · 1913 阅读 · 0 评论