Skip to content

STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase - #45

Merged
fdesbiens merged 14 commits into
eclipse-threadx:devfrom
AmmarOkla12772:feat/clean-nucleo-demo
Jul 20, 2026
Merged

STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase#45
fdesbiens merged 14 commits into
eclipse-threadx:devfrom
AmmarOkla12772:feat/clean-nucleo-demo

Conversation

@AmmarOkla12772

Copy link
Copy Markdown
Contributor

Note: This PR supersedes the previous submission having addressed the review feedback. The AZ3166 refactoring has been undone, and the required MIT license header has been added to main.c.

Overview

This PR extends the validation demo for the STMicroelectronics NUCLEO-F401RE board under STMicroelectronics/NUCLEO_F401RE/.

The goal is to provide a comprehensive ThreadX RTOS demonstration showcasing dynamic memory management, runtime diagnostics, thread monitoring, and synchronization primitives using public ThreadX APIs.

Changes

  • Replaced static thread stack allocation with a central TX_BYTE_POOL
  • Added runtime memory diagnostics reporting total, allocated, and free byte pool capacity
  • Added TX_BLOCK_POOL for fixed-size deterministic memory allocation
  • Added message passing between sender and receiver threads using TX_QUEUE
  • Added pointer-based queue transfers backed by block pool allocations
  • Added TX_MUTEX synchronization with two competing worker threads sharing a simulated SPI resource
  • Added TX_EVENT_FLAGS_GROUP synchronization between the LED heartbeat thread and an event-processing thread
  • Added TX_SEMAPHORE synchronization with a dedicated consumer thread awakened by LED activity
  • Added TX_TIMER periodic callback executing once per second from the ThreadX system timer thread
  • Expanded the demo from 3 threads to 9 threads to exercise core ThreadX scheduling and synchronization features
  • Added registry-based thread diagnostics using tx_thread_info_get()
  • Added stack high-water mark monitoring by scanning the ThreadX stack fill pattern (0xEFEFEFEF)
  • Added per-thread stack usage and utilization reporting
  • Added formatted runtime telemetry output over USART2 including thread states, priorities, run counts, memory statistics, and synchronization activity counters
  • Added the required MIT license header to main.c to align with project licensing requirements.

Validation

Tested on physical NUCLEO-F401RE board:

  • System runs continuously without crashes or scheduler instability
  • UART output remains stable at 115200 baud
  • Free memory remains constant at 79028 bytes during operation, indicating no byte pool or block pool leaks
  • Thread diagnostics correctly report state transitions, run counts, priorities, and stack watermarks
  • Stack utilization remains within safe limits for all threads
  • System uptime tracks wall-clock time accurately
  • ThreadX synchronization primitives operate as expected under active scheduling
  • No build warnings with Arm GNU Toolchain 15.2.Rel1

Toolchain

  • Arm GNU Toolchain 15.2.Rel1
  • CMake + Ninja build system

Notes

All runtime diagnostics are implemented using documented ThreadX public APIs. No private kernel structures or undocumented internal ThreadX data are accessed, maintaining portability across ThreadX targets.

ammarokla123and others added 14 commits June 8, 2026 05:10
	new file: STMicroelectronics/NUCLEO_F401RE/README.md
new file: STMicroelectronics/NUCLEO_F401RE/app/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/app/common/board_init.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/board_init.h
new file: STMicroelectronics/NUCLEO_F401RE/app/common/console.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/sntp_client.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/NUCLEO_F401RE.ld
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/startup_stm32f401xe.s
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/tx_initialize_low_level.S
new file: STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c
new file: STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h
new file: STMicroelectronics/NUCLEO_F401RE/app/starter/main.c
new file: STMicroelectronics/NUCLEO_F401RE/cmake/FindCMSIS.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/FindSTM32HAL.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-m4.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-toolchain.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/utilities.cmake
new file: STMicroelectronics/NUCLEO_F401RE/lib/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.c
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.h
new file: STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/config/stm32f4xx_hal_conf.h
Booted ThreadX on NUCLEO-F401RE
Validated scheduler operation
Validated UART console output
Validated LED thread
Validated flashing and hardware execution
…and event flags. Modified demo README file to reflect changes.
…aphore functionality and 1 hz applicaion timer.
Co-authored-by: Codex <codex@openai.com>
Retained the PR implementation for overlapping NUCLEO-F401RE files.\n\nCo-authored-by: Codex <codex@openai.com>
@fdesbiensfdesbiens changed the title feat(nucleo-f401re): implement comprehensive ThreadX RTOS monitor and primitives showcaseSTMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcaseJul 20, 2026
@fdesbiens
fdesbiens merged commit 1bddd17 into eclipse-threadx:devJul 20, 2026
1 check passed
@fdesbiens

Copy link
Copy Markdown
Contributor

I merged to dev; this will ship with the Q3 2026 release in September.

Thank you for this contribution, @AmmarOkla12772.

In the future, make sure your original files contain the full mandatory header as shown below.

/* * Copyright (c) 2026 Eclipse ThreadX contributors * * This program and the accompanying materials are made available * under the terms of the MIT license which is available at * https://opensource.org/license/mit. * * SPDX-License-Identifier: MIT */

Also, there were some minor merge conflicts. Always make sure you pull from upstream before creating a PR. Don't worry, I forget this from time to time myself...

fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR eclipse-threadx#45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR eclipse-threadx#45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR eclipse-threadx#45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR eclipse-threadx#45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
fdesbiens added a commit that referenced this pull request Aug 31, 2026
…50)
* feat(nucleo): Relocate NUCLEO_F401RE into targets and migrate to generic BSP framework
* Bounded the newlib heap to its linker reservation
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR #45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
* Restored console error handling and the AI disclosure headers
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR #45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
* Pinned the ARM toolchain to GCC 14 and refreshed the target documentation
The build-arm-nucleo job installed the distribution's gcc-arm-none-eabi,
which is GCC 13.2 on ubuntu-24.04, so the compiler drifted with the runner
image. AGENTS.md specifies GCC 14 and the sibling RISC-V job already pins
xPack GCC 14.2.0 by URL; the ARM job now pins Arm GNU Toolchain 14.2.Rel1
the same way. The toolchain bundles its own newlib, so the separate newlib
packages are no longer installed.
CMAKE_C_STANDARD moves from 11 to 99 per the AGENTS.md C99 requirement.
The target builds clean under both GCC 13.2.1 and the pinned GCC 14.2.1
with -Wall -Wshadow -Wdouble-promotion -Werror.
README.md moved with git mv but still described the pre-migration layout:
the build directory as STMicroelectronics/NUCLEO_F401RE, the HAL timebase
overrides as living in board_init.c, and the BSP as lib/nucleo_bsp/. All
three are corrected and the BSP entry now lists the four sources behind the
generic interfaces.
The Validation Record quoted 18244 B ROM and 5632 B RAM against a toolchain
the CI pipeline does not use. Re-measured against the newly pinned GCC
14.2.1: 20120 B ROM and 6000 B RAM. The hardware verification checklist is
left as the contributor recorded it.
---------
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frédéric Desbiens <frederic.desbiens@eclipse-foundation.org>
Sign up for freeto 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.

3 participants

@AmmarOkla12772@fdesbiens@ammarokla123
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase by AmmarOkla12772 · Pull Request #45 · eclipse-threadx/samplex · GitHub
Skip to content

STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase - #45

Merged
fdesbiens merged 14 commits into
eclipse-threadx:devfrom
AmmarOkla12772:feat/clean-nucleo-demo
Jul 20, 2026
Merged

STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase#45
fdesbiens merged 14 commits into
eclipse-threadx:devfrom
AmmarOkla12772:feat/clean-nucleo-demo

Conversation

@AmmarOkla12772

Copy link
Copy Markdown
Contributor

Note: This PR supersedes the previous submission having addressed the review feedback. The AZ3166 refactoring has been undone, and the required MIT license header has been added to main.c.

Overview

This PR extends the validation demo for the STMicroelectronics NUCLEO-F401RE board under STMicroelectronics/NUCLEO_F401RE/.

The goal is to provide a comprehensive ThreadX RTOS demonstration showcasing dynamic memory management, runtime diagnostics, thread monitoring, and synchronization primitives using public ThreadX APIs.

Changes

  • Replaced static thread stack allocation with a central TX_BYTE_POOL
  • Added runtime memory diagnostics reporting total, allocated, and free byte pool capacity
  • Added TX_BLOCK_POOL for fixed-size deterministic memory allocation
  • Added message passing between sender and receiver threads using TX_QUEUE
  • Added pointer-based queue transfers backed by block pool allocations
  • Added TX_MUTEX synchronization with two competing worker threads sharing a simulated SPI resource
  • Added TX_EVENT_FLAGS_GROUP synchronization between the LED heartbeat thread and an event-processing thread
  • Added TX_SEMAPHORE synchronization with a dedicated consumer thread awakened by LED activity
  • Added TX_TIMER periodic callback executing once per second from the ThreadX system timer thread
  • Expanded the demo from 3 threads to 9 threads to exercise core ThreadX scheduling and synchronization features
  • Added registry-based thread diagnostics using tx_thread_info_get()
  • Added stack high-water mark monitoring by scanning the ThreadX stack fill pattern (0xEFEFEFEF)
  • Added per-thread stack usage and utilization reporting
  • Added formatted runtime telemetry output over USART2 including thread states, priorities, run counts, memory statistics, and synchronization activity counters
  • Added the required MIT license header to main.c to align with project licensing requirements.

Validation

Tested on physical NUCLEO-F401RE board:

  • System runs continuously without crashes or scheduler instability
  • UART output remains stable at 115200 baud
  • Free memory remains constant at 79028 bytes during operation, indicating no byte pool or block pool leaks
  • Thread diagnostics correctly report state transitions, run counts, priorities, and stack watermarks
  • Stack utilization remains within safe limits for all threads
  • System uptime tracks wall-clock time accurately
  • ThreadX synchronization primitives operate as expected under active scheduling
  • No build warnings with Arm GNU Toolchain 15.2.Rel1

Toolchain

  • Arm GNU Toolchain 15.2.Rel1
  • CMake + Ninja build system

Notes

All runtime diagnostics are implemented using documented ThreadX public APIs. No private kernel structures or undocumented internal ThreadX data are accessed, maintaining portability across ThreadX targets.

ammarokla123and others added 14 commits June 8, 2026 05:10
	new file: STMicroelectronics/NUCLEO_F401RE/README.md
new file: STMicroelectronics/NUCLEO_F401RE/app/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/app/common/board_init.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/board_init.h
new file: STMicroelectronics/NUCLEO_F401RE/app/common/console.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/sntp_client.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/NUCLEO_F401RE.ld
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/startup_stm32f401xe.s
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/tx_initialize_low_level.S
new file: STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c
new file: STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h
new file: STMicroelectronics/NUCLEO_F401RE/app/starter/main.c
new file: STMicroelectronics/NUCLEO_F401RE/cmake/FindCMSIS.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/FindSTM32HAL.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-m4.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-toolchain.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/utilities.cmake
new file: STMicroelectronics/NUCLEO_F401RE/lib/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.c
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.h
new file: STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/config/stm32f4xx_hal_conf.h
Booted ThreadX on NUCLEO-F401RE
Validated scheduler operation
Validated UART console output
Validated LED thread
Validated flashing and hardware execution
…and event flags. Modified demo README file to reflect changes.
…aphore functionality and 1 hz applicaion timer.
Co-authored-by: Codex <codex@openai.com>
Retained the PR implementation for overlapping NUCLEO-F401RE files.\n\nCo-authored-by: Codex <codex@openai.com>
@fdesbiensfdesbiens changed the title feat(nucleo-f401re): implement comprehensive ThreadX RTOS monitor and primitives showcaseSTMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcaseJul 20, 2026
@fdesbiens
fdesbiens merged commit 1bddd17 into eclipse-threadx:devJul 20, 2026
1 check passed
@fdesbiens

Copy link
Copy Markdown
Contributor

I merged to dev; this will ship with the Q3 2026 release in September.

Thank you for this contribution, @AmmarOkla12772.

In the future, make sure your original files contain the full mandatory header as shown below.

/* * Copyright (c) 2026 Eclipse ThreadX contributors * * This program and the accompanying materials are made available * under the terms of the MIT license which is available at * https://opensource.org/license/mit. * * SPDX-License-Identifier: MIT */

Also, there were some minor merge conflicts. Always make sure you pull from upstream before creating a PR. Don't worry, I forget this from time to time myself...

fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR eclipse-threadx#45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR eclipse-threadx#45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR eclipse-threadx#45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR eclipse-threadx#45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
fdesbiens added a commit that referenced this pull request Aug 31, 2026
…50)
* feat(nucleo): Relocate NUCLEO_F401RE into targets and migrate to generic BSP framework
* Bounded the newlib heap to its linker reservation
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR #45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
* Restored console error handling and the AI disclosure headers
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR #45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
* Pinned the ARM toolchain to GCC 14 and refreshed the target documentation
The build-arm-nucleo job installed the distribution's gcc-arm-none-eabi,
which is GCC 13.2 on ubuntu-24.04, so the compiler drifted with the runner
image. AGENTS.md specifies GCC 14 and the sibling RISC-V job already pins
xPack GCC 14.2.0 by URL; the ARM job now pins Arm GNU Toolchain 14.2.Rel1
the same way. The toolchain bundles its own newlib, so the separate newlib
packages are no longer installed.
CMAKE_C_STANDARD moves from 11 to 99 per the AGENTS.md C99 requirement.
The target builds clean under both GCC 13.2.1 and the pinned GCC 14.2.1
with -Wall -Wshadow -Wdouble-promotion -Werror.
README.md moved with git mv but still described the pre-migration layout:
the build directory as STMicroelectronics/NUCLEO_F401RE, the HAL timebase
overrides as living in board_init.c, and the BSP as lib/nucleo_bsp/. All
three are corrected and the BSP entry now lists the four sources behind the
generic interfaces.
The Validation Record quoted 18244 B ROM and 5632 B RAM against a toolchain
the CI pipeline does not use. Re-measured against the newly pinned GCC
14.2.1: 20120 B ROM and 6000 B RAM. The hardware verification checklist is
left as the contributor recorded it.
---------
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frédéric Desbiens <frederic.desbiens@eclipse-foundation.org>
Sign up for freeto 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.

