杰理 SDK 文档中心
首页
首页
  • 概述与快速开始

    • SDK 总览与芯片能力
    • 环境搭建与编译构建
    • 烧录与固件升级
    • 文档与版本资源
  • 应用与示例方案

    • demo 示例工程
    • WiFi 摄像头方案 (wifi_camera)
    • WiFi 音箱方案 (wifi_soundbox)
    • WiFi 婴儿监护方案 (wifi_bbm)
    • 公共应用模块库
    • 示例代码库 (example)
  • 系统架构与平台

    • 总体架构与工程分层
    • 系统启动与运行框架
    • 芯片驱动与板级适配
    • 设备管理与文件系统
    • 系统工具库与算法
  • 音频子系统

    • 音频框架与处理节点
    • 音频编解码与音效
    • 播放器与录音器
    • 语音交互与 AI 唤醒
    • LE Audio 与蓝牙音频
    • 音频调试与歌词
  • 视频与显示子系统

    • 摄像头驱动与 ISP
    • 视频编码与图像处理
    • 显示与 GPU 加速
    • 屏幕镜像 (screen_mirror)
  • 无线连接与网络

    • 蓝牙协议栈 (双模蓝牙)
    • WiFi 协议栈与配网
    • 网络协议栈
    • 云平台与 IoT 协议
  • UI 子系统

    • LVGL 集成与应用
    • UI 工程与工具链
  • 配置系统

    • 功能配置
    • 板级配置
    • 网络与蓝牙配置
    • 音频配置与提示音
  • 工具与测试

    • 产测与射频测试工具
    • 固件升级与更新机制
    • 调试与日志工具
  • 硬件参考设计

    • 原理图参考设计
    • 芯片数据手册

摄像头驱动与 ISP

本文档介绍 AC792N SDK 中摄像头(Camera)设备驱动与 ISP(图像信号处理器)子系统的整体架构、接口定义、数据流与控制流,涵盖从传感器(Sensor)采集、DVP/CSI2 接口传输、ISP 图像处理到视频帧输出的完整链路。

Purpose and Scope

本页面覆盖 AC792N SDK 中"摄像头驱动与 ISP"这一完整能力域,包括:

  • 摄像头设备抽象层(camera.h)——平台数据结构、设备枚举、ioctl 命令与驱动 API;
  • ISP 接口层(isp.h)——ISP 工作模式、通用/定制配置命令、IOCTL 通道;
  • 视频链路相关头文件(video.h、video_ioctl.h、videobuf.h、fb.h、dec_stream.h、usb_cam_dev.h)在链路中的角色;
  • 应用层示例(isp_scenes.c、isp_tools.c)与具体传感器驱动(nt99141.c、TVP5150A_DVP.c)的接线方式。

以下相关主题属于兄弟页面,不在本页展开:视频编解码流(dec_stream)、帧缓冲显示(fb/LVGL 显示移植)、USB UVC 摄像头协议细节、WiFi 摄像头应用整体流程。

概述

在 AC792N 这类 SoC 上,摄像头子系统是"传感器 → 物理接口 → ISP → 视频管道"的串行链路。SDK 通过统一的设备模型(struct device_operations)把摄像头抽象为可挂载、可打开、可 ioctl 的标准设备,同时把 ISP 抽象为独立的通道化图像处理器。

核心设计意图:

  1. 接口与传感器解耦:应用层只面向 camera_init() / camera_driver_open() / camera_driver_ioctl() 等统一 API,具体传感器(NT99141、TVP5150A 等)的差异被收敛到 camera_platform_data 平台数据与传感器驱动内部,更换传感器不需要改动上层业务。
  2. 接口类型统一:DVP(并行数字视频端口)、CSI2(MIPI 串行摄像头接口)、MCV(多通道视频)共用同一套 camera_platform_data,通过 interface 字段区分,并以内嵌 union 承载各自专用配置。
  3. ISP 通道化:ISP 支持录制(ISP_MODE_REC)与拍照(ISP_MODE_IMAGE_CAPTURE)两种模式,通过 isp_ioctl() 下发 isp_generic_cfg / ispt_customize_cfg,既可走通用参数(EV、白平衡、锐度、DRC),也可走工具/文件/专用定制通道,兼顾易用与灵活性。
  4. 裁剪与重挂载:摄像头提供 crop(裁剪)与 remount(重挂载)命令,支持在运行期调整输出尺寸。

架构

flowchart TD
    subgraph sg_App["应用层 (sdk/apps/common/camera)"]
        ISP_Tools["isp_tools.c / isp_scenes.c"]
        Sensor_NT["nt99141.c 传感器驱动"]
        Sensor_TVP["TVP5150A_DVP.c 传感器驱动"]
        App["业务应用 (wifi_camera 等)"]
    end

    subgraph sg_Driver["驱动接口层 (sdk/include_lib/driver/device/video)"]
        CameraH["camera.h 摄像头设备接口"]
        IspH["isp.h ISP 接口"]
        VideoH["video.h / video_ioctl.h"]
        Videobuf["videobuf.h 视频缓冲"]
        FbH["fb.h 帧缓冲"]
        DecStream["dec_stream.h 解码流"]
        UsbCam["usb_cam_dev.h USB 摄像头"]
    end

    subgraph sg_Hw["硬件链路"]
        DVP["DVP 并行接口 (DVP0/DVP1)"]
        CSI2["CSI2 MIPI 接口 (x0~x4 lane)"]
        MCV["MCV 多通道视频"]
        ISP["ISP 图像信号处理器"]
        SensorHW["CMOS 传感器 (NT99141/TVP5150A)"]
    end

    App --> CameraH
    App --> IspH
    ISP_Tools --> IspH
    Sensor_NT --> CameraH
    Sensor_TVP --> CameraH

    CameraH -->|"camera_platform_data.interface"| DVP
    CameraH -->|"camera_platform_data.interface"| CSI2
    CameraH -->|"camera_platform_data.interface"| MCV
    DVP --> SensorHW
    CSI2 --> SensorHW
    DVP --> ISP
    CSI2 --> ISP
    ISP --> Videobuf
    ISP --> FbH
    Videobuf --> DecStream
    UsbCam --> VideoH

架构说明:

  • 应用层通过 camera.h 暴露的设备接口打开摄像头、下发 ioctl;通过 isp.h 暴露的接口配置 ISP 图像参数(场景、EV、白平衡等)。isp_scenes.c / isp_tools.c 封装了常用场景参数,是应用与 ISP 之间的便捷桥梁。
  • 驱动接口层是 SDK 提供给应用的头文件集合,camera.h 与 isp.h 是核心;video.h/video_ioctl.h 定义视频流设备;videobuf.h 描述视频缓冲管理;fb.h 面向显示;dec_stream.h 面向解码流;usb_cam_dev.h 面向 USB UVC 摄像头。
  • 硬件链路中,传感器通过 DVP 或 CSI2 把原始 Bayer 数据送入 ISP;ISP 完成降噪、锐化、色彩校正(CCM)、Gamma、DRC 等处理后输出标准视频帧,进入 videobuf/fb 管道。

摄像头驱动层(camera.h)

设备标签与接口类型

camera.h 通过 VIDEO_TAG 宏为不同视频源打标签,并定义物理接口枚举:

#define VIDEO_TAG_CAMERA        VIDEO_TAG('c', 'a', 'm', 'e')
#define VIDEO_TAG_UVC           VIDEO_TAG('u', 'v', 'c', ' ')
#define VIDEO_TAG_MASS           VIDEO_TAG('m', 'a', 's', 's')

#define ENDPOINT_NUM 	5
#define CAMERA_DEVICE_NUM  13

#define CSI2_X0_LANE    0
#define CSI2_X1_LANE    1
#define CSI2_X2_LANE    2
#define CSI2_X3_LANE    3
#define CSI2_X4_LANE    4

#define DVP0_INTERFACE  0
#define DVP1_INTERFACE  1
#define CSI2_INTERFACE  2

#define MCV0_INTERFACE  4   //修改序号需要修改跟之相关的逻辑(非作者本人勿动)
#define MCV1_INTERFACE  5
#define MCV2_INTERFACE  6
#define MCV3_INTERFACE  7

来源:camera.h

设计意图:interface 字段用整数枚举区分物理传输方式——DVP 是并行总线(PCLK/HSYNC/VSYNC + 数据线),CSI2 是 MIPI 串行差分总线(最多 4 条 data lane),MCV 是多通道视频端口。枚举值 0/1/2/4~7 之间预留了 3(原 UVC 接口,被注释掉),注释特别警告 MCV 序号与相关逻辑耦合,修改需谨慎。

camera_platform_data:传感器平台配置

这是把一块具体传感器接到 SoC 上的"接线说明书":

struct camera_platform_data {
    char *iic_sel;
    u8 xclk_gpio;
    u8 reset_gpio;
    u8 pwdn_gpio;
    u8 power_value;
    u32 interface;
    bool (*online_detect)();
    union {
        struct {
            u32 pclk_gpio;
            u32 hsync_gpio;
            u32 vsync_gpio;
            u8 group_port;  //DVP0 0: PD9~PE2 1: PA4~PA11  DVP1 0: PB0_PB7 1: PB8_PB15
            u8 reverse;     //0: 正序 1: 反序
            u8 shift;       //数据位偏移量
            u8 timing_mode; //时序选择 0:DVP 1:BT601 2:VSYNC 3:BT656
            u8 scan_mode;   //扫描模式 0:逐行扫描(default) 1:奇场数据 2:偶场数据
            u8 width_mode;  //位宽选择 0:全位宽(8/10bit) 1: 4bit 2: 2bit 3: 1bit
            u32 h_blank; //水平消隐后肩周期数, 默认填0
            u32 v_blank; //垂直消隐后肩行数, 默认填0
            u32 data_gpio[10];
        } dvp;
        struct {
            u8 data_lane_num;
            u8 clk_rmap;
            u8 clk_inv;
            u8 d0_rmap;
            u8 d0_inv;
            u8 d1_rmap;
            u8 d1_inv;
            u8 d2_rmap;
            u8 d2_inv;
            u8 d3_rmap;
            u8 d3_inv;
            u8 tval_hstt;
            u8 tval_stto;
        } csi2;
    };
};

来源:camera.h

结构设计要点:

  • 公共字段:iic_sel(传感器寄存器读写用的 I2C 控制器选择)、xclk_gpio(主时钟输出脚)、reset_gpio / pwdn_gpio(复位/掉电控制)、power_value(供电电压档位)、interface(选择 DVP/CSI2/MCV)、online_detect()(在线检测回调,用于热插拔判断)。
  • 联合体:DVP 与 CSI2 配置互斥存放。DVP 需要声明 PCLK/HSYNC/VSYNC 引脚、端口分组(group_port)、数据位序(reverse)、位偏移(shift)、时序模式(BT601/BT656/VSYNC)、扫描模式(逐行/奇偶场)、位宽(8/10/4/2/1 bit)以及最多 10 根数据 GPIO;CSI2 需要声明 lane 数、时钟与各 lane 的映射(rmap)与极性反转(inv)、以及 tval_hstt / tval_stto 时序参数。
  • 配套宏 CAMERA_PLATFORM_DATA_BEGIN(data) / CAMERA_PLATFORM_DATA_END() 用于以静态 const 方式简洁地初始化平台数据。

摄像头 ioctl 命令与驱动 API

命令集合

摄像头驱动以 CAMERA_CMD_BASE (0x00400000) 为基址定义运行期控制命令:

#define CAMERA_CMD_BASE		0x00400000
#define CAMERA_GET_ISP_SRC_SIZE		(CAMERA_CMD_BASE + 1)
#define CAMERA_GET_ISP_SIZE		(CAMERA_CMD_BASE + 2)
#define CAMERA_SET_CROP_SIZE		(CAMERA_CMD_BASE + 3)
#define CAMERA_CROP_TRIG		(CAMERA_CMD_BASE + 4)
#define CAMERA_NEED_REMOUNT		(CAMERA_CMD_BASE + 5)
#define CAMERA_GET_SENSOR_ID    (CAMERA_CMD_BASE + 6)
#define CAMERA_GET_CAPTURE_RAW  (CAMERA_CMD_BASE + 7)
#define CAMERA_SET_TEST_KICK    (CAMERA_CMD_BASE + 8)
#define CAMERA_GET_TEST_DONE    (CAMERA_CMD_BASE + 9)

来源:camera.h

命令方向用途
CAMERA_GET_ISP_SRC_SIZE查询获取 ISP 输入(传感器原始)尺寸
CAMERA_GET_ISP_SIZE查询获取 ISP 输出尺寸
CAMERA_SET_CROP_SIZE设置设置裁剪窗口尺寸
CAMERA_CROP_TRIG触发触发裁剪生效
CAMERA_NEED_REMOUNT查询/设置请求视频设备重挂载(尺寸变更后重建管道)
CAMERA_GET_SENSOR_ID查询读取传感器 ID(用于识别 sensor 型号)
CAMERA_GET_CAPTURE_RAW查询获取 RAW 抓拍缓冲
CAMERA_SET_TEST_KICK触发触发产测动作
CAMERA_GET_TEST_DONE查询查询产测完成状态

这些命令通过 camera_driver_ioctl() 统一下发,业务代码无需关心具体寄存器,做到了"应用层只发语义命令、驱动层负责翻译成硬件操作"。

驱动 API

extern const struct device_operations camera_dev_ops;

int camera_init(const char *name, void *camera_data);
void *camera_driver_open(int id, struct camera_device_info *info);
int camera_driver_close(void *_camera);
int camera_driver_force_close(void *_camera);
int camera_driver_ioctl(void *_camera, u32 cmd, void *arg);

来源:camera.h

  • camera_dev_ops:标准设备操作表(open/close/ioctl 等),供系统设备框架挂载 camera 设备节点。
  • camera_init(name, camera_data):注册一个摄像头设备,name 是设备名,camera_data 指向 camera_platform_data。
  • camera_driver_open(id, info):按 id(0~CAMERA_DEVICE_NUM-1)打开摄像头,返回驱动句柄;info(struct camera_device_info)回传当前帧率与分辨率(fps、sen_width、sen_height、width、height、real_fps)。
  • camera_driver_close / camera_driver_force_close:正常关闭与强制关闭(后者用于异常路径兜底)。
  • camera_driver_ioctl(handle, cmd, arg):下发上述命令集。

