学写驱动抽象层

驱动的抽象层其实类似一个管理层,管理多种资源,使资源之间更加有序,高效的工作。使软件的复用性和鲁棒性更强。其核心思想是面向对象的编程思想,创建抽象的概念,增加抽象层之间的逻辑给更高层,屏蔽底层的“杂乱无章”。

 

理清芯片之间的关系和逻辑

学写驱动抽象层_第1张图片

硬件上8541e通过mipi和i2c连接到9288,9288通过gmsl信号线连接到96705编串器上,96705和0144是通过dvp接口连接,包含i2c。软件上平台8541e通过i2c访问配置9288,通过9288的映射寄存器来访问96705和0144,所以我们软件实现的目标是在8541e上获取0144的图像数据,9288和96705是一种通信的编串和解串方式,不影响数据格式。

 

所以8541e看到的是关闭打开摄像头,读取摄像头id,设置摄像头格式,帧率等接口。不需要关心中间环节。这也是驱动抽象层给上层看到的接口。对于软件的底层,我们可以把serdes抽象成桥,把传感器抽象成sensor。不管什么桥,不管什么sensor都适用这套方法。

创建对象结构体

三个抽象对象:

  1. 面向平台的camera操作方法和数据
  2. 面向brg的操作方法和数据
  3. 面向sensor的操作方法和数据

学写驱动抽象层_第2张图片

1和3的区别在于比如1的power on会包含2和3的power on。

灵活使用链表管理

链表用于管理已创建的数据对象,把相同的数据结构连起来,方便管理。比如在sensor的power中会用到brg的i2c_rw_0144的方法,就可以遍历brg的链表,查找链表中名字为“9288”的brg,当然如果注册了多个brg,可以按照名字区分,也可以按照id来区分。

static LIST_HEAD(brg_list);

list_add_tail(&brg->list, &brg_list);

static inline struct serdbrg_device * sensor2brg(void)

{

    struct serdbrg_device *ambrg;

 

    list_for_each_entry(ambrg, &brg_list, list) {

            if (ambrg->id == 0)

                return ambrg;

    }

 

    printk("Can't find serdbrg in list\n");

    return NULL;

}

创建逻辑层,抽象接口

当需要创建一个brg的设备驱动时候,我们需要调用一个注册的接口:

int _register_serdes_brg(struct serdbrg_device *brg, struct serdbrg_ops *ops)

当需要创建一个sensor的设备驱动时候,我们需要调用一个注册的接口:

int _register_serdes_brg_device(struct sensor_brg_device *sensor, struct sensor_brg_ops *ops)

 

调用这两个接口之前,要完成对象结构体的创建,就是传送到函数的参数。

 

这两个函数所做的逻辑主要是:

  1. 获取设备id信息,不成功则退出注册,并提示用户失败。成功进入下一步。
  2. 加入设备到链表。
  3. 创建文件系统接口。
  4. 提供文件系统接口访问逻辑,主要是camera抽象函数的实现,比如:

Camera的stream on方法,上层访问文件系统接口,传入参数POWERON,然后底层调用brg和sensor的方法,输出图像:

     gbrg->ops->brg_power_on(gbrg,1) ;

     gbrg->ops->brg_hw_init_pre(gbrg);

     gbrg->ops->brg_set_clk_si(gbrg,0);

     gsensor->ops->init_device(gsensor);

    gbrg->ops->brg_vout_config(gbrg,1);
  1. 文件系统接口可以使用字符设备ioctl的方法也可以使用sys文件属性的方法,都可以实现。

总结

虽然本例程没有对多个sensor和brg做测试,但是原理上是可以很容易的兼容多个设备,通过id或者名字进行选择操作方法。

你可能感兴趣的:(车机)