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_PHYS	4
#elif defined CONFIG_MACH_SUN8I_A83T
	#define CONFIG_SUNXI_USB_PHYS	3
#elif defined CONFIG_MACH_SUN8I_V3S
	#define CONFIG_SUNXI_USB_PHYS	1
#else
	#define CONFIG_SUNXI_USB_PHYS	2
#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 = <3>;
		interrupt-controller;
		#interrupt-cells = <3>;

		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 = <1>;
		#size-cells = <0>;
	};

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-emac
			syscon = <&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 = <1>;
				#size-cells = <0>;
				compatible = "snps,dwmac-mdio";
			};

			mdio-mux {
				compatible = "allwinner,sun8i-h3-mdio-mux";
				#address-cells = <1>;
				#size-cells = <0>;
                
				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 = <1>;
					#size-cells = <0>;
                 
					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 = <1>;
					#size-cells = <0>;
				};
			};
		};

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

Allwinner V3s + ov2640 + SPR5801_第1张图片按这个路径去找勾选即可。

  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 _DEBUG
			FILE *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 _DEBUG
			FILE *s;
			s = fopen("gti.bin", "wb");
			if (!s)
				ERROR("fopen: %s", strerror(errno));
			else {
				fwrite(gtibitmap, 1, 224*224*3, s);
				fclose(s);
			}
#endif

			processRGBdata(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 _DEBUG
			FILE *t;
			t = fopen("face.bin", "wb");
			if (!s)
				ERROR("fopen: %s", strerror(errno));
			else {
				fwrite(inface, 1, 224*224*3, t);
				fclose(t);
			}
#endif
			if (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 = 720000
SRC_PAL_YUV420P 
cnnW_size = 262144, Bias_size = 512
src.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

Allwinner V3s + ov2640 + SPR5801_第2张图片

你可能感兴趣的:(边缘AI计算)