×

嵌入式日记:破解RPi摄像头以与Zynq FPGA配合使用

消耗积分:2 | 格式:zip | 大小:0.00 MB | 2023-06-27

刘英

分享资料个

描述

动机

FPGA 非常适合低延迟、高吞吐量的成像应用。最好使用直接与 FPGA 接口的相机(而不是 USB/网络相机)来实现这一点。然而,对于业余爱好者、修补匠和小型初创企业来说,可用的相机模块选项数量有限,而且并非所有可用选项都便宜(相对而言)。最重要的是,许多都有自己的物理接口,所以通常你只能将相机与它的开发套件一起使用。没有相当大的努力,就是这样。

然而,由于具有 15 针 FFC 摄像头接口 (MIPI-CSI) 的 Raspberry Pi 等低成本单板计算机的普及,情况正在好转。随着时间的推移,RPi 相机接口变得非常流行,如今许多单板计算机都可以使用相同的相机连接器(Jetson 套件、RPi 替代板等)。甚至一些 FPGA 板现在也配备了相同的 15 针连接器(Zybo-Z7、Kria 等)。由于受欢迎程度,现在可以从各种供应商(RPi 基金会、Arducam、VEYE 等)处获得许多低成本图像传感器。

pYYBAGNkdGeAFCb6AACDWzhFxBE228.jpg
树莓派 15 针 MIPI-CSI 摄像头接口
 

不幸的是,一旦我们开始将这些图像传感器之一与我们的 FPGA 一起使用,我们就会遇到一个大问题:大多数图像传感器的数据表都是不公开的!

您会看到,在使用任何现代图像传感器之前,您需要根据您的用例对其进行配置。虽然高吞吐量数据通过 MIPI-CSI 等协议传输,但配置通常通过 I2C 进行。然而,要知道通过 I2C 接口发送什么命令需要知道传感器的寄存器映射,以及这些寄存器的每一位的功能。但如果没有公开的数据表,这是一个大问题。在某些情况下,如果您足够幸运,您将能够在互联网上找到您的特定图像传感器的泄露数据表,但情况并非总是如此。例如,在撰写本文时(2021 年 9 月),RPi“高质量”相机没有公开的数据表。

有时即使有数据表,事情也不会太乐观。现代图像传感器是复杂的硅片,配置大多数图像传感器需要正确设置数百个寄存器,然后才能开始以正确格式输出正确的图像数据。有时钟/PLL 配置、分辨率、binning、曝光、增益、白平衡、输出接口格式等设置。至少获得参考或起点不是很好吗?

所以,我们能做些什么?

“嗅探”或“窃听”是软件/硬件黑客中常用的一种技术。这个想法是监听两个设备之间的通信,而不干扰原始对话,并保持细致的记录以备后用。我们可能不明白对话的每个部分的含义是什么,但有时我们可以重播相同的序列,并设法欺骗目标设备给我们需要的东西。

我的设置

在这种特殊情况下,我有一个我之前购买的Zybo-z7-20板,以及PCAM-5C板相机。使用Digilent 提供的运行“baremetal”的演示项目,我能够非常快速地让两者一起工作。但是,对于未来的项目,我希望有更多的相机选项,而不仅仅是 PCAM-5C。许多与 RPi 接口兼容的传感器都带有自己的 Linux 驱动程序。我希望能够在运行裸机时使用相同的传感器。

我的计划如下:

  • 选择具有匹配物理/电气接口的相机
  • 使用我需要的设置(分辨率、帧率等)让它在它的本机平台(RPi、Jetson 等)上工作
  • 使用逻辑分析仪设置 I2C 嗅探器并记录从处理器到相机的所有命令。
  • 使用我自己的 FPGA 板进行清理、适当格式化和重播命令。

对于这个特定的实验,我将使用我已经拥有的:- Raspberry Pi v2.1 相机- RaspberryPi 4B 作为“本机”平台- Saleae Logic 16 pro 作为我的逻辑分析仪- Zybo-Zy-20 作为我的“目标” FPGA板。

让我们开始吧……!

第 1 步:验证接口兼容性

