简介:这份资源面向嵌入式驱动开发与摄像头模组调试人员,提供JX-F23图像传感器的驱动源码,用于在目标平台上完成1920×1080@30FPS高清视频流的采集与控制。包内共6个文件,以C源码与头文件为核心,包含f23_sensor_ctl.c、f23_cmos.c及f23_cmos_ex.h等实现,另附编译生成的.o目标文件与Makefile构建脚本,整体约42KB,结构紧凑,便于直接集成到现有工程中编译验证。已有387人学习下载,说明该驱动在同类模组调试中具有一定参考价值。读者可从中获取传感器寄存器配置、CMOS初始化流程、中断与电源管理等关键实现思路,并借助Makefile快速搭建编译环境,对照源码理解驱动与硬件交互的完整链路,适合需要快速移植或二次开发F23 sensor驱动的工程师参考。
1. JX-F23 sensor 驱动到底在驱动什么:从上电到出图的那条链路
JX-F23 是一颗 CMOS sensor,常出现在嵌入式视觉模组里,配合 SoC 的 ISP 管线完成从光信号到 YUV/RGB 帧的转换。很多人第一次拿到「soi_f23_JX-F23_sensor驱动」这类命名时,会以为它只是一个.c文件,实际上它是一整条链路:SoC 端 CSI/MIPI 控制器配置、I2C 寄存器序列、时钟与复位时序、电源域上电顺序、ISP 输入格式匹配,缺一环就黑屏或花屏。我见过太多人卡在「驱动 probe 成功但不出图」,最后发现是 MCLK 没给或 PWDN 极性反了。这篇面向正在调 JX-F23 的嵌入式工程师,也适合刚接触 sensor 出图全流程的新手,按步骤能复现,熟手能对照边界条件。核心就一件事:把 sensor 从「I2C 能读到 ID」推到「ISP 稳定出帧」。
2. 先立住原理:JX-F23 出图依赖哪些硬条件
2.1 上电时序与三路电源的先后关系
JX-F23 通常需要三路电源:模拟 AVDD、数字 DVDD、IO DOVDD。常见做法是 AVDD → DVDD → DOVDD,或者按 datasheet 要求的顺序,但很多模组把三路合并成两路,这时就要看具体原理图。上电顺序错了不会立刻烧,但会出现 I2C 能通、出图随机花屏的玄学问题。我一般会先用万用表确认每路电压到位,再用示波器看 PWDN 和 RESET 的释放时刻是否在电源稳定之后。参数上,PWDN 高电平有效还是低电平有效必须和驱动里的gpio_set_value对应,反了就是一直复位。
2.2 MCLK、I2C 地址与 ID 读取的验证
MCLK 是 sensor 的工作时钟,常见 24MHz 或 27MHz。没有 MCLK,I2C 可能还能读,但出图一定失败。验证顺序:先给 MCLK,再释放 RESET,再读 ID。JX-F23 的 I2C 地址常见 0x36(7 位),但不同模组可能因 SID 引脚改地址。读 ID 的寄存器通常是 0x0000/0x0001 或厂商自定义页。如果读不到,先查 I2C 波形,再看地址是否被 7 位/8 位写法搞混。Linux 下可以用i2cdetect扫总线,但注意 sensor 可能只在特定电源状态下才响应。
2.3 MIPI CSI-2 链路与 ISP 输入格式匹配
JX-F23 输出通常是 MIPI CSI-2,lane 数常见 1 或 2 lane。SoC 端要配置 CSI 控制器、PHY、ISP 输入尺寸和 Bayer 顺序。Bayer 顺序错了,颜色会偏绿或偏紫。常见做法是先用 sensor 的测试图案模式出图,确认链路通,再切真实曝光。如果 ISP 不支持该 sensor 的 RAW 位宽(比如 10bit 打包成 8bit),也会出图异常。这里的关键参数:>&i2c3 { status = "okay"; clock-frequency = <400000>; jx_f23: sensor@36 { compatible = "vendor,jx-f23"; reg = <0x36>; clocks = <&cru CLK_MIPI_CAMARAOUT_M2>; clock-names = "xvclk"; power-domains = <&power RK3568_PD_VI>; pinctrl-names = "default"; pinctrl-0 = <&mipim0_camera2_clk>; reset-gpios = <&gpio1 RK_PB0 GPIO_ACTIVE_LOW>; pwdn-gpios = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>; avdd-supply = <&vcc_2v8>; dovdd-supply = <&vcc_1v8>; dvdd-supply = <&vcc_1v2>; port { jx_f23_out: endpoint { remote-endpoint = <&mipi_in_ucam2>; >static int jx_f23_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct jx_f23 *sensor; int ret; sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL); if (!sensor) return -ENOMEM; sensor->client = client; mutex_init(&sensor->mutex); /* 1. 获取 regulator 并上电,顺序按 datasheet */ ret = jx_f23_power_on(&client->dev); if (ret) { dev_err(&client->dev, "power on failed\n"); return ret; } /* 2. 给 MCLK,常见 24MHz */ ret = clk_prepare_enable(sensor->xvclk); if (ret) { dev_err(&client->dev, "clk enable failed\n"); goto err_power_off; } /* 3. 释放 reset 和 pwdn,注意极性 */ gpiod_set_value_cansleep(sensor->reset_gpio, 0); gpiod_set_value_cansleep(sensor->pwdn_gpio, 0); usleep_range(1000, 2000); /* 4. 读 chip id,确认 I2C 通 */ ret = jx_f23_read_id(sensor); if (ret) { dev_err(&client->dev, "read id failed\n"); goto err_clk_disable; } /* 5. 注册 v4l2 subdev 和 media entity */ ret = jx_f23_register_subdev(sensor); if (ret) goto err_clk_disable; return 0; err_clk_disable: clk_disable_unprepare(sensor->xvclk); err_power_off: jx_f23_power_off(&client->dev); return ret; }
参数说明:usleep_range(1000, 2000)是复位释放后的稳定等待,太短可能读不到 ID。gpiod_set_value_cansleep的第二个参数取决于 GPIO_ACTIVE_LOW/HIGH,设备树里写错这里就反。jx_f23_read_id一般读 0x0000 和 0x0001,返回值拼成 16 位 ID,和 datasheet 对比。如果 probe 失败,先看dmesg里哪一步打印,再量电压和波形。
3.3 用 v4l2-ctl 抓第一帧并确认格式
驱动 probe 成功后,用v4l2-ctl列出设备,确认 subdev 和 video 节点。常见命令如下:
# 列出所有 video 设备 v4l2-ctl --list-devices # 查看 sensor subdev 支持的格式 v4l2-ctl -d /dev/v4l-subdev2 --list-subdev-mbus-codes # 设置格式并抓 10 帧 v4l2-ctl -d /dev/video0 \ --set-fmt-video=width=1920,height=1080,pixelformat=RG10 \ --stream-mmap=4 --stream-count=10 --stream-to=frames.raw # 查看帧率 v4l2-ctl -d /dev/video0 --get-parm逻辑说明:--list-subdev-mbus-codes看 sensor 支持的 Bayer 格式,常见RG10、BG10。--set-fmt-video的pixelformat要和 ISP 输入匹配,写错会出绿屏。--stream-count=10抓 10 帧存成 raw,可以用raw2rgb或 Python 转成图片看 Bayer 顺序。如果抓不到帧,先看dmesg里 CSI 报错,再查 lane 数和 link frequency。
4. 避坑与排查:JX-F23 调试中最容易翻车的 5 个点
4.1 现象:I2C 能读到 ID,但 v4l2 抓流超时
原因:MCLK 没给或频率不对,或者 CSI lane 配置和硬件不一致。解决:用示波器量 MCLK 引脚,确认 24MHz 或 27MHz 存在;检查设备树># 假设 sensor 在 i2c-3,地址 0x36,测试图案寄存器 0x3e00 i2cset -y 3 0x36 0x3e 0x00 0x01 w # 抓一帧看是否有图案 v4l2-ctl -d /dev/video0 --stream-mmap=4 --stream-count=1 --stream-to=test.raw
逻辑说明:i2cset的w表示 16 位寄存器地址。测试图案能出,说明 MIPI 和 ISP 没问题,问题在曝光或镜头。出不了,说明链路还有问题。
5.2 寄存器 dump 对比法
我一般会在出图正常和异常时各 dump 一次寄存器,用i2cdump或驱动里加 debug 打印,然后 diff。常见差异在 0x3e 页的 PLL 配置、0x01 页的曝光和增益。如果 PLL 没锁,出图会黑或花。PLL 配置和 MCLK 频率相关,换晶振就要重算。
# dump 0x00 页 256 字节 i2cdump -y 3 0x36 0x00 # dump 0x3e 页 i2cdump -y 3 0x36 0x3e参数说明:-y跳过交互确认,0x00是页地址。dump 出来和正常板子对比,能快速定位是配置问题还是硬件问题。
5.3 一个我常犯的错
早期调 JX-F23 时,我总以为 probe 成功就万事大吉,结果卡在出图三天。后来养成习惯:probe 成功后先读 ID,再读几帧 raw,用 Python 转 RGB 看颜色。这个习惯帮我省了很多后悔药。另外,设备树里的 GPIO 极性一定要和原理图对照,不要凭感觉写。希望帮到你。
本文还有配套的精品资源,点击获取