3 participants

@AmmarOkla12772@fdesbiens@ammarokla123
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase by AmmarOkla12772 · Pull Request #45 · eclipse-threadx/samplex · GitHub
Skip to content

STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase - #45

Merged
fdesbiens merged 14 commits into
eclipse-threadx:devfrom
AmmarOkla12772:feat/clean-nucleo-demo
Jul 20, 2026
Merged

STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase#45
fdesbiens merged 14 commits into
eclipse-threadx:devfrom
AmmarOkla12772:feat/clean-nucleo-demo

Conversation

@AmmarOkla12772

Copy link
Copy Markdown
Contributor

Note: This PR supersedes the previous submission having addressed the review feedback. The AZ3166 refactoring has been undone, and the required MIT license header has been added to main.c.

Overview

This PR extends the validation demo for the STMicroelectronics NUCLEO-F401RE board under STMicroelectronics/NUCLEO_F401RE/.

The goal is to provide a comprehensive ThreadX RTOS demonstration showcasing dynamic memory management, runtime diagnostics, thread monitoring, and synchronization primitives using public ThreadX APIs.

Changes

  • Replaced static thread stack allocation with a central TX_BYTE_POOL
  • Added runtime memory diagnostics reporting total, allocated, and free byte pool capacity
  • Added TX_BLOCK_POOL for fixed-size deterministic memory allocation
  • Added message passing between sender and receiver threads using TX_QUEUE
  • Added pointer-based queue transfers backed by block pool allocations
  • Added TX_MUTEX synchronization with two competing worker threads sharing a simulated SPI resource
  • Added TX_EVENT_FLAGS_GROUP synchronization between the LED heartbeat thread and an event-processing thread
  • Added TX_SEMAPHORE synchronization with a dedicated consumer thread awakened by LED activity
  • Added TX_TIMER periodic callback executing once per second from the ThreadX system timer thread
  • Expanded the demo from 3 threads to 9 threads to exercise core ThreadX scheduling and synchronization features
  • Added registry-based thread diagnostics using tx_thread_info_get()
  • Added stack high-water mark monitoring by scanning the ThreadX stack fill pattern (0xEFEFEFEF)
  • Added per-thread stack usage and utilization reporting
  • Added formatted runtime telemetry output over USART2 including thread states, priorities, run counts, memory statistics, and synchronization activity counters
  • Added the required MIT license header to main.c to align with project licensing requirements.

Validation

Tested on physical NUCLEO-F401RE board:

  • System runs continuously without crashes or scheduler instability
  • UART output remains stable at 115200 baud
  • Free memory remains constant at 79028 bytes during operation, indicating no byte pool or block pool leaks
  • Thread diagnostics correctly report state transitions, run counts, priorities, and stack watermarks
  • Stack utilization remains within safe limits for all threads
  • System uptime tracks wall-clock time accurately
  • ThreadX synchronization primitives operate as expected under active scheduling
  • No build warnings with Arm GNU Toolchain 15.2.Rel1

Toolchain

  • Arm GNU Toolchain 15.2.Rel1
  • CMake + Ninja build system

Notes

All runtime diagnostics are implemented using documented ThreadX public APIs. No private kernel structures or undocumented internal ThreadX data are accessed, maintaining portability across ThreadX targets.

ammarokla123and others added 14 commits June 8, 2026 05:10
	new file: STMicroelectronics/NUCLEO_F401RE/README.md
new file: STMicroelectronics/NUCLEO_F401RE/app/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/app/common/board_init.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/board_init.h
new file: STMicroelectronics/NUCLEO_F401RE/app/common/console.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/sntp_client.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/NUCLEO_F401RE.ld
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/startup_stm32f401xe.s
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/tx_initialize_low_level.S
new file: STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c
new file: STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h
new file: STMicroelectronics/NUCLEO_F401RE/app/starter/main.c
new file: STMicroelectronics/NUCLEO_F401RE/cmake/FindCMSIS.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/FindSTM32HAL.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-m4.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-toolchain.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/utilities.cmake
new file: STMicroelectronics/NUCLEO_F401RE/lib/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.c
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.h
new file: STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/config/stm32f4xx_hal_conf.h
Booted ThreadX on NUCLEO-F401RE
Validated scheduler operation
Validated UART console output
Validated LED thread
Validated flashing and hardware execution
…and event flags. Modified demo README file to reflect changes.
…aphore functionality and 1 hz applicaion timer.
Co-authored-by: Codex <codex@openai.com>
Retained the PR implementation for overlapping NUCLEO-F401RE files.\n\nCo-authored-by: Codex <codex@openai.com>
@fdesbiensfdesbiens changed the title feat(nucleo-f401re): implement comprehensive ThreadX RTOS monitor and primitives showcaseSTMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcaseJul 20, 2026
@fdesbiens
fdesbiens merged commit 1bddd17 into eclipse-threadx:devJul 20, 2026
1 check passed
@fdesbiens

Copy link
Copy Markdown
Contributor

I merged to dev; this will ship with the Q3 2026 release in September.

Thank you for this contribution, @AmmarOkla12772.

In the future, make sure your original files contain the full mandatory header as shown below.

/* * Copyright (c) 2026 Eclipse ThreadX contributors * * This program and the accompanying materials are made available * under the terms of the MIT license which is available at * https://opensource.org/license/mit. * * SPDX-License-Identifier: MIT */

Also, there were some minor merge conflicts. Always make sure you pull from upstream before creating a PR. Don't worry, I forget this from time to time myself...

fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR eclipse-threadx#45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR eclipse-threadx#45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR eclipse-threadx#45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR eclipse-threadx#45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
fdesbiens added a commit that referenced this pull request Aug 31, 2026
…50)
* feat(nucleo): Relocate NUCLEO_F401RE into targets and migrate to generic BSP framework
* Bounded the newlib heap to its linker reservation
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR #45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
* Restored console error handling and the AI disclosure headers
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR #45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
* Pinned the ARM toolchain to GCC 14 and refreshed the target documentation
The build-arm-nucleo job installed the distribution's gcc-arm-none-eabi,
which is GCC 13.2 on ubuntu-24.04, so the compiler drifted with the runner
image. AGENTS.md specifies GCC 14 and the sibling RISC-V job already pins
xPack GCC 14.2.0 by URL; the ARM job now pins Arm GNU Toolchain 14.2.Rel1
the same way. The toolchain bundles its own newlib, so the separate newlib
packages are no longer installed.
CMAKE_C_STANDARD moves from 11 to 99 per the AGENTS.md C99 requirement.
The target builds clean under both GCC 13.2.1 and the pinned GCC 14.2.1
with -Wall -Wshadow -Wdouble-promotion -Werror.
README.md moved with git mv but still described the pre-migration layout:
the build directory as STMicroelectronics/NUCLEO_F401RE, the HAL timebase
overrides as living in board_init.c, and the BSP as lib/nucleo_bsp/. All
three are corrected and the BSP entry now lists the four sources behind the
generic interfaces.
The Validation Record quoted 18244 B ROM and 5632 B RAM against a toolchain
the CI pipeline does not use. Re-measured against the newly pinned GCC
14.2.1: 20120 B ROM and 6000 B RAM. The hardware verification checklist is
left as the contributor recorded it.
---------
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frédéric Desbiens <frederic.desbiens@eclipse-foundation.org>
Sign up for freeto 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.

3 participants

@AmmarOkla12772@fdesbiens@ammarokla123
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase by AmmarOkla12772 · Pull Request #45 · eclipse-threadx/samplex · GitHub
Skip to content

STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase - #45

Merged
fdesbiens merged 14 commits into
eclipse-threadx:devfrom
AmmarOkla12772:feat/clean-nucleo-demo
Jul 20, 2026
Merged

STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase#45
fdesbiens merged 14 commits into
eclipse-threadx:devfrom
AmmarOkla12772:feat/clean-nucleo-demo

Conversation

@AmmarOkla12772

Copy link
Copy Markdown
Contributor

Note: This PR supersedes the previous submission having addressed the review feedback. The AZ3166 refactoring has been undone, and the required MIT license header has been added to main.c.

Overview

This PR extends the validation demo for the STMicroelectronics NUCLEO-F401RE board under STMicroelectronics/NUCLEO_F401RE/.

The goal is to provide a comprehensive ThreadX RTOS demonstration showcasing dynamic memory management, runtime diagnostics, thread monitoring, and synchronization primitives using public ThreadX APIs.

Changes

  • Replaced static thread stack allocation with a central TX_BYTE_POOL
  • Added runtime memory diagnostics reporting total, allocated, and free byte pool capacity
  • Added TX_BLOCK_POOL for fixed-size deterministic memory allocation
  • Added message passing between sender and receiver threads using TX_QUEUE
  • Added pointer-based queue transfers backed by block pool allocations
  • Added TX_MUTEX synchronization with two competing worker threads sharing a simulated SPI resource
  • Added TX_EVENT_FLAGS_GROUP synchronization between the LED heartbeat thread and an event-processing thread
  • Added TX_SEMAPHORE synchronization with a dedicated consumer thread awakened by LED activity
  • Added TX_TIMER periodic callback executing once per second from the ThreadX system timer thread
  • Expanded the demo from 3 threads to 9 threads to exercise core ThreadX scheduling and synchronization features
  • Added registry-based thread diagnostics using tx_thread_info_get()
  • Added stack high-water mark monitoring by scanning the ThreadX stack fill pattern (0xEFEFEFEF)
  • Added per-thread stack usage and utilization reporting
  • Added formatted runtime telemetry output over USART2 including thread states, priorities, run counts, memory statistics, and synchronization activity counters
  • Added the required MIT license header to main.c to align with project licensing requirements.

Validation

Tested on physical NUCLEO-F401RE board:

  • System runs continuously without crashes or scheduler instability
  • UART output remains stable at 115200 baud
  • Free memory remains constant at 79028 bytes during operation, indicating no byte pool or block pool leaks
  • Thread diagnostics correctly report state transitions, run counts, priorities, and stack watermarks
  • Stack utilization remains within safe limits for all threads
  • System uptime tracks wall-clock time accurately
  • ThreadX synchronization primitives operate as expected under active scheduling
  • No build warnings with Arm GNU Toolchain 15.2.Rel1

Toolchain

  • Arm GNU Toolchain 15.2.Rel1
  • CMake + Ninja build system

Notes

All runtime diagnostics are implemented using documented ThreadX public APIs. No private kernel structures or undocumented internal ThreadX data are accessed, maintaining portability across ThreadX targets.

ammarokla123and others added 14 commits June 8, 2026 05:10
	new file: STMicroelectronics/NUCLEO_F401RE/README.md
new file: STMicroelectronics/NUCLEO_F401RE/app/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/app/common/board_init.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/board_init.h
new file: STMicroelectronics/NUCLEO_F401RE/app/common/console.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/sntp_client.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/NUCLEO_F401RE.ld
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/startup_stm32f401xe.s
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/tx_initialize_low_level.S
new file: STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c
new file: STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h
new file: STMicroelectronics/NUCLEO_F401RE/app/starter/main.c
new file: STMicroelectronics/NUCLEO_F401RE/cmake/FindCMSIS.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/FindSTM32HAL.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-m4.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-toolchain.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/utilities.cmake
new file: STMicroelectronics/NUCLEO_F401RE/lib/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.c
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.h
new file: STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/config/stm32f4xx_hal_conf.h
Booted ThreadX on NUCLEO-F401RE
Validated scheduler operation
Validated UART console output
Validated LED thread
Validated flashing and hardware execution
…and event flags. Modified demo README file to reflect changes.
…aphore functionality and 1 hz applicaion timer.
Co-authored-by: Codex <codex@openai.com>
Retained the PR implementation for overlapping NUCLEO-F401RE files.\n\nCo-authored-by: Codex <codex@openai.com>
@fdesbiensfdesbiens changed the title feat(nucleo-f401re): implement comprehensive ThreadX RTOS monitor and primitives showcaseSTMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcaseJul 20, 2026
@fdesbiens
fdesbiens merged commit 1bddd17 into eclipse-threadx:devJul 20, 2026
1 check passed
@fdesbiens

Copy link
Copy Markdown
Contributor

I merged to dev; this will ship with the Q3 2026 release in September.

Thank you for this contribution, @AmmarOkla12772.

In the future, make sure your original files contain the full mandatory header as shown below.

/* * Copyright (c) 2026 Eclipse ThreadX contributors * * This program and the accompanying materials are made available * under the terms of the MIT license which is available at * https://opensource.org/license/mit. * * SPDX-License-Identifier: MIT */

Also, there were some minor merge conflicts. Always make sure you pull from upstream before creating a PR. Don't worry, I forget this from time to time myself...

fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR eclipse-threadx#45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR eclipse-threadx#45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR eclipse-threadx#45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR eclipse-threadx#45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
fdesbiens added a commit that referenced this pull request Aug 31, 2026
…50)
* feat(nucleo): Relocate NUCLEO_F401RE into targets and migrate to generic BSP framework
* Bounded the newlib heap to its linker reservation
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR #45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
* Restored console error handling and the AI disclosure headers
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR #45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
* Pinned the ARM toolchain to GCC 14 and refreshed the target documentation
The build-arm-nucleo job installed the distribution's gcc-arm-none-eabi,
which is GCC 13.2 on ubuntu-24.04, so the compiler drifted with the runner
image. AGENTS.md specifies GCC 14 and the sibling RISC-V job already pins
xPack GCC 14.2.0 by URL; the ARM job now pins Arm GNU Toolchain 14.2.Rel1
the same way. The toolchain bundles its own newlib, so the separate newlib
packages are no longer installed.
CMAKE_C_STANDARD moves from 11 to 99 per the AGENTS.md C99 requirement.
The target builds clean under both GCC 13.2.1 and the pinned GCC 14.2.1
with -Wall -Wshadow -Wdouble-promotion -Werror.
README.md moved with git mv but still described the pre-migration layout:
the build directory as STMicroelectronics/NUCLEO_F401RE, the HAL timebase
overrides as living in board_init.c, and the BSP as lib/nucleo_bsp/. All
three are corrected and the BSP entry now lists the four sources behind the
generic interfaces.
The Validation Record quoted 18244 B ROM and 5632 B RAM against a toolchain
the CI pipeline does not use. Re-measured against the newly pinned GCC
14.2.1: 20120 B ROM and 6000 B RAM. The hardware verification checklist is
left as the contributor recorded it.
---------
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frédéric Desbiens <frederic.desbiens@eclipse-foundation.org>
Sign up for freeto 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.

3 participants

@AmmarOkla12772@fdesbiens@ammarokla123
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase by AmmarOkla12772 · Pull Request #45 · eclipse-threadx/samplex · GitHub
Skip to content

STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase - #45

Merged
fdesbiens merged 14 commits into
eclipse-threadx:devfrom
AmmarOkla12772:feat/clean-nucleo-demo
Jul 20, 2026
Merged

STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase#45
fdesbiens merged 14 commits into
eclipse-threadx:devfrom
AmmarOkla12772:feat/clean-nucleo-demo

Conversation

@AmmarOkla12772

Copy link
Copy Markdown
Contributor

Note: This PR supersedes the previous submission having addressed the review feedback. The AZ3166 refactoring has been undone, and the required MIT license header has been added to main.c.

Overview

This PR extends the validation demo for the STMicroelectronics NUCLEO-F401RE board under STMicroelectronics/NUCLEO_F401RE/.

The goal is to provide a comprehensive ThreadX RTOS demonstration showcasing dynamic memory management, runtime diagnostics, thread monitoring, and synchronization primitives using public ThreadX APIs.

Changes

  • Replaced static thread stack allocation with a central TX_BYTE_POOL
  • Added runtime memory diagnostics reporting total, allocated, and free byte pool capacity
  • Added TX_BLOCK_POOL for fixed-size deterministic memory allocation
  • Added message passing between sender and receiver threads using TX_QUEUE
  • Added pointer-based queue transfers backed by block pool allocations
  • Added TX_MUTEX synchronization with two competing worker threads sharing a simulated SPI resource
  • Added TX_EVENT_FLAGS_GROUP synchronization between the LED heartbeat thread and an event-processing thread
  • Added TX_SEMAPHORE synchronization with a dedicated consumer thread awakened by LED activity
  • Added TX_TIMER periodic callback executing once per second from the ThreadX system timer thread
  • Expanded the demo from 3 threads to 9 threads to exercise core ThreadX scheduling and synchronization features
  • Added registry-based thread diagnostics using tx_thread_info_get()
  • Added stack high-water mark monitoring by scanning the ThreadX stack fill pattern (0xEFEFEFEF)
  • Added per-thread stack usage and utilization reporting
  • Added formatted runtime telemetry output over USART2 including thread states, priorities, run counts, memory statistics, and synchronization activity counters
  • Added the required MIT license header to main.c to align with project licensing requirements.

Validation

Tested on physical NUCLEO-F401RE board:

  • System runs continuously without crashes or scheduler instability
  • UART output remains stable at 115200 baud
  • Free memory remains constant at 79028 bytes during operation, indicating no byte pool or block pool leaks
  • Thread diagnostics correctly report state transitions, run counts, priorities, and stack watermarks
  • Stack utilization remains within safe limits for all threads
  • System uptime tracks wall-clock time accurately
  • ThreadX synchronization primitives operate as expected under active scheduling
  • No build warnings with Arm GNU Toolchain 15.2.Rel1

Toolchain

  • Arm GNU Toolchain 15.2.Rel1
  • CMake + Ninja build system

Notes

All runtime diagnostics are implemented using documented ThreadX public APIs. No private kernel structures or undocumented internal ThreadX data are accessed, maintaining portability across ThreadX targets.

ammarokla123and others added 14 commits June 8, 2026 05:10
	new file: STMicroelectronics/NUCLEO_F401RE/README.md
new file: STMicroelectronics/NUCLEO_F401RE/app/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/app/common/board_init.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/board_init.h
new file: STMicroelectronics/NUCLEO_F401RE/app/common/console.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/sntp_client.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/NUCLEO_F401RE.ld
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/startup_stm32f401xe.s
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/tx_initialize_low_level.S
new file: STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c
new file: STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h
new file: STMicroelectronics/NUCLEO_F401RE/app/starter/main.c
new file: STMicroelectronics/NUCLEO_F401RE/cmake/FindCMSIS.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/FindSTM32HAL.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-m4.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-toolchain.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/utilities.cmake
new file: STMicroelectronics/NUCLEO_F401RE/lib/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.c
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.h
new file: STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/config/stm32f4xx_hal_conf.h
Booted ThreadX on NUCLEO-F401RE
Validated scheduler operation
Validated UART console output
Validated LED thread
Validated flashing and hardware execution
…and event flags. Modified demo README file to reflect changes.
…aphore functionality and 1 hz applicaion timer.
Co-authored-by: Codex <codex@openai.com>
Retained the PR implementation for overlapping NUCLEO-F401RE files.\n\nCo-authored-by: Codex <codex@openai.com>
@fdesbiensfdesbiens changed the title feat(nucleo-f401re): implement comprehensive ThreadX RTOS monitor and primitives showcaseSTMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcaseJul 20, 2026
@fdesbiens
fdesbiens merged commit 1bddd17 into eclipse-threadx:devJul 20, 2026
1 check passed
@fdesbiens

Copy link
Copy Markdown
Contributor

I merged to dev; this will ship with the Q3 2026 release in September.

Thank you for this contribution, @AmmarOkla12772.

In the future, make sure your original files contain the full mandatory header as shown below.

/* * Copyright (c) 2026 Eclipse ThreadX contributors * * This program and the accompanying materials are made available * under the terms of the MIT license which is available at * https://opensource.org/license/mit. * * SPDX-License-Identifier: MIT */

Also, there were some minor merge conflicts. Always make sure you pull from upstream before creating a PR. Don't worry, I forget this from time to time myself...

fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR eclipse-threadx#45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR eclipse-threadx#45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR eclipse-threadx#45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR eclipse-threadx#45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
fdesbiens added a commit that referenced this pull request Aug 31, 2026
…50)
* feat(nucleo): Relocate NUCLEO_F401RE into targets and migrate to generic BSP framework
* Bounded the newlib heap to its linker reservation
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR #45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
* Restored console error handling and the AI disclosure headers
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR #45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
* Pinned the ARM toolchain to GCC 14 and refreshed the target documentation
The build-arm-nucleo job installed the distribution's gcc-arm-none-eabi,
which is GCC 13.2 on ubuntu-24.04, so the compiler drifted with the runner
image. AGENTS.md specifies GCC 14 and the sibling RISC-V job already pins
xPack GCC 14.2.0 by URL; the ARM job now pins Arm GNU Toolchain 14.2.Rel1
the same way. The toolchain bundles its own newlib, so the separate newlib
packages are no longer installed.
CMAKE_C_STANDARD moves from 11 to 99 per the AGENTS.md C99 requirement.
The target builds clean under both GCC 13.2.1 and the pinned GCC 14.2.1
with -Wall -Wshadow -Wdouble-promotion -Werror.
README.md moved with git mv but still described the pre-migration layout:
the build directory as STMicroelectronics/NUCLEO_F401RE, the HAL timebase
overrides as living in board_init.c, and the BSP as lib/nucleo_bsp/. All
three are corrected and the BSP entry now lists the four sources behind the
generic interfaces.
The Validation Record quoted 18244 B ROM and 5632 B RAM against a toolchain
the CI pipeline does not use. Re-measured against the newly pinned GCC
14.2.1: 20120 B ROM and 6000 B RAM. The hardware verification checklist is
left as the contributor recorded it.
---------
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frédéric Desbiens <frederic.desbiens@eclipse-foundation.org>
Sign up for freeto 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.

3 participants

@AmmarOkla12772@fdesbiens@ammarokla123
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase by AmmarOkla12772 · Pull Request #45 · eclipse-threadx/samplex · GitHub
Skip to content

STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase - #45

Merged
fdesbiens merged 14 commits into
eclipse-threadx:devfrom
AmmarOkla12772:feat/clean-nucleo-demo
Jul 20, 2026
Merged

STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase#45
fdesbiens merged 14 commits into
eclipse-threadx:devfrom
AmmarOkla12772:feat/clean-nucleo-demo

Conversation

@AmmarOkla12772

Copy link
Copy Markdown
Contributor

Note: This PR supersedes the previous submission having addressed the review feedback. The AZ3166 refactoring has been undone, and the required MIT license header has been added to main.c.

Overview

This PR extends the validation demo for the STMicroelectronics NUCLEO-F401RE board under STMicroelectronics/NUCLEO_F401RE/.

The goal is to provide a comprehensive ThreadX RTOS demonstration showcasing dynamic memory management, runtime diagnostics, thread monitoring, and synchronization primitives using public ThreadX APIs.

Changes

  • Replaced static thread stack allocation with a central TX_BYTE_POOL
  • Added runtime memory diagnostics reporting total, allocated, and free byte pool capacity
  • Added TX_BLOCK_POOL for fixed-size deterministic memory allocation
  • Added message passing between sender and receiver threads using TX_QUEUE
  • Added pointer-based queue transfers backed by block pool allocations
  • Added TX_MUTEX synchronization with two competing worker threads sharing a simulated SPI resource
  • Added TX_EVENT_FLAGS_GROUP synchronization between the LED heartbeat thread and an event-processing thread
  • Added TX_SEMAPHORE synchronization with a dedicated consumer thread awakened by LED activity
  • Added TX_TIMER periodic callback executing once per second from the ThreadX system timer thread
  • Expanded the demo from 3 threads to 9 threads to exercise core ThreadX scheduling and synchronization features
  • Added registry-based thread diagnostics using tx_thread_info_get()
  • Added stack high-water mark monitoring by scanning the ThreadX stack fill pattern (0xEFEFEFEF)
  • Added per-thread stack usage and utilization reporting
  • Added formatted runtime telemetry output over USART2 including thread states, priorities, run counts, memory statistics, and synchronization activity counters
  • Added the required MIT license header to main.c to align with project licensing requirements.

Validation

Tested on physical NUCLEO-F401RE board:

  • System runs continuously without crashes or scheduler instability
  • UART output remains stable at 115200 baud
  • Free memory remains constant at 79028 bytes during operation, indicating no byte pool or block pool leaks
  • Thread diagnostics correctly report state transitions, run counts, priorities, and stack watermarks
  • Stack utilization remains within safe limits for all threads
  • System uptime tracks wall-clock time accurately
  • ThreadX synchronization primitives operate as expected under active scheduling
  • No build warnings with Arm GNU Toolchain 15.2.Rel1

Toolchain

  • Arm GNU Toolchain 15.2.Rel1
  • CMake + Ninja build system

Notes

All runtime diagnostics are implemented using documented ThreadX public APIs. No private kernel structures or undocumented internal ThreadX data are accessed, maintaining portability across ThreadX targets.

ammarokla123and others added 14 commits June 8, 2026 05:10
	new file: STMicroelectronics/NUCLEO_F401RE/README.md
new file: STMicroelectronics/NUCLEO_F401RE/app/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/app/common/board_init.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/board_init.h
new file: STMicroelectronics/NUCLEO_F401RE/app/common/console.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/sntp_client.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/NUCLEO_F401RE.ld
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/startup_stm32f401xe.s
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/tx_initialize_low_level.S
new file: STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c
new file: STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h
new file: STMicroelectronics/NUCLEO_F401RE/app/starter/main.c
new file: STMicroelectronics/NUCLEO_F401RE/cmake/FindCMSIS.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/FindSTM32HAL.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-m4.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-toolchain.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/utilities.cmake
new file: STMicroelectronics/NUCLEO_F401RE/lib/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.c
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.h
new file: STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/config/stm32f4xx_hal_conf.h
Booted ThreadX on NUCLEO-F401RE
Validated scheduler operation
Validated UART console output
Validated LED thread
Validated flashing and hardware execution
…and event flags. Modified demo README file to reflect changes.
…aphore functionality and 1 hz applicaion timer.
Co-authored-by: Codex <codex@openai.com>
Retained the PR implementation for overlapping NUCLEO-F401RE files.\n\nCo-authored-by: Codex <codex@openai.com>
@fdesbiensfdesbiens changed the title feat(nucleo-f401re): implement comprehensive ThreadX RTOS monitor and primitives showcaseSTMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcaseJul 20, 2026
@fdesbiens
fdesbiens merged commit 1bddd17 into eclipse-threadx:devJul 20, 2026
1 check passed
@fdesbiens

