鸿 网 互 联 www.68idc.cn

当前位置 : 服务器租用 > 编程语言开发 > c++ > >

[arm驱动]从零开始写个platform平台总线

来源:互联网 作者:佚名 时间:2014-05-07 18:04
首先要知道platform是总线中的一种,要实现platform总线先要从总线开始下手。第一阶段:先创建一个mybus总线和为测试match匹配而写的device和driver1、先创建一个

       首先要知道platform是总线中的一种,要实现platform总线先要从总线开始下手。

第一阶段:先创建一个mybus总线和为测试match匹配而写的device和driver

1、先创建一个mybus的bus

structbus_type mybustype = { .name = "mybus",/*创建的总线目录为/sys/bus/mybus */ }; EXPORT_SYMBOL(mybustype);///proc/kallsyms staticint__init bustest_init(void){ intret; printk("*****%s****\n", __FUNCTION__); ret = bus_register(&mybustype); if(ret < 0){ printk("bus_register fail\n"); returnret; } return0; }

2、一般总线都需要一些属性的描述,也提供获取版本信息的外部接口


/************声明一个总线(bus)的总线的属性(attribute)对象*******************/ charbusversion[SIZE] = "mybus"; staticssize_t mybusattrshow(structbus_type * bus, char* buf){//提供外部访问设备属性的接口 printk("*****%s****\n", __FUNCTION__); returnsnprintf(buf, SIZE, "%s\n", busversion); } staticssize_t mybusattrstore(structbus_type *bus, constchar* buf, size_tcount){//提供外部访问设备属性的接口 printk("*****%s****\n", __FUNCTION__); returnsnprintf(busversion, SIZE, "%s", buf); } BUS_ATTR(busversion, S_IRUGO|S_IWUGO, mybusattrshow, mybusattrstore); //生成bus_attribute对象bus_attr_busversion /************声明一个总线(bus)的总线的属性(attribute)对象*******************/

3、创建bus属性对象的文件

staticint__init bustest_init(void){ intret; printk("*****%s****\n", __FUNCTION__); ret = bus_register(&mybustype); if(ret < 0){ printk("bus_register fail\n"); returnret; } ret = bus_create_file(&mybustype, &bus_attr_busversion);//创建属性文件 if(ret < 0) { returnret; } return0; }

4、给总线完善匹配match函数

staticintmybus_match(structdevice * dev, structdevice_driver * drv){ printk("*****%s****\n", __FUNCTION__); return1;//先默认返回匹配成功 }


   测试

   在mybus总线上创建driver和device

   device.c

extern struct bus_type mybustype; void mydevicetest_release(structdevice *dev){ printk("*******%s*******\n", __FUNCTION__); } struct device mydevicetest_device = { .bus_id = "mybusname",//在2.6.3版本中被init_name代替 /*static int my_match(struct device *dev, struct device_driver *driver) { return !strncmp(dev->bus_id, driver->name, strlen(driver->name)); } */ .bus = &mybustype, .release = mydevicetest_release, }; static int __init mydevicetest_init(void){ intret; printk("*******%s*******\n", __FUNCTION__); if(IS_ERR(&mydevicetest_device)){ returnPTR_ERR(&mydevicetest_device); } ret = device_register(&mydevicetest_device); if(ret < 0){ printk("mydevicetest_init fail\n"); return ret; } return0; }

   driver.c

static int mydevice_driver_probe (structdevice * dev){ printk("*****%s*****\n", __FUNCTION__); return0; } static int mydevice_driver_remove(structdevice * dev){ printk("*****%s*****\n", __FUNCTION__); return0; } extern structbus_type mybustype; struct device_driver mydevice_driver = { .name = "mybusname",//对应的驱动名称在/sys/bus/mybus/driver/mybusname .owner = THIS_MODULE, .bus = &mybustype, .probe = mydevice_driver_probe, .remove= mydevice_driver_remove, }; static int__init drivertest_init(void) { int ret; ret = driver_register(&mydevice_driver); if(ret < 0)return ret; return0; }

   完整代码下载地址,对应压缩包mybusone

   测试结果,看出总线没问题,match强行返回1,可以probe        

$ insmod kodir/bustest.ko *****bustest_init**** $ insmod kodir/devicetest.ko *******mydevicetest_init******* $ insmod kodir/drivertest.ko *****mybus_match**** *****mydevice_driver_probe***** $

Tip:你可以通过cat /sys/bus/mybus/busversion 查看版本号,也可以echo "..." > /sys/bus/mybus/busversion修改版本号,对应函数会调mybusattrshow和mybusattrstore

第二阶段,从上面的driver和device的注册可以看出,driver和device都要预先知道总线的对象的名称extern structbus_type  mybustype;

   我们可以在bus中封装对应的driver和device的函数

   修改bus.c

//注释掉EXPORT_SYMBOL(mybustype);同时封装device和driver注册注销函数 //EXPORT_SYMBOL(mybustype);///proc/kallsyms //添加下面封装device和driver注册注销函数 int mybus_device_register(struct device *dev){ dev->bus = &mybustype; return device_register(dev); } EXPORT_SYMBOL(mybus_device_register); void mybus_device_unregister(struct device *dev){ dev->bus = &mybustype; device_unregister(dev); } EXPORT_SYMBOL(mybus_device_unregister); int mybus_driver_register(struct device_driver *driver){ driver->bus = &mybustype; return driver_register(driver); } EXPORT_SYMBOL(mybus_driver_register); void mybus_driver_unregister(struct device_driver *driver){ driver->bus = &mybustype; driver_unregister(driver); } EXPORT_SYMBOL(mybus_driver_unregister);

  修改device.c

//添加mybus.c中封装的device注册注销相关函数mybus_device_register,,mybus_device_unregister extern int mybus_device_register(struct device * dev); extern void mybus_device_unregister(struct device * dev); static int __init mydevicetest_init(void){ //.............. ret = mybus_device_register(&mydevicetest_device); //............ } static void __exit mydevicetest_exit(void){ //............. mybus_device_unregister(&mydevicetest_device); }
网友评论
<