展锐平台手机camera 软硬件架构

devtools/2024/9/25 16:56:00/

曾经在紫光展锐做过几年的camera驱动,经历过从2013 年最初的几人团队,每人独当一面,负责很多的模块的粗放,到后面的逐步的精细化,设计部门按照内核驱动,hal驱动,tuning效果,3A,效果算法等展开,个人和团组只需专注于某一层面的模块或者算法的反复迭代。现在虽然离开展锐已经数年,对其中软硬件开发过程中的映像还是比较深刻,对开发的规范执行和架构和feature实现的优化选择尤为感慨,这里做个对当时情景的分享回顾,让大家对手机里面的camera架构有个了解。

在这里插入图片描述
以上是当时展锐 camera系统的软硬件大致架构。最底下是展锐的isp 硬件系统和外部sensor。其上是内核层的各类对应驱动。再上面是内核层之上,hal层之下的hal 分层驱动,最上就是安卓自带的cameraserver,负责在camera的app 和 hal之间来调用传递帧和各类参量。

HW 层

HW这个对应的层级是硬件层,主要是芯片里面的isp 硬件系统,相机后处理模块cpp,csi /mipi,外部的各类典型的sensor。

这里isp 硬件系统包含了online 处理部分的DCAM 和offline的isp,不包括mipi csi controller和dphy,展锐对于isp硬件的定义和行业稍有差异,业内把所有从sensor 进入的mipi dphy 到最终输出到DDR buffer 之前的所有关于图像流处理的硬件系统都称之为isp,如上图虚线框内的这部分。

online 部分的DCAM 硬件接收从mipi csi controller 过来的数据流,实现预览录像和拍照的数据分流,还有其他的pdaf,vch 虚拟通道的解包分流等。预览拍照通路接受sensor过来的全尺寸图像,变换为最终输出的图像流的各种尺寸。在通路内部增加了不同的效果处理模块,online 主要关注raw 域的效果处理,这些模块会在后续展开。dcam 分流出来的通路最终会把图像帧吐到驱动设定的各个内部轮转的buffer内,给offline的isp 硬件做输入。
这里一个DCAM 硬件对应一个mipi csi controller 过来的数据流,也就是一个正在运行的sensor,如果是多个sensor 同时运行,那就有多个DCAM 接入到mipi csi controller 后面在运行,经典的isp 系统一般有两个主要的online的DCAM,支持大尺寸的sensor,1~2 个小的DCAM支持小尺寸的sensor。
offline部分的isp硬件只有1个,它接收各个DCAM送来的图像帧,在各路流的30fps的基础上做分时的预览/拍照/录像的帧的效果处理,最终输出YUV420 图像。一般来说,一个33ms内分成4个slot,按照预览/拍照/录像/拍照 这样的顺序做分时处理,之所以这样设计isp,是因为针对大尺寸的拍照图片,在online 的处理上带宽不容易满足,容易产生瓶颈导致堵塞整条通路。做成这种offline 处理后,将图像在宽度方向上按照2592 的最大切片宽度做分割,这样64M 或者上亿分辨率的大图像,在宽度方向上切割成几个slice切片,针对每个slice 做分别处理,在输出设置上做准确的配置,使isp输出在每个行buffer上对应的切片位置,最终得出完整的一帧处理后的大图像,绕开了超级大图带来带宽瓶颈。唯一的不足就是拍照牺牲了实时性。需要几帧的时间来完成大图的isp 处理。
对于预览和录像来说,没有这种切片需求,1个slot 内基本都能处理完毕。如果在运行期间没有拍照,那isp会调度把拍照这部分的带宽让出来优先处理正在运行的预览录像。
这样多个online 部分的DCAM 硬件,加上单个的isp组合,基本实现了各种场景尤其是双摄的典型应用了,同时可以降低zsl 拍照时的运行带宽。只有zsl 拍照时刻,DCAM 的拍照通道的大图才会被offline部分的isp硬件处理,而且是分割切片处理了各个slice。

