Harmony鸿蒙南向驱动开发-MIPI CSI接口使用

news2024/11/29 8:43:55

功能简介

CSI(Camera Serial Interface)是由MIPI联盟下Camera工作组指定的接口标准。CSI-2是MIPI CSI第二版,主要由应用层、协议层、物理层组成,最大支持4通道数据传输、单线传输速度高达1Gb/s。

物理层支持HS(High Speed)和LP(Low Speed)两种工作模式。HS模式下采用低压差分信号,功耗较大,但数据传输速率可以很高(数据速率为80M~1Gbps);LP模式下采用单端信号,数据速率很低(<10Mbps),但是相应的功耗也很低。两种模式的结合保证了MIPI总线在需要传输大量数据(如图像)时可以高速传输,而在不需要传输大数据量时又能够减少功耗。

图1显示了简化的CSI接口。D-PHY采用1对源同步的差分时钟和1~4对差分数据线来进行数据传输。数据传输采用DDR方式,即在时钟的上下边沿都有数据传输。

图 1 CSI发送、接收接口

CSI发送、接收接口

MIPI CSI标准分为应用层、协议层与物理层,协议层又细分为像素字节转换层、低级协议层、Lane管理层。

  • 物理层(PHY Layer)

    PHY层指定了传输媒介,在电气层面从串行bit流中捕捉“0”与“1”,同时生成SoT与EoT等信号。

  • 协议层(Protocol Layer)

    协议层由三个子层组成,每个子层有不同的职责。CSI-2协议能够在host侧处理器上用一个单独的接口处理多条数据流。协议层规定了多条数据流该如何标记和交织起来,以便每条数据流能够被正确地恢复出来。

    • 像素字节转换层(Pixel/Byte Packing/Unpacking Layer)

      CSI-2规范支持多种不同像素格式的图像应用。在发送方中,本层在发送数据到Low Level Protocol层之前,将来自应用层的像素封包为字节数据。在接收方中,本层在发送数据到应用层之前,将来自Low Level Protocol层的字节数据解包为像素。8位的像素数据在本层中传输时保持不变。

    • 低级协议层(Low Level Protocol) LLP主要包含了在SoT和EoT事件之间的bit和byte级别的同步方法,以及和下一层传递数据的方法。LLP最小数据粒度是1个字节。LLP也包含了一个字节内的bit值解析,即Endian(大小端里的Endian的意思)的处理。

    • Lane管理层(Lane Management)

      CSI-2的Lane是可扩展的。具体的数据Lane的数量规范并没有给出限制,具体根据应用的带宽需求而定。发送侧分发(distributor功能)来自出口方向数据流的字节到1条或多条Lane上。接收侧则从一条或多条Lane中收集字节并合并(merge功能)到一个数据流上,复原出原始流的字节顺序。对于C-PHY物理层来说,本层专门分发字节对(16 bits)到数据Lane或从数据Lane中收集字节对。基于每Lane的扰码功能是可选特性。

      协议层的数据组织形式是包(packet)。接口的发送侧会增加包头(header)和错误校验(error-checking)信息到即将被LLP发送的数据上。接收侧在LLP将包头剥掉,包头会被接收器中对应的逻辑所解析。错误校验信息可以用来做入口数据的完整性检查。

  • 应用层(Application Layer)

    本层描述了更高层级的应用对于数据中的数据的处理,规范并不涵盖应用层。CSI-2规范只给出了像素值和字节的映射关系。

运作机制

MIPI CSI模块各分层的作用为:接口层提供打开设备、写入数据和关闭设备的接口。核心层主要提供绑定设备、初始化设备以及释放设备的能力。适配层实现其它具体的功能。

说明:
核心层可以调用接口层的函数,核心层通过钩子函数调用适配层函数,从而适配层可以间接的调用接口层函数,但是不可逆转接口层调用适配层函数。

图 2 CSI无服务模式结构图

CSI无服务模式结构图

约束与限制

由于使用无服务模式,MIPI_CSI接口暂不支持用户态使用。

使用指导

场景介绍

MIPI CSI主要用于连接摄像头组件。

接口说明

MIPI CSI模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/framework/include/platform/mipi_csi_if.h。

表 1 ComboDevAttr结构体介绍

名称描述
devno设备号
inputMode输入模式:MIPI/LVDS/SUBSLVDS/HISPI/DC
dataRateMipi Rx,SLVS输入速率
imgRectMIPI Rx设备裁剪区域(与原始传感器输入图像大小相对应)
MIPIAttrMipi设备属性
lvdsAttrLVDS/SubLVDS/HiSPi设备属性

表 2 ExtDataType结构体介绍

名称描述
devno设备号
numSensor号
extDataBitWidth图片的位深
extDataType定义YUV和原始数据格式以及位深度

表 3 MIPI CSI API接口功能介绍

