驱动内核平台移植步骤

本文详细介绍了Linux平台驱动的移植步骤,包括设备模型、资源管理、总线驱动、设备描述结构体和驱动描述结构体等内容。通过设备树文件添加自定义设备,驱动文件的修改,以及注册和移除驱动的实现过程。此外,还提到了内核设备节点的动态创建和udev管理设备文件的方法。
摘要由CSDN通过智能技术生成

驱动内核平台移植步骤

在计算机中有这样一类设备(如I2C ,USB等),它们通过各自的设备控制器,直接和CPU连接,CPU可 以通过常规的寻址操作访问它们(或者说访问它们的控制器)。
这种连接方式,并不属于传统意义上的总线连接。但设备模型应该具备普适性,因此Linux就虚构了一条Platform Bus,供这些设备挂靠。
为了便于统一管理, linux抽象出 了资源的概念,使用时仅需get_ resource.

优点:
1隔离了硬件信息和驱动,做 到板相关的代码和驱动分离。 ----》 修改扩展
如果硬件有改动或移植,仅 需修改一下platform中关于资源的描述就可以了。
2符合 总线 驱动 设备的统设备模型, 方便管理

在层次结构上,有一个设备serial,将有一个serial的目录,serial设备里面是属性文件,可以通过修改属性文件值修改驱动

/sys                            sysfs
  |
 bus							keset
  |
 pci                            keset
  |
drivers							keset(一组有共性的驱动集合)
  |
serial							kobject(一个具体的设备)
  |
newid							attribute

设备描述结构体:

struct device{
	struct kobject kobj;
	struct bus_type * bus;
	struct device_driver *driver;
	void *driver_data;
}

驱动描述结构体:

struct device_driver{
	const char                *name;
	struct bus_type			  *bus;
	int (*probe) (struct device *dev);//初始化函数需要自己实现
	int (*remove) (struct device *dev);//退出函数需要自己实现
}

总线描述结构体:

struct bus_type{
	const char					*name;//总线类型名称
	int (*match)(struct deviec *dev,struct device_driver *drv);//函数会自动通过名字去匹配设备device 和驱动driver
	int (*uevent)(struct device *dev,char **envp);
	int (*probe)(struct device *dev);
	int (*remove)(struct device *dev);
}

硬件资源结构体:

struct resource{
	resource_size_t start;//资源开始位置
	resource_size_t end;//资源结束位置
	const char *name;
	unsigned long flags;//资源的类型 IORESOURCE_MEM(内存地址)  IORESOURCE_IRQ(中断)
}

平台设备结构体:

struct platform_ device {
	const char		* name; //平台设备的名称
	u32				id;
	struct device	dev; //内嵌的device实现继承
	u32				num_ resources ;
	struct resource * resource; // 平台设备的资源
};

平台驱动结构体:

struct platform_driver {
	int (*probe)(struct platform_device *) ;
	int (* remove)(struct platfbrm_device *) ;
	struct device_ driver driver; // 内嵌的device_ driver实现继承
};

平台驱动具体操作:

1.在内核的设备树文件中添加自定义设备:
例:vim linux-3.14/arch/arm/boot/dts/exynos4412-origen.dts
参考模板:

myled@0x11000c40{
	compatible = "farsight,myled";
	reg = <0x0203F000 0x4>,<0x0203F0c5 0x4>;
}

解释说明:
compatible 表示设备描述作用是与设备进行匹配,必须保证字符串的内容完全一致。
reg:表示初始的地址,和内存空间的大小。如果有两个地址需要定义,那么写法如下:

reg = <0x0203F000 0x4>,<0x0203F0c5 0x4>;

驱动文件修改:

static int myled_probe(struct platform_device *pdev)
{
	int ret = -1;
	//内核相关的部分
	//1.注册
	devno = MKDEV(MA,MI);
	ret = register_chrdev_region(devno,devNum,devName);
	if(ret != 0)
		return ret;
	//2.初始化
	cdev_init(&mydev,&myops);
	//3.添加到系统
	ret = cdev_add(&mydev,devno,devNum);
	if(0!=ret)
	{
		unregister_chrdev_region(devno,devNum);
		return ret;
	}
	//硬件相关的部分
	//1.将实际的物理地址映射为虚拟地址
	resource *pgx2conres = platform_get_resource(pdev,IORESOURCE_MEM,0);//将实际的内存地址存在了设备树中
	resource *pgx2datres = platform_get_resource(pdev,IORESOURCE_MEM,1);
	gpx2con = ioremap(pgx2conres->start,4);
	gpx2dat = ioremap(pgx2datres->start,4);
	//2.对硬件进行初始化操作
	writel((readl(gpx2con) & ~(0xf<<28)) | (0x1<<28),gpx2con);
	writel(readl(gpx2dat) & ~(0x1<<7) ,gpx2dat);
	printk("mod init OK\n");
	return 0;
}
static void myled_drv_remove (struct platform_device *)
{
	//内核部分
	//1.删除设备
	cdev_del(&mydev);
	//2.注销设备
	unregister_chrdev_region(devno,devNum);
	//硬件部分
	//1.复位(不是必须操作)
	writel(readl(gpx2dat) & ~(0xf<<7), gpx2dat);
	//2.地址回收(必须操作)
	iounmap(gpx2con);
	iounmap(gpx2dat);
	printk("mod exit OK\n");
	return;
}
#ifdef CONFIG_OF
static const struct of_ device_ id myled_ of_ matches[] = {
	{	.compatible = "farsight,myled"}//(这个名字与设备树中的compatible必须完全匹配)
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, myled_of_matches);
#endif
static struct platform_ driver myled_ driver = {
	.driver = {
			.name	= "myled".
			.owner	= THIS_ MODULE,
			.of_ match_ table = of_match_ptr(myled_ of_ matches),
	},
	.probe	= myled_probe,
	.remove = myled_drv_remove,
};
module_platform_driver( myled_driver);

平台驱动与纯模块驱动的最大的改动为模块注册部分,然后就是硬件操作时的地址读取部分

最后进入linux3.14目录下重新编译一下设备树文件:make dtbs,再将设备树移动到tftp文件夹下

//在/dev下自动创建设备节点(管理设备文件方法演变mkdnod -- > devfs(动态内核) --> udev(真实用户) )
	//?什么是devfs,它有何优缺点
	是由Linux2.4 引入的,它使得设备驱动能管理自己,如创建删除/dev,修改权限等。
	优:
	1.无需手动mknod,它可devfs_ mk cdev 等自动生成
	2.不需要指定主次设备号,传e的主设备号,它会动态获取。
	缺:
	1.不确定的设备映射,
	2. /dev下文件太多,且不是表示当前系统实际的设备,
//?什么是udev,它有何优缺点
	是由linux2.6 引入的用于替代devfs。
	优:
	1. 稳定的设备映射
	2. /dev下只包含系统真实存在的设备
	3.无需手动mknod,用device_ create会 自动创建
struct class *my_ class ;
//加到init函数的内核部分
	/* creating your Own cLass */
	my_class = class_create(THIS_MODULE, "dev_class");
	if (IS_ERR(my_class)) {
		printk("Err: failed in creating class.\n");
		return ;
		}
	/* register your own device in sysfs, and this will cause udevd to create corresponding device node */
	device_create(my_class, NULL, devno, NULL, "myled");

该段代码主要是动态在/sys/class目录下创建一个dev_class的文件夹,再在文件夹中创建一个myled的设备,然后系统会自动调用/dev/mydev目录,如果该目录下没有相应地设备驱动,那么系统会自动添加驱动。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值