cpp 这部分是相机的后处理模块,主要是关于图像的旋转和拉伸,拉伸主要用于在拍照过程中需要的输出320*240的thubmbnail 图,这样方便和大图一起合成最终的jpeg图,这样在PC 上能被正确的看到小图标。旋转主要是90,180,270 ,mirror,flip这类简单的翻转。

csi/phy 是关于mipi csi controller和dphy,cphy 这类,展锐有自己实现的这类模块,实现国产化的替代。csi/phy 也是对应一个sensor 一路,一般的isp 硬件系统有至少3路这样的mipi csi controller和phy。

sensor 就是手机上的各类sensor,包括前后摄像头,双摄的第2颗辅助摄像头,其他应用场景的摄像头等,都是用i2c来写入配置,产生mipi 总线上的图像流输出到ISP系统

kenerl 驱动层

对应于硬件上的结构设计, 在kernel 内部驱动也是做了相应的匹配设计。
展锐isp 的驱动在最早的版本上是实现了V4L2 框架的设计,后续为了方便支持双摄等场景,剥离了V4L2 ,采用了简单的类V4L2 接口的misc 设备节点,在对应V4L2 ioctl 命令的基础上增加了BIND/UNBIND 摄像头指定的dcam id这样的操作接口。这样不用大改user到HAL 这层的驱动,就能沿用上之前的框架。

isp 驱动最上层是dcam_core 这层接口,实现输入图像流尺寸,格式,输出各路图像的尺寸,格式,帧buffer的配置,最终启动streamon, 通过dequeue,queue 实现各路图像帧的完成上传和回收排队再次等待接收图像帧。或者streamoff 停止图像流的接收等,这一层完全是逻辑相关的,不涉及到任何的硬件操作。实现了对上的cmr_grab 的适配,对下的dcam_drv 和isp_drv 的调配。
dcam_core下面有dcam drv 和isp drv 这两种驱动模块,分别处理online 和offline 硬件部分,dcam drv主要是关于online的输入图像的接口模块的cap_top和各个输出通路的寄存器的配置,各类中断的响应,输出buffer的完成接收,给到dcam_core,上传给cmr_grab到和上层使用完毕,压回dcam_core到dcam drv 。还有关于各个效果模块的分别参数配置,3A信息帧的配置输出和回收配入,通道sof 等中断信息的发出。isp drv 是关于offline 分时调度的配置和大图slice 切割的配置,中间还是dcam 剩余的效果处理,比如full RGB域,YUV域的效果模块配置。

类似的cpp 也是这样分为cpp_core和cpp_drv 这样的分层处理,cpp_core是逻辑层的接口,主要识别是拉伸还是旋转的配置启动。在cpp_drv里面实现了具体的拉伸还是旋转的寄存器配置和完成通知。

sensor 驱动抽象了所有sensor的供电,配置clk,配置i2c 地址,传输配置参数这类共同的操作接口,还有就是mipi phy和controller的初始化装载和卸载。user 层sensor驱动只需要将具体的配置表(寄存器和值这样)和相关的reset,powerdown有效配置传入,kernel就能正确的驱动。

除此之外,kernel 还有你关于各个模块内需要的上下电接口pw,clk 配置接口等。

需要说明的是,展锐当时实现在了一个族的系列片最小的修改量,来支持不同系列的芯片项目,这样沿用一套完全相同的驱动框架,通过反复的软件迭代来保证项目的稳定。,如下图这样,将有不同的差异部分的操作抽象出来,实现在xxx_drv层的调用。
在这里插入图片描述

HAL层驱动

kernel 之上是user层的驱动,也就是HAL分层驱动。除了HAL 使用了安卓原生的c++之外,其他都是用标准c写的,增加了可移植性,同样的一套code,从HAL层以下都能方便的移植到其他的linux系统上去。

HAL层code 最早支持HAL1.0,中间也曾短暂搞过2.0,最终在展锐那会是HAL3.0 的框架,1.0,2.0 基本不再维护和使用。这部分code 是对安卓框架,尤其是java app 这边的功能支持,同时也要调用到sprd_oem 层里面。

sprd_oem 是综合场景的实现层,实现了最终各种场景的顶层设计。它可以调用其下各个模块来实现hal层需要的接口。
sprd_oem层下面的各个模块不能互相调用,只能由sprd_oem来调用实现完整流程。这模块提供接口或者回调函数指针,来实现往下的调用和往sprd_oem上层的信息传递。

cmr_preview 模块 是实现预览或者录像通路的完整配置和数据帧的流转。其中包含了设置输出帧的格式,大小,ion 管理的buffer 地址,输入帧的格式,大小等。
cmr_snapshot 模块是实现拍照通路的完整配置和数据帧的流转, 其中包含了设置输出帧的格式,大小,ion 管理的buffer 地址,输入帧的格式,大小等。 它的大小图生成和转化成合成的jpeg 输出的内存的分割由sprd_oem调用cmr_mem 来实现。
cmr_mem 是管理拍照的内存分割,如果按照拍照时需要各种类型的内存完全平铺来申请,那内存会耗的非常厉害,这里采用了优化的合并复用,来减少内存的开销。
cmr_grab 是HAL 分层驱动的最底层,是适配kernel 层的dcam core,来实现图像帧,统计帧的抓取,sof 各帧时间戳的获取等。

关于ISP效果类的配置和统计信息,cmr_grab 将会通过判断接收类型分发到isp mw层去。isp mw 会把3A 信息再传递给isp 3A alg,结合app这边给出的配置来决定3A的调配运行。同时isp tune 这层也会把app 这边给出来的配置通过isp mw ,cmr_grab ,下发到内核中配置硬件,实现效果的动态配置。

cmr_sensor 是关于各种支持sensor的驱动配置,具体的mipi类型,供电参数,powerdown,reset,供电电压,帧率,寄存器配置表等,通过内核sensor 驱动实现了最终的sensor的配置。同时isp 这边需要的3A 统计部分也有对sensor 这边的动态配置。

cmr_sensor 里面的sensor 配置和 isp tune的sensor 效果是一一对应的,展锐把sensor的驱动放到了cmr_sensor 层,把sensor对应的数据流ISP 调校放到了 isp tune,通过项目的编译xml 文件来生成对应的可配置。而且展锐还做了了按需生成项目需要sensor库和tuning库,防止了无关的sensor库和tuning库带来的尺寸开销和运行时遍历sensor带来的性能问题。
这部分可以参考 展锐平台的camera sensor驱动代码设计解析

关于图像帧的流转

在这里插入图片描述

对帧的流转,从dcam的online 到isp的offline,然后和hal层的传递回传,这里大致介绍下。

展锐的所有需要的应用需要的图像帧buffer 是在HAL分层驱动里面由ion 来申请的,然后通过QUEUE 这个ioctl 传入,在kernel转换成物理地址,刷入到camera IOMMU的一级页表中去。streamon 以后不再动态改动这个页表,在streamoff 的时候才会撤除。
内核需要的从dcam 输出传递到isp 输入的帧是内核层分配的,在streamon 前根据格式和尺寸预先分配好,然后也是变换成物理地址以及设置页表的camera 专用IOMMU中去。