接口名接口描述
DevHandle MipiCsiOpen(uint8_t id)获取MIPI_CSI控制器操作句柄
void MipiCsiClose(DevHandle handle)释放MIPI_CSI控制器操作句柄
int32_t MipiCsiSetComboDevAttr(DevHandle handle, ComboDevAttr *pAttr)设置MIPI,CMOS或者LVDS相机的参数给控制器,参数包括工作模式,图像区域,图像深度,数据速率和物理通道等
int32_t MipiCsiSetExtDataType(DevHandle handle, ExtDataType *dataType)设置YUV和RAW数据格式和位深(可选)
int32_t MipiCsiSetHsMode(DevHandle handle, LaneDivideMode laneDivideMode)设置MIPI RX的Lane分布。根据硬件连接的形式选择具体的mode
int32_t MipiCsiSetPhyCmvmode(DevHandle handle, uint8_t devno, PhyCmvMode cmvMode)设置共模电压模式
int32_t MipiCsiResetSensor(DevHandle handle, uint8_t snsResetSource)复位Sensor
int32_t MipiCsiUnresetSensor(DevHandle handle, uint8_t snsResetSource)撤销复位Sensor
int32_t MipiCsiResetRx(DevHandle handle, uint8_t comboDev)复位MIPI RX。不同的s32WorkingViNum有不同的enSnsType
int32_t MipiCsiUnresetRx(DevHandle handle, uint8_t comboDev)撤销复位MIPI RX
int32_t MipiCsiEnableClock(DevHandle handle, uint8_t comboDev)使能MIPI的时钟。根据上层函数电泳传递的enSnsType参数决定是用MIPI还是LVDS
int32_t MipiCsiDisableClock(DevHandle handle, uint8_t comboDev)关闭MIPI设备的时钟
int32_t MipiCsiEnableSensorClock(DevHandle handle, uint8_t snsClkSource)使能MIPI上的Sensor时钟
int32_t MipiCsiDisableSensorClock(DevHandle handle, uint8_t snsClkSource)关闭Sensor的时钟

开发步骤

使用流程

使用MIPI CSI的一般流程如图3所示。

图 3 MIPI CSI使用流程图

MIPI CSI使用流程图

获取MIPI CSI控制器操作句柄

在进行MIPI CSI进行通信前,首先要调用MipiCsiOpen获取控制器操作句柄,该函数会返回指定通道ID的控制器操作句柄。

DevHandle MipiCsiOpen(uint8_t id);

表 4 MipiCsiOpen的参数和返回值描述

参数参数描述
iduint8_t类型,MIPI CSI通道ID
返回值返回值描述
NULL获取失败
设备句柄获取到指令通道的控制器操作句柄,类型为DevHandle

假设系统中的MIPI CSI通道为0,获取该通道控制器操作句柄的示例如下:

DevHandle MipiCsiHandle = NULL;  // 设备句柄
id = 0;                          // MIPI CSI通道ID

// 获取控制器操作句柄 
MipiCsiHandle = MipiCsiOpen(id);
if (MipiCsiHandle == NULL) {
    HDF_LOGE("MipiCsiOpen: mipi csi open fail.\n");
    return NULL;
}
进行MIPI CSI相应配置
  • 写入MIPI CSI配置

    int32_t MipiCsiSetComboDevAttr(DevHandle handle, ComboDevAttr *pAttr);

    表 5 MipiCsiSetComboDevAttr的参数和返回值描述

    参数参数描述
    handleDevHandle类型,控制器操作句柄
    pAttr结构体指针,MIPI CSI相应配置
    返回值返回值描述
    HDF_SUCCESS设置成功
    负数设置失败
    int32_t ret;
    struct ComboDevAttr attr;
    
    // 当前配置如下 
    (void)memset_s(&attr, sizeof(ComboDevAttr), 0, sizeof(ComboDevAttr));
    attr.devno = 0;                    // 设备0 
    attr.inputMode = INPUT_MODE_MIPI;  // 输入模式为MIPI 
    attr.dataRate = MIPI_DATA_RATE_X1; // 每时钟输出1像素 
    attr.imgRect.x = 0;                // 0: 图像传感器左上位置 
    attr.imgRect.y = 0;                // 0: 图像传感器右上位置 
    attr.imgRect.width = 2592;         // 2592: 图像传感器宽度大小 
    attr.imgRect.height = 1944;        // 1944: 图像传感器高度尺寸 
    // 写入配置数据 
    ret = MipiCsiSetComboDevAttr(MipiCsiHandle, &attr);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("MipiCsiSetComboDevAttr: mipi csi set combo dev attr fail, ret=%d\n", ret);
        return ret;
    }
  • 设置YUV和RAW数据格式和位深

    int32_t MipiCsiSetExtDataType(DevHandle handle, ExtDataType* dataType);

    表 6 MipiCsiSetExtDataType的参数和返回值描述

    参数参数描述
    handleDevHandle类型,控制器操作句柄
    dataType结构体指针,定义YUV和原始数据格式以及位深度
    返回值返回值描述
    HDF_SUCCESS设置成功
    负数设置失败
    int32_t ret;
    struct ExtDataType dataType;
    
    // 配置YUV和RAW数据格式和位深参数 
    dataType.devno = 0;               // 设备0 
    dataType.num = 0;                 // Sensor 0 
    dataType.extDataBitWidth[0] = 12; // 位深数组元素0 
    dataType.extDataBitWidth[1] = 12; // 位深数组元素1 
    dataType.extDataBitWidth[2] = 12; // 位深数组元素2 
    
    dataType.extDataType[0] = 0x39;   // 定义YUV和原始数据格式以及位深度元素0 
    dataType.extDataType[1] = 0x39;   // 定义YUV和原始数据格式以及位深度元素1 
    dataType.extDataType[2] = 0x39;   // 定义YUV和原始数据格式以及位深度元素2 
    // 设置YUV和RAW数据格式和位深 
    ret = MipiCsiSetExtDataType(MipiCsiHandle, &dataType);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("MipiCsiSetExtDataType: mipi csi set ext data type fail, ret=%d\n", ret);
        return ret;
    }
  • 设置MIPI RX的Lane分布

    int32_t MipiCsiSetHsMode(DevHandle handle, LaneDivideMode laneDivideMode);

    表 7 MipiCsiSetHsMode的参数和返回值描述

    参数参数描述
    handleDevHandle类型,控制器操作句柄
    laneDivideMode结构体类型,Lane模式参数
    返回值返回值描述
    HDF_SUCCESS设置成功
    负数设置失败
    int32_t ret;
    enum LaneDivideMode mode;
    
    // Lane模式参数为0 
    mode = LANE_DIVIDE_MODE_0;
    // 设置MIPI RX的 Lane分布 
    ret = MipiCsiSetHsMode(MipiCsiHandle, mode);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("MipiCsiSetHsMode: mipi csi set hs mode fail, ret=%d\n", ret);
        return ret;
    }
  • 设置共模电压模式

    int32_t MipiCsiSetPhyCmvmode(DevHandle handle, uint8_t devno, PhyCmvMode cmvMode);

    表 8 MipiCsiSetPhyCmvmode的参数和返回值描述

    参数参数描述
    handleDevHandle类型,控制器操作句柄
    cmvMode结构体类型,共模电压模式参数
    devnouint8_t类型,设备编号
    返回值返回值描述
    HDF_SUCCESS设置成功
    负数设置失败
    int32_t ret;
    enum PhyCmvMode mode;
    uint8_t devno;
    
    // 共模电压模式参数为0 
    mode = PHY_CMV_GE1200MV;
    // 设备编号为0 
    devno = 0;
    // 设置共模电压模式 
    ret = MipiCsiSetPhyCmvmode(MipiCsiHandle, devno, mode);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("MipiCsiSetPhyCmvmode: mipi csi set phy cmv mode fail, ret=%d\n", ret);
        return ret;
    }
复位/撤销复位Sensor
  • 复位Sensor

    int32_t MipiCsiResetSensor(DevHandle handle, uint8_t snsResetSource);

    表 9 MipiCsiResetSensor的参数和返回值描述

    参数参数描述
    handleDevHandle类型,控制器操作句柄
    snsResetSourceuint8_t类型,传感器的复位信号线号,在软件中称为传感器的复位源
    返回值返回值描述
    HDF_SUCCESS复位成功
    负数复位失败
    int32_t ret;
    uint8_t snsResetSource;
    
    // 传感器复位信号线号为0 
    snsResetSource = 0;
    // 复位Sensor 
    ret = MipiCsiResetSensor(MipiCsiHandle, snsResetSource);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("MipiCsiResetSensor: mipi csi reset sensor fail, ret=%d\n", ret);
        return ret;
    }
  • 撤销复位Sensor

    int32_t MipiCsiUnresetSensor(DevHandle handle, uint8_t snsResetSource);

    表 10 MipiCsiUnresetSensor的参数和返回值描述

    参数参数描述
    handleDevHandle类型,控制器操作句柄
    snsResetSourceuint8_t类型,传感器的复位信号线号,在软件中称为传感器的复位源
    返回值返回值描述
    HDF_SUCCESS撤销复位成功
    负数撤销复位失败
    int32_t ret;
    uint8_t snsResetSource;
    
    // 传感器撤销复位信号线号为0 
    snsResetSource = 0;
    // 撤销复位Sensor 
    ret = MipiCsiUnresetSensor(MipiCsiHandle, snsResetSource);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("MipiCsiUnresetSensor: mipi csi unreset sensor fail, ret=%d\n", ret);
        return ret;
    }