Copy link
Copy Markdown
Contributor

I merged to dev; this will ship with the Q3 2026 release in September.

Thank you for this contribution, @AmmarOkla12772.

In the future, make sure your original files contain the full mandatory header as shown below.

/* * Copyright (c) 2026 Eclipse ThreadX contributors * * This program and the accompanying materials are made available * under the terms of the MIT license which is available at * https://opensource.org/license/mit. * * SPDX-License-Identifier: MIT */

Also, there were some minor merge conflicts. Always make sure you pull from upstream before creating a PR. Don't worry, I forget this from time to time myself...

fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR eclipse-threadx#45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR eclipse-threadx#45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR eclipse-threadx#45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR eclipse-threadx#45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
fdesbiens added a commit that referenced this pull request Aug 31, 2026
…50)
* feat(nucleo): Relocate NUCLEO_F401RE into targets and migrate to generic BSP framework
* Bounded the newlib heap to its linker reservation
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR #45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
* Restored console error handling and the AI disclosure headers
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR #45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
* Pinned the ARM toolchain to GCC 14 and refreshed the target documentation
The build-arm-nucleo job installed the distribution's gcc-arm-none-eabi,
which is GCC 13.2 on ubuntu-24.04, so the compiler drifted with the runner
image. AGENTS.md specifies GCC 14 and the sibling RISC-V job already pins
xPack GCC 14.2.0 by URL; the ARM job now pins Arm GNU Toolchain 14.2.Rel1
the same way. The toolchain bundles its own newlib, so the separate newlib
packages are no longer installed.
CMAKE_C_STANDARD moves from 11 to 99 per the AGENTS.md C99 requirement.
The target builds clean under both GCC 13.2.1 and the pinned GCC 14.2.1
with -Wall -Wshadow -Wdouble-promotion -Werror.
README.md moved with git mv but still described the pre-migration layout:
the build directory as STMicroelectronics/NUCLEO_F401RE, the HAL timebase
overrides as living in board_init.c, and the BSP as lib/nucleo_bsp/. All
three are corrected and the BSP entry now lists the four sources behind the
generic interfaces.
The Validation Record quoted 18244 B ROM and 5632 B RAM against a toolchain
the CI pipeline does not use. Re-measured against the newly pinned GCC
14.2.1: 20120 B ROM and 6000 B RAM. The hardware verification checklist is
left as the contributor recorded it.
---------
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frédéric Desbiens <frederic.desbiens@eclipse-foundation.org>
Sign up for freeto 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.

3 participants

@AmmarOkla12772@fdesbiens@ammarokla123
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase by AmmarOkla12772 · Pull Request #45 · eclipse-threadx/samplex · GitHub
Skip to content

STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase - #45

Merged
fdesbiens merged 14 commits into
eclipse-threadx:devfrom
AmmarOkla12772:feat/clean-nucleo-demo
Jul 20, 2026
Merged

STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase#45
fdesbiens merged 14 commits into
eclipse-threadx:devfrom
AmmarOkla12772:feat/clean-nucleo-demo

Conversation

@AmmarOkla12772

Copy link
Copy Markdown
Contributor

Note: This PR supersedes the previous submission having addressed the review feedback. The AZ3166 refactoring has been undone, and the required MIT license header has been added to main.c.

Overview

This PR extends the validation demo for the STMicroelectronics NUCLEO-F401RE board under STMicroelectronics/NUCLEO_F401RE/.

The goal is to provide a comprehensive ThreadX RTOS demonstration showcasing dynamic memory management, runtime diagnostics, thread monitoring, and synchronization primitives using public ThreadX APIs.

Changes

  • Replaced static thread stack allocation with a central TX_BYTE_POOL
  • Added runtime memory diagnostics reporting total, allocated, and free byte pool capacity
  • Added TX_BLOCK_POOL for fixed-size deterministic memory allocation
  • Added message passing between sender and receiver threads using TX_QUEUE
  • Added pointer-based queue transfers backed by block pool allocations
  • Added TX_MUTEX synchronization with two competing worker threads sharing a simulated SPI resource
  • Added TX_EVENT_FLAGS_GROUP synchronization between the LED heartbeat thread and an event-processing thread
  • Added TX_SEMAPHORE synchronization with a dedicated consumer thread awakened by LED activity
  • Added TX_TIMER periodic callback executing once per second from the ThreadX system timer thread
  • Expanded the demo from 3 threads to 9 threads to exercise core ThreadX scheduling and synchronization features
  • Added registry-based thread diagnostics using tx_thread_info_get()
  • Added stack high-water mark monitoring by scanning the ThreadX stack fill pattern (0xEFEFEFEF)
  • Added per-thread stack usage and utilization reporting
  • Added formatted runtime telemetry output over USART2 including thread states, priorities, run counts, memory statistics, and synchronization activity counters
  • Added the required MIT license header to main.c to align with project licensing requirements.

Validation

Tested on physical NUCLEO-F401RE board:

  • System runs continuously without crashes or scheduler instability
  • UART output remains stable at 115200 baud
  • Free memory remains constant at 79028 bytes during operation, indicating no byte pool or block pool leaks
  • Thread diagnostics correctly report state transitions, run counts, priorities, and stack watermarks
  • Stack utilization remains within safe limits for all threads
  • System uptime tracks wall-clock time accurately
  • ThreadX synchronization primitives operate as expected under active scheduling
  • No build warnings with Arm GNU Toolchain 15.2.Rel1

Toolchain

  • Arm GNU Toolchain 15.2.Rel1
  • CMake + Ninja build system

Notes

All runtime diagnostics are implemented using documented ThreadX public APIs. No private kernel structures or undocumented internal ThreadX data are accessed, maintaining portability across ThreadX targets.

ammarokla123and others added 14 commits June 8, 2026 05:10
	new file: STMicroelectronics/NUCLEO_F401RE/README.md
new file: STMicroelectronics/NUCLEO_F401RE/app/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/app/common/board_init.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/board_init.h
new file: STMicroelectronics/NUCLEO_F401RE/app/common/console.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/sntp_client.c
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/NUCLEO_F401RE.ld
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/startup_stm32f401xe.s
new file: STMicroelectronics/NUCLEO_F401RE/app/common/startup/tx_initialize_low_level.S
new file: STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c
new file: STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h
new file: STMicroelectronics/NUCLEO_F401RE/app/starter/main.c
new file: STMicroelectronics/NUCLEO_F401RE/cmake/FindCMSIS.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/FindSTM32HAL.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-m4.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-toolchain.cmake
new file: STMicroelectronics/NUCLEO_F401RE/cmake/utilities.cmake
new file: STMicroelectronics/NUCLEO_F401RE/lib/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.c
new file: STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.h
new file: STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/CMakeLists.txt
new file: STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/config/stm32f4xx_hal_conf.h
Booted ThreadX on NUCLEO-F401RE
Validated scheduler operation
Validated UART console output
Validated LED thread
Validated flashing and hardware execution
…and event flags. Modified demo README file to reflect changes.
…aphore functionality and 1 hz applicaion timer.
Co-authored-by: Codex <codex@openai.com>
Retained the PR implementation for overlapping NUCLEO-F401RE files.\n\nCo-authored-by: Codex <codex@openai.com>
@fdesbiensfdesbiens changed the title feat(nucleo-f401re): implement comprehensive ThreadX RTOS monitor and primitives showcaseSTMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcaseJul 20, 2026
@fdesbiens
fdesbiens merged commit 1bddd17 into eclipse-threadx:devJul 20, 2026
1 check passed
@fdesbiens