具体流程这样,dcam 在sof中断到来的时候设置下一帧的buffer到寄存器中去,这帧地址在下一个sof到来才会真正的生效,是下一帧的图像存在这帧的buffer,同时当前帧buffer 地址截接收生效。streamon后 的第一帧buffer 不需要sof,需要强写一个立即生效位,硬件就把当前帧写入buffer。
如图,dcam 后面一共有4片buffer,A2 这片已经收完整帧,然后给isp 去做输入。下一帧buffer A3 在之前A2帧的sof 已经设置好,在A3的sof 触发时生效,等待硬件刷入整帧数据,刷完后也是和A2一样,在A2 后面输入给isp,后面的A0,A1 也是同样处理。A2这帧的buffer如果isp 处理完,那就把它还给DCAM,排队到A1后面,依次等待dcam 的使用和输出。这样形成online 到offline的内循环处理。中间如果系统发生瓶颈问题,所有帧都给了isp,但是都没有处理完成,为了防止dcam online 的误踩有效图像,破坏已有数据帧,给DCAM 一个reseve帧,这个帧只是空转,不会传递给isp。等isp 有帧返回给dcam 了,再接着使用这些有效帧循环。

isp 这边的帧是HAL 分层驱动传递过来的,也是类似的思路。ISP 只有dcam 给过来帧和HAL 给输出帧buffer都有了,才会做offline的转换,否则啥都不干,因为没有输入输出buffer可用。当前图上 ISP 的0 buffer已经完成,上传给HAL,HAL 传递到app 去处理。1 号buffer 接着对应下一帧dcam 的输入处理,1号buffer如果处理完,也是上传到HAL,然后app,后面2号也是同样。app 处理完的3 号buffer当前回传给isp,ISP会把它放到2之后依次处理,这样形成isp 这边的外循环。

这就是展锐当时的camera 内部的软硬件系统架构。


http://www.ppmy.cn/devtools/117066.html

相关文章

Sui通过对共享对象的阻塞控制简化交易

高吞吐量区块链的核心是它能快速、安全地处理大量交易。然而,当交易涉及写入相同的共享对象时,它们必须依次执行。这可能导致较长的检查点时间,进而降低状态同步的效率。 共享对象阻塞控制的首要目标是提高检查点执行的效率。通过控制每个检…

大数据新视界 --大数据大厂之探索ES:大数据时代的高效搜索引擎实战攻略

💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-24

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-24 1. Enriching Datasets with Demographics through Large Language Models: What’s in a Name? K AlNuaimi, G Marti, M Ravaut, A AlKetbi, A Henschel… - arXiv preprint arXiv …, 2024 通过大型语言…

ARCGIS PRO SDK MapProjectItem 地图项目类

一、获取工程中的所有地图 Dim projectMaps As IEnumerable(Of MapProjectItem) Project.Current.GetItems(Of MapProjectItem)() 二、从项目中删除地图 Dim mapProjItem Project.Current.GetItems(Of MapProjectItem)().FirstOrDefault(Function(mpi) mpi.Name "需…

【计算机网络 - 基础问题】每日 3 题(二十一)

✍个人博客:Pandaconda-CSDN博客 📣专栏地址:http://t.csdnimg.cn/fYaBd 📚专栏简介:在这个专栏中,我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞👍收藏&…

Python 学习之虚拟环境

一、为什么需要虚拟环境 到目前位置我们所有的第三方包安装都是直接通过 pip install xx 的方式进行安装的,这样安装会将那个包安装到你的系统级的 python 环境中。但是这样有一个问题,就是如果你现在 Diango 1.10.x写了个网站,然后你的领导…

鸿蒙开发(HarmonyOS)组件化浅谈

众所周知,现在组件化在移动开发中是很常见的,那么组件化有哪些好处: 1. 提高代码复用性:组件化允许将应用程序的不同功能模块化,使得这些模块可以在不同的项目中重复使用,从而提高开发效率并减少重复工作。…

卷积神经网络-最优模型

文章目录 一、关键步骤1. 定义性能评估指标2. 设置保存逻辑3. 保存最佳模型4.使用最优模型 二、代码运用1. 保存模型参数(state_dict)2. 保存完整的模型3.使用模型参数4.读取完整模型的方法 三、保存模型优缺点1.优点2.缺点 在卷积神经网络(C…