目录
一、Linux驱动开发
Linux操作系统框架图
Linux系统一般有4个主要部分:内核、shell、文件系统和应用程序。内核、shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序、管理文件并使用系统。
Linux内核组成
Linux驱动
广义定义:操作硬件,让硬件工作起来的程序代码。
狭义定义:操作系统中用来控制硬件的逻辑方法的那部分代码。
1、分类
(1)system驱动:SOC、Memory、GPIO、CLK
(2)多媒体驱动:Display、Audio、camera
(3)功耗:PMIC、LDO、charger
(4)RF:WiFi、BT、GPS、UWB、NFC
(5)Sensor/外设:IMU、BIO、Touch、LED、Key/Button、USB
2、Linux驱动三大组件
(1)Bus(总线):总线是CPU和一个或多个设备之间信息交互的通道。而为了方便设备模型的建立,Linux就虚构了Platform Bus(虚拟总线),使得所有设备都能挂靠。
(2)Device:用来描述硬件设备信息的结构体,描述它的名字、属性、连接的Bus、归属的Class等信息。
(3)Driver:描述硬件设备的驱动程序的结构体,它包含设备初始化等函数操作,是linux内核驱动的核心。
(4)Device与Driver的匹配方法:
①直接根据名字来进行匹配,即device name和driver name相同。
②通过id_table来实现,采用表中的name与device name匹配。
(5)三大驱动组件之间的关系
关系一:
硬件模块 → 模块信息 → Device → 匹配device和driver → BUS
→ 功能实现 → Driver → 匹配device和driver → BUS
关系二:
Devices list → BUS → drivers list
一 对 多
3、Linux设备驱动模型
Linux设备驱动模型是一种抽象模型,为内核建立起统一的设备模型,其目的是提供一个对系统结构的一般性抽象描述。Linux设备驱动模型提供统一的设备管理抽象,这些抽象包括总线、类、设备和设备驱动等。
Class(类):集合具有相似功能或属性的设备,抽象出一套可以在多个设备之间共用的数据结构和接口函数。
Linux 内核编译
kernel源代码 —— 根目录 —— Linux配置文件:Makefile、.config
—— Drivers等各级子目录 —— Linux配置文件:kconfig、Makefile
—— Arch目录中platform子目录 —— Linux配置文件:Deficonfig
1、内核配置及编译步骤:
- make distclean :清除临时文件、中间文件和配置文件。
- make xxx_config(默认配置文件):得到内核的当前配置文件.config。
- make menuconfig(或config、xconfig):进入配置用户界面,进行内核的详细配置。
- make all:编译内核。
2、Firmware(固件)简介:
Linux系统编译输出物:Lk.img,boot.img,dtbo.img,system.img,userdata.img,ramdisk.img,recovery.img(img是一种文件压缩格式,镜像文件)。
userdata.img(User data)——使用→ system.img(UI/Android) ←加载——boot.img(kernel) ←传递——dtbo.img(DTS) boot.img(kernel) ←运行——Lk.img(bootloader)
Linux 驱动编程
1、驱动开发流程
分配资源(gpio、IRQ、data等) → 配置结构体(device、driver、map等) → 注册/实现file_operation(Open()、Close()、Write()、Read()等) → 入口函数(Model_init()) → 出口函数(Model_exit())
2、驱动编写的三种方法
传统法 |(Linux2.6)| 总线法 |(Linux3.0)| DTS注册法
(1)Linux驱动编程 - 传统法
配置资源:
#define GPF(n) (5<<16 | n)
static int led_pin = GPF(5);
static volatile unsigned int *gpio_con;
static volatile unsigned int *gpio_dat;
static int major;
static struct class *led_class;
完善file_operations:
static struct file_operations led_oprs = {
.owner = THIS_MODULE,
.open = led_open,
.write = led_write,
.release = led_release,
};
实现driver入口/出口函数:
static int myled_init(void)
{
major = register_chrdev(0,"myled",&led_oprs);
led_class =class_create(THIS_MODULE,"myled");
device_create(led_class,NULL,MKDEV(major,0),NULL,
return 0;
}
static void myled_exit(void)
{
unregister_chrdev(major,"myled");
device_destroy(led_class,MKDEV( ...还有一部分没写完
class_destroy(led_class);
}
module_init(myled_init);
module_exit(myled_exit);
MODULE_LICENSE("GPL");
优点:操作简单
缺点:不易扩展,每次修改需要重新编译驱动
(2)总线(platform)法
驱动和设备分开,分别在dev.c,drv.c文件中,实现以下几个结构体:
struct platform_device
struct platform_driver
struct device_driver
struct platform_device_id
drv.c中实现GPIO、中断等资源定义
dev.c
struct platform_device{
const char = name;
int id;
...
};
drv.c