camera_device_info 结构(camera.h#L79-L86)把传感器尺寸(sen_width/sen_height)与输出尺寸(width/height)分开描述——这正是 ISP 裁剪能力的体现:传感器输出可以大于应用需要的最终尺寸。

ISP 接口层(isp.h)

工作模式

enum isp_mode {
    ISP_MODE_NONE   = 0x0,
    ISP_MODE_REC,
    ISP_MODE_IMAGE_CAPTURE,
};

enum {
    ISP_CFG_MODE_GENERIC    = 0x0,
    ISP_CFG_MODE_CUSTOMIZE,
};

来源:isp.h

  • ISP_MODE_REC:录制模式,面向视频流实时处理(预览/录像)。
  • ISP_MODE_IMAGE_CAPTURE:拍照模式,面向静态图像质量优先。
  • 配置模式 ISP_CFG_MODE_GENERIC(通用参数)与 ISP_CFG_MODE_CUSTOMIZE(定制参数)决定 isp_ioctl 走哪套数据结构。

命令集

通用命令(3A/图像基础参数):

enum isp_generic_cmd {
    ISP_SET_INPUT_SIZE = 0x4A4C0000,
    ISP_SET_OUTPUT_SIZE,
    ISP_SET_MODE,
    ISP_SET_EV,
    ISP_SET_WB,
    ISP_SET_SHP,
    ISP_SET_DRC,

    ISP_GET_LV,
    ISP_GET_FREQ,
    ISP_GET_SEN_STATUS,
    ISP_GET_VISGNAL,
    ISP_GET_SEN_SIZE,
    ISP_GET_ISP_SIZE,
};

来源:isp.h

特殊命令(图像画质细调):

enum isp_special_cmd {
    ISP_SET_CCM,
    ISP_SET_NR,
    ISP_SET_SHPN,
    ISP_SET_SATURATION,
    ISP_SET_GAMMA,
    ISP_SET_BRIGHTNESS,
    ISP_SET_CONTRAST,
};

来源:isp.h

定制模式来源:

#define     ISP_CUSTOMIZE_MODE_TOOL     0x1
#define     ISP_CUSTOMIZE_MODE_FILE     0x2
#define     ISP_CUSTOMIZE_MODE_SPECIAL  0x3

来源:isp.h

数据结构与 IOCTL

isp_generic_cfg 是通用配置的载体——一条结构同时携带命令字、通道号、3A 参数与输入/输出/传感器三组格式:

struct isp_pix_format {
    u32 fps;
    u16 width;
    u16 height;
};

struct isp_generic_cfg {
    u32 cmd;
    u8 channel;
    u8 mode;
    u8 sen_status;
    u8 vsignal;
    s8 ev;
    u8 white_blance;
    u8 sharpness;
    u8 drc;
    s32 lv;

    struct isp_pix_format in_fmt;
    struct isp_pix_format out_fmt;
    struct isp_pix_format sen_fmt;
};

来源:isp.h

ispt_customize_cfg 则用于传递不定长的定制数据块(如从 ISP 工具导出的寄存器表、参数文件),带版本号与 CRC 校验:

struct ispt_customize_cfg {
    u8      mode;
    u8      channel;
    u8      cmd;
    u8      *data;
    int     len;
    u16     version;
    u16     crc;
    void    *private;
};

来源:isp.h

IOCTL 命令宏与导出函数:

#define ISP_IOCTL_SET_GENERIC_CFG 		_IOW('I', 0,  struct isp_generic_cfg)
#define ISP_IOCTL_GET_GENERIC_CFG           _IOR('I', 1,  struct isp_generic_cfg)
#define ISP_IOCTL_SET_CUSTOMIZE_CFG         _IOW('I', 2,  struct ispt_customize_cfg)
#define ISP_IOCTL_GET_CUSTOMIZE_CFG         _IOR('I', 3,  struct ispt_customize_cfg)
#define ISP_IOCTL_SET_FPS                   _IOW('I', 4,  int)

s32 isp0_mount(void *arg);
void isp_dump_reg();
int isp_delete(int channel);
s32 isp0_ioctrl(void *parm, u32 cmd);
int isp_ioctl(u32 cmd, void *arg);

来源:isp.h

设计意图:ISP_IOCTL_SET_GENERIC_CFG 走通用路径(适合日常调节),ISP_IOCTL_SET_CUSTOMIZE_CFG 走定制路径(适合产线校准/ISP 工具联调)。isp0_ioctrl / isp0_mount 是通道 0 的设备回调,isp_ioctl 是应用层统一入口;isp_dump_reg() 用于调试时导出寄存器;isp_delete(channel) 用于销毁指定 ISP 通道。

核心流程

摄像头打开与 ISP 配置流程

sequenceDiagram
    participant App as 业务应用
    participant Cam as camera 驱动 (camera_dev_ops)
    participant Plat as camera_platform_data
    participant Sen as 传感器驱动 (nt99141/TVP5150A)
    participant ISP as ISP 通道 (isp0)
    participant VB as videobuf 视频管道

    App->>Cam: camera_init("cam0", &platform_data)
    Cam->>Plat: 读取 iic_sel/xclk_gpio/reset_gpio/interface
    App->>Cam: camera_driver_open(id, &info)
    Cam->>Sen: 上电 (xclk/reset/pwdn) + I2C 初始化
    Sen-->>Cam: 回读 sensor ID 确认
    Cam->>ISP: 按 interface 配置 DVP/CSI2 时序
    ISP-->>Cam: 建立 ISP 通道 (in/out/sen fmt)
    Cam-->>App: 返回句柄 + camera_device_info(fps/width/height)
    App->>ISP: isp_ioctl(ISP_IOCTL_SET_GENERIC_CFG, {cmd=ISP_SET_MODE, mode=ISP_MODE_REC})
    App->>ISP: isp_ioctl(ISP_IOCTL_SET_GENERIC_CFG, {cmd=ISP_SET_EV/ISP_SET_WB/ISP_SET_SHP/ISP_SET_DRC})
    ISP->>VB: 输出处理后的视频帧
    VB-->>App: 预览/录像消费帧
    App->>Cam: camera_driver_ioctl(handle, CAMERA_SET_CROP_SIZE, ...)
    App->>Cam: camera_driver_ioctl(handle, CAMERA_CROP_TRIG, ...)
    Cam->>ISP: 更新输出尺寸
    App->>Cam: camera_driver_close(handle)

流程说明:

  1. 注册:应用调用 camera_init() 传入 camera_platform_data,驱动据此完成 GPIO/I2C 资源登记,但不立即上电。
  2. 打开:camera_driver_open() 触发传感器上电(xclk_gpio 输出主时钟、reset_gpio 释放复位、pwdn_gpio 解除掉电),通过 iic_sel 指定的 I2C 控制器初始化传感器寄存器,并回读 sensor ID 校验。
  3. ISP 建链:驱动依据 interface 字段配置 DVP(PCLK/HSYNC/VSYNC/数据线 GPIO、时序模式、扫描模式、位宽)或 CSI2(lane 数、映射、极性)时序,建立 ISP 通道,填入 in_fmt(传感器格式)、out_fmt(输出格式)。
  4. 参数下发:应用通过 isp_ioctl() 下发录制/拍照模式、EV、白平衡、锐度、DRC 等参数;isp_scenes.c/isp_tools.c 提供的封装可一次性套用某个场景的整套参数。
  5. 运行期调整:需要变更分辨率时,先 CAMERA_SET_CROP_SIZE 设置裁剪窗口,再 CAMERA_CROP_TRIG 触发,必要时通过 CAMERA_NEED_REMOUNT 让视频设备重建管道。
  6. 关闭:camera_driver_close() 停止 ISP 通道、释放缓冲;异常场景用 camera_driver_force_close() 兜底。

运行期 ioctl 决策流

flowchart TD
    Start([camera_driver_ioctl]) --> Cmd{"命令分类"}
    Cmd -->|"查询类 (GET_*)"| Q["读取 ISP 尺寸/传感器 ID/RAW 缓冲"]
    Cmd -->|"裁剪类 (SET_CROP/CROP_TRIG)"| C["更新裁剪窗口并触发 ISP 重算输出"]
    Cmd -->|"重挂载类 (NEED_REMOUNT)"| R["通知视频管道重建"]
    Cmd -->|"产测类 (TEST_KICK/TEST_DONE)"| T["触发/查询产测流程"]
    Q --> Done([返回])
    C --> Done
    R --> Done
    T --> Done

视频链路相关头文件角色

摄像头输出并不直接送给应用,而是汇入视频管道。SDK 在 sdk/include_lib/driver/device/video/ 下提供了配套头文件:

头文件角色与摄像头/ISP 的关系
video.h视频设备抽象(open/close/ioctl/流控)消费 ISP 输出的视频帧,是 CAMERA_NEED_REMOUNT 后重建的对象
video_ioctl.h视频 ioctl 命令定义定义取流、缓冲队列等命令
videobuf.h视频帧缓冲管理承载 ISP 输出帧,供预览/编码消费
fb.h帧缓冲(显示)把 ISP 帧送到屏幕显示路径
dec_stream.h解码流摄像头 RAW 抓拍(CAMERA_GET_CAPTURE_RAW)相关
usb_cam_dev.hUSB UVC 摄像头设备与 VIDEO_TAG_UVC 对应,属独立 UVC 链路

注:上述头文件为设备接口层组成部分;本页聚焦摄像头驱动与 ISP 本身,视频编解码与显示细节见对应兄弟页面。

使用示例

示例 1:定义摄像头平台数据(DVP 传感器接线)

以 DVP 接口为例,通过平台宏声明 camera_platform_data,声明 I2C、时钟、复位、掉电引脚与 DVP 时序参数:

CAMERA_PLATFORM_DATA_BEGIN(camera_platform_data)
    .iic_sel = "iic0",
    .xclk_gpio = 25,
    .reset_gpio = 26,
    .pwdn_gpio = 27,
    .power_value = 0,
    .interface = DVP0_INTERFACE,
    .online_detect = NULL,
    .dvp = {
        .pclk_gpio  = ...,
        .hsync_gpio = ...,
        .vsync_gpio = ...,
        .group_port = 0,   // DVP0: 0=PD9~PE2  1=PA4~PA11
        .reverse    = 0,   // 0: 正序 1: 反序
        .shift      = 0,   // 数据位偏移量
        .timing_mode = 0,  // 0:DVP 1:BT601 2:VSYNC 3:BT656
        .scan_mode   = 0,  // 0:逐行扫描 1:奇场 2:偶场
        .width_mode  = 0,  // 0:全位宽(8/10bit) 1:4bit 2:2bit 3:1bit
        .h_blank = 0,
        .v_blank = 0,
    },
CAMERA_PLATFORM_DATA_END()

结构定义来源:camera.h;具体传感器(NT99141、TVP5150A)的实例见 nt99141.c 与 TVP5150A_DVP.c

示例 2:注册并打开摄像头

// 注册摄像头设备
camera_init("cam0", (void *)&camera_platform_data);

// 打开摄像头,获取当前分辨率/帧率
struct camera_device_info info;
void *cam = camera_driver_open(0, &info);
// info.width / info.height / info.fps / info.real_fps 可用

// 下发 ioctl(例如查询 ISP 输出尺寸或设置裁剪)
u32 w = 0, h = 0;
camera_driver_ioctl(cam, CAMERA_GET_ISP_SIZE, &w);

// 关闭
camera_driver_close(cam);

API 声明来源:camera.h 与 camera.h#L79-L86

示例 3:下发 ISP 通用配置

struct isp_generic_cfg cfg = {0};
cfg.cmd      = ISP_SET_MODE;
cfg.channel  = 0;
cfg.mode     = ISP_MODE_REC;          // 录制模式
cfg.in_fmt   = (struct isp_pix_format){ .fps = 30, .width = 640, .height = 480 };
cfg.out_fmt  = (struct isp_pix_format){ .fps = 30, .width = 640, .height = 480 };

isp_ioctl(ISP_IOCTL_SET_GENERIC_CFG, &cfg);

// 调节曝光/白平衡/锐度/DRC
cfg.cmd = ISP_SET_EV; cfg.ev = 0;      isp_ioctl(ISP_IOCTL_SET_GENERIC_CFG, &cfg);
cfg.cmd = ISP_SET_WB; cfg.white_blance = 0; isp_ioctl(ISP_IOCTL_SET_GENERIC_CFG, &cfg);
cfg.cmd = ISP_SET_SHP; cfg.sharpness = 0;   isp_ioctl(ISP_IOCTL_SET_GENERIC_CFG, &cfg);
cfg.cmd = ISP_SET_DRC; cfg.drc = 0;         isp_ioctl(ISP_IOCTL_SET_GENERIC_CFG, &cfg);

结构体与命令定义来源:isp.h;更便捷的场景化封装见 isp_scenes.c 与 isp_tools.c

配置选项

camera_platform_data 字段

字段类型默认/取值说明
iic_selchar *"iic0" 等传感器寄存器访问使用的 I2C 控制器
xclk_gpiou8平台相关传感器主时钟(XCLK)输出 GPIO
reset_gpiou8平台相关传感器复位 GPIO
pwdn_gpiou8平台相关传感器掉电控制 GPIO
power_valueu8平台相关供电档位
interfaceu32DVP0_INTERFACE(0) / DVP1_INTERFACE(1) / CSI2_INTERFACE(2) / MCVx_INTERFACE(4~7)物理接口类型
online_detectbool (*)()NULL在线检测回调(热插拔场景)
dvp.pclk_gpiou32平台相关DVP 像素时钟引脚
dvp.hsync_gpio / dvp.vsync_gpiou32平台相关行/场同步引脚
dvp.group_portu80/1DVP0: 0=PD9~PE2, 1=PA4~PA11;DVP1: 0=PB0~PB7, 1=PB8~PB15
dvp.reverseu80数据位序:0 正序 / 1 反序
dvp.shiftu80数据位偏移量
dvp.timing_modeu80时序:0 DVP / 1 BT601 / 2 VSYNC / 3 BT656
dvp.scan_modeu80扫描:0 逐行 / 1 奇场 / 2 偶场
dvp.width_modeu80位宽:0 全位宽(8/10bit) / 1 4bit / 2 2bit / 3 1bit
dvp.h_blank / dvp.v_blanku320水平/垂直消隐后肩(默认 0)
dvp.data_gpio[10]u32[]平台相关最多 10 根数据 GPIO
csi2.data_lane_numu81~4MIPI data lane 数量
csi2.clk_rmap / clk_invu80时钟引脚映射/极性反转
csi2.d0_rmap~d3_rmapu80各 lane 引脚映射
csi2.d0_inv~d3_invu80各 lane 极性反转
csi2.tval_hstt / tval_sttou80CSI2 时序参数(HS 建立/退出时间)

isp_generic_cfg 常用字段

字段类型说明
cmdu32通用命令(ISP_SET_* / ISP_GET_*)
channelu8ISP 通道号
modeu8ISP_MODE_NONE / ISP_MODE_REC / ISP_MODE_IMAGE_CAPTURE
sen_status / vsignalu8传感器状态/视频信号标志(查询回填)
evs8曝光补偿
white_blanceu8白平衡档位
sharpnessu8锐度
drcu8动态范围压缩强度
lvs32亮度电平(查询回填)
in_fmt / out_fmt / sen_fmtstruct isp_pix_format输入/输出/传感器 帧格式(fps/width/height)

API 参考

int camera_init(const char *name, void *camera_data)

注册一个摄像头设备。

  • 参数:name 设备名;camera_data 指向 struct camera_platform_data 的指针。
  • 返回:0 成功,负值失败。
  • 说明:通常在系统初始化阶段调用,每个摄像头实例调用一次。

void *camera_driver_open(int id, struct camera_device_info *info)

按设备号打开摄像头并完成传感器上电与 ISP 建链。

  • 参数:id 设备号(0~CAMERA_DEVICE_NUM-1);info 输出参数,回填 fps、sen_width、sen_height、width、height、real_fps。
  • 返回:摄像头驱动句柄;失败返回 NULL。
  • 说明:打开后即可通过返回句柄执行 ioctl。

int camera_driver_close(void *_camera) / int camera_driver_force_close(void *_camera)

关闭摄像头。force_close 用于异常/抢占场景强制释放。

  • 参数:_camera 由 camera_driver_open 返回的句柄。
  • 返回:0 成功,负值失败。

int camera_driver_ioctl(void *_camera, u32 cmd, void *arg)

下发摄像头控制命令。

  • 参数:_camera 句柄;cmd 取 CAMERA_GET_ISP_SRC_SIZE、CAMERA_SET_CROP_SIZE、CAMERA_CROP_TRIG、CAMERA_NEED_REMOUNT、CAMERA_GET_SENSOR_ID、CAMERA_GET_CAPTURE_RAW、CAMERA_SET_TEST_KICK、CAMERA_GET_TEST_DONE 等;arg 命令参数指针。
  • 返回:0 成功,负值失败。

int isp_ioctl(u32 cmd, void *arg)

ISP 统一控制入口。

  • 参数:cmd 取 ISP_IOCTL_SET_GENERIC_CFG、ISP_IOCTL_GET_GENERIC_CFG、ISP_IOCTL_SET_CUSTOMIZE_CFG、ISP_IOCTL_GET_CUSTOMIZE_CFG、ISP_IOCTL_SET_FPS;arg 对应结构体指针(isp_generic_cfg / ispt_customize_cfg / int)。
  • 返回:0 成功,负值失败。
  • 说明:内部根据 cmd 路由到 isp0_ioctrl 等通道回调。

s32 isp0_mount(void *arg) / int isp_delete(int channel)

ISP 通道挂载与销毁。isp0_mount 在设备打开时建立通道 0;isp_delete(channel) 释放指定通道资源。

void isp_dump_reg()

调试接口,导出当前 ISP 寄存器状态(配合 ISP_CUSTOMIZE_MODE_TOOL 联调使用)。

故障模式、边界情况与并发

传感器识别失败

camera_driver_open() 内部会通过 iic_sel 指定的 I2C 回读传感器 ID。若接线错误、供电异常或 I2C 控制器选择错误,回读失败将导致打开失败(返回 NULL)。建议:

  • 核对 iic_sel 与硬件上传感器 SDA/SCL 实际挂载的 I2C 控制器;
  • 核对 xclk_gpio 是否输出有效主时钟(多数 CMOS 传感器无时钟不响应 I2C);
  • 核对 reset_gpio / pwdn_gpio 电平极性是否符合传感器手册。

DVP 时序错配

DVP 场景下 group_port、reverse、shift、timing_mode、scan_mode、width_mode 任一配置错误都会导致花屏或无图。timing_mode 需与传感器输出格式匹配(如 BT656 只支持特定传感器),scan_mode 用于隔行传感器,逐行传感器必须保持默认 0。h_blank / v_blank 默认填 0,只有传感器输出带特殊消隐需求时才需要调整。

CSI2 极性/映射错误

CSI2 场景下 clk_inv / d0_inv~d3_inv 与 rmap 必须与 PCB 布线一致;data_lane_num 与实际接线的 lane 数一致。tval_hstt / tval_stto 影响 HS 建立/退出时序,高速模式不稳定时可微调。这类问题通常表现为"能识别 sensor 但取流失败/花屏"。

裁剪与重挂载的时序约束

CAMERA_SET_CROP_SIZE 只设置参数,必须再发 CAMERA_CROP_TRIG 才生效;尺寸变更后视频管道需要重建,应用必须处理 CAMERA_NEED_REMOUNT,否则可能出现取流尺寸与缓冲不匹配(越界/撕裂)。裁剪尺寸不能超出 ISP 输出能力。

并发与资源竞争

  • 多个摄像头设备(最多 CAMERA_DEVICE_NUM 13 个、ENDPOINT_NUM 5 个端点)共享 ISP 与视频管道资源,通道号(channel)必须唯一,重复挂载同一通道可能导致 ISP 状态错乱。
  • ISP 参数下发与取流并行时,建议在帧回调外(或临界区)下发 isp_ioctl,避免参数在帧处理中途切换造成短暂画质跳变。
  • 异常退出场景应使用 camera_driver_force_close() 兜底,避免残留占用导致后续打开失败。
  • MCVx_INTERFACE 序号与驱动内部逻辑强耦合(源码注释明确"非作者本人勿动"),自行修改枚举值可能破坏多通道路由。

产测路径

CAMERA_SET_TEST_KICK / CAMERA_GET_TEST_DONE 用于产线测试(如坏点、动态范围测试),测试期间摄像头可能暂停正常取流,业务应避免并发取流。

性能与运维

  • 带宽:DVP 并行接口在 8/10bit 全位宽下占用较多 GPIO 与总线带宽;CSI2 通过 lane 数可扩展带宽(CSI2_X0_LANE~CSI2_X4_LANE),高速场景优先 CSI2。
  • 帧率控制:ISP_IOCTL_SET_FPS 与 isp_pix_format.fps 共同决定输出帧率;camera_device_info.real_fps 反映实际帧率,可用于诊断帧率不足(排除时钟、带宽、曝光过长问题)。
  • 调试手段:isp_dump_reg() 导出 ISP 寄存器;ISP_IOCTL_GET_GENERIC_CFG 回读当前参数(含 lv 亮度、sen_status、vsignal),用于确认 3A 是否收敛。
  • 定制参数管理:ispt_customize_cfg 携带 version 与 crc,用于区分和校验 ISP 工具导出的参数版本,避免旧参数覆盖新参数;三种来源 TOOL / FILE / SPECIAL 对应联调、量产固化与特殊场景注入。
  • 传感器驱动维护:新传感器接入时,在 sdk/apps/common/camera/ 下新建类似 nt99141.c 的驱动文件(寄存器初始化 + 平台数据 + 注册),并在应用初始化处调用 camera_init() 即可,无需改动驱动框架。

扩展点

  1. 新增传感器:参照 nt99141.c / TVP5150A_DVP.c 提供传感器驱动与 camera_platform_data 实例,通过 camera_init() 挂载。
  2. ISP 场景封装:在 isp_scenes.c 中扩展场景表(室内/室外/夜视等),通过 isp_tools.c 提供快捷接口,业务只需按场景切换。
  3. 定制 ISP 参数:使用 ISP_IOCTL_SET_CUSTOMIZE_CFG + ISP_CUSTOMIZE_MODE_*,可注入 ISP 工具产出的寄存器表、量产校准文件或特殊效果参数。
  4. 在线检测:实现 online_detect 回调可支持摄像头热插拔(配合 CAMERA_NEED_REMOUNT 重建管道)。
  5. 视频管道接入:ISP 输出汇入 videobuf/fb/dec_stream 链路,接入编码器、显示或网络推流(如 wifi_camera 应用),扩展点在视频设备层。

测试

仓库内相关测试/验证主要体现为:

  • 传感器驱动验证:nt99141.c(CMOS 数字传感器)与 TVP5150A_DVP.c(模拟转数字 DVP 传感器)两套真实驱动作为接入范例,覆盖了 I2C 初始化、平台数据定义与 camera_init 注册的完整路径。
  • ISP 场景验证:isp_scenes.c 的场景参数集合用于验证不同光照下的画质表现;isp_tools.c 提供与 ISP 工具联调的基础设施(寄存器读写/参数导入导出)。
  • 应用集成验证:sdk/apps/wifi_camera 工程的 tx_camera_cWF.c 展示摄像头取流 + WiFi 推流的端到端用法;sdk/apps/wifi_camera/board/wl83/AC792N_WIFI_CAMERA.cbp(Code::Blocks 工程文件)展示板级接线与工程组织。

相关链接

  • camera.h — 摄像头设备接口
  • isp.h — ISP 接口
  • video.h / video_ioctl.h / videobuf.h — 视频管道接口
  • isp_scenes.c — ISP 场景配置
  • isp_tools.c — ISP 工具封装
  • nt99141.c — NT99141 传感器驱动
  • TVP5150A_DVP.c — TVP5150A 传感器驱动
  • 兄弟页面:视频编解码流(dec_stream)、帧缓冲显示(fb/LVGL)、USB UVC 摄像头、WiFi 摄像头应用
Next
视频编码与图像处理