ブログ:
NXP iMX8 M4核心FreeRTOS Rpmsg 应用示例

2020年6月11日木曜日

简介

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版本,下载地址如下:

https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads/7-2018-q2-update

解压下载好的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核心通讯的示例。

記者: 秦海,技术销售工程师,韬睿(上海)

コメントを投稿

Please login to leave a comment!
Have a Question?