文章目录
平台总线笔记
一、平台总线模型
设备里写硬件相关的,驱动里面写控制相关的。
优势:主要是为了提高代码的可移植性,在对于不同的处理器只需要更改device中对应硬件资源,而driver驱动中控制的部分不需要改变,大大提高了代码的可以执行。
二、注册platfrom设备(即device部分)
第一个成员name就是device的name
第二个成员id是跟在name后面的数字用来区分设备,一般设置成-1意思是没有后缀。
第三个成员id_auto自动设置id,一般不用
第四个成员 dev结构体 表示的设备的通用属性成员,在编写dev的时候要使用dev中的release函数,否则会报错。
第五个Resource结构体是重中之重,其结构如下
主要关注前四个成员,
Name:表示存储的资源
Falg:表示资源的种类
Start和end:描述的资源的起始和终止未知,例如寄存器的起始地址和终止地址。
num_resource: 存储资源的个数。
举例子
name是可写可不写。
Platfrom设备加载和卸载函数
device对应代码
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/ioport.h>
#define MEM_START_ADDR 0xFDD60000
#define MEM_END_ADDR 0xFDD60004
#define IRQ_NUMBER 101
static struct resource my_resources[] = {
{
.start = MEM_START_ADDR, // 内存资源起始地址
.end = MEM_END_ADDR, // 内存资源结束地址
.flags = IORESOURCE_MEM, // 标记为内存资源
},
{
.start = IRQ_NUMBER, // 中断资源号
.end = IRQ_NUMBER, // 中断资源号
.flags = IORESOURCE_IRQ, // 标记为中断资源
},
};
static void my_platform_device_release(struct device *dev)
{
// 释放资源的回调函数
}
static struct platform_device my_platform_device = {
.name = "my_platform_device", // 设备名称
.id = -1, // 设备ID
.num_resources = ARRAY_SIZE(my_resources), // 资源数量
.resource = my_resources, // 资源数组
.dev.release = my_platform_device_release, // 释放资源的回调函数
};
static int __init my_platform_device_init(void)
{
int ret;
ret = platform_device_register(&my_platform_device); // 注册平台设备
if (ret) {
printk(KERN_ERR "Failed to register platform device\n");
return ret;
}
printk(KERN_INFO "Platform device registered\n");
return 0;
}
static void __exit my_platform_device_exit(void)
{
platform_device_unregister(&my_platform_device); // 注销平台设备
printk(KERN_INFO "Platform device unregistered\n");
}
module_init(my_platform_device_init);
module_exit(my_platform_device_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("topeet");
三、注册platfrom驱动(即driver部分)
举例
不涉及name了,name在.driver里,补充上:
关于id_table的设置如下
id_table中的name的优先级高于.driver中的name
四、注册platfrom驱动(probe函数部分)
device对应代码
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/ioport.h>
static int my_platform_driver_probe(struct platform_device *pdev)
{
struct resource *res_mem, *res_irq;
// 方法1:直接访问 platform_device 结构体的资源数组
if (pdev->num_resources >= 2) {
struct resource *res_mem = &pdev->resource[0];
struct resource *res_irq = &pdev->resource[1];
// 使用获取到的硬件资源进行处理
printk("Method 1: Memory Resource: start = 0x%llx, end = 0x%llx\n",
res_mem->start, res_mem->end);
printk("Method 1: IRQ Resource: number = %lld\n", res_irq->start);
}
// 方法2:使用 platform_get_resource() 获取硬件资源
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res_mem) {
dev_err(&pdev->dev, "Failed to get memory resource\n");
return -ENODEV;
}
res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res_irq) {
dev_err(&pdev->dev, "Failed to get IRQ resource\n");
return -ENODEV;
}
// 使用获取到的硬件资源进行处理
printk("Method 2: Memory Resource: start = 0x%llx, end = 0x%llx\n",
res_mem->start, res_mem->end);
printk("Method 2: IRQ Resource: number = %lld\n", res_irq->start);
return 0;
}
static int my_platform_driver_remove(struct platform_device *pdev)
{
// 设备移除操作
return 0;
}
static struct platform_driver my_platform_driver = {
.driver = {
.name = "my_platform_device", // 与 platform_device.c 中的设备名称匹配
.owner = THIS_MODULE,
},
.probe = my_platform_driver_probe,
.remove = my_platform_driver_remove,
};
static int __init my_platform_driver_init(void)
{
int ret;
ret = platform_driver_register(&my_platform_driver); // 注册平台驱动
if (ret) {
printk("Failed to register platform driver\n");
return ret;
}
printk("Platform driver registered\n");
return 0;
}
static void __exit my_platform_driver_exit(void)
{
platform_driver_unregister(&my_platform_driver); // 注销平台驱动
printk("Platform driver unregistered\n");
}
module_init(my_platform_driver_init);
module_exit(my_platform_driver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("topeet");