linux设备驱动开发详解_Linux设备驱动开发 - 平台设备驱动

721a01cd13550943d1c176bd0f65c260.png

Linux2.6的内核中引入了一种新的设备驱动模型-平台(platform)设备驱动,平台设备驱动分为平台设备(platform_device)和平台驱动(platform_driver),平台设备的引入使得Linux设备驱动更加便于移植。

一、平台设备
平台设备结构体:

struct platform_device {

const char * name; /* 设备名 */

int id;

struct device dev; /* 设备结构体 */

u32 num_resources; /* 设备资源数量 */

struct resource * resource; /* 设备资源 */

const struct platform_device_id *id_entry;

/* arch specific additions */

struct pdev_archdata archdata;

};

平台设备主要是提供设备资源和平台数据给平台驱动,resource为设备资源数组,类型有IORESOURCE_IO、IORESOURCE_MEM、IORESOURCE_IRQ、IORESOURCE_DMA、IORESOURCE_DMA。下面是一个网卡芯片DM9000的外设资源:


static struct resource dm9000_resources[] = {

[0] = {

.start = S3C64XX_PA_DM9000,

.end = S3C64XX_PA_DM9000 + 3,

.flags = IORESOURCE_MEM,

},

[1] = {

.start = S3C64XX_PA_DM9000 + 4,

.end = S3C64XX_PA_DM9000 + S3C64XX_SZ_DM9000 - 1,

.flags = IORESOURCE_MEM,

},

[2] = {

.start = IRQ_EINT(7),

.end = IRQ_EINT(7),

.flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,

},

};

dm9000_resources里面有三个设备资源,第一个为IORESOURCE_MEM类型,指明了第一个资源内存的起始地址为S3C64XX_PA_DM9000结束地址为S3C64XX_PA_DM9000 + 3,第二个同样为IORESOURCE_MEM类型,指明了第二个资源内存的起始地址为S3C64XX_PA_DM9000 + 4结束地址为S3C64XX_PA_DM9000 + S3C64XX_SZ_DM9000 - 1,第三个为IORESOURCE_IRQ类型,指明了中断号为IRQ_EINT(7)。

struct device {

struct device *parent;

struct device_private *p;

struct kobject kobj;

const char *init_name; /* initial name of the device */

struct device_type *type;

struct mutex mutex; /* mutex to synchronize calls to

* its driver.

*/

struct bus_type *bus; /* type of bus device is on */

struct device_driver *driver; /* which driver has allocated this

device */

void *platform_data; /* Platform specific data, device

core doesn't touch it */

...

};

struct device结构体里面有一个重要成员platform_data,它是平台设备和平台驱动进行数据传递的重要成员。

平台设备注册:

1 int platform_device_register(struct platform_device *pdev);

platform_device_register()会对平台设备进行相应的初始化之后调用platform_device_register()函数把它添加到子系统中。

平台设备注销:

1 void platform_device_unregister(struct platform_device *pdev);

platform_device_unregister()函数释放设备资源之后从子系统中将其移除。

平台设备模板:

static struct resource xxx_resource =

{

[0] =

{

.start = ...,

.end = ...,

.flags = ...,

},

[1] =

{

...

}

...

};

static struct xxx_plat_data xxx_data =

{

...

};

static struct platform_device xxx_platform_device =

{

.name = NAME,

.num_resources = ARRAY_SIZE(xxx_resource),

.resource = xxx_resource,

.dev =

{

.platform_data = &xxx_data,

}

};

static int __init xxx_device_init(void)

{

...

/* 注册平台设备 */

platform_device_register(&xxx_platform_device);

...

}

static void __exit xxx_device_exit(void)

{

...

/* 注销平台设备 */

platform_device_unregister(&xxx_platform_device);

...

}

二、平台驱动

平台驱动结构体:

struct platform_driver {

int (*probe)(struct platform_device *);

int (*remove)(struct platform_device *);

void (*shutdown)(struct platform_device *);

int (*suspend)(struct platform_device *, pm_message_t state);

int (*resume)(struct platform_device *);

struct device_driver driver;

const struct platform_device_id *id_table;

};

平台驱动结构体driver成员里面的name必须与平台设备结构体里面的name成员一致,在系统注册一个设备的时候,会通过设备结构体里面的name成员和平台驱动driver里面的name成员匹配,当匹配成功则调用平台驱动的probe函数,
通常在probe函数中获取平台设备的资源和私有数据并进行设备的初始化。

获取设备资源:

1 struct resource *platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num);

platform_get_resource()函数用于获取平台设备的资源,dev为要平台设备,type为平台设备资源类型,num为平台资源号(比如同一个资源有两个则资源号为0,1)。

平台驱动注册:

1 int platform_driver_register(struct platform_driver *drv);

platform_driver_register()函数完成平台驱动的注册,在驱动模块加载时调用。

平台驱动注销:

1 void platform_driver_unregister(struct platform_driver *drv);

platform_driver_unregister()函数完成平台驱动的注销,在驱动模块卸载时调用。

平台驱动模板:


static int __devinit xxx_probe(struct platform_device *pdev)

{

struct xxx_plat_data *pdata = pdev->dev.platform_data; /* 获取私有数据 */

platform_get_resource(pdev,xxx,x); /* 获取设备资源 */

...

}

static struct platform_driver xxx_platform_driver =

{

.probe = xxx_probe,

.remove = __devexit_p(xxx_remove),

.driver =

{

.name = NAME, /* 跟平台设备名一致 */

...

},

...

};

static int __init xxx_driver_init(void)

{

...

/* 驱动注册 */

platform_driver_register(&xxx_platform_driver);

...

}

static void __exit xxx_driver_exit(void)

{

...

/* 驱动注销 */

platform_driver_unregister(&xxx_platform_driver);

...

}

嵌入式物联网资料分享交流群:707159742 入群有全套学习视频资料电子书免费赠送!

参考资料:

嵌入式开发直播课 - 精通Linux设备驱动模型-Kobject​www.makeru.com.cn 嵌入式Linux驱动 - linux设备驱动开发必备技能 - 设备树​www.makeru.com.cn 嵌入式底层开发 - linux驱动开发必备:全面认识设备树​www.makeru.com.cn
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值