Skip to content

Commit eb8cabb

Browse files
yangbolu1991dkalowsk
authored andcommitted
boards: nxp: imx95_evk: support generating/flashing bootable firmware
Supported NXP Secure Provisioning SDK (SPSDK) generating and flashing bootable firmware for imx95_evk_mimx9596_m7/a55. Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> Signed-off-by: Jiafei Pan <Jiafei.Pan@nxp.com>
1 parent 0ce5178 commit eb8cabb

File tree

7 files changed

+276
-44
lines changed

7 files changed

+276
-44
lines changed

boards/nxp/common/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Copyright 2025 NXP
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config BOARD_NXP_SPSDK_IMAGE
5+
bool "Generate bootable firmware image with SPSDK"
6+
help
7+
Generate bootable firmware image with NXP Secure
8+
Provisioning SDK (SPSDK).

boards/nxp/imx95_evk/CMakeLists.txt

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,118 @@ if (CONFIG_SOF AND CONFIG_BOARD_IMX95_EVK_MIMX9596_M7_DDR)
1212
)
1313
endif()
1414

15+
if(CONFIG_BOARD_NXP_SPSDK_IMAGE OR (DEFINED ENV{USE_NXP_SPSDK_IMAGE}
16+
AND "$ENV{USE_NXP_SPSDK_IMAGE}" STREQUAL "y"))
17+
find_program(7Z_EXECUTABLE 7z REQUIRED)
18+
set(FIRMWARE_RELEASE "imx95-19x19-lpddr5-evk-boot-firmware-0.1")
19+
# Parse SPSDK version
20+
execute_process(
21+
COMMAND spsdk --version
22+
OUTPUT_VARIABLE SPSDK_VERSION_OUTPUT
23+
OUTPUT_STRIP_TRAILING_WHITESPACE
24+
)
25+
string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" SPSDK_VERSION "${SPSDK_VERSION_OUTPUT}")
26+
message(STATUS "SPSDK version is ${SPSDK_VERSION}")
27+
28+
if(CONFIG_BOARD_IMX95_EVK_MIMX9596_M7)
29+
set(AHAB_CONFIG_FILE "imx95_evk_mimx9596_m7_ahab.yaml")
30+
31+
file(WRITE ${CMAKE_BINARY_DIR}/zephyr/${AHAB_CONFIG_FILE}
32+
"
33+
family: mimx9596
34+
revision: a1
35+
target_memory: standard
36+
output: ${CMAKE_BINARY_DIR}/zephyr/flash.bin
37+
containers:
38+
- binary_container:
39+
path: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/mx95a0-ahab-container.img
40+
- container:
41+
srk_set: none
42+
images:
43+
- lpddr_imem: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/lpddr5_imem_v202311.bin
44+
lpddr_imem_qb: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/lpddr5_imem_qb_v202311.bin
45+
lpddr_dmem: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/lpddr5_dmem_v202311.bin
46+
lpddr_dmem_qb: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/lpddr5_dmem_qb_v202311.bin
47+
oei_ddr: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/oei-m33-ddr.bin
48+
- oei_tcm: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/oei-m33-tcm.bin
49+
- system_manager: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/m33_image-mx95alt.bin
50+
- cortex_m7_app: ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.bin
51+
- v2x_dummy: true
52+
")
53+
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
54+
COMMAND ${7Z_EXECUTABLE} x ${ZEPHYR_HAL_NXP_MODULE_DIR}/zephyr/blobs/imx-boot-firmware/${FIRMWARE_RELEASE}.bin -o./imx-boot-firmware -aos -bso0 -bse1
55+
COMMAND ${7Z_EXECUTABLE} x imx-boot-firmware/${FIRMWARE_RELEASE} -aos -bso0 -bse1
56+
COMMAND nxpimage ahab export -c ${CMAKE_BINARY_DIR}/zephyr/${AHAB_CONFIG_FILE}
57+
)
58+
elseif(CONFIG_SOC_MIMX9596_A55)
59+
file(WRITE ${CMAKE_BINARY_DIR}/zephyr/imx95_evk_mimx9596_a55_ahab_primary.yaml
60+
"
61+
family: mimx9596
62+
revision: a1
63+
target_memory: standard
64+
output: ${CMAKE_BINARY_DIR}/zephyr/primary_ahab.bin
65+
containers:
66+
- binary_container:
67+
path: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/mx95a0-ahab-container.img
68+
- container:
69+
srk_set: none
70+
images:
71+
- lpddr_imem: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/lpddr5_imem_v202311.bin
72+
lpddr_imem_qb: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/lpddr5_imem_qb_v202311.bin
73+
lpddr_dmem: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/lpddr5_dmem_v202311.bin
74+
lpddr_dmem_qb: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/lpddr5_dmem_qb_v202311.bin
75+
oei_ddr: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/oei-m33-ddr.bin
76+
- oei_tcm: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/oei-m33-tcm.bin
77+
- system_manager: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/m33_image-mx95evk.bin
78+
- spl: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/u-boot-spl.bin-imx95-19x19-lpddr5-evk-sd
79+
- v2x_dummy: true
80+
")
81+
file(WRITE ${CMAKE_BINARY_DIR}/zephyr/imx95_evk_mimx9596_a55_ahab_secondary.yaml
82+
"
83+
family: mimx9596
84+
revision: a1
85+
target_memory: standard
86+
output: ${CMAKE_BINARY_DIR}/zephyr/secondary_ahab.bin
87+
containers:
88+
- container:
89+
srk_set: none
90+
images:
91+
- atf: ${CMAKE_BINARY_DIR}/zephyr/${FIRMWARE_RELEASE}/bl31-imx95-zephyr.bin
92+
- image_path: ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.bin
93+
load_address: '${CONFIG_SRAM_BASE_ADDRESS}'
94+
entry_point: '${CONFIG_SRAM_BASE_ADDRESS}'
95+
image_type: executable
96+
core_id: cortex-a55
97+
is_encrypted: false
98+
")
99+
file(WRITE ${CMAKE_BINARY_DIR}/zephyr/imx95_evk_mimx9596_a55_ahab_flash_template.yaml
100+
"
101+
family: mimx9596
102+
revision: latest
103+
memory_type: serial_downloader
104+
primary_image_container_set: ${CMAKE_BINARY_DIR}/zephyr/imx95_evk_mimx9596_a55_ahab_primary.yaml
105+
secondary_image_container_set: ${CMAKE_BINARY_DIR}/zephyr/imx95_evk_mimx9596_a55_ahab_secondary.yaml
106+
")
107+
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
108+
COMMAND ${7Z_EXECUTABLE} x ${ZEPHYR_HAL_NXP_MODULE_DIR}/zephyr/blobs/imx-boot-firmware/${FIRMWARE_RELEASE}.bin -o./imx-boot-firmware -aos -bso0 -bse1
109+
COMMAND ${7Z_EXECUTABLE} x imx-boot-firmware/${FIRMWARE_RELEASE} -aos -bso0 -bse1
110+
)
111+
if(SPSDK_VERSION VERSION_GREATER_EQUAL "3.0.0")
112+
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
113+
COMMAND nxpimage bootable-image export -c ${CMAKE_BINARY_DIR}/zephyr/imx95_evk_mimx9596_a55_ahab_flash_template.yaml -o flash.bin
114+
)
115+
else()
116+
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
117+
COMMAND nxpimage bootable-image merge -c ${CMAKE_BINARY_DIR}/zephyr/imx95_evk_mimx9596_a55_ahab_flash_template.yaml -o flash.bin
118+
)
119+
endif()
120+
else()
121+
message(FATAL_ERROR "SPSDK Image not supported on the platform!")
122+
endif()
123+
zephyr_blobs_verify(FILES
124+
${ZEPHYR_HAL_NXP_MODULE_DIR}/zephyr/blobs/imx-boot-firmware/${FIRMWARE_RELEASE}.bin
125+
REQUIRED)
126+
endif()
127+
15128
zephyr_library()
16129
zephyr_library_sources(board.c)

boards/nxp/imx95_evk/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright 2025 NXP
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
source "boards/nxp/common/Kconfig"

boards/nxp/imx95_evk/board.cmake

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,19 @@
33
if (CONFIG_SOF AND CONFIG_BOARD_IMX95_EVK_MIMX9596_M7_DDR)
44
board_set_rimage_target(imx95)
55
endif()
6+
7+
if(CONFIG_BOARD_NXP_SPSDK_IMAGE OR (DEFINED ENV{USE_NXP_SPSDK_IMAGE}
8+
AND "$ENV{USE_NXP_SPSDK_IMAGE}" STREQUAL "y"))
9+
board_set_flasher_ifnset(spsdk)
10+
11+
board_runner_args(spsdk "--family=mimx9596")
12+
board_runner_args(spsdk "--bootloader=${CMAKE_BINARY_DIR}/zephyr/imx95-19x19-lpddr5-evk-boot-firmware-0.1/imx-boot-imx95-19x19-lpddr5-evk-sd.bin-flash_all")
13+
board_runner_args(spsdk "--flashbin=${CMAKE_BINARY_DIR}/zephyr/flash.bin")
14+
if(CONFIG_CPU_CORTEX_A55)
15+
board_runner_args(spsdk "--containers=two")
16+
else()
17+
board_runner_args(spsdk "--containers=one")
18+
endif()
19+
20+
include(${ZEPHYR_BASE}/boards/common/spsdk.board.cmake)
21+
endif()

boards/nxp/imx95_evk/doc/index.rst

Lines changed: 128 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -115,88 +115,139 @@ Programming and Debugging (A55)
115115

116116
.. zephyr:board-supported-runners::
117117
118-
Use this configuration to run basic Zephyr applications and kernel tests,
119-
for example, with the :zephyr:code-sample:`synchronization` sample:
118+
There are multiple methods to program and run Zephyr on the A55 core:
119+
120+
Option 1. Boot Zephyr by Using SPSDK Runner
121+
===========================================
122+
123+
SPSDK runner leverages SPSDK tools (https://spsdk.readthedocs.io), it builds an
124+
bootable flash image ``flash.bin`` which includes all necessary firmware components,
125+
such as ELE+V2X firmware, System Manager, TCM OEI, TF-A images etc. Using west flash
126+
command will download the boot image flash.bin to DDR memory, SD card or eMMC flash.
127+
By using flash.bin, as no U-Boot image is available, so TF-A will boot up Zephyr on
128+
the first Cortex-A55 Core directly.
129+
130+
In order to use SPSDK runner, it requires fetching binary blobs, which can be achieved
131+
by running the following command:
132+
133+
.. code-block:: console
120134
121-
1. Build and run the Non-SMP application
135+
west blobs fetch hal_nxp
136+
137+
.. note::
138+
139+
It is recommended running the command above after :file:`west update`.
140+
141+
SPSDK runner is enabled by configure item :kconfig:option:`CONFIG_BOARD_NXP_SPSDK_IMAGE`, currently
142+
it is not enabled by default for i.MX95 EVK board, so use this configuration to enable
143+
it, for example, with the :zephyr:code-sample:`synchronization` sample:
122144

123145
.. zephyr-app-commands::
124146
:zephyr-app: samples/synchronization
125147
:host-os: unix
126148
:board: imx95_evk/mimx9596/a55
127149
:goals: build
150+
:gen-args: -DCONFIG_BOARD_NXP_SPSDK_IMAGE=y
128151

129-
This will build an image (zephyr.bin) with the synchronization sample app.
152+
If :kconfig:option:`CONFIG_BOARD_NXP_SPSDK_IMAGE` is available and enabled for the board variant,
153+
``flash.bin`` will be built automatically. The programming could be through below commands.
154+
Before that, switch SW7[1:4] should be configured to 0b1001 for usb download mode
155+
to boot, and USB1 and DBG ports should be connected to PC. There are 4 serial ports
156+
enumerated (115200 8n1), and we use the first for M7 and the fourth for M33 System Manager.
157+
(The flasher is spsdk which already installed via scripts/requirements.txt.
158+
On linux host, usb device permission should be configured per Installation Guide
159+
of https://spsdk.readthedocs.io)
130160

131-
Copy the compiled ``zephyr.bin`` to the first FAT partition of the SD card and
132-
plug the SD card into the board. Power it up and stop the u-boot execution at
133-
prompt.
161+
.. code-block:: none
134162
135-
Use U-Boot to load and kick zephyr.bin to Cortex-A55 Core1:
163+
# load and run without programming. for next flashing, execute 'reset' in the
164+
# fourth serail port
165+
$ west flash
136166
137-
.. code-block:: console
167+
# program to SD card, then set SW7[1:4]=0b1011 to reboot
168+
$ west flash --bootdevice sd
138169
139-
fatload mmc 1:1 0xd0000000 zephyr.bin; dcache flush; icache flush; cpu 1 release 0xd0000000
170+
# program to emmc card, then set SW7[1:4]=0b1010 to reboot
171+
$ west flash --bootdevice=emmc
140172
141173
142-
Or use the following command to kick zephyr.bin to Cortex-A55 Core0:
174+
Option 2. Boot Zephyr by Using U-Boot Command
175+
=============================================
143176

144-
.. code-block:: console
177+
U-Boot "go" command can be used to start Zephyr on A55 core0 and U-Boot "cpu" command
178+
is used to load and kick Zephyr to the other A55 secondary Cores. Currently "cpu" command
179+
is supported in : `Real-Time Edge U-Boot`_ (use the branch "uboot_vxxxx.xx-y.y.y,
180+
xxxx.xx is uboot version and y.y.y is Real-Time Edge Software version, for example
181+
"uboot_v2023.04-2.9.0" branch is U-Boot v2023.04 used in Real-Time Edge Software release
182+
v2.9.0), and pre-build images and user guide can be found at `Real-Time Edge Software`_.
145183

146-
fatload mmc 1:1 0xd0000000 zephyr.bin; dcache flush; icache flush; go 0xd0000000
184+
.. _Real-Time Edge U-Boot:
185+
https://github.com/nxp-real-time-edge-sw/real-time-edge-uboot
186+
.. _Real-Time Edge Software:
187+
https://www.nxp.com/rtedge
147188

189+
Step 1: Download Zephyr Image into DDR Memory
190+
---------------------------------------------
148191

149-
It will display the following console output:
192+
Firstly need to download Zephyr binary image into DDR memory, it can use tftp:
150193

151194
.. code-block:: console
152195
153-
*** Booting Zephyr OS build v3.6.0-4569-g483c01ca11a7 ***
154-
thread_a: Hello World from cpu 0 on imx95_evk!
155-
thread_b: Hello World from cpu 0 on imx95_evk!
156-
thread_a: Hello World from cpu 0 on imx95_evk!
157-
thread_b: Hello World from cpu 0 on imx95_evk!
158-
thread_a: Hello World from cpu 0 on imx95_evk!
196+
tftp 0xd0000000 zephyr.bin
197+
198+
Or copy the Zephyr image ``zephyr.bin`` SD card and plug the card into the board, for example
199+
if copy to the FAT partition of the SD card, use the following U-Boot command to load the image
200+
into DDR memory (assuming the SD card is dev 1, fat partition ID is 1, they could be changed
201+
based on actual setup):
159202

160-
2. Build and run the SMP application
203+
.. code-block:: console
204+
205+
fatload mmc 1:1 0xd0000000 zephyr.bin;
206+
207+
Step 2: Boot Zephyr
208+
-------------------
209+
210+
Use this configuration to run basic Zephyr applications and kernel tests,
211+
for example, with the :zephyr:code-sample:`synchronization` sample:
161212

162213
.. zephyr-app-commands::
163214
:zephyr-app: samples/synchronization
164215
:host-os: unix
165-
:board: imx95_evk/mimx9596/a55/smp
216+
:board: imx95_evk/mimx9596/a55
166217
:goals: build
167218

168219
This will build an image (zephyr.bin) with the synchronization sample app.
169220

170-
Copy the compiled ``zephyr.bin`` to the first FAT partition of the SD card and
171-
plug the SD card into the board. Power it up and stop the u-boot execution at
172-
prompt.
173-
174-
Use the following command to kick zephyr.bin to Cortex-A55 Core0:
221+
Then use the following command to boot Zephyr on the core0:
175222

176223
.. code-block:: console
177224
178-
fatload mmc 1:1 0xd0000000 zephyr.bin; dcache flush; icache flush; go 0xd0000000
225+
dcache off; icache flush; go 0xd0000000;
179226
227+
Or use "cpu" command to boot from secondary Core, for example Core1:
228+
229+
.. code-block:: console
230+
231+
dcache flush; icache flush; cpu 1 release 0xd0000000
180232
181233
It will display the following console output:
234+
182235
.. code-block:: console
183236
184-
*** Booting Zephyr OS build v3.7.0-rc3-15-g2f0beaea144a ***
185-
Secondary CPU core 1 (MPID:0x100) is up
186-
Secondary CPU core 2 (MPID:0x200) is up
187-
Secondary CPU core 3 (MPID:0x300) is up
188-
Secondary CPU core 4 (MPID:0x400) is up
189-
Secondary CPU core 5 (MPID:0x500) is up
190-
thread_a: Hello World from cpu 0 on imx95_evk!
191-
thread_b: Hello World from cpu 4 on imx95_evk!
192-
thread_a: Hello World from cpu 0 on imx95_evk!
193-
thread_b: Hello World from cpu 3 on imx95_evk!
237+
*** Booting Zephyr OS build v3.6.0-4569-g483c01ca11a7 ***
194238
thread_a: Hello World from cpu 0 on imx95_evk!
195-
thread_b: Hello World from cpu 1 on imx95_evk!
239+
thread_b: Hello World from cpu 0 on imx95_evk!
196240
thread_a: Hello World from cpu 0 on imx95_evk!
197-
thread_b: Hello World from cpu 5 on imx95_evk!
241+
thread_b: Hello World from cpu 0 on imx95_evk!
198242
thread_a: Hello World from cpu 0 on imx95_evk!
199-
thread_b: Hello World from cpu 2 on imx95_evk!
243+
244+
Option 3. Boot Zephyr by Using Remoteproc under Linux
245+
=====================================================
246+
247+
When running Linux on the A55 core, it can use the remoteproc framework to load and boot Zephyr,
248+
refer to Real-Time Edge user guide for more details. Pre-build images and user guide can be found
249+
at `Real-Time Edge Software`_.
250+
200251

201252
Programming and Debugging (M7)
202253
******************************
@@ -213,13 +264,47 @@ To program M7, an i.MX container image ``flash.bin`` must be made, which contain
213264
multiple elements required, like ELE+V2X firmware, System Manager, TCM OEI, Cortex-M7
214265
image and so on.
215266

216-
The steps making flash.bin and programming should refer to ``Getting Started with
267+
SPSDK runner is used to build ``flash.bin``, and it requires fetching binary blobs, which
268+
can be achieved by running the following command:
269+
270+
.. code-block:: console
271+
272+
west blobs fetch hal_nxp
273+
274+
.. note::
275+
276+
It is recommended running the command above after :file:`west update`.
277+
278+
Two methods to build and program ``flash.bin``.
279+
280+
1. If :kconfig:option:`CONFIG_BOARD_NXP_SPSDK_IMAGE` is not available for the board variant,
281+
the steps making flash.bin and programming should refer to ``Getting Started with
217282
MCUXpresso SDK for IMX95LPD5EVK-19.pdf`` in i.MX95 `MCUX SDK release`_. Note that
218283
for the DDR variant, one should use the Makefile targets containing the ``ddr`` keyword.
219-
220284
See ``4.2 Run an example application``, just rename ``zephyr.bin`` to ``m7_image.bin``
221285
to make flash.bin and program to SD/eMMC.
222286

287+
2. If :kconfig:option:`CONFIG_BOARD_NXP_SPSDK_IMAGE` is available and enabled for the board variant,
288+
``flash.bin`` will be built automatically. The programming could be through below commands.
289+
Before that, switch SW7[1:4] should be configured to 0b1001 for usb download mode
290+
to boot, and USB1 and DBG ports should be connected to PC. There are 4 serial ports
291+
enumerated (115200 8n1), and we use the first for M7 and the fourth for M33 System Manager.
292+
(The flasher is spsdk which already installed via scripts/requirements.txt.
293+
On linux host, usb device permission should be configured per Installation Guide
294+
of https://spsdk.readthedocs.io)
295+
296+
.. code-block:: none
297+
298+
# load and run without programming. for next flashing, execute 'reset' in the
299+
# fourth serail port
300+
$ west flash
301+
302+
# program to SD card, then set SW7[1:4]=0b1011 to reboot
303+
$ west flash --bootdevice sd
304+
305+
# program to emmc card, then set SW7[1:4]=0b1010 to reboot
306+
$ west flash --bootdevice=emmc
307+
223308
Zephyr supports two M7-based i.MX95 boards: ``imx95_evk/mimx9596/m7`` and
224309
``imx95_evk/mimx9596/m7/ddr``. The main difference between them is the memory
225310
used. ``imx95_evk/mimx9596/m7`` uses TCM (ITCM for code and, generally, read-only

boards/nxp/imx95_evk/imx95_evk_mimx9596_a55.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright 2024 NXP
2+
# Copyright 2024-2025 NXP
33
#
44
# SPDX-License-Identifier: Apache-2.0
55
#
@@ -16,4 +16,7 @@ supported:
1616
- counter
1717
- i2c
1818
- uart
19+
testing:
20+
binaries:
21+
- flash.bin
1922
vendor: nxp

0 commit comments

Comments
 (0)