Copy link
Copy Markdown
Contributor

I merged to dev; this will ship with the Q3 2026 release in September.

Thank you for this contribution, @AmmarOkla12772.

In the future, make sure your original files contain the full mandatory header as shown below.

/* * Copyright (c) 2026 Eclipse ThreadX contributors * * This program and the accompanying materials are made available * under the terms of the MIT license which is available at * https://opensource.org/license/mit. * * SPDX-License-Identifier: MIT */

Also, there were some minor merge conflicts. Always make sure you pull from upstream before creating a PR. Don't worry, I forget this from time to time myself...

fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR eclipse-threadx#45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR eclipse-threadx#45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR eclipse-threadx#45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
fdesbiens added a commit to AmmarOkla12772/samplexFork2 that referenced this pull request Aug 31, 2026
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR eclipse-threadx#45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
fdesbiens added a commit that referenced this pull request Aug 31, 2026
…50)
* feat(nucleo): Relocate NUCLEO_F401RE into targets and migrate to generic BSP framework
* Bounded the newlib heap to its linker reservation
_sbrk() bounded the heap at BSP_RAM_END (0x20018000), the end of physical
SRAM. On this target that is not a guard at all. NUCLEO_F401RE.ld lays RAM
out as:
_end 0x20001170 heap base
_end + _Min_Heap_Size 0x20001370 intended heap ceiling
__RAM_segment_used_end__ 0x20001770 ThreadX byte pool starts here
byte pool end 0x20017000
_estack / BSP_RAM_END 0x20018000
so malloc() could grow the break through the reserved main stack, through
the entire ThreadX byte pool holding every thread stack and the queue
buffer, and into the live MSP, all while _sbrk() reported success. Only an
allocation past the top of SRAM returned ENOMEM.
The linker script now exports _heap_limit at the end of the heap
reservation and _sbrk() bounds against that, which keeps the heap inside
the 0x200 the script already set aside for it. Both bounds checks are also
computed in uintptr_t rather than by forming an out-of-bounds pointer
first, and the negative branch derives its magnitude without negating
PTRDIFF_MIN. BSP_RAM_END keeps documenting the memory map but now carries
a note against reusing it as a heap bound.
All newlib syscall overrides move into newlib_stubs.c, which the
application compiles directly. _write() and _read() previously sat in
bsp_console.c inside libbsp.a, where the linker extracted them only
because bsp_board.o happened to reference bsp_console_init(); breaking
that incidental chain would have silently handed printf to the libnosys
stubs, and CI only checks that the ELF exists. Console input stays board
specific behind nucleo_console.h, since the shared <bsp/console.h>
contract is write-only.
The BSP library is renamed nucleo_bsp, matching polarfire_bsp and freeing
the bare "bsp" target name.
The AI Disclosure header on newlib_stubs.c records the Codex-assisted
origin of the syscall shims moved in from console.c. That work was done by
Frederic Desbiens while editing PR #45, not by the PR author; the
squash-merge in 1bddd17 assigned git authorship to the contributor and its
Co-authored-by trailers are the accurate record.
* Restored console error handling and the AI disclosure headers
bsp_console_init() dropped the return value of HAL_UART_Init(). The code it
replaced routed the failure to Error_Handler(); the migration left the call
bare, so a UART that failed to initialise booted on silently with no
console. MISRA C:2012 Rule 17.7. The status is checked again and a failure
now halts, matching the previous behaviour.
The UART handle was a non-static global named UartHandle, but the extern
declaration that used to live in board_init.h went away with that header,
leaving an object with external linkage that nothing declared (Rule 8.4 and
8.7). It is now file-scope static console_uart. The redundant GPIOA and
USART2 clock enables are gone as well: HAL_UART_MspInit() already owns that
configuration, which is what "single UART owner" should mean. The const
cast required by HAL_UART_Transmit() is documented as a Rule 11.8
deviation.
bsp_board.c, bsp_led.c and bsp_console.c carry the AI Disclosure header
required by AGENTS.md for new files. They derive from board_init.c,
nucleo_bsp.c and console.c, each of which carried "Some portions generated
by Codex (GPT-5)"; the rename dropped the disclosure while keeping most of
the content, and git scores bsp_board.c as an 80% similarity rename.
That Codex work was Frederic Desbiens', done while editing another
contributor's PR under the AGENTS.md exception permitting edits to
incoming PRs. It reached the tree through 1bddd17, a GitHub squash-merge
of PR #45 whose git author is the PR author but whose trailers name the
real participants:
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frederic Desbiens <frederic.desbiens@eclipse-foundation.org>
Co-authored-by: Codex <codex@openai.com>
The disclosure is therefore not a statement about this PR's author.
* Pinned the ARM toolchain to GCC 14 and refreshed the target documentation
The build-arm-nucleo job installed the distribution's gcc-arm-none-eabi,
which is GCC 13.2 on ubuntu-24.04, so the compiler drifted with the runner
image. AGENTS.md specifies GCC 14 and the sibling RISC-V job already pins
xPack GCC 14.2.0 by URL; the ARM job now pins Arm GNU Toolchain 14.2.Rel1
the same way. The toolchain bundles its own newlib, so the separate newlib
packages are no longer installed.
CMAKE_C_STANDARD moves from 11 to 99 per the AGENTS.md C99 requirement.
The target builds clean under both GCC 13.2.1 and the pinned GCC 14.2.1
with -Wall -Wshadow -Wdouble-promotion -Werror.
README.md moved with git mv but still described the pre-migration layout:
the build directory as STMicroelectronics/NUCLEO_F401RE, the HAL timebase
overrides as living in board_init.c, and the BSP as lib/nucleo_bsp/. All
three are corrected and the BSP entry now lists the four sources behind the
generic interfaces.
The Validation Record quoted 18244 B ROM and 5632 B RAM against a toolchain
the CI pipeline does not use. Re-measured against the newly pinned GCC
14.2.1: 20120 B ROM and 6000 B RAM. The hardware verification checklist is
left as the contributor recorded it.
---------
Co-authored-by: Ammar Okla <ammargawkla@gmail.com>
Co-authored-by: Frédéric Desbiens <frederic.desbiens@eclipse-foundation.org>
Sign up for freeto 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.

3 participants

@AmmarOkla12772@fdesbiens@ammarokla123