NXP i.MX8M Plus Cortex-M7应用开发详解

 2025-5-28 15:15:28     作者:刘乾坤     联系作者    

 1、概述

i.MX8M Plus是NXP推出的异构多核处理器,配置了主频高达1.6GHz的四核ARM Cortex-A53和一颗运行速度800MHz、带硬件浮点运算的MCU——ARM Cotex-M7内核。本文将基于英创的i.MX8M Plus主板ESM8400,详细介绍NXP i.MX8M Plus Cortex-M7程序的开发方法,包括开发环境搭建,如何编译/调试,以及如何自动启动MCU应用程序等内容。

1.png

ESM8400是英创基于i.MX8M Plus处理器开发的64位高性能工控主板,与市面上其他i.MX8M Plus核心板不同,ESM8400直接支持4网口、7串口、同时板载了独立硬件RTC,独立的触摸驱动芯片等必要外设。ESM8400除支持基于Linux-6.6.x内核的多种文件系统,包括Yocto Rootfs、Ubuntu以及Debian桌面系统外,还独家支持Windows 10 IoT企业版操作系统。


 2、MCU SDK

NXP提供的 MCU SDK是一个综合的软件开发包,其中包含了i.MX8M系列处理器MCU初始化代码,外设驱动程序,已经移植好的FreeRTOS操作系统和多核通讯协议栈RPMsg等。

2.png

图 1:NXP MCU SDK Layers

       

MCU SDK包含了对基于i.MX8M系列处理器的多个主板的支持,各主板对应的硬件定义和例程位于<install_dir>/boards/<board_name>目录中。

3.png

图 2:boards目录


evkmimx8mp是NXP i.MX8M Plus官方评估板,我们根据ESM8400的硬件资源,在参考evkmimx8mp的基上,对代码结构和封装进行了进一步优化,在<install_dir>/boards下创建了esm8400_m7目录, 基于esm8400_m7目录,用户可以更加简便、快速的进行m7程序开发。

esm8400_m7目录内容及简要说明如下:

4.png

esm8000_m7目录中除包含demo_apps、driver_examples、drivers、multicore_examples 4个子目录外,还包含以下公共文件:    

l   board.c/h: board.h包含了ESM8400在M7侧所有可用的硬件资源宏定义,包括调试串口、SPI、PWM、可用的GPIO资源等。board.c中包含了各硬件外设的时钟及RDC初始化代码。

l  clock_freq.c/h:包含了封装好的用于设置和获取外设当前时钟频率的功能函数。

l  ESM8400_*.ld:ARM GCC链接文件,配置M7程序的CODE及DATA段。

l  pin_mux.c/h:CPU管脚的复用设置。

l  utilities.c/h:一些有用的实例程序,比如CPU使用率统计等。

ESM8400_m7下的所有examples和demo都将引用上述公共文件,所以一般不建议修改。


 3、M7软件开发环境搭建

i.MX8M Plus Cortex-M7应用程序开发与普通的Cortex-M7单片机程序的开发完全一样,本文仅以使用ARM GCC工具链为例,对开发环境的搭建进行说明。


3.1 Win10 安装Linux子系统 

<install_dir>/boards/esm8400_m7下的例子程序是在Win10的Linux子系统(WSL)环境下编译测试的,使用的Linux版本为Ubuntu 18.04,如果用户已经有了Linux开发主机,请跳过此小节。

Win10安装Linux子系统请参考:https://docs.microsoft.com/zh-cn/windows/wsl/


3.2 Win10 安装ARM GCC及CMake 

l  根据所用开发主机的操作系统,下载对应的GUN Arm Embedded工具链,下载地址:https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads 。这里以64位Win10操作系统下的Ubuntu 18.04 Linux子系统举例 ,下载对应的工具包gcc-arm-none-eabi-10-2020-q4-major-x84_64-Linux.tar.bz2到D盘根目录。

5.png

l  解压tarball,执行:

sudo tar xjf /mnt/d/gcc-arm-none-eabi-10-2020-q4-major-x86_64-Linux.tar.bz2 -C /usr/share

l  建软链接,执行:

sudo ln -s /usr/share/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gcc  /usr/bin/arm-none-edbi-gcc

sudo ln -s /usr/share/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-g++  /usr/bin/arm-none-edbi-g++

sudo ln -s /usr/share/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gdb  /usr/bin/arm-none-edbi-gdb

sudo ln -s /usr/share/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-size  /usr/bin/arm-none-edbi-size

l  可通过--version命令查看gcc版本:arm-none-edbi-gcc --version

l  安装CMake,执行:sudo apt-get install cmake


3.3 使用ARM GCC编译Hello_world 

解压英创提供的SDK_1.0.0_ESM8400-MCU.tar.gz软件包,在编译任何工程之前,需要先设置一次编译工具链的环境变量,执行:

export ARMGCC_DIR=/usr/share/gcc-arm-none-eabi-10-2020-q4-major

接下来就可编译SDK中的例程了,进入<install_dir>/boards/esm8400_m7/demo_apps/ hello_world/armgcc目录:

执行./build_realse.sh,编译工具将基于ESM8400_tcm.ld文件在armgcc目录下自动创建release子目录,并在其下生成在ESM8400 TCM上运行的hello_world.bin文件。

执行./build_ddr_realse.sh,编译工具将基于ESM8400_ddr_ram.ld在armgcc目录下自动创建ddr_release子目录,并在其下生成在ESM8400 DDR上运行的hello_world.bin文件。


3.4 在WSL2中编译vs在Windows文件系统中编译 

WSL2使用了最新的虚拟技术在经量化的虚拟机中运行Linux内核,WSL2在多个方面与微软最初推出的WSL1相比都更具优势,但除了跨操作系统文件系统性能。详细说明请参考:https://docs.microsoft.com/zh-cn/windows/wsl/compare-versions

我们将MCU SDK分别解压到WSL2 Linux文件系统中和Windows文件系统中进行测试,与将文件存放在Windows中跨文件系统编译相比,把文件存放在WSL中直接编译速度要快5倍以上。


 4、运行i.MX8M plus Cortex-M7应用程序

在M7程序开发过程中,可利用U-Boot直接加载并运行编译好的M7应用程序,通过PRINTF输出打印信息来调试应用程序。程序发布时可利用Linux的flash_opt工具,将要发布的M7应用程序bin文件固化到系统eMMC中,U-Boot在启动时会先自动启动M7程序,再启动Linux系统。


4.1 硬件连接 

最基本的需要连接并配置好网络、连接ESM8400控制台串口(调试串口)和给系统提供电源。ESM8400的UART2为M7程序的调试串口,在M7程序中调用PRINTF将从此串口输出信息。UART2缺省配置为RS232电平,通讯格式与ESM8400的控制台串口完全一样,默认为115200-8-N-1。为了查看M7输出的打印信息,需要再用一条串口线将ESM8400开发评估底板上的UART2与开发主机的串口相连。


4.2 在U-boot中通过TFTP下载并运行M7应用程序 

安装TFTP Server

用户可以在开发主板上选择自己熟悉的TFTP Server工具,这里以在Win10下使用Tfptd64配置为例,只需要设置好目录,就可以使用TFTP服务了。(可能需要合理配置开发主机的防火墙)

启动Tfptd64,点击Setting,在TFTP界面点击Browse设置TFTP目录。Tfptd64支持直接选择WSL系统下的文件目录,这里直接选择SDK安装目录下的boards文件夹:<install_dir>/boards。

6.png

通过U-boot在TCM上运行M7应用程序

TCM(Cortex-M Core’s Tightly Coupled Memory)是i.MX8M Plus CPU片内为Cortex-M内核使用的一块专用内存,包含128KBytes的代码存储空间(CODE)和128KBytes运行内存空间(DATA)。连接好网线、ESM8400控制终端串口(这里连接到开发主机的COM1)、M7调试串口(这里连接到开发主机的COM3),短接开发评估底板上的JP1,以便让ESM8400运行在调试模式,然后给ESM8400上电,在开发主机COM1串口工具上按空格键进入ESM8400 U-boot,依次执行如下命令:

a.       setenv serverip 192.168.201.211     // 设置TFTP Server IP地址(开发主板IP地址)

b.       setenv ipaddr 192.168.201.213       // 设置ESM8400 网口IP地址(与开发主机同一网段)

c.        saveenv  // 可以使用saveenv命令保存环境变量,系统下次启动时就不需要重复设置IP地址了。

d.       tftp 0x48000000 esm8400_m7/demo_apps/hello_world/armgcc/release/hello_world.bin    // 从开发主机上下载hello_world.bin到ESM8400内存中

e.      cp.b 0x48000000 0x7e0000 ${filesize}  // 将下载的内容copy到i.MX8M Plus的TCM

f.        bootaux 0x7e0000      // 从TCM启动M7程序

 7.png

如果程序正常启动运行,在开发主机的COM3口上(连接到了M7的调试串口ESM8400-UART2) 可以看到程序运行时输出的Hello World! 信息。

8.png

通过U-boot在DDR上运行M7应用程序

连接好网线、ESM8400控制终端串口(这里连接到开发主机的COM1)、M7调试串口(这里连接到开发主机的COM3),短接开发评估底板上的JP1,以便让ESM8400运行在调试模式,然后给ESM8400上电,在开发主板COM1串口工具上按空格键进入ESM8400 U-boot,依次执行如下命令:

·  DDR

a.       setenv serverip 192.168.201.211     // 设置TFTP Server IP地址(开发主板IP地址)

b.       setenv ipaddr 192.168.201.213       // 设置ESM8400 网口IP地址(与开发主机同一网段)

c.        saveenv  // 可以使用saveenv命令保存环境变量,系统下次启动时就不需要重复设置IP地址了。

d.       tftp 0x80000000 esm8400_m7/demo_apps/hello_world/armgcc/ddr_release/hello_world.bin    // 从开发主机上下载hello_world.bin到ESM8400内存中

e.       bootaux 0x80000000       //从系统DDR 0x80000000地址启动M7程序


4.3 M7程序固化及开机自动运行 

如前所述,M7程序可以加载到i.MX8M Plus的TCM或系统DDR中运行,各个memory区域提供的程序CODE和DATA空间如下表所示:

配置

CODE

DATA

A53   & M7 Sheard Memory

CoreMark

TCM

128K

(007E0000-007FFFFF)

128K

(00800000-0081FFFF)

16M

(80000000-0x80FFFFFF)

2322.88

DDR

2MB

(80000000-801FFFFF)

2MB

(80200000-803FFFFF)

12M

(80400000-0x80FFFFFF)

2354.88

M7程序运行位置由<install_dir>/boards/<board_name>/*.ld链接文件决定。

对于M7程序的固化,在进入Linux系统后,可以调用flash_opt命令进行设置。flash_opt在将M7程序固化到系统eMMC的同时,会根据烧写文件的尾缀进行相应设置,以便在系统启动时能根据设置自动将M7程序加载到TCM或DDR中运行。具体步骤为:将需要烧写的程序(以hello_world.bin为例),拷贝到主板可以访问的目录中(比如/mnt/mmc),并根据程序实际运行的位置对程序重命名,如果程序是在TCM中运行,则需要命名为hello_world_tcm.bin,如果是在DDR在运行,则命名为hello_world_ddr.bin。重命名只是为了满足flash_opt对命令格式的要求,程序在编译时必须根据程序加载的位置选择对应的*.ld文件

执行烧写命令(以烧写到TCM为例):

#>flash_opt m7 hello_world_tcm.bin

操作完成后,就可以重启主板,此后系统在启动时就会自动运行M7程序hello_world.bin了,如果要更新程序,重复上述操作即可。

M7程序一旦通过flash_opt固化到系统中,在系统每次启动时M7程序就会自动加载运行,此时就不能再在U-boot中手动下载、启动M7程序进行调试。如果要重新在U-boot中调试M7程序,需要在Linux中执行#>flash_opt m7 dump.bin来擦除先前写入的应用程序,dump.bin实际上是一个内容全为0xFF的二进行文件。