NXP/Freescale MQX™ is a real-time operating system (RTOS) mainly for NXP/Freescale's Kinetis MCUs, but is also available for NXP/Freescale's Vybrid SoCs. NXP/Freescale provides a free basic license of MQX for its products. MQX can be used on both cores of the Vybrid SoCs - both the Cortex-A5 primary core & the Cortex-M4 secondary core. This article focuses on MQX running on the secondary Cortex-M4 core.
Note that Toradex promotes FreeRTOS support for Vybrids secondary core. This article is provided "as is". We have limited experience with MQX and hence limited MQX support capability. If you have general MQX problems, please use NXP/Freescale's official support channels.
This article demonstrates how to compile and run the Hello World sample application using MQX RTOS for the Cortex-M4 of a Colibri VF61 module. The instructions in this article assume that a Linux host is used for development along with a GNU GCC toolchain. MQX also supports Microsoft Windows as a development host and different toolchains/IDE's, please refer to the documentation in the doc/ folder within the files distributed by the MQX RTOS for more information.
Note: The MQX 4.2.0 release notes recommend the 2014-q3 release of the Linaro toolchain containing GCC 4.8.4. The build files provided by MQX default to GCC 4.8.4, as provided by the symbol GCC_VERSION. The GCC_VERSION symbol is crucial for standard header includes. Linaro also offers newer releases, which may work too; however in that case GCC_VERSION needs to be updated accordingly (in build/twrvf65gs10_m4/make/tools/gcc_arm.mak).
Extract both packages in your home folder:
$ tar xzf "~/Downloads/Freescale MQX RTOS 4.2.0 Linux Base.gz" ... $ tar xjf ~/Downloads/gcc-arm-none-eabi-4_8-2014q3-20140805-linux.tar.bz2 ...
Switch to the MQX root folder and configure the toolchain in build/common/make/global.mak.
$ cd FSLMQXOS_4_2_0_GA/ $ gedit build/common/make/global.mak
TOOLCHAIN_ROOTDIR = /home/yourname/gcc-arm-none-eabi-4_8-2014q3/
The MQX 4.2.0 release supports several NXP/Freescale boards by default. The board most similar to Colibri VF61 is the Vybrid Tower reference board. There are two configurations available, one for the Cortex-A5 and another for the Cortex-M4. This article focuses on Cortex-M4 support only. Therefore, this article uses the twrvf65gs10_m4 board as a template.
By default, the Colibri VF61 uses UART_A (Colibri pinout) as the serial console of the primary core and UART_B (Colibri pinout) as the serial console of the secondary core. UART_A is connected to UART0 (MQX TTYA), UART_B is connected to UART2 (MQX TTYC) of the Vybrid SoC. (See also: UART (Linux))
In the user configuration file located at config/twrvf65gs10_m4/user_config.h we can enable the MQX console TTYC only:
... #define BSPCFG_ENABLE_TTYB 0 #define BSPCFG_ENABLE_ITTYB 0 #define BSPCFG_ENABLE_TTYC 1 #define BSPCFG_ENABLE_ITTYC 0 ...
An important aspect to consider is peripheral support. Vybrid has no resource controller which protects access to peripherals. Therefore, it is very important to properly partition the hardware between the two cores (allocate each peripheral to one of the two cores). Since this is very application specific, we do not offer a specific standard partitioning. The default configuration of Linux tries to make use of most peripherals.
However, due to device tree support of Linux, disabling peripherals is quite simple. By setting the status property to disabled, the kernel does not use the given peripheral. Both the Linux device tree and the MQX configuration header files use the peripheral naming of the official Vybrid SoC reference manual, hence the first I2C instance is called I2C0 in both files. Refer to the Device Tree Customization article for how to alter the device tree.
To print a simple "Hello World", no peripherals other than the serial console (UART) are required. Therefore, we disable MQX support of the unrequired hardware by again editing config/twrvf65gs10_m4/user_config.h:
... #define BSPCFG_ENABLE_I2C0 0 #define BSPCFG_ENABLE_II2C0 0 ... #define BSPCFG_ENABLE_SPI0 0 ... #define BSPCFG_ENABLE_RTCDEV 0 ... #define BSPCFG_ENABLE_ESDHC 0 #define BSPCFG_ENABLE_SAI 0 ...
Another important detail is clocking. The base clocks are shared between the two cores, hence the two operating systems can not independently alter clocks! By default, the boot loader (U-Boot) sets up base clocking and the clocks of some peripherals. Linux adopts the base clocking (without changing the core/bus clocks) and enables/disables peripheral clocks as required. MQX has a complete clock tree for Vybrid, allowing it to configure clocks from scratch (see mqx/source/io/cm/vybrid/). However, by default, the option BSPCFG_ENABLE_CLKTREE_MGMT is disabled (0) such that MQX behaves similar to Linux - preventing it from altering the core clocks.
However, the Vybrid Tower board uses a different core clock configuration by default - running at 400MHz core clock, whereas Colibri VF61 runs at 500MHz. Therefore, some basic bus clocks need to be configured accordingly.
Edit the clocks in ./mqx/source/bsp/twrvf65gs10_m4/twrvf65gs10_m4.h as follows:
... #define BSP_CORE_CLOCK (166700000) #define BSP_BUS_CLOCK (166700000) #define BSP_SYSTEM_CLOCK (83300000) #define BSP_IPG_CLOCK (83300000) ...
To build the Hello World example, one has to switch into the example's make folder and execute the build shell script from that folder. If building succeeds, the script should end with "Build done":
# cd mqx/examples/hello/build/make/hello_twrvf65gs10_m4/ # ./build_gcc_arm.sh ... Build done Press any key to continue...
Current boot utilities for Cortex-M4 only support raw binaries. However, the current MQX release (or the GCC ARM support thereof) only builds a .elf binary.
By using the objcopy utility (provided by the toolchain), the elf binary can easily be converted into a raw binary file:
$ export PATH=~/gcc-arm-none-eabi-4_9-2014q4/bin/:$PATH $ arm-none-eabi-objcopy -O binary gcc_arm/ram_release/hello_twrvf65gs10_m4.elf gcc_arm/ram_release/hello_twrvf65gs10_m4.bin
Since this binary firmware does not have any headers which state the load address or the entry point of the application, the boot utility will need that information as arguments later on. The entry point can be retrieved from the elf binary:
$ arm-none-eabi-objdump -f gcc_arm/ram_release/hello_twrvf65gs10_m4.elf gcc_arm/ram_release/hello_twrvf65gs10_m4.elf: file format elf32-littlearm architecture: arm, flags 0x00000112: EXEC_P, HAS_SYMS, D_PAGED start address 0x3f000791
The load address depends on the linker file used. The default linker file (mqx/source/bsp/twrvf65gs10_m4/gcc_arm/ram.ld) seems to use 0x3f000000.
Booting the Cortex-M4 core is currently possible using the mqxboot utility directly from Linux user-space. You can use the Linux serial console (UART_A) to get to a Linux prompt.
The serial console (TTY) output of MQX running on the Cortex-M4 CPU should appear on UART_B (UART2 in Vybrid SoC terms). Hence make sure to connect UART_B to your host computer as well and start a serial console for this serial connection too (at a baudrate of 115200).
After transferring the binary to the target (e.g. by using scp), one can use the mqxboot utility to load the firmware into SRAM and execute it. Please note the previously mentioned load address and entry point.
# mqxboot hello_twrvf65gs10_m4.bin 0x3f000000 0x3f000791
Shortly after running that command, "Hello World" should appear on the serial console on UART_B: