Skip to content

Added the NXP i.MX RT1064-EVK target with three demos and Renode CI - #66

Merged
fdesbiens merged 12 commits into
eclipse-threadx:devfrom
alieissa-commits:dev
Sep 16, 2026
Merged

fdesbiens merged 12 commits into
eclipse-threadx:devfrom
alieissa-commits:dev

Conversation

@alieissa-commits

@alieissa-commits alieissa-commits commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

samplex demonstrates Eclipse ThreadX and NetX Duo on Cortex-M4 and RISC-V, but had no reference enablement for NXP's Cortex-M7 crossover parts, and no way to exercise the network stack in CI without hardware.

This adds targets/NXP/MIMXRT1064-EVK/, built from templates/target/ and implementing the bsp/include/bsp/ contract, with three demos: threadx_basic (scheduling, timers, LED), netx_echo (ICMP, UDP and TCP echo on port 7) and netx_trng_console (on-chip TRNG behind a single-session TCP shell on port 23, serving one connection at a time). The ENET and KSZ8081 PHY drivers are vendored rather than tracked from getting-started, which is on the same archive track as iot-devkit. Every SDK and CMSIS download is pinned to a tag or commit and SHA256-verified. A Renode platform model and a headless Python runner join the existing CI, reusing the pinned toolchain and Renode steps from #53 and #55.

Renode 1.16.1, all three demos green: threadx_basic asserts the worker thread runs at tick 100; netx_echo asserts link up, ARP, ICMP reply and 23-byte UDP and TCP echoes across two emulated nodes; netx_trng_console asserts four distinct non-zero entropy words, remote LED toggle, uptime telemetry, and that an over-long command line is refused without dropping the session. Not run on hardware. The README records what the emulator stubs: CCM and ANALOG are tag stubs whose registers read back fixed values, the 600 MHz banner is a compile-time constant, and Renode's TRNG model implements neither the programming sequence nor the ENT15 block-consume semantics, so the driver's bring-up is unverified on silicon.

Signed-off-by: Ali Eissa ali.eissa.dev@gmail.com
Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) noreply@antigravity.google

@fdesbiens fdesbiens left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, it is a substantial piece of work and parts of it are the best-structured contribution the pipeline has had. The CI job picks up the pinned, checksum-verified Arm toolchain and Renode steps from #53 and #55 rather than reinventing them, and it caches both. Three demos that build clean and run under multi-node emulation is a real result.

I am requesting changes on four things: two structural, one a claim that is ahead of its evidence, and one a test that cannot fail. Detail is in the inline comments, summary here.

Where it lands. docs/architecture.md sections 2 and 4 place new boards under targets/<Vendor>/<Board>/, started from templates/target/ and implementing the abstract interfaces in bsp/include/bsp/. This PR adds a root-level NXP/, alongside MXChip, OpenHW and STMicroelectronics, which that document labels [Pre-framework] and freezes. It also defines its own board_init(), console_write() and USER_LED_* macros in place of bsp_board_init, bsp_console_write and bsp_led_*. The framework exists to stop that legacy set growing, so this needs to move to targets/NXP/MIMXRT1064-EVK/ and implement the contract. The existing console_* functions can stay exactly as they are, sitting behind bsp_console_write.

fetch_sdk.sh reintroduces what #55 removed. Three of the five fetches track a moving ref, mcuxsdk-examples at main, getting-started at master and CMSIS_5 at its default branch, and not one of the five is checksummed. The CI step also runs the full CMSIS clone on every build with no cache. Pin each ref to a tag or a commit, verify what comes down, and cache on the pin, the way the toolchain steps in that same workflow file already do.

The verification claims are ahead of the verification. The passing Renode run emits 1,472 non existing peripheral warnings. Renode 1.16.1 ships platforms/cpus/imxrt1064.repl, which declares CCM, ANALOG, IOMUXC, IOMUXC_GPR, SRC and OCOTP as Tag stubs, two of them returning fixed values: CCM_CBCDR reads back 0x000A8200 and the analog register at 0x400D8030 reads back 0x80002001 no matter what the code writes. So BOARD_BootClockRUN(), the PLL bring-up and the pin mux are not merely unverified, the emulator reports success to anything that polls them. The 600 MHz in the banner is a compile-time constant assigned in the SDK's clock_config.c, not a readback. What this suite establishes is that the image boots and that ThreadX and NetX Duo work over Renode's Ethernet model. That is worth having, and worth saying precisely in the README.

The TRNG test cannot fail, which matters more than the rest because there is an open driver correctness question behind it. See the comments on app/trng.c and on both netx_trng_console files.

