DualOS架构说明
1. 概述¶
为了满足有快速启动和便携功能的特殊用途相机的需求,我们结合 RTOS的轻量、快启动和Linux系统的通用可扩展 特性,Sigmastar为现有产品提供了DualOS的系统解决方案,该方案可以使用户避免大幅度代码重构以及 降低用户开发周期,并可以满足经济型和高性能平台的不同要求。
DualOS的API层与Sigmastar的Pure Linux完全一致,这样用户可以快速把基于Pure Linux 平台开发的应用移植到DualOS系统平台。
DualOS项目主要使用了ARM的TrustZone技术。
TrustZone 在概念上将 SoC 的硬件和软件资源划分为安全(Secure World)和非安全(Non-Secure World,也称Normal World)两个世界。
处理器架构上,TrustZone 将每个物理核虚拟为两个核,一个非安全核(Non-Secure Core, NS Core),运行非安全世界的代码(LINUX);和另一个安全核(Secure Core),运行安全世界的代码(RTOS)。
图1-1 Normal World 和 Secure World架构图
2. 系统架构以及流程¶
2.1. SMPLH系统架构¶
图1-2 SMPLH(Symmetric Multi-processing Light Hypervisor)架构图
多核双系统架构,Iford平台默认支持该架构。
Linux运行在core0~core1的Non-Secure World。
RTOS运行在core1的Secure World。
Linux为SMP kernel,core1跑SMP Linux及RTOS,RTOS在需要使用时core1会切换过去执行,否则切换回来执行Linux,以此达到user态更好的CPU利用率。
2.2. Hypervisor系统架构¶
Hypervisor是一套运行在物理层与客体操作系统(guest operating system)之间的架构,负责管理guest OS与硬件资源的虚拟机监视器(virtual machine monitor)。
-
sstar 的 virtual machine monitor (简称 SSVMM) 基于 ARM Virtualization Extensions 架构实现,可高效能调度 guest OS 达到 OS 虚拟化效果。
-
sstar 支持两种 DaulOS 架构:
a. 原本的 SMPLH 架构让 Linux 跑在 non-secure world, RTOS 跑在 secure world。
b. 基于 SSVMM 的 Hypervisor 架构让 Linux 和 RTOS 都跑在 non-secure world,secure world 用于 trustzone。可根据 "是否需要 trust zone" 来决定要采用 SMPLH 还是 Hypervisor 架构。
-
SSVMM 目前仅支持两个 guest OS,其中 guest OS 1 (RTOS) 的执行优先级高于 guest OS 2 (Linux),这是基于 sstar DualOS image pipeline 双系统化需求而制定。
图1-3 Hypervisor架构图
2.3. 启动流程¶
启动模式一般分为快速启动模式和普通启动模式。以下SMPLH架构介绍均为快速启动模式。
注意: 快速启动过程不会有Uboot参与。如果需要进入Uboot,请参考环境搭建,开机进入Uboot章节说明。
2.3.1. SMPLH启动流程¶
Iford平台,IPL阶段会加载并运行 Earlyinit Bin,Earlyinit Bin中做一些Sensor和VIF的硬件初始化,Earlyinit完成后,此时Sensor已经出流,VIF将视频流的画面缓存起来(最多缓存4张),等到RTOS阶段创建完成Pipeline后,会直接将VIF缓存的视频流图像给到ISP处理,以此达到快速出流的目的。
图1-3 SMPLH启动流程图
SMPLH架构下,在IPL和IPL_CUST阶段只有core0会使用,core1此时在睡眠,core0 在IPL_CUST阶段Load RTOS和MISC分区后,会唤醒core1去跑RTOS,core0还同时在load linux和ramdisk,用户注意此时不能在RTOS内操作flash,flash会用于core0 load linux和ramdisk。直至core1 RTOS idle了,core1同时会让出来给Linux调度,如图1-3所示。
2.3.2. Hypervisor启动流程¶
Hypervisor boot flow完整流程可参考启动流程。
2.4. 内存结构¶
chip中会使用到DRAM和SRAM,SRAM为sstar内部IP使用,以下只对DRAM部分做详解。
2.4.1. Memory Layout组成和调整¶
请参考:DualOs Alkaid Config Guide,其中的DualOs memory layout章节说明。
2.4.2. RTOS内存管理机制¶
SigmaStar RTOS 内自带一套 heap 管理机制,以及由 heap 扩展而來的 pool 机制。Heap 如同一般熟知的 C library 提供的内存管理,由 malloc、calloc、realloc、free 构成;在 CamOsWrapper API 分別对应 CamOsMemAlloc、CamOsMemCalloc、CamOsMemRealloc、CamOsMemRelease。若 C code 内直接呼叫 C library 提供的 malloc、calloc、realloc、free,在最后阶段会统一导向 CamOsMemAlloc、CamOsMemCalloc、CamOsMemRealloc、CamOsMemRelease 以确保内存分配正确以及第三方code相容性。
一般 heap 在大量且频繁 allocate / free 小块内存时都需要考虑内存碎片问题,有此需求时可考虑使用 pool 机制,概念是开机时将所需的特定大小与数量的 buffer 从 heap 里预留下來,需要反复 allocate / free 时就从预留区 (pool) 里配出。Pool 对应的 CamOsWrapper API 为贴近 Linux 用法,设计为CamOsMemCacheCreate、CamOsMemCacheDestroy、CamOsMemCacheAlloc、CamOsMemCacheFree,详细用法参考 cam_os_wrapper.h。
Pool 大小与数量配置可透过rtos defconfig 的 CONFIG_MEMORY_POOL_CLUSTER_SETTING
进行调整,一组 size * number 称为一個 pool cluster,可同时创建多个cluster。若 rtos defconfig 的 CONFIG_MEMORY_POOL_SUPPORT
注释掉时,CamOsMemCacheCreate、CamOsMemCacheDestroy、CamOsMemCacheAlloc、CamOsMemCacheFree 还是可以使用,只是这些 API 在配置 buffer 时就不是走 Pool 机制而是一般的 heap 机制,自然也就没有抗碎片能力了。
若 code运行过程中遇到 CamOsMemCacheAlloc 返回 NULL 申请不到内存,可参考以下方法进行调整
- 若
CONFIG_MEMORY_POOL_SUPPORT
没有开启,表示整体 heap 耗尽了或太过破碎,以至于无法再配出连续的空间,这种情况请考虑加大RTOS的Memory Size。 - 若
CONFIG_MEMORY_POOL_SUPPORT
有开启,表示预留的 Pool 在运行期间被用光了,可参考上述 size * number 控制 pool cluster 原则对Pool规划进行微调。
2.4.3. 运行时查看内存方法¶
1、蓝色部分划分给linux,由linux管理;使用情况可以用linux通用命令查看,如:
cat /proc/meminfo cat /proc/vmallocinfo
2、黄色部分划分给MMA,由sys管理;使用情况查看:
cat /proc/mi_modules/mi_sys/mi_sys0 cat /proc/mi_modules/mi_sys_mma/mma_heap_name0
3、绿色部分主要划分给RTOS,由RTOS自己管理。
RTOS主要用heap和pool管理memory,查看方法如下:
先将uart log输出模式由buffer mode切换至direct mode,防止打印内存信息太多,导致messages dropped,输入命令:
echo cli log_mode_sw > /proc/dualos/rtos
然后查看对应memoryinfo,输入命令:echo cli memstat ? > /proc/dualos/rtos
显示结果如图1-5所示:
图1-5 memstat图
根据需要打印相关信息,例如打印内存使用信息,输入命令:echo cli memstat --usage > /proc/dualos/rtos
显示结果如图1-6所示:
图1-6 memstat --usage图
以BGA12 DDR4 512M(SSC029A-S01A-S的EVB板)为例,RTOS总的划分16M = Total Heap size + 代码段 size(可通过未压缩的rtos bin档size确认) + misc分区size
2.5. RTOS中线程task介绍¶
RTOS有两种不同级别的task,system task、customer task,两个task 都是对应linux 线程的概念。system task由xTaskCreateStatic函数创建,customer task由CamOsThreadCreate创建。两者的区别如下表:
表1-3 rtos task说明表
特性 | system task | customer task |
---|---|---|
优先级 | 由RTOS defconfig选项CONFIG_TASK_PRIORITY_LEVELS 决定,公版默认配置为128,不建议修改该参数,优先级范围为0~127。 |
会受RTOS defconfig选项CONFIG_TASK_PRIORITY_LEVELS 和CONFIG_TASK_PRIORITY_LEVELS_FOR_PRIVILEGE 影响,不建议修改该参数,默认优先级范围为0~99,大于99的优先级只有system task可设置。 |
创建api | xTaskCreateStatic | CamOsThreadCreate |
适用范围 | 只建议在sys_init.c中const cus_InitTask_t cus_InitTask []结构体中配置的task使用,这里面不建议做客制化,Sigmastar sdk 出来已经做好,不建议用户添加,以免影响系统使用。 | Main函数被叫起来后,用户在rtk里面需要创建线程就用此task。 |
StackSize | Sdk原有创建的task,默认配置的stacksize已经够用,如果用户在原有的task中增加自己的代码,里面有很多局部变量需要用到stack,有可能原有的stacksize会爆掉,根据需要可以调整对应task的stacksize。其中RTOS的defconfig选项:CONFIG_TASK_CUST_STACK_SIZE 对应为"SYS_CUST" task的stacksize。 CONFIG_TASK_MENU_STACK_SIZE 对应为"MENU" task的stacksize。 |
需要根据自己创建线程设置size,例如CamOsThreadAttrb_t threadAttr = {.nPriority = 99,.szName = "mi_init",.nStackSize = 4096};CamOsTsemInit(&tMiInitTsem,0);CamOsThreadCreate(&rtos_vpe_func_tid, &threadAttr, rtos_vpe_func, NULL); |
3. 软件架构¶
3.1. SDK软件架构¶
App以及API层都是跑在Linux系统上,通过Sigmastar 封装过的ioctl调用到linux-rtos-adaptor层,然后透过arm的smc机制调用到RTOS端,所以视频、音频实现层是在RTOS端。具体架构图如下:
图1-7 linux-rtos-adaptor架构图
3.2. MI模块介绍¶
表1-4 MI模块介绍
简称 | 全称 | 职责 |
---|---|---|
SYS | System | 实现MI系统初始化、内存管理、各个模块之间数据流的管理 |
VDEC | Video Decoder | H264/H265 视频解码器 |
JPD | Jpeg Decoder | Jpeg解码器 |
SCL | Scaler | 缩放/裁剪/格式转换等功能 |
VDISP | Virtual Display | 软件拼图 |
DISP | Display Engine | DISP对VDEC/SCL 处理单元输出的图像做硬件拼图,并连同AO输出音频信号一起编码成HDMI/VGA/CVBS 输出信号的单元 |
VENC | Video Encoder | H264/H265/MotionJpeg编码器 |
AI | Audio Input Interface | audio input采集单元 |
AO | Audio Output Interface | 音频输出 |
GFX | Graphics Engine | Graphic Engine 提供对2D画图的基本硬件加速支援,降低CPU的负荷 |
FB | Frame Buffer | UI显示 |
HDMI | High Definition Multimedia Interface | HDMI/VGA标准输出 |
AEC | Acoustic Echo Cancellation | 回声消除,抑制远程回声的算法 |
AED | Acoustic Event Detection | 声学事件检测,用于在音讯码流中侦测特定的声音事件 |
APC | Audio Process Chain | 音频处理链路,包含降噪、均衡器和自动增益控制的算法组合 |
BF | beam forming | 波束形成或空间滤波,用于传感器数组的定向信号处理技术传输或接收 |
SRC | Sample Rate Conversion | 重采样,用于对音频流做采样频率转换 |
SSL | Sound Source Localization | 声源定位,用于定位声音来源的方向 |
SENSOR | Sensor | 获取摄像头接口信息、调整分辨率和帧率等功能 |
VIF | VIDEO Input Interface | MIPI/BT656/BT1120信号采集单元 |
ISP | Image Signal Processing | 实现 HDR,3D/2D 降噪,3A 算法,WDR 等相关功能 |
IQSERVER | Image Quality tuning Server | 图像质量调校服务,用来完成调校工具(IQ Tool)和开发板之间的数据通信, 包括 ISP 参数设置,获取图像,上传/下载相关文件等功能 |
RGN | Region | 区域管理模块,对SCL数据进行遮挡或叠加 |
SED | Smart Encode | 智能编码,主要提供智能编码通道的创建和销毁、开启和停止检测源图像、计算结果并关联到指定的编码通道等功能 |
IVE | Intelligent Video Engine | 提供图形智能识别算法中的基本算子支援 |
VDF | Video Detection Framework | 整合各个视频算法识别库的中间件架构,包括MD/OD/VG |
IPU | Intelligent Process Unit | 智能处理器,模块实现了AI 模型的推演功能加速 |
CIPHER | Cipher | 提供数据的加解密功能,包括 AES\RSA\SHA 加解密算法 |
3.3. MI基本概念¶
-
数据流:各个MI Module 可以看成是一个纯数据处理单元,数据流推送由MI SYS内部统一调度。输入数据流表示该数据单元的input数据,输出数据流表示该处理单元处理过的output数据。
-
控制流:APP 对各个MI Module 数据处理过程进行参数控制的过程,比如设置MI_VDEC解码参数,启动停止MI_VDEC 通道,设置MI_VDEC通道输出端口之分辨率及format等
-
Channel(通道)
对于需要处理或者输出stream的MI模块,一个channel代表该MI模块处理或者输出一路stream的分时复用的上下文(context)及相关控制流设定
对于可分时复用的模块如MI_VDEC, MI_DIVP, MI_DISP,可支援多个channel
-
Port(端口)
Port分为2种,input port和output port。input port为channel输入数据流的位置,而output port则是channel输出数据流的位置。
一个channel可以有多个input port及多个output port。
3.4. DualOS通信机制¶
3.4.1. Rpmsg概念¶
Rpmsg是一种开放式的processors之间、SoCs之间的通信协议。Linux Kernel内置了Rpmsg协议的实现,而FreeRTOS用的是RPMsg-Lite。
Rpmsg是一种通信协议,本身不提供Linux和FreeRTOS之间数据交换的具体实现。它需要依赖于Virtio来完成数据交换。
Virtio是为了提升虚拟化环境下的I/O性能而提出的一套半虚拟化解决方案。Virtio是一种前后端架构,包括前端驱动、后端设备、传输协议。在DualOS中,Linux Kernel作为前端驱动角色,FreeRTOS作为后端设备角色,Virtio通过共享内存在Linux和FreeRTOS之间进行数据传输,其中共享内存区域被称作vring。
3.4.2. Rpmsg软件架构¶
图1-8 Rpmsg架构图
如上图可以看到软件结构基本分为三层。FreeRTOS、Linux KERNEL和Linux USER层透过Rpmsg交互,下面简单介绍Linux通过Virtio向FreeRTOS发送数据(这部分对于用户来讲时无感的)的流程如下。
3.4.3. Rpmsg通信流程¶
图1-9 Rpmsg通信图
-
get buffer head index (Linux): 可以理解为下一次Linux写数据的地方
-
fill buffer: linux填充buffer(可以理解成Linux端申请的一块buffer)
-
update AvaliRing: Linux端写ring buffer地方
-
notify:Linux通知FreeRTOS
-
get buffer head index(FreeRTOS):FreeRTOS写数据的地方
-
get buffer and process data :数据传输,从buffer queue get buffer
-
update UsedRing:FreeRTOS更新数据,表示这个地方已经有数据了,Linux可以获取
-
buffer queue(共享内存)
3.4.4. Rpmsg通信实例¶
channel: Rpmsg设备之间的通信通道。VirIO ↔VHost
endpoint: Rpmsg endpoint在Rpmsg channel之上提供逻辑连接,是发送数据的实体。它允许用户在同一个通道上绑定多个rx回调(即通过创建多个endpoint来达到该目标)。每个Rpmsg endpoint都有一个唯一的src地址和自定义的回调函数。当应用程序使用本地地址创建endpoint时,目标地址等于endpoint本地地址的所有后续数据都将路由到该回调函数。
src: 数据包的发送端endpoint地址。
dst: 数据包的接收端endpoint地址。
图1-10 Rpmsg通信示例图
图1-11 Rpmsg endpoint
channel两边收到Rpmsg格式的数据会依据其dst地址,分发给对应的endpoint,即调用创建该endpoint时注册的回调函数(callback)。channel两边的地址空间是独立的,因此两边可以使用同一个地址,互不干扰。但是相同一边的地址必须互不相同,否则会出现不知道把数据分发给谁的问题。
3.4.5. Rpmsg注意事项¶
两边的数据分发是线性的,每一个数据包通过调用对应的callback函数进行分发,所以在设计应用时,要考虑endpoints间的相互影响,callback函数必须不能阻塞。标准的应用模式是callback里只把data放到一个队列(queue)后就返回,另一个实际的工作线程从队列里取数据进行后续处理。
4. 目录结构说明¶
4.1. SDK目录结构¶
图1-12 sdk目录结构图
Source code说明:
sdk:关于sensor driver和sample_code的源码,以及依赖Linux kernel的相关sdk源码。
boot:Uboot的相关源码与编译环境。
kernel:kernel的相关源码与编译环境。
project:编译整个工程的配置文件和环境。
rtos:rtos的相关源码与编译环境。
optee:optee的相关源码与编译环境。
4.2. 内容详解¶
4.2.1. rtos¶
cd rtos/proj . ├── add-config.mk//用户无需关注 ├── build//编译后会产生的目录 │ └── iford_ssc029a_s01a_512_ipc_lh_spinand //根据编译的配置生成的目录, | //会把所有编译需要用到的lib/c file复制过来,然后在此生成对应的链接文件,axf、map、elf、bin等 ├── clear-config.mk //用户无需关注 ├── config.mak //编译环境配置 ├── configs//配置文件及脚本文件,编译脚本会自动处理,用户无需关注 ├── gen_ext_cfg.sh//make配置相关脚本 ├── hdrs//头文件目录 │ └── iford_ssc029a_s01a_512_ipc_lh_spinand//配置文件对应的头文件 ├── Kconfig//menuconfig配置文件 ├── libs │ ├── algo//算法相关lib │ ├── otp//otp相关lib │ ├── product//不同的mak文件对应的系统、MI、Mhal的lib │ └── toolchain//标准C库 ├── mak │ ├── common //通用的lib/h file路径定义 │ ├── defconfigs //配置文件,用户需要关注,所有应用配置在这。 │ └── Kconfigs //menuconfig各级配置文件 │ ├── defconfigs//配置文件,用户需要关注,所有应用配置在这。 ├── Makefile ├── sc//源码目录 │ ├── application//应用目录 │ │ ├── bootloader │ │ ├── ...//其他应用 │ │ └── dualos_camera//主要关注串流应用demo │ ├── customer//客制化模块目录 │ └── driver//驱动目录 │ ├── sysdriver//系统模块driver,例如:I2C/PWM/UART/earlyinit_fw等. │ └── thirdparty//用于放置外接模块driver,例如wifi等 ├── scatter//链接使用的lds文件 ├── scripts//编译脚本目录,用户无需关注 ├── tng//配置脚本目录 │ └── configure.pl//主要是使用这个 └── tools//一些工具,用户无需关注
4.2.2. boot¶
目录结构和原版U-Boot一致,用户主要关注以下目录:
. ├── .... ├── common │ └── cmd │ └── mstar //sstar提供的uboot下相关cmd,其中包含estar.c涉及系统升级 ├── drivers │ └── mstar//sstar提供的外设驱动 ├── configs │ └──iford_ssc029a_s01a_lh_spinand_defconfig//项目配置文件,不同型号使用不同, | //具体查看alkaid defconfig里面CONFIG_UBOOT_CONFIG参数的定义。 └── ....
4.2.3. kernel¶
目录和原版kernel基本一致,用户主要关注以下目录:
. ├── .... ├── arch │ └── arm │ ├──boot │ │ └──dts │ │ └──iford-ssc029a-s01a-dualos.dts//设备树文件 │ └── configs │ └── iford_ssc029a_s01a_lh_spinand_defconfig/项目配置文件,不同型号使用不同, | //具体查看alkaid defconfig里面CONFIG_KERNEL_CONFIG参数的定义。 ├── drivers │ └── sstar//sstar提供的外设驱动 └── ....
4.2.4. sdk¶
sdk ├── verify │ └── mi_demo //sstar mi完整ut demo,建议只参考RTOS_preload demo │ └── sample_code │ ├──source//各种demo例子,用户也可以在这新增自己demo │ │ └──Makefile//要在这里DualOS on判断下加上demo名字才会编译到 │ └──out//编译完毕后可以在这里找到bin档案 |── driver | └──SensorDriver//sensor drv源码,RTOS也是使用这里的drv源码 | └── linux //sdk与kernel解耦后,sdk编译所需源码,dualos不支持sdk与kernel解耦,无需关心该目录。
4.2.5. project¶
. ├── board//板子相关 │ ├── iford │ │ ├── boot │ │ │ └── nor/nand │ │ │ ├── ipl-dualos//用于存放DualOS需要的IPL/IPL_CUST。用户想切换到其他版本可以在这里找。 │ │ │ │ ├── IPL.bin │ │ │ │ └── IPL_CUST.bin │ │ │ └── partition//用于存放flash list文件 │ │ │ ├── flash_list.nri │ │ │ └── flash.nri │ │ ├── dla_file//如果chip带ipu,会有对应的ipu fw bin和model bin │ │ ├── iqfile//IQ文件 │ │ ├── json //mi获取的外部参数json文件,RTOS是否要preload video或audio,也在此配置。 │ |──rtos//RTOS中会去读取这些文件,该目录下的文件一般会copy到板子端/misc目录下。 │ │ ├── 200X131.argb1555//argb文件 │ │ ├── hanzi_16x16//字体文件 │ │ ├── rtos.sz//编译后的RTOS的bin档。放在此处编译project后,会自动copy到out/image目录下 │ │ └── PreloadSetting.txt//RTOS demo使用的串流信息文件 │ └── uboot//公版默认uboot打包文件 ├── configs │ └── verify │ │ └── defconfigs │ │ └──ipc-rtos_iford.spinand.glibc-11.1.0-ramdisk.ssc029a.512.bga12_ddr4_defconfig//project的配置文件,例如KERNEL/MMA/SENSORIQ配置等等;不同型号使用不同配置文件,此处以SSM000C-S01A-S型号为例。 ├── image//所有制作image的配置文件/工具/脚本。 │ ├── build//已经编译好的部分image制作工具,例:lfs/fwfs的制作工具 │ ├── busybox//已经裁剪编译好的busybox │ ├── configs//分区相关的配置文件,请重点关注 │ │ └── general │ │ ├── customer.mk//决定打包哪些文件到customer分区(UBI)下,并且输出执行命令到脚本 │ │ ├── misc.mk//决定打包哪些文件到misc分区(FWFS)下 │ │ ├── miservice.mk//决定打包哪些文件到miservice分区(UBI)下,一般放置MI动态库和kernel的KO │ │ ├── ramdisk.mk//决定打包哪些文件到ramdisk,决定启动脚本中执行哪些应用。ramdisk也是真正第一个挂起的rootfs │ │ ├── rootfs_fastboot.mk//rootfs fastboot版本 │ │ ├── rootfs.mk//同上都是管理roofs的打包信息,这个是第二个挂载的rootfs,实际是挂到ramdisk上。细节可看ramdisk.mk。 │ │ ├── nor-ramdisk.rtos.partition.config//nor flash的分区脚本 │ │ └── spinand-ramdisk.rtos.partition.config//nand flash的分区脚本,所有分区信息都在这里配置。包括上面提到的IPL选择也在这里完成。 │ ├── image.mk//分区的制作脚本,根据分区表信息,这里会调用对应工具去制作相应的bin档,在images/目录下。 │ │ //并且生成分区表images/boot/PARTINFO.pni。 │ ├── ota.mk//如果使用sstar提供的ota工具,这里是用于制作ota bin的对应脚本。 │ ├── script.mk//用于制作分区烧录的脚本,生成在images/scripts。一般uboot进行烧录的时候,会调用该脚本,对flash进行擦除/写入。 │ ├── etc │ │ └── init.d//系统初始化配置 │ ├── firmwarefs-fuse//fwfs linux应用 │ ├── fuse//lfs or fwfs 执行需要依赖的库 │ ├── littlefs-fuse//lfs linux应用 │ ├── makefiletools//制作rootfs的工具 │ ├── rootfs//rootfs包 │ └── systemtap//内核调试工具 ├── kbuild │ └── customize │ └── 5.10 │ └── iford │ └── ipc-rtos──nor/nand //主要关注下面的脚本,决定会从kernel copy哪些ko到project下和ramdisk ├── release │ ├── chip │ │ └── iford//SDK对应的库文件 │ │ └── ipc-rtos//DualOS的主要在这里面 │ └── include//SDK头文件 ├── scripts//project使用的脚本,用户无需关注 └── tools//调试工具,iqtool等
5. 分区配置¶
DualOS公版的分区配置举例如表1-5所示
表1-5 公版分区配置
IDX: | StartBlk: | BlkCnt: | Trunk/BkTrunk: | Group: | Active: | Name: | BUS:CS: |
---|---|---|---|---|---|---|---|
0: | 0,(0000000000) | 10,(0X00140000) | 0/1 | 0 | 1 | CIS | 0:00 |
1: | 10,(0X00140000) | 3,(0X00060000) | 0/1 | 1 | 1 | IPL | 0:00 |
2: | 13,(0X001A0000) | 3,(0X00060000) | 0/1 | 1 | 1 | IPL_CUST | 0:00 |
3: | 16,(0X00200000) | 3,(0X00060000) | 0/1 | 1 | 1 | OPTEE | 0:00 |
4: | 19,(0X00260000) | 1,(0X00020000) | 0/1 | 1 | 1 | TF_A | 0:00 |
5: | 20,(0X00280000) | 1,(0X00020000) | 0/1 | 1 | 1 | VMM | 0:00 |
6: | 21,(0X002A0000) | 6,(0X000C0000) | 0/1 | 1 | 1 | UBOOT | 0:00 |
7: | 27,(0X00360000) | 3,(0X00060000) | 1/0 | 2 | 0 | IPL | 0:00 |
8: | 30,(0X003C0000) | 3,(0X00060000) | 1/0 | 2 | 0 | IPL_CUST | 0:00 |
9: | 33,(0X00420000) | 3,(0X00060000) | 1/0 | 2 | 0 | OPTEE | 0:00 |
10: | 36,(0X00480000) | 1,(0X00020000) | 1/0 | 2 | 0 | TF_A | 0:00 |
11: | 37,(0X004A0000) | 1,(0X00020000) | 1/0 | 2 | 0 | VMM | 0:00 |
12: | 38,(0X004C0000) | 6,(0X000C0000) | 1/0 | 2 | 0 | UBOOT | 0:00 |
13: | 44,(0X00580000) | 2,(0X00040000) | 0/0 | 0 | 1 | ENV | 0:00 |
14: | 46,(0X005C0000) | 40,(0X00500000) | 0/0 | 0 | 1 | KERNEL | 0:00 |
15: | 86,(0X00AC0000) | 40,(0X00500000) | 0/0 | 0 | 1 | RECOVERY | 0:00 |
16: | 126,(0X00FC0000) | 9,(0X00120000) | 0/0 | 0 | 1 | MISC | 0:00 |
17: | 135,(0X010E0000) | 18,(0X00240000) | 0/0 | 0 | 1 | MISCL | 0:00 |
18: | 153,(0X01320000) | 40,(0X00500000) | 0/0 | 0 | 1 | RTOS | 0:00 |
19: | 193,(0X01820000) | 40,(0X00500000) | 0/0 | 0 | 1 | RTOS_BACKUP | 0:00 |
20: | 233,(0X01D20000) | 8,(0X00100000) | 0/0 | 0 | 1 | RAMDISK | 0:00 |
21: | 241,(0X01E20000) | 8,(0X00100000) | 0/0 | 0 | 1 | RAMDISK_BACKUP | 0:00 |
22: | 249,(0X01F20000) | 1,(0X00020000) | 0/0 | 0 | 1 | EIB | 0:00 |
23: | 250,(0X01F40000) | 1,(0X00020000) | 0/0 | 0 | 1 | EIB_BACKUP | 0:00 |
24: | 251,(0X01F60000) | 773,(0X060A0000) | 0/0 | 0 | 1 | ubia | 0:00 |
DualOS需要特别关注的是:
MISC:RTOS启动时会挂载的fwfs文件系统,RTOS所需使用的文件放在这里。
MISCL:也是挂载的fwfs文件系统,RTOS目前未使用到的文件,暂做保留放在这里。
RTOS:RTOS bin文件。
RAMDISK:kernel ramdisk。
EIB:Earlyinit bin用于在IPL阶段做earlyinit。
如果使用hypervisor版本,还需要特别关注VMM、OPTEE、TF-A。
各个分区存在的bin文件介绍、分配配置修改等相关内容参考系统分区。
6. fwfs使用流程¶
CamFs会定义如下几种文件系统,RTOS上主要会使用到fwfs和proxfs。
typedef enum { CAM_FS_FMT_LWFS = 0, CAM_FS_LITTLEFS, CAM_FS_FMT_PROXFS, //proxfs CAM_FS_FMT_FIRMWAREFS, //fwfs } CamFsFmt_e;
RTOS启动后会先挂载fwfs文件系统,创建misc分区,支持RTOS端和Linux端读写,Preload阶段需要使用到的文件都会放在这个分区下,fwfs是在IPL阶段load到memory。在RTOS上访问时分两种情况:
1、在Linux未启动时,是直接从内存中读取数据。
2、在Linux启动后,是通过proxfs,走Rpmsg在Linux从flash中读取数据。
使用流程如图1-13所示。
图1-13 DualOS fwfs使用流程
使用限制:
在RTOS上访问时,读取数据的Buffer需要64byte对齐。
7. code size裁剪说明¶
目前使用如下defconfig是最基本的pipeline,并且关掉debug log,用户最终产品形态可根据此版本进行拓展:
ipc-rtos_iford.spinand.glibc-11.1.0-ramdisk.ssc029c.256.qfn128_ddr3_no_dbg_defconfig
8. Preload Demo¶
8.1. RTOS Demo¶
代码路径:
rtos/proj/sc/application/pipeline_demo/dualos_camera/src/rtos_preload.c
在启动流程中,启动到RTOS后就会跑Preload Demo,创建Pipeline,对应Preload Demo的入口函数为RtosAppMainEntry
,主要创建MI_PreloadMiPipe Task、实现MI初始化、创建Pipeline、创建MI_PreloadFile TASK以及实现从misc分区读取档案。
图1-14 公版默认串接的Pipeline
公版只实现了一个基本的Pipeline,用于测量TTFF/TTCL,用户可根据实际应用场景拓展。子码流如果没有快起需求,建议在linux起来之后再去创建。快启过程中RTOS Preload Demo是否需要创建Video、Audio是由misc分区中的modparam.json文件配置的,Venc、Ai缓存的Buffer帧数、Video的参数等参数由misc分区中的PreloadSetting.txt文件配置的,各参数含义参考配置文件介绍。
注意:
-
PreloadSetting.txt 的预录参数u32PreloadVideoFrame 代表缓存到MMA的帧数。这个帧数对应的时长应该大于Linux启动的时间(例如,预录fps30, linux启动要2秒,那缓存要准备60帧也就是2秒的数据),不然可能导致少帧现象。取流的时候要先把预录帧数取完才会去取实时流。保留码流的原则是丢弃新数据。
-
demo中的流程如果有修改,函数_Exit_PreloadForce里面的退出流程也同步修改。
8.2. Linux拉流Demo¶
代码路径
sdk/verify/mi_demo/source/rtos_preload/st_main_rtos_preload.cpp
开机启动后,可进入/customer/mi_demo/rtos_preload
目录直接运行prog_rtos_preload
取流查看效果。
如果Demo做了修改,重新编译后可以在下面目录找到可执行档案:
sdk/verify/mi_demo/out/demo/app/prog_rtos_preload
RTOS默认串接音视频流的Pipeline后,会将抓到的音视频流保存在共享内存MMA中,等Linux App启动之后,会直接从MMA获取音视频流,这样就能获取到启动阶段的音视频流。
所以当linux应用启动的时候,发现如果RTOS已经串流完毕,则不需要重新初始化Sensor、AI、AO等设备,应该直接GetFrame(例:MI_VENC_GetStream)取流即可。或者在此基础上直接继续创建子码流等。
注意: 如果用户需要直接跑其他Linux端demo(例如:Mixer,sample_code),可以先运行一下prog_rtos_preload,输入19退出应用(目的是使rtos的串流退出,避免冲突)然后再执行其他应用。
8.3. 配置文件介绍¶
misc分区下会存放Preload阶段需要使用到的文件,其中modparam.json和PreloadSetting.txt文件是Preload demo会需要使用到的。
modparam.json对应代码的路径为:project/board/chip/json/ipc-rtos/
,默认会打包在misc分区中,用于MI Pipe和Preload Demo共同参考的一些参数配置,是否需要Preload创建AI、AO、Video,Venc PreloadChn的buffersize等。
iford平台支持将misc分区做sz压缩,从而节省load misc分区的时间加快TTCL,压缩后misc分区并不支持直接mount在linux,所以在linux会mount一个misc_lnx分区,在linux端更改misc_lnx分区内容后,执行回写脚本,将内容回写到RTOS的misc分区。
具体步骤如下:
vi /misc/modparam.json #Modify file content /customer/writeback.sh #Execute the write back script reboot
表1-6 modparam.json参数说明
json栏位 | 参数 | 说明 |
---|---|---|
s32PreloadChnFlag | s32PreloadChnFlag | 是否需要Preload创建Video pipeline,Venc多少个chn需要额外创建Ringpool Buffer,这是一个二级制bitmask值,bit0置1代表chn0创建,bit1置1代表chn1创建。 |
u32Chn0PreloadBufSize | Venc Chn0自定义Preload的Buffer size,如果为0,MI VENC内部自行计算Buffersize | |
u32Chn1PreloadBufSize | Venc Chn1自定义Preload的Buffer size,如果为0,MI VENC内部自行计算Buffersize | |
u32Chn2PreloadBufSize | Venc Chn2自定义Preload的Buffer size,如果为0,MI VENC内部自行计算Buffersize | |
E_MI_MODULE_ID_AI | s32PreloadAI | 是否需要Preload创建AI |
E_MI_MODULE_ID_AO | s32PreloadAO | 是否需要Preload创建AO |
PreloadSetting.txt对应代码的路径为:project/board/rtos/
,默认会打包在misc分区中,用于根据配置文件的值取串接不同的Pipeline来满足不同的需求。
表1-7 PreloadSetting.txt参数说明
参数 | 说明 |
---|---|
r_SensorFrameRate=30 | Sensor Fps,与earlyinit fw设定一致 |
r_Lux=2000 | 预留,暂时没有使用 环境亮度 |
r_DayNightMode=0 | api bin设定mode,取值范围: 0: day mode. 1: night mode. 2: color night mode. |
r_AntiFlicker=1 | SensorEarlyinit Flicker参数 |
r_shutter=24978 | SensorEarlyinit Shutter参数,与earlyinit fw设定一致 |
r_SensorGain=1280 | SensorEarlyinit GainX1024参数,与earlyinit fw设定一致 |
r_DigitalGain=1024 | SensorEarlyinit DGain参数 |
r_AWBRGain=1405 | SensorEarlyinit AWBRGain参数 |
r_AWBGGain=1024 | SensorEarlyinit AWBGGain参数 |
r_AWBBGain=2317 | SensorEarlyinit AWBBGain参数 |
r_Orientation=0 | 取值范围: 0:E_MI_SYS_ROTATE_NONE 1:E_MI_SYS_ROTATE_90:Mirror=0,Flip=1 2:E_MI_SYS_ROTATE_180:Mirror=1,Flip=1 3:E_MI_SYS_ROTATE_270:Mirror=1,Flip=0 |
r_ExposureLevel=0 | 目前没有使用 |
r_HDRMode=0 | 目前没有使用 |
r_SensorNum=1 | 用双sensor功能的时候这个地方设置为2,u8VideoNum设置为2或3。Linux那边的demo会从txt文件里面拿这个参数使用。 取值范围: 1:一个sensor 2:双sensor |
r_PreloadVideo=1 | 目前没有使用 |
r_PreloadAudio=1 | 目前没有使用 |
r_stSystemTime.nSec=1546300800 r_stSystemTime.nNanoSec=0 | 系统时间 |
r_RegionsCun=0 | Osd开关 |
r_IspClkIndex=0 | 模块clock设定 ,目前没有使用 |
r_SclClkIndex=2 | 模块clock设定 ,目前没有使用 |
r_DivpClk=384000000 | 模块clock设定 ,目前没有使用 |
r_VencClk=384000000 | 模块clock设定 ,目前没有使用 |
r_Venc2ndpuClk=320000000 | 模块clock设定 ,目前没有使用 |
r_enableIPU=0 | IPU是否要串流整个系统,IPU整个功能的开关。 取值范围:0:关;1:开 |
r_PreloadYUVFrameRate=5 | 目前没有使用 |
r_PreloadYUVFrameDepth=25 | 目前没有使用 |
r_PreloadVideoFrame=120 | 每路venc缓存的最大张数,用于RTOS快起之后把内容存起来给linux端使用 |
r_PreloadAudioFrame=150 | audio缓存的最大张数,用于RTOS快起之后把内容存起来给linux端使用 |
r_IPUClk=1 | 模块clock设定 ,目前没有使用 |
r_JpeClk=480000000 | 模块clock设定 ,目前没有使用 |
r_AIDevId=0 | 音频输入设备编号,取值范围:0:AMIC;1:DMIC;2:I2S |
r_AISamplerate=16000 | 取值范围: 8000, /* 8kHz sampling rate / 11025, / 11.025kHz sampling rate / 12000, / 12kHz sampling rate / 16000, / 16kHz sampling rate /默认 22050, / 22.05kHz sampling rate / 24000, / 24kHz sampling rate / 32000, / 32kHz sampling rate / 44100, / 44.1kHz sampling rate / 48000, / 48kHz sampling rate / 96000, / 96kHz sampling rate */ |
r_AIVol=14 | 目前没有使用 |
r_VideoNum=1 | RTOS串几路流,最多设置为3,通路如下。 Linux那边的demo会从txt文件里面拿这个参数使用。 |
r_Video0Format=0 | venc0 format: 0:H264, 1:H265, 2:JPEGE |
r_Video0EncFrameRate=30 | venc0 FrameRate |
r_Video0Width=1920 | Video0 Width |
r_Video0Height=1080 | Video0 Height |
r_Video0Bitrate=2097152 | Video0 Bitrate |
r_Video0Profile=1 | Video0 Profile |
r_Video0Minqp=12 | Video0 Minqp,取值范围:[12, u32MaxQp) |
r_Video0Maxqp=48 | Video0 Maxqp,取值范围:(u32MinQp, 48] |
r_Video0Gop=60 | Video0 Gop |
r_Video0H264RcMode=0 | Video0 H264RcMode: CBR = 0, VBR = 1, FIXQP = 2, AVBR = 3 |
r_Video0H265RcMode=2 | Video0 H265RcMode: CBR =0, VBR = 1, FIXQP =2, AVBR = 3 |
r_Video0Metadata=0 | 预留,暂时没有使用 |
r_Video0VPECropx=0 | Video0 SCL Cropx |
r_Video0VPECropy=0 | Video0 SCL Cropy |
r_Video0VPECropw=0 | Video0 SCL Cropw |
r_Video0VPECroph=0 | Video0 SCL Croph |
r_Video1Format=0 | venc1 format: 0:H264, 1:H265, 2:JPEGE |
r_Video1EncFrameRate=30 | venc1 FrameRate |
r_Video1Width=640 | Video1 Width |
r_Video1Height=360 | Video1 Height |
r_Video1Bitrate=2097152 | Video1 Bitrate |
r_Video1Profile=1 | Video1 Profile |
r_Video1Minqp=12 | Video1 Minqp,取值范围:[12, u32MaxQp) |
r_Video1Maxqp=48 | Video1 Maxqp,取值范围:(u32MinQp, 48] |
r_Video1Gop=60 | Video1 Gop |
r_Video1H264RcMode=0 | Video1 H264RcMode: CBR = 0, VBR = 1, FIXQP = 2, AVBR = 3 |
r_Video1H265RcMode=2 | Video1 H265RcMode: CBR = 0, VBR = 1, FIXQP =2, AVBR = 3 |
r_Video1VPECropx=0 | Video1 SCL Cropx |
r_Video1VPECropy=0 | Video1 SCL Cropy |
r_Video1VPECropw=0 | Video1 SCL Cropw |
r_Video1VPECroph=0 | Video1 SCL Croph |
r_Video2Format=0 | venc2 format: 0:H264, 1:H265, 2:JPEGE |
r_Video2EncFrameRate=30 | venc2 FrameRate |
r_Video2Width=384 | Video2 Width |
r_Video2Height=216 | Video2 Height |
r_Video2Bitrate=2097152 | Video2 Bitrate |
r_Video2Profile=1 | Video2 Profile |
r_Video2Minqp=12 | Video2 Minqp,取值范围:[12, u32MaxQp) |
r_Video2Maxqp=48 | Video2 Maxqp,取值范围:(u32MinQp, 48] |
r_Video2Gop=60 | Video2 Gop |
r_Video2H264RcMode=0 | Video2 H264RcMode: CBR = 0, VBR = 1, FIXQP = 2, AVBR = 3 |
r_Video2H265RcMode=2 | Video2 H265RcMode: CBR = 0, VBR = 1, FIXQP = 2, AVBR = 3 |
r_Video2VPECropx=0 | Video2 SCL Cropx |
r_Video2VPECropy=0 | Video2 SCL Cropy |
r_Video2VPECropw=0 | Video2 SCL Cropw |
r_Video2VPECroph=0 | Video2 SCL Croph |
9. mixer多场景(待定)¶
包含5个场景:1、基本Pipeline;2、 HDR 2F/3F;3、LDC畸变矫正+HDR;4、Ipu人型检测+MD/OD动态监测;5、Ive背景虚化。
10. DualOS调试手段¶
10.1. RTOS Log 开启方法¶
RTOS log默认是打印在buffer中,log level为3,如要将log打印在uart或者是调高log level,可以更改env参数bootargs_rtos的loglevel参数和logmode参数。
#修改前 bootargs_rtos=rtos_size=0x01000000 limit_dram_size=0x20000000 mma_base=0x28000000 mma_size=0x17000000 rtosrd_addr=0x3FA00000 rtosrd_size=0x120000 rtosts_addr=0x3F900000 rtosts_size=0x800 loglevel=3 #修改后 bootargs_rtos=rtos_size=0x01000000 limit_dram_size=0x20000000 mma_base=0x28000000 mma_size=0x17000000 rtosrd_addr=0x3FA00000 rtosrd_size=0x120000 rtosts_addr=0x3F900000 rtosts_size=0x800 loglevel=7 logmode=direct
也可以在Llinux起来后,使用Cli cmd切换:
echo cli log_mode_sw > /proc/dualos/rtos echo cli loglevel 7 > /proc/dualos/rtos
10.2. RTOS 挂掉信息分析¶
RTOS系统在出现异常时,通常会产生exception log辅助debug,一般来说会给出建议检查的address,通过code address反查,检查代码是否异常。
在RTOS编译时会同时生成一个.elf文件,以公版ddr3的defconfig为例,编译生成elf文件为:rtos/proj/build/iford_ssc029a_s01a_512_ipc_lh_spinand/out/iford_ssc029a_s01a_512_ipc_lh_spinand.elf
,每一个版本记得保存该.elf文件,如果遇到RTOS中挂掉的问题,可以通过该文件来定位。
例如挂掉的信息如下:
------------------------------ ARCH OVERVIEW ------------------------------- Exception type: DATA ABORT (246), Param: 0x5f14f8c2 Processor access illegal data address 0x00000000 Please check code at address: 0x5f14f8c2 (unknown symbol) Exception in Task [procctx] (mode: 0x1f)
在编译的服务器上使用如下命令进行反查:
arm-eabi-addr2line -e iford_ssc029a_s01a_512_ipc_lh_spinand.elf 0x5f14f8c2
10.3. MI Proc信息查看¶
用法与Purelinux相差不大,参考各个MI模块的API说明文档。