Running FreeRTOS on the Cortex-M4 of a Colibri iMX8X
Introduction
The objective of this article is to guide you through case-oriented examples on the implementation of FreeRTOS on the Cortex-M of a Colibri iMX8X System on Module, focusing on the execution of a sample application firmwares leveraging the Heterogeneous Multicore Processing architecture.
The use cases described in this article were tested and validated with FreeRTOS on the Cortex-M running alongside an embedded Linux image (Linux BSP) on the A-cores.
Prerequisites
- Set up the NXP SDK and GCC Toolchain as described in the article Setting Up MCUXpresso SDK and Toolchain for Cortex-M development
- Consider the architecture and memory areas of the specific i.MX-based SoC as explained in the article Cortex-M and Memory Areas Overview on Toradex SoMs
Preparing the Environment
Download the MCUXpresso SDK as described at Setting Up MCUXpresso SDK and Toolchain for Cortex-M development. For Colibri iMX8X, you should download:
- Colibri iMX8DX: MIMX8UX5xxxFZ
- Colibri iMX8QXP: MIMX8QX5xxxFZ
Verify the source code structure from the
boards/mekmimx8qx
folder$ cd <colibri-imx8x-sdk>/boards/
$ tree -L 2
.
└── mekmimx8qx
├── cmsis_driver_examples
├── demo_apps
├── driver_examples
├── lwip_examples
├── mekmimx8qx.png
├── mmcau_examples
├── multicore_examples
├── project_template
└── rtos_examplesDownload and setup the GCC toolchain as explained at Setting Up MCUXpresso SDK and Toolchain for Cortex-M development. We recommend the Arm GNU Toolchain AArch32 bare-metal target (arm-none-eabi) for your host OS.
Case-oriented Examples
To understand and execute the examples below, make sure that you are in the root folder <colibri-imx8x-sdk>
, unless specified.
Hello World Example
Go to the demo directory on the SDK folder.
$ cd ./boards/mekmimx8qx/demo_apps/hello_world
$ tree -L 1
.
├── armgcc
├── board.c
├── board.h
├── clock_config.c
├── clock_config.h
├── empty_rsc_table.c
├── hello_world.bin
├── hello_world.c
├── hello_world.mex
├── hello_world_TCM.bin
├── hello_world_v3_8.xml
├── pin_mux.c
├── pin_mux.h
└── readme.txtChange the
pin_mux.c
andpin_mux.h
accordingly as explained at Run the Firmware.Run the script to build the demo
$ export ARMGCC_DIR=<PATH_TO_GCC_TOOLCHAIN>/<GCC_TOOLCHAIN_FOLDER>
$ cd armgcc/
$ ./build_debug.shCopy the generated binary to your device
$ scp debug/hello_world.bin root@<board-ip>:/home/root
Load the firmware on Flash. On U-boot terminal, run the following commands
> setenv load_cmd "ext4load mmc 0:2"
> setenv m4_0_image "/home/root/hello_world.bin"
> saveenvStart the firmware at boot level
> run m4boot_0
Multicore Examples
Before diving into the examples:
Apply the related devicetree overlay:
colibri-imx8x_hmp_overlay.dtbo
. Refer to Cortex-M RPMsg Guide.Make sure that the rpmsg driver is loaded.
# dmesg | grep -i rpmsg
[ 0.045742] imx rpmsg driver is registered.
RPMsg TTY Example
Go to the demo directory on the SDK folder.
$ cd ./boards/evkmimx8mm/multicore_examples/rpmsg_lite_str_echo_rtos
$ tree -L 2
.
├── app_srtm.c
├── app_srtm.h
├── armgcc
├── board.c
├── board.h
├── clock_config.c
├── clock_config.h
├── FreeRTOSConfig.h
├── main_remote.c
├── pin_mux.c
├── pin_mux.h
├── readme.txt
├── remoteproc.h
├── rpmsg_config.h
├── rpmsg_lite_str_echo_rtos_imxcm4_v3_8.xml
├── rsc_table.c
├── rsc_table.h
└── srtmRun the script to build the demo
$ export ARMGCC_DIR=<PATH_TO_GCC_TOOLCHAIN>/<GCC_TOOLCHAIN_FOLDER>
$ cd armgcc/
$ ./build_debug.shCopy the generated binary to your device
$ scp debug/rpmsg_lite_str_echo_rtos_imxcm4.bin root@<board-ip>:/home/root
Reset the module and load the firmware on U-boot:
> setenv load_cmd "ext4load mmc 0:2"
> setenv m4_0_image "/home/root/rpmsg_lite_str_echo_rtos_imxcm4.bin"
> saveenv
> run m4bootBoot and then load the
imx_rpmsg_tty
kernel module.# sudo modprobe imx_rpmsg_tty
After the kernel module has been loaded, the Cortex-M should print a "Hello World" in the screen, showing that the channel has been created correctly.
RPMSG String Echo FreeRTOS RTOS API Demo...
Nameservice sent, ready for incoming messages...
Get Message From Master Side : "hello world!" [len : 12]Check if ttyRPMSG device was created:
# ls /dev/ | grep -i rpmsg
rpmsg_ctrl0
ttyRPMSG30Write through this device and check on the serial port connected to Cortex-M4
# echo Toradex! > /dev/ttyRPMSG30
Which results in
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 : "Toradex!" [len : 8]
Get New Line From Master Side
RPMsg Ping Pong Example
Go to the demo directory on the SDK folder.
$ cd ./boards/mekmimx8qx/multicore_examples/rpmsg_lite_pingpong_rtos
$ tree -L 2
.
└── linux_remote
├── app_srtm.c
├── app_srtm.h
├── armgcc
├── board.c
├── board.h
├── clock_config.c
├── clock_config.h
├── FreeRTOSConfig.h
├── main_remote.c
├── pin_mux.c
├── pin_mux.h
├── readme.txt
├── remoteproc.h
├── rpmsg_config.h
├── rpmsg_lite_pingpong_rtos_linux_remote_v3_8.xml
├── rsc_table.c
├── rsc_table.h
└── srtmRun the script to build the demo
$ export ARMGCC_DIR=<PATH_TO_GCC_TOOLCHAIN>/<GCC_TOOLCHAIN_FOLDER>
$ cd linux_remote/armgcc/
$ ./build_debug.shCopy the generated binary to your device
$ scp debug/rpmsg_lite_pingpong_rtos_linux_remote.bin root@<board-ip>:/home/root
Reset the module and load the firmware on U-boot:
> setenv load_cmd "ext4load mmc 0:2"
> setenv m4_0_image "/home/root/rpmsg_lite_pingpong_rtos_linux_remote.bin"
> saveenv
> run m4bootBoot the module and then you will be able to see the following message on the Cortex-M4
RPMSG Ping-Pong FreeRTOS RTOS API Demo...
RPMSG Share Base Addr is 0xb8000000
Link is up!
Nameservice announce sent.Load the kernel module:
# sudo modprobe imx_rpmsg_pingpong
And on the Cortex-M4 side you can see
Sending pong...
Waiting for ping...
Sending pong...
Waiting for ping...
Sending pong...
Waiting for ping...