首页 > 代码库 > 教你一招如何开发平台无关的内核驱动
教你一招如何开发平台无关的内核驱动
相信搞过内核驱动开发的人员都面临过这样的问题:为了让上层代码尽可能的不改变,需要底层驱动对上层提供的接口在各种形态上都要保持不变,但是底层的逻辑实现又不可避免的有差异,甚至有些时候在同一款产品形态上都会有很大差异,那么我们此时该如何设计驱动架构,使代码看起来既好看又易于维护呢?接下来我们来具体分析一下。
举一个例子,现在有两种规格的定时器,内部实现逻辑不一样,要操作的寄存器也有差别,那么我现在有三种产品形态,一种形态上使用feature1,一种形态上使用feature2,另一种形态上这两种feature都会使用,那么此时还需要对上层提供的接口一致,接下来我们该如何做呢?
1、实现feature1的接口:
void timer_feature1_enable(u32 timer_id){........}
void timer_feature1_disable(u32 timer_id){........}
/*此处略去其他接口......................*/
2、实现feature2的接口:
void timer_feature2_enable(u32 timer_id){........}
void timer_feature2_disable(u32 timer_id){........}
3、对上层提供的接口:
void timer_enable(u32 timer_id){........}
void timer_disable(u32 timer_id){........}
对上层的这两个接口里边该如何实现呢?
首先我们先来设一个控制回调函数的ops结构体:
struct timer_ops{
void (*enable)(u32 timer_id);
void (*disable)(u32 timer_id);
..............
};
struct timer_ctrl{
struct *timer_ops[8];/*假设有8个定时器*/
};
struct timer_ops feature1_ops ={
.enable = timer_feature1_enable,
.disable = timer_feature1_disable
};
struct timer_ops feature2_ops ={
.enable = timer_feature2_enable,
.disable = timer_feature2_disable
};
/*如果此产品形态上只使用feature1*/
#ifdef TIMER_FEATURE1
static struct_ctrl common_ctrl = {
timer_ops[0] = &feature1_ops,
timer_ops[1] = &feature1_ops,
.......
};
#endif
/*如果此产品形态上只使用feature2*/
#ifdef TIMER_FEATURE2
static struct_ctrl common_ctrl = {
timer_ops[0] = &feature2_ops,
timer_ops[1] = &feature2_ops,
.......
};
#endif
/*如果此产品形态上同时使用feature1和feature2,比如前4个使用feature1,后四个使用feature2*/
#ifdef TIMER_FEATURE1_AND_FEATURE2
static struct_ctrl common_ctrl = {
timer_ops[0] = &feature1_ops,
timer_ops[1] = &feature1_ops,
...................
timer_ops[4] = &feature2_ops,
timer_ops[5] = &feature2_ops,
.......
}
#endif
控制结构体设置好之后,我们就可以在对上层接口里尽情调用了
void timer_enable(u32 timer_id)
{
common_ctrl.timer_ops[timer_id]->enable(timer_id);
}
void timer_disable(u32 timer_id)
{
common_ctrl.timer_ops[timer_id]->disable(timer_id);
}
这样设计驱动架构之后,无论后续又有多少个新特性,我们可以随心所欲进行添加,可扩展性极强,而且还特别易于维护。
其他任何有差异性的IP均可采用此思想进行平台无关的开发。