N. 从电路板的示意图中检查引脚配置和电压电平。

poYBAGNkdGmAdldYAAB6ZhsPGwA942.jpg
Shematics 的 Zybo-Z7 相机连接器配置
 

我们可以看到连接器将为连接的相机提供 3.3V 电压,并且 I2C 也在 3.3V 下工作。

接下来,我们看一下摄像头模块。从 RPi v2.1 摄像头模块的示意图中,我们可以验证引脚配置和电压确实匹配。

poYBAGNkdGyAeKjIAACXiKDSgbQ472.jpg
RPi v2.1 摄像头引脚配置
 

您可能会注意到上拉电压为 1.8V 而不是 3.3V,但这没关系,因为组件 Q1 正在执行电压电平转换。Ctrl+C退出。注意上面使用 gstreamer 管道,这是上述命令正常工作的先决条件。

第 3 步:嗅探 I2C 通信

现在我们有了一个工作系统,下一步是嗅探 RPi 和图像传感器之间的 I2C 通信。首先,我使用烙铁将三根细跳线连接到 FFC 上的接地、SDA、SCL 引脚,然后用 Kapton 胶带覆盖以作为连接线的机械释放。我这样做是因为与在焊接过程中弄乱 RPi 或摄像头板相比,FFC 电缆便宜且易于更换。此外,这给了我一根“间谍电缆”,我也可以将其重新用于其他相机/平台。

poYBAGNkdG6AKJfAAACDgYqcxps690.jpg
间谍跳线焊接到相机 FFC
 

在此之后,我将这些电线与我的逻辑分析仪连接起来。在这一步中,我使用 USB“逻辑分析仪”来嗅探 I2C 通道上的通信。我使用的是 Saleae Logic 16 pro,因为这是我所拥有的,但任何便宜的逻辑分析仪都可以解决这个问题(I2C 的数据速率相当慢)。最后,我为 I2C 解码配置了逻辑分析仪并点击了开始按钮。

pYYBAGNkdHeAAmuPABcdjUwvtIk224.jpg
RPi 4 通过 FFC 连接到 v2 摄像头,同时 Logic Analyzer 窃听 I2C 事务
 

现在我们有一些捕获的数据。

poYBAGNkdHuAdWHjAAHvHVcF63Y109.jpg
逻辑分析仪捕获的 I2C 信号(左)。右侧的解码 I2C 事务。
 

第 4 步:清理和准备 I2C 数据

现在我们有了一些捕获的数据,我们需要清理和准备数据,然后才能将其与 FPGA 板一起使用。由于我遵循的确切过程非常具体到我所拥有的设置,因此我将详细说明每个步骤的意图以供读者理解。

我注意到的第一件事是有一个初始的命令突发(左),然后是另一个密集的命令突发(中),然后经过一段时间的延迟后,每隔约 15 毫秒就会有一个 I2C 命令(右)。

poYBAGNkdH2AMdVBAABhk9Ks9j8909.jpg
I2C 命令日志
 

每 ~15ms 的命令对应于 60fps 帧之间的时间。此外,这些命令被发送到相同的 I2C 地址,并且都是写命令。

pYYBAGNkdIKAYq_4AACX3i604ec556.jpg
每~15ms重复I2C命令序列
 

因此,经过一些实验后,我得出结论,这些必须是从 ISP 到相机的命令,以便在处理每一帧后根据不断变化的照明条件(自动增益/曝光控制,可能还有自动白平衡)进行调整。这也意味着,就目前而言,我可以删除在这些命令的第一个实例之后发送的任何数据数据,因为发送一次曝光命令就足以开始了。另外,请注意这些重复的命令被发送到 I2C 地址 0x10。因此我们可以推断出我们相机的 I2C 地址是 0x10

接下来,我查看了修剪后的数据,注意到开头有一些读命令,还有一些写到 I2C 地址 0x71 的命令。

pYYBAGNkdIWAEOX8AADU3fssgjo573.jpg
 

由于我们不知道如何处理从读取命令返回的数据,因此保留它们没有意义,因此我删除了它们。

寻址到 0x71 的命令很可能用于位于 Rpi V2.1 cam 上的 EEPROM,Raspberry pi 固件使用它来查看是否连接了正版相机,因此我们也不需要保留它们。因此我也删除了它们。

对于转储的数据,我将仅提及一些细分。让我们随机选择一行转储数据:

write to 0x10 ack data: 0x01 0x62 0x0D 0xE8

在这一行中,0x10 是相机的 I2C 地址,0x0162 是寄存器地址,0x0D、0xE8 是数据字节。通常一个寄存器是一个字节长,因此由于大多数传感器中的 I2C 地址自动递增功能,第二个字节实际上会转到下一个寄存器地址 (0x1063)。

无论如何,在此之后,我将剩余的修剪数据复制到 Excel 表中,删除除 I2C 数据之外的所有文本并对其进行格式化(通过一些手动操作),以便稍后在 Xilinx 内部将其用作 C 中的数组开发工具包。其中一部分包括在每行中添加一个包含 I2C 字节数的列,因为转储数据中的不同行发送的 I2C 字节数不同。

第 5 步:使用 FPGA 重放命令

现在,要使用我们的 FPGA 板测试我们的数据,我需要一个 Vivado &SDK 项目。幸运的是,我已经从 Adam Taylor 的优秀帖子中下载了一个 Vivado 项目,它为我提供了一个工作系统,以 720p60 分辨率从 PCAM-5C 相机获取数据并通过 HDMI 输出显示。

接下来,我为此访问了 SDK 项目,并添加了一个包含先前步骤中转储和格式化的 I2C 数据的数组,并将其设置为在启动后发送到 v2 相机 I2C 地址 (0x10)。其余什么都不需要更改,事实上我什至将以前的 PCAM-5C 代码留在了文件中,因为当该地址上没有设备响应时,该地址的命令会被简单地忽略。我还将 Adam 的 vivado 项目配置为使用 CSI 输入(而不是 HDMI IN)作为源。包含所有修改的完整项目链接在帖子末尾。

完成软件修改后,剩下要做的就是将 RPi v2.1 摄像头连接到 Zybo-Z7 上的 MIPI 连接器,将 HDMI 电缆从 HDMI TX 端口连接到显示器,然后上传代码。

pYYBAGNkdI6AOTlEABX6w62z_4s158.jpg
RPi V2.1 摄像头连接到 Zybo-Z7-20
 

poYBAGNkdJWAfar5AAuVQgbfTGY529.jpg
说“茄子”
 

 

pYYBAGNkdJyAJHw9AAYeiBPOWmc316.jpg
 

我愿意称之为成功。这证明这里采用的概念适用于其他可用的传感器(尽管有一些警告),并且应该为我们提供更多 MIPI 图像传感器选项以用于 FPGA 项目。这意味着,如果其中一个传感器是与 FPGA 一起使用,那么我们将需要在 FPGA 中自己处理这些功能。通过在受控的光照条件变化下查看每帧后发送到相机的数据,应该可以找到相关的寄存器。另一方面,一些摄像头模块还带有板载 ISP,在这种情况下,这不是问题。(看看一些来自 Arducam、VEYE 的传感器)

  • 并非所有图像传感器本身都支持 720p 或 1080p 等格式。因此,在某些情况下,驱动程序会将传感器设置为在高度/宽度(或两者)上大于用户通过命令行请求的模式。在这种情况下,Raspberry Pi/Jetson 等内部的 ISP(图像信号处理器)预计会将图像裁剪为用户请求的分辨率。这意味着如果我们使用 FPGA 来接收这个流,那么我们需要在 FPGA 内部进行裁剪。通过在水平和垂直方向上为图像开始位置、活动像素和步幅设置适当的值,Xilinx VDMA 可轻松用于执行此裁剪,而无需任何处理开销。

 

希望你喜欢阅读和跟随。下次我们可能会尝试不同的 MIPI 传感器(RPi HQ 相机?),看看效果如何。

如果您发现这有用(或没有),请在下面的评论部分分享您的评论/想法!


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !