本章節(jié)介紹V853平臺(tái) Camera 模塊的開發(fā)。
V853支持并口CSI、MIPI,使用VIN camera驅(qū)動(dòng)框架。
Camera通路框架
- VIN支持靈活配置單/雙路輸入雙ISP多通路輸出的規(guī)格
- 引入media框架實(shí)現(xiàn)pipeline管理
- 將libisp移植到用戶空間解決GPL問題
- 將統(tǒng)計(jì)buffer獨(dú)立為v4l2 subdev
- 將的scaler(vipp)模塊獨(dú)立為v4l2 subdev
- 將video buffer修改為mplane方式,使用戶層取圖更方便
- 采用v4l2-event實(shí)現(xiàn)事件管理
- 采用v4l2-controls新特性
VIN框架
框架簡(jiǎn)介
VIN是全志基于linux 內(nèi)核v4l2 框架實(shí)現(xiàn)自己Soc 的camera 驅(qū)動(dòng)框架。
-
vin.c
是驅(qū)動(dòng)的主要功能實(shí)現(xiàn),包括注冊(cè)/注銷、參數(shù)讀取、與v4l2上層接口、與各device的下層接口、中斷處理、buffer申請(qǐng)切換等; - 使用過程中可簡(jiǎn)單的看成是vin模塊+ device模塊 +af driver + flash控制模塊的方式;
-
modules/sensor
文件夾里面是各個(gè)sensor的器件層實(shí)現(xiàn),一般包括上下電、初始化,各分辨率切換,yuv sensor
包括絕大部分的v4l2
定義的ioctrl
命令的實(shí)現(xiàn);而raw sensor
的話大部分ioctrl命令在vin層調(diào)用isp庫(kù)實(shí)現(xiàn),少數(shù)如曝光/增益調(diào)節(jié)會(huì)透過vin層到實(shí)際器件層; -
modules/actuator
文件夾內(nèi)是各種vcm的驅(qū)動(dòng); -
modules/flash
文件夾內(nèi)是閃光燈控制接口實(shí)現(xiàn); -
vin-csi
和vin-mipi
為對(duì)csi接口和mipi接口的控制文件; -
vin-isp
文件夾為isp的庫(kù)操作文件; -
vin-video
文件夾內(nèi)主要是video設(shè)備操作文件。
源碼結(jié)構(gòu)(linux4.9)
驅(qū)動(dòng)路徑位于linux-4.9/drivers/media/platform/sunxi-vin
下
sunxi-vin:
│ vin.c ;v4l2驅(qū)動(dòng)實(shí)現(xiàn)主體(包含視頻接口和ISP部分)
│ vin.h ;v4l2驅(qū)動(dòng)頭文件
│ top_reg.c ;vin對(duì)各v4l2 subdev管理接口實(shí)現(xiàn)主體
│ top_reg.h ;管理接口頭文件
│ top_reg_i.h ;vin模塊接口層部分結(jié)構(gòu)體
├── modules
│ ├── actuator ;vcm driver
│ │ ├── actuator.c
│ │ ├── actuator.h
│ │ ├── dw9714_act.c
│ │ ├── Makefile
│ ├── flash ;閃光燈 driver
│ │ ├── flash.c
│ │ └── flash.h
│ └── sensor ;sensor driver
│ ├── ar0144_mipi.c
│ ├── camera_cfg.h ;camera ioctl擴(kuò)展命令頭文件
│ ├── camera.h ;camera公用結(jié)構(gòu)體頭文件
│ ├── Makefile
│ ├── gc2053_mipi.c
│ ├── ov2775_mipi.c
│ ├── ov5640.c
│ ├── sensor-compat-ioctl32.c
│ ├── sensor_helper.c ;sensor公用操作接口函數(shù)文件
│ ├── sensor_helper.h
├── platform ;平臺(tái)相關(guān)的配置接口
├── utility
│ ├── bsp_common.c
│ ├── bsp_common.h
│ ├── cfg_op.c
│ ├── cfg_op.h
│ ├── config.c
│ ├── config.h
│ ├── sensor_info.c
│ ├── sensor_info.h
│ ├── vin_io.h
│ ├── vin_os.c
│ ├── vin_os.h
│ ├── vin_supply.c
│ └── vin_supply.h
├── vin-cci
│ ├── sunxi_cci.c
│ └── sunxi_cci.h
├── vin-csi
│ ├── parser_reg.c
│ ├── parser_reg.h
│ ├── parser_reg_i.h
│ ├── sunxi_csi.c
│ └── sunxi_csi.h
├── vin-isp
│ ├── sunxi_isp.c
│ └── sunxi_isp.h
├── vin-mipi
│ ├── sunxi_mipi.c
│ └── sunxi_mipi.h
├── vin-stat
│ ├── vin_h3a.c
│ ├── vin_h3a.h
│ ├── vin_ispstat.c
│ └── vin_ispstat.h
├── vin_test
├── vin-video
│ ├── vin_core.c
│ ├── vin_core.h
│ ├── vin_video.c
│ └── vin_video.h
└── vin-vipp
├── sunxi_scaler.c
├── sunxi_scaler.h
├── vipp_reg.c
├── vipp_reg.h
└── vipp_reg_i.h
GC2063雙攝模組
V853開發(fā)板配套了GC2063雙攝像頭模組,其復(fù)用GC2053的驅(qū)動(dòng),驅(qū)動(dòng)代碼路徑為:
tina/lichee/linux-4.9/drivers/media/platform/sunxi-vin/modules/sensor/gc2053_mipi.c
此處以GC2063雙攝模組為例,介紹V853 Tina系統(tǒng)下的攝像頭模塊相關(guān)配置文件。
Tina配置
Tina 中主要是修改平臺(tái)的modules.mk配置,modules.mk主要完成兩個(gè)方面:
- 拷貝相關(guān)的ko模塊到小機(jī)rootfs中
- rootfs啟動(dòng)時(shí),按順序自動(dòng)加載相關(guān)的ko模塊。
modules.mk文件路徑:
tina/target/allwinner/v853-vision/modules.mk
驅(qū)動(dòng)加載配置
define KernelPackage/vin-v4l2
SUBMENU:=$(VIDEO_MENU)
TITLE:=Video input support (staging)
DEPENDS:=
FILES:=$(LINUX_DIR)/drivers/media/v4l2-core/videobuf2-core.ko
FILES+=$(LINUX_DIR)/drivers/media/v4l2-core/videobuf2-dma-contig.ko
FILES+=$(LINUX_DIR)/drivers/media/v4l2-core/videobuf2-memops.ko
FILES+=$(LINUX_DIR)/drivers/media/v4l2-core/videobuf2-v4l2.ko
FILES+=$(LINUX_DIR)/drivers/media/platform/sunxi-vin/vin_io.ko
FILES+=$(LINUX_DIR)/drivers/media/platform/sunxi-vin/modules/sensor/gc2053_mipi.ko
# FILES+=$(LINUX_DIR)/drivers/media/platform/sunxi-vin/modules/sensor_power/sensor_power.ko
FILES+=$(LINUX_DIR)/drivers/media/platform/sunxi-vin/vin_v4l2.ko
FILES+=$(LINUX_DIR)/drivers/input/sensor/da380/da380.ko
AUTOLOAD:=$(call AutoProbe,videobuf2-core videobuf2-dma-contig videobuf2-memops videobuf2-v4l2 vin_io gc2053_mipi vin_v4l2 da380.ko)
endef
define KernelPackage/vin-v4l2/description
Kernel modules for video input support
endef
$(eval $(call KernelPackage,vin-v4l2))
S00mpp配置
V853平臺(tái)在完成modules.mk配置后,還需要完成.ko掛載腳本S00mpp的配置,以便開機(jī)快速啟動(dòng)攝像頭模塊。
S00mpp配置路徑:
target/allwinner/v853-vision/busybox-init-base-files/etc/init.d
腳本對(duì)攝像頭驅(qū)動(dòng)進(jìn)行了提前加載,應(yīng)用需要使用的時(shí)候即可快速配置并啟動(dòng)。
#!/bin/sh
#
# Load mpp modules....
#
MODULES_DIR="/lib/modules/`uname -r`"
start() {
printf "Load mpp modulesn"
insmod $MODULES_DIR/videobuf2-core.ko
insmod $MODULES_DIR/videobuf2-memops.ko
insmod $MODULES_DIR/videobuf2-dma-contig.ko
insmod $MODULES_DIR/videobuf2-v4l2.ko
insmod $MODULES_DIR/vin_io.ko
# insmod $MODULES_DIR/sensor_power.ko
insmod $MODULES_DIR/gc4663_mipi.ko
insmod $MODULES_DIR/vin_v4l2.ko
insmod $MODULES_DIR/sunxi_aio.ko
insmod $MODULES_DIR/sunxi_eise.ko
# insmod $MODULES_DIR/vipcore.ko
}
stop() {
printf "Unload mpp modulesn"
# rmmod $MODULES_DIR/vipcore.ko
rmmod $MODULES_DIR/sunxi_eise.ko
rmmod $MODULES_DIR/sunxi_aio.ko
rmmod $MODULES_DIR/vin_v4l2.ko
rmmod $MODULES_DIR/gc4663_mipi.ko
# rmmod $MODULES_DIR/sensor_power.ko
rmmod $MODULES_DIR/vin_io.ko
rmmod $MODULES_DIR/videobuf2-v4l2.ko
rmmod $MODULES_DIR/videobuf2-dma-contig.ko
rmmod $MODULES_DIR/videobuf2-memops.ko
rmmod $MODULES_DIR/videobuf2-core.ko
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart|reload)
stop
start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit $?
DTS配置
DTS配置文件路徑:
tina/device/config/chips/v853/configs/vision
camera相關(guān)配置:
vind0:vind@0 {
vind0_clk = <300000000>;
status = "okay";
csi2:csi@2 {
pinctrl-names = "default","sleep";
pinctrl-0 = <&ncsi_pins_a>;
pinctrl-1 = <&ncsi_pins_b>;
status = "disabled";
};
tdm0:tdm@0 {
work_mode = <1>;
};
isp00:isp@0 {
work_mode = <1>;
};
scaler00:scaler@0 {
work_mode = <1>;
};
scaler10:scaler@4 {
work_mode = <1>;
};
scaler20:scaler@8 {
work_mode = <1>;
};
scaler30:scaler@12 {
work_mode = <1>;
};
actuator0:actuator@0 {
device_type = "actuator0";
actuator0_name = "ad5820_act";
actuator0_slave = <0x18>;
actuator0_af_pwdn = <>;
actuator0_afvdd = "afvcc-csi";
actuator0_afvdd_vol = <2800000>;
status = "disabled";
};
flash0:flash@0 {
device_type = "flash0";
flash0_type = <2>;
flash0_en = <>;
flash0_mode = <>;
flash0_flvdd = "";
flash0_flvdd_vol = <>;
status = "disabled";
};
sensor0:sensor@0 {
device_type = "sensor0";
sensor0_mname = "gc2053_mipi";
sensor0_twi_cci_id = <1>;
sensor0_twi_addr = <0x6e>;
sensor0_mclk_id = <0>;
sensor0_pos = "rear";
sensor0_isp_used = <1>;
sensor0_fmt = <1>;
sensor0_stby_mode = <0>;
sensor0_vflip = <0>;
sensor0_hflip = <0>;
sensor0_iovdd-supply = ;
sensor0_iovdd_vol = <1800000>;
sensor0_avdd-supply = ;
sensor0_avdd_vol = <2800000>;
sensor0_dvdd-supply = ;
sensor0_dvdd_vol = <1200000>;
sensor0_power_en = <>;
sensor0_reset = <&pio PA 18 1 0 1 0>;
sensor0_pwdn = <&pio PA 19 1 0 1 0>;
sensor0_sm_hs = <>;
sensor0_sm_vs = <>;
flash_handle = <&flash0>;
act_handle = <&actuator0>;
status = "okay";
};
sensor1:sensor@1 {
device_type = "sensor1";
sensor1_mname = "gc2053_mipi_2";
sensor1_twi_cci_id = <0>;
sensor1_twi_addr = <0x7f>;
sensor1_mclk_id = <1>;
sensor1_pos = "front";
sensor1_isp_used = <1>;
sensor1_fmt = <1>;
sensor1_stby_mode = <0>;
sensor1_vflip = <0>;
sensor1_hflip = <0>;
sensor1_iovdd-supply = ;
sensor1_iovdd_vol = <1800000>;
sensor1_avdd-supply = ;
sensor1_avdd_vol = <2800000>;
sensor1_dvdd-supply = ;
sensor1_dvdd_vol = <1200000>;
sensor1_power_en = <>;
sensor1_reset = <&pio PA 20 1 0 1 0>;
sensor1_pwdn = <&pio PA 21 1 0 1 0>;
sensor1_sm_hs = <>;
sensor1_sm_vs = <>;
flash_handle = <>;
act_handle = <>;
status = "okay";
};
vinc00:vinc@0 {
vinc0_csi_sel = <0>;
vinc0_mipi_sel = <0>;
vinc0_isp_sel = <0>;
vinc0_isp_tx_ch = <0>;
vinc0_tdm_rx_sel = <0>;
vinc0_rear_sensor_sel = <0>;
vinc0_front_sensor_sel = <0>;
vinc0_sensor_list = <0>;
work_mode = <0x1>;
status = "okay";
};
vinc01:vinc@1 {
vinc1_csi_sel = <1>;
vinc1_mipi_sel = <1>;
vinc1_isp_sel = <1>;
vinc1_isp_tx_ch = <0>;
vinc1_tdm_rx_sel = <1>;
vinc1_rear_sensor_sel = <1>;
vinc1_front_sensor_sel = <1>;
vinc1_sensor_list = <0>;
status = "okay";
};
vinc02:vinc@2 {
vinc2_csi_sel = <2>;
vinc2_mipi_sel = <0xff>;
vinc2_isp_sel = <2>;
vinc2_isp_tx_ch = <2>;
vinc2_tdm_rx_sel = <2>;
vinc2_rear_sensor_sel = <0>;
vinc2_front_sensor_sel = <0>;
vinc2_sensor_list = <0>;
status = "disabled";
};
vinc03:vinc@3 {
vinc3_csi_sel = <0>;
vinc3_mipi_sel = <0xff>;
vinc3_isp_sel = <0>;
vinc3_isp_tx_ch = <0>;
vinc3_tdm_rx_sel = <0>;
vinc3_rear_sensor_sel = <1>;
vinc3_front_sensor_sel = <1>;
vinc3_sensor_list = <0>;
status = "disabled";
};
vinc10:vinc@4 {
vinc4_csi_sel = <0>;
vinc4_mipi_sel = <0>;
vinc4_isp_sel = <0>;
vinc4_isp_tx_ch = <0>;
vinc4_tdm_rx_sel = <0>;
vinc4_rear_sensor_sel = <0>;
vinc4_front_sensor_sel = <0>;
vinc4_sensor_list = <0>;
work_mode = <0x1>;
status = "okay";
};
vinc11:vinc@5 {
vinc5_csi_sel = <1>;
vinc5_mipi_sel = <1>;
vinc5_isp_sel = <1>;
vinc5_isp_tx_ch = <0>;
vinc5_tdm_rx_sel = <1>;
vinc5_rear_sensor_sel = <1>;
vinc5_front_sensor_sel = <1>;
vinc5_sensor_list = <0>;
status = "okay";
};
vinc12:vinc@6 {
vinc6_csi_sel = <2>;
vinc6_mipi_sel = <0xff>;
vinc6_isp_sel = <0>;
vinc6_isp_tx_ch = <0>;
vinc6_tdm_rx_sel = <0>;
vinc6_rear_sensor_sel = <0>;
vinc6_front_sensor_sel = <0>;
vinc6_sensor_list = <0>;
status = "disabled";
};
vinc13:vinc@7 {
vinc7_csi_sel = <2>;
vinc7_mipi_sel = <0xff>;
vinc7_isp_sel = <0>;
vinc7_isp_tx_ch = <0>;
vinc7_tdm_rx_sel = <0>;
vinc7_rear_sensor_sel = <0>;
vinc7_front_sensor_sel = <0>;
vinc7_sensor_list = <0>;
status = "disabled";
};
vinc20:vinc@8 {
vinc8_csi_sel = <0>;
vinc8_mipi_sel = <0x0>;
vinc8_isp_sel = <0>;
vinc8_isp_tx_ch = <0>;
vinc8_tdm_rx_sel = <0>;
vinc8_rear_sensor_sel = <0>;
vinc8_front_sensor_sel = <0>;
vinc8_sensor_list = <0>;
work_mode = <0x1>;
status = "okay";
};
vinc21:vinc@9 {
vinc9_csi_sel = <2>;
vinc9_mipi_sel = <0xff>;
vinc9_isp_sel = <0>;
vinc9_isp_tx_ch = <0>;
vinc9_tdm_rx_sel = <0>;
vinc9_rear_sensor_sel = <0>;
vinc9_front_sensor_sel = <0>;
vinc9_sensor_list = <0>;
status = "disabled";
};
vinc22:vinc@10 {
vinc10_csi_sel = <2>;
vinc10_mipi_sel = <0xff>;
vinc10_isp_sel = <0>;
vinc10_isp_tx_ch = <0>;
vinc10_tdm_rx_sel = <0>;
vinc10_rear_sensor_sel = <0>;
vinc10_front_sensor_sel = <0>;
vinc10_sensor_list = <0>;
status = "disabled";
};
vinc23:vinc@11 {
vinc11_csi_sel = <2>;
vinc11_mipi_sel = <0xff>;
vinc11_isp_sel = <0>;
vinc11_isp_tx_ch = <0>;
vinc11_tdm_rx_sel = <0>;
vinc11_rear_sensor_sel = <0>;
vinc11_front_sensor_sel = <0>;
vinc11_sensor_list = <0>;
status = "disabled";
};
vinc30:vinc@12 {
vinc12_csi_sel = <0>;
vinc12_mipi_sel = <0x0>;
vinc12_isp_sel = <0>;
vinc12_isp_tx_ch = <0>;
vinc12_tdm_rx_sel = <0>;
vinc12_rear_sensor_sel = <0>;
vinc12_front_sensor_sel = <0>;
vinc12_sensor_list = <0>;
work_mode = <0x1>;
status = "okay";
};
vinc31:vinc@13 {
vinc13_csi_sel = <2>;
vinc13_mipi_sel = <0xff>;
vinc13_isp_sel = <0>;
vinc13_isp_tx_ch = <0>;
vinc13_tdm_rx_sel = <0>;
vinc13_rear_sensor_sel = <0>;
vinc13_front_sensor_sel = <0>;
vinc13_sensor_list = <0>;
status = "disabled";
};
vinc32:vinc@14 {
vinc14_csi_sel = <2>;
vinc14_mipi_sel = <0xff>;
vinc14_isp_sel = <0>;
vinc14_isp_tx_ch = <0>;
vinc14_tdm_rx_sel = <0>;
vinc14_rear_sensor_sel = <0>;
vinc14_front_sensor_sel = <0>;
vinc14_sensor_list = <0>;
status = "disabled";
};
vinc33:vinc@15 {
vinc15_csi_sel = <2>;
vinc15_mipi_sel = <0xff>;
vinc15_isp_sel = <0>;
vinc15_isp_tx_ch = <0>;
vinc15_tdm_rx_sel = <0>;
vinc15_rear_sensor_sel = <0>;
vinc15_front_sensor_sel = <0>;
vinc15_sensor_list = <0>;
status = "disabled";
};
};
修改該文件之后,需要重新編譯固件再打包,才會(huì)更新到 dts。
使用雙攝像頭時(shí),雙攝分別使用到兩個(gè)ISP,那么內(nèi)核需要選上SUPPORT_ISP_TDM
配置。
menuconfig配置
在命令行進(jìn)入Tina根目錄,執(zhí)行命令進(jìn)入配置主界面:
source build/envsetup.sh (詳見1)
lunch 方案編號(hào) (詳見2)
make menuconfig (詳見3)
詳注:
1.加載環(huán)境變量及tina提供的命令;
2.輸入編號(hào),選擇方案;
3.進(jìn)入配置主界面(對(duì)一個(gè)shell而言,前兩個(gè)命令只需要執(zhí)行一次)
make menuconfig配置路徑:
Kernel modules
└─>Video Support
└─>kmod-sunxi-vfe(vfe框架的csi camera) (詳見1)
└─>kmod-sunxi-vin(vin框架的csi camera) (詳見2)
└─>kmod-sunxi-uvc(uvc camera) (詳見3)
詳注:
1.平臺(tái)使用vfe框架的csi camera選擇該驅(qū)動(dòng);
2.平臺(tái)使用vin框架的csi camera選擇該驅(qū)動(dòng);(該項(xiàng)與vfe框架,在同一個(gè)平臺(tái)只會(huì)出現(xiàn)其中一個(gè))
3.usb camera選擇該驅(qū)動(dòng);
在完成 sensor 驅(qū)動(dòng)編寫,modules.mk
和板級(jí)配置后,通過make menuconfig
選上相應(yīng)的驅(qū)動(dòng),camera即可正常使用。
ISP效果調(diào)試
正在撰寫,敬請(qǐng)期待……
常見問題
內(nèi)核代碼注意事項(xiàng)
驅(qū)動(dòng)中一般禁止使用mdelay
或者msleep
實(shí)現(xiàn)延時(shí),例如使用msleep
實(shí)現(xiàn)10~20ms的延時(shí),通常會(huì)因?yàn)橄到y(tǒng)調(diào)度而變成延時(shí)更長(zhǎng)的時(shí)間,這種做法精度較差。所以如果需要使用ms級(jí)別延時(shí),則使用usleep_range(a, b)
,比如原來mdelay(1)
、mdelay(10)
可改為usleep_range(1000, 2000)
、usleep_range(10000, 12000)
。如果是長(zhǎng)達(dá)30ms或以上的延時(shí)可選擇使用msleep();
中斷過程中不能使用msleep
和usleep_range
,除了特殊情況必須加延時(shí)之外,mdelay
一般也不可使用。
如何進(jìn)行Camera模塊調(diào)試
Camera模塊調(diào)試一般可以分為三步:
(1)使用lsmod命令查看驅(qū)動(dòng)是否加載,查看/lib/modules/
內(nèi)核版本號(hào) 目錄下是否存在相應(yīng)的ko,如果沒有,確認(rèn)modules.mk
是否修改正確,配置了開機(jī)自動(dòng)加載。如果存在相應(yīng)的.ko
,可手動(dòng)加載測(cè)試確認(rèn)ko是否正常,手動(dòng)加載成功,則確認(rèn)內(nèi)核的版本是否一致,導(dǎo)致開機(jī)時(shí)沒有找到相應(yīng)的ko從而沒有加載;
(2)使用ls /dev/v*
查看是否有video0/1
節(jié)點(diǎn)生成;
(3)在adb shell 中使用cat /proc/kmsg
命令,或者是使用串口查看內(nèi)核的打印信息,查看不能正常加載的原因。一般情況下驅(qū)動(dòng)加載不成功的原因有:一是讀取的sys_config.fex
文件中的配置信息與加載的驅(qū)動(dòng)不匹配,二是probe
函數(shù)遇到某些錯(cuò)誤沒能正確的完成probe
的時(shí)候返回。
移植一款 sensor 需要進(jìn)行哪些操作
移植 camera sensor,主要進(jìn)行以下操作:
(1)根據(jù)主板的原理圖,確認(rèn)與 sensor 模組的接口是否一致,一致才可以保證配置和數(shù)據(jù)的正常接收。
(2)根據(jù)產(chǎn)品的需求,讓 sensor 模組廠提供產(chǎn)品所需的分辨率、幀率的寄存器配置,這一步需要注意,提供的配置需要是和模組匹配的。比如模組的 mipi 接口只引出 2lane,而提供的寄存器配置卻是配置為 4lane 輸出的,那么該配置在該模組無法正常使用,讓模組廠提供該模組可以正常使用的正確配置。注意,該寄存器配置 SOC 原廠沒有,需要 sensor 廠提供。
(3)拿到寄存器配置之后,按照Tina驅(qū)動(dòng)模塊配置等相關(guān)文檔完成 sensor 驅(qū)動(dòng)的編寫。
(4)在完成驅(qū)動(dòng)的編寫之后,按照Tina系統(tǒng)軟件開發(fā)指南等相關(guān)文檔等完成modules.mk
的修改。
(5)根據(jù)板子的原理圖與模組的硬件連接,參照Tina系統(tǒng)軟件開發(fā)指南等相關(guān)文檔完成sys_config.fex
或者board.dts
的修改。
(6)完成上述操作之后,在menuconfig
中進(jìn)行camera相關(guān)配置,并配置camera demo進(jìn)行調(diào)試測(cè)試,測(cè)試驅(qū)動(dòng)移植是否正常。
如何開始camera模塊調(diào)試
初次調(diào)試建議打開device
中的DEV_DBG_EN
為1,方便調(diào)試。
調(diào)試camera常見現(xiàn)象和功能檢查
(1)insmod
之后首先看內(nèi)核打印,看加載有無錯(cuò)誤打印,部分驅(qū)動(dòng)在加載驅(qū)動(dòng)進(jìn)行上下電時(shí)候會(huì)進(jìn)行i2c操作,如果此時(shí)報(bào)錯(cuò)的話就不需要再進(jìn)入camera了,先檢查是否io或電源配置不對(duì)。或者是在復(fù)用模組時(shí)候有可能是另外一個(gè)模組將i2c拉住了。
(2)如果i2c讀寫沒有問題的話,一般就可以認(rèn)為sensor控制是ok的,只需要根據(jù)sensor的配置填好H/VREF、PCLK的極性就能正常接收?qǐng)D像了。這個(gè)時(shí)候可以在進(jìn)入camera應(yīng)用之后用示波器測(cè)量sensor的各個(gè)信號(hào),看h/vref、pclk極性、幅度是否正常(2.8V的vpp)。
(3)如果看到畫面了,但是看起來是綠色和粉紅色的,但是有輪廓,一般是YUYV的順序設(shè)置反了,可檢查yuyv那幾個(gè)寄存器是否填寫正確配置,其次,看是否是在配置的其他地方有填寫同一個(gè)寄存器的地方導(dǎo)致將yuyv fmt的寄存器被改寫。
(4) 如果畫面顏色正常,但是看到有一些行是粉紅或者綠色的,往往是sensor信號(hào)質(zhì)量不好所致,通常在比較長(zhǎng)的排線中出現(xiàn)這個(gè)情況。在信號(hào)質(zhì)量不好并且yuyv順序不對(duì)的時(shí)候也會(huì)看見整個(gè)畫面的是綠色的花屏。
(5)當(dāng)驅(qū)動(dòng)能力不足的時(shí)候增強(qiáng)sensor的io驅(qū)動(dòng)能力有可能解決這個(gè)問題。此時(shí)用示波器觀察pclk和數(shù)據(jù)線可能會(huì)發(fā)現(xiàn):pclk波形擺幅不夠IOVDD的幅度,或者是data輸出波形擺幅有時(shí)候能高電平達(dá)到IOVDD的幅度,有時(shí)候可能連一半都不夠。
(6)如果是兩個(gè)模組復(fù)用數(shù)據(jù)線的話,不排除是另外一個(gè)sensor在進(jìn)入standby時(shí)候沒有將其數(shù)據(jù)線設(shè)置成高阻,也會(huì)影響到當(dāng)前模組的信號(hào)擺幅,允許的話可以剪斷另一個(gè)模組來證實(shí)。
(7)當(dāng)畫面都正常之后檢查前置攝像頭垂直方向是否正確,水平方向是否是鏡像,后置水平垂直是否正確,不對(duì)的話可以調(diào)節(jié)sys_config.fex
中的hflip和vflip參數(shù)來解決,但如果屏幕上看到的畫面與人眼看到的畫面是成90度的話,只能是通過修改模組的方向來解決。
(8)之后可以檢查不同分辨率之間的切換是否ok,是否有切換不成功的問題;以及拍照時(shí)候是否圖形正常,亮度顏色是否和預(yù)覽一致;雙攝像頭的話需要檢查前后切換是否正常。
(9)如果上述都沒有問題的話,可認(rèn)為驅(qū)動(dòng)無大問題,接下來可以進(jìn)行其他功能(awb/exp bias/color effect等其他功能的測(cè)試)。
(10) 測(cè)試對(duì)焦功能,單次點(diǎn)觸屏幕,可正確對(duì)上不同距離的物體;不點(diǎn)屏幕時(shí)候可以自動(dòng)對(duì)焦對(duì)上畫面中心物體,點(diǎn)下拍照后拍出來的畫面能清晰。
(11)打開閃光燈功能,檢查在單次對(duì)焦時(shí)候能打開燈,對(duì)完之后無論成功失敗或者超時(shí)能夠關(guān)閉,在點(diǎn)下拍照之后能打開,拍完之后能關(guān)閉。
(12)如果加載模塊后,發(fā)現(xiàn)dev/videoX
節(jié)點(diǎn)沒有生成,請(qǐng)檢查下面幾點(diǎn):
a. 模塊加載的順序
一定要按照以下順序加載模塊
insmod videobuf-core.ko
insmod videobuf-dma-contig.ko
;如果有對(duì)應(yīng)的vcm driver,在這里加載,如果沒有,請(qǐng)省略。
insmod actuator.ko
insmod ad5820_act.ko
;以下是camera驅(qū)動(dòng)和vfe驅(qū)動(dòng)的加載,先安裝一些公共資源。
insmod vfe_os.ko
insmod vfe_subdev.ko
insmod cci.ko
insmod ov5640.ko
insmod gc0308.ko
;如果一個(gè)csi接兩個(gè)camera,所有camera對(duì)應(yīng)的ko都要在vfe_v4l2.ko之前加載。
insmod vfe_v4l2.ko
b. sys_config.fex配置
vip_used = 1 ;確保used為1
vip_dev_qty = 2 ;確保csi接口上接的camera數(shù)量與ko加載情況相同
vip_dev0_mname = "ov5640" ;確保camera型號(hào)與ko加載情況相同
vip_dev0_twi_id = 1 ;確保camera使用的i2c總線id與配置一樣
vip_dev1_mname = "gc0308" ;確保camera型號(hào)與ko加載情況相同
vip_dev1_twi_id = 1 ;確保camera使用的i2c總線id與配置一樣
常見異?,F(xiàn)象與處理方法
-
I2C通信出錯(cuò)
I2C出現(xiàn)問題內(nèi)核一般會(huì)伴隨打印cci_write_aX_dX error! slave = 0xXX, addr = 0xXX, value = 0xXX"
如果與此同時(shí),內(nèi)核出現(xiàn)打印chip found is not an target chip.
,則說明在初始化camera前,讀取camera的ID已經(jīng)失敗。
此時(shí),一般是如下幾點(diǎn)出現(xiàn)問題。
a. 最先考慮應(yīng)該是更換一個(gè)camera模組試試。
b. 電源
檢查sys_config.fex
vip_dev0_iovdd = "axp22_eldo3"
vip_dev0_iovdd_vol = 2800000
vip_dev0_avdd = "axp22_dldo4"
vip_dev0_avdd_vol = 2800000
vip_dev0_dvdd = "axp22_eldo2"
vip_dev0_dvdd_vol = 1500000
一定要與原理圖設(shè)計(jì)保持一致。必要時(shí),需要用萬用表測(cè)量camera模組的各路電壓是否正常。
c. reset和power down腳
檢查sys_config.fex配置
vip_dev0_reset = port:PH2<1>
vip_dev0_pwdn = port:PH1<1>
是否與原理圖設(shè)計(jì)保持一致。必要時(shí),需要用示波器測(cè)量reset,pwdn腳,在camera加載時(shí),是否有動(dòng)作。
d. mclk
檢查sys_config.fex配置
vip_csi_mck = port:PE01<3>
pin腳是否與原理圖設(shè)計(jì)保持一致。必要時(shí),在加載camera時(shí),測(cè)量mclk,看是否有正確輸出(一般是24MHz或27MHz)
如果已經(jīng)能夠正確通過camera的id讀取,只是在使用過程當(dāng)中,偶爾出現(xiàn)I2C的讀寫錯(cuò)誤,此時(shí)需要從打印里面,將報(bào)錯(cuò)的地址和讀寫值,結(jié)合camera具體的spec來分析,到底是操作了camera哪些寄存器帶來的問題。
還有可能出現(xiàn)如下信息:
[ 5.556579] sunxi_i2c_do_xfer()1942 - [i2c1] incomplete xfer (status: 0x20, dev addr: 0x30)
[ 5.566234] sunxi_i2c_do_xfer()1942 - [i2c1] incomplete xfer (status: 0x20, dev addr: 0x30)
[ 5.575963] sunxi_i2c_do_xfer()1942 - [i2c1] incomplete xfer (status: 0x20, dev addr: 0x30)
[ 5.585375] [VIN_DEV_I2C]sc031gs_mipi sensor read retry = 2
[ 5.591666] [sensorname_mipi] error, chip found is not an target chip.
出現(xiàn)上述錯(cuò)誤打印時(shí),可按以下操作逐步debug。
(1)確認(rèn)sys_config.fex
中配置的 sensor I2C 地址是否正確(sensor datasheet 中標(biāo)注,讀地址為 0x6d,寫地址為 0x6c,那么 sys_config.fex 配置 sensor I2C 地址為 0x6c);
(2)在完成以上操作之后,在 senor 上電函數(shù)中,將掉電操作屏蔽,保持 sensor 一直上電狀態(tài),方便 debug;
(3)確認(rèn) I2C 地址正確之后,測(cè)量 sensor 的各路電源電壓是否正確且電壓幅值達(dá)到 datasheet 標(biāo)注的電壓要求;
(4)測(cè)量 MCLK 的電壓幅值與頻率,是否正常;
(5)測(cè)量 senso r的 reset、pown 引腳電平配置是否正確,I2C 引腳 SCK、SDA 是否已經(jīng)硬件上拉;
(6)確認(rèn) I2C 接口使用正確并使能(CCI / TWI);
(7)如果還是 I2C 出錯(cuò),協(xié)調(diào)硬件同事使用邏輯分析儀等儀器進(jìn)行debug;
I2C沒有硬件上拉
I2C沒有硬件上拉時(shí)一般會(huì)異常報(bào)錯(cuò):
twi_start()450 - [i2c2] START can't sendout!
twi_start()450 - [i2c2] START can't sendout!
twi_start()450 - [i2c2] START can't sendout!
[VFE_DEV_I2C_ERR]cci_write_a16_d16 error! slave = 0x1e, addr = 0xa03e, value = 0x1
出現(xiàn)上述的問題是因?yàn)?SDA、SCK 沒有拉上,導(dǎo)致在進(jìn)行 I2C 通信時(shí),發(fā)送開始信號(hào)失敗,SDA、SCK 添加上拉即可。
I2C沒有使能
I2C沒有使能時(shí)一般會(huì)異常報(bào)錯(cuò):
[VFE]Sub device register "ov2775_mipi" i2c_addr = 0x6c start!
[VFE_ERR]request i2c adapter failed!
[VFE_ERR]vfe sensor register check error at input_num = 0
出現(xiàn)上述的錯(cuò)誤,是因?yàn)槭褂?twi 進(jìn)行 I2C 通信但沒有使能 twi 導(dǎo)致的錯(cuò)誤,此時(shí)需要確認(rèn) sys_config.fex 中,[twiX] 中的 twiX_used 是否已經(jīng)設(shè)置為 1。
圖像全黑如何處理
異常現(xiàn)象:
當(dāng) camerademo 成功采集到圖像時(shí),發(fā)現(xiàn)圖像是全黑的
首先最起碼整條數(shù)據(jù)通路已經(jīng)正常,而發(fā)現(xiàn)圖像時(shí)全黑的,注意以下幾點(diǎn):
(1)在編譯 camerademo 之前,是根據(jù)平臺(tái)正確的選上了Enable vin isp support
,選上之后,重新編譯camerademo(建議cd package/allwinner/camerademo
目錄后執(zhí)行mm -B編譯);
(2)通過上述操作之后,執(zhí)行新編譯的camerademo可執(zhí)行程序,運(yùn)行過程應(yīng)可看到類似[ISP]create isp0 server thread!
信息,則正確運(yùn)行isp,這時(shí)再查看新抓取的圖像數(shù)據(jù);
(3)執(zhí)行運(yùn)行camerademo只會(huì)抓取5張圖像數(shù)據(jù),由于isp計(jì)算合適的圖像曝光需要一定的幀數(shù),所以可能存在前面幾張圖像黑的情況,修改camerademo運(yùn)行參數(shù),抓取多幾張圖像數(shù)據(jù)查看(20張);
(4)如果是沒有移植isp的環(huán)境,則可修改sensor驅(qū)動(dòng)中寄存器組中的曝光參數(shù)配置,增加初始化時(shí)曝光時(shí)間,從而使初始輸出的圖像亮度較合適。
** camerademo 采集的圖像顏色異常**
異?,F(xiàn)象:
運(yùn)行 camerademo 采集圖像之后,發(fā)現(xiàn)拍攝得到的輪廓正確但顏色不對(duì),比如紅藍(lán)互換、畫面整體偏紅或偏藍(lán)等顏色異常的情況
出現(xiàn)這樣的問題,首先考慮是sensor驅(qū)動(dòng)中配置的RAW數(shù)據(jù)RGB順序錯(cuò)誤導(dǎo)致的。在sensor驅(qū)動(dòng)中有類似以下的配置:
static struct sensor_format_struct sensor_formats[] = {
{
.desc = "Raw RGB Bayer",
.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
.regs = sensor_fmt_raw,
.regs_size = ARRAY_SIZE(sensor_fmt_raw),
.bpp = 1
},
};
以上配置表明sensor輸出的圖像數(shù)據(jù)是RAW10,RGB排列順序是BGGR,出現(xiàn)顏色異常時(shí),一般就是RGB的排列順序配置錯(cuò)誤導(dǎo)致的,RGB排列順序一共有4種 (MEDIA_BUS_FMT_SBGGR10_1X10/MEDIA_BUS_FMT_SGBRG10_1X10/MEDIA_BUS_FMT_SGRBG10_1X10/MEDIA_BUS_FMT_SRGGB10_1X10),修改驅(qū)動(dòng)中的mbus_code
為上述的4種之一,確認(rèn)哪一種顏色比較正常,則驅(qū)動(dòng)配置正確。如果顏色還有細(xì)微的不夠艷麗、準(zhǔn)確等問題,需要進(jìn)行isp效果調(diào)試,改善圖像色彩。
上述是以10bit sensor為例進(jìn)行介紹,其他的8bit、12bit、14bit類似,參考上述即可。
- 畫面大體輪廓正常,顏色出現(xiàn)大片綠色和紫紅色
一般可能是csi采樣到的yuyv順序出現(xiàn)錯(cuò)位。
確認(rèn)camera輸出的yuyv順序的設(shè)置與camera的spec一致
若camera輸出的yuyv順序沒有問題,則可能是由于走線問題,導(dǎo)致pclk采樣data時(shí)發(fā)生錯(cuò)位,此時(shí)可以調(diào)整pclk的采樣沿。具體做法如下:
在對(duì)應(yīng)的camara驅(qū)動(dòng)源碼,如ov5640.c里面,找到宏定義#define CLK_POL。此宏定義可以有兩個(gè)值V4L2_MBUS_PCLK_SAMPLE_RISING
和V4L2_MBUS_PCLK_SAMPLE_FALLING
。若原來是其中一個(gè)值,則修改成另外一個(gè)值,便可將PCLK的采樣沿做反相。
- 畫面大體輪廓正常,但出現(xiàn)不規(guī)則的綠色紫色條紋
一般可能是pclk驅(qū)動(dòng)能力不足,導(dǎo)致某個(gè)時(shí)刻采樣data時(shí)發(fā)生錯(cuò)位。
解決辦法:
- 若pclk走線上有串聯(lián)電阻,嘗試將電阻阻值減小。
- 增強(qiáng)pclk的驅(qū)動(dòng)能力,需要設(shè)置camera的內(nèi)部寄存器。
- 畫面看起來像油畫效果,過渡漸變的地方有一圈一圈
一般是CSI的data線沒有接好,或短路,或斷路。
- 常見報(bào)錯(cuò): [VFE_WARN] Nobody is waiting on this video buffer
上層還回來所有的buffer,但是沒有再來取buffer。
- 常見報(bào)錯(cuò) - [VFE_WARN] Only three buffer left for csi
上層占用了大部分buffer,沒有還回,驅(qū)動(dòng)部分只有三個(gè)buffer此時(shí)驅(qū)動(dòng)不再進(jìn)行buffer切換,直到有buffer還回為止。
sensor的硬件接口注意事項(xiàng)
(1)如果是使用并口的sensor模組,會(huì)使用到720p@30fps或更高速度的,必須在mclk/pclk/data/vsync/hsync
上面串33ohm電阻,5M的sensor一律串電阻;
(2)使用Mipi模組時(shí)候PCB layout需要盡量保證clk/data的差分對(duì)等長(zhǎng),過孔數(shù)相等,特征阻抗100ohm;
(3)如果使用并口復(fù)用pin的模組時(shí)候,不建議reset腳的復(fù)用;
(4)并口模組的排線長(zhǎng)度加上pcb板上走線長(zhǎng)度不超過10cm, mipi模組排線長(zhǎng)度加上pcb板上走線長(zhǎng)度不超過20cm,超過此距離不保證能正常使用。
(5)主控并口數(shù)據(jù)線有D11~D0共12bit,并口的sensor輸出一般為8/10bit,原理圖連接需要做高位對(duì)齊。
Camera demo
Tina系統(tǒng)可以通過 SDK 中的 camerademo 包來驗(yàn)證 camera sensor(usb camera) 是否移植成功,如果可以正常捕獲保存圖像數(shù)據(jù),則底層驅(qū)動(dòng)、板子硬件正常。
camerademo配置
在命令行中進(jìn)入Tina根目錄,執(zhí)行make menuconfig進(jìn)入配置主界面,并按以下配置路徑操作:
Allwinner
└─>camerademo
-
開發(fā)
+關(guān)注
關(guān)注
0文章
370瀏覽量
40836 -
MIPI
+關(guān)注
關(guān)注
11文章
310瀏覽量
48613 -
CSI
+關(guān)注
關(guān)注
1文章
36瀏覽量
50981 -
Camera
+關(guān)注
關(guān)注
0文章
79瀏覽量
20805 -
V853
+關(guān)注
關(guān)注
2文章
19瀏覽量
2152
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論