boards/nxp/imx93_evk/doc/index.rst
.. zephyr:board:: imx93_evk
Overview
The i.MX93 Evaluation Kit (MCIMX93-EVK board) is a platform designed to show the most commonly used features of the i.MX 93 Applications Processor in a small and low cost package. The MCIMX93-EVK board is an entry-level development board, which helps developers to get familiar with the processor before investing a large amount of resources in more specific designs.
i.MX93 MPU is composed of one cluster of 2x Cortex®-A55 cores and a single Cortex®-M33 core. Zephyr OS is ported on Cortex®-A55 core and Cortex®-M33 core.
Board features:
RAM: 2GB LPDDR4
Storage:
Wireless:
USB:
Ethernet
PCI-E M.2
Connectors:
LEDs:
Debug
.. zephyr:board-supported-hw::
For M33 Core, TPM2 is enabled. Signals can be observerd with oscilloscope or logic analyzer. Connect J1005-3 and J1005-7(GND) to Oscilloscope or logic analyzer
For A55 Core, TPM3 is enabled for :zephyr:code-sample:pwm-blinky application,
the Green Colored LED in RGB LED D1001 on the board will blink with different frequency.
.. zephyr-app-commands:: :zephyr-app: samples/basic/blinky_pwm :host-os: unix :board: imx93_evk/mimx9352/a55 :goals: build
sar_adc1 is enabled for M33 core. Pins ADC_IN0/1/2/3 are connected to J1003-1/3/5/7
This board configuration uses a system clock frequency of 24 MHz. Cortex-A55 Core runs up to 1.7 GHz. Cortex-M33 Core runs up to 200MHz in which SYSTICK runs on same frequency.
This board configuration uses a single serial communication channel with the CPU's UART2 for A55 core and M33 core.
i.MX 93 processor has three ultra secured digital host controller (uSDHC) modules for SD/eMMC interface support. On the MCIMX93-EVK board, the uSDHC2 interface of the processor connects to the MicroSD card slot (J1002), and uSDHC1 interface connects to the eMMC memory (located at the SOM board). DTS overlay file "usdhc1.overlay" and "usdhc2.overlay" are provided to enable specified the uSDHC controller.
Currently it rely on U-boot or Linux to boot Zephyr on Cortex-A Core, so Zephyr need to use different uSDHC controller from U-boot or Linux to avoid resource conflict. For example, if EVK board boots from SD Card which uses uSDHC2, Zephyr can use MMC which uses uSDHC1 for testing:
.. zephyr-app-commands:: :zephyr-app: tests/subsys/sd/mmc :host-os: unix :board: imx93_evk/mimx9352/a55 :goals: build :gen-args: -DEXTRA_DTC_OVERLAY_FILE=usdhc1.overlay
And if EVK board boots from MMC which uses uSDHC1, Zephyr can use SD Card which uses uSDHC2 for testing:
.. zephyr-app-commands:: :zephyr-app: tests/subsys/sd/sdmmc :host-os: unix :board: imx93_evk/mimx9352/a55 :goals: build :gen-args: -DEXTRA_DTC_OVERLAY_FILE=usdhc2.overlay
This board configuration uses a series of digital multiplexers to switch between
different board functions. The multiplexers are controlled by a GPIO signal called
EXP_SEL from onboard GPIO expander ADP5585. It can be configured to select
function set "A" or "B" by dts configuration if board control module is enabled.
The following dts node is defined:
.. code-block:: dts
board_exp_sel: board-exp-sel {
compatible = "imx93evk-exp-sel";
mux-gpios = <&gpio_exp0 4 GPIO_ACTIVE_HIGH>;
mux = "A";
};
Following steps are required to configure the EXP_SEL signal:
CONFIG_BOARD_MIMX93_EVK_EXP_SEL_INIT.mux="A"; or mux="B"; in &board_exp_sel devicetree node.Kconfig option CONFIG_BOARD_MIMX93_EVK_EXP_SEL_INIT is enabled if a board
function that requires configuring the mux is enabled. The MUX option is
automatically selected if certain board function is enabled, and takes precedence
over dts config. For instance, if CONFIG_CAN is enabled, MUX A is selected
even if mux="B"; is configured in dts, and an warning would be reported in
the log.
The user buttons RFU_BTN1 and RFU_BTN2 is connected to i.MX 93 GPIO by default, but can be changed to connect to onboard GPIO expander PCAL6524 with on-board DIP switches. To do this, switch SW1006 to 0000, then switch SW1005 to 0101. An devicetree overlay is included to support this.
Run following command to test user buttons on PCAL6524:
.. zephyr-app-commands:: :zephyr-app: samples/basic/button :host-os: unix :board: imx93_evk/mimx9352/a55 :goals: build :gen-args: -DEXTRA_DTC_OVERLAY_FILE=imx93_evk_mimx9352_exp_btn.overlay
Run the app, press RFU_BTN1 and the red LED turns on accordingly.
Note: The overlay only supports mimx9352/a55, but can be extended to support
mimx9352/m33 if I2C and PCAL6524 is enabled.
Programming and Debugging (A55)
.. zephyr:board-supported-runners::
There are multiple method to program and debug Zephyr on the A55 core:
The default runner for the board is JLink, connect the EVK board's JTAG connector to the host computer using a J-Link debugger, power up the board and stop the board at U-Boot command line, execute the following U-boot command to disable D-Cache:
.. code-block:: console
dcache off
then use "west flash" or "west debug" command to load the zephyr.bin image from the host computer and start the Zephyr application on A55 core0.
Here is an example for the :zephyr:code-sample:synchronization application.
.. zephyr-app-commands:: :zephyr-app: samples/synchronization :host-os: unix :board: imx93_evk/mimx9352/a55 :goals: flash
Then the following log could be found on UART2 console:
.. code-block:: console
*** Booting Zephyr OS build Booting Zephyr OS build v3.7.0-2055-g630f27a5a867 ***
thread_a: Hello World from cpu 0 on imx93_evk!
thread_b: Hello World from cpu 0 on imx93_evk!
thread_a: Hello World from cpu 0 on imx93_evk!
thread_b: Hello World from cpu 0 on imx93_evk!
Here is an example for the :zephyr:code-sample:hello_world application.
.. zephyr-app-commands:: :zephyr-app: samples/hello_world :host-os: unix :board: imx93_evk/mimx9352/a55 :goals: debug
U-Boot "go" command can be used to start Zephyr on A55 core0 and U-Boot "cpu" command
is used to load and kick Zephyr to the other A55 secondary Cores. Currently "cpu" command
is supported in : Real-Time Edge U-Boot_ (use the branch "uboot_vxxxx.xx-y.y.y,
xxxx.xx is uboot version and y.y.y is Real-Time Edge Software version, for example
"uboot_v2023.04-2.9.0" branch is U-Boot v2023.04 used in Real-Time Edge Software release
v2.9.0), and pre-build images and user guide can be found at Real-Time Edge Software_.
.. _Real-Time Edge U-Boot: https://github.com/nxp-real-time-edge-sw/real-time-edge-uboot .. _Real-Time Edge Software: https://www.nxp.com/rtedge
Firstly need to download Zephyr binary image into DDR memory, it can use tftp:
.. code-block:: console
tftp 0xd0000000 zephyr.bin
Or copy the Zephyr image zephyr.bin SD card and plug the card into the board, for example
if copy to the FAT partition of the SD card, use the following U-Boot command to load the image
into DDR memory (assuming the SD card is dev 1, fat partition ID is 1, they could be changed
based on actual setup):
.. code-block:: console
fatload mmc 1:1 0xd0000000 zephyr.bin;
Then use the following command to boot Zephyr on the core0:
.. code-block:: console
dcache off; icache flush; go 0xd0000000;
Or use "cpu" command to boot from secondary Core, for example Core1:
.. code-block:: console
dcache flush; icache flush; cpu 1 release 0xd0000000
.. note::
Use U-Boot "go" command to boot Zephyr when build with target imx93_evk/mimx9352/a55/smp, since i.MX 93 only has 2 Cortex-A55 cores.
When running Linux on the A55 core, it can use the remoteproc framework to load and boot Zephyr,
refer to Real-Time Edge user guide for more details. Pre-build images and user guide can be found
at Real-Time Edge Software_.
Use this configuration to run basic Zephyr applications and kernel tests,
for example, with the :zephyr:code-sample:synchronization sample:
.. zephyr-app-commands:: :zephyr-app: samples/synchronization :host-os: unix :board: imx93_evk/mimx9352/a55 :goals: build
This will build an image with the synchronization sample app, boot it and display the following console output:
.. code-block:: console
*** Booting Zephyr OS build Booting Zephyr OS build v3.7.0-2055-g630f27a5a867 ***
thread_a: Hello World from cpu 0 on imx93_evk!
thread_b: Hello World from cpu 0 on imx93_evk!
thread_a: Hello World from cpu 0 on imx93_evk!
thread_b: Hello World from cpu 0 on imx93_evk!
SPSDK runner leverages SPSDK tools (https://spsdk.readthedocs.io), it builds an
bootable flash image flash.bin which includes all necessary firmware components.
Using west flash command will download the boot image flash.bin to DDR memory, SD card
or eMMC flash. By using flash.bin, as no U-Boot image is available, so TF-A will boot
up Zephyr on the first Cortex-A55 Core directly.
In order to use SPSDK runner, it requires fetching binary blobs, which can be achieved by running the following command:
.. code-block:: console
west blobs fetch hal_nxp
.. note::
It is recommended running the command above after :file:west update.
SPSDK runner is enabled by configure item :kconfig:option:CONFIG_BOARD_NXP_SPSDK_IMAGE, currently
it is not enabled by default for i.MX93 EVK board, so use this configuration to enable
it, for example, with the :zephyr:code-sample:synchronization sample:
.. zephyr-app-commands:: :zephyr-app: samples/synchronization :host-os: unix :board: imx93_evk/mimx9352/a55 :goals: build :gen-args: -DCONFIG_BOARD_NXP_SPSDK_IMAGE=y
If :kconfig:option:CONFIG_BOARD_NXP_SPSDK_IMAGE is available and enabled for the board variant,
flash.bin will be built automatically. The programming could be through below commands.
Before that, onboard switch SW1301[3:0] should be configured to 0b0011 for USB download mode
to boot, and USB1 and DBG ports should be connected to Linux host PC. There are 4 serial ports
enumerated (115200 8n1), the fourth serial port will be used for Cortex-A55 Zephyr's Console.
(The flasher is spsdk which already installed via scripts/requirements.txt.
On linux host, USB device permission should be configured per Installation Guide
of https://spsdk.readthedocs.io)
.. code-block:: none
$ west flash -r spsdk
$ west flash -r spsdk --bootdevice sd
$ west flash -r spsdk --bootdevice=emmc
Then the Zephyr log will be displayed in the fourth serial port's Console.
Currently i.MX93 only support cold reboot and doesn't support warm reboot.
Use this configuratiuon to verify cold reboot with :zephyr:code-sample:shell-module
sample:
.. zephyr-app-commands:: :zephyr-app: samples/subsys/shell/shell_module :host-os: unix :board: imx93_evk/mimx9352/a55 :goals: build
This will build an image with the shell sample app, boot it and execute kernel reboot command in shell command line:
.. code-block:: console
uart:~$ kernel reboot cold
Programming and Debugging (M33)
Copy the compiled zephyr.bin to the first FAT partition of the SD card and
plug the SD card into the board. Power it up and stop the u-boot execution at
prompt.
Use U-Boot to load and kick zephyr.bin to Cortex-M33 Core:
.. code-block:: console
load mmc 1:1 0x80000000 zephyr.bin;cp.b 0x80000000 0x201e0000 0x30000;bootaux 0x1ffe0000 0
.. code-block:: console
load mmc 1:1 0x84000000 zephyr.bin;dcache flush;bootaux 0x84000000 0
Note: Cortex M33 need execute permission to run code from DDR memory. In order
to enable this, imx-atf_ can to be modified in "plat/imx/imx93/trdc_config.h".
.. _imx-atf: https://github.com/nxp-imx/imx-atf
imx-atf changes:
.. code-block:: console
git diff plat/imx/imx93/trdc_config.h
diff --git a/plat/imx/imx93/trdc_config.h b/plat/imx/imx93/trdc_config.h
index 6c8b8f8fa..b155f9048 100644
--- a/plat/imx/imx93/trdc_config.h
+++ b/plat/imx/imx93/trdc_config.h
@@ -302,7 +302,7 @@ struct trdc_mbc_config trdc_n_mbc[] = {
};
struct trdc_glbac_config trdc_n_mrc_glbac[] = {
- { 0, 0, SP(RW) | SU(RW) | NP(RW) | NU(RW) },
+ { 0, 0, SP(RWX) | SU(RW) | NP(RW) | NU(RW) },
{ 0, 1, SP(RWX) | SU(RWX) | NP(RWX) | NU(RWX) },
};
@@ -356,7 +356,7 @@ struct trdc_mrc_config trdc_n_mrc[] = {
struct trdc_mrc_config trdc_n_mrc[] = {
{ 0, 0, 0, 0x80000000, 0x80000000, 0, false }, /* MRC0 DRAM for S400 DID0 */
{ 0, 1, 0, 0x80000000, 0x80000000, 0, false }, /* MRC0 DRAM for MTR DID1 */
- { 0, 2, 0, 0x80000000, 0x80000000, 0, true }, /* MRC0 DRAM for M33 DID2 */
+ { 0, 2, 0, 0x80000000, 0x80000000, 1, true }, /* MRC0 DRAM for M33 DID2 */
{ 0, 3, 0, 0x80000000, 0x80000000, 1, false }, /* MRC0 DRAM for A55 DID3 */
{ 0, 5, 0, 0x80000000, 0x80000000, 0, false }, /* MRC0 DRAM for USDHC1 DID5 */
{ 0, 6, 0, 0x80000000, 0x80000000, 0, false }, /* MRC0 DRAM for USDHC2 DID6 */
Use this configuration to run basic Zephyr applications and kernel tests,
for example, with the :zephyr:code-sample:synchronization sample:
.. zephyr-app-commands:: :zephyr-app: samples/synchronization :host-os: unix :board: imx93_evk/mimx9352/m33 :goals: run
This will build an image with the synchronization sample app, boot it and display the following console output:
.. code-block:: console
*** Booting Zephyr OS build v3.7.0-684-g71a7d05ba60a ***
thread_a: Hello World from cpu 0 on imx93_evk!
thread_b: Hello World from cpu 0 on imx93_evk!
thread_a: Hello World from cpu 0 on imx93_evk!
thread_b: Hello World from cpu 0 on imx93_evk!
To make a container image flash.bin with zephyr.bin for SD/eMMC programming and booting
from BootROM. Refer to user manual of i.MX93 MCUX SDK release_.
.. _MCUX SDK release: https://mcuxpresso.nxp.com/
More information can refer to NXP official website:
NXP website_.
Using the SOF-specific variant
Since this board doesn't have a DSP, an alternative for people who might be interested
in running SOF on this board had to be found. The alternative consists of running SOF
on an A55 core using Jailhouse as a way to "take away" one A55 core from Linux and
assign it to Zephyr with SOF_.
.. _SOF: https://github.com/thesofproject/sof
Jailhouse is a light-weight hypervisor that allows the partitioning of hardware resources.
For more details on how this is done and, generally, about Jailhouse, please see: 1,
2 and 3. The GitHub repo can be found here.
.. _1: https://lwn.net/Articles/578295/
.. _2: https://lwn.net/Articles/578852/
.. _3: http://events17.linuxfoundation.org/sites/events/files/slides/ELCE2016-Jailhouse-Tutorial.pdf
.. _here: https://github.com/siemens/jailhouse
Firstly, we need to explain a few Jailhouse concepts that will be referred to later on:
Cell: refers to a set of hardware resources that the OS assigned to this cell can utilize.
Root cell: refers to the cell in which Linux is running. This is the main cell which will contain all the hardware resources that Linux will utilize and will be used to assign resources to the inmates. The inmates CANNOT use resources such as the CPU that haven't been assigned to the root cell.
Inmate: refers to any other OS that runs alongside Linux. The resources an inmate will use are taken from the root cell (the cell Linux is running in).
SOF+Zephyr will run as an inmate, alongside Linux, on core 1 of the board. This means that said core will be taken away from Linux and will only be utilized by Zephyr.
The hypervisor restricts inmate's/root's access to certain hardware resources using the second-stage translation table which is based on the memory regions described in the configuration files. Please consider the following scenario:
Root cell wants to use the **UART** which let's say has its registers mapped in
the **[0x0 - 0x42000000]** region. If the inmate wants to use the same **UART** for
some reason then we'd need to also add this region to inmate's configuration
file and add the **JAILHOUSE_MEM_ROOTSHARED** flag. This flag means that the inmate
is allowed to share this region with the root. If this region is not set in
the inmate's configuration file and Zephyr (running as an inmate here) tries
to access this region this will result in a second stage translation fault.
Notes:
The architecture overview can be found at this location_. (latest status update as of now
and the only one containing diagrams).
.. _location: https://github.com/thesofproject/sof/issues/7192
This board has been designed for SOF so it's only intended to be used with SOF.
TODO: document the SOF build process for this board. For now, the support for i.MX93 is still in review and has yet to merged on SOF side.
.. include:: ../../common/board-footer.rst.inc