针对你在K230上通过MIPI读取CIF节点RAW数据的需求,这是嵌入式视觉开发中的核心挑战。你正尝试完全绕过ISP管线,直接获取原始传感器数据。以下是我的方案和操作步骤:
/dev/videoX设备节点,与K230的MIPI CSI控制器(Camera Interface)绑定&csi {
status = "okay";
// 强制禁用ISP通路
ports {
port@0 {
reg = <0>;
/* CSI直通到虚拟节点而不经过ISP */
endpoint {
remote-endpoint = <&raw_out>;
};
};
};
};
// 建立RAW数据输出节点
vip_raw: vip-raw {
compatible = "kendryte,vip-raw";
status = "okay";
};
&vip_raw {
ports {
port@0 {
reg = <0>;
raw_out: endpoint {
remote-endpoint = <&csi_out>;
};
};
};
};在初始化序列中强制设置RAW格式:
// drivers/media/i2c/ov5640.c
static int ov5640_s_power(struct v4l2_subdev *sd, int on) {
...
// 覆盖默认YUV配置
ov5640_write_reg(client, OV5640_REG_FORMAT, OV5640_RAW_10BIT);
...
}修改CSI控制器的数据处理路径(关键文件:drivers/media/platform/kendryte_cif.c):
static int cif_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f) {
...
// 覆盖格式为RAW
f->fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR10; // Bayer RGGB
...
}
static void cif_capture_frame(struct cif_dev *cif) {
// 取消ISP数据提交调用
// isp_submit_frame(cif->isp_dev); // !!! 注释掉这行
// 直通DMA缓冲区到用户空间
vb2_buffer_done(&cif->vb.vb2_buf, VB2_BUF_STATE_DONE);
}使用标准接口但指定RAW格式:
struct v4l2_format fmt = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.fmt.pix = {
.width = 1920,
.height = 1080,
.pixelformat = V4L2_PIX_FMT_SBGGR10, // 必需匹配
.field = V4L2_FIELD_NONE,
}
};
ioctl(fd, VIDIOC_S_FMT, &fmt);由于内核精简,实现更直接:
output_format设为SENSOR_OUTPUT_RAW_10BITtransfer_end()回调,直接映射DMA地址/dev/csi0节点mmap原始内存块在SDK层面提供RAW模式开关:
import sensor
sensor.reset()
sensor.set_pixformat(sensor.RAW10) # 新增RAW模式
img = sensor.snapshot()
# img.data为Bayer阵列二进制流时序失锁问题:
位宽不匹配:
V4L2_PIX_FMT_Sxxx与传感器实际位宽一致(10/12/14 bit)内存爆裂:
# 增大DMA内存池
echo 256M > /sys/module/videobuf2_common/parameters/dma_contig_memdcraw -E -T raw_0.raw总结:本质上是打通 Sensor → CSI Controller → Userspace 的物理通路,关键在于拦截进入ISP的数据流向。K230的全志V85x系列芯片在寄存器层支持CSI直通模式(CIF_CTRL寄存器的ISP_BYPASS位),最终性能取决于CSI控制器的DMA吞吐量。
建议从RT-Smart系统开始实验,因其驱动层次更浅。CanMV社区已有部分RAW采集的PR提交可参考(GitHub搜索关键词:k230 raw capture)。实际项目若需深度优化,可能需要修改V4L2的vb2内存分配器以支持物理连续内存分配。
举报
更多回帖