The description reads as a feature announcement rather than cause, fix and proof, and it describes the shell as multi-client when it is one socket in one thread serving one connection at a time. The numbering also skips 4. Please rewrite it around what changed and what the run actually asserts: on a squash with this many commits the PR title and body become the permanent history entry.

@@ -0,0 +1,241 @@
# Copyright (c) 2026 Eclipse ThreadX contributors

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking, placement. This whole tree should live at targets/NXP/MIMXRT1064-EVK/, not at the repository root.

docs/architecture.md section 4 describes onboarding a board as: create targets/<Vendor>/<Board_Name>/ from templates/target/, then implement the interfaces in bsp/include/bsp/. The root-level vendor directories are the pre-framework set that section 1 explicitly freezes, and adding a fourth reopens it.

Beyond the move, the board needs to implement bsp_board_init, bsp_led_init/on/off/toggle and bsp_console_init/write. board_init() and console_write() here are the right implementations, they just need to sit behind those names so the demos can be built against the contract rather than against this board.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I relocated the target directory to targets/NXP/MIMXRT1064-EVK/ per repository architecture guidelines. I also implemented the standard BSP interfaces under lib/bsp so application demos link against the contract rather than board-specific functions.

Comment thread NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh Outdated
trap clean_temp EXIT

# 1. Download official NXP MIMXRT1064 DFP pack from NXP repository
PACK_URL="https://mcuxpresso.nxp.com/cmsis_pack/repo/NXP.MIMXRT1064_DFP.15.1.0.pack"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pack version is pinned, good, but there is no checksum. #55 established pin plus SHA256 verification for every download in this repository, and this is the one path that does not follow it.

The same applies to the four curl calls and the clone below.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pinned the NXP MCUXpresso SDK pack download and enforced SHA256 cryptographic checksum verification in fetch scripts.

Comment thread NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh Outdated
echo ""

# 2. Download EVK-MIMXRT1064 Board Support Files from official NXP mcuxsdk-examples
RAW_BASE="https://raw.githubusercontent.com/nxp-mcuxpresso/mcuxsdk-examples/main/_boards/evkmimxrt1064"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking. Ten build-critical files fetched from main. Any commit upstream silently changes what this board compiles, with nothing recording which version produced a given build.

Pin to a tag or a commit SHA and verify the downloads.

A second problem in the loops that follow: the if [ -f ... ]; then cp guard means a missing file is skipped silently rather than failing. That defeats set -e, so an upstream layout change produces a half-populated SDK and a confusing compile error instead of a clear failure here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pinned all individual SDK source files to an immutable commit SHA with checksum validation and removed the silent file skipping conditionals.

Comment thread NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh Outdated
# 3. Fetch CMSIS Core headers
echo "[INFO] Cloning CMSIS Core headers (depth=1)..."
CMSIS_CLONE_DIR="${TEMP_DIR}/cmsis_core_repo"
git clone --depth 1 https://github.com/ARM-software/CMSIS_5.git "${CMSIS_CLONE_DIR}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking. An unpinned clone of the CMSIS_5 default branch. Pin it to a release tag.

This is also uncached in CI, so every run re-clones the repository in full. #55 removed exactly this cost for the toolchain and Renode downloads; once the ref is pinned, actions/cache keyed on that pin will do the same here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pinned the CMSIS repository checkout to official release tag 5.9.0 in the fetch scripts and added GitHub Actions caching keyed on the tag.

Comment thread NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh Outdated

# 5. Fetch official NetX Duo NXP Ethernet driver (100% stock upstream)
echo "[INFO] Downloading official NetX Duo NXP Ethernet driver..."
NETX_RAW_BASE="https://raw.githubusercontent.com/eclipse-threadx/getting-started/master/NXP/MIMXRT1060-EVK/lib/netx_driver"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking. The NetX Ethernet driver and, just above, the KSZ8081 PHY driver are pulled from getting-started at master, unpinned.

Worth a separate decision from the two of us before this merges: getting-started is on the same archive track as iot-devkit, which the root README says will be retired. Making two build-critical drivers depend on its master HEAD points this board at a repository the project intends to stop maintaining. Vendoring the two drivers, as the NUCLEO target does with the STM32 HAL, may be the better answer.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you suggested, I vendored the drivers directly into lib/ and stopped relying on getting-started.

Comment thread NXP/MIMXRT1064-EVK/app/sysmem.c Outdated
/**
* @brief _sbrk() allocates memory to the newlib heap and is used by malloc.
*/
void *_sbrk(ptrdiff_t incr)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_sbrk has no mutual exclusion, and there are no __malloc_lock / __malloc_unlock implementations anywhere in the board.

All three demos call printf from two or more threads, and threadx_basic also calls it from a TX_TIMER callback. newlib allocates the stdout buffer on the first buffered write, so two threads reaching that point together can corrupt the heap. This is the kind of defect that will not show up in a two-second emulation run and will show up on a desk after an hour.

Either implement the malloc lock hooks over a TX_MUTEX, or give the console its own mutex and make stdout unbuffered.

Separately: the bound here is __StackLimit, while the linker script also defines __heap_limit with the comment Add for _sbrk. One of the two should go.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I implemented thread-safe __malloc_lock and __malloc_unlock hooks to protect newlib's heap and stdout allocations. Synchronized _sbrk allocations and consolidated linker memory bounds onto __heap_limit.

#include "tx_api.h"
#include <stdio.h>

#define HEARTBEAT_THREAD_STACK_SIZE 1024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 KB is too small for a thread that calls printf.

newlib's full vfprintf wants on the order of a kilobyte of stack by itself, and both threads here format %lu conversions. ThreadX stack checking is off by default, so an overflow corrupts whatever is adjacent rather than faulting, which makes it painful to diagnose later.

2 KB would be the safe floor. It is also worth enabling TX_ENABLE_STACK_CHECKING in the debug configuration so the suite catches this class of problem itself.

One more, unrelated to size: these stacks are uint8_t[] here and in netx_echo, but ULONG[] in netx_trng_console. ThreadX realigns internally so nothing breaks, but pick one.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now using 2 KB, unified ULONG[], and also enabled TX_ENABLE_STACK_CHECKING as suggested.

Comment thread NXP/MIMXRT1064-EVK/app/MIMXRT1062.h Outdated
* Compatibility header: redirects MIMXRT1062.h from stock NetX Duo driver
* to MIMXRT1064 device registers without modifying vendor source files.
*/
#ifndef _MIMXRT1062_H_

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_MIMXRT1062_H_ is a reserved identifier: a leading underscore followed by a capital is reserved to the implementation in every C standard, and MISRA C 2012 Rule 21.2 rejects it.

MIMXRT1062_H is enough. The shim itself is a neat solution to keeping the vendor driver unmodified.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, now changed to MIMXRT1062_H

Comment thread NXP/MIMXRT1064-EVK/CMakeLists.txt Outdated
${SDK_DIR}/drivers/fsl_enet.c
)

target_compile_definitions(netx_imxrt_driver_client

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This eight-line definitions block is the fourth verbatim copy in this file, and the include list below is the fourth near-copy.

An INTERFACE library carrying both, linked by each target, would remove all of it. netx_imxrt_driver and netx_imxrt_driver_client differ only by NETX_CLIENT_NODE=1 and could otherwise share everything.

The block starting at the # 2. comment is also indented four spaces where nothing else in the file is.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created mimxrt1064_common and netx_imxrt_driver_common CMake INTERFACE libraries to centralize compile definitions, includes, and driver flags. Also deduplicated server/client driver targets so they share all sources and differ only by NETX_CLIENT_NODE=1, and corrected section indentation.

Comment thread .github/workflows/ci.yml Outdated
on:
push:
branches: [ main, master, dev, 'feat/**' ]
branches: [ main, master, dev, 'feat/**', 'test/**' ]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test/** is a branch-naming convention from this contribution rather than something the pipeline needs, and it changes the trigger for every job in the file. Please drop it.

workflow_dispatch below is a good addition, keep that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed test/** and preserved workflow_dispatch.

Signed-off-by: Ali Eissa <ali.eissa.dev@gmail.com>
Assisted-by: Google DeepMind Antigravity
Signed-off-by: Ali Eissa <ali.eissa.dev@gmail.com>
Assisted-by: Google DeepMind Antigravity
Signed-off-by: Ali Eissa <ali.eissa.dev@gmail.com>
Assisted-by: Google DeepMind Antigravity
Signed-off-by: Ali Eissa <ali.eissa.dev@gmail.com>
Assisted-by: Google DeepMind Antigravity
Signed-off-by: Ali Eissa <ali.eissa.dev@gmail.com>
Assisted-by: Google DeepMind Antigravity
Signed-off-by: Ali Eissa <ali.eissa.dev@gmail.com>
Assisted-by: Google DeepMind Antigravity
Signed-off-by: Ali Eissa <ali.eissa.dev@gmail.com>
Assisted-by: Google DeepMind Antigravity
…rhaul

Signed-off-by: Ali Eissa <ali.eissa.dev@gmail.com>
Assisted-by: Google DeepMind Antigravity
…fication pipeline

Signed-off-by: Ali Eissa <ali.eissa.dev@gmail.com>
Assisted-by: Google DeepMind Antigravity
…, and Renode simulation

- Relocate target under targets/NXP/MIMXRT1064-EVK with modular BSP architecture
- Provide ThreadX basic, NetX Duo echo, and TRNG console demos
- Vendor NetX Duo Ethernet driver and KSZ8081 PHY driver
- Align TRNG bring-up, entropy extraction, and status verification
- Enforce thread-safe heap (_sbrk) and console mutex protection
- Expand thread stacks to 2KB and enable stack checking
- Pin official NXP SDK and CMSIS dependencies with SHA-256 verification
- Deduplicate CMake targets with mimxrt1064_common INTERFACE library
- Integrate headless single-node and multi-node Renode CI verification

Signed-off-by: Ali Eissa <ali.eissa.dev@gmail.com>
Assisted-by: Google DeepMind Antigravity
Signed-off-by: Ali Eissa <ali.eissa.dev@gmail.com>
Assisted-by: Google DeepMind Antigravity
@alieissa-commits alieissa-commits changed the title [NXP: MIMXRT1064-EVK] Board Enablement feat(nxp): add NXP i.MX RT1064-EVK board enablement with ThreadX, NetX Duo, and Renode CI verification Sep 16, 2026
nx_packet_data_retrieve copies an entire packet chain into the caller's buffer and
takes no destination size. Four call sites clamped bytes_copied after the call, by
which point the copy had already overrun. The worst is the TRNG console shell: a
128-byte line buffer on a 2 KB thread stack, reachable from the network on port 23
with a 1536-byte pool payload.

The shell now refuses a line that does not fit before retrieving it, rather than
truncating one, which would run a different command than the client sent. The three
client-side sites use nx_packet_data_extract_offset, which takes a buffer length and
truncates safely. The README moves the TRNG from what Renode models to what it stubs,
citing the emulator's own Unhandled write warnings for MCTL[PRGM], MCTL[RST_DEF] and
SDCTL, and the seed-12345 comparison now reports a mismatch instead of passing in
silence.

A new client test sends a 199-byte line and asserts the shell refuses it and still
answers ping. It fails against the unpatched server, which replied "Unknown command"
after overrunning the buffer by roughly 70 bytes, and passes with the fix. Renode
1.16.1: 3/3 demos green, zero build warnings with Arm GCC 14.3.Rel1.

Signed-off-by: Frédéric Desbiens <frederic.desbiens@eclipse-foundation.org>
Assisted-by: Claude Code (Opus 5) <noreply@anthropic.com>
@fdesbiens fdesbiens changed the title feat(nxp): add NXP i.MX RT1064-EVK board enablement with ThreadX, NetX Duo, and Renode CI verification Added the NXP i.MX RT1064-EVK target with three demos and Renode CI Sep 16, 2026
@fdesbiens

Copy link
Copy Markdown
Contributor

Every point from the first pass is addressed, and the two that mattered most are fixed properly rather than worked around: every SDK and CMSIS download is now pinned to a tag or commit and SHA256-verified, and the TRNG driver follows the documented bring-up and consumes the block through ENT15. Vendoring the ENET and PHY drivers was the right call. I have pushed one commit on top rather than send you round again for it, and retitled the PR and rewrote the description, since with this many commits the squash takes both from here.

nx_packet_data_retrieve takes no destination size -- it copies the whole chain, and the NetX source says so at common/src/nx_packet_data_retrieve.c:96. The four sites that clamped bytes_copied after the call were clamping after the copy had already happened. The worst was the shell's 128-byte line_buffer on a 2 KB stack, reachable on port 23 with a 1536-byte pool payload. The shell now refuses an over-long line before retrieving it, because truncating one would run a different command than the client sent, and the three client-side sites use nx_packet_data_extract_offset, which takes a buffer length. Your own guard at netx_echo/main.c:248 was the model for it.

The new client test sends a 199-byte line and asserts the shell refuses it and still answers ping. I checked it against the unpatched server, and how it fails is the interesting part: no crash, just Unknown command after a roughly 70-byte overrun. That is why a green run never caught it.

I also moved the TRNG out of "what Renode accurately simulates" in the README. The emulator logs Unhandled write for MCTL[PRGM], MCTL[RST_DEF] and SDCTL, so the corrected bring-up sequence is a no-op there and nothing in CI exercises it. The driver reads correct against the reference manual; it simply has not met silicon yet. That is now tracked in #70 rather than holding up the target.

Thanks for the care on this one. The BSP split landed cleanly against the framework contract, and 6/6 CI jobs are green.

@fdesbiens fdesbiens left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in full. Detail in the comment above.

@fdesbiens
fdesbiens merged commit 8a133d7 into eclipse-threadx:dev Sep 16, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants