Blog:
NXP iMX8 M4核心FreeRTOS Rpmsg 应用示例
简介
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嵌入式平台。
准备
Apalis iMX8QM ARM核心版配合Apalis Evaluation Board载板,连接调试串口UART1(载板X29)到开发主机方便调试。
Apalis iMX8 M40和M41分别使用独立的调试UART,在Apalis Evaluation Board进行跳线将M4对应的调试UART连接到开发主机的方式请参考这里。
Apalis iMX8 Cortex-A核心安装Toradex Ycoto Linux Console image V3.04版本,详细信息请参考这里。
由于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
M4 FreeRTOS SDK部署
根据这里的说明从NXP MCUXpresso网站下载对应iMX8QM的SDK,当前的最新版本为2.5.2。下载界面如下图所示,在这个页面同时也可以下载到关于SDK的一些说明文档。下载好的SDK文件为 ”SDK_2.5.2_MIMX8QM6xxxFF.tar.gz”
下载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
编译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 区域分配请参考这里。
部署测试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: ethernet@5b040000
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
M4 FreeRTOS Rpmsg 示例程序测试
根据章节三同样的方法编译 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做演示示例
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 调试串口终端
root@apalis-imx8:~# 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
root@apalis-imx8:~# 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
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驱动
root@apalis-imx8:~# modprobe imx_rpmsg_pingpong
[ 34.508241] imx_rpmsg_pingpong virtio1.rpmsg-openamp-demo-channel.-1.30: new channel: 0x400 -> 0x1e!
root@apalis-imx8:~# [ 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...
M4s Firmware配置开机自动加载执行测试
上面的测试都是通过Uboot命令从SD卡加载M4 Firmware进行加载运行,下面我们通过str_echo示例程序演示将M40和M41的固件存放在Apalis iMX8 eMMC Flash空间内,并开机自动加载运行
首先进入Linux系统,分别将之前编译好的存放在SD卡上面的M40和M41的 str_echo程序Firmware复制到Flash vfat分区,也就是存放Linux kernel和device tree等文件的分区
UART1 调试串口终端
root@apalis-imx8:~# cd /media/mmcblk0p1/
root@apalis-imx8:/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 示例程序固件
root@apalis-imx8:/media/mmcblk0p1# cp /media/mmcblk2p1/m4_image.bin .
root@apalis-imx8:/media/mmcblk0p1# cp /media/mmcblk2p1/m4_1_image.bin .
root@apalis-imx8:/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
重启进入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
配置好重启后可以看到在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
Linux端加载Rpmsg tty驱动并进行发送测试
UART1 调试串口终端
加载驱动
root@apalis-imx8:~# 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!
发送信息
root@apalis-imx8:~# echo "this is a message from apalis imx8 linux to m4 0" > /dev/ttyRPMSG30
root@apalis-imx8:~# 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
总结
本文基于NXP iMX8示例了其多核异构架构下Cortex-A核心Linux通过Rpmsg驱动和Cortex-M4核心通讯的示例。