You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

400 lines
17 KiB

\chapter{硬件接口}
\section{网络}
系统里有两个网口,一个是从 SOC 直出的,一个从 PCIE 接 RTL81111芯片出来的网口。他们的IP地址配置文件是 /etc/network/interfaces.d 下的
eth0 和 eth1。其对应关系如下表所示:
\begin{table}[H]
\centering
\begin{tabular}{ccc}
\toprule
网络接口 & 驱动 & 默认地址 \\
\midrule
\texttt{eth0} & \texttt{\small st\_gmac} \tablefootnote{用命令 \tikz[baseline=(cmd.base)]\node [fill=black!8,font=\scriptsize\ttfamily] (cmd){ethtool -i eth0 | grep driver};查看。} & \texttt{\small 192.168.1.80} \\
\texttt{eth1} & \texttt{\small r8168} & \texttt{\small 192.168.2.80} \\
\bottomrule
\end{tabular}
\caption{网口对应关系}
\end{table}
网口的 MAC 地址参数会从 uboot 的环境变量中获取。但是 eth1 是从 pcie 出来的,没有 dts 设备节点,它的 MAC 地址需要
处理。具体的方法请参看 {\tt /etc/network/interface.d/eth1} 文件中的 pre-up 后的 script 文件。
\subsection{设备树节点}
\begin{figure}[H]
\centering
\begin{tikzpicture}
\node [anchor=south west, inner sep=0] (image) at (0,0) {
\begin{tcolorbox}[colframe=gray!20]
\begin{footnotesize}
\begin{Verbatim}
&gmac0 {
/* Use rgmii-rxid mode to disable rx delay inside Soc */
phy-mode = "rgmii-rxid";
clock_in_out = "output";
snps,reset-gpio = <&gpio4 RK_PB6 GPIO_ACTIVE_LOW>;
snps,reset-active-low;
/* Reset time is 20ms, 100ms for rtl8211f */
snps,reset-delays-us = <0 20000 100000>;
pinctrl-names = "default";
pinctrl-0 = <&gmac0_miim
&gmac0_tx_bus2
&gmac0_rx_bus2
&gmac0_rgmii_clk
&gmac0_rgmii_bus
>;
tx_delay = <0x43>;
/* rx_delay = <0x3f>; */
phy-handle = <&rgmii_phy>;
status = "okay";
};
\end{Verbatim}
\end{footnotesize}
\end{tcolorbox}
};
\begin{scope}[
x={($0.1*(image.south east)$)},
y={($0.1*(image.north west)$)}
]
% grid for debugging
%\draw [lightgray, step=1] (image.south west) grid (image.north east);
%\foreach \x in {0, 1, ..., 10} {\node [below] at (\x, 0) {\x};}
%\foreach \y in {0, 1, ..., 10} {\node [left] at (0, \y) {\y};}
\draw [red,thick, rounded corners] (0.9, 7.0) rectangle (9.0, 8.0);
\end{scope}
\end{tikzpicture}
\caption{gmac0 节点}
\end{figure}
注意 \textcolor{blue!70}{\tt snps,reset-gpio} 这个 gpio,它是连接到 PHY 芯片的复位管脚上的,特别需要对照原理图检查一下。另外,如果在一些环境下不稳定的话
可以尝试调整这里的 \textcolor{blue!70}{\tt tx\_delay}\textcolor{blue!70}{\tt rx\_delay}。 delay 的调整一般还需要改 phy-mode 这个参数:
\begin{table}[H]
\centering
\begin{tabular}{ll}
\toprule
phy-mode & 含义 \\
\midrule
rgmii & tx,tx 都不调整 \\
rgmii-id & tx, rx 都调整 \\
rgmii-txid & 只调整 tx delay \\
rgmii-rxid & 只调整 rx delay \\
\bottomrule
\end{tabular}
\caption{phy-mode 参数}
\end{table}
\subsection{PHY 寄存器读写调试}
驱动提供了读写寄存器的接口,
路径: /sys/bus/mdio\_bus/devices/stmmac-0:01,其中 stmmac-0:01 表示 gmac0 的 PHY 地址是 1。
\subsubsection{读寄存器}
\begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{bash}
cat /sys/bus/mdio_bus/devices/stmmac-1\:01/phy_registers
\end{minted}
\subsubsection{写寄存器}
例如, 往 reg0 写入 0x8100:
\begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{bash}
echo 00 0x8100 > /sys/bus/mdio_bus/devices/stmmac-1\:01/phy_registers
\end{minted}
\subsection{输出25M时钟}
对 gmac0:
\begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{bash}
&gmac0 {
/* Use rgmii-rxid mode to disable rx delay inside Soc */
phy-mode = "rgmii-rxid";
clock_in_out = "output";
snps,reset-gpio = <&gpio4 RK_PB3 GPIO_ACTIVE_LOW>;
snps,reset-active-low;
/* Reset time is 20ms, 100ms for rtl8211f */
snps,reset-delays-us = <0 20000 100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac0_miim
+ &gmac0_tx_bus2
+ &gmac0_rx_bus2
+ &gmac0_rgmii_clk
+ &gmac0_rgmii_bus
+ &eth0_pins>;
tx_delay = <0x45>;
/* rx_delay = <0x43>; */
phy-handle = <&rgmii_phy>;
status = "okay";
};
&mdio0 {
rgmii_phy: phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <0x1>;
+ clocks = <&cru REFCLKO25M_ETH0_OUT>;
};
};
\end{minted}
对 gmac1:
\begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{bash}
&gmac1 {
/* Use rgmii-rxid mode to disable rx delay inside Soc */
phy-mode = "rgmii-rxid";
+ clock_in_out = "output";
snps,reset-gpio = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>;
snps,reset-active-low;
/* Reset time is 20ms, 100ms for rtl8211f */
snps,reset-delays-us = <0 20000 100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac1_miim
+ &gmac1_tx_bus2
+ &gmac1_rx_bus2
+ &gmac1_rgmii_clk
+ &gmac1_rgmii_bus
+ &eth1_pins>; tx_delay = <0x45>;
/* rx_delay = <0x43>; */
phy-handle = <&rgmii_phy>;
status = "okay";
};
&mdio1 {
rgmii_phy: phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <0x1>;
+ clocks = <&cru REFCLKO25M_ETH0_OUT>;
};
};
\end{minted}
\subsection{RGMII 延时扫描}
通过 /sys/devices/platform/fe1b0000.ethernet 和 /sys/devices/platform/fe1c0000.ethernet 节点下的 phy\_lb\_scan 来扫描延时值。
扫描前需要拔掉网线。
通过 \verb+phy_lb_scan+ 节点扫描到一个窗口,会得到一个中间坐标,需要使用千兆速度 1000 来扫描:
\begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{bash}
echo 1000 > phy_lb_scan
\end{minted}
把扫描的结果配置到 dts 的 gmac0 或 gmac1 节点下 (tx-delay 和 rx-delay)。
\section{Camera}
RK3588 camera 资源硬件如下所示,拥有 2 路 DCPHY, 2 路 DPHY, 一路 DVP, 6 路 CSI HOST, 一个 vicap 控制器, 2个isp控制器。其中 2 路 DPHY 可以分解成 4x2lane 的模式工作,如下图所示:
% convert PDF to EPS
% gswin64c -sDEVICE=eps2write -dEPSCrop -o camera01.eps camera01.drawio.pdf
\begin{figure}[H]
\centering
\begin{tikzpicture}
\node [draw=none, inner sep=12pt]{\includegraphics[width=0.9\textwidth]{camera01.drawio.pdf}};
\end{tikzpicture}
\caption{Camera 模块架构}
\end{figure}
\subsection{Camera 概述}
\subsubsection{MIPI-CSI 资源}
RK3588 MIPI-CSI 资源如下:
\begin{table}[H]
\centering
\begin{tabular}{lllll}
\toprule
& Type & bandwidth & NUM & Mode \\
\midrule
{\scriptsize DPHY} & {\scriptsize DPHY-v1.2 } & {\scriptsize 2.5Gbps x 4 lanes } & {\scriptsize 2} & {\scriptsize 4lane or 2lane+2lane} \\
{\scriptsize DCPHY} & {\scriptsize DPHY-v2.0 } & {\scriptsize DPHY-v2.0: 2.5Gbps x 4lanes } & {\scriptsize 2} & {\scriptsize 4lane} \\
& {\scriptsize CSI-HOST } & \makecell[l]{{\scriptsize MIPI D-PHY v1.2}\\{\scriptsize D-PHY v2.0}\\{\scriptsize C-PHY v1.1}} & {\scriptsize 6} & \\
\bottomrule
\end{tabular}
\end{table}
RK3588有2个4lane的DPHY,2个4lane的DCPHY,其中DPHY可以拆分模式按照4个2lane进行工作,有6个CSI-HOST工作,总计可以接入6路MIPI camera。2lane最大带宽是5G,分辨率可以达到8M@30帧,4lane最大带宽达到10G。
\subsubsection{VICAP 资源}
RK3588 VICAP支持输入输出规格:
\begin{table}[H]
\centering
\small
\begin{tabular}{llm{6cm}m{3cm}}
\toprule
接口 & 数量 & 输入 & 输出 \\
\midrule
{\scriptsize VICAP} & {\scriptsize 1} & { \scriptsize BT601 YCbCr 422 8bit
{\scriptsize RAW8/10/12BT656 YCbCr 422 8bit 逐行/隔行}
{\scriptsize BT1120 YCbCr 422 16bit 逐行/隔行,单/双边沿采样}
{\scriptsize 2/4 通道交错 BT656/BT1120 YCbCr 422 8/16bit 逐行/隔行}
{\scriptsize MIPI CSI 4路IDs虚拟通道}
{\scriptsize MIPI CSI RAW8/10/12/14, YUV422} } & {\scriptsize NV16/NV12/YUV400/YUYV 紧凑/非紧凑 RAW} \\
\bottomrule
\end{tabular}
\end{table}
\subsubsection{ISP 资源}
RK3588 的ISP属于RK ISP v3.0版本,拥有2个ISP。
\begin{table}[H]
\centering
\small
\begin{tabular}{lccl}
\toprule
工作模式 & 吞吐率 & 最大分辨率 & 输入格式 \\
\midrule
{\scriptsize 单ISP 单CSI} &{\scriptsize 16M@30fps }& {\scriptsize 4672x3504 } & {\scriptsize VICAP: raw8/raw10/raw12} \\
{\scriptsize 单ISP 2CSI } &{\scriptsize 8M@30FPS }& {\scriptsize 3840x2160/3264x2448 } & {\scriptsize VICAP: raw8/raw10/raw12} \\
{\scriptsize 单ISP 4CSI } &{\scriptsize 4M@30FPS }& {\scriptsize 2560x1536 } & {\scriptsize VICAP: raw8/raw10/raw12} \\
\multirow{2}{*}{\scriptsize 双ISP 2合1单CSI} & {\scriptsize 32M@30fps} & \multirow{2}{*}{\scriptsize 8064x6048 } & \multirow{2}{*}{\scriptsize VICAP: raw8/raw10/raw12} \\
& {\scriptsize 48M@15fps} & & \\
\bottomrule
\end{tabular}
\end{table}
\subsubsection{最多支持的 Camera}
RK3588最多支持7路正常的CSI摄像头。
\begin{table}[H]
\centering
\begin{tabular}{lll}
\toprule
MIPI-CSI & DVP接口 & 支持Camera数量 \\
\midrule
{\scriptsize 6} & {\scriptsize 1} & \makecell[l]{
{\scriptsize 1x48M@15fps} \\
{\scriptsize 1x32M@30fps} \\
{\scriptsize 2x16M@30FPS} \\
{\scriptsize 4x8M@30FPS} \\
{\scriptsize 7x4M@30FPS}
} \\
\bottomrule
\end{tabular}
\end{table}
RK3588 的 7 路 Camera 连接情况如下图所示:
\begin{figure}[H]
\centering
\begin{tikzpicture}
\node [draw=none, inner sep=0pt]{\includegraphics[width=0.90\textwidth]{camera02.drawio.pdf}};
\end{tikzpicture}
\caption{Camera 模块连接关系}
\end{figure}
根据上述的结构图可以大概看出MIPI和DVP分别是如何连接的,关键点如下:
\begin{enumerate}[(1),nosep]
\item rk3588支持两个dcphy,节点名称分别为csi2\_dcphy0/csi2\_dcphy1。每个dcphy硬件支持RX/TX同时使用,对于camera输入使用的是RX。支持DPHY/CPHY协议复用;需要注意的是同一个dcphy的TX/RX只能同时使用DPHY或同时使用CPHY。
\item rk3588支持2个dphy硬件,这里我们称之为dphy0\_hw/dphy1\_hw,两个dphy硬件都可以工作在full mode 和split mode两种模式下。
\begin{itemize}
\item full mode:节点名称使用csi2\_dphy0 和 csi2\_dphy3,最多支持4 lane。
\item split mode: 拆分成2个phy使用,分别为csi2\_dphy1(使用0/1 lane)、csi2\_dphy2(使用2/3 lane),dphy1\_hw 则拆分成csi2\_dphy4和csi2\_dphy5,每个phy最多支持2 lane。
\item 当dphy0\_hw使用full mode时,链路需要按照csi2\_dphy1这条链路来配置,但是节点名称csi2\_dphy1需要修改为csi2\_dphy0,软件上是通过phy的序号来区分phy使用的模式。dphy1\_hw同理。
\end{itemize}
\item 使用上述 mipi phy节点,需要把对应的物理节点 \\
{csi2\_dcphy0\_hw/csi2\_dcphy1\_hw/csi2\_dphy0\_hw/csi2\_dphy1\_hw} \\
配置上。
\item 每个mipi phy都需要一个csi2模块来解析mipi协议,节点名称分别mipi0\_csi2 \textasciitilde{}mipi5\_csi2。
\item rk3588所有camera数据都需要通过vicap,再链接到isp。rk3588仅支持一个vicap硬件,这个
vicap支持同时输入6路mipi phy,及一路dvp数据,所以我们将vicap分化成rkcif\_mipi\_lvds \textasciitilde{}rkcif\_mipi\_lvds5、rkcif\_dvp等7个节点,各个节点的绑定关系需要严格按照框图的节点序号配置。
\item 每个vicap节点与isp的链接关系,通过对应虚拟出的XXX\_sditf来指明链接关系。
\item rk3588支持2个isp硬件,每个isp设备可虚拟出多个虚拟节点,软件上通过回读的方式,依次从ddr读取每一路的图像数据进isp处理。对于多摄方案,建议将数据流平均分配到两个isp上。
\item 直通与回读模式:
\begin{itemize}
\item 直通:指数据经过vicap采集,直接发送给isp处理,不存储到ddr。需要注意的是hdr直通时,只有短帧是真正的直通,长帧需要存在ddr,isp再从ddr读取。
\item 回读:指数据经过vicap采集到ddr,应用获取到数据后,将buffer地址推送给isp,isp再从ddr获取图像数据。
\item dts配置时,一个isp硬件,如果只配置一个虚拟节点,默认使用直通模式,如果配置了多个虚拟节点默认使用回读模式。
\end{itemize}
\end{enumerate}
\subsubsection{AHD 摄像头}
AHD摄像头可通过转换芯片,转成支持4路虚拟通道的MIPI/BT1120接口到RK3588
最大可以支持到28路1080p30的摄像头。
\begin{table}[H]
\centering
\begin{tabular}{ccl}
\toprule
MIPI-CSI & DVP接口 & 支持Camera数量 \\
\midrule
{\scriptsize 6} & {\scriptsize 1} & {\scriptsize 28(7x4)*1920x1080@30FPS} \\
\bottomrule
\end{tabular}
\end{table}
\subsection{RTP Stream}
从 HDMI 输入的视频数据,在 Linux 系统里从 /dev/videoX 的设备中获取出来。可以用 多媒体框架 gstreamer 来做测试。
用 gstreamer 的 gst-launch-1.0 可以用来控制 video 的视频数据。
这里以 板子上用 gstreamer 提供 rtp 服务,在电脑的 windows 端用 VLC 程序来实现视频的播放为例,展示一下 video 功能。
\begin{enumerate} [(1),nosep]
\item 在板子上启动 rtp 服务:
\begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{bash}
gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! x264enc \
! rtph264pay pt=96 ! udpsink host=192.168.1.27 port=5000
\end{minted}
用 RockChip 的 H264 硬编码,可以用下面命令:
\begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{bash}
gst-launch-1.0 v4l2src device=/dev/video0 ! mpph264enc ! rtph264pay pt=96 \
! udpsink host=192.168.1.27 port=5000
\end{minted}
这里假定电脑的IP地址是:192.168.1.27。这根据实际情况修改。
\item 在电脑上新建一个名为 hdmi.sdp 的 sdp 文件\footnote{ SDP 的完整定义,请查看 rfc4566},内容如下:
\begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{bash}
m=video 5000 RTP/AVP 96
a=rtpmap:96 H264
a=framerate:30
c=IN IP4 192.168.1.27
\end{minted}
这里的 5000 是端口号, 192.168.1.27 是 IP 地址,要与上面命令中的参数保持一致。
\item 在电脑上用 VLC 程序打开 hdmi.sdp 文件:
\begin{figure}[H]
\centering
\includegraphics[width=0.8\textwidth]{vlc}
\caption{VLC 播放 video}
\end{figure}
如果一切正常可以在 vlc 里面看到 HDMI 输入的视频。
\end{enumerate}
\begin{comment}
\begin{minted}[bgcolor=lightgray!30,fontsize=\tiny]{bash}
gst-launch-1.0 v4l2src device=/dev/video0 ! video/x-raw,width=1920,height=1080,framerate=30/1 \
! timeoverlay ! tee name=vsrc vsrc. ! queue ! videoconvert \
! ximagesink vsrc. ! queue ! x264enc tune=zerolatency \
! rtph264pay name=pay0 pt=96
\end{minted}
gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! x264enc ! rtph264pay ! udpsink host=192.168.1.10 port=5000
在 windows 端用 vlc 打开 \verb+rtsp://<目标IP>:8554/test+ 可以拉取视频数据。
\noindent 发送端:
\begin{minted}[bgcolor=lightgray!30,fontsize=\footnotesize]{bash}
gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! x264enc ! rtph264pay ! udpsink host=127.0.0.1 port=5000
\end{minted}
接收端:
\begin{minted}[bgcolor=lightgray!30,fontsize=\footnotesize]{bash}
gst-launch-1.0 -v udpsrc port=5000 ! rtpmp2tdepay ! decodebin ! autovideosink
\end{minted}
\end{comment}
注意这里的操作顺序,最好是打开 vlc, 紧接着运行 gs-launch 命令,否则会出现很久才出视频。
\subsection{ V4L2 调试}
\begin{enumerate} [(1),nosep]
\item 推灰度图像的视频流:
\begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{bash}
gst-launch-1.0 v4l2src device=/dev/video1 ! capsfilter \
caps=video/x-raw,format=GRAY8 ! videoconvert ! mpph264enc \
! rtph264pay config-interval=5 pt=96 ! \
udpsink host=192.168.1.27 port=5000
\end{minted}
\item 将灰度图像显示到屏上:
\begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{bash}
gst-launch-1.0 v4l2src device=/dev/video1 io-mode=dmabuf \
! capsfilter caps=video/x-raw,format=GRAY8 ! videoconvert \
! capsfilter caps=video/x-raw,format=RGB ! kmssink
\end{minted}
\item 用 dmabuf 模式并推流:
\begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{bash}
gst-launch-1.0 v4l2src device=/dev/video0 io-mode=dmabuf ! \
mpph264enc ! rtph264pay config-interval=5 pt=96 ! \
udpsink host=192.168.1.27 port=5000
\end{minted}
\item 将 camera 视频显示在屏上:
\begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{bash}
gst-launch-1.0 v4l2src device=/dev/video0 io-mode=dmabuf ! kmssink \
force-modesetting=true
\end{minted}
\item 抓图:
\begin{minted}[bgcolor=lightgray!30,fontsize=\scriptsize]{bash}
v4l2-ctl -d 0 --stream-mmap --stream-count=1 --stream-to file.yuv
\end{minted}
\end{enumerate}