> 文档中心 > Allwinner V3s + ov2640 + SPR5801

Allwinner V3s + ov2640 + SPR5801

最近在调试荔枝派Zero Allwinner V3s + ov2640 + SPR5801

1. uboot,正常修改,增加zImage 8k 地址 dd烧录。

首先获取u-boot源码: git clone https://github.com/Lichee-Pi/u-boot.git -b v3s-current
修改 include/configs/sun8i.h, 使u-boot可以直接从tf卡启动:

/* * (C) Copyright 2014 Chen-Yu Tsai  * * Configuration settings for the Allwinner A23 (sun8i) CPU * * SPDX-License-Identifier:GPL-2.0+ */#ifndef __CONFIG_H#define __CONFIG_H/* * A23 specific configuration */#ifdef CONFIG_USB_EHCI#define CONFIG_USB_EHCI_SUNXI#endif#ifdef CONFIG_MACH_SUN8I_H3#define CONFIG_SUNXI_USB_PHYS4#elif defined CONFIG_MACH_SUN8I_A83T#define CONFIG_SUNXI_USB_PHYS3#elif defined CONFIG_MACH_SUN8I_V3S#define CONFIG_SUNXI_USB_PHYS1#else#define CONFIG_SUNXI_USB_PHYS2#endif/* * Include common sunxi configuration where most the settings are */#define CONFIG_BOOTCOMMAND   "setenv bootm_boot_mode sec; " \   "load mmc 0:1 0x41000000 zImage; "  \   "load mmc 0:1 0x41800000 sun8i-v3s-licheepi-zero-dock.dtb; " \   "bootz 0x41000000 - 0x41800000;"#define CONFIG_BOOTARGS      "console=ttyS0,115200 panic=5 rootwait root=/dev/mmcblk0p2 earlyprintk rw  vt.global_cursor_default=0"#include #endif /* __CONFIG_H */

2. kernel

下载 linux-zero-5.2.y 增加对 ov2640 的配置。linux-zero-5.2.y/arch/arm/boot/dts$ gedit sun8i-v3s.dtsi...
csi1: csi@1cb4000 {compatible = "allwinner,sun8i-v3s-csi";reg = <0x01cb4000 0x1000>;interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;clocks = <&ccu CLK_BUS_CSI>,<&ccu CLK_CSI1_SCLK>,<&ccu CLK_DRAM_CSI>;clock-names = "bus", "mod", "ram";resets = <&ccu RST_BUS_CSI>;status = "disabled";};pio: pinctrl@1c20800 {compatible = "allwinner,sun8i-v3s-pinctrl";reg = <0x01c20800 0x400>;interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;clocks = <&ccu CLK_BUS_PIO>, <&osc24M>, <&osc32k>;clock-names = "apb", "hosc", "losc";gpio-controller;#gpio-cells = ;interrupt-controller;#interrupt-cells = ;emac_rgmii_pins: emac-rgmii-pins {pins = "PD0", "PD1", "PD2", "PD3", "PD4","PD5", "PD7", "PD8", "PD9", "PD10","PD12", "PD13", "PD15", "PD16", "PD17";function = "emac";allwinner,drive = <SUN4I_PINCTRL_40_MA>;allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;drive-strength = <40>;};i2c0_pins: i2c0-pins {pins = "PB6", "PB7";function = "i2c0";};pwm0_pins: pwm0 {pins = "PB4";function = "pwm0";};uart0_pb_pins: uart0-pb-pins {pins = "PB8", "PB9";function = "uart0";};lcd_rgb666_pins_a: lcd-rgb666-pe {pins = "PE0", "PE1", "PE2", "PE3", "PE4", "PE5","PE6", "PE7", "PE8", "PE9", "PE10", "PE11","PE12", "PE13", "PE14", "PE15", "PE16", "PE17","PE18", "PE19", "PE23", "PE24";function = "lcd";};mmc0_pins: mmc0-pins {pins = "PF0", "PF1", "PF2", "PF3","PF4", "PF5";function = "mmc0";drive-strength = <30>;bias-pull-up;};mmc1_pins: mmc1-pins {pins = "PG0", "PG1", "PG2", "PG3","PG4", "PG5";function = "mmc1";drive-strength = <30>;bias-pull-up;};spi0_pins: spi0-pins {pins = "PC0", "PC1", "PC2", "PC3";function = "spi0";};csi1_8bit: csi1-8bit@0 {pins  = "PE6","PE7","PE8","PE9","PE10","PE11","PE12","PE13","PE14","PE15";bias-disable;function = "csi";};csi1_clk: csi1-clk@0 { pins = "PE0","PE2","PE3"; bias-disable; function = "csi";};csi1_mclk: csi1-mclk@0 { pins = "PE1"; bias-disable; function = "csi";};i2c1_pins: i2c1 {pins = "PE21", "PE22";function = "i2c1";};};i2c1: i2c@1c2b000 {compatible = "allwinner,sun6i-a31-i2c";reg = <0x01c2b000 0x400>;interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;clocks = <&ccu CLK_BUS_I2C1>;resets = <&ccu RST_BUS_I2C1>;status = "disabled";#address-cells = ;#size-cells = ;};

linux-zero-5.2.y/arch/arm/boot/dts$ gedit sun8i-v3s-licheepi-zero.dts

&csi1 {status = "okay";pinctrl-names = "default";pinctrl-0 = <&csi1_clk &csi1_8bit>;port {csi1_ep: endpoint {remote-endpoint = <&ov2640_0>;hsync-active = <0>;vsync-active = <0>;bus-width = <10>;    pclk-sample = <1>;};}; };&i2c1 {    pinctrl-0 = <&i2c1_pins>;pinctrl-names = "default";status = "okay";ov2640: camera@30 {compatible = "ovti,ov2640";reg = <0x30>;pinctrl-names = "default";pinctrl-0 = <&csi1_mclk>;clocks = <&ccu CLK_CSI1_MCLK>;clock-names = "xvclk";assigned-clocks = <&ccu CLK_CSI1_MCLK>;assigned-clock-rates = <24000000>;port {ov2640_0: endpoint {remote-endpoint = <&csi1_ep>;bus-width = <10>;};};};};

其他的没有改动
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- licheepi_zero_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs

sudo cp -r ./arch/arm/boot/dts/sun8i-v3s-licheepi-zero-dock.dtb /media/t/BOOT/
sudo cp -r ./arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dtb /media/t/BOOT/
sudo cp -r arch/arm/boot/zImage /media/t/BOOT/

insmod video、csi 、ov2640 的ko即可。

Ethernet 的支持,内核4.*的版本需是在 linux-zero-5.2.y/drivers/net/ethernet/allwinner/sun8i-emac.c,
开始我看5.2没有这个,我想着增加sun8i-emac.c Kconfig 后来发现在 sun8i-v3s.dtsi

emac: ethernet@1c30000 {compatible = "allwinner,sun8i-h3-emac"; //  请注意这个sun8i-h3-emacsyscon = <&syscon>;reg = <0x01c30000 0x10000>;interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;interrupt-names = "macirq";resets = <&ccu RST_BUS_EMAC>;reset-names = "stmmaceth";clocks = <&ccu CLK_BUS_EMAC>;clock-names = "stmmaceth";status = "disabled";mdio: mdio {#address-cells = ;#size-cells = ;compatible = "snps,dwmac-mdio";};mdio-mux {compatible = "allwinner,sun8i-h3-mdio-mux";#address-cells = ;#size-cells = ;  mdio-parent-bus = <&mdio>;/* Only one MDIO is usable at the time */internal_mdio: mdio@1 {compatible = "allwinner,sun8i-h3-mdio-internal";reg = <1>;#address-cells = ;#size-cells = ;   int_mii_phy: ethernet-phy@1 {compatible = "ethernet-phy-ieee802.3-c22";reg = <1>;clocks = <&ccu CLK_BUS_EPHY>;resets = <&ccu RST_BUS_EPHY>;};};external_mdio: mdio@2 {reg = <2>;#address-cells = ;#size-cells = ;};};};

然后在kernel 目录下搜索,发现 5.2 对 sun8i-emac.c 的支持换了位置,只需要配置一下即可
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig

在这里插入图片描述按这个路径去找勾选即可。

  1. buildroot-2017.08.1
    选择开发自己需要的一些工具,alsa、ssh、fswebcam等,需要什么自己点

./fswebcam -S 20 -d /dev/video0 -p UYVY -r 800x600 --dumpframe dump.bin fswebcam.jpg

这样就可以抓取到图片了,声卡不用修改可以直接运行。

基于5801实现人脸检测、识别

基于fswebcam修改,不想写代码。
修改fswebcam.c

case SRC_PAL_YUV420P:printf("SRC_PAL_YUV420P \n");fswc_add_image_yuv420p(&src, abitmap);fswc_add_image_yuv420pGTI(&src, rgbbitmap);/* * bgrbitmap rgb 800 * 600 * * */bboxes_nms = (vec *)malloc(sizeof(vec));if (!bboxes_nms) {printf("malloc error.\n");return -1;}float *feature_vector = (float *)malloc(512*4*2);Read_registerData(feature_vector);ssdDetectionInit();faceRecog_init(recog_convFile, recog_fcFile);pModel = GtiCreateModel(detect_modelFile);if (pModel == NULL) {printf(" ===============\n Failed to load model. detect \n");return -1;}//GtiResize(bgrbitmap, src.height, src.width, gtibitmap, INPUT_IMAGE_H, INPUT_IMAGE_W);GtiCvtColor(rgbbitmap, src.height, src.width, Inbitmap);printf("src.height = %d , src.width = %d \n", src.height, src.width);imageResize(Inbitmap, src.height, src.width, gtibitmap, INPUT_IMAGE_H, INPUT_IMAGE_W);#ifdef _DEBUGFILE *f;f = fopen("rgb.bin", "wb");if (!f)ERROR("fopen: %s", strerror(errno));else {fwrite(rgbbitmap, 1, 800*600*3, f);fclose(f);}printf("abitmap.bin success !\n");#endif#ifdef _DEBUGFILE *s;s = fopen("gti.bin", "wb");if (!s)ERROR("fopen: %s", strerror(errno));else {fwrite(gtibitmap, 1, 224*224*3, s);fclose(s);}#endifprocessRGBdata(pModel, gtibitmap, bboxes_nms);GtiDestroyModel(pModel);for (int nI=0; nI<vec_size(bboxes_nms); nI++) {if ((vec_get_elem(bboxes_nms, nI).label) != 1)continue;float tmp_x1 = vec_get_elem(bboxes_nms, nI).x1 < 0 ? 0:vec_get_elem(bboxes_nms, nI).x1*800;float tmp_y1 = vec_get_elem(bboxes_nms, nI).y1 < 0 ? 0:vec_get_elem(bboxes_nms, nI).y1*600;float tmp_x2 = vec_get_elem(bboxes_nms, nI).x2 < 0 ? 0:vec_get_elem(bboxes_nms, nI).x2*800;float tmp_y2 = vec_get_elem(bboxes_nms, nI).y2 < 0 ? 0:vec_get_elem(bboxes_nms, nI).y2*600;float tmp_area = (tmp_x2 - tmp_x1) * (tmp_y2 - tmp_y1);if (tmp_area > area) {area = tmp_area;x1 = tmp_x1;y1 = tmp_y1;x2 = tmp_x2;y2 = tmp_y2;}}if (area <= 0) {printf("detect no face\n");continue;}printf("Location: ");printf("%.3f %.3f / %.3f %.3f.\n", x1, y1, x2, y2);   // x2 W y2 H//system("aplay amixer_src/tmp.wav ");vec_free(bboxes_nms); unsigned char *Pface_boxes = calloc((x2)*(y2)*3, sizeof(unsigned char)); imageCut(Inbitmap, 600, 800, Pface_boxes, x1, y1, y2, x2); unsigned char *inface = calloc(imageLength, sizeof(unsigned char)); imageResize(Pface_boxes, y2, x2, inface, 224, 224); if (Pface_boxes) {     free(Pface_boxes);  Pface_boxes = NULL; }  pModel = GtiCreateModel(recog_modelFile);  printf("recog CNN time diff %lld\n", getTimeDiff(recTime_s, recTime_e));if (pModel == NULL) {printf("===============\n Failed to load model. \n");}float *feature = calloc(512*4, sizeof(float));faceRecog_process(pModel, inface, feature);if (config->registered != NULL) {FILE *ptr;ptr = fopen("tbs.bin", "wb");if (!ptr)ERROR("fopen: %s", strerror(errno));else {fwrite(feature, 1, sizeof(float) * 512, ptr);fclose(ptr);}char buffer[50];sprintf(buffer, "arecord -D hw:0,0 -d 5 -f S16_LE -r 16000 %s.wav", config->registered);printf("%s \n", buffer);//system(src);printf("registered success \n");}#ifdef _DEBUGFILE *t;t = fopen("face.bin", "wb");if (!s)ERROR("fopen: %s", strerror(errno));else {fwrite(inface, 1, 224*224*3, t);fclose(t);}#endifif (inface) {free(inface);inface = NULL;}GtiDestroyModel(pModel); float distbuf[2] = {0}; for (int i = 0; i < 2; i++) {     distbuf[i] = faceRecog_cosDistance(&feature_vector[512*i], feature, 512);     printf("=============dist = %f\n",distbuf[i]); } float maxvalue = distbuf[0]; int index = 0; for (int i = 1; i < 2; i++) {     if (distbuf[i] > maxvalue) {  maxvalue = distbuf[i];  index = i;     } } if (maxvalue < 0.8) {     printf("result: recognize no face\n"); } else {     printf("result: index = %d \n", index);     if (index == 0) {     system("aplay ./feature/0.wav");     }     if (index == 1) {     system("aplay ./feature/1.wav");     } } if (feature) {     free(feature);  feature = NULL; }break;

运行结果:

# ./fswebcam -S 20 -d /dev/video0 -p YUV420P -r 800x600 --dumpframe dump.bin fswebcam.jpg --- Opening /dev/video0...Trying source module v4l2.../dev/video0 opened.No input was specified, using the first.--- Capturing frame...Skipping 20 frames...Capturing 1 frames...Dumping raw frame to 'dump.bin'...src.length = 720000SRC_PAL_YUV420P cnnW_size = 262144, Bias_size = 512src.height = 600 , src.width = 800 Location: 316.259 32.925 / 610.643 408.263.result: index = 1 Playing WAVE './feature/1.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Mono

在这里插入图片描述