复位/撤销复位MIPI RX
  • 复位MIPI RX

    int32_t MipiCsiResetRx(DevHandle handle, uint8_t comboDev);

    表 11 MipiCsiResetRx的参数和返回值描述

    参数参数描述
    handleDevHandle类型,控制器操作句柄
    comboDevuint8_t类型,MIPI RX或LVDS通路序号
    返回值返回值描述
    HDF_SUCCESS复位成功
    负数复位失败
    int32_t ret;
    uint8_t comboDev;
    
    // 通路序号为0 
    comboDev = 0;
    // 复位MIPI RX 
    ret = MipiCsiResetRx(MipiCsiHandle, comboDev);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("MipiCsiResetRx: mipi csi reset rx fail, ret=%d\n", ret);
        return ret;
    }
  • 撤销复位MIPI RX

    int32_t MipiCsiUnresetRx(DevHandle handle, uint8_t comboDev);

    表 12 MipiCsiUnresetRx的参数和返回值描述

    参数参数描述
    handleDevHandle类型,控制器操作句柄
    comboDevuint8_t类型,MIPI RX或LVDS通路序号
    返回值返回值描述
    HDF_SUCCESS撤销复位成功
    负数撤销复位失败
    int32_t ret;
    uint8_t comboDev;
    
    // 通路序号为0 
    comboDev = 0;
    // 撤销复位MIPI RX 
    ret = MipiCsiUnresetRx(MipiCsiHandle, comboDev);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("MipiCsiUnresetRx: mipi csi unreset rx fail, ret=%d\n", ret);
        return ret;
    }
使能/关闭MIPI的时钟
  • 使能MIPI的时钟

    int32_t MipiCsiEnableClock(DevHandle handle, uint8_t comboDev);

    表 13 MipiCsiEnableClock的参数和返回值描述

    参数参数描述
    handleDevHandle类型,控制器操作句柄
    comboDevuint8_t类型,通路序号
    返回值返回值描述
    HDF_SUCCESS使能成功
    负数使能失败
    int32_t ret;
    uint8_t comboDev;
    
    // 通路序号为0 
    comboDev = 0;
    // 使能MIPI的时钟 
    ret = MipiCsiEnableClock(MipiCsiHandle, comboDev);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("MipiCsiEnableClock: mipi csi enable clock fail, ret=%d\n", ret);
        return ret;
    }
  • 关闭MIPI的时钟

    int32_t MipiCsiDisableClock(DevHandle handle, uint8_t comboDev);

    表 14 MipiCsiDisableClock的参数和返回值描述

    参数参数描述
    handleDevHandle类型,控制器操作句柄
    comboDevuint8_t类型,通路序号
    返回值返回值描述
    HDF_SUCCESS关闭成功
    负数关闭失败
    int32_t ret;
    uint8_t comboDev;
    
    // 通路序号为0 
    comboDev = 0;
    // 关闭MIPI的时钟 
    ret = MipiCsiDisableClock(MipiCsiHandle, comboDev);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("MipiCsiDisableClock: mipi csi disable clock fail, ret=%d\n", ret);
        return ret;
    }
使能/关闭MIPI上的Sensor时钟
  • 使能MIPI上的Sensor时钟

    int32_t MipiCsiEnableSensorClock(DevHandle handle, uint8_t snsClkSource);

    表 15 MipiCsiEnableSensorClock的参数和返回值描述

    参数参数描述
    handleDevHandle类型,控制器操作句柄
    snsClkSourceuint8_t类型,传感器的时钟信号线号,在软件中称为传感器的时钟源
    返回值返回值描述
    HDF_SUCCESS使能成功
    负数使能失败
    int32_t ret;
    uint8_t snsClkSource;
    
    // 传感器的时钟信号线号为0 
    snsClkSource = 0;
    // 使能MIPI上的Sensor时钟 
    ret = MipiCsiEnableSensorClock(MipiCsiHandle, snsClkSource);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("MipiCsiEnableSensorClock: mipi csi enable sensor clock fail, ret=%d\n", ret);
        return ret;
    }
  • 关闭MIPI上的Sensor时钟

    int32_t MipiCsiDisableSensorClock(DevHandle handle, uint8_t snsClkSource);

    表 16 MipiCsiDisableSensorClock的参数和返回值描述

    参数参数描述
    handleDevHandle类型,控制器操作句柄
    snsClkSourceuint8_t类型,传感器的时钟信号线号,在软件中称为传感器的时钟源
    返回值返回值描述
    HDF_SUCCESS关闭成功
    负数关闭失败
    int32_t ret;
    uint8_t snsClkSource;
    
    // 传感器的时钟信号线号为0 
    snsClkSource = 0;
    // 关闭MIPI上的Sensor时钟 
    ret = MipiCsiDisableSensorClock(MipiCsiHandle, snsClkSource);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("MipiCsiDisableSensorClock: mipi csi disable sensor clock fail, ret=%d\n", ret);
        return ret;
    }
释放MIPI CSI控制器操作句柄

MIPI CSI使用完成之后,需要释放控制器操作句柄,释放句柄的函数如下所示:

void MipiCsiClose(DevHandle handle);

该函数会释放掉由MipiCsiOpen申请的资源。

表 17 MipiCsiClose的参数和返回值描述

参数参数描述
handleDevHandle类型,MIPI CSI控制器操作句柄
MipiCsiClose(MIPIHandle); // 释放掉MIPI CSI控制器操作句柄 

使用实例

本例拟对Hi3516DV300开发板上MIPI CSI设备进行操作。

MIPI CSI完整的使用示例如下所示:

#include "hdf_log.h"
#include "mipi_csi_if.h"
#include "securec.h"

enum InterfaceType {
    INTERFACE_MIPI = 0,
    INTERFACE_LVDS,
    INTERFACE_CMOS,
    INTERFACE_BUTT
};

static void InitMipiDevAttr(MipiDevAttr *mipiAttr)
{
    MipiDevAttr attr;
    if (mipiAttr == NULL) {
        return;
    }

    HDF_LOGI("InitMipiDevAttr: enter.");
    (void)memset_s(&attr, sizeof(MipiDevAttr), 0, sizeof(MipiDevAttr));
    attr.inputDataType = DATA_TYPE_RAW_12BIT;
    attr.wdrMode = HI_MIPI_WDR_MODE_NONE;
    // laneId: -1 - disable
    attr.laneId[0] = 0;          // 0 -- laneId 0 
    attr.laneId[1] = 1;          // 1 -- laneId 1 
    attr.laneId[2] = 2;          // 2 -- laneId 2 
    attr.laneId[3] = 3;          // 3 -- laneId 3 

    // Used by the HI_MIPI_WDR_MODE_DT, This is not fully tested!
    if (attr.wdrMode == HI_MIPI_WDR_MODE_DT) {
        attr.dataType[0] = 0x39; // 0x39 -- data type reserved 
        attr.dataType[1] = 0x39; // 0x39 -- data type reserved 
        attr.dataType[2] = 0x39; // 0x39 -- data type reserved 
        attr.dataType[3] = 0x39; // 0x39 -- data type reserved 
    }

    *mipiAttr = attr;
}

static int MipiGetIntputModeType(InputMode inputMode)
{
    switch (inputMode) {
        case INPUT_MODE_SUBLVDS:
        case INPUT_MODE_LVDS:
        case INPUT_MODE_HISPI:
            return INTERFACE_LVDS;
        case INPUT_MODE_MIPI:
            return INTERFACE_MIPI;
        case INPUT_MODE_CMOS:
        case INPUT_MODE_BT1120:
        case INPUT_MODE_BT656:
        case INPUT_MODE_BYPASS:
            return INTERFACE_CMOS;
        default:
            break;
    }

    return INTERFACE_BUTT;
}

static void InitLvdsDevAttr(LvdsDevAttr *lvdsAttr)
{
    int i;
    int j;
    int k;
    LvdsDevAttr attr;

    if (lvdsAttr == NULL) {
        return;
    }

    (void)memset_s(&attr, sizeof(LvdsDevAttr), 0, sizeof(LvdsDevAttr));
    attr.inputDataType = DATA_TYPE_RAW_12BIT;
    attr.wdrMode = HI_WDR_MODE_NONE;
    // LVDS synchronization mode. LVDS_SYNC_MODE_SOF, LVDS_SYNC_MODE_SAV
    attr.syncMode = LVDS_SYNC_MODE_SOF;
    // LVDS Vsync type. LVDS_VSYNC_NORMAL, LVDS_VSYNC_SHARE, LVDS_VSYNC_HCONNECT
    attr.vsyncAttr.syncType = LVDS_VSYNC_NORMAL;
    // hconnect vsync blanking len, valid when the syncType is LVDS_VSYNC_HCONNECT
    // This is not fully tested!
    if (attr.vsyncAttr.syncType == LVDS_VSYNC_HCONNECT) {
        attr.vsyncAttr.hblank1 = 0;
        attr.vsyncAttr.hblank2 = 0;
    }
    // frame identification code: LVDS_FID_NONE, LVDS_FID_IN_SAV, LVDS_FID_IN_DATA
    attr.fidAttr.fidType = LVDS_FID_NONE;
    // Sony DOL has the Frame Information Line, in DOL H-Connection mode, should
    // configure this flag as false to disable output the Frame Information Line.
    // This is not fully tested!
    attr.fidAttr.outputFil = 'm';
    // LVDS bit size end mode: LVDS_ENDIAN_LITTLE, LVDS_ENDIAN_BIG
    attr.dataEndian = LVDS_ENDIAN_LITTLE;
    // sync code endian: little/big, LVDS_ENDIAN_LITTLE, LVDS_ENDIAN_BIG
    attr.syncCodeEndian = LVDS_ENDIAN_LITTLE;
    // laneId: -1 - disable
    attr.laneId[0] = 0; // 0 -- laneId 0 
    attr.laneId[1] = 1; // 1 -- laneId 1 
    attr.laneId[2] = 2; // 2 -- laneId 2 
    attr.laneId[3] = 3; // 3 -- laneId 3 

    /* each vc has 4 params, syncCode[i]:
        syncMode is SYNC_MODE_SOF: SOF, EOF, SOL, EOL
        syncMode is SYNC_MODE_SAV: invalid sav, invalid eav, valid sav, valid eav 
       This is not fully tested! */
    for (i = 0; i < LVDS_LANE_NUM; i++) {
        for (j = 0; j < WDR_VC_NUM; j++) {
            for (k = 0; k < SYNC_CODE_NUM; k++) {
                attr.syncCode[i][j][k] = 0; // 0 -- frame0 sof 
            }
        }
    }

    *lvdsAttr = attr;
}

