The i.MX93 SoC includes a high efficiency Cortex-M33 processor with security considerations. The Cortex-M33 implements the Armv8-M architecture with Main Extensions, including a single-precision floating-point unit (FPU), a nested vectored interrupt controller (NVIC), flash patch breakpoint (FPB), the data watchpoint and trace (DWT) unit, and instrumentation trace macrocell.
|
Communication between NPU and Cortex-A55 processor is done through the Cortex-M33 processor. As a consequence, you cannot run any custom firmware on the Cortex-M33 and make use of the NPU at the same time. To use the Cortex-M33 processor with a custom firmware, you first need to disable the NPU. |
Features
The Cortex-M33 on the i.MX93 SoC includes the following features:
-
Arm Cortex-M33 CPU processor (up to 250 MHz)
-
Two-way set-associative 16 KB instruction cache
-
Two-way set-associative 16 KB data cache
-
256 KB tightly coupled memory (TCM)
-
-
Supports FPU
-
Supports MPU
Download the SDK and toolchain
Before building the Cortex-M33 firmware, you must download and install the SDK, which includes example applications and the toolchain to build your firmware application.
Download the SDK
NXP offers an SDK that facilitates firmware development for the Cortex-M33 core. The SDK provides examples that demonstrate how to access the peripherals available on this subsystem.
| You may need to register for an account on the NXP website. |
-
On the left sidebar, click Select Board.
-
Select Boards > i.MX > EVK-MIMX93.
-
Click Build MCUXpresso SDK.
-
Select your Toolchain/IDE and your Host OS.
-
Click Download SDK.
Download the toolchain
You must also download the toolchain to build your firmware application:
-
Go to https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads.
-
Select the latest available version for the Linux hosted "AArch32 bare-metal target" toolchain.
Install the SDK and toolchain
-
Decompress the SDK in a directory of your choice:
$ tar -xvf <SDK_VER>_EVK-MIMX93.tar.gz -C <sdk-install-path> -
Decompress the toolchain in a directory of your choice:
$ tar -xvf arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz -C <toolchain_install_path>
Debug console UART
The Cortex-M33 uses UART2 as default debug console. By default the UART2 is in use on the wireless variant of the ConnectCore 93 by the Bluetooth UART. Therefore, for debug purposes, modify the application code to use a different console port. For instance, change the console port to UART4 (used for XBee, available on the J37 connector, pin2: RX, pin3: TX).
As reference, the changes needed to modify the debug port from UART2 to UART4 are:
/* The UART to use for debug messages. */
-#define BOARD_DEBUG_UART_INSTANCE 2U
+#define BOARD_DEBUG_UART_INSTANCE 4U
#define BOARD_DEBUG_UART_BAUDRATE 115200U
#define BOARD_DEBUG_UART_TYPE kSerialPort_Uart
-#define BOARD_DEBUG_UART_CLOCK_ROOT kCLOCK_Root_Lpuart2
-#define BOARD_DEBUG_UART_CLOCK_GATE kCLOCK_Lpuart2
+#define BOARD_DEBUG_UART_CLOCK_ROOT kCLOCK_Root_Lpuart4
+#define BOARD_DEBUG_UART_CLOCK_GATE kCLOCK_Lpuart4
- IOMUXC_SetPinMux(IOMUXC_PAD_UART2_RXD__LPUART2_RX, 0U);
- IOMUXC_SetPinMux(IOMUXC_PAD_UART2_TXD__LPUART2_TX, 0U);
+ IOMUXC_SetPinMux(IOMUXC_PAD_ENET2_RD0__LPUART4_RX, 0U);
+ IOMUXC_SetPinMux(IOMUXC_PAD_ENET2_TD0__LPUART4_TX, 0U);
- IOMUXC_SetPinConfig(IOMUXC_PAD_UART2_RXD__LPUART2_RX,
+ IOMUXC_SetPinConfig(IOMUXC_PAD_ENET2_RD0__LPUART4_RX,
IOMUXC_PAD_PD_MASK);
- IOMUXC_SetPinConfig(IOMUXC_PAD_UART2_TXD__LPUART2_TX,
+ IOMUXC_SetPinConfig(IOMUXC_PAD_ENET2_TD0__LPUART4_TX,
IOMUXC_PAD_DSE(15U));
Build the "Hello World" demo application
-
Export the variable
ARMGCC_DIRwith the absolute path to the GCC ARM Embedded toolchain.$ export ARMGCC_DIR=<toolchain_install_path>/arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi -
Build the hello_world application.
$ cd <sdk-install-path>/boards/evkmimx93/demo_apps/hello_world/armgcc $ ./build_all.shFind the artifacts in the
debug/releasedirectory.
| For more information, see the MCUXpresso Software Development Kit |
Run the firmware
You have two options to run the Cortex-M33 firmware:
Option 1: Run from U-Boot
Containerize the demo application
To run the Cortex-M33 firmware from U-Boot, you must embed it in an AHAB container.
-
Source the Digi Embedded Yocto SDK environment.
$ . /opt/dey/5.0-r4/ccimx93-dvk/environment-setup-armv8a-dey-linux -
Create the AHAB container from your firmware image.
$ mkimage_imx8 -soc IMX9 -c -m33 hello_world.bin 0 0x1FFE0000 0x201E0000 -out hello_world_cntr.bin
Transfer and run the demo application
-
Boot your device and stop in the U-Boot console.
-
Add parameter
clk-imx93.mcore_booted=1to the Linux kernel command line to prevent the Cortex-M33 application from freezing after Linux starts:=> setenv extra_bootargs clk-imx93.mcore_booted=1,${extra_bootargs} => saveenv -
Transfer the application to RAM, for example via TFTP:
=> tftp $loadaddr <m33_firmware.bin> TFTP from server 192.168.1.1; our IP address is 192.168.1.2 Filename 'm33_firmware.bin'. Load address: 0x40480000 Loading: # 1.6 MiB/s done Bytes transferred = 6528 (1980 hex)where <m33_firmware.bin> is the binary filename.
-
Use the
bootaux_cntrcommand to run the application on the Cortex-M33:=> bootaux_cntr $loadaddr 0 Authenticate auxcore container at 0x80400000 ## Starting auxiliary core addr = 0x1FFE0000...
Auto-run the firmware on every boot
The Cortex-M33 doesn’t have ROM memory.
To instruct the Cortex-M33 to run an application every time the device boots, you must store the application on the eMMC and modify U-Boot’s default bootcmd to load the firmware to RAM and run it on the Cortex-M33 before booting the operating system:
-
Transfer the Cortex-M33 firmware to the eMMC at the linux_a partition:
=> updatefile linux_a tftp <m33_firmware.bin> -
Create a U-Boot script to read and load the Cortex-M33 firmware, and prepend it to the default boot command:
=> setenv boot_cortexm "load mmc 0:1 ${loadaddr} <m33_firmware.bin>; bootaux_cntr ${loadaddr} 0" => setenv bootcmd "run boot_cortexm; ${bootcmd}" => saveenv
Option 2: Run from Linux remoteproc framework
Modern SoCs typically have remote processing devices on the same chip silicon. The remoteproc framework allows different platforms/architectures to control (power on, load firmware, power off) those remote processors.
| The firmware file must be in ELF format to be used with the remoteproc framework. |
Enable the remoteproc framework
remoteproc support is enabled as built-in on the ConnectCore 93 Development Kit kernel configuration file.
-
Linux remoteproc framework (
CONFIG_REMOTEPROC) -
IMX remoteproc driver (
CONFIG_IMX_REMOTEPROC)
Control remote processors with remoteproc framework
You can use the remoteproc framework to load firmware onto an SoC and power it off and on. The location of the remoteproc device is available in the file system at:
# /sys/class/remoteproc/remoteprocX
Where X is the index of the device node, 0 by default.
To load the firmware:
# echo -n <firmware_name.elf> > /sys/class/remoteproc/remoteproc0/firmware
To start the firmware:
# echo start > /sys/class/remoteproc/remoteproc0/state
To stop the firmware:
# echo stop > /sys/class/remoteproc/remoteproc0/state
You can monitor the state of the remoteproc firmware with:
# cat /sys/class/remoteproc/remoteproc0/state
Auto-run the firmware on every boot
To run the firmware from Linux on every boot, create a systemd service that loads and runs the firmware using the remoteproc instructions described above.