By Toradex秦海
1). 简介
NXP iMX8是NXP去年底发布的基于Cortex-A72/A53和Coretex-M4异构多核架构的ARM处理器,作为NXP i.MX系列最新性能也最为强大的处理器,升级了从iMX6 SoloX开始到iMX7的异构双核架构(如下框图),使得不同架构核心的使用更加方便稳定,本文就演示iMX8 Cortex-A和Coretx-M核心之间通过Rpmsg来进行通讯的示例。
本文所演示的ARM平台来自于Toradex 基于NXP iMX8QM ARM处理器的Apalis iMX8QM ARM嵌入式平台。
2). 准备
a). Apalis iMX8QM ARM核心版配合Apalis Evaluation Board载板,连接调试串口UART1(载板X29)到开发主机方便调试。
b). Apalis iMX8 M40和M41分别使用独立的调试UART,在Apalis Evaluation Board进行跳线将M4对应的调试UART连接到开发主机的方式请参考这里。
c). Apalis iMX8 Cortex-A核心安装Toradex Ycoto Linux Console image V3.04版本,详细信息请参考这里。
d). 由于M4s调试UART所用到的管脚和Cortex-A核心Linux系统device tree中管脚配置有冲突,需要修改device tree并重新编译部署
./ device tree 修改patch文件请参考如下,下载Linux kernel源代码以及编译部署方法请参考这里。
https://github.com/simonqin09/Apalis_iMX8_M4_Rpmsg/blob/master/apalis_imx8_m4s_uart.patch
3). M4 FreeRTOS SDK部署
a). 根据这里的说明从NXP MCUXpresso网站下载对应iMX8QM的SDK,当前的最新版本为2.5.2。下载界面如下图所示,在这个页面同时也可以下载到关于SDK的一些说明文档。下载好的SDK文件为 ”SDK_2.5.2_MIMX8QM6xxxFF.tar.gz”
b). 下载Toolchain
./ 根据SDK文档建议使用 gcc-arm 7 2018q2版本,下载地址如下:
./ 解压下载好的Toolchain文件到<Toolchain_dir>
-----------------------------------
# 解压
$ cd <Toolchain_dir>
$ tar xvf gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2
# 测试
$ gcc-arm-none-eabi-7-2018-q2-update/bin/arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors 7-2018-q2-update) 7.3.1 20180622 (release) [ARM/embedded-7-branch revision 261907]
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# 可能需要安装额外的工具供后续编译使用,以Ubuntu为例
$ sudo apt-get install make cmake
-----------------------------------
c). 编译Helloworld测试应用
./ 解压步骤a下载的SDK文件到<Work_dir>
-----------------------------------
$ cd <Work_dir>
$ tar xvf SDK_2.5.2_MIMX8QM6xxxFF.tar.gz
-----------------------------------
./ 导出toolchain路径
-----------------------------------
$ export ARMGCC_DIR=<Toolchain_dir>/gcc-arm-none-eabi-7-2018-q2-update/
-----------------------------------
./ 编译M40 Helloworld应用
-----------------------------------
# SDK中包含的示例代码均在 <Work_dir>/boards/mekmimx8qm/ 目录
# M40 Helloworld demo 编译
$ cd <Work_dir>/boards/mekmimx8qm/demo_apps/hello_world/cm4_core0
$ armgcc/build_all.sh
-----------------------------------
./ 编译好的二进制文件位于 armgcc 目录下的 debug/release、ddr_debug/ddr_release、flash_debug/flash_release 目录。默认M4应用从TCM加载,ddr和flash分别对应ddr和flash加载模式,本文不做讨论。另外,Apalis iMX8的memory 区域分配请参考这里。
d). 部署测试M40 Helloworld示例应用
./ 由于目前Apalis iMX8 uboot版本(U-Boot 2018.03-toradex_imx_v2018.03_4.14.78_1.0.0_ga-bringup+g92d0497781)暂时还不支持ELF格式镜像,因此我们将生成的二进制文件m4_image.bin 复制到FAT32分区的SD卡根目录,然后将SD卡连接到Apalis Evaluation Board X19 4bit SD卡插槽
-----------------------------------
# Apalis iMX8 上电开机,Cortex-A 核心调试串口UART1 串口终端按住空格键进入uboot
U-Boot 2018.03-toradex_imx_v2018.03_4.14.98_2.3.0_bringup+gd626574ba1 (Apr 17 2020 - 19:28:04 +0000)
CPU: Freescale i.MX8QM revB A53 at 1200 MHz at 25C
DRAM: 4 GiB
MMC: FSL_SDHC: 0, FSL_SDHC: 1, FSL_SDHC: 2
Loading Environment from MMC... OK
In: serial
Out: serial
Err: serial
Model: Toradex Apalis iMX8 QuadMax 4GB Wi-Fi / BT IT V1.0B, Serial# 06548514
BuildInfo:
- SCFW b929edfe, SECO-FW 27167ff2, IMX-MKIMAGE d7f9440d, ATF bb209a0
- U-Boot 2018.03-toradex_imx_v2018.03_4.14.98_2.3.0_bringup+gd626574ba1
switch to partitions #0, OK
mmc0(part 0) is current device
flash target is MMC:0
Net: eth0: [email protected]
Fastboot: Normal
Normal Boot
Hit any key to stop autoboot: 0
Apalis iMX8 #
# 查看SD卡image
Apalis iMX8 # ls mmc 2
…
# 加载Helloworld程序并运行
Apalis iMX8 # fatload mmc 2 ${loadaddr} m4_image.bin && dcache flush && bootaux ${loadaddr} 0
9032 bytes read in 20 ms (440.4 KiB/s)
## Starting auxiliary core at 0x80280000 ...
Power on M4 and MU
Copy M4 image from 0x80280000 to TCML 0x34fe0000
Start M4 0
bootaux complete
-----------------------------------
./ 运行后,在M40 调试UART对应的串口终端可以看到 ”hello world” 打印输出,然后应用程序可以接收并打印键盘输入,比如这里输入了” this is input before linux boot up” 字符串。
-----------------------------------
hello world.
this is input before linux boot up
-----------------------------------
./ 此时切换到UART1 调试串口终端,执行下面命令继续启动Linux
-----------------------------------
Apalis iMX8 # run bootcmd
-----------------------------------
./ 再切换到M40调试串口终端,键盘输入测试
-----------------------------------
hello world.
this is input before linux boot up this is input after linux boot up
-----------------------------------
./ 对于M41,操作方式类似,只是加载的时候将将命令最后0替换为1
-----------------------------------
Apalis iMX8 # fatload mmc 2 ${loadaddr} m4_1_image.bin && dcache flush && bootaux ${loadaddr} 1
-----------------------------------
4). M4 FreeRTOS Rpmsg 示例程序测试
a). 根据章节三同样的方法编译 M40/M41 Rpmsg 示例程序,分为两个:
./ rpmsg_lite_str_echo_rtos
<Work_dir>/boards/mekmimx8qm/multicore_examples/rpmsg_lite_str_echo_rtos
./ rpmsg_lite_pingpong_rtos
<Work_dir>/boards/mekmimx8qm/multicore_examples/rpmsg_lite_pingpong_rtos/linux_remote
./ 相关demo的说明请参考对应项目下的readme.txt文件,因为M40和M41的测试结果都一致,本文下面就只用M40做演示示例
b). str_echo 示例程序测试
./ 使用章节3测试中同样方法从SD卡加载str_echo 示例程序 “m4_image.bin” 执行
-----------------------------------
# UART1 调试串口终端
Apalis iMX8 # fatload mmc 2 ${loadaddr} m4_image.bin && dcache flush && bootaux ${loadaddr} 0
20112 bytes read in 21 ms (934.6 KiB/s)
## Starting auxiliary core at 0x80280000 ...
Power on M4 and MU
Copy M4 image from 0x80280000 to TCML 0x34fe0000
Start M4 0
bootaux complete
-----------------------------------
./ M40 调试串口终端输出
-----------------------------------
RPMSG String Echo FreeRTOS RTOS API Demo...
-----------------------------------
./ 启动linux
-----------------------------------
# UART1 调试串口终端
Apalis iMX8 # run bootcmd
-----------------------------------
./ M40 调试串口终端输出
-----------------------------------
RPMSG String Echo FreeRTOS RTOS API Demo...
Nameservice sent, ready for incoming messages...
-----------------------------------
./ 加载Linux下Rpmsg tty驱动建立rpmsg链接
-----------------------------------
# UART1 调试串口终端
[email protected]:~# modprobe imx_rpmsg_tty
[ 539.316502] imx_rpmsg_tty virtio1.rpmsg-virtual-tty-channel.-1.30: new channel: 0x400 -> 0x1e!
[ 539.325355] Install rpmsg tty driver!
-----------------------------------
./ M40 调试串口终端输出
-----------------------------------
RPMSG String Echo FreeRTOS RTOS API Demo...
Nameservice sent, ready for incoming messages...
Get Message From Master Side : "hello world!" [len : 12]
-----------------------------------
./ 发送数据测试,如果是M41,则对应虚拟串口为 /dev/ttyRPMSG31
-----------------------------------
[email protected]:~# echo "this is a test from toradex" > /dev/ttyRPMSG30
-----------------------------------
./ M40 调试串口终端输出
-----------------------------------
RPMSG String Echo FreeRTOS RTOS API Demo...
Nameservice sent, ready for incoming messages...
Get Message From Master Side : "hello world!" [len : 12]
Get Message From Master Side : "this is a test from toradex" [len : 27]
Get New Line From Master Side
-----------------------------------
c). pingpong 示例程序测试,测试流程和str_echo基本一致,这里简单罗列对应串口打印输出
./ UART1 调试串口终端
-----------------------------------
# 在M41上运行Rpmsg pingpong 示例程序
Apalis iMX8 # fatload mmc 2 ${loadaddr} m4_image_pingpong.bin && dcache flush && bootaux ${loadaddr} 0
20696 bytes read in 21 ms (961.9 KiB/s)
## Starting auxiliary core at 0x80280000 ...
Power on M4 and MU
Copy M4 image from 0x80280000 to TCML 0x34fe0000
Start M4 0
bootaux complete
# 启动Linux
Apalis iMX8 # run bootcmd
# 加载Pinpong驱动
[email protected]:~# modprobe imx_rpmsg_pingpong
[ 34.508241] imx_rpmsg_pingpong virtio1.rpmsg-openamp-demo-channel.-1.30: new channel: 0x400 -> 0x1e!
[email protected]:~# [ 34.520657] get 1 (src: 0x1e)
[ 34.525069] get 3 (src: 0x1e)
[ 34.529515] get 5 (src: 0x1e)
……
[ 34.738211] get 99 (src: 0x1e)
[ 34.742665] get 101 (src: 0x1e)
[ 34.745865] imx_rpmsg_pingpong virtio1.rpmsg-openamp-demo-channel.-1.30: goodbye!
-----------------------------------
./ M40 调试串口终端输出
-----------------------------------
# pingpong 程序启动后输出
RPMSG Ping-Pong FreeRTOS RTOS API Demo...
RPMSG Share Base Addr is 0x90010000
# Linux启动后输出
Link is up!
Nameservice announce sent.
# Pingpong 驱动加载后输出
Waiting for ping...
Sending pong...
……
Waiting for ping...
Sending pong...
Ping pong done, deinitializing...
Looping forever...
-----------------------------------
5). M4s Firmware配置开机自动加载执行测试
a). 上面的测试都是通过Uboot命令从SD卡加载M4 Firmware进行加载运行,下面我们通过str_echo示例程序演示将M40和M41的固件存放在Apalis iMX8 eMMC Flash空间内,并开机自动加载运行
b). 首先进入Linux系统,分别将之前编译好的存放在SD卡上面的M40和M41的 str_echo程序Firmware复制到Flash vfat分区,也就是存放Linux kernel和device tree等文件的分区
-----------------------------------
# UART1 调试串口终端
[email protected]:~# cd /media/mmcblk0p1/
[email protected]:/media/mmcblk0p1# ls
Image dpfw.bin fsl-imx8qm-apalis-eval.dtb.bak fsl-imx8qm-apalis-v1.1-eval.dtb
boot.scr fsl-imx8qm-apalis-eval.dtb fsl-imx8qm-apalis-ixora-v1.1.dtb hdmitxfw.bin
# 从SD卡挂载路径复制M4s Str_echo 示例程序固件
[email protected]:/media/mmcblk0p1# cp /media/mmcblk2p1/m4_image.bin .
[email protected]:/media/mmcblk0p1# cp /media/mmcblk2p1/m4_1_image.bin .
[email protected]:/media/mmcblk0p1# ls
Image fsl-imx8qm-apalis-eval.dtb fsl-imx8qm-apalis-v1.1-eval.dtb m4_image.bin boot.scr fsl-imx8qm-apalis-eval.dtb.bak hdmitxfw.bin dpfw.bin fsl-imx8qm-apalis-ixora-v1.1.dtb m4_1_image.bin
-----------------------------------
c). 重启进入uboot,配置环境变量
-----------------------------------
# UART1 调试串口终端
# 分别指定M4s固件名称
Apalis iMX8 # setenv m4_0_image 'm4_image.bin'
Apalis iMX8 # setenv m4_1_image 'm4_1_image.bin'
# 设置启动顺序,分别启动M40,M41以及Linux
Apalis iMX8 # setenv bootcmd 'run m4boot_0 && run m4boot_1 && run distro_bootcmd'
Apalis iMX8 # saveenv && reset
-----------------------------------
d). 配置好重启后可以看到在Linux启动过程中 M40和M41的调试串口都分别打印了相关程序输出
-----------------------------------
# UART1 调试串口终端
U-Boot 2018.03-toradex_imx_v2018.03_4.14.98_2.3.0_bringup+gd626574ba1 (Apr 17 2020 - 19:28:04 +0000)
……
Normal Boot
Hit any key to stop autoboot: 0
20112 bytes read in 13 ms (1.5 MiB/s)
## Starting auxiliary core at 0x80280000 ...
Power on M4 and MU
Copy M4 image from 0x80280000 to TCML 0x34fe0000
Start M4 0
bootaux complete
61488 bytes read in 13 ms (4.5 MiB/s)
## Starting auxiliary core at 0x80280000 ...
Power on M4 and MU
Copy M4 image from 0x80280000 to TCML 0x38fe0000
Start M4 1
bootaux complete
……
Scanning mmc 0:1...
Found U-Boot script /boot.scr
……
Starting kernel ...
……
-----------------------------------
./ M40 调试串口终端
-----------------------------------
RPMSG String Echo FreeRTOS RTOS API Demo...
Nameservice sent, ready for incoming messages...
-----------------------------------
./ M41 调试串口终端
-----------------------------------
RPMSG String Echo FreeRTOS RTOS API Demo...
Nameservice sent, ready for incoming messages...
app_srtm: AUTO and I2C service registered
-----------------------------------
e). Linux端加载Rpmsg tty驱动并进行发送测试
-----------------------------------
# UART1 调试串口终端
# 加载驱动
[email protected]:~# modprobe imx_rpmsg_tty
[ 34.795096] imx_rpmsg_tty virtio1.rpmsg-virtual-tty-channel.-1.30: new channel: 0x400 -> 0x1e!
[ 34.803985] Install rpmsg tty driver!
[ 34.807934] imx_rpmsg_tty virtio3.rpmsg-virtual-tty-channel-1.-1.31: new channel: 0x400 -> 0x1f!
[ 34.817031] Install rpmsg tty driver!
# 发送信息
[email protected]:~# echo "this is a message from apalis imx8 linux to m4 0" > /dev/ttyRPMSG30
[email protected]:~# echo "this is a message from apalis imx8 linux to m4 1" > /dev/ttyRPMSG31
-----------------------------------
./ M40 调试串口终端
-----------------------------------
RPMSG String Echo FreeRTOS RTOS API Demo...
Nameservice sent, ready for incoming messages...
Get Message From Master Side : "hello world!" [len : 12]
Get Message From Master Side : "this is a message from apalis imx8 linux to m4 0" [len : 48]
Get New Line From Master Side
-----------------------------------
./ M41 调试串口终端
-----------------------------------
RPMSG String Echo FreeRTOS RTOS API Demo...
Namapp_srtm: AUTO and I2C service registered
eservice sent, ready for incoming messages...
Get Message From Master Side : "hello world!" [len : 12]
Get Message From Master Side : "this is a message from apalis imx8 linux to m4 1" [len : 48]
Get New Line From Master Side
-----------------------------------
6). 总结
本文基于NXP iMX8示例了其多核异构架构下Cortex-A核心Linux通过Rpmsg驱动和Cortex-M4核心通讯的示例