驱动开发-platform
linux驱动的分离与分层因为驱动程序占用了Linux内核代码量的大头,如果不对驱动程序加以管理,任由重复的代码肆意增加,那么用不了多久Linux 内核的文件数量就庞大到无法接受的地步。 总线-驱动-设备将设备信息从设备驱动中剥离开来,驱动使用标准方法去获取到设备信息(比如从设备树中获取到设备信息),然后根据获取到的设备信息来初始化设备。 这样就相当于驱动只负责驱动,设备只负责设备,想办法将两者进行匹配即可。这个就是Linux 中的总线(bus)、驱动(driver)和设备(device)模型,也就是常说的驱动分离。 总线(bus)、驱动(driver)和设备(device)。总线是linux直接提供,driver和device是我们需要编写的 platformLinux设备模型的核心思想。Platform机制将硬件信息(platform_device)和驱动代码(platform_driver)分离开来。 platform_device:代表一个具体的硬件设备,包含了设备的物理资源(如内存地址、中断号等)。这部分信息通常来自设备树(Device Tree)或ACPI表...
驱动开发-PWM
PWM(Pulse Width Modulation)基础概念与理论1.什么是 PWM?它的主要参数是什么? PWM (Pulse Width Modulation) 即脉冲宽度调制,是一种通过控制数字信号在一个周期内高电平时间(脉宽)与周期时间之比(占空比)来模拟连续电平的技术。 主要参数: 周期 (Period) / 频率 (Frequency): 一个完整 PWM 波形的持续时间 (T)。频率 f = 1 / T。 占空比 (Duty Cycle): 高电平时间 (Ton) 占整个周期 (T) 的百分比 (D = (Ton / T) * 100%)。 极性 (Polarity): PWM 信号有效电平(Active Level)是高电平有效 (Normal) 还是低电平有效 (Inversed)。 2.应用场景 电机控制: 调节速度和方向(如直流电机、步进电机)。 LED 调光: 控制亮度(通过改变平均电流)。 电源管理: DCDC 转换器输出电压调节(通过控制开关管导通时间)。 音频: 简单的 D 类放大器。 伺服控制: 控制舵机角度(特定脉宽范围对应特...
驱动开发-pinctrl与gpio子系统
pinctrl子系统i.MX 芯片(以及很多其他 SoC)面临的一个根本问题:芯片的引脚(PAD)数量有限,但内部功能模块(如 USDHC, UART, I2C, GPIO 等)非常多。为了解决这个矛盾,芯片设计引入了 IOMUX Controller (IOMUXC)。 IOMUXC (I/O Multiplexer Controller): 功能:它是一个硬件控制器,允许一个物理引脚(PAD)被复用到多个内部功能模块上。 工作方式:通过寄存器配置,为每个引脚选择 up to 8 种不同的工作模式(ALT modes,即 Alternate Function 复用功能)。例如,一个引脚可以被配置为 GPIO1_IO00、UART1_TXD 或 I2C1_SDA 等功能。 额外控制:除了选择功能,IOMUXC 还控制每个引脚的电气特性,如上拉/下拉电阻、驱动强度、转换速率等。这被称为 Pad Settings。 我们需要在设备树中设置PIN的信息,在imx6ull.dtsi文件中,找到iomuxc的节点,iomuxc 节点就是I.MX6ULL的IOMU...
驱动开发-设备驱动模块
LINUX设备驱动模块设备驱动程序,就是驱使设备按照用户的预期进行工作的软件,它是应用程序与设备沟通的桥梁。设备驱动程序主要负责硬件设备的参数配置、数据读写与中断处理。 Linux中的大部分驱动程序是以内核模块的形式编写的。内核模块是Linux 内核向外部提供的一个接口,其全称为动态可加载内核模块(Loadable Kernel Module,LKM)。 驱动程序的加载方式内核模式将新驱动程序编译进内核,需要修改内核代码和编译选项,这种方式将驱动程序代码直接编译到内核镜像(zImage或uImage等)中,成为内核的一部分。 特点: 集成度高:驱动随内核启动自动加载,无法卸载。 性能稍好:省去了模块加载和解析的开销。 安全性/稳定性高:常用于系统最核心、必须的驱动(如根文件系统驱动)。 内核体积大:所有驱动都会被编译进去,导致内核镜像文件变大。 配置方法:通过内核的配置菜单(make menuconfig等)将对应的驱动选项配置为 y。 实验一本次实验是通过静态添加自己编写的驱动如:beep.c/ap3216c.c/icm20608.c等驱动。 ...
驱动开发-图形化编译内核与系统自带驱动的添加
1.配置linux自带的驱动使能1.1图形化配置要使用 Linux内核自带的 LED灯驱动首先得先配置 Linux,输入如下命令打开 Linux配置菜单: 1make menuconfig 按照如下路径打开 LED驱动配置项: 按照上述路径,选择“ LED Support for GPIO connected LEDs”,将其编译进 Linux内核,也即是在此选项上按下“ Y”键,使此选项前面变为 “<*>”: 在“ LED Support for GPIO connected LEDs”上按下 可以打开此选项的帮助信息, 1make -j16 1.2.config文件查看配置 好 Linux内核以后退出配置界面,打开 .config文件,会找到“ CONFIG_LEDS_GPIO=y这一行,如图 56.1.3所示: 1.3Makefile文件LED灯驱动文件为 /drivers/leds/leds-gpio.c,大家可以打开 /drivers/leds/Makefile这个文件, 如果定义了 CONFIG_LEDS_GPIO的话就会编...
CH2-中断处理流程分析
linux中断处理的流程linux-5.10.4版本:interrupt.h linux系统启动的流程irq_domainirq_domain 是一个中间翻译层,它负责将硬件的中断号(Hardware Interrupt Number)映射到 Linux 内核的虚拟中断号(Virtual IRQ Number),并管理中断控制器的相关操作。 你可以把它想象成一个翻译官或接线总机: 硬件中断号 (HW IRQ):是中断控制器自己识别的编号。例如,对于 ARM GIC,SGIs 是 0-15,PPIs 是 16-31,SPIs 从 32 开始。这是硬件固定的,不同控制器完全不同。 虚拟中断号 (VIRQ):是 Linux 内核内部使用的、统一的软件中断编号。驱动开发者请求和使用的就是这个号。 它的作用: 抽象硬件差异 世界上有无数种中断控制器(GIC, APIC, IO-APIC, GPIO 控制器等),每种都有自己的编号方案和编程模型。内核无法为每种控制器都写一套独立的中断处理流程。irq_domain 提供了一个统一的抽象接口,让内核核心代码只需与 irq_domain...
CH3-中断程序的编写
linux中断程序编写中断的API函数request_irq1int request_irq(unsigned int irq,irq_handler_t handler,unsigned long flags,const char *name,void *dev) **irq:**要申请中断的中断号。 **handler:**中断处理函数,当中断发生以后就会执行此中断处理函数。 **flags:**中断标志,可以在文件include/linux/interrupt.h 里面查看所有的中断标志 标志 描述 IRQF_SHARED 多个设备共享一个中断线,共享的所有中断都必须指定此标志。如果使用共享中断的话,request_irq 函数的dev参数就是唯一区分他们的标志。 IRQF_ONESHOT 单次中断,中断执行一次就结束。 IRQF_TRIGGER_NONE 无触发。 IRQF_TRIGGER_RISING 上升沿触发。 IRQF_TRIGGER_FALLING 下降沿触发。 IRQF_TRIGGER_HIGH 高电平触发。 IRQF_T...
CH1-中断子系统介绍
中断子系统中断Linux中断是指在CPU正常运行期间,由于内外部事件或由程序预先安排的事件引起的CPU暂时停止正在运行的程序,转而为该内部或外部事件或预先安排的事件服务的程序中去,服务完毕后再返回去继续运行被暂时中断的程序。 中断子系统框架 CPU 中断控制器 外设 中断向量表 中断号 Linux内核中断子系统 中断编程接口(request_irq接口函数) 具体的外设驱动 中断控制器 GIC 是ARM 公司给Cortex-A/R 内核提供的一个中断控制器,类似Cortex-M 内核中的NVIC。GIC 接收众多的外部中断,然后对其进行处理,最终就只通过四个信号报给ARM 内核,这四个信号的含义如下: VFIQ:虚拟快速FIQ。 VIRQ:虚拟外部IRQ。 FIQ:快速中断IRQ。 IRQ:外部中断IRQ。 单核 上图中我们可以看到所有的中断都发送给了GIC控制器,它负责处理各种中断,判断优先级、屏蔽、使能等工作。在GIC控制器中有Distributor、Interface **Distributor(分发器端):**块负责处理各...
CH4-中断的上半部与下半部
中断的上半部与下半部Linux内核将中断分为上半部和下半部的主要目的就是实现中断处理函数的快进快出,我们在使用request_irq申请中断的时候注册的中断服务函数属于中断处理的上半部,只要中断触发,那么中断处理函数就会执行。 上半部:上半部就是中断处理函数,那些处理过程比较快,不会占用很长时间的处理就可以放在上半部完成。 下半部:如果中断处理过程比较耗时,那么就将这些比较耗时的代码提出来,交给下半部去执行,这样中断处理函数就会快进快出。 可以参考: 如果要处理的内容不希望被其他中断打断,那么可以放到上半部。 如果要处理的任务对时间敏感,可以放到上半部。 如果要处理的任务与硬件有关,可以放到上半部 除了上述三点以外的其他任务,优先考虑放到下半部 软中断Linux 内核使用结构体softirq_action 表示软中断, softirq_action结构体定义在文include/linux/interrupt.h中softirq_action 1234struct softirq_action{ void (*action)(struct soft...
CH4-内核虚拟空间学习与I.MX6ULL嵌入式驱动开发实践
虚拟内存内核空间 ==内核态虚拟内存空间是所有进程共享的,不同进程进入内核态之后看到的虚拟内存空间全部是一样的。== 线性映射区 lowmem在总共大小1G的内核虚拟内存空间中,位于最前边有一块896M大小的区域,我们称之为直接映射区或者线性映射区,地址范围为3G—–3G+896m。 之所以这块896M大小的区域称为直接映射区或者线性映射区,是因为这块连续的虚拟内存地址会映射到0-896M这块连续的物理内存上。 也就是说3G-3G+896m这块896M大小的虚拟内存会直接映射到0-896M这块896M大小的物理内存上,这块区域中的虚拟内存地址直接减去0xC0000000(3G)就得到了物理内存地址。所以我们称这块区域为直接映射区。直接映射区中的映射关系是一比一映射。映射关系是固定的不会改变。 原理线性映射区(Direct Mapping Area)是内核虚拟地址空间中一段固定偏移映射的区域,其核心原理是通过简单的数学关系建立虚拟地址与物理地址的直接对应: 经典通常是: 1虚拟地址 = 物理地址 + PAGE_OFFSET P...