FreeRTOS Porting Guide for AXON/EDM/PICO-IMX93
Applicable Platforms
This guide applies to the following SOMs.
- AXON-IMX93
- EDM-IMX93
Introduction
This article details the process of porting and running FreeRTOS on the Cortex-M33 core of the NXP i.MX93 platform. It covers booting the M33 core via binary loading with U-Boot, synchronizing boot parameters with Linux, and establishing inter-core communication using the remoteproc and RPMsg drivers. The setup is validated through successful execution of example applications: hello_world
, rpmsg_lite_str_echo_rtos
and rpmsg_lite_pingpong_rtos
.
Part1: Set Up the Environment
You can use our prebuilt image through the following link for verification. It includes the binary files, allowing directly run M33 core example without rebuilding.
Platform | Image |
---|---|
AXON-IMX93 | axon-imx93_axon-wb_yocto-5.0-qt6_iw416_lvds-1280x800_20250520.zip |
EDM-IMX93 | edm-imx93_edm-wb_yocto-5.0-qt6_iw416_lvds-1280x800_20250520.zip |
1.1 Clone the repository
git clone https://github.com/TechNexion/freertos-tn.git
1.2 Download the GNU Compiler Toolchain
-
Download the GNU compiler toolchain for your environment from Arm Developer. Here we use the x86_64 Linux version. https://developer.arm.com/downloads/-/gnu-rm
-
Set the environment variables.
export ARMGCC_DIR=/home/platforms/Downloads/gcc-arm-none-eabi-10.3-2021.10
export PATH=$PATH:/home/platforms/Downloads/gcc-arm-none-eabi-10.3-2021.10/bin/
Part2: Build and run hello_world example
2.1 Build hello_world application
- Ensure you export the environment variable ARMGCC_DIR which is pointed to directory of tool chain .
cd freertos-tn/boards/${board_name}/demo_apps/hello_world/armgcc/
./build_release.sh
- Copy binary file to 1st FAT partition of eMMC :
cp ./release/sdk20-app.bin /media/username/boot/
2.2 Run hello_world example
- Choose to load bin with cortex-m33 support.
In u-boot prompt:
run m33boot
You should see the following output from debug console:
Part3: Build and run rpmsg_lite_str_echo_rtos example
3.1 Build rpmsg_lite_str_echo_rtos application:
- Ensure you export the environment variable ARMGCC_DIR which is pointed to directory of tool chain.
cd freertos-tn/boards/${board_name}/multicore_examples/rpmsg_lite_str_echo_rtos/linux_remote/armgcc
./build_release.sh
- Copy binary file to 1st FAT partition of eMMC :
cp ./release/rpmsg_lite_str_echo_rtos.bin /media/username/boot/
- Copy .elf file to /lib/firmware
cp ./release/rpmsg_lite_str_echo_rtos_imxcm33.elf /media/username/root/lib/firmware
3.2 Run rpmsg_lite_str_echo_rtos example
- Method 1 : Choose to load bin with cortex-m33 support.
In u-boot prompt:
setenv m33image rpmsg_lite_str_echo_rtos.bin
run m33boot
In Yocto prompt:
modprobe imx_rpmsg_tty
echo "this is a test" > /dev/ttyRPMSG30
You should see the following output from debug console:
- Method 2 : Choose to load elf with cortex-m33 support (Alternatively).
In Yocto prompt:
echo stop > /sys/class/remoteproc/remoteproc0/state
echo rpmsg_lite_str_echo_rtos_imxcm33.elf > /sys/class/remoteproc/remoteproc0/firmware
echo start > /sys/class/remoteproc/remoteproc0/state
modprobe imx_rpmsg_tty
echo "this is a test" > /dev/ttyRPMSG30
Part4: Build and run rpmsg_lite_pingpong_rtos example
4.1 Build rpmsg_lite_pingpong_rtos application
- Ensure you export the environment variable ARMGCC_DIR which is pointed to directory of tool chain.
cd freertos-tn/boards/${board_name}/multicore_examples/rpmsg_lite_pingpong_rtos/linux_remote/armgcc
./build_release.sh
2.Copy binary file to 1st FAT partition of eMMC :
cp ./release/rpmsg_lite_pingpong_rtos_linux_remote.bin /media/username/boot/
- Copy .elf file to /lib/firmware
cp ./release/rpmsg_lite_pingpong_rtos_linux_remote.elf /media/username/root/lib/firmware
4.2 Run rpmsg_lite_pingpong_rtos example
- Method 1 : Choose to load bin with cortex-m33 support.
In u-boot prompt:
setenv m33image rpmsg_lite_pingpong_rtos_linux_remote.bin
run m33boot
In Yocto prompt:
modprobe imx_rpmsg_pingpong
- Method 2 : Choose to load elf with cortex-m33 support (Alternatively).
In Yocto prompt:
echo stop > /sys/class/remoteproc/remoteproc0/state
echo rpmsg_lite_pingpong_rtos_linux_remote.elf > /sys/class/remoteproc/remoteproc0/firmware
echo start > /sys/class/remoteproc/remoteproc0/state
modprobe imx_rpmsg_pingpong
Troubleshooting
common problems and corresponding solutions:
- RPMsg Messages Cannot Be Sent or Received
- Make sure
clk-imx93.mcore_booted=1
is included in the bootargs to prevent Linux from restarting the M33 core. - Ensure the firmware loaded is the
*_linux_remote
version. - Load the
imx_rpmsg_tty
module usingmodprobe
. - Check
dmesg | grep rpmsg
to verify if the RPMsg channel was successfully created.
- M33 Core Fails to Boot
- Verify the
fatload
andcp.b
memory addresses match the expected start address for M33. - Ensure the binary image is correctly built and linked for the M33 target.
- Confirm the binary is loaded into the correct memory region (e.g., TCM or OCRAM).
- Failed to Load Firmware via Remoteproc
- Ensure the firmware file is placed in
/lib/firmware/
and matches the name specified. - If the error says
Device or resource busy
, it indicates M33 was already started by U-Boot, so remoteproc should not try to restart it.
/dev/ttyRPMSG*
Device Not Found
- Ensure the Linux kernel is compiled with
CONFIG_IMX_RPMSG_TTY
. - Use
dmesg | grep rpmsg
to verify thatrpmsg-virtual-tty-channel
was successfully created.