static int32_t PalMipiCsiTestSample(void)
{
    uint8_t id;
    int32_t ret;
    uint8_t comboDev;
    uint8_t snsClkSource;
    uint8_t snsResetSource;
    uint8_t devno;
    LaneDivideMode laneMode;
    PhyCmvMode CmvMode;
    ComboDevAttr attr;
    DevHandle MipiCsiHandle = NULL;
    enum InterfaceType interType;
    
    // 控制器ID号 
    id = 0; 
    // 获取控制器操作句柄 
    MipiCsiHandle = MipiCsiOpen(id);
    if (MipiCsiHandle == NULL) {
        HDF_LOGE("PalMipiCsiTestSample: mipi csi open fail!\n");
        return HDF_FAILURE;
    }

    // Lane模式参数为0 
    laneMode = LANE_DIVIDE_MODE_0;
    // 设置MIPI RX的Lane分布 
    ret = MipiCsiSetHsMode(MipiCsiHandle, laneMode);
    if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) {
        HDF_LOGE("PalMipiCsiTestSample: mipi csi set hs mode fail, ret=%d\n", ret);
        return ret;
    }

    // 通路序号为0 
    comboDev = 0;
    // 使能MIPI的时钟 
    ret = MipiCsiEnableClock(MipiCsiHandle, comboDev);
    if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) {
        HDF_LOGE("PalMipiCsiTestSample: mipi csi enable clock fail, ret=%d\n", ret);
        return ret;
    }
    
    // 复位MIPI RX 
    ret = MipiCsiResetRx(MipiCsiHandle, comboDev);
    if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) {
        HDF_LOGE("PalMipiCsiTestSample: mipi csi reset rx fail, ret=%d\n", ret);
        return ret;
    }

    // 传感器的时钟信号线号为0 
    snsClkSource = 0;
    // 使能MIPI上的Sensor时钟 
    ret = MipiCsiEnableSensorClock(MipiCsiHandle, snsClkSource);
    if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) {
        HDF_LOGE("PalMipiCsiTestSample: mipi csi enable sensor clock fail, ret=%d\n", ret);
        return ret;
    }
    snsResetSource = 0;
    // 复位Sensor 
    ret = MipiCsiResetSensor(MipiCsiHandle, snsResetSource);
    if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) {
        HDF_LOGE("PalMipiCsiTestSample: mipi csi reset sensor fail, ret=%d\n", ret);
        return ret;
    }
    
    // MIPI参数配置如下 
    (void)memset_s(&attr, sizeof(ComboDevAttr), 0, sizeof(ComboDevAttr));
    attr.devno = 0;                    // 设备0 
    attr.inputMode = INPUT_MODE_MIPI;  // 输入模式为MIPI 
    attr.dataRate = MIPI_DATA_RATE_X1; // 每时钟输出1像素 
    attr.imgRect.x = 0;                // 0: 图像传感器左上位置 
    attr.imgRect.y = 0;                // 0: 图像传感器右上位置 
    attr.imgRect.width = 2592;         // 2592: 图像传感器宽度大小 
    attr.imgRect.height = 1944;        // 1944: 图像传感器高度尺寸 
    interType = MipiGetIntputModeType(attr.inputMode);
    if (interType == INTERFACE_MIPI) {
        HDF_LOGI("PalMipiCsiTestSample: call[InitMipiDevAttr].");
        InitMipiDevAttr(&attr.mipiAttr);
    } else if (interType == INTERFACE_LVDS) {
        HDF_LOGI("PalMipiCsiTestSample: call[InitLvdsDevAttr].");
        InitLvdsDevAttr(&attr.lvdsAttr);
    } else {
        HDF_LOGE("PalMipiCsiTestSample: interType = %d is error!", attr.inputMode);
    }
    // 写入配置数据 
    ret = MipiCsiSetComboDevAttr(MipiCsiHandle, &attr);
    if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) {
        HDF_LOGE("PalMipiCsiTestSample: mipi csi set combo devAttr fail, ret=%d\n", ret);
        return ret;
    }
    
    // 共模电压模式参数为0 
    CmvMode = PHY_CMV_GE1200MV;
    // 设备编号为0 
    devno = 0;
    // 设置共模电压模式 
    ret = MipiCsiSetPhyCmvmode(MipiCsiHandle, devno, CmvMode);
    if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) {
        HDF_LOGE("PalMipiCsiTestSample: mipi csi set phy cmv mode fail, ret=%d\n", ret);
        return ret;
    }
    
    // 通路序号为0 
    comboDev = 0;
    // 撤销复位MIPI RX 
    ret = MipiCsiUnresetRx(MipiCsiHandle, comboDev);
    if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) {
        HDF_LOGE("PalMipiCsiTestSample: mipi csi unreset rx fail, ret=%d\n", ret);
        return ret;
    }
    
    // 关闭MIPI的时钟 
    ret = MipiCsiDisableClock(MipiCsiHandle, comboDev);
    if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) {
        HDF_LOGE("PalMipiCsiTestSample: mipi csi disable clock fail, ret=%d\n", ret);
        return ret;
    }
    
    // 传感器撤销复位信号线号为0 
    snsResetSource = 0;
    // 撤销复位Sensor 
    ret = MipiCsiUnresetSensor(MipiCsiHandle, snsResetSource);
    if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) {
        HDF_LOGE("PalMipiCsiTestSample: mipi csi unreset sensor fail, ret=%d\n", ret);
        return ret;
    }
    
    // 关闭MIPI上的Sensor时钟 
    ret = MipiCsiDisableSensorClock(MipiCsiHandle, snsClkSource);
    if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) {
        HDF_LOGE("PalMipiCsiTestSample: mipi csi disable sensor clock fail, ret=%d\n", ret);
        return ret;
    }
    HDF_LOGI("PalMipiCsiTestSample: function tests end.");
    // 释放MIPI DSI设备句柄 
    MipiCsiClose(MipiCsiHandle);
    return ret;
}

最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。 

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

鸿蒙(HarmonyOS NEXT)最新学习路线

  •  HarmonOS基础技能

  • HarmonOS就业必备技能 
  •  HarmonOS多媒体技术

  • 鸿蒙NaPi组件进阶

  • HarmonOS高级技能

  • 初识HarmonOS内核 
  • 实战就业级设备开发

有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

《鸿蒙 (OpenHarmony)开发入门教学视频》

《鸿蒙生态应用开发V2.0白皮书》

图片

《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

图片

 《鸿蒙开发基础》

  • ArkTS语言
  • 安装DevEco Studio
  • 运用你的第一个ArkTS应用
  • ArkUI声明式UI开发
  • .……

图片

 《鸿蒙开发进阶》

  • Stage模型入门
  • 网络管理
  • 数据管理
  • 电话服务
  • 分布式应用开发
  • 通知与窗口管理
  • 多媒体技术
  • 安全技能
  • 任务管理
  • WebGL
  • 国际化开发
  • 应用测试
  • DFX面向未来设计
  • 鸿蒙系统移植和裁剪定制
  • ……

图片

《鸿蒙进阶实战》

  • ArkTS实践
  • UIAbility应用
  • 网络案例
  • ……

图片

 获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

总结

总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1586670.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

18_SPI通信外设

SPI通信外设 SPI通信外设SPI外设简介SPI框图SPI基本结构主模式全双工连续传输非连续传输 SPI通信外设 SPI外设简介 STM32内部集成了硬件SPI收发电路&#xff0c;可以由硬件自动执行时钟生成、数据收发等功能&#xff0c;减轻CPU的负担 可配置8位/16位数据帧、高位先行/低位先…

基于 MATLAB 和 App Designer 的 UI 交互框架开发的一款电力系统潮流计算工具

基于 MATLAB 和 App Designer 的 UI 交互框架开发的一款电力系统潮流计算工具 文章目录 基于 MATLAB 和 App Designer 的 UI 交互框架开发的一款电力系统潮流计算工具一、软件介绍二、软件功能1、数据输入 2、潮流作业设置3、 潮流结果报表及可视化三、 软件设计思路1 、牛顿拉…

蓝桥杯备考day4

1.1 二分查找模板 bool check(int x) {// 进行某些操作 } // 二分查找函数 int binarySearch() {int l 1, r n; // 初始化左右边界while (r - l > 1) // 当右边界与左边界相差大于1时{int mid (l r) >> 1; // 取中间位置if (check(mid)) // 如果满足条件r mid; …

[目标检测] OCR: 文字检测、文字识别、text spotter

概述 OCR技术存在两个步骤&#xff1a;文字检测和文字识别&#xff0c;而end-to-end完成这两个步骤的方法就是text spotter。 文字检测数据集摘要 daaset语言体量特色MTWI中英文20k源于网络图像&#xff0c;主要由合成图像&#xff0c;产品描述&#xff0c;网络广告(淘宝)MS…

AcWing-直方图中最大的矩形

131. 直方图中最大的矩形 - AcWing题库 所需知识&#xff1a;单调栈 思路&#xff1a;要求最大矩形&#xff0c;所以需要使矩形的高与长的乘积最大即可&#xff0c;依次从左到右将每一列当作中心列&#xff0c;向两边扩散&#xff0c;直到两边的高都小于该列的高&#xff0c;…

Prj文件的几种制作方式

0.序&#xff1a; 多数平面坐标的设计成果&#xff0c;不论是CAD文件&#xff0c;还是BIM模型&#xff0c;还是投影单独存储的tif影像&#xff0c;还是国土部门申请的平面坐标的文本文件&#xff0c;要想和底图叠加&#xff0c;都需要通过正确的投影匹配起来。 多数软件都提供…

解决源 “MySQL 8.0 Community Server“ 的 GPG 密钥已安装,但是不适用于此软件包。请检查源的公钥 URL 是否配置正确。

源 “MySQL 8.0 Community Server” 的 GPG 密钥已安装&#xff0c;但是不适用于此软件包。请检查源的公钥 URL 是否配置正确。 失败的软件包是&#xff1a;mysql-community-server-8.0.31-1.el7.x86_64 GPG 密钥配置为&#xff1a;file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql…

8. 托盘图标与菜单

内容概要&#xff1a; 托盘图标的设置与事件 右键菜单的相关操作 窗口组件&#xff1a; 1.组件的属性 组件属性&#xff1a;位置 组件属性&#xff1a;可视 2.组件的事件 窗口_托盘事件-带有参数的事件的使用方法 3.组件的方法 置托盘图标 菜单的操作 1.创建菜单 …

模型训练----apex库报错IndexError: tuple index out of range

问题描述 在训练模型的过程中遇到了apex库的报错IndexError: tuple index out of range导致无法训练。在github查询后找到了解决方法 问题解决 需要修改/apex-master/apex/amp/utils.py这个文件的代码 从93行开始修改 if x in cache:cached_x cache[x]next_functions_ava…

nvm更新node版本

1、nvm安装和管理多个 Node.js 版本&#xff1a;NVM 允许用户在计算机上同时安装多个不同版本的 Node.js。这使得开发人员可以轻松地在不同的项目中使用不同的 Node.js 版本&#xff0c;而无需手动安装或卸载。 2、nvm切换 Node.js 版本&#xff1a;通过 NVM&#xff0c;用户可…

软考122-上午题-【软件工程】-需求分析

一、软件需求 在进行需求获取之前&#xff0c;首先要明确需要获取什么&#xff0c;也就是需求包含哪些内容。 软件需求是指用户对目标软件系统在功能、行为、性能、设计约束等方面的期望。通常&#xff0c;这些需求包括功能需求、性能需求、用户或人的因素、环境需求、界面需…

深入探索力扣第12题:整数转罗马数字的算法之旅

作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 欢迎加入社区&#xff1a;码上找工作http://t.csdnimg.cn/Q59WX作者专栏每日更新&#xff1a; LeetCode解锁1000题: 打…

国家统计局行政区划获取及入库ES实践

我们先看下最终效果&#xff1a; 1. ES索引新建 PUT administrative_division {"mappings": {"properties": {"province": {"type": "keyword"},"province_code": {"type": "keyword"},&q…

Factory Method 工厂方法

意图 定义一个用户创建对象的接口&#xff0c;让子类决定实例化哪一个类&#xff0c;Factory Method使一个类的实例化延迟到其子类 结构 其中 Product定义工厂方法做创建的对象的接口。ConcreteProduct实现Product接口Creator声明工厂方法&#xff0c;该方法返回一个Product…

海外软文通稿代发 - 大舍传媒

引言 在当今高度信息化的时代&#xff0c;企业和个人品牌形象的塑造与传播变得越来越重要。为了在国际舞台上获得更大的竞争优势&#xff0c;许多企业和品牌纷纷将视线投向了国外市场。而在这个过程中&#xff0c;专业的软文通稿代发服务成为了他们的得力助手。本文将向您介绍…

milvus各组件的结构体分析

milvus各组件的结构体分析 各组件启动&#xff0c;需要构建各组件的结构体&#xff0c;一共8个。 runComponent(ctx, localMsg, wg, components.NewRootCoord, metrics.RegisterRootCoord) runComponent(ctx, localMsg, wg, components.NewProxy, metrics.RegisterProxy) run…

HTTPS证书是什么?申请方法是什么?

HTTPS证书是互联网上由权威证书颁发机构&#xff08;CA&#xff09;签发的数字文件&#xff0c;用于证明网站的身份&#xff0c;并通过其中包含的公钥为网站启用HTTPS加密连接&#xff0c;确保用户与网站间的通信数据安全且不可被第三方窃取或篡改。 怎么申请&#xff1f; 一&…

什么是云原生

什么是云原生 云原生的定义 aws&#xff1a; 云原生是在云计算环境中构建、部署和管理现代应用程序的软件方法。现代公司希望构建高度可伸缩、灵活和有弹性的应用程序&#xff0c;以便能够快速更新以满足客户需求。为此&#xff0c;他们使用了支持云基础设施上应用程序开发的现…

【低成本-点云采集】使用XRFoundation实现点云采集

使用XR Foundation 现基于XR Foundation的接口实现渲染和采集 关键类 ARPointCloudManager 介绍 ARPointCloudManager&#xff1a;ARTrackedObjects的管理器。使用XRDepthSubsystem来识别和跟踪物理环境中的深度数据。 属性 NameDescriptiongameObjectNameThe name to b…

接口自动化入门: Requests请求头设置详解!

在进行接口自动化测试时&#xff0c;设置请求头是非常重要的一步。请求头可以包含各种信息&#xff0c;例如身份验证、内容类型、接受语言等。在实际的测试中&#xff0c;我们使用Python的Requests库来发送HTTP请求&#xff0c;并设置请求头来模拟不同的场景和需求。 下面将通…