stm32-usart
[toc] drivers/tty/serial/stm32-usart.c涉及的寄存器及其作用12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970/* Register offsets */static struct stm32_usart_info __maybe_unused stm32f4_info = { .ofs = { .isr = 0x00, .rdr = 0x04, .tdr = 0x04, .brr = 0x08, .cr1 = 0x0c, .cr2 = 0x10, .cr3 = 0x14, .gtpr = 0x18, .rtor = UNDEF_REG, .rqr = UNDEF_REG, .icr = UNDEF_REG, .presc = UND...
stm32-dma
[toc] drivers/dma/stm32/stm32-dmamux.cSTM32 DMAMUX (DMA多路复用器) 驱动此代码片段是STM32 DMAMUX的完整平台驱动程序。它的核心作用是充当一个硬件”路由交换机”的软件抽象层。在复杂的STM32微控制器(如STM32H7系列)中, 有大量的外设(如SPI, I2C, UART)可以发起DMA请求, 但实际的DMA控制器(DMA1, DMA2)通道数量是有限的。DMAMUX就是处在这两者之间的一个硬件单元, 它能将任意一个外设的请求信号连接到任意一个空闲的DMA通道上。 这个驱动的根本原理是实现内核DMA框架中的dma_router(DMA路由)模式。当一个外设驱动(如SPI驱动)请求一个DMA通道时, 它并不知道DMAMUX的存在。它在设备树中的dmas属性指向的是DMAMUX设备, 而不是最终的DMA控制器。内核的DMA框架看到这个dmas属性后, 会识别出这是一个DMA路由, 于是它不会直接与DMA控制器驱动交互, 而是调用这个DMAMUX驱动注册的route_allocate回...
dmaengine
[toc] drivers/dma/dmaengine.hstruct dma_chan / struct dma_chan_dev: DMA 通道对象与其 sysfs 设备包装对象的语义建模 struct dma_chan:DMAengine 框架中“可被客户端申请与提交事务”的通道抽象,承载运行期状态(cookie、完成度、客户端引用计数、路由信息等)以及与上层可见性的关联(sysfs/debugfs 相关字段)。 struct dma_chan_dev:把通道映射为 Linux 设备模型中的一个 struct device,用于 sysfs 节点呈现与生命周期管理;同时保存 dma_chan * 的反向指针(也就是你前面讨论的 chan->dev->chan 这一条关键可见性路径)。 这两个结构体之所以分开,是因为 DMAengine 需要同时满足: 运行期快速访问与调度(dma_chan) 设备模型可见性、热插拔/解绑生命周期、sysfs 目录树一致性(dma_chan_dev + struct d...
dmapool
[toc] [mm/dmapool.c] [DMA 池分配器(dma_pool)] [为指定 device 提供“小块、一致性(coherent)可 DMA”的池化分配/释放接口]介绍dma_pool 的目标很明确:给驱动提供固定大小的小块 DMA 一致性内存,避免频繁用 dma_alloc_coherent() 做“小块分配”带来的浪费与开销;实现方式是:先用 dma_alloc_coherent() 一次拿一段(通常至少一页)一致性内存,然后切成等大小 block,用空闲链表管理。源码文件开头注释把这个设计讲得很直接:从页分配器拿 coherent page,再拆分成 blocks,并用跨页的单链表跟踪空闲块。 历史与背景这项技术是为了解决什么问题而诞生的?驱动里常见“很多很小、但必须设备可直接 DMA 访问且无需显式 cache flush”的对象(例如描述符、队列元素等)。直接 dma_alloc_coherent() 去分配这些小对象会导致: 粒度偏大:coherent 分配往往以页或更大粒度管理,小对象会产生明显内部碎片; 频繁分配...
core
[TOC] drivers/base/core.c 设备核心(Device Core) 设备模型的运转中枢drivers/base/core.c 是Linux内核统一设备模型的心脏。它不是一个孤立的功能,而是整个设备模型框架的中央实现和调度器。文件中包含了设备注册与注销、设备与驱动的绑定与解绑、设备生命周期管理、sysfs 核心接口以及电源管理回调等最核心的逻辑。可以说,内核中任何设备的任何状态变化,都离不开core.c中代码的直接或间接执行。 历史与背景这项技术是为了解决什么特定问题而诞生的?在统一设备模型被构想出来时,需要一个集中的地方来实现所有设备和驱动都必须遵循的通用规则和流程。core.c正是为了这个目的而创建的,它解决了以下核心问题: 通用设备管理:提供一个单一、标准的接口(device_register, device_unregister)来处理系统中所有类型设备的添加和移除,避免每个子系统(PCI, USB等)重复造轮子。 驱动绑定协调:建立一个通用的机制,在设备或驱动被添加时,主动触发匹配过程,并在匹配成功后,以标准的顺序调用驱动的...
map
[toc] drivers/base/map.ckobj_map: 一个通用的设备号到内核对象的映射引擎本代码片段是Linux内核中一个相对底层但非常关键的通用映射子系统——kobj_map。其核心功能是提供一个可扩展的、基于回调的哈希表,用于将一个设备号(dev_t)高效地映射到一个内核对象(kobject)。这个机制是cdev(字符设备)、bdev(块设备)等许多与设备号相关的子系统的基础引擎。它通过一种链式哈希表和回调函数的设计,实现了设备注册、注销和查找的核心逻辑。 实现原理分析如代码开头的注释所言,这是一个历史悠久的设计,虽然性能可能不是最优,但其设计思想非常精巧。 核心数据结构 (kobj_map): probes[255]: 这是一个哈希表。它的大小是固定的255个桶(bucket)。 哈希函数: MAJOR(dev) % 255。它使用设备号的主设备号(Major number)对255取模,来决定一个设备应该被放入哪个桶中。 struct probe: 这是哈希表中的节点。它不是直接存储kobject,而是存储一个**“探测器”**...
gpiolib
[toc] drivers/gpio/gpiolib.cgpiochip_setup_dev: 为单个GPIO控制器完成设备和接口的注册此函数的核心职责是接收一个代表GPIO控制器(如STM32的GPIOA)的内核对象gdev,并完成以下三件关键事情: 初始化设备对象: 确保gdev中的struct device成员被正确初始化。 创建字符设备: 在/dev目录下创建对应的gpiochipN字符设备节点,使用户空间程序可以通过文件I/O操作来访问GPIO。 创建sysfs接口: 在/sys/class/gpio目录下创建对应的gpiochipN目录和属性文件,提供一种基于文件的、用于管理和调试GPIO的接口。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687/* ...
simple-pm-bus
[toc] drivers/bus/simple-pm-bus.c 简单电源管理总线(Simple PM Bus) 通用的、轻量级的设备电源管理协调器历史与背景这项技术是为了解决什么特定问题而诞生的?simple-pm-bus 的诞生是为了解决在复杂的片上系统(SoC)中一个常见的、但缺乏标准化解决方案的问题:如何以一种通用、有序的方式管理一组相互关联的、但又不属于任何标准总线(如I2C, SPI)的设备的电源状态(主要是休眠与唤醒)。 在许多SoC设计中,存在大量简单的、直接挂在内存映射I/O(MMIO)上的设备。这些设备可能在逻辑上属于一个功能单元(例如,一个视频处理流水线上的多个IP核),它们需要按照特定的顺序进入休眠(suspend)或从中恢复(resume)。 在simple-pm-bus出现之前,处理这种情况通常依赖于: 平台代码中的硬编码:在板级支持文件(board file)中硬编码休眠/唤醒的调用顺序,这使得代码难以移植和维护。 驱动间的隐式依赖:驱动程序之间通过msleep等脆弱的方式来猜测和等待其他设备的状态。...
sysrq
[toc] drivers/tty/sysrq.c 内核魔法键(Magic SysRq Key) 系统的终极应急与调试工具历史与背景这项技术是为了解决什么特定问题而诞生的?Magic SysRq Key(魔法系统请求键)是为了解决一个系统管理员和内核开发者面临的终极难题:当系统完全冻结,无法通过网络(SSH)或本地终端响应时,如何进行诊断或安全地重启? 在系统严重死锁或负载极高的情况下,用户空间的程序、Shell、甚至内核的调度器都可能停止工作。然而,内核的底层部分,如键盘中断处理,可能仍然在运行。SysRq机制就是利用这个“一线生机”,提供了一个直接与内核底层进行通信的“后门”。它允许操作员通过一个特殊的键盘组合键,绕过所有上层软件栈,直接向内核发送预定义的命令,从而: 获取调试信息:在系统崩溃的瞬间,抓取任务状态、内存使用情况等快照。 执行应急操作:如同步磁盘、以只读方式重新挂载文件系统。 安全地重启系统:在别无选择时,执行一个比直接按电源键(硬重启)更安全的重启序列,最大限度地减少数据损坏的风险。 它的发展经历了哪些重要的里程碑或版本迭代? 源自...
sys
[toc] kernel/sys.c 系统信息与控制接口(System Information and Control) 内核的通用系统调用集合历史与背景这项技术是为了解决什么特定问题而诞生的?kernel/sys.c 是Linux内核中历史最悠久、最基础的文件之一。它不是为了解决某一个单一、特定的技术问题而生,而是扮演着一个内核“工具箱”的角色。它实现了一大批杂项但至关重要的系统调用,这些系统调用为用户空间提供了一个与内核进行全局性、管理性和信息性交互的标准化接口。 这些系统调用解决的问题包括: 获取系统状态:如何让 top, free, uptime 等工具知道系统的负载、内存使用情况和运行时间?(sysinfo) 识别系统身份:程序如何知道自己运行在哪个操作系统版本、哪个硬件架构上?(uname) 控制系统生命周期:管理员如何安全地重启或关闭计算机?(reboot) 配置系统标识:系统启动时如何设置自己的主机名?(sethostname) 调整进程行为和资源:如何设置进程的调度优先级 (setpriority) 或资源限制 (setrlimit)? 细粒度...








