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)。

  1. sstar 的 virtual machine monitor (简称 SSVMM) 基于 ARM Virtualization Extensions 架构实现,可高效能调度 guest OS 达到 OS 虚拟化效果。

  2. 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 架构。

  3. 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 申请不到内存,可参考以下方法进行调整

  1. CONFIG_MEMORY_POOL_SUPPORT 没有开启,表示整体 heap 耗尽了或太过破碎,以至于无法再配出连续的空间,这种情况请考虑加大RTOS的Memory Size。
  2. 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通信图

  1. get buffer head index (Linux): 可以理解为下一次Linux写数据的地方

  2. fill buffer: linux填充buffer(可以理解成Linux端申请的一块buffer)

  3. update AvaliRing: Linux端写ring buffer地方

  4. notify:Linux通知FreeRTOS

  5. get buffer head index(FreeRTOS):FreeRTOS写数据的地方

  6. get buffer and process data :数据传输,从buffer queue get buffer

  7. update UsedRing:FreeRTOS更新数据,表示这个地方已经有数据了,Linux可以获取

  8. 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说明文档。