嵌入式linux开发——stm32mp1完成视觉检测(一)

这里从今天开始给自己挖坑然后慢慢填坑……

打算基于自己买的正点原子的stm32mp157开发板还有OV5640摄像头,完成一个视觉检测的项目,最基础的版本是直接OpenCV打开摄像头然后完成简单的检测;进阶版把sklearn训练的模型通过cpp读取然后显示;最终目标是跑之前训练好的yolo模型。

那么问题就可以分成以下几步走:

  1. 驱动移植:包括linux的基础驱动,OV5640驱动,LCD驱动等等
  2. OpenCV+QT的库移植
  3. Python的机器学习库sklearn的相关模型保存还有C++读取方法
  4. 深度学习yolo的C++读取方法

那么第一篇显然就是基础的驱动移植,正式内容就此展开!

linux驱动移植

这里直接看正点原子开源的教程就可以了,里面很详细的有讲解linux驱动的移植过程,总结一下就是以下几步骤:

  1. TF-A:这个是imx这个最常见初学嵌入式linux的开发板芯片所没有的,是一个安全系统,需要完成移植
  2. U_Boot:经典的导引加载系统
  3. Linux内核:可剪裁的操作系统
  4. 根文件系统:这里主要使用Buildroot制作加载

可以直接跟着教程一步步完成。

LCD驱动

完成基础的Linux操作系统搭建后,视觉检测项目就需要一个显示器,买的开发板上就有LCD显示器,可以同样跟着教程完成LCD的驱动移植用于显示图像。

OV5640驱动

这个是这篇文章的重点!!!虽然开发板的出产系统是自带驱动的,但是那个驱动太多了,QT的界面也是已经搭建好的,对于我想从头自己做项目的话,起不到学习作用,所以也是对着出厂设置来自行移植!

这里的话,我搜了网上的很多资料,因为stm32mp1系列的开发板,根据正点原子工作人员的讲法,当时ST公司是限制了其产量,所以用的人很少,大多数都是用imx或者直接rk系列芯片,mp1系列的相关资料就很少,我网上就只找到了华清有几个相关的摄像头驱动教程,但是是直接加载到内核,而且写的文件跟正点原子的风格还是不太一样的,本着自我学习的精神,我也是自己研究出来了怎么移植,而不是网上搜到的大多数基于正点原子出厂系统的使用

进入正题,看看如何完成OV5640驱动移植。

设备树修改

需要在相关的设备树dts和dtsi文件中加入相关的内容,涉及到摄像头接口dcmi节点,ov5640节点以及相关的电源和时钟节点信息。

dcmi接口

首先需要添加dcmi节点,这是一个摄像头接口所使用的节点,这里根据正点原子的GPIO口需要在stm32mp157d-atk.dtsi文件中加入以下内容:

&pinctrl {
	dcmi_pins_b: dcmi-1 {
		pins {
			pinmux = <STM32_PINMUX('H', 8,  AF13)>,/* DCMI_HSYNC */
				<STM32_PINMUX('B', 7,  AF13)>,/* DCMI_VSYNC */
				<STM32_PINMUX('A', 6,  AF13)>,/* DCMI_PIXCLK */
				<STM32_PINMUX('H', 9,  AF13)>,/* DCMI_D0 */
                <STM32_PINMUX('H', 10, AF13)>,/* DCMI_D1 */
                <STM32_PINMUX('H', 11, AF13)>,/* DCMI_D2 */
                <STM32_PINMUX('H', 12, AF13)>,/* DCMI_D3 */
                <STM32_PINMUX('H', 14, AF13)>,/* DCMI_D4 */
                <STM32_PINMUX('I', 4,  AF13)>,/* DCMI_D5 */
             	<STM32_PINMUX('B', 8,  AF13)>,/* DCMI_D6 */
                <STM32_PINMUX('E', 6,  AF13)>;/* DCMI_D7 */
            	bias-disable;
		};
	};

	dcmi_sleep_pins_b: dcmi-sleep-1 {
        	pins {
			pinmux = <STM32_PINMUX('H', 8,  ANALOG)>,/* DCMI_HSYNC */
					<STM32_PINMUX('B', 7,  ANALOG)>,/* DCMI_VSYNC */
               		<STM32_PINMUX('A', 6,  ANALOG)>,/* DCMI_PIXCLK */
                	<STM32_PINMUX('H', 9,  ANALOG)>,/* DCMI_D0 */
                	<STM32_PINMUX('H', 10, ANALOG)>,/* DCMI_D1 */
                	<STM32_PINMUX('H', 11, ANALOG)>,/* DCMI_D2 */
                	<STM32_PINMUX('H', 12, ANALOG)>,/* DCMI_D3 */
                	<STM32_PINMUX('H', 14, ANALOG)>,/* DCMI_D4 */
                	<STM32_PINMUX('I', 4,  ANALOG)>,/* DCMI_D5 */
                	<STM32_PINMUX('B', 8,  ANALOG)>,/* DCMI_D6 */
                	<STM32_PINMUX('E', 6,  ANALOG)>;/* DCMI_D7 */
        	};
	};
};

这一部分相当于给定了dcmi接口所使用的GPIO口的定义。

然后在stm32mp157d-atk.dts中加入如下内容:

&dcmi {
	status = "okay";
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&dcmi_pins_b>;
	pinctrl-1 = <&dcmi_sleep_pins_b>;

	port {
        	dcmi_0: endpoint {
            	remote-endpoint = <&ov5640_0>;
           		bus-width = <8>;
            	hsync-active = <0>;
            	vsync-active = <0>;
            	pclk-sample = <1>;
            	pclk-max-frequency = <77000000>;
        	};
    	};
};

这里就是在设备树中添加了dcmi的节点,连接到了ov5640的节点,并且定义了一些属性内容,这一部分只要复制过来就可以了。

ov5640

需要在设备树节点中添加ov5640节点,这里可以去参考Documentation/devicetree/bindings/media/i2c/ov5640.txt,里面有通过i2c驱动ov5640需要在设备树中添加内容的示例,基于示例以及正点原子开发板的出厂配置,可以在stm32mp157d-atk.dts添加如下内容:

&i2c5 {	
	pinctrl-names = "default", "sleep";
    	pinctrl-0 = <&i2c5_pins_a>;
    	pinctrl-1 = <&i2c5_pins_sleep_a>;
    	i2c-scl-rising-time-ns = <100>;
    	i2c-scl-falling-time-ns = <7>;
    	status = "okay";
    	/delete-property/dmas;
    	/delete-property/dma-names;

   	ov5640: camera@3c {
		compatible = "ovti,ov5640";
		reg = <0x3c>;
		clocks = <&clk_ext_camera>;
		clock-names = "xclk";
		DOVDD-supply = <&v2v8>;
		powerdown-gpios = <&gpioe 11 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>;
		reset-gpios = <&gpioe 1 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>;
		rotation = <180>;
		status = "okay";

		port {
	    		ov5640_0: endpoint {
	        		remote-endpoint = <&dcmi_0>;
	        		bus-width = <8>;
	        		data-shift = <2>;
	        		hsync-active = <0>;
	        		vsync-active = <0>;
	        		pclk-sample = <1>;
	        		pclk-max-frequency = <77000000>;
	    		};
		};
    	};
};

这里就是把txt的内容拉过来,然后适配一下gpio的节点就可以了。

辅助节点

通过对ov5640的节点,可以发现需要时钟定义以及2.8V的电源定义,所以在stm32mp157d-atk.dts的根节点添加如下内容:

clocks {
		clk_ext_camera: clk-ext-camera {
			#clock-cells = <0>;
            compatible = "fixed-clock";
           	clock-frequency = <24000000>;
        	};
    	};

v2v8: regulator-v2v8 {
        	compatible = "regulator-fixed";
        	regulator-name = "v2v8";
        	regulator-min-microvolt = <2800000>;
        	regulator-max-microvolt = <2800000>;
        	regulator-always-on;
        	regulator-over-current-protection;
    	};

之后就顺利的完成了设备树的内容一致啦。

Linux内核

这里的话其实也不用改,我按照教程学习Linux驱动的时候,按照教程移植过来的内核里面,menuconfig里面是已经把改配置的都已经配置好了。这里就我截个图,如果没配置就按照下面配置一下:

-> Device Drivers
-> <M> Multimedia support
-> V4L platform devices
-> <M> STM32 Digital Camera Memory Interface (DCMI) support
-> Device Drivers
-> <M> Multimedia support
-> I2C Encoders, decoders, sensors and other helper chips
-> <M> OmniVision OV5640 sensor support
我这边是把他都编译成模块化去生成动态加载的ko文件,之后去drivers文件夹里面复制到开发板就可以了。

以上操作均完成后就重新编译,命令如下:

make dtbs uImage LOADADDR=0XC2000040 -j16

最终移植加载

这一步也是很重要的,需要把如下的ko文件全部移动到开发板的/lib/modules/5.4.31中:

/drivers/media/i2c/ov5640.ko
/drivers/media/mc/mc.ko
/drivers/media/v4l2-core/vediodev.ko
/drivers/media/v4l2-core/v4l2-fwnode.ko
/drivers/media/v4l2-core/videobuf2-common.ko
/drivers/media/v4l2-core/videobuf2-memops.ko
/drivers/media/v4l2-core/videobuf2-v4l2.ko
/drivers/media/v4l2-core/videobuf2-dma-contig.ko
/drivers/media/platform/stm32/stm32-dcmi.ko

然后进去之后就只要输入以下命令就可以:

cd /lib/modules/5.4.31
modprobe stm32-dcmi.ko
modprobe ov5640.ko

大功告成!!

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
欢迎下载研华科技主题白皮书: 【深度剖析】研华多核异构ARM核心板之机器视觉应用案例 [摘要] TI Sitara系列AM5718/5728是采用ARM+DSP多核异构架构,可以实现图像采集、算法处理、显示、控制等功能,具有实时控制、低功耗、多标准工业控制网络互联、工业人机界面的优化、2D/3D图形处理、1080 HD的高清视频应用、工业控制设备的小型化等特点。广泛应用在机器视觉、工业通讯、汽车多媒体、医疗影像、工厂自动化、工业物联网等领域。 https://www.eefocus.com/resource/advantech/index.p... OpenMV Cam概述: OpenMV项目旨在通过开发开源的低成本机器视觉摄像机,为业余爱好者和制造商提供机器视觉。OpenMV项目于2015年成功通过Kickstarter资助。第一代OpenMV摄像机基于STM的STM32F ARM Cortex-M MCU和Omnivision OV7725传感器。OpenMV摄像机可以在Python3中进行编程,并附有大量的图像处理功能,如面部检测和跟踪,关键点描述符,彩色斑点跟踪,QR和条形码支持,AprilTags,GIF和MJPEG记录等等。 OpenMV摄像机板内置RGB和红外LED,用于编程和视频流的USB FS,uSD插座和I / O头,可以分解PWM,UART,SPI和I2C。此外,OpenMV还支持使用诸如WiFi,BLE,Thermal(FIR)和LCD屏蔽等I / O头的扩展模块(屏蔽)。 OpenMV配备了专门用于支持OpenMV摄像机的跨平台IDE(基于QT创建者)。IDE允许查看帧缓冲区,访问传感器控制,上传脚本并通过串行通过USB(或WiFi / BLE(如果可用))在相机上运行它们。 STM32 机器人视觉摄像机OpenMV Cam实物截图: STM32 机器人视觉摄像机OpenMV Cam特性: 所有I / O引脚输出3.3V并具有5V容限。 在标准的M12镜头座上配有一个2.8mm镜头,便于其他镜头交换。 全速USB(12Mbs)接口到您的计算机。您的OpenMV摄像机在插入时将显示为虚拟COM端口和USB闪存驱动器。 一个能够100Mb读/写的微型SD卡插槽,允许您的OpenMV摄像头记录视频并轻松拉取机器视觉资产从微型SD卡。 SPI总线可以运行高达45Mbs,使您可以轻松地将系统中的图像数据传输到LCD屏蔽,WiFi屏蔽或另一个微控制器。 I2C总线,CAN总线和异步串行总线(TX / RX),用于与其他微控制器和传感器接口。 12位ADC和12位DAC。 两个用于伺服控制的I / O引脚。 所有I / O引脚上的中断和PWM(板上有9个I / O引脚)。 另外还有一个RGB LED和两个高功率的850nm红外LED。 由MacroFab在美国制造的OpenMV LLC OpenMV Cam M4 与 M7区别: STM32 机器人视觉摄像机OpenMV Cam应用: 标记跟踪 您可以使用您的OpenMV Cam来检测组的颜色,而不是独立的颜色。这允许您创建可以放置在对象上的色彩制作者(2个或更多颜色标签),允许您的OpenMV Cam了解标签对象的内容。视频演示这里。 人脸检测 您可以使用OpenMV Cam(或任何通用对象)检测Faces。您的OpenMV Cam可以处理Haar Cascades进行通用对象检测,并配有内置的Frontal Face Cascade和Eye Haar Cascade来检测脸部和眼睛。 眼睛追踪 您可以使用眼动跟踪与您的OpenMV摄像头来检测某人的注视。然后,您可以使用它来控制机器人。眼睛跟踪检测瞳孔的位置,同时检测图像中是否有眼睛。 光流 您可以使用光流来检测您的OpenMV摄像机正在查看的翻译。例如,您可以使用四通孔上的光流来确定其在空气中的稳定性。 QR码检测/解码 您可以使用OpenMV Cam在其视野中读取QR码。通过QR码检测/解码,您可以使智能机器人能够读取环境中的标签。您可以在此处查看我们的视频。 边缘/线路检测 您可以通过Canny Edge Detector算法或简单的高通滤波进行边缘检测,然后进行阈值处理。在您拥有二进制图像后,您可以使用霍夫检测器查找图像中的所有行。通过边缘/线检测,您可以使用OpenMV Cam来轻松检测对象的方向。 模板匹配 您可以使用与OpenMV Cam模板匹配来检测翻译的预先保存的图像何时被视图。例如,可以使用模板匹配来查找PCB上的基准或读取显示器上的已知数字。 图像捕获 您可以使用OpenMV摄像头捕获多达320x240 RGB565(或640x480灰度)BMP / JPG / PPM / PGM图像。您可
STM32MP1是意法半导体(STMicroelectronics)推出的一款高度集成的多核微控制器,它结合了Cortex-A7和Cortex-M4核心。而ThreadX则是一种实时操作系统(RTOS),用于嵌入系统中进行多任务处理。 STM32MP1和ThreadX的结合为嵌入系统提供了强大的处理和多任务处理能力。STM32MP1的Cortex-A7核心可以运行Linux等高级操作系统,提供丰富的应用开发环境,而Cortex-M4核心则负责实时应用程序和低层硬件控制。ThreadX作为RTOS可以管理这些多个任务的执行和资源分配,提供实时性和可预测性。 使用STM32MP1和ThreadX的好处是可以实现复杂的系统设计和功能,同时保持实时响应能力。多核架构可以实现高性能计算,而ThreadX可以保证各个任务的实时性。此外,ThreadX也提供了轻量级的内核,占用较小的存储空间,适合嵌入系统的应用。 对于开发人员来说,使用STM32MP1和ThreadX可以加快开发周期,提高可靠性和稳定性,同时也降低了开发成本。此外,ThreadX还有丰富的特性,如中断处理、任务管理、内存管理、通信和定时器等,方便开发人员进行系统设计和编程。 总之,STM32MP1和ThreadX的结合为嵌入系统提供了强大的处理和多任务处理能力,提高了系统的性能、可靠性和稳定性。它们的广泛应用范围包括工业自动化、智能家居、智能交通等领域,能够满足各种实时要求的嵌入应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值