总结
Rk3566的emmc接口最高支持hs200 (200MHz SDR)
HPS SD/eMMC Timing Characteristics
可以看到, DataStrobe是一个 emmc颗粒向rk3566主控发送的信号,而且只有在hs400模式下启用. 因此rk3566的datastrobe没有任何作用可以不接.
全員が等しく 不幸の世界を見せてやる!
Rk3566的emmc接口最高支持hs200 (200MHz SDR)
HPS SD/eMMC Timing Characteristics
可以看到, DataStrobe是一个 emmc颗粒向rk3566主控发送的信号,而且只有在hs400模式下启用. 因此rk3566的datastrobe没有任何作用可以不接.
设备:rk3566
emmc:8GB/32GB Sandisk emmc
Host: Ubuntu22.04(24.04's qemu has problem when creating ubuntu base rootfs, so skip it)
参考: 【每周学习摘要06(23/10/27-23/11/10)】
Image
, ko
and dtb
files,TBD
boot.img包含kernel以及设备树等,以及uboot保存的env(saveenv)
预留63M
空间足以(未压缩的Image最大50MiB), 如果要更大,请修改parameter.txt
以防止烧录时干涉rootfs分区
touch boot.img
dd if=/dev/zero of=boot.img bs=1M count=63
sync
mkfs.fat boot.img
sync
sudo mount boot.img /mnt
sudo cp -a -r boot/* /mnt
sync
sudo umount /mnt
地址:https://cdimage.ubuntu.com/ubuntu-base/releases/jammy/release/
wget https://cdimage.ubuntu.com/ubuntu-base/releases/jammy/release/ubuntu-base-22.04.5-base-arm64.tar.gz
mkdir rootfs && tar --same-owner -xf ubuntu-base-22.04.5-base-arm64.tar.gz -C rootfs
Note you shall
添加dns解析
echo nameserver 114.114.114.114 > rootfs/etc/resolv.conf
以及apt源(vim rootfs/etc/apt/source.list
)
deb [trusted=yes] http://mirrors.aliyun.com/ubuntu-ports/ jammy main restricted
deb [trusted=yes] http://mirrors.aliyun.com/ubuntu-ports/ jammy-updates main restricted
deb [trusted=yes] http://mirrors.aliyun.com/ubuntu-ports/ jammy universe
deb [trusted=yes] http://mirrors.aliyun.com/ubuntu-ports/ jammy-updates universe
deb [trusted=yes] http://mirrors.aliyun.com/ubuntu-ports/ jammy multiverse
deb [trusted=yes] http://mirrors.aliyun.com/ubuntu-ports/ jammy-updates multiverse
deb [trusted=yes] http://mirrors.aliyun.com/ubuntu-ports/ jammy-backports main restricted universe multiverse
deb [trusted=yes] http://mirrors.aliyun.com/ubuntu-ports/ jammy-security main restricted
deb [trusted=yes] http://mirrors.aliyun.com/ubuntu-ports/ jammy-security universe
deb [trusted=yes] http://mirrors.aliyun.com/ubuntu-ports/ jammy-security multiverse
进入环境后更新apt 源并且下载必要包
sudo chroot rootfs
apt update
apt upgrade
apt install vim sudo kmod net-tools ethtool ifupdown language-pack-en-base rsyslog htop iputils-ping udev systemd network-manager -y
change passwd for root
passwd root
create user meta
adduser meta
add meta to sudoers
chmod +w /etc/sudoers
vim /etc/sudoers
on line 44
# User privilege specification
root ALL=(ALL:ALL) ALL
meta ALL=(ALL:ALL) ALL
Finally pack it
return to the father of rootfs
directory.
Create a rootfs.img
buffer with 1G size
shrink its size by e2fsck
and resize2fs
touch rootfs.img
dd if=/dev/zero of=rootfs.img bs=1M count=900
sync
mkfs.ext4 rootfs.img
sudo mount rootfs.img /mnt
sudo cp -a -r rootfs/* /mnt
sync
sudo umount /mnt
e2fsck -f -p rootfs.img
resize2fs -M rootfs.img
You can adjust count in the second command by check fs usage by mounting it to /mnt
and then check df -h
. To achieve a smaller image size, better make the Available space to be less than 50M.
example:
➜ my-emmc-image df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 6.3G 2.2M 6.3G 1% /run
/dev/nvme1n1p3 60G 31G 27G 54% /
tmpfs 32G 148M 32G 1% /dev/shm
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
efivarfs 268K 144K 120K 55% /sys/firmware/efi/efivars
/dev/nvme0n1p1 256M 49M 208M 19% /boot/efi
tmpfs 6.3G 64K 6.3G 1% /run/user/1000
/dev/nvme0n1p5 480G 405G 51G 89% /media/ztn/4ca5df7c-065c-4b2b-b868-bab13a2816b0
/dev/loop10 868M 783M 24M 98% /mnt
TBD, both kernel and user space
TBD, only mali so libs
if you want to accesss net after connecting to ZJUWLAN but lacks of a webbrowser to authenticate, you can use
https://github.com/Mythologyli/zju-web-login
First install python3
apt install python3
then follow https://pip.pypa.io/en/stable/installation/ to install pip
By using host's system's wget, we can get rid of downloading wget
and its dependency.
su meta
cd ~
wget https://bootstrap.pypa.io/get-pip.py
python3 get-pip.py
In order to shrink the rootfs size, don't install git
but rather clone by downloading.
Again, by using host's system's wget, to avoid downloading wget and its dependency. Then unzip it.
wget https://github.com/Mythologyli/zju-web-login/archive/refs/heads/master.zip
unzip master.zip
cd master
pip3 install -r requirements.txt
after adding, use command sudo depmod -a
to build a tree where you can call modprobe to find your module.
Line5:
# swap to uart2 by tz61 25/02/14
console=ttyS2,115200
Line112
; swap to uart2 debug by tz61. 25/02/14
[uart_para]
uart_debug_port = 2
;uart_debug_tx = port:PF02<3><1><default><default>
;uart_debug_rx = port:PF04<3><1><default><default>
uart_debug_tx = port:PB00<2><1><default><default>
uart_debug_rx = port:PB01<2><1><default><default>
[force_uart_para]
force_uart_port = 2
;force_uart_tx = port:PF02<3><1><default><default>
;force_uart_rx = port:PF04<3><1><default><default>
force_uart_tx = port:PB00<2><1><default><default>
force_uart_rx = port:PB01<2><1><default><default>
目录:drivers/staging/fbtft
其中文件分为核心驱动与面板驱动
fbtft-core.c
, fbtft-bus.c
, fbtft-sysfs.c
, fbtft-io.c
, fbtft.h
fb_st7789v.c
write_reg -> fbtftops.write_register
fbtftops.write_register -> fbtft_write_reg8_bus8 -> fbtft_write_buf_dc -> fbtftops.write
fbtft_update_display -> fbtftops.write_vmem -> fbtft_write_vmem16_bus8 -> fbtftops.write
reg,value对本质上就是两个u8参数.
用于覆盖默认的ops
这个是更新整个屏幕的核心函数,首先调用特定的display驱动的set_addr_win,来指定行列起始(x start/end; y start/end)
在设置完起始后write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
来直接写入屏幕的VRAM
流程图如下(MIPI_DCS_WRITE_MEMORY_START)(0x2C)(RAMWR)
deferred_io 每次调用会回调fbtftops.update_display
来更新屏幕. deferred_io 是整个驱动的上层接口
见https://docs.kernel.org/fb/deferred_io.html
TBD
TBD
在fbtft.h
有一个FBTFT_REGISTER_DRIVER
宏,在每个display驱动里面调用这个.
进入文件夹talowe-t113-linux-sdk
然后运行./build.sh
在运行过一遍./build.sh
后,将我编译的Mplayer1.5
,以及测试视频
,Qt5.12.6
等等覆盖到默认的Buildroot下面,这样省得再重复上述操作重新编译一遍了.具体编译Qt和Mplayer的方法见后面
tar -xzf ~/target.tar.gz -C /home/talowe/talowe-t113-linux-sdk/out/t113/evb1_auto/longan/buildroot
运行完成后重新运行
./build.sh rootfs
./build.sh pack
在out/pack
下面就能看到打包好的img文件
打开PheonixSuit,选择要烧录的img,然后usb连接开发板,先安卓emmc按钮,然后再按rst按钮(然后马上松开),然后观察PheonixSuit软件,如果看到左下角红色字显示Begin XXXX
则立刻松开emmc按钮,如果不松开则烧录不了emmc(原理是这个按键拉低了emmc 的D2脚)
烧录完成后T113s3会自动重启加载固件
此时使用MobaXterm
打开串口,串口连接至板子的UART3(杜邦线3Pin处)就能看到内核启动日志及其他信息,或者使用adb shell
命令进入终端
见SDK/evb1_auto/.BoardConfig.mk
可知
export DTS_NAME=talowe-t113-s3
export UBOOT_DTS_NAME=talowe-t113-s3-uboot
用的是kernel/arch/arm/boot/dts/talowe-t113-s3.dts
kernel的defconfig请见SDK根目录下的.buildconfig
可见
export LICHEE_KERN_DEFCONF_ABSOLUTE=/home/talowe/talowe-t113-linux-sdk/kernel/linux-5.4/arch/arm/configs/sun8iw20p1smp_t113_auto_defconfig
直接修改kernel下面的dts还有defconfig,不需要删除out下面的任何东西然后重新./build.sh
然后./build.sh pack
然后用Phoenix Suit烧录就行
记得更新rootfs里面的modules,具体在pack前面运行./build.sh rootfs
fex是t113_auto下面的sys_config.fex
删除out
下面的pack_out
然后重新按照 ./build.sh kernel
, ./build.sh rootfs
, ./build.sh pack
的顺序打包或者直接删除out
重新·./build.sh
(如果你不想保留buildroot rootfs里面放的东西)
./configure --cc=arm-linux-gnueabi-gcc --enable-cross-compile --strip=arm-linux-gnueabi-strip --target=arm-linux --enable-alsa --enable-fbdev --prefix=/home/talowe/talowe-t113-linux-sdk/out/t113/evb1_auto/longan/buildroot/target/usr --extra-ldflags=--sysroot=/home/talowe/talowe-t113-linux-sdk/out/t113/evb1_auto/longan/buildroot/host/arm-buildroot-linux-gnueabi/sysroot --extra-cflags=-I/home/talowe/talowe-t113-linux-sdk/out/t113/evb1_auto/longan/buildroot/host/arm-buildroot-linux-gnueabi/sysroot/usr/include
1.下载源码
2.编译脚本
export PATH="$PATH:"
mk.sh(不需要prefix,默认安装到sysroot/usr/local/Qt5.12.6
):
#!/bin/sh
export PATH="$PATH:/home/talowe/talowe-t113-linux-sdk/out/gcc-linaro-5.3.1-2016.05-x86_64_arm-linux-gnueabi/bin"
./configure \
-release \
-opensource \
-shared \
-xplatform linux-arm-gnueabi-g++ \
-optimized-qmake \
-pch \
-qt-sqlite \
-qt-libjpeg \
-qt-libpng \
-qt-zlib \
-no-opengl \
-skip qt3d \
-skip qtcanvas3d \
-skip qtpurchasing \
-skip qtlocation \
-skip qttools \
-no-sse2 \
-no-openssl \
-no-cups \
-no-glib \
-no-dbus \
-no-xcb \
-no-iconv \
-no-separate-debug-info \
-no-fontconfig \
-tslib \
-I /home/talowe/talowe-t113-linux-sdk/out/t113/evb1_auto/longan/buildroot/host/arm-buildroot-linux-gnueabi/sysroot/usr/include \
-L /home/talowe/talowe-t113-linux-sdk/out/t113/evb1_auto/longan/buildroot/host/arm-buildroot-linux-gnueabi/sysroot/usr/lib \
-sysroot /home/talowe/talowe-t113-linux-sdk/out/t113/evb1_auto/longan/buildroot/host/arm-buildroot-linux-gnueabi/sysroot \
-recheck-all \
-make examples
记得把sysroot里面的/usr/include/vulkan
文件夹重命名成别的否则会编译一坨vulkan的玩意然后卡报错
编译完成后把sysroot/usr/local/Qt*
拷贝到target/usr/local
运行Qt程序前设置环境变量(fb0/fb1):
export QT_PLUGIN_PATH=/usr/local/Qt-5.12.6/plugins
export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0
export LD_LIBRARY_PATH=/usr/local/Qt-5.12.6/lib
驱动:尚未合并主线
input: add driver for Hynitron CST816X touchscreen
export QT_QPA_GENERIC_PLUGINS=tslib:/dev/input/event5
此处event5和event6为屏幕驱动事件.
更多参数:How to configure Qt to use tslib instead of evdev?
mkdir /usr/local/Qt-5.12.6/lib/fonts
把dejavu的所有ttf文件放到该目录下.
参考 linux下如何利用QtCreator编译ARM版本的Qt程序
mplayer -vo fbdev2:/dev/fb1 -ao alsa:device=hw=1.0 -fps 30 maimai240.mp4
mplayer -vo fbdev2:/dev/fb0 -vf scale=360:212 -geometry 0:77 -ao alsa:device=hw=1.0 -fps 30 ba_360x212_30fps.mp4
首先设定要测试的input设备.
export TSLIB_TSDEVICE=/dev/input/event5
然后
ts_print
这个屏幕貌似没有压力检测,所以tslib的pthres没有作用,要么上报0要么上报255(可以通过运行ts_print
观察第三个参数)所以这个在屏幕上点击按钮需要长一点时间
参考How to turn USB-connected device on and off in linux?
也许有用,没试过,多数情况是kernel module和rootfs没更新导致驱动没加载
mplayer -vo fbdev2:/dev/fb1 -ao alsa:device=hw=1.0 maimai240.mp4
使用arecord
,声卡是hw0, 由于只有单声道所以-c1
arecord -d 10 -f S16_LE -c1 -r44100 -t wav -D "hw:0,0" test.wav
vim /etc/wpa_supplicant.con
输入密码和SSID
然后
wpa_supplicant -i wlan0 -B -c /etc/wpa_supplicant.conf
最后观察ip
ip addr
插网线到电脑(或者路由器都可以,我直接直连PC,PC当NAT)
参考用Windows通过网线共享网络给其他电脑(Windows、Ubuntu)
连接
adb connect 192.168.137.35:55555
下载完apk后安装launcher3
adb install launcher3.apk
启动设置(可以把桌面设成launcher3),在触摸屏里面手动设置
adb shell monkey -p com.android.settings -c android.intent.category.LAUNCHER 1
启动Launcher3的activity
adb shell am start -n com.android.launcher3/com.android.launcher3.Launcher
然后就ok了
MyGesture - 全面屏手势/导航手势操作扩展
根据提示设置权限,然后在设置的无障碍里面开启这个服务.
以下所有的操作基于``
kernel下面生成的boot.img
是RKIMG
(RKIMG is a format customized by Rockchip from Android boot image)的镜像,因为u-boot里面用的命令是android_boot
(之前不知道这个东西是用安卓启动的方式启动linux内核的,误解成是bootrkp)
然后FIT镜像是uboot.itb
,在uboot目录下的fit
,可以用dumpimage -l uboot.itb
查看.
TSPI的原厂固件boot.img
,recovery.img
也是一个FIT镜像
所以镜像分两种,一个是uboot FIT
一个是android
镜像
分区信息可以在执行完./make.sh orangepi-3b-rk3566
后看见fit/u-boot.its
/*
* Copyright (C) 2020 Rockchip Electronic Co.,Ltd
*
* Simple U-boot fit source file containing ATF/OP-TEE/U-Boot/dtb/MCU
*/
/dts-v1/;
/ {
description = "FIT Image with ATF/OP-TEE/U-Boot/MCU";
#address-cells = <1>;
images {
uboot {
description = "U-Boot";
data = /incbin/("u-boot-nodtb.bin");
type = "standalone";
arch = "arm64";
os = "U-Boot";
compression = "none";
load = <0x00a00000>;
hash {
algo = "sha256";
};
};
atf-1 {
description = "ARM Trusted Firmware";
data = /incbin/("./bl31_0x00040000.bin");
type = "firmware";
arch = "arm64";
os = "arm-trusted-firmware";
compression = "none";
load = <0x00040000>;
hash {
algo = "sha256";
};
};
atf-2 {
description = "ARM Trusted Firmware";
data = /incbin/("./bl31_0xfdcc1000.bin");
type = "firmware";
arch = "arm64";
os = "arm-trusted-firmware";
compression = "none";
load = <0xfdcc1000>;
hash {
algo = "sha256";
};
};
atf-3 {
description = "ARM Trusted Firmware";
data = /incbin/("./bl31_0x0006b000.bin");
type = "firmware";
arch = "arm64";
os = "arm-trusted-firmware";
compression = "none";
load = <0x0006b000>;
hash {
algo = "sha256";
};
};
atf-4 {
description = "ARM Trusted Firmware";
data = /incbin/("./bl31_0xfdcd0000.bin");
type = "firmware";
arch = "arm64";
os = "arm-trusted-firmware";
compression = "none";
load = <0xfdcd0000>;
hash {
algo = "sha256";
};
};
atf-5 {
description = "ARM Trusted Firmware";
data = /incbin/("./bl31_0xfdcce000.bin");
type = "firmware";
arch = "arm64";
os = "arm-trusted-firmware";
compression = "none";
load = <0xfdcce000>;
hash {
algo = "sha256";
};
};
atf-6 {
description = "ARM Trusted Firmware";
data = /incbin/("./bl31_0x00069000.bin");
type = "firmware";
arch = "arm64";
os = "arm-trusted-firmware";
compression = "none";
load = <0x00069000>;
hash {
algo = "sha256";
};
};
fdt {
description = "U-Boot dtb";
data = /incbin/("./u-boot.dtb");
type = "flat_dt";
arch = "arm64";
compression = "none";
hash {
algo = "sha256";
};
};
};
configurations {
default = "conf";
conf {
description = "rk3566-orangepi-3b";
rollback-index = <0x0>;
firmware = "atf-1";
loadables = "uboot", "atf-2", "atf-3", "atf-4", "atf-5", "atf-6";
fdt = "fdt";
signature {
algo = "sha256,rsa2048";
key-name-hint = "dev";
sign-images = "fdt", "firmware", "loadables";
};
};
};
};
在u-boot下面进行
./make.sh --idblock
shell源码:
function pack_idblock()
{
INI=${INI_LOADER}
if [ ! -f ${INI} ]; then
echo "ERROR: No ${INI}"
exit 1
fi
# chip
COMMON_H=`grep "_common.h:" include/autoconf.mk.dep | awk -F "/" '{ printf $3 }'`
PLAT=${COMMON_H%_*}
# file
SPL_BIN=${RKBIN}/`filt_val "FlashBoot" ${INI}`
TPL_BIN=${RKBIN}/`filt_val "FlashData" ${INI}`
if [ ! -z "${ARG_SPL_BIN}" ]; then
SPL_BIN=${ARG_SPL_BIN}
fi
if [ ! -z "${ARG_TPL_BIN}" ]; then
TPL_BIN=${ARG_TPL_BIN}
fi
# pack
rm idblock.bin -f
./tools/mkimage -n ${PLAT} -T rksd -d ${TPL_BIN}:${SPL_BIN} idblock.bin
echo "Input:"
echo " ${INI}"
echo " ${TPL_BIN}"
echo " ${SPL_BIN}"
echo
echo "Pack ${PLAT} idblock.bin okay!"
echo
}
运行后终端提示:
(py2) ➜ u-boot-orangepi git:(v2017.09-rk3588) ./make.sh --idblock
Image Type: Rockchip RK35 boot image
Init Data Size: 55296 bytes
Boot Data Size: 241664 bytes
Input:
/home/ztn/Embedded/RK/rkbin/RKBOOT/RK3566MINIALL.ini
/home/ztn/Embedded/RK/rkbin/bin/rk35/rk3566_ddr_1056MHz_v1.18.bin
/home/ztn/Embedded/RK/rkbin/bin/rk35/rk356x_spl_v1.12.bin
Pack rk3568 idblock.bin okay!
./make.sh xxx
时候INI_LOADER如何被选中?看源码make.sh
, 是从当前目录下的.config
中寻找CONFIG_LOADER_INI
function select_ini_file()
{
# default
INI_LOADER=${RKBIN}/RKBOOT/${RKCHIP_LOADER}MINIALL.ini
if [ "${ARM64_TRUSTZONE}" == "y" ]; then
INI_TRUST=${RKBIN}/RKTRUST/${RKCHIP_TRUST}TRUST.ini
else
INI_TRUST=${RKBIN}/RKTRUST/${RKCHIP_TRUST}TOS.ini
fi
# defconfig
NAME=`filt_val "CONFIG_LOADER_INI" .config`
if [ ! -z "${NAME}" ]; then
INI_LOADER=${RKBIN}/RKBOOT/${NAME}
fi
NAME=`filt_val "CONFIG_TRUST_INI" .config`
if [ ! -z "${NAME}" ]; then
INI_TRUST=${RKBIN}/RKTRUST/${NAME}
fi
# args
if [ ! -z "${ARG_INI_TRUST}" ]; then
INI_TRUST=${ARG_INI_TRUST}
fi
if [ ! -z "${ARG_INI_LOADER}" ]; then
INI_LOADER=${ARG_INI_LOADER}
fi
}
rockchip wiki上面是这样从bin 制作img的(img烧录到sd卡中)
tools/mkimage -n rkxxxx -T rksd -d rkxx_ddr_vx.xx.bin idbloader.img
cat rkxx_miniloader_vx.xx.bin >> idbloader.img
但是这样会有问题(提示文件过大)
然后用make.sh
里面的方法:
./tools/mkimage -n ${PLAT} -T rksd -d ${TPL_BIN}:${SPL_BIN} idblock.bin
camera调试:RK3588 MIPI/DVP camera关键配置
基于瑞芯微平台cif接口dvp相机的视频接入(ov2640、rv1126为例)
(BT656)rk3568制冷项目驱动开发流程汇总(只适用于部分模块CIF DVP等,自用)
瑞芯微摄像头移植流程和注意事项
(全志平台,仅供参考)MQ-r T113 ov2640驱动
https://blog.csdn.net/weixin_35723192/category_11824879_3.html
其中注意瑞芯微rk3566/68平台的VICAP(rkcif)和ISP是两个不同的IP核,两个IP核都能进行capture.
其中rk3566的ISP21是lite版本,看描述是不支持HDR
rk3566/3568没有ispp这个东西,只有rv1126/rv1109/rk3588有(可能是因为VI 3.0才有这个)
详见ISP21/Rockchip_Driver_Guide_VI_CN_v1.1.3.pdf
➜ ~ cd /sys/class/gpio
➜ gpio cd gpio144
➜ gpio144 echo 0 > value
➜ gpio144 cd ../145
cd: no such file or directory: ../145
➜ gpio144 echo 0 > value
➜ gpio144 cd../g
➜ gpio144 cd ../gpio145
➜ gpio145 echo 0 > value
➜ gpio145 echo 1 > value
➜ gpio145 cd ../gpio144
➜ gpio144 echo 1 > value
➜ gpio144 devmem2 0xFDC60070 w 0x00FF0011
/dev/mem opened.
Memory mapped at address 0x7fb954d000.
Value at address 0xFDC60070 (0x7fb954d070): 0x0
Written 0xFF0011; readback 0x11
GRF 是 General Register File 的意思,其中有IOMUX的作用.
其中的SYS_GRF
掌管了GPIO的IOMUX工作
我们可以通过devmem2 0xFDC60070 w 0x00FF0011
来改变GPIO4_C bank 的复用,其中一个pin 4bit,高16位是用来做mask的.
比如dts长这样
device {
pinctrl-names = "active", "idle";
pinctrl-0 = <&state_0_node_a>;
pinctrl-1 = <&state_1_node_a>, <&state_1_node_b>;
};
然后active
对应pinctrl-0
.
#define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default"
gc4c33->pins_default = pinctrl_lookup_state(gc4c33->pinctrl, OF_CAMERA_PINCTRL_STATE_DEFAULT);
pinctrl_select_state(gc4c33->pinctrl, gc4c33->pins_default);
当然这里的names可以是任何名字, 然后每个组内可以有多个pins.
对于标有default
的pinstate
, 驱动会默认进行pinctrl_select, 不需要在像i2c这种设备的源码里面手动再mux一遍. source:
The pin control core will automatically claim the default pinctrl state for us when the device is probed. If one defines an init state, the pinctrl core will automatically set pinctrl to this state before the probe() function, and then switch to the default state after probe() (unless the driver explicitly changed states already).
cat /sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pinmux-pins
➜ / cd /sys/kernel/debug/clk/clk_cif_out
➜ clk_cif_out cat clk_enable_count
4
可以看到clock被开启了4次, 位于gc1054.c
的测试代码:
// should enable 4 times
ret = __gc1054_power_on(gc1054);
ret = __gc1054_power_on(gc1054);
ret = __gc1054_power_on(gc1054);
ret = __gc1054_power_on(gc1054);
需要在g_mbus_config
中设置V4L2_MBUS_BT656
, PARALLEL是给BT601用的
找根目录Makefile前几行
可以看到pinmux 还没mux上去.可能mux工作是在rkcif_dvp驱动里面做的,但是i2c摄像头节点没有注册成功?(但是需要开起来).
[ 8.849418] rkcif_dvp: get_remote_sensor: remote pad is null
看了下源码, pinmux在userspace不能通过sysfs改变, 只能查看. 然后根据迅为电子的教程看到改pinmux用到了这个函数:pinctrl_select_state
, 于是查看了driver/media/i2c
下面的调用, 发现改pinmux是在i2c driver里面做的,然后从linux4.19搬过来的gc1054驱动没有调用这个函数.
现在尝试把这个加进powerup函数里面
现在发现之前无法读取ov2640,第一个是因为CLK_CIF_OUT并非开启,然而IOMUX和clock确实都是开过的.后来用电压表量了一下,发现是clk在设备probe失败后自动关闭了,即使我在i2c设备内注释了所有关闭clock的函数.(可能是i2c驱动的上级驱动帮忙关闭的). 当我在开启clock后,关闭probe结束前加入一段很长的delay, 这样示波器能观察到稳定的波形。 delay 代码如下
dev_info(&client->dev, "[debug] ov2640 xvclk start extreme long sleep(5s) - trial 1!");
usleep_range(5 * 1000000, 6 * 1000000); // sleep 10s
dev_info(&client->dev, "[debug] ov2640 xvclk stop extreme long sleep(5s) - trial 1!");
i2c_smbus_write_byte_data(client, BANK_SEL, BANK_SEL_SENS);
pid = i2c_smbus_read_byte_data(client, PID);
ver = i2c_smbus_read_byte_data(client, VER);
midh = i2c_smbus_read_byte_data(client, MIDH);
midl = i2c_smbus_read_byte_data(client, MIDL);
然后发现OV2640的i2c地址(ID地址)是0x30. 然后现在dmesg
信息如下, 看描述是因为ov2640这个驱动是主线的驱动(linux 5.10.160
),并非能在rockchip那套平台(rkcif/rkisp)下面正常工作,因为rkcif(rkcif_dvp)会通过设备树里的endpoint链接,从而获取i2c v4l2subdev的信息,并且通过一些函数进行对应操作。
例如v4l2_subdev_video_ops
里面缺乏.g_frame_interval
, 然后v4l2_subdev_pad_ops
里面缺乏.get_mbus_config
,该函数是rkcif判断该摄像头是否为BT656/BT1120还是BT601,亦或是CSI2等类型,所以必须得有.可能在别的platform下面这个函数并非必须的.
还有一个很严重的误解, 才发现有外同步信号的叫BT.601/PARALLEL, 然后BT656没有外同步(HS,VS), 27MHz 的一般是BT656
[ 5.273685] i2c /dev entries driver
[ 5.276240] fan53555-regulator 0-001c: FAN53555 Option[12] Rev[15] Detected!
[ 5.278280] vdd_cpu: supplied by vcc5v0_sys
[ 5.288395] ov2640 2-0030: [debug] ov2640 xvclk start extreme long sleep(5s) - trial 1!
[ 10.290330] ov2640 2-0030: [debug] ov2640 xvclk stop extreme long sleep(5s) - trial 1!
[ 10.292579] ov2640 2-0030: ov2640 Product ID 26:42 Manufacturer ID 7f:a2
[ 10.292613] ov2640 2-0030: [debug] ov2640 xvclk start extreme long sleep(5s) - trial 2!
[ 15.320326] ov2640 2-0030: [debug] ov2640 xvclk stop extreme long sleep(5s) - trial 2!
[ 15.320357] i2c i2c-2: OV2640 Probed
[ 15.321788] rkcifhw fdfe0000.rkcif: Adding to iommu group 7
[ 15.322363] rkcifhw fdfe0000.rkcif: can't request region for resource [mem 0xfdfe0000-0xfdfe7fff]
[ 15.322494] rkcifhw fdfe0000.rkcif: No reserved memory region assign to CIF
[ 15.322720] rkcif rkcif_dvp: rkcif driver version: v00.02.00
[ 15.322880] rkcif rkcif_dvp: attach to cif hw node
[ 15.322898] rkcif rkcif_dvp: rkcif wait line 0
[ 15.322913] : terminal subdev does not exist
[ 15.322925] : terminal subdev does not exist
[ 15.322935] : terminal subdev does not exist
[ 15.322946] : terminal subdev does not exist
[ 15.324769] ov2640 2-0030: Async registered subdev
[ 15.324792] rkcif_dvp: get mbus config failed for linking
[ 15.324809] rkcif rkcif_dvp: Entity type for entity rkcif-dvp-sof was not initialized!
[ 15.325155] rkcif_dvp: rkcif_update_sensor_info: get terminal ov2640 2-0030 g_frame_interval failed!
[ 15.325182] rkcif_dvp: input mbus_code 0x2006, can't transform to RG10
[ 15.325196] rkcif_dvp: input mbus_code 0x2006, can't transform to RG10
[ 15.325208] rkcif_dvp: input mbus_code 0x2006, can't transform to RG10
[ 15.325220] rkcif_dvp: input mbus_code 0x2006, can't transform to RG10
[ 15.325241] rkcif_dvp: Async subdev notifier completed
[ 15.325264] rkcif_dvp: rkcif_update_sensor_info: get terminal ov2640 2-0030 g_frame_interval failed!
[ 15.325283] rkcif_dvp: There is not terminal subdev, not synchronized with ISP
[ 15.325483] rkcif rkcif_dvp: No memory-region-thunderboot specified
[ 15.327104] rockchip-mipi-csi2-hw fdfb0000.mipi-csi2-hw: enter mipi csi2 hw probe!
[ 15.327343] rockchip-mipi-csi2-hw fdfb0000.mipi-csi2-hw: probe success, v4l2_dev:mipi-csi2-hw!
[ 15.329032] rkisp_hw fdff0000.rkisp: Adding to iommu group 8
[ 15.329287] rkisp_hw fdff0000.rkisp: is_thunderboot: 0
[ 15.329330] rkisp_hw fdff0000.rkisp: can't request region for resource [mem 0xfdff0000-0xfdffffff]
[ 15.329370] rkisp_hw fdff0000.rkisp: max input:0x0@0fps
[ 15.329601] rkisp_hw fdff0000.rkisp: no find phandle sram
[ 15.330220] rkisp rkisp-vir0: rkisp driver version: v02.03.00
[ 15.330429] rkisp rkisp-vir0: No memory-region-thunderboot specified
[ 15.330706] rkisp rkisp-vir0: Entity type for entity rkisp-isp-subdev was not initialized!
[ 15.330738] rkisp rkisp-vir0: Entity type for entity rkisp-csi-subdev was not initialized!
[ 15.334198] usbcore: registered new interface driver uvcvideo
[ 15.334221] USB Video Class driver (1.1.1)
[ 15.336410] Bluetooth: HCI UART driver ver 2.3
[ 15.336436] Bluetooth: HCI UART protocol H4 registered
[ 15.336447] Bluetooth: HCI UART protocol ATH3K registered
现在可以直接参考gc2145
的文档,因为这个是BT-601 YUV(外同步)来移植OV2640
也可以参考这个全志平台的移植MQ-r T113 ov2640驱动 因为都是MEDIA_BUS_FMT_UYUV8_2X8. 有些驱动是1X12,但我的硬件做的是2X8(8根CIF数据线). 所以只能看gc2145的代码和全志的这个(gc1054的驱动是MEDIA_BUS_FMT_SRGGB10_1X10, bayer RGB) 关于一个摄像头驱动用的哪种格式读取图像信息直接搜索关键词MEDIA_BUS_FMT
. 然后RK的框架/硬件貌似不支持RGB565,见附录B MEDIA_BUS_FMT表
,因为在整个文档都没搜到
这里说的RAW RGB 就是Bayer RAW RGB的意思.然后还有个RAW BW
主线的摄像头驱动貌似支持多种MEDIA_BUS_FMT
, 详见ov2640
/ov5640
,不过一般在probe的时候都会选一个default类型.
基本上rk的摄像头只支持了一种特定的camera output数据格式,毕竟没必要写那么多别output format支持,主打一个能用就行.
gc2145用的是MEDIA_BUS_FMT_UYVY8_2X8
,主线ov2640的default也是MEDIA_BUS_FMT_UYVY8_2X8
接下来的工作是照着这些资料完善主线ov2640
的一些函数,基本上只要上报正确信息就好
注意gc2145 的vsync是low active,(见手册 7.1. Timing), 而ov2640的vsync是high active(待确认?,因为那个全志的人写的是high active但是我看手册确实是low active,可以看到gc1054也是vsync low active,凭逻辑判断也是这样,不放心多看几个V4L2_MBUS_PARALLEL的驱动,看了七八个都是这样的估计全志那个人写错了)但是hsync(href)都是high active,然后pclk_sample 基本上都是rising
ar0230是一个桥接芯片并不是camera, 见手册第23页
这里的source(虽然是BT656的):rk3568制冷项目驱动开发流程汇总(只适用于部分模块CIF DVP等,自用)
第二个参考,虽然是rv1126的,但完整的展现了既有rkcif又有isp的情况下的拓扑(主要是知道哪个video设备是哪个产生的,哪个是裸的,哪个是经过处理的)
media-ctl 工具打印media control框架下media设备节点拓扑结构
第三个参考:
第四个参考:
(Rk的wiki,虽然是ISPv1)Rockchip-isp1
一开始只有accel的代码
这个是注册驱动后,irq中断次数(iio的bmi088挂载在spi4(fecb0000节点下面)