![](https://img-blog.csdnimg.cn/20190918140129601.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
Linux内核之驱动
文章平均质量分 75
linux设备驱动
qxqxa
这个作者很懒,什么都没留下…
展开
-
内核模块的各种概念及示例
在Linux中,所有标识为__init的函数如果直接编译进入内核,成为内核镜像的一部分,在连接的时候都会放在.init.text这个区段内--#define _ _init _ _attribute_ _ ((_ _section_ _ (".init.text")))所有的__init函数在区段.initcall.init中还保存了一份函数指针,在初始化时内核会通过这些函数指针调用这些__init函数,并在初始化完成后,释放init区段(包括.init.text、.initcall.init等)的内存。原创 2024-06-20 11:28:06 · 774 阅读 · 0 评论 -
内核启动时的中断和时钟的初始化流程
内核通过start_kernel从汇编进入c世界,在用serup_arch设置体系架构的时候,会返回当前机器的machine_desc;然后init_IRQ和time_init来初始化中断。时钟子系统mdesc = setup_machine_fdt(atags_vaddr) //返回成功匹配的machine_desc//赋值给全局变量machine_desc,以供后续初始化等操作使用,比如给下面的中断和时钟子系统使用......init_IRQ......time_initelse。原创 2024-06-19 11:22:41 · 783 阅读 · 0 评论 -
gpio-0设置成输出失败的原因
影响代码如下:of_property_read_u32返回0是找到节点里的属性了,返回负数是没找到;而且没对gpio_request做返回判断,如果有冲突的情况,这个地方还设置了gpio0为输入---那就异常了,该输出的gpio,被异常设置成了输入。但是后面其他驱动,使用of_property_read_u32获取设备树节点的属性时,没去判断返回值;而直接使用参数返回的0,导致gpio-0又被设置成了输入。修改如下:所以对接口的返回值做判断很重要,能避免一些奇葩的bug。正常的如下,gpio显示为输出。原创 2024-06-14 17:54:59 · 232 阅读 · 0 评论 -
poweroff, reboot流程
当传递特定的magic值如 LINUX_REBOOT_CMD_POWER_OFF时,内核会执行关机并尝试触发硬件层面的电源关闭。poweroff /halt /reboot操作通常由用户空间的systemd或其他初始化系统通过sys_reboot()系统调用触发。poweroff流程,pm_power_off函数被各平台赋值到具体函数,比如通过操作PMIC来实现关机。reboot流程,arm_pm_restart函数可能被具体平台赋值到具体函数,比如操作WDT实现重启。原创 2024-06-06 15:22:16 · 233 阅读 · 0 评论 -
简述等待队列的概念和实例
就是创建队列头,和队列元素;然后将元素加入队列;然后让出调度器;等资源满足,就将该元素从队列移除for (;;) {break;break;schedule();内核封装了一些步骤,统一简化使用方法for (;;) {break;schedule();原创 2024-06-03 11:20:41 · 413 阅读 · 0 评论 -
sdhci怎么通过dma/pio传输数据
sdio设备驱动调用sdio_memcpy_toio/sdio_memcpy_fromio来读写sdio设备,都会调用到host->ops->request(host, mrq),其框架如下。如果是dma传输完成中断,就会走sdhci_set_sdma_addr重新设置需要传输数据块的dma地址。对于adma就要通过dma_map_sg对一个sgl做映射,并返回sg_count。通过for_each_sg遍历每个sg,并通过__sdhci_adma_write_desc将描述符依次写进对应寄存器。原创 2024-05-17 17:47:50 · 406 阅读 · 0 评论 -
runtime pm的实例分析
他们会来执行设备驱动实现的对应操作;比如在drivers/spi/spi_qsd.c中,unprepare_transfer_hardware接口会去通过pm_runtime_put_autosuspend,去调用pm_dev_ops的runtime_suspend成员。比如在drivers/spi/spi_qsd.c中,prepare_transfer_hardware接口会去通过pm_runtime_get_sync,去调用pm_dev_ops的runtime_resume成员。原创 2024-05-15 11:23:09 · 913 阅读 · 0 评论 -
pci设备枚举流程
PCI桥设备:由于电子负载限制,每条PCI总线上可以挂载的设备数目是有限的因此使用了一种特殊的设备,即PCI-PCI桥设备将两条独立的PCI总线连接起来,PCI-PCI桥设备简称PCI桥。PCI设备:遵循PCI规范,工作在PCI局部总线环境下的设备。通讯:PCI设备也有自己内存空间和IO空间,这些空间被映射到CPU的内存空间和IO空间,在映射之后,PCI设备上的物理资源“变成”了CPU的本地资源。主桥设备:和CPU以及内存连在一起的Host-PCI桥设备为主桥设备,主桥设备引出的总线也称为PCI根总线。原创 2024-05-13 09:22:48 · 357 阅读 · 0 评论 -
pinctrl驱动详解
pinmux_enable_setting调用pinctrl_ops->get_group_pins获取对应的group,及其里面的pin信息;还是从pcs_parse_one_pinctrl_entry和pcs_parse_pinconf看到 ----每个state会有两个type的map;pinctrl主机驱动会用devm_pinctrl_register注册时,放进去的那三个ops(下面的代码前几行就可以看出)来真正的配置pin的复用功能和电气属性;根据从设备树获取的pinctrl的信息;原创 2024-04-30 14:57:55 · 392 阅读 · 0 评论 -
dwc3控制器是怎么处理otg
我们直接看支持otg的dwc3是怎么处理otg的,从设备开始看驱动,usb3_0的这个节点一般就是厂商自己定义的,主要包括中断,一般用于vbus检测,usb的插拔情况;为高就是DWC3_OTG_ROLE_DEVICE,为低就是DWC3_OTG_ROLE_HOST;xhci_init_driver将通用的xhci_hc_driver,赋值给xhci_plat_hc_driver;dwc3_core_init_mode根据设备树获得的模式,初始化控制器为对应模式,初始化控制器的操作函数:主机有主机的操作函数;原创 2024-04-26 22:03:18 · 881 阅读 · 0 评论 -
linux信号机制分析
对于有通过 signal、sigaction 注册信号处理函数的信号,设定堆栈后跳转到用户态的信号处理函数开始执行,此函数返回后触发一个 sigreturn 系统调用后再次回到内核,然后恢复旧的堆栈继续运行。原创 2024-04-23 17:02:55 · 766 阅读 · 0 评论 -
linux休眠唤醒流程,及示例分析
应用请求休眠,系统进入休眠流程,此时如果设备触发了中断,中断处理程序中首先关闭中断,然后调度内核线程去处理work,但假如这个时候此work还未被调度到,系统就进入休眠了,那么这个设备就被永久关闭中断了,再也不能唤醒系统。休眠后系统卡住,组织串口来休眠,并开启相关打印;设置pm_debug_messages,打印来自系统的调试消息的暂停/休眠内核日志的基础结构。平台休眠的最后,会开启中断,用与响应外部中断,来唤醒系统并继续执行接下来的代码唤醒系统。设备进入休眠,被唤醒或者休眠失败,就会走对应的唤醒流程;原创 2024-04-22 11:27:00 · 524 阅读 · 0 评论 -
USB设备热插拔流程解析
usb_hcd_poll_rh_status函数中,调用主机控制器的hub_status_data函数获取端口状态。如果端口的状态有变化,那么length > 0,把获取到的端口状态的数组拷贝到urb->transfer_buffer中,就是前面的hub->buffer中,同时调用usb_hcd_giveback_urb函数。在usb_hub_init函数中完成了注册hub驱动,然后创建一个工作队列hub_wq,每当有设备连接到USB接口时;sdio的话,主机驱动初始化的时候,会去枚举卡;原创 2024-04-15 16:55:24 · 481 阅读 · 0 评论 -
USB主机驱动分析
ehci_hc_driver实现了绝大多数ECHI主机驱动的工作,具体的EHCI实例简单地调用ehci_init_driver(struct hc_driver *drv,const struct ehci_driver_overrides *over)来初始化hc_driver即可,上层通过usb_submit_urb提交1个USB请求后,该函数调用usb_hcd_submit_urb,并最终调用至usb_hcd的driver成员(hc_driver类型的urb_enqueue成员函数)原创 2024-04-11 17:03:46 · 284 阅读 · 0 评论 -
块设备的读写框架
open系统调用打开字符设备文件时,会调用do_dentry_open,里面的f->f_op = fops_get(inode->i_fop);就是把上面init_special_inode里的inode->i_fop = &def_blk_fops赋给f->f_op;vfs_read里的file->f_op->read_iter就等于def_blk_fops的read_iter成员。其中file->f_op->write_iter就等于def_blk_fops的write_iter成员。原创 2024-04-03 16:06:27 · 420 阅读 · 0 评论 -
驱动的阻塞与非阻塞IO
(1)select,poll实现需要自己不断轮询所有fd集合,直到设备就绪,期间可能要睡眠和唤醒多次交替。而epoll其实也需要调用epoll_wait不断轮询就绪链表,期间也可能多次睡眠和唤醒交替,但是它是设备就绪时,调用回调函数(ep_ptable_queue_proc),把就绪fd放入就绪链表中,并唤醒在epoll_wait中进入睡眠的进程。原创 2024-03-27 10:28:10 · 240 阅读 · 0 评论 -
YT8531调试记录
还是从设备树,mac驱动,mac驱动对mdio总线的注册,phy驱动 ,phy的datasheet,cpu的datasheet 几个方面来看来看0.确认供电,以及phy的地址(一般会有多个地址,根据相关引脚电平可配置)1.确认reset的有效电平2.确认IO的有效电平3.确认phy-mode,以及它的pinctrl的复用情况 (cat /sys/kernel/debug/pinctrl/pinctrl-handles 看current state)原创 2024-03-26 09:45:35 · 755 阅读 · 0 评论 -
PCIe的<配置/IO/MEM空间>的区别
首先是root bus中io和mem的基地址,然后是给bridge(type 01)分配的mem地址,然后写到bridge的bar0;如上图设备树中,pcie两组地址转换关系,每一组的几个数字分别定义了属性(32bit),pci地址空间(64bit),cpu地址(32bit/64bit),长度(64bit)配置空间是一段特殊的IO空间,它的作用是为外设内存空间、IO空间分配物理地址基地址,即配置BAR(Base Address Registers)内存空间:访问内存的地址空间,32位平台为4G。原创 2024-03-22 16:29:29 · 479 阅读 · 0 评论 -
DMA控制器驱动分析
驱动按上面的步骤1,2分配通道和传输信息后,通过通道找到dma设备,再调用设备的device_prep_dma_memcpy这个成员,就会调用到dma控制器的这个具体实现。4、dma数据提交, dmaengine_submit(),主要是将DMA处理事务提交到dma通道处理链上,这个submit用的是第四步得到的DMA TX结构。2、dma通道配置, dmaengine_slave_config(), 用户通过该函数,可以配置指定通道的参数,比如目的和源地址,位宽,传输方向等。原创 2024-03-07 16:41:13 · 1012 阅读 · 0 评论 -
详解kobject_uevent_env上报机制
在用户层,通过一个进程来创建一个netlink,这个应用程序可以是mdev,udev或者openwrt的procd,这三种方式都是基于netlink来管理热插拔的,比如procd通过NETLINK_KOBJECT_UEVENT参数来通过socket系统调用创建一个fd来与内核的netlink交互数据,内核上报uevent被这个进程接受后,然后调用/etc/hotplug.d/的各脚本来执行热插拔操作。这是热插拔触后,触发的事件给应用层,然后执行的脚本,跟上面的信息是对上的。比如插拔sim卡会打印如下信息。原创 2024-02-04 10:15:02 · 462 阅读 · 0 评论 -
给驱动设备添加属性文件
先动态分配内存,存放kobject对象,并调用kobject_init完成目录属性文件的操作接口设置,设置kobject对象的ktype为dynamic_kobj_ktype,设置dynamic_kobj_ktype中的sysfs_ops变量为kobj_sysfs_ops,设置kobj_sysfs_ops为show变量为kobj_attr_show,store变量为kobj_attr_store,这就是该kobject对象默认的属性文件操作接口,分别对应着读写操作。就会在sysfs生成如下节点,便于操作。原创 2024-02-01 16:11:01 · 879 阅读 · 0 评论 -
详解PHY设备驱动的工作原理
不管什么驱动,简单的说:我们总是按照设备-驱动-总线的方式去看。原创 2024-01-14 11:29:30 · 706 阅读 · 0 评论 -
USB设备的检测,枚举和数据传输
USB采用差分信号传输,使用的是NRZI编码方式:数据为0时,电平翻转;数据为1时,电平不翻转。如果出现6个连续的数据1,则插入一个数据0,强制电平翻转,以便时钟同步。上面的一条线表示的是原始数据序列,下面的一条线表示的是经过NRZI编码后的数据序列。同步信号的抓包如下。原创 2023-12-23 22:11:19 · 1035 阅读 · 0 评论 -
configfs配置usb gadget原理
usb gadget configfs模块的初始化函数为gadget_cfs_init。该函数调用后,会向configfs注册一个子系统,子系统使用configfs_subsystem结构体描述。子系统中又可分为组,使用config_group描述,组内又有成员,使用config_item描述。原创 2023-12-09 17:43:15 · 1587 阅读 · 1 评论 -
usb通过wireshark抓包,并分析各描述符
安装很简单,在安装wireshark的时候,选中usbpcap就行了。原创 2023-12-08 20:19:51 · 2085 阅读 · 0 评论 -
input子系统的使用和调试
一般来说input的框架为三部分:1.设备驱动层,2.核心层,3.事件驱动;如下图已经很详细了,对应源码和实际设备debug就一目了然了,不做过多赘述。原创 2023-12-04 22:43:28 · 385 阅读 · 0 评论 -
设备树配置GPIO的简单总结
和,这两章已经简单说了下gpio是怎么在linux里面工作的,说白了就是为了统一的接口,半导体厂商按照框架在自己的驱动里去在底层做的实现gpio我们一般就是指的是通用的具有输入输出高低电平的控制器,这个做的也就是gpio子系统干的事,设置方向,电平等。但是外接的io引脚,一般不光有gpio的功能,还有其他的复用功能,比如i2c,spi等;这个io怎么输入输出就取决于连接的外设的驱动,怎么定义的了;这个一般有个复用管理的控制器来选择当前跟io连接的是那种功能,当然这个也就是pinctrl的部分工作内容。原创 2023-12-03 11:32:00 · 2297 阅读 · 1 评论 -
sdhc框架概述
Secure Digital(SD) Host Controller一般挂载sd和sdio设备,隶属于mmc子系统,其核心其实跟mmc子系统没什么差异;从我们先前的经验看,总线总是作为数据流通的的载体,那么这个载体我们总是分三段来看:设备--核心--主机;也可以简化成一句话:"设备在收发数据的时候,会调用核心提供的接口,这个接口会去匹配到设备挂载的具体控制器的具体收发的接口实现"。那我们还是按照先前这个并不成熟的总结依然往下看。原创 2023-11-25 12:08:49 · 496 阅读 · 0 评论 -
字符设备框架概述
在fs/char_dev.c中,有255个char_device_struct元素的数组来管理设备号,主设备号取余等于这个数组的index;相同index的字符设备通过char_device_struct链表连接,也就是chrdevs[1]这个表头,链接了主设备号m;这个是动态申请设备号的接口,分配一次就会占用一个或多个设备号这个是静态分配,可能需要多次分配;如果跨主设备号了,则需要多次执行__register_chrdev_region。原创 2023-11-25 10:26:53 · 491 阅读 · 0 评论 -
mdio总线框架概述
比如这个emac_mdio_init,去到emac节点里找到“mdio-bus”这个属性,然后申请一个mii成员,将emac驱动里面实现的成员函数赋值给mii的成员,然后再通过of_mdiobus_register,将拿到的这个mdio-bus节点,去注册总线和挂在上面的设备。简单看下mdio的初始化干了什么,主要就是实现mdio的读写函数,以及对挂在mdio总线的设备就,比如phy,switch设备进行创建和注册。注册mdio总线,后续的phy设备都会在这个总线下面。设备注册后,就是跟驱动的匹配了。原创 2023-11-23 22:59:52 · 720 阅读 · 0 评论 -
简述mmc子系统框架
下面这句dev->driver = drv,就跟mmc_bus_probe的dev->driver对上了,就是总线上已注册的mmc_driver,当执行dev->bus->probe就调用了上面的mmc_bus_probe。设备-总线-驱动,注册了两条总线,还是像之前i2c/spi总线一样,还是core给出处理数据的通用接口,host-driver来做具体的实现,device-driver来调用。比如检查到mmc卡插上了,就会attach上mmc相关的初始化操作mmc_ops,设置电压,初始化card等。原创 2023-09-23 17:33:07 · 133 阅读 · 1 评论 -
简述spi内核框架
spi_master_initialize_queue主要是spi_init_queue建立起队列来处理message,和spi_start_queue来调用queue_kthread_work(&master->kworker, &master->pump_messages)执行一次工作的调度。内核加载spidev.c是一个通用的spi驱动;用的时候填充tx_buf/rx_buf到spi_transfer,放入message队列中,并通过spidev_sync调用spi_sync去接发数据。原创 2023-09-16 16:48:52 · 247 阅读 · 1 评论 -
总线,设备,驱动模型
bus_register:bus_type_private的初始化,在这条总线目录下创建/bus/busname,/device, /driver 目录,初始化这条总线上的设备链表:struct klist klist_devices;初始化这条总线上的驱动链表:struct klist klist_drivers。原创 2023-09-05 11:21:55 · 69 阅读 · 0 评论 -
linux中的i2c主控驱动,设备驱动示例分析
无论是i2c,spi,pci等总线,以及虚拟总线platforn,总线的注册究其根本都是通过int bus_register(struct bus_type *bus);这个bus的.name定义为i2c或者platform,其他成员函数也被定义成特定总线的设备的注册都是通过int device_register(struct device *dev);这个dev被包含到i2c_client或者spi_device等其他xxx_device中int status;if (!client)原创 2023-09-02 11:41:54 · 154 阅读 · 0 评论 -
概述gpio子系统工作原理
gpio子系统工作原理原创 2023-03-08 23:25:39 · 596 阅读 · 0 评论 -
概述pinctrl子系统工作原理
pinctrl子系统的工作流程原创 2023-03-04 17:57:31 · 999 阅读 · 1 评论