Skip to main content

Running FreeRTOS on the Cortex-M7 of a Verdin iMX8M Plus

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 Verdin iMX8M Plus 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

Preparing the Environment

  1. Download the MCUXpresso SDK as described at Setting Up MCUXpresso SDK and Toolchain for Cortex-M development. For Verdin iMX8M Plus you should download:

    • Verdin iMX8M Plus Quad: MIMX8ML8xxxKZ
    • Verdin iMX8M Plus QuadLite: MIMX8ML4xxxKZ
  2. Verify the source code structure from the boards/evkmimx8mp folder

    $ cd <verdin-imx8mp-sdk>/boards/
    $ tree -L 2
    .
    └── evkmimx8mp
    ├── cmsis_driver_examples
    ├── demo_apps
    ├── driver_examples
    ├── evkmimx8mp.png
    ├── freertos_examples
    ├── multicore_examples
    └── project_template
  3. Download 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

Hello World Example

  1. Go to the demo directory on the SDK folder.

    $ cd ./boards/evkmimx8mp/demo_apps/hello_world
    $ tree -L 1
    .
    ├── armgcc
    ├── board.c
    ├── board.h
    ├── clock_config.c
    ├── clock_config.h
    ├── empty_rsc_table.c
    ├── fsl_iomuxc.h
    ├── hello_world.bin
    ├── hello_world.c
    ├── hello_world_v3_13.xml
    ├── pin_mux.c
    ├── pin_mux.h
    └── readme.txt
  2. Write and compile the necessary devicetree overlays as explained at Run the Firmware.

  3. Run the script to build the demo

    $ export ARMGCC_DIR=<PATH_TO_GCC_TOOLCHAIN>/<GCC_TOOLCHAIN_FOLDER>
    $ cd armgcc/
    $ ./build_debug.sh
  4. Copy the generated binary to your device

    $ scp debug/hello_world.bin root@<board-ip>:/home/root
  5. Load the firmware on Flash. On U-boot terminal, run the following commands:

    > setenv load_cmd "ext4load mmc 0:2"
    > setenv cm_image "/home/root/hello_world.bin"
    > setenv cm_image_size 20000
    > setenv load_cm_image "${load_cmd} ${loadaddr} ${cm_image}"
    > setenv cm_boot "${load_cm_image}; cp.b ${loadaddr} 0x7e0000 ${cm_image_size}; dcache flush; bootaux 0x7e0000"
    > saveenv
  6. Start the firmware at boot level

    > run cm_boot

RPMsg Examples

Before diving into the examples:

  1. Apply the related devicetree overlay: verdin-imx8mm_hmp_overlay.dtbo.

  2. Make sure that the rpmsg driver is loaded.

    # dmesg | grep -i rpmsg
    [ 0.045742] imx rpmsg driver is registered.

RPMsg TTY Example

  1. Go to the demo directory on the SDK folder.

    $ cd ./boards/evkmimx8mp/multicore_examples/rpmsg_lite_str_echo_rtos
    $ tree -L 2
    .
    ├── armgcc
    ├── board.c
    ├── board.h
    ├── clock_config.c
    ├── clock_config.h
    ├── FreeRTOSConfig.h
    ├── fsl_iomuxc.h
    ├── main_remote.c
    ├── pin_mux.c
    ├── pin_mux.h
    ├── readme.txt
    ├── remoteproc.h
    ├── rpmsg_config.h
    ├── rpmsg_lite_str_echo_rtos_imxcm4_v3_13.xml
    ├── rsc_table.c
    └── rsc_table.h
  2. Run the script to build the demo

    $ export ARMGCC_DIR=<PATH_TO_GCC_TOOLCHAIN>/<GCC_TOOLCHAIN_FOLDER>
    $ cd armgcc/
    $ ./build_debug.sh
  3. Copy the generated binary to your device

    $ scp debug/rpmsg_lite_str_echo_rtos_imxcm7.bin root@<board-ip>:/home/root
  4. Reset the module and load the firmware on U-boot:

    > setenv load_cmd "ext4load mmc 0:2"
    > setenv cm_image "/home/root/rpmsg_lite_str_echo_rtos_imxcm7.bin"
    > setenv cm_image_size 20000
    > setenv load_cm_image "${load_cmd} ${loadaddr} ${cm_image}"
    > setenv cm_boot "${load_cm_image}; cp.b ${loadaddr} 0x7e0000 ${cm_image_size}; dcache flush; bootaux 0x7e0000"
    > saveenv
    > run cm_boot
  5. Boot 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]
  6. Check if ttyRPMSG device was created:

    # ls /dev/ | grep -i rpmsg
    rpmsg_ctrl0
    ttyRPMSG30
  7. Write through this device and check on the serial port connected to Cortex-M7

    # 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

  1. Go to the demo directory on the SDK folder.

    $ cd ./boards/evkmimx8mp/multicore_examples/rpmsg_lite_pingpong_rtos
    $ tree -L 2
    .
    └── linux_remote
    ├── armgcc
    ├── board.c
    ├── board.h
    ├── clock_config.c
    ├── clock_config.h
    ├── FreeRTOSConfig.h
    ├── fsl_iomuxc.h
    ├── main_remote.c
    ├── pin_mux.c
    ├── pin_mux.h
    ├── readme.txt
    ├── remoteproc.h
    ├── rpmsg_config.h
    ├── rpmsg_lite_pingpong_rtos_linux_remote_v3_13.xml
    ├── rsc_table.c
    └── rsc_table.h
  2. Run the script to build the demo

    $ export ARMGCC_DIR=<PATH_TO_GCC_TOOLCHAIN>/<GCC_TOOLCHAIN_FOLDER>
    $ cd linux_remote/armgcc/
    $ ./build_debug.sh
  3. Copy the generated binary to your device

    $ scp debug/rpmsg_lite_pingpong_rtos_linux_remote.bin root@<board-ip>:/home/root
  4. Reset the module and load the firmware on U-boot:

    > setenv load_cmd "ext4load mmc 0:2"
    > setenv cm_image "/home/root/rpmsg_lite_pingpong_rtos_linux_remote.bin"
    > setenv cm_image_size 20000
    > setenv load_cm_image "${load_cmd} ${loadaddr} ${cm_image}"
    > setenv cm_boot "${load_cm_image}; cp.b ${loadaddr} 0x7e0000 ${cm_image_size}; dcache flush; bootaux 0x7e0000"
    > saveenv
    > run cm_boot
  5. Boot the module and then you will be able to see the following message on the Cortex-M7

    RPMSG Ping-Pong FreeRTOS RTOS API Demo...
    RPMSG Share Base Addr is 0xb8000000
    Link is up!
    Nameservice announce sent.
  6. Load the kernel module:

    # sudo modprobe imx_rpmsg_pingpong

    And on the Cortex-M7 side you can see

    Sending pong...
    Waiting for ping...
    Sending pong...
    Waiting for ping...
    Sending pong...
    Waiting for ping...


Send Feedback!