tag 标签: iMX8MP

相关博文
  • 热度 3
    2024-3-8 11:37
    749 次阅读|
    1 个评论
    B y Toradex 胡珊逢 简介 Verdin iMX8M Plus 具有四个串口,其中 UART3 是用于 A53 核心上的系统如 Linux 的默认调试串口,出于设计需要可能需要将调试口换到其他串口,文章将介绍如何使用 UART1 作调试串口。 硬件介绍 Verdin iMX8M Plus 的四个串口 UART1 ~ UART4 中, UART3 为默认的 A53 调试串口, UART4 为 M7 调试串口,其余两个作为通用 UART 使用。 Verdin 系列的模块均使用 1.8V TTL 电平,在连接外部设备时请先检查电压。本次测试使用的是 Dahlia 底板,在 X20 扩展接口 Pin12 和 Pin13 分别将模块的 UART1_RXD 和 UART1_TXD 引出。四个串口的物理地址如下: UART 起始地址 结束地址 UART1 0x3086_0000 0x3086_FFFF UART2 0x3089_0000 0x3089_FFFF UART3 0x3088_0000 0x3088_FFFF UART4 0x30A6_0000 0x30A6_FFFF 软件修改 调试串口更改的软件涉及到三个部分, ATF 、 U-Boot 和 Linux 。 ATF 会和 U-Boot 等其他文件如 DDR 固件一起打包成用于 NXP i.MX 8M Plus 处理器的启动文件。这些文件的下载和编译请参考 该网页 。文章使用到的完整补丁请从 这里下载 。 ATF ATF 代码的 imx8mp_bl31_setup.c 中,把 RDC_PDAP_UART1 划分到 A53 所在的 D0 域。 --------------------------- --- a/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c +++ b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c @@ -53,7 +53,7 @@ static const struct imx_rdc_cfg rdc = { - MX8MP_PAD_UART3_RXD__UART3_DCE_RX | MUX_PAD_CTRL(UART_PAD_CTRL), - MX8MP_PAD_UART3_TXD__UART3_DCE_TX | MUX_PAD_CTRL(UART_PAD_CTRL), + MX8MP_PAD_UART1_RXD__UART1_DCE_RX | MUX_PAD_CTRL(UART_PAD_CTRL), + MX8MP_PAD_UART1_TXD__UART1_DCE_TX | MUX_PAD_CTRL(UART_PAD_CTRL), }; imx_iomux_v3_setup_multiple_pads(uart_pads, ARRAY_SIZE(uart_pads)); - init_uart_clk(2); + init_uart_clk(0); return 0; } --------------------------- 在 include/configs/verdin-imx8mp.h 将 CONFIG_MXC_UART_BASE 的地址也设置为 UART1 。同时修改 console 。 --------------------------- --- a/include/configs/verdin-imx8mp.h +++ b/include/configs/verdin-imx8mp.h "boot_script_dhcp=" BOOT_SCRIPT "\0" \ - "console=ttymxc2\0" \ + "console=ttymxc0\0" \ "fdt_board=dev\0" \ @@ -111,7 +111,7 @@ #define PHYS_SDRAM_2_SIZE (SZ_4G + SZ_1G) /* UART */ -#define CONFIG_MXC_UART_BASE UART3_BASE_ADDR +#define CONFIG_MXC_UART_BASE UART1_BASE_ADDR /* Monitor Command Prompt */ #define CONFIG_SYS_CBSIZE SZ_2K --------------------------- Linux Linux 的 device tree 同样也需要做修改。在 freescale/imx8mp-verdin-dev.dtsi 中取消 UART1 默认配置下的 RS485 功能。 --------------------------- --- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-dev.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-dev.dtsi /* Verdin UART_1, connector X50 through RS485 transceiver */ &uart1 { + /* linux,rs485-enabled-at-boot-time; rs485-rts-active-low; rs485-rx-during-tx; + */ status = "okay"; }; --------------------------- imx8mp-verdin.dtsi 中更改 stdout-path 调试串口输出至 UART1 ,并删除 RTS 和 CTS 功能引脚。 --------------------------- --- a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi @@ -8,7 +8,7 @@ / { chosen { - stdout-path = &uart3; + stdout-path = &uart1; }; aliases { @@ -891,7 +891,7 @@ &snvs_pwrkey { &uart1 { pinctrl-names = "default"; pinctrl-0 = ; - uart-has-rtscts; + /* uart-has-rtscts; */ }; /* Verdin UART_2 */ @@ -1331,8 +1331,8 @@ pinctrl_sai3: sai3grp { pinctrl_uart1: uart1grp { fsl,pins = - , /* SODIMM 135 */ - , /* SODIMM 133 */ + /* , SODIMM 135 */ + /* , SODIMM 133 */ --------------------------- 修改完毕上述文件后重新编译 flash.bin ( imx-boot )和 device tree 文件,并将其放入支持 Toradex Easy Installer 烧录的镜像文件中。同时也需要修改镜像文件中的 u-boot-initial-env-sd ,将 console 改为 console=ttymxc0 。该文件会在烧录系统时配置 U-Boot 环境变量。安装完镜像后,在 UART1 即可看到启动日志。 总结 通过上述几个文件的修改,可以切换 A53 调试串口。对于 Linux 系统通常建议保留一个调试串口,这将有利于调试和后期其他问题排查。
  • 热度 5
    2024-1-19 14:39
    1653 次阅读|
    0 个评论
    B y Toradex 胡珊逢 简介 在嵌入式Linux设备上常使用Qt作为开发图形界面应用的框架,随着web和移动端图形框架技术快速发展,嵌入式Linux也可以从这些技术中受益。由Google开发的Flutter最初用于Android和iOS应用开发,后期加入web、Windwos桌面和Linux桌面的支持。配合适当的渲染引擎,Flutter也可以运行在嵌入式Linux设备上。文章将介绍如何在使用Linux BSP的Verdin iMX8M Plus上运行Flutter应用。 硬件介绍 本次演示使用基于NXP iMX8M Plus SoC 的计算机模块 Verdin iMX8M Plus 。底板为 Dahlia ,该底板可以直接使用Verdin iMX8M Plus 的 HDMI 显示输出。屏幕则使用支持电容屏的 HDMI 显示器,用于测试 Flutter 应用的交互性。 Flutter介绍 Flutter使用Dart语言开发,可以跨平台运行,支持AOT(Ahead of time)预编译,使应用在设备上更高效地运行。对于Flutter应用,用户通常只需要开发apps代码,Framework、Engine和Embedder都油Flutter SDK提供。使用不同的embedder,Flutter app可以运行在不同的平台上。目前官方支持embedder包括Android,iOS,MacOS、Windwos桌面、Linux桌面、Web浏览器 Linux桌面需要依赖GTK和X11,现在的嵌入式Linux系统已经普遍使用Wayland,例如NXP的iMX处理器在新的BSP已经不再支持X11。对于嵌入式Linux系统,可以使用下面两个非官方的embedder。 Flutter-elinux ,这是由Sony 维护的项目,支持 Arm64 和 X64 处理器。可以使用 Wayland 或者 X11 后台,或者直接基于 DRM。 Flutter-pi 是针对树莓派开发和优化的embbeder,其不依赖于 X11 和 GTK 的任何组件。支持 KMS 和 DRI,3D 硬件加速。可以运行在 ARMv7、ARMv8、x86 处理器上。Flutter-pi 拥有更活跃的社区和开发者。结合 flutterpi_tool 工具可以非常容易地开发flutter 应用。 Verdin iMX8M Plus 的 Linux BSP 支持 KMS,其 CPU 也是 Armv8 架构。因此,我们本次选用 Flutter-pi 作为 embedder。关于 Flutter-elinux 在 Toradex 模块上的应用,可以参考 该文章 。 添加meta-flutter meta-flutter 提供了编译flutter-pi 以及 flutter demo 的文件。meta-flutter 依赖 meta-clang layer。Toradex Linux BSP v6 基于 Yocto Project 的 kirkstone 分支。首先,参考 这里 创建Yocto Project 编译环境。然后进入 layers 文件夹,下载 meta-flutter 和 meta-clang。 $ git clone --branch kirkstone https://github.com/meta-flutter/meta-flutter.git $ git clone --branch kirkstone https://github.com/kraj/meta-clang.git 然后在build/conf/bblayers.conf 文件的 BBLAYERS 中添加 meta-flutter 和 meta-clang 的路径。 BBLAYERS ?= " \ ${BBLAYERS_NXP} \ ... ${TOPDIR}/../layers/meta-clang \ ${TOPDIR}/../layerss/meta-flutter \ " 在build/conf/local.conf 文件的结尾添加以下内容。 DEFAULT_TIMEZONE = "Asia/Shanghai" ENABLE_BINARY_LOCALE_GENERATION = "1" IMAGE_LINGUAS:append = " en-us en-gb es-us zh-cn" GLIBC_GENERATE_LOCALES:append = " en_US.UTF-8 es_US.UTF-8 en_GB.UTF-8 zh_CN.UTF-8" IMAGE_INSTALL:append = " tzdata-core tzdata-asia" DISTRO_FEATURES:append = " opengl wayland pam" PACKAGECONFIG:append:pn-weston = " remoting" PACKAGECONFIG:append:pn-flutter-engine = " profile debug" IMAGE_INSTALL:append = " flutter-auto packagegroup-flutter-test-apps \ flutter-pi flutter-gallery" IMAGE_INSTALL:remove = " packagegroup-tdx-qt5" 删除meta-flutter/recipes-platform/packagegroups/ packagegroup-flutter-test-apps.bb 中的 flutter-test-texture-egl。最后编译 tdx-reference-multimedia-image 镜像文件。 $ bitbake tdx-reference-multimedia-image 测试Flutter 应用 禁用自启动的weston 服务。 root@verdin-imx8mp:~# systemctl stop weston.service root@verdin-imx8mp:~# systemctl disable weston.service 镜像中的/usr/share/flutter/gallery/3.16.5/release 中已经包含一个 flutter gallery 应用,现在可以使用 flutter-pi 直接运行。 root@verdin-imx8mp:# cd /usr/share/flutter/gallery/3.16.5/release root@verdin-imx8mp:# flutter-pi --release ./ 在HDMI 显示器上可以看到 gallery 应用的界面。 安装Flutter SDK 和 flutterpi_tool 在Linux 电脑(例如 Ubuntu 23.04)上,首先安装 Flutter SDK。由于 Flutter 和 flutter-pi 两个项目更新都比较活跃,在安装前需求确认 Flutter 版本。在 这里 查看flutter-pi 目前使用的 Flutter 版本。例如撰写文章时其为 3.16.7。在 Flutter SDK 手动安装页面 选择对应的版本进行安装,如flutter_linux_3.16.7-stable.tar.xz。 $ sudo apt-get install clang cmake git ninja-build \ pkg-config libgtk-3-dev liblzma-dev libstdc++-12-dev $ cd FLUTTER_SDK_INSTALL_PATH $ tar vxf flutter_linux_3.16.7-stable.tar.xz $ export PATH="$PATH:`pwd`/flutter/bin" $ flutter doctor -v 上面的flutter 环境诊断工具如果提示缺少 chrome 浏览器,可以安装后再运行。 $ sudo dpkg -i google-chrome-stable_current_amd64.deb $ flutter doctor -v 检查flutter 和 dart 命令是否都来自同一个的 SDK 安装目录。 $ which flutter dart /home/ben/flutter-sdk/flutter/bin/flutter /home/ben/flutter-sdk/flutter/bin/dart 安装完Flutter SDK 后使用下面命令安装 flutterpi_tool $ flutter pub global activate flutterpi_tool $ export PATH="$PATH":"$HOME/.pub-cache/bin" 使用下面命令测试 $ flutterpi_tool --help 如果已经安装好Flutter SDK 和 flutterpi_tool,需要编译其他 flutter 应用时,只需要进入之前 Flutter SDK 的安装目录后执行下面命令,重新配置编译环境即可。 $ cd FLUTTER_SDK_INSTALL_PATH $ export PATH="$PATH:`pwd`/flutter/bin" $ export PATH="$PATH":"$HOME/.pub-cache/bin" 使用flutterpi_tool 编译应用 借助flutterpi_tool 可以非常简单的编译 flutter 应用,例如针对 64 位 Arm CPU 的编译命令 flutterpi_tool build --arch=arm64 --cpu=pi4 --release ,参数说明如下: 参数 说明 Runtime mode --debug Build for debug mode. --profile Build for profile mode. --release Build for release mode. --debug-unoptimized Build for debug mode and use unoptimized engine. (For stepping throughengine code) Target,--arch= arm Build for 32-bit ARM. (armv7-linux-gnueabihf) arm64 Build for 64-bit ARM. (aarch64-linux-gnu) x64 Build for x86-64. (x86_64-linux-gnu) Target,--cpu= generic (default) Don’t use a tuned engine. The generic engine will work on all CPUs of the specified architecture. pi3 Use a Raspberry Pi 3 tuned engine. Compatible with arm and arm64. (-mcpu=cortex-a53+nocrypto -mtune=cortex-a53) pi4 Use a Raspberry Pi 4 tuned engine. Compatible with arm and arm64. (-mcpu=cortex-a72+nocrypto -mtune=cortex-a72) 下面是在Linux电脑上编译flutter gallery应用。由于Verdin iMX8M Plus是基于arm64的Cortex-A53 CPU,因此选择--arch=arm64和--cpu=pi3两个参数。 $ git clone https://github.com/flutter/gallery.git flutter_gallery $ cd flutter_gallery/ $ git checkout 6a8d738c94d0710e229d726729c09fdb5ccaf7ed $ flutter pub get $ flutterpi_tool build --arch=arm64 --cpu=pi3 --release 编译结束后,在build/flutter_assets 目录下可以看到如下文件。 build/flutter_assets/ ├── app.so ├── AssetManifest.bin ├── AssetManifest.json ├── FontManifest.json ├── fonts ├── icudtl.dat ├── libflutter_engine.so ├── NOTICES.Z ├── packages └── shaders flutteri_tool 目前使用新的编译方法生成的文件结构尚不能直接使用 flutter_pi 在设备上直接运行,需要重新调整文件位置,参考 Verdin iMX8M Plus 上的 /usr/share/flutter/gallery/3.16.5/release 的内容。 release/ ├── data │ ├── flutter_assets │ └── icudtl.dat └── lib ├── libapp.so └── libflutter_engine.so 在flutter_gallery/build/flutter_assets/ 目录创建 data 和 lib 两个文件夹,app.so 重命名为 libapp.so 后和 libflutter_engine.so 一起移动到 lib 目录。icudtl.dat 移动到 data 目录下。在 data 目录下创建 flutter_assets 文件夹后,将 build/flutter_assets/ 中剩余的 AssetManifest.bin,AssetManifest.json,FontManifest.json,fonts,NOTICES.Z,packages 和 shaders 均移动到 data/flutter_assets 中。完场后将 data 和 lib 两个目录复制到 Verdin iMX8M Plus 上的 /home/root/flutter_gallery 目录中,例如使用 scp 命令。 $ scp -r build/flutter_assets/ root@imx8mp_ip:/home/root/flutter_gallery 复制好文件后可以在Verdin iMX8M Plus 上的 /home/root/flutter_gallery 看到以下内容。 root@verdin-imx8mp-07320826:~/flutter_gallery# ls * data: flutter_assets icudtl.dat lib: libapp.so libflutter_engine.so 运行下面命令即可启动在电脑上编译的flutter 应用。 root@verdin-imx8mp:~# flutter-pi --release /home/root/flutter_gallery/ 总结 使用Flutter 可以开发跨平台应用,并获得流畅的本地运行体验,在移动端和 Web 端都有广泛的应用。但是针对嵌入式 Linux 的 embedder 目前是第三方维护的,所以在实际应用时需要做详尽的测试。 ​
  • 热度 4
    2023-9-14 09:09
    409 次阅读|
    0 个评论
    飞凌嵌入式OKMX8MP-C开发板 有两路原生CAN总线,但用户在开发产品时可能需要用到更多的CAN,这该如何解决呢?今天小编将为大家介绍一种SPI转CAN的方法,供各位工程师小伙伴参考。 说明 OKMX8MP-C核心板有两路原生的SPI总线,目前是将SPI1的引脚用作了LED和UART3的功能,SPI2做成了正常的SPI2接口。此处以SPI2转CAN为例,移植SPI转CAN芯片; SPI转CAN芯片型号为:MCP2518,这款芯片可转出CAN-FD,若只需要CAN功能,可参照该方式移植MCP2515或其他芯片; 本次移植的MCP2518芯片驱动来源是i.MX8MQ的源码(处理器中默认移植MCP2518芯片)。 0 1 移植MC2518芯片驱动 在 OK8MP-linux-kernel/drivers/net/can/spi/ 路径下创建一个文件夹—— mcp25xxfd ,将相关文件(包含.c文件、.h文件、Makefile、Kconfig等)放置到此文件夹中。 0 2 补全对can_rx_offload_add_manual函数的定义 vi OK8MQ-linux-kernel/include/linux/can/rx-offload.h 添加: int can_rx_offload_add_manual ( struct net_device*dev, struct can_rx_offload *offload, unsigned int weight ) vi OK8MQ-linux-kernel/drivers/net/can/rx-offload.c 添加: int can_rx_offload_add_manual ( struct net_device*dev, struct can_rx_offload *offload, unsigned int weight ) { if mailbox_read) return -EINVAL; return can_rx_offload_init_queue(dev, offload, weight); } EXPORT_SYMBOL_GPL(can_rx_offload_add_manual); 0 3 修改上一级目录spi/下的Makefile和Kconfig vi OK8MP-linux-kernel/drivers/net/can/spi/Makefile 添加: obj-y += mcp25xxfd/ vi OK8MP-linux-kernel/drivers/net/can/spi/Kconfig 添加: source "drivers/net/can/spi/mcp25xxfd/Kconfig" 0 4 修改驱动配置文件,将MCP2518编译进内核 vi OK8MP-linux-kernel/arch/arm64/configs/OK8MP-C_defconfig 找到: CONFIG_CAN_MCP251X=y 改为: # CONFIG_CAN_MCP251X is not set 添加: CONFIG_CAN_MCP25XXFD=y 0 5 在设备树中配置时钟 vi OK8MP-linux-kernel/arch/arm64/boot/dts/freescale/OK8MP-C.dts 添加: clocks{ mcp2518fd_clock : mcp2518fd_clock{ compatible = "fixed-clock"; #clock-cells = ; clock-frequency = ; }; }; 0 6 找一个引脚用作芯片的中断引脚 此处是将 GPIO4_IO21用作了中断引脚。 vi OK8MP-linux-kernel/arch/arm64/boot/dts/freescale/OK8MP-C.dts 添加: pinctrl_ecspi2_can : ecspi2can{ fsl,pins = < MX8MP_IOMUXC_SAI2_RXFS__GPIO4_IO21 0x40000 ; }; 0 7 在设备树的ecspi2节点中进行修改 vi OK8MP-linux-kernel/arch/arm64/boot/dts/freescale/OK8MP-C.dts 从: &ecspi2{ #address-cells= < 1 ; #size-cells= < 0 ; fsl,spi-num-chipselects= < 1 ; pinctrl-names="default"; pinctrl-0= < &pinctrl_ecspi2 & pinctrl_ecspi2_cs ; cs-gpios= < &gpio5 13 GPIO_ACTIVE_LOW ; status="okay"; spidev1:spi@0{ reg= < 0 ; compatible="rohm,dh2228fv"; spi-max-frequency= < 500000 ; }; }; 改为: &ecspi2{ #address-cells= < 1 ; #size-cells= < 0 ; fsl,spi-num-chipselects= < 1 ; pinctrl-names="default"; pinctrl-0= < &pinctrl_ecspi2 & pinctrl_ecspi2_cs & pinctrl_ecspi2_can ; cs-gpios= < &gpio5 13 GPIO_ACTIVE_LOW ; status="okay"; mcp1:mcp2518fd@0{ compatible="microchip,mcp2518fd"; reg= < 0 ; spi-max-frequency= < 20000000 ; clocks= < &mcp2518fd_clock2 ; interrupts-extended= < &gpio4 21 IRQ_TYPE_LEVEL_LOW ; }; }; 完成上述修改后即可进行编译,并用新生成的镜像烧写 OKMX8MP-C 开发板。 0 8 开发板验证 将MCP2518芯片接到SPI2的接口上,启动OKMX8MP-C开发板,启动后使用ifconfig -a命令查看,即可看到多出了1个CAN节点。 节点生成后,即可按照用户使用手册 【 4.18 FlexCAN测试】 章节进行测试,验证功能是否正常。 用户使用手册下载链接: https://pan.baidu.com/s/1TY4R5BrAnjAuTTJj9fNGWw 提取码: 7qc8
  • 热度 7
    2023-7-14 11:39
    1266 次阅读|
    0 个评论
    B y Toradex 胡珊逢 LVGL (Light and Versatile Graphics Library) 是一个轻量级的开源图形库,采用 C 或者 MicroPython 语言开发。可以在资源有限的 MCU 上轻松地绘制图形界面。 Verdin iMX8M Plus 模块的处理器除了 Cortex-A53 核心外,还具有一个 Cortex-M7 核心,其可以运行诸如 FreeRTOS 的实时操作系统。本文接下来就将介绍如何移植 LVGL 到 Verdin iMX8M Plus 的 Cortex-M7 核上。 本次演示采用一块 SPI 接口的 LCD , 屏幕控制器为 ILI9341 。除了 VCC 、 GND 和背光外 , 和 Verdin iMX8M Plus 连接的引脚主要有下面四个。 ILI9341 Verdin iMX8M Plus CS SPI 片选 ECSPI1_SS0 SODIMM202 RESET 复位 GPIO1_IO001 SODIMM208 DC 命令 / 数据 GPIO1_IO00 SODIMM206 MOSI SPI MOSI ECSPI1_MOSI SODIMM200 SCK SPI 时钟 ECSPI1_SCLK SODIMM196 表一: Verdin iMX8M Plus 连接 ILI9341 注意 Verdin iMX8M Plus 的 SoC 使用 1.8V IO ,在连接 SPI LCD 时需要使用 3.3V – 1.8V 电压转换电路。 LVGL 库分为两部分。 第一部 分是图形实现,包括绘制各类形状、色彩管理、动画事件、定时器等, 第二部 分是硬件驱动实现 lvgl_drivers 。 LVGL 将每一帧绘制好的图片数据保存在 RAM 中 , lvgl_drivers 负责将数据传输到外部显示设备。 lvgl_drivers 支持多种显示器 , 如 TFT 、电子墨水屏、 OLED 等。 这里 是 lvgl_drivers 支持的常见显示控制器。 LVGL 移植时通常只需要修改 lvgl_drivers 。例如在本次演示使用了 SPI 接口的 显示屏。 Verdin iMX8M Plus 可以提供连接显示屏所需的 SPI Master 功能。移植任务主要是适配 lvgl_drivers 中 ILI9341 的 SPI 数据传输以及 LVGL 图形库的几个重要定时任务。 首先 安装 iMX8M Plus M7 开发所需的 SDK , 如 SDK_2_12_1_MIMX8ML8xxxKZ 。将 该工程 下载到 SDK 安装目录的 SDK_2_12_1_MIMX8ML8xxxKZ/boards/evkmimx8mp/rtos_examples/freertos_ecspi/ 位置。这个工程已经包含了下面提到的修改内容。 在工程目录的 armgcc/CmakeLists.txt 添加 lvgl 和 lvgl_drivers 。这里指定 v8.3.7 , 其他的版本可能发生 API 变更 , 需要做对应的修改。设置 lvgl 和 lvgl_drivers 的 github 下载源。 --------------------------------------- # Fetch LVGL from GitHub FetchContent_Declare(lvgl GIT_REPOSITORY https://github.com/lvgl/lvgl.git GIT_TAG v8.3.7) FetchContent_MakeAvailable(lvgl) FetchContent_Declare(lv_drivers GIT_REPOSITORY https://github.com/lvgl/lv_drivers GIT_TAG v8.3.0) FetchContent_MakeAvailable(lv_drivers) --------------------------------------- 将 lvgl::lvgl 和 lvgl::drivers 编译到工程中。 --------------------------------------- target_link_libraries(${MCUX_SDK_PROJECT_NAME} PRIVATE lvgl::lvgl lvgl::drivers) --------------------------------------- 在 add_executable(${MCUX_SDK_PROJECT_NAME} 添加下面两个头文件。 --------------------------------------- "${ProjDirPath}/../lv_drv_conf.h" "${ProjDirPath}/../lv_conf.h" --------------------------------------- 设置变量 LV_CONF_PATH , 这是 lvgl 的配置文件 lv_conf.h , 里面包含屏幕分辨率和 lvgl 图形库参数。 --------------------------------------- # Specify path to own LVGL config header set(LV_CONF_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../lv_conf.h CACHE STRING "" FORCE) --------------------------------------- FETCHCONTENT_UPDATES_DISCONNECTED 允许每次编译的时候不必重新下载 lvgl 代码。 --------------------------------------- SET(FETCHCONTENT_UPDATES_DISCONNECTED ON) --------------------------------------- 在工程目录下的 lv_conf.h 设置 SPI TFT 屏幕分辨率 240*320 。 --------------------------------------- #define LV_HOR_RES_MAX 240 #define LV_VER_RES_MAX 320 --------------------------------------- 在工程目录下的 lv_drv_conf.h 设置 LVGL 硬件驱动相关参数。 LV_DRV_DELAY_US() 和 LV_DRV_DELAY_MS() 需要在自己的代码中实现(位于 freertos_ecspi_loopback.c )。 --------------------------------------- /********************* * DELAY INTERFACE *********************/ #define LV_DRV_DELAY_INCLUDE /*Dummy include by default*/ #define LV_DRV_DELAY_US(us) LVGL_DELAY_MS((1)) /*Delay the given number of microseconds*/ #define LV_DRV_DELAY_MS(ms) LVGL_DELAY_MS((ms)) /*Delay the given number of milliseconds*/ --------------------------------------- 延时函数在每个平台上的实现方法都不同 , 有的可以使用 while() 或 for() 循环 , 在运行操作系统的平台上可以利用系统提供的 API , 例如 Verdin iMX8M Plus M7 的 FreeRTOS 中使用 vTaskDelay() 。 --------------------------------------- void LVGL_DELAY_MS(uint8_t ms) { vTaskDelay( ms / portTICK_PERIOD_MS ); } --------------------------------------- SPI TFT LCD 采用了 ILI9341 控制器,因此设置 USE_ILI9341 宏定义,以及分辨率参数。 --------------------------------------- #ifndef USE_ILI9341 # define USE_ILI9341 1 #endif # define LV_HOR_RES 240 # define LV_VER_RES 320 --------------------------------------- 除了上面的延时函数外 , 用于控制 ILI9341 数据 / 命令引脚 的 LV_DRV_DISP_CMD_DATA() 、复位 ILI9341 的 LV_DRV_DISP_RST() 和 SPI 传输一个字节、多个字节的函数 s pi_transaction_one_byte() , spi_transaction_array () 也需要自己实现。在 lv_drv_conf.h 里定义 lv_diplay_cmd_data() 和 lv_diplay_reset() 。 --------------------------------------- #define LV_DRV_DISP_INCLUDE /*Dummy include by default*/ #define LV_DRV_DISP_CMD_DATA(val) lv_diplay_cmd_data((val)) /*Set the command/data pin to 'val'*/ #define LV_DRV_DISP_RST(val) lv_diplay_reset((val)) /*Set the reset pin to 'val'*/ --------------------------------------- 由于 iMX8M Plus 的 SPI 在收发时会自动控制 CS 引脚,因此 LV_DRV_DISP_SPI_CS(val) 可以设置为空函数。 --------------------------------------- #define LV_DRV_DISP_SPI_CS(val) /*spi_cs_set(val)*/ /*Set the SPI's Chip select to 'val'*/ #define LV_DRV_DISP_SPI_WR_BYTE(data) spi_transaction_one_byte((data))/*spi_wr(data)*/ /*Write a byte the SPI bus*/ #define LV_DRV_DISP_SPI_WR_ARRAY(adr, n) spi_transaction_array((adr), (n))/*spi_wr_mem(adr, n)*/ /*Write 'n' bytes to SPI bus from 'adr'*/ --------------------------------------- 在 freertos_ecspi_loopback.c 中实现 lv_diplay_cmd_data() , lv_diplay_reset() , spi_transaction_one_byte() , spi_transaction_array() 。 --------------------------------------- void lv_diplay_cmd_data(uint8_t val) { GPIO_PinWrite(GPIO_PAD, LCD_CMD_DATA, val); } void lv_diplay_reset(uint8_t val) { GPIO_PinWrite(GPIO_PAD, LCD_RESET, val); } --------------------------------------- LCD_CMD_DATA 和 LCD_RESET 分别定义如下 , 用于控制 ILI9341 的 命令 / 数据和复位引脚。 --------------------------------------- #define GPIO_PAD GPIO1 #define LCD_CMD_DATA 0U #define LCD_RESET 1U --------------------------------------- SPI 数据传输采用列队形式发送。 spi_transaction_one_byte() 和 spi_transaction_array() 均采用 xQueueSend() 将需要发送的数据加入到 spi_queue 列队中 , 该列队长度为 128 字节。然后运行一个高优先级的任务 ecspi_task() 将数据从列队中通过 ECSPI_RTOS_Transfer() 发送到 ILI9341 控制器。由于发送数据的任务优先级高于写入列队的,所以 spi_queue 列队中保存的数据会被很快发送出去。 --------------------------------------- void spi_transaction_one_byte(uint8_t data) { BaseType_t xStatus; uint32_t data_to_queue; data_to_queue = (uint32_t)data; xStatus = xQueueSend(spi_queue, &data_to_queue, portMAX_DELAY); if( xStatus != pdPASS ) { PRINTF( "Could not send to the queue.\r\n" ); } } --------------------------------------- 本演示中,采用不同优先级的任务来实现相应的工作。优先级数字越大便是优先级越高。为了保证 SPI 及时发送到 ILI9341 ,将其设置为最高优先级。 任务函数 优先级 功能描述 draw_lvgl_ui 2 LVGL UI lv_task_hander_task 1 调用 lv_task_handler init_task 3 SPI 、 lv_init, hal_init 初始化 ecspi_task 4 发送 SPI 数据到 ILI9341 vApplicationTickHook executed every tick 调用 lv_tick_inc 表二: FreeRTOS 任务描述 draw_lvgl_ui() 中 绘制 需要显示的 LVGL UI 内容 , 本 演示中将显示一个动态伸缩变化的彩色柱。 lv_task_hander_task() 将每隔 5ms 调用 lv_task_handler() ,该函数会每 5ms 处理 lvgl 相关任务。 init_task() 中完成 SPI 、 ILI9341 的初始化,以及 LVGL 图形库的相关初始化。为了防止在初始化完成前调用 lv_task_handler 和 UI 绘制 , 该任务运行时 使用 vTaskSuspend 暂时停止 draw_lvgl_ui 和 lv_task_hander_task 两个任务。但 ecspi_task 继续运行 。 --------------------------------------- void init_task(void *pvParameters) { vTaskSuspend(xUITaskHandle); //suspend ui task untill init task finisded. vTaskSuspend(xLVTaskHandle); spi_init(); ili9341_init(); lv_init(); hal_init(); PRINTF("Init finised. resume xUI and XLV tasks\r\n"); vTaskResume(xUITaskHandle); vTaskResume(xLVTaskHandle); --------------------------------------- vApplicationTickHook 并不是一个单独的 FreeRTOS 任务 , 而是在每个 tick 都会被执行。因此 , lv_tick_inc 将在每 2ms 运行。该函数向 LVGL 动画和其他任务提供已经运行的时间 信息 , 需要保证其运行的准确性和粒度。 --------------------------------------- void vApplicationTickHook(void) { static uint32_t ulCount = 0; ulCount++; = 2UL) { lv_tick_inc(2); //calling every 2 milliseconds. ulCount = 0UL; } } --------------------------------------- 修改 FreeRTOSConfig.h 中的下面参数,实现每个 TICK 为 1ms ,以及启用 上面提到的 TICK_HOOK 。 --------------------------------------- #define configTICK_RATE_HZ ((TickType_t)1000) #define configUSE_TICK_HOOK 1 --------------------------------------- 由于 LVGL 运行需要较大的 RAM 空间 , 因此该演示 的 M7 固件 会被加载到 DDR RAM 上运行。在编译的时候使用 build_ddr_release.sh 脚本。 --------------------------------------- export ARMGCC_DIR=/opt/gcc-arm-none-eabi-10.3-2021.10 cd armgcc ./build_ddr_release.sh --------------------------------------- 在 U-Boot 里面设置 m7bootddr 参数,将上面编译好的 M7 固件加载到地址为 0x80000000 的 DDR RAM 中。 --------------------------------------- Verdin iMX8MP # print m7bootddr m7bootddr=tftp 0x80000000 m7.bin; dcache flush; bootaux 0x80000000 --------------------------------------- 启动时在 U-Boot 中运行下面命令。 --------------------------------------- run m7bootddr --------------------------------------- 运行效果如下。 ​ 总结 本文介绍为 Verdin iMX8M Plus M7 移植 LVGL 的步骤和创建对应 FreeRTOS 任务。在项目中需要 为 实际使用的外设和业务设置合适的任务优先级,保证图形流畅显示以及数据及时处理。 在 device tree 也需要把 M7 所使用的外设禁用,避免和 L inux 系统的冲突。
  • 热度 5
    2023-4-10 11:45
    887 次阅读|
    0 个评论
    机器人大致可分为工业机器人、服务机器人和特种机器人,虽然相较于前两类机器人而言特种机器人的市场规模最小,但随着新一轮的科技和产业变革的加速演进,5G和人工智能与机器人技术深度融合,这让特种机器人的应用场景不断拓宽,在各行各业中发挥着的作用也愈加关键。今天小编就为大家介绍一种用于替代人工对设备进行检查和维护的特种机器人——智能巡检机器人。 01 智能巡检机器人 在城市快速发展的过程中,越来越多的管道被铺设在地下,如此大面积的地下管廊该如何快速而精准的维护呢?考虑到地下管廊环境复杂并且具有一定的危险性,地下空间智能巡检机器人便应运而生,可以为地下管廊加装智能机器人巡检监测系统和处置系统,构建智慧运维软件平台,实现对该空间内的基础属性做常态化的检测,来保证设施的正常运转。 智能巡检机器人一般分为三大部分——机器人运行部分、物联传感部分和应用部分,分别用来“保障机器人的正常运行”、“感知地下空间”以及“对物联传感部分采集到的数据进行处理和响应”。 02 功能需求 某特种机器人研发制造厂商希望推出一款具有强悍功能的智能巡检机器人产品,产品特点及功能需求如下: (1) 实时检测及环境监测 机器人系统能够通过高清摄像头实时监视现场环境,通过外接温、湿度传感器等来采集设备现场的湿度温度、有害气体浓度等信息,通过4G、5G上传至云端; (2) 全自动巡检 根据自身时间设定或云端远程控制,通过GPS和5G实时定位巡检机器人的位置来实现日常例行任务和特训两种方式的巡检; (3) 自动充电,低电自动返航 能够自主判断电池电量状态,电量不足自动返航,并与充电设备配合完成自主充电; (4) 自主避障功能 机器人在监测的过程中通过加入NPU机器视觉,对摄像头采集数据进行识别并区分是否存在轨道障碍物和管道障碍物,即时停止并上传报警信息; (5) 自动生成巡检监测报告 将此次巡检采集信息整理,经过CPU简化处理后出具现场状态的巡检监测报告,将现场数据可视化。 03 选型方案 经过多轮测试,该厂商最终选择将飞凌嵌入式FETMX8MP-C核心板作为这款智能巡检机器人产品的主控平台,以满足客户对机器视觉和高速接口的需求。 FETMX8MP-C核心板基于NXP i.MX 8M Plus高性能处理器打造,拥有四个Arm® Cortex-A53处理器,主频高达1.6GHz,能够高效处理巡检采集的信息; 内置NPU,AI计算能力达到了2.3TOPS,大大提高了神经网络的计算速度和能效比,可以更好地实现主动避障功能; FETMX8MP-C核心板在视频处理方面也有相当明显的优势,它支持H.265/H.264 1080P60fps视频编码,可以带来更高效的视频压缩、更高质量的视频播放和更广泛的应用场景; 同时还拥有高稳定性,可在-40℃~+85℃严苛工业环境长时间运行,适应各种场景的应用; 此外,还支持Linux5.4.0/Android11高版本、高稳定性的操作系统,驱动更加完善,系统源码开放,可以让客户快速进入产品测试阶段。