From 4b0d848824b543b89a109654d7e4275e77768cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Fri, 12 Jun 2026 17:58:38 +0200 Subject: [PATCH 01/20] Fixed CORE-V-MCU deploy.sh scripts (#32) --- OpenHW/CORE-V-MCU/cli-test/scripts/deploy.sh | 2 +- OpenHW/CORE-V-MCU/slideshow/scripts/deploy.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenHW/CORE-V-MCU/cli-test/scripts/deploy.sh b/OpenHW/CORE-V-MCU/cli-test/scripts/deploy.sh index b2a621bc..2b961b21 100755 --- a/OpenHW/CORE-V-MCU/cli-test/scripts/deploy.sh +++ b/OpenHW/CORE-V-MCU/cli-test/scripts/deploy.sh @@ -49,7 +49,7 @@ OPENOCD_PID="" OPENOCD_TIMEOUT=10 DEFAULT_ELF="${PROJECT_DIR}/build/core_v_mcu_cli_test.elf" -DEFAULT_CFG="${PROJECT_DIR}/../../libs/threadx/ports/risc-v32/gnu/example_build/core_v_mcu/openocd-nexys-Ashling-Opella-LD.cfg" +DEFAULT_CFG="${PROJECT_DIR}/../../../libs/threadx/ports/risc-v32/gnu/example_build/core_v_mcu/openocd-nexys-Ashling-Opella-LD.cfg" OPT_BUILD=0 OPT_DEBUG=0 diff --git a/OpenHW/CORE-V-MCU/slideshow/scripts/deploy.sh b/OpenHW/CORE-V-MCU/slideshow/scripts/deploy.sh index c14ae601..1ad3ff75 100755 --- a/OpenHW/CORE-V-MCU/slideshow/scripts/deploy.sh +++ b/OpenHW/CORE-V-MCU/slideshow/scripts/deploy.sh @@ -49,7 +49,7 @@ OPENOCD_PID="" OPENOCD_TIMEOUT=10 DEFAULT_ELF="${PROJECT_DIR}/build/core_v_mcu_slideshow.elf" -DEFAULT_CFG="${PROJECT_DIR}/../../libs/threadx/ports/risc-v32/gnu/example_build/core_v_mcu/openocd-nexys-Ashling-Opella-LD.cfg" +DEFAULT_CFG="${PROJECT_DIR}/../../../libs/threadx/ports/risc-v32/gnu/example_build/core_v_mcu/openocd-nexys-Ashling-Opella-LD.cfg" OPT_BUILD=0 OPT_DEBUG=0 From 93ca8fa69dc1d4c67ea891e522e8eaa0338bf6ed Mon Sep 17 00:00:00 2001 From: Ali Eissa Date: Fri, 19 Jun 2026 19:05:52 +0400 Subject: [PATCH 02/20] feat(stm32f767zi): refactor BSP and add NetX Duo Echo demo (#39) * refactor(stm32f767): restructure project to support scalable demos and default to threadx_basic * feat(stm32f767zi): refactored BSP and added NetX Duo Echo demo --- .gitignore | 3 + .../STM32F767ZI-Nucleo/CMakeLists.txt | 104 +++++--- .../STM32F767ZI-Nucleo/README.md | 224 ++++++++++++++---- .../STM32F767ZI-Nucleo/app/board_init.c | 121 ++++++++++ .../STM32F767ZI-Nucleo/app/board_init.h | 4 + .../app/demos/netx_echo/CMakeLists.txt | 44 ++++ .../app/demos/netx_echo/main.c | 209 ++++++++++++++++ .../app/demos/netx_echo/nx_stm32_eth_config.h | 30 +++ .../netx_echo/nx_user.h} | 20 +- .../app/demos/netx_echo/test_echo_simple.ps1 | 34 +++ .../app/demos/netx_echo/test_echo_simple.sh | 49 ++++ .../app/demos/threadx_basic/CMakeLists.txt | 42 ++++ .../app/{ => demos/threadx_basic}/main.c | 0 .../STM32F767ZI-Nucleo/app/ethernet_phy.c | 68 ------ .../app/startup/STM32F767ZITx_FLASH.ld | 14 +- .../app/stm32f7xx_hal_msp.c | 21 +- .../STM32F767ZI-Nucleo/scripts/fetch_sdk.ps1 | 38 +++ .../STM32F767ZI-Nucleo/scripts/fetch_sdk.sh | 28 +++ 18 files changed, 888 insertions(+), 165 deletions(-) create mode 100644 STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/CMakeLists.txt create mode 100644 STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/main.c create mode 100644 STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/nx_stm32_eth_config.h rename STMicroelectronics/STM32F767ZI-Nucleo/app/{ethernet_phy.h => demos/netx_echo/nx_user.h} (53%) create mode 100644 STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/test_echo_simple.ps1 create mode 100644 STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/test_echo_simple.sh create mode 100644 STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/CMakeLists.txt rename STMicroelectronics/STM32F767ZI-Nucleo/app/{ => demos/threadx_basic}/main.c (100%) delete mode 100644 STMicroelectronics/STM32F767ZI-Nucleo/app/ethernet_phy.c diff --git a/.gitignore b/.gitignore index 9005e0fe..b70e1261 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,6 @@ CTestTestfile.cmake *.log shared/lib/netxduo/* shared/lib/threadx/* +STMicroelectronics/STM32F767ZI-Nucleo/lib/stm32cubef7/ +STMicroelectronics/STM32F767ZI-Nucleo/lib/netxduo/ + diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/CMakeLists.txt b/STMicroelectronics/STM32F767ZI-Nucleo/CMakeLists.txt index 4a562f6e..1aac36be 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/CMakeLists.txt +++ b/STMicroelectronics/STM32F767ZI-Nucleo/CMakeLists.txt @@ -24,9 +24,8 @@ include(utilities) # Define the Project project(stm32f767_threadx C CXX ASM) -# Define ThreadX User Configurations -set(TX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/lib/threadx/tx_user.h" CACHE STRING "Enable TX user configuration") -set(TX_USER_FILE_DIR "${CMAKE_CURRENT_LIST_DIR}/lib/threadx") +# Select the active demo to build (threadx_basic) +set(ACTIVE_DEMO "threadx_basic" CACHE STRING "Active demo name to build: threadx_basic") # Set up standard paths for find modules set(STM32_FAMILY "F7") @@ -54,52 +53,99 @@ target_include_directories(${HAL_TARGET} ${CMAKE_CURRENT_LIST_DIR}/app ) +# Dynamic Middleware Auto-Detection +# Check if the active demo uses NetX Duo by looking for nx_user.h +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/nx_user.h") + set(USE_NETXDUO ON) + set(NX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/nx_user.h" CACHE STRING "Enable NetX Duo user configuration" FORCE) +else() + set(USE_NETXDUO OFF) +endif() + +# Check if the active demo has custom tx_user.h; otherwise fallback to app/tx_user.h +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/tx_user.h") + set(TX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/tx_user.h" CACHE STRING "Enable TX user configuration" FORCE) + set(TX_USER_FILE_DIR "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}") +else() + set(TX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/lib/threadx/tx_user.h" CACHE STRING "Enable TX user configuration" FORCE) + set(TX_USER_FILE_DIR "${CMAKE_CURRENT_LIST_DIR}/lib/threadx") +endif() + # Compile ThreadX Kernel from root shared libs submodule set(THREADX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../libs/threadx") add_subdirectory(${THREADX_DIR} threadx) -# Create the Main Executable -set(EXE_TARGET stm32f767_threadx) +if(USE_NETXDUO) + # Compile NetX Duo TCP/IP Stack from root shared libs submodule + set(NXD_ENABLE_FILE_SERVERS OFF CACHE BOOL "Disable FileX dependency in NetX Duo" FORCE) + set(NETXDUO_DIR "${CMAKE_CURRENT_LIST_DIR}/../../libs/netxduo") + add_subdirectory(${NETXDUO_DIR} netxduo) +endif() -add_executable(${EXE_TARGET} +# 1. Define the Board BSP static library +add_library(board_bsp OBJECT app/startup/startup_stm32f767zitx.s app/startup/system_stm32f7xx.c app/startup/tx_initialize_low_level.S app/board_init.c app/console.c - app/ethernet_phy.c - app/main.c app/stm32f7xx_hal_msp.c app/sysmem.c app/syscalls.c ) -# Set compile definitions for our executable -target_compile_definitions(${EXE_TARGET} - PRIVATE - STM32F767xx - USE_HAL_DRIVER - STM32F7 +# Include paths for BSP +target_include_directories(board_bsp PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/app + ${CMSIS_INCLUDE_DIRS} + ${STM32HAL_INCLUDE_DIR} + ${TX_USER_FILE_DIR} +) + +# Compile definitions for BSP +target_compile_definitions(board_bsp PRIVATE + STM32F767xx + USE_HAL_DRIVER + STM32F7 ) -# Include paths -target_include_directories(${EXE_TARGET} - PRIVATE +# Link libraries for BSP (HAL and CMSIS) +target_link_libraries(board_bsp PUBLIC + stm32cubef7 + threadx +) + + +# 2. Define conditional NetX Duo driver library target +if(USE_NETXDUO) + add_library(netx_stm32_driver OBJECT + lib/netxduo/nx_stm32_eth_driver.c + lib/netxduo/nx_stm32_phy_driver.c + lib/netxduo/lan8742.c + ) + + # NetX driver needs its local files, HAL, CMSIS, ThreadX, NetX Duo and the active demo folder (for nx_stm32_eth_config.h and nx_user.h) + target_include_directories(netx_stm32_driver PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/lib/netxduo + ${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO} ${CMAKE_CURRENT_LIST_DIR}/app ${CMSIS_INCLUDE_DIRS} ${STM32HAL_INCLUDE_DIR} - ${TX_USER_FILE_DIR} -) - -# Link libraries (includes ThreadX kernel and HAL object libraries) -target_link_libraries(${EXE_TARGET} - PRIVATE - threadx + ) + + target_compile_definitions(netx_stm32_driver PRIVATE + STM32F767xx + USE_HAL_DRIVER + STM32F7 + STM32_ETH_HAL_LEGACY + ) + + target_link_libraries(netx_stm32_driver PUBLIC + netxduo stm32cubef7 -) + ) +endif() -# Apply GCC linker script and print memory usage (utilities.cmake function) -set_target_linker(${EXE_TARGET} "${CMAKE_CURRENT_LIST_DIR}/app/startup/STM32F767ZITx_FLASH.ld") +# 3. Add the active demo subdirectory to build the executable target +add_subdirectory(app/demos/${ACTIVE_DEMO}) -# Post-build commands to generate raw .bin and .hex files -post_build(${EXE_TARGET}) diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/README.md b/STMicroelectronics/STM32F767ZI-Nucleo/README.md index d0370f63..1f4c0c57 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/README.md +++ b/STMicroelectronics/STM32F767ZI-Nucleo/README.md @@ -1,8 +1,19 @@ -# STM32F767ZI-Nucleo Board Enablement Demo +# STM32F767ZI-Nucleo Board Enablement Demos -This directory contains the Board Support Package (BSP) and build environment for running the Eclipse ThreadX RTOS on the **STMicroelectronics NUCLEO-F767ZI** evaluation board (ARM Cortex-M7). +This directory contains the Board Support Package (BSP) static library (`board_bsp`) and build configurations for running the **Eclipse ThreadX RTOS** and **NetX Duo TCP/IP stack** on the **STMicroelectronics NUCLEO-F767ZI** evaluation board (ARM Cortex-M7). -The project is structured with an isolated build framework, keeping all platform dependencies localized to ensure clean integration. +The project features a decoupled static BSP library that hides all low-level hardware initializations (clocks, GPIO, MPU, DMA descriptors, and interrupts) from the application code. + +--- + +## Supported Demos + +Use the `ACTIVE_DEMO` CMake variable to select which demo to compile: + +| Demo Name | Description | Targets | +| :--- | :--- | :--- | +| **`netx_echo`** *(Default)* | Dynamic network state machine monitoring cable hot-plugging, DHCP IP configuration, and a TCP Echo Server listening on port 7. | ThreadX, NetX Duo | +| **`threadx_basic`** | Multi-threaded RTOS demo showcasing thread scheduling, mechanical button debouncing, message queue logging, and interrupt-driven UART ring buffers. | ThreadX | --- @@ -10,39 +21,20 @@ The project is structured with an isolated build framework, keeping all platform * **Development Board**: NUCLEO-F767ZI (Nucleo-144) * **Microcontroller**: STM32F767ZIT6 (ARM Cortex-M7 running at 216 MHz) -* **Memory**: 2 MB Flash, 320 KB SRAM +* **Memory Layout**: 2 MB Flash, 512 KB SRAM + * *Note: The MPU maps `128 KB` of SRAM2 (starting at `0x20060000`) as non-cacheable/non-bufferable for Ethernet DMA descriptors and the packet pool.* * **Virtual COM Port**: USART3 (PD8/PD9) connected to ST-LINK debugger (115,200 baud, 8N1) +* **User Button**: PC13 (Blue button, Active High) * **Board LEDs**: * `LD1` (Green) - PB0 * `LD2` (Blue) - PB7 * `LD3` (Red) - PB14 -* **User Button**: PC13 (Blue button, Active High) - ---- - -## Demo Application Architecture - -The application runs a multi-threaded demo showcasing cooperation between ThreadX scheduling, queues, hardware interrupts, and status indicator peripherals: - -1. **Thread 1 (Green LED - Heartbeat)** (Priority 15): - * Toggles the green LED (`LD1`) continuously at `2 Hz` (250 ms active, 250 ms idle) to verify basic scheduler clock ticks. -2. **Thread 2 (User Button Scanner)** (Priority 10): - * Scans the blue User Button (`PC13`) using software-level mechanical debouncing (20 ms). - * Turns the Blue LED (`LD2`) ON when the button is held. - * Sends the current system tick count over a **ThreadX Message Queue** on a button press transition. -3. **Thread 3 (System Logger)** (Priority 10): - * Blocks efficiently on the Message Queue. - * Wakes up when a button press event is queued and prints a timestamped system log over the serial port. -4. **Thread 4 (Serial Terminal Input)** (Priority 5): - * Integrates an asynchronous, non-blocking **Interrupt Service Routine (ISR)** (`USART3_IRQHandler`) and a 256-byte volatile circular **ring buffer** to read keyboard input at 115,200 baud. - * Collects incoming characters, prints the received string on carriage return/newline, and flashes the Red LED (`LD3`) for 50 ms. - * Avoids the use of `HAL_GetTick()` to prevent CPU starvation when idle. --- ## Prerequisites -Before building, ensure you have the following cross-compilation tools installed on your PATH: +Before building, ensure you have the following cross-compilation tools installed on your system PATH: * **ARM GNU Toolchain** (`arm-none-eabi-gcc`) * **CMake** (version 3.5 or higher) @@ -54,42 +46,178 @@ Before building, ensure you have the following cross-compilation tools installed ## Quick Start Guide ### 1. Download SDK Dependencies -Run the driver fetcher script to clone the official, lightweight STMicroelectronics HAL drivers and CMSIS files locally: +Run the driver fetcher script to clone official, stock STMicroelectronics HAL drivers and CMSIS files locally: * **On Windows (PowerShell)**: ```powershell powershell -ExecutionPolicy Bypass -File .\scripts\fetch_sdk.ps1 ``` -* **On Linux (Bash - Ubuntu 24.04)**: +* **On Linux (Bash)**: ```bash chmod +x ./scripts/fetch_sdk.sh ./scripts/fetch_sdk.sh ``` -### 2. Build the Project -Run the compilation script to compile the libraries and application, linking the ThreadX RTOS kernel: +### 2. Configure and Build the Project -* **On Windows (PowerShell)**: - ```powershell - powershell -ExecutionPolicy Bypass -File .\scripts\build.ps1 -Rebuild - ``` -* **On Linux (Bash - Ubuntu 24.04)**: - ```bash - chmod +x ./scripts/build.sh - ./scripts/build.sh --rebuild - ``` +#### Option A: Build `netx_echo` (Default) +```bash +# Configure CMake +cmake -DACTIVE_DEMO=netx_echo -B build + +# Compile +cmake --build build +``` + +#### Option B: Build `threadx_basic` +```bash +# Configure CMake +cmake -DACTIVE_DEMO=threadx_basic -B build + +# Compile +cmake --build build +``` + +The raw binary files will be generated in `build/app/demos//stm32f767_threadx.bin`. --- ## Deployment & Verification -1. **Flash the Board**: - * Connect the NUCLEO-F767ZI board to your computer using a Micro-USB cable via the ST-LINK port. - * The board will mount as an external USB drive (e.g., `NUCLEO_F767ZI`). - * Copy the raw binary output file `build/stm32f767_threadx.bin` and paste it directly onto the board's drive. - * The ST-LINK status LED will blink rapidly while writing, then the board will auto-reboot. +### 1. Flash the Board +1. Connect the Nucleo board to your computer using a Micro-USB cable via the ST-LINK port. +2. The board will mount as an external USB drive (e.g., named `NOD_F767ZI` or `NUCLEO`). +3. Copy the compiled raw binary output file `build/app/demos//stm32f767_threadx.bin` and paste it directly onto the board's drive. +4. The ST-LINK status LED will blink rapidly while writing, then the board will auto-reboot. + +--- + +### 2. How to Run & Verify the `netx_echo` Demo +1. **Set Up Serial Monitor**: Open your serial terminal program (e.g., VS Code Serial Monitor, PuTTY, or Tera Term) to the virtual ST-LINK COM Port at **115,200 baud, 8N1**. +2. **Boot Unplugged**: Reset the board with the Ethernet cable disconnected. You should see the following log confirming the BSP initialization completed successfully and the network monitor is polling: + ```text + ========================================== + NetX Echo Demo Booted! + ========================================== + [HAL] Calling HAL_ETH_Init... + [HAL] HAL_ETH_Init returned status: 0 + [NetX] Initializing PHY transceiver... + [NetX] Waiting for Ethernet link (max 3s)... + [NetX] Ethernet link timeout! Cable connected? + [NetX] Packet pool created + [NetX] IP instance created + [NetX] Enabling ARP... + [NetX] Enabling TCP... + [NetX] Enabling UDP... + [NetX] Enabling ICMP... + [NetX] Creating DHCP Thread... + [NetX] tx_application_define completed + [NetX] Network Monitor Thread Started. + ``` +3. **Connect Cable**: Plug in your network Ethernet cable. The console will report the connection, initiate DHCP, and spawn the TCP Echo Server: + ```text + [NetX] Ethernet cable connected! Enabling link... + [NetX] Ethernet link is UP! Starting DHCP client... + [NetX] DHCP Success! + [NetX] IP Address : + [NetX] Subnet Mask: 255.255.255.0 + [Echo] TCP Echo Server listening on port 7 + ``` +4. **Run the Simple Echo Test**: Open a terminal on your computer and run one of the included scripts: + * **On Windows (PowerShell)**: + ```powershell + powershell -ExecutionPolicy Bypass -File "app/demos/netx_echo/test_echo_simple.ps1" + ``` + * **On Linux (Bash)**: + ```bash + chmod +x app/demos/netx_echo/test_echo_simple.sh + ./app/demos/netx_echo/test_echo_simple.sh + ``` + * **Expected Output**: + ```text + Connecting to on port 7... + Sending: 'Hello ThreadX NetX Echo!' + Received: 'Hello ThreadX NetX Echo!' + ``` +5. **Test Mid-Run Hot-Unplugging**: Disconnect the Ethernet cable. You will see `[NetX] Ethernet cable disconnected! Disabling link...` on the serial console, and the interface IP resets to `0.0.0.0`. Plug the cable back in, and it will re-acquire its configuration dynamically. + +--- + +### 3. How to Run & Verify the `threadx_basic` Demo +1. Open your serial terminal program at **115,200 baud, 8N1**. +2. Flash the `threadx_basic` binary to the board. +3. **Verify Heartbeat**: The Green LED (`LD1`) will blink continuously at `2 Hz` (250ms ON, 250ms OFF). +4. **Verify Button Scanner**: Press and hold the blue User Button on the board. The Blue LED (`LD2`) will light up immediately. In your serial terminal, a log message will print showing the system tick timestamp of the button transition. +5. **Verify UART Echo**: Type a word or string into your serial terminal and press `Enter`. The board will print the string back to you and flash the Red LED (`LD3`) for 50ms. + +--- -2. **Monitor Serial Console**: - * Connect a serial terminal program (VS Code Serial Monitor, PuTTY, or Tera Term) to the virtual ST-LINK COM Port. - * Configuration: **115,200 baud**, **8 data bits**, **1 stop bit**, **no parity**, **CRLF line endings** (`\r\n`). - * Press the blue button to check log telemetry, and type strings into the console to test the interrupt-driven echo thread! +## Developer Guide: How to Add a New Demo + +The decoupled architecture of the BSP (`board_bsp`) makes adding a new application or demo extremely simple: + +### Step 1: Create the Demo Directory +Create a new folder under `app/demos/` (e.g., `app/demos/my_demo/`). + +### Step 2: Write your Application Code +Create your `main.c`. Keep it clean by using the BSP initialization calls: +```c +#include "board_init.h" +#include "tx_api.h" + +int main(void) +{ + /* Initialize MPU, Clocks, GPIOs, and Serial Console */ + board_init(); + + /* Optional: Initialize Ethernet hardware if using networking */ + // board_ethernet_init(); + + /* Enter ThreadX Kernel */ + tx_kernel_enter(); + return 0; +} +``` + +### Step 3: Create `CMakeLists.txt` +Create a `CMakeLists.txt` in your demo folder: +```cmake +add_executable(${PROJECT_NAME} + main.c +) + +# Set compile definitions +target_compile_definitions(${PROJECT_NAME} + PRIVATE + STM32F767xx + USE_HAL_DRIVER + STM32F7 +) + +# Include paths +target_include_directories(${PROJECT_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} +) + +# Link with BSP, ThreadX, and optionally NetX Duo +target_link_libraries(${PROJECT_NAME} + PRIVATE + board_bsp + threadx + # netxduo # Uncomment if using network + # netx_stm32_driver # Uncomment if using network + stm32cubef7 +) + +# Apply linker script and print size +set_target_linker(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/STM32F767ZITx_FLASH.ld") +post_build(${PROJECT_NAME}) +``` + +### Step 4: Run your Demo +Configure CMake and build: +```bash +cmake -DACTIVE_DEMO=my_demo -B build +cmake --build build +``` diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/board_init.c b/STMicroelectronics/STM32F767ZI-Nucleo/app/board_init.c index 8788fbe3..53efb8a2 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/app/board_init.c +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/board_init.c @@ -13,11 +13,20 @@ */ #include "board_init.h" +#include "tx_api.h" #include +#include /* Global UART handler */ UART_HandleTypeDef huart3; +/* Global Ethernet handle */ +ETH_HandleTypeDef heth; + +/* Place the Ethernet DMA descriptors in the .nx_data section (uncacheable memory) */ +__attribute__((section(".RxDecripSection"))) ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; +__attribute__((section(".TxDecripSection"))) ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; + void SystemClock_Config(void); void MPU_Config(void); void MX_GPIO_Init(void); @@ -188,8 +197,29 @@ void MPU_Config(void) MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); + + /* Configure the MPU for the NetXDuo/Ethernet DMA buffers in SRAM2 (0x20060000) */ + MPU_InitStruct.Number = MPU_REGION_NUMBER1; + MPU_InitStruct.BaseAddress = 0x20060000; + MPU_InitStruct.Size = MPU_REGION_SIZE_128KB; + MPU_InitStruct.SubRegionDisable = 0x0; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; + MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; + + HAL_MPU_ConfigRegion(&MPU_InitStruct); + /* Enables the MPU */ HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); + + /* Enable I-Cache */ + SCB_EnableICache(); + + /* Enable D-Cache */ + SCB_EnableDCache(); } /** @@ -203,3 +233,94 @@ void Error_Handler(void) { } } + +void ETH_IRQHandler(void) +{ + HAL_ETH_IRQHandler(&heth); +} + + + +void board_ethernet_init(void) +{ + /* Unique MAC address generation based on STM32 96-bit Unique ID (UID) */ + static uint8_t MACAddr[6]; + uint32_t uid0 = HAL_GetUIDw0(); + + MACAddr[0] = 0x02; /* Locally administered unicast MAC address */ + MACAddr[1] = 0x00; + MACAddr[2] = (uint8_t)(uid0 >> 24); + MACAddr[3] = (uint8_t)(uid0 >> 16); + MACAddr[4] = (uint8_t)(uid0 >> 8); + MACAddr[5] = (uint8_t)(uid0); + + heth.Instance = ETH; + heth.Init.MACAddr = MACAddr; + heth.Init.MediaInterface = HAL_ETH_RMII_MODE; + heth.Init.TxDesc = DMATxDscrTab; + heth.Init.RxDesc = DMARxDscrTab; + heth.Init.RxBuffLen = 1524; + + printf("[HAL] Calling HAL_ETH_Init...\r\n"); + HAL_StatusTypeDef status = HAL_ETH_Init(&heth); + printf("[HAL] HAL_ETH_Init returned status: %d\r\n", status); + + /* Initialize the PHY transceiver and wait for the link to be established. + This ensures that when NetX Duo enables the interface during startup, + the hardware link is already up, avoiding driver initialization failures. */ + extern int32_t nx_eth_phy_init(void); + extern int32_t nx_eth_phy_get_link_state(void); + printf("[NetX] Initializing PHY transceiver...\r\n"); + if (nx_eth_phy_init() == 0) + { + printf("[NetX] Waiting for Ethernet link (max 3s)...\r\n"); + uint32_t retries = 300; /* 300 * 10ms = 3 seconds */ + while (nx_eth_phy_get_link_state() <= 1) + { + HAL_Delay(10); + retries--; + if (retries == 0) + { + printf("[NetX] Ethernet link timeout! Cable connected?\r\n"); + break; + } + } + if (nx_eth_phy_get_link_state() > 1) + { + printf("[NetX] Ethernet link up!\r\n"); + } + } + else + { + printf("[NetX] Failed to initialize PHY transceiver!\r\n"); + } +} + +/* Override the weak HAL_GetTick function to provide a working tick source + both before and after the ThreadX scheduler starts. */ +uint32_t HAL_GetTick(void) +{ + /* If the ThreadX scheduler is running, use the ThreadX time */ + if (tx_thread_identify() != TX_NULL) + { + return (uint32_t)tx_time_get(); + } + else + { + /* Return actual elapsed milliseconds based on SysTick hardware counter wrap-around. + Since SysTick counts down from LOAD to 0, a wrap-around occurs when the current + value is greater than the last checked value, or if COUNTFLAG is set. */ + static uint32_t last_val = 0; + static uint32_t ms_ticks = 0; + + uint32_t ctrl = SysTick->CTRL; + uint32_t val = SysTick->VAL; + + if ((ctrl & SysTick_CTRL_COUNTFLAG_Msk) || (val > last_val)) + { + ms_ticks++; + } + last_val = val; + return ms_ticks; + } +} diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/board_init.h b/STMicroelectronics/STM32F767ZI-Nucleo/app/board_init.h index e48dff8a..7cb42fe0 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/app/board_init.h +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/board_init.h @@ -36,7 +36,11 @@ extern UART_HandleTypeDef huart3; #define UartHandle huart3 +/* Global Ethernet handle */ +extern ETH_HandleTypeDef heth; + /* Define prototypes. */ void board_init(void); +void board_ethernet_init(void); #endif // _BOARD_INIT_H diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/CMakeLists.txt b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/CMakeLists.txt new file mode 100644 index 00000000..f3672d6b --- /dev/null +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/CMakeLists.txt @@ -0,0 +1,44 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +add_executable(${PROJECT_NAME} + main.c +) + +# Set compile definitions for our executable +target_compile_definitions(${PROJECT_NAME} + PRIVATE + STM32F767xx + USE_HAL_DRIVER + STM32F7 +) + +# Include paths for the executable target +target_include_directories(${PROJECT_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} +) + +# Link libraries +target_link_libraries(${PROJECT_NAME} + PRIVATE + board_bsp + threadx + netxduo + netx_stm32_driver + stm32cubef7 +) + +# Apply GCC linker script and print memory usage (utilities.cmake function) +set_target_linker(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/STM32F767ZITx_FLASH.ld") + +# Post-build commands to generate raw .bin and .hex files +post_build(${PROJECT_NAME}) diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/main.c b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/main.c new file mode 100644 index 00000000..7e762986 --- /dev/null +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/main.c @@ -0,0 +1,209 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#include "board_init.h" +#include "tx_api.h" +#include "nx_api.h" +#include "nxd_dhcp_client.h" +#include + +#define DEMO_STACK_SIZE 2048 +#define PACKET_SIZE 1536 +#define PACKET_POOL_SIZE (PACKET_SIZE * 20) +#define ECHO_SERVER_PORT 7 + +#define ARP_CACHE_SIZE 1024 + +TX_THREAD dhcp_thread; +uint8_t dhcp_thread_stack[DEMO_STACK_SIZE]; + +TX_THREAD tcp_echo_thread; +uint8_t tcp_echo_stack[DEMO_STACK_SIZE]; + +uint8_t ip_thread_stack[DEMO_STACK_SIZE]; +uint8_t arp_cache_area[ARP_CACHE_SIZE]; + +NX_PACKET_POOL pool_0; +NX_IP ip_0; +NX_DHCP dhcp_client; + +/* Place the NetX Duo packet pool in the .nx_data section (uncacheable memory) */ +__attribute__((section(".NetXPoolSection"))) uint8_t packet_pool_area[PACKET_POOL_SIZE]; + +extern VOID nx_stm32_eth_driver(NX_IP_DRIVER *driver_req_ptr); + +void dhcp_thread_entry(ULONG thread_input); +void tcp_echo_thread_entry(ULONG thread_input); + +int main(void) +{ + board_init(); + printf("\r\n==========================================\r\n"); + printf("NetX Echo Demo Booted!\r\n"); + printf("==========================================\r\n\r\n"); + + /* Initialize the Ethernet hardware, MAC, and wait for link to be established */ + board_ethernet_init(); + + tx_kernel_enter(); + return 0; +} + +void tx_application_define(void *first_unused_memory) +{ + (void)first_unused_memory; + + nx_system_initialize(); + + /* Create the packet pool in our uncacheable section */ + if (nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", + PACKET_SIZE, packet_pool_area, PACKET_POOL_SIZE) != NX_SUCCESS) { + printf("[NetX] Failed to create packet pool.\r\n"); + return; + } + printf("[NetX] Packet pool created\r\n"); + + /* Create the IP instance using the STM32 Ethernet driver */ + if (nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(0, 0, 0, 0), + 0xFFFFFF00UL, &pool_0, nx_stm32_eth_driver, + ip_thread_stack, DEMO_STACK_SIZE, 1) != NX_SUCCESS) { + printf("[NetX] Failed to create IP instance.\r\n"); + return; + } + printf("[NetX] IP instance created\r\n"); + + /* Enable ARP, TCP, UDP, and ICMP */ + printf("[NetX] Enabling ARP...\r\n"); + nx_arp_enable(&ip_0, (VOID *)arp_cache_area, ARP_CACHE_SIZE); + printf("[NetX] Enabling TCP...\r\n"); + nx_tcp_enable(&ip_0); + printf("[NetX] Enabling UDP...\r\n"); + nx_udp_enable(&ip_0); + printf("[NetX] Enabling ICMP...\r\n"); + nx_icmp_enable(&ip_0); + + /* Start DHCP Thread */ + printf("[NetX] Creating DHCP Thread...\r\n"); + tx_thread_create(&dhcp_thread, "DHCP Thread", dhcp_thread_entry, 0, + dhcp_thread_stack, DEMO_STACK_SIZE, 2, 2, TX_NO_TIME_SLICE, TX_AUTO_START); + printf("[NetX] tx_application_define completed\r\n"); +} + +void dhcp_thread_entry(ULONG thread_input) +{ + ULONG ip_address; + ULONG network_mask; + ULONG actual_status; + UINT prev_link_up = NX_FALSE; + UINT tcp_server_started = NX_FALSE; + extern int32_t nx_eth_phy_get_link_state(void); + + /* Create the DHCP client instance once */ + nx_dhcp_create(&dhcp_client, &ip_0, "DHCP Client"); + + printf("[NetX] Network Monitor Thread Started.\r\n"); + + while (1) + { + /* Poll the physical link state */ + int32_t phy_state = nx_eth_phy_get_link_state(); + UINT curr_link_up = (phy_state > 1) ? NX_TRUE : NX_FALSE; + + if (curr_link_up != prev_link_up) + { + if (curr_link_up) + { + printf("[NetX] Ethernet cable connected! Enabling link...\r\n"); + UINT status = nx_ip_driver_direct_command(&ip_0, NX_LINK_ENABLE, &actual_status); + if (status == NX_SUCCESS || status == NX_ALREADY_ENABLED) + { + printf("[NetX] Ethernet link is UP! Starting DHCP client...\r\n"); + nx_dhcp_start(&dhcp_client); + + /* Wait up to 10 seconds for IP address resolution */ + if (nx_ip_status_check(&ip_0, NX_IP_ADDRESS_RESOLVED, &ip_address, 1000) == NX_SUCCESS) + { + nx_ip_address_get(&ip_0, &ip_address, &network_mask); + printf("[NetX] DHCP Success!\r\n"); + printf("[NetX] IP Address : %lu.%lu.%lu.%lu\r\n", + (ip_address >> 24) & 0xFF, (ip_address >> 16) & 0xFF, + (ip_address >> 8) & 0xFF, ip_address & 0xFF); + printf("[NetX] Subnet Mask: %lu.%lu.%lu.%lu\r\n", + (network_mask >> 24) & 0xFF, (network_mask >> 16) & 0xFF, + (network_mask >> 8) & 0xFF, network_mask & 0xFF); + } + else + { + printf("[NetX] DHCP Timeout! Using static IP 192.168.0.100\r\n"); + nx_dhcp_stop(&dhcp_client); + nx_ip_address_set(&ip_0, IP_ADDRESS(192, 168, 0, 100), 0xFFFFFF00UL); + } + + /* Start the TCP Echo Server thread if not already started */ + if (!tcp_server_started) + { + tx_thread_create(&tcp_echo_thread, "TCP Echo Thread", tcp_echo_thread_entry, 0, + tcp_echo_stack, DEMO_STACK_SIZE, 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START); + tcp_server_started = NX_TRUE; + } + } + else + { + printf("[NetX] Failed to enable driver link: 0x%02x\r\n", status); + } + } + else + { + printf("[NetX] Ethernet cable disconnected! Disabling link...\r\n"); + nx_dhcp_stop(&dhcp_client); + nx_ip_driver_direct_command(&ip_0, NX_LINK_DISABLE, &actual_status); + /* Reset IP address to 0.0.0.0 */ + nx_ip_address_set(&ip_0, IP_ADDRESS(0, 0, 0, 0), 0xFFFFFF00UL); + } + prev_link_up = curr_link_up; + } + + tx_thread_sleep(100); /* Poll every 1 second (100 ticks) */ + } +} + +void tcp_echo_thread_entry(ULONG thread_input) +{ + NX_TCP_SOCKET echo_socket; + NX_PACKET *packet_ptr; + + nx_tcp_socket_create(&ip_0, &echo_socket, "Echo Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 512, NX_NULL, NX_NULL); + + printf("[Echo] TCP Echo Server listening on port %d\r\n", ECHO_SERVER_PORT); + + while (1) { + if (nx_tcp_server_socket_listen(&ip_0, ECHO_SERVER_PORT, &echo_socket, 5, NX_NULL) != NX_SUCCESS) { + nx_tcp_server_socket_unlisten(&ip_0, ECHO_SERVER_PORT); + continue; + } + + if (nx_tcp_server_socket_accept(&echo_socket, NX_WAIT_FOREVER) == NX_SUCCESS) { + printf("[Echo] Client connected.\r\n"); + + while (nx_tcp_socket_receive(&echo_socket, &packet_ptr, NX_WAIT_FOREVER) == NX_SUCCESS) { + /* Echo the packet back */ + nx_tcp_socket_send(&echo_socket, packet_ptr, NX_WAIT_FOREVER); + } + + printf("[Echo] Client disconnected.\r\n"); + nx_tcp_socket_disconnect(&echo_socket, NX_WAIT_FOREVER); + nx_tcp_server_socket_unaccept(&echo_socket); + } + nx_tcp_server_socket_unlisten(&ip_0, ECHO_SERVER_PORT); + } +} diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/nx_stm32_eth_config.h b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/nx_stm32_eth_config.h new file mode 100644 index 00000000..9f64d9f0 --- /dev/null +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/nx_stm32_eth_config.h @@ -0,0 +1,30 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#ifndef NX_STM32_ETH_CONFIG_H +#define NX_STM32_ETH_CONFIG_H + +#include "stm32f7xx_hal.h" +#include "lan8742.h" + +extern ETH_HandleTypeDef heth; +#define eth_handle heth + +/* Define the PHY physical address */ +#define LAN8742_PHY_ADDRESS 0 + +/* This define enables the call of nx_eth_init() from the interface layer.*/ +/* #define NX_DRIVER_ETH_HW_IP_INIT */ +void nx_eth_init(void); + +#endif /* NX_STM32_ETH_CONFIG_H */ diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/ethernet_phy.h b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/nx_user.h similarity index 53% rename from STMicroelectronics/STM32F767ZI-Nucleo/app/ethernet_phy.h rename to STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/nx_user.h index af254b73..6eb41c8e 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/app/ethernet_phy.h +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/nx_user.h @@ -7,20 +7,16 @@ * * SPDX-License-Identifier: MIT * - * Contributors: + * Contributors: * Ali Eissa - 2026 version. */ -#ifndef _ETHERNET_PHY_H -#define _ETHERNET_PHY_H + #ifndef NX_USER_H +#define NX_USER_H -#include "stm32f7xx_hal.h" +#define NX_DISABLE_IPV6 +#define NX_ENABLE_INTERFACE_CAPABILITY +#define NX_PHYSICAL_HEADER 16 +#define NX_ENABLE_EXTENDED_NOTIFY_SUPPORT -/* Global Ethernet Handle */ -extern ETH_HandleTypeDef heth; -extern ETH_TxPacketConfig TxConfig; - -/* Function Prototypes */ -void ethernet_phy_init(void); - -#endif // _ETHERNET_PHY_H +#endif /* NX_USER_H */ diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/test_echo_simple.ps1 b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/test_echo_simple.ps1 new file mode 100644 index 00000000..6924b802 --- /dev/null +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/test_echo_simple.ps1 @@ -0,0 +1,34 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +param ( + [string]$IP = "192.168.0.100" +) + +Write-Host "Connecting to $IP on port 7..." +try { + $client = New-Object System.Net.Sockets.TcpClient($IP, 7) + $stream = $client.GetStream() + $writer = New-Object System.IO.StreamWriter($stream) + $reader = New-Object System.IO.StreamReader($stream) + + $msg = "Hello ThreadX NetX Echo!" + Write-Host "Sending: '$msg'" + $writer.WriteLine($msg) + $writer.Flush() + + $response = $reader.ReadLine() + Write-Host "Received: '$response'" +} catch { + Write-Error "Failed to connect or communicate: $_" +} finally { + if ($client) { $client.Close() } +} diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/test_echo_simple.sh b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/test_echo_simple.sh new file mode 100644 index 00000000..986b95ca --- /dev/null +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/test_echo_simple.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +IP=${1:-"192.168.0.100"} +PORT=7 +MSG="Hello ThreadX NetX Echo!" + +echo "Connecting to $IP on port $PORT..." + +# Check if netcat is installed +if command -v nc >/dev/null 2>&1; then + # Use netcat with a 2-second timeout to send the message and read the echo + RESPONSE=$(echo "$MSG" | nc -w 2 "$IP" "$PORT") + if [ $? -eq 0 ] && [ ! -z "$RESPONSE" ]; then + echo "Sending: '$MSG'" + echo "Received: '$RESPONSE'" + else + echo "Error: Failed to receive echo response. Is the server running?" + exit 1 + fi +else + # Fallback to Python if netcat is not available (standard on almost all Linux distros) + echo "netcat (nc) not found, falling back to python3..." + python3 -c " +import socket, sys +try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(2.0) + s.connect(('$IP', $PORT)) + s.sendall(b'$MSG\n') + data = s.recv(1024) + print('Sending: $MSG') + print('Received: ' + data.decode().strip()) +except Exception as e: + print('Error:', e) + sys.exit(1) +finally: + s.close() +" +fi diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/CMakeLists.txt b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/CMakeLists.txt new file mode 100644 index 00000000..9d269018 --- /dev/null +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/CMakeLists.txt @@ -0,0 +1,42 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +add_executable(${PROJECT_NAME} + main.c +) + +# Set compile definitions for our executable +target_compile_definitions(${PROJECT_NAME} + PRIVATE + STM32F767xx + USE_HAL_DRIVER + STM32F7 +) + +# Include paths for the executable target +target_include_directories(${PROJECT_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} +) + +# Link libraries +target_link_libraries(${PROJECT_NAME} + PRIVATE + board_bsp + threadx + stm32cubef7 +) + +# Apply GCC linker script and print memory usage (utilities.cmake function) +set_target_linker(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/STM32F767ZITx_FLASH.ld") + +# Post-build commands to generate raw .bin and .hex files +post_build(${PROJECT_NAME}) diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/main.c b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/main.c similarity index 100% rename from STMicroelectronics/STM32F767ZI-Nucleo/app/main.c rename to STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/main.c diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/ethernet_phy.c b/STMicroelectronics/STM32F767ZI-Nucleo/app/ethernet_phy.c deleted file mode 100644 index 2f4649c0..00000000 --- a/STMicroelectronics/STM32F767ZI-Nucleo/app/ethernet_phy.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 - * - * Contributors: - * Ali Eissa - 2026 version. - */ - -#include "ethernet_phy.h" -#include "board_init.h" -#include - -/* Global Ethernet descriptors mapped to physical DMA sections */ -ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */ -ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".TxDecripSection"))); /* Ethernet Tx DMA Descriptors */ - -ETH_TxPacketConfig TxConfig; -ETH_HandleTypeDef heth; - -static void MX_ETH_Init(void); - -/** - * @brief Initialize Ethernet peripheral MAC and RMII interfaces. - * - * @retval None - */ -void ethernet_phy_init(void) -{ - MX_ETH_Init(); -} - -/** - * @brief ETH Initialization Function - * - * @retval None - */ -static void MX_ETH_Init(void) -{ - static uint8_t MACAddr[6]; - - heth.Instance = ETH; - MACAddr[0] = 0x00; - MACAddr[1] = 0x80; - MACAddr[2] = 0xE1; - MACAddr[3] = 0x00; - MACAddr[4] = 0x00; - MACAddr[5] = 0x00; - heth.Init.MACAddr = &MACAddr[0]; - heth.Init.MediaInterface = HAL_ETH_RMII_MODE; - heth.Init.TxDesc = DMATxDscrTab; - heth.Init.RxDesc = DMARxDscrTab; - heth.Init.RxBuffLen = 1524; - - if (HAL_ETH_Init(&heth) != HAL_OK) - { - Error_Handler(); - } - - memset(&TxConfig, 0 , sizeof(ETH_TxPacketConfig)); - TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD; - TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC; - TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT; -} diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/startup/STM32F767ZITx_FLASH.ld b/STMicroelectronics/STM32F767ZI-Nucleo/app/startup/STM32F767ZITx_FLASH.ld index ad892409..2d3db60d 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/app/startup/STM32F767ZITx_FLASH.ld +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/startup/STM32F767ZITx_FLASH.ld @@ -31,7 +31,7 @@ ENTRY(Reset_Handler) _vectors = g_pfnVectors; /* Highest address of the user mode stack */ -_estack = 0x20050000; /* end of RAM */ +_estack = 0x20080000; /* end of RAM */ /* Generate a link error if heap and stack don't fit into RAM */ _Min_Heap_Size = 0x200; /* required amount of heap */ _Min_Stack_Size = 0x400; /* required amount of stack */ @@ -40,7 +40,7 @@ _Min_Stack_Size = 0x400; /* required amount of stack */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K -RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 512K } /* Define output sections */ @@ -141,6 +141,16 @@ SECTIONS __RAM_segment_used_end__ = _ebss; } >RAM + .nx_data 0x20060000 (NOLOAD): + { + . = ALIGN(4); + *(.RxDecripSection) + *(.TxDecripSection) + *(.RxArraySection) + *(.NetXPoolSection) + . = ALIGN(4); + } >RAM + /* User_heap_stack section, used to check that there is enough RAM left */ ._user_heap_stack : { diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/stm32f7xx_hal_msp.c b/STMicroelectronics/STM32F767ZI-Nucleo/app/stm32f7xx_hal_msp.c index 9ae84075..d17dc1da 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/app/stm32f7xx_hal_msp.c +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/stm32f7xx_hal_msp.c @@ -90,8 +90,16 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) /* USER CODE BEGIN ETH_MspInit 0 */ /* USER CODE END ETH_MspInit 0 */ + /* Enable SYSCFG Clock */ + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + /* Select RMII Mode */ + SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL; + /* Peripheral clock enable */ - __HAL_RCC_ETH_CLK_ENABLE(); + __HAL_RCC_ETHMAC_CLK_ENABLE(); + __HAL_RCC_ETHMACTX_CLK_ENABLE(); + __HAL_RCC_ETHMACRX_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); @@ -111,33 +119,34 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) GPIO_InitStruct.Pin = RMII_MDC_Pin|RMII_RXD0_Pin|RMII_RXD1_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF11_ETH; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); GPIO_InitStruct.Pin = RMII_REF_CLK_Pin|RMII_MDIO_Pin|RMII_CRS_DV_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF11_ETH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = RMII_TXD1_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF11_ETH; HAL_GPIO_Init(RMII_TXD1_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = RMII_TX_EN_Pin|RMII_TXD0_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF11_ETH; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); /* USER CODE BEGIN ETH_MspInit 1 */ - + HAL_NVIC_SetPriority(ETH_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(ETH_IRQn); /* USER CODE END ETH_MspInit 1 */ } diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.ps1 b/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.ps1 index 115c1774..3f7102c1 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.ps1 +++ b/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.ps1 @@ -15,6 +15,7 @@ $DriversDir = Join-Path $LibDir "Drivers" $HalDest = Join-Path $DriversDir "STM32F7xx_HAL_Driver" $CmsisDeviceDest = Join-Path $DriversDir "CMSIS/Device/ST/STM32F7xx" $CmsisIncludeDest = Join-Path $DriversDir "CMSIS/Include" +$NetxDriverDest = Join-Path $BoardDir "lib/netxduo" Write-Host "==========================================" Write-Host "STM32CubeF7 Standalone Driver Fetcher" @@ -26,10 +27,12 @@ Write-Host "" if (Test-Path $HalDest) { Remove-Item -Path $HalDest -Recurse -Force } if (Test-Path $CmsisDeviceDest) { Remove-Item -Path $CmsisDeviceDest -Recurse -Force } if (Test-Path $CmsisIncludeDest) { Remove-Item -Path $CmsisIncludeDest -Recurse -Force } +if (Test-Path $NetxDriverDest) { Remove-Item -Path $NetxDriverDest -Recurse -Force } New-Item -ItemType Directory -Path $HalDest -Force | Out-Null New-Item -ItemType Directory -Path $CmsisDeviceDest -Force | Out-Null New-Item -ItemType Directory -Path $CmsisIncludeDest -Force | Out-Null +New-Item -ItemType Directory -Path $NetxDriverDest -Force | Out-Null $TempDir = Join-Path $BoardDir "temp_clone" @@ -83,6 +86,41 @@ CleanTemp Write-Host "[OK] Up-to-date CMSIS Core Include headers copied" Write-Host "" +# 4. Fetch NetX Duo STM32 middleware drivers +Write-Host "[INFO] Cloning STM32 NetX Duo middleware drivers (depth=1)..." +git clone --depth 1 https://github.com/STMicroelectronics/x-cube-azrtos-f7.git $TempDir +if ($LASTEXITCODE -ne 0) { + Write-Host "[ERROR] Failed to clone NetX Duo middleware repository!" -ForegroundColor Red + CleanTemp + exit 1 +} +Copy-Item -Path "$TempDir/Middlewares/ST/netxduo/common/drivers/ethernet/nx_stm32_eth_driver.c" -Destination $NetxDriverDest -Force +Copy-Item -Path "$TempDir/Middlewares/ST/netxduo/common/drivers/ethernet/nx_stm32_eth_driver.h" -Destination $NetxDriverDest -Force +Copy-Item -Path "$TempDir/Middlewares/ST/netxduo/common/drivers/ethernet/lan8742/nx_stm32_phy_driver.c" -Destination $NetxDriverDest -Force +Copy-Item -Path "$TempDir/Middlewares/ST/netxduo/common/drivers/ethernet/nx_stm32_phy_driver.h" -Destination $NetxDriverDest -Force + +# ST modified the HAL ETH driver to match the new H7-style API for NetX Duo, so we must overwrite the default ones +Copy-Item -Path "$TempDir/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_eth.c" -Destination "$HalDest/Src" -Force +Copy-Item -Path "$TempDir/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_eth.h" -Destination "$HalDest/Inc" -Force + +CleanTemp +Write-Host "[OK] NetX Duo STM32 Ethernet drivers copied" +Write-Host "" + +# 5. Fetch LAN8742 PHY driver +Write-Host "[INFO] Cloning LAN8742 PHY driver (depth=1)..." +git clone --depth 1 https://github.com/STMicroelectronics/stm32-lan8742.git $TempDir +if ($LASTEXITCODE -ne 0) { + Write-Host "[ERROR] Failed to clone LAN8742 PHY repository!" -ForegroundColor Red + CleanTemp + exit 1 +} +Copy-Item -Path "$TempDir/lan8742.c" -Destination $NetxDriverDest -Force +Copy-Item -Path "$TempDir/lan8742.h" -Destination $NetxDriverDest -Force +CleanTemp +Write-Host "[OK] LAN8742 PHY drivers copied" +Write-Host "" + Write-Host "==========================================" Write-Host "[SUCCESS] STM32CubeF7 drivers successfully fetched!" Write-Host "==========================================" diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.sh b/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.sh index b9038950..443db778 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.sh +++ b/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.sh @@ -21,6 +21,7 @@ DRIVERS_DIR="${LIB_DIR}/Drivers" HAL_DEST="${DRIVERS_DIR}/STM32F7xx_HAL_Driver" CMSIS_DEVICE_DEST="${DRIVERS_DIR}/CMSIS/Device/ST/STM32F7xx" CMSIS_INCLUDE_DEST="${DRIVERS_DIR}/CMSIS/Include" +NETX_DRIVER_DEST="${BOARD_DIR}/lib/netxduo" echo "==========================================" echo "STM32CubeF7 Standalone Driver Fetcher (Linux)" @@ -32,11 +33,13 @@ echo "" rm -rf "${HAL_DEST}" rm -rf "${CMSIS_DEVICE_DEST}" rm -rf "${CMSIS_INCLUDE_DEST}" +rm -rf "${NETX_DRIVER_DEST}" # Re-create directories mkdir -p "${HAL_DEST}" mkdir -p "${CMSIS_DEVICE_DEST}" mkdir -p "${CMSIS_INCLUDE_DEST}" +mkdir -p "${NETX_DRIVER_DEST}" TEMP_DIR="${BOARD_DIR}/temp_clone" @@ -77,6 +80,31 @@ clean_temp echo "[OK] Up-to-date CMSIS Core Include headers copied" echo "" +# 4. Fetch NetX Duo STM32 middleware drivers +echo "[INFO] Cloning STM32 NetX Duo middleware drivers (depth=1)..." +git clone --depth 1 https://github.com/STMicroelectronics/x-cube-azrtos-f7.git "${TEMP_DIR}" +cp -f "${TEMP_DIR}/Middlewares/ST/netxduo/common/drivers/ethernet/nx_stm32_eth_driver.c" "${NETX_DRIVER_DEST}/" +cp -f "${TEMP_DIR}/Middlewares/ST/netxduo/common/drivers/ethernet/nx_stm32_eth_driver.h" "${NETX_DRIVER_DEST}/" +cp -f "${TEMP_DIR}/Middlewares/ST/netxduo/common/drivers/ethernet/lan8742/nx_stm32_phy_driver.c" "${NETX_DRIVER_DEST}/" +cp -f "${TEMP_DIR}/Middlewares/ST/netxduo/common/drivers/ethernet/nx_stm32_phy_driver.h" "${NETX_DRIVER_DEST}/" + +# ST modified the HAL ETH driver to match the new H7-style API for NetX Duo, so we must overwrite the default ones +cp -f "${TEMP_DIR}/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_eth.c" "${HAL_DEST}/Src/" +cp -f "${TEMP_DIR}/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_eth.h" "${HAL_DEST}/Inc/" + +clean_temp +echo "[OK] NetX Duo STM32 Ethernet drivers copied" +echo "" + +# 5. Fetch LAN8742 PHY driver +echo "[INFO] Cloning LAN8742 PHY driver (depth=1)..." +git clone --depth 1 https://github.com/STMicroelectronics/stm32-lan8742.git "${TEMP_DIR}" +cp -f "${TEMP_DIR}/lan8742.c" "${NETX_DRIVER_DEST}/" +cp -f "${TEMP_DIR}/lan8742.h" "${NETX_DRIVER_DEST}/" +clean_temp +echo "[OK] LAN8742 PHY drivers copied" +echo "" + echo "==========================================" echo "[SUCCESS] STM32CubeF7 drivers successfully fetched!" echo "==========================================" From 1bddd17b334b37f9eddb30c67798e075899dfce2 Mon Sep 17 00:00:00 2001 From: AmmarOkla12772 <146969371+AmmarOkla12772@users.noreply.github.com> Date: Mon, 20 Jul 2026 18:25:27 +0300 Subject: [PATCH 03/20] STMicro Nucleo-F401re: implemented comprehensive ThreadX RTOS monitor and primitives showcase (#45) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * new file: STMicroelectronics/NUCLEO_F401RE/CMakeLists.txt 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 * Cmake files populated, HAL library and boot code copied and modified * Startup files obtained from official repositories and adjusted to meet board specs and ThreadX requirements * Fixed build sequence * STM32F401RE: achieve first successful ThreadX hardware bring-up Booted ThreadX on NUCLEO-F401RE Validated scheduler operation Validated UART console output Validated LED thread Validated flashing and hardware execution * implement ThreadX board initialization and multi-threading demo for NUCLEO-F401RE (continued) * Fixed licensing, added documentation * added CMake build configuration for NUCLEO-F401RE board * implemented dynamic memory management, added monitor thread * added bytepools and demonstrations of threadx features such as mutex and event flags. Modified demo README file to reflect changes. * Implemented block pools to prevent fragmentation of memory. Added semaphore functionality and 1 hz applicaion timer. * Added missing licensing header to main.c * Fixed incomplete NUCLEO licensing headers --------- Co-authored-by: Ammar Okla Co-authored-by: Frédéric Desbiens Co-authored-by: Codex --- STMicroelectronics/NUCLEO_F401RE/README.md | 43 +- .../NUCLEO_F401RE/app/common/board_init.c | 5 + .../NUCLEO_F401RE/app/common/board_init.h | 4 + .../NUCLEO_F401RE/app/common/console.c | 5 + .../common/stm32cubef4/stm32f4xx_hal_msp.c | 5 + .../NUCLEO_F401RE/app/starter/cloud_config.h | 4 + .../NUCLEO_F401RE/app/starter/main.c | 611 +++++++++++++++--- .../NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.c | 5 + .../NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.h | 4 + 9 files changed, 567 insertions(+), 119 deletions(-) diff --git a/STMicroelectronics/NUCLEO_F401RE/README.md b/STMicroelectronics/NUCLEO_F401RE/README.md index ac0a507a..16e8e227 100644 --- a/STMicroelectronics/NUCLEO_F401RE/README.md +++ b/STMicroelectronics/NUCLEO_F401RE/README.md @@ -140,25 +140,44 @@ The BSP overrides `HAL_InitTick()` to configure TIM2 as the HAL timebase and pro ## Validation Record ### Verification Environment -- **Toolchain**: Arm GNU Toolchain 15.2.Rel1 -- **ROM usage**: 11716 Bytes (2.23% of 512 KB Flash) -- **RAM usage**: 7312 Bytes (7.44% of 96 KB RAM) +- **Toolchain**: Arm GNU Toolchain 15.2.Rel1 (GCC 15.2.1) +- **Static ROM usage**: 18244 Bytes (3.48% of 512 KB Flash) +- **Static RAM usage**: 5632 Bytes (5.73% of 96 KB RAM) +- **Dynamic Stack & Buffer allocation**: Stacks (8 x 1024 bytes) and Queue buffer (40 bytes) are dynamically allocated from the `TX_BYTE_POOL` (consuming 8312 bytes total, including pool headers). - **Board Hardware**: NUCLEO-F401RE ### Hardware Verification Checklist - [x] **Board boots successfully**: System clock configuration correctly executes and sets SysClk to 84 MHz. -- [x] **LED heartbeat operates correctly**: Onboard user LED LD2 (PA5) blinks at a steady 1 Hz interval (toggled by blink thread). +- [x] **LED heartbeat operates correctly**: Onboard user LED LD2 (PA5) blinks at a steady rate. - [x] **UART console operates at 115200 baud**: Diagnostic outputs are cleanly transmitted over USART2 and displayed in the terminal. -- [x] **ThreadX scheduler runs correctly**: RTOS scheduler successfully handles multi-threaded execution (Blink, Worker, and Reporter threads). -- [x] **Runtime monitor output verified on hardware**: UART serial output prints thread performance stats and uptime reports every 2 seconds: +- [x] **ThreadX scheduler runs correctly**: RTOS scheduler successfully handles 8 threads with priorities ranging from 9 to 15. +- [x] **Thread Registry & Traversal**: Monitor thread queries thread names, states, run counts, and priorities dynamically using `tx_thread_info_get()`. +- [x] **Stack High-Water Mark Profiling**: Dynamic upward memory scanning verifies stack peaks (e.g., reporter thread at 42%, other tasks at 11-14%). +- [x] **RTOS Primitives Showcase**: Verified mutex lock hand-offs under contention, queue message transfers, and event flag synchronization. +- [x] **Runtime monitor output verified on hardware**: UART serial output prints thread diagnostics table and showcase counters every 2 seconds: ```text -========================================== -Nucleo F401RE ThreadX Multithreading Demo -========================================== -[Reporter] Uptime: 0 s | Blink Thread: 0 runs | Worker Thread: 0 runs | Reporter: 1 runs -[Reporter] Uptime: 2 s | Blink Thread: 4 runs | Worker Thread: 10 runs | Reporter: 2 runs -[Reporter] Uptime: 4 s | Blink Thread: 8 runs | Worker Thread: 20 runs | Reporter: 3 runs +System Status: +------------------------------------------ +Uptime: 257 s +Byte Pool Size: 88572 bytes +Allocated Memory: 8312 bytes +Free Memory: 80260 bytes +------------------------------------------ + +Thread Name Priority State Run Count Stack Peak (Max / Size) +---------------------------------------------------------------------------- +monitor thread 9 READY 2575 120 / 1024 bytes (11%) +reporter thread 10 SLEEP 256 432 / 1024 bytes (42%) +blink thread 11 SLEEP 488 136 / 1024 bytes (13%) +event thread 12 EVENT_FLAG 488 128 / 1024 bytes (12%) +mutex thread 1 13 SLEEP 7319 144 / 1024 bytes (14%) +mutex thread 2 13 READY 7319 144 / 1024 bytes (14%) +queue sender 14 READY 1220 128 / 1024 bytes (12%) +queue receiver 15 QUEUE_SUSP 1220 128 / 1024 bytes (12%) +---------------------------------------------------------------------------- +Runs: Monitor: 2576 | Reporter: 123 | Blink: 488 +RTOS Showcase: Mutex Locks: 2440/2440 | Queue Msgs: 1220 | Event Wakes: 488 ``` diff --git a/STMicroelectronics/NUCLEO_F401RE/app/common/board_init.c b/STMicroelectronics/NUCLEO_F401RE/app/common/board_init.c index 9c5f1100..9e8e052e 100644 --- a/STMicroelectronics/NUCLEO_F401RE/app/common/board_init.c +++ b/STMicroelectronics/NUCLEO_F401RE/app/common/board_init.c @@ -1,8 +1,13 @@ /* * 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 */ +// Some portions generated by Codex (GPT-5). #include "board_init.h" diff --git a/STMicroelectronics/NUCLEO_F401RE/app/common/board_init.h b/STMicroelectronics/NUCLEO_F401RE/app/common/board_init.h index 4365faba..75341c19 100644 --- a/STMicroelectronics/NUCLEO_F401RE/app/common/board_init.h +++ b/STMicroelectronics/NUCLEO_F401RE/app/common/board_init.h @@ -1,6 +1,10 @@ /* * 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 */ diff --git a/STMicroelectronics/NUCLEO_F401RE/app/common/console.c b/STMicroelectronics/NUCLEO_F401RE/app/common/console.c index fcf9539d..326ccda6 100644 --- a/STMicroelectronics/NUCLEO_F401RE/app/common/console.c +++ b/STMicroelectronics/NUCLEO_F401RE/app/common/console.c @@ -1,8 +1,13 @@ /* * 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 */ +// Some portions generated by Codex (GPT-5). #include "stm32f4xx_hal.h" diff --git a/STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c b/STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c index ffacbddf..2a90bad1 100644 --- a/STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c +++ b/STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c @@ -1,8 +1,13 @@ /* * 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 */ +// Some portions generated by Codex (GPT-5). #include "stm32f4xx_hal.h" diff --git a/STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h b/STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h index fd7372de..03b5e1f9 100644 --- a/STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h +++ b/STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h @@ -1,6 +1,10 @@ /* * 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 */ diff --git a/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c b/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c index 44c4009b..c1b2488f 100644 --- a/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c +++ b/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c @@ -1,6 +1,10 @@ /* * 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 */ @@ -14,141 +18,534 @@ #define THREAD_STACK_SIZE 1024 -/* Thread Priorities: Lower value means higher priority */ -#define BLINK_THREAD_PRIORITY 4 -#define WORKER_THREAD_PRIORITY 6 -#define REPORTER_THREAD_PRIORITY 10 +typedef struct { + CHAR *name; + UINT state; + ULONG run_count; + UINT priority; + ULONG stack_used; + ULONG stack_size; +} ThreadStats; + +#define MAX_THREADS 9 + +typedef struct { + ULONG timestamp; + ULONG reading_id; + ULONG data_value; +} SensorData; + +typedef struct { + ULONG uptime; + ULONG byte_pool_total; + ULONG byte_pool_free; + ULONG byte_pool_used; + ThreadStats threads[MAX_THREADS]; + UINT thread_count; +} SystemStats; + +static SystemStats system_stats = {0}; + +/* Thread Registry */ +static TX_THREAD *thread_registry[MAX_THREADS]; + +/* Global Byte Pool for dynamic stack allocation */ +static TX_BYTE_POOL byte_pool; /* Thread Control Blocks */ -static TX_THREAD blink_thread; -static TX_THREAD worker_thread; +static TX_THREAD monitor_thread; static TX_THREAD reporter_thread; +static TX_THREAD blink_thread; +static TX_THREAD event_thread; +static TX_THREAD mutex_thread_1; +static TX_THREAD mutex_thread_2; +static TX_THREAD queue_sender_thread; +static TX_THREAD queue_receiver_thread; +static TX_THREAD semaphore_thread; -/* Thread Stacks */ -static ULONG blink_thread_stack[THREAD_STACK_SIZE / sizeof(ULONG)]; -static ULONG worker_thread_stack[THREAD_STACK_SIZE / sizeof(ULONG)]; -static ULONG reporter_thread_stack[THREAD_STACK_SIZE / sizeof(ULONG)]; +/* RTOS Primitives */ +static TX_MUTEX spi_mutex; +static TX_QUEUE msg_queue; +static TX_EVENT_FLAGS_GROUP event_flags; +static TX_BLOCK_POOL sensor_block_pool; +static TX_SEMAPHORE sensor_semaphore; +static TX_TIMER app_timer; -/* Activity counters */ -static ULONG blink_counter = 0; -static ULONG worker_counter = 0; +/* Activity and Primitive Counters */ +static ULONG monitor_counter = 0; static ULONG reporter_counter = 0; +static ULONG blink_counter = 0; + +static ULONG mutex_acquires_1 = 0; +static ULONG mutex_acquires_2 = 0; +static ULONG queue_msgs_received = 0; +static ULONG event_flags_processed = 0; +static ULONG semaphore_wakes = 0; +static ULONG timer_counter = 0; + +static const char *get_state_string(UINT state) { + switch (state) { + case TX_READY: + return "READY"; + case TX_COMPLETED: + return "COMPLETED"; + case TX_TERMINATED: + return "TERMINATED"; + case TX_SUSPENDED: + return "SUSPENDED"; + case TX_SLEEP: + return "SLEEP"; + case TX_QUEUE_SUSP: + return "QUEUE_SUSP"; + case TX_SEMAPHORE_SUSP: + return "SEMA_SUSP"; + case TX_EVENT_FLAG: + return "EVENT_FLAG"; + case TX_MUTEX_SUSP: + return "MUTEX_SUSP"; + default: + return "BLOCKED"; + } +} + +/* Monitor Thread: Producer of statistics */ +static void monitor_thread_entry(ULONG parameter) { + (void)parameter; + + while (1) { + monitor_counter++; + + /* 1. Track system uptime */ + system_stats.uptime = tx_time_get() / TX_TIMER_TICKS_PER_SECOND; + + /* 2. Track dynamic memory allocation stats */ + CHAR *name; + ULONG available_bytes; + ULONG fragments; + TX_THREAD *suspended_thread; + ULONG suspended_count; + TX_BYTE_POOL *next_pool; + + if (tx_byte_pool_info_get(&byte_pool, &name, &available_bytes, &fragments, + &suspended_thread, &suspended_count, + &next_pool) == TX_SUCCESS) { + system_stats.byte_pool_total = byte_pool.tx_byte_pool_size; + system_stats.byte_pool_free = available_bytes; + system_stats.byte_pool_used = + byte_pool.tx_byte_pool_size - available_bytes; + } -/* Thread entries */ -static void blink_thread_entry(ULONG parameter) -{ - (void)parameter; + /* 3. Query all registered threads' metrics */ + for (int i = 0; i < MAX_THREADS; i++) { + TX_THREAD *thread = thread_registry[i]; + if (thread != NULL) { + CHAR *t_name; + UINT t_state; + ULONG t_run_count; + UINT t_priority; + UINT preemption_threshold; + ULONG time_slice; + TX_THREAD *next_thread; + TX_THREAD *next_suspended; - while (1) - { - nucleo_led_toggle(); - blink_counter++; - tx_thread_sleep(TX_TIMER_TICKS_PER_SECOND / 2); /* Sleep 500ms */ + UINT status = tx_thread_info_get( + thread, &t_name, &t_state, &t_run_count, &t_priority, + &preemption_threshold, &time_slice, &next_thread, &next_suspended); + if (status == TX_SUCCESS) { + system_stats.threads[i].name = t_name; + system_stats.threads[i].state = t_state; + system_stats.threads[i].run_count = t_run_count; + system_stats.threads[i].priority = t_priority; + + /* Scan stack from bottom (tx_thread_stack_start) upward to find first + * non-0xEF byte */ + ULONG *stack_lowest = (ULONG *)thread->tx_thread_stack_start; + ULONG *stack_highest = (ULONG *)thread->tx_thread_stack_end; + ULONG fill_value = 0xEFEFEFEFUL; + while (stack_lowest <= stack_highest) { + if (*stack_lowest != fill_value) { + break; + } + stack_lowest++; + } + ULONG unused = + (ULONG)stack_lowest - (ULONG)thread->tx_thread_stack_start; + system_stats.threads[i].stack_used = + thread->tx_thread_stack_size - unused; + system_stats.threads[i].stack_size = thread->tx_thread_stack_size; + } + } + } + system_stats.thread_count = MAX_THREADS; + + tx_thread_sleep(TX_TIMER_TICKS_PER_SECOND / 10); /* Run at 10 Hz (100ms) */ + } +} + +/* Reporter Thread: Consumer/Printer of statistics */ +static void reporter_thread_entry(ULONG parameter) { + (void)parameter; + + printf("\r\n==========================================\r\n"); + printf("NUCLEO-F401RE Device Monitor Demo\r\n"); + printf("Third-party licensing info in NOTICE.md\r\n"); + printf("==========================================\r\n"); + + while (1) { + reporter_counter++; + + printf("\r\nSystem Status:\r\n"); + printf("------------------------------------------\r\n"); + printf("Uptime: %lu s\r\n", system_stats.uptime); + printf("Byte Pool Size: %lu bytes\r\n", system_stats.byte_pool_total); + printf("Allocated Memory: %lu bytes\r\n", system_stats.byte_pool_used); + printf("Free Memory: %lu bytes\r\n", system_stats.byte_pool_free); + printf("------------------------------------------\r\n"); + + printf("\r\n%-16s %-8s %-10s %-12s %-22s\r\n", "Thread Name", "Priority", + "State", "Run Count", "Stack Peak (Max / Size)"); + printf("-------------------------------------------------------------------" + "---------\r\n"); + for (UINT i = 0; i < system_stats.thread_count; i++) { + if (system_stats.threads[i].name != NULL) { + ULONG pct = 0; + if (system_stats.threads[i].stack_size > 0) { + pct = (system_stats.threads[i].stack_used * 100) / + system_stats.threads[i].stack_size; + } + printf("%-16s %-8u %-10s %-12lu %4lu / %4lu bytes (%lu%%)\r\n", + system_stats.threads[i].name, system_stats.threads[i].priority, + get_state_string(system_stats.threads[i].state), + system_stats.threads[i].run_count, + system_stats.threads[i].stack_used, + system_stats.threads[i].stack_size, pct); + } } + printf("-------------------------------------------------------------------" + "---------\r\n"); + + printf("Runs: Monitor: %lu | Reporter: %lu | Blink: %lu | Timer Wakes: %lu\r\n", + monitor_counter, reporter_counter, blink_counter, timer_counter); + printf("RTOS Showcase: Mutex Locks: %lu/%lu | Queue Msgs: %lu | Event Wakes: %lu | Sema Wakes: %lu\r\n", + mutex_acquires_1, mutex_acquires_2, queue_msgs_received, event_flags_processed, semaphore_wakes); + + tx_thread_sleep(TX_TIMER_TICKS_PER_SECOND * 2); /* Report every 2 seconds */ + } } -static void worker_thread_entry(ULONG parameter) -{ - (void)parameter; +static void blink_thread_entry(ULONG parameter) { + (void)parameter; + + while (1) { + nucleo_led_toggle(); + blink_counter++; + /* Toggle Event Flag bit 0 when LED toggles */ + tx_event_flags_set(&event_flags, 0x01, TX_OR); + /* Signal Counting Semaphore */ + tx_semaphore_put(&sensor_semaphore); + tx_thread_sleep(TX_TIMER_TICKS_PER_SECOND / 2); /* Sleep 500ms */ + } +} - while (1) - { - /* Simulate simple cooperative workload */ - worker_counter++; - tx_thread_sleep(TX_TIMER_TICKS_PER_SECOND / 5); /* Sleep 200ms */ +static void event_thread_entry(ULONG parameter) { + (void)parameter; + ULONG actual_flags; + + while (1) { + /* Wait for event flag bit 0 to be set by blink_thread */ + UINT status = tx_event_flags_get(&event_flags, 0x01, TX_AND_CLEAR, + &actual_flags, TX_WAIT_FOREVER); + if (status == TX_SUCCESS) { + event_flags_processed++; } + } } -static void reporter_thread_entry(ULONG parameter) -{ - (void)parameter; +static void semaphore_thread_entry(ULONG parameter) { + (void)parameter; - printf("\r\n==========================================\r\n"); - printf("Nucleo F401RE ThreadX Multithreading Demo\r\n"); - printf("==========================================\r\n"); + while (1) { + /* Block on counting semaphore */ + if (tx_semaphore_get(&sensor_semaphore, TX_WAIT_FOREVER) == TX_SUCCESS) { + semaphore_wakes++; + } + } +} - while (1) - { - reporter_counter++; - - /* Calculate system uptime in seconds */ - ULONG uptime_seconds = tx_time_get() / TX_TIMER_TICKS_PER_SECOND; +static void app_timer_callback(ULONG input) { + (void)input; + timer_counter++; +} - printf("[Reporter] Uptime: %lu s | Blink Thread: %lu runs | Worker Thread: %lu runs | Reporter: %lu runs\r\n", - uptime_seconds, blink_counter, worker_counter, reporter_counter); +static void mutex_thread_1_entry(ULONG parameter) { + (void)parameter; - tx_thread_sleep(TX_TIMER_TICKS_PER_SECOND * 2); /* Report every 2 seconds */ + while (1) { + /* Compete for SPI Mutex */ + if (tx_mutex_get(&spi_mutex, TX_WAIT_FOREVER) == TX_SUCCESS) { + mutex_acquires_1++; + tx_thread_sleep(5); /* Simulate SPI usage (50ms) */ + tx_mutex_put(&spi_mutex); } + tx_thread_sleep(5); /* Give Mutex Thread 2 a chance (50ms) */ + } } -void tx_application_define(void* first_unused_memory) -{ - (void)first_unused_memory; - UINT status; +static void mutex_thread_2_entry(ULONG parameter) { + (void)parameter; + + while (1) { + /* Compete for SPI Mutex */ + if (tx_mutex_get(&spi_mutex, TX_WAIT_FOREVER) == TX_SUCCESS) { + mutex_acquires_2++; + tx_thread_sleep(5); /* Simulate SPI usage (50ms) */ + tx_mutex_put(&spi_mutex); + } + tx_thread_sleep(5); /* Give Mutex Thread 1 a chance (50ms) */ + } +} - /* Create Blink Thread */ +static void queue_sender_entry(ULONG parameter) { + (void)parameter; + ULONG msg_val = 0; + + while (1) { + msg_val++; + SensorData *data_ptr; + /* Allocate block from fixed-size block pool */ + if (tx_block_allocate(&sensor_block_pool, (VOID **)&data_ptr, TX_NO_WAIT) == TX_SUCCESS) { + data_ptr->timestamp = tx_time_get(); + data_ptr->reading_id = msg_val; + data_ptr->data_value = msg_val * 42; + + /* Send pointer containing SensorData */ + if (tx_queue_send(&msg_queue, &data_ptr, TX_NO_WAIT) != TX_SUCCESS) { + /* Release block if queue was full to prevent leak */ + tx_block_release(data_ptr); + } + } + tx_thread_sleep(TX_TIMER_TICKS_PER_SECOND / 5); /* Send every 200ms */ + } +} + +static void queue_receiver_entry(ULONG parameter) { + (void)parameter; + SensorData *rx_data_ptr; + + while (1) { + /* Block on queue waiting for messages */ + UINT status = tx_queue_receive(&msg_queue, &rx_data_ptr, TX_WAIT_FOREVER); + if (status == TX_SUCCESS) { + queue_msgs_received++; + /* Release block back to block pool */ + tx_block_release(rx_data_ptr); + } + } +} + +void tx_application_define(void *first_unused_memory) { + UINT status; + CHAR *stack_ptr; + ULONG pool_size; + + /* Calculate available RAM for the byte pool, leaving 4KB margin for system + * stack at the top (0x20018000) */ + pool_size = (0x20018000 - 4096) - (ULONG)first_unused_memory; + + /* Initialize the byte pool */ + status = tx_byte_pool_create(&byte_pool, "system byte pool", + first_unused_memory, pool_size); + if (status != TX_SUCCESS) { + printf("Byte pool create failed: 0x%08x\r\n", status); + return; + } + + /* Create Mutex */ + status = tx_mutex_create(&spi_mutex, "SPI Mutex", TX_NO_INHERIT); + if (status != TX_SUCCESS) { + printf("Mutex create failed: 0x%08x\r\n", status); + return; + } + + /* Create Event Flags Group */ + status = tx_event_flags_create(&event_flags, "Event Flags"); + if (status != TX_SUCCESS) { + printf("Event flags create failed: 0x%08x\r\n", status); + return; + } + + /* Create Counting Semaphore */ + status = tx_semaphore_create(&sensor_semaphore, "Sensor Semaphore", 0); + if (status != TX_SUCCESS) { + printf("Semaphore create failed: 0x%08x\r\n", status); + return; + } + + /* Create Application Timer */ + status = tx_timer_create(&app_timer, "App Timer", app_timer_callback, 0, + TX_TIMER_TICKS_PER_SECOND, TX_TIMER_TICKS_PER_SECOND, + TX_AUTO_START); + if (status != TX_SUCCESS) { + printf("Timer create failed: 0x%08x\r\n", status); + return; + } + + /* Allocate Block Pool memory and create Block Pool */ + VOID *block_pool_ptr; + ULONG block_pool_size = 10 * (sizeof(SensorData) + sizeof(VOID *)) + 32; + status = tx_byte_allocate(&byte_pool, &block_pool_ptr, block_pool_size, TX_NO_WAIT); + if (status != TX_SUCCESS) { + printf("Block pool memory allocate failed: 0x%08x\r\n", status); + return; + } + status = tx_block_pool_create(&sensor_block_pool, "Sensor Block Pool", sizeof(SensorData), + block_pool_ptr, block_pool_size); + if (status != TX_SUCCESS) { + printf("Block pool create failed: 0x%08x\r\n", status); + return; + } + + /* Allocate Queue memory and create Queue (Stores 10 SensorData pointers) */ + VOID *queue_buffer_ptr; + status = tx_byte_allocate(&byte_pool, &queue_buffer_ptr, 10 * sizeof(ULONG), + TX_NO_WAIT); + if (status != TX_SUCCESS) { + printf("Queue memory allocate failed: 0x%08x\r\n", status); + return; + } + status = tx_queue_create(&msg_queue, "Msg Queue", TX_1_ULONG, + queue_buffer_ptr, 10 * sizeof(ULONG)); + if (status != TX_SUCCESS) { + printf("Queue create failed: 0x%08x\r\n", status); + return; + } + + /* Allocate stack and create Monitor Thread (Priority 9) */ + status = tx_byte_allocate(&byte_pool, (VOID **)&stack_ptr, THREAD_STACK_SIZE, + TX_NO_WAIT); + if (status == TX_SUCCESS) { status = tx_thread_create( - &blink_thread, - "blink thread", - blink_thread_entry, - 0, - blink_thread_stack, - sizeof(blink_thread_stack), - BLINK_THREAD_PRIORITY, - BLINK_THREAD_PRIORITY, - TX_NO_TIME_SLICE, - TX_AUTO_START); - - if (status != TX_SUCCESS) - { - printf("Blink thread create failed: 0x%08x\r\n", status); - } - - /* Create Worker Thread */ + &monitor_thread, "monitor thread", monitor_thread_entry, 0, stack_ptr, + THREAD_STACK_SIZE, 9, 9, TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) { + printf("Monitor thread create failed: 0x%08x\r\n", status); + } + } + + /* Allocate stack and create Reporter Thread (Priority 10) */ + status = tx_byte_allocate(&byte_pool, (VOID **)&stack_ptr, THREAD_STACK_SIZE, + TX_NO_WAIT); + if (status == TX_SUCCESS) { status = tx_thread_create( - &worker_thread, - "worker thread", - worker_thread_entry, - 0, - worker_thread_stack, - sizeof(worker_thread_stack), - WORKER_THREAD_PRIORITY, - WORKER_THREAD_PRIORITY, - TX_NO_TIME_SLICE, - TX_AUTO_START); - - if (status != TX_SUCCESS) - { - printf("Worker thread create failed: 0x%08x\r\n", status); - } - - /* Create Reporter Thread */ + &reporter_thread, "reporter thread", reporter_thread_entry, 0, + stack_ptr, THREAD_STACK_SIZE, 10, 10, TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) { + printf("Reporter thread create failed: 0x%08x\r\n", status); + } + } + + /* Allocate stack and create Blink Thread (Priority 11) */ + status = tx_byte_allocate(&byte_pool, (VOID **)&stack_ptr, THREAD_STACK_SIZE, + TX_NO_WAIT); + if (status == TX_SUCCESS) { + status = tx_thread_create(&blink_thread, "blink thread", blink_thread_entry, + 0, stack_ptr, THREAD_STACK_SIZE, 11, 11, + TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) { + printf("Blink thread create failed: 0x%08x\r\n", status); + } + } + + /* Allocate stack and create Event Thread (Priority 12) */ + status = tx_byte_allocate(&byte_pool, (VOID **)&stack_ptr, THREAD_STACK_SIZE, + TX_NO_WAIT); + if (status == TX_SUCCESS) { + status = tx_thread_create(&event_thread, "event thread", event_thread_entry, + 0, stack_ptr, THREAD_STACK_SIZE, 12, 12, + TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) { + printf("Event thread create failed: 0x%08x\r\n", status); + } + } + + /* Allocate stack and create Semaphore Thread (Priority 12) */ + status = tx_byte_allocate(&byte_pool, (VOID **)&stack_ptr, THREAD_STACK_SIZE, + TX_NO_WAIT); + if (status == TX_SUCCESS) { + status = tx_thread_create(&semaphore_thread, "semaphore thread", semaphore_thread_entry, + 0, stack_ptr, THREAD_STACK_SIZE, 12, 12, + TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) { + printf("Semaphore thread create failed: 0x%08x\r\n", status); + } + } + + /* Allocate stack and create Mutex Thread 1 (Priority 13) */ + status = tx_byte_allocate(&byte_pool, (VOID **)&stack_ptr, THREAD_STACK_SIZE, + TX_NO_WAIT); + if (status == TX_SUCCESS) { status = tx_thread_create( - &reporter_thread, - "reporter thread", - reporter_thread_entry, - 0, - reporter_thread_stack, - sizeof(reporter_thread_stack), - REPORTER_THREAD_PRIORITY, - REPORTER_THREAD_PRIORITY, - TX_NO_TIME_SLICE, - TX_AUTO_START); - - if (status != TX_SUCCESS) - { - printf("Reporter thread create failed: 0x%08x\r\n", status); + &mutex_thread_1, "mutex thread 1", mutex_thread_1_entry, 0, stack_ptr, + THREAD_STACK_SIZE, 13, 13, TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) { + printf("Mutex thread 1 create failed: 0x%08x\r\n", status); } -} + } -int main(void) -{ - board_init(); - - /* Start the ThreadX kernel */ - tx_kernel_enter(); + /* Allocate stack and create Mutex Thread 2 (Priority 13) */ + status = tx_byte_allocate(&byte_pool, (VOID **)&stack_ptr, THREAD_STACK_SIZE, + TX_NO_WAIT); + if (status == TX_SUCCESS) { + status = tx_thread_create( + &mutex_thread_2, "mutex thread 2", mutex_thread_2_entry, 0, stack_ptr, + THREAD_STACK_SIZE, 13, 13, TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) { + printf("Mutex thread 2 create failed: 0x%08x\r\n", status); + } + } - while (1) - { + /* Allocate stack and create Queue Sender Thread (Priority 14) */ + status = tx_byte_allocate(&byte_pool, (VOID **)&stack_ptr, THREAD_STACK_SIZE, + TX_NO_WAIT); + if (status == TX_SUCCESS) { + status = tx_thread_create( + &queue_sender_thread, "queue sender", queue_sender_entry, 0, stack_ptr, + THREAD_STACK_SIZE, 14, 14, TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) { + printf("Queue sender create failed: 0x%08x\r\n", status); } + } + + /* Allocate stack and create Queue Receiver Thread (Priority 15) */ + status = tx_byte_allocate(&byte_pool, (VOID **)&stack_ptr, THREAD_STACK_SIZE, + TX_NO_WAIT); + if (status == TX_SUCCESS) { + status = tx_thread_create( + &queue_receiver_thread, "queue receiver", queue_receiver_entry, 0, + stack_ptr, THREAD_STACK_SIZE, 15, 15, TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) { + printf("Queue receiver create failed: 0x%08x\r\n", status); + } + } + + /* Save pointers to thread control blocks in the registry */ + thread_registry[0] = &monitor_thread; + thread_registry[1] = &reporter_thread; + thread_registry[2] = &blink_thread; + thread_registry[3] = &event_thread; + thread_registry[4] = &mutex_thread_1; + thread_registry[5] = &mutex_thread_2; + thread_registry[6] = &queue_sender_thread; + thread_registry[7] = &queue_receiver_thread; + thread_registry[8] = &semaphore_thread; +} + +int main(void) { + board_init(); + + /* Start the ThreadX kernel */ + tx_kernel_enter(); + + while (1) { + } } diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.c b/STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.c index ac15e216..4dd79c61 100644 --- a/STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.c +++ b/STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.c @@ -1,8 +1,13 @@ /* * 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 */ +// Some portions generated by Codex (GPT-5). #include "nucleo_bsp.h" diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.h b/STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.h index 08d77eab..14831f9d 100644 --- a/STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.h +++ b/STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.h @@ -1,6 +1,10 @@ /* * 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 */ From 71f059c0b7aa7f583a412b78599cde49c5efed6c Mon Sep 17 00:00:00 2001 From: Ali Eissa Date: Tue, 21 Jul 2026 19:33:07 +0400 Subject: [PATCH 04/20] Network-connected Environmental Station Demo (#44) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added an STM32F767ZI environmental station demo using ThreadX, FileX, NetX Duo, MQTT, and an HTS221 sensor with mock fallback. Included resilient telemetry queueing, local RAM-disk logging, DHCP/DNS handling, MQTT reconnection, and updated board support and documentation. --------- Signed-off-by: alieissa-commits Co-authored-by: Frédéric Desbiens Co-authored-by: Codex --- SECURITY.md | 38 +- .../STM32F767ZI-Nucleo/CMakeLists.txt | 11 +- .../STM32F767ZI-Nucleo/README.md | 88 +- .../STM32F767ZI-Nucleo/app/ansi_colors.h | 49 + .../STM32F767ZI-Nucleo/app/board_init.c | 62 +- .../STM32F767ZI-Nucleo/app/board_init.h | 5 + .../app/demos/network_station/CMakeLists.txt | 49 + .../app/demos/network_station/hts221_reg.c | 945 ++++++++++++++++++ .../app/demos/network_station/hts221_reg.h | 336 +++++++ .../app/demos/network_station/main.c | 693 +++++++++++++ .../app/demos/network_station/mock_sensor.c | 49 + .../app/demos/network_station/mqtt_config.h | 21 + .../app/demos/network_station/nx_user.h | 22 + .../app/demos/network_station/sensor.h | 40 + .../app/demos/network_station/sensor_driver.c | 241 +++++ .../app/demos/netx_echo/CMakeLists.txt | 1 + .../app/demos/netx_echo/main.c | 51 +- .../app/demos/threadx_basic/CMakeLists.txt | 1 + .../app/demos/threadx_basic/main.c | 11 +- .../app/stm32f7xx_hal_conf.h | 2 +- .../app/stm32f7xx_hal_msp.c | 45 + .../STM32F767ZI-Nucleo/scripts/fetch_sdk.ps1 | 1 + .../STM32F767ZI-Nucleo/scripts/fetch_sdk.sh | 1 + 23 files changed, 2667 insertions(+), 95 deletions(-) create mode 100644 STMicroelectronics/STM32F767ZI-Nucleo/app/ansi_colors.h create mode 100644 STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/CMakeLists.txt create mode 100644 STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/hts221_reg.c create mode 100644 STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/hts221_reg.h create mode 100644 STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/main.c create mode 100644 STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/mock_sensor.c create mode 100644 STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/mqtt_config.h create mode 100644 STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/nx_user.h create mode 100644 STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/sensor.h create mode 100644 STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/sensor_driver.c diff --git a/SECURITY.md b/SECURITY.md index f77818b2..79dfb729 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,21 +1,39 @@ # Security Policy -## Supported Versions +This Eclipse Foundation Project adheres to the [Eclipse Foundation Vulnerability Reporting Policy](https://www.eclipse.org/security/policy/). -For the time being, the contents of this repository are not in scope for quarterly releases. New versions will be published as needed to address bugs, vulnerabilities, or integrated updated third-party components. +## How To Report a Vulnerability -## Reporting a Vulnerability +If you think you have found a vulnerability in this repository, please report it to us through coordinated disclosure. -If you think you have found a vulnerability in Eclipse ThreadX or one of its companion components, you can report it using one of the following ways: +**Please do not report security vulnerabilities through public issues, discussions, or change requests.** -* Contact the [Eclipse Foundation Security Team](mailto:security@eclipse-foundation.org) -* [Report a Vulnerability](https://github.com/eclipse-threadx/threadx/security/advisories/new) +Instead, [report it privately here](https://github.com/eclipse-threadx/samplex/security/advisories/new) on GitHub You can find more information about reporting and disclosure at the [Eclipse Foundation Security page](https://www.eclipse.org/security/). -## Security Policy +Please include as much of the information listed below as you can to help us better understand and resolve the issue: + +* The type of issue (e.g., buffer overflow, SQL injection, or cross-site scripting) +* Affected version(s) +* Impact of the issue, including how an attacker might exploit the issue +* Step-by-step instructions to reproduce the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Full paths of source file(s) related to the manifestation of the issue +* Configuration required to reproduce the issue +* Log files that are related to this issue (if possible) +* Proof-of-concept or exploit code (if possible) + +This information will help us triage your report more quickly. + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| 6.5.x | :white_check_mark: | + +Eclipse ThreadX publishes a release every quarter. There are no long-term support branches or backports to older releases. -This project follows [Eclipse Foundation Vulnerability Reporting Policy](https://www.eclipse.org/security/policy/). +Normally, fixes for non-critical vulnerabilities will ship in a regularly scheduled quarterly release. If fixes for an urgent or critical vulnerability must ship quickly, then the project will publish a hotfix release of the affected component(s) without waiting for the next quarterly release. -## About this repository -This repository contains only sample code for learning and evaluation purposes. It is not part of the core Eclipse ThreadX release process. +You can learn more about the [project's release cadence in this blog post](https://blogs.eclipse.org/post/fr%C3%A9d%C3%A9ric-desbiens/eclipse-threadx-more-predictable-more-open). diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/CMakeLists.txt b/STMicroelectronics/STM32F767ZI-Nucleo/CMakeLists.txt index 1aac36be..af6b0e7d 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/CMakeLists.txt +++ b/STMicroelectronics/STM32F767ZI-Nucleo/CMakeLists.txt @@ -9,8 +9,9 @@ # Contributors: # Ali Eissa - 2026 version. -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) set(CMAKE_C_STANDARD 99) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Set the toolchain if not defined if(NOT CMAKE_TOOLCHAIN_FILE) @@ -33,7 +34,7 @@ set(STM32Cube_DIR "${CMAKE_CURRENT_LIST_DIR}/lib/stm32cubef7") # Find CMSIS and HAL driver packages find_package(CMSIS REQUIRED) -find_package(STM32HAL REQUIRED COMPONENTS cortex pwr rcc gpio uart dma eth) +find_package(STM32HAL REQUIRED COMPONENTS cortex pwr rcc gpio uart dma eth i2c) # Compile the STM32F7xx HAL Driver Library as an Object Library set(HAL_TARGET stm32cubef7) @@ -75,6 +76,10 @@ endif() set(THREADX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../libs/threadx") add_subdirectory(${THREADX_DIR} threadx) +# Compile FileX Filesystem from root shared libs submodule +set(FILEX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../libs/filex") +add_subdirectory(${FILEX_DIR} filex) + if(USE_NETXDUO) # Compile NetX Duo TCP/IP Stack from root shared libs submodule set(NXD_ENABLE_FILE_SERVERS OFF CACHE BOOL "Disable FileX dependency in NetX Duo" FORCE) @@ -137,7 +142,6 @@ if(USE_NETXDUO) STM32F767xx USE_HAL_DRIVER STM32F7 - STM32_ETH_HAL_LEGACY ) target_link_libraries(netx_stm32_driver PUBLIC @@ -148,4 +152,3 @@ endif() # 3. Add the active demo subdirectory to build the executable target add_subdirectory(app/demos/${ACTIVE_DEMO}) - diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/README.md b/STMicroelectronics/STM32F767ZI-Nucleo/README.md index 1f4c0c57..6d00171e 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/README.md +++ b/STMicroelectronics/STM32F767ZI-Nucleo/README.md @@ -1,6 +1,6 @@ # STM32F767ZI-Nucleo Board Enablement Demos -This directory contains the Board Support Package (BSP) static library (`board_bsp`) and build configurations for running the **Eclipse ThreadX RTOS** and **NetX Duo TCP/IP stack** on the **STMicroelectronics NUCLEO-F767ZI** evaluation board (ARM Cortex-M7). +This directory contains the Board Support Package (BSP) static library (`board_bsp`) and build configurations for running the **Eclipse ThreadX RTOS**, **FileX Embedded File System**, and **NetX Duo TCP/IP stack** on the **STMicroelectronics NUCLEO-F767ZI** evaluation board (ARM Cortex-M7). The project features a decoupled static BSP library that hides all low-level hardware initializations (clocks, GPIO, MPU, DMA descriptors, and interrupts) from the application code. @@ -13,6 +13,7 @@ Use the `ACTIVE_DEMO` CMake variable to select which demo to compile: | Demo Name | Description | Targets | | :--- | :--- | :--- | | **`netx_echo`** *(Default)* | Dynamic network state machine monitoring cable hot-plugging, DHCP IP configuration, and a TCP Echo Server listening on port 7. | ThreadX, NetX Duo | +| **`network_station`** | Complete Environmental Station demo polling temperature and humidity metrics, logging CSV records to a local FileX FAT RAM Disk, and publishing JSON telemetry to an MQTT broker. | ThreadX, FileX, NetX Duo | | **`threadx_basic`** | Multi-threaded RTOS demo showcasing thread scheduling, mechanical button debouncing, message queue logging, and interrupt-driven UART ring buffers. | ThreadX | --- @@ -25,10 +26,10 @@ Use the `ACTIVE_DEMO` CMake variable to select which demo to compile: * *Note: The MPU maps `128 KB` of SRAM2 (starting at `0x20060000`) as non-cacheable/non-bufferable for Ethernet DMA descriptors and the packet pool.* * **Virtual COM Port**: USART3 (PD8/PD9) connected to ST-LINK debugger (115,200 baud, 8N1) * **User Button**: PC13 (Blue button, Active High) -* **Board LEDs**: - * `LD1` (Green) - PB0 - * `LD2` (Blue) - PB7 - * `LD3` (Red) - PB14 +* **Board LEDs (VT100 State Indicators)**: + * `LD1` (Green) - PB0: Blinks to indicate ThreadX heartbeat. + * `LD2` (Blue) - PB7: ON when Ethernet link is up and IP address is resolved. + * `LD3` (Red) - PB14: Flashes when network is disconnected or MQTT broker is unreachable. --- @@ -37,7 +38,7 @@ Use the `ACTIVE_DEMO` CMake variable to select which demo to compile: Before building, ensure you have the following cross-compilation tools installed on your system PATH: * **ARM GNU Toolchain** (`arm-none-eabi-gcc`) -* **CMake** (version 3.5 or higher) +* **CMake** (version 3.10 or higher) * **Ninja** or **Make** * **Git** (for downloading SDK dependencies) @@ -46,7 +47,7 @@ Before building, ensure you have the following cross-compilation tools installed ## Quick Start Guide ### 1. Download SDK Dependencies -Run the driver fetcher script to clone official, stock STMicroelectronics HAL drivers and CMSIS files locally: +Run the driver fetcher script to clone official, stock STMicroelectronics HAL drivers, CMSIS files, and driver configurations locally: * **On Windows (PowerShell)**: ```powershell @@ -69,7 +70,16 @@ cmake -DACTIVE_DEMO=netx_echo -B build cmake --build build ``` -#### Option B: Build `threadx_basic` +#### Option B: Build `network_station` +```bash +# Configure CMake +cmake -DACTIVE_DEMO=network_station -B build + +# Compile +cmake --build build +``` + +#### Option C: Build `threadx_basic` ```bash # Configure CMake cmake -DACTIVE_DEMO=threadx_basic -B build @@ -92,38 +102,31 @@ The raw binary files will be generated in `build/app/demos//stm32f767 --- -### 2. How to Run & Verify the `netx_echo` Demo -1. **Set Up Serial Monitor**: Open your serial terminal program (e.g., VS Code Serial Monitor, PuTTY, or Tera Term) to the virtual ST-LINK COM Port at **115,200 baud, 8N1**. -2. **Boot Unplugged**: Reset the board with the Ethernet cable disconnected. You should see the following log confirming the BSP initialization completed successfully and the network monitor is polling: - ```text - ========================================== - NetX Echo Demo Booted! - ========================================== - [HAL] Calling HAL_ETH_Init... - [HAL] HAL_ETH_Init returned status: 0 - [NetX] Initializing PHY transceiver... - [NetX] Waiting for Ethernet link (max 3s)... - [NetX] Ethernet link timeout! Cable connected? - [NetX] Packet pool created - [NetX] IP instance created - [NetX] Enabling ARP... - [NetX] Enabling TCP... - [NetX] Enabling UDP... - [NetX] Enabling ICMP... - [NetX] Creating DHCP Thread... - [NetX] tx_application_define completed - [NetX] Network Monitor Thread Started. - ``` -3. **Connect Cable**: Plug in your network Ethernet cable. The console will report the connection, initiate DHCP, and spawn the TCP Echo Server: - ```text - [NetX] Ethernet cable connected! Enabling link... - [NetX] Ethernet link is UP! Starting DHCP client... - [NetX] DHCP Success! - [NetX] IP Address : - [NetX] Subnet Mask: 255.255.255.0 - [Echo] TCP Echo Server listening on port 7 - ``` -4. **Run the Simple Echo Test**: Open a terminal on your computer and run one of the included scripts: +### 2. How to Run & Verify the `network_station` Demo +1. **Set Up Serial Monitor**: Open your serial terminal program (e.g., VS Code Serial Monitor, PuTTY, or Tera Term) to the virtual ST-LINK COM Port at **115,200 baud, 8N1** (ANSI colored logging is enabled, VT100-compatible terminal recommended). +2. **Boot Logs**: You will see colored output detailing the startup steps: + * **[HAL]** initializing the Ethernet MAC layer. + * **[NetX]** setting up the packet pool, ARP cache, and link state. + * **[Sensor Thread]** probing the I2C bus (falling back to Mock Mode if HTS221 shield is absent). + * **[Logger Thread]** formatting and mounting the 32 KB virtual RAM disk. + * **[NetX]** enabling link, running DHCP client, and printing the resolved IP address. + * **[DNS]** resolving the IP address of the public MQTT broker. + * **[MQTT]** connecting to `test.mosquitto.org:1883` and beginning periodic JSON telemetry publishes. +3. **Outage/Disconnect Verification**: + * Pull the Ethernet cable. The console immediately prints warning codes and enters reconnect state (Red LED starts flashing). + * Local writes to `sensor_log.txt` continue unaffected. + * When `network_queue` fills up, the **Evict Oldest** circular policy discards the oldest unsent reading at the front to prioritize live data upon reconnection. +4. **Subscribe to Cloud Telemetry**: + * Open the [HiveMQ WebSocket Client](http://www.hivemq.com/demos/websocket-client/). + * Connect to host `test.mosquitto.org`, port `8081` (ensure **SSL checkbox is active**). + * Subscribe to the topic: `samplex/env_station/+/telemetry`. You will see the JSON environmental records arriving in real-time. + +--- + +### 3. How to Run & Verify the `netx_echo` Demo +1. Open your serial terminal program at **115,200 baud, 8N1**. +2. Connect the Ethernet cable and boot the board. +3. Once the Blue LED (`LD2`) turns ON, run the simple client script to test the TCP echo loop: * **On Windows (PowerShell)**: ```powershell powershell -ExecutionPolicy Bypass -File "app/demos/netx_echo/test_echo_simple.ps1" @@ -139,11 +142,10 @@ The raw binary files will be generated in `build/app/demos//stm32f767 Sending: 'Hello ThreadX NetX Echo!' Received: 'Hello ThreadX NetX Echo!' ``` -5. **Test Mid-Run Hot-Unplugging**: Disconnect the Ethernet cable. You will see `[NetX] Ethernet cable disconnected! Disabling link...` on the serial console, and the interface IP resets to `0.0.0.0`. Plug the cable back in, and it will re-acquire its configuration dynamically. --- -### 3. How to Run & Verify the `threadx_basic` Demo +### 4. How to Run & Verify the `threadx_basic` Demo 1. Open your serial terminal program at **115,200 baud, 8N1**. 2. Flash the `threadx_basic` binary to the board. 3. **Verify Heartbeat**: The Green LED (`LD1`) will blink continuously at `2 Hz` (250ms ON, 250ms OFF). @@ -198,6 +200,7 @@ target_compile_definitions(${PROJECT_NAME} target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../.. ) # Link with BSP, ThreadX, and optionally NetX Duo @@ -205,6 +208,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE board_bsp threadx + # filex # Uncomment if using filesystem # netxduo # Uncomment if using network # netx_stm32_driver # Uncomment if using network stm32cubef7 diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/ansi_colors.h b/STMicroelectronics/STM32F767ZI-Nucleo/app/ansi_colors.h new file mode 100644 index 00000000..c1bb61db --- /dev/null +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/ansi_colors.h @@ -0,0 +1,49 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#ifndef ANSI_COLORS_H +#define ANSI_COLORS_H + +/* ANSI Terminal Escape Codes for Colored Serial Output */ +#define ANSI_RESET "\x1b[0m" +#define ANSI_BOLD "\x1b[1m" + +/* Standard Primary Colors for Banners */ +#define ANSI_RED "\x1b[31m" +#define ANSI_GREEN "\x1b[32m" +#define ANSI_YELLOW "\x1b[33m" +#define ANSI_BLUE "\x1b[34m" +#define ANSI_MAGENTA "\x1b[35m" +#define ANSI_CYAN "\x1b[36m" +#define ANSI_WHITE "\x1b[37m" + +/* Subsystem Tags: Muted Slate Gray (256-color 243) to push them into visual background */ +#define TAG_SYSTEM "\x1b[38;5;243m[System]" +#define TAG_HAL "\x1b[38;5;243m[HAL]" +#define TAG_SENSOR "\x1b[38;5;243m[Sensor Thread]" +#define TAG_LOGGER "\x1b[38;5;243m[Logger Thread]" +#define TAG_NETWORK "\x1b[38;5;243m[NetX]" +#define TAG_NET_THREAD "\x1b[38;5;243m[Network Thread]" +#define TAG_DNS "\x1b[38;5;243m[DNS]" +#define TAG_MQTT "\x1b[38;5;243m[MQTT]" +#define TAG_STATUS "\x1b[38;5;243m[Status Thread]" +#define TAG_ECHO "\x1b[38;5;243m[Echo]" + +/* Message Colors: Soft, pastel feedback colors */ +#define MSG_INFO "\x1b[38;5;250m" /* Soft White/Gray for normal logs */ +#define MSG_SUCCESS "\x1b[38;5;114m" /* Soft Pastel Green for success */ +#define MSG_WARNING "\x1b[38;5;215m" /* Muted Gold/Orange for warnings */ +#define MSG_ERROR "\x1b[38;5;203m" /* Muted Coral/Red for failures */ +#define MSG_METRIC "\x1b[38;5;111m" /* Soft Sky Blue for data/measurements */ + +#endif /* ANSI_COLORS_H */ diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/board_init.c b/STMicroelectronics/STM32F767ZI-Nucleo/app/board_init.c index 53efb8a2..c67df4e6 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/app/board_init.c +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/board_init.c @@ -16,6 +16,7 @@ #include "tx_api.h" #include #include +#include "ansi_colors.h" /* Global UART handler */ UART_HandleTypeDef huart3; @@ -53,6 +54,9 @@ void board_init(void) /* Initialize USART3 console */ MX_USART3_UART_Init(); + + /* Initialize I2C1 for environmental sensors */ + board_i2c_init(); } /** @@ -261,19 +265,26 @@ void board_ethernet_init(void) heth.Init.RxDesc = DMARxDscrTab; heth.Init.RxBuffLen = 1524; - printf("[HAL] Calling HAL_ETH_Init...\r\n"); + printf(TAG_HAL " " MSG_INFO "Calling HAL_ETH_Init...\r\n" ANSI_RESET); HAL_StatusTypeDef status = HAL_ETH_Init(&heth); - printf("[HAL] HAL_ETH_Init returned status: %d\r\n", status); + if (status == HAL_OK) + { + printf(TAG_HAL " " MSG_SUCCESS "HAL_ETH_Init succeeded (status: %d)\r\n" ANSI_RESET, status); + } + else + { + printf(TAG_HAL " " MSG_ERROR "HAL_ETH_Init failed (status: %d)\r\n" ANSI_RESET, status); + } /* Initialize the PHY transceiver and wait for the link to be established. This ensures that when NetX Duo enables the interface during startup, the hardware link is already up, avoiding driver initialization failures. */ extern int32_t nx_eth_phy_init(void); extern int32_t nx_eth_phy_get_link_state(void); - printf("[NetX] Initializing PHY transceiver...\r\n"); + printf(TAG_NETWORK " " MSG_INFO "Initializing PHY transceiver...\r\n" ANSI_RESET); if (nx_eth_phy_init() == 0) { - printf("[NetX] Waiting for Ethernet link (max 3s)...\r\n"); + printf(TAG_NETWORK " " MSG_WARNING "Waiting for Ethernet link (max 3s)...\r\n" ANSI_RESET); uint32_t retries = 300; /* 300 * 10ms = 3 seconds */ while (nx_eth_phy_get_link_state() <= 1) { @@ -281,13 +292,13 @@ void board_ethernet_init(void) retries--; if (retries == 0) { - printf("[NetX] Ethernet link timeout! Cable connected?\r\n"); + printf(TAG_NETWORK " " MSG_ERROR "Ethernet link timeout! Cable connected?\r\n" ANSI_RESET); break; } } if (nx_eth_phy_get_link_state() > 1) { - printf("[NetX] Ethernet link up!\r\n"); + printf(TAG_NETWORK " " MSG_SUCCESS "Ethernet link up!\r\n" ANSI_RESET); } } else @@ -300,10 +311,11 @@ void board_ethernet_init(void) both before and after the ThreadX scheduler starts. */ uint32_t HAL_GetTick(void) { - /* If the ThreadX scheduler is running, use the ThreadX time */ + /* If the ThreadX scheduler is running, use the ThreadX time converted to milliseconds. + Perform intermediate multiplication in 64-bit space to prevent early integer overflow. */ if (tx_thread_identify() != TX_NULL) { - return (uint32_t)tx_time_get(); + return (uint32_t)(((uint64_t)tx_time_get() * 1000) / TX_TIMER_TICKS_PER_SECOND); } else { @@ -324,3 +336,37 @@ uint32_t HAL_GetTick(void) return ms_ticks; } } + +/* Global I2C handler */ +I2C_HandleTypeDef hi2c1; + +void board_i2c_init(void) +{ + hi2c1.Instance = I2C1; + hi2c1.Init.Timing = 0x20404768; /* 100 kHz standard mode timing value at 54 MHz I2C clock */ + hi2c1.Init.OwnAddress1 = 0; + hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + hi2c1.Init.OwnAddress2 = 0; + hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK; + hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + + if (HAL_I2C_Init(&hi2c1) != HAL_OK) + { + Error_Handler(); + } + + /* Configure Analogue filter */ + if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK) + { + Error_Handler(); + } + + /* Configure Digital filter */ + if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK) + { + Error_Handler(); + } +} + diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/board_init.h b/STMicroelectronics/STM32F767ZI-Nucleo/app/board_init.h index 7cb42fe0..64a9728a 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/app/board_init.h +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/board_init.h @@ -39,8 +39,13 @@ extern UART_HandleTypeDef huart3; /* Global Ethernet handle */ extern ETH_HandleTypeDef heth; +/* Global I2C handle */ +extern I2C_HandleTypeDef hi2c1; + /* Define prototypes. */ void board_init(void); void board_ethernet_init(void); +void board_i2c_init(void); + #endif // _BOARD_INIT_H diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/CMakeLists.txt b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/CMakeLists.txt new file mode 100644 index 00000000..1b57b7d6 --- /dev/null +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/CMakeLists.txt @@ -0,0 +1,49 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +add_executable(${PROJECT_NAME} + main.c + sensor_driver.c + mock_sensor.c + hts221_reg.c +) + +# Set compile definitions for our executable +target_compile_definitions(${PROJECT_NAME} + PRIVATE + STM32F767xx + USE_HAL_DRIVER + STM32F7 +) + +# Include paths for the executable target +target_include_directories(${PROJECT_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../.. +) + +# Link libraries +target_link_libraries(${PROJECT_NAME} + PRIVATE + board_bsp + threadx + filex + netxduo + netx_stm32_driver + stm32cubef7 +) + +# Apply GCC linker script and print memory usage (utilities.cmake function) +set_target_linker(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/STM32F767ZITx_FLASH.ld") + +# Post-build commands to generate raw .bin and .hex files +post_build(${PROJECT_NAME}) diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/hts221_reg.c b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/hts221_reg.c new file mode 100644 index 00000000..88656cc3 --- /dev/null +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/hts221_reg.c @@ -0,0 +1,945 @@ +/* + ****************************************************************************** + * @file hts221_reg.c + * @author Sensors Software Solution Team + * @brief HTS221 driver file + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +#include "hts221_reg.h" + +/** + * @defgroup HTS221 + * @brief This file provides a set of functions needed to drive the + * hts221 enhanced inertial module. + * @{ + * + */ + +/** + * @defgroup HTS221_interfaces_functions + * @brief This section provide a set of functions used to read and write + * a generic register of the device. + * @{ + * + */ + +/** + * @brief Read generic device register + * + * @param ctx read / write interface definitions(ptr) + * @param reg register to read + * @param data pointer to buffer that store the data read(ptr) + * @param len number of consecutive register to read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_read_reg(stmdev_ctx_t* ctx, uint8_t reg, uint8_t* data, + uint16_t len) +{ + int32_t ret; + ret = ctx->read_reg(ctx->handle, reg, data, len); + return ret; +} + +/** + * @brief Write generic device register + * + * @param ctx read / write interface definitions(ptr) + * @param reg register to write + * @param data pointer to data to write in register reg(ptr) + * @param len number of consecutive register to write + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_write_reg(stmdev_ctx_t* ctx, uint8_t reg, uint8_t* data, + uint16_t len) +{ + int32_t ret; + ret = ctx->write_reg(ctx->handle, reg, data, len); + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup HTS221_Data_Generation + * @brief This section group all the functions concerning data generation + * @{ + * + */ + +/** + * @brief The numbers of averaged humidity samples.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of avgh in reg AV_CONF + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_humidity_avg_set(stmdev_ctx_t *ctx, hts221_avgh_t val) +{ + hts221_av_conf_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_AV_CONF, (uint8_t*) ®, 1); + + if(ret == 0){ + reg.avgh = (uint8_t)val; + ret = hts221_write_reg(ctx, HTS221_AV_CONF, (uint8_t*) ®, 1); + } + + return ret; +} + +/** + * @brief The numbers of averaged humidity samples.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of avgh in reg AV_CONF + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_humidity_avg_get(stmdev_ctx_t *ctx, hts221_avgh_t *val) +{ + hts221_av_conf_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_AV_CONF, (uint8_t*) ®, 1); + + switch (reg.avgh) { + case HTS221_H_AVG_4: + *val = HTS221_H_AVG_4; + break; + case HTS221_H_AVG_8: + *val = HTS221_H_AVG_8; + break; + case HTS221_H_AVG_16: + *val = HTS221_H_AVG_16; + break; + case HTS221_H_AVG_32: + *val = HTS221_H_AVG_32; + break; + case HTS221_H_AVG_64: + *val = HTS221_H_AVG_64; + break; + case HTS221_H_AVG_128: + *val = HTS221_H_AVG_128; + break; + case HTS221_H_AVG_256: + *val = HTS221_H_AVG_256; + break; + case HTS221_H_AVG_512: + *val = HTS221_H_AVG_512; + break; + default: + *val = HTS221_H_AVG_ND; + break; + } + + return ret; +} + +/** + * @brief The numbers of averaged temperature samples.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of avgt in reg AV_CONF + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_temperature_avg_set(stmdev_ctx_t *ctx, hts221_avgt_t val) +{ + hts221_av_conf_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_AV_CONF, (uint8_t*) ®, 1); + + if(ret == 0){ + reg.avgt = (uint8_t)val; + ret = hts221_write_reg(ctx, HTS221_AV_CONF, (uint8_t*) ®, 1); + } + + return ret; +} + +/** + * @brief The numbers of averaged temperature samples.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of avgt in reg AV_CONF + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_temperature_avg_get(stmdev_ctx_t *ctx, hts221_avgt_t *val) +{ + hts221_av_conf_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_AV_CONF, (uint8_t*) ®, 1); + + switch (reg.avgh) { + case HTS221_T_AVG_2: + *val = HTS221_T_AVG_2; + break; + case HTS221_T_AVG_4: + *val = HTS221_T_AVG_4; + break; + case HTS221_T_AVG_8: + *val = HTS221_T_AVG_8; + break; + case HTS221_T_AVG_16: + *val = HTS221_T_AVG_16; + break; + case HTS221_T_AVG_32: + *val = HTS221_T_AVG_32; + break; + case HTS221_T_AVG_64: + *val = HTS221_T_AVG_64; + break; + case HTS221_T_AVG_128: + *val = HTS221_T_AVG_128; + break; + case HTS221_T_AVG_256: + *val = HTS221_T_AVG_256; + break; + default: + *val = HTS221_T_AVG_ND; + break; + } + + return ret; +} + +/** + * @brief Output data rate selection.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of odr in reg CTRL_REG1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_data_rate_set(stmdev_ctx_t *ctx, hts221_odr_t val) +{ + hts221_ctrl_reg1_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_CTRL_REG1, (uint8_t*) ®, 1); + + if(ret == 0){ + reg.odr = (uint8_t)val; + ret = hts221_write_reg(ctx, HTS221_CTRL_REG1, (uint8_t*) ®, 1); + } + + return ret; +} + +/** + * @brief Output data rate selection.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of odr in reg CTRL_REG1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_data_rate_get(stmdev_ctx_t *ctx, hts221_odr_t *val) +{ + hts221_ctrl_reg1_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_CTRL_REG1, (uint8_t*) ®, 1); + + switch (reg.odr) { + case HTS221_ONE_SHOT: + *val = HTS221_ONE_SHOT; + break; + case HTS221_ODR_1Hz: + *val = HTS221_ODR_1Hz; + break; + case HTS221_ODR_7Hz: + *val = HTS221_ODR_7Hz; + break; + case HTS221_ODR_12Hz5: + *val = HTS221_ODR_12Hz5; + break; + default: + *val = HTS221_ODR_ND; + break; + } + + return ret; +} + +/** + * @brief Block data update.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of bdu in reg CTRL_REG1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_block_data_update_set(stmdev_ctx_t *ctx, uint8_t val) +{ + hts221_ctrl_reg1_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_CTRL_REG1, (uint8_t*) ®, 1); + + if(ret == 0){ + reg.bdu = val; + ret = hts221_write_reg(ctx, HTS221_CTRL_REG1, (uint8_t*) ®, 1); + } + + return ret; +} + +/** + * @brief Block data update.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of bdu in reg CTRL_REG1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_block_data_update_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + hts221_ctrl_reg1_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_CTRL_REG1, (uint8_t*) ®, 1); + *val = reg.bdu; + + return ret; +} + +/** + * @brief One-shot mode. Device perform a single measure.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of one_shot in reg CTRL_REG2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_one_shoot_trigger_set(stmdev_ctx_t *ctx, uint8_t val) +{ + hts221_ctrl_reg2_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_CTRL_REG2, (uint8_t*) ®, 1); + + if(ret == 0){ + reg.one_shot = val; + ret = hts221_write_reg(ctx, HTS221_CTRL_REG2, (uint8_t*) ®, 1); + } + + return ret; +} + +/** + * @brief One-shot mode. Device perform a single measure.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of one_shot in reg CTRL_REG2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_one_shoot_trigger_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + hts221_ctrl_reg2_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_CTRL_REG2, (uint8_t*) ®, 1); + *val = reg.one_shot; + + return ret; +} + +/** + * @brief Temperature data available.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of t_da in reg STATUS_REG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_temp_data_ready_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + hts221_status_reg_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_STATUS_REG, (uint8_t*) ®, 1); + *val = reg.t_da; + + return ret; +} + +/** + * @brief Humidity data available.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of h_da in reg STATUS_REG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_hum_data_ready_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + hts221_status_reg_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_STATUS_REG, (uint8_t*) ®, 1); + *val = reg.h_da; + + return ret; +} + +/** + * @brief Humidity output value[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_humidity_raw_get(stmdev_ctx_t *ctx, uint8_t *buff) +{ + int32_t ret; + ret = hts221_read_reg(ctx, HTS221_HUMIDITY_OUT_L, buff, 2); + return ret; +} + +/** + * @brief Temperature output value[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_temperature_raw_get(stmdev_ctx_t *ctx, uint8_t *buff) +{ + int32_t ret; + ret = hts221_read_reg(ctx, HTS221_TEMP_OUT_L, buff, 2); + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup HTS221_common + * @brief This section group common usefull functions + * @{ + * + */ + +/** + * @brief Device Who amI.[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_device_id_get(stmdev_ctx_t *ctx, uint8_t *buff) +{ + int32_t ret; + ret = hts221_read_reg(ctx, HTS221_WHO_AM_I, buff, 1); + return ret; +} + +/** + * @brief Switch device on/off.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of pd in reg CTRL_REG1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_power_on_set(stmdev_ctx_t *ctx, uint8_t val) +{ + hts221_ctrl_reg1_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_CTRL_REG1, (uint8_t*) ®, 1); + + if(ret == 0){ + reg.pd = val; + ret = hts221_write_reg(ctx, HTS221_CTRL_REG1, (uint8_t*) ®, 1); + } + return ret; +} + +/** + * @brief Switch device on/off.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of pd in reg CTRL_REG1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_power_on_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + hts221_ctrl_reg1_t reg; + int32_t mm_error; + + mm_error = hts221_read_reg(ctx, HTS221_CTRL_REG1, (uint8_t*) ®, 1); + *val = reg.pd; + + return mm_error; +} + +/** + * @brief Heater enable / disable.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of heater in reg CTRL_REG2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_heater_set(stmdev_ctx_t *ctx, uint8_t val) +{ + hts221_ctrl_reg2_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_CTRL_REG2, (uint8_t*) ®, 1); + + if(ret == 0){ + reg.heater = val; + ret = hts221_write_reg(ctx, HTS221_CTRL_REG2, (uint8_t*) ®, 1); + } + + return ret; +} + +/** + * @brief Heater enable / disable.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of heater in reg CTRL_REG2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_heater_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + hts221_ctrl_reg2_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_CTRL_REG2, (uint8_t*) ®, 1); + *val = reg.heater; + + return ret; +} + +/** + * @brief Reboot memory content. Reload the calibration parameters.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of boot in reg CTRL_REG2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_boot_set(stmdev_ctx_t *ctx, uint8_t val) +{ + hts221_ctrl_reg2_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_CTRL_REG2, (uint8_t*) ®, 1); + + if(ret == 0){ + reg.boot = val; + ret = hts221_write_reg(ctx, HTS221_CTRL_REG2, (uint8_t*) ®, 1); + } + + return ret; +} + +/** + * @brief Reboot memory content. Reload the calibration parameters.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of boot in reg CTRL_REG2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_boot_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + hts221_ctrl_reg2_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_CTRL_REG2, (uint8_t*) ®, 1); + *val = reg.boot; + + return ret; +} + +/** + * @brief Info about device status.[get] + * + * @param ctx read / write interface definitions + * @param val Registers STATUS_REG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_status_get(stmdev_ctx_t *ctx, hts221_status_reg_t *val) +{ + int32_t ret; + ret = hts221_read_reg(ctx, HTS221_STATUS_REG, (uint8_t*) val, 1); + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup HTS221_interrupts + * @brief This section group all the functions that manage interrupts + * @{ + * + */ + +/** + * @brief Data-ready signal on INT_DRDY pin.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of drdy in reg CTRL_REG3 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_drdy_on_int_set(stmdev_ctx_t *ctx, uint8_t val) +{ + hts221_ctrl_reg3_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_CTRL_REG3, (uint8_t*) ®, 1); + + if(ret == 0){ + reg.drdy = val; + ret = hts221_write_reg(ctx, HTS221_CTRL_REG3, (uint8_t*) ®, 1); + } + + return ret; +} + +/** + * @brief Data-ready signal on INT_DRDY pin.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of drdy in reg CTRL_REG3 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_drdy_on_int_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + hts221_ctrl_reg3_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_CTRL_REG3, (uint8_t*) ®, 1); + *val = reg.drdy; + + return ret; +} + +/** + * @brief Push-pull/open drain selection on interrupt pads.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of pp_od in reg CTRL_REG3 + * + */ +int32_t hts221_pin_mode_set(stmdev_ctx_t *ctx, hts221_pp_od_t val) +{ + hts221_ctrl_reg3_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_CTRL_REG3, (uint8_t*) ®, 1); + + if(ret == 0){ + reg.pp_od = (uint8_t)val; + ret = hts221_write_reg(ctx, HTS221_CTRL_REG3, (uint8_t*) ®, 1); + } + + return ret; +} + +/** + * @brief Push-pull/open drain selection on interrupt pads.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of pp_od in reg CTRL_REG3 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_pin_mode_get(stmdev_ctx_t *ctx, hts221_pp_od_t *val) +{ + hts221_ctrl_reg3_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_CTRL_REG3, (uint8_t*) ®, 1); + + switch (reg.pp_od) { + case HTS221_PUSH_PULL: + *val = HTS221_PUSH_PULL; + break; + case HTS221_OPEN_DRAIN: + *val = HTS221_OPEN_DRAIN; + break; + default: + *val = HTS221_PIN_MODE_ND; + break; + } + + return ret; +} + +/** + * @brief Interrupt active-high/low.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of drdy_h_l in reg CTRL_REG3 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_int_polarity_set(stmdev_ctx_t *ctx, hts221_drdy_h_l_t val) +{ + hts221_ctrl_reg3_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_CTRL_REG3, (uint8_t*) ®, 1); + + if(ret == 0){ + reg.drdy_h_l = (uint8_t)val; + ret = hts221_write_reg(ctx, HTS221_CTRL_REG3, (uint8_t*) ®, 1); + } + + return ret; +} + +/** + * @brief Interrupt active-high/low.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of drdy_h_l in reg CTRL_REG3 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_int_polarity_get(stmdev_ctx_t *ctx, hts221_drdy_h_l_t *val) +{ + hts221_ctrl_reg3_t reg; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_CTRL_REG3, (uint8_t*) ®, 1); + + switch (reg.drdy_h_l) { + case HTS221_ACTIVE_HIGH: + *val = HTS221_ACTIVE_HIGH; + break; + case HTS221_ACTIVE_LOW: + *val = HTS221_ACTIVE_LOW; + break; + default: + *val = HTS221_ACTIVE_ND; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup HTS221_calibration + * @brief This section group all the calibration coefficients need + * for reading data + * @{ + * + */ + +/** + * @brief First calibration point for Rh Humidity.[get] + * + * @param ctx read / write interface definitions + * @param val buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_hum_rh_point_0_get(stmdev_ctx_t *ctx, float_t *val) +{ + uint8_t coeff; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_H0_RH_X2, &coeff, 1); + *val = coeff / 2.0f; + + return ret; +} + +/** + * @brief Second calibration point for Rh Humidity.[get] + * + * @param ctx read / write interface definitions + * @param val buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_hum_rh_point_1_get(stmdev_ctx_t *ctx, float_t *val) +{ + uint8_t coeff; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_H1_RH_X2, &coeff, 1); + *val = coeff / 2.0f; + + return ret; +} + +/** + * @brief First calibration point for degC temperature.[get] + * + * @param ctx read / write interface definitions + * @param val buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_temp_deg_point_0_get(stmdev_ctx_t *ctx, float_t *val) +{ + hts221_t1_t0_msb_t reg; + uint8_t coeff_h, coeff_l; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_T0_DEGC_X8, &coeff_l, 1); + + if(ret == 0){ + ret = hts221_read_reg(ctx, HTS221_T1_T0_MSB, (uint8_t*) ®, 1); + coeff_h = reg.t0_msb; + *val = ((coeff_h * 256) + coeff_l) / 8.0f; + } + + return ret; +} + +/** + * @brief Second calibration point for degC temperature.[get] + * + * @param ctx read / write interface definitions + * @param val buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_temp_deg_point_1_get(stmdev_ctx_t *ctx, float_t *val) +{ + hts221_t1_t0_msb_t reg; + uint8_t coeff_h, coeff_l; + int32_t ret; + + ret = hts221_read_reg(ctx, HTS221_T1_DEGC_X8, &coeff_l, 1); + + if(ret == 0){ + ret = hts221_read_reg(ctx, HTS221_T1_T0_MSB, (uint8_t*) ®, 1); + coeff_h = reg.t1_msb; + *val = ((coeff_h * 256) + coeff_l) / 8.0f; + } + + return ret; +} + +/** + * @brief First calibration point for humidity in LSB.[get] + * + * @param ctx read / write interface definitions + * @param val buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_hum_adc_point_0_get(stmdev_ctx_t *ctx, float_t *val) +{ + uint8_t coeff_p[2]; + int16_t coeff; + int32_t ret; + ret = hts221_read_reg(ctx, HTS221_H0_T0_OUT_L, coeff_p, 2); + coeff = (coeff_p[1] * 256) + coeff_p[0]; + *val = coeff * 1.0f; + return ret; +} + +/** + * @brief Second calibration point for humidity in LSB.[get] + * + * @param ctx read / write interface definitions + * @param val buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_hum_adc_point_1_get(stmdev_ctx_t *ctx, float_t *val) +{ + uint8_t coeff_p[2]; + int16_t coeff; + int32_t ret; + ret = hts221_read_reg(ctx, HTS221_H1_T0_OUT_L, coeff_p, 2); + coeff = (coeff_p[1] * 256) + coeff_p[0]; + *val = coeff * 1.0f; + return ret; +} + +/** + * @brief First calibration point for temperature in LSB.[get] + * + * @param ctx read / write interface definitions + * @param val buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_temp_adc_point_0_get(stmdev_ctx_t *ctx, float_t *val) +{ + uint8_t coeff_p[2]; + int16_t coeff; + int32_t ret; + ret = hts221_read_reg(ctx, HTS221_T0_OUT_L, coeff_p, 2); + coeff = (coeff_p[1] * 256) + coeff_p[0]; + *val = coeff * 1.0f; + return ret; +} + +/** + * @brief Second calibration point for temperature in LSB.[get] + * + * @param ctx read / write interface definitions + * @param val buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t hts221_temp_adc_point_1_get(stmdev_ctx_t *ctx, float_t *val) +{ + uint8_t coeff_p[2]; + int16_t coeff; + int32_t ret; + ret = hts221_read_reg(ctx, HTS221_T1_OUT_L, coeff_p, 2); + coeff = (coeff_p[1] * 256) + coeff_p[0]; + *val = coeff * 1.0f; + return ret; +} + +/** + * @} + * + */ diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/hts221_reg.h b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/hts221_reg.h new file mode 100644 index 00000000..95d1bf21 --- /dev/null +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/hts221_reg.h @@ -0,0 +1,336 @@ +/* + ****************************************************************************** + * @file hts221_reg.h + * @author Sensors Software Solution Team + * @brief This file contains all the functions prototypes for the + * hts221_reg.c driver. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef HTS221_REGS_H +#define HTS221_REGS_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include +#include + +/** @addtogroup HTS221 + * @{ + * + */ + +/** @defgroup STMicroelectronics sensors common types + * @{ + * + */ + +#ifndef MEMS_SHARED_TYPES +#define MEMS_SHARED_TYPES + +typedef struct{ + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +} bitwise_t; + +#define PROPERTY_DISABLE (0U) +#define PROPERTY_ENABLE (1U) + +/** @addtogroup Interfaces_Functions + * @brief This section provide a set of functions used to read and + * write a generic register of the device. + * MANDATORY: return 0 -> no Error. + * @{ + * + */ + +typedef int32_t (*stmdev_write_ptr)(void *, uint8_t, uint8_t*, uint16_t); +typedef int32_t (*stmdev_read_ptr) (void *, uint8_t, uint8_t*, uint16_t); + +typedef struct { + /** Component mandatory fields **/ + stmdev_write_ptr write_reg; + stmdev_read_ptr read_reg; + /** Customizable optional pointer **/ + void *handle; +} stmdev_ctx_t; + +/** + * @} + * + */ + +#endif /* MEMS_SHARED_TYPES */ + +#ifndef MEMS_UCF_SHARED_TYPES +#define MEMS_UCF_SHARED_TYPES + +/** @defgroup Generic address-data structure definition + * @brief This structure is useful to load a predefined configuration + * of a sensor. + * You can create a sensor configuration by your own or using + * Unico / Unicleo tools available on STMicroelectronics + * web site. + * + * @{ + * + */ + +typedef struct { + uint8_t address; + uint8_t data; +} ucf_line_t; + +/** + * @} + * + */ + +#endif /* MEMS_UCF_SHARED_TYPES */ + +/** + * @} + * + */ + +/** @defgroup HTS221_Infos + * @{ + * + */ + +/** I2C Device Address 8 bit format **/ +#define HTS221_I2C_ADDRESS 0xBFU + +/** Device Identification (Who am I) **/ +#define HTS221_ID 0xBCU + +/** + * @} + * + */ + +#define HTS221_WHO_AM_I 0x0FU +#define HTS221_AV_CONF 0x10U +typedef struct { + uint8_t avgh : 3; + uint8_t avgt : 3; + uint8_t not_used_01 : 2; +} hts221_av_conf_t; + +#define HTS221_CTRL_REG1 0x20U +typedef struct { + uint8_t odr : 2; + uint8_t bdu : 1; + uint8_t not_used_01 : 4; + uint8_t pd : 1; +} hts221_ctrl_reg1_t; + +#define HTS221_CTRL_REG2 0x21U +typedef struct { + uint8_t one_shot : 1; + uint8_t heater : 1; + uint8_t not_used_01 : 5; + uint8_t boot : 1; +} hts221_ctrl_reg2_t; + +#define HTS221_CTRL_REG3 0x22U +typedef struct { + uint8_t not_used_01 : 2; + uint8_t drdy : 1; + uint8_t not_used_02 : 3; + uint8_t pp_od : 1; + uint8_t drdy_h_l : 1; +} hts221_ctrl_reg3_t; + +#define HTS221_STATUS_REG 0x27U +typedef struct { + uint8_t t_da : 1; + uint8_t h_da : 1; + uint8_t not_used_01 : 6; +} hts221_status_reg_t; + +#define HTS221_HUMIDITY_OUT_L 0x28U +#define HTS221_HUMIDITY_OUT_H 0x29U +#define HTS221_TEMP_OUT_L 0x2AU +#define HTS221_TEMP_OUT_H 0x2BU +#define HTS221_H0_RH_X2 0x30U +#define HTS221_H1_RH_X2 0x31U +#define HTS221_T0_DEGC_X8 0x32U +#define HTS221_T1_DEGC_X8 0x33U +#define HTS221_T1_T0_MSB 0x35U +typedef struct { + uint8_t t0_msb : 2; + uint8_t t1_msb : 2; + uint8_t not_used_01 : 4; +} hts221_t1_t0_msb_t; + +#define HTS221_H0_T0_OUT_L 0x36U +#define HTS221_H0_T0_OUT_H 0x37U +#define HTS221_H1_T0_OUT_L 0x3AU +#define HTS221_H1_T0_OUT_H 0x3BU +#define HTS221_T0_OUT_L 0x3CU +#define HTS221_T0_OUT_H 0x3DU +#define HTS221_T1_OUT_L 0x3EU +#define HTS221_T1_OUT_H 0x3FU + +/** + * @defgroup HTS221_Register_Union + * @brief This union group all the registers that has a bitfield + * description. + * This union is useful but not need by the driver. + * + * REMOVING this union you are compliant with: + * MISRA-C 2012 [Rule 19.2] -> " Union are not allowed " + * + * @{ + * + */ +typedef union{ + hts221_av_conf_t av_conf; + hts221_ctrl_reg1_t ctrl_reg1; + hts221_ctrl_reg2_t ctrl_reg2; + hts221_ctrl_reg3_t ctrl_reg3; + hts221_status_reg_t status_reg; + hts221_t1_t0_msb_t t1_t0_msb; + bitwise_t bitwise; + uint8_t byte; +} hts221_reg_t; + +/** + * @} + * + */ + +int32_t hts221_read_reg(stmdev_ctx_t *ctx, uint8_t reg, uint8_t* data, + uint16_t len); +int32_t hts221_write_reg(stmdev_ctx_t *ctx, uint8_t reg, uint8_t* data, + uint16_t len); + +typedef enum { + HTS221_H_AVG_4 = 0, + HTS221_H_AVG_8 = 1, + HTS221_H_AVG_16 = 2, + HTS221_H_AVG_32 = 3, + HTS221_H_AVG_64 = 4, + HTS221_H_AVG_128 = 5, + HTS221_H_AVG_256 = 6, + HTS221_H_AVG_512 = 7, + HTS221_H_AVG_ND = 8, +} hts221_avgh_t; +int32_t hts221_humidity_avg_set(stmdev_ctx_t *ctx, hts221_avgh_t val); +int32_t hts221_humidity_avg_get(stmdev_ctx_t *ctx, hts221_avgh_t *val); + +typedef enum { + HTS221_T_AVG_2 = 0, + HTS221_T_AVG_4 = 1, + HTS221_T_AVG_8 = 2, + HTS221_T_AVG_16 = 3, + HTS221_T_AVG_32 = 4, + HTS221_T_AVG_64 = 5, + HTS221_T_AVG_128 = 6, + HTS221_T_AVG_256 = 7, + HTS221_T_AVG_ND = 8, +} hts221_avgt_t; +int32_t hts221_temperature_avg_set(stmdev_ctx_t *ctx, hts221_avgt_t val); +int32_t hts221_temperature_avg_get(stmdev_ctx_t *ctx, hts221_avgt_t *val); + +typedef enum { + HTS221_ONE_SHOT = 0, + HTS221_ODR_1Hz = 1, + HTS221_ODR_7Hz = 2, + HTS221_ODR_12Hz5 = 3, + HTS221_ODR_ND = 4, +} hts221_odr_t; +int32_t hts221_data_rate_set(stmdev_ctx_t *ctx, hts221_odr_t val); +int32_t hts221_data_rate_get(stmdev_ctx_t *ctx, hts221_odr_t *val); + +int32_t hts221_block_data_update_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t hts221_block_data_update_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t hts221_one_shoot_trigger_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t hts221_one_shoot_trigger_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t hts221_temp_data_ready_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t hts221_hum_data_ready_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t hts221_humidity_raw_get(stmdev_ctx_t *ctx, uint8_t *buff); + +int32_t hts221_temperature_raw_get(stmdev_ctx_t *ctx, uint8_t *buff); + +int32_t hts221_device_id_get(stmdev_ctx_t *ctx, uint8_t *buff); + +int32_t hts221_power_on_set(stmdev_ctx_t *ctx, uint8_t val); + +int32_t hts221_power_on_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t hts221_heater_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t hts221_heater_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t hts221_boot_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t hts221_boot_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t hts221_status_get(stmdev_ctx_t *ctx, hts221_status_reg_t *val); + +int32_t hts221_drdy_on_int_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t hts221_drdy_on_int_get(stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum { + HTS221_PUSH_PULL = 0, + HTS221_OPEN_DRAIN = 1, + HTS221_PIN_MODE_ND = 2, +} hts221_pp_od_t; +int32_t hts221_pin_mode_set(stmdev_ctx_t *ctx, hts221_pp_od_t val); +int32_t hts221_pin_mode_get(stmdev_ctx_t *ctx, hts221_pp_od_t *val); + +typedef enum { + HTS221_ACTIVE_HIGH = 0, + HTS221_ACTIVE_LOW = 1, + HTS221_ACTIVE_ND = 2, +} hts221_drdy_h_l_t; +int32_t hts221_int_polarity_set(stmdev_ctx_t *ctx, hts221_drdy_h_l_t val); +int32_t hts221_int_polarity_get(stmdev_ctx_t *ctx, hts221_drdy_h_l_t *val); + +int32_t hts221_hum_rh_point_0_get(stmdev_ctx_t *ctx, float_t *val); +int32_t hts221_hum_rh_point_1_get(stmdev_ctx_t *ctx, float_t *val); + +int32_t hts221_temp_deg_point_0_get(stmdev_ctx_t *ctx, float_t *val); +int32_t hts221_temp_deg_point_1_get(stmdev_ctx_t *ctx, float_t *val); + +int32_t hts221_hum_adc_point_0_get(stmdev_ctx_t *ctx, float_t *val); +int32_t hts221_hum_adc_point_1_get(stmdev_ctx_t *ctx, float_t *val); + +int32_t hts221_temp_adc_point_0_get(stmdev_ctx_t *ctx, float_t *val); +int32_t hts221_temp_adc_point_1_get(stmdev_ctx_t *ctx, float_t *val); + +/** + * @} + * + */ + +#ifdef __cplusplus +} +#endif + +#endif /*HTS221_REGS_H */ diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/main.c b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/main.c new file mode 100644 index 00000000..33eead44 --- /dev/null +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/main.c @@ -0,0 +1,693 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#include "tx_api.h" +#include "fx_api.h" +#include "nx_api.h" +#include "nxd_dhcp_client.h" +#include "nxd_dns.h" +#include "nxd_mqtt_client.h" +#include "board_init.h" +#include "sensor.h" +#include "mqtt_config.h" +#include +#include +#include "ansi_colors.h" + +#define DEMO_STACK_SIZE 2048 +#define DEMO_BYTE_POOL_SIZE 65536 /* Increased byte pool size to accommodate NetX Duo and ThreadX stacks */ +#define SENSOR_QUEUE_MAX_MSGS 10 +#define SENSOR_MSG_WORDS 3 /* 12 bytes = 3 ULONGs */ +#define RAM_DISK_SIZE 32768 /* 32 KB RAM Disk */ +#define RAM_DISK_SECTOR_SIZE 512 + +/* NetX Duo Configuration Constants */ +#define PACKET_SIZE 1536 +#define PACKET_POOL_SIZE (PACKET_SIZE * 20) +#define ARP_CACHE_SIZE 1024 + +/* ThreadX objects */ +TX_THREAD sensor_thread; +TX_THREAD logger_thread; +TX_THREAD network_thread; +TX_THREAD status_thread; +TX_THREAD dhcp_thread; + +TX_QUEUE sensor_queue; +TX_QUEUE network_queue; +TX_BYTE_POOL byte_pool_sensor; + +/* FileX objects */ +FX_MEDIA ram_disk; +FX_FILE log_file; + +/* NetX Duo objects */ +NX_PACKET_POOL pool_0; +NX_IP ip_0; +NX_DHCP dhcp_client; +NX_DNS dns_client; +NXD_MQTT_CLIENT mqtt_client; + +/* Connection States shared with Status Thread */ +static volatile UINT ip_resolved = NX_FALSE; +static volatile UINT mqtt_connected = NX_FALSE; +static char mqtt_topic[64]; + +/* Place the NetX Duo packet pool in the .nx_data section (uncacheable memory) */ +__attribute__((section(".NetXPoolSection"))) uint8_t packet_pool_area[PACKET_POOL_SIZE]; +static uint8_t arp_cache_area[ARP_CACHE_SIZE]; + +/* Memory area for byte pool */ +static uint8_t pool_memory[DEMO_BYTE_POOL_SIZE]; + +/* Statically allocated memory for RAM disk and sector cache */ +static uint8_t ram_disk_memory[RAM_DISK_SIZE]; +static uint8_t cache_buffer[RAM_DISK_SECTOR_SIZE]; + +/* External FileX and NetX driver prototypes */ +VOID _fx_ram_driver(FX_MEDIA *media_ptr); +extern VOID nx_stm32_eth_driver(NX_IP_DRIVER *driver_req_ptr); + +/* Thread entry prototypes */ +static void sensor_thread_entry(ULONG thread_input); +static void logger_thread_entry(ULONG thread_input); +static void network_thread_entry(ULONG thread_input); +static void status_thread_entry(ULONG thread_input); +static void dhcp_thread_entry(ULONG thread_input); + +int main(void) +{ + /* Initialize Board Support Package (BSP) - clock, GPIO, UART, I2C, etc. */ + board_init(); + + printf(ANSI_BOLD ANSI_CYAN "\r\n==================================================\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN " Network Environmental Station Demo \r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN "==================================================\r\n" ANSI_RESET); + + /* Initialize the Ethernet hardware, MAC, and wait for link to be established */ + board_ethernet_init(); + + /* Enter the ThreadX kernel */ + tx_kernel_enter(); + + return 0; +} + +void tx_application_define(void *first_unused_memory) +{ + CHAR *pointer; + (void)first_unused_memory; + + /* Create a byte memory pool from which to allocate the thread stacks and queues */ + if (tx_byte_pool_create(&byte_pool_sensor, "sensor_pool", pool_memory, DEMO_BYTE_POOL_SIZE) != TX_SUCCESS) + { + Error_Handler(); + } + + /* Allocate and create sensor message queue */ + if (tx_byte_allocate(&byte_pool_sensor, (VOID **) &pointer, + SENSOR_QUEUE_MAX_MSGS * SENSOR_MSG_WORDS * sizeof(ULONG), TX_NO_WAIT) != TX_SUCCESS) + { + Error_Handler(); + } + if (tx_queue_create(&sensor_queue, "sensor_queue", SENSOR_MSG_WORDS, pointer, + SENSOR_QUEUE_MAX_MSGS * SENSOR_MSG_WORDS * sizeof(ULONG)) != TX_SUCCESS) + { + Error_Handler(); + } + + /* Allocate and create network message queue */ + if (tx_byte_allocate(&byte_pool_sensor, (VOID **) &pointer, + SENSOR_QUEUE_MAX_MSGS * SENSOR_MSG_WORDS * sizeof(ULONG), TX_NO_WAIT) != TX_SUCCESS) + { + Error_Handler(); + } + if (tx_queue_create(&network_queue, "network_queue", SENSOR_MSG_WORDS, pointer, + SENSOR_QUEUE_MAX_MSGS * SENSOR_MSG_WORDS * sizeof(ULONG)) != TX_SUCCESS) + { + Error_Handler(); + } + + /* Allocate the stack for the sensor thread */ + if (tx_byte_allocate(&byte_pool_sensor, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT) != TX_SUCCESS) + { + Error_Handler(); + } + /* Create the sensor thread (Priority 3) */ + if (tx_thread_create(&sensor_thread, "sensor_thread", sensor_thread_entry, 0, + pointer, DEMO_STACK_SIZE, + 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START) != TX_SUCCESS) + { + Error_Handler(); + } + + /* Allocate the stack for the logger thread */ + if (tx_byte_allocate(&byte_pool_sensor, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT) != TX_SUCCESS) + { + Error_Handler(); + } + /* Create the logger thread (Priority 5) */ + if (tx_thread_create(&logger_thread, "logger_thread", logger_thread_entry, 0, + pointer, DEMO_STACK_SIZE, + 5, 5, TX_NO_TIME_SLICE, TX_AUTO_START) != TX_SUCCESS) + { + Error_Handler(); + } + + /* Allocate the stack for the network telemetry thread */ + if (tx_byte_allocate(&byte_pool_sensor, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT) != TX_SUCCESS) + { + Error_Handler(); + } + /* Create the network thread (Priority 4) */ + if (tx_thread_create(&network_thread, "network_thread", network_thread_entry, 0, + pointer, DEMO_STACK_SIZE, + 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START) != TX_SUCCESS) + { + Error_Handler(); + } + + /* Allocate the stack for the status monitor thread */ + if (tx_byte_allocate(&byte_pool_sensor, (VOID **) &pointer, 1024, TX_NO_WAIT) != TX_SUCCESS) + { + Error_Handler(); + } + /* Create the status thread (Priority 6) */ + if (tx_thread_create(&status_thread, "status_thread", status_thread_entry, 0, + pointer, 1024, + 6, 6, TX_NO_TIME_SLICE, TX_AUTO_START) != TX_SUCCESS) + { + Error_Handler(); + } + + /* Initialize NetX Duo System */ + nx_system_initialize(); + + /* Create the packet pool in our uncacheable section */ + if (nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", + PACKET_SIZE, packet_pool_area, PACKET_POOL_SIZE) != NX_SUCCESS) { + printf(ANSI_BLUE "[NetX] " ANSI_RED "Failed to create packet pool.\r\n" ANSI_RESET); + Error_Handler(); + } + + /* Allocate the stack for NetX IP thread */ + if (tx_byte_allocate(&byte_pool_sensor, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT) != TX_SUCCESS) + { + Error_Handler(); + } + + /* Create the IP instance using the STM32 Ethernet driver */ + if (nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(0, 0, 0, 0), + 0xFFFFFF00UL, &pool_0, nx_stm32_eth_driver, + pointer, DEMO_STACK_SIZE, 1) != NX_SUCCESS) { + printf(ANSI_BLUE "[NetX] " ANSI_RED "Failed to create IP instance.\r\n" ANSI_RESET); + Error_Handler(); + } + + /* Enable ARP, TCP, UDP, and ICMP */ + nx_arp_enable(&ip_0, (VOID *)arp_cache_area, ARP_CACHE_SIZE); + nx_tcp_enable(&ip_0); + nx_udp_enable(&ip_0); + nx_icmp_enable(&ip_0); + + /* Allocate the stack for the DHCP client thread */ + if (tx_byte_allocate(&byte_pool_sensor, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT) != TX_SUCCESS) + { + Error_Handler(); + } + + /* Create DHCP/Link Monitor Thread (Priority 2) */ + if (tx_thread_create(&dhcp_thread, "DHCP/Link Thread", dhcp_thread_entry, 0, + pointer, DEMO_STACK_SIZE, 2, 2, TX_NO_TIME_SLICE, TX_AUTO_START) != TX_SUCCESS) + { + Error_Handler(); + } + + printf(ANSI_BOLD ANSI_WHITE "[System] " ANSI_GREEN "ThreadX, FileX, and NetX objects initialized successfully.\r\n" ANSI_RESET); +} + +static void sensor_thread_entry(ULONG thread_input) +{ + (void)thread_input; + float temp = 0.0f; + float hum = 0.0f; + sensor_msg_t msg; + + /* Initialize sensor hardware (or fallback to mock) */ + if (sensor_init() != SENSOR_OK) + { + printf(ANSI_CYAN "[Sensor Thread] " ANSI_RED "Critical Error: Sensor initialization failed!\r\n" ANSI_RESET); + Error_Handler(); + } + + printf(ANSI_CYAN "[Sensor Thread] " ANSI_WHITE "Started polling loop (every 2 seconds).\r\n" ANSI_RESET); + + while (1) + { + /* Read sensor data */ + if (sensor_read(&temp, &hum) == SENSOR_OK) + { + /* Pack the message */ + msg.temperature = temp; + msg.humidity = hum; + msg.timestamp = HAL_GetTick(); + + /* Send the message to the queue */ + if (tx_queue_send(&sensor_queue, &msg, TX_NO_WAIT) == TX_SUCCESS) + { + float temp_abs = (temp < 0.0f) ? -temp : temp; + int temp_dec = (int)temp_abs; + int temp_frac = (int)((temp_abs - (float)temp_dec) * 100.0f); + + int hum_dec = (int)hum; + int hum_frac = (int)((hum - (float)hum_dec) * 100.0f); + + printf(ANSI_CYAN "[Sensor Thread] " ANSI_WHITE "Temp: %s%d.%02d C, Hum: %d.%02d %%, Time: %lu ms (Sent to Queue)\r\n" ANSI_RESET, + (temp < 0.0f) ? "-" : "", temp_dec, temp_frac, hum_dec, hum_frac, (unsigned long)msg.timestamp); + } + else + { + printf(ANSI_CYAN "[Sensor Thread] " ANSI_YELLOW "WARNING: Queue is full, message dropped.\r\n" ANSI_RESET); + } + } + else + { + printf(ANSI_CYAN "[Sensor Thread] " ANSI_RED "Error: Failed to read sensor data.\r\n" ANSI_RESET); + } + + /* Sleep for 2 seconds (assuming 100 ticks per second) */ + tx_thread_sleep(2 * TX_TIMER_TICKS_PER_SECOND); + } +} + +static void logger_thread_entry(ULONG thread_input) +{ + (void)thread_input; + UINT status; + sensor_msg_t msg; + char write_buffer[64]; + + printf(ANSI_MAGENTA "[Logger Thread] " ANSI_WHITE "Starting FileX RAM Disk Logger...\r\n" ANSI_RESET); + + /* Initialize FileX system */ + fx_system_initialize(); + + /* Format the RAM disk. This is required before opening it. */ + status = fx_media_format(&ram_disk, + _fx_ram_driver, + ram_disk_memory, + cache_buffer, + sizeof(cache_buffer), + "RAM DISK", + 1, + 32, + 0, + RAM_DISK_SIZE / RAM_DISK_SECTOR_SIZE, + RAM_DISK_SECTOR_SIZE, + 1, + 1, + 1); + if (status != FX_SUCCESS) + { + printf(ANSI_MAGENTA "[Logger Thread] " ANSI_RED "Error: RAM Disk format failed! (0x%02X)\r\n" ANSI_RESET, status); + Error_Handler(); + } + + /* Open the RAM Disk */ + status = fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory, + cache_buffer, sizeof(cache_buffer)); + if (status != FX_SUCCESS) + { + printf(ANSI_MAGENTA "[Logger Thread] " ANSI_RED "Error: RAM Disk open failed! (0x%02X)\r\n" ANSI_RESET, status); + Error_Handler(); + } + + /* Create the log file */ + status = fx_file_create(&ram_disk, "sensor_log.txt"); + if (status != FX_SUCCESS && status != FX_ALREADY_CREATED) + { + printf(ANSI_MAGENTA "[Logger Thread] " ANSI_RED "Error: Failed to create log file! (0x%02X)\r\n" ANSI_RESET, status); + Error_Handler(); + } + + /* Open the log file for writing */ + status = fx_file_open(&ram_disk, &log_file, "sensor_log.txt", FX_OPEN_FOR_WRITE); + if (status != FX_SUCCESS) + { + printf(ANSI_MAGENTA "[Logger Thread] " ANSI_RED "Error: Failed to open log file! (0x%02X)\r\n" ANSI_RESET, status); + Error_Handler(); + } + + /* Move the write pointer to the end of the file to append new data */ + fx_file_seek(&log_file, log_file.fx_file_current_file_size); + + printf(ANSI_MAGENTA "[Logger Thread] " ANSI_GREEN "RAM Disk initialized. Logging 'sensor_log.txt'...\r\n" ANSI_RESET); + + while (1) + { + /* Retrieve the next sensor reading from the queue (blocks until a message is available) */ + if (tx_queue_receive(&sensor_queue, &msg, TX_WAIT_FOREVER) == TX_SUCCESS) + { + /* Format the sensor reading as a CSV line: timestamp,temp,hum */ + float temp_abs = (msg.temperature < 0.0f) ? -msg.temperature : msg.temperature; + int temp_dec = (int)temp_abs; + int temp_frac = (int)((temp_abs - (float)temp_dec) * 100.0f); + + int hum_dec = (int)msg.humidity; + int hum_frac = (int)((msg.humidity - (float)hum_dec) * 100.0f); + + int len = snprintf(write_buffer, sizeof(write_buffer), "%lu,%s%d.%02d,%d.%02d\n", + (unsigned long)msg.timestamp, + (msg.temperature < 0.0f) ? "-" : "", temp_dec, temp_frac, + hum_dec, hum_frac); + + if (len > 0) + { + /* Write the CSV line to the file */ + status = fx_file_write(&log_file, write_buffer, (ULONG)len); + if (status == FX_SUCCESS) + { + /* Flush the media to commit changes to the RAM Disk immediately */ + fx_media_flush(&ram_disk); + + printf(ANSI_MAGENTA "[Logger Thread] " ANSI_WHITE "Logged to RAM Disk: %lu,%s%d.%02d,%d.%02d\r\n" ANSI_RESET, + (unsigned long)msg.timestamp, + (msg.temperature < 0.0f) ? "-" : "", temp_dec, temp_frac, + hum_dec, hum_frac); + } + else + { + printf(ANSI_MAGENTA "[Logger Thread] " ANSI_RED "Error: Failed to write to log file! (0x%02X)\r\n" ANSI_RESET, status); + } + } + + /* Forward the sensor reading to the network telemetry queue (Evict Oldest policy) */ + if (tx_queue_send(&network_queue, &msg, TX_NO_WAIT) != TX_SUCCESS) + { + sensor_msg_t discarded_msg; + /* Evict the oldest item at the front of the queue to make room */ + if (tx_queue_receive(&network_queue, &discarded_msg, TX_NO_WAIT) == TX_SUCCESS) + { + printf(ANSI_MAGENTA "[Logger Thread] " ANSI_YELLOW "WARNING: Network queue full. Evicting oldest message (Time: %lu ms).\r\n" ANSI_RESET, + (unsigned long)discarded_msg.timestamp); + } + + /* Try sending the new message again */ + tx_queue_send(&network_queue, &msg, TX_NO_WAIT); + } + } + } +} + +static void dhcp_thread_entry(ULONG thread_input) +{ + (void)thread_input; + ULONG ip_address; + ULONG network_mask; + ULONG actual_status; + UINT prev_link_up = NX_FALSE; + extern int32_t nx_eth_phy_get_link_state(void); + + /* Create the DHCP client instance once */ + nx_dhcp_create(&dhcp_client, &ip_0, "DHCP Client"); + + printf(ANSI_BLUE "[NetX] " ANSI_WHITE "Network Monitor Thread Started.\r\n" ANSI_RESET); + + while (1) + { + /* Poll the physical link state */ + int32_t phy_state = nx_eth_phy_get_link_state(); + UINT curr_link_up = (phy_state > 1) ? NX_TRUE : NX_FALSE; + + if (curr_link_up != prev_link_up) + { + if (curr_link_up) + { + printf(ANSI_BLUE "[NetX] " ANSI_YELLOW "Ethernet cable connected! Enabling link...\r\n" ANSI_RESET); + UINT status = nx_ip_driver_direct_command(&ip_0, NX_LINK_ENABLE, &actual_status); + if (status == NX_SUCCESS || status == NX_ALREADY_ENABLED) + { + printf(ANSI_BLUE "[NetX] " ANSI_GREEN "Ethernet link is UP! Starting DHCP client...\r\n" ANSI_RESET); + nx_dhcp_start(&dhcp_client); + + /* Wait up to 10 seconds for IP address resolution */ + if (nx_ip_status_check(&ip_0, NX_IP_ADDRESS_RESOLVED, &ip_address, 1000) == NX_SUCCESS) + { + nx_ip_address_get(&ip_0, &ip_address, &network_mask); + printf(ANSI_BLUE "[NetX] " ANSI_BOLD ANSI_GREEN "DHCP Success!\r\n" ANSI_RESET); + printf(ANSI_BLUE "[NetX] " ANSI_GREEN "IP Address : %lu.%lu.%lu.%lu\r\n" ANSI_RESET, + (ip_address >> 24) & 0xFF, (ip_address >> 16) & 0xFF, + (ip_address >> 8) & 0xFF, ip_address & 0xFF); + ip_resolved = NX_TRUE; + } + else + { + printf(ANSI_BLUE "[NetX] " ANSI_YELLOW "DHCP Timeout! Using static IP 192.168.0.100\r\n" ANSI_RESET); + nx_dhcp_stop(&dhcp_client); + nx_ip_address_set(&ip_0, IP_ADDRESS(192, 168, 0, 100), 0xFFFFFF00UL); + ip_resolved = NX_TRUE; + } + } + else + { + printf(ANSI_BLUE "[NetX] " ANSI_RED "Failed to enable driver link: 0x%02x\r\n" ANSI_RESET, status); + } + } + else + { + printf(ANSI_BLUE "[NetX] " ANSI_RED "Ethernet cable disconnected! Disabling link...\r\n" ANSI_RESET); + ip_resolved = NX_FALSE; + nx_dhcp_stop(&dhcp_client); + nx_ip_driver_direct_command(&ip_0, NX_LINK_DISABLE, &actual_status); + /* Reset IP address to 0.0.0.0 */ + nx_ip_address_set(&ip_0, IP_ADDRESS(0, 0, 0, 0), 0xFFFFFF00UL); + } + prev_link_up = curr_link_up; + } + + tx_thread_sleep(100); /* Poll every 1 second (100 ticks) */ + } +} + +static void network_thread_entry(ULONG thread_input) +{ + (void)thread_input; + UINT status; + sensor_msg_t msg; + char payload[128]; + NXD_ADDRESS broker_ip; + VOID *mqtt_stack; + char client_id[32]; + uint32_t uid_w0 = HAL_GetUIDw0(); + + /* Format unique topic and client ID using board's hardware unique ID */ + snprintf(client_id, sizeof(client_id), "stm32f767_%08lX", (unsigned long)uid_w0); + snprintf(mqtt_topic, sizeof(mqtt_topic), "samplex/env_station/%s/telemetry", client_id); + + printf(ANSI_BLUE "[Network Thread] " ANSI_WHITE "Starting Network Telemetry Thread...\r\n" ANSI_RESET); + + /* Allocate stack for internal MQTT thread from our byte memory pool */ + if (tx_byte_allocate(&byte_pool_sensor, (VOID **) &mqtt_stack, DEMO_STACK_SIZE, TX_NO_WAIT) != TX_SUCCESS) + { + Error_Handler(); + } + + /* Create the NetX Duo MQTT Client Instance */ + status = nxd_mqtt_client_create(&mqtt_client, "Samplex Client", client_id, strlen(client_id), + &ip_0, &pool_0, mqtt_stack, DEMO_STACK_SIZE, 4, NX_NULL, 0); + if (status != NX_SUCCESS) + { + printf(ANSI_BLUE "[MQTT] " ANSI_RED "Error: Failed to create MQTT client (0x%02X)\r\n" ANSI_RESET, status); + Error_Handler(); + } + + /* Reconnection/Publish state machine */ + while (1) + { + /* 1. Wait until network link is established and IP is resolved */ + while (!ip_resolved) + { + tx_thread_sleep(100); + } + + /* 2. Initialize DNS Client if not already running */ + static UINT dns_initialized = NX_FALSE; + if (!dns_initialized) + { + /* Fallback to Google DNS */ + ULONG dns_server = IP_ADDRESS(8, 8, 8, 8); + UINT size = sizeof(dns_server); + status = nx_dhcp_user_option_retrieve(&dhcp_client, NX_DHCP_OPTION_DNS_SVR, (UCHAR *)&dns_server, &size); + + if (status != NX_SUCCESS) + { + printf(ANSI_BLUE "[DNS] " ANSI_YELLOW "Warning: Failed to retrieve DHCP DNS option (0x%02X). Using fallback Google DNS.\r\n" ANSI_RESET, status); + } + + if (nx_dns_create(&dns_client, &ip_0, (UCHAR *)"DNS Client") == NX_SUCCESS) + { + nx_dns_server_add(&dns_client, dns_server); + dns_initialized = NX_TRUE; + printf(ANSI_BLUE "[DNS] " ANSI_GREEN "DNS Client initialized. Server: %lu.%lu.%lu.%lu\r\n" ANSI_RESET, + (dns_server >> 24) & 0xFF, (dns_server >> 16) & 0xFF, + (dns_server >> 8) & 0xFF, dns_server & 0xFF); + } + else + { + printf(ANSI_BLUE "[DNS] " ANSI_RED "Error: Failed to create DNS client! Retrying...\r\n" ANSI_RESET); + tx_thread_sleep(200); + continue; + } + } + + /* 3. Resolve DNS name of the Mosquitto broker */ + broker_ip.nxd_ip_version = NX_IP_VERSION_V4; + status = nxd_dns_host_by_name_get(&dns_client, (UCHAR *)MQTT_BROKER_HOST, &broker_ip, 500, NX_IP_VERSION_V4); + if (status != NX_SUCCESS) + { + printf(ANSI_BLUE "[DNS] " ANSI_RED "Error: Failed to resolve broker '%s' (0x%02X). Retrying...\r\n" ANSI_RESET, MQTT_BROKER_HOST, status); + tx_thread_sleep(500); + continue; + } + + printf(ANSI_BLUE "[DNS] " ANSI_GREEN "Resolved '%s' to %lu.%lu.%lu.%lu\r\n" ANSI_RESET, MQTT_BROKER_HOST, + (broker_ip.nxd_ip_address.v4 >> 24) & 0xFF, + (broker_ip.nxd_ip_address.v4 >> 16) & 0xFF, + (broker_ip.nxd_ip_address.v4 >> 8) & 0xFF, + broker_ip.nxd_ip_address.v4 & 0xFF); + + /* 4. Connect to Mosquitto Broker */ + printf(ANSI_BLUE "[MQTT] " ANSI_YELLOW "Connecting to broker %s:%d...\r\n" ANSI_RESET, MQTT_BROKER_HOST, MQTT_BROKER_PORT); + status = nxd_mqtt_client_connect(&mqtt_client, &broker_ip, MQTT_BROKER_PORT, + 60, 1, 1000); /* 60s keepalive, clean session, 10s wait */ + if (status != NX_SUCCESS) + { + printf(ANSI_BLUE "[MQTT] " ANSI_RED "Error: Connection failed (0x%02X). Retrying...\r\n" ANSI_RESET, status); + tx_thread_sleep(500); + continue; + } + + printf(ANSI_BLUE "[MQTT] " ANSI_BOLD ANSI_GREEN "Connected successfully to Mosquitto broker!\r\n" ANSI_RESET); + printf(ANSI_BLUE "[MQTT] " ANSI_WHITE "Publishing to topic: %s\r\n" ANSI_RESET, mqtt_topic); + mqtt_connected = NX_TRUE; + + /* 5. Publish Telemetry Loop */ + while (ip_resolved && mqtt_connected) + { + /* Retrieve messages from the network forwarding queue (blocks until available) */ + if (tx_queue_receive(&network_queue, &msg, 500) == TX_SUCCESS) + { + /* Check if the link was lost while waiting for the message */ + if (!ip_resolved || !mqtt_connected) + { + /* Put the message back so its not lost */ + UINT queue_status = tx_queue_front_send(&network_queue, &msg, TX_NO_WAIT); + if (queue_status != TX_SUCCESS) + { + printf(ANSI_BLUE "[Network Thread] " ANSI_RED "Error: Failed to re-queue message to front (0x%02X).\r\n" ANSI_RESET, queue_status); + } + break; + } + + float temp_abs = (msg.temperature < 0.0f) ? -msg.temperature : msg.temperature; + int temp_dec = (int)temp_abs; + int temp_frac = (int)((temp_abs - (float)temp_dec) * 100.0f); + + int hum_dec = (int)msg.humidity; + int hum_frac = (int)((msg.humidity - (float)hum_dec) * 100.0f); + + /* Create JSON payload */ + snprintf(payload, sizeof(payload), + "{\"temp\":%s%d.%02d,\"hum\":%d.%02d,\"ts\":%lu}", + (msg.temperature < 0.0f) ? "-" : "", temp_dec, temp_frac, + hum_dec, hum_frac, (unsigned long)msg.timestamp); + + /* Publish telemetry QoS 0 */ + status = nxd_mqtt_client_publish(&mqtt_client, mqtt_topic, strlen(mqtt_topic), + payload, strlen(payload), 0, 0, 500); + if (status == NX_SUCCESS) + { + printf(ANSI_BLUE "[Network Thread] " ANSI_GREEN "MQTT Published: %s\r\n" ANSI_RESET, payload); + } + else + { + printf(ANSI_BLUE "[Network Thread] " ANSI_RED "Error: Publish failed (0x%02X)\r\n" ANSI_RESET, status); + nxd_mqtt_client_disconnect(&mqtt_client); + mqtt_connected = NX_FALSE; + } + } + } + + if (mqtt_connected) + { + nxd_mqtt_client_disconnect(&mqtt_client); + } + + mqtt_connected = NX_FALSE; + } +} + +static void status_thread_entry(ULONG thread_input) +{ + (void)thread_input; + UINT state = 0; + + printf(ANSI_YELLOW "[Status Thread] " ANSI_WHITE "Status Monitor Thread Started.\r\n" ANSI_RESET); + + while (1) + { + /* 1. Heartbeat Toggle (Green LED1) */ + if (state) + { + LED1_ON(); + } + else + { + LED1_OFF(); + } + state = !state; + + /* 2. Ethernet Connection Indicator (Blue LED2) */ + if (ip_resolved) + { + LED2_ON(); + } + else + { + LED2_OFF(); + } + + /* 3. MQTT Connection / Network Fault Indicator (Red LED3) */ + if (!ip_resolved || !mqtt_connected) + { + /* Blink Red LED if we have no connection */ + static UINT red_state = 0; + if (red_state) + { + LED3_ON(); + } + else + { + LED3_OFF(); + } + red_state = !red_state; + } + else + { + LED3_OFF(); + } + + /* Sleep 500ms */ + tx_thread_sleep(50); + } +} diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/mock_sensor.c b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/mock_sensor.c new file mode 100644 index 00000000..a5f5fdb5 --- /dev/null +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/mock_sensor.c @@ -0,0 +1,49 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#include "sensor.h" +#include "stm32f7xx_hal.h" +#include + +/* Initialize mock sensor */ +sensor_status_t mock_sensor_init(void) +{ + /* No hardware initialization needed for mock sensor */ + return SENSOR_OK; +} + +/* Read mock sensor data */ +sensor_status_t mock_sensor_read(float *temp, float *hum) +{ + /* Generate simulated values using a slow sine wave + small noise */ + uint32_t tick = HAL_GetTick(); + + /* Simulated temperature: 22.0°C base + 3.0°C variation */ + float sim_temp = 22.0f + 3.0f * sinf((float)tick / 10000.0f); + + /* Simulated humidity: 55.0% base + 10.0% variation */ + float sim_hum = 55.0f + 10.0f * cosf((float)tick / 15000.0f); + + /* Add a tiny bit of noise (pseudo-random based on tick) */ + float noise = (float)(tick % 100) / 500.0f - 0.1f; // -0.1 to +0.1 + sim_temp += noise; + sim_hum += noise * 5.0f; // humidity noise is larger + + /* Keep humidity within physical limits */ + if (sim_hum < 0.0f) sim_hum = 0.0f; + if (sim_hum > 100.0f) sim_hum = 100.0f; + + *temp = sim_temp; + *hum = sim_hum; + return SENSOR_OK; +} diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/mqtt_config.h b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/mqtt_config.h new file mode 100644 index 00000000..b7dda99d --- /dev/null +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/mqtt_config.h @@ -0,0 +1,21 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#ifndef MQTT_CONFIG_H +#define MQTT_CONFIG_H + +/* Eclipse Foundation Mosquitto test broker as default sandbox */ +#define MQTT_BROKER_HOST "test.mosquitto.org" +#define MQTT_BROKER_PORT 1883 + +#endif /* MQTT_CONFIG_H */ diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/nx_user.h b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/nx_user.h new file mode 100644 index 00000000..48c024c1 --- /dev/null +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/nx_user.h @@ -0,0 +1,22 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#ifndef NX_USER_H +#define NX_USER_H + +#define NX_DISABLE_IPV6 +#define NX_ENABLE_INTERFACE_CAPABILITY +#define NX_PHYSICAL_HEADER 16 +#define NX_ENABLE_EXTENDED_NOTIFY_SUPPORT + +#endif /* NX_USER_H */ diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/sensor.h b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/sensor.h new file mode 100644 index 00000000..fa83a174 --- /dev/null +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/sensor.h @@ -0,0 +1,40 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#ifndef SENSOR_H +#define SENSOR_H + +#include + +/* Sensor reading message structure sent through ThreadX queue */ +typedef struct { + float temperature; + float humidity; + uint32_t timestamp; +} sensor_msg_t; + +/* Sensor status enum */ +typedef enum { + SENSOR_OK = 0, + SENSOR_ERROR = 1 +} sensor_status_t; + +/* Public API */ +sensor_status_t sensor_init(void); +sensor_status_t sensor_read(float *temp, float *hum); + +/* Mock Sensor API (used internally by sensor_driver when physical sensor is missing) */ +sensor_status_t mock_sensor_init(void); +sensor_status_t mock_sensor_read(float *temp, float *hum); + +#endif /* SENSOR_H */ diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/sensor_driver.c b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/sensor_driver.c new file mode 100644 index 00000000..95569b65 --- /dev/null +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/network_station/sensor_driver.c @@ -0,0 +1,241 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#include "sensor.h" +#include "hts221_reg.h" +#include "board_init.h" +#include +#include +#include + +/* Private variables */ +static uint8_t mock_mode_active = 0; +static uint8_t whoamI = 0; + +/* Calibration coefficients for HTS221 */ +typedef struct { + float x0; + float y0; + float x1; + float y1; +} lin_t; + +static lin_t lin_hum; +static lin_t lin_temp; + +/* Linear interpolation helper */ +static float linear_interpolation(lin_t *lin, int16_t x) +{ + if (fabsf(lin->x1 - lin->x0) < 0.001f) + { + return lin->y0; + } + return ((lin->y1 - lin->y0) * x + ((lin->x1 * lin->y0) - (lin->x0 * lin->y1))) / (lin->x1 - lin->x0); +} + +/* Platform I2C read/write callbacks */ +static int32_t platform_write(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len) +{ + /* HTS221 requires setting the MSB (0x80) of the register address for multi-byte writes */ + if (len > 1) + { + reg |= 0x80; + } + if (HAL_I2C_Mem_Write((I2C_HandleTypeDef*)handle, HTS221_I2C_ADDRESS, reg, I2C_MEMADD_SIZE_8BIT, bufp, len, 100) == HAL_OK) + { + return 0; + } + return -1; +} + +static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len) +{ + /* HTS221 requires setting the MSB (0x80) of the register address for multi-byte reads */ + if (len > 1) + { + reg |= 0x80; + } + if (HAL_I2C_Mem_Read((I2C_HandleTypeDef*)handle, HTS221_I2C_ADDRESS, reg, I2C_MEMADD_SIZE_8BIT, bufp, len, 100) == HAL_OK) + { + return 0; + } + return -1; +} + +/* Initialize ST device context */ +static stmdev_ctx_t dev_ctx = { + .write_reg = platform_write, + .read_reg = platform_read, + .handle = &hi2c1 +}; + +/* Initialize the sensor */ +sensor_status_t sensor_init(void) +{ + printf("[Sensor] Initializing I2C sensor...\r\n"); + + /* Check if the physical device is responsive on the I2C bus */ + if (HAL_I2C_IsDeviceReady(&hi2c1, HTS221_I2C_ADDRESS, 3, 100) != HAL_OK) + { + printf("[Sensor] WARNING: Physical HTS221 not detected on I2C1 (no ack). Switching to MOCK mode.\r\n"); + mock_mode_active = 1; + return mock_sensor_init(); + } + + /* Read WHO_AM_I register */ + whoamI = 0; + if (hts221_device_id_get(&dev_ctx, &whoamI) != 0 || whoamI != HTS221_ID) + { + printf("[Sensor] WARNING: WHO_AM_I failed (got 0x%02X, expected 0x%02X). Switching to MOCK mode.\r\n", whoamI, HTS221_ID); + mock_mode_active = 1; + return mock_sensor_init(); + } + + printf("[Sensor] Physical HTS221 detected (WHO_AM_I = 0x%02X).\r\n", whoamI); + + /* Read humidity calibration coefficients */ + if (hts221_hum_adc_point_0_get(&dev_ctx, &lin_hum.x0) != 0) + { + printf("[Sensor] WARNING: H0_T0_OUT read failed. Switching to MOCK mode.\r\n"); + mock_mode_active = 1; + return mock_sensor_init(); + } + if (hts221_hum_rh_point_0_get(&dev_ctx, &lin_hum.y0) != 0) + { + printf("[Sensor] WARNING: H0_rH read failed. Switching to MOCK mode.\r\n"); + mock_mode_active = 1; + return mock_sensor_init(); + } + if (hts221_hum_adc_point_1_get(&dev_ctx, &lin_hum.x1) != 0) + { + printf("[Sensor] WARNING: H1_T0_OUT read failed. Switching to MOCK mode.\r\n"); + mock_mode_active = 1; + return mock_sensor_init(); + } + if (hts221_hum_rh_point_1_get(&dev_ctx, &lin_hum.y1) != 0) + { + printf("[Sensor] WARNING: H1_rH read failed. Switching to MOCK mode.\r\n"); + mock_mode_active = 1; + return mock_sensor_init(); + } + + /* Read temperature calibration coefficients */ + if (hts221_temp_adc_point_0_get(&dev_ctx, &lin_temp.x0) != 0) + { + printf("[Sensor] WARNING: T0_OUT read failed. Switching to MOCK mode.\r\n"); + mock_mode_active = 1; + return mock_sensor_init(); + } + if (hts221_temp_deg_point_0_get(&dev_ctx, &lin_temp.y0) != 0) + { + printf("[Sensor] WARNING: T0_degC read failed. Switching to MOCK mode.\r\n"); + mock_mode_active = 1; + return mock_sensor_init(); + } + if (hts221_temp_adc_point_1_get(&dev_ctx, &lin_temp.x1) != 0) + { + printf("[Sensor] WARNING: T1_OUT read failed. Switching to MOCK mode.\r\n"); + mock_mode_active = 1; + return mock_sensor_init(); + } + if (hts221_temp_deg_point_1_get(&dev_ctx, &lin_temp.y1) != 0) + { + printf("[Sensor] WARNING: T1_degC read failed. Switching to MOCK mode.\r\n"); + mock_mode_active = 1; + return mock_sensor_init(); + } + + /* Enable Block Data Update (BDU) - prevents reading partial data */ + if (hts221_block_data_update_set(&dev_ctx, PROPERTY_ENABLE) != 0) + { + printf("[Sensor] WARNING: Enable BDU write failed. Switching to MOCK mode.\r\n"); + mock_mode_active = 1; + return mock_sensor_init(); + } + + /* Set Output Data Rate to 1Hz */ + if (hts221_data_rate_set(&dev_ctx, HTS221_ODR_1Hz) != 0) + { + printf("[Sensor] WARNING: Set ODR write failed. Switching to MOCK mode.\r\n"); + mock_mode_active = 1; + return mock_sensor_init(); + } + + /* Power on the device */ + if (hts221_power_on_set(&dev_ctx, PROPERTY_ENABLE) != 0) + { + printf("[Sensor] WARNING: Power on write failed. Switching to MOCK mode.\r\n"); + mock_mode_active = 1; + return mock_sensor_init(); + } + + printf("[Sensor] Physical HTS221 initialized successfully.\r\n"); + mock_mode_active = 0; + return SENSOR_OK; +} + +/* Read sensor data */ +sensor_status_t sensor_read(float *temp, float *hum) +{ + if (mock_mode_active) + { + return mock_sensor_read(temp, hum); + } + + /* Physical sensor read */ + hts221_status_reg_t status; + int32_t ret = hts221_status_get(&dev_ctx, &status); + if (ret != 0) + { + return SENSOR_ERROR; + } + + /* Wait/check if new data is ready */ + if (status.t_da && status.h_da) + { + union { + int16_t i16; + uint8_t u8[2]; + } raw_data; + + /* Read raw humidity */ + memset(raw_data.u8, 0, sizeof(raw_data.u8)); + if (hts221_humidity_raw_get(&dev_ctx, raw_data.u8) == 0) + { + float rh = linear_interpolation(&lin_hum, raw_data.i16); + if (rh < 0.0f) rh = 0.0f; + if (rh > 100.0f) rh = 100.0f; + *hum = rh; + } + else + { + return SENSOR_ERROR; + } + + /* Read raw temperature */ + memset(raw_data.u8, 0, sizeof(raw_data.u8)); + if (hts221_temperature_raw_get(&dev_ctx, raw_data.u8) == 0) + { + *temp = linear_interpolation(&lin_temp, raw_data.i16); + } + else + { + return SENSOR_ERROR; + } + + return SENSOR_OK; + } + + /* If data wasn't ready yet, return last known values or wait */ + return SENSOR_ERROR; +} diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/CMakeLists.txt b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/CMakeLists.txt index f3672d6b..c946ce03 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/CMakeLists.txt +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/CMakeLists.txt @@ -25,6 +25,7 @@ target_compile_definitions(${PROJECT_NAME} target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../.. ) # Link libraries diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/main.c b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/main.c index 7e762986..13c7ea90 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/main.c +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/netx_echo/main.c @@ -16,6 +16,7 @@ #include "nx_api.h" #include "nxd_dhcp_client.h" #include +#include "ansi_colors.h" #define DEMO_STACK_SIZE 2048 #define PACKET_SIZE 1536 @@ -48,9 +49,9 @@ void tcp_echo_thread_entry(ULONG thread_input); int main(void) { board_init(); - printf("\r\n==========================================\r\n"); - printf("NetX Echo Demo Booted!\r\n"); - printf("==========================================\r\n\r\n"); + printf(ANSI_BOLD ANSI_CYAN "\r\n==========================================\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN "NetX Echo Demo Booted!\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN "==========================================\r\n\r\n" ANSI_RESET); /* Initialize the Ethernet hardware, MAC, and wait for link to be established */ board_ethernet_init(); @@ -68,35 +69,35 @@ void tx_application_define(void *first_unused_memory) /* Create the packet pool in our uncacheable section */ if (nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", PACKET_SIZE, packet_pool_area, PACKET_POOL_SIZE) != NX_SUCCESS) { - printf("[NetX] Failed to create packet pool.\r\n"); + printf(TAG_NETWORK " " MSG_ERROR "Failed to create packet pool.\r\n" ANSI_RESET); return; } - printf("[NetX] Packet pool created\r\n"); + printf(TAG_NETWORK " " MSG_SUCCESS "Packet pool created\r\n" ANSI_RESET); /* Create the IP instance using the STM32 Ethernet driver */ if (nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(0, 0, 0, 0), 0xFFFFFF00UL, &pool_0, nx_stm32_eth_driver, ip_thread_stack, DEMO_STACK_SIZE, 1) != NX_SUCCESS) { - printf("[NetX] Failed to create IP instance.\r\n"); + printf(TAG_NETWORK " " MSG_ERROR "Failed to create IP instance.\r\n" ANSI_RESET); return; } - printf("[NetX] IP instance created\r\n"); + printf(TAG_NETWORK " " MSG_SUCCESS "IP instance created\r\n" ANSI_RESET); /* Enable ARP, TCP, UDP, and ICMP */ - printf("[NetX] Enabling ARP...\r\n"); + printf(TAG_NETWORK " " MSG_INFO "Enabling ARP...\r\n" ANSI_RESET); nx_arp_enable(&ip_0, (VOID *)arp_cache_area, ARP_CACHE_SIZE); - printf("[NetX] Enabling TCP...\r\n"); + printf(TAG_NETWORK " " MSG_INFO "Enabling TCP...\r\n" ANSI_RESET); nx_tcp_enable(&ip_0); - printf("[NetX] Enabling UDP...\r\n"); + printf(TAG_NETWORK " " MSG_INFO "Enabling UDP...\r\n" ANSI_RESET); nx_udp_enable(&ip_0); - printf("[NetX] Enabling ICMP...\r\n"); + printf(TAG_NETWORK " " MSG_INFO "Enabling ICMP...\r\n" ANSI_RESET); nx_icmp_enable(&ip_0); /* Start DHCP Thread */ - printf("[NetX] Creating DHCP Thread...\r\n"); + printf(TAG_NETWORK " " MSG_INFO "Creating DHCP Thread...\r\n" ANSI_RESET); tx_thread_create(&dhcp_thread, "DHCP Thread", dhcp_thread_entry, 0, dhcp_thread_stack, DEMO_STACK_SIZE, 2, 2, TX_NO_TIME_SLICE, TX_AUTO_START); - printf("[NetX] tx_application_define completed\r\n"); + printf(TAG_NETWORK " " MSG_SUCCESS "tx_application_define completed\r\n" ANSI_RESET); } void dhcp_thread_entry(ULONG thread_input) @@ -111,7 +112,7 @@ void dhcp_thread_entry(ULONG thread_input) /* Create the DHCP client instance once */ nx_dhcp_create(&dhcp_client, &ip_0, "DHCP Client"); - printf("[NetX] Network Monitor Thread Started.\r\n"); + printf(TAG_NETWORK " " MSG_INFO "Network Monitor Thread Started.\r\n" ANSI_RESET); while (1) { @@ -123,28 +124,28 @@ void dhcp_thread_entry(ULONG thread_input) { if (curr_link_up) { - printf("[NetX] Ethernet cable connected! Enabling link...\r\n"); + printf(TAG_NETWORK " " MSG_WARNING "Ethernet cable connected! Enabling link...\r\n" ANSI_RESET); UINT status = nx_ip_driver_direct_command(&ip_0, NX_LINK_ENABLE, &actual_status); if (status == NX_SUCCESS || status == NX_ALREADY_ENABLED) { - printf("[NetX] Ethernet link is UP! Starting DHCP client...\r\n"); + printf(TAG_NETWORK " " MSG_SUCCESS "Ethernet link is UP! Starting DHCP client...\r\n" ANSI_RESET); nx_dhcp_start(&dhcp_client); /* Wait up to 10 seconds for IP address resolution */ if (nx_ip_status_check(&ip_0, NX_IP_ADDRESS_RESOLVED, &ip_address, 1000) == NX_SUCCESS) { nx_ip_address_get(&ip_0, &ip_address, &network_mask); - printf("[NetX] DHCP Success!\r\n"); - printf("[NetX] IP Address : %lu.%lu.%lu.%lu\r\n", + printf(TAG_NETWORK " " ANSI_BOLD MSG_SUCCESS "DHCP Success!\r\n" ANSI_RESET); + printf(TAG_NETWORK " " MSG_SUCCESS "IP Address : %lu.%lu.%lu.%lu\r\n" ANSI_RESET, (ip_address >> 24) & 0xFF, (ip_address >> 16) & 0xFF, (ip_address >> 8) & 0xFF, ip_address & 0xFF); - printf("[NetX] Subnet Mask: %lu.%lu.%lu.%lu\r\n", + printf(TAG_NETWORK " " MSG_SUCCESS "Subnet Mask: %lu.%lu.%lu.%lu\r\n" ANSI_RESET, (network_mask >> 24) & 0xFF, (network_mask >> 16) & 0xFF, (network_mask >> 8) & 0xFF, network_mask & 0xFF); } else { - printf("[NetX] DHCP Timeout! Using static IP 192.168.0.100\r\n"); + printf(TAG_NETWORK " " MSG_WARNING "DHCP Timeout! Using static IP 192.168.0.100\r\n" ANSI_RESET); nx_dhcp_stop(&dhcp_client); nx_ip_address_set(&ip_0, IP_ADDRESS(192, 168, 0, 100), 0xFFFFFF00UL); } @@ -159,12 +160,12 @@ void dhcp_thread_entry(ULONG thread_input) } else { - printf("[NetX] Failed to enable driver link: 0x%02x\r\n", status); + printf(TAG_NETWORK " " MSG_ERROR "Failed to enable driver link: 0x%02x\r\n" ANSI_RESET, status); } } else { - printf("[NetX] Ethernet cable disconnected! Disabling link...\r\n"); + printf(TAG_NETWORK " " MSG_ERROR "Ethernet cable disconnected! Disabling link...\r\n" ANSI_RESET); nx_dhcp_stop(&dhcp_client); nx_ip_driver_direct_command(&ip_0, NX_LINK_DISABLE, &actual_status); /* Reset IP address to 0.0.0.0 */ @@ -184,7 +185,7 @@ void tcp_echo_thread_entry(ULONG thread_input) nx_tcp_socket_create(&ip_0, &echo_socket, "Echo Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 512, NX_NULL, NX_NULL); - printf("[Echo] TCP Echo Server listening on port %d\r\n", ECHO_SERVER_PORT); + printf(TAG_ECHO " " MSG_INFO "TCP Echo Server listening on port %d\r\n" ANSI_RESET, ECHO_SERVER_PORT); while (1) { if (nx_tcp_server_socket_listen(&ip_0, ECHO_SERVER_PORT, &echo_socket, 5, NX_NULL) != NX_SUCCESS) { @@ -193,14 +194,14 @@ void tcp_echo_thread_entry(ULONG thread_input) } if (nx_tcp_server_socket_accept(&echo_socket, NX_WAIT_FOREVER) == NX_SUCCESS) { - printf("[Echo] Client connected.\r\n"); + printf(TAG_ECHO " " MSG_SUCCESS "Client connected.\r\n" ANSI_RESET); while (nx_tcp_socket_receive(&echo_socket, &packet_ptr, NX_WAIT_FOREVER) == NX_SUCCESS) { /* Echo the packet back */ nx_tcp_socket_send(&echo_socket, packet_ptr, NX_WAIT_FOREVER); } - printf("[Echo] Client disconnected.\r\n"); + printf(TAG_ECHO " " MSG_WARNING "Client disconnected.\r\n" ANSI_RESET); nx_tcp_socket_disconnect(&echo_socket, NX_WAIT_FOREVER); nx_tcp_server_socket_unaccept(&echo_socket); } diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/CMakeLists.txt b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/CMakeLists.txt index 9d269018..b1b76fe6 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/CMakeLists.txt +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/CMakeLists.txt @@ -25,6 +25,7 @@ target_compile_definitions(${PROJECT_NAME} target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../.. ) # Link libraries diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/main.c b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/main.c index ff5fb791..2ecd58cf 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/main.c +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/main.c @@ -14,6 +14,7 @@ #include "board_init.h" #include "tx_api.h" #include +#include "ansi_colors.h" /* --- ThreadX Resource Definitions --- */ @@ -138,9 +139,9 @@ void green_thread_entry(ULONG thread_input) { (void)thread_input; - printf("\r\n==========================================\r\n"); - printf("ThreadX Multitasking Edge Node Demo Booted!\r\n"); - printf("==========================================\r\n\r\n"); + printf(ANSI_BOLD ANSI_CYAN "\r\n==========================================\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN "ThreadX Multitasking Edge Node Demo Booted!\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN "==========================================\r\n\r\n" ANSI_RESET); while (1) { @@ -210,7 +211,7 @@ void logger_thread_entry(ULONG thread_input) /* Block until a message arrives in the queue */ if (tx_queue_receive(&msg_queue, &received_ticks, TX_WAIT_FOREVER) == TX_SUCCESS) { - printf("[LOG] Button Pressed! System Tick Count: %lu\r\n", received_ticks); + printf("\x1b[38;5;243m[LOG]" ANSI_RESET " " MSG_SUCCESS "Button Pressed! System Tick Count: %lu\r\n" ANSI_RESET, received_ticks); } } } @@ -304,7 +305,7 @@ void input_thread_entry(ULONG thread_input) if (line_index > 0) { line_buffer[line_index] = '\0'; - printf(" -> [CONSOLE] Received string: \"%s\"\r\n", line_buffer); + printf(" -> \x1b[38;5;243m[CONSOLE]" ANSI_RESET " " MSG_INFO "Received string: \"%s\"\r\n" ANSI_RESET, line_buffer); /* Flash LD3 to signal successful reception */ LED3_ON(); diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/stm32f7xx_hal_conf.h b/STMicroelectronics/STM32F767ZI-Nucleo/app/stm32f7xx_hal_conf.h index 0f275c74..4f134d9b 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/app/stm32f7xx_hal_conf.h +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/stm32f7xx_hal_conf.h @@ -52,7 +52,7 @@ /* #define HAL_SRAM_MODULE_ENABLED */ /* #define HAL_SDRAM_MODULE_ENABLED */ /* #define HAL_HASH_MODULE_ENABLED */ -/* #define HAL_I2C_MODULE_ENABLED */ +#define HAL_I2C_MODULE_ENABLED /* #define HAL_I2S_MODULE_ENABLED */ /* #define HAL_IWDG_MODULE_ENABLED */ /* #define HAL_LPTIM_MODULE_ENABLED */ diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/stm32f7xx_hal_msp.c b/STMicroelectronics/STM32F767ZI-Nucleo/app/stm32f7xx_hal_msp.c index d17dc1da..d8c3a429 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/app/stm32f7xx_hal_msp.c +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/stm32f7xx_hal_msp.c @@ -361,5 +361,50 @@ void HAL_PCD_MspDeInit(PCD_HandleTypeDef* hpcd) } /* USER CODE BEGIN 1 */ +void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + if(hi2c->Instance==I2C1) + { + /* Initializes the peripherals clock */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2C1; + PeriphClkInitStruct.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) + { + Error_Handler(); + } + + __HAL_RCC_GPIOB_CLK_ENABLE(); + + /**I2C1 GPIO Configuration + PB8 ------> I2C1_SCL + PB9 ------> I2C1_SDA + */ + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* Peripheral clock enable */ + __HAL_RCC_I2C1_CLK_ENABLE(); + } +} + +void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c) +{ + if(hi2c->Instance==I2C1) + { + /* Peripheral clock disable */ + __HAL_RCC_I2C1_CLK_DISABLE(); + /**I2C1 GPIO Configuration + PB8 ------> I2C1_SCL + PB9 ------> I2C1_SDA + */ + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8|GPIO_PIN_9); + } +} /* USER CODE END 1 */ diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.ps1 b/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.ps1 index 3f7102c1..d0d2f0a1 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.ps1 +++ b/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.ps1 @@ -98,6 +98,7 @@ Copy-Item -Path "$TempDir/Middlewares/ST/netxduo/common/drivers/ethernet/nx_stm3 Copy-Item -Path "$TempDir/Middlewares/ST/netxduo/common/drivers/ethernet/nx_stm32_eth_driver.h" -Destination $NetxDriverDest -Force Copy-Item -Path "$TempDir/Middlewares/ST/netxduo/common/drivers/ethernet/lan8742/nx_stm32_phy_driver.c" -Destination $NetxDriverDest -Force Copy-Item -Path "$TempDir/Middlewares/ST/netxduo/common/drivers/ethernet/nx_stm32_phy_driver.h" -Destination $NetxDriverDest -Force +Copy-Item -Path "$TempDir/Projects/STM32F767ZI-Nucleo/Applications/NetXDuo/Nx_TCP_Echo_Client/NetXDuo/Target/nx_stm32_eth_config.h" -Destination $NetxDriverDest -Force # ST modified the HAL ETH driver to match the new H7-style API for NetX Duo, so we must overwrite the default ones Copy-Item -Path "$TempDir/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_eth.c" -Destination "$HalDest/Src" -Force diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.sh b/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.sh index 443db778..82b8866e 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.sh +++ b/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.sh @@ -87,6 +87,7 @@ cp -f "${TEMP_DIR}/Middlewares/ST/netxduo/common/drivers/ethernet/nx_stm32_eth_d cp -f "${TEMP_DIR}/Middlewares/ST/netxduo/common/drivers/ethernet/nx_stm32_eth_driver.h" "${NETX_DRIVER_DEST}/" cp -f "${TEMP_DIR}/Middlewares/ST/netxduo/common/drivers/ethernet/lan8742/nx_stm32_phy_driver.c" "${NETX_DRIVER_DEST}/" cp -f "${TEMP_DIR}/Middlewares/ST/netxduo/common/drivers/ethernet/nx_stm32_phy_driver.h" "${NETX_DRIVER_DEST}/" +cp -f "${TEMP_DIR}/Projects/STM32F767ZI-Nucleo/Applications/NetXDuo/Nx_TCP_Echo_Client/NetXDuo/Target/nx_stm32_eth_config.h" "${NETX_DRIVER_DEST}/" # ST modified the HAL ETH driver to match the new H7-style API for NetX Duo, so we must overwrite the default ones cp -f "${TEMP_DIR}/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_eth.c" "${HAL_DEST}/Src/" From 82f7ad5056bd62102e73a10b3c9c4230254be8ce Mon Sep 17 00:00:00 2001 From: Ammar Okla <146969371+AmmarOkla12772@users.noreply.github.com> Date: Mon, 31 Aug 2026 15:47:58 +0300 Subject: [PATCH 05/20] Added generic BSP framework and PolarFire SoC Icicle Kit target (#49) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add Microchip PolarFire SoC target, reusable BSP framework, and Renode CI pipeline * Add dynamic runtime self-tests for _sbrk bounds, timer catch-up, and queue integrity * Refine timer catch-up test and add per-thread run counters * Initialize early mtvec, add deliberate timeout and trap testing hooks, and port collision fix * Separate synchronous trap dispatch from interrupt context save * feat(polarfire): Implement and dynamically verify PLIC Hart 1 configuration and MMUART1 interrupt routing * Fixed PLIC machine-mode context and made the Renode self-tests gate CI Addressed the outstanding review items on the PolarFire SoC target. PLIC: plic.h programmed context 2, which is the supervisor-mode context for u54_1 on PolarFire SoC; the machine-mode context for that hart is context 1. Writing the supervisor context is silently accepted by the PLIC but leaves the machine-mode enable bitmap clear, so MEIP never asserts and MMUART1 interrupts could not be delivered. Threshold/claim move to 0x0C201000/0x0C201004 and the enable word to 0x0C002088. The context and enable-word offsets are now derived from the source ID rather than hardcoded. Self-tests: run_startup_self_tests() printed "All startup verification tests PASSED!" unconditionally, and test_renode.py grepped for exactly that string, so a failing sub-test still produced a green build. Results now feed a failure counter that decides the summary line, and the harness fails on any "[-] FAIL:". Renode harness: the exit code considered only ticks and the alarm, discarding the self-test and PLIC-RX flags it computed. All four assertions now gate the result, and the harness injects a byte into MMUART1 so the PLIC path is actually exercised instead of only having its registers inspected. The timer catch-up self-test no longer writes mtime. That register is the platform-wide monotonic counter shared by every hart, and this demo is meant to be copied. Only the per-hart mtimecmp is staged into the past, with the expected result bracketed by mtime sampled either side of hwtimer_ack(). Also: - Hardened _sbrk() in templates/target, which is the copy-me template: bounds check against BSP_RAM_END, reject underflow and pointer overflow, return (void *)-1 with errno, and take ptrdiff_t so it stays correct on 64-bit. - Implemented __malloc_lock/__malloc_unlock instead of leaving them empty, so the newlib arena is genuinely serialised rather than only appearing to be. - Gave the tick source one owner: _tx_initialize_low_level calls hwtimer_init, board_init handles board peripherals, so board_init no longer runs twice. - Pinned Renode to 1.16.1 and checksum-verified both CI downloads. - Updated polarfire_demo.robot, which asserted on telemetry strings the demo no longer emits, and added an RX interrupt case. - Derived the demo sleep intervals from TX_TIMER_TICKS_PER_SECOND. - Corrected the architecture.md tree and normalised the licence URL to the form used in AGENTS.md. * Fixed the timer catch-up self-test to exercise pure arithmetic The previous self-test staged mtimecmp eight ticks behind by subtracting from mtime. Renode starts mtime near zero, so that subtraction underflowed to 2^64-79900 and the test failed itself in CI. The production clamp was never wrong; the test fed it a value real code cannot produce. Extracted the catch-up decision into hwtimer_next_cmp(), a pure function of the current comparand and mtime, and left hwtimer_ack() as a thin wrapper. The test now covers both branches with synthetic values and touches no CLINT register at all, which also removes the last reason for the demo to write timer state. Replaced the TX_TIMER_TICKS_PER_SECOND fallback in hwtimer.h with BSP_TICK_RATE_HZ in board_config.h. The BSP does not see the ThreadX headers, so that fallback silently applied whenever the two disagreed; main.c sees both and now carries a C99 compile-time check that they match. The Renode harness no longer stops at the first failing self-test, so a single failure reports the state of every other assertion instead of hiding it. * Made the Renode run deterministic so the PLIC interrupt is actually exercised The RX assertion added in the previous commit never fired in CI. Renode does not read its monitor from stdin (it logs "Monitor available in telnet mode on port 1234"), so the byte the harness wrote was silently discarded and the PLIC path still went untested. Added renode/polarfire_ci.resc, which steps through fixed virtual-time intervals with emulation RunFor, injects the byte itself via WriteChar, and quits. The run is reproducible and terminates on its own rather than depending on wall clock. It duplicates the machine setup instead of including polarfire_demo.resc because Renode expands $ORIGIN only in variable assignment, so an included script cannot be located relative to the file including it; both "include @$ORIGIN/..." and a bare relative include hang the process rather than reporting an error. polarfire_demo.resc is left free-running for interactive use. Verified locally against Renode 1.16.1, both directions: context 1 -> [Console RX] PLIC IRQ 91 handled: byte 'X' ... harness exit 0 context 2 -> no RX line harness exit 1 Both builds print an identical "[+] PASS: PLIC Hart 1 (IRQ 91 prio=1 en=0x08000000 thresh=0 mie=0x800)" self-test line, which is the point: register readback cannot separate a correct context from an incorrect one, and only a delivered interrupt can. Also added timeout-minutes to both CI jobs as a backstop, and corrected the target README, whose expected-output block still showed telemetry strings the demo stopped emitting. --------- Co-authored-by: Ammar Okla Co-authored-by: Frédéric Desbiens --- .github/workflows/ci.yml | 103 ++++++ bsp/include/bsp/board.h | 19 + bsp/include/bsp/console.h | 29 ++ bsp/include/bsp/led.h | 34 ++ cmake/utilities.cmake | 50 +++ docs/architecture.md | 67 ++++ .../POLARFIRE_ICICLE_RENODE/CMakeLists.txt | 41 +++ .../POLARFIRE_ICICLE_RENODE/README.md | 88 +++++ .../app/CMakeLists.txt | 62 ++++ .../app/common/linker/linker.ld | 69 ++++ .../app/common/startup/entry.S | 53 +++ .../app/common/startup/newlib_stubs.c | 136 ++++++++ .../common/startup/tx_initialize_low_level.S | 113 ++++++ .../POLARFIRE_ICICLE_RENODE/app/main.c | 328 ++++++++++++++++++ .../lib/CMakeLists.txt | 1 + .../lib/bsp/CMakeLists.txt | 27 ++ .../lib/bsp/include/board_config.h | 31 ++ .../lib/bsp/include/csr.h | 31 ++ .../lib/bsp/include/hwtimer.h | 47 +++ .../lib/bsp/include/plic.h | 62 ++++ .../lib/bsp/include/uart.h | 26 ++ .../lib/bsp/src/board.c | 25 ++ .../lib/bsp/src/bsp_board.c | 29 ++ .../lib/bsp/src/bsp_console.c | 29 ++ .../lib/bsp/src/bsp_led.c | 39 +++ .../lib/bsp/src/hwtimer.c | 34 ++ .../lib/bsp/src/plic.c | 36 ++ .../lib/bsp/src/trap.c | 68 ++++ .../lib/bsp/src/uart.c | 59 ++++ .../renode/polarfire_ci.resc | 46 +++ .../renode/polarfire_demo.resc | 29 ++ .../renode/polarfire_demo.robot | 25 ++ .../POLARFIRE_ICICLE_RENODE/scripts/build.ps1 | 77 ++++ .../POLARFIRE_ICICLE_RENODE/scripts/build.sh | 75 ++++ .../scripts/test_renode.py | 163 +++++++++ templates/target/CMakeLists.txt | 54 +++ templates/target/README.md | 144 ++++++++ templates/target/app/CMakeLists.txt | 40 +++ templates/target/app/common/linker/README.md | 12 + templates/target/app/common/startup/README.md | 11 + templates/target/lib/CMakeLists.txt | 23 ++ templates/target/lib/bsp/CMakeLists.txt | 26 ++ .../target/lib/bsp/include/board_config.h | 36 ++ templates/target/lib/bsp/src/bsp_board.c | 28 ++ templates/target/lib/bsp/src/bsp_console.c | 35 ++ templates/target/lib/bsp/src/bsp_led.c | 42 +++ templates/target/lib/bsp/src/newlib_stubs.c | 133 +++++++ templates/target/lib/vendor/README.md | 14 + templates/target/scripts/build.ps1 | 79 +++++ 49 files changed, 2828 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 bsp/include/bsp/board.h create mode 100644 bsp/include/bsp/console.h create mode 100644 bsp/include/bsp/led.h create mode 100644 cmake/utilities.cmake create mode 100644 docs/architecture.md create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/CMakeLists.txt create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/README.md create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/app/CMakeLists.txt create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/linker/linker.ld create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/entry.S create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/newlib_stubs.c create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/tx_initialize_low_level.S create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/app/main.c create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/CMakeLists.txt create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/CMakeLists.txt create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/board_config.h create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/csr.h create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/hwtimer.h create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/plic.h create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/uart.h create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/board.c create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_board.c create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_console.c create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_led.c create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/hwtimer.c create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/plic.c create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/trap.c create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/uart.c create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_ci.resc create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_demo.resc create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_demo.robot create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/build.ps1 create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/build.sh create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py create mode 100644 templates/target/CMakeLists.txt create mode 100644 templates/target/README.md create mode 100644 templates/target/app/CMakeLists.txt create mode 100644 templates/target/app/common/linker/README.md create mode 100644 templates/target/app/common/startup/README.md create mode 100644 templates/target/lib/CMakeLists.txt create mode 100644 templates/target/lib/bsp/CMakeLists.txt create mode 100644 templates/target/lib/bsp/include/board_config.h create mode 100644 templates/target/lib/bsp/src/bsp_board.c create mode 100644 templates/target/lib/bsp/src/bsp_console.c create mode 100644 templates/target/lib/bsp/src/bsp_led.c create mode 100644 templates/target/lib/bsp/src/newlib_stubs.c create mode 100644 templates/target/lib/vendor/README.md create mode 100644 templates/target/scripts/build.ps1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..37d2ee3f --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,103 @@ +# +# 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/licenses/MIT. +# +# SPDX-License-Identifier: MIT +# + +name: SampleX CI Verification Pipeline + +on: + push: + branches: [ main, master, dev, 'feat/**' ] + pull_request: + branches: [ main, master, dev ] + +jobs: + build-riscv-polarfire: + name: Build PolarFire SoC Icicle Kit (64-Bit RISC-V) + runs-on: ubuntu-24.04 + timeout-minutes: 20 + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install CMake and Ninja + run: | + sudo apt-get update + sudo apt-get install -y cmake ninja-build + + - name: Install Pinned xPack RISC-V GCC 14.2.0 + env: + XPACK_TARBALL: xpack-riscv-none-elf-gcc-14.2.0-1-linux-x64.tar.gz + XPACK_SHA256: a5eb707595e1424ff4127cc8b21b8b8cb076e6f0070b670485e72b9f74806200 + run: | + set -euo pipefail + wget -q "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v14.2.0-1/${XPACK_TARBALL}" + echo "${XPACK_SHA256} ${XPACK_TARBALL}" | sha256sum --check --strict + mkdir -p $HOME/riscv-gcc + tar -xzf "${XPACK_TARBALL}" -C $HOME/riscv-gcc --strip-components=1 + rm "${XPACK_TARBALL}" + echo "$HOME/riscv-gcc/bin" >> $GITHUB_PATH + + - name: Build SampleX PolarFire Condition-Monitoring Demo + run: | + bash targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/build.sh --rebuild + + - name: Verify SampleX Demo ELF + run: | + test -f targets/Microchip/POLARFIRE_ICICLE_RENODE/build/app/polarfire_icicle_demo.elf + echo "[OK] PolarFire SampleX demo ELF verified." + + - name: Archive Built PolarFire ELF + uses: actions/upload-artifact@v4 + with: + name: polarfire-demo-elf + path: targets/Microchip/POLARFIRE_ICICLE_RENODE/build/app/polarfire_icicle_demo.elf + retention-days: 1 + + test-polarfire-renode: + name: Headless Renode Emulation & Assertion Test + needs: build-riscv-polarfire + runs-on: ubuntu-24.04 + # Backstop in case Renode itself wedges before the in-script deadline fires. + timeout-minutes: 15 + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Set Up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Download Built PolarFire ELF + uses: actions/download-artifact@v4 + with: + name: polarfire-demo-elf + path: targets/Microchip/POLARFIRE_ICICLE_RENODE/build/app + + - name: Install Pinned Portable Renode Emulation Environment + env: + RENODE_VERSION: 1.16.1 + RENODE_SHA256: 1a532d4b5b82de0dd154970c401e0c7b0e498d17304b2cecc007e306c8f9617c + run: | + set -euo pipefail + TARBALL="renode-${RENODE_VERSION}.linux-portable.tar.gz" + wget -q "https://github.com/renode/renode/releases/download/v${RENODE_VERSION}/${TARBALL}" + echo "${RENODE_SHA256} ${TARBALL}" | sha256sum --check --strict + mkdir -p $HOME/renode + tar -xzf "${TARBALL}" -C $HOME/renode --strip-components=1 + rm "${TARBALL}" + echo "$HOME/renode" >> $GITHUB_PATH + + - name: Run Deterministic Headless Renode Test + run: | + python3 targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py diff --git a/bsp/include/bsp/board.h b/bsp/include/bsp/board.h new file mode 100644 index 00000000..f38224eb --- /dev/null +++ b/bsp/include/bsp/board.h @@ -0,0 +1,19 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +#ifndef BSP_BOARD_H +#define BSP_BOARD_H + +/** + * @brief Initialize the system core (clocks, flash latency, system configuration). + */ +void bsp_board_init(void); + +#endif /* BSP_BOARD_H */ diff --git a/bsp/include/bsp/console.h b/bsp/include/bsp/console.h new file mode 100644 index 00000000..46d52324 --- /dev/null +++ b/bsp/include/bsp/console.h @@ -0,0 +1,29 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +#ifndef BSP_CONSOLE_H +#define BSP_CONSOLE_H + +#include + +/** + * @brief Initialize the serial console peripheral and pin muxing. + */ +void bsp_console_init(void); + +/** + * @brief Write a buffer of data to the serial console. + * + * @param data Pointer to the character buffer to send. + * @param length Number of characters to transmit. + */ +void bsp_console_write(const char *data, size_t length); + +#endif /* BSP_CONSOLE_H */ diff --git a/bsp/include/bsp/led.h b/bsp/include/bsp/led.h new file mode 100644 index 00000000..a139b04e --- /dev/null +++ b/bsp/include/bsp/led.h @@ -0,0 +1,34 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +#ifndef BSP_LED_H +#define BSP_LED_H + +/** + * @brief Initialize the user LED hardware pin/peripherals. + */ +void bsp_led_init(void); + +/** + * @brief Turn the user LED on. + */ +void bsp_led_on(void); + +/** + * @brief Turn the user LED off. + */ +void bsp_led_off(void); + +/** + * @brief Toggle the state of the user LED. + */ +void bsp_led_toggle(void); + +#endif /* BSP_LED_H */ diff --git a/cmake/utilities.cmake b/cmake/utilities.cmake new file mode 100644 index 00000000..2686c1f8 --- /dev/null +++ b/cmake/utilities.cmake @@ -0,0 +1,50 @@ +# Copyright (c) Microsoft +# Copyright (c) 2024 Eclipse Foundation +# +# This program and the accompanying materials are made available +# under the terms of the MIT license which is available at +# https://opensource.org/licenses/MIT. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Microsoft - Initial version +# Frédéric Desbiens - 2024 version. + +function(post_build TARGET) + if(CMAKE_C_COMPILER_ID STREQUAL "IAR") + add_custom_target(${TARGET}.bin ALL + DEPENDS ${TARGET} + COMMAND ${CMAKE_IAR_ELFTOOL} --bin ${TARGET}.elf ${TARGET}.bin) + elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") + add_custom_target(${TARGET}.bin ALL + DEPENDS ${TARGET} + COMMAND ${CMAKE_OBJCOPY} -Obinary ${TARGET}.elf ${TARGET}.bin + COMMAND ${CMAKE_OBJCOPY} -Oihex ${TARGET}.elf ${TARGET}.hex) + else() + message(FATAL_ERROR "Unknown CMAKE_C_COMPILER_ID ${CMAKE_C_COMPILER_ID}") + endif() +endfunction() + +function(set_target_linker TARGET LINKER_SCRIPT) + if(CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PRIVATE --config ${LINKER_SCRIPT}) + target_link_options(${TARGET} PRIVATE --map=${TARGET}.map) + elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PRIVATE -T${LINKER_SCRIPT}) + target_link_options(${TARGET} PRIVATE -Wl,-Map=${TARGET}.map) + set_target_properties(${TARGET} PROPERTIES SUFFIX ".elf") + + else() + message(FATAL_ERROR "Unknown CMAKE_C_COMPILER_ID ${CMAKE_C_COMPILER_ID}") + endif() +endfunction() + +macro(print_all_variables) + message(STATUS "print_all_variables------------------------------------------{") + get_cmake_property(_variableNames VARIABLES) + foreach (_variableName ${_variableNames}) + message(STATUS "${_variableName}=${${_variableName}}") + endforeach() + message(STATUS "print_all_variables------------------------------------------}") +endmacro() diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 00000000..e0049690 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,67 @@ +# Eclipse ThreadX BSP Framework Architecture + +This document describes the architecture, design philosophy, directory structure, and onboarding process for the reusable Board Support Package (BSP) framework. + +--- + +## 1. Design Philosophy + +The BSP framework is designed to be **additive and non-invasive**, allowing new boards to be integrated without modifying existing board implementations. + +1. **Legacy Isolation**: The board directories that predate this framework (`/MXChip`, `/OpenHW`, `/STMicroelectronics`) remain completely untouched, preserving their drivers, submodules, and build systems. +2. **Platform-Independent Applications**: Target applications use only the abstract BSP interfaces and have no compile-time dependency on vendor-specific HALs, SDKs, or hardware registers. +3. **Reusable Infrastructure**: Shared CMake toolchains and build utilities are centralized under `/cmake` to eliminate duplicated build configuration across supported boards. + +--- + +## 2. Directory Structure + +```text +samplex/ (repository root) +├── libs/ # Shared RTOS components (ThreadX, NetX Duo, FileX, USBX) +├── scripts/ # Repository-wide helper scripts +├── MXChip/ # [Pre-framework] Standalone board sample +├── OpenHW/ # [Pre-framework] Standalone board sample +├── STMicroelectronics/ # [Pre-framework] Standalone board samples +├── targets/ # [Framework] Supported BSP target boards +│ └── Microchip/ +│ └── POLARFIRE_ICICLE_RENODE/ # Board-specific BSP implementation & Renode target +├── bsp/ # [Framework] Abstract BSP interface definitions +│ └── include/bsp/ # board.h, led.h, console.h +├── cmake/ # [Framework] Shared CMake configuration and utilities +├── docs/ # [Framework] Architecture and onboarding documentation +└── templates/ # [Framework] Templates for onboarding new boards +``` + +--- + +## 3. BSP Interface Contract + +Every board added to the framework under `/targets` must implement the abstract APIs defined in `/bsp/include/bsp/`. + +### Core Board Control (`board.h`) + +* `void bsp_board_init(void)`: Initializes the board, including system clocks, GPIO, and required peripherals. + +### LED Control (`led.h`) + +* `void bsp_led_init(void)`: Configures the board's user LED. +* `void bsp_led_on(void)`: Turns the LED on. +* `void bsp_led_off(void)`: Turns the LED off. +* `void bsp_led_toggle(void)`: Toggles the LED state. + +### Serial Console (`console.h`) + +* `void bsp_console_init(void)`: Initializes the default UART console. +* `void bsp_console_write(const char *data, size_t length)`: Transmits a block of data over the console interface. + +--- + +## 4. How to Onboard a New Board + +1. **Create the Target Folder**: Create a new directory under `targets///` using `/templates/target/` as the starting point. +2. **Define Local Configuration**: Create a `board_config.h` file containing board-specific settings such as clock configuration, UART parameters, and ThreadX memory allocation. +3. **Implement the BSP APIs**: Implement the interfaces defined in `/bsp/include/bsp/` using the vendor SDK or direct register access. +4. **Configure CMake**: Add the board target to `CMakeLists.txt`, build the BSP as a static library, and link it with the desired application from `/apps/`. + +Once a board implements the required BSP interfaces, any compatible application under `/apps` can be built for that board without modifying the application source. diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/CMakeLists.txt b/targets/Microchip/POLARFIRE_ICICLE_RENODE/CMakeLists.txt new file mode 100644 index 00000000..08da8f2a --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/CMakeLists.txt @@ -0,0 +1,41 @@ +# +# 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/licenses/MIT. +# +# SPDX-License-Identifier: MIT +# + +cmake_minimum_required(VERSION 3.20) + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR riscv64) + +# Set 64-bit RISC-V Cross Compiler +if(DEFINED ENV{RISCV64_TOOLCHAIN_PATH}) + set(TOOLCHAIN_BIN_DIR "$ENV{RISCV64_TOOLCHAIN_PATH}/bin") + find_program(CMAKE_C_COMPILER NAMES riscv-none-elf-gcc riscv64-none-elf-gcc riscv64-unknown-elf-gcc PATHS ${TOOLCHAIN_BIN_DIR} NO_DEFAULT_PATH REQUIRED) + find_program(CMAKE_CXX_COMPILER NAMES riscv-none-elf-g++ riscv64-none-elf-g++ riscv64-unknown-elf-g++ PATHS ${TOOLCHAIN_BIN_DIR} NO_DEFAULT_PATH REQUIRED) + find_program(CMAKE_ASM_COMPILER NAMES riscv-none-elf-gcc riscv64-none-elf-gcc riscv64-unknown-elf-gcc PATHS ${TOOLCHAIN_BIN_DIR} NO_DEFAULT_PATH REQUIRED) +else() + find_program(CMAKE_C_COMPILER NAMES riscv-none-elf-gcc riscv64-none-elf-gcc riscv64-unknown-elf-gcc REQUIRED) + find_program(CMAKE_CXX_COMPILER NAMES riscv-none-elf-g++ riscv64-none-elf-g++ riscv64-unknown-elf-g++ REQUIRED) + find_program(CMAKE_ASM_COMPILER NAMES riscv-none-elf-gcc riscv64-none-elf-gcc riscv64-unknown-elf-gcc REQUIRED) +endif() + +project(polarfire_icicle_renode C ASM) + +# Root Directories +set(SAMPLEX_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/../../..") +set(THREADX_DIR "${SAMPLEX_ROOT_DIR}/libs/threadx") + +# Architecture flags for SiFive U54 64-Bit RISC-V Core (RV64GC / lp64d) +set(RISCV_FLAGS "-march=rv64gc -mabi=lp64d -mcmodel=medany") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${RISCV_FLAGS} -O2 -g -Wall -Wextra") +set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${RISCV_FLAGS}") +set(CMAKE_EXE_LINKER_FLAGS "${RISCV_FLAGS} -T${CMAKE_CURRENT_LIST_DIR}/app/common/linker/linker.ld -nostartfiles -Wl,--gc-sections") + +add_subdirectory(lib) +add_subdirectory(app) diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/README.md b/targets/Microchip/POLARFIRE_ICICLE_RENODE/README.md new file mode 100644 index 00000000..4ea1e9f2 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/README.md @@ -0,0 +1,88 @@ +# Microchip PolarFire SoC Icicle Kit Target Integration (Renode 64-Bit RISC-V) + +This directory contains the target Board Support Package (BSP) and condition-monitoring demonstration application for the **Microchip PolarFire SoC Icicle Kit** running in the **Renode** emulation environment. + +--- + +## 1. Hardware Architecture Overview + +* **Target Board**: Microchip PolarFire SoC Icicle Kit (`targets/Microchip/POLARFIRE_ICICLE_RENODE`) +* **Processor Subsystem**: 5 RISC-V Harts (1x E51 Monitor Core + 4x 64-bit U54 Application Cores) +* **Execution Hart**: **Hart 1 (`u54_1`)** executes ThreadX; Harts 2–4 are parked in `wfi` loops while Hart 0 (E51) remains under platform monitor supervision. +* **CPU Core Architecture**: 64-Bit RISC-V (`rv64gc` / `lp64d` ABI @ 600 MHz) +* **System DRAM**: 1 GiB LPDDR4 Memory (`0x80000000` – `0xC0000000`) +* **Machine Timer**: SiFive CLINT `mtime` running at 1 MHz (`0x02000000`, 10ms tick = 10,000 cycles) +* **Serial Debug Console**: Microchip MMUART1 (`0x20100000`) at 115200 baud (8-N-1) +* **Telemetry**: Simulated LM75 temperature data processed via ThreadX queues and event flags + +--- + +## 2. Compilation Instructions + +Requirements: +* CMake 3.20+ and Ninja (or Make) +* 64-bit RISC-V GCC cross-compiler (`riscv64-none-elf-gcc`, `riscv-none-elf-gcc`, or xPack RISC-V GCC 14.2.0) + +### On Windows (PowerShell): +```powershell +powershell -ExecutionPolicy Bypass -File .\targets\Microchip\POLARFIRE_ICICLE_RENODE\scripts\build.ps1 -Clean -Rebuild +``` + +### On Linux / macOS (Bash): +```bash +bash targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/build.sh --rebuild +``` + +--- + +## 3. Renode Execution & Verification + +### Interactive Simulation (GUI / Terminal Analyzers): +Inside the Renode monitor: +```renode +include @targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_demo.resc +``` +This free-runs the machine so the telemetry stream can be watched live. + +### Automated Headless Test Runner: +```bash +python targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py +``` +The runner drives `renode/polarfire_ci.resc`, which steps through fixed +virtual-time intervals rather than free-running, injects a byte into MMUART1 to +exercise the PLIC external-interrupt path, and quits on its own. It asserts on +four things and exits non-zero if any of them is missing: + +| Assertion | Covers | +|---|---| +| Startup self-tests all passed | `_sbrk()` bounds, timer catch-up, PLIC configuration | +| ThreadX system tick advancing | CLINT machine timer and `_tx_timer_interrupt` | +| LM75 overtemperature alarm | Queue, event flags, and the analyzer thread | +| PLIC IRQ 91 RX interrupt delivered | MMUART1 -> PLIC -> Hart 1 machine-mode trap path | + +The last of these is the only check that proves the PLIC is programmed for the +right context. Reading the controller's registers back cannot: the machine-mode +context (1) and the supervisor-mode context (2) for Hart 1 both accept the +writes and read back identically, but only the former ever raises `MEIP`. + +### Expected Output Stream (`mmuart1` @ 115200 baud): +```text +==================================================== +Microchip PolarFire SoC Icicle Kit (Renode Target) +64-Bit RISC-V Industrial LM75 Condition-Monitoring App +==================================================== +[SELF-TEST] Starting Hardware & Runtime Verification... +[+] PASS: _sbrk() valid allocation returned base pointer +[+] PASS: _sbrk() underflow guard rejected with EINVAL +[+] PASS: _sbrk() overflow guard rejected with ENOMEM +[+] PASS: HWTimer catch-up (missed deadline rebased to ..., pending deadline advanced to ...) +[+] PASS: PLIC Hart 1 (IRQ 91 prio=1 en=0x08000000 thresh=0 mie=0x800) +[SELF-TEST] All startup verification tests PASSED! + +[+] PASS: Queue 16-byte structure round-trip verified +[Monitor] Ticks: 0 | Active Runs: Sampler=1, Analyzer=1, Reporter=1 +[Monitor] Ticks: 100 | Active Runs: Sampler=3, Analyzer=3, Reporter=2 +[Console RX] PLIC IRQ 91 handled: byte 'X' received and processed by ThreadX +[Monitor] Ticks: 200 | Active Runs: Sampler=5, Analyzer=5, Reporter=3 +[LM75 Sensor] Temperature: OVERTEMP ALARM TRIGGERED (>45.0C) +``` diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/CMakeLists.txt b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/CMakeLists.txt new file mode 100644 index 00000000..64605b99 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/CMakeLists.txt @@ -0,0 +1,62 @@ +# +# 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/licenses/MIT. +# +# SPDX-License-Identifier: MIT +# + +# Glob all common C source files for ThreadX with CONFIGURE_DEPENDS +file(GLOB THREADX_COMMON_SOURCES CONFIGURE_DEPENDS "${THREADX_DIR}/common/src/*.c") + +# ThreadX Library Target for RISC-V 64-bit GNU Port +add_library(threadx STATIC + ${THREADX_COMMON_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/common/startup/tx_initialize_low_level.S + ${THREADX_DIR}/ports/risc-v64/gnu/src/tx_thread_context_restore.S + ${THREADX_DIR}/ports/risc-v64/gnu/src/tx_thread_context_save.S + ${THREADX_DIR}/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S + ${THREADX_DIR}/ports/risc-v64/gnu/src/tx_thread_schedule.S + ${THREADX_DIR}/ports/risc-v64/gnu/src/tx_thread_stack_build.S + ${THREADX_DIR}/ports/risc-v64/gnu/src/tx_thread_system_return.S + ${THREADX_DIR}/ports/risc-v64/gnu/src/tx_timer_interrupt.S +) + +target_include_directories(threadx + PUBLIC + ${THREADX_DIR}/common/inc + ${THREADX_DIR}/ports/risc-v64/gnu/inc + ${CMAKE_CURRENT_SOURCE_DIR}/../lib/bsp/include +) + +# ------------------------------------------------------------- +# PolarFire SoC Icicle Kit Telemetry Executable +# ------------------------------------------------------------- +add_executable(polarfire_icicle_demo + main.c + common/startup/entry.S + common/startup/newlib_stubs.c +) + +set_target_properties(polarfire_icicle_demo PROPERTIES SUFFIX ".elf") + +target_include_directories(polarfire_icicle_demo + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/../lib/bsp/include + ${SAMPLEX_ROOT_DIR}/bsp/include +) + +option(ENABLE_FAULT_INJECTION "Enable deliberate synchronous fault injection for trap handler testing" OFF) +if(ENABLE_FAULT_INJECTION) + target_compile_definitions(polarfire_icicle_demo PRIVATE TEST_FAULT_INJECTION=1) +endif() + +target_link_libraries(polarfire_icicle_demo + PRIVATE + -Wl,--start-group + polarfire_bsp + threadx + -Wl,--end-group +) diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/linker/linker.ld b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/linker/linker.ld new file mode 100644 index 00000000..e80a0ca6 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/linker/linker.ld @@ -0,0 +1,69 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +/* + * Linker Script for Microchip PolarFire SoC Icicle Kit (Renode Execution) + * Target Memory: LPDDR4 DRAM starting at 0x80000000 (1 GiB range) + */ + +OUTPUT_ARCH("riscv") +ENTRY(_start) + +MEMORY +{ + DRAM (rwx) : ORIGIN = 0x80000000, LENGTH = 0x40000000 /* 1 GiB System DRAM */ +} + +SECTIONS +{ + . = 0x80000000; + + .text : ALIGN(16) + { + *(.text._start) + *(.text*) + *(.rodata*) + } > DRAM + + .data : ALIGN(16) + { + *(.data*) + } > DRAM + + .sdata : ALIGN(8) + { + __global_pointer$ = . + 0x800; + *(.srodata*) + *(.sdata*) + *(.gnu.linkonce.s.*) + } > DRAM + + .sbss : ALIGN(8) + { + *(.sbss*) + *(.gnu.linkonce.sb.*) + } > DRAM + + .bss : ALIGN(16) + { + __bss_start = .; + *(.bss*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(8); + __bss_end = .; + } > DRAM + + . = ALIGN(16); + . = . + 0x4000; /* 16 KB Boot Stack */ + __stack_top = .; + __end = .; + _end = .; +} diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/entry.S b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/entry.S new file mode 100644 index 00000000..a59f4786 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/entry.S @@ -0,0 +1,53 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + + .section .text._start + .global _start + .align 4 + +_start: + /* Disable interrupts on current hart */ + csrci mstatus, 8 + + /* Read machine hart ID (mhartid) */ + csrr a0, mhartid + li t0, 1 + bne a0, t0, .park_hart + + /* Setup stack pointer and global pointer for Hart 1 */ + .option push + .option norelax + la gp, __global_pointer$ + .option pop + la sp, __stack_top + + /* Set Machine Trap-Vector Base Address to trap_entry */ + la t0, trap_entry + csrw mtvec, t0 + + /* Note: In Renode direct ELF loading, LMA == VMA so .data is already placed in DRAM. + * On physical hardware booting via HSS, HSS loads sections before jumping to _start. */ + /* Zero-initialize .bss section */ + la t0, __bss_start + la t1, __bss_end +.zero_bss_loop: + bgeu t0, t1, .bss_done + sd zero, 0(t0) + addi t0, t0, 8 + j .zero_bss_loop +.bss_done: + + /* Jump to main application entry */ + call main + +.park_hart: + /* Park unused harts in low-power WFI loop */ + wfi + j .park_hart diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/newlib_stubs.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/newlib_stubs.c new file mode 100644 index 00000000..8d196500 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/newlib_stubs.c @@ -0,0 +1,136 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +// Some portions generated by Claude Code (Opus 5) + +#include +#include +#include +#include +#include +#include "board_config.h" +#include "bsp/console.h" + +extern char __end; /* Symbol set by linker at end of BSS / top of boot stack */ +static char *heap_ptr = NULL; + +static inline uintptr_t disable_interrupts(void) { + uintptr_t mstatus; + __asm__ volatile("csrrci %0, mstatus, 8" : "=r"(mstatus)); + return mstatus; +} + +static inline void restore_interrupts(uintptr_t mstatus) { + if (mstatus & 8) { + __asm__ volatile("csrrs zero, mstatus, 8"); + } +} + +/* Newlib calls these around every heap operation. The U54 hart running ThreadX + * is single-core, so masking machine interrupts is sufficient to serialise the + * malloc arena against both other threads and interrupt handlers. The nesting + * counter keeps recursive newlib entries from re-enabling interrupts early. */ +static uintptr_t s_malloc_lock_mstatus = 0; +static uint32_t s_malloc_lock_depth = 0; + +void __malloc_lock(struct _reent *reent) { + (void)reent; + uintptr_t mstatus = disable_interrupts(); + if (s_malloc_lock_depth == 0U) { + s_malloc_lock_mstatus = mstatus; + } + s_malloc_lock_depth++; +} + +void __malloc_unlock(struct _reent *reent) { + (void)reent; + if (s_malloc_lock_depth == 0U) { + return; + } + s_malloc_lock_depth--; + if (s_malloc_lock_depth == 0U) { + restore_interrupts(s_malloc_lock_mstatus); + } +} + +int _write(int file, char *ptr, int len) { + (void)file; + if (ptr == NULL || len <= 0) + return 0; + bsp_console_write(ptr, (size_t)len); + return len; +} + +void *_sbrk(ptrdiff_t incr) { + char *prev_heap_ptr; + uintptr_t mstatus = disable_interrupts(); + + if (heap_ptr == NULL) { + heap_ptr = &__end; + } + + if (incr > 0) { + if ((uintptr_t)heap_ptr + (uintptr_t)incr > (uintptr_t)BSP_RAM_END || + (uintptr_t)heap_ptr + (uintptr_t)incr < (uintptr_t)heap_ptr) { + restore_interrupts(mstatus); + errno = ENOMEM; + return (void *)-1; + } + } else if (incr < 0) { + if ((uintptr_t)heap_ptr < (uintptr_t)&__end + (uintptr_t)(-incr)) { + restore_interrupts(mstatus); + errno = EINVAL; + return (void *)-1; + } + } + + prev_heap_ptr = heap_ptr; + heap_ptr += incr; + + restore_interrupts(mstatus); + return (void *)prev_heap_ptr; +} + +int _read(int file, char *ptr, int len) { + (void)file; + (void)ptr; + (void)len; + return 0; +} + +int _close(int file) { + (void)file; + return -1; +} + +int _fstat(int file, struct stat *st) { + (void)file; + st->st_mode = S_IFCHR; + return 0; +} + +int _isatty(int file) { + (void)file; + return 1; +} + +int _lseek(int file, int ptr, int dir) { + (void)file; + (void)ptr; + (void)dir; + return 0; +} + +void _exit(int status) { + (void)status; + while (1) { + /* Hang on fatal exit */ + } +} diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/tx_initialize_low_level.S b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/tx_initialize_low_level.S new file mode 100644 index 00000000..9081ef5a --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/tx_initialize_low_level.S @@ -0,0 +1,113 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +// Some portions generated by Claude Code (Opus 5) + +#include "csr.h" + + .section .data + .global __tx_free_memory_start +__tx_free_memory_start: + + .section .text + .align 4 + .global trap_entry + .extern trap_handler + .extern _tx_thread_context_save + .extern _tx_thread_context_restore + +trap_entry: + /* Read trap cause, program counter, and trap value */ + csrr a0, mcause + csrr a1, mepc + csrr a2, mtval + + /* Check if trap is synchronous (bit 63 is 0) */ + bgez a0, .synchronous_fault + + /* Asynchronous Interrupt (CLINT Timer) - Save ThreadX context */ +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi sp, sp, -520 // 65*8 with floating point +#else + addi sp, sp, -256 // 32*8 without floating point +#endif + sd x1, 224(sp) // Save RA at offset 224 (28*8) + + call _tx_thread_context_save + + csrr a0, mcause + csrr a1, mepc + csrr a2, mtval + addi sp, sp, -8 + sd ra, 0(sp) + call trap_handler + ld ra, 0(sp) + addi sp, sp, 8 + + call _tx_thread_context_restore + +_err_hang: + wfi + j _err_hang + +.synchronous_fault: + /* Synchronous exception / fatal trap: Call trap_handler directly */ + addi sp, sp, -8 + sd ra, 0(sp) + call trap_handler + ld ra, 0(sp) + addi sp, sp, 8 +.halt_loop: + wfi + j .halt_loop + + .section .text + .global _tx_initialize_low_level + .weak _tx_initialize_low_level + .extern _end + .extern hwtimer_init + +_tx_initialize_low_level: + /* Save the system stack pointer */ + la t0, _tx_thread_system_stack_ptr + sd sp, 0(t0) + + /* Pickup first free memory address */ + la t0, _end + la t1, _tx_initialize_unused_memory + sd t0, 0(t1) + + /* Configure machine interrupt registers */ + li t0, MSTATUS_MIE + csrrc zero, mstatus, t0 + li t0, (MSTATUS_MPP_M | MSTATUS_MPIE) + csrrs zero, mstatus, t0 + li t0, (MIE_MTIE | MIE_MEIE) + csrrs zero, mie, t0 + +#ifdef __riscv_flen + li t0, MSTATUS_FS + csrrs zero, mstatus, t0 + fscsr x0 +#endif + + /* Arm the CLINT machine timer that drives the ThreadX system tick. + * Board peripherals are brought up separately by bsp_board_init(). */ + addi sp, sp, -8 + sd ra, 0(sp) + call hwtimer_init + ld ra, 0(sp) + addi sp, sp, 8 + + /* Set Machine Trap-Vector Base Address to trap_entry */ + la t0, trap_entry + csrw mtvec, t0 + + ret diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/main.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/main.c new file mode 100644 index 00000000..50e3808a --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/main.c @@ -0,0 +1,328 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +// Some portions generated by Claude Code (Opus 5) + +#include +#include +#include +#include +#include +#include "tx_api.h" +#include "hwtimer.h" +#include "plic.h" +#include "csr.h" +#include "bsp/board.h" +#include "bsp/console.h" +#include "bsp/led.h" + +extern void *_sbrk(ptrdiff_t incr); + +/* board_config.h derives TICK_CYCLES from BSP_TICK_RATE_HZ without seeing the + * ThreadX headers. This translation unit sees both, so it is where the two are + * checked against each other. C99 has no _Static_assert, hence the negative + * array size idiom. */ +typedef char bsp_tick_rate_matches_threadx[ + (BSP_TICK_RATE_HZ == (unsigned long long)TX_TIMER_TICKS_PER_SECOND) ? 1 : -1]; + +#define DEMO_STACK_SIZE 4096 +#define DEMO_QUEUE_ITEMS 10 + +/* Sample and report periods expressed in milliseconds, converted to ThreadX + * ticks so they stay correct if TX_TIMER_TICKS_PER_SECOND is retuned. */ +#define DEMO_MS_TO_TICKS(ms) (((ms) * (ULONG)TX_TIMER_TICKS_PER_SECOND) / 1000UL) +#define DEMO_SAMPLE_PERIOD_MS 500UL +#define DEMO_REPORT_PERIOD_MS 1000UL + +typedef struct SENSOR_DATA_STRUCT { + ULONG timestamp; + float temperature_celsius; + uint32_t reserved; +} SENSOR_DATA; + +#define DEMO_QUEUE_MSG_WORDS (sizeof(SENSOR_DATA) / sizeof(ULONG)) + +TX_THREAD sampler_thread; +TX_THREAD analyzer_thread; +TX_THREAD reporter_thread; +TX_QUEUE sensor_queue; +TX_EVENT_FLAGS_GROUP alarm_flags; + +UCHAR sampler_stack[DEMO_STACK_SIZE]; +UCHAR analyzer_stack[DEMO_STACK_SIZE]; +UCHAR reporter_stack[DEMO_STACK_SIZE]; +UCHAR queue_area[DEMO_QUEUE_ITEMS * sizeof(SENSOR_DATA)]; + +#define ALARM_OVERTEMP 0x01 +#define EVENT_FLAG_UART_RX 0x02 + +volatile char g_last_rx_char = 0; +volatile uint32_t g_rx_irq_count = 0; +volatile uint32_t g_rx_flag_errors = 0; + +void console_rx_isr_callback(char c) { + g_last_rx_char = c; + g_rx_irq_count++; + if (tx_event_flags_set(&alarm_flags, EVENT_FLAG_UART_RX, TX_OR) != TX_SUCCESS) { + /* Cannot print from interrupt context; record the loss for the reporter. */ + g_rx_flag_errors++; + } +} + +static void console_print(const char *s) { + if (s) { + bsp_console_write(s, strlen(s)); + } +} + +void sampler_thread_entry(ULONG input); +void analyzer_thread_entry(ULONG input); +void reporter_thread_entry(ULONG input); + +static volatile ULONG s_sampler_runs = 0; +static volatile ULONG s_analyzer_runs = 0; +static volatile ULONG s_reporter_runs = 0; + +static unsigned s_selftest_failures = 0; + +static void selftest_report(int passed, const char *message) { + if (passed) { + console_print("[+] PASS: "); + } else { + s_selftest_failures++; + console_print("[-] FAIL: "); + } + console_print(message); + console_print("\n"); +} + +static void run_startup_self_tests(void) { + extern char __end; + char num_buf[160]; + console_print("[SELF-TEST] Starting Hardware & Runtime Verification...\n"); + + /* 1. _sbrk() Valid allocation test */ + void *p1 = _sbrk(64); + selftest_report(p1 != (void *)-1 && (uintptr_t)p1 >= (uintptr_t)&__end, + "_sbrk() valid allocation returned base pointer"); + + /* 2. _sbrk() Underflow test (shrink below heap base) */ + errno = 0; + void *p_under = _sbrk(-128); + selftest_report(p_under == (void *)-1 && errno == EINVAL, + "_sbrk() underflow guard rejected with EINVAL"); + + /* 3. _sbrk() Overflow test (request beyond 1 GiB DRAM) */ + errno = 0; + void *p_over = _sbrk((ptrdiff_t)0x40000000ULL); + selftest_report(p_over == (void *)-1 && errno == ENOMEM, + "_sbrk() overflow guard rejected with ENOMEM"); + + /* 4. HWTimer catch-up clamp. + * + * Exercised as pure arithmetic through hwtimer_next_cmp(), so no CLINT + * register is disturbed: mtime is the platform-wide counter shared by every + * hart, and mtimecmp drives the live kernel tick. Both branches are covered + * - a deadline still in the future advances relatively, one already missed + * is rebased onto the current time instead of firing continuously. */ + uint64_t now = 5000000ULL; + uint64_t missed_cmp = now - (TICK_CYCLES * 8ULL); /* 8 ticks behind */ + uint64_t pending_cmp = now - (TICK_CYCLES / 2ULL); /* deadline not yet due */ + int clamp_ok = (hwtimer_next_cmp(missed_cmp, now) == now + TICK_CYCLES) && + (hwtimer_next_cmp(pending_cmp, now) == pending_cmp + TICK_CYCLES); + snprintf(num_buf, sizeof(num_buf), + "HWTimer catch-up (missed deadline rebased to %llu, pending deadline advanced to %llu)", + (unsigned long long)hwtimer_next_cmp(missed_cmp, now), + (unsigned long long)hwtimer_next_cmp(pending_cmp, now)); + selftest_report(clamp_ok, num_buf); + + /* 5. PLIC Configuration & Addressing Verification. + * A wrong PLIC base would read back zeroes here, so the register values + * confirm the addressing as well as the configuration. */ + uint32_t prio = PLIC_PRIORITY_REG(MMUART1_IRQ); + uint32_t en_bitmap = PLIC_HART1_M_ENABLE_REG(MMUART1_IRQ); + uint32_t thresh = PLIC_HART1_M_THRESHOLD_REG; + uint64_t mie_val; + __asm__ volatile("csrr %0, mie" : "=r"(mie_val)); + + int plic_ok = (prio == 1) && + ((en_bitmap & (1U << (MMUART1_IRQ % 32))) != 0) && + (thresh == 0) && + ((mie_val & MIE_MEIE) != 0); + snprintf(num_buf, sizeof(num_buf), + "PLIC Hart 1 (IRQ %u prio=%u en=0x%08X thresh=%u mie=0x%llX)", + (unsigned)MMUART1_IRQ, (unsigned)prio, (unsigned)en_bitmap, + (unsigned)thresh, (unsigned long long)mie_val); + selftest_report(plic_ok, num_buf); + + if (s_selftest_failures == 0) { + console_print("[SELF-TEST] All startup verification tests PASSED!\n\n"); + } else { + snprintf(num_buf, sizeof(num_buf), + "[SELF-TEST] %u startup verification test(s) FAILED!\n\n", + s_selftest_failures); + console_print(num_buf); + } +} + +int main(void) { + /* Initialize Board Peripherals & MMUART1 */ + bsp_board_init(); + + console_print("\n====================================================\n"); + console_print("Microchip PolarFire SoC Icicle Kit (Renode Target)\n"); + console_print("64-Bit RISC-V Industrial LM75 Condition-Monitoring App\n"); + console_print("====================================================\n"); + + /* Execute Dynamic Hardware & Runtime Self-Tests */ + run_startup_self_tests(); + +#ifdef TEST_FAULT_INJECTION + console_print("[FAULT-TEST] Injecting deliberate synchronous illegal instruction...\n"); + __asm__ volatile(".word 0x00000000"); /* Illegal instruction to exercise trap_handler */ +#endif + + /* Enter ThreadX Kernel */ + tx_kernel_enter(); + + return 0; +} + +void tx_application_define(void *first_unused_memory) { + (void)first_unused_memory; + UINT status; + + /* Create Sensor Queue */ + status = tx_queue_create(&sensor_queue, "sensor queue", DEMO_QUEUE_MSG_WORDS, + queue_area, sizeof(queue_area)); + if (status != TX_SUCCESS) { + console_print("[ERROR] Failed to create sensor queue\n"); + return; + } + + /* Create Event Flags Group */ + status = tx_event_flags_create(&alarm_flags, "alarm flags"); + if (status != TX_SUCCESS) { + console_print("[ERROR] Failed to create alarm flags\n"); + return; + } + + /* Create Sampler Thread */ + status = tx_thread_create(&sampler_thread, "Sampler Thread", sampler_thread_entry, 0, + sampler_stack, DEMO_STACK_SIZE, + 10, 10, TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) { + console_print("[ERROR] Failed to create sampler thread\n"); + return; + } + + /* Create Analyzer Thread */ + status = tx_thread_create(&analyzer_thread, "Analyzer Thread", analyzer_thread_entry, 0, + analyzer_stack, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) { + console_print("[ERROR] Failed to create analyzer thread\n"); + return; + } + + /* Create Reporter Thread */ + status = tx_thread_create(&reporter_thread, "Reporter Thread", reporter_thread_entry, 0, + reporter_stack, DEMO_STACK_SIZE, + 12, 12, TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) { + console_print("[ERROR] Failed to create reporter thread\n"); + return; + } +} + +void sampler_thread_entry(ULONG input) { + (void)input; + SENSOR_DATA data; + float simulated_temp = 25.0f; + + while (1) { + s_sampler_runs++; + data.timestamp = tx_time_get(); + data.temperature_celsius = simulated_temp; + data.reserved = 0x55AA55AA; + + /* Send telemetry to Queue */ + UINT status = tx_queue_send(&sensor_queue, &data, TX_NO_WAIT); + if (status != TX_SUCCESS) { + console_print("[WARN] Telemetry queue send failed\n"); + } + + simulated_temp += 2.5f; + if (simulated_temp > 55.0f) { + simulated_temp = 25.0f; + } + + tx_thread_sleep(DEMO_MS_TO_TICKS(DEMO_SAMPLE_PERIOD_MS)); + } +} + +void analyzer_thread_entry(ULONG input) { + (void)input; + SENSOR_DATA data; + static int s_verified_queue = 0; + + while (1) { + if (tx_queue_receive(&sensor_queue, &data, TX_WAIT_FOREVER) == TX_SUCCESS) { + s_analyzer_runs++; + if (data.reserved != 0x55AA55AA) { + console_print("[-] FAIL: Queue payload corruption detected!\n"); + } else if (!s_verified_queue) { + s_verified_queue = 1; + console_print("[+] PASS: Queue 16-byte structure round-trip verified\n"); + } + + if (data.temperature_celsius > 45.0f) { + UINT status = tx_event_flags_set(&alarm_flags, ALARM_OVERTEMP, TX_OR); + if (status != TX_SUCCESS) { + console_print("[WARN] Alarm flag set failed\n"); + } + bsp_led_on(); + } else { + bsp_led_off(); + } + } + } +} + +void reporter_thread_entry(ULONG input) { + (void)input; + char msg_buf[160]; + ULONG actual_flags; + + while (1) { + s_reporter_runs++; + snprintf(msg_buf, sizeof(msg_buf), + "[Monitor] Ticks: %lu | Active Runs: Sampler=%lu, Analyzer=%lu, Reporter=%lu\n", + (unsigned long)tx_time_get(), + (unsigned long)s_sampler_runs, + (unsigned long)s_analyzer_runs, + (unsigned long)s_reporter_runs); + console_print(msg_buf); + + if (tx_event_flags_get(&alarm_flags, ALARM_OVERTEMP, TX_OR_CLEAR, &actual_flags, TX_NO_WAIT) == TX_SUCCESS) { + console_print("[LM75 Sensor] Temperature: OVERTEMP ALARM TRIGGERED (>45.0C)\n"); + } + + if (tx_event_flags_get(&alarm_flags, EVENT_FLAG_UART_RX, TX_OR_CLEAR, &actual_flags, TX_NO_WAIT) == TX_SUCCESS) { + char rx_buf[96]; + snprintf(rx_buf, sizeof(rx_buf), + "[Console RX] PLIC IRQ 91 handled: byte '%c' received and processed by ThreadX\n", + g_last_rx_char); + console_print(rx_buf); + } + + tx_thread_sleep(DEMO_MS_TO_TICKS(DEMO_REPORT_PERIOD_MS)); + } +} diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/CMakeLists.txt b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/CMakeLists.txt new file mode 100644 index 00000000..2c1005bd --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(bsp) diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/CMakeLists.txt b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/CMakeLists.txt new file mode 100644 index 00000000..a2111562 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/CMakeLists.txt @@ -0,0 +1,27 @@ +# +# 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/licenses/MIT. +# +# SPDX-License-Identifier: MIT +# + +# Static library compilation rule for Microchip PolarFire SoC Icicle Kit BSP Target +add_library(polarfire_bsp STATIC + src/bsp_board.c + src/bsp_led.c + src/bsp_console.c + src/board.c + src/uart.c + src/plic.c + src/hwtimer.c + src/trap.c +) + +target_include_directories(polarfire_bsp + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${SAMPLEX_ROOT_DIR}/bsp/include +) diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/board_config.h b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/board_config.h new file mode 100644 index 00000000..40400d9a --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/board_config.h @@ -0,0 +1,31 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +// Some portions generated by Claude Code (Opus 5) + +#ifndef BOARD_CONFIG_H +#define BOARD_CONFIG_H + +/* CPU Subsystem Frequencies */ +#define BSP_CPU_CLOCK_HZ 600000000ULL /* 600 MHz U54 Application Core Clock */ +#define BSP_SYSTEM_CLOCK_HZ BSP_CPU_CLOCK_HZ +#define BSP_CLINT_RTC_FREQ_HZ 1000000ULL /* 1 MHz Real-Time CLINT Clock in Renode */ + +/* ThreadX system tick rate. Must match TX_TIMER_TICKS_PER_SECOND; main.c + * enforces that with a compile-time check. */ +#define BSP_TICK_RATE_HZ 100ULL + +#define BSP_UART_BAUDRATE 115200 +#define BSP_RAM_END 0xC0000000ULL /* 1 GiB LPDDR4 DRAM End Address */ + +#define BSP_HAS_LED 1 +#define BSP_HAS_CONSOLE 1 + +#endif /* BOARD_CONFIG_H */ diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/csr.h b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/csr.h new file mode 100644 index 00000000..78da1ca1 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/csr.h @@ -0,0 +1,31 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +#ifndef RISCV_CSR_H +#define RISCV_CSR_H + +// Machine Status Register, mstatus +#define MSTATUS_MPP_MASK (3L << 11) // previous mode. +#define MSTATUS_MPP_M (3L << 11) +#define MSTATUS_MPP_S (1L << 11) +#define MSTATUS_MPP_U (0L << 11) +#define MSTATUS_MIE (1L << 3) // machine-mode interrupt enable. +#define MSTATUS_MPIE (1L << 7) +#define MSTATUS_FS (1L << 13) + +// Machine-mode Interrupt Enable +#define MIE_MTIE (1L << 7) +#define MIE_MSIE (1L << 3) +#define MIE_MEIE (1L << 11) +#define MIE_STIE (1L << 5) // supervisor timer +#define MIE_SSIE (1L << 1) +#define MIE_SEIE (1L << 9) + +#endif /* RISCV_CSR_H */ diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/hwtimer.h b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/hwtimer.h new file mode 100644 index 00000000..72ab0150 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/hwtimer.h @@ -0,0 +1,47 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +#ifndef POLARFIRE_HWTIMER_H +#define POLARFIRE_HWTIMER_H + +#include +#include "board_config.h" + +#define CLINT_BASE 0x02000000ULL +#define MTIME_REG (*(volatile uint64_t *)(CLINT_BASE + 0xBFF8)) +#define HART1_MTIMECMP_REG (*(volatile uint64_t *)(CLINT_BASE + 0x4008)) + +/* CLINT cycles between ThreadX system ticks. BSP_TICK_RATE_HZ lives in + * board_config.h so this header stays independent of the ThreadX includes; + * main.c carries a compile-time check that it still agrees with + * TX_TIMER_TICKS_PER_SECOND, so the two cannot silently desync. */ +#define TICK_CYCLES (BSP_CLINT_RTC_FREQ_HZ / BSP_TICK_RATE_HZ) + +void hwtimer_init(void); +void hwtimer_ack(void); + +/** + * @brief Compute the comparand for the next system tick. + * + * Normally this is one tick past the previous deadline. If the previous + * deadline is already at or behind @p now, one or more ticks were missed and + * re-arming relatively would leave the timer firing continuously until it + * caught up, so the deadline is rebased onto @p now instead. + * + * Kept as a pure function of its arguments so the catch-up behaviour can be + * verified without writing to the CLINT. + * + * @param current_cmp Comparand currently programmed into mtimecmp. + * @param now Current value of the shared mtime counter. + * @return Comparand to program for the next tick. + */ +uint64_t hwtimer_next_cmp(uint64_t current_cmp, uint64_t now); + +#endif /* POLARFIRE_HWTIMER_H */ diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/plic.h b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/plic.h new file mode 100644 index 00000000..8133a828 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/plic.h @@ -0,0 +1,62 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +// Some portions generated by Claude Code (Opus 5) + +#ifndef PLIC_H +#define PLIC_H + +#include + +/* SiFive PLIC Base Address on Microchip PolarFire SoC Icicle Kit */ +#define PLIC_BASE 0x0C000000ULL + +/* Standard SiFive PLIC register-block offsets. */ +#define PLIC_PRIORITY_OFFSET 0x000000ULL /* 4 bytes per source */ +#define PLIC_ENABLE_OFFSET 0x002000ULL /* 0x80 per context */ +#define PLIC_CONTEXT_OFFSET 0x200000ULL /* 0x1000 per context */ + +/* + * PolarFire SoC PLIC context assignment. The E51 monitor core has machine mode + * only; each U54 application core contributes a machine-mode context followed + * by a supervisor-mode one: + * + * 0: E51 M 3: U54_2 M 5: U54_3 M 7: U54_4 M + * 1: U54_1 M 4: U54_2 S 6: U54_3 S 8: U54_4 S + * 2: U54_1 S + * + * ThreadX runs in machine mode on Hart 1 (u54_1), so the correct context is 1. + * Context 2 is the supervisor-mode context for the same hart: programming it + * is silently accepted by the PLIC but leaves the machine-mode enable bitmap + * clear, so MEIP never asserts and no external interrupt is ever delivered. + */ +#define PLIC_HART1_M_CONTEXT 1U + +#define PLIC_CONTEXT_BASE(ctx) (PLIC_BASE + PLIC_CONTEXT_OFFSET + ((uint64_t)(ctx) * 0x1000ULL)) +#define PLIC_ENABLE_BASE(ctx) (PLIC_BASE + PLIC_ENABLE_OFFSET + ((uint64_t)(ctx) * 0x80ULL)) + +/* Hart 1 Machine-Mode (Context 1) Control Registers */ +#define PLIC_HART1_M_THRESHOLD_REG (*(volatile uint32_t *)(PLIC_CONTEXT_BASE(PLIC_HART1_M_CONTEXT))) +#define PLIC_HART1_M_CLAIM_REG (*(volatile uint32_t *)(PLIC_CONTEXT_BASE(PLIC_HART1_M_CONTEXT) + 4ULL)) + +/* Hart 1 Machine-Mode enable bitmap word holding source `irq` (32 sources per word) */ +#define PLIC_HART1_M_ENABLE_REG(irq) (*(volatile uint32_t *)(PLIC_ENABLE_BASE(PLIC_HART1_M_CONTEXT) + (((uint64_t)(irq) / 32ULL) * 4ULL))) + +/* Interrupt Source Priority Register (1..186) */ +#define PLIC_PRIORITY_REG(irq) (*(volatile uint32_t *)(PLIC_BASE + PLIC_PRIORITY_OFFSET + ((irq) * 4ULL))) + +/* Microchip PolarFire SoC MMUART1 PLIC Source ID */ +#define MMUART1_IRQ 91 + +void plic_init(void); +uint32_t plic_claim(void); +void plic_complete(uint32_t irq); + +#endif /* PLIC_H */ diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/uart.h b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/uart.h new file mode 100644 index 00000000..9d980492 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/uart.h @@ -0,0 +1,26 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +#ifndef POLARFIRE_UART_H +#define POLARFIRE_UART_H + +#include +#include + +#define MMUART1_BASE 0x20100000ULL + +void uart_init(void); +void uart_putc(char ch); +void uart_puts(const char *str); +void uart_write(const char *data, size_t len); +int uart_has_rx(void); +char uart_getc(void); + +#endif /* POLARFIRE_UART_H */ diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/board.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/board.c new file mode 100644 index 00000000..91192bba --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/board.c @@ -0,0 +1,25 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +// Some portions generated by Claude Code (Opus 5) + +#include "plic.h" + +/* Board-level peripheral bring-up, owned by bsp_board_init(). + * + * The ThreadX system tick is deliberately NOT started here: hwtimer_init() is + * called from _tx_initialize_low_level so the CLINT comparand is armed + * immediately before the scheduler starts, which is the single owner of the + * kernel tick. Keeping the two apart avoids the peripheral being initialised + * twice on the path main() -> bsp_board_init() -> tx_kernel_enter(). */ +void board_init(void) { + /* Initialize PLIC (Hart 1 Context 2, enable MMUART1 IRQ 91) */ + plic_init(); +} diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_board.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_board.c new file mode 100644 index 00000000..293c5a86 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_board.c @@ -0,0 +1,29 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +#include +#include "bsp/board.h" +#include "bsp/console.h" +#include "bsp/led.h" +#include "board_config.h" + +extern void board_init(void); + +void bsp_board_init(void) { + /* Initialize PolarFire hardware peripherals */ + board_init(); + + bsp_console_init(); + bsp_led_init(); +} + +uint32_t bsp_board_get_system_clock(void) { + return (uint32_t)BSP_SYSTEM_CLOCK_HZ; +} diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_console.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_console.c new file mode 100644 index 00000000..4695e21b --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_console.c @@ -0,0 +1,29 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +#include "bsp/console.h" +#include "board_config.h" +#include + +extern void uart_init(void); +extern void uart_write(const char *data, size_t len); + +void bsp_console_init(void) { +#if BSP_HAS_CONSOLE + uart_init(); +#endif +} + +void bsp_console_write(const char *data, size_t length) { +#if BSP_HAS_CONSOLE + if (!data || length == 0) return; + uart_write(data, length); +#endif +} diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_led.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_led.c new file mode 100644 index 00000000..a8e3590e --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_led.c @@ -0,0 +1,39 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +#include +#include "bsp/led.h" +#include "board_config.h" + +static bool s_virtual_led_state = false; + +void bsp_led_init(void) { +#if BSP_HAS_LED + s_virtual_led_state = false; +#endif +} + +void bsp_led_on(void) { +#if BSP_HAS_LED + s_virtual_led_state = true; +#endif +} + +void bsp_led_off(void) { +#if BSP_HAS_LED + s_virtual_led_state = false; +#endif +} + +void bsp_led_toggle(void) { +#if BSP_HAS_LED + s_virtual_led_state = !s_virtual_led_state; +#endif +} diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/hwtimer.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/hwtimer.c new file mode 100644 index 00000000..2f7635a2 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/hwtimer.c @@ -0,0 +1,34 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +// Some portions generated by Claude Code (Opus 5) + +#include "hwtimer.h" + +void hwtimer_init(void) { + /* Program initial mtimecmp target to current mtime + 10,000 cycles (10ms) */ + uint64_t current_mtime = MTIME_REG; + HART1_MTIMECMP_REG = current_mtime + TICK_CYCLES; +} + +uint64_t hwtimer_next_cmp(uint64_t current_cmp, uint64_t now) { + uint64_t next_cmp = current_cmp + TICK_CYCLES; + + /* Deadline already missed: rebase onto now rather than chasing it. */ + if (next_cmp <= now) { + next_cmp = now + TICK_CYCLES; + } + + return next_cmp; +} + +void hwtimer_ack(void) { + HART1_MTIMECMP_REG = hwtimer_next_cmp(HART1_MTIMECMP_REG, MTIME_REG); +} diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/plic.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/plic.c new file mode 100644 index 00000000..f4f5fd7d --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/plic.c @@ -0,0 +1,36 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +// Some portions generated by Claude Code (Opus 5) + +#include "plic.h" +#include "csr.h" + +void plic_init(void) { + /* Set Priority for MMUART1 (IRQ 91) to 1 */ + PLIC_PRIORITY_REG(MMUART1_IRQ) = 1; + + /* Enable IRQ 91 for Hart 1 Machine Mode (Context 1). Bit position = 91 % 32 = 27 */ + PLIC_HART1_M_ENABLE_REG(MMUART1_IRQ) |= (1U << (MMUART1_IRQ % 32)); + + /* Set Priority Threshold for Hart 1 to 0 (allow all non-zero priority interrupts) */ + PLIC_HART1_M_THRESHOLD_REG = 0; + + /* Enable Machine External Interrupts in CPU mie register */ + __asm__ volatile("csrs mie, %0" : : "r"(MIE_MEIE)); +} + +uint32_t plic_claim(void) { + return PLIC_HART1_M_CLAIM_REG; +} + +void plic_complete(uint32_t irq) { + PLIC_HART1_M_CLAIM_REG = irq; +} diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/trap.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/trap.c new file mode 100644 index 00000000..00795f5a --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/trap.c @@ -0,0 +1,68 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +#include +#include "hwtimer.h" +#include "plic.h" +#include "uart.h" + +extern void _tx_timer_interrupt(void); +extern void console_rx_isr_callback(char c); + +static void print_hex64(uint64_t val) { + const char hex_chars[] = "0123456789ABCDEF"; + char buf[19]; + buf[0] = '0'; + buf[1] = 'x'; + for (int i = 15; i >= 0; --i) { + buf[2 + (15 - i)] = hex_chars[(val >> (i * 4)) & 0xF]; + } + buf[18] = '\0'; + uart_puts(buf); +} + +void trap_handler(uint64_t mcause, uint64_t mepc, uint64_t mtval) { + /* Check if trap is an interrupt (bit 63 set) */ + if (mcause & (1ULL << 63)) { + uint64_t irq = mcause & 0x3FULL; + if (irq == 7) { + /* Machine Timer Interrupt (CLINT MTIME) */ + hwtimer_ack(); + _tx_timer_interrupt(); + return; + } else if (irq == 11) { + /* Machine External Interrupt (PLIC) */ + uint32_t source = plic_claim(); + if (source == MMUART1_IRQ) { + while (uart_has_rx()) { + char c = uart_getc(); + console_rx_isr_callback(c); + } + } + plic_complete(source); + return; + } + } + + /* Unhandled interrupt or synchronous exception */ + uart_puts("\r\n========================================\r\n"); + uart_puts("[FATAL TRAP] System Halted!\r\n"); + uart_puts(" mcause: "); + print_hex64(mcause); + uart_puts("\r\n mepc: "); + print_hex64(mepc); + uart_puts("\r\n mtval: "); + print_hex64(mtval); + uart_puts("\r\n========================================\r\n"); + + while (1) { + __asm__ volatile("wfi"); + } +} diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/uart.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/uart.c new file mode 100644 index 00000000..57767aa0 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/uart.c @@ -0,0 +1,59 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +#include "uart.h" + +#define REG_THR (*(volatile uint32_t *)(MMUART1_BASE + 0x00)) +#define REG_RBR (*(volatile uint32_t *)(MMUART1_BASE + 0x00)) +#define REG_IER (*(volatile uint32_t *)(MMUART1_BASE + 0x04)) +#define REG_LCR (*(volatile uint32_t *)(MMUART1_BASE + 0x0C)) +#define REG_LSR (*(volatile uint32_t *)(MMUART1_BASE + 0x14)) + +#define LSR_THRE 0x20 /* Transmitter Holding Register Empty */ + +void uart_init(void) { + /* 8 data bits, 1 stop bit, no parity (8-N-1) */ + REG_LCR = 0x03; + /* Enable Received Data Available (ERBFI, bit 0) interrupt for PLIC IRQ 91 */ + REG_IER = 0x01; +} + +int uart_has_rx(void) { + return (REG_LSR & 0x01); /* Bit 0: Data Ready */ +} + +char uart_getc(void) { + return (char)(REG_RBR & 0xFF); +} + +void uart_putc(char ch) { + /* Poll Transmitter Holding Register Empty (THRE) bit */ + while ((REG_LSR & LSR_THRE) == 0); + REG_THR = (uint32_t)ch; + + if (ch == '\n') { + while ((REG_LSR & LSR_THRE) == 0); + REG_THR = '\r'; + } +} + +void uart_puts(const char *str) { + if (!str) return; + while (*str) { + uart_putc(*str++); + } +} + +void uart_write(const char *data, size_t len) { + if (!data || len == 0) return; + for (size_t i = 0; i < len; i++) { + uart_putc(data[i]); + } +} diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_ci.resc b/targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_ci.resc new file mode 100644 index 00000000..27ba34e3 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_ci.resc @@ -0,0 +1,46 @@ +:name: PolarFire SoC - ThreadX Demo (headless CI run) +:description: Deterministic virtual-time run driven by scripts/test_renode.py. + +# This is a standalone counterpart to polarfire_demo.resc rather than an include +# of it. Renode resolves $ORIGIN only in variable assignment, so an included +# script cannot be located relative to the file including it, and the two run +# differently anyway: the demo script free-runs for interactive use, while this +# one steps through fixed virtual-time intervals so the run is reproducible and +# terminates on its own instead of depending on wall clock. + +Clear + +using sysbus +mach create "PolarFire_SoC_Icicle" +machine LoadPlatformDescription @platforms/cpus/polarfire-soc.repl + +# Under --plain --disable-gui this logs MMUART1 traffic to stdout, which is +# what the assertions in test_renode.py read. +showAnalyzer mmuart1 + +$bin?=$ORIGIN/../build/app/polarfire_icicle_demo.elf + +macro reset +""" + sysbus LoadELF $bin + # Route execution directly to Hart 1 (U54 Core 1) + u54_1 PC `e51 PC` + e51 IsHalted true + u54_2 IsHalted true + u54_3 IsHalted true + u54_4 IsHalted true +""" +runMacro $reset + +# Boot, startup self-tests, and the first system ticks. +emulation RunFor "0.5" + +# Deliver a byte to MMUART1. This is the only step that exercises the PLIC +# external-interrupt path: configuring the controller and reading its registers +# back cannot distinguish the machine-mode context from the supervisor one. +mmuart1 WriteChar 88 + +# Long enough for the simulated LM75 ramp to cross the 45C alarm threshold. +emulation RunFor "7" + +quit diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_demo.resc b/targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_demo.resc new file mode 100644 index 00000000..6cf2cee5 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_demo.resc @@ -0,0 +1,29 @@ +:name: PolarFire SoC - ThreadX Industrial LM75 Demo +:description: Eclipse ThreadX RTOS on Microchip PolarFire SoC (Renode 64-Bit RISC-V) + +# Clear previous emulation state +Clear + +using sysbus +mach create "PolarFire_SoC_Icicle" +machine LoadPlatformDescription @platforms/cpus/polarfire-soc.repl + +# Show terminal analyzer for Hart 1 (u54_1) MMUART1 at 0x20100000 +showAnalyzer mmuart1 + +# Portable relative path using Renode's built-in $ORIGIN variable +$bin?=$ORIGIN/../build/app/polarfire_icicle_demo.elf + +macro reset +""" + sysbus LoadELF $bin + # Route execution directly to Hart 1 (U54 Core 1) + u54_1 PC `e51 PC` + e51 IsHalted true + u54_2 IsHalted true + u54_3 IsHalted true + u54_4 IsHalted true +""" +runMacro $reset + +start diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_demo.robot b/targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_demo.robot new file mode 100644 index 00000000..0d982533 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_demo.robot @@ -0,0 +1,25 @@ +*** Settings *** +Suite Setup Setup +Suite Teardown Teardown +Test Setup Reset Emulation +Test Teardown Test Teardown +Resource ${RENODEKEYWORDS} + +*** Test Cases *** +Should Boot ThreadX And Trigger Telemetry Alarms + Execute Command include @${CURDIR}/polarfire_demo.resc + Create Terminal Tester sysbus.mmuart1 + + Wait For Line On Uart Microchip PolarFire SoC Icicle Kit (Renode Target) timeout=10 + Wait For Line On Uart [SELF-TEST] All startup verification tests PASSED! timeout=10 + Wait For Line On Uart [Monitor] Ticks: 0 timeout=10 + Wait For Line On Uart [Monitor] Ticks: 100 timeout=10 + Wait For Line On Uart OVERTEMP ALARM TRIGGERED timeout=15 + +Should Deliver MMUART1 RX Interrupt Through The PLIC + Execute Command include @${CURDIR}/polarfire_demo.resc + Create Terminal Tester sysbus.mmuart1 + + Wait For Line On Uart [Monitor] Ticks: 0 timeout=10 + Write Char On Uart X + Wait For Line On Uart PLIC IRQ 91 handled timeout=10 diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/build.ps1 b/targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/build.ps1 new file mode 100644 index 00000000..8e57b262 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/build.ps1 @@ -0,0 +1,77 @@ +# PowerShell build automation script for Microchip PolarFire SoC Icicle Kit (Renode 64-Bit RISC-V Target) + +param( + [switch]$Clean, + [switch]$Rebuild, + [string]$BuildType = "Debug", + [string]$ToolchainPath = "" +) + +$ErrorActionPreference = "Stop" +$TargetDir = Split-Path -Parent $PSScriptRoot +$BuildDir = Join-Path $TargetDir "build" + +Write-Host "==========================================" -ForegroundColor Cyan +Write-Host " Building PolarFire SoC Icicle Kit Target " -ForegroundColor Cyan +Write-Host "==========================================" -ForegroundColor Cyan + +# 1. Dynamic Toolchain Path Detection +if ($ToolchainPath -ne "") { + $env:RISCV64_TOOLCHAIN_PATH = $ToolchainPath +} elseif (-not $env:RISCV64_TOOLCHAIN_PATH) { + # Check default toolchain candidates in user profile + $Candidates = @( + (Join-Path $env:USERPROFILE "Downloads\xpack-riscv-none-elf-gcc-14.2.0-1-win32-x64\xpack-riscv-none-elf-gcc-14.2.0-1"), + (Join-Path $env:USERPROFILE "Downloads\tools\xpack-riscv-none-elf-gcc-14.2.0-1"), + (Join-Path $env:ProgramFiles "xpack-riscv-none-elf-gcc-14.2.0-1") + ) + foreach ($Candidate in $Candidates) { + if (Test-Path $Candidate) { + $env:RISCV64_TOOLCHAIN_PATH = $Candidate + break + } + } +} + +# 2. Dynamic Ninja Tool Detection +$NinjaCandidates = @( + (Join-Path $env:USERPROFILE "Downloads\tools\ninja-win"), + (Join-Path $env:ProgramFiles "Ninja") +) +foreach ($NinjaPath in $NinjaCandidates) { + if (Test-Path $NinjaPath) { + $env:PATH = "$NinjaPath;" + $env:PATH + break + } +} + +if ($env:RISCV64_TOOLCHAIN_PATH) { + Write-Host "Using RISCV64_TOOLCHAIN_PATH: $env:RISCV64_TOOLCHAIN_PATH" -ForegroundColor Yellow +} + +if ($Clean -or $Rebuild) { + if (Test-Path $BuildDir) { + Write-Host "Cleaning build directory..." -ForegroundColor Yellow + Remove-Item -Path $BuildDir -Recurse -Force + } +} + +if (-not (Test-Path $BuildDir)) { + New-Item -Path $BuildDir -ItemType Directory | Out-Null +} + +Push-Location $BuildDir +try { + Write-Host "Configuring CMake (Ninja Generator)..." -ForegroundColor Green + cmake -G "Ninja" "-DCMAKE_BUILD_TYPE=$BuildType" .. + + Write-Host "Building target binaries..." -ForegroundColor Green + ninja + + Write-Host "==========================================" -ForegroundColor Cyan + Write-Host " Build Completed Successfully! " -ForegroundColor Green + Write-Host "==========================================" -ForegroundColor Cyan +} +finally { + Pop-Location +} diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/build.sh b/targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/build.sh new file mode 100644 index 00000000..bd5eaa9e --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/build.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# SPDX-License-Identifier: MIT + +# Fail on error +set -e + +BUILD_TYPE="Debug" +CLEAN=false +REBUILD=false + +# Directory resolution +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)" +TARGET_DIR="$(dirname "$SCRIPT_DIR")" +BUILD_DIR="$TARGET_DIR/build" + +# Print banner +echo "==========================================" +echo " PolarFire SoC Icicle Kit - Build (Bash) " +echo "==========================================" +echo "Target Dir: $TARGET_DIR" +echo "Build Dir: $BUILD_DIR" +echo "Build Type: $BUILD_TYPE" +echo "" + +# Parse options +while [[ $# -gt 0 ]]; do + case "$1" in + --clean) + CLEAN=true + shift + ;; + --rebuild) + REBUILD=true + shift + ;; + --release) + BUILD_TYPE="Release" + shift + ;; + *) + echo "Unknown option: $1" + echo "Usage: $0 [--clean] [--rebuild] [--release]" + exit 1 + ;; + esac +done + +if [ "$CLEAN" = true ] || [ "$REBUILD" = true ]; then + echo "[INFO] Cleaning build directory..." + if [ -d "$BUILD_DIR" ]; then + rm -rf "$BUILD_DIR" + fi +fi + +mkdir -p "$BUILD_DIR" +cd "$BUILD_DIR" + +echo "[INFO] Configuring CMake..." +if command -v ninja &>/dev/null; then + cmake -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" "$TARGET_DIR" + echo "[INFO] Building with Ninja..." + ninja +else + cmake -DCMAKE_BUILD_TYPE="$BUILD_TYPE" "$TARGET_DIR" + echo "[INFO] Building..." + cmake --build . +fi + +echo "" +echo "==========================================" +echo "[OK] Build completed successfully!" +echo "==========================================" diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py b/targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py new file mode 100644 index 00000000..c9731e9b --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 +# +# 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/licenses/MIT. +# +# SPDX-License-Identifier: MIT +# + +""" +Headless Renode Verification Test for PolarFire SoC Icicle Kit ThreadX Demo +""" + +import os +import sys +import time +import subprocess +import shutil +import threading +import queue + +# Deterministic virtual-time run script. It injects RX_TEST_CHAR into MMUART1 +# itself; Renode's monitor is not on stdin, so injection has to happen there. +RESC_NAME = "polarfire_ci.resc" +RX_TEST_CHAR = "X" + +def find_renode(): + # Check PATH first + renode_bin = shutil.which("renode") + if renode_bin: + return renode_bin + + # Common Windows locations + win_paths = [ + r"C:\Program Files\Renode\renode.exe", + os.path.expanduser(r"~\AppData\Local\Programs\Renode\renode.exe") + ] + for path in win_paths: + if os.path.isfile(path): + return path + + return "renode" + +def reader_thread_fn(pipe, q): + try: + for line in iter(pipe.readline, ''): + q.put(line) + except Exception: + pass + finally: + pipe.close() + +def run_test(test_timeout_mode=False): + renode = find_renode() + script_dir = os.path.dirname(os.path.abspath(__file__)) + target_dir = os.path.dirname(script_dir) + resc_path = os.path.join(target_dir, "renode", RESC_NAME).replace("\\", "/") + + if test_timeout_mode: + print("[*] Running intentional timeout test mode (2.0s deadline against unresponsive wait)...") + timeout_seconds = 2.0 + else: + print(f"[*] Starting headless Renode test using: {renode}") + print(f"[*] Loading script: {resc_path}") + timeout_seconds = 120.0 + + cmd = [ + renode, + "--plain", + "--disable-gui", + "--port", "-1", + "-e", f"include @{resc_path}" + ] + + proc = subprocess.Popen( + cmd, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + bufsize=1 + ) + + output_q = queue.Queue() + reader_t = threading.Thread(target=reader_thread_fn, args=(proc.stdout, output_q), daemon=True) + reader_t.start() + + output_lines = [] + found_selftests = False + found_selftest_failure = False + found_ticks = False + found_alarm = False + found_plic_rx = False + start_time = time.time() + + try: + while time.time() - start_time < timeout_seconds: + try: + line = output_q.get(timeout=0.1) + output_lines.append(line) + print(line, end="") + if test_timeout_mode: + continue + + if "[-] FAIL:" in line or "startup verification test(s) FAILED" in line: + found_selftest_failure = True + if "[SELF-TEST] All startup verification tests PASSED!" in line: + found_selftests = True + if "Ticks:" in line: + found_ticks = True + if "OVERTEMP ALARM TRIGGERED" in line: + found_alarm = True + if "PLIC IRQ 91 handled" in line: + found_plic_rx = True + + # A failed self-test is recorded but does not stop the run, so + # the remaining assertions are still reported rather than hidden. + if (found_selftests and not found_selftest_failure + and found_ticks and found_alarm and found_plic_rx): + print("\n[+] SUCCESS: startup self-tests, ThreadX ticks, " + "LM75 alarm, and PLIC RX interrupt all verified!") + break + except queue.Empty: + if proc.poll() is not None: + break + finally: + try: + proc.terminate() + proc.wait(timeout=2) + except Exception: + try: + proc.kill() + except Exception: + pass + + if test_timeout_mode: + elapsed = time.time() - start_time + print(f"\n[+] SUCCESS: Intentional timeout triggered after {elapsed:.2f}s " + f"and terminated child process cleanly.") + sys.exit(0) + + checks = { + "startup self-tests passed": found_selftests and not found_selftest_failure, + "ThreadX system tick advancing": found_ticks, + "LM75 overtemperature alarm": found_alarm, + "PLIC IRQ 91 RX interrupt delivered": found_plic_rx, + } + failed = [name for name, ok in checks.items() if not ok] + + if not failed: + print("[+] Renode headless test PASSED.") + sys.exit(0) + + print("\n[-] FAILED. Unmet assertions:") + for name in failed: + print(" - %s" % name) + sys.exit(1) + +if __name__ == "__main__": + timeout_test = "--test-timeout" in sys.argv + run_test(test_timeout_mode=timeout_test) diff --git a/templates/target/CMakeLists.txt b/templates/target/CMakeLists.txt new file mode 100644 index 00000000..13ac5b52 --- /dev/null +++ b/templates/target/CMakeLists.txt @@ -0,0 +1,54 @@ +# 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/licenses/MIT. +# +# SPDX-License-Identifier: MIT + +cmake_minimum_required(VERSION 3.15) + +# TODO: Replace 'TARGET_BOARD_TEMPLATE' with your target board name (e.g. MY_CUSTOM_BOARD) +project(TARGET_BOARD_TEMPLATE C CXX ASM) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) + +# Define root paths +get_filename_component(WORKSPACE_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../.." ABSOLUTE) +set(SHARED_LIB_DIR "${WORKSPACE_ROOT}/libs") +set(SHARED_APP_DIR "${WORKSPACE_ROOT}/apps") +set(SHARED_BSP_DIR "${WORKSPACE_ROOT}/bsp") +set(SHARED_CMAKE_DIR "${WORKSPACE_ROOT}/cmake") + +# Include GNU ARM Toolchain setup if building for bare-metal ARM Cortex-M +if(EXISTS "${SHARED_CMAKE_DIR}/gcc-arm-none-eabi.cmake") + include("${SHARED_CMAKE_DIR}/gcc-arm-none-eabi.cmake") +endif() + +# Global compiler flags +add_compile_options( + -g3 + -ffunction-sections + -fdata-sections + -fno-strict-aliasing + -fno-builtin + -fno-common + -Wall + -Wshadow + -Wdouble-promotion + -Werror + -Wno-unused-parameter +) + +# Global preprocessor definitions +add_compile_definitions( + TX_INCLUDE_USER_DEFINE_FILE +) + +# TODO: Add vendor SDK / HAL subdirectories here if needed +# Example: add_subdirectory(lib/vendor_hal) + +# Add libraries and application targets +add_subdirectory(lib) +add_subdirectory(app) diff --git a/templates/target/README.md b/templates/target/README.md new file mode 100644 index 00000000..43a35a13 --- /dev/null +++ b/templates/target/README.md @@ -0,0 +1,144 @@ +# Target Board Onboarding Blueprint & Template Guide + +The core philosophy of the Eclipse ThreadX Reusable BSP Framework is to separate platform-independent application logic from board-specific hardware implementations through abstract C interfaces. By establishing a strict boundary between generic application code and physical registers, the same application source code can be compiled for multiple hardware targets (such as STM32, Raspberry Pi Pico, ESP32, or NXP platforms using vendor SDKs or other platform support packages) without requiring changes to the application itself. + +This directory contains the skeletal blueprint for onboarding a new hardware board into the framework. + +> [!NOTE] +> **Blueprint Nature**: +> This template is a **documented blueprint**, not a compilable target out-of-the-box. To compile it successfully, the developer must supply target-specific startup assemblies, linker scripts, and a vendor SDK or platform support package. + +--- + +## 1. Dependency Flow Architecture + +The following diagram illustrates how the generic application layer is decoupled from physical MCU registers using the BSP framework: + +```mermaid +flowchart TD + App["Generic Application (apps/threadx_demo/main.c)"] + BSP_API["BSP Interface Contract (bsp/include/bsp/)"] + Target_BSP["Target BSP Driver Library (targets/<Vendor>/<Board>/lib/bsp/)"] + Vendor_SDK["Vendor SDK / Platform Support Libraries"] + Hardware["Physical Target Board Hardware"] + + App -->|Uses generic C APIs| BSP_API + BSP_API -->|Implemented by| Target_BSP + Target_BSP -->|Controls hardware via| Vendor_SDK + Vendor_SDK -->|Configures| Hardware +``` + +### High-Level Repository Layout + +```text +Repository +│ +├── apps/ (Platform-independent application logic) +├── bsp/ (Target-agnostic C interface contracts) +├── cmake/ (Shared build infrastructure & toolchains) +└── targets/ (Independent board support implementations) + ├── STMicroelectronics/NUCLEO_F401RE/ + └── Microchip/POLARFIRE_ICICLE_RENODE/ +``` + +--- + +## 2. Shared Directory Governance & BSP Ownership + +To maintain long-term framework maintainability and portability, the following root directories should generally remain **unchanged** when onboarding a new board: + +* `/apps`: Contains shared example applications and reusable demos (such as `threadx_demo`). Applications in this directory interact with hardware solely through the abstract headers in ``. Developers may also add additional applications alongside the provided examples. +* `/bsp`: Defines the target-agnostic C interface contracts (`board.h`, `led.h`, `console.h`). New board targets must implement these existing interfaces rather than modifying core interface definitions. +* `/cmake`: Contains shared cross-compilation toolchain settings and build utility functions. + +> [!NOTE] +> **Core Architectural Principle**: +> The framework intentionally standardizes only the BSP interface and build structure. Board startup code, linker scripts, and vendor SDK integration remain board-specific. + +> [!IMPORTANT] +> **Independent Target BSP Ownership**: +> Each target board owns its BSP implementation independently within `targets///`. No BSP code is shared across target directories, guaranteeing that modifying or updating one board target will never cause side effects or build regressions on another target. + +--- + +## 3. "What Goes Where" Asset Mapping + +The table below maps common embedded software components to their designated locations within a target board package: + +| Asset / Component | Framework Location | Sourced From | +| :--- | :--- | :--- | +| **Vendor SDK / Platform Libraries** | `targets///lib/vendor/` or external CMake package | Official MCU Vendor SDK / Reference Package | +| **Startup Assembly & System Code** | `targets///app/common/startup/` | Vendor SDK (`startup_.s`, `system_.c`) | +| **Linker Script** | `targets///app/common/linker/` | Vendor SDK (`.ld` or compiler script) | +| **ThreadX Low-Level Setup** | `targets///app/common/startup/` | `libs/threadx/ports///src/` | +| **BSP Driver Implementation** | `targets///lib/bsp/src/` | Target developer (`bsp_board.c`, `bsp_led.c`, `bsp_console.c`) | +| **Target Specification Constants** | `targets///lib/bsp/include/board_config.h` | Target developer (declarative defines only) | +| **Target Build Automation** | `targets///scripts/build.ps1` | Target developer (PowerShell automation template) | +| **Shared Application Code** | `/apps//` | Framework shared application layer (remains in root) | + +--- + +## 4. Quick-Start Onboarding Steps + +To add support for a new board (e.g. `MY_VENDOR / MY_BOARD`): + +1. **Copy the Template Directory**: + Copy `/templates/target/` to `/targets///`. + ```bash + cp -r templates/target targets/MyVendor/MY_BOARD + ``` + +2. **Configure Board Hardware Specs**: + Edit `targets/MyVendor/MY_BOARD/lib/bsp/include/board_config.h`. This file contains **compile-time configuration constants only** (no executable code or function prototypes) and is consumed by the target BSP implementation layer to configure clock trees, UART registers, and dynamic memory boundaries: + - Set `BSP_SYSTEM_CLOCK_HZ` to your core CPU frequency. + - Set `BSP_UART_BAUDRATE` to your debug serial speed. + - Set `BSP_RAM_END` to the physical top address of your MCU SRAM. + +3. **Implement Abstract C BSP Drivers**: + Populate the driver stubs in `targets/MyVendor/MY_BOARD/lib/bsp/src/`: + - `bsp_board.c`: Configure System Clocks, Flash Wait States, and low-level timers in `bsp_board_init()`. + - `bsp_led.c`: Configure GPIO pin muxing and implement `bsp_led_on()`, `bsp_led_off()`, `bsp_led_toggle()`. + - `bsp_console.c`: Configure UART peripheral and implement `bsp_console_write()`. + +4. **Add Startup Files & Linker Script**: + Obtain the standard startup assembly (`startup_.s`), system initialization (`system_.c`), and linker script (`.ld`) **directly from your MCU vendor's official SDK or reference package** (do not write these from scratch). Developers should avoid modifying vendor startup code unless strictly necessary, as these files are maintained by the silicon vendor. Place them under `targets/MyVendor/MY_BOARD/app/common/startup/` and `targets/MyVendor/MY_BOARD/app/common/linker/`. + +5. **Copy the ThreadX Low-Level Setup**: + Copy the `tx_initialize_low_level.S` assembly file from the **specific ThreadX architecture and toolchain port directory** (`libs/threadx/ports///src/`) matching your target MCU core (e.g., Cortex-M4, Cortex-M33, or RISC-V) into your target's startup directory. This file manages core register setups and vector layout for that processor family and should generally be copied unchanged. + +6. **Update CMake Configuration**: + The target's CMake build scripts are responsible for exposing include paths and linking the BSP drivers, vendor SDK, ThreadX kernel, and shared application executable together into the final firmware image: + - Update `targets/MyVendor/MY_BOARD/CMakeLists.txt` with your target project name and any required vendor SDK configuration. + - Update `targets/MyVendor/MY_BOARD/lib/CMakeLists.txt` to register vendor SDK libraries and subdirectories. + - Update `targets/MyVendor/MY_BOARD/app/CMakeLists.txt` to register startup assembly files, system initialization code, linker scripts, target BSP sources, and link against the required ThreadX libraries. + +7. **Build and Test**: + Run the PowerShell build script: + ```powershell + powershell -ExecutionPolicy Bypass -File .\targets\MyVendor\MY_BOARD\scripts\build.ps1 -Clean -Rebuild + ``` + +--- + +## 5. Framework Architectural Contract + +### Baseline C Interface Headers (`/bsp/include/bsp/`) + +The current framework defines the following core baseline C interfaces in `/bsp/include/bsp/`: + +| Generic Header | Baseline API | Description | +| :--- | :--- | :--- | +| `` | `bsp_board_init()` | Core MCU clock tree, power scaling, and flash wait state setup. | +| `` | `bsp_led_init()`, `bsp_led_toggle()`, etc. | GPIO user LED initialization and state toggling. | +| `` | `bsp_console_init()`, `bsp_console_write()` | Serial UART initialization and output transmission. | + +### Target Configuration Component (`board_config.h`) + +| Configuration File | Expected Constants | Description | +| :--- | :--- | :--- | +| `board_config.h` | `BSP_RAM_END`, `BSP_SYSTEM_CLOCK_HZ`, `BSP_UART_BAUDRATE` | Compile-time hardware specification constants consumed by the BSP driver implementation layer. | + +> [!TIP] +> **Optional Interfaces & Hardware Variants**: +> * The baseline interfaces currently cover core board setup, user LED control, and debug console output. Future versions of the BSP framework may introduce additional optional interfaces (e.g., non-volatile storage, networking, I2C/SPI bus drivers). +> * If a specific target board lacks dedicated LED or UART hardware, implement the interface functions as **no-op implementations** so that generic application binaries continue to link and execute cleanly. diff --git a/templates/target/app/CMakeLists.txt b/templates/target/app/CMakeLists.txt new file mode 100644 index 00000000..1fad0eaa --- /dev/null +++ b/templates/target/app/CMakeLists.txt @@ -0,0 +1,40 @@ +# 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/licenses/MIT. +# +# SPDX-License-Identifier: MIT + +set(COMMON_DIR ${CMAKE_CURRENT_SOURCE_DIR}/common) + +set(SOURCES + # TODO: Add MCU system init and assembly startup files (.c / .s / .S) + # Example: + # ${COMMON_DIR}/startup/system_mcu.c + # ${COMMON_DIR}/startup/startup_mcu.s + # ${COMMON_DIR}/startup/tx_initialize_low_level.S + + # Link the shared platform-independent ThreadX application + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../apps/threadx_demo/main.c + + # Link GCC Newlib syscall stubs + ${CMAKE_CURRENT_SOURCE_DIR}/../lib/bsp/src/newlib_stubs.c +) + +add_executable(${PROJECT_NAME} ${SOURCES}) + +target_link_libraries(${PROJECT_NAME} + PRIVATE + azrtos::threadx + target_bsp + # TODO: Add vendor HAL libraries here if needed +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${COMMON_DIR} +) + +# TODO: Specify target linker script path +# Example: set_target_linker(${PROJECT_NAME} ${COMMON_DIR}/startup/mcu.ld) diff --git a/templates/target/app/common/linker/README.md b/templates/target/app/common/linker/README.md new file mode 100644 index 00000000..d8d36aab --- /dev/null +++ b/templates/target/app/common/linker/README.md @@ -0,0 +1,12 @@ +# Target Linker Scripts + +Place your target MCU linker script (`.ld` for GCC, `.icf` for IAR, or `.sct` for Keil ARMClang) here. + +## Recommended Files: +- `.ld` (Memory region definitions for FLASH, SRAM, CCMRAM, and section mapping) + +## CMake Integration: +Specify the linker script path in `targets///app/CMakeLists.txt`: +```cmake +set_target_linker(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/common/linker/.ld) +``` diff --git a/templates/target/app/common/startup/README.md b/templates/target/app/common/startup/README.md new file mode 100644 index 00000000..7519cce1 --- /dev/null +++ b/templates/target/app/common/startup/README.md @@ -0,0 +1,11 @@ +# Target MCU Startup Files + +Place your target MCU startup assembly file and CMSIS system initialization file here. + +## Recommended Files: +- `startup_.s` or `startup_.c` (Vector table definition & Reset_Handler) +- `system_.c` (SystemCoreClock update & CMSIS system initialization) +- `tx_initialize_low_level.S` (ThreadX low-level architecture initialization for your Cortex-M core) + +## CMake Integration: +Reference these files in `targets///app/CMakeLists.txt` under the `SOURCES` list. diff --git a/templates/target/lib/CMakeLists.txt b/templates/target/lib/CMakeLists.txt new file mode 100644 index 00000000..d668e148 --- /dev/null +++ b/templates/target/lib/CMakeLists.txt @@ -0,0 +1,23 @@ +# 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/licenses/MIT. +# +# SPDX-License-Identifier: MIT + +# ThreadX configuration +set(TX_USER_FILE + "${CMAKE_CURRENT_LIST_DIR}/threadx/tx_user.h" + CACHE STRING + "Enable TX user configuration" +) + +# Core RTOS libraries +add_subdirectory(${SHARED_LIB_DIR}/threadx threadx) + +# TODO: Include vendor hardware libraries / HAL here if applicable +# Example: add_subdirectory(vendor_hal) + +# Add BSP library +add_subdirectory(bsp) diff --git a/templates/target/lib/bsp/CMakeLists.txt b/templates/target/lib/bsp/CMakeLists.txt new file mode 100644 index 00000000..de096665 --- /dev/null +++ b/templates/target/lib/bsp/CMakeLists.txt @@ -0,0 +1,26 @@ +# 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/licenses/MIT. +# +# SPDX-License-Identifier: MIT + +# TODO: Rename target_bsp library name if desired (e.g., custom_bsp) +add_library(target_bsp STATIC + src/bsp_board.c + src/bsp_led.c + src/bsp_console.c +) + +# Export BSP headers and shared abstract C BSP headers to PUBLIC include paths +target_include_directories(target_bsp PUBLIC + include + ${CMAKE_CURRENT_LIST_DIR}/../../../../../bsp/include +) + +# Link ThreadX and vendor HAL dependencies if required +target_link_libraries(target_bsp PRIVATE + azrtos::threadx + # TODO: Add vendor HAL library target here if needed (e.g. stm32cubef4) +) diff --git a/templates/target/lib/bsp/include/board_config.h b/templates/target/lib/bsp/include/board_config.h new file mode 100644 index 00000000..6fc2cc8e --- /dev/null +++ b/templates/target/lib/bsp/include/board_config.h @@ -0,0 +1,36 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +#ifndef BOARD_CONFIG_H +#define BOARD_CONFIG_H + +/** + * @file board_config.h + * @brief Target Hardware Configuration Template + * + * Target board developers must populate these parameters to match their MCU hardware specs. + */ + +/* TODO: Set the physical core CPU clock frequency in Hz */ +#define BSP_SYSTEM_CLOCK_HZ 84000000 + +/* TODO: Set the serial debug console baud rate (e.g. 115200) */ +#define BSP_UART_BAUDRATE 115200 + +/* TODO: Set the end address of physical SRAM (SRAM_BASE + SRAM_SIZE_BYTES) + * Example for 96KB RAM starting at 0x20000000: 0x20000000 + 0x18000 = 0x20018000 + */ +#define BSP_RAM_END 0x20018000 + +/* Optional hardware peripheral availability flags */ +#define BSP_HAS_LED 1 +#define BSP_HAS_CONSOLE 1 + +#endif /* BOARD_CONFIG_H */ diff --git a/templates/target/lib/bsp/src/bsp_board.c b/templates/target/lib/bsp/src/bsp_board.c new file mode 100644 index 00000000..e2d04304 --- /dev/null +++ b/templates/target/lib/bsp/src/bsp_board.c @@ -0,0 +1,28 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +#include "bsp/board.h" +#include "board_config.h" + +/* TODO: Include vendor hardware HAL or register definitions here (e.g. #include "mcu_hal.h") */ + +/** + * @brief Initialize the system core (clocks, flash latency, system configuration). + */ +void bsp_board_init(void) +{ + /* TODO: 1. Initialize Low-level Hardware Abstraction Layer / Power Regulators if applicable */ + + /* TODO: 2. Configure System Clock Tree (Oscillators, PLL, Bus Dividers) to run at BSP_SYSTEM_CLOCK_HZ */ + + /* TODO: 3. Configure Flash Read Latency / Wait states matching the CPU clock frequency */ + + /* TODO: 4. Configure OS Tick Timer if MCU HAL requires a separate hardware timer to keep SysTick free for ThreadX */ +} diff --git a/templates/target/lib/bsp/src/bsp_console.c b/templates/target/lib/bsp/src/bsp_console.c new file mode 100644 index 00000000..23dae914 --- /dev/null +++ b/templates/target/lib/bsp/src/bsp_console.c @@ -0,0 +1,35 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +#include "bsp/console.h" +#include "board_config.h" + +/* TODO: Include vendor UART / Serial hardware headers here */ + +void bsp_console_init(void) +{ +#if BSP_HAS_CONSOLE + /* TODO: Enable UART peripheral and GPIO clocks. + * Configure RX/TX pins for alternate function serial mode and configure baud rate to BSP_UART_BAUDRATE. + */ +#endif +} + +void bsp_console_write(const char *data, size_t length) +{ +#if BSP_HAS_CONSOLE + /* TODO: Transmit character array over serial UART hardware */ + (void)data; + (void)length; +#else + (void)data; + (void)length; +#endif +} diff --git a/templates/target/lib/bsp/src/bsp_led.c b/templates/target/lib/bsp/src/bsp_led.c new file mode 100644 index 00000000..890ab358 --- /dev/null +++ b/templates/target/lib/bsp/src/bsp_led.c @@ -0,0 +1,42 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +#include "bsp/led.h" +#include "board_config.h" + +/* TODO: Include vendor hardware GPIO headers here */ + +void bsp_led_init(void) +{ +#if BSP_HAS_LED + /* TODO: Enable GPIO port peripheral clock and configure LED pin as Push-Pull Output */ +#endif +} + +void bsp_led_on(void) +{ +#if BSP_HAS_LED + /* TODO: Drive LED pin HIGH / LOW depending on board active state */ +#endif +} + +void bsp_led_off(void) +{ +#if BSP_HAS_LED + /* TODO: Drive LED pin to inactive state */ +#endif +} + +void bsp_led_toggle(void) +{ +#if BSP_HAS_LED + /* TODO: Toggle the output state of the LED pin */ +#endif +} diff --git a/templates/target/lib/bsp/src/newlib_stubs.c b/templates/target/lib/bsp/src/newlib_stubs.c new file mode 100644 index 00000000..70b0f76f --- /dev/null +++ b/templates/target/lib/bsp/src/newlib_stubs.c @@ -0,0 +1,133 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + */ + +// Some portions generated by Claude Code (Opus 5) + +#ifdef __GNUC__ + +#include +#include +#include +#include +#include +#include "board_config.h" +#include "bsp/console.h" + +/* Placed by the linker script at the first address above .bss, below the stack. */ +extern char _end; + +/** + * @brief Dynamic memory allocation heap growth stub for Newlib standard C library. + * + * The heap is bounded by BSP_RAM_END from board_config.h. An allocation that + * would run past the end of physical RAM, overflow the pointer, or shrink the + * heap below its base is rejected with (void *)-1 and errno set, which is what + * newlib expects. Returning an out-of-range pointer instead would hand malloc() + * memory that does not exist. + * + * The increment is ptrdiff_t rather than int so the stub stays correct on + * 64-bit targets. + */ +void* _sbrk(ptrdiff_t incr) +{ + static char* heap = NULL; + char* prev_heap; + + if (heap == NULL) + { + heap = &_end; + } + + if (incr > 0) + { + if ((uintptr_t)heap + (uintptr_t)incr > (uintptr_t)BSP_RAM_END || + (uintptr_t)heap + (uintptr_t)incr < (uintptr_t)heap) + { + errno = ENOMEM; + return (void*)-1; + } + } + else if (incr < 0) + { + if ((uintptr_t)heap < (uintptr_t)&_end + (uintptr_t)(-incr)) + { + errno = EINVAL; + return (void*)-1; + } + } + + prev_heap = heap; + heap += incr; + + return prev_heap; +} + +int _close(int file) +{ + (void)file; + return -1; +} + +int _fstat(int file, struct stat* st) +{ + (void)file; + st->st_mode = S_IFCHR; + return 0; +} + +int _isatty(int file) +{ + (void)file; + return 1; +} + +int _lseek(int file, int ptr, int dir) +{ + (void)file; + (void)ptr; + (void)dir; + return 0; +} + +void _exit(int status) +{ + (void)status; + while (1) + { + } +} + +void _kill(int pid, int sig) +{ + (void)pid; + (void)sig; +} + +int _getpid(void) +{ + return -1; +} + +int _read(int file, char* ptr, int len) +{ + (void)file; + (void)ptr; + (void)len; + return 0; +} + +int _write(int file, char* ptr, int len) +{ + (void)file; + bsp_console_write(ptr, (size_t)len); + return len; +} + +#endif /* __GNUC__ */ diff --git a/templates/target/lib/vendor/README.md b/templates/target/lib/vendor/README.md new file mode 100644 index 00000000..01ea40f1 --- /dev/null +++ b/templates/target/lib/vendor/README.md @@ -0,0 +1,14 @@ +# Vendor Hardware Abstraction Libraries (HAL / SDK) + +Place vendor-supplied hardware abstraction drivers or SDK source code here if your target board does not use a system-installed CMake package manager. + +## Integration Patterns: + +### Option A: Embedded Source Tree (e.g., STM32Cube HAL) +Place the driver source files here and register a static library in `targets///lib/CMakeLists.txt`: +```cmake +add_subdirectory(vendor/stm32cubef4) +``` + +### Option B: External SDK Package (e.g., Raspberry Pi Pico SDK) +If using an external CMake package manager, do not place files here. Instead, call `find_package(...)` or include the SDK's CMake entry point in `targets///CMakeLists.txt`. diff --git a/templates/target/scripts/build.ps1 b/templates/target/scripts/build.ps1 new file mode 100644 index 00000000..f032f95f --- /dev/null +++ b/templates/target/scripts/build.ps1 @@ -0,0 +1,79 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# SPDX-License-Identifier: MIT + +param( + [string]$Config = "starter", + [switch]$Clean, + [switch]$Rebuild +) + +$BOARD_DIR = Resolve-Path "$PSScriptRoot/.." +$BUILD_DIR = Join-Path $BOARD_DIR "build" +$NUM_JOBS = 4 + +Write-Host "==========================================" +Write-Host "Target Board Build Script (PowerShell)" +Write-Host "==========================================" +Write-Host "Board Dir: $BOARD_DIR" +Write-Host "Build Dir: $BUILD_DIR" +Write-Host "Config: $Config" +Write-Host "" + +# Check for ARM GCC compiler +$armGcc = Get-Command "arm-none-eabi-gcc" -ErrorAction SilentlyContinue +if (!$armGcc -and !$env:ARM_GCC_PATH) { + Write-Host "[WARNING] arm-none-eabi-gcc not found on PATH." -ForegroundColor Yellow +} + +if ($Clean -or $Rebuild) { + Write-Host "[INFO] Cleaning build directory..." + if (Test-Path $BUILD_DIR) { + Remove-Item -Path $BUILD_DIR -Recurse -Force + } + New-Item -ItemType Directory -Path $BUILD_DIR -Force + Write-Host "[OK] Build directory cleaned" + Write-Host "" +} + +if (!(Test-Path $BUILD_DIR)) { + New-Item -ItemType Directory -Path $BUILD_DIR -Force +} + +Push-Location $BUILD_DIR + +if (!(Test-Path "CMakeCache.txt") -or !(Test-Path "build.ninja") -or $Rebuild) { + Write-Host "[INFO] Configuring CMake..." + cmake -G Ninja ` + "-DCMAKE_BUILD_TYPE=Release" ` + "-DAPP_CONFIG=$Config" ` + "-DCMAKE_POLICY_VERSION_MINIMUM=3.5" ` + $BOARD_DIR + if ($LASTEXITCODE -ne 0) { + Write-Host "[ERROR] CMake configuration failed!" -ForegroundColor Red + Pop-Location + exit 1 + } + Write-Host "[OK] CMake configured" + Write-Host "" +} + +Write-Host "[INFO] Building with $NUM_JOBS parallel jobs..." +if (Get-Command ninja -ErrorAction SilentlyContinue) { + ninja -j $NUM_JOBS +} else { + cmake --build . --parallel $NUM_JOBS --config Release +} + +$buildExitCode = $LASTEXITCODE +Pop-Location + +if ($buildExitCode -ne 0) { + Write-Host "[ERROR] Build failed!" -ForegroundColor Red + exit 1 +} + +Write-Host "" +Write-Host "==========================================" +Write-Host "[OK] Build completed successfully!" +Write-Host "==========================================" From 70f7da9f8b15cabfe671f9606893b439f8c4f87b Mon Sep 17 00:00:00 2001 From: Ammar Okla <146969371+AmmarOkla12772@users.noreply.github.com> Date: Mon, 31 Aug 2026 18:15:11 +0300 Subject: [PATCH 06/20] Relocated NUCLEO_F401RE to targets and adopted generic BSP framework (#50) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 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 Co-authored-by: Frederic Desbiens Co-authored-by: Codex 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 Co-authored-by: Frédéric Desbiens --- .github/workflows/ci.yml | 38 ++++ .../NUCLEO_F401RE/app/common/board_init.h | 20 -- .../NUCLEO_F401RE/app/common/console.c | 52 ----- .../app/common/newlib_syscalls.c | 80 ------- .../lib/nucleo_bsp/CMakeLists.txt | 27 --- .../NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.c | 42 ---- .../NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.h | 25 --- .../NUCLEO_F401RE/CMakeLists.txt | 8 +- .../NUCLEO_F401RE/NOTICE.md | 0 .../NUCLEO_F401RE/README.md | 16 +- .../NUCLEO_F401RE/app/CMakeLists.txt | 20 +- .../NUCLEO_F401RE/app/common/sntp_client.c | 0 .../app/common/startup/NUCLEO_F401RE.ld | 3 + .../app/common/startup/startup_stm32f401xe.s | 0 .../app/common/startup/system_stm32f4xx.c | 0 .../common/startup/tx_initialize_low_level.S | 0 .../common/stm32cubef4/stm32f4xx_hal_msp.c | 0 .../NUCLEO_F401RE/app/starter/cloud_config.h | 0 .../NUCLEO_F401RE/app/starter/main.c | 10 +- .../NUCLEO_F401RE/cmake/FindCMSIS.cmake | 0 .../NUCLEO_F401RE/cmake/FindSTM32HAL.cmake | 0 .../cmake/arm-gcc-cortex-m4.cmake | 0 .../cmake/arm-gcc-cortex-toolchain.cmake | 0 .../NUCLEO_F401RE/cmake/utilities.cmake | 0 .../NUCLEO_F401RE/lib/CMakeLists.txt | 3 +- .../NUCLEO_F401RE/lib/bsp/CMakeLists.txt | 28 +++ .../lib/bsp/include/board_config.h | 35 +++ .../lib/bsp/include/nucleo_console.h | 28 +++ .../NUCLEO_F401RE/lib/bsp/src/bsp_board.c | 70 ++---- .../NUCLEO_F401RE/lib/bsp/src/bsp_console.c | 99 +++++++++ .../NUCLEO_F401RE/lib/bsp/src/bsp_led.c | 59 +++++ .../NUCLEO_F401RE/lib/bsp/src/newlib_stubs.c | 201 ++++++++++++++++++ .../lib/stm32cubef4/CMakeLists.txt | 0 .../Device/ST/STM32F4xx/Include/stm32f401xe.h | 0 .../Device/ST/STM32F4xx/Include/stm32f412rx.h | 0 .../Device/ST/STM32F4xx/Include/stm32f4xx.h | 0 .../ST/STM32F4xx/Include/system_stm32f4xx.h | 0 .../Device/ST/STM32F4xx/Release_Notes.html | 0 .../Templates/gcc/startup_stm32f401xc.s | 0 .../Templates/gcc/startup_stm32f401xe.s | 0 .../Templates/gcc/startup_stm32f405xx.s | 0 .../Templates/gcc/startup_stm32f407xx.s | 0 .../Templates/gcc/startup_stm32f410cx.s | 0 .../Templates/gcc/startup_stm32f410rx.s | 0 .../Templates/gcc/startup_stm32f410tx.s | 0 .../Templates/gcc/startup_stm32f411xe.s | 0 .../Templates/gcc/startup_stm32f412cx.s | 0 .../Templates/gcc/startup_stm32f412rx.s | 0 .../Templates/gcc/startup_stm32f412vx.s | 0 .../Templates/gcc/startup_stm32f412zx.s | 0 .../Templates/gcc/startup_stm32f413xx.s | 0 .../Templates/gcc/startup_stm32f415xx.s | 0 .../Templates/gcc/startup_stm32f417xx.s | 0 .../Templates/gcc/startup_stm32f423xx.s | 0 .../Templates/gcc/startup_stm32f427xx.s | 0 .../Templates/gcc/startup_stm32f429xx.s | 0 .../Templates/gcc/startup_stm32f437xx.s | 0 .../Templates/gcc/startup_stm32f439xx.s | 0 .../Templates/gcc/startup_stm32f446xx.s | 0 .../Templates/gcc/startup_stm32f469xx.s | 0 .../Templates/gcc/startup_stm32f479xx.s | 0 .../Source/Templates/system_stm32f4xx.c | 0 .../Device/ST/STM32F4xx/_htmresc/mini-st.css | 0 .../Device/ST/STM32F4xx/_htmresc/st_logo.png | Bin .../Drivers/CMSIS/Include/cmsis_armcc.h | 0 .../Drivers/CMSIS/Include/cmsis_armclang.h | 0 .../Drivers/CMSIS/Include/cmsis_compiler.h | 0 .../Drivers/CMSIS/Include/cmsis_gcc.h | 0 .../Drivers/CMSIS/Include/cmsis_iccarm.h | 0 .../Drivers/CMSIS/Include/cmsis_version.h | 0 .../Drivers/CMSIS/Include/core_armv8mbl.h | 0 .../Drivers/CMSIS/Include/core_armv8mml.h | 0 .../Drivers/CMSIS/Include/core_cm0.h | 0 .../Drivers/CMSIS/Include/core_cm0plus.h | 0 .../Drivers/CMSIS/Include/core_cm1.h | 0 .../Drivers/CMSIS/Include/core_cm23.h | 0 .../Drivers/CMSIS/Include/core_cm3.h | 0 .../Drivers/CMSIS/Include/core_cm33.h | 0 .../Drivers/CMSIS/Include/core_cm4.h | 0 .../Drivers/CMSIS/Include/core_cm7.h | 0 .../Drivers/CMSIS/Include/core_sc000.h | 0 .../Drivers/CMSIS/Include/core_sc300.h | 0 .../Drivers/CMSIS/Include/mpu_armv7.h | 0 .../Drivers/CMSIS/Include/mpu_armv8.h | 0 .../Drivers/CMSIS/Include/tz_context.h | 0 .../lib/stm32cubef4/Drivers/CMSIS/LICENSE.txt | 0 .../lib/stm32cubef4/Drivers/CMSIS/README.md | 0 .../Inc/Legacy/stm32_hal_legacy.h | 0 .../Inc/Legacy/stm32f4xx_hal_can_legacy.h | 0 .../Inc/stm32_assert_template.h | 0 .../STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h | 0 .../Inc/stm32f4xx_hal_adc.h | 0 .../Inc/stm32f4xx_hal_adc_ex.h | 0 .../Inc/stm32f4xx_hal_can.h | 0 .../Inc/stm32f4xx_hal_cec.h | 0 .../Inc/stm32f4xx_hal_conf_template.h | 0 .../Inc/stm32f4xx_hal_cortex.h | 0 .../Inc/stm32f4xx_hal_crc.h | 0 .../Inc/stm32f4xx_hal_cryp.h | 0 .../Inc/stm32f4xx_hal_cryp_ex.h | 0 .../Inc/stm32f4xx_hal_dac.h | 0 .../Inc/stm32f4xx_hal_dac_ex.h | 0 .../Inc/stm32f4xx_hal_dcmi.h | 0 .../Inc/stm32f4xx_hal_dcmi_ex.h | 0 .../Inc/stm32f4xx_hal_def.h | 0 .../Inc/stm32f4xx_hal_dfsdm.h | 0 .../Inc/stm32f4xx_hal_dma.h | 0 .../Inc/stm32f4xx_hal_dma2d.h | 0 .../Inc/stm32f4xx_hal_dma_ex.h | 0 .../Inc/stm32f4xx_hal_dsi.h | 0 .../Inc/stm32f4xx_hal_eth.h | 0 .../Inc/stm32f4xx_hal_exti.h | 0 .../Inc/stm32f4xx_hal_flash.h | 0 .../Inc/stm32f4xx_hal_flash_ex.h | 0 .../Inc/stm32f4xx_hal_flash_ramfunc.h | 0 .../Inc/stm32f4xx_hal_fmpi2c.h | 0 .../Inc/stm32f4xx_hal_fmpi2c_ex.h | 0 .../Inc/stm32f4xx_hal_fmpsmbus.h | 0 .../Inc/stm32f4xx_hal_gpio.h | 0 .../Inc/stm32f4xx_hal_gpio_ex.h | 0 .../Inc/stm32f4xx_hal_hash.h | 0 .../Inc/stm32f4xx_hal_hash_ex.h | 0 .../Inc/stm32f4xx_hal_hcd.h | 0 .../Inc/stm32f4xx_hal_i2c.h | 0 .../Inc/stm32f4xx_hal_i2c_ex.h | 0 .../Inc/stm32f4xx_hal_i2s.h | 0 .../Inc/stm32f4xx_hal_i2s_ex.h | 0 .../Inc/stm32f4xx_hal_irda.h | 0 .../Inc/stm32f4xx_hal_iwdg.h | 0 .../Inc/stm32f4xx_hal_lptim.h | 0 .../Inc/stm32f4xx_hal_ltdc.h | 0 .../Inc/stm32f4xx_hal_ltdc_ex.h | 0 .../Inc/stm32f4xx_hal_mmc.h | 0 .../Inc/stm32f4xx_hal_nand.h | 0 .../Inc/stm32f4xx_hal_nor.h | 0 .../Inc/stm32f4xx_hal_pccard.h | 0 .../Inc/stm32f4xx_hal_pcd.h | 0 .../Inc/stm32f4xx_hal_pcd_ex.h | 0 .../Inc/stm32f4xx_hal_pwr.h | 0 .../Inc/stm32f4xx_hal_pwr_ex.h | 0 .../Inc/stm32f4xx_hal_qspi.h | 0 .../Inc/stm32f4xx_hal_rcc.h | 0 .../Inc/stm32f4xx_hal_rcc_ex.h | 0 .../Inc/stm32f4xx_hal_rng.h | 0 .../Inc/stm32f4xx_hal_rtc.h | 0 .../Inc/stm32f4xx_hal_rtc_ex.h | 0 .../Inc/stm32f4xx_hal_sai.h | 0 .../Inc/stm32f4xx_hal_sai_ex.h | 0 .../Inc/stm32f4xx_hal_sd.h | 0 .../Inc/stm32f4xx_hal_sdram.h | 0 .../Inc/stm32f4xx_hal_smartcard.h | 0 .../Inc/stm32f4xx_hal_smbus.h | 0 .../Inc/stm32f4xx_hal_spdifrx.h | 0 .../Inc/stm32f4xx_hal_spi.h | 0 .../Inc/stm32f4xx_hal_sram.h | 0 .../Inc/stm32f4xx_hal_tim.h | 0 .../Inc/stm32f4xx_hal_tim_ex.h | 0 .../Inc/stm32f4xx_hal_uart.h | 0 .../Inc/stm32f4xx_hal_usart.h | 0 .../Inc/stm32f4xx_hal_wwdg.h | 0 .../Inc/stm32f4xx_ll_adc.h | 0 .../Inc/stm32f4xx_ll_bus.h | 0 .../Inc/stm32f4xx_ll_cortex.h | 0 .../Inc/stm32f4xx_ll_crc.h | 0 .../Inc/stm32f4xx_ll_dac.h | 0 .../Inc/stm32f4xx_ll_dma.h | 0 .../Inc/stm32f4xx_ll_dma2d.h | 0 .../Inc/stm32f4xx_ll_exti.h | 0 .../Inc/stm32f4xx_ll_fmc.h | 0 .../Inc/stm32f4xx_ll_fmpi2c.h | 0 .../Inc/stm32f4xx_ll_fsmc.h | 0 .../Inc/stm32f4xx_ll_gpio.h | 0 .../Inc/stm32f4xx_ll_i2c.h | 0 .../Inc/stm32f4xx_ll_iwdg.h | 0 .../Inc/stm32f4xx_ll_lptim.h | 0 .../Inc/stm32f4xx_ll_pwr.h | 0 .../Inc/stm32f4xx_ll_rcc.h | 0 .../Inc/stm32f4xx_ll_rng.h | 0 .../Inc/stm32f4xx_ll_rtc.h | 0 .../Inc/stm32f4xx_ll_sdmmc.h | 0 .../Inc/stm32f4xx_ll_spi.h | 0 .../Inc/stm32f4xx_ll_system.h | 0 .../Inc/stm32f4xx_ll_tim.h | 0 .../Inc/stm32f4xx_ll_usart.h | 0 .../Inc/stm32f4xx_ll_usb.h | 0 .../Inc/stm32f4xx_ll_utils.h | 0 .../Inc/stm32f4xx_ll_wwdg.h | 0 .../Drivers/STM32F4xx_HAL_Driver/License.md | 0 .../Drivers/STM32F4xx_HAL_Driver/README.md | 0 .../Src/Legacy/stm32f4xx_hal_can.c | 0 .../STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c | 0 .../Src/stm32f4xx_hal_adc.c | 0 .../Src/stm32f4xx_hal_adc_ex.c | 0 .../Src/stm32f4xx_hal_can.c | 0 .../Src/stm32f4xx_hal_cec.c | 0 .../Src/stm32f4xx_hal_cortex.c | 0 .../Src/stm32f4xx_hal_crc.c | 0 .../Src/stm32f4xx_hal_cryp.c | 0 .../Src/stm32f4xx_hal_cryp_ex.c | 0 .../Src/stm32f4xx_hal_dac.c | 0 .../Src/stm32f4xx_hal_dac_ex.c | 0 .../Src/stm32f4xx_hal_dcmi.c | 0 .../Src/stm32f4xx_hal_dcmi_ex.c | 0 .../Src/stm32f4xx_hal_dfsdm.c | 0 .../Src/stm32f4xx_hal_dma.c | 0 .../Src/stm32f4xx_hal_dma2d.c | 0 .../Src/stm32f4xx_hal_dma_ex.c | 0 .../Src/stm32f4xx_hal_dsi.c | 0 .../Src/stm32f4xx_hal_eth.c | 0 .../Src/stm32f4xx_hal_exti.c | 0 .../Src/stm32f4xx_hal_flash.c | 0 .../Src/stm32f4xx_hal_flash_ex.c | 0 .../Src/stm32f4xx_hal_flash_ramfunc.c | 0 .../Src/stm32f4xx_hal_fmpi2c.c | 0 .../Src/stm32f4xx_hal_fmpi2c_ex.c | 0 .../Src/stm32f4xx_hal_fmpsmbus.c | 0 .../Src/stm32f4xx_hal_gpio.c | 0 .../Src/stm32f4xx_hal_hash.c | 0 .../Src/stm32f4xx_hal_hash_ex.c | 0 .../Src/stm32f4xx_hal_hcd.c | 0 .../Src/stm32f4xx_hal_i2c.c | 0 .../Src/stm32f4xx_hal_i2c_ex.c | 0 .../Src/stm32f4xx_hal_i2s.c | 0 .../Src/stm32f4xx_hal_i2s_ex.c | 0 .../Src/stm32f4xx_hal_irda.c | 0 .../Src/stm32f4xx_hal_iwdg.c | 0 .../Src/stm32f4xx_hal_lptim.c | 0 .../Src/stm32f4xx_hal_ltdc.c | 0 .../Src/stm32f4xx_hal_ltdc_ex.c | 0 .../Src/stm32f4xx_hal_mmc.c | 0 .../Src/stm32f4xx_hal_msp_template.c | 0 .../Src/stm32f4xx_hal_nand.c | 0 .../Src/stm32f4xx_hal_nor.c | 0 .../Src/stm32f4xx_hal_pccard.c | 0 .../Src/stm32f4xx_hal_pcd.c | 0 .../Src/stm32f4xx_hal_pcd_ex.c | 0 .../Src/stm32f4xx_hal_pwr.c | 0 .../Src/stm32f4xx_hal_pwr_ex.c | 0 .../Src/stm32f4xx_hal_qspi.c | 0 .../Src/stm32f4xx_hal_rcc.c | 0 .../Src/stm32f4xx_hal_rcc_ex.c | 0 .../Src/stm32f4xx_hal_rng.c | 0 .../Src/stm32f4xx_hal_rtc.c | 0 .../Src/stm32f4xx_hal_rtc_ex.c | 0 .../Src/stm32f4xx_hal_sai.c | 0 .../Src/stm32f4xx_hal_sai_ex.c | 0 .../Src/stm32f4xx_hal_sd.c | 0 .../Src/stm32f4xx_hal_sdram.c | 0 .../Src/stm32f4xx_hal_smartcard.c | 0 .../Src/stm32f4xx_hal_smbus.c | 0 .../Src/stm32f4xx_hal_spdifrx.c | 0 .../Src/stm32f4xx_hal_spi.c | 0 .../Src/stm32f4xx_hal_sram.c | 0 .../Src/stm32f4xx_hal_tim.c | 0 .../Src/stm32f4xx_hal_tim_ex.c | 0 ...tm32f4xx_hal_timebase_rtc_alarm_template.c | 0 ...m32f4xx_hal_timebase_rtc_wakeup_template.c | 0 .../Src/stm32f4xx_hal_timebase_tim.c | 0 .../Src/stm32f4xx_hal_timebase_tim_template.c | 0 .../Src/stm32f4xx_hal_uart.c | 0 .../Src/stm32f4xx_hal_usart.c | 0 .../Src/stm32f4xx_hal_wwdg.c | 0 .../Src/stm32f4xx_ll_adc.c | 0 .../Src/stm32f4xx_ll_crc.c | 0 .../Src/stm32f4xx_ll_dac.c | 0 .../Src/stm32f4xx_ll_dma.c | 0 .../Src/stm32f4xx_ll_dma2d.c | 0 .../Src/stm32f4xx_ll_exti.c | 0 .../Src/stm32f4xx_ll_fmc.c | 0 .../Src/stm32f4xx_ll_fmpi2c.c | 0 .../Src/stm32f4xx_ll_fsmc.c | 0 .../Src/stm32f4xx_ll_gpio.c | 0 .../Src/stm32f4xx_ll_i2c.c | 0 .../Src/stm32f4xx_ll_lptim.c | 0 .../Src/stm32f4xx_ll_pwr.c | 0 .../Src/stm32f4xx_ll_rcc.c | 0 .../Src/stm32f4xx_ll_rng.c | 0 .../Src/stm32f4xx_ll_rtc.c | 0 .../Src/stm32f4xx_ll_sdmmc.c | 0 .../Src/stm32f4xx_ll_spi.c | 0 .../Src/stm32f4xx_ll_tim.c | 0 .../Src/stm32f4xx_ll_usart.c | 0 .../Src/stm32f4xx_ll_usb.c | 0 .../Src/stm32f4xx_ll_utils.c | 0 .../stm32cubef4/config/stm32f4xx_hal_conf.h | 0 .../NUCLEO_F401RE/lib/threadx/tx_user.h | 0 .../NUCLEO_F401RE/scripts/build.ps1 | 3 - .../NUCLEO_F401RE/scripts/build.sh | 10 +- 288 files changed, 543 insertions(+), 334 deletions(-) delete mode 100644 STMicroelectronics/NUCLEO_F401RE/app/common/board_init.h delete mode 100644 STMicroelectronics/NUCLEO_F401RE/app/common/console.c delete mode 100644 STMicroelectronics/NUCLEO_F401RE/app/common/newlib_syscalls.c delete mode 100644 STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/CMakeLists.txt delete mode 100644 STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.c delete mode 100644 STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.h rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/CMakeLists.txt (86%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/NOTICE.md (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/README.md (91%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/app/CMakeLists.txt (73%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/app/common/sntp_client.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/app/common/startup/NUCLEO_F401RE.ld (97%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/app/common/startup/startup_stm32f401xe.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/app/common/startup/system_stm32f4xx.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/app/common/startup/tx_initialize_low_level.S (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/app/starter/cloud_config.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/app/starter/main.c (99%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/cmake/FindCMSIS.cmake (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/cmake/FindSTM32HAL.cmake (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/cmake/arm-gcc-cortex-m4.cmake (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/cmake/arm-gcc-cortex-toolchain.cmake (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/cmake/utilities.cmake (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/CMakeLists.txt (94%) create mode 100644 targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/CMakeLists.txt create mode 100644 targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/board_config.h create mode 100644 targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/nucleo_console.h rename STMicroelectronics/NUCLEO_F401RE/app/common/board_init.c => targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_board.c (73%) create mode 100644 targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_console.c create mode 100644 targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_led.c create mode 100644 targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/newlib_stubs.c rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/CMakeLists.txt (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f401xe.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f412rx.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Release_Notes.html (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f401xc.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f401xe.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f405xx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f407xx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f410cx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f410rx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f410tx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f411xe.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412cx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412rx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412vx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412zx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f413xx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f415xx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f417xx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f423xx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f427xx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f429xx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f437xx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f439xx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f446xx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f469xx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f479xx.s (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/_htmresc/mini-st.css (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/_htmresc/st_logo.png (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_armcc.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_armclang.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_compiler.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_gcc.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_iccarm.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_version.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_armv8mbl.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_armv8mml.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm0.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm0plus.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm1.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm23.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm3.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm33.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm4.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm7.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_sc000.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_sc300.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/mpu_armv7.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/mpu_armv8.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/tz_context.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/LICENSE.txt (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/README.md (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32f4xx_hal_can_legacy.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32_assert_template.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cec.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_conf_template.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_crc.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dac.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dac_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dfsdm.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma2d.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dsi.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_eth.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpsmbus.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hcd.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_irda.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_iwdg.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_lptim.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_mmc.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nand.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nor.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pccard.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_qspi.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rng.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sd.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sdram.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smartcard.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smbus.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spdifrx.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sram.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_usart.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_wwdg.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_adc.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_bus.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_cortex.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_crc.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dac.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma2d.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_exti.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmc.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmpi2c.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fsmc.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_gpio.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_i2c.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_iwdg.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_lptim.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_pwr.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rcc.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rng.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rtc.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_sdmmc.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_spi.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_system.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_tim.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usart.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usb.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_utils.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_wwdg.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/License.md (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/README.md (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/Legacy/stm32f4xx_hal_can.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cec.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_crc.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp_ex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac_ex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi_ex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dfsdm.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma2d.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dsi.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_eth.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c_ex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpsmbus.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash_ex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hcd.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s_ex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_irda.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_iwdg.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_lptim.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc_ex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_mmc.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_msp_template.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nand.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nor.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pccard.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_qspi.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rng.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc_ex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai_ex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sdram.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smartcard.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smbus.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spdifrx.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sram.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_alarm_template.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_wakeup_template.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_tim.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_tim_template.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_usart.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_wwdg.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_adc.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_crc.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dac.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma2d.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_exti.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmc.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmpi2c.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fsmc.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_gpio.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_i2c.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_lptim.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_pwr.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rcc.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rng.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rtc.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_spi.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_tim.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usart.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_utils.c (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/stm32cubef4/config/stm32f4xx_hal_conf.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/lib/threadx/tx_user.h (100%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/scripts/build.ps1 (96%) rename {STMicroelectronics => targets/STMicroelectronics}/NUCLEO_F401RE/scripts/build.sh (91%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 37d2ee3f..6a20de7e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,3 +101,41 @@ jobs: - name: Run Deterministic Headless Renode Test run: | python3 targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py + + build-arm-nucleo: + name: Build ST Nucleo-F401RE (ARM Cortex-M4) + runs-on: ubuntu-24.04 + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install CMake and Ninja + run: | + sudo apt-get update + sudo apt-get install -y cmake ninja-build + + - name: Install Pinned Arm GNU Toolchain 14.2.Rel1 + run: | + wget -q https://developer.arm.com/-/media/Files/downloads/gnu/14.2.rel1/binrel/arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz + mkdir -p $HOME/arm-gcc + tar -xJf arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz -C $HOME/arm-gcc --strip-components=1 + rm arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz + echo "$HOME/arm-gcc/bin" >> $GITHUB_PATH + + - name: Build NUCLEO-F401RE Demo + run: | + bash targets/STMicroelectronics/NUCLEO_F401RE/scripts/build.sh --rebuild + + - name: Verify NUCLEO-F401RE Demo ELF + run: | + test -f targets/STMicroelectronics/NUCLEO_F401RE/build/app/nucleo_f401re.elf + echo "[OK] NUCLEO-F401RE demo ELF verified." + + - name: Archive Built NUCLEO-F401RE ELF + uses: actions/upload-artifact@v4 + with: + name: nucleo-f401re-demo-elf + path: targets/STMicroelectronics/NUCLEO_F401RE/build/app/nucleo_f401re.elf + retention-days: 1 diff --git a/STMicroelectronics/NUCLEO_F401RE/app/common/board_init.h b/STMicroelectronics/NUCLEO_F401RE/app/common/board_init.h deleted file mode 100644 index 75341c19..00000000 --- a/STMicroelectronics/NUCLEO_F401RE/app/common/board_init.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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 - */ - -#ifndef BOARD_INIT_H -#define BOARD_INIT_H - -#include "stm32f4xx_hal.h" - -extern UART_HandleTypeDef UartHandle; - -void board_init(void); - -#endif /* BOARD_INIT_H */ diff --git a/STMicroelectronics/NUCLEO_F401RE/app/common/console.c b/STMicroelectronics/NUCLEO_F401RE/app/common/console.c deleted file mode 100644 index 326ccda6..00000000 --- a/STMicroelectronics/NUCLEO_F401RE/app/common/console.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 - */ -// Some portions generated by Codex (GPT-5). - -#include "stm32f4xx_hal.h" - -#include "board_init.h" - -int __io_putchar(int ch); -int __io_getchar(void); -int _read(int file, char* ptr, int len); -int _write(int file, char* ptr, int len); - -int __io_putchar(int ch) -{ - HAL_UART_Transmit(&UartHandle, (uint8_t*)&ch, 1, HAL_MAX_DELAY); - return ch; -} - -int __io_getchar(void) -{ - uint8_t ch; - HAL_UART_Receive(&UartHandle, &ch, 1, HAL_MAX_DELAY); - return (int)ch; -} - -int _read(int file, char* ptr, int len) -{ - (void)file; - for (int i = 0; i < len; i++) - { - ptr[i] = (char)__io_getchar(); - } - return len; -} - -int _write(int file, char* ptr, int len) -{ - (void)file; - for (int i = 0; i < len; i++) - { - __io_putchar((int)ptr[i]); - } - return len; -} diff --git a/STMicroelectronics/NUCLEO_F401RE/app/common/newlib_syscalls.c b/STMicroelectronics/NUCLEO_F401RE/app/common/newlib_syscalls.c deleted file mode 100644 index 128e9ec1..00000000 --- a/STMicroelectronics/NUCLEO_F401RE/app/common/newlib_syscalls.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2026 Eclipse ThreadX contributors - * - * SPDX-License-Identifier: MIT - * - * Minimal newlib-nano syscall stubs (same role as MXChip/AZ3166 deps/src/newlib_nano.c). - */ - -#ifdef __GNUC__ - -#include -#include -#include -#include - -extern int errno; -extern int _end; - -void* _sbrk(int incr) -{ - static unsigned char* heap = NULL; - unsigned char* prev_heap; - - if (heap == NULL) - { - heap = (unsigned char*)&_end; - } - prev_heap = heap; - heap += incr; - - return prev_heap; -} - -int _close(int file) -{ - (void)file; - return -1; -} - -int _fstat(int file, struct stat* st) -{ - (void)file; - st->st_mode = S_IFCHR; - return 0; -} - -int _isatty(int file) -{ - (void)file; - return 1; -} - -int _lseek(int file, int ptr, int dir) -{ - (void)file; - (void)ptr; - (void)dir; - return 0; -} - -void _exit(int status) -{ - (void)status; - while (1) - { - } -} - -void _kill(int pid, int sig) -{ - (void)pid; - (void)sig; -} - -int _getpid(void) -{ - return -1; -} - -#endif /* __GNUC__ */ diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/CMakeLists.txt b/STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/CMakeLists.txt deleted file mode 100644 index 4d9a8695..00000000 --- a/STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# 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 - -set(SOURCES - nucleo_bsp.c -) - -set(TARGET nucleo_bsp) - -add_library(${TARGET} OBJECT - ${SOURCES} -) - -target_link_libraries(${TARGET} - PUBLIC - stm32cubef4 -) - -target_include_directories(${TARGET} - PUBLIC - . -) diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.c b/STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.c deleted file mode 100644 index 4dd79c61..00000000 --- a/STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 - */ -// Some portions generated by Codex (GPT-5). - -#include "nucleo_bsp.h" - -void nucleo_bsp_init(void) -{ - GPIO_InitTypeDef gpio = {0}; - - __HAL_RCC_GPIOA_CLK_ENABLE(); - - gpio.Pin = NUCLEO_LED_PIN; - gpio.Mode = GPIO_MODE_OUTPUT_PP; - gpio.Pull = GPIO_NOPULL; - gpio.Speed = GPIO_SPEED_FREQ_LOW; - HAL_GPIO_Init(NUCLEO_LED_GPIO_PORT, &gpio); - - nucleo_led_off(); -} - -void nucleo_led_on(void) -{ - HAL_GPIO_WritePin(NUCLEO_LED_GPIO_PORT, NUCLEO_LED_PIN, GPIO_PIN_SET); -} - -void nucleo_led_off(void) -{ - HAL_GPIO_WritePin(NUCLEO_LED_GPIO_PORT, NUCLEO_LED_PIN, GPIO_PIN_RESET); -} - -void nucleo_led_toggle(void) -{ - HAL_GPIO_TogglePin(NUCLEO_LED_GPIO_PORT, NUCLEO_LED_PIN); -} diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.h b/STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.h deleted file mode 100644 index 14831f9d..00000000 --- a/STMicroelectronics/NUCLEO_F401RE/lib/nucleo_bsp/nucleo_bsp.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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 - */ - -#ifndef NUCLEO_BSP_H -#define NUCLEO_BSP_H - -#include "stm32f4xx_hal.h" - -/* Nucleo-F401RE user LED (LD2) on PA5 — UM1724 user manual. */ -#define NUCLEO_LED_PIN GPIO_PIN_5 -#define NUCLEO_LED_GPIO_PORT GPIOA - -void nucleo_bsp_init(void); -void nucleo_led_on(void); -void nucleo_led_off(void); -void nucleo_led_toggle(void); - -#endif /* NUCLEO_BSP_H */ diff --git a/STMicroelectronics/NUCLEO_F401RE/CMakeLists.txt b/targets/STMicroelectronics/NUCLEO_F401RE/CMakeLists.txt similarity index 86% rename from STMicroelectronics/NUCLEO_F401RE/CMakeLists.txt rename to targets/STMicroelectronics/NUCLEO_F401RE/CMakeLists.txt index 9cc25d35..c6eb27d9 100644 --- a/STMicroelectronics/NUCLEO_F401RE/CMakeLists.txt +++ b/targets/STMicroelectronics/NUCLEO_F401RE/CMakeLists.txt @@ -20,10 +20,14 @@ project(nucleo_f401re C ASM) enable_language(ASM) -set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD 99) + +set(SAMPLEX_ROOT_DIR + ${CMAKE_CURRENT_LIST_DIR}/../../.. +) set(SHARED_LIB_DIR - ${CMAKE_CURRENT_LIST_DIR}/../../libs + ${SAMPLEX_ROOT_DIR}/libs ) list(APPEND CMAKE_MODULE_PATH diff --git a/STMicroelectronics/NUCLEO_F401RE/NOTICE.md b/targets/STMicroelectronics/NUCLEO_F401RE/NOTICE.md similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/NOTICE.md rename to targets/STMicroelectronics/NUCLEO_F401RE/NOTICE.md diff --git a/STMicroelectronics/NUCLEO_F401RE/README.md b/targets/STMicroelectronics/NUCLEO_F401RE/README.md similarity index 91% rename from STMicroelectronics/NUCLEO_F401RE/README.md rename to targets/STMicroelectronics/NUCLEO_F401RE/README.md index 16e8e227..828a66ba 100644 --- a/STMicroelectronics/NUCLEO_F401RE/README.md +++ b/targets/STMicroelectronics/NUCLEO_F401RE/README.md @@ -34,7 +34,7 @@ arm-none-eabi-objdump --version ``` ### CMake-Based Build -From the `STMicroelectronics/NUCLEO_F401RE` directory: +From the `targets/STMicroelectronics/NUCLEO_F401RE` directory: ```bash cmake -Bbuild -GNinja -DCMAKE_TOOLCHAIN_FILE=cmake/arm-gcc-cortex-m4.cmake . @@ -120,17 +120,19 @@ The BSP separates the ThreadX scheduler tick from the STM32 HAL timebase to avoi ThreadX requires exclusive ownership of the SysTick exception for scheduler operation. To avoid conflicts, the STM32 HAL timebase is implemented using TIM2 instead of the default SysTick source. -The BSP overrides `HAL_InitTick()` to configure TIM2 as the HAL timebase and provides custom implementations of `HAL_SuspendTick()` and `HAL_ResumeTick()` in `board_init.c`. These functions enable and disable the TIM2 update interrupt without affecting the ThreadX scheduler tick. +The BSP overrides `HAL_InitTick()` to configure TIM2 as the HAL timebase and provides custom implementations of `HAL_SuspendTick()` and `HAL_ResumeTick()` in `lib/bsp/src/bsp_board.c`. These functions enable and disable the TIM2 update interrupt without affecting the ThreadX scheduler tick. ## File Organization - **`app/`**: Main application logic and boot setups - - **`app/common/`**: Console serial driver and board configurations + - **`app/common/`**: Vendor HAL MSP hooks and boot sources - **`app/common/startup/`**: Linker scripts and assembly boot startup code - **`app/starter/`**: Demo main thread logic - **`lib/`**: Libraries and dependencies - - **`lib/nucleo_bsp/`**: Board specific support libraries (LD2 LED) + - **`lib/bsp/`**: Board support implementing the generic `` interfaces + (`bsp_board.c` clocks and HAL timebase, `bsp_led.c` LD2, `bsp_console.c` + USART2, `newlib_stubs.c` newlib syscall overrides) - **`lib/stm32cubef4/`**: HAL Driver wrapper and platform drivers - **`lib/threadx/`**: ThreadX user configuration file (`tx_user.h`) - **`cmake/`**: Cross-compilation module definitions @@ -140,9 +142,9 @@ The BSP overrides `HAL_InitTick()` to configure TIM2 as the HAL timebase and pro ## Validation Record ### Verification Environment -- **Toolchain**: Arm GNU Toolchain 15.2.Rel1 (GCC 15.2.1) -- **Static ROM usage**: 18244 Bytes (3.48% of 512 KB Flash) -- **Static RAM usage**: 5632 Bytes (5.73% of 96 KB RAM) +- **Toolchain**: Arm GNU Toolchain 14.2.Rel1 (GCC 14.2.1), the version pinned by CI +- **Static ROM usage**: 20120 Bytes (3.84% of 512 KB Flash) +- **Static RAM usage**: 6000 Bytes (6.10% of 96 KB RAM) - **Dynamic Stack & Buffer allocation**: Stacks (8 x 1024 bytes) and Queue buffer (40 bytes) are dynamically allocated from the `TX_BYTE_POOL` (consuming 8312 bytes total, including pool headers). - **Board Hardware**: NUCLEO-F401RE diff --git a/STMicroelectronics/NUCLEO_F401RE/app/CMakeLists.txt b/targets/STMicroelectronics/NUCLEO_F401RE/app/CMakeLists.txt similarity index 73% rename from STMicroelectronics/NUCLEO_F401RE/app/CMakeLists.txt rename to targets/STMicroelectronics/NUCLEO_F401RE/app/CMakeLists.txt index 8d79eb17..19172319 100644 --- a/STMicroelectronics/NUCLEO_F401RE/app/CMakeLists.txt +++ b/targets/STMicroelectronics/NUCLEO_F401RE/app/CMakeLists.txt @@ -6,14 +6,8 @@ # # SPDX-License-Identifier: MIT -if(NOT APP_CONFIG) - set(APP_CONFIG "starter") -endif() - -message(STATUS "Building application with configuration: ${APP_CONFIG}") - set(COMMON_DIR ${CMAKE_CURRENT_SOURCE_DIR}/common) -set(CONFIG_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${APP_CONFIG}) +set(STARTER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/starter) set(SOURCES ${COMMON_DIR}/startup/system_stm32f4xx.c @@ -22,11 +16,11 @@ set(SOURCES ${COMMON_DIR}/stm32cubef4/stm32f4xx_hal_msp.c - ${COMMON_DIR}/board_init.c - ${COMMON_DIR}/console.c - ${COMMON_DIR}/newlib_syscalls.c - - ${CONFIG_DIR}/main.c + # Newlib syscall overrides. Compiled into the executable rather than into + # libnucleo_bsp.a so the linker always takes these definitions instead of + # falling back to the libnosys stubs. + ${CMAKE_CURRENT_SOURCE_DIR}/../lib/bsp/src/newlib_stubs.c + ${STARTER_DIR}/main.c ) add_executable(${PROJECT_NAME} ${SOURCES}) @@ -41,7 +35,7 @@ target_link_libraries(${PROJECT_NAME} target_include_directories(${PROJECT_NAME} PUBLIC ${COMMON_DIR} - ${CONFIG_DIR} + ${STARTER_DIR} ) # Linker script diff --git a/STMicroelectronics/NUCLEO_F401RE/app/common/sntp_client.c b/targets/STMicroelectronics/NUCLEO_F401RE/app/common/sntp_client.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/app/common/sntp_client.c rename to targets/STMicroelectronics/NUCLEO_F401RE/app/common/sntp_client.c diff --git a/STMicroelectronics/NUCLEO_F401RE/app/common/startup/NUCLEO_F401RE.ld b/targets/STMicroelectronics/NUCLEO_F401RE/app/common/startup/NUCLEO_F401RE.ld similarity index 97% rename from STMicroelectronics/NUCLEO_F401RE/app/common/startup/NUCLEO_F401RE.ld rename to targets/STMicroelectronics/NUCLEO_F401RE/app/common/startup/NUCLEO_F401RE.ld index 6a476ef6..89063664 100644 --- a/STMicroelectronics/NUCLEO_F401RE/app/common/startup/NUCLEO_F401RE.ld +++ b/targets/STMicroelectronics/NUCLEO_F401RE/app/common/startup/NUCLEO_F401RE.ld @@ -23,6 +23,7 @@ ** @attention ** ** Copyright (c) 2022 STMicroelectronics. +** Copyright (c) 2026 Eclipse ThreadX contributors ** All rights reserved. ** ** This software is licensed under terms that can be found in the LICENSE file @@ -171,6 +172,8 @@ SECTIONS PROVIDE ( end = . ); PROVIDE ( _end = . ); . = . + _Min_Heap_Size; + /* Upper bound enforced by _sbrk() in lib/bsp/src/newlib_stubs.c. */ + PROVIDE ( _heap_limit = . ); . = . + _Min_Stack_Size; . = ALIGN(8); /* ThreadX: first free RAM after reserved heap/stack (tx_initialize_low_level.S). */ diff --git a/STMicroelectronics/NUCLEO_F401RE/app/common/startup/startup_stm32f401xe.s b/targets/STMicroelectronics/NUCLEO_F401RE/app/common/startup/startup_stm32f401xe.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/app/common/startup/startup_stm32f401xe.s rename to targets/STMicroelectronics/NUCLEO_F401RE/app/common/startup/startup_stm32f401xe.s diff --git a/STMicroelectronics/NUCLEO_F401RE/app/common/startup/system_stm32f4xx.c b/targets/STMicroelectronics/NUCLEO_F401RE/app/common/startup/system_stm32f4xx.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/app/common/startup/system_stm32f4xx.c rename to targets/STMicroelectronics/NUCLEO_F401RE/app/common/startup/system_stm32f4xx.c diff --git a/STMicroelectronics/NUCLEO_F401RE/app/common/startup/tx_initialize_low_level.S b/targets/STMicroelectronics/NUCLEO_F401RE/app/common/startup/tx_initialize_low_level.S similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/app/common/startup/tx_initialize_low_level.S rename to targets/STMicroelectronics/NUCLEO_F401RE/app/common/startup/tx_initialize_low_level.S diff --git a/STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c b/targets/STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c rename to targets/STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c diff --git a/STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h b/targets/STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h rename to targets/STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h diff --git a/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c b/targets/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c similarity index 99% rename from STMicroelectronics/NUCLEO_F401RE/app/starter/main.c rename to targets/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c index c1b2488f..53b79b84 100644 --- a/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c +++ b/targets/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c @@ -11,10 +11,10 @@ #include #include "tx_api.h" - -#include "board_init.h" +#include "bsp/board.h" +#include "bsp/led.h" +#include "bsp/console.h" #include "cloud_config.h" -#include "nucleo_bsp.h" #define THREAD_STACK_SIZE 1024 @@ -237,7 +237,7 @@ static void blink_thread_entry(ULONG parameter) { (void)parameter; while (1) { - nucleo_led_toggle(); + bsp_led_toggle(); blink_counter++; /* Toggle Event Flag bit 0 when LED toggles */ tx_event_flags_set(&event_flags, 0x01, TX_OR); @@ -541,7 +541,7 @@ void tx_application_define(void *first_unused_memory) { } int main(void) { - board_init(); + bsp_board_init(); /* Start the ThreadX kernel */ tx_kernel_enter(); diff --git a/STMicroelectronics/NUCLEO_F401RE/cmake/FindCMSIS.cmake b/targets/STMicroelectronics/NUCLEO_F401RE/cmake/FindCMSIS.cmake similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/cmake/FindCMSIS.cmake rename to targets/STMicroelectronics/NUCLEO_F401RE/cmake/FindCMSIS.cmake diff --git a/STMicroelectronics/NUCLEO_F401RE/cmake/FindSTM32HAL.cmake b/targets/STMicroelectronics/NUCLEO_F401RE/cmake/FindSTM32HAL.cmake similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/cmake/FindSTM32HAL.cmake rename to targets/STMicroelectronics/NUCLEO_F401RE/cmake/FindSTM32HAL.cmake diff --git a/STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-m4.cmake b/targets/STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-m4.cmake similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-m4.cmake rename to targets/STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-m4.cmake diff --git a/STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-toolchain.cmake b/targets/STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-toolchain.cmake similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-toolchain.cmake rename to targets/STMicroelectronics/NUCLEO_F401RE/cmake/arm-gcc-cortex-toolchain.cmake diff --git a/STMicroelectronics/NUCLEO_F401RE/cmake/utilities.cmake b/targets/STMicroelectronics/NUCLEO_F401RE/cmake/utilities.cmake similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/cmake/utilities.cmake rename to targets/STMicroelectronics/NUCLEO_F401RE/cmake/utilities.cmake diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/CMakeLists.txt b/targets/STMicroelectronics/NUCLEO_F401RE/lib/CMakeLists.txt similarity index 94% rename from STMicroelectronics/NUCLEO_F401RE/lib/CMakeLists.txt rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/CMakeLists.txt index 1cc6f3c4..ffd3d29e 100644 --- a/STMicroelectronics/NUCLEO_F401RE/lib/CMakeLists.txt +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/CMakeLists.txt @@ -18,4 +18,5 @@ add_subdirectory(${SHARED_LIB_DIR}/threadx threadx) # STM32 platform libraries add_subdirectory(stm32cubef4) -add_subdirectory(nucleo_bsp) +add_subdirectory(bsp) + diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/CMakeLists.txt b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/CMakeLists.txt new file mode 100644 index 00000000..bd70c9b0 --- /dev/null +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/CMakeLists.txt @@ -0,0 +1,28 @@ +# 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 + +# Board support implementation for the ST NUCLEO-F401RE. +# newlib_stubs.c is deliberately absent: the newlib syscall overrides are +# compiled straight into the application so they are never subject to static +# archive extraction order. See ../../app/CMakeLists.txt. +add_library(nucleo_bsp STATIC + src/bsp_board.c + src/bsp_led.c + src/bsp_console.c +) + +target_include_directories(nucleo_bsp + PUBLIC + include + ${SAMPLEX_ROOT_DIR}/bsp/include +) + +target_link_libraries(nucleo_bsp + PUBLIC + stm32cubef4 +) diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/board_config.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/board_config.h new file mode 100644 index 00000000..3f7af472 --- /dev/null +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/board_config.h @@ -0,0 +1,35 @@ +/* + * 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 + */ + +#ifndef BOARD_CONFIG_H +#define BOARD_CONFIG_H + +#include + +/* CPU Subsystem Frequencies */ +#define BSP_CPU_CLOCK_HZ 84000000UL /* 84 MHz Cortex-M4 SYSCLK */ +#define BSP_SYSTEM_CLOCK_HZ BSP_CPU_CLOCK_HZ + +#define BSP_UART_BAUDRATE 115200 + +/* SRAM Memory Limits (STM32F401RE: 96 KB SRAM from 0x20000000 to 0x20018000). + * + * Descriptive only. Do NOT bound the heap against BSP_RAM_END: the top of SRAM + * holds the main stack, and NUCLEO_F401RE.ld places the ThreadX byte pool (and + * therefore every thread stack) below it. _sbrk() uses the linker-provided + * _heap_limit symbol, which is the single source of truth for the heap extent. */ +#define BSP_RAM_START 0x20000000UL +#define BSP_RAM_SIZE 0x00018000UL /* 96 KB */ +#define BSP_RAM_END (BSP_RAM_START + BSP_RAM_SIZE) + +#define BSP_HAS_LED 1 +#define BSP_HAS_CONSOLE 1 + +#endif /* BOARD_CONFIG_H */ diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/nucleo_console.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/nucleo_console.h new file mode 100644 index 00000000..a9f66dff --- /dev/null +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/nucleo_console.h @@ -0,0 +1,28 @@ +/* + * 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 + */ + +#ifndef NUCLEO_CONSOLE_H +#define NUCLEO_CONSOLE_H + +#include + +/** + * @brief Block until length characters have been read from the console UART. + * + * Target-local companion to bsp_console_write(). The generic + * contract is write-only, so console input stays board specific rather than + * forcing an unimplemented read into every target's BSP. + * + * @param data Buffer receiving the characters read. + * @param length Number of characters to read. + */ +void nucleo_console_read(char *data, size_t length); + +#endif /* NUCLEO_CONSOLE_H */ diff --git a/STMicroelectronics/NUCLEO_F401RE/app/common/board_init.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_board.c similarity index 73% rename from STMicroelectronics/NUCLEO_F401RE/app/common/board_init.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_board.c index 9e8e052e..75c5f201 100644 --- a/STMicroelectronics/NUCLEO_F401RE/app/common/board_init.c +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_board.c @@ -1,38 +1,37 @@ -/* +/*************************************************************************** * 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 - */ -// Some portions generated by Codex (GPT-5). - -#include "board_init.h" - -#include - -#include "nucleo_bsp.h" - -UART_HandleTypeDef UartHandle; + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Codex (GPT-5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +#include "bsp/board.h" +#include "bsp/led.h" +#include "bsp/console.h" +#include "board_config.h" +#include "stm32f4xx_hal.h" static TIM_HandleTypeDef hal_tick_tim_handle; static void SystemClock_Config(void); -static void GPIO_Init(void); -static void UART_Console_Init(void); static void Error_Handler(void); -void board_init(void) +void bsp_board_init(void) { HAL_Init(); SystemClock_Config(); SystemCoreClockUpdate(); - GPIO_Init(); - UART_Console_Init(); - nucleo_bsp_init(); + bsp_led_init(); + bsp_console_init(); } /** @@ -72,28 +71,6 @@ static void SystemClock_Config(void) } } -static void GPIO_Init(void) -{ - __HAL_RCC_GPIOA_CLK_ENABLE(); -} - -static void UART_Console_Init(void) -{ - UartHandle.Instance = USART2; - UartHandle.Init.BaudRate = 115200; - UartHandle.Init.WordLength = UART_WORDLENGTH_8B; - UartHandle.Init.StopBits = UART_STOPBITS_1; - UartHandle.Init.Parity = UART_PARITY_NONE; - UartHandle.Init.Mode = UART_MODE_TX_RX; - UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; - UartHandle.Init.OverSampling = UART_OVERSAMPLING_16; - - if (HAL_UART_Init(&UartHandle) != HAL_OK) - { - Error_Handler(); - } -} - static void Error_Handler(void) { while (1) @@ -135,7 +112,6 @@ HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) return HAL_ERROR; } - /* Save the new tick priority */ uwTickPrio = TickPriority; return HAL_TIM_Base_Start_IT(&hal_tick_tim_handle); @@ -156,12 +132,10 @@ void TIM2_IRQHandler(void) void HAL_SuspendTick(void) { - /* Disable TIM2 update interrupt */ __HAL_TIM_DISABLE_IT(&hal_tick_tim_handle, TIM_IT_UPDATE); } void HAL_ResumeTick(void) { - /* Enable TIM2 update interrupt */ __HAL_TIM_ENABLE_IT(&hal_tick_tim_handle, TIM_IT_UPDATE); } diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_console.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_console.c new file mode 100644 index 00000000..df71a8ca --- /dev/null +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_console.c @@ -0,0 +1,99 @@ +/*************************************************************************** + * 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/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Codex (GPT-5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +#include "bsp/console.h" +#include "board_config.h" +#include "nucleo_console.h" +#include "stm32f4xx_hal.h" + +#include +#include + +#if BSP_HAS_CONSOLE +static UART_HandleTypeDef console_uart; + +static void console_error_handler(void); + +/** + * Halt on an unrecoverable console fault. The console is the only diagnostic + * channel on this board, so there is nothing left to report a failure through. + */ +static void console_error_handler(void) +{ + while (1) + { + } +} +#endif + +void bsp_console_init(void) +{ +#if BSP_HAS_CONSOLE + /* GPIO and USART2 clocks are enabled by HAL_UART_MspInit(); enabling them + * here as well would duplicate the single owner of that configuration. */ + console_uart.Instance = USART2; + console_uart.Init.BaudRate = BSP_UART_BAUDRATE; + console_uart.Init.WordLength = UART_WORDLENGTH_8B; + console_uart.Init.StopBits = UART_STOPBITS_1; + console_uart.Init.Parity = UART_PARITY_NONE; + console_uart.Init.Mode = UART_MODE_TX_RX; + console_uart.Init.HwFlowCtl = UART_HWCONTROL_NONE; + console_uart.Init.OverSampling = UART_OVERSAMPLING_16; + + if (HAL_UART_Init(&console_uart) != HAL_OK) + { + console_error_handler(); + } +#endif +} + +void bsp_console_write(const char *data, size_t length) +{ +#if BSP_HAS_CONSOLE + if ((data == NULL) || (length == 0U)) + { + return; + } + + /* MISRA C:2012 Rule 11.8 deviation: HAL_UART_Transmit() takes a non-const + * uint8_t* even though it only reads the buffer. The cast is confined to + * this call and the pointed-to data is never modified. */ + (void)HAL_UART_Transmit(&console_uart, + (uint8_t *)(uintptr_t)(const void *)data, + (uint16_t)length, + HAL_MAX_DELAY); +#else + (void)data; + (void)length; +#endif +} + +void nucleo_console_read(char *data, size_t length) +{ +#if BSP_HAS_CONSOLE + if ((data == NULL) || (length == 0U)) + { + return; + } + + (void)HAL_UART_Receive(&console_uart, + (uint8_t *)data, + (uint16_t)length, + HAL_MAX_DELAY); +#else + (void)data; + (void)length; +#endif +} diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_led.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_led.c new file mode 100644 index 00000000..07b0a385 --- /dev/null +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_led.c @@ -0,0 +1,59 @@ +/*************************************************************************** + * 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/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Codex (GPT-5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +#include "bsp/led.h" +#include "board_config.h" +#include "stm32f4xx_hal.h" + +#define NUCLEO_LED_PIN GPIO_PIN_5 +#define NUCLEO_LED_GPIO_PORT GPIOA + +void bsp_led_init(void) +{ +#if BSP_HAS_LED + GPIO_InitTypeDef gpio = {0}; + + __HAL_RCC_GPIOA_CLK_ENABLE(); + + gpio.Pin = NUCLEO_LED_PIN; + gpio.Mode = GPIO_MODE_OUTPUT_PP; + gpio.Pull = GPIO_NOPULL; + gpio.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(NUCLEO_LED_GPIO_PORT, &gpio); + + bsp_led_off(); +#endif +} + +void bsp_led_on(void) +{ +#if BSP_HAS_LED + HAL_GPIO_WritePin(NUCLEO_LED_GPIO_PORT, NUCLEO_LED_PIN, GPIO_PIN_SET); +#endif +} + +void bsp_led_off(void) +{ +#if BSP_HAS_LED + HAL_GPIO_WritePin(NUCLEO_LED_GPIO_PORT, NUCLEO_LED_PIN, GPIO_PIN_RESET); +#endif +} + +void bsp_led_toggle(void) +{ +#if BSP_HAS_LED + HAL_GPIO_TogglePin(NUCLEO_LED_GPIO_PORT, NUCLEO_LED_PIN); +#endif +} diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/newlib_stubs.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/newlib_stubs.c new file mode 100644 index 00000000..82d8c851 --- /dev/null +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/newlib_stubs.c @@ -0,0 +1,201 @@ +/*************************************************************************** + * 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/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Codex (GPT-5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* + * Newlib retargeting for the NUCLEO-F401RE. + * + * Every newlib syscall override lives in this translation unit, which is + * compiled directly into the application (see ../../../app/CMakeLists.txt) + * rather than archived into libnucleo_bsp.a. A static archive member is only + * extracted when an undefined symbol already demands it, and newlib's own + * references are resolved after the BSP archive has been scanned; keeping the + * overrides in an always-linked object guarantees they win over the + * libnosys stubs instead of depending on archive ordering. + */ + +#include +#include +#include +#include + +#include "bsp/console.h" +#include "nucleo_console.h" +#include "stm32f4xx.h" + +/* + * Linker-defined bounds of the heap reservation in NUCLEO_F401RE.ld. + * MISRA C:2012 Rule 8.6 deviation: these symbols are defined by the linker + * script, not by any translation unit, which is the only way to import an + * address decided at link time. + */ +extern char _end; +extern char _heap_limit; + +/* + * newlib declares these in its internal headers only. Declaring them here + * keeps every definition preceded by a prototype (MISRA C:2012 Rule 8.4). + */ +void *_sbrk(ptrdiff_t incr); +int _close(int file); +int _fstat(int file, struct stat *st); +int _isatty(int file); +int _lseek(int file, int ptr, int dir); +void _exit(int status); +int _kill(int pid, int sig); +int _getpid(void); +int _read(int file, char *ptr, int len); +int _write(int file, char *ptr, int len); +int __io_putchar(int ch); +int __io_getchar(void); + +void *_sbrk(ptrdiff_t incr) +{ + static uint8_t *heap_ptr = NULL; + + const uintptr_t heap_base = (uintptr_t)&_end; + const uintptr_t heap_limit = (uintptr_t)&_heap_limit; + + uintptr_t current; + uintptr_t next; + uint32_t primask; + + /* Mask interrupts to ensure thread-safe heap pointer mutation on Cortex-M4. + * This protects the break pointer only; newlib's malloc free lists remain + * unguarded, so concurrent malloc() from multiple threads still requires + * newlib's own lock hooks. */ + primask = __get_PRIMASK(); + __disable_irq(); + + if (heap_ptr == NULL) { + heap_ptr = (uint8_t *)heap_base; + } + current = (uintptr_t)heap_ptr; + + if (incr < 0) { + /* Negate without overflowing on PTRDIFF_MIN. */ + uintptr_t decrement = (uintptr_t)(-(incr + 1)) + 1U; + + if (decrement > (current - heap_base)) { + __set_PRIMASK(primask); + errno = EINVAL; + return (void *)-1; + } + next = current - decrement; + } else { + uintptr_t increment = (uintptr_t)incr; + + /* Bound against the end of the heap reservation, not the end of SRAM: + * beyond _heap_limit lie the reserved main stack and the ThreadX byte + * pool holding every thread stack. */ + if (increment > (heap_limit - current)) { + __set_PRIMASK(primask); + errno = ENOMEM; + return (void *)-1; + } + next = current + increment; + } + + heap_ptr = (uint8_t *)next; + + __set_PRIMASK(primask); + return (void *)current; +} + +int _close(int file) +{ + (void)file; + return -1; +} + +int _fstat(int file, struct stat *st) +{ + (void)file; + st->st_mode = S_IFCHR; + return 0; +} + +int _isatty(int file) +{ + (void)file; + return 1; +} + +int _lseek(int file, int ptr, int dir) +{ + (void)file; + (void)ptr; + (void)dir; + return 0; +} + +void _exit(int status) +{ + (void)status; + __disable_irq(); + while (1) { + __WFI(); + } +} + +int _kill(int pid, int sig) +{ + (void)pid; + (void)sig; + errno = EINVAL; + return -1; +} + +int _getpid(void) +{ + return 1; +} + +int __io_putchar(int ch) +{ + char c = (char)ch; + + bsp_console_write(&c, 1U); + return ch; +} + +int __io_getchar(void) +{ + char ch = '\0'; + + nucleo_console_read(&ch, 1U); + return (int)(unsigned char)ch; +} + +int _read(int file, char *ptr, int len) +{ + (void)file; + + if ((ptr == NULL) || (len <= 0)) { + return 0; + } + nucleo_console_read(ptr, (size_t)len); + return len; +} + +int _write(int file, char *ptr, int len) +{ + (void)file; + + if ((ptr == NULL) || (len <= 0)) { + return 0; + } + bsp_console_write(ptr, (size_t)len); + return len; +} diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/CMakeLists.txt b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/CMakeLists.txt similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/CMakeLists.txt rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/CMakeLists.txt diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f401xe.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f401xe.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f401xe.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f401xe.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f412rx.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f412rx.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f412rx.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f412rx.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Include/system_stm32f4xx.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Release_Notes.html b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Release_Notes.html similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Release_Notes.html rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Release_Notes.html diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f401xc.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f401xc.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f401xc.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f401xc.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f401xe.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f401xe.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f401xe.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f401xe.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f405xx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f405xx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f405xx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f405xx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f407xx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f407xx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f407xx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f407xx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f410cx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f410cx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f410cx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f410cx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f410rx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f410rx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f410rx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f410rx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f410tx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f410tx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f410tx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f410tx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f411xe.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f411xe.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f411xe.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f411xe.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412cx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412cx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412cx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412cx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412rx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412rx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412rx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412rx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412vx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412vx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412vx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412vx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412zx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412zx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412zx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f412zx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f413xx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f413xx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f413xx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f413xx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f415xx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f415xx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f415xx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f415xx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f417xx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f417xx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f417xx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f417xx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f423xx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f423xx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f423xx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f423xx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f427xx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f427xx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f427xx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f427xx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f429xx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f429xx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f429xx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f429xx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f437xx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f437xx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f437xx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f437xx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f439xx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f439xx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f439xx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f439xx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f446xx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f446xx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f446xx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f446xx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f469xx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f469xx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f469xx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f469xx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f479xx.s b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f479xx.s similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f479xx.s rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f479xx.s diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/_htmresc/mini-st.css b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/_htmresc/mini-st.css similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/_htmresc/mini-st.css rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/_htmresc/mini-st.css diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/_htmresc/st_logo.png b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/_htmresc/st_logo.png similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/_htmresc/st_logo.png rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Device/ST/STM32F4xx/_htmresc/st_logo.png diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_armcc.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_armcc.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_armcc.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_armcc.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_armclang.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_armclang.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_armclang.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_armclang.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_compiler.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_compiler.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_compiler.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_compiler.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_gcc.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_gcc.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_gcc.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_gcc.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_iccarm.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_iccarm.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_iccarm.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_iccarm.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_version.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_version.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_version.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/cmsis_version.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_armv8mbl.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_armv8mbl.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_armv8mbl.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_armv8mbl.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_armv8mml.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_armv8mml.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_armv8mml.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_armv8mml.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm0.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm0.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm0.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm0.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm0plus.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm0plus.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm0plus.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm0plus.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm1.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm1.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm1.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm1.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm23.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm23.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm23.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm23.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm3.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm3.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm3.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm3.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm33.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm33.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm33.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm33.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm4.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm4.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm4.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm4.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm7.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm7.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm7.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_cm7.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_sc000.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_sc000.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_sc000.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_sc000.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_sc300.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_sc300.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_sc300.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/core_sc300.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/mpu_armv7.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/mpu_armv7.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/mpu_armv7.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/mpu_armv7.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/mpu_armv8.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/mpu_armv8.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/mpu_armv8.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/mpu_armv8.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/tz_context.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/tz_context.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/tz_context.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/Include/tz_context.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/LICENSE.txt b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/LICENSE.txt similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/LICENSE.txt rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/LICENSE.txt diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/README.md b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/README.md similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/README.md rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/CMSIS/README.md diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32f4xx_hal_can_legacy.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32f4xx_hal_can_legacy.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32f4xx_hal_can_legacy.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32f4xx_hal_can_legacy.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32_assert_template.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32_assert_template.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32_assert_template.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32_assert_template.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cec.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cec.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cec.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cec.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_conf_template.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_conf_template.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_conf_template.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_conf_template.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_crc.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_crc.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_crc.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_crc.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dac.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dac.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dac.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dac.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dac_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dac_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dac_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dac_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dfsdm.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dfsdm.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dfsdm.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dfsdm.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma2d.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma2d.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma2d.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma2d.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dsi.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dsi.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dsi.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dsi.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_eth.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_eth.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_eth.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_eth.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpsmbus.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpsmbus.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpsmbus.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpsmbus.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hcd.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hcd.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hcd.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hcd.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_irda.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_irda.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_irda.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_irda.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_iwdg.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_iwdg.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_iwdg.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_iwdg.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_lptim.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_lptim.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_lptim.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_lptim.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_mmc.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_mmc.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_mmc.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_mmc.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nand.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nand.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nand.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nand.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nor.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nor.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nor.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nor.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pccard.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pccard.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pccard.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pccard.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_qspi.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_qspi.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_qspi.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_qspi.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rng.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rng.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rng.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rng.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sd.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sd.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sd.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sd.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sdram.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sdram.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sdram.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sdram.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smartcard.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smartcard.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smartcard.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smartcard.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smbus.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smbus.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smbus.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smbus.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spdifrx.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spdifrx.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spdifrx.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spdifrx.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sram.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sram.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sram.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sram.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_usart.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_usart.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_usart.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_usart.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_wwdg.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_wwdg.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_wwdg.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_wwdg.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_adc.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_adc.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_adc.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_adc.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_bus.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_bus.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_bus.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_bus.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_cortex.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_cortex.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_cortex.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_cortex.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_crc.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_crc.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_crc.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_crc.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dac.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dac.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dac.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dac.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma2d.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma2d.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma2d.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma2d.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_exti.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_exti.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_exti.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_exti.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmc.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmc.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmc.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmc.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmpi2c.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmpi2c.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmpi2c.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmpi2c.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fsmc.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fsmc.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fsmc.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fsmc.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_gpio.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_gpio.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_gpio.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_gpio.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_i2c.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_i2c.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_i2c.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_i2c.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_iwdg.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_iwdg.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_iwdg.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_iwdg.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_lptim.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_lptim.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_lptim.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_lptim.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_pwr.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_pwr.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_pwr.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_pwr.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rcc.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rcc.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rcc.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rcc.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rng.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rng.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rng.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rng.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rtc.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rtc.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rtc.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rtc.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_sdmmc.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_sdmmc.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_sdmmc.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_sdmmc.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_spi.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_spi.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_spi.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_spi.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_system.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_system.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_system.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_system.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_tim.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_tim.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_tim.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_tim.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usart.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usart.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usart.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usart.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usb.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usb.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usb.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usb.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_utils.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_utils.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_utils.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_utils.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_wwdg.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_wwdg.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_wwdg.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_wwdg.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/License.md b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/License.md similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/License.md rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/License.md diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/README.md b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/README.md similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/README.md rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/README.md diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/Legacy/stm32f4xx_hal_can.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/Legacy/stm32f4xx_hal_can.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/Legacy/stm32f4xx_hal_can.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/Legacy/stm32f4xx_hal_can.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cec.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cec.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cec.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cec.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_crc.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_crc.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_crc.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_crc.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp_ex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp_ex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp_ex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp_ex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac_ex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac_ex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac_ex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac_ex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi_ex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi_ex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi_ex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi_ex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dfsdm.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dfsdm.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dfsdm.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dfsdm.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma2d.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma2d.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma2d.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma2d.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dsi.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dsi.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dsi.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dsi.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_eth.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_eth.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_eth.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_eth.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c_ex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c_ex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c_ex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c_ex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpsmbus.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpsmbus.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpsmbus.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpsmbus.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash_ex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash_ex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash_ex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash_ex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hcd.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hcd.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hcd.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hcd.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s_ex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s_ex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s_ex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s_ex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_irda.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_irda.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_irda.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_irda.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_iwdg.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_iwdg.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_iwdg.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_iwdg.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_lptim.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_lptim.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_lptim.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_lptim.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc_ex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc_ex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc_ex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc_ex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_mmc.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_mmc.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_mmc.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_mmc.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_msp_template.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_msp_template.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_msp_template.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_msp_template.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nand.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nand.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nand.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nand.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nor.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nor.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nor.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nor.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pccard.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pccard.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pccard.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pccard.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_qspi.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_qspi.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_qspi.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_qspi.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rng.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rng.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rng.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rng.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc_ex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc_ex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc_ex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc_ex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai_ex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai_ex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai_ex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai_ex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sdram.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sdram.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sdram.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sdram.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smartcard.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smartcard.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smartcard.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smartcard.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smbus.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smbus.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smbus.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smbus.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spdifrx.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spdifrx.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spdifrx.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spdifrx.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sram.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sram.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sram.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sram.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_alarm_template.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_alarm_template.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_alarm_template.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_alarm_template.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_wakeup_template.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_wakeup_template.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_wakeup_template.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_wakeup_template.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_tim.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_tim.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_tim.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_tim.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_tim_template.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_tim_template.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_tim_template.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_tim_template.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_usart.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_usart.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_usart.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_usart.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_wwdg.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_wwdg.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_wwdg.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_wwdg.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_adc.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_adc.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_adc.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_adc.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_crc.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_crc.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_crc.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_crc.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dac.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dac.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dac.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dac.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma2d.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma2d.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma2d.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma2d.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_exti.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_exti.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_exti.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_exti.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmc.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmc.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmc.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmc.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmpi2c.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmpi2c.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmpi2c.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmpi2c.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fsmc.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fsmc.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fsmc.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fsmc.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_gpio.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_gpio.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_gpio.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_gpio.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_i2c.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_i2c.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_i2c.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_i2c.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_lptim.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_lptim.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_lptim.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_lptim.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_pwr.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_pwr.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_pwr.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_pwr.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rcc.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rcc.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rcc.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rcc.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rng.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rng.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rng.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rng.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rtc.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rtc.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rtc.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rtc.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_spi.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_spi.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_spi.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_spi.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_tim.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_tim.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_tim.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_tim.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usart.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usart.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usart.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usart.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_utils.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_utils.c similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_utils.c rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_utils.c diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/config/stm32f4xx_hal_conf.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/config/stm32f4xx_hal_conf.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/config/stm32f4xx_hal_conf.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/stm32cubef4/config/stm32f4xx_hal_conf.h diff --git a/STMicroelectronics/NUCLEO_F401RE/lib/threadx/tx_user.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/threadx/tx_user.h similarity index 100% rename from STMicroelectronics/NUCLEO_F401RE/lib/threadx/tx_user.h rename to targets/STMicroelectronics/NUCLEO_F401RE/lib/threadx/tx_user.h diff --git a/STMicroelectronics/NUCLEO_F401RE/scripts/build.ps1 b/targets/STMicroelectronics/NUCLEO_F401RE/scripts/build.ps1 similarity index 96% rename from STMicroelectronics/NUCLEO_F401RE/scripts/build.ps1 rename to targets/STMicroelectronics/NUCLEO_F401RE/scripts/build.ps1 index bcb31ae6..07af7c68 100644 --- a/STMicroelectronics/NUCLEO_F401RE/scripts/build.ps1 +++ b/targets/STMicroelectronics/NUCLEO_F401RE/scripts/build.ps1 @@ -3,7 +3,6 @@ # SPDX-License-Identifier: MIT param( - [string]$Config = "starter", [switch]$Clean, [switch]$Rebuild ) @@ -17,7 +16,6 @@ Write-Host "Nucleo F401RE - Build Script (PowerShell)" Write-Host "==========================================" Write-Host "Board Dir: $BOARD_DIR" Write-Host "Build Dir: $BUILD_DIR" -Write-Host "Config: $Config" Write-Host "" # Check for ARM GCC compiler @@ -49,7 +47,6 @@ if (!(Test-Path "CMakeCache.txt") -or !(Test-Path "build.ninja") -or $Rebuild) { Write-Host "[INFO] Configuring CMake..." cmake -G Ninja ` "-DCMAKE_BUILD_TYPE=Release" ` - "-DAPP_CONFIG=$Config" ` "-DCMAKE_POLICY_VERSION_MINIMUM=3.5" ` $BOARD_DIR if ($LASTEXITCODE -ne 0) { diff --git a/STMicroelectronics/NUCLEO_F401RE/scripts/build.sh b/targets/STMicroelectronics/NUCLEO_F401RE/scripts/build.sh similarity index 91% rename from STMicroelectronics/NUCLEO_F401RE/scripts/build.sh rename to targets/STMicroelectronics/NUCLEO_F401RE/scripts/build.sh index f1a48f3c..eb062451 100644 --- a/STMicroelectronics/NUCLEO_F401RE/scripts/build.sh +++ b/targets/STMicroelectronics/NUCLEO_F401RE/scripts/build.sh @@ -7,7 +7,6 @@ # Fail on error set -e -CONFIG="starter" CLEAN=false REBUILD=false @@ -23,16 +22,11 @@ echo "Nucleo F401RE - Build Script (Bash)" echo "==========================================" echo "Board Dir: $BOARD_DIR" echo "Build Dir: $BUILD_DIR" -echo "Config: $CONFIG" echo "" # Parse options while [[ $# -gt 0 ]]; do case "$1" in - -c|--config) - CONFIG="$2" - shift 2 - ;; --clean) CLEAN=true shift @@ -43,7 +37,7 @@ while [[ $# -gt 0 ]]; do ;; *) echo "Unknown option: $1" - echo "Usage: $0 [--config CONFIG] [--clean] [--rebuild]" + echo "Usage: $0 [--clean] [--rebuild]" exit 1 ;; esac @@ -101,13 +95,11 @@ if [ ! -f "CMakeCache.txt" ] || [ ! -f "build.ninja" ] || [ "$REBUILD" = true ]; if command -v ninja &>/dev/null; then cmake -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ - -DAPP_CONFIG="$CONFIG" \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ "$BOARD_DIR" else cmake \ -DCMAKE_BUILD_TYPE=Release \ - -DAPP_CONFIG="$CONFIG" \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ "$BOARD_DIR" fi From ef61eae9bf256b0b2d92819971e7a25b86d06887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 31 Aug 2026 11:44:17 -0400 Subject: [PATCH 07/20] Added Renode regression tests for the NUCLEO-F401RE target (#51) The ARM target had no runtime test. Its CI job checked only that the ELF existed, so the clock configuration, the TIM2 HAL timebase, the console and the heap bound were all unexercised. This brings it to parity with the PolarFire target, which gates CI on a headless Renode run. Renode ships no NUCLEO-F401RE board description, so renode/nucleo_f401re.repl derives one from the generic STM32F4 CPU platform and corrects Flash to 512 KB and SRAM to 96 KB. The generic platform is sized for the larger F407/F429 parts, and both the linker script's heap reservation and the _sbrk() bound depend on those limits being right. main.c gains seven startup self-tests that run before tx_kernel_enter(), so a failure is reported even when the scheduler never starts. They cover the _sbrk() allocate, release, underflow and over-limit paths, the invariant that the heap reservation ends at or below the ThreadX byte pool, the 84 MHz SystemCoreClock, and that TIM2 still ticks after HAL_RCC_ClockConfig() re-enters HAL_InitTick(). Test 4 is the regression guard for the heap bound fixed in #50. Requesting 32 KB fits inside the 96 KB SRAM but far exceeds the heap reservation. Reinstating the old end-of-SRAM bound was verified to fail the suite: newlib's first malloc() then took roughly 4 KB and put the break at 0x20002170, inside the ThreadX byte pool, which also broke self-tests 1 and 3. With the bound correct, _sbrk() refuses the oversized request, newlib retries smaller, and malloc(64) succeeds using 72 bytes of the 512-byte reservation - so the reservation is adequate and no heap growth is needed. scripts/test_renode.py drives nucleo_f401re_ci.resc, which advances a fixed span of virtual time and quits on its own rather than depending on wall clock. Beyond the self-tests it asserts the boot banner, that the blink thread and the 1 Hz application timer have both run (covering the LED path and the timer service), and that the mutex, queue, event-flag and semaphore counters are all non-zero. The suite was confirmed to exit 1 on a reintroduced bug and 0 on the fixed tree. The Robot Framework suite covers the same ground for renode-test, and the new test-nucleo-renode CI job mirrors test-polarfire-renode. main.c also drops a hardcoded 0x20018000 in favour of BSP_RAM_END now that board_config.h is in scope, with the 4 KB main-stack margin named. --- .github/workflows/ci.yml | 33 ++++ .../NUCLEO_F401RE/README.md | 58 +++++- .../NUCLEO_F401RE/app/starter/main.c | 108 ++++++++++- .../NUCLEO_F401RE/renode/nucleo_f401re.repl | 22 +++ .../renode/nucleo_f401re_ci.resc | 35 ++++ .../renode/nucleo_f401re_demo.resc | 25 +++ .../renode/nucleo_f401re_demo.robot | 26 +++ .../NUCLEO_F401RE/scripts/test_renode.py | 172 ++++++++++++++++++ 8 files changed, 474 insertions(+), 5 deletions(-) create mode 100644 targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re.repl create mode 100644 targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_ci.resc create mode 100644 targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_demo.resc create mode 100644 targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_demo.robot create mode 100755 targets/STMicroelectronics/NUCLEO_F401RE/scripts/test_renode.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a20de7e..88e9bb28 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -139,3 +139,36 @@ jobs: name: nucleo-f401re-demo-elf path: targets/STMicroelectronics/NUCLEO_F401RE/build/app/nucleo_f401re.elf retention-days: 1 + + test-nucleo-renode: + name: Headless Renode Emulation & Assertion Test (NUCLEO-F401RE) + needs: build-arm-nucleo + runs-on: ubuntu-24.04 + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Set Up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Download Built NUCLEO-F401RE ELF + uses: actions/download-artifact@v4 + with: + name: nucleo-f401re-demo-elf + path: targets/STMicroelectronics/NUCLEO_F401RE/build/app + + - name: Install Portable Renode Emulation Environment + run: | + wget -q https://builds.renode.io/renode-latest.linux-portable.tar.gz + mkdir -p $HOME/renode + tar -xzf renode-latest.linux-portable.tar.gz -C $HOME/renode --strip-components=1 + rm renode-latest.linux-portable.tar.gz + echo "$HOME/renode" >> $GITHUB_PATH + + - name: Run Deterministic Headless Renode Test + run: | + python3 targets/STMicroelectronics/NUCLEO_F401RE/scripts/test_renode.py diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/README.md b/targets/STMicroelectronics/NUCLEO_F401RE/README.md index 828a66ba..0c932dc4 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/README.md +++ b/targets/STMicroelectronics/NUCLEO_F401RE/README.md @@ -50,6 +50,59 @@ The package includes build scripts under the `scripts/` directory for convenienc These scripts clean the build directory, run CMake configuration, and compile the target executable. +## Emulation & Regression Testing + +Renode ships no NUCLEO-F401RE board description, so `renode/nucleo_f401re.repl` +derives one from the generic STM32F4 CPU platform, correcting Flash to 512 KB +and SRAM to 96 KB. Those limits matter: the linker script's heap reservation and +the `_sbrk()` bound both depend on them. + +### Interactive Simulation + +```bash +renode targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_demo.resc +``` + +USART2 is the demo console, shown in a terminal analyzer. + +### Automated Headless Test + +```bash +python3 targets/STMicroelectronics/NUCLEO_F401RE/scripts/test_renode.py +``` + +Runs `nucleo_f401re_ci.resc`, which advances a fixed span of virtual time and +quits on its own, so the result does not depend on host speed. Exits non-zero +if any assertion is unmet. This gates CI as the `test-nucleo-renode` job. + +The Robot Framework suite in `renode/nucleo_f401re_demo.robot` covers the same +ground for use with `renode-test`. + +### What is asserted + +The demo runs seven startup self-tests before `tx_kernel_enter()` and prints a +`[SELF-TEST]` summary the harness asserts on: + +| # | Self-test | Guards against | +|---|-----------|----------------| +| 1 | `_sbrk()` allocation lands inside the heap reservation | heap escaping its linker reservation | +| 2 | `_sbrk()` releases back to the heap base | broken negative-increment path | +| 3 | `_sbrk()` underflow rejected with `EINVAL` | shrinking below the heap base | +| 4 | `_sbrk()` rejects a request that fits SRAM but not the heap | bounding the heap at the end of SRAM | +| 5 | Heap reservation ends at or below the ThreadX byte pool | linker script layout regression | +| 6 | `SystemCoreClock` is 84 MHz | a silently wrong PLL configuration | +| 7 | HAL timebase (TIM2) tick advancing | `HAL_InitTick()` re-entry leaving TIM2 stopped | + +Test 4 is the regression guard for the heap bound. Requesting 32 KB fits inside +the 96 KB SRAM but far exceeds the heap reservation, so bounding `_sbrk()` +against the end of SRAM rather than `_heap_limit` let it succeed and handed +`malloc()` memory owned by the ThreadX byte pool and the main stack. + +Beyond the self-tests, the harness asserts the boot banner reaches the console, +the blink thread and the 1 Hz application timer have both run (covering the LED +path and the timer service), and that the mutex, queue, event-flag and semaphore +counters are all non-zero. + ## Flashing the Application Connect the NUCLEO-F401RE board via the ST-LINK USB connector. @@ -136,14 +189,15 @@ The BSP overrides `HAL_InitTick()` to configure TIM2 as the HAL timebase and pro - **`lib/stm32cubef4/`**: HAL Driver wrapper and platform drivers - **`lib/threadx/`**: ThreadX user configuration file (`tx_user.h`) - **`cmake/`**: Cross-compilation module definitions -- **`scripts/`**: Utility build automation scripts +- **`scripts/`**: Utility build automation scripts and the headless Renode test runner +- **`renode/`**: Renode platform description, run scripts, and Robot Framework suite ## Validation Record ### Verification Environment - **Toolchain**: Arm GNU Toolchain 14.2.Rel1 (GCC 14.2.1), the version pinned by CI -- **Static ROM usage**: 20120 Bytes (3.84% of 512 KB Flash) +- **Static ROM usage**: 22068 Bytes (4.21% of 512 KB Flash), including the startup self-tests - **Static RAM usage**: 6000 Bytes (6.10% of 96 KB RAM) - **Dynamic Stack & Buffer allocation**: Stacks (8 x 1024 bytes) and Queue buffer (40 bytes) are dynamically allocated from the `TX_BYTE_POOL` (consuming 8312 bytes total, including pool headers). - **Board Hardware**: NUCLEO-F401RE diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c b/targets/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c index 53b79b84..5493933e 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c +++ b/targets/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c @@ -8,16 +8,25 @@ * SPDX-License-Identifier: MIT */ +#include +#include +#include #include #include "tx_api.h" #include "bsp/board.h" #include "bsp/led.h" #include "bsp/console.h" +#include "board_config.h" #include "cloud_config.h" +#include "stm32f4xx_hal.h" #define THREAD_STACK_SIZE 1024 +/* Bytes of SRAM held back above the ThreadX byte pool for the main stack, + * which serves every interrupt handler once the scheduler is running. */ +#define MAIN_STACK_MARGIN 4096 + typedef struct { CHAR *name; UINT state; @@ -348,9 +357,9 @@ void tx_application_define(void *first_unused_memory) { CHAR *stack_ptr; ULONG pool_size; - /* Calculate available RAM for the byte pool, leaving 4KB margin for system - * stack at the top (0x20018000) */ - pool_size = (0x20018000 - 4096) - (ULONG)first_unused_memory; + /* Calculate available RAM for the byte pool, leaving a 4 KB margin for the + * main stack at the top of SRAM. */ + pool_size = (BSP_RAM_END - MAIN_STACK_MARGIN) - (ULONG)first_unused_memory; /* Initialize the byte pool */ status = tx_byte_pool_create(&byte_pool, "system byte pool", @@ -540,9 +549,102 @@ void tx_application_define(void *first_unused_memory) { thread_registry[8] = &semaphore_thread; } +/* ------------------------------------------------------------------------- * + * Startup self-tests + * + * These run before tx_kernel_enter() so a failure is reported even when the + * scheduler never starts. scripts/test_renode.py asserts on the summary line. + * ------------------------------------------------------------------------- */ + +/* Defined by NUCLEO_F401RE.ld rather than by any translation unit. */ +extern char _end; +extern char _heap_limit; +extern char __RAM_segment_used_end__; + +extern void *_sbrk(ptrdiff_t incr); + +static unsigned selftest_failures = 0; + +static void selftest_report(int passed, const char *message) { + if (passed) { + printf("[+] PASS: %s\r\n", message); + } else { + selftest_failures++; + printf("[-] FAIL: %s\r\n", message); + } +} + +static void run_startup_self_tests(void) { + const uintptr_t heap_base = (uintptr_t)&_end; + const uintptr_t heap_limit = (uintptr_t)&_heap_limit; + const uintptr_t pool_base = (uintptr_t)&__RAM_segment_used_end__; + char msg[128]; + + printf("[SELF-TEST] Starting BSP & Runtime Verification...\r\n"); + + /* 1. A modest request lands inside the heap reservation. */ + void *p_ok = _sbrk(64); + selftest_report((p_ok != (void *)-1) && ((uintptr_t)p_ok >= heap_base) && + ((uintptr_t)p_ok < heap_limit), + "_sbrk() valid allocation inside the heap reservation"); + + /* 2. Releasing it returns the break to the heap base, leaving the heap + * exactly as the remaining tests found it. */ + selftest_report(_sbrk(-64) != (void *)-1, + "_sbrk() released 64 bytes back to the heap base"); + + /* 3. Shrinking below the heap base is rejected. */ + errno = 0; + void *p_under = _sbrk(-128); + selftest_report((p_under == (void *)-1) && (errno == EINVAL), + "_sbrk() underflow guard rejected with EINVAL"); + + /* 4. Regression guard for the heap bound. 32 KB fits inside the 96 KB SRAM + * but far exceeds the heap reservation, so bounding _sbrk() against the end + * of SRAM rather than _heap_limit let this succeed and handed malloc() + * memory owned by the ThreadX byte pool and the main stack. */ + errno = 0; + void *p_over = _sbrk((ptrdiff_t)0x8000); + selftest_report((p_over == (void *)-1) && (errno == ENOMEM), + "_sbrk() rejects a request that fits SRAM but not the heap"); + + /* 5. The heap reservation must end at or below the first byte ThreadX owns. */ + snprintf(msg, sizeof(msg), + "heap [0x%08lX,0x%08lX) ends at or below the ThreadX pool at 0x%08lX", + (unsigned long)heap_base, (unsigned long)heap_limit, + (unsigned long)pool_base); + selftest_report(heap_limit <= pool_base, msg); + + /* 6. SystemClock_Config() reached the documented 84 MHz. */ + snprintf(msg, sizeof(msg), "SystemCoreClock is %lu Hz (expected %lu Hz)", + (unsigned long)SystemCoreClock, (unsigned long)BSP_CPU_CLOCK_HZ); + selftest_report(SystemCoreClock == (uint32_t)BSP_CPU_CLOCK_HZ, msg); + + /* 7. The HAL timebase runs on TIM2 so ThreadX keeps SysTick. HAL_InitTick() + * is re-entered by HAL_RCC_ClockConfig() once the PLL is live, so confirm the + * timer is still ticking afterwards. The spin cap is a liveness bound, not a + * timing expectation: one TIM2 tick is ~84000 core cycles. */ + uint32_t tick_start = HAL_GetTick(); + uint32_t spins = 0; + while ((HAL_GetTick() == tick_start) && (spins < 5000000UL)) { + spins++; + } + selftest_report(HAL_GetTick() != tick_start, + "HAL timebase (TIM2) tick advancing"); + + if (selftest_failures == 0) { + printf("[SELF-TEST] All startup verification tests PASSED!\r\n\r\n"); + } else { + printf("[SELF-TEST] %u startup verification test(s) FAILED!\r\n\r\n", + selftest_failures); + } +} + int main(void) { bsp_board_init(); + run_startup_self_tests(); + /* Start the ThreadX kernel */ tx_kernel_enter(); diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re.repl b/targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re.repl new file mode 100644 index 00000000..b6c15aec --- /dev/null +++ b/targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re.repl @@ -0,0 +1,22 @@ +// 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 +// +// ST NUCLEO-F401RE (STM32F401RET6, Cortex-M4F). +// +// Renode ships no NUCLEO-F401RE board description, so this derives one from the +// generic STM32F4 CPU platform. That platform is sized for the larger F407/F429 +// parts; the F401RE has 512 KB Flash and 96 KB SRAM, and the demo's linker +// script and _sbrk() bound both depend on those limits being accurate. + +using "platforms/cpus/stm32f4.repl" + +sram: + size: 0x18000 + +flash: + size: 0x80000 diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_ci.resc b/targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_ci.resc new file mode 100644 index 00000000..4294976c --- /dev/null +++ b/targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_ci.resc @@ -0,0 +1,35 @@ +:name: NUCLEO-F401RE - ThreadX Demo (headless CI run) +:description: Deterministic virtual-time run driven by scripts/test_renode.py. + +# Standalone counterpart to nucleo_f401re_demo.resc rather than an include of +# it. Renode resolves $ORIGIN only in variable assignment, so an included script +# cannot be located relative to the file including it, and the two run +# differently anyway: the demo script free-runs for interactive use, while this +# one advances a fixed span of virtual time so the run is reproducible and +# terminates on its own instead of depending on wall clock. + +Clear + +using sysbus +mach create "NUCLEO_F401RE" + +$platform?=$ORIGIN/nucleo_f401re.repl +machine LoadPlatformDescription $platform + +# Under --plain --disable-gui this logs USART2 traffic to stdout, which is what +# the assertions in test_renode.py read. +showAnalyzer usart2 + +$bin?=$ORIGIN/../build/app/nucleo_f401re.elf + +macro reset +""" + sysbus LoadELF $bin +""" +runMacro $reset + +# Long enough for the startup self-tests, the 1 Hz application timer, and at +# least two reporter-thread status blocks with non-zero RTOS counters. +emulation RunFor "4" + +quit diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_demo.resc b/targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_demo.resc new file mode 100644 index 00000000..53497f07 --- /dev/null +++ b/targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_demo.resc @@ -0,0 +1,25 @@ +:name: NUCLEO-F401RE - ThreadX Device Monitor Demo +:description: Eclipse ThreadX RTOS on ST NUCLEO-F401RE (Renode, ARM Cortex-M4) + +# Clear previous emulation state +Clear + +using sysbus +mach create "NUCLEO_F401RE" + +$platform?=$ORIGIN/nucleo_f401re.repl +machine LoadPlatformDescription $platform + +# USART2 is the ST-LINK virtual COM port on this board and the demo console. +showAnalyzer usart2 + +# Portable relative path using Renode's built-in $ORIGIN variable +$bin?=$ORIGIN/../build/app/nucleo_f401re.elf + +macro reset +""" + sysbus LoadELF $bin +""" +runMacro $reset + +start diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_demo.robot b/targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_demo.robot new file mode 100644 index 00000000..20f94ee6 --- /dev/null +++ b/targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_demo.robot @@ -0,0 +1,26 @@ +*** Settings *** +Suite Setup Setup +Suite Teardown Teardown +Test Setup Reset Emulation +Test Teardown Test Teardown +Resource ${RENODEKEYWORDS} + +*** Test Cases *** +Should Pass Startup Self-Tests + Execute Command include @${CURDIR}/nucleo_f401re_demo.resc + Create Terminal Tester sysbus.usart2 + + Wait For Line On Uart NUCLEO-F401RE Device Monitor Demo timeout=15 + Wait For Line On Uart [SELF-TEST] Starting BSP & Runtime Verification... timeout=15 + Wait For Line On Uart [SELF-TEST] All startup verification tests PASSED! timeout=15 + +Should Run ThreadX Scheduler And Exercise RTOS Primitives + Execute Command include @${CURDIR}/nucleo_f401re_demo.resc + Create Terminal Tester sysbus.usart2 + + Wait For Line On Uart [SELF-TEST] All startup verification tests PASSED! timeout=15 + Wait For Line On Uart System Status: timeout=15 + # The blink thread drives bsp_led_toggle() on PA5 and the application timer + # drives the wake counter, so a non-zero pair covers both BSP paths. + Wait For Line On Uart Runs: Monitor: (\\d+) .* Blink: [1-9]\\d* timeout=20 treatAsRegex=true + Wait For Line On Uart Mutex Locks: [1-9]\\d*.*Queue Msgs: [1-9]\\d* timeout=20 treatAsRegex=true diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/scripts/test_renode.py b/targets/STMicroelectronics/NUCLEO_F401RE/scripts/test_renode.py new file mode 100755 index 00000000..e37a8a74 --- /dev/null +++ b/targets/STMicroelectronics/NUCLEO_F401RE/scripts/test_renode.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python3 +# +# 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/licenses/MIT. +# +# SPDX-License-Identifier: MIT +# + +""" +Headless Renode Verification Test for the NUCLEO-F401RE ThreadX Demo. + +Runs targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_ci.resc and +asserts on the USART2 console output. The run advances a fixed span of virtual +time and quits on its own, so the result does not depend on host speed. +""" + +import os +import re +import shutil +import subprocess +import sys +import threading +import queue +import time + +RESC_NAME = "nucleo_f401re_ci.resc" + +# The reporter thread prints these once the RTOS primitives have been exercised. +RUNS_RE = re.compile(r"Runs: Monitor: (\d+) \| Reporter: (\d+) \| Blink: (\d+) \| Timer Wakes: (\d+)") +RTOS_RE = re.compile( + r"Mutex Locks: (\d+)/(\d+) \| Queue Msgs: (\d+) \| Event Wakes: (\d+) \| Sema Wakes: (\d+)" +) + + +def find_renode(): + renode_bin = shutil.which("renode") + if renode_bin: + return renode_bin + + win_paths = [ + r"C:\Program Files\Renode\renode.exe", + os.path.expanduser(r"~\AppData\Local\Programs\Renode\renode.exe"), + ] + for path in win_paths: + if os.path.isfile(path): + return path + + return "renode" + + +def reader_thread_fn(pipe, q): + try: + for line in iter(pipe.readline, ""): + q.put(line) + except Exception: + pass + finally: + pipe.close() + + +def run_test(test_timeout_mode=False): + renode = find_renode() + script_dir = os.path.dirname(os.path.abspath(__file__)) + target_dir = os.path.dirname(script_dir) + resc_path = os.path.join(target_dir, "renode", RESC_NAME).replace("\\", "/") + + if test_timeout_mode: + print("[*] Running intentional timeout test mode (2.0s deadline)...") + timeout_seconds = 2.0 + else: + print(f"[*] Starting headless Renode test using: {renode}") + print(f"[*] Loading script: {resc_path}") + timeout_seconds = 600.0 + + cmd = [renode, "--plain", "--disable-gui", "--port", "-1", + "-e", f"include @{resc_path}"] + + proc = subprocess.Popen( + cmd, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + bufsize=1, + ) + + output_q = queue.Queue() + reader_t = threading.Thread(target=reader_thread_fn, args=(proc.stdout, output_q), daemon=True) + reader_t.start() + + found_banner = False + found_selftests = False + found_selftest_failure = False + found_led_and_timer = False + found_rtos_primitives = False + start_time = time.time() + + try: + while time.time() - start_time < timeout_seconds: + try: + line = output_q.get(timeout=0.1) + print(line, end="") + if test_timeout_mode: + continue + + if "NUCLEO-F401RE Device Monitor Demo" in line: + found_banner = True + if "[-] FAIL:" in line or "startup verification test(s) FAILED" in line: + found_selftest_failure = True + if "[SELF-TEST] All startup verification tests PASSED!" in line: + found_selftests = True + + # The blink thread is the only caller of bsp_led_toggle(), and + # timer wakes come from the 1 Hz ThreadX application timer, so a + # non-zero pair covers the LED path and the timer service. + m = RUNS_RE.search(line) + if m and int(m.group(3)) > 0 and int(m.group(4)) > 0: + found_led_and_timer = True + + m = RTOS_RE.search(line) + if m and all(int(g) > 0 for g in m.groups()): + found_rtos_primitives = True + + # A failed self-test is recorded but does not stop the run, so + # the remaining assertions are still reported rather than hidden. + if (found_banner and found_selftests and not found_selftest_failure + and found_led_and_timer and found_rtos_primitives): + print("\n[+] SUCCESS: boot banner, startup self-tests, LED and " + "timer activity, and all RTOS primitives verified!") + break + except queue.Empty: + if proc.poll() is not None: + break + finally: + try: + proc.terminate() + proc.wait(timeout=5) + except Exception: + try: + proc.kill() + except Exception: + pass + + if test_timeout_mode: + elapsed = time.time() - start_time + print(f"\n[+] SUCCESS: Intentional timeout triggered after {elapsed:.2f}s " + f"and terminated child process cleanly.") + sys.exit(0) + + checks = { + "boot banner reached the console": found_banner, + "startup self-tests passed": found_selftests and not found_selftest_failure, + "LED blink thread and application timer ran": found_led_and_timer, + "mutex, queue, event flag and semaphore all exercised": found_rtos_primitives, + } + failed = [name for name, ok in checks.items() if not ok] + + if not failed: + print("[+] Renode headless test PASSED.") + sys.exit(0) + + print("\n[-] FAILED. Unmet assertions:") + for name in failed: + print(" - %s" % name) + sys.exit(1) + + +if __name__ == "__main__": + run_test(test_timeout_mode="--test-timeout" in sys.argv) From 414377664910c37a7c0cf05abf82708a73272282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 31 Aug 2026 12:10:44 -0400 Subject: [PATCH 08/20] Corrected the target template to describe how the framework actually works (#52) templates/target/ documented a structure the repository does not have, and following it produced a build that could not configure. Its app/CMakeLists.txt compiled ../../../../apps/threadx_demo/main.c, but there is no apps/ directory and never has been, so the first thing a new contributor hit was a CMake error on a path that does not exist. Of the three shared root directories the template declared governed, only one was real: /bsp real - both framework targets implement board.h, led.h, console.h /cmake dead - cmake/utilities.cmake was referenced by nothing. All four targets carry their own copy, and the root file was byte-identical to the NUCLEO one apart from a license URL typo /apps absent - referenced by the template, docs/architecture.md, and the template's own CMake, but never created The template now says what the framework does: applications and toolchain files live with their target. The claim that applications have no compile-time dependency on vendor headers is retired rather than restated, because neither existing demo satisfies it - both include their board_config.h for memory sizing and vendor headers for board-specific startup self-tests. A portable shared application layer stays documented as a goal, labelled as one. templates/target/app/main.c is added because the template now points at it. It depends only on and the contracts and uses static thread stacks, so it avoids needing the board's memory extents and will compile for any target implementing the interfaces. It is a starting point to grow in place, not a shared application. Also removed the template's dead SHARED_APP_DIR and its guarded include of ${SHARED_CMAKE_DIR}/gcc-arm-none-eabi.cmake, a file that was never added, so the include silently never fired. The template's BSP CMake now uses SHARED_BSP_DIR instead of a five-level relative path, matching what both real targets do, and CMAKE_C_STANDARD moves from 11 to 99 per AGENTS.md. The deleted cmake/utilities.cmake is recoverable from history if the intent was for it to become the shared location; nothing referenced it in this state, and leaving a duplicate that looks authoritative invites edits that have no effect. Verified the NUCLEO target still builds clean (22068 B ROM, 6000 B RAM) and its Renode suite still passes; neither target used the removed file. Assisted-by: Claude Opus 5 (1M context) --- cmake/utilities.cmake | 50 ----------- docs/architecture.md | 15 ++-- templates/target/CMakeLists.txt | 17 ++-- templates/target/README.md | 16 ++-- templates/target/app/CMakeLists.txt | 5 +- templates/target/app/main.c | 105 ++++++++++++++++++++++++ templates/target/lib/bsp/CMakeLists.txt | 2 +- 7 files changed, 135 insertions(+), 75 deletions(-) delete mode 100644 cmake/utilities.cmake create mode 100644 templates/target/app/main.c diff --git a/cmake/utilities.cmake b/cmake/utilities.cmake deleted file mode 100644 index 2686c1f8..00000000 --- a/cmake/utilities.cmake +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (c) Microsoft -# Copyright (c) 2024 Eclipse Foundation -# -# This program and the accompanying materials are made available -# under the terms of the MIT license which is available at -# https://opensource.org/licenses/MIT. -# -# SPDX-License-Identifier: MIT -# -# Contributors: -# Microsoft - Initial version -# Frédéric Desbiens - 2024 version. - -function(post_build TARGET) - if(CMAKE_C_COMPILER_ID STREQUAL "IAR") - add_custom_target(${TARGET}.bin ALL - DEPENDS ${TARGET} - COMMAND ${CMAKE_IAR_ELFTOOL} --bin ${TARGET}.elf ${TARGET}.bin) - elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") - add_custom_target(${TARGET}.bin ALL - DEPENDS ${TARGET} - COMMAND ${CMAKE_OBJCOPY} -Obinary ${TARGET}.elf ${TARGET}.bin - COMMAND ${CMAKE_OBJCOPY} -Oihex ${TARGET}.elf ${TARGET}.hex) - else() - message(FATAL_ERROR "Unknown CMAKE_C_COMPILER_ID ${CMAKE_C_COMPILER_ID}") - endif() -endfunction() - -function(set_target_linker TARGET LINKER_SCRIPT) - if(CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${TARGET} PRIVATE --config ${LINKER_SCRIPT}) - target_link_options(${TARGET} PRIVATE --map=${TARGET}.map) - elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${TARGET} PRIVATE -T${LINKER_SCRIPT}) - target_link_options(${TARGET} PRIVATE -Wl,-Map=${TARGET}.map) - set_target_properties(${TARGET} PROPERTIES SUFFIX ".elf") - - else() - message(FATAL_ERROR "Unknown CMAKE_C_COMPILER_ID ${CMAKE_C_COMPILER_ID}") - endif() -endfunction() - -macro(print_all_variables) - message(STATUS "print_all_variables------------------------------------------{") - get_cmake_property(_variableNames VARIABLES) - foreach (_variableName ${_variableNames}) - message(STATUS "${_variableName}=${${_variableName}}") - endforeach() - message(STATUS "print_all_variables------------------------------------------}") -endmacro() diff --git a/docs/architecture.md b/docs/architecture.md index e0049690..b932fcbe 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -9,8 +9,8 @@ This document describes the architecture, design philosophy, directory structure The BSP framework is designed to be **additive and non-invasive**, allowing new boards to be integrated without modifying existing board implementations. 1. **Legacy Isolation**: The board directories that predate this framework (`/MXChip`, `/OpenHW`, `/STMicroelectronics`) remain completely untouched, preserving their drivers, submodules, and build systems. -2. **Platform-Independent Applications**: Target applications use only the abstract BSP interfaces and have no compile-time dependency on vendor-specific HALs, SDKs, or hardware registers. -3. **Reusable Infrastructure**: Shared CMake toolchains and build utilities are centralized under `/cmake` to eliminate duplicated build configuration across supported boards. +2. **Hardware Access Through the BSP**: Application logic reaches LEDs and the console through the abstract interfaces in `/bsp`, not through vendor registers. Applications are target-resident: each target owns its demo under `app/`, and today's demos do additionally include their own `board_config.h` for memory sizing and vendor headers for board-specific startup self-tests. A fully portable shared application layer is a goal of the framework, not a property it has yet. +3. **Independent Build Configuration**: Each target carries its own `cmake/` toolchain files and build helpers. Nothing in the build is shared between targets, so changing one board cannot break another. --- @@ -24,11 +24,12 @@ samplex/ (repository root) ├── OpenHW/ # [Pre-framework] Standalone board sample ├── STMicroelectronics/ # [Pre-framework] Standalone board samples ├── targets/ # [Framework] Supported BSP target boards -│ └── Microchip/ -│ └── POLARFIRE_ICICLE_RENODE/ # Board-specific BSP implementation & Renode target +│ ├── Microchip/ +│ │ └── POLARFIRE_ICICLE_RENODE/ # Board-specific BSP implementation & Renode target +│ └── STMicroelectronics/ +│ └── NUCLEO_F401RE/ # Board-specific BSP implementation & Renode target ├── bsp/ # [Framework] Abstract BSP interface definitions │ └── include/bsp/ # board.h, led.h, console.h -├── cmake/ # [Framework] Shared CMake configuration and utilities ├── docs/ # [Framework] Architecture and onboarding documentation └── templates/ # [Framework] Templates for onboarding new boards ``` @@ -62,6 +63,6 @@ Every board added to the framework under `/targets` must implement the abstract 1. **Create the Target Folder**: Create a new directory under `targets///` using `/templates/target/` as the starting point. 2. **Define Local Configuration**: Create a `board_config.h` file containing board-specific settings such as clock configuration, UART parameters, and ThreadX memory allocation. 3. **Implement the BSP APIs**: Implement the interfaces defined in `/bsp/include/bsp/` using the vendor SDK or direct register access. -4. **Configure CMake**: Add the board target to `CMakeLists.txt`, build the BSP as a static library, and link it with the desired application from `/apps/`. +4. **Configure CMake**: Add the board target to `CMakeLists.txt`, supply the target's toolchain file under its own `cmake/`, build the BSP as a static library, and link it with the application in the target's `app/` directory. -Once a board implements the required BSP interfaces, any compatible application under `/apps` can be built for that board without modifying the application source. +Start from `templates/target/app/main.c`, which depends only on `` and the `` contracts and therefore builds on any target that implements them. Grow it in place as the board needs; there is no shared `/apps` directory to link an application from. diff --git a/templates/target/CMakeLists.txt b/templates/target/CMakeLists.txt index 13ac5b52..f68bc8d2 100644 --- a/templates/target/CMakeLists.txt +++ b/templates/target/CMakeLists.txt @@ -11,20 +11,21 @@ cmake_minimum_required(VERSION 3.15) # TODO: Replace 'TARGET_BOARD_TEMPLATE' with your target board name (e.g. MY_CUSTOM_BOARD) project(TARGET_BOARD_TEMPLATE C CXX ASM) -set(CMAKE_C_STANDARD 11) +# AGENTS.md requires C99 compatibility. +set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED ON) -# Define root paths +# Define root paths. Only libs/ and bsp/ are shared; the toolchain file and any +# CMake helper modules belong to this target, under cmake/. get_filename_component(WORKSPACE_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../.." ABSOLUTE) set(SHARED_LIB_DIR "${WORKSPACE_ROOT}/libs") -set(SHARED_APP_DIR "${WORKSPACE_ROOT}/apps") set(SHARED_BSP_DIR "${WORKSPACE_ROOT}/bsp") -set(SHARED_CMAKE_DIR "${WORKSPACE_ROOT}/cmake") -# Include GNU ARM Toolchain setup if building for bare-metal ARM Cortex-M -if(EXISTS "${SHARED_CMAKE_DIR}/gcc-arm-none-eabi.cmake") - include("${SHARED_CMAKE_DIR}/gcc-arm-none-eabi.cmake") -endif() +# TODO: Add this target's cmake/ directory and select its toolchain file, e.g. +# if(NOT CMAKE_TOOLCHAIN_FILE) +# set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_LIST_DIR}/cmake/-toolchain.cmake") +# endif() +# list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) # Global compiler flags add_compile_options( diff --git a/templates/target/README.md b/templates/target/README.md index 43a35a13..a5be06db 100644 --- a/templates/target/README.md +++ b/templates/target/README.md @@ -12,11 +12,11 @@ This directory contains the skeletal blueprint for onboarding a new hardware boa ## 1. Dependency Flow Architecture -The following diagram illustrates how the generic application layer is decoupled from physical MCU registers using the BSP framework: +The following diagram illustrates how application code reaches hardware through the BSP framework rather than through vendor registers directly: ```mermaid flowchart TD - App["Generic Application (apps/threadx_demo/main.c)"] + App["Application (targets/<Vendor>/<Board>/app/)"] BSP_API["BSP Interface Contract (bsp/include/bsp/)"] Target_BSP["Target BSP Driver Library (targets/<Vendor>/<Board>/lib/bsp/)"] Vendor_SDK["Vendor SDK / Platform Support Libraries"] @@ -33,9 +33,8 @@ flowchart TD ```text Repository │ -├── apps/ (Platform-independent application logic) ├── bsp/ (Target-agnostic C interface contracts) -├── cmake/ (Shared build infrastructure & toolchains) +├── libs/ (Shared RTOS components: ThreadX, NetX Duo, FileX, USBX) └── targets/ (Independent board support implementations) ├── STMicroelectronics/NUCLEO_F401RE/ └── Microchip/POLARFIRE_ICICLE_RENODE/ @@ -47,9 +46,11 @@ Repository To maintain long-term framework maintainability and portability, the following root directories should generally remain **unchanged** when onboarding a new board: -* `/apps`: Contains shared example applications and reusable demos (such as `threadx_demo`). Applications in this directory interact with hardware solely through the abstract headers in ``. Developers may also add additional applications alongside the provided examples. * `/bsp`: Defines the target-agnostic C interface contracts (`board.h`, `led.h`, `console.h`). New board targets must implement these existing interfaces rather than modifying core interface definitions. -* `/cmake`: Contains shared cross-compilation toolchain settings and build utility functions. +* `/libs`: Shared RTOS components consumed by every target as submodules. Targets reference these rather than vendoring their own copy. + +> [!NOTE] +> **Applications are currently target-resident.** Each target owns its demo under `targets///app/`, along with its own `cmake/` toolchain files and build helpers. A shared `/apps` layer is a goal of this framework, not something it provides yet: today's demos also include their target's `board_config.h` for memory sizing and vendor headers for board-specific startup self-tests. Onboard a new board by starting from the app in this template, not by linking one from a shared directory. > [!NOTE] > **Core Architectural Principle**: @@ -74,7 +75,8 @@ The table below maps common embedded software components to their designated loc | **BSP Driver Implementation** | `targets///lib/bsp/src/` | Target developer (`bsp_board.c`, `bsp_led.c`, `bsp_console.c`) | | **Target Specification Constants** | `targets///lib/bsp/include/board_config.h` | Target developer (declarative defines only) | | **Target Build Automation** | `targets///scripts/build.ps1` | Target developer (PowerShell automation template) | -| **Shared Application Code** | `/apps//` | Framework shared application layer (remains in root) | +| **Application Code** | `targets///app/` | Target developer (start from this template's `app/main.c`) | +| **Toolchain & Build Helpers** | `targets///cmake/` | Target developer (cross-compilation settings per target) | --- diff --git a/templates/target/app/CMakeLists.txt b/templates/target/app/CMakeLists.txt index 1fad0eaa..6e9a585f 100644 --- a/templates/target/app/CMakeLists.txt +++ b/templates/target/app/CMakeLists.txt @@ -15,8 +15,9 @@ set(SOURCES # ${COMMON_DIR}/startup/startup_mcu.s # ${COMMON_DIR}/startup/tx_initialize_low_level.S - # Link the shared platform-independent ThreadX application - ${CMAKE_CURRENT_SOURCE_DIR}/../../../../apps/threadx_demo/main.c + # This target's ThreadX application. Applications are target-resident: + # there is no shared apps/ directory to link one from. + ${CMAKE_CURRENT_SOURCE_DIR}/main.c # Link GCC Newlib syscall stubs ${CMAKE_CURRENT_SOURCE_DIR}/../lib/bsp/src/newlib_stubs.c diff --git a/templates/target/app/main.c b/templates/target/app/main.c new file mode 100644 index 00000000..668cf681 --- /dev/null +++ b/templates/target/app/main.c @@ -0,0 +1,105 @@ +/*************************************************************************** + * 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/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* + * Minimal ThreadX starting point for a new board target. + * + * This file deliberately depends on nothing but and the generic BSP + * contracts in , so it compiles for any target that implements them. + * Thread stacks are static, which avoids needing the board's memory extents. + * + * Once the board boots this, grow the demo in place. Real targets do include + * their own board_config.h and vendor headers - for byte-pool sizing and for + * board-specific startup self-tests - and that is expected; applications live + * with their target rather than in a shared directory. + */ + +#include "tx_api.h" + +#include "bsp/board.h" +#include "bsp/console.h" +#include "bsp/led.h" + +#include + +#define DEMO_STACK_SIZE 1024 +#define BLINK_PERIOD_TICKS (TX_TIMER_TICKS_PER_SECOND / 2) +#define REPORT_PERIOD_TICKS (TX_TIMER_TICKS_PER_SECOND) + +static TX_THREAD blink_thread; +static TX_THREAD report_thread; + +static UCHAR blink_stack[DEMO_STACK_SIZE]; +static UCHAR report_stack[DEMO_STACK_SIZE]; + +static void console_print(const char *text) +{ + bsp_console_write(text, strlen(text)); +} + +static void blink_thread_entry(ULONG parameter) +{ + (void)parameter; + + while (1) + { + bsp_led_toggle(); + tx_thread_sleep(BLINK_PERIOD_TICKS); + } +} + +static void report_thread_entry(ULONG parameter) +{ + (void)parameter; + + while (1) + { + console_print("[template] ThreadX is running\r\n"); + tx_thread_sleep(REPORT_PERIOD_TICKS); + } +} + +void tx_application_define(void *first_unused_memory) +{ + (void)first_unused_memory; + + /* TODO: Create a TX_BYTE_POOL from first_unused_memory if this target's + * demo outgrows static stacks. Doing so needs the board's RAM extent, so + * it belongs with the target rather than in shared code. */ + + (void)tx_thread_create(&blink_thread, "blink thread", blink_thread_entry, 0, + blink_stack, DEMO_STACK_SIZE, + 10, 10, TX_NO_TIME_SLICE, TX_AUTO_START); + + (void)tx_thread_create(&report_thread, "report thread", report_thread_entry, 0, + report_stack, DEMO_STACK_SIZE, + 11, 11, TX_NO_TIME_SLICE, TX_AUTO_START); +} + +int main(void) +{ + bsp_board_init(); + + console_print("\r\n=== Eclipse ThreadX target template ===\r\n"); + + /* TODO: Run any board-specific startup self-tests here, before the + * scheduler starts, so failures are reported even if it never runs. */ + + tx_kernel_enter(); + + while (1) + { + } +} diff --git a/templates/target/lib/bsp/CMakeLists.txt b/templates/target/lib/bsp/CMakeLists.txt index de096665..8b7ddebb 100644 --- a/templates/target/lib/bsp/CMakeLists.txt +++ b/templates/target/lib/bsp/CMakeLists.txt @@ -16,7 +16,7 @@ add_library(target_bsp STATIC # Export BSP headers and shared abstract C BSP headers to PUBLIC include paths target_include_directories(target_bsp PUBLIC include - ${CMAKE_CURRENT_LIST_DIR}/../../../../../bsp/include + ${SHARED_BSP_DIR}/include ) # Link ThreadX and vendor HAL dependencies if required From 1ff7ae1b587cefb150cb037a734eb665b5299c69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 31 Aug 2026 15:22:55 -0400 Subject: [PATCH 09/20] Pinned the Arm toolchain to 14.3.Rel1 and adopted the ThreadX install pattern (#53) The ARM job pinned 14.2.Rel1, chosen only because it was the newest release at the time. eclipse-threadx/threadx already pins 14.3.rel1 in ci_cortex_m.yml for the Cortex-M ports, so samplex was lagging the flagship repository rather than choosing between two versions. Both satisfy the AGENTS.md GCC 14 requirement; matching threadx means a toolchain bump is one reviewable line in each repository instead of a per-repository decision. The install steps now mirror ci_cortex_m.yml rather than paraphrasing it, which fixes three weaknesses in the version this replaces: - The archive was fetched with no integrity check at all. It is now verified with sha256sum against the published .sha256asc. - Roughly 150 MB was downloaded on every run. actions/cache, keyed on the pinned version, now avoids that. - wget -q hid transfer detail. curl -fsSL fails the step on an HTTP error, and a new step reports the resulting compiler version so the log records what actually built the ELF. Version and target move into job env vars (GCC_VERSION, GCC_TARGET) using the same names threadx uses, so the two files stay diffable and a future bump is a one-line change. Re-measured the NUCLEO validation record under the newly pinned compiler: 22064 B ROM, down 4 bytes from 14.2.1; RAM unchanged at 6000 B. The figures and the pin move together deliberately, since letting them drift is what left a stale 15.2.1 measurement in this file before. Verified under Arm GNU Toolchain 14.3.Rel1: clean build with -Wall -Wshadow -Wdouble-promotion -Werror, no new diagnostics from the point release, and the headless Renode suite still passes with all seven startup self-tests. Assisted-by: Claude Opus 5 (1M context) --- .github/workflows/ci.yml | 42 ++++++++++++++++--- .../NUCLEO_F401RE/README.md | 4 +- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 88e9bb28..c6375aa1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -105,6 +105,16 @@ jobs: build-arm-nucleo: name: Build ST Nucleo-F401RE (ARM Cortex-M4) runs-on: ubuntu-24.04 + + env: + # Pinned deliberately, as the runner image is: a toolchain upgrade should + # be a reviewable commit rather than something that changes underneath the + # targets. Kept in step with eclipse-threadx/threadx ci_cortex_m.yml, which + # pins the same release for the Cortex-M ports. + # Releases: https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads + GCC_VERSION: 14.3.rel1 + GCC_TARGET: arm-none-eabi + steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -116,13 +126,33 @@ jobs: sudo apt-get update sudo apt-get install -y cmake ninja-build - - name: Install Pinned Arm GNU Toolchain 14.2.Rel1 + - name: Cache the Arm GNU toolchain + id: cache-arm-gcc + uses: actions/cache@v4 + with: + path: toolchain + key: arm-gnu-toolchain-${{ env.GCC_VERSION }}-x86_64-${{ env.GCC_TARGET }} + + - name: Install the Arm GNU toolchain + if: steps.cache-arm-gcc.outputs.cache-hit != 'true' + run: | + set -eu + base="https://developer.arm.com/-/media/Files/downloads/gnu/${GCC_VERSION}/binrel" + archive="arm-gnu-toolchain-${GCC_VERSION}-x86_64-${GCC_TARGET}.tar.xz" + mkdir -p toolchain && cd toolchain + curl -fsSLO "$base/$archive" + curl -fsSLO "$base/$archive.sha256asc" + sha256sum -c "$archive.sha256asc" + tar xf "$archive" + rm -f "$archive" + + - name: Put the toolchain on PATH run: | - wget -q https://developer.arm.com/-/media/Files/downloads/gnu/14.2.rel1/binrel/arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz - mkdir -p $HOME/arm-gcc - tar -xJf arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz -C $HOME/arm-gcc --strip-components=1 - rm arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz - echo "$HOME/arm-gcc/bin" >> $GITHUB_PATH + set -eu + echo "$GITHUB_WORKSPACE/toolchain/arm-gnu-toolchain-${GCC_VERSION}-x86_64-${GCC_TARGET}/bin" >> "$GITHUB_PATH" + + - name: Report the toolchain version + run: ${{ env.GCC_TARGET }}-gcc --version - name: Build NUCLEO-F401RE Demo run: | diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/README.md b/targets/STMicroelectronics/NUCLEO_F401RE/README.md index 0c932dc4..e1d3025d 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/README.md +++ b/targets/STMicroelectronics/NUCLEO_F401RE/README.md @@ -196,8 +196,8 @@ The BSP overrides `HAL_InitTick()` to configure TIM2 as the HAL timebase and pro ## Validation Record ### Verification Environment -- **Toolchain**: Arm GNU Toolchain 14.2.Rel1 (GCC 14.2.1), the version pinned by CI -- **Static ROM usage**: 22068 Bytes (4.21% of 512 KB Flash), including the startup self-tests +- **Toolchain**: Arm GNU Toolchain 14.3.Rel1 (GCC 14.3.1), the version pinned by CI and by the ThreadX Cortex-M ports +- **Static ROM usage**: 22064 Bytes (4.21% of 512 KB Flash), including the startup self-tests - **Static RAM usage**: 6000 Bytes (6.10% of 96 KB RAM) - **Dynamic Stack & Buffer allocation**: Stacks (8 x 1024 bytes) and Queue buffer (40 bytes) are dynamically allocated from the `TX_BYTE_POOL` (consuming 8312 bytes total, including pool headers). - **Board Hardware**: NUCLEO-F401RE From a166e86d073658260f2bb7902cdd395f509e34e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 31 Aug 2026 15:34:25 -0400 Subject: [PATCH 10/20] Pinned the RISC-V toolchain to xPack GCC 14.3.0 (#54) The PolarFire job pinned xPack riscv-none-elf-gcc 14.2.0-1 while the ARM job now pins Arm GNU Toolchain 14.3.Rel1, so the two cross-compilers in this pipeline were a minor release apart for no reason. xPack published v14.3.0-1 on 2025-10-23; moving to it puts both targets on GCC 14.3 and keeps the AGENTS.md GCC 14 requirement satisfied. The published SHA256 is updated alongside the version. The existing checksum verification is kept as it was: this job already verified its download, which is why it needed no other hardening. Verified locally with xPack GNU RISC-V Embedded GCC 14.3.0: - Clean build of polarfire_icicle_demo.elf. - Headless Renode suite passes, exit 0, with all startup self-tests green: _sbrk bounds, HWTimer catch-up clamp, PLIC Hart 1 configuration, the queue round-trip, ThreadX ticks, the LM75 alarm, and the PLIC RX interrupt. The linker warning about a LOAD segment with RWX permissions is unchanged by this bump. It is emitted identically by 14.2.0 in the current pipeline, so it predates this change and is left for separate treatment rather than folded in here. Assisted-by: Claude Opus 5 (1M context) --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6375aa1..602cf2d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,13 +32,13 @@ jobs: sudo apt-get update sudo apt-get install -y cmake ninja-build - - name: Install Pinned xPack RISC-V GCC 14.2.0 + - name: Install Pinned xPack RISC-V GCC 14.3.0 env: - XPACK_TARBALL: xpack-riscv-none-elf-gcc-14.2.0-1-linux-x64.tar.gz - XPACK_SHA256: a5eb707595e1424ff4127cc8b21b8b8cb076e6f0070b670485e72b9f74806200 + XPACK_TARBALL: xpack-riscv-none-elf-gcc-14.3.0-1-linux-x64.tar.gz + XPACK_SHA256: be1768ef22789f4d9c41384e0261996f51724b84c2efa940d975dd7d9938c726 run: | set -euo pipefail - wget -q "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v14.2.0-1/${XPACK_TARBALL}" + wget -q "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v14.3.0-1/${XPACK_TARBALL}" echo "${XPACK_SHA256} ${XPACK_TARBALL}" | sha256sum --check --strict mkdir -p $HOME/riscv-gcc tar -xzf "${XPACK_TARBALL}" -C $HOME/riscv-gcc --strip-components=1 From bba3b910ebd4524ea2c904fa7678038d0adb4be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 31 Aug 2026 15:40:41 -0400 Subject: [PATCH 11/20] Pinned the NUCLEO Renode download and cached every toolchain fetch (#55) Two problems in the pipeline, one of them mine. The NUCLEO Renode job fetched renode-latest.linux-portable.tar.gz with no version pin and no checksum, while the PolarFire job three jobs above it already pinned Renode 1.16.1 and verified its SHA256. That pin landed in #49, so it was present in this file when #51 added the NUCLEO job; the new job was modelled on an older copy of the PolarFire step rather than the current one. The result was a suite whose emulator could change under it on any Renode release, with nothing verifying what was downloaded. The NUCLEO job now uses the same pinned, checksum-verified step as PolarFire. The checksum was recomputed from the published artefact rather than copied on trust. Separately, every run re-downloaded roughly a gigabyte: the xPack RISC-V toolchain at ~414 MB and Renode at ~52 MB in each of two jobs. All three are now restored by actions/cache, keyed on the pinned version so a future bump invalidates the cache instead of silently serving the old one. This completes what #53 started for the Arm toolchain. Caching only makes sense because these are now pinned. Caching an unpinned "latest" artefact would have frozen CI on whichever build happened to be fetched first, turning a reproducibility gap into an invisible one. All four jobs now follow the same shape: cache, install only on a cache miss, then put the tool on PATH as a separate step so it runs on hit and miss alike. The PolarFire job also gains a version-reporting step, matching the Arm job, so the log records which compiler produced the ELF. Verified both constructed download URLs resolve, and that the Renode 1.16.1 checksum matches the published artefact. Assisted-by: Claude Opus 5 (1M context) --- .github/workflows/ci.yml | 74 ++++++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 602cf2d3..721cdc2e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,6 +21,12 @@ jobs: name: Build PolarFire SoC Icicle Kit (64-Bit RISC-V) runs-on: ubuntu-24.04 timeout-minutes: 20 + + env: + XPACK_VERSION: 14.3.0-1 + XPACK_TARBALL: xpack-riscv-none-elf-gcc-14.3.0-1-linux-x64.tar.gz + XPACK_SHA256: be1768ef22789f4d9c41384e0261996f51724b84c2efa940d975dd7d9938c726 + steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -32,18 +38,28 @@ jobs: sudo apt-get update sudo apt-get install -y cmake ninja-build - - name: Install Pinned xPack RISC-V GCC 14.3.0 - env: - XPACK_TARBALL: xpack-riscv-none-elf-gcc-14.3.0-1-linux-x64.tar.gz - XPACK_SHA256: be1768ef22789f4d9c41384e0261996f51724b84c2efa940d975dd7d9938c726 + - name: Cache the xPack RISC-V toolchain + id: cache-xpack + uses: actions/cache@v4 + with: + path: ~/riscv-gcc + key: xpack-riscv-none-elf-gcc-${{ env.XPACK_VERSION }}-linux-x64 + + - name: Install Pinned xPack RISC-V GCC + if: steps.cache-xpack.outputs.cache-hit != 'true' run: | set -euo pipefail - wget -q "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v14.3.0-1/${XPACK_TARBALL}" + wget -q "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v${XPACK_VERSION}/${XPACK_TARBALL}" echo "${XPACK_SHA256} ${XPACK_TARBALL}" | sha256sum --check --strict mkdir -p $HOME/riscv-gcc tar -xzf "${XPACK_TARBALL}" -C $HOME/riscv-gcc --strip-components=1 rm "${XPACK_TARBALL}" - echo "$HOME/riscv-gcc/bin" >> $GITHUB_PATH + + - name: Put the RISC-V toolchain on PATH + run: echo "$HOME/riscv-gcc/bin" >> $GITHUB_PATH + + - name: Report the toolchain version + run: riscv-none-elf-gcc --version - name: Build SampleX PolarFire Condition-Monitoring Demo run: | @@ -67,6 +83,10 @@ jobs: runs-on: ubuntu-24.04 # Backstop in case Renode itself wedges before the in-script deadline fires. timeout-minutes: 15 + env: + RENODE_VERSION: 1.16.1 + RENODE_SHA256: 1a532d4b5b82de0dd154970c401e0c7b0e498d17304b2cecc007e306c8f9617c + steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -84,10 +104,15 @@ jobs: name: polarfire-demo-elf path: targets/Microchip/POLARFIRE_ICICLE_RENODE/build/app + - name: Cache the portable Renode environment + id: cache-renode + uses: actions/cache@v4 + with: + path: ~/renode + key: renode-${{ env.RENODE_VERSION }}-linux-portable + - name: Install Pinned Portable Renode Emulation Environment - env: - RENODE_VERSION: 1.16.1 - RENODE_SHA256: 1a532d4b5b82de0dd154970c401e0c7b0e498d17304b2cecc007e306c8f9617c + if: steps.cache-renode.outputs.cache-hit != 'true' run: | set -euo pipefail TARBALL="renode-${RENODE_VERSION}.linux-portable.tar.gz" @@ -96,7 +121,9 @@ jobs: mkdir -p $HOME/renode tar -xzf "${TARBALL}" -C $HOME/renode --strip-components=1 rm "${TARBALL}" - echo "$HOME/renode" >> $GITHUB_PATH + + - name: Put Renode on PATH + run: echo "$HOME/renode" >> $GITHUB_PATH - name: Run Deterministic Headless Renode Test run: | @@ -174,6 +201,10 @@ jobs: name: Headless Renode Emulation & Assertion Test (NUCLEO-F401RE) needs: build-arm-nucleo runs-on: ubuntu-24.04 + env: + RENODE_VERSION: 1.16.1 + RENODE_SHA256: 1a532d4b5b82de0dd154970c401e0c7b0e498d17304b2cecc007e306c8f9617c + steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -191,13 +222,26 @@ jobs: name: nucleo-f401re-demo-elf path: targets/STMicroelectronics/NUCLEO_F401RE/build/app - - name: Install Portable Renode Emulation Environment + - name: Cache the portable Renode environment + id: cache-renode + uses: actions/cache@v4 + with: + path: ~/renode + key: renode-${{ env.RENODE_VERSION }}-linux-portable + + - name: Install Pinned Portable Renode Emulation Environment + if: steps.cache-renode.outputs.cache-hit != 'true' run: | - wget -q https://builds.renode.io/renode-latest.linux-portable.tar.gz + set -euo pipefail + TARBALL="renode-${RENODE_VERSION}.linux-portable.tar.gz" + wget -q "https://github.com/renode/renode/releases/download/v${RENODE_VERSION}/${TARBALL}" + echo "${RENODE_SHA256} ${TARBALL}" | sha256sum --check --strict mkdir -p $HOME/renode - tar -xzf renode-latest.linux-portable.tar.gz -C $HOME/renode --strip-components=1 - rm renode-latest.linux-portable.tar.gz - echo "$HOME/renode" >> $GITHUB_PATH + tar -xzf "${TARBALL}" -C $HOME/renode --strip-components=1 + rm "${TARBALL}" + + - name: Put Renode on PATH + run: echo "$HOME/renode" >> $GITHUB_PATH - name: Run Deterministic Headless Renode Test run: | From 92707e0b752c9974cdca39183cf06f008eccb05e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 31 Aug 2026 16:17:20 -0400 Subject: [PATCH 12/20] Moved the startup self-tests and RAM sizing behind new BSP interfaces (#56) The framework's stated purpose is that application code can be built for any board implementing the `bsp/` contracts. Neither demo could be, because both `main.c` files reached past those contracts for two things no portable application can see: the board's memory extents, and the hardware specifics its startup self-tests assert on. Neither was ever application logic. The self-tests test the BSP - linker reservations, clock trees, interrupt controllers - so they belong in the BSP. Two new contracts move both behind the boundary: * `bsp/selftest.h` - `bsp_self_test()` runs the board's checks and reports each through an application-supplied callback, so message formatting (and therefore the choice between `printf()` and `bsp_console_write()`) stays with the application while the checks stay with the board. * `bsp/memory.h` - `bsp_ram_region()` reports what RAM the application may claim, clamped against whatever the board reserves. Both targets implement both, and both `main.c` files now include nothing but the C standard headers, `tx_api.h` and ``. The NUCLEO byte pool comes out byte-identical at 88204 bytes. Prototyping `bsp_ram_region()` on the PolarFire first surfaced a latent bug there. Its `_sbrk()` bounded the heap at the end of DRAM, which is the same mistake the NUCLEO shipped with before #50: harmless only because nothing else claimed that memory. The moment `bsp_ram_region()` promises it to an application, an oversized `malloc()` could take memory holding thread stacks. The heap is now bounded against a documented 64 KB reservation that `bsp_ram_region()` skips, and a new self-test guards the bound the way the NUCLEO's test 4 does. Measured heap use is under 256 bytes, so the reservation has ample headroom. The PolarFire tick-rate compile-time check moved to `hwtimer.c`, next to the `TICK_CYCLES` constant it guards, since it needed ThreadX headers that a portable `main.c` should not have to pull in. Verified locally on both targets: clean builds plus `test_renode.py` green on Cortex-M4 and RV64. Both suites were also confirmed to still have teeth - weakening each target's `_sbrk()` bound back to the end of RAM makes them exit 1 (three failures on the NUCLEO, one on the PolarFire), so no assertion was lost in the move. Assisted-by: Claude Opus 5 (1M context) --- bsp/include/bsp/memory.h | 41 +++++ bsp/include/bsp/selftest.h | 51 ++++++ docs/architecture.md | 20 ++- .../POLARFIRE_ICICLE_RENODE/README.md | 2 +- .../app/common/startup/newlib_stubs.c | 7 +- .../POLARFIRE_ICICLE_RENODE/app/main.c | 96 ++-------- .../lib/bsp/CMakeLists.txt | 8 + .../lib/bsp/include/board_config.h | 19 ++ .../lib/bsp/src/bsp_memory.c | 59 +++++++ .../lib/bsp/src/bsp_selftest.c | 167 ++++++++++++++++++ .../lib/bsp/src/hwtimer.c | 9 + .../NUCLEO_F401RE/README.md | 10 +- .../NUCLEO_F401RE/app/starter/main.c | 104 +++-------- .../NUCLEO_F401RE/lib/bsp/CMakeLists.txt | 2 + .../lib/bsp/include/board_config.h | 7 + .../NUCLEO_F401RE/lib/bsp/src/bsp_memory.c | 45 +++++ .../NUCLEO_F401RE/lib/bsp/src/bsp_selftest.c | 161 +++++++++++++++++ templates/target/README.md | 13 +- templates/target/app/main.c | 50 ++++-- templates/target/lib/bsp/CMakeLists.txt | 2 + .../target/lib/bsp/include/board_config.h | 6 + templates/target/lib/bsp/src/bsp_memory.c | 49 +++++ templates/target/lib/bsp/src/bsp_selftest.c | 77 ++++++++ 23 files changed, 821 insertions(+), 184 deletions(-) create mode 100644 bsp/include/bsp/memory.h create mode 100644 bsp/include/bsp/selftest.h create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_memory.c create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_selftest.c create mode 100644 targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_memory.c create mode 100644 targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_selftest.c create mode 100644 templates/target/lib/bsp/src/bsp_memory.c create mode 100644 templates/target/lib/bsp/src/bsp_selftest.c diff --git a/bsp/include/bsp/memory.h b/bsp/include/bsp/memory.h new file mode 100644 index 00000000..2a3d2055 --- /dev/null +++ b/bsp/include/bsp/memory.h @@ -0,0 +1,41 @@ +/*************************************************************************** + * 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/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +#ifndef BSP_MEMORY_H +#define BSP_MEMORY_H + +#include + +/** + * @brief Reports the RAM region the application may claim. + * + * ThreadX hands tx_application_define() the first address it believes to be + * unused, but only the board knows what sits above it: a C heap reservation, a + * main stack at the top of RAM, or a memory-mapped peripheral window. This + * call clamps the region against whatever the board holds back, so an + * application can size a TX_BYTE_POOL without naming a single board symbol. + * + * The returned region is the application's to divide up. A board must never + * include its own heap or stack reservations in it. + * + * @param first_unused The pointer ThreadX passed to tx_application_define(). + * @param base Receives the first address the application owns. Must not be + * NULL. + * @param size Receives the length of that region in bytes, zero when the board + * has no RAM to spare. Must not be NULL. + */ +void bsp_ram_region(void *first_unused, void **base, size_t *size); + +#endif /* BSP_MEMORY_H */ diff --git a/bsp/include/bsp/selftest.h b/bsp/include/bsp/selftest.h new file mode 100644 index 00000000..6b42059b --- /dev/null +++ b/bsp/include/bsp/selftest.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * 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/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +#ifndef BSP_SELFTEST_H +#define BSP_SELFTEST_H + +/** + * @brief Reports the outcome of one board self-test. + * + * The board owns the checks; the application owns how their results reach the + * user. Formatting the line - and therefore the choice between printf() and + * bsp_console_write() - stays entirely on the application side of this + * callback, so a board never has to know which is available. + * + * @param passed Non-zero when the check succeeded, zero when it failed. + * @param message Description of the check, including any measured values. + * Valid only for the duration of the call. + * @param context The context pointer that was handed to bsp_self_test(). + */ +typedef void (*bsp_selftest_report_fn)(int passed, const char *message, + void *context); + +/** + * @brief Runs the board's startup self-tests. + * + * Intended to be called before tx_kernel_enter(), so a hardware or runtime + * fault is reported even when the scheduler never starts. Each check reports + * through @p report in execution order; checks that mutate board state undo it + * before returning, leaving the board as the caller found it. + * + * @param report Callback invoked once per check. Must not be NULL; passing + * NULL runs no check and returns 1, since a board whose results + * cannot be reported must not be assumed healthy. + * @param context Opaque pointer passed back to @p report unmodified. + * @return Number of checks that failed; zero when every check passed. + */ +unsigned bsp_self_test(bsp_selftest_report_fn report, void *context); + +#endif /* BSP_SELFTEST_H */ diff --git a/docs/architecture.md b/docs/architecture.md index b932fcbe..5bfa785b 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -9,7 +9,7 @@ This document describes the architecture, design philosophy, directory structure The BSP framework is designed to be **additive and non-invasive**, allowing new boards to be integrated without modifying existing board implementations. 1. **Legacy Isolation**: The board directories that predate this framework (`/MXChip`, `/OpenHW`, `/STMicroelectronics`) remain completely untouched, preserving their drivers, submodules, and build systems. -2. **Hardware Access Through the BSP**: Application logic reaches LEDs and the console through the abstract interfaces in `/bsp`, not through vendor registers. Applications are target-resident: each target owns its demo under `app/`, and today's demos do additionally include their own `board_config.h` for memory sizing and vendor headers for board-specific startup self-tests. A fully portable shared application layer is a goal of the framework, not a property it has yet. +2. **Hardware Access Through the BSP**: Application logic reaches LEDs, the console, the board's RAM budget and its startup self-tests through the abstract interfaces in `/bsp`, not through vendor registers. Both shipped demos now include only `` and `` headers. Applications are still target-resident, though: each target owns its demo under `app/`, and there is no shared application directory to link one from. A fully portable shared application layer is a goal of the framework, not a property it has yet. 3. **Independent Build Configuration**: Each target carries its own `cmake/` toolchain files and build helpers. Nothing in the build is shared between targets, so changing one board cannot break another. --- @@ -29,7 +29,7 @@ samplex/ (repository root) │ └── STMicroelectronics/ │ └── NUCLEO_F401RE/ # Board-specific BSP implementation & Renode target ├── bsp/ # [Framework] Abstract BSP interface definitions -│ └── include/bsp/ # board.h, led.h, console.h +│ └── include/bsp/ # board.h, led.h, console.h, memory.h, selftest.h ├── docs/ # [Framework] Architecture and onboarding documentation └── templates/ # [Framework] Templates for onboarding new boards ``` @@ -56,6 +56,22 @@ Every board added to the framework under `/targets` must implement the abstract * `void bsp_console_init(void)`: Initializes the default UART console. * `void bsp_console_write(const char *data, size_t length)`: Transmits a block of data over the console interface. +### Application RAM Budget (`memory.h`) + +* `void bsp_ram_region(void *first_unused, void **base, size_t *size)`: Reports the RAM region the application may claim, given the pointer ThreadX passed to `tx_application_define()`. + +ThreadX reports the first address it believes to be unused, but only the board knows what sits above it - a C heap reservation, a main stack at the top of RAM, or a peripheral window. This interface is what lets an application size a `TX_BYTE_POOL` without naming a board symbol. A board must never include its own reservations in the region it returns; an application will allocate every byte of it. + +The two shipped targets show the two shapes this takes. The NUCLEO-F401RE keeps its main stack at the top of SRAM and clamps the region below a fixed reservation; the PolarFire SoC Icicle Kit keeps its boot stack *below* ThreadX's first unused address and only has to skip its C heap reservation. + +### Startup Self-Tests (`selftest.h`) + +* `unsigned bsp_self_test(bsp_selftest_report_fn report, void *context)`: Runs the board's startup self-tests, reporting each through the callback, and returns the number of failures. + +Checks that the board came up as its own configuration promised are BSP tests, not application tests: they need vendor headers, linker symbols and register maps that no portable application can see. Keeping them behind this interface is what removed those headers from both demos' `main.c`. + +The application supplies only the reporting callback, so message formatting - and therefore the choice between `printf()` and `bsp_console_write()` - stays on the application side. Both shipped targets verify that their C heap cannot grow into the region `bsp_ram_region()` promises the application; the NUCLEO-F401RE additionally checks its clock tree and HAL timebase, and the PolarFire its CLINT tick arithmetic and PLIC routing. + --- ## 4. How to Onboard a New Board diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/README.md b/targets/Microchip/POLARFIRE_ICICLE_RENODE/README.md index 4ea1e9f2..b2f5fb49 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/README.md +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/README.md @@ -55,7 +55,7 @@ four things and exits non-zero if any of them is missing: | Assertion | Covers | |---|---| -| Startup self-tests all passed | `_sbrk()` bounds, timer catch-up, PLIC configuration | +| Startup self-tests all passed | `_sbrk()` bounds against the heap reservation, the `bsp_ram_region()` invariant, timer catch-up, PLIC configuration | | ThreadX system tick advancing | CLINT machine timer and `_tx_timer_interrupt` | | LM75 overtemperature alarm | Queue, event flags, and the analyzer thread | | PLIC IRQ 91 RX interrupt delivered | MMUART1 -> PLIC -> Hart 1 machine-mode trap path | diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/newlib_stubs.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/newlib_stubs.c index 8d196500..cf63f695 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/newlib_stubs.c +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/newlib_stubs.c @@ -18,7 +18,7 @@ #include "board_config.h" #include "bsp/console.h" -extern char __end; /* Symbol set by linker at end of BSS / top of boot stack */ +/* __end, BSP_HEAP_BASE and BSP_HEAP_LIMIT come from board_config.h. */ static char *heap_ptr = NULL; static inline uintptr_t disable_interrupts(void) { @@ -77,7 +77,10 @@ void *_sbrk(ptrdiff_t incr) { } if (incr > 0) { - if ((uintptr_t)heap_ptr + (uintptr_t)incr > (uintptr_t)BSP_RAM_END || + /* Bound against the end of the heap reservation, not the end of DRAM: + * everything above BSP_HEAP_LIMIT is what bsp_ram_region() hands the + * application for its ThreadX pool. */ + if ((uintptr_t)heap_ptr + (uintptr_t)incr > BSP_HEAP_LIMIT || (uintptr_t)heap_ptr + (uintptr_t)incr < (uintptr_t)heap_ptr) { restore_interrupts(mstatus); errno = ENOMEM; diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/main.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/main.c index 50e3808a..9ca5e605 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/main.c +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/main.c @@ -14,23 +14,11 @@ #include #include #include -#include #include "tx_api.h" -#include "hwtimer.h" -#include "plic.h" -#include "csr.h" #include "bsp/board.h" #include "bsp/console.h" #include "bsp/led.h" - -extern void *_sbrk(ptrdiff_t incr); - -/* board_config.h derives TICK_CYCLES from BSP_TICK_RATE_HZ without seeing the - * ThreadX headers. This translation unit sees both, so it is where the two are - * checked against each other. C99 has no _Static_assert, hence the negative - * array size idiom. */ -typedef char bsp_tick_rate_matches_threadx[ - (BSP_TICK_RATE_HZ == (unsigned long long)TX_TIMER_TICKS_PER_SECOND) ? 1 : -1]; +#include "bsp/selftest.h" #define DEMO_STACK_SIZE 4096 #define DEMO_QUEUE_ITEMS 10 @@ -90,13 +78,16 @@ static volatile ULONG s_sampler_runs = 0; static volatile ULONG s_analyzer_runs = 0; static volatile ULONG s_reporter_runs = 0; -static unsigned s_selftest_failures = 0; +/* The startup checks themselves belong to the board and live in its BSP; this + * side only decides how their results are printed. scripts/test_renode.py + * asserts on the summary line. */ + +static void selftest_report(int passed, const char *message, void *context) { + (void)context; -static void selftest_report(int passed, const char *message) { if (passed) { console_print("[+] PASS: "); } else { - s_selftest_failures++; console_print("[-] FAIL: "); } console_print(message); @@ -104,71 +95,20 @@ static void selftest_report(int passed, const char *message) { } static void run_startup_self_tests(void) { - extern char __end; - char num_buf[160]; - console_print("[SELF-TEST] Starting Hardware & Runtime Verification...\n"); - - /* 1. _sbrk() Valid allocation test */ - void *p1 = _sbrk(64); - selftest_report(p1 != (void *)-1 && (uintptr_t)p1 >= (uintptr_t)&__end, - "_sbrk() valid allocation returned base pointer"); - - /* 2. _sbrk() Underflow test (shrink below heap base) */ - errno = 0; - void *p_under = _sbrk(-128); - selftest_report(p_under == (void *)-1 && errno == EINVAL, - "_sbrk() underflow guard rejected with EINVAL"); - - /* 3. _sbrk() Overflow test (request beyond 1 GiB DRAM) */ - errno = 0; - void *p_over = _sbrk((ptrdiff_t)0x40000000ULL); - selftest_report(p_over == (void *)-1 && errno == ENOMEM, - "_sbrk() overflow guard rejected with ENOMEM"); - - /* 4. HWTimer catch-up clamp. - * - * Exercised as pure arithmetic through hwtimer_next_cmp(), so no CLINT - * register is disturbed: mtime is the platform-wide counter shared by every - * hart, and mtimecmp drives the live kernel tick. Both branches are covered - * - a deadline still in the future advances relatively, one already missed - * is rebased onto the current time instead of firing continuously. */ - uint64_t now = 5000000ULL; - uint64_t missed_cmp = now - (TICK_CYCLES * 8ULL); /* 8 ticks behind */ - uint64_t pending_cmp = now - (TICK_CYCLES / 2ULL); /* deadline not yet due */ - int clamp_ok = (hwtimer_next_cmp(missed_cmp, now) == now + TICK_CYCLES) && - (hwtimer_next_cmp(pending_cmp, now) == pending_cmp + TICK_CYCLES); - snprintf(num_buf, sizeof(num_buf), - "HWTimer catch-up (missed deadline rebased to %llu, pending deadline advanced to %llu)", - (unsigned long long)hwtimer_next_cmp(missed_cmp, now), - (unsigned long long)hwtimer_next_cmp(pending_cmp, now)); - selftest_report(clamp_ok, num_buf); - - /* 5. PLIC Configuration & Addressing Verification. - * A wrong PLIC base would read back zeroes here, so the register values - * confirm the addressing as well as the configuration. */ - uint32_t prio = PLIC_PRIORITY_REG(MMUART1_IRQ); - uint32_t en_bitmap = PLIC_HART1_M_ENABLE_REG(MMUART1_IRQ); - uint32_t thresh = PLIC_HART1_M_THRESHOLD_REG; - uint64_t mie_val; - __asm__ volatile("csrr %0, mie" : "=r"(mie_val)); - - int plic_ok = (prio == 1) && - ((en_bitmap & (1U << (MMUART1_IRQ % 32))) != 0) && - (thresh == 0) && - ((mie_val & MIE_MEIE) != 0); - snprintf(num_buf, sizeof(num_buf), - "PLIC Hart 1 (IRQ %u prio=%u en=0x%08X thresh=%u mie=0x%llX)", - (unsigned)MMUART1_IRQ, (unsigned)prio, (unsigned)en_bitmap, - (unsigned)thresh, (unsigned long long)mie_val); - selftest_report(plic_ok, num_buf); - - if (s_selftest_failures == 0) { + char msg[96]; + unsigned failures; + + console_print("[SELF-TEST] Starting BSP & Runtime Verification...\n"); + + failures = bsp_self_test(selftest_report, NULL); + + if (failures == 0U) { console_print("[SELF-TEST] All startup verification tests PASSED!\n\n"); } else { - snprintf(num_buf, sizeof(num_buf), + snprintf(msg, sizeof(msg), "[SELF-TEST] %u startup verification test(s) FAILED!\n\n", - s_selftest_failures); - console_print(num_buf); + failures); + console_print(msg); } } diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/CMakeLists.txt b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/CMakeLists.txt index a2111562..27e02a7e 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/CMakeLists.txt +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/CMakeLists.txt @@ -18,10 +18,18 @@ add_library(polarfire_bsp STATIC src/plic.c src/hwtimer.c src/trap.c + src/bsp_memory.c + src/bsp_selftest.c ) +# The ThreadX headers are needed for headers only: hwtimer.c checks the board's +# configured tick rate against TX_TIMER_TICKS_PER_SECOND at compile time. The +# BSP links no ThreadX code, so no dependency on the threadx target is implied. target_include_directories(polarfire_bsp PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${SAMPLEX_ROOT_DIR}/bsp/include + PRIVATE + ${THREADX_DIR}/common/inc + ${THREADX_DIR}/ports/risc-v64/gnu/inc ) diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/board_config.h b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/board_config.h index 40400d9a..bb129a41 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/board_config.h +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/board_config.h @@ -13,6 +13,8 @@ #ifndef BOARD_CONFIG_H #define BOARD_CONFIG_H +#include + /* CPU Subsystem Frequencies */ #define BSP_CPU_CLOCK_HZ 600000000ULL /* 600 MHz U54 Application Core Clock */ #define BSP_SYSTEM_CLOCK_HZ BSP_CPU_CLOCK_HZ @@ -25,6 +27,23 @@ #define BSP_UART_BAUDRATE 115200 #define BSP_RAM_END 0xC0000000ULL /* 1 GiB LPDDR4 DRAM End Address */ +/* First byte of DRAM above the 16 KB boot stack, placed by linker.ld. + * MISRA C:2012 Rule 8.6 deviation: defined by the linker script rather than by + * any translation unit, which is the only way to import a link-time address. */ +extern char __end; + +/* Bytes of DRAM reserved for the newlib heap immediately above __end. + * + * _sbrk() bounds itself against BSP_HEAP_LIMIT and bsp_ram_region() hands the + * application only the DRAM above it, so malloc() and a ThreadX byte pool + * placed at the first unused address cannot overlap. Bounding _sbrk() against + * BSP_RAM_END instead would let one oversized malloc() take memory the + * application already owns - the failure NUCLEO-F401RE shipped with before its + * heap was bounded against the linker reservation. */ +#define BSP_HEAP_RESERVE_BYTES 0x10000ULL /* 64 KB */ +#define BSP_HEAP_BASE ((uintptr_t)&__end) +#define BSP_HEAP_LIMIT (BSP_HEAP_BASE + (uintptr_t)BSP_HEAP_RESERVE_BYTES) + #define BSP_HAS_LED 1 #define BSP_HAS_CONSOLE 1 diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_memory.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_memory.c new file mode 100644 index 00000000..539c75ed --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_memory.c @@ -0,0 +1,59 @@ +/*************************************************************************** + * 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/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* + * Application RAM budget for the PolarFire SoC Icicle Kit. + * + * linker.ld lays DRAM out as .text, .data, .bss, the 16 KB boot stack, then + * __end - which tx_initialize_low_level.S reports as ThreadX's first unused + * address. Unlike a Cortex-M board there is no stack at the top of RAM to hold + * back, because the boot stack sits below __end; the only reservation above it + * is the newlib heap, which _sbrk() grows up from __end towards + * BSP_HEAP_LIMIT. Everything above that reservation is the application's. + */ + +#include + +#include "bsp/memory.h" +#include "board_config.h" + +/* ThreadX wants an aligned pool base, and linker.ld aligns its sections to 16 + * bytes, so the region starts on the same boundary. */ +#define BSP_RAM_REGION_ALIGN 16U + +void bsp_ram_region(void *first_unused, void **base, size_t *size) +{ + /* + * MISRA C:2012 Rule 11.4 deviation: converting between a pointer and an + * integer is unavoidable here. Clamping against the heap reservation and + * the end of DRAM is arithmetic on absolute addresses, which C cannot + * express on pointers to distinct objects. + */ + uintptr_t start = (uintptr_t)first_unused; + + /* Never hand out the heap reservation, wherever ThreadX believes free + * memory begins. */ + if (start < BSP_HEAP_LIMIT) { + start = BSP_HEAP_LIMIT; + } + + start = (start + (BSP_RAM_REGION_ALIGN - 1U)) & + ~(uintptr_t)(BSP_RAM_REGION_ALIGN - 1U); + + *base = (void *)start; + *size = ((uintptr_t)BSP_RAM_END > start) + ? (size_t)((uintptr_t)BSP_RAM_END - start) + : (size_t)0U; +} diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_selftest.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_selftest.c new file mode 100644 index 00000000..e329fcc2 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_selftest.c @@ -0,0 +1,167 @@ +/*************************************************************************** + * 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/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* + * Startup self-tests for the PolarFire SoC Icicle Kit. + * + * These check the board support package - the bounds its heap enforces, the + * CLINT arithmetic its timebase relies on, the PLIC routing its console + * interrupt needs - so they live with the board rather than with any + * application. The application supplies only the reporting callback, which is + * why this translation unit can include plic.h, hwtimer.h and csr.h without + * dragging any of them into an application. + * + * Every check runs before tx_kernel_enter(), so a failure is reported even + * when the scheduler never starts. + */ + +#include +#include +#include +#include + +#include "bsp/memory.h" +#include "bsp/selftest.h" +#include "board_config.h" +#include "csr.h" +#include "hwtimer.h" +#include "plic.h" + +/* Defined in app/common/startup/newlib_stubs.c, which newlib declares only in + * its private headers. */ +extern void *_sbrk(ptrdiff_t incr); + +/* Reporting state, kept on the caller's stack so bsp_self_test() holds no + * mutable state of its own. */ +typedef struct { + bsp_selftest_report_fn report; + void *context; + unsigned failures; +} selftest_state; + +static void check(selftest_state *state, int passed, const char *message) +{ + if (passed == 0) { + state->failures++; + } + state->report(passed, message, state->context); +} + +unsigned bsp_self_test(bsp_selftest_report_fn report, void *context) +{ + selftest_state state; + char msg[160]; + + void *region_base = NULL; + size_t region_size = 0U; + void *p1; + void *p_under; + void *p_over; + void *p_past_heap; + uint64_t now; + uint64_t missed_cmp; + uint64_t pending_cmp; + uint32_t prio; + uint32_t en_bitmap; + uint32_t thresh; + uint64_t mie_val; + int clamp_ok; + int plic_ok; + + if (report == NULL) { + return 1U; + } + + state.report = report; + state.context = context; + state.failures = 0U; + + /* 1. _sbrk() valid allocation test. */ + p1 = _sbrk(64); + check(&state, (p1 != (void *)-1) && ((uintptr_t)p1 >= BSP_HEAP_BASE), + "_sbrk() valid allocation returned base pointer"); + + /* 2. _sbrk() underflow test (shrink below the heap base). */ + errno = 0; + p_under = _sbrk(-128); + check(&state, (p_under == (void *)-1) && (errno == EINVAL), + "_sbrk() underflow guard rejected with EINVAL"); + + /* 3. _sbrk() overflow test (request beyond the 1 GiB DRAM). */ + errno = 0; + p_over = _sbrk((ptrdiff_t)0x40000000ULL); + check(&state, (p_over == (void *)-1) && (errno == ENOMEM), + "_sbrk() overflow guard rejected with ENOMEM"); + + /* 4. Regression guard for the heap bound. This request fits DRAM with a + * gigabyte to spare but exceeds the heap reservation, so bounding _sbrk() + * against BSP_RAM_END rather than BSP_HEAP_LIMIT lets it succeed and hands + * malloc() memory bsp_ram_region() has already promised the application. */ + errno = 0; + p_past_heap = _sbrk((ptrdiff_t)(BSP_HEAP_RESERVE_BYTES + 0x1000ULL)); + check(&state, (p_past_heap == (void *)-1) && (errno == ENOMEM), + "_sbrk() rejects a request that fits DRAM but not the heap"); + + /* 5. The region bsp_ram_region() hands the application must start above + * the heap reservation and end inside DRAM. This is the invariant that + * keeps malloc() and a ThreadX byte pool from ever overlapping. */ + bsp_ram_region(&__end, ®ion_base, ®ion_size); + (void)snprintf(msg, sizeof(msg), + "bsp_ram_region() yields [0x%llX,0x%llX), clear of the heap and inside DRAM", + (unsigned long long)(uintptr_t)region_base, + (unsigned long long)((uintptr_t)region_base + region_size)); + check(&state, + (region_size > 0U) && ((uintptr_t)region_base >= BSP_HEAP_LIMIT) && + (((uintptr_t)region_base + region_size) <= (uintptr_t)BSP_RAM_END), + msg); + + /* 6. HWTimer catch-up clamp. + * + * Exercised as pure arithmetic through hwtimer_next_cmp(), so no CLINT + * register is disturbed: mtime is the platform-wide counter shared by every + * hart, and mtimecmp drives the live kernel tick. Both branches are covered + * - a deadline still in the future advances relatively, one already missed + * is rebased onto the current time instead of firing continuously. */ + now = 5000000ULL; + missed_cmp = now - (TICK_CYCLES * 8ULL); /* 8 ticks behind */ + pending_cmp = now - (TICK_CYCLES / 2ULL); /* deadline not yet due */ + clamp_ok = (hwtimer_next_cmp(missed_cmp, now) == now + TICK_CYCLES) && + (hwtimer_next_cmp(pending_cmp, now) == pending_cmp + TICK_CYCLES); + (void)snprintf(msg, sizeof(msg), + "HWTimer catch-up (missed deadline rebased to %llu, pending deadline advanced to %llu)", + (unsigned long long)hwtimer_next_cmp(missed_cmp, now), + (unsigned long long)hwtimer_next_cmp(pending_cmp, now)); + check(&state, clamp_ok, msg); + + /* 7. PLIC configuration and addressing verification. + * A wrong PLIC base would read back zeroes here, so the register values + * confirm the addressing as well as the configuration. */ + prio = PLIC_PRIORITY_REG(MMUART1_IRQ); + en_bitmap = PLIC_HART1_M_ENABLE_REG(MMUART1_IRQ); + thresh = PLIC_HART1_M_THRESHOLD_REG; + __asm__ volatile("csrr %0, mie" : "=r"(mie_val)); + + plic_ok = (prio == 1) && + ((en_bitmap & (1U << (MMUART1_IRQ % 32))) != 0) && + (thresh == 0) && + ((mie_val & MIE_MEIE) != 0); + (void)snprintf(msg, sizeof(msg), + "PLIC Hart 1 (IRQ %u prio=%u en=0x%08X thresh=%u mie=0x%llX)", + (unsigned)MMUART1_IRQ, (unsigned)prio, (unsigned)en_bitmap, + (unsigned)thresh, (unsigned long long)mie_val); + check(&state, plic_ok, msg); + + return state.failures; +} diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/hwtimer.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/hwtimer.c index 2f7635a2..374722c9 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/hwtimer.c +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/hwtimer.c @@ -11,6 +11,15 @@ // Some portions generated by Claude Code (Opus 5) #include "hwtimer.h" +#include "tx_api.h" + +/* hwtimer.h derives TICK_CYCLES from BSP_TICK_RATE_HZ without seeing the + * ThreadX headers. This translation unit sees both, so it is where the two are + * checked against each other. C99 has no _Static_assert, hence the negative + * array size idiom. */ +typedef char bsp_tick_rate_matches_threadx[ + (BSP_TICK_RATE_HZ == (unsigned long long)TX_TIMER_TICKS_PER_SECOND) ? 1 : -1]; + void hwtimer_init(void) { /* Program initial mtimecmp target to current mtime + 10,000 cycles (10ms) */ diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/README.md b/targets/STMicroelectronics/NUCLEO_F401RE/README.md index e1d3025d..dbee3ce3 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/README.md +++ b/targets/STMicroelectronics/NUCLEO_F401RE/README.md @@ -80,8 +80,11 @@ ground for use with `renode-test`. ### What is asserted -The demo runs seven startup self-tests before `tx_kernel_enter()` and prints a -`[SELF-TEST]` summary the harness asserts on: +The board runs eight startup self-tests before `tx_kernel_enter()` and the demo +prints a `[SELF-TEST]` summary the harness asserts on. The checks live in +`lib/bsp/src/bsp_selftest.c` behind ``, because they test the +BSP - its linker reservations, its clock tree, its HAL timebase - rather than +the application. `main.c` supplies only the reporting callback: | # | Self-test | Guards against | |---|-----------|----------------| @@ -92,6 +95,7 @@ The demo runs seven startup self-tests before `tx_kernel_enter()` and prints a | 5 | Heap reservation ends at or below the ThreadX byte pool | linker script layout regression | | 6 | `SystemCoreClock` is 84 MHz | a silently wrong PLL configuration | | 7 | HAL timebase (TIM2) tick advancing | `HAL_InitTick()` re-entry leaving TIM2 stopped | +| 8 | `bsp_ram_region()` stays clear of the heap and inside SRAM | a bad stack reservation handing the byte pool memory it does not own | Test 4 is the regression guard for the heap bound. Requesting 32 KB fits inside the 96 KB SRAM but far exceeds the heap reservation, so bounding `_sbrk()` @@ -197,7 +201,7 @@ The BSP overrides `HAL_InitTick()` to configure TIM2 as the HAL timebase and pro ### Verification Environment - **Toolchain**: Arm GNU Toolchain 14.3.Rel1 (GCC 14.3.1), the version pinned by CI and by the ThreadX Cortex-M ports -- **Static ROM usage**: 22064 Bytes (4.21% of 512 KB Flash), including the startup self-tests +- **Static ROM usage**: 22272 Bytes (4.25% of 512 KB Flash), including the startup self-tests - **Static RAM usage**: 6000 Bytes (6.10% of 96 KB RAM) - **Dynamic Stack & Buffer allocation**: Stacks (8 x 1024 bytes) and Queue buffer (40 bytes) are dynamically allocated from the `TX_BYTE_POOL` (consuming 8312 bytes total, including pool headers). - **Board Hardware**: NUCLEO-F401RE diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c b/targets/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c index 5493933e..401e04de 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c +++ b/targets/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c @@ -8,25 +8,19 @@ * SPDX-License-Identifier: MIT */ -#include +// Some portions generated by Claude Code (Opus 5) + #include -#include #include #include "tx_api.h" #include "bsp/board.h" #include "bsp/led.h" -#include "bsp/console.h" -#include "board_config.h" -#include "cloud_config.h" -#include "stm32f4xx_hal.h" +#include "bsp/memory.h" +#include "bsp/selftest.h" #define THREAD_STACK_SIZE 1024 -/* Bytes of SRAM held back above the ThreadX byte pool for the main stack, - * which serves every interrupt handler once the scheduler is running. */ -#define MAIN_STACK_MARGIN 4096 - typedef struct { CHAR *name; UINT state; @@ -355,15 +349,17 @@ static void queue_receiver_entry(ULONG parameter) { void tx_application_define(void *first_unused_memory) { UINT status; CHAR *stack_ptr; - ULONG pool_size; + void *pool_base; + size_t pool_size; - /* Calculate available RAM for the byte pool, leaving a 4 KB margin for the - * main stack at the top of SRAM. */ - pool_size = (BSP_RAM_END - MAIN_STACK_MARGIN) - (ULONG)first_unused_memory; + /* The board decides how much of the RAM above ThreadX's first unused address + * the application may claim; whatever it reserves for its own heap and stack + * is already excluded. */ + bsp_ram_region(first_unused_memory, &pool_base, &pool_size); /* Initialize the byte pool */ - status = tx_byte_pool_create(&byte_pool, "system byte pool", - first_unused_memory, pool_size); + status = tx_byte_pool_create(&byte_pool, "system byte pool", pool_base, + (ULONG)pool_size); if (status != TX_SUCCESS) { printf("Byte pool create failed: 0x%08x\r\n", status); return; @@ -552,91 +548,33 @@ void tx_application_define(void *first_unused_memory) { /* ------------------------------------------------------------------------- * * Startup self-tests * - * These run before tx_kernel_enter() so a failure is reported even when the - * scheduler never starts. scripts/test_renode.py asserts on the summary line. + * The checks themselves belong to the board and live in its BSP; this side + * only decides how their results are printed. scripts/test_renode.py asserts + * on the summary line. * ------------------------------------------------------------------------- */ -/* Defined by NUCLEO_F401RE.ld rather than by any translation unit. */ -extern char _end; -extern char _heap_limit; -extern char __RAM_segment_used_end__; - -extern void *_sbrk(ptrdiff_t incr); +static void selftest_report(int passed, const char *message, void *context) { + (void)context; -static unsigned selftest_failures = 0; - -static void selftest_report(int passed, const char *message) { if (passed) { printf("[+] PASS: %s\r\n", message); } else { - selftest_failures++; printf("[-] FAIL: %s\r\n", message); } } static void run_startup_self_tests(void) { - const uintptr_t heap_base = (uintptr_t)&_end; - const uintptr_t heap_limit = (uintptr_t)&_heap_limit; - const uintptr_t pool_base = (uintptr_t)&__RAM_segment_used_end__; - char msg[128]; + unsigned failures; printf("[SELF-TEST] Starting BSP & Runtime Verification...\r\n"); - /* 1. A modest request lands inside the heap reservation. */ - void *p_ok = _sbrk(64); - selftest_report((p_ok != (void *)-1) && ((uintptr_t)p_ok >= heap_base) && - ((uintptr_t)p_ok < heap_limit), - "_sbrk() valid allocation inside the heap reservation"); - - /* 2. Releasing it returns the break to the heap base, leaving the heap - * exactly as the remaining tests found it. */ - selftest_report(_sbrk(-64) != (void *)-1, - "_sbrk() released 64 bytes back to the heap base"); - - /* 3. Shrinking below the heap base is rejected. */ - errno = 0; - void *p_under = _sbrk(-128); - selftest_report((p_under == (void *)-1) && (errno == EINVAL), - "_sbrk() underflow guard rejected with EINVAL"); - - /* 4. Regression guard for the heap bound. 32 KB fits inside the 96 KB SRAM - * but far exceeds the heap reservation, so bounding _sbrk() against the end - * of SRAM rather than _heap_limit let this succeed and handed malloc() - * memory owned by the ThreadX byte pool and the main stack. */ - errno = 0; - void *p_over = _sbrk((ptrdiff_t)0x8000); - selftest_report((p_over == (void *)-1) && (errno == ENOMEM), - "_sbrk() rejects a request that fits SRAM but not the heap"); - - /* 5. The heap reservation must end at or below the first byte ThreadX owns. */ - snprintf(msg, sizeof(msg), - "heap [0x%08lX,0x%08lX) ends at or below the ThreadX pool at 0x%08lX", - (unsigned long)heap_base, (unsigned long)heap_limit, - (unsigned long)pool_base); - selftest_report(heap_limit <= pool_base, msg); - - /* 6. SystemClock_Config() reached the documented 84 MHz. */ - snprintf(msg, sizeof(msg), "SystemCoreClock is %lu Hz (expected %lu Hz)", - (unsigned long)SystemCoreClock, (unsigned long)BSP_CPU_CLOCK_HZ); - selftest_report(SystemCoreClock == (uint32_t)BSP_CPU_CLOCK_HZ, msg); - - /* 7. The HAL timebase runs on TIM2 so ThreadX keeps SysTick. HAL_InitTick() - * is re-entered by HAL_RCC_ClockConfig() once the PLL is live, so confirm the - * timer is still ticking afterwards. The spin cap is a liveness bound, not a - * timing expectation: one TIM2 tick is ~84000 core cycles. */ - uint32_t tick_start = HAL_GetTick(); - uint32_t spins = 0; - while ((HAL_GetTick() == tick_start) && (spins < 5000000UL)) { - spins++; - } - selftest_report(HAL_GetTick() != tick_start, - "HAL timebase (TIM2) tick advancing"); + failures = bsp_self_test(selftest_report, NULL); - if (selftest_failures == 0) { + if (failures == 0U) { printf("[SELF-TEST] All startup verification tests PASSED!\r\n\r\n"); } else { printf("[SELF-TEST] %u startup verification test(s) FAILED!\r\n\r\n", - selftest_failures); + failures); } } diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/CMakeLists.txt b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/CMakeLists.txt index bd70c9b0..3b1a9ba6 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/CMakeLists.txt +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/CMakeLists.txt @@ -14,6 +14,8 @@ add_library(nucleo_bsp STATIC src/bsp_board.c src/bsp_led.c src/bsp_console.c + src/bsp_memory.c + src/bsp_selftest.c ) target_include_directories(nucleo_bsp diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/board_config.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/board_config.h index 3f7af472..929e0815 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/board_config.h +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/board_config.h @@ -8,6 +8,8 @@ * SPDX-License-Identifier: MIT */ +// Some portions generated by Claude Code (Opus 5) + #ifndef BOARD_CONFIG_H #define BOARD_CONFIG_H @@ -29,6 +31,11 @@ #define BSP_RAM_SIZE 0x00018000UL /* 96 KB */ #define BSP_RAM_END (BSP_RAM_START + BSP_RAM_SIZE) +/* Bytes of SRAM held back below _estack for the main stack, which serves every + * interrupt handler once the scheduler is running. bsp_ram_region() clamps the + * application's RAM budget below this reservation. */ +#define BSP_MAIN_STACK_RESERVE 4096UL + #define BSP_HAS_LED 1 #define BSP_HAS_CONSOLE 1 diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_memory.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_memory.c new file mode 100644 index 00000000..a087e4bf --- /dev/null +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_memory.c @@ -0,0 +1,45 @@ +/*************************************************************************** + * 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/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* + * Application RAM budget for the NUCLEO-F401RE. + * + * NUCLEO_F401RE.ld lays SRAM out as .data, .bss, the newlib heap reservation + * and _Min_Stack_Size, then __RAM_segment_used_end__ - which is what + * tx_initialize_low_level.S reports as ThreadX's first unused address. The + * main stack grows down from _estack at the top of SRAM, so the region between + * the two is what the application may claim. + */ + +#include + +#include "bsp/memory.h" +#include "board_config.h" + +void bsp_ram_region(void *first_unused, void **base, size_t *size) +{ + /* + * MISRA C:2012 Rule 11.4 deviation: converting between a pointer and an + * integer is unavoidable here. The comparison against BSP_RAM_END is + * arithmetic on absolute addresses, which C cannot express on pointers to + * distinct objects. + */ + const uintptr_t start = (uintptr_t)first_unused; + const uintptr_t end = (uintptr_t)BSP_RAM_END - + (uintptr_t)BSP_MAIN_STACK_RESERVE; + + *base = first_unused; + *size = (end > start) ? (size_t)(end - start) : (size_t)0U; +} diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_selftest.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_selftest.c new file mode 100644 index 00000000..4c893966 --- /dev/null +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_selftest.c @@ -0,0 +1,161 @@ +/*************************************************************************** + * 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/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* + * Startup self-tests for the NUCLEO-F401RE. + * + * These check the board support package - the heap bounds its linker script + * reserves, the clock its init code programs, the timebase its HAL drives - so + * they live with the board rather than with any application. The application + * supplies only the reporting callback, which is why this translation unit can + * include board_config.h and the vendor HAL without dragging either into an + * application. + * + * Every check runs before tx_kernel_enter(), so a failure is reported even + * when the scheduler never starts. + */ + +#include +#include +#include +#include + +#include "bsp/memory.h" +#include "bsp/selftest.h" +#include "board_config.h" +#include "stm32f4xx_hal.h" + +/* + * Bounds of the heap reservation and of ThreadX's first free byte. + * MISRA C:2012 Rule 8.6 deviation: these symbols are defined by + * NUCLEO_F401RE.ld rather than by any translation unit, which is the only way + * to import an address decided at link time. + */ +extern char _end; +extern char _heap_limit; +extern char __RAM_segment_used_end__; + +/* Defined in newlib_stubs.c, which newlib declares only in private headers. */ +extern void *_sbrk(ptrdiff_t incr); + +/* Reporting state, kept on the caller's stack so bsp_self_test() holds no + * mutable state of its own. */ +typedef struct { + bsp_selftest_report_fn report; + void *context; + unsigned failures; +} selftest_state; + +static void check(selftest_state *state, int passed, const char *message) +{ + if (passed == 0) { + state->failures++; + } + state->report(passed, message, state->context); +} + +unsigned bsp_self_test(bsp_selftest_report_fn report, void *context) +{ + selftest_state state; + char msg[128]; + + const uintptr_t heap_base = (uintptr_t)&_end; + const uintptr_t heap_limit = (uintptr_t)&_heap_limit; + const uintptr_t pool_base = (uintptr_t)&__RAM_segment_used_end__; + + void *region_base = NULL; + size_t region_size = 0U; + void *p_ok; + void *p_under; + void *p_over; + uint32_t tick_start; + uint32_t spins; + + if (report == NULL) { + return 1U; + } + + state.report = report; + state.context = context; + state.failures = 0U; + + /* 1. A modest request lands inside the heap reservation. */ + p_ok = _sbrk(64); + check(&state, (p_ok != (void *)-1) && ((uintptr_t)p_ok >= heap_base) && + ((uintptr_t)p_ok < heap_limit), + "_sbrk() valid allocation inside the heap reservation"); + + /* 2. Releasing it returns the break to the heap base, leaving the heap + * exactly as the remaining checks found it. */ + check(&state, _sbrk(-64) != (void *)-1, + "_sbrk() released 64 bytes back to the heap base"); + + /* 3. Shrinking below the heap base is rejected. */ + errno = 0; + p_under = _sbrk(-128); + check(&state, (p_under == (void *)-1) && (errno == EINVAL), + "_sbrk() underflow guard rejected with EINVAL"); + + /* 4. Regression guard for the heap bound. 32 KB fits inside the 96 KB SRAM + * but far exceeds the heap reservation, so bounding _sbrk() against the end + * of SRAM rather than _heap_limit let this succeed and handed malloc() + * memory owned by the ThreadX byte pool and the main stack. */ + errno = 0; + p_over = _sbrk((ptrdiff_t)0x8000); + check(&state, (p_over == (void *)-1) && (errno == ENOMEM), + "_sbrk() rejects a request that fits SRAM but not the heap"); + + /* 5. The heap reservation must end at or below the first byte ThreadX + * owns. */ + (void)snprintf(msg, sizeof(msg), + "heap [0x%08lX,0x%08lX) ends at or below the ThreadX pool at 0x%08lX", + (unsigned long)heap_base, (unsigned long)heap_limit, + (unsigned long)pool_base); + check(&state, heap_limit <= pool_base, msg); + + /* 6. SystemClock_Config() reached the documented 84 MHz. */ + (void)snprintf(msg, sizeof(msg), + "SystemCoreClock is %lu Hz (expected %lu Hz)", + (unsigned long)SystemCoreClock, + (unsigned long)BSP_CPU_CLOCK_HZ); + check(&state, SystemCoreClock == (uint32_t)BSP_CPU_CLOCK_HZ, msg); + + /* 7. The HAL timebase runs on TIM2 so ThreadX keeps SysTick. HAL_InitTick() + * is re-entered by HAL_RCC_ClockConfig() once the PLL is live, so confirm + * the timer is still ticking afterwards. The spin cap is a liveness bound, + * not a timing expectation: one TIM2 tick is ~84000 core cycles. */ + tick_start = HAL_GetTick(); + spins = 0; + while ((HAL_GetTick() == tick_start) && (spins < 5000000UL)) { + spins++; + } + check(&state, HAL_GetTick() != tick_start, + "HAL timebase (TIM2) tick advancing"); + + /* 8. The region bsp_ram_region() hands the application must start above + * the heap reservation and end inside SRAM. This is the invariant that + * keeps malloc() and the ThreadX byte pool from ever overlapping. */ + bsp_ram_region(&__RAM_segment_used_end__, ®ion_base, ®ion_size); + (void)snprintf(msg, sizeof(msg), + "bsp_ram_region() yields [0x%08lX,0x%08lX), clear of the heap and inside SRAM", + (unsigned long)(uintptr_t)region_base, + (unsigned long)((uintptr_t)region_base + region_size)); + check(&state, + (region_size > 0U) && ((uintptr_t)region_base >= heap_limit) && + (((uintptr_t)region_base + region_size) <= (uintptr_t)BSP_RAM_END), + msg); + + return state.failures; +} diff --git a/templates/target/README.md b/templates/target/README.md index a5be06db..beddee2d 100644 --- a/templates/target/README.md +++ b/templates/target/README.md @@ -46,11 +46,11 @@ Repository To maintain long-term framework maintainability and portability, the following root directories should generally remain **unchanged** when onboarding a new board: -* `/bsp`: Defines the target-agnostic C interface contracts (`board.h`, `led.h`, `console.h`). New board targets must implement these existing interfaces rather than modifying core interface definitions. +* `/bsp`: Defines the target-agnostic C interface contracts (`board.h`, `led.h`, `console.h`, `memory.h`, `selftest.h`). New board targets must implement these existing interfaces rather than modifying core interface definitions. * `/libs`: Shared RTOS components consumed by every target as submodules. Targets reference these rather than vendoring their own copy. > [!NOTE] -> **Applications are currently target-resident.** Each target owns its demo under `targets///app/`, along with its own `cmake/` toolchain files and build helpers. A shared `/apps` layer is a goal of this framework, not something it provides yet: today's demos also include their target's `board_config.h` for memory sizing and vendor headers for board-specific startup self-tests. Onboard a new board by starting from the app in this template, not by linking one from a shared directory. +> **Applications are currently target-resident.** Each target owns its demo under `targets///app/`, along with its own `cmake/` toolchain files and build helpers. A shared `/apps` layer is a goal of this framework, not something it provides yet, so onboard a new board by starting from the app in this template rather than by linking one from a shared directory. What a demo no longer needs is board headers: `` covers byte-pool sizing and `` covers startup self-tests, so both shipped demos include only `` and ``. > [!NOTE] > **Core Architectural Principle**: @@ -72,7 +72,7 @@ The table below maps common embedded software components to their designated loc | **Startup Assembly & System Code** | `targets///app/common/startup/` | Vendor SDK (`startup_.s`, `system_.c`) | | **Linker Script** | `targets///app/common/linker/` | Vendor SDK (`.ld` or compiler script) | | **ThreadX Low-Level Setup** | `targets///app/common/startup/` | `libs/threadx/ports///src/` | -| **BSP Driver Implementation** | `targets///lib/bsp/src/` | Target developer (`bsp_board.c`, `bsp_led.c`, `bsp_console.c`) | +| **BSP Driver Implementation** | `targets///lib/bsp/src/` | Target developer (`bsp_board.c`, `bsp_led.c`, `bsp_console.c`, `bsp_memory.c`, `bsp_selftest.c`) | | **Target Specification Constants** | `targets///lib/bsp/include/board_config.h` | Target developer (declarative defines only) | | **Target Build Automation** | `targets///scripts/build.ps1` | Target developer (PowerShell automation template) | | **Application Code** | `targets///app/` | Target developer (start from this template's `app/main.c`) | @@ -95,12 +95,15 @@ To add support for a new board (e.g. `MY_VENDOR / MY_BOARD`): - Set `BSP_SYSTEM_CLOCK_HZ` to your core CPU frequency. - Set `BSP_UART_BAUDRATE` to your debug serial speed. - Set `BSP_RAM_END` to the physical top address of your MCU SRAM. + - Set `BSP_MAIN_STACK_RESERVE` to the bytes your board holds back at the top of RAM for the main stack, so `bsp_ram_region()` keeps an application's byte pool clear of it. 3. **Implement Abstract C BSP Drivers**: Populate the driver stubs in `targets/MyVendor/MY_BOARD/lib/bsp/src/`: - `bsp_board.c`: Configure System Clocks, Flash Wait States, and low-level timers in `bsp_board_init()`. - `bsp_led.c`: Configure GPIO pin muxing and implement `bsp_led_on()`, `bsp_led_off()`, `bsp_led_toggle()`. - `bsp_console.c`: Configure UART peripheral and implement `bsp_console_write()`. + - `bsp_memory.c`: Report the RAM the application may claim in `bsp_ram_region()`, subtracting whatever this board reserves for its C heap and stacks. + - `bsp_selftest.c`: Verify in `bsp_self_test()` that the board came up as configured - clocks, timebase, interrupt routing, and that the C heap cannot grow into the region `bsp_ram_region()` hands out. 4. **Add Startup Files & Linker Script**: Obtain the standard startup assembly (`startup_.s`), system initialization (`system_.c`), and linker script (`.ld`) **directly from your MCU vendor's official SDK or reference package** (do not write these from scratch). Developers should avoid modifying vendor startup code unless strictly necessary, as these files are maintained by the silicon vendor. Place them under `targets/MyVendor/MY_BOARD/app/common/startup/` and `targets/MyVendor/MY_BOARD/app/common/linker/`. @@ -133,12 +136,14 @@ The current framework defines the following core baseline C interfaces in `/bsp/ | `` | `bsp_board_init()` | Core MCU clock tree, power scaling, and flash wait state setup. | | `` | `bsp_led_init()`, `bsp_led_toggle()`, etc. | GPIO user LED initialization and state toggling. | | `` | `bsp_console_init()`, `bsp_console_write()` | Serial UART initialization and output transmission. | +| `` | `bsp_ram_region()` | RAM the application may claim, clamped against the board's own heap and stack reservations. | +| `` | `bsp_self_test()` | Board startup verification, reported through an application-supplied callback. | ### Target Configuration Component (`board_config.h`) | Configuration File | Expected Constants | Description | | :--- | :--- | :--- | -| `board_config.h` | `BSP_RAM_END`, `BSP_SYSTEM_CLOCK_HZ`, `BSP_UART_BAUDRATE` | Compile-time hardware specification constants consumed by the BSP driver implementation layer. | +| `board_config.h` | `BSP_RAM_END`, `BSP_MAIN_STACK_RESERVE`, `BSP_SYSTEM_CLOCK_HZ`, `BSP_UART_BAUDRATE` | Compile-time hardware specification constants consumed by the BSP driver implementation layer. | > [!TIP] > **Optional Interfaces & Hardware Variants**: diff --git a/templates/target/app/main.c b/templates/target/app/main.c index 668cf681..1169b3f6 100644 --- a/templates/target/app/main.c +++ b/templates/target/app/main.c @@ -18,12 +18,12 @@ * * This file deliberately depends on nothing but and the generic BSP * contracts in , so it compiles for any target that implements them. - * Thread stacks are static, which avoids needing the board's memory extents. + * That includes the two things a demo used to need board headers for: sizing a + * byte pool, which answers, and running the board's startup + * self-tests, which answers. * - * Once the board boots this, grow the demo in place. Real targets do include - * their own board_config.h and vendor headers - for byte-pool sizing and for - * board-specific startup self-tests - and that is expected; applications live - * with their target rather than in a shared directory. + * Once the board boots this, grow the demo in place. Applications live with + * their target rather than in a shared directory. */ #include "tx_api.h" @@ -31,7 +31,10 @@ #include "bsp/board.h" #include "bsp/console.h" #include "bsp/led.h" +#include "bsp/memory.h" +#include "bsp/selftest.h" +#include #include #define DEMO_STACK_SIZE 1024 @@ -49,6 +52,18 @@ static void console_print(const char *text) bsp_console_write(text, strlen(text)); } +/* The startup checks belong to the board and live in its BSP; this side only + * decides how their results are printed. A board with no console of its own + * could just as well count failures and blink the LED. */ +static void selftest_report(int passed, const char *message, void *context) +{ + (void)context; + + console_print(passed ? "[+] PASS: " : "[-] FAIL: "); + console_print(message); + console_print("\r\n"); +} + static void blink_thread_entry(ULONG parameter) { (void)parameter; @@ -73,11 +88,16 @@ static void report_thread_entry(ULONG parameter) void tx_application_define(void *first_unused_memory) { - (void)first_unused_memory; + void *pool_base; + size_t pool_size; - /* TODO: Create a TX_BYTE_POOL from first_unused_memory if this target's - * demo outgrows static stacks. Doing so needs the board's RAM extent, so - * it belongs with the target rather than in shared code. */ + /* Stacks below are static, so this pool is unused as shipped. It is here + * because it is how a demo grows past static stacks without naming a + * single board symbol: the board reports what it has to spare, having + * already excluded its own heap and stack reservations. */ + bsp_ram_region(first_unused_memory, &pool_base, &pool_size); + (void)pool_base; + (void)pool_size; (void)tx_thread_create(&blink_thread, "blink thread", blink_thread_entry, 0, blink_stack, DEMO_STACK_SIZE, @@ -94,8 +114,16 @@ int main(void) console_print("\r\n=== Eclipse ThreadX target template ===\r\n"); - /* TODO: Run any board-specific startup self-tests here, before the - * scheduler starts, so failures are reported even if it never runs. */ + /* Run the board's startup self-tests before the scheduler starts, so a + * failure is reported even if it never runs. */ + if (bsp_self_test(selftest_report, NULL) == 0U) + { + console_print("[SELF-TEST] All startup verification tests PASSED!\r\n"); + } + else + { + console_print("[SELF-TEST] Startup verification FAILED!\r\n"); + } tx_kernel_enter(); diff --git a/templates/target/lib/bsp/CMakeLists.txt b/templates/target/lib/bsp/CMakeLists.txt index 8b7ddebb..ca073971 100644 --- a/templates/target/lib/bsp/CMakeLists.txt +++ b/templates/target/lib/bsp/CMakeLists.txt @@ -11,6 +11,8 @@ add_library(target_bsp STATIC src/bsp_board.c src/bsp_led.c src/bsp_console.c + src/bsp_memory.c + src/bsp_selftest.c ) # Export BSP headers and shared abstract C BSP headers to PUBLIC include paths diff --git a/templates/target/lib/bsp/include/board_config.h b/templates/target/lib/bsp/include/board_config.h index 6fc2cc8e..5898dc0d 100644 --- a/templates/target/lib/bsp/include/board_config.h +++ b/templates/target/lib/bsp/include/board_config.h @@ -29,6 +29,12 @@ */ #define BSP_RAM_END 0x20018000 +/* TODO: Set the number of bytes this board reserves at the top of RAM, if any. + * bsp_ram_region() subtracts it so an application's byte pool never overlaps + * the main stack. Boards that keep their stack below ThreadX's first unused + * address can leave this at 0 and reserve for the C heap instead. */ +#define BSP_MAIN_STACK_RESERVE 4096UL + /* Optional hardware peripheral availability flags */ #define BSP_HAS_LED 1 #define BSP_HAS_CONSOLE 1 diff --git a/templates/target/lib/bsp/src/bsp_memory.c b/templates/target/lib/bsp/src/bsp_memory.c new file mode 100644 index 00000000..217b0e4b --- /dev/null +++ b/templates/target/lib/bsp/src/bsp_memory.c @@ -0,0 +1,49 @@ +/*************************************************************************** + * 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/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +#include + +#include "bsp/memory.h" +#include "board_config.h" + +/* + * Reports how much of the RAM above ThreadX's first unused address the + * application may claim. Only this board knows what sits above it, which is + * why the application never has to. + * + * The two shipped targets show the two shapes this takes: + * + * - NUCLEO-F401RE keeps its main stack at the top of SRAM, so it clamps the + * region below a fixed reservation. + * - PolarFire SoC keeps its boot stack below the first unused address and + * only has to skip the C heap reservation. + * + * TODO: Subtract whatever this board reserves. Anything the C heap, the main + * stack, or a memory-mapped window owns must NOT appear in the returned + * region - an application will allocate every byte of it. + */ +void bsp_ram_region(void *first_unused, void **base, size_t *size) +{ + /* + * MISRA C:2012 Rule 11.4 deviation: converting between a pointer and an + * integer is unavoidable when comparing against an absolute address, which + * C cannot express on pointers to distinct objects. + */ + const uintptr_t start = (uintptr_t)first_unused; + const uintptr_t end = (uintptr_t)BSP_RAM_END - (uintptr_t)BSP_MAIN_STACK_RESERVE; + + *base = first_unused; + *size = (end > start) ? (size_t)(end - start) : (size_t)0U; +} diff --git a/templates/target/lib/bsp/src/bsp_selftest.c b/templates/target/lib/bsp/src/bsp_selftest.c new file mode 100644 index 00000000..a9664f56 --- /dev/null +++ b/templates/target/lib/bsp/src/bsp_selftest.c @@ -0,0 +1,77 @@ +/*************************************************************************** + * 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/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* + * Startup self-tests for this board. + * + * Checks that the board came up as its own configuration promised belong here + * rather than in an application: they need vendor headers, linker symbols and + * register maps that no portable application can see. The application supplies + * only the reporting callback, so this file is free to include anything the + * board needs. + * + * Worthwhile checks, drawn from the two shipped targets: + * + * - The C heap cannot grow into memory bsp_ram_region() hands the + * application. Both shipped targets carry a regression guard for exactly + * this, because getting it wrong corrupts thread stacks silently. + * - The clock the board programmed matches BSP_SYSTEM_CLOCK_HZ. + * - The timebase driving the kernel tick is actually advancing. + * - The interrupt controller routes the console IRQ where the driver expects. + */ + +#include + +#include "bsp/selftest.h" +#include "board_config.h" + +/* TODO: Include the vendor HAL, linker-symbol externs and register headers the + * checks below need. */ + +/* Reporting state, kept on the caller's stack so bsp_self_test() holds no + * mutable state of its own. */ +typedef struct { + bsp_selftest_report_fn report; + void *context; + unsigned failures; +} selftest_state; + +static void check(selftest_state *state, int passed, const char *message) +{ + if (passed == 0) { + state->failures++; + } + state->report(passed, message, state->context); +} + +unsigned bsp_self_test(bsp_selftest_report_fn report, void *context) +{ + selftest_state state; + + if (report == NULL) { + return 1U; + } + + state.report = report; + state.context = context; + state.failures = 0U; + + /* TODO: Replace this placeholder with the board's real checks. Report each + * through check(), including any measured values in the message so a + * failure is diagnosable from the console log alone. */ + check(&state, 1, "board self-tests not yet implemented for this target"); + + return state.failures; +} From 4ddc8b46d18bf0d7b488dc77d4138d6b620fe878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 1 Sep 2026 07:21:25 -0400 Subject: [PATCH 13/20] Moved the demo into apps/ and made both targets build it (#57) The framework documented a portable application layer it did not have: each target owned its own demo under app/, so nothing checked that a demo could actually move between boards. This adds apps/, moves the NUCLEO-F401RE demo into apps/threadx_demo/main.c unchanged in behaviour, and has the PolarFire SoC Icicle Kit build that same source as a second executable beside its LM75 monitor. CI runs it under Renode on 32-bit Cortex-M4 and 64-bit RISC-V and asserts on the same console output from both, so the claim is now enforced rather than stated. apps/ holds portable demos; targets///app/ holds board-specific ones, and a target's app/CMakeLists.txt picks either. The PolarFire LM75 monitor stays a target app because it genuinely models a sensor. Linking a second executable first required removing a hard undefined reference: polarfire_bsp's trap.c called console_rx_isr_callback(), a symbol only its own demo defined, so any other application had to define a PolarFire-specific ISR callback just to link. bsp/console.h gains a registration call in the shape bsp_self_test() already established: typedef void (*bsp_console_rx_fn)(char c, void *context); void bsp_console_set_rx_handler(bsp_console_rx_fn handler, void *context); The board stores a nullable pointer and checks it before dispatching, so bytes arriving with no handler attached are dropped instead of faulting, and an application that ignores console input defines nothing. The LM75 demo registers its existing handler in main(); the NUCLEO-F401RE polls USART2 and so stores a handler it never invokes, which keeps the contract uniform enough to register against unconditionally. A weak symbol was rejected: it keeps the up-call and is a GCC extension in a C99 codebase. Building the demo for a second architecture found two real defects: - Every %lu in the demo was wrong on one target. ThreadX defines ULONG as unsigned long on the Cortex-M4 port and unsigned int on the RISC-V 64 one, so each value now casts to unsigned long, matching the existing idiom in the LM75 demo. - Both boards' _sbrk() underflow self-test asked for a fixed -128, which is an underflow only when nothing has allocated yet. The NUCLEO's passed by accident of a printf buffer malloc that failed against a small reservation; the PolarFire's failed outright once a demo reached printf first. Both now hand back one byte more than has ever been taken, which underflows whatever ran before them. Thread stacks are sized in machine words rather than bytes, since every saved register and the newlib printf() call chain double in width on a 64-bit hart: 1024 bytes on Cortex-M4 as before, 2048 on RISC-V, measured peak 1048. Measured PolarFire heap use under printf, the first stdio on that board, is 2944 bytes; the run also completes with BSP_HEAP_RESERVE_BYTES cut to 4 KB, so the 64 KB reservation holds unchanged. Verified locally on both toolchains: three Renode suites green, and with the _sbrk() bound deliberately widened the self-tests still fail - two checks on the NUCLEO-F401RE, one on each PolarFire executable. Assisted-by: Claude Opus 5 (1M context) --- .github/workflows/ci.yml | 32 ++- .../app/starter => apps/threadx_demo}/main.c | 95 ++++++-- bsp/include/bsp/console.h | 33 +++ docs/architecture.md | 16 +- .../POLARFIRE_ICICLE_RENODE/README.md | 84 ++++++- .../app/CMakeLists.txt | 64 ++++-- .../POLARFIRE_ICICLE_RENODE/app/main.c | 12 +- .../lib/bsp/include/polarfire_console.h | 36 +++ .../lib/bsp/src/bsp_console.c | 27 +++ .../lib/bsp/src/bsp_selftest.c | 13 +- .../lib/bsp/src/trap.c | 6 +- .../renode/polarfire_threadx_demo.resc | 32 +++ .../renode/polarfire_threadx_demo_ci.resc | 38 +++ .../scripts/test_renode.py | 216 ++++++++++++++---- .../NUCLEO_F401RE/README.md | 20 +- .../NUCLEO_F401RE/app/CMakeLists.txt | 10 +- .../NUCLEO_F401RE/app/starter/cloud_config.h | 16 -- .../lib/bsp/include/nucleo_console.h | 14 ++ .../NUCLEO_F401RE/lib/bsp/src/bsp_console.c | 34 +++ .../NUCLEO_F401RE/lib/bsp/src/bsp_selftest.c | 18 +- .../renode/nucleo_f401re_demo.robot | 2 +- .../NUCLEO_F401RE/scripts/test_renode.py | 11 +- templates/target/README.md | 17 +- templates/target/app/CMakeLists.txt | 5 +- templates/target/app/main.c | 7 +- templates/target/lib/bsp/src/bsp_console.c | 37 +++ 26 files changed, 734 insertions(+), 161 deletions(-) rename {targets/STMicroelectronics/NUCLEO_F401RE/app/starter => apps/threadx_demo}/main.c (81%) create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/polarfire_console.h create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_threadx_demo.resc create mode 100644 targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_threadx_demo_ci.resc mode change 100644 => 100755 targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py delete mode 100644 targets/STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 721cdc2e..f883765e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,20 +61,26 @@ jobs: - name: Report the toolchain version run: riscv-none-elf-gcc --version - - name: Build SampleX PolarFire Condition-Monitoring Demo + - name: Build SampleX PolarFire Executables run: | bash targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/build.sh --rebuild - - name: Verify SampleX Demo ELF + - name: Verify Both PolarFire ELFs run: | + # Two executables: the board's own LM75 demo, and the shared portable + # demo from apps/threadx_demo that the NUCLEO-F401RE builds from the + # very same source. test -f targets/Microchip/POLARFIRE_ICICLE_RENODE/build/app/polarfire_icicle_demo.elf - echo "[OK] PolarFire SampleX demo ELF verified." + test -f targets/Microchip/POLARFIRE_ICICLE_RENODE/build/app/polarfire_threadx_demo.elf + echo "[OK] PolarFire LM75 and shared ThreadX demo ELFs verified." - - name: Archive Built PolarFire ELF + - name: Archive Built PolarFire ELFs uses: actions/upload-artifact@v4 with: name: polarfire-demo-elf - path: targets/Microchip/POLARFIRE_ICICLE_RENODE/build/app/polarfire_icicle_demo.elf + path: | + targets/Microchip/POLARFIRE_ICICLE_RENODE/build/app/polarfire_icicle_demo.elf + targets/Microchip/POLARFIRE_ICICLE_RENODE/build/app/polarfire_threadx_demo.elf retention-days: 1 test-polarfire-renode: @@ -98,7 +104,7 @@ jobs: with: python-version: "3.11" - - name: Download Built PolarFire ELF + - name: Download Built PolarFire ELFs uses: actions/download-artifact@v4 with: name: polarfire-demo-elf @@ -125,9 +131,17 @@ jobs: - name: Put Renode on PATH run: echo "$HOME/renode" >> $GITHUB_PATH - - name: Run Deterministic Headless Renode Test + - name: Run Deterministic Headless Renode Test (LM75 demo) + run: | + python3 targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py --app lm75 + + # The other half of the portability claim. apps/threadx_demo/main.c is + # asserted here on 64-bit RISC-V and in test-nucleo-renode on 32-bit + # Cortex-M4, against the same console output from the same source file. + # A claim only one architecture verifies is not a claim. + - name: Run Deterministic Headless Renode Test (shared ThreadX demo) run: | - python3 targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py + python3 targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py --app threadx_demo build-arm-nucleo: name: Build ST Nucleo-F401RE (ARM Cortex-M4) @@ -181,6 +195,8 @@ jobs: - name: Report the toolchain version run: ${{ env.GCC_TARGET }}-gcc --version + # Builds apps/threadx_demo/main.c, the same application source the + # PolarFire SoC Icicle Kit job builds for 64-bit RISC-V. - name: Build NUCLEO-F401RE Demo run: | bash targets/STMicroelectronics/NUCLEO_F401RE/scripts/build.sh --rebuild diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c b/apps/threadx_demo/main.c similarity index 81% rename from targets/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c rename to apps/threadx_demo/main.c index 401e04de..c1541f7e 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/app/starter/main.c +++ b/apps/threadx_demo/main.c @@ -1,16 +1,42 @@ -/* +/*************************************************************************** * 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/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* + * Eclipse ThreadX device monitor demo - shared across every target. * - * 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. + * This application depends on nothing but the C standard library, + * and the board contracts in , so the same source builds for any + * target that implements them. It is built today for the ST NUCLEO-F401RE + * (32-bit Cortex-M4) and the Microchip PolarFire SoC Icicle Kit (64-bit + * RISC-V), and CI runs it under Renode on both: a portability claim only one + * architecture verifies is not a claim. * - * SPDX-License-Identifier: MIT + * Nothing here may name a board symbol, a vendor header or a linker-defined + * address. The two things a demo used to need those for are answered by + * contracts instead - sizes the byte pool, and + * runs the board's startup checks - and anything else a + * future demo needs belongs behind a new contract in bsp/include/bsp/, not an + * #ifdef here. + * + * A board-specific demo is still legitimate; it just lives with its board, + * under targets///app/. A target's app/CMakeLists.txt picks + * either. */ -// Some portions generated by Claude Code (Opus 5) - #include +#include #include #include "tx_api.h" @@ -19,7 +45,13 @@ #include "bsp/memory.h" #include "bsp/selftest.h" -#define THREAD_STACK_SIZE 1024 +/* Thread stacks are sized in machine words rather than in bytes. Every saved + * register, return address and spilled pointer doubles in width between the + * 32-bit Cortex-M4 and the 64-bit RISC-V hart this demo runs on, and so does + * the newlib printf() call chain each of these threads reaches. The reporter + * thread's measured peak is printed in the status table below, which is where + * to look before changing this. */ +#define THREAD_STACK_SIZE ((ULONG)(256U * sizeof(void *))) typedef struct { CHAR *name; @@ -171,8 +203,13 @@ static void monitor_thread_entry(ULONG parameter) { } stack_lowest++; } + /* MISRA C:2012 Rule 11.4 deviation: the distance between two + * stack addresses is only expressible by converting them to an + * integer type. uintptr_t is the width-correct one on both a + * 32-bit and a 64-bit target. */ ULONG unused = - (ULONG)stack_lowest - (ULONG)thread->tx_thread_stack_start; + (ULONG)((uintptr_t)stack_lowest - + (uintptr_t)thread->tx_thread_stack_start); system_stats.threads[i].stack_used = thread->tx_thread_stack_size - unused; system_stats.threads[i].stack_size = thread->tx_thread_stack_size; @@ -185,13 +222,21 @@ static void monitor_thread_entry(ULONG parameter) { } } -/* Reporter Thread: Consumer/Printer of statistics */ +/* Reporter Thread: Consumer/Printer of statistics + * + * Every ULONG reaching printf() is cast to unsigned long, because ULONG is not + * the same type on every port: the Cortex-M4 port defines it as unsigned long + * and the RISC-V 64 port as unsigned int. A bare %lu is therefore wrong on one + * of the two targets this file builds for, and the cast is what makes one + * format string correct on both. */ static void reporter_thread_entry(ULONG parameter) { (void)parameter; + /* Deliberately names no board: this same source runs on every target, and + * both Renode suites assert on this line. Any third-party licensing notice + * belongs with the target that carries the third-party code, not here. */ printf("\r\n==========================================\r\n"); - printf("NUCLEO-F401RE Device Monitor Demo\r\n"); - printf("Third-party licensing info in NOTICE.md\r\n"); + printf("Eclipse ThreadX Device Monitor Demo\r\n"); printf("==========================================\r\n"); while (1) { @@ -199,10 +244,13 @@ static void reporter_thread_entry(ULONG parameter) { printf("\r\nSystem Status:\r\n"); printf("------------------------------------------\r\n"); - printf("Uptime: %lu s\r\n", system_stats.uptime); - printf("Byte Pool Size: %lu bytes\r\n", system_stats.byte_pool_total); - printf("Allocated Memory: %lu bytes\r\n", system_stats.byte_pool_used); - printf("Free Memory: %lu bytes\r\n", system_stats.byte_pool_free); + printf("Uptime: %lu s\r\n", (unsigned long)system_stats.uptime); + printf("Byte Pool Size: %lu bytes\r\n", + (unsigned long)system_stats.byte_pool_total); + printf("Allocated Memory: %lu bytes\r\n", + (unsigned long)system_stats.byte_pool_used); + printf("Free Memory: %lu bytes\r\n", + (unsigned long)system_stats.byte_pool_free); printf("------------------------------------------\r\n"); printf("\r\n%-16s %-8s %-10s %-12s %-22s\r\n", "Thread Name", "Priority", @@ -219,18 +267,23 @@ static void reporter_thread_entry(ULONG parameter) { printf("%-16s %-8u %-10s %-12lu %4lu / %4lu bytes (%lu%%)\r\n", system_stats.threads[i].name, system_stats.threads[i].priority, get_state_string(system_stats.threads[i].state), - system_stats.threads[i].run_count, - system_stats.threads[i].stack_used, - system_stats.threads[i].stack_size, pct); + (unsigned long)system_stats.threads[i].run_count, + (unsigned long)system_stats.threads[i].stack_used, + (unsigned long)system_stats.threads[i].stack_size, + (unsigned long)pct); } } printf("-------------------------------------------------------------------" "---------\r\n"); printf("Runs: Monitor: %lu | Reporter: %lu | Blink: %lu | Timer Wakes: %lu\r\n", - monitor_counter, reporter_counter, blink_counter, timer_counter); + (unsigned long)monitor_counter, (unsigned long)reporter_counter, + (unsigned long)blink_counter, (unsigned long)timer_counter); printf("RTOS Showcase: Mutex Locks: %lu/%lu | Queue Msgs: %lu | Event Wakes: %lu | Sema Wakes: %lu\r\n", - mutex_acquires_1, mutex_acquires_2, queue_msgs_received, event_flags_processed, semaphore_wakes); + (unsigned long)mutex_acquires_1, (unsigned long)mutex_acquires_2, + (unsigned long)queue_msgs_received, + (unsigned long)event_flags_processed, + (unsigned long)semaphore_wakes); tx_thread_sleep(TX_TIMER_TICKS_PER_SECOND * 2); /* Report every 2 seconds */ } diff --git a/bsp/include/bsp/console.h b/bsp/include/bsp/console.h index 46d52324..442022bb 100644 --- a/bsp/include/bsp/console.h +++ b/bsp/include/bsp/console.h @@ -8,6 +8,8 @@ * SPDX-License-Identifier: MIT */ +// Some portions generated by Claude Code (Opus 5) + #ifndef BSP_CONSOLE_H #define BSP_CONSOLE_H @@ -26,4 +28,35 @@ void bsp_console_init(void); */ void bsp_console_write(const char *data, size_t length); +/** + * @brief Receives one byte that arrived on the console. + * + * Invoked from interrupt context on boards that drive their console receiver + * from an interrupt, so it must not block, allocate, or call any ThreadX + * service that is illegal from an ISR. + * + * @param c The byte that arrived. + * @param context The context pointer that was handed to + * bsp_console_set_rx_handler(). + */ +typedef void (*bsp_console_rx_fn)(char c, void *context); + +/** + * @brief Registers the handler invoked for each byte the console receives. + * + * A board that raises an interrupt per received byte must route it here rather + * than to a symbol the application is required to define: an application that + * does not care about console input should not have to define anything to + * link. Bytes that arrive with no handler attached are dropped. + * + * Boards whose console has no receive-interrupt path still implement this + * call; the handler they store is simply never invoked. An application can + * therefore register unconditionally. + * + * @param handler Handler to invoke per received byte. Passing NULL detaches + * the current handler. + * @param context Opaque pointer passed back to @p handler unmodified. + */ +void bsp_console_set_rx_handler(bsp_console_rx_fn handler, void *context); + #endif /* BSP_CONSOLE_H */ diff --git a/docs/architecture.md b/docs/architecture.md index 5bfa785b..83d5f6af 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -9,8 +9,9 @@ This document describes the architecture, design philosophy, directory structure The BSP framework is designed to be **additive and non-invasive**, allowing new boards to be integrated without modifying existing board implementations. 1. **Legacy Isolation**: The board directories that predate this framework (`/MXChip`, `/OpenHW`, `/STMicroelectronics`) remain completely untouched, preserving their drivers, submodules, and build systems. -2. **Hardware Access Through the BSP**: Application logic reaches LEDs, the console, the board's RAM budget and its startup self-tests through the abstract interfaces in `/bsp`, not through vendor registers. Both shipped demos now include only `` and `` headers. Applications are still target-resident, though: each target owns its demo under `app/`, and there is no shared application directory to link one from. A fully portable shared application layer is a goal of the framework, not a property it has yet. -3. **Independent Build Configuration**: Each target carries its own `cmake/` toolchain files and build helpers. Nothing in the build is shared between targets, so changing one board cannot break another. +2. **Hardware Access Through the BSP**: Application logic reaches LEDs, the console, the board's RAM budget and its startup self-tests through the abstract interfaces in `/bsp`, not through vendor registers. Every shipped demo includes only C standard headers, `` and ``. +3. **A Shared Application Layer**: `apps/` holds portable demos; `targets///app/` holds board-specific ones. Both are legitimate, and a target's `app/CMakeLists.txt` picks either. `apps/threadx_demo/main.c` is built by both shipped targets from one source file, and CI runs it under Renode on 32-bit Cortex-M4 and 64-bit RISC-V, asserting on the same console output in both. Portability here is a property CI enforces, not a stated goal: a claim only one architecture verifies is not a claim. +4. **Independent Build Configuration**: Each target carries its own `cmake/` toolchain files and build helpers. Nothing in the build is shared between targets, so changing one board cannot break another. --- @@ -23,6 +24,8 @@ samplex/ (repository root) ├── MXChip/ # [Pre-framework] Standalone board sample ├── OpenHW/ # [Pre-framework] Standalone board sample ├── STMicroelectronics/ # [Pre-framework] Standalone board samples +├── apps/ # [Framework] Portable applications, built by any target +│ └── threadx_demo/ # Device monitor demo; built for Cortex-M4 and RISC-V ├── targets/ # [Framework] Supported BSP target boards │ ├── Microchip/ │ │ └── POLARFIRE_ICICLE_RENODE/ # Board-specific BSP implementation & Renode target @@ -55,6 +58,11 @@ Every board added to the framework under `/targets` must implement the abstract * `void bsp_console_init(void)`: Initializes the default UART console. * `void bsp_console_write(const char *data, size_t length)`: Transmits a block of data over the console interface. +* `void bsp_console_set_rx_handler(bsp_console_rx_fn handler, void *context)`: Registers the handler invoked, from interrupt context, for each byte the console receives. Passing `NULL` detaches it. + +A board that raises an interrupt per received byte must route it through this registration rather than to a symbol the application is required to define. The PolarFire SoC Icicle Kit is why: its trap handler called a fixed `console_rx_isr_callback()` that only its own demo defined, so any second executable linking that BSP failed to link, and a portable application would have had to define a PolarFire-specific ISR callback to say it wanted nothing. That is the same violation this framework exists to remove - the BSP reaching up into the application - simply expressed through the linker instead of through a header. + +The handler is nullable and the board checks it before dispatching, so bytes that arrive with no handler attached are dropped rather than faulting. A board whose console has no receive-interrupt path still implements the call and stores what it is given; the NUCLEO-F401RE polls USART2, so the handler it stores is never invoked. That uniformity is what lets an application register unconditionally without asking which boards have wired an interrupt. ### Application RAM Budget (`memory.h`) @@ -81,4 +89,6 @@ The application supplies only the reporting callback, so message formatting - an 3. **Implement the BSP APIs**: Implement the interfaces defined in `/bsp/include/bsp/` using the vendor SDK or direct register access. 4. **Configure CMake**: Add the board target to `CMakeLists.txt`, supply the target's toolchain file under its own `cmake/`, build the BSP as a static library, and link it with the application in the target's `app/` directory. -Start from `templates/target/app/main.c`, which depends only on `` and the `` contracts and therefore builds on any target that implements them. Grow it in place as the board needs; there is no shared `/apps` directory to link an application from. +A new board has two ways to get an application. Point its `app/CMakeLists.txt` at `apps/threadx_demo/main.c` to build the shared portable demo, which is the fastest way to prove a fresh BSP implementation is complete and correct - it exercises `board.h`, `led.h`, `memory.h` and `selftest.h`, and it is already known to run on two architectures, so a failure is a finding about the new board rather than about the demo. Or start from `templates/target/app/main.c` and grow a board-specific application in place, which is what the PolarFire SoC Icicle Kit does with its LM75 monitor because that demo genuinely models a sensor. + +The rule for which directory a demo belongs in is what it names: an application that names no board symbol, vendor header or linker-defined address belongs in `apps/`, and one that does belongs with its board under `targets///app/`. diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/README.md b/targets/Microchip/POLARFIRE_ICICLE_RENODE/README.md index b2f5fb49..fefb6ff5 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/README.md +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/README.md @@ -1,6 +1,13 @@ # Microchip PolarFire SoC Icicle Kit Target Integration (Renode 64-Bit RISC-V) -This directory contains the target Board Support Package (BSP) and condition-monitoring demonstration application for the **Microchip PolarFire SoC Icicle Kit** running in the **Renode** emulation environment. +This directory contains the target Board Support Package (BSP) for the **Microchip PolarFire SoC Icicle Kit** running in the **Renode** emulation environment, and it builds **two executables** against that one BSP: + +| Executable | Application source | Why it lives there | +|---|---|---| +| `polarfire_icicle_demo.elf` | `app/main.c` | The board's own LM75 condition-monitoring demo. It models a sensor and drives the MMUART1 receive interrupt, so it is board specific and stays with the board. | +| `polarfire_threadx_demo.elf` | `apps/threadx_demo/main.c` | The shared portable demo, byte for byte the same source `targets/STMicroelectronics/NUCLEO_F401RE` builds for 32-bit Cortex-M4. Building it here is what makes the framework's portability claim something CI verifies on a second architecture rather than something the documentation asserts. | + +Both are exercised by their own headless Renode suite, and CI runs both. --- @@ -13,7 +20,7 @@ This directory contains the target Board Support Package (BSP) and condition-mon * **System DRAM**: 1 GiB LPDDR4 Memory (`0x80000000` – `0xC0000000`) * **Machine Timer**: SiFive CLINT `mtime` running at 1 MHz (`0x02000000`, 10ms tick = 10,000 cycles) * **Serial Debug Console**: Microchip MMUART1 (`0x20100000`) at 115200 baud (8-N-1) -* **Telemetry**: Simulated LM75 temperature data processed via ThreadX queues and event flags +* **Telemetry**: Simulated LM75 temperature data processed via ThreadX queues and event flags (LM75 demo only) --- @@ -38,34 +45,57 @@ bash targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/build.sh --rebuild ## 3. Renode Execution & Verification ### Interactive Simulation (GUI / Terminal Analyzers): -Inside the Renode monitor: +Inside the Renode monitor, pick the executable to watch free-run: ```renode include @targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_demo.resc +include @targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_threadx_demo.resc ``` -This free-runs the machine so the telemetry stream can be watched live. ### Automated Headless Test Runner: +One runner drives both suites; `--app` selects which executable to verify. ```bash -python targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py +python targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py --app lm75 # default +python targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py --app threadx_demo ``` -The runner drives `renode/polarfire_ci.resc`, which steps through fixed -virtual-time intervals rather than free-running, injects a byte into MMUART1 to -exercise the PLIC external-interrupt path, and quits on its own. It asserts on -four things and exits non-zero if any of them is missing: +Both step through fixed virtual-time intervals rather than free-running and +quit on their own, and both exit non-zero if any assertion is missing. They +share every line of Renode process handling, which is the reason they are one +script: the plumbing is what would drift if it were copied. + +**`--app lm75`** drives `renode/polarfire_ci.resc`, which also injects a byte +into MMUART1 to exercise the PLIC external-interrupt path: | Assertion | Covers | |---|---| | Startup self-tests all passed | `_sbrk()` bounds against the heap reservation, the `bsp_ram_region()` invariant, timer catch-up, PLIC configuration | | ThreadX system tick advancing | CLINT machine timer and `_tx_timer_interrupt` | | LM75 overtemperature alarm | Queue, event flags, and the analyzer thread | -| PLIC IRQ 91 RX interrupt delivered | MMUART1 -> PLIC -> Hart 1 machine-mode trap path | +| PLIC IRQ 91 RX interrupt delivered | MMUART1 -> PLIC -> Hart 1 machine-mode trap path, and the handler registered through `bsp_console_set_rx_handler()` | The last of these is the only check that proves the PLIC is programmed for the right context. Reading the controller's registers back cannot: the machine-mode context (1) and the supervisor-mode context (2) for Hart 1 both accept the writes and read back identically, but only the former ever raises `MEIP`. -### Expected Output Stream (`mmuart1` @ 115200 baud): +**`--app threadx_demo`** drives `renode/polarfire_threadx_demo_ci.resc`. Its +four assertions are deliberately the same ones +`targets/STMicroelectronics/NUCLEO_F401RE/scripts/test_renode.py` makes, so the +two runs compare one source file built for two architectures: + +| Assertion | Covers | +|---|---| +| Boot banner reached the console | `bsp_console_write()` through `printf()`, and a banner that names no board | +| Startup self-tests all passed | The same BSP checks as above, reached through the portable `` callback | +| LED blink thread and application timer ran | `bsp_led_toggle()` and the ThreadX application timer | +| Mutex, queue, event flag and semaphore all exercised | The RTOS primitives, sized out of the pool `bsp_ram_region()` reports | + +The shared demo prints through `printf()` where the LM75 demo calls +`bsp_console_write()` directly, so it is the first executable on this board to +pull in newlib stdio. Measured heap use is **2944 bytes** of the 64 KB +`BSP_HEAP_RESERVE_BYTES`, and the whole run completes with the reservation +temporarily cut to 4 KB, so the reservation holds with room to spare. + +### Expected Output Stream, `--app lm75` (`mmuart1` @ 115200 baud): ```text ==================================================== Microchip PolarFire SoC Icicle Kit (Renode Target) @@ -86,3 +116,35 @@ Microchip PolarFire SoC Icicle Kit (Renode Target) [Monitor] Ticks: 200 | Active Runs: Sampler=5, Analyzer=5, Reporter=3 [LM75 Sensor] Temperature: OVERTEMP ALARM TRIGGERED (>45.0C) ``` + +### Expected Output Stream, `--app threadx_demo`: +```text +========================================== +Eclipse ThreadX Device Monitor Demo +========================================== + +System Status: +------------------------------------------ +Uptime: 4 s +Byte Pool Size: 1073585120 bytes +Allocated Memory: 18896 bytes +Free Memory: 1073566224 bytes +------------------------------------------ + +Thread Name Priority State Run Count Stack Peak (Max / Size) +---------------------------------------------------------------------------- +monitor thread 9 READY 41 536 / 2048 bytes (26%) +reporter thread 10 READY 2 1048 / 2048 bytes (51%) +blink thread 11 READY 8 536 / 2048 bytes (26%) +... +---------------------------------------------------------------------------- +Runs: Monitor: 41 | Reporter: 3 | Blink: 8 | Timer Wakes: 4 +RTOS Showcase: Mutex Locks: 40/40 | Queue Msgs: 20 | Event Wakes: 8 | Sema Wakes: 8 +``` + +Thread stacks are 2048 bytes here and 1024 on the NUCLEO-F401RE from the one +`THREAD_STACK_SIZE` expression, which is written in machine words rather than +bytes: every saved register and spilled pointer doubles in width on a 64-bit +hart, as does the newlib `printf()` call chain. The byte pool spans the whole +region `bsp_ram_region()` reports, which on this board is the DRAM above the +heap reservation - roughly 1 GiB. diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/CMakeLists.txt b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/CMakeLists.txt index 64605b99..6f36200a 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/CMakeLists.txt +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/CMakeLists.txt @@ -32,31 +32,55 @@ target_include_directories(threadx ) # ------------------------------------------------------------- -# PolarFire SoC Icicle Kit Telemetry Executable +# Executables +# +# This target builds two. Both link the same BSP, the same startup assembly +# and the same newlib retargeting; they differ only in which application +# source they compile. +# +# polarfire_icicle_demo - the board's own LM75 condition-monitoring demo, +# in app/main.c. It models a sensor and drives the +# MMUART1 receive interrupt, so it stays here with +# the board. +# polarfire_threadx_demo - the shared portable demo from apps/threadx_demo/, +# the same source the NUCLEO-F401RE builds. Nothing +# about it is RISC-V specific; building it here is +# what turns the framework's portability claim into +# something CI verifies on a second architecture. # ------------------------------------------------------------- -add_executable(polarfire_icicle_demo - main.c - common/startup/entry.S - common/startup/newlib_stubs.c -) +function(polarfire_add_app TARGET_NAME APP_SOURCE) + add_executable(${TARGET_NAME} + ${APP_SOURCE} + ${CMAKE_CURRENT_SOURCE_DIR}/common/startup/entry.S + ${CMAKE_CURRENT_SOURCE_DIR}/common/startup/newlib_stubs.c + ) -set_target_properties(polarfire_icicle_demo PROPERTIES SUFFIX ".elf") + set_target_properties(${TARGET_NAME} PROPERTIES SUFFIX ".elf") -target_include_directories(polarfire_icicle_demo - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/../lib/bsp/include - ${SAMPLEX_ROOT_DIR}/bsp/include -) + # board_config.h is on this path for newlib_stubs.c, which bounds _sbrk() + # against the board's heap reservation. The shared application never + # includes it - and cannot, since it also has to compile for Cortex-M4. + target_include_directories(${TARGET_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/../lib/bsp/include + ${SAMPLEX_ROOT_DIR}/bsp/include + ) + target_link_libraries(${TARGET_NAME} + PRIVATE + -Wl,--start-group + polarfire_bsp + threadx + -Wl,--end-group + ) +endfunction() + +polarfire_add_app(polarfire_icicle_demo ${CMAKE_CURRENT_SOURCE_DIR}/main.c) +polarfire_add_app(polarfire_threadx_demo ${SAMPLEX_ROOT_DIR}/apps/threadx_demo/main.c) + +# Applies to the LM75 demo only: it is the executable with the deliberate +# illegal instruction that exercises trap_handler(). option(ENABLE_FAULT_INJECTION "Enable deliberate synchronous fault injection for trap handler testing" OFF) if(ENABLE_FAULT_INJECTION) target_compile_definitions(polarfire_icicle_demo PRIVATE TEST_FAULT_INJECTION=1) endif() - -target_link_libraries(polarfire_icicle_demo - PRIVATE - -Wl,--start-group - polarfire_bsp - threadx - -Wl,--end-group -) diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/main.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/main.c index 9ca5e605..e4a4c150 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/main.c +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/main.c @@ -55,7 +55,12 @@ volatile char g_last_rx_char = 0; volatile uint32_t g_rx_irq_count = 0; volatile uint32_t g_rx_flag_errors = 0; -void console_rx_isr_callback(char c) { +/* Registered with bsp_console_set_rx_handler() in main(), and invoked from the + * MMUART1 trap path. The BSP no longer requires this application to define a + * fixed symbol, so an application that ignores console input links unchanged. */ +static void console_rx_handler(char c, void *context) { + (void)context; + g_last_rx_char = c; g_rx_irq_count++; if (tx_event_flags_set(&alarm_flags, EVENT_FLAG_UART_RX, TX_OR) != TX_SUCCESS) { @@ -116,6 +121,11 @@ int main(void) { /* Initialize Board Peripherals & MMUART1 */ bsp_board_init(); + /* Attach the console receiver before any byte can arrive. Bytes that + * arrive with no handler attached are dropped rather than lost to a link + * error, which is what lets the shared demo link the same BSP. */ + bsp_console_set_rx_handler(console_rx_handler, NULL); + console_print("\n====================================================\n"); console_print("Microchip PolarFire SoC Icicle Kit (Renode Target)\n"); console_print("64-Bit RISC-V Industrial LM75 Condition-Monitoring App\n"); diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/polarfire_console.h b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/polarfire_console.h new file mode 100644 index 00000000..62064b30 --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/polarfire_console.h @@ -0,0 +1,36 @@ +/*************************************************************************** + * 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/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +#ifndef POLARFIRE_CONSOLE_H +#define POLARFIRE_CONSOLE_H + +/* + * Board-private console plumbing. This header is internal to the PolarFire + * BSP: it lives beside the driver rather than in bsp/include/bsp/ because no + * application should reach for it. + */ + +/** + * @brief Hands one received byte to the registered bsp/console.h RX handler. + * + * Called by trap_handler() from machine-mode interrupt context once MMUART1 + * has raised its PLIC source. Drops the byte when no handler is attached, so + * the trap path never depends on a symbol the application must define. + * + * @param c The byte read out of the MMUART1 receive holding register. + */ +void polarfire_console_rx_dispatch(char c); + +#endif /* POLARFIRE_CONSOLE_H */ diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_console.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_console.c index 4695e21b..f915a7af 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_console.c +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_console.c @@ -8,13 +8,24 @@ * SPDX-License-Identifier: MIT */ +// Some portions generated by Claude Code (Opus 5) + #include "bsp/console.h" #include "board_config.h" +#include "polarfire_console.h" #include extern void uart_init(void); extern void uart_write(const char *data, size_t len); +/* Receive handler registered through bsp_console_set_rx_handler(). Written + * from thread context and read from the MMUART1 trap path, so both are + * volatile: the compiler must not cache either across the store. A single + * aligned pointer store is atomic on RV64, so no further guard is needed for + * attaching or detaching. */ +static bsp_console_rx_fn volatile s_rx_handler = NULL; +static void *volatile s_rx_context = NULL; + void bsp_console_init(void) { #if BSP_HAS_CONSOLE uart_init(); @@ -27,3 +38,19 @@ void bsp_console_write(const char *data, size_t length) { uart_write(data, length); #endif } + +void bsp_console_set_rx_handler(bsp_console_rx_fn handler, void *context) { + /* Publish the context first: the trap path reads the handler to decide + * whether to dispatch at all, so a handler that is visible must already + * have its context beside it. */ + s_rx_context = context; + s_rx_handler = handler; +} + +void polarfire_console_rx_dispatch(char c) { + bsp_console_rx_fn handler = s_rx_handler; + + if (handler != NULL) { + handler(c, s_rx_context); + } +} diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_selftest.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_selftest.c index e329fcc2..817d1421 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_selftest.c +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_selftest.c @@ -70,6 +70,7 @@ unsigned bsp_self_test(bsp_selftest_report_fn report, void *context) void *p_under; void *p_over; void *p_past_heap; + ptrdiff_t heap_taken; uint64_t now; uint64_t missed_cmp; uint64_t pending_cmp; @@ -93,9 +94,17 @@ unsigned bsp_self_test(bsp_selftest_report_fn report, void *context) check(&state, (p1 != (void *)-1) && ((uintptr_t)p1 >= BSP_HEAP_BASE), "_sbrk() valid allocation returned base pointer"); - /* 2. _sbrk() underflow test (shrink below the heap base). */ + /* 2. _sbrk() underflow test (shrink below the heap base). + * + * The decrement is derived from the live break rather than fixed. An + * application that reached printf() before this point already carries a + * newlib stdio buffer on the heap, so a fixed -128 would be an ordinary + * shrink rather than an underflow, and this check would pass or fail on + * which application happened to link the BSP. Handing back one byte more + * than has ever been taken underflows no matter what ran first. */ errno = 0; - p_under = _sbrk(-128); + heap_taken = (ptrdiff_t)((uintptr_t)_sbrk(0) - BSP_HEAP_BASE); + p_under = _sbrk(-(heap_taken + 1)); check(&state, (p_under == (void *)-1) && (errno == EINVAL), "_sbrk() underflow guard rejected with EINVAL"); diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/trap.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/trap.c index 00795f5a..71c283e3 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/trap.c +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/trap.c @@ -8,13 +8,15 @@ * SPDX-License-Identifier: MIT */ +// Some portions generated by Claude Code (Opus 5) + #include #include "hwtimer.h" #include "plic.h" +#include "polarfire_console.h" #include "uart.h" extern void _tx_timer_interrupt(void); -extern void console_rx_isr_callback(char c); static void print_hex64(uint64_t val) { const char hex_chars[] = "0123456789ABCDEF"; @@ -43,7 +45,7 @@ void trap_handler(uint64_t mcause, uint64_t mepc, uint64_t mtval) { if (source == MMUART1_IRQ) { while (uart_has_rx()) { char c = uart_getc(); - console_rx_isr_callback(c); + polarfire_console_rx_dispatch(c); } } plic_complete(source); diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_threadx_demo.resc b/targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_threadx_demo.resc new file mode 100644 index 00000000..fe55262f --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_threadx_demo.resc @@ -0,0 +1,32 @@ +:name: PolarFire SoC - shared Eclipse ThreadX Device Monitor Demo +:description: apps/threadx_demo on Microchip PolarFire SoC (Renode 64-Bit RISC-V) + +# Interactive counterpart to polarfire_threadx_demo_ci.resc: this one free-runs +# so the status table can be watched live. It loads the shared portable demo, +# the same source targets/STMicroelectronics/NUCLEO_F401RE builds. + +Clear + +using sysbus +mach create "PolarFire_SoC_Icicle" +machine LoadPlatformDescription @platforms/cpus/polarfire-soc.repl + +# Show terminal analyzer for Hart 1 (u54_1) MMUART1 at 0x20100000 +showAnalyzer mmuart1 + +# Portable relative path using Renode's built-in $ORIGIN variable +$bin?=$ORIGIN/../build/app/polarfire_threadx_demo.elf + +macro reset +""" + sysbus LoadELF $bin + # Route execution directly to Hart 1 (U54 Core 1) + u54_1 PC `e51 PC` + e51 IsHalted true + u54_2 IsHalted true + u54_3 IsHalted true + u54_4 IsHalted true +""" +runMacro $reset + +start diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_threadx_demo_ci.resc b/targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_threadx_demo_ci.resc new file mode 100644 index 00000000..70cb964e --- /dev/null +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/renode/polarfire_threadx_demo_ci.resc @@ -0,0 +1,38 @@ +:name: PolarFire SoC - shared Eclipse ThreadX demo (headless CI run) +:description: Deterministic virtual-time run of apps/threadx_demo, driven by scripts/test_renode.py --app threadx_demo. + +# Counterpart to polarfire_ci.resc for the second executable this target +# builds. The two differ only in which ELF they load and how long they run: +# the shared demo has no MMUART1 receive path to exercise, so there is no +# WriteChar step here, and its reporter thread prints every two seconds rather +# than every one. + +Clear + +using sysbus +mach create "PolarFire_SoC_Icicle" +machine LoadPlatformDescription @platforms/cpus/polarfire-soc.repl + +# Under --plain --disable-gui this logs MMUART1 traffic to stdout, which is +# what the assertions in test_renode.py read. +showAnalyzer mmuart1 + +$bin?=$ORIGIN/../build/app/polarfire_threadx_demo.elf + +macro reset +""" + sysbus LoadELF $bin + # Route execution directly to Hart 1 (U54 Core 1) + u54_1 PC `e51 PC` + e51 IsHalted true + u54_2 IsHalted true + u54_3 IsHalted true + u54_4 IsHalted true +""" +runMacro $reset + +# Long enough for the startup self-tests, the 1 Hz application timer, and at +# least two reporter-thread status blocks with non-zero RTOS counters. +emulation RunFor "5" + +quit diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py b/targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py old mode 100644 new mode 100755 index c9731e9b..ba3566bc --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py @@ -10,28 +10,153 @@ # """ -Headless Renode Verification Test for PolarFire SoC Icicle Kit ThreadX Demo +Headless Renode verification tests for the PolarFire SoC Icicle Kit. + +This target builds two executables, so this runner drives two suites: + + --app lm75 the board's own LM75 condition-monitoring demo + (app/main.c), which is the default + --app threadx_demo the shared portable demo (apps/threadx_demo/main.c), + the same source the NUCLEO-F401RE builds + +They share every line of Renode process handling below and differ only in +which .resc they load and what they assert on, which is why they are one +script rather than two: the plumbing is what would drift if it were copied. """ +import argparse import os -import sys -import time -import subprocess +import re import shutil +import subprocess +import sys import threading import queue +import time + + +class Assertions(object): + """Consumes console lines and tracks which named checks have been met.""" + + def __init__(self, names): + self._met = dict((name, False) for name in names) + + def mark(self, name): + self._met[name] = True + + def is_met(self, name): + return self._met[name] + + def satisfied(self): + return all(self._met.values()) + + def unmet(self): + return [name for name, ok in self._met.items() if not ok] + + +class Lm75Suite(object): + """The board's own demo: sensor pipeline plus the MMUART1 receive path.""" + + resc = "polarfire_ci.resc" + # The .resc injects this byte into MMUART1 itself; Renode's monitor is not + # on stdin, so the injection has to happen there rather than here. + description = "LM75 condition-monitoring demo (app/main.c)" + timeout_seconds = 120.0 + + NAMES = ( + "startup self-tests passed", + "ThreadX system tick advancing", + "LM75 overtemperature alarm", + "PLIC IRQ 91 RX interrupt delivered", + ) + + def __init__(self): + self.checks = Assertions(self.NAMES) + self.failed_selftest = False + + def feed(self, line): + if "[-] FAIL:" in line or "startup verification test(s) FAILED" in line: + self.failed_selftest = True + if "[SELF-TEST] All startup verification tests PASSED!" in line: + self.checks.mark("startup self-tests passed") + if "Ticks:" in line: + self.checks.mark("ThreadX system tick advancing") + if "OVERTEMP ALARM TRIGGERED" in line: + self.checks.mark("LM75 overtemperature alarm") + # The only check that proves the PLIC is programmed for the machine-mode + # context: reading its registers back cannot distinguish that from the + # supervisor one. It now also proves bsp_console_set_rx_handler() took + # effect, since the trap path dispatches through the registered handler. + if "PLIC IRQ 91 handled" in line: + self.checks.mark("PLIC IRQ 91 RX interrupt delivered") + + def success_message(self): + return ("startup self-tests, ThreadX ticks, LM75 alarm, and PLIC RX " + "interrupt all verified!") + + +class ThreadxDemoSuite(object): + """The shared portable demo, asserted here exactly as it is on Cortex-M4.""" + + resc = "polarfire_threadx_demo_ci.resc" + description = "shared portable demo (apps/threadx_demo/main.c)" + timeout_seconds = 600.0 + + # The reporter thread prints these once the RTOS primitives have run. + RUNS_RE = re.compile( + r"Runs: Monitor: (\d+) \| Reporter: (\d+) \| Blink: (\d+) \| Timer Wakes: (\d+)") + RTOS_RE = re.compile( + r"Mutex Locks: (\d+)/(\d+) \| Queue Msgs: (\d+) \| Event Wakes: (\d+) \| Sema Wakes: (\d+)") + + NAMES = ( + "boot banner reached the console", + "startup self-tests passed", + "LED blink thread and application timer ran", + "mutex, queue, event flag and semaphore all exercised", + ) + + def __init__(self): + self.checks = Assertions(self.NAMES) + self.failed_selftest = False + + def feed(self, line): + # Deliberately board-neutral: the identical assertion runs against the + # Cortex-M4 build of this same source. + if "Eclipse ThreadX Device Monitor Demo" in line: + self.checks.mark("boot banner reached the console") + if "[-] FAIL:" in line or "startup verification test(s) FAILED" in line: + self.failed_selftest = True + if "[SELF-TEST] All startup verification tests PASSED!" in line: + self.checks.mark("startup self-tests passed") + + # The blink thread is the only caller of bsp_led_toggle(), and timer + # wakes come from the 1 Hz ThreadX application timer, so a non-zero + # pair covers the LED path and the timer service. + m = self.RUNS_RE.search(line) + if m and int(m.group(3)) > 0 and int(m.group(4)) > 0: + self.checks.mark("LED blink thread and application timer ran") + + m = self.RTOS_RE.search(line) + if m and all(int(g) > 0 for g in m.groups()): + self.checks.mark("mutex, queue, event flag and semaphore all exercised") + + def success_message(self): + return ("boot banner, startup self-tests, LED and timer activity, and " + "all RTOS primitives verified!") + + +SUITES = { + "lm75": Lm75Suite, + "threadx_demo": ThreadxDemoSuite, +} -# Deterministic virtual-time run script. It injects RX_TEST_CHAR into MMUART1 -# itself; Renode's monitor is not on stdin, so injection has to happen there. -RESC_NAME = "polarfire_ci.resc" -RX_TEST_CHAR = "X" def find_renode(): # Check PATH first renode_bin = shutil.which("renode") if renode_bin: return renode_bin - + # Common Windows locations win_paths = [ r"C:\Program Files\Renode\renode.exe", @@ -40,9 +165,10 @@ def find_renode(): for path in win_paths: if os.path.isfile(path): return path - + return "renode" + def reader_thread_fn(pipe, q): try: for line in iter(pipe.readline, ''): @@ -52,20 +178,23 @@ def reader_thread_fn(pipe, q): finally: pipe.close() -def run_test(test_timeout_mode=False): + +def run_test(app, test_timeout_mode=False): + suite = SUITES[app]() renode = find_renode() script_dir = os.path.dirname(os.path.abspath(__file__)) target_dir = os.path.dirname(script_dir) - resc_path = os.path.join(target_dir, "renode", RESC_NAME).replace("\\", "/") - + resc_path = os.path.join(target_dir, "renode", suite.resc).replace("\\", "/") + if test_timeout_mode: print("[*] Running intentional timeout test mode (2.0s deadline against unresponsive wait)...") timeout_seconds = 2.0 else: print(f"[*] Starting headless Renode test using: {renode}") + print(f"[*] Suite: {suite.description}") print(f"[*] Loading script: {resc_path}") - timeout_seconds = 120.0 - + timeout_seconds = suite.timeout_seconds + cmd = [ renode, "--plain", @@ -73,7 +202,7 @@ def run_test(test_timeout_mode=False): "--port", "-1", "-e", f"include @{resc_path}" ] - + proc = subprocess.Popen( cmd, stdin=subprocess.PIPE, @@ -82,45 +211,27 @@ def run_test(test_timeout_mode=False): text=True, bufsize=1 ) - + output_q = queue.Queue() reader_t = threading.Thread(target=reader_thread_fn, args=(proc.stdout, output_q), daemon=True) reader_t.start() - - output_lines = [] - found_selftests = False - found_selftest_failure = False - found_ticks = False - found_alarm = False - found_plic_rx = False + start_time = time.time() try: while time.time() - start_time < timeout_seconds: try: line = output_q.get(timeout=0.1) - output_lines.append(line) print(line, end="") if test_timeout_mode: continue - if "[-] FAIL:" in line or "startup verification test(s) FAILED" in line: - found_selftest_failure = True - if "[SELF-TEST] All startup verification tests PASSED!" in line: - found_selftests = True - if "Ticks:" in line: - found_ticks = True - if "OVERTEMP ALARM TRIGGERED" in line: - found_alarm = True - if "PLIC IRQ 91 handled" in line: - found_plic_rx = True + suite.feed(line) # A failed self-test is recorded but does not stop the run, so # the remaining assertions are still reported rather than hidden. - if (found_selftests and not found_selftest_failure - and found_ticks and found_alarm and found_plic_rx): - print("\n[+] SUCCESS: startup self-tests, ThreadX ticks, " - "LM75 alarm, and PLIC RX interrupt all verified!") + if suite.checks.satisfied() and not suite.failed_selftest: + print("\n[+] SUCCESS: " + suite.success_message()) break except queue.Empty: if proc.poll() is not None: @@ -128,7 +239,7 @@ def run_test(test_timeout_mode=False): finally: try: proc.terminate() - proc.wait(timeout=2) + proc.wait(timeout=5) except Exception: try: proc.kill() @@ -141,16 +252,12 @@ def run_test(test_timeout_mode=False): f"and terminated child process cleanly.") sys.exit(0) - checks = { - "startup self-tests passed": found_selftests and not found_selftest_failure, - "ThreadX system tick advancing": found_ticks, - "LM75 overtemperature alarm": found_alarm, - "PLIC IRQ 91 RX interrupt delivered": found_plic_rx, - } - failed = [name for name, ok in checks.items() if not ok] + failed = suite.checks.unmet() + if suite.failed_selftest and "startup self-tests passed" not in failed: + failed.append("startup self-tests passed") if not failed: - print("[+] Renode headless test PASSED.") + print(f"[+] Renode headless test PASSED ({suite.description}).") sys.exit(0) print("\n[-] FAILED. Unmet assertions:") @@ -158,6 +265,15 @@ def run_test(test_timeout_mode=False): print(" - %s" % name) sys.exit(1) + if __name__ == "__main__": - timeout_test = "--test-timeout" in sys.argv - run_test(test_timeout_mode=timeout_test) + parser = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument("--app", choices=sorted(SUITES), default="lm75", + help="which of this target's two executables to verify " + "(default: lm75)") + parser.add_argument("--test-timeout", action="store_true", + help="exercise the runner's own deadline and cleanup path") + args = parser.parse_args() + + run_test(args.app, test_timeout_mode=args.test_timeout) diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/README.md b/targets/STMicroelectronics/NUCLEO_F401RE/README.md index dbee3ce3..b872f93f 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/README.md +++ b/targets/STMicroelectronics/NUCLEO_F401RE/README.md @@ -11,13 +11,13 @@ Eclipse ThreadX contributors - Initial version and validation. --> -# Eclipse ThreadX NUCLEO-F401RE Starter Application +# Eclipse ThreadX NUCLEO-F401RE Target -This demonstration application validates the NUCLEO-F401RE Board Support Package for Eclipse ThreadX. +This target validates the NUCLEO-F401RE Board Support Package for Eclipse ThreadX. -The demo creates multiple threads, blinks the onboard LED, and reports runtime statistics through USART2 using the ST-LINK virtual COM port. +The application it builds is **`apps/threadx_demo/main.c`**, the shared portable demo, not a source file of its own. That same file is built by `targets/Microchip/POLARFIRE_ICICLE_RENODE` for 64-bit RISC-V, and CI asserts on the same console output from both, so this target's role is to prove the BSP contracts hold on 32-bit Cortex-M4. The demo creates multiple threads, blinks the onboard LED, and reports runtime statistics through USART2 using the ST-LINK virtual COM port; it reaches all three through `` and names no STM32 symbol. -It integrates the Eclipse ThreadX RTOS with the STM32CubeF4 HAL library in a clean, self-contained CMake build structure. +Everything board-specific lives under `lib/bsp/` and `app/common/`: this target integrates the Eclipse ThreadX RTOS with the STM32CubeF4 HAL library in a clean, self-contained CMake build structure. Third-party licensing information is provided in [NOTICE.md](NOTICE.md). @@ -126,7 +126,7 @@ To view console output: ## Hardware Configuration -The starter application is preconfigured to work with the physical STMicroelectronics NUCLEO-F401RE board: +The BSP is preconfigured to work with the physical STMicroelectronics NUCLEO-F401RE board: - **MCU**: Single-core ARM Cortex-M4 running at 84 MHz - **Onboard User LED**: LD2 connected to pin `PA5` for heartbeat feedback - **UART Console**: USART2 connected to the ST-Link virtual COM port on pins `PA2` (TX) and `PA3` (RX) configured for 115200 baud, 8N1 @@ -172,6 +172,7 @@ The BSP separates the ThreadX scheduler tick from the STM32 HAL timebase to avoi - **USART2** - Operates in polling mode and does not use interrupts in this demonstration. + - `bsp_console_set_rx_handler()` is therefore implemented as a store only: the handler an application registers is kept, but nothing on this board delivers received bytes one at a time to invoke it. `nucleo_console_rx_dispatch()` in `lib/bsp/src/bsp_console.c` is the hook a `USART2_IRQHandler` would call. The contract is honoured anyway so a portable application can register unconditionally. ### HAL Timebase Integration @@ -182,14 +183,17 @@ The BSP overrides `HAL_InitTick()` to configure TIM2 as the HAL timebase and pro ## File Organization -- **`app/`**: Main application logic and boot setups +- **`../../../apps/threadx_demo/`**: The application this target builds. Shared + with the PolarFire SoC Icicle Kit; nothing in it is board specific. +- **`app/`**: Boot setup and the CMake glue that pulls in the shared application - **`app/common/`**: Vendor HAL MSP hooks and boot sources - **`app/common/startup/`**: Linker scripts and assembly boot startup code - - **`app/starter/`**: Demo main thread logic - **`lib/`**: Libraries and dependencies - **`lib/bsp/`**: Board support implementing the generic `` interfaces (`bsp_board.c` clocks and HAL timebase, `bsp_led.c` LD2, `bsp_console.c` - USART2, `newlib_stubs.c` newlib syscall overrides) + USART2 and the receive-handler registration, `bsp_memory.c` the application + RAM budget, `bsp_selftest.c` the startup checks, `newlib_stubs.c` newlib + syscall overrides) - **`lib/stm32cubef4/`**: HAL Driver wrapper and platform drivers - **`lib/threadx/`**: ThreadX user configuration file (`tx_user.h`) - **`cmake/`**: Cross-compilation module definitions diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/app/CMakeLists.txt b/targets/STMicroelectronics/NUCLEO_F401RE/app/CMakeLists.txt index 19172319..71b18bf4 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/app/CMakeLists.txt +++ b/targets/STMicroelectronics/NUCLEO_F401RE/app/CMakeLists.txt @@ -7,7 +7,12 @@ # SPDX-License-Identifier: MIT set(COMMON_DIR ${CMAKE_CURRENT_SOURCE_DIR}/common) -set(STARTER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/starter) + +# The shared portable demo, built from apps/ rather than from this target. It +# names no board symbol, so the PolarFire SoC Icicle Kit builds the same file. +# A board-specific application would live here under app/ instead; a target +# picks one or the other. +set(SHARED_APP_DIR ${SAMPLEX_ROOT_DIR}/apps/threadx_demo) set(SOURCES ${COMMON_DIR}/startup/system_stm32f4xx.c @@ -20,7 +25,7 @@ set(SOURCES # libnucleo_bsp.a so the linker always takes these definitions instead of # falling back to the libnosys stubs. ${CMAKE_CURRENT_SOURCE_DIR}/../lib/bsp/src/newlib_stubs.c - ${STARTER_DIR}/main.c + ${SHARED_APP_DIR}/main.c ) add_executable(${PROJECT_NAME} ${SOURCES}) @@ -35,7 +40,6 @@ target_link_libraries(${PROJECT_NAME} target_include_directories(${PROJECT_NAME} PUBLIC ${COMMON_DIR} - ${STARTER_DIR} ) # Linker script diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h b/targets/STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h deleted file mode 100644 index 03b5e1f9..00000000 --- a/targets/STMicroelectronics/NUCLEO_F401RE/app/starter/cloud_config.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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 - */ - -#ifndef CLOUD_CONFIG_H -#define CLOUD_CONFIG_H - -/* Placeholder for future cloud connectivity settings. */ - -#endif /* CLOUD_CONFIG_H */ diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/nucleo_console.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/nucleo_console.h index a9f66dff..d899a2b3 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/nucleo_console.h +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/nucleo_console.h @@ -8,6 +8,8 @@ * SPDX-License-Identifier: MIT */ +// Some portions generated by Claude Code (Opus 5) + #ifndef NUCLEO_CONSOLE_H #define NUCLEO_CONSOLE_H @@ -25,4 +27,16 @@ */ void nucleo_console_read(char *data, size_t length); +/** + * @brief Hands one received character to the registered bsp/console.h handler. + * + * Board-private, and currently without a caller: USART2 is read by polling on + * this board, so no interrupt delivers bytes one at a time. It is the hook a + * USART2_IRQHandler would call, and it is what reads the pointer that + * bsp_console_set_rx_handler() stores. + * + * @param c The character read out of the USART2 data register. + */ +void nucleo_console_rx_dispatch(char c); + #endif /* NUCLEO_CONSOLE_H */ diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_console.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_console.c index df71a8ca..f78b7d3d 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_console.c +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_console.c @@ -13,6 +13,8 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ +// Some portions generated by Claude Code (Opus 5) + #include "bsp/console.h" #include "board_config.h" #include "nucleo_console.h" @@ -38,6 +40,38 @@ static void console_error_handler(void) } #endif +/* + * Receive handler registered through bsp_console_set_rx_handler(). + * + * USART2 is read by polling on this board - nucleo_console_read() blocks in + * HAL_UART_Receive() - so nothing raises a per-byte receive interrupt and this + * handler is never invoked. It is stored anyway because the contract in + * is what lets a portable application register unconditionally + * without asking which boards have wired an RX interrupt. Wiring USART2_IRQHandler + * is what would give it a caller. + */ +static bsp_console_rx_fn volatile console_rx_handler = NULL; +static void *volatile console_rx_context = NULL; + +void bsp_console_set_rx_handler(bsp_console_rx_fn handler, void *context) +{ + /* Publish the context first: a reader tests the handler to decide whether + * to dispatch, so a visible handler must already have its context beside + * it. A single aligned pointer store is atomic on Cortex-M4. */ + console_rx_context = context; + console_rx_handler = handler; +} + +void nucleo_console_rx_dispatch(char c) +{ + bsp_console_rx_fn handler = console_rx_handler; + + if (handler != NULL) + { + handler(c, console_rx_context); + } +} + void bsp_console_init(void) { #if BSP_HAS_CONSOLE diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_selftest.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_selftest.c index 4c893966..8e7d6e2c 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_selftest.c +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_selftest.c @@ -80,6 +80,7 @@ unsigned bsp_self_test(bsp_selftest_report_fn report, void *context) void *p_ok; void *p_under; void *p_over; + ptrdiff_t heap_taken; uint32_t tick_start; uint32_t spins; @@ -97,14 +98,23 @@ unsigned bsp_self_test(bsp_selftest_report_fn report, void *context) ((uintptr_t)p_ok < heap_limit), "_sbrk() valid allocation inside the heap reservation"); - /* 2. Releasing it returns the break to the heap base, leaving the heap - * exactly as the remaining checks found it. */ + /* 2. Releasing it puts the break back where step 1 found it, leaving the + * heap exactly as the remaining checks found it. That is the heap base + * only for an application that has not yet allocated. */ check(&state, _sbrk(-64) != (void *)-1, "_sbrk() released 64 bytes back to the heap base"); - /* 3. Shrinking below the heap base is rejected. */ + /* 3. Shrinking below the heap base is rejected. + * + * The decrement is derived from the live break rather than fixed. Step 2 + * only returns the break to where step 1 found it, which is the heap base + * only for an application that has not yet allocated; one that reached + * printf() first carries a newlib stdio buffer below it, and a fixed -128 + * would then be an ordinary shrink rather than an underflow. Handing back + * one byte more than has ever been taken underflows either way. */ errno = 0; - p_under = _sbrk(-128); + heap_taken = (ptrdiff_t)((uintptr_t)_sbrk(0) - heap_base); + p_under = _sbrk(-(heap_taken + 1)); check(&state, (p_under == (void *)-1) && (errno == EINVAL), "_sbrk() underflow guard rejected with EINVAL"); diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_demo.robot b/targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_demo.robot index 20f94ee6..4e788db5 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_demo.robot +++ b/targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_demo.robot @@ -10,7 +10,7 @@ Should Pass Startup Self-Tests Execute Command include @${CURDIR}/nucleo_f401re_demo.resc Create Terminal Tester sysbus.usart2 - Wait For Line On Uart NUCLEO-F401RE Device Monitor Demo timeout=15 + Wait For Line On Uart Eclipse ThreadX Device Monitor Demo timeout=15 Wait For Line On Uart [SELF-TEST] Starting BSP & Runtime Verification... timeout=15 Wait For Line On Uart [SELF-TEST] All startup verification tests PASSED! timeout=15 diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/scripts/test_renode.py b/targets/STMicroelectronics/NUCLEO_F401RE/scripts/test_renode.py index e37a8a74..03e4afc2 100755 --- a/targets/STMicroelectronics/NUCLEO_F401RE/scripts/test_renode.py +++ b/targets/STMicroelectronics/NUCLEO_F401RE/scripts/test_renode.py @@ -15,6 +15,12 @@ Runs targets/STMicroelectronics/NUCLEO_F401RE/renode/nucleo_f401re_ci.resc and asserts on the USART2 console output. The run advances a fixed span of virtual time and quits on its own, so the result does not depend on host speed. + +The application under test is apps/threadx_demo/main.c, shared with the +Microchip PolarFire SoC Icicle Kit. The assertions below are deliberately the +same ones targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py +makes with --app threadx_demo, so the two runs compare the same source built +for a 32-bit Cortex-M4 and a 64-bit RISC-V hart. """ import os @@ -106,7 +112,10 @@ def run_test(test_timeout_mode=False): if test_timeout_mode: continue - if "NUCLEO-F401RE Device Monitor Demo" in line: + # apps/threadx_demo/main.c prints this, and it names no + # board on purpose: the PolarFire suite asserts on the very + # same line against the RISC-V build of that same source. + if "Eclipse ThreadX Device Monitor Demo" in line: found_banner = True if "[-] FAIL:" in line or "startup verification test(s) FAILED" in line: found_selftest_failure = True diff --git a/templates/target/README.md b/templates/target/README.md index beddee2d..3e8f1d07 100644 --- a/templates/target/README.md +++ b/templates/target/README.md @@ -49,8 +49,12 @@ To maintain long-term framework maintainability and portability, the following r * `/bsp`: Defines the target-agnostic C interface contracts (`board.h`, `led.h`, `console.h`, `memory.h`, `selftest.h`). New board targets must implement these existing interfaces rather than modifying core interface definitions. * `/libs`: Shared RTOS components consumed by every target as submodules. Targets reference these rather than vendoring their own copy. +* `/apps`: Portable applications that any target can build. `apps/threadx_demo/main.c` is built today by both shipped targets from the one source file, and CI runs it under Renode on 32-bit Cortex-M4 and 64-bit RISC-V. Point a new board's `app/CMakeLists.txt` at it to get a demo for free; extend it only in ways that stay board-neutral. + > [!NOTE] -> **Applications are currently target-resident.** Each target owns its demo under `targets///app/`, along with its own `cmake/` toolchain files and build helpers. A shared `/apps` layer is a goal of this framework, not something it provides yet, so onboard a new board by starting from the app in this template rather than by linking one from a shared directory. What a demo no longer needs is board headers: `` covers byte-pool sizing and `` covers startup self-tests, so both shipped demos include only `` and ``. +> **A demo belongs in `/apps` or with its board, and what it names decides which.** An application that names no board symbol, vendor header or linker-defined address is portable and belongs in `apps/`; one that does belongs under `targets///app/`. Both are legitimate - the PolarFire SoC Icicle Kit keeps its LM75 monitor as a target app because it genuinely models a sensor, and builds the shared demo as a second executable alongside it. A target's `app/CMakeLists.txt` picks either. +> +> What no demo needs any more is board headers. `` covers byte-pool sizing and `` covers startup self-tests, so every shipped demo includes only C standard headers, `` and ``. > [!NOTE] > **Core Architectural Principle**: @@ -75,7 +79,8 @@ The table below maps common embedded software components to their designated loc | **BSP Driver Implementation** | `targets///lib/bsp/src/` | Target developer (`bsp_board.c`, `bsp_led.c`, `bsp_console.c`, `bsp_memory.c`, `bsp_selftest.c`) | | **Target Specification Constants** | `targets///lib/bsp/include/board_config.h` | Target developer (declarative defines only) | | **Target Build Automation** | `targets///scripts/build.ps1` | Target developer (PowerShell automation template) | -| **Application Code** | `targets///app/` | Target developer (start from this template's `app/main.c`) | +| **Portable Application Code** | `apps//` | Shared across targets (`apps/threadx_demo/` builds on every target) | +| **Board-Specific Application Code** | `targets///app/` | Target developer (start from this template's `app/main.c`) | | **Toolchain & Build Helpers** | `targets///cmake/` | Target developer (cross-compilation settings per target) | --- @@ -101,7 +106,7 @@ To add support for a new board (e.g. `MY_VENDOR / MY_BOARD`): Populate the driver stubs in `targets/MyVendor/MY_BOARD/lib/bsp/src/`: - `bsp_board.c`: Configure System Clocks, Flash Wait States, and low-level timers in `bsp_board_init()`. - `bsp_led.c`: Configure GPIO pin muxing and implement `bsp_led_on()`, `bsp_led_off()`, `bsp_led_toggle()`. - - `bsp_console.c`: Configure UART peripheral and implement `bsp_console_write()`. + - `bsp_console.c`: Configure the UART peripheral and implement `bsp_console_write()`. Store what `bsp_console_set_rx_handler()` is given even if this board only polls its console; if the board does raise a receive interrupt, dispatch to the stored handler from its IRQ handler rather than calling a symbol the application must define. A BSP that requires an application-defined symbol cannot be linked by an application that does not want it. - `bsp_memory.c`: Report the RAM the application may claim in `bsp_ram_region()`, subtracting whatever this board reserves for its C heap and stacks. - `bsp_selftest.c`: Verify in `bsp_self_test()` that the board came up as configured - clocks, timebase, interrupt routing, and that the C heap cannot grow into the region `bsp_ram_region()` hands out. @@ -115,7 +120,7 @@ To add support for a new board (e.g. `MY_VENDOR / MY_BOARD`): The target's CMake build scripts are responsible for exposing include paths and linking the BSP drivers, vendor SDK, ThreadX kernel, and shared application executable together into the final firmware image: - Update `targets/MyVendor/MY_BOARD/CMakeLists.txt` with your target project name and any required vendor SDK configuration. - Update `targets/MyVendor/MY_BOARD/lib/CMakeLists.txt` to register vendor SDK libraries and subdirectories. - - Update `targets/MyVendor/MY_BOARD/app/CMakeLists.txt` to register startup assembly files, system initialization code, linker scripts, target BSP sources, and link against the required ThreadX libraries. + - Update `targets/MyVendor/MY_BOARD/app/CMakeLists.txt` to register startup assembly files, system initialization code, linker scripts, target BSP sources, and link against the required ThreadX libraries. Point it either at `${SAMPLEX_ROOT_DIR}/apps/threadx_demo/main.c` for the shared portable demo or at this template's own `app/main.c` to grow a board-specific one. 7. **Build and Test**: Run the PowerShell build script: @@ -135,7 +140,7 @@ The current framework defines the following core baseline C interfaces in `/bsp/ | :--- | :--- | :--- | | `` | `bsp_board_init()` | Core MCU clock tree, power scaling, and flash wait state setup. | | `` | `bsp_led_init()`, `bsp_led_toggle()`, etc. | GPIO user LED initialization and state toggling. | -| `` | `bsp_console_init()`, `bsp_console_write()` | Serial UART initialization and output transmission. | +| `` | `bsp_console_init()`, `bsp_console_write()`, `bsp_console_set_rx_handler()` | Serial UART initialization, output transmission, and registration of a receive handler. | | `` | `bsp_ram_region()` | RAM the application may claim, clamped against the board's own heap and stack reservations. | | `` | `bsp_self_test()` | Board startup verification, reported through an application-supplied callback. | @@ -148,4 +153,4 @@ The current framework defines the following core baseline C interfaces in `/bsp/ > [!TIP] > **Optional Interfaces & Hardware Variants**: > * The baseline interfaces currently cover core board setup, user LED control, and debug console output. Future versions of the BSP framework may introduce additional optional interfaces (e.g., non-volatile storage, networking, I2C/SPI bus drivers). -> * If a specific target board lacks dedicated LED or UART hardware, implement the interface functions as **no-op implementations** so that generic application binaries continue to link and execute cleanly. +> * If a specific target board lacks dedicated LED or UART hardware, implement the interface functions as **no-op implementations** so that generic application binaries continue to link and execute cleanly. The same applies to `bsp_console_set_rx_handler()` on a board with no receive path: accept and store the handler, and simply never invoke it. diff --git a/templates/target/app/CMakeLists.txt b/templates/target/app/CMakeLists.txt index 6e9a585f..3ec30b76 100644 --- a/templates/target/app/CMakeLists.txt +++ b/templates/target/app/CMakeLists.txt @@ -15,8 +15,9 @@ set(SOURCES # ${COMMON_DIR}/startup/startup_mcu.s # ${COMMON_DIR}/startup/tx_initialize_low_level.S - # This target's ThreadX application. Applications are target-resident: - # there is no shared apps/ directory to link one from. + # This target's ThreadX application. Swap this for + # ${SAMPLEX_ROOT_DIR}/apps/threadx_demo/main.c to build the shared portable + # demo instead; a target picks one or the other. ${CMAKE_CURRENT_SOURCE_DIR}/main.c # Link GCC Newlib syscall stubs diff --git a/templates/target/app/main.c b/templates/target/app/main.c index 1169b3f6..1ce95f70 100644 --- a/templates/target/app/main.c +++ b/templates/target/app/main.c @@ -22,8 +22,11 @@ * byte pool, which answers, and running the board's startup * self-tests, which answers. * - * Once the board boots this, grow the demo in place. Applications live with - * their target rather than in a shared directory. + * Once the board boots this, either grow the demo in place - which is what a + * board-specific application such as the PolarFire LM75 monitor does - or + * point app/CMakeLists.txt at apps/threadx_demo/main.c and get the shared + * portable demo instead. What a demo names decides where it belongs: name a + * board symbol and it stays here, name none and it belongs in apps/. */ #include "tx_api.h" diff --git a/templates/target/lib/bsp/src/bsp_console.c b/templates/target/lib/bsp/src/bsp_console.c index 23dae914..d84d1aa3 100644 --- a/templates/target/lib/bsp/src/bsp_console.c +++ b/templates/target/lib/bsp/src/bsp_console.c @@ -8,9 +8,13 @@ * SPDX-License-Identifier: MIT */ +// Some portions generated by Claude Code (Opus 5) + #include "bsp/console.h" #include "board_config.h" +#include + /* TODO: Include vendor UART / Serial hardware headers here */ void bsp_console_init(void) @@ -33,3 +37,36 @@ void bsp_console_write(const char *data, size_t length) (void)length; #endif } + +/* Handler registered by the application to receive console input. + * + * Store it even if this board has no receive-interrupt path: the contract lets + * an application register unconditionally, and a board that silently drops the + * registration would make a portable demo fail only on that board. */ +static bsp_console_rx_fn volatile console_rx_handler = NULL; +static void *volatile console_rx_context = NULL; + +void bsp_console_set_rx_handler(bsp_console_rx_fn handler, void *context) +{ + /* Publish the context first, so a handler visible to an interrupt already + * has its context beside it. */ + console_rx_context = context; + console_rx_handler = handler; +} + +/* + * Call this from the board's UART receive interrupt handler, once per byte. + * + * TODO: Enable the peripheral's RX interrupt in bsp_console_init() and invoke + * this from its IRQ handler. A board that only polls its console can leave + * this without a caller; the registration above still has to work. + */ +void bsp_console_rx_dispatch(char c) +{ + bsp_console_rx_fn handler = console_rx_handler; + + if (handler != NULL) + { + handler(c, console_rx_context); + } +} From 962dc1ea1ad79be628ab80bf37de7e1a4e8ecfde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 15 Sep 2026 19:04:45 -0400 Subject: [PATCH 14/20] Normalized the AI disclosure comment to one fixed line per file (#69) The per-edit disclosure named the product and model, so every tool and every model version appended another line rather than recognising the one already there. Deduplication was by exact string, which a version bump defeats. Every file now carries exactly one line, fixed text naming no product: Portions of this file were generated with AI assistance. written with the comment character that file already uses. Precise attribution stays on the commit, where the Assisted-by trailer is dated and attached to the diff it describes. A header line cannot keep that record honest, because the code it names gets rewritten and the line stays. Comment-only, 32 files: every removed line was a disclosure line, every added line is the fixed text, and no file is left with zero or more than one. Nested repositories were excluded, so no submodule content or gitlink is touched. Assisted-by: Claude Code (Opus 5) --- MXChip/AZ3166/app/arcade/button_handler.c | 2 +- MXChip/AZ3166/app/arcade/button_handler.h | 2 +- MXChip/AZ3166/app/arcade/fosgame.c | 2 +- MXChip/AZ3166/app/arcade/fosgame.h | 2 +- MXChip/AZ3166/app/arcade/main.c | 2 +- MXChip/AZ3166/app/arcade/menu.c | 2 +- MXChip/AZ3166/app/arcade/menu.h | 2 +- MXChip/AZ3166/app/arcade/screen.c | 2 +- MXChip/AZ3166/app/arcade/screen.h | 2 +- MXChip/AZ3166/app/arcade/slotmachine.c | 2 +- MXChip/AZ3166/app/arcade/slotmachine.h | 2 +- MXChip/AZ3166/app/arcade/snake.c | 2 +- MXChip/AZ3166/app/arcade/snake.h | 2 +- MXChip/AZ3166/app/arcade/space.c | 2 +- MXChip/AZ3166/app/arcade/space.h | 2 +- bsp/include/bsp/console.h | 2 +- .../POLARFIRE_ICICLE_RENODE/app/common/startup/newlib_stubs.c | 2 +- .../app/common/startup/tx_initialize_low_level.S | 2 +- targets/Microchip/POLARFIRE_ICICLE_RENODE/app/main.c | 2 +- .../POLARFIRE_ICICLE_RENODE/lib/bsp/include/board_config.h | 2 +- .../Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/plic.h | 2 +- targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/board.c | 2 +- .../Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_console.c | 2 +- targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/hwtimer.c | 2 +- targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/plic.c | 2 +- targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/trap.c | 2 +- .../NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c | 2 +- .../NUCLEO_F401RE/lib/bsp/include/board_config.h | 2 +- .../NUCLEO_F401RE/lib/bsp/include/nucleo_console.h | 2 +- .../STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_console.c | 2 +- templates/target/lib/bsp/src/bsp_console.c | 2 +- templates/target/lib/bsp/src/newlib_stubs.c | 2 +- 32 files changed, 32 insertions(+), 32 deletions(-) diff --git a/MXChip/AZ3166/app/arcade/button_handler.c b/MXChip/AZ3166/app/arcade/button_handler.c index 6f19cf0d..a3a4d0dc 100644 --- a/MXChip/AZ3166/app/arcade/button_handler.c +++ b/MXChip/AZ3166/app/arcade/button_handler.c @@ -11,7 +11,7 @@ * Sébastien Heurtematte - 2026 version. * * - * // Some portions generated by Co-Pilot + // Portions of this file were generated with AI assistance. */ #include "button_handler.h" diff --git a/MXChip/AZ3166/app/arcade/button_handler.h b/MXChip/AZ3166/app/arcade/button_handler.h index 186f8d1b..6a18d284 100644 --- a/MXChip/AZ3166/app/arcade/button_handler.h +++ b/MXChip/AZ3166/app/arcade/button_handler.h @@ -11,7 +11,7 @@ * Sébastien Heurtematte - 2026 version. * * - * // Some portions generated by Co-Pilot + // Portions of this file were generated with AI assistance. */ #ifndef _BUTTON_HANDLER_H diff --git a/MXChip/AZ3166/app/arcade/fosgame.c b/MXChip/AZ3166/app/arcade/fosgame.c index 9a784385..38a91825 100644 --- a/MXChip/AZ3166/app/arcade/fosgame.c +++ b/MXChip/AZ3166/app/arcade/fosgame.c @@ -11,7 +11,7 @@ * Sébastien Heurtematte - 2026 version. * * - * // Some portions generated by Co-Pilot + // Portions of this file were generated with AI assistance. */ #include "fosgame.h" diff --git a/MXChip/AZ3166/app/arcade/fosgame.h b/MXChip/AZ3166/app/arcade/fosgame.h index af190584..1c0bacf8 100644 --- a/MXChip/AZ3166/app/arcade/fosgame.h +++ b/MXChip/AZ3166/app/arcade/fosgame.h @@ -11,7 +11,7 @@ * Sébastien Heurtematte - 2026 version. * * - * // Some portions generated by Co-Pilot + // Portions of this file were generated with AI assistance. */ #ifndef _FOSGAME_H diff --git a/MXChip/AZ3166/app/arcade/main.c b/MXChip/AZ3166/app/arcade/main.c index 1e3acfe4..dc7943a3 100644 --- a/MXChip/AZ3166/app/arcade/main.c +++ b/MXChip/AZ3166/app/arcade/main.c @@ -14,7 +14,7 @@ * Sébastien Heurtematte - 2026 version. * * - * // Some portions generated by Co-Pilot + // Portions of this file were generated with AI assistance. */ #include diff --git a/MXChip/AZ3166/app/arcade/menu.c b/MXChip/AZ3166/app/arcade/menu.c index c187a2aa..8367c6e6 100644 --- a/MXChip/AZ3166/app/arcade/menu.c +++ b/MXChip/AZ3166/app/arcade/menu.c @@ -11,7 +11,7 @@ * Sébastien Heurtematte - 2026 version. * * - * // Some portions generated by Co-Pilot + // Portions of this file were generated with AI assistance. */ #include "menu.h" #include "screen.h" diff --git a/MXChip/AZ3166/app/arcade/menu.h b/MXChip/AZ3166/app/arcade/menu.h index 998df71c..df805368 100644 --- a/MXChip/AZ3166/app/arcade/menu.h +++ b/MXChip/AZ3166/app/arcade/menu.h @@ -11,7 +11,7 @@ * Sébastien Heurtematte - 2026 version. * * - * // Some portions generated by Co-Pilot + // Portions of this file were generated with AI assistance. */ #ifndef _MENU_H diff --git a/MXChip/AZ3166/app/arcade/screen.c b/MXChip/AZ3166/app/arcade/screen.c index 73cf7057..b97ba403 100644 --- a/MXChip/AZ3166/app/arcade/screen.c +++ b/MXChip/AZ3166/app/arcade/screen.c @@ -11,7 +11,7 @@ * Sébastien Heurtematte - 2026 version. * * - * // Some portions generated by Co-Pilot + // Portions of this file were generated with AI assistance. */ #include "screen.h" diff --git a/MXChip/AZ3166/app/arcade/screen.h b/MXChip/AZ3166/app/arcade/screen.h index b8f44bf6..24a1ab6b 100644 --- a/MXChip/AZ3166/app/arcade/screen.h +++ b/MXChip/AZ3166/app/arcade/screen.h @@ -11,7 +11,7 @@ * Sébastien Heurtematte - 2026 version. * * - * // Some portions generated by Co-Pilot + // Portions of this file were generated with AI assistance. */ #ifndef _SCREEN_H diff --git a/MXChip/AZ3166/app/arcade/slotmachine.c b/MXChip/AZ3166/app/arcade/slotmachine.c index bd039c30..5cad72b6 100644 --- a/MXChip/AZ3166/app/arcade/slotmachine.c +++ b/MXChip/AZ3166/app/arcade/slotmachine.c @@ -11,7 +11,7 @@ * Sébastien Heurtematte - 2026 version. * * - * // Some portions generated by Co-Pilot + // Portions of this file were generated with AI assistance. */ #include "slotmachine.h" diff --git a/MXChip/AZ3166/app/arcade/slotmachine.h b/MXChip/AZ3166/app/arcade/slotmachine.h index a7df118f..1e0b876b 100644 --- a/MXChip/AZ3166/app/arcade/slotmachine.h +++ b/MXChip/AZ3166/app/arcade/slotmachine.h @@ -11,7 +11,7 @@ * Sébastien Heurtematte - 2026 version. * * - * // Some portions generated by Co-Pilot + // Portions of this file were generated with AI assistance. */ #ifndef _SLOTMACHINE_H diff --git a/MXChip/AZ3166/app/arcade/snake.c b/MXChip/AZ3166/app/arcade/snake.c index c579a1fd..1b2dbaeb 100644 --- a/MXChip/AZ3166/app/arcade/snake.c +++ b/MXChip/AZ3166/app/arcade/snake.c @@ -11,7 +11,7 @@ * Sébastien Heurtematte - 2026 version. * * - * // Some portions generated by Co-Pilot + // Portions of this file were generated with AI assistance. */ #include "snake.h" diff --git a/MXChip/AZ3166/app/arcade/snake.h b/MXChip/AZ3166/app/arcade/snake.h index 415526f2..35b363ba 100644 --- a/MXChip/AZ3166/app/arcade/snake.h +++ b/MXChip/AZ3166/app/arcade/snake.h @@ -11,7 +11,7 @@ * Sébastien Heurtematte - 2026 version. * * - * // Some portions generated by Co-Pilot + // Portions of this file were generated with AI assistance. */ #ifndef _SNAKE_H diff --git a/MXChip/AZ3166/app/arcade/space.c b/MXChip/AZ3166/app/arcade/space.c index af3f0da4..a6d9a698 100644 --- a/MXChip/AZ3166/app/arcade/space.c +++ b/MXChip/AZ3166/app/arcade/space.c @@ -11,7 +11,7 @@ * Sébastien Heurtematte - 2026 version. * * - * // Some portions generated by Co-Pilot + // Portions of this file were generated with AI assistance. */ #include "space.h" diff --git a/MXChip/AZ3166/app/arcade/space.h b/MXChip/AZ3166/app/arcade/space.h index 40fbdf9d..01008a9a 100644 --- a/MXChip/AZ3166/app/arcade/space.h +++ b/MXChip/AZ3166/app/arcade/space.h @@ -11,7 +11,7 @@ * Sébastien Heurtematte - 2026 version. * * - * // Some portions generated by Co-Pilot + // Portions of this file were generated with AI assistance. */ #ifndef _SPACE_H diff --git a/bsp/include/bsp/console.h b/bsp/include/bsp/console.h index 442022bb..be715e18 100644 --- a/bsp/include/bsp/console.h +++ b/bsp/include/bsp/console.h @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT */ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #ifndef BSP_CONSOLE_H #define BSP_CONSOLE_H diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/newlib_stubs.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/newlib_stubs.c index cf63f695..8039934d 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/newlib_stubs.c +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/newlib_stubs.c @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT */ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #include #include diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/tx_initialize_low_level.S b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/tx_initialize_low_level.S index 9081ef5a..56df8651 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/tx_initialize_low_level.S +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/common/startup/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT */ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #include "csr.h" diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/main.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/main.c index e4a4c150..82727e4f 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/main.c +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/app/main.c @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT */ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #include #include diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/board_config.h b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/board_config.h index bb129a41..7683d41a 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/board_config.h +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/board_config.h @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT */ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #ifndef BOARD_CONFIG_H #define BOARD_CONFIG_H diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/plic.h b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/plic.h index 8133a828..535d02ae 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/plic.h +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/include/plic.h @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT */ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #ifndef PLIC_H #define PLIC_H diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/board.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/board.c index 91192bba..d4361321 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/board.c +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/board.c @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT */ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #include "plic.h" diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_console.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_console.c index f915a7af..1be5f1ad 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_console.c +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/bsp_console.c @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT */ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #include "bsp/console.h" #include "board_config.h" diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/hwtimer.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/hwtimer.c index 374722c9..d954046e 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/hwtimer.c +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/hwtimer.c @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT */ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #include "hwtimer.h" #include "tx_api.h" diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/plic.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/plic.c index f4f5fd7d..69eae8e1 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/plic.c +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/plic.c @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT */ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #include "plic.h" #include "csr.h" diff --git a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/trap.c b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/trap.c index 71c283e3..acd1a5ec 100644 --- a/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/trap.c +++ b/targets/Microchip/POLARFIRE_ICICLE_RENODE/lib/bsp/src/trap.c @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT */ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #include #include "hwtimer.h" diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c b/targets/STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c index 2a90bad1..ddfea956 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c +++ b/targets/STMicroelectronics/NUCLEO_F401RE/app/common/stm32cubef4/stm32f4xx_hal_msp.c @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: MIT */ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. #include "stm32f4xx_hal.h" diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/board_config.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/board_config.h index 929e0815..81f6fffe 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/board_config.h +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/board_config.h @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT */ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #ifndef BOARD_CONFIG_H #define BOARD_CONFIG_H diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/nucleo_console.h b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/nucleo_console.h index d899a2b3..4bb945b2 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/nucleo_console.h +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/include/nucleo_console.h @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT */ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #ifndef NUCLEO_CONSOLE_H #define NUCLEO_CONSOLE_H diff --git a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_console.c b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_console.c index f78b7d3d..ddc3729e 100644 --- a/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_console.c +++ b/targets/STMicroelectronics/NUCLEO_F401RE/lib/bsp/src/bsp_console.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #include "bsp/console.h" #include "board_config.h" diff --git a/templates/target/lib/bsp/src/bsp_console.c b/templates/target/lib/bsp/src/bsp_console.c index d84d1aa3..e153dd67 100644 --- a/templates/target/lib/bsp/src/bsp_console.c +++ b/templates/target/lib/bsp/src/bsp_console.c @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT */ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #include "bsp/console.h" #include "board_config.h" diff --git a/templates/target/lib/bsp/src/newlib_stubs.c b/templates/target/lib/bsp/src/newlib_stubs.c index 70b0f76f..7e0222f0 100644 --- a/templates/target/lib/bsp/src/newlib_stubs.c +++ b/templates/target/lib/bsp/src/newlib_stubs.c @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT */ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #ifdef __GNUC__ From 8a133d71ba753a79152e7c8dc7310ad7d2c69ff7 Mon Sep 17 00:00:00 2001 From: Ali Eissa Date: Thu, 17 Sep 2026 03:15:57 +0400 Subject: [PATCH 15/20] Added the NXP i.MX RT1064-EVK target with three demos and Renode CI samplex demonstrates Eclipse ThreadX and NetX Duo on Cortex-M4 and RISC-V, but had no reference enablement for NXP's Cortex-M7 crossover parts, and no way to exercise the network stack in CI without hardware. This adds `targets/NXP/MIMXRT1064-EVK/`, built from `templates/target/` and implementing the `bsp/include/bsp/` contract, with three demos: `threadx_basic` (scheduling, timers, LED), `netx_echo` (ICMP, UDP and TCP echo on port 7) and `netx_trng_console` (on-chip TRNG behind a single-session TCP shell on port 23, serving one connection at a time). The ENET and KSZ8081 PHY drivers are vendored rather than tracked from `getting-started`, which is on the same archive track as `iot-devkit`. Every SDK and CMSIS download is pinned to a tag or commit and SHA256-verified. A Renode platform model and a headless Python runner join the existing CI, reusing the pinned toolchain and Renode steps from #53 and #55. Renode 1.16.1, all three demos green: `threadx_basic` asserts the worker thread runs at tick 100; `netx_echo` asserts link up, ARP, ICMP reply and 23-byte UDP and TCP echoes across two emulated nodes; `netx_trng_console` asserts four distinct non-zero entropy words, remote LED toggle, uptime telemetry, and that an over-long command line is refused without dropping the session. Not run on hardware. The README records what the emulator stubs: CCM and ANALOG are tag stubs whose registers read back fixed values, the 600 MHz banner is a compile-time constant, and Renode's TRNG model implements neither the programming sequence nor the ENT15 block-consume semantics, so the driver's bring-up is unverified on silicon. Signed-off-by: Ali Eissa Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) --- .github/workflows/ci.yml | 178 + targets/NXP/MIMXRT1064-EVK/.gitignore | 10 + targets/NXP/MIMXRT1064-EVK/CMakeLists.txt | 166 + targets/NXP/MIMXRT1064-EVK/NOTICE.md | 128 + targets/NXP/MIMXRT1064-EVK/README.md | 266 ++ targets/NXP/MIMXRT1064-EVK/app/MIMXRT1062.h | 33 + targets/NXP/MIMXRT1064-EVK/app/ansi_colors.h | 46 + .../app/demos/netx_echo/CMakeLists.txt | 70 + .../app/demos/netx_echo/client_main.c | 357 ++ .../MIMXRT1064-EVK/app/demos/netx_echo/main.c | 342 ++ .../app/demos/netx_echo/test_echo.ps1 | 131 + .../app/demos/netx_echo/test_echo.sh | 97 + .../demos/netx_trng_console/CMakeLists.txt | 70 + .../app/demos/netx_trng_console/client_main.c | 359 +++ .../app/demos/netx_trng_console/main.c | 397 +++ .../app/demos/threadx_basic/CMakeLists.txt | 36 + .../app/demos/threadx_basic/main.c | 167 + .../startup/MIMXRT1064xxxxx_flexspi_nor.ld | 279 ++ .../app/startup/startup_mimxrt1064.S | 1142 +++++++ .../app/startup/tx_initialize_low_level.S | 207 ++ targets/NXP/MIMXRT1064-EVK/app/syscalls.c | 131 + targets/NXP/MIMXRT1064-EVK/app/sysmem.c | 105 + targets/NXP/MIMXRT1064-EVK/app/trng.c | 198 ++ targets/NXP/MIMXRT1064-EVK/app/trng.h | 55 + .../cmake/arm-gcc-cortex-m7.cmake | 20 + .../cmake/arm-gcc-cortex-toolchain.cmake | 77 + .../NXP/MIMXRT1064-EVK/cmake/utilities.cmake | 50 + .../NXP/MIMXRT1064-EVK/lib/bsp/CMakeLists.txt | 52 + .../lib/bsp/include/board_config.h | 38 + .../MIMXRT1064-EVK/lib/bsp/src/bsp_board.c | 51 + .../MIMXRT1064-EVK/lib/bsp/src/bsp_console.c | 166 + .../NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_led.c | 56 + .../MIMXRT1064-EVK/lib/bsp/src/bsp_memory.c | 27 + .../MIMXRT1064-EVK/lib/bsp/src/bsp_selftest.c | 55 + .../gnu/nx_driver_imxrt1062_low_level.S | 84 + .../lib/netx_driver/nx_driver_imxrt1062.c | 2870 +++++++++++++++++ .../lib/netx_driver/nx_driver_imxrt1062.h | 244 ++ .../NXP/MIMXRT1064-EVK/lib/netxduo/nx_user.h | 21 + .../MIMXRT1064-EVK/lib/phyksz8081/fsl_phy.c | 301 ++ .../MIMXRT1064-EVK/lib/phyksz8081/fsl_phy.h | 200 ++ .../NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h | 29 + .../MIMXRT1064-EVK/renode/mimxrt1064-evk.repl | 30 + .../MIMXRT1064-EVK/renode/mimxrt1064-evk.resc | 45 + .../renode/mimxrt1064-headless-multinode.resc | 53 + .../renode/mimxrt1064-headless-single.resc | 35 + .../renode/mimxrt1064-network-multinode.resc | 62 + .../renode/mimxrt1064-trng-console.resc | 62 + targets/NXP/MIMXRT1064-EVK/scripts/build.ps1 | 113 + targets/NXP/MIMXRT1064-EVK/scripts/build.sh | 107 + .../NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 | 228 ++ .../NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh | 160 + .../NXP/MIMXRT1064-EVK/scripts/simulate.ps1 | 133 + .../NXP/MIMXRT1064-EVK/scripts/simulate.sh | 145 + .../MIMXRT1064-EVK/scripts/test_headless.ps1 | 35 + .../MIMXRT1064-EVK/scripts/test_headless.sh | 29 + .../NXP/MIMXRT1064-EVK/scripts/test_renode.py | 243 ++ 56 files changed, 10791 insertions(+) create mode 100644 targets/NXP/MIMXRT1064-EVK/.gitignore create mode 100644 targets/NXP/MIMXRT1064-EVK/CMakeLists.txt create mode 100644 targets/NXP/MIMXRT1064-EVK/NOTICE.md create mode 100644 targets/NXP/MIMXRT1064-EVK/README.md create mode 100644 targets/NXP/MIMXRT1064-EVK/app/MIMXRT1062.h create mode 100644 targets/NXP/MIMXRT1064-EVK/app/ansi_colors.h create mode 100644 targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/CMakeLists.txt create mode 100644 targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/client_main.c create mode 100644 targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/main.c create mode 100644 targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/test_echo.ps1 create mode 100644 targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/test_echo.sh create mode 100644 targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/CMakeLists.txt create mode 100644 targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/client_main.c create mode 100644 targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/main.c create mode 100644 targets/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/CMakeLists.txt create mode 100644 targets/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/main.c create mode 100644 targets/NXP/MIMXRT1064-EVK/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld create mode 100644 targets/NXP/MIMXRT1064-EVK/app/startup/startup_mimxrt1064.S create mode 100644 targets/NXP/MIMXRT1064-EVK/app/startup/tx_initialize_low_level.S create mode 100644 targets/NXP/MIMXRT1064-EVK/app/syscalls.c create mode 100644 targets/NXP/MIMXRT1064-EVK/app/sysmem.c create mode 100644 targets/NXP/MIMXRT1064-EVK/app/trng.c create mode 100644 targets/NXP/MIMXRT1064-EVK/app/trng.h create mode 100644 targets/NXP/MIMXRT1064-EVK/cmake/arm-gcc-cortex-m7.cmake create mode 100644 targets/NXP/MIMXRT1064-EVK/cmake/arm-gcc-cortex-toolchain.cmake create mode 100644 targets/NXP/MIMXRT1064-EVK/cmake/utilities.cmake create mode 100644 targets/NXP/MIMXRT1064-EVK/lib/bsp/CMakeLists.txt create mode 100644 targets/NXP/MIMXRT1064-EVK/lib/bsp/include/board_config.h create mode 100644 targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_board.c create mode 100644 targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_console.c create mode 100644 targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_led.c create mode 100644 targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_memory.c create mode 100644 targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_selftest.c create mode 100644 targets/NXP/MIMXRT1064-EVK/lib/netx_driver/gnu/nx_driver_imxrt1062_low_level.S create mode 100644 targets/NXP/MIMXRT1064-EVK/lib/netx_driver/nx_driver_imxrt1062.c create mode 100644 targets/NXP/MIMXRT1064-EVK/lib/netx_driver/nx_driver_imxrt1062.h create mode 100644 targets/NXP/MIMXRT1064-EVK/lib/netxduo/nx_user.h create mode 100644 targets/NXP/MIMXRT1064-EVK/lib/phyksz8081/fsl_phy.c create mode 100644 targets/NXP/MIMXRT1064-EVK/lib/phyksz8081/fsl_phy.h create mode 100644 targets/NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h create mode 100644 targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl create mode 100644 targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc create mode 100644 targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc create mode 100644 targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc create mode 100644 targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-network-multinode.resc create mode 100644 targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-trng-console.resc create mode 100644 targets/NXP/MIMXRT1064-EVK/scripts/build.ps1 create mode 100644 targets/NXP/MIMXRT1064-EVK/scripts/build.sh create mode 100644 targets/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 create mode 100644 targets/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh create mode 100644 targets/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 create mode 100644 targets/NXP/MIMXRT1064-EVK/scripts/simulate.sh create mode 100644 targets/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 create mode 100644 targets/NXP/MIMXRT1064-EVK/scripts/test_headless.sh create mode 100644 targets/NXP/MIMXRT1064-EVK/scripts/test_renode.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f883765e..0a02c051 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,7 @@ on: branches: [ main, master, dev, 'feat/**' ] pull_request: branches: [ main, master, dev ] + workflow_dispatch: jobs: build-riscv-polarfire: @@ -262,3 +263,180 @@ jobs: - name: Run Deterministic Headless Renode Test run: | python3 targets/STMicroelectronics/NUCLEO_F401RE/scripts/test_renode.py + + build-arm-nxp: + name: Build NXP i.MX RT1064 (ARM Cortex-M7) + runs-on: ubuntu-24.04 + + env: + GCC_VERSION: 14.3.rel1 + GCC_TARGET: arm-none-eabi + CMSIS_VERSION: 5.9.0 + NXP_DFP_VERSION: 15.1.0 + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install CMake and Ninja + run: | + sudo apt-get update + sudo apt-get install -y cmake ninja-build + + - name: Cache the Arm GNU toolchain + id: cache-arm-gcc + uses: actions/cache@v4 + with: + path: toolchain + key: arm-gnu-toolchain-${{ env.GCC_VERSION }}-x86_64-${{ env.GCC_TARGET }} + + - name: Install the Arm GNU toolchain + if: steps.cache-arm-gcc.outputs.cache-hit != 'true' + run: | + set -eu + base="https://developer.arm.com/-/media/Files/downloads/gnu/${GCC_VERSION}/binrel" + archive="arm-gnu-toolchain-${GCC_VERSION}-x86_64-${GCC_TARGET}.tar.xz" + mkdir -p toolchain && cd toolchain + curl -fsSLO "$base/$archive" + curl -fsSLO "$base/$archive.sha256asc" + sha256sum -c "$archive.sha256asc" + tar xf "$archive" + rm -f "$archive" + + - name: Put the toolchain on PATH + run: | + set -eu + echo "$GITHUB_WORKSPACE/toolchain/arm-gnu-toolchain-${GCC_VERSION}-x86_64-${GCC_TARGET}/bin" >> "$GITHUB_PATH" + + - name: Report the toolchain version + run: ${{ env.GCC_TARGET }}-gcc --version + + - name: Cache NXP SDK & CMSIS Dependencies + id: cache-nxp-sdk + uses: actions/cache@v4 + with: + path: targets/NXP/MIMXRT1064-EVK/lib/mcux-sdk + key: nxp-sdk-${{ env.NXP_DFP_VERSION }}-cmsis-${{ env.CMSIS_VERSION }}-${{ hashFiles('targets/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh') }} + + - name: Fetch NXP SDK & CMSIS Dependencies + if: steps.cache-nxp-sdk.outputs.cache-hit != 'true' + run: | + bash targets/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh + + - name: Build All NXP MIMXRT1064-EVK Demos + run: | + bash targets/NXP/MIMXRT1064-EVK/scripts/build.sh --demo all --rebuild + + - name: Verify Built NXP ELFs + run: | + test -f targets/NXP/MIMXRT1064-EVK/build/app/demos/threadx_basic/mimxrt1064_threadx.elf + test -f targets/NXP/MIMXRT1064-EVK/build/app/demos/netx_echo/mimxrt1064_threadx.elf + test -f targets/NXP/MIMXRT1064-EVK/build/app/demos/netx_echo/mimxrt1064_client.elf + test -f targets/NXP/MIMXRT1064-EVK/build/app/demos/netx_trng_console/mimxrt1064_threadx.elf + test -f targets/NXP/MIMXRT1064-EVK/build/app/demos/netx_trng_console/mimxrt1064_client.elf + echo "[OK] All NXP MIMXRT1064-EVK demo ELFs verified." + + - name: Archive Built NXP ELFs + uses: actions/upload-artifact@v4 + with: + name: nxp-mimxrt1064-demo-elfs + path: targets/NXP/MIMXRT1064-EVK/build/app/demos/ + retention-days: 1 + + test-nxp-renode: + name: Headless Renode Emulation & Assertion Test (NXP i.MX RT1064) + needs: build-arm-nxp + runs-on: ubuntu-24.04 + timeout-minutes: 15 + env: + RENODE_VERSION: 1.16.1 + RENODE_SHA256: 1a532d4b5b82de0dd154970c401e0c7b0e498d17304b2cecc007e306c8f9617c + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Set Up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Download Built NXP ELFs + uses: actions/download-artifact@v4 + with: + name: nxp-mimxrt1064-demo-elfs + path: targets/NXP/MIMXRT1064-EVK/build/app/demos + + - name: Inspect Downloaded ELF Artifacts + run: | + echo "=== Extracted NXP Demo ELF Artifacts ===" + ls -laR targets/NXP/MIMXRT1064-EVK/build/app/demos/ + + - name: Cache the portable Renode environment + id: cache-renode + uses: actions/cache@v4 + with: + path: ~/renode + key: renode-${{ env.RENODE_VERSION }}-linux-portable + + - name: Install Pinned Portable Renode Emulation Environment + if: steps.cache-renode.outputs.cache-hit != 'true' + run: | + set -euo pipefail + TARBALL="renode-${RENODE_VERSION}.linux-portable.tar.gz" + wget -q "https://github.com/renode/renode/releases/download/v${RENODE_VERSION}/${TARBALL}" + echo "${RENODE_SHA256} ${TARBALL}" | sha256sum --check --strict + mkdir -p $HOME/renode + tar -xzf "${TARBALL}" -C $HOME/renode --strip-components=1 + rm "${TARBALL}" + + - name: Install Renode System Prerequisites + run: | + sudo apt-get update -qq + sudo apt-get install -y -qq libx11-6 libxkbcommon-x11-0 libxcb1 strace + + - name: Put Renode on PATH + run: echo "$HOME/renode" >> $GITHUB_PATH + + - name: Link Renode Scripts & Dependencies + run: | + ln -sf $HOME/renode/scripts $HOME/renode/bin/scripts 2>/dev/null || true + ln -sf $HOME/renode/platforms $HOME/renode/bin/platforms 2>/dev/null || true + + - name: Report Runner Environment & Diagnostics + run: | + echo "=== System Architecture & Kernel ===" + uname -a + lsb_release -a + echo "=== Renode Version ===" + renode --version + echo "=== Python Version ===" + python3 --version + + + - name: Run Deterministic Headless Renode Test (threadx_basic) + run: | + python3 targets/NXP/MIMXRT1064-EVK/scripts/test_renode.py --demo threadx_basic + + - name: Run Deterministic Headless Renode Test (netx_echo) + run: | + python3 targets/NXP/MIMXRT1064-EVK/scripts/test_renode.py --demo netx_echo + + - name: Run Deterministic Headless Renode Test (netx_trng_console) + run: | + python3 targets/NXP/MIMXRT1064-EVK/scripts/test_renode.py --demo netx_trng_console --seed 12345 + + - name: Upload Renode Execution Logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: nxp-renode-execution-logs + path: | + targets/NXP/MIMXRT1064-EVK/build/*.log + targets/NXP/MIMXRT1064-EVK/*.log + if-no-files-found: ignore + diff --git a/targets/NXP/MIMXRT1064-EVK/.gitignore b/targets/NXP/MIMXRT1064-EVK/.gitignore new file mode 100644 index 00000000..c44f7285 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/.gitignore @@ -0,0 +1,10 @@ +# Build artifacts +build/ +*.elf +*.bin +*.hex +*.map + +# Downloaded SDK dependencies +lib/mcux-sdk/ +temp_fetch/ diff --git a/targets/NXP/MIMXRT1064-EVK/CMakeLists.txt b/targets/NXP/MIMXRT1064-EVK/CMakeLists.txt new file mode 100644 index 00000000..1e376aa5 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/CMakeLists.txt @@ -0,0 +1,166 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) +set(CMAKE_C_STANDARD 99) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Set the toolchain if not defined +if(NOT CMAKE_TOOLCHAIN_FILE) + set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_LIST_DIR}/cmake/arm-gcc-cortex-m7.cmake") +endif() + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) + +include(utilities) + +# Define the Project +project(mimxrt1064_threadx C CXX ASM) + +# Select demo to build: all (default), threadx_basic, netx_echo, netx_trng_console +set(ACTIVE_DEMO "all" CACHE STRING "Active demo name to build: all, netx_echo, netx_trng_console, threadx_basic") + +# Set up paths for MCUXpresso SDK +set(SDK_DIR "${CMAKE_CURRENT_LIST_DIR}/lib/mcux-sdk") +if(NOT EXISTS "${SDK_DIR}/devices/MIMXRT1064/MIMXRT1064.h") + message(FATAL_ERROR "NXP SDK dependencies missing! Please run 'scripts/fetch_sdk.ps1' or 'scripts/fetch_sdk.sh' first.") +endif() + +# Dynamic Middleware Configuration +if(NOT ACTIVE_DEMO STREQUAL "all" AND EXISTS "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/nx_user.h") + set(NX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/nx_user.h" CACHE STRING "Enable NetX Duo user configuration" FORCE) +else() + set(NX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/lib/netxduo/nx_user.h" CACHE STRING "Enable NetX Duo user configuration" FORCE) +endif() + +if(NOT ACTIVE_DEMO STREQUAL "all" AND EXISTS "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/tx_user.h") + set(TX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/tx_user.h" CACHE STRING "Enable TX user configuration" FORCE) + set(TX_USER_FILE_DIR "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}") +else() + set(TX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/lib/threadx/tx_user.h" CACHE STRING "Enable TX user configuration" FORCE) + set(TX_USER_FILE_DIR "${CMAKE_CURRENT_LIST_DIR}/lib/threadx") +endif() + +get_filename_component(WORKSPACE_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../.." ABSOLUTE) +set(SHARED_LIB_DIR "${WORKSPACE_ROOT}/libs") +set(SHARED_BSP_DIR "${WORKSPACE_ROOT}/bsp") + +# Compile ThreadX Kernel from root shared libs submodule +set(THREADX_DIR "${SHARED_LIB_DIR}/threadx") +add_subdirectory(${THREADX_DIR} threadx) + +# Compile NetX Duo TCP/IP Stack from root shared libs submodule (cached for networking demos) +set(NXD_ENABLE_FILE_SERVERS OFF CACHE BOOL "Disable FileX dependency in NetX Duo" FORCE) +set(NETXDUO_DIR "${SHARED_LIB_DIR}/netxduo") +add_subdirectory(${NETXDUO_DIR} netxduo) + +# Common board configuration interface carrying compile definitions and core SDK include directories +add_library(mimxrt1064_common INTERFACE) + +target_compile_definitions(mimxrt1064_common + INTERFACE + CPU_MIMXRT1064DVL6A + XIP_EXTERNAL_FLASH=1 + XIP_BOOT_HEADER_ENABLE=1 + XIP_BOOT_HEADER_DCD_ENABLE=1 + FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE=1 + SDK_DEBUGCONSOLE=1 + SKIP_SYSCLK_INIT=1 + __STARTUP_INITIALIZE_NONCACHEDATA=1 +) + +target_include_directories(mimxrt1064_common + INTERFACE + ${SDK_DIR}/CMSIS/Include + ${SDK_DIR}/devices/MIMXRT1064 + ${SDK_DIR}/drivers + ${SDK_DIR}/board + ${SDK_DIR}/utilities + ${SDK_DIR}/components/uart + ${CMAKE_CURRENT_LIST_DIR}/app + ${TX_USER_FILE_DIR} +) + +# Compile the NXP MCUXpresso Driver & Board Library as an Object Library +set(SDK_TARGET mcux_sdk) + +add_library(${SDK_TARGET} OBJECT + ${SDK_DIR}/devices/MIMXRT1064/system_MIMXRT1064.c + ${SDK_DIR}/devices/MIMXRT1064/fsl_flexspi_nor_boot.c + ${SDK_DIR}/drivers/fsl_clock.c + ${SDK_DIR}/drivers/fsl_common.c + ${SDK_DIR}/drivers/fsl_common_arm.c + ${SDK_DIR}/drivers/fsl_gpio.c + ${SDK_DIR}/drivers/fsl_lpuart.c + ${SDK_DIR}/board/board.c + ${SDK_DIR}/board/clock_config.c + ${SDK_DIR}/board/pin_mux.c + ${SDK_DIR}/board/dcd.c + ${SDK_DIR}/board/evkmimxrt1064_flexspi_nor_config.c + ${SDK_DIR}/utilities/fsl_debug_console.c + ${SDK_DIR}/utilities/fsl_str.c + ${SDK_DIR}/utilities/fsl_assert.c + ${SDK_DIR}/components/uart/fsl_adapter_lpuart.c +) + +target_link_libraries(${SDK_TARGET} + PUBLIC + mimxrt1064_common +) + +# 1. Define Board Support Package library +add_subdirectory(lib/bsp) + +# 2. Define NetX Duo driver library targets (cached for networking demos) +add_library(netx_imxrt_driver_common INTERFACE) + +target_include_directories(netx_imxrt_driver_common + INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/lib/netx_driver + ${CMAKE_CURRENT_LIST_DIR}/lib/phyksz8081 + ${CMAKE_CURRENT_LIST_DIR}/lib/netxduo +) + +target_compile_options(netx_imxrt_driver_common + INTERFACE + -Wno-unused-variable +) + +target_link_libraries(netx_imxrt_driver_common + INTERFACE + mimxrt1064_common + netxduo + threadx + mcux_sdk +) + +set(NETX_DRIVER_SOURCES + ${CMAKE_CURRENT_LIST_DIR}/lib/netx_driver/nx_driver_imxrt1062.c + ${CMAKE_CURRENT_LIST_DIR}/lib/netx_driver/gnu/nx_driver_imxrt1062_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/lib/phyksz8081/fsl_phy.c + ${SDK_DIR}/drivers/fsl_enet.c +) + +add_library(netx_imxrt_driver OBJECT ${NETX_DRIVER_SOURCES}) +target_link_libraries(netx_imxrt_driver PUBLIC netx_imxrt_driver_common) + +add_library(netx_imxrt_driver_client OBJECT ${NETX_DRIVER_SOURCES}) +target_link_libraries(netx_imxrt_driver_client PUBLIC netx_imxrt_driver_common) +target_compile_definitions(netx_imxrt_driver_client PUBLIC NETX_CLIENT_NODE=1) + +# 3. Add demo subdirectories to build executable targets +if(ACTIVE_DEMO STREQUAL "all") + add_subdirectory(app/demos/threadx_basic) + add_subdirectory(app/demos/netx_echo) + add_subdirectory(app/demos/netx_trng_console) +else() + add_subdirectory(app/demos/${ACTIVE_DEMO}) +endif() diff --git a/targets/NXP/MIMXRT1064-EVK/NOTICE.md b/targets/NXP/MIMXRT1064-EVK/NOTICE.md new file mode 100644 index 00000000..2aaba080 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/NOTICE.md @@ -0,0 +1,128 @@ +# Third-Party Software Notices + +This directory contains third-party software components included in the repository as well as build automation scripts and configurations that download and compile external dependencies. This notice lists the licenses and copyrights applicable to those components. + +--- + +## 1. NXP MCUXpresso SDK Drivers, Device Support & Startup Files +* **Source**: https://github.com/nxp-mcuxpresso/mcuxsdk-core / https://github.com/nxp-mcuxpresso/mcuxsdk-examples / https://mcuxpresso.nxp.com +* **Location**: `app/startup/startup_mimxrt1064.S`, `app/startup/MIMXRT1064xxxxx_flexspi_nor.ld`, and `lib/mcux-sdk/` +* **License**: BSD 3-Clause + +```text +Copyright (c) 2015-2016, Freescale Semiconductor, Inc. +Copyright 2018-2025 NXP + +The BSD 3 Clause License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +``` + +--- + +## 2. ARM CMSIS Core +* **Source**: https://github.com/ARM-software/CMSIS_5 +* **Location**: `lib/mcux-sdk/CMSIS/Include/` +* **License**: Apache License 2.0 + +```text +Copyright (c) 2009-2025 Arm Limited. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` + +--- + +## 3. NetX Duo NXP i.MX RT1062 Ethernet Driver +* **Source**: Eclipse ThreadX getting-started repository (`NXP/MIMXRT1060-EVK/lib/netx_driver`) +* **Location**: `lib/netx_driver/` +* **License**: MIT License +* **Copyright**: Copyright (c) 2024 Microsoft Corporation / Eclipse ThreadX contributors + +```text +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` + +--- + +## 4. NXP KSZ8081 PHY Driver +* **Source**: NXP MCUXpresso SDK / Freescale Semiconductor +* **Location**: `lib/phyksz8081/` +* **License**: BSD 3-Clause License +* **Copyright**: Copyright (c) 2015 Freescale Semiconductor, Inc., Copyright 2016-2020 NXP + +```text +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +``` diff --git a/targets/NXP/MIMXRT1064-EVK/README.md b/targets/NXP/MIMXRT1064-EVK/README.md new file mode 100644 index 00000000..0d104799 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/README.md @@ -0,0 +1,266 @@ +# NXP i.MX RT1064-EVK — Eclipse ThreadX & NetX Duo + +Welcome to the board enablement package for running **Eclipse ThreadX RTOS** and **NetX Duo** on the high-performance **NXP i.MX RT1064-EVK** (ARM Cortex-M7 @ 600 MHz). + +This target provides ready demos ranging from fundamental task scheduling and GPIO blinking to full multi-node TCP/IP networking and on-chip hardware cryptographic entropy. +The demos are testable on physical hardware or immediately on your workstation using **Antmicro Renode** system simulation. + +--- + +## Quick Start + +You don't need a physical board to get started! You can fetch dependencies, build all targets, and run the automated test suite in three simple steps: + +### 1. Prerequisites +Ensure you have the following installed on your machine: +* **ARM GNU Toolchain** (`arm-none-eabi-gcc` 10.3+) +* **CMake** (3.20+) and **Ninja** (recommended) or Make +* **Python 3** (3.8+, for automated Renode test runners) +* **Antmicro Renode** (1.15.3+, for simulation) +* **Git** (for repository submodules) + +### 2. Fetch Dependencies & Build +Download the official NXP MCUXpresso SDK drivers and build all demos: + +* **Windows (PowerShell)**: + ```powershell + # 1. Fetch NXP SDK peripheral drivers and CMSIS headers + powershell -ExecutionPolicy Bypass -File .\scripts\fetch_sdk.ps1 + + # 2. Build all demos + powershell -ExecutionPolicy Bypass -File .\scripts\build.ps1 + ``` + +* **Linux / macOS (Bash)**: + ```bash + # 1. Fetch NXP SDK peripheral drivers and CMSIS headers + chmod +x ./scripts/*.sh + ./scripts/fetch_sdk.sh + + # 2. Build all demos + ./scripts/build.sh + ``` + +> [!NOTE] +> The NetX Duo Ethernet driver (`lib/netx_driver`) and KSZ8081 PHY driver (`lib/phyksz8081`) are pre-vendored in this repository. `fetch_sdk` only downloads the official NXP core MCU peripheral drivers and CMSIS headers, verifying every archive against pinned SHA-256 checksums. + +### 3. Run Automated Tests +Verify that all demos build and pass under Renode simulation: +```bash +python ./scripts/test_renode.py --demo threadx_basic +python ./scripts/test_renode.py --demo netx_echo +python ./scripts/test_renode.py --demo netx_trng_console --seed 12345 +``` + +--- + +## Supported Applications + +The build system can compile all demos together (default) or individual demos on demand. Output artifacts are placed in `build/app/demos//`: + +| Application | Architecture | What It Demonstrates | Generated Binaries | +| :--- | :--- | :--- | :--- | +| **`threadx_basic`** | Single-Node | ThreadX kernel fundamentals: preemptive priority scheduling, software timer callbacks, and user LED (`D18`) heartbeat blinking. | `mimxrt1064_threadx.elf`
`mimxrt1064_threadx.bin` | +| **`netx_echo`** | Multi-Node | Full NetX Duo network stack: ARP resolution, ICMP ping replies, UDP datagram echo (port 7), and TCP stream echo (port 7). | `mimxrt1064_threadx.elf` *(Server: 192.168.0.100)*
`mimxrt1064_client.elf` *(Client: 192.168.0.101)* | +| **`netx_trng_console`** | Multi-Node | On-chip hardware True Random Number Generator (`0x400CC000`) integrated with an interactive TCP remote diagnostics management shell (port 23). | `mimxrt1064_threadx.elf` *(Server: 192.168.0.100)*
`mimxrt1064_client.elf` *(Client: 192.168.0.101)* | + +> [!NOTE] +> **How Multi-Node Verification Works**: +> In `netx_echo` and `netx_trng_console`, Renode boots **two independent virtual i.MX RT1064 machines** interconnected via a simulated Ethernet switch. The **server** node runs ThreadX services, while the **client** node runs an automated test suite that transmits network traffic. + +--- + +## Renode Simulation Guide + +Renode provides accurate instruction-level simulation of the ARM Cortex-M7 core and key peripherals, enabling end-to-end verification without hardware. + +### 1. Interactive Simulation (GUI) +Launch Renode with virtual serial terminal windows attached to the microcontroller's UART console: + +* **Windows (PowerShell)**: + ```powershell + # ThreadX Core Basic (single node) + powershell -ExecutionPolicy Bypass -File .\scripts\simulate.ps1 -Demo threadx_basic + + # NetX Duo Network Echo (multi-node server + client) + powershell -ExecutionPolicy Bypass -File .\scripts\simulate.ps1 -Demo netx_echo + + # Hardware TRNG Diagnostic Console (multi-node server + client) + powershell -ExecutionPolicy Bypass -File .\scripts\simulate.ps1 -Demo netx_trng_console + # You can specify a pseudo-random seed for reproducible test runs + powershell -ExecutionPolicy Bypass -File .\scripts\simulate.ps1 -Demo netx_trng_console -Seed 12345 + ``` + +* **Linux / macOS (Bash)**: + ```bash + # ThreadX Core Basic (single node) + ./scripts/simulate.sh -d threadx_basic + + # NetX Duo Network Echo (multi-node server + client) + ./scripts/simulate.sh -d netx_echo + + # Hardware TRNG Diagnostic Console (multi-node server + client) + ./scripts/simulate.sh -d netx_trng_console + # You can specify a pseudo-random seed for reproducible test runs + ./scripts/simulate.sh -d netx_trng_console -s 12345 + ``` + +### 2. Headless Automated Regression Testing (CI/CD) +Headless testing is designed for automated continuous integration pipelines. The runner boots the simulation, monitors the virtual UART logs, and exits with code `0` on success or code `1` on failure/timeout. + +#### Direct Python Runner (Matches CI): +```bash +# Verify ThreadX basic scheduling & timers +python ./scripts/test_renode.py --demo threadx_basic + +# Verify NetX Duo ICMP ping, UDP echo, and TCP echo +python ./scripts/test_renode.py --demo netx_echo + +# Verify Hardware TRNG entropy generation and remote console +python ./scripts/test_renode.py --demo netx_trng_console --seed 12345 +``` + +#### Convenience Shell Wrappers: +* **Windows (PowerShell)**: + ```powershell + powershell -ExecutionPolicy Bypass -File .\scripts\test_headless.ps1 -Demo threadx_basic + powershell -ExecutionPolicy Bypass -File .\scripts\test_headless.ps1 -Demo netx_echo + powershell -ExecutionPolicy Bypass -File .\scripts\test_headless.ps1 -Demo netx_trng_console -Seed 12345 + ``` +* **Linux / macOS (Bash)**: + ```bash + ./scripts/test_headless.sh --demo threadx_basic + ./scripts/test_headless.sh --demo netx_echo + ./scripts/test_headless.sh --demo netx_trng_console --seed 12345 + ``` + +--- + +## Simulation Scope & Hardware Status + +> [!WARNING] +> **Hardware Status: Verified in simulation, not yet on physical silicon.** +> All automated tests in this repository currently run under **Antmicro Renode** system emulation. + +### What Renode Accurately Simulates: +* **Boot & Vector Table**: Boots from simulated FlexSPI NOR Flash into Cortex-M7 privileged mode. +* **ThreadX RTOS Kernel**: Preemptive priority scheduling, thread synchronization (mutexes, semaphores), and software timer ticks. +* **NetX Duo Networking**: Ethernet MAC (`ENET`) DMA transfers, ARP cache handling, ICMP ping replies, UDP socket datagrams, and TCP stream connections. + +### What Renode Stubs: +* **Clock Tree & PLLs**: Renode uses stub tags for the Clock Control Module (`CCM`) and `ANALOG` power blocks. Registers return fixed default values (e.g. `CCM_CBCDR` returns `0x000A8200`), so PLL lock loops succeed unconditionally without exercising analog timing. +* **Core Frequency**: The `600 MHz` banner in the console is a compile-time SDK constant (`SystemCoreClock`), not a measured silicon frequency. +* **Pin Multiplexing**: `IOMUXC` and `IOMUXC_GPR` writes are acknowledged without modeling electrical pin drive strengths or pin collisions. +* **TRNG Bring-up and Entropy Semantics**: Renode's `IMX_TRNG` model implements neither the programming sequence nor the block-consume semantics, and logs `Unhandled write` for `MCTL[PRGM]`, `MCTL[RST_DEF]` and `SDCTL[SAMP_SIZE]`/`SDCTL[ENT_DLY]`. It also returns a fresh pseudo-random word on *any* `ENT[n]` read, whereas silicon refills the block only when `ENT15` is read and re-arms `ENT_VAL`. The driver follows the reference manual on both points, but the emulator would accept a driver that does neither, so this is the part of the target most in need of a run on real hardware. + +--- + +## Target Hardware & Flashing Guide + +If you are flashing to a physical **NXP MIMXRT1064-EVK** board: + +### Hardware Specifications +* **Evaluation Board**: NXP MIMXRT1064-EVK (ARM Cortex-M7 @ up to 600 MHz) +* **Memory**: 4 MB on-chip FlexSPI NOR Flash (`0x70000000`), 1 MB on-chip SRAM (ITCM, DTCM, NonCacheable OCRAM) +* **Serial Console**: LPUART1 via OpenSDA micro-USB (`J41`), 115,200 baud, 8N1 +* **User LED & Button**: Green LED `D18` (`GPIO1_IO09`), SW8 WAKEUP button (`GPIO5_IO00`) +* **Ethernet**: ENET MAC + Microchip KSZ8081RNA PHY via RMII +* **TRNG Hardware**: On-chip True Random Number Generator (`0x400CC000`) + +### Boot Switch Configuration +Set boot switches **SW7** for **Internal Boot (FlexSPI NOR Flash)**: +* `SW7-1`: OFF +* `SW7-2`: ON +* `SW7-3`: OFF +* `SW7-4`: ON + +### Flashing Methods + +#### Option 1: OpenSDA Drag-and-Drop (Fastest) +1. Connect micro-USB cable to `J41` on the EVK board. +2. The board mounts as a USB drive named `RT1064-EVK`. +3. Copy `build/app/demos//mimxrt1064_threadx.bin` and paste it directly onto the drive. +4. The OpenSDA LED blinks rapidly during flashing. Press `SW3` (RESET) to boot. + +#### Option 2: SEGGER J-Link +```text +JLink.exe -device MIMXRT1064xxx6A -if SWD -speed 4000 -autoconnect 1 +loadfile build/app/demos//mimxrt1064_threadx.hex +r +g +``` + +#### Option 3: pyOCD Command Line +```bash +pip install pyocd && pyocd pack install MIMXRT1064 +pyocd flash -t mimxrt1064 build/app/demos//mimxrt1064_threadx.hex +``` + +#### Option 4: NXP MCUXpresso IDE / GUI Flash Tool +1. In MCUXpresso IDE, select **GUI Flash Tool** from the toolbar. +2. Choose target device `MIMXRT1064xxxxA` and memory `PROGRAM_FLASH` (`0x70000000`). +3. Select `build/app/demos//mimxrt1064_threadx.elf` and click **Program**. + +--- + +## Software Architecture & Developer Guide + +### Modular BSP Architecture +The target features a decoupled, three-tier design: +* **`mimxrt1064_bsp`**: Clean C hardware abstraction layer (`bsp/board.h`, `bsp/led.h`, `bsp/console.h`). Application code interacts solely through BSP APIs rather than raw vendor registers. +* **`board_bsp`**: Startup assembly (`startup_mimxrt1064.S`), low-level ThreadX initialization (`tx_initialize_low_level.S`), newlib standard C library syscalls (`_sbrk` heap protection), and hardware TRNG drivers. +* **`mimxrt1064_common`**: Central CMake `INTERFACE` library propagating required MCU compiler definitions (`CPU_MIMXRT1064DVL6A`, `XIP_EXTERNAL_FLASH=1`, etc.) and SDK include directories to all targets automatically. + +### Adding a Custom Demo in 4 Steps + +#### Step 1: Create the Demo Directory +Create a folder under `app/demos/` (e.g., `app/demos/my_new_demo/`). + +#### Step 2: Write Application Code (`main.c`) +```c +#include "bsp/board.h" +#include "bsp/led.h" +#include "bsp/console.h" +#include "tx_api.h" + +int main(void) +{ + /* Initialize MPU, system clocks, pins, LED, and console */ + bsp_board_init(); + + /* Enter ThreadX RTOS Kernel */ + tx_kernel_enter(); + return 0; +} +``` + +#### Step 3: Create `CMakeLists.txt` +Thanks to CMake target inheritance, you only need to link `board_bsp`, `threadx`, and `mcux_sdk` — all compiler definitions and SDK include paths are inherited automatically: +```cmake +set(DEMO_TARGET "demo_my_new_demo") +add_executable(${DEMO_TARGET} main.c) +set_target_properties(${DEMO_TARGET} PROPERTIES OUTPUT_NAME "mimxrt1064_threadx") + +# Only private demo includes are needed; SDK headers and board definitions +# are inherited automatically from board_bsp. +target_include_directories(${DEMO_TARGET} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_link_libraries(${DEMO_TARGET} PRIVATE + board_bsp + threadx + mcux_sdk + # netxduo # Uncomment if using network stack + # netx_imxrt_driver # Uncomment if using network driver +) + +set_target_linker(${DEMO_TARGET} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") +post_build(${DEMO_TARGET}) +``` + +#### Step 4: Build and Simulate +```bash +cmake -B build -G Ninja -DACTIVE_DEMO=my_new_demo +cmake --build build +``` diff --git a/targets/NXP/MIMXRT1064-EVK/app/MIMXRT1062.h b/targets/NXP/MIMXRT1064-EVK/app/MIMXRT1062.h new file mode 100644 index 00000000..344898f4 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/MIMXRT1062.h @@ -0,0 +1,33 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +/* + * Compatibility header: redirects MIMXRT1062.h from stock NetX Duo driver + * to MIMXRT1064 device registers without modifying vendor source files. + */ +#ifndef MIMXRT1062_H +#define MIMXRT1062_H + +#include "fsl_device_registers.h" + +/* + * Assign distinct MAC addresses to server and client nodes + * to prevent address collision on the Renode virtual switch. + */ +#if defined(NETX_CLIENT_NODE) +#define NX_DRIVER_ETHERNET_MAC {0x02, 0x11, 0x22, 0x33, 0x44, 0x53} +#else +#define NX_DRIVER_ETHERNET_MAC {0x02, 0x11, 0x22, 0x33, 0x44, 0x52} +#endif + +#endif /* MIMXRT1062_H */ diff --git a/targets/NXP/MIMXRT1064-EVK/app/ansi_colors.h b/targets/NXP/MIMXRT1064-EVK/app/ansi_colors.h new file mode 100644 index 00000000..5b448d0c --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/ansi_colors.h @@ -0,0 +1,46 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#ifndef ANSI_COLORS_H +#define ANSI_COLORS_H + +/* ANSI Terminal Escape Codes for Colored Serial Output */ +#define ANSI_RESET "\x1b[0m" +#define ANSI_BOLD "\x1b[1m" + +/* Standard Primary Colors for Banners */ +#define ANSI_RED "\x1b[31m" +#define ANSI_GREEN "\x1b[32m" +#define ANSI_YELLOW "\x1b[33m" +#define ANSI_BLUE "\x1b[34m" +#define ANSI_MAGENTA "\x1b[35m" +#define ANSI_CYAN "\x1b[36m" +#define ANSI_WHITE "\x1b[37m" + +/* Subsystem Tags: Muted Slate Gray (256-color 243) */ +#define TAG_SYSTEM "\x1b[38;5;243m[System]" +#define TAG_HAL "\x1b[38;5;243m[HAL]" +#define TAG_NETWORK "\x1b[38;5;243m[NetX]" +#define TAG_NET_THREAD "\x1b[38;5;243m[Network Thread]" +#define TAG_ECHO "\x1b[38;5;243m[Echo]" +#define TAG_SERVER "\x1b[38;5;243m[Server]" +#define TAG_CLIENT "\x1b[38;5;243m[Client]" + +/* Message Colors: Soft, pastel feedback colors */ +#define MSG_INFO "\x1b[38;5;250m" /* Soft White/Gray for normal logs */ +#define MSG_SUCCESS "\x1b[38;5;114m" /* Soft Pastel Green for success */ +#define MSG_WARNING "\x1b[38;5;215m" /* Muted Gold/Orange for warnings */ +#define MSG_ERROR "\x1b[38;5;203m" /* Muted Coral/Red for failures */ +#define MSG_METRIC "\x1b[38;5;111m" /* Soft Sky Blue for data/measurements */ + +#endif /* ANSI_COLORS_H */ diff --git a/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/CMakeLists.txt b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/CMakeLists.txt new file mode 100644 index 00000000..f060bf47 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/CMakeLists.txt @@ -0,0 +1,70 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +# Server Executable Target (mimxrt1064_threadx) +set(SERVER_TARGET "demo_netx_echo_server") +add_executable(${SERVER_TARGET} + main.c +) +set_target_properties(${SERVER_TARGET} PROPERTIES OUTPUT_NAME "mimxrt1064_threadx") + +# Include paths for server +target_include_directories(${SERVER_TARGET} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} +) + +# Link libraries for server +target_link_libraries(${SERVER_TARGET} + PRIVATE + board_bsp + threadx + netxduo + netx_imxrt_driver + mcux_sdk +) + +# Apply GCC linker script and post-build outputs for server +set_target_linker(${SERVER_TARGET} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") +post_build(${SERVER_TARGET}) + +# Automated Verification Client Executable Target (mimxrt1064_client) +set(CLIENT_TARGET "demo_netx_echo_client") +add_executable(${CLIENT_TARGET} + client_main.c +) +set_target_properties(${CLIENT_TARGET} PROPERTIES OUTPUT_NAME "mimxrt1064_client") + +# Set compile definitions for client +target_compile_definitions(${CLIENT_TARGET} + PRIVATE + NETX_CLIENT_NODE=1 +) + +# Include paths for client +target_include_directories(${CLIENT_TARGET} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} +) + +# Link libraries for client +target_link_libraries(${CLIENT_TARGET} + PRIVATE + board_bsp + threadx + netxduo + netx_imxrt_driver_client + mcux_sdk +) + +# Apply GCC linker script and post-build outputs for client +set_target_linker(${CLIENT_TARGET} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") +post_build(${CLIENT_TARGET}) diff --git a/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/client_main.c b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/client_main.c new file mode 100644 index 00000000..745fe0e8 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/client_main.c @@ -0,0 +1,357 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#include +#include +#include +#include +#include "bsp/board.h" +#include "bsp/led.h" +#include "bsp/console.h" +#include "board_config.h" +#include "tx_api.h" +#include "nx_api.h" +#include "ansi_colors.h" + +#define DEMO_STACK_SIZE 2048 +#define PACKET_SIZE 1536 +#define PACKET_POOL_SIZE (PACKET_SIZE * 24) +#define ECHO_SERVER_PORT 7 +#define ARP_CACHE_SIZE 1024 + +/* Static IP Configuration for Automated Verification Client */ +#define CLIENT_IP_ADDRESS IP_ADDRESS(192, 168, 0, 101) +#define SERVER_IP_ADDRESS IP_ADDRESS(192, 168, 0, 100) +#define NETWORK_MASK_VAL IP_ADDRESS(255, 255, 255, 0) +#define GATEWAY_ADDRESS_VAL IP_ADDRESS(192, 168, 0, 1) + +static TX_THREAD client_thread; +static ULONG client_thread_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; + +static ULONG ip_thread_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static uint8_t arp_cache_area[ARP_CACHE_SIZE]; + +static NX_PACKET_POOL client_pool; +static NX_IP client_ip; + +/* Place the NetX Duo packet pool in the NonCacheable section to ensure DMA coherency */ +__attribute__((section("NonCacheable"), aligned(64))) +static uint8_t packet_pool_area[PACKET_POOL_SIZE]; + +/* External hardware driver entry point for NXP i.MX RT ENET MAC */ +extern VOID nx_driver_imx(NX_IP_DRIVER *driver_req_ptr); + +static void client_thread_entry(ULONG thread_input); + +int main(void) +{ + /* Initialize hardware via BSP interface */ + bsp_board_init(); + + printf(ANSI_BOLD ANSI_CYAN "\r\n==================================================\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN " Eclipse ThreadX & NetX Duo on NXP i.MX RT1064-EVK\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN " Automated Network Verification Client (Renode)\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN "==================================================\r\n\r\n" ANSI_RESET); + + printf(TAG_SYSTEM " " MSG_INFO "Core Clock: %lu MHz | Tick Rate: %u Hz\r\n" ANSI_RESET, + SystemCoreClock / 1000000UL, TX_TIMER_TICKS_PER_SECOND); + + /* Enter ThreadX kernel */ + tx_kernel_enter(); + + return 0; +} + +void tx_application_define(void *first_unused_memory) +{ + (void)first_unused_memory; + UINT status; + + printf(TAG_CLIENT " " MSG_INFO "Initializing NetX Duo System...\r\n" ANSI_RESET); + nx_system_initialize(); + + /* 1. Create packet pool in NonCacheable memory */ + status = nx_packet_pool_create(&client_pool, "Client Packet Pool", + PACKET_SIZE, packet_pool_area, PACKET_POOL_SIZE); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR "Failed to create packet pool: 0x%02X\r\n" ANSI_RESET, status); + return; + } + printf(TAG_CLIENT " " MSG_SUCCESS "Packet pool created (size: %u bytes in NonCacheable memory)\r\n" ANSI_RESET, + (unsigned int)sizeof(packet_pool_area)); + + /* 2. Create IP instance using the NXP i.MX RT ENET driver */ + status = nx_ip_create(&client_ip, "NetX Client IP", CLIENT_IP_ADDRESS, + NETWORK_MASK_VAL, &client_pool, nx_driver_imx, + ip_thread_stack, DEMO_STACK_SIZE, 1); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR "Failed to create IP instance: 0x%02X\r\n" ANSI_RESET, status); + return; + } + printf(TAG_CLIENT " " MSG_SUCCESS "IP instance created (192.168.0.101)\r\n" ANSI_RESET); + + /* 3. Set Gateway Address */ + nx_ip_gateway_address_set(&client_ip, GATEWAY_ADDRESS_VAL); + + /* 4. Enable ARP */ + printf(TAG_CLIENT " " MSG_INFO "Enabling ARP...\r\n" ANSI_RESET); + status = nx_arp_enable(&client_ip, (VOID *)arp_cache_area, ARP_CACHE_SIZE); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR "Failed to enable ARP: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 5. Enable ICMP (Ping) */ + printf(TAG_CLIENT " " MSG_INFO "Enabling ICMP...\r\n" ANSI_RESET); + status = nx_icmp_enable(&client_ip); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR "Failed to enable ICMP: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 6. Enable UDP */ + printf(TAG_CLIENT " " MSG_INFO "Enabling UDP...\r\n" ANSI_RESET); + status = nx_udp_enable(&client_ip); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR "Failed to enable UDP: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 7. Enable TCP */ + printf(TAG_CLIENT " " MSG_INFO "Enabling TCP...\r\n" ANSI_RESET); + status = nx_tcp_enable(&client_ip); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR "Failed to enable TCP: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 8. Start Automated Verification Thread */ + tx_thread_create(&client_thread, "Client Verification Thread", client_thread_entry, 0, + client_thread_stack, DEMO_STACK_SIZE, 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START); + + printf(TAG_CLIENT " " MSG_SUCCESS "Verification thread registered.\r\n" ANSI_RESET); +} + +static void client_thread_entry(ULONG thread_input) +{ + (void)thread_input; + ULONG actual_status = 0; + UINT status; + int test_ping_passed = 0; + int test_udp_passed = 0; + int test_tcp_passed = 0; + + printf(TAG_CLIENT " " MSG_INFO "Bringing Ethernet Link UP...\r\n" ANSI_RESET); + status = nx_ip_driver_direct_command(&client_ip, NX_LINK_ENABLE, &actual_status); + if (status == NX_SUCCESS || status == NX_ALREADY_ENABLED) + { + printf(TAG_CLIENT " " MSG_SUCCESS "Ethernet link is UP!\r\n" ANSI_RESET); + } + else + { + printf(TAG_CLIENT " " MSG_WARNING "nx_ip_driver_direct_command NX_LINK_ENABLE status: 0x%02X\r\n" ANSI_RESET, status); + } + + /* Allow network stack and server node to settle */ + printf(TAG_CLIENT " " MSG_INFO "Waiting for network convergence...\r\n" ANSI_RESET); + tx_thread_sleep(150); + + printf("\r\n" ANSI_BOLD ANSI_CYAN "==================================================\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN " Starting Multi-Node Network Verification Suite\r\n" ANSI_RESET); + printf(ANSI_CYAN " Target Echo Server: 192.168.0.100 (Port 7)\r\n" ANSI_RESET); + printf(ANSI_CYAN " Local Client Node: 192.168.0.101\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN "==================================================\r\n\r\n" ANSI_RESET); + + /* ------------------------------------------------------------------ + * Test 1: ICMP Ping (Echo Request & Reply) + * ------------------------------------------------------------------ */ + printf(TAG_CLIENT " [Test 1/3] Testing ICMP Ping to 192.168.0.100...\r\n"); + NX_PACKET *ping_response = NX_NULL; + status = nx_icmp_ping(&client_ip, SERVER_IP_ADDRESS, "ThreadX_Ping", 12, &ping_response, 200); + if (status == NX_SUCCESS && ping_response != NX_NULL) + { + printf(TAG_CLIENT " " MSG_SUCCESS "[PASS] ICMP Ping successful! Response received from 192.168.0.100\r\n" ANSI_RESET); + nx_packet_release(ping_response); + test_ping_passed = 1; + } + else + { + printf(TAG_CLIENT " " MSG_ERROR "[FAIL] ICMP Ping timed out or failed: status 0x%02X\r\n" ANSI_RESET, status); + } + + /* Small delay between tests */ + tx_thread_sleep(50); + + /* ------------------------------------------------------------------ + * Test 2: UDP Echo (Datagram Tx & Rx on Port 7) + * ------------------------------------------------------------------ */ + printf("\r\n" TAG_CLIENT " [Test 2/3] Testing UDP Echo on port 7...\r\n"); + NX_UDP_SOCKET udp_client_socket; + status = nx_udp_socket_create(&client_ip, &udp_client_socket, "Client UDP Socket", + NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5); + if (status == NX_SUCCESS) + { + status = nx_udp_socket_bind(&udp_client_socket, NX_ANY_PORT, TX_WAIT_FOREVER); + if (status == NX_SUCCESS) + { + NX_PACKET *tx_packet = NX_NULL; + if (nx_packet_allocate(&client_pool, &tx_packet, NX_UDP_PACKET, TX_WAIT_FOREVER) == NX_SUCCESS) + { + const char *udp_payload = "Hello ThreadX UDP Echo!"; + status = nx_packet_data_append(tx_packet, (VOID *)udp_payload, strlen(udp_payload), &client_pool, TX_WAIT_FOREVER); + if (status == NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_INFO "Sent UDP payload: '%s'\r\n" ANSI_RESET, udp_payload); + status = nx_udp_socket_send(&udp_client_socket, tx_packet, SERVER_IP_ADDRESS, ECHO_SERVER_PORT); + } + if (status != NX_SUCCESS) + { + nx_packet_release(tx_packet); + printf(TAG_CLIENT " " MSG_ERROR "[FAIL] Failed to send UDP packet: 0x%02X\r\n" ANSI_RESET, status); + } + else + { + NX_PACKET *rx_packet = NX_NULL; + status = nx_udp_socket_receive(&udp_client_socket, &rx_packet, 200); + if (status == NX_SUCCESS && rx_packet != NX_NULL) + { + CHAR rx_buf[128]; + ULONG bytes_copied = 0; + + /* Bounded extract: a response longer than the buffer is truncated. */ + nx_packet_data_extract_offset(rx_packet, 0, rx_buf, + (ULONG)(sizeof(rx_buf) - 1), &bytes_copied); + rx_buf[bytes_copied] = '\0'; + printf(TAG_CLIENT " " MSG_SUCCESS "[PASS] Received UDP Echo: '%s' (%lu bytes)\r\n" ANSI_RESET, + rx_buf, bytes_copied); + nx_packet_release(rx_packet); + test_udp_passed = 1; + } + else + { + printf(TAG_CLIENT " " MSG_ERROR "[FAIL] UDP Echo receive timed out or failed: 0x%02X\r\n" ANSI_RESET, status); + } + } + } + nx_udp_socket_unbind(&udp_client_socket); + } + nx_udp_socket_delete(&udp_client_socket); + } + else + { + printf(TAG_CLIENT " " MSG_ERROR "[FAIL] Failed to create UDP socket: 0x%02X\r\n" ANSI_RESET, status); + } + + /* Small delay between tests */ + tx_thread_sleep(50); + + /* ------------------------------------------------------------------ + * Test 3: TCP Echo (Connection, Stream Tx & Rx on Port 7) + * ------------------------------------------------------------------ */ + printf("\r\n" TAG_CLIENT " [Test 3/3] Testing TCP Echo on port 7...\r\n"); + NX_TCP_SOCKET tcp_client_socket; + status = nx_tcp_socket_create(&client_ip, &tcp_client_socket, "Client TCP Socket", + NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 512, NX_NULL, NX_NULL); + if (status == NX_SUCCESS) + { + status = nx_tcp_client_socket_bind(&tcp_client_socket, NX_ANY_PORT, TX_WAIT_FOREVER); + if (status == NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_INFO "Connecting to 192.168.0.100:7...\r\n" ANSI_RESET); + status = nx_tcp_client_socket_connect(&tcp_client_socket, SERVER_IP_ADDRESS, ECHO_SERVER_PORT, 200); + if (status == NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_SUCCESS "TCP Connected! Sending stream payload...\r\n" ANSI_RESET); + NX_PACKET *tx_packet = NX_NULL; + if (nx_packet_allocate(&client_pool, &tx_packet, NX_TCP_PACKET, TX_WAIT_FOREVER) == NX_SUCCESS) + { + const char *tcp_payload = "Hello ThreadX TCP Echo!"; + status = nx_packet_data_append(tx_packet, (VOID *)tcp_payload, strlen(tcp_payload), &client_pool, TX_WAIT_FOREVER); + if (status == NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_INFO "Sent TCP payload: '%s'\r\n" ANSI_RESET, tcp_payload); + status = nx_tcp_socket_send(&tcp_client_socket, tx_packet, 200); + } + if (status != NX_SUCCESS) + { + nx_packet_release(tx_packet); + printf(TAG_CLIENT " " MSG_ERROR "[FAIL] Failed to send TCP packet: 0x%02X\r\n" ANSI_RESET, status); + } + else + { + NX_PACKET *rx_packet = NX_NULL; + status = nx_tcp_socket_receive(&tcp_client_socket, &rx_packet, 200); + if (status == NX_SUCCESS && rx_packet != NX_NULL) + { + CHAR rx_buf[128]; + ULONG bytes_copied = 0; + + /* Bounded extract: a response longer than the buffer is truncated. */ + nx_packet_data_extract_offset(rx_packet, 0, rx_buf, + (ULONG)(sizeof(rx_buf) - 1), &bytes_copied); + rx_buf[bytes_copied] = '\0'; + printf(TAG_CLIENT " " MSG_SUCCESS "[PASS] Received TCP Echo: '%s' (%lu bytes)\r\n" ANSI_RESET, + rx_buf, bytes_copied); + nx_packet_release(rx_packet); + test_tcp_passed = 1; + } + else + { + printf(TAG_CLIENT " " MSG_ERROR "[FAIL] TCP Echo receive timed out or failed: 0x%02X\r\n" ANSI_RESET, status); + } + } + } + nx_tcp_socket_disconnect(&tcp_client_socket, 100); + } + else + { + printf(TAG_CLIENT " " MSG_ERROR "[FAIL] TCP connect to 192.168.0.100:7 failed: 0x%02X\r\n" ANSI_RESET, status); + } + nx_tcp_client_socket_unbind(&tcp_client_socket); + } + nx_tcp_socket_delete(&tcp_client_socket); + } + else + { + printf(TAG_CLIENT " " MSG_ERROR "[FAIL] Failed to create TCP socket: 0x%02X\r\n" ANSI_RESET, status); + } + + /* ------------------------------------------------------------------ + * Verification Summary + * ------------------------------------------------------------------ */ + printf("\r\n" ANSI_BOLD "==================================================\r\n" ANSI_RESET); + if (test_ping_passed && test_udp_passed && test_tcp_passed) + { + printf(ANSI_BOLD ANSI_GREEN " [VERIFICATION SUCCESS] ALL NETWORK TESTS PASSED!\r\n" ANSI_RESET); + printf(ANSI_GREEN " - [PASS] ICMP Ping (Echo Request & Reply)\r\n" ANSI_RESET); + printf(ANSI_GREEN " - [PASS] UDP Echo (Datagram Tx & Rx)\r\n" ANSI_RESET); + printf(ANSI_GREEN " - [PASS] TCP Echo (Connection, Stream Tx & Rx)\r\n" ANSI_RESET); + } + else + { + printf(ANSI_BOLD ANSI_RED " [VERIFICATION INCOMPLETE] SOME TESTS FAILED!\r\n" ANSI_RESET); + if (!test_ping_passed) printf(ANSI_RED " - [FAIL] ICMP Ping\r\n" ANSI_RESET); + if (!test_udp_passed) printf(ANSI_RED " - [FAIL] UDP Echo\r\n" ANSI_RESET); + if (!test_tcp_passed) printf(ANSI_RED " - [FAIL] TCP Echo\r\n" ANSI_RESET); + } + printf(ANSI_BOLD "==================================================\r\n\r\n" ANSI_RESET); + + /* Heartbeat loop */ + while (1) + { + tx_thread_sleep(50); + bsp_led_toggle(); + } +} diff --git a/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/main.c b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/main.c new file mode 100644 index 00000000..b77f521e --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/main.c @@ -0,0 +1,342 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#include +#include +#include +#include "bsp/board.h" +#include "bsp/led.h" +#include "bsp/console.h" +#include "board_config.h" +#include "tx_api.h" +#include "nx_api.h" +#include "ansi_colors.h" + +#define DEMO_STACK_SIZE 2048 +#define PACKET_SIZE 1536 +#define PACKET_POOL_SIZE (PACKET_SIZE * 24) +#define ECHO_SERVER_PORT 7 +#define ARP_CACHE_SIZE 1024 + +/* Static IP Configuration for Renode Simulation & Physical Testing */ +#define IP_ADDRESS_VAL IP_ADDRESS(192, 168, 0, 100) +#define NETWORK_MASK_VAL IP_ADDRESS(255, 255, 255, 0) +#define GATEWAY_ADDRESS_VAL IP_ADDRESS(192, 168, 0, 1) + +static TX_THREAD monitor_thread; +static ULONG monitor_thread_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; + +static TX_THREAD udp_echo_thread; +static ULONG udp_echo_thread_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; + +static TX_THREAD tcp_echo_thread; +static ULONG tcp_echo_thread_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; + +static ULONG ip_thread_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static uint8_t arp_cache_area[ARP_CACHE_SIZE]; + +static NX_PACKET_POOL pool_0; +static NX_IP ip_0; + +/* Place the NetX Duo packet pool in the NonCacheable section to ensure DMA coherency */ +__attribute__((section("NonCacheable"), aligned(64))) +static uint8_t packet_pool_area[PACKET_POOL_SIZE]; + +/* External hardware driver entry point for NXP i.MX RT ENET MAC */ +extern VOID nx_driver_imx(NX_IP_DRIVER *driver_req_ptr); + +static void monitor_thread_entry(ULONG thread_input); +static void udp_echo_thread_entry(ULONG thread_input); +static void tcp_echo_thread_entry(ULONG thread_input); + +int main(void) +{ + /* Initialize hardware via BSP interface */ + bsp_board_init(); + + printf(ANSI_BOLD ANSI_CYAN "\r\n==================================================\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN " Eclipse ThreadX & NetX Duo on NXP i.MX RT1064-EVK\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN " Virtual Ethernet Networking & Echo Demo (Renode)\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN "==================================================\r\n\r\n" ANSI_RESET); + + printf(TAG_SYSTEM " " MSG_INFO "Core Clock: %lu MHz | Tick Rate: %u Hz\r\n" ANSI_RESET, + SystemCoreClock / 1000000UL, TX_TIMER_TICKS_PER_SECOND); + + /* Enter ThreadX kernel */ + tx_kernel_enter(); + + return 0; +} + +void tx_application_define(void *first_unused_memory) +{ + (void)first_unused_memory; + UINT status; + + printf(TAG_NETWORK " " MSG_INFO "Initializing NetX Duo System...\r\n" ANSI_RESET); + nx_system_initialize(); + + /* 1. Create packet pool in NonCacheable memory */ + status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", + PACKET_SIZE, packet_pool_area, PACKET_POOL_SIZE); + if (status != NX_SUCCESS) + { + printf(TAG_NETWORK " " MSG_ERROR "Failed to create packet pool: 0x%02X\r\n" ANSI_RESET, status); + return; + } + printf(TAG_NETWORK " " MSG_SUCCESS "Packet pool created (size: %u bytes in NonCacheable memory)\r\n" ANSI_RESET, + (unsigned int)sizeof(packet_pool_area)); + + /* 2. Create IP instance using the NXP i.MX RT ENET driver */ + status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS_VAL, + NETWORK_MASK_VAL, &pool_0, nx_driver_imx, + ip_thread_stack, DEMO_STACK_SIZE, 1); + if (status != NX_SUCCESS) + { + printf(TAG_NETWORK " " MSG_ERROR "Failed to create IP instance: 0x%02X\r\n" ANSI_RESET, status); + return; + } + printf(TAG_NETWORK " " MSG_SUCCESS "IP instance created\r\n" ANSI_RESET); + + /* 3. Set Gateway Address */ + nx_ip_gateway_address_set(&ip_0, GATEWAY_ADDRESS_VAL); + + /* 4. Enable ARP */ + printf(TAG_NETWORK " " MSG_INFO "Enabling ARP...\r\n" ANSI_RESET); + status = nx_arp_enable(&ip_0, (VOID *)arp_cache_area, ARP_CACHE_SIZE); + if (status != NX_SUCCESS) + { + printf(TAG_NETWORK " " MSG_ERROR "Failed to enable ARP: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 5. Enable ICMP (Ping) */ + printf(TAG_NETWORK " " MSG_INFO "Enabling ICMP (Ping responder)...\r\n" ANSI_RESET); + status = nx_icmp_enable(&ip_0); + if (status != NX_SUCCESS) + { + printf(TAG_NETWORK " " MSG_ERROR "Failed to enable ICMP: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 6. Enable UDP */ + printf(TAG_NETWORK " " MSG_INFO "Enabling UDP...\r\n" ANSI_RESET); + status = nx_udp_enable(&ip_0); + if (status != NX_SUCCESS) + { + printf(TAG_NETWORK " " MSG_ERROR "Failed to enable UDP: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 7. Enable TCP */ + printf(TAG_NETWORK " " MSG_INFO "Enabling TCP...\r\n" ANSI_RESET); + status = nx_tcp_enable(&ip_0); + if (status != NX_SUCCESS) + { + printf(TAG_NETWORK " " MSG_ERROR "Failed to enable TCP: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 8. Start Monitor / Heartbeat Thread */ + tx_thread_create(&monitor_thread, "Network Monitor", monitor_thread_entry, 0, + monitor_thread_stack, DEMO_STACK_SIZE, 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* 9. Start UDP Echo Server Thread */ + tx_thread_create(&udp_echo_thread, "UDP Echo Thread", udp_echo_thread_entry, 0, + udp_echo_thread_stack, DEMO_STACK_SIZE, 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* 10. Start TCP Echo Server Thread */ + tx_thread_create(&tcp_echo_thread, "TCP Echo Thread", tcp_echo_thread_entry, 0, + tcp_echo_thread_stack, DEMO_STACK_SIZE, 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START); + + printf(TAG_NETWORK " " MSG_SUCCESS "All network threads registered successfully.\r\n" ANSI_RESET); +} + +static void monitor_thread_entry(ULONG thread_input) +{ + (void)thread_input; + ULONG ip_address = 0; + ULONG network_mask = 0; + ULONG actual_status = 0; + uint8_t led_state = 0; + + printf(TAG_NETWORK " " MSG_INFO "Bringing Ethernet Link UP...\r\n" ANSI_RESET); + UINT status = nx_ip_driver_direct_command(&ip_0, NX_LINK_ENABLE, &actual_status); + if (status == NX_SUCCESS || status == NX_ALREADY_ENABLED) + { + printf(TAG_NETWORK " " MSG_SUCCESS "Ethernet link is UP!\r\n" ANSI_RESET); + } + else + { + printf(TAG_NETWORK " " MSG_WARNING "nx_ip_driver_direct_command NX_LINK_ENABLE status: 0x%02X\r\n" ANSI_RESET, status); + } + + nx_ip_address_get(&ip_0, &ip_address, &network_mask); + printf("\r\n" ANSI_BOLD ANSI_GREEN "================ Network Ready ================\r\n" ANSI_RESET); + printf(ANSI_GREEN " Static IPv4 : %lu.%lu.%lu.%lu\r\n" ANSI_RESET, + (ip_address >> 24) & 0xFF, (ip_address >> 16) & 0xFF, + (ip_address >> 8) & 0xFF, ip_address & 0xFF); + printf(ANSI_GREEN " Subnet Mask : %lu.%lu.%lu.%lu\r\n" ANSI_RESET, + (network_mask >> 24) & 0xFF, (network_mask >> 16) & 0xFF, + (network_mask >> 8) & 0xFF, network_mask & 0xFF); + printf(ANSI_GREEN " Services : ICMP Ping, UDP Echo (Port 7), TCP Echo (Port 7)\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_GREEN "===============================================\r\n\r\n" ANSI_RESET); + + while (1) + { + /* Sleep 500 ms (50 ticks) */ + tx_thread_sleep(50); + + /* Toggle User LED to indicate active heartbeat */ + bsp_led_toggle(); + led_state = !led_state; + } +} + +static void udp_echo_thread_entry(ULONG thread_input) +{ + NX_UDP_SOCKET udp_socket; + NX_PACKET *rx_packet; + UINT status; + + (void)thread_input; + + status = nx_udp_socket_create(&ip_0, &udp_socket, "UDP Echo Socket", + NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5); + if (status != NX_SUCCESS) + { + printf(TAG_ECHO " " MSG_ERROR "Failed to create UDP socket: 0x%02X\r\n" ANSI_RESET, status); + return; + } + + status = nx_udp_socket_bind(&udp_socket, ECHO_SERVER_PORT, TX_WAIT_FOREVER); + if (status != NX_SUCCESS) + { + printf(TAG_ECHO " " MSG_ERROR "Failed to bind UDP port %u: 0x%02X\r\n" ANSI_RESET, ECHO_SERVER_PORT, status); + nx_udp_socket_delete(&udp_socket); + return; + } + + printf(TAG_ECHO " " MSG_INFO "UDP Echo Server listening on port %d\r\n" ANSI_RESET, ECHO_SERVER_PORT); + + while (1) + { + status = nx_udp_socket_receive(&udp_socket, &rx_packet, TX_WAIT_FOREVER); + if (status == NX_SUCCESS) + { + ULONG peer_ip = 0; + UINT peer_port = 0; + nx_udp_source_extract(rx_packet, &peer_ip, &peer_port); + + printf(TAG_ECHO " " MSG_SUCCESS "UDP Rx from %lu.%lu.%lu.%lu:%u (%lu bytes), echoing...\r\n" ANSI_RESET, + (peer_ip >> 24) & 0xFF, (peer_ip >> 16) & 0xFF, + (peer_ip >> 8) & 0xFF, peer_ip & 0xFF, + peer_port, rx_packet->nx_packet_length); + + /* Allocate a response packet from the pool */ + NX_PACKET *tx_packet = NX_NULL; + if (nx_packet_allocate(&pool_0, &tx_packet, NX_UDP_PACKET, TX_NO_WAIT) == NX_SUCCESS) + { + CHAR echo_buf[512]; + ULONG bytes_copied = 0; + if (rx_packet->nx_packet_length <= sizeof(echo_buf) && + nx_packet_data_retrieve(rx_packet, echo_buf, &bytes_copied) == NX_SUCCESS) + { + status = nx_packet_data_append(tx_packet, echo_buf, bytes_copied, &pool_0, TX_NO_WAIT); + if (status == NX_SUCCESS) + { + status = nx_udp_socket_send(&udp_socket, tx_packet, peer_ip, peer_port); + } + if (status != NX_SUCCESS) + { + nx_packet_release(tx_packet); + } + } + else + { + nx_packet_release(tx_packet); + } + } + + /* Release the received packet */ + nx_packet_release(rx_packet); + } + } +} + +static void tcp_echo_thread_entry(ULONG thread_input) +{ + NX_TCP_SOCKET echo_socket; + NX_PACKET *packet_ptr; + UINT status; + + (void)thread_input; + + status = nx_tcp_socket_create(&ip_0, &echo_socket, "TCP Echo Socket", + NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, + 512, NX_NULL, NX_NULL); + if (status != NX_SUCCESS) + { + printf(TAG_ECHO " " MSG_ERROR "Failed to create TCP socket: 0x%02X\r\n" ANSI_RESET, status); + return; + } + + printf(TAG_ECHO " " MSG_INFO "TCP Echo Server listening on port %d\r\n" ANSI_RESET, ECHO_SERVER_PORT); + + while (1) + { + status = nx_tcp_server_socket_listen(&ip_0, ECHO_SERVER_PORT, &echo_socket, 5, NX_NULL); + if (status != NX_SUCCESS) + { + nx_tcp_server_socket_unlisten(&ip_0, ECHO_SERVER_PORT); + tx_thread_sleep(10); + continue; + } + + if (nx_tcp_server_socket_accept(&echo_socket, NX_WAIT_FOREVER) == NX_SUCCESS) + { + printf(TAG_ECHO " " MSG_SUCCESS "TCP Client connected.\r\n" ANSI_RESET); + + while (nx_tcp_socket_receive(&echo_socket, &packet_ptr, NX_WAIT_FOREVER) == NX_SUCCESS) + { + printf(TAG_ECHO " " MSG_SUCCESS "TCP Rx %lu bytes, echoing...\r\n" ANSI_RESET, + packet_ptr->nx_packet_length); + NX_PACKET *tx_packet = NX_NULL; + if (nx_packet_allocate(&pool_0, &tx_packet, NX_TCP_PACKET, TX_WAIT_FOREVER) == NX_SUCCESS) + { + CHAR echo_buf[512]; + ULONG bytes_copied = 0; + if (packet_ptr->nx_packet_length <= sizeof(echo_buf) && + nx_packet_data_retrieve(packet_ptr, echo_buf, &bytes_copied) == NX_SUCCESS) + { + status = nx_packet_data_append(tx_packet, echo_buf, bytes_copied, &pool_0, TX_WAIT_FOREVER); + if (status == NX_SUCCESS) + { + status = nx_tcp_socket_send(&echo_socket, tx_packet, TX_WAIT_FOREVER); + } + if (status != NX_SUCCESS) + { + nx_packet_release(tx_packet); + } + } + else + { + nx_packet_release(tx_packet); + } + } + nx_packet_release(packet_ptr); + } + + printf(TAG_ECHO " " MSG_WARNING "TCP Client disconnected.\r\n" ANSI_RESET); + nx_tcp_socket_disconnect(&echo_socket, NX_WAIT_FOREVER); + nx_tcp_server_socket_unaccept(&echo_socket); + } + nx_tcp_server_socket_unlisten(&ip_0, ECHO_SERVER_PORT); + } +} diff --git a/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/test_echo.ps1 b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/test_echo.ps1 new file mode 100644 index 00000000..cf1e5d0a --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/test_echo.ps1 @@ -0,0 +1,131 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +param ( + [string]$IP = "192.168.0.100", + [int]$Port = 7 +) + +Write-Host "==========================================" -ForegroundColor Cyan +Write-Host " NetX Duo Virtual Networking Verification" -ForegroundColor Cyan +Write-Host " Target Device: $IP (Port: $Port)" -ForegroundColor Cyan +Write-Host "==========================================" -ForegroundColor Cyan +Write-Host "" + +$AllPassed = $true + +# ---------------------------------------------------- +# Test 1: ICMP Ping +# ---------------------------------------------------- +Write-Host "[Test 1/3] Testing ICMP Ping (Echo Request)..." -ForegroundColor Yellow +$PingSuccess = $false +try { + $pingRes = Test-Connection -ComputerName $IP -Count 2 -Quiet -ErrorAction Stop + if ($pingRes) { + $PingSuccess = $true + } +} catch { + # Fallback to ping.exe + $res = ping -n 2 -w 1000 $IP + if ($LASTEXITCODE -eq 0) { + $PingSuccess = $true + } +} + +if ($PingSuccess) { + Write-Host "[PASS] ICMP Ping responded successfully from $IP" -ForegroundColor Green +} else { + Write-Host "[FAIL] ICMP Ping timed out or failed to reach $IP" -ForegroundColor Red + $AllPassed = $false +} +Write-Host "" + +# ---------------------------------------------------- +# Test 2: UDP Echo +# ---------------------------------------------------- +Write-Host "[Test 2/3] Testing UDP Echo on port $Port..." -ForegroundColor Yellow +$UdpClient = New-Object System.Net.Sockets.UdpClient +$UdpClient.Client.ReceiveTimeout = 3000 + +$UdpMsg = "Hello ThreadX UDP Echo!" +$UdpBytes = [System.Text.Encoding]::ASCII.GetBytes($UdpMsg) + +try { + $UdpClient.Connect($IP, $Port) + [void]$UdpClient.Send($UdpBytes, $UdpBytes.Length) + Write-Host "Sent UDP: '$UdpMsg'" + + $RemoteEndpoint = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Any, 0) + $ReceivedBytes = $UdpClient.Receive([ref]$RemoteEndpoint) + $ReceivedMsg = [System.Text.Encoding]::ASCII.GetString($ReceivedBytes) + Write-Host "Received UDP: '$ReceivedMsg'" + + if ($ReceivedMsg -eq $UdpMsg) { + Write-Host "[PASS] UDP Echo verified successfully!" -ForegroundColor Green + } else { + Write-Host "[FAIL] UDP payload mismatch: expected '$UdpMsg', got '$ReceivedMsg'" -ForegroundColor Red + $AllPassed = $false + } +} catch { + Write-Host "[FAIL] UDP Echo failed: $_" -ForegroundColor Red + $AllPassed = $false +} finally { + $UdpClient.Close() +} +Write-Host "" + +# ---------------------------------------------------- +# Test 3: TCP Echo +# ---------------------------------------------------- +Write-Host "[Test 3/3] Testing TCP Echo on port $Port..." -ForegroundColor Yellow +$TcpClient = $null +try { + $TcpClient = New-Object System.Net.Sockets.TcpClient + $TcpClient.ReceiveTimeout = 3000 + $TcpClient.SendTimeout = 3000 + $TcpClient.Connect($IP, $Port) + + $Stream = $TcpClient.GetStream() + $Writer = New-Object System.IO.StreamWriter($Stream) + $Reader = New-Object System.IO.StreamReader($Stream) + + $TcpMsg = "Hello ThreadX TCP Echo!" + Write-Host "Sent TCP: '$TcpMsg'" + $Writer.WriteLine($TcpMsg) + $Writer.Flush() + + $TcpResponse = $Reader.ReadLine() + Write-Host "Received TCP: '$TcpResponse'" + + if ($TcpResponse -eq $TcpMsg) { + Write-Host "[PASS] TCP Echo verified successfully!" -ForegroundColor Green + } else { + Write-Host "[FAIL] TCP payload mismatch: expected '$TcpMsg', got '$TcpResponse'" -ForegroundColor Red + $AllPassed = $false + } +} catch { + Write-Host "[FAIL] TCP Echo failed: $_" -ForegroundColor Red + $AllPassed = $false +} finally { + if ($TcpClient) { $TcpClient.Close() } +} +Write-Host "" + +# ---------------------------------------------------- +# Summary +# ---------------------------------------------------- +Write-Host "==========================================" -ForegroundColor Cyan +if ($AllPassed) { + Write-Host " ALL TESTS PASSED! NetX Duo is fully verified." -ForegroundColor Green +} else { + Write-Host " SOME TESTS FAILED. Verify Renode TAP and network connection." -ForegroundColor Red +} +Write-Host "==========================================" -ForegroundColor Cyan diff --git a/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/test_echo.sh b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/test_echo.sh new file mode 100644 index 00000000..ec316cec --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/test_echo.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +set -e + +IP=${1:-"192.168.0.100"} +PORT=7 + +echo "==========================================" +echo " NetX Duo Virtual Networking Verification" +echo " Target Device: ${IP} (Port: ${PORT})" +echo "==========================================" +echo "" + +ALL_PASSED=1 + +# 1. ICMP Ping Test +echo "[Test 1/3] Testing ICMP Ping (Echo Request)..." +if ping -c 2 -W 2 "${IP}" > /dev/null 2>&1; then + echo "[PASS] ICMP Ping responded successfully from ${IP}" +else + echo "[FAIL] ICMP Ping timed out or failed to reach ${IP}" + ALL_PASSED=0 +fi +echo "" + +# 2. UDP Echo Test +echo "[Test 2/3] Testing UDP Echo on port ${PORT}..." +UDP_MSG="Hello ThreadX UDP Echo!" +UDP_RES=$(python3 -c " +import socket, sys +try: + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.settimeout(3.0) + s.sendto(b'${UDP_MSG}', ('${IP}', ${PORT})) + data, _ = s.recvfrom(1024) + print(data.decode('ascii', errors='ignore')) +except Exception as e: + sys.exit(1) +finally: + s.close() +" 2>/dev/null || true) + +if [ "${UDP_RES}" = "${UDP_MSG}" ]; then + echo "Sent UDP: '${UDP_MSG}'" + echo "Received UDP: '${UDP_RES}'" + echo "[PASS] UDP Echo verified successfully!" +else + echo "[FAIL] UDP Echo failed (got '${UDP_RES}')" + ALL_PASSED=0 +fi +echo "" + +# 3. TCP Echo Test +echo "[Test 3/3] Testing TCP Echo on port ${PORT}..." +TCP_MSG="Hello ThreadX TCP Echo!" +TCP_RES=$(python3 -c " +import socket, sys +try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(3.0) + s.connect(('${IP}', ${PORT})) + s.sendall(b'${TCP_MSG}\n') + data = s.recv(1024) + print(data.decode('ascii', errors='ignore').strip()) +except Exception as e: + sys.exit(1) +finally: + s.close() +" 2>/dev/null || true) + +if [ "${TCP_RES}" = "${TCP_MSG}" ]; then + echo "Sent TCP: '${TCP_MSG}'" + echo "Received TCP: '${TCP_RES}'" + echo "[PASS] TCP Echo verified successfully!" +else + echo "[FAIL] TCP Echo failed (got '${TCP_RES}')" + ALL_PASSED=0 +fi +echo "" + +echo "==========================================" +if [ "${ALL_PASSED}" -eq 1 ]; then + echo " ALL TESTS PASSED! NetX Duo is fully verified." +else + echo " SOME TESTS FAILED. Verify Renode TAP and network connection." +fi +echo "==========================================" diff --git a/targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/CMakeLists.txt b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/CMakeLists.txt new file mode 100644 index 00000000..14c28d2f --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/CMakeLists.txt @@ -0,0 +1,70 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +# Server Executable Target (mimxrt1064_threadx) +set(SERVER_TARGET "demo_netx_trng_server") +add_executable(${SERVER_TARGET} + main.c +) +set_target_properties(${SERVER_TARGET} PROPERTIES OUTPUT_NAME "mimxrt1064_threadx") + +# Include paths for server +target_include_directories(${SERVER_TARGET} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} +) + +# Link libraries for server +target_link_libraries(${SERVER_TARGET} + PRIVATE + board_bsp + threadx + netxduo + netx_imxrt_driver + mcux_sdk +) + +# Apply GCC linker script and post-build outputs for server +set_target_linker(${SERVER_TARGET} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") +post_build(${SERVER_TARGET}) + +# Automated Verification Client Executable Target (mimxrt1064_client) +set(CLIENT_TARGET "demo_netx_trng_client") +add_executable(${CLIENT_TARGET} + client_main.c +) +set_target_properties(${CLIENT_TARGET} PROPERTIES OUTPUT_NAME "mimxrt1064_client") + +# Set compile definitions for client +target_compile_definitions(${CLIENT_TARGET} + PRIVATE + NETX_CLIENT_NODE=1 +) + +# Include paths for client +target_include_directories(${CLIENT_TARGET} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} +) + +# Link libraries for client +target_link_libraries(${CLIENT_TARGET} + PRIVATE + board_bsp + threadx + netxduo + netx_imxrt_driver_client + mcux_sdk +) + +# Apply GCC linker script and post-build outputs for client +set_target_linker(${CLIENT_TARGET} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") +post_build(${CLIENT_TARGET}) diff --git a/targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/client_main.c b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/client_main.c new file mode 100644 index 00000000..42eeca31 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/client_main.c @@ -0,0 +1,359 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) + */ + +#include +#include +#include +#include +#include "bsp/board.h" +#include "bsp/led.h" +#include "bsp/console.h" +#include "board_config.h" +#include "ansi_colors.h" +#include "tx_api.h" +#include "nx_api.h" + +#define DEMO_STACK_SIZE 2048 +#define PACKET_SIZE 1536 +#define PACKET_POOL_SIZE ((PACKET_SIZE + sizeof(NX_PACKET)) * 24) +#define ARP_CACHE_SIZE 512 +#define CONSOLE_SERVER_PORT 23 + +#define CLIENT_IP_ADDRESS_VAL IP_ADDRESS(192, 168, 0, 101) +#define SERVER_IP_ADDRESS IP_ADDRESS(192, 168, 0, 100) +#define NETWORK_MASK_VAL IP_ADDRESS(255, 255, 255, 0) +#define GATEWAY_ADDRESS_VAL IP_ADDRESS(192, 168, 0, 1) + + + +static ULONG client_ip_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG client_test_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG client_arp_cache[ARP_CACHE_SIZE / sizeof(ULONG)]; + +__attribute__((section(".NonCacheable"))) +static uint8_t client_packet_pool_area[PACKET_POOL_SIZE]; + +static NX_PACKET_POOL client_pool; +static NX_IP client_ip; +static TX_THREAD client_test_thread; + +VOID nx_driver_imx(NX_IP_DRIVER *driver_req_ptr); +static void client_test_thread_entry(ULONG thread_input); + +int main(void) +{ + bsp_board_init(); + + printf(ANSI_BOLD ANSI_YELLOW "\r\n==================================================\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_YELLOW " MIMXRT1064 TRNG & Console Verification Client\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_YELLOW " Running on Simulated Node 2 (192.168.0.101)\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_YELLOW "==================================================\r\n\r\n" ANSI_RESET); + + tx_kernel_enter(); + + return 0; +} + +void tx_application_define(void *first_unused_memory) +{ + (void)first_unused_memory; + UINT status; + + nx_system_initialize(); + + status = nx_packet_pool_create(&client_pool, "Client Packet Pool", + PACKET_SIZE, client_packet_pool_area, PACKET_POOL_SIZE); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR " Failed to create packet pool: 0x%02X\r\n", status); + return; + } + + status = nx_ip_create(&client_ip, "Client IP", CLIENT_IP_ADDRESS_VAL, + NETWORK_MASK_VAL, &client_pool, nx_driver_imx, + client_ip_stack, DEMO_STACK_SIZE, 1); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR " Failed to create IP instance: 0x%02X\r\n", status); + return; + } + + nx_ip_gateway_address_set(&client_ip, GATEWAY_ADDRESS_VAL); + nx_arp_enable(&client_ip, (VOID *)client_arp_cache, ARP_CACHE_SIZE); + nx_icmp_enable(&client_ip); + nx_tcp_enable(&client_ip); + + status = tx_thread_create(&client_test_thread, "Client Test Thread", + client_test_thread_entry, 0, + client_test_stack, DEMO_STACK_SIZE, + 10, 10, TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR " Failed to create test thread: 0x%02X\r\n", status); + } +} + +static UINT send_and_receive(NX_TCP_SOCKET *socket, const char *cmd, char *rx_buf, size_t rx_buf_size, ULONG timeout) +{ + NX_PACKET *tx_packet = NX_NULL; + NX_PACKET *rx_packet = NX_NULL; + UINT status; + + status = nx_packet_allocate(&client_pool, &tx_packet, NX_TCP_PACKET, TX_WAIT_FOREVER); + if (status != NX_SUCCESS) + { + return status; + } + + status = nx_packet_data_append(tx_packet, (VOID *)cmd, strlen(cmd), &client_pool, TX_WAIT_FOREVER); + if (status != NX_SUCCESS) + { + nx_packet_release(tx_packet); + return status; + } + + status = nx_tcp_socket_send(socket, tx_packet, TX_WAIT_FOREVER); + if (status != NX_SUCCESS) + { + nx_packet_release(tx_packet); + return status; + } + + status = nx_tcp_socket_receive(socket, &rx_packet, timeout); + if (status == NX_SUCCESS && rx_packet != NX_NULL) + { + ULONG bytes_copied = 0; + + /* Bounded extract: a response longer than the buffer is truncated. */ + nx_packet_data_extract_offset(rx_packet, 0, rx_buf, + (ULONG)(rx_buf_size - 1), &bytes_copied); + rx_buf[bytes_copied] = '\0'; + nx_packet_release(rx_packet); + } + return status; +} + +static void client_test_thread_entry(ULONG thread_input) +{ + (void)thread_input; + UINT status; + ULONG actual_status; + int all_passed = 1; + char buffer[256]; + + printf(TAG_CLIENT " " MSG_INFO " Bringing Ethernet Link UP...\r\n"); + status = nx_ip_driver_direct_command(&client_ip, NX_LINK_ENABLE, &actual_status); + if (status == NX_SUCCESS || status == NX_ALREADY_ENABLED) + { + printf(TAG_CLIENT " " MSG_SUCCESS " Ethernet link is UP!\r\n"); + } + + printf(TAG_CLIENT " " MSG_INFO " Waiting for network convergence...\r\n"); + tx_thread_sleep(150); + + printf("\r\n" ANSI_BOLD ANSI_CYAN "==================================================\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN " Starting Hardware TRNG & Console Verification Suite\r\n" ANSI_RESET); + printf(ANSI_CYAN " Target Server: 192.168.0.100 (Port %d)\r\n" ANSI_RESET, CONSOLE_SERVER_PORT); + printf(ANSI_BOLD ANSI_CYAN "==================================================\r\n\r\n" ANSI_RESET); + + /* Test 1: ICMP Ping */ + printf(TAG_CLIENT " [Test 1/6] Testing ICMP Ping to 192.168.0.100...\r\n"); + NX_PACKET *ping_resp = NX_NULL; + status = nx_icmp_ping(&client_ip, SERVER_IP_ADDRESS, "TRNG_Ping", 9, &ping_resp, 200); + if (status == NX_SUCCESS && ping_resp != NX_NULL) + { + printf(TAG_CLIENT " " MSG_SUCCESS " ICMP Ping successful! Response from 192.168.0.100\r\n"); + nx_packet_release(ping_resp); + } + else + { + printf(TAG_CLIENT " " MSG_ERROR " ICMP Ping failed: 0x%02X\r\n", status); + all_passed = 0; + } + + tx_thread_sleep(30); + + /* Test 2: Connect to TCP Port 23 */ + printf("\r\n" TAG_CLIENT " [Test 2/6] Connecting to TRNG Console Server on port %d...\r\n", CONSOLE_SERVER_PORT); + NX_TCP_SOCKET client_socket; + status = nx_tcp_socket_create(&client_ip, &client_socket, "Client Shell Socket", + NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, + 512, NX_NULL, NX_NULL); + if (status != NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_ERROR " Failed to create TCP socket: 0x%02X\r\n", status); + return; + } + + nx_tcp_client_socket_bind(&client_socket, NX_ANY_PORT, TX_WAIT_FOREVER); + status = nx_tcp_client_socket_connect(&client_socket, SERVER_IP_ADDRESS, CONSOLE_SERVER_PORT, 200); + if (status == NX_SUCCESS) + { + printf(TAG_CLIENT " " MSG_SUCCESS " TCP Connected! Receiving greeting banner...\r\n"); + + /* Receive welcome banner */ + NX_PACKET *banner_packet = NX_NULL; + if (nx_tcp_socket_receive(&client_socket, &banner_packet, 100) == NX_SUCCESS) + { + nx_packet_release(banner_packet); + } + + /* Test 3: Query Hardware TRNG Entropy */ + printf("\r\n" TAG_CLIENT " [Test 3/6] Querying on-chip TRNG entropy ('trng')...\r\n"); + memset(buffer, 0, sizeof(buffer)); + status = send_and_receive(&client_socket, "trng\r\n", buffer, sizeof(buffer), 200); + + char *entropy_str = (status == NX_SUCCESS) ? strstr(buffer, "[TRNG] Hardware Entropy:") : NX_NULL; + if (entropy_str != NX_NULL) + { + const char *vals_str = entropy_str + strlen("[TRNG] Hardware Entropy:"); + unsigned long w1 = 0, w2 = 0, w3 = 0, w4 = 0; + int parsed = sscanf(vals_str, "%lx %lx %lx %lx", &w1, &w2, &w3, &w4); + + if (parsed != 4) + { + printf(TAG_CLIENT " " MSG_ERROR " Assertion failed: Expected 4 entropy words, parsed %d\r\n", parsed); + all_passed = 0; + } + else if (w1 == 0 && w2 == 0 && w3 == 0 && w4 == 0) + { + printf(TAG_CLIENT " " MSG_ERROR " Assertion failed: All 4 entropy words are zero (0x00000000)\r\n"); + all_passed = 0; + } + else if (w1 == w2 || w1 == w3 || w1 == w4 || w2 == w3 || w2 == w4 || w3 == w4) + { + printf(TAG_CLIENT " " MSG_ERROR " Assertion failed: Entropy words are not distinct (0x%08lX 0x%08lX 0x%08lX 0x%08lX)\r\n", + w1, w2, w3, w4); + all_passed = 0; + } + else + { + printf(TAG_CLIENT " " MSG_SUCCESS " Hardware TRNG Entropy Received:\r\n %s", buffer); + printf(TAG_CLIENT " " MSG_SUCCESS " Entropy words verified: 4 words parsed, non-zero, all mutually distinct.\r\n"); + + /* Renode's PRNG is deterministic, so under --seed 12345 these four + words are a known sequence. Real silicon will not match them. */ + const unsigned long seed_12345_w1 = 0x69D43FF3UL; + const unsigned long seed_12345_w2 = 0x54E900EEUL; + const unsigned long seed_12345_w3 = 0x2514F462UL; + const unsigned long seed_12345_w4 = 0x39F5B5D8UL; + + if (w1 == seed_12345_w1 && w2 == seed_12345_w2 && w3 == seed_12345_w3 && w4 == seed_12345_w4) + { + printf(TAG_CLIENT " " MSG_SUCCESS " Deterministic seed (12345) PRNG sequence verified exactly!\r\n"); + } + else + { + printf(TAG_CLIENT " Entropy does not match the seed-12345 reference sequence, which is expected on hardware or under another seed.\r\n"); + } + } + } + else + { + printf(TAG_CLIENT " " MSG_ERROR " TRNG query failed (status: 0x%02X, response: '%s')\r\n", status, buffer); + all_passed = 0; + } + + /* Test 4: Remote LED Control */ + printf("\r\n" TAG_CLIENT " [Test 4/6] Testing Remote LED Control ('led toggle')...\r\n"); + memset(buffer, 0, sizeof(buffer)); + status = send_and_receive(&client_socket, "led toggle\r\n", buffer, sizeof(buffer), 200); + if (status == NX_SUCCESS && strstr(buffer, "[LED] State: TOGGLED")) + { + printf(TAG_CLIENT " " MSG_SUCCESS " Remote LED toggle acknowledged by server!\r\n"); + } + else + { + printf(TAG_CLIENT " " MSG_ERROR " LED control failed (status: 0x%02X)\r\n", status); + all_passed = 0; + } + + /* Test 5: Target Info Query */ + printf("\r\n" TAG_CLIENT " [Test 5/6] Querying processor and RTOS status ('info')...\r\n"); + memset(buffer, 0, sizeof(buffer)); + status = send_and_receive(&client_socket, "info\r\n", buffer, sizeof(buffer), 200); + if (status == NX_SUCCESS && strstr(buffer, "MIMXRT1064-EVK")) + { + printf(TAG_CLIENT " " MSG_SUCCESS " Processor & ThreadX status verified:\r\n %s", buffer); + } + else + { + printf(TAG_CLIENT " " MSG_ERROR " Info query failed (status: 0x%02X)\r\n", status); + all_passed = 0; + } + + /* Test 6: an over-long line is refused and the session survives it */ + printf("\r\n" TAG_CLIENT " [Test 6/6] Testing over-long command line rejection...\r\n"); + { + char long_cmd[200]; + + memset(long_cmd, 'A', sizeof(long_cmd) - 3); + long_cmd[sizeof(long_cmd) - 3] = '\r'; + long_cmd[sizeof(long_cmd) - 2] = '\n'; + long_cmd[sizeof(long_cmd) - 1] = '\0'; + + memset(buffer, 0, sizeof(buffer)); + status = send_and_receive(&client_socket, long_cmd, buffer, sizeof(buffer), 200); + + if (status == NX_SUCCESS && strstr(buffer, "Command line too long")) + { + memset(buffer, 0, sizeof(buffer)); + status = send_and_receive(&client_socket, "ping\r\n", buffer, sizeof(buffer), 200); + if (status == NX_SUCCESS && strstr(buffer, "[PONG]")) + { + printf(TAG_CLIENT " " MSG_SUCCESS " Over-long line refused, session still responsive.\r\n"); + } + else + { + printf(TAG_CLIENT " " MSG_ERROR " Session unresponsive after over-long line (status: 0x%02X)\r\n", status); + all_passed = 0; + } + } + else + { + printf(TAG_CLIENT " " MSG_ERROR " Over-long line was not refused (status: 0x%02X, response: '%s')\r\n", + status, buffer); + all_passed = 0; + } + } + + /* Graceful disconnect */ + send_and_receive(&client_socket, "quit\r\n", buffer, sizeof(buffer), 50); + nx_tcp_socket_disconnect(&client_socket, 10); + } + else + { + printf(TAG_CLIENT " " MSG_ERROR " Failed to connect to server: 0x%02X\r\n", status); + all_passed = 0; + } + + nx_tcp_client_socket_unbind(&client_socket); + nx_tcp_socket_delete(&client_socket); + + printf("\r\n==================================================\r\n"); + if (all_passed) + { + printf(ANSI_BOLD ANSI_GREEN " [VERIFICATION SUCCESS] ALL TRNG & CONSOLE TESTS PASSED!\r\n" ANSI_RESET); + } + else + { + printf(ANSI_BOLD ANSI_RED " [VERIFICATION FAILED] One or more tests failed.\r\n" ANSI_RESET); + } + printf("==================================================\r\n\r\n"); + + while (1) + { + tx_thread_sleep(100); + } +} diff --git a/targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/main.c b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/main.c new file mode 100644 index 00000000..692cab16 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/main.c @@ -0,0 +1,397 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) + */ + +#include +#include +#include +#include +#include "bsp/board.h" +#include "bsp/led.h" +#include "bsp/console.h" +#include "board_config.h" +#include "ansi_colors.h" +#include "trng.h" +#include "tx_api.h" +#include "nx_api.h" + +#define DEMO_STACK_SIZE 2048 +#define PACKET_SIZE 1536 +#define PACKET_POOL_SIZE ((PACKET_SIZE + sizeof(NX_PACKET)) * 24) +#define ARP_CACHE_SIZE 512 +#define CONSOLE_SERVER_PORT 23 + +#define IP_ADDRESS_VAL IP_ADDRESS(192, 168, 0, 100) +#define NETWORK_MASK_VAL IP_ADDRESS(255, 255, 255, 0) +#define GATEWAY_ADDRESS_VAL IP_ADDRESS(192, 168, 0, 1) + +#define TAG_SHELL "\x1b[38;5;243m[Shell]" +#define TAG_TRNG "\x1b[38;5;243m[TRNG]" + +/* Memory buffers */ +static ULONG ip_thread_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG heartbeat_thread_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG shell_thread_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG arp_cache_area[ARP_CACHE_SIZE / sizeof(ULONG)]; + +__attribute__((section(".NonCacheable"))) +static uint8_t packet_pool_area[PACKET_POOL_SIZE]; + +/* NetX Duo & ThreadX objects */ +static NX_PACKET_POOL pool_0; +static NX_IP ip_0; +static TX_THREAD heartbeat_thread; +static TX_THREAD shell_thread; + +/* External driver entry point */ +VOID nx_driver_imx(NX_IP_DRIVER *driver_req_ptr); + +/* Thread prototypes */ +static void heartbeat_thread_entry(ULONG thread_input); +static void shell_thread_entry(ULONG thread_input); + +int main(void) +{ + /* Initialize hardware via BSP interface */ + bsp_board_init(); + + /* Initialize on-chip Hardware TRNG */ + trng_init(); + + printf(ANSI_BOLD ANSI_CYAN "\r\n==================================================\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN " Eclipse ThreadX & NetX Duo on NXP i.MX RT1064-EVK\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN " Hardware TRNG & Network Diagnostic Shell (Renode)\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN "==================================================\r\n\r\n" ANSI_RESET); + + printf(TAG_SYSTEM " " MSG_INFO "Core Clock: %lu MHz | Tick Rate: %u Hz\r\n" ANSI_RESET, + SystemCoreClock / 1000000UL, TX_TIMER_TICKS_PER_SECOND); + printf(TAG_TRNG " " MSG_INFO "On-chip True Random Number Generator initialized @ 0x400CC000\r\n" ANSI_RESET); + + /* Enter ThreadX kernel */ + tx_kernel_enter(); + + return 0; +} + +void tx_application_define(void *first_unused_memory) +{ + (void)first_unused_memory; + UINT status; + + printf(TAG_NETWORK " " MSG_INFO "Initializing NetX Duo System...\r\n" ANSI_RESET); + nx_system_initialize(); + + /* 1. Create packet pool in NonCacheable memory */ + status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", + PACKET_SIZE, packet_pool_area, PACKET_POOL_SIZE); + if (status != NX_SUCCESS) + { + printf(TAG_NETWORK " " MSG_ERROR "Failed to create packet pool: 0x%02X\r\n" ANSI_RESET, status); + return; + } + printf(TAG_NETWORK " " MSG_SUCCESS "Packet pool created (%u bytes in NonCacheable memory)\r\n" ANSI_RESET, + (unsigned int)sizeof(packet_pool_area)); + + /* 2. Create IP instance */ + status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS_VAL, + NETWORK_MASK_VAL, &pool_0, nx_driver_imx, + ip_thread_stack, DEMO_STACK_SIZE, 1); + if (status != NX_SUCCESS) + { + printf(TAG_NETWORK " " MSG_ERROR "Failed to create IP instance: 0x%02X\r\n" ANSI_RESET, status); + return; + } + printf(TAG_NETWORK " " MSG_SUCCESS "IP instance created\r\n" ANSI_RESET); + + /* 3. Gateway & Services */ + nx_ip_gateway_address_set(&ip_0, GATEWAY_ADDRESS_VAL); + + printf(TAG_NETWORK " " MSG_INFO "Enabling ARP...\r\n" ANSI_RESET); + nx_arp_enable(&ip_0, (VOID *)arp_cache_area, ARP_CACHE_SIZE); + + printf(TAG_NETWORK " " MSG_INFO "Enabling ICMP (Ping responder)...\r\n" ANSI_RESET); + nx_icmp_enable(&ip_0); + + printf(TAG_NETWORK " " MSG_INFO "Enabling TCP...\r\n" ANSI_RESET); + nx_tcp_enable(&ip_0); + + /* 4. Create Heartbeat Thread */ + status = tx_thread_create(&heartbeat_thread, "Heartbeat Thread", + heartbeat_thread_entry, 0, + heartbeat_thread_stack, DEMO_STACK_SIZE, + 15, 15, TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) + { + printf(TAG_SYSTEM " " MSG_ERROR "Failed to create Heartbeat thread: 0x%02X\r\n" ANSI_RESET, status); + } + + /* 5. Create TRNG Console Shell Thread */ + status = tx_thread_create(&shell_thread, "TRNG Shell Thread", + shell_thread_entry, 0, + shell_thread_stack, DEMO_STACK_SIZE, + 10, 10, TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) + { + printf(TAG_SYSTEM " " MSG_ERROR "Failed to create Shell thread: 0x%02X\r\n" ANSI_RESET, status); + } + + printf(TAG_NETWORK " " MSG_SUCCESS "Network threads registered successfully.\r\n" ANSI_RESET); +} + +static void heartbeat_thread_entry(ULONG thread_input) +{ + (void)thread_input; + UINT status; + ULONG actual_status; + ULONG ip_address, network_mask; + + printf(TAG_NETWORK " " MSG_INFO "Bringing Ethernet Link UP...\r\n" ANSI_RESET); + status = nx_ip_driver_direct_command(&ip_0, NX_LINK_ENABLE, &actual_status); + if (status == NX_SUCCESS || status == NX_ALREADY_ENABLED) + { + printf(TAG_NETWORK " " MSG_SUCCESS "Ethernet link is UP!\r\n" ANSI_RESET); + } + else + { + printf(TAG_NETWORK " " MSG_ERROR "nx_ip_driver_direct_command NX_LINK_ENABLE status: 0x%02X\r\n" ANSI_RESET, status); + } + + nx_ip_address_get(&ip_0, &ip_address, &network_mask); + printf("\r\n" ANSI_BOLD ANSI_GREEN "================ Network Ready ================\r\n" ANSI_RESET); + printf(ANSI_GREEN " Static IPv4 : %lu.%lu.%lu.%lu\r\n" ANSI_RESET, + (ip_address >> 24) & 0xFF, (ip_address >> 16) & 0xFF, + (ip_address >> 8) & 0xFF, ip_address & 0xFF); + printf(ANSI_GREEN " Subnet Mask : %lu.%lu.%lu.%lu\r\n" ANSI_RESET, + (network_mask >> 24) & 0xFF, (network_mask >> 16) & 0xFF, + (network_mask >> 8) & 0xFF, network_mask & 0xFF); + printf(ANSI_GREEN " Services : ICMP Ping, Hardware TRNG Shell (TCP Port %d)\r\n" ANSI_RESET, CONSOLE_SERVER_PORT); + printf(ANSI_BOLD ANSI_GREEN "===============================================\r\n\r\n" ANSI_RESET); + + while (1) + { + tx_thread_sleep(50); + bsp_led_toggle(); + } +} + +static void send_tcp_response(NX_TCP_SOCKET *socket, const char *msg) +{ + NX_PACKET *tx_packet = NX_NULL; + UINT status; + size_t len = strlen(msg); + + status = nx_packet_allocate(&pool_0, &tx_packet, NX_TCP_PACKET, TX_WAIT_FOREVER); + if (status != NX_SUCCESS) + { + return; + } + + status = nx_packet_data_append(tx_packet, (VOID *)msg, len, &pool_0, TX_WAIT_FOREVER); + if (status != NX_SUCCESS) + { + nx_packet_release(tx_packet); + return; + } + + status = nx_tcp_socket_send(socket, tx_packet, 200); + if (status != NX_SUCCESS) + { + /* In NetX Duo, a failed send leaves packet ownership with the caller */ + nx_packet_release(tx_packet); + } +} + +static void shell_thread_entry(ULONG thread_input) +{ + NX_TCP_SOCKET shell_socket; + NX_PACKET *packet_ptr; + UINT status; + char line_buffer[128]; + char resp_buffer[256]; + + (void)thread_input; + + status = nx_tcp_socket_create(&ip_0, &shell_socket, "TRNG Shell Socket", + NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, + 1024, NX_NULL, NX_NULL); + if (status != NX_SUCCESS) + { + printf(TAG_SHELL " " MSG_ERROR "Failed to create TCP socket: 0x%02X\r\n" ANSI_RESET, status); + return; + } + + printf(TAG_SHELL " " MSG_INFO "TRNG Diagnostic Shell listening on port %d\r\n" ANSI_RESET, CONSOLE_SERVER_PORT); + + while (1) + { + status = nx_tcp_server_socket_listen(&ip_0, CONSOLE_SERVER_PORT, &shell_socket, 5, NX_NULL); + if (status != NX_SUCCESS) + { + nx_tcp_server_socket_unlisten(&ip_0, CONSOLE_SERVER_PORT); + tx_thread_sleep(10); + continue; + } + + status = nx_tcp_server_socket_accept(&shell_socket, NX_WAIT_FOREVER); + if (status == NX_SUCCESS) + { + ULONG peer_ip = 0; + ULONG peer_port = 0; + nx_tcp_socket_peer_info_get(&shell_socket, &peer_ip, &peer_port); + + printf(TAG_SHELL " " MSG_SUCCESS "Client connected from %lu.%lu.%lu.%lu:%lu\r\n" ANSI_RESET, + (peer_ip >> 24) & 0xFF, (peer_ip >> 16) & 0xFF, + (peer_ip >> 8) & 0xFF, peer_ip & 0xFF, peer_port); + + /* Send Welcome Banner */ + send_tcp_response(&shell_socket, + "\r\n==================================================\r\n" + " NXP i.MX RT1064-EVK Hardware TRNG Console\r\n" + " Eclipse ThreadX & NetX Duo Management Shell\r\n" + "==================================================\r\n" + "Type 'help' for available commands.\r\n\r\nmimxrt1064> "); + + while (1) + { + status = nx_tcp_socket_receive(&shell_socket, &packet_ptr, NX_WAIT_FOREVER); + if (status != NX_SUCCESS) + { + break; + } + + ULONG bytes_copied = 0; + + /* nx_packet_data_retrieve copies the whole chain and takes no + destination size, so an over-long line is refused, not truncated. */ + if (packet_ptr->nx_packet_length >= sizeof(line_buffer)) + { + nx_packet_release(packet_ptr); + send_tcp_response(&shell_socket, + "[ERROR] Command line too long\r\n\r\nmimxrt1064> "); + continue; + } + + status = nx_packet_data_retrieve(packet_ptr, line_buffer, &bytes_copied); + nx_packet_release(packet_ptr); + + if (status != NX_SUCCESS && bytes_copied == 0) + { + continue; + } + + line_buffer[bytes_copied] = '\0'; + + /* Safe trimming of trailing CRLF and spaces without pointer underflow */ + size_t len = strlen(line_buffer); + while (len > 0 && (line_buffer[len - 1] == '\r' || + line_buffer[len - 1] == '\n' || + line_buffer[len - 1] == ' ')) + { + line_buffer[--len] = '\0'; + } + + if (strlen(line_buffer) == 0) + { + send_tcp_response(&shell_socket, "mimxrt1064> "); + continue; + } + + printf(TAG_SHELL " Received command: '%s'\r\n", line_buffer); + + if (strcmp(line_buffer, "help") == 0) + { + send_tcp_response(&shell_socket, + "Available commands:\r\n" + " trng - Read 4x 32-bit hardware entropy words from on-chip TRNG\r\n" + " info - Print processor clock, memory, and ThreadX ticks\r\n" + " led on|off|toggle - Control or toggle User LED D18\r\n" + " ping - Connection health check\r\n" + " quit - Terminate console session\r\n\r\nmimxrt1064> "); + } + else if (strcmp(line_buffer, "trng") == 0 || strcmp(line_buffer, "rand") == 0) + { + uint32_t r1 = 0, r2 = 0, r3 = 0, r4 = 0; + int s1 = trng_get_random_u32(&r1); + int s2 = trng_get_random_u32(&r2); + int s3 = trng_get_random_u32(&r3); + int s4 = trng_get_random_u32(&r4); + + if (s1 != 0 || s2 != 0 || s3 != 0 || s4 != 0) + { + snprintf(resp_buffer, sizeof(resp_buffer), + "[TRNG] Error: Entropy generation failed (status: %d, %d, %d, %d)\r\n\r\nmimxrt1064> ", + s1, s2, s3, s4); + printf(TAG_TRNG " " MSG_ERROR "Entropy generation failed (status: %d, %d, %d, %d)\r\n", + s1, s2, s3, s4); + send_tcp_response(&shell_socket, resp_buffer); + } + else + { + snprintf(resp_buffer, sizeof(resp_buffer), + "[TRNG] Hardware Entropy: 0x%08lX 0x%08lX 0x%08lX 0x%08lX\r\n\r\nmimxrt1064> ", + (unsigned long)r1, (unsigned long)r2, (unsigned long)r3, (unsigned long)r4); + printf(TAG_TRNG " Generated entropy: 0x%08lX 0x%08lX 0x%08lX 0x%08lX\r\n", + (unsigned long)r1, (unsigned long)r2, (unsigned long)r3, (unsigned long)r4); + send_tcp_response(&shell_socket, resp_buffer); + } + } + else if (strcmp(line_buffer, "info") == 0) + { + snprintf(resp_buffer, sizeof(resp_buffer), + "[INFO] Target: NXP MIMXRT1064-EVK (ARM Cortex-M7 @ 600 MHz)\r\n" + "[INFO] RTOS: Eclipse ThreadX | Uptime: %lu ticks\r\n" + "[INFO] TRNG: On-chip hardware entropy engine active @ 0x400CC000\r\n\r\nmimxrt1064> ", + tx_time_get()); + send_tcp_response(&shell_socket, resp_buffer); + } + else if (strncmp(line_buffer, "led", 3) == 0) + { + if (strstr(line_buffer, "on")) + { + bsp_led_on(); + send_tcp_response(&shell_socket, "[LED] State: ON\r\n\r\nmimxrt1064> "); + } + else if (strstr(line_buffer, "off")) + { + bsp_led_off(); + send_tcp_response(&shell_socket, "[LED] State: OFF\r\n\r\nmimxrt1064> "); + } + else + { + bsp_led_toggle(); + send_tcp_response(&shell_socket, "[LED] State: TOGGLED\r\n\r\nmimxrt1064> "); + } + } + else if (strcmp(line_buffer, "ping") == 0) + { + send_tcp_response(&shell_socket, "[PONG] Network connection alive\r\n\r\nmimxrt1064> "); + } + else if (strcmp(line_buffer, "quit") == 0 || strcmp(line_buffer, "exit") == 0) + { + send_tcp_response(&shell_socket, "Goodbye!\r\n"); + break; + } + else + { + send_tcp_response(&shell_socket, "Unknown command. Type 'help' for options.\r\n\r\nmimxrt1064> "); + } + } + + printf(TAG_SHELL " Client disconnected\r\n"); + nx_tcp_socket_disconnect(&shell_socket, 10); + nx_tcp_server_socket_unaccept(&shell_socket); + } + + nx_tcp_server_socket_unlisten(&ip_0, CONSOLE_SERVER_PORT); + } +} diff --git a/targets/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/CMakeLists.txt b/targets/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/CMakeLists.txt new file mode 100644 index 00000000..a7ba6275 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/CMakeLists.txt @@ -0,0 +1,36 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +set(DEMO_TARGET "demo_threadx_basic") +add_executable(${DEMO_TARGET} + main.c +) +set_target_properties(${DEMO_TARGET} PROPERTIES OUTPUT_NAME "mimxrt1064_threadx") + +# Include paths for the executable target +target_include_directories(${DEMO_TARGET} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} +) + +# Link libraries +target_link_libraries(${DEMO_TARGET} + PRIVATE + board_bsp + threadx + mcux_sdk +) + +# Apply GCC linker script and print memory usage (utilities.cmake function) +set_target_linker(${DEMO_TARGET} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/MIMXRT1064xxxxx_flexspi_nor.ld") + +# Post-build commands to generate raw .bin and .hex files +post_build(${DEMO_TARGET}) diff --git a/targets/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/main.c b/targets/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/main.c new file mode 100644 index 00000000..bf868eb8 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/main.c @@ -0,0 +1,167 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#include +#include +#include +#include "bsp/board.h" +#include "bsp/led.h" +#include "bsp/console.h" +#include "board_config.h" +#include "tx_api.h" + +#define HEARTBEAT_THREAD_STACK_SIZE 2048 +#define WORKER_THREAD_STACK_SIZE 2048 + +static TX_THREAD heartbeat_thread; +static ULONG heartbeat_thread_stack[HEARTBEAT_THREAD_STACK_SIZE / sizeof(ULONG)]; + +static TX_THREAD worker_thread; +static ULONG worker_thread_stack[WORKER_THREAD_STACK_SIZE / sizeof(ULONG)]; + +static TX_TIMER app_timer; +static volatile ULONG timer_fire_count = 0; + +/* Thread Function Prototypes */ +static void heartbeat_thread_entry(ULONG thread_input); +static void worker_thread_entry(ULONG thread_input); +static void app_timer_callback(ULONG timer_input); + +int main(void) +{ + /* Initialize hardware via BSP interface */ + bsp_board_init(); + + printf("\r\n"); + printf("==================================================\r\n"); + printf(" Eclipse ThreadX RTOS on NXP i.MX RT1064-EVK\r\n"); + printf(" Simulated in Antmicro Renode\r\n"); + printf("==================================================\r\n"); + printf("[System] Core Clock: %lu MHz | Tick Rate: %u Hz\r\n", + SystemCoreClock / 1000000UL, + TX_TIMER_TICKS_PER_SECOND); + printf("[System] Initializing ThreadX kernel...\r\n"); + + /* Enter the ThreadX kernel */ + tx_kernel_enter(); + + return 0; +} + +void tx_application_define(void *first_unused_memory) +{ + (void)first_unused_memory; + + UINT status; + + /* Create Heartbeat Thread (Priority 15 - lower priority) */ + status = tx_thread_create(&heartbeat_thread, + "Heartbeat Thread", + heartbeat_thread_entry, + 0, + heartbeat_thread_stack, + HEARTBEAT_THREAD_STACK_SIZE, + 15, + 15, + TX_NO_TIME_SLICE, + TX_AUTO_START); + if (status != TX_SUCCESS) + { + printf("[ERROR] Failed to create Heartbeat Thread (status: 0x%02X)\r\n", status); + } + + /* Create Worker Thread (Priority 10 - medium priority) */ + status = tx_thread_create(&worker_thread, + "Worker Thread", + worker_thread_entry, + 0, + worker_thread_stack, + WORKER_THREAD_STACK_SIZE, + 10, + 10, + TX_NO_TIME_SLICE, + TX_AUTO_START); + if (status != TX_SUCCESS) + { + printf("[ERROR] Failed to create Worker Thread (status: 0x%02X)\r\n", status); + } + + /* Create Application Timer (Periodic 200 ms / 20 ticks) */ + status = tx_timer_create(&app_timer, + "App Timer", + app_timer_callback, + 0, + 20, /* Initial ticks (200 ms) */ + 20, /* Reschedule ticks (200 ms) */ + TX_AUTO_ACTIVATE); + if (status != TX_SUCCESS) + { + printf("[ERROR] Failed to create App Timer (status: 0x%02X)\r\n", status); + } + + printf("[System] ThreadX threads and timer registered successfully.\r\n"); +} + +static void heartbeat_thread_entry(ULONG thread_input) +{ + (void)thread_input; + ULONG count = 0; + uint8_t led_state = 0; + + printf("[Heartbeat Thread] Started.\r\n"); + + while (1) + { + /* Sleep for 50 ticks (500 ms @ 100 Hz) */ + tx_thread_sleep(50); + count++; + + /* Toggle User LED (D18) on GPIO1 Pin 9 */ + bsp_led_toggle(); + led_state = !led_state; + + printf("[Heartbeat Thread] Heartbeat #%lu (System Tick: %lu | User LED: %s)\r\n", + count, tx_time_get(), led_state ? "ON" : "OFF"); + } +} + +static void worker_thread_entry(ULONG thread_input) +{ + (void)thread_input; + ULONG iteration = 0; + + printf("[Worker Thread] Started.\r\n"); + + while (1) + { + /* Sleep for 100 ticks (1000 ms @ 100 Hz) */ + tx_thread_sleep(100); + iteration++; + + printf("[Worker Thread] Executing periodic task (iteration #%lu, System Tick: %lu)\r\n", + iteration, tx_time_get()); + } +} + +static void app_timer_callback(ULONG timer_input) +{ + (void)timer_input; + timer_fire_count++; + + /* Report every 5 fires (1 second) */ + if ((timer_fire_count % 5) == 0) + { + printf("[App Timer] Kernel timer callback active (total firings: %lu)\r\n", + timer_fire_count); + } +} diff --git a/targets/NXP/MIMXRT1064-EVK/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld b/targets/NXP/MIMXRT1064-EVK/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld new file mode 100644 index 00000000..9fd0ae83 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/startup/MIMXRT1064xxxxx_flexspi_nor.ld @@ -0,0 +1,279 @@ +/* +** ################################################################### +** Processors: MIMXRT1064CVJ5A +** MIMXRT1064CVJ5B +** MIMXRT1064CVL5A +** MIMXRT1064CVL5B +** MIMXRT1064DVJ6A +** MIMXRT1064DVJ6B +** MIMXRT1064DVL6A +** MIMXRT1064DVL6B +** +** Compiler: GNU C Compiler +** Reference manual: IMXRT1064RM Rev.2, 7/2021 | IMXRT106XSRM Rev.0 +** Version: rev. 0.1, 2018-06-22 +** Build: b230821 +** +** Abstract: +** Linker file for the GNU C Compiler +** +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2023 NXP +** SPDX-License-Identifier: BSD-3-Clause +** +** http: www.nxp.com +** mail: support@nxp.com +** +** ################################################################### +*/ + +/* +** Adapted memory sections for Eclipse ThreadX RTOS by Eclipse ThreadX contributors. +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x0400; +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0400; +VECTOR_RAM_SIZE = DEFINED(__ram_vector_table__) ? 0x00000400 : 0; + +/* Specify the memory areas */ +MEMORY +{ + m_flash_config (RX) : ORIGIN = 0x70000000, LENGTH = 0x00001000 + m_ivt (RX) : ORIGIN = 0x70001000, LENGTH = 0x00001000 + m_interrupts (RX) : ORIGIN = 0x70002000, LENGTH = 0x00000400 + m_text (RX) : ORIGIN = 0x70002400, LENGTH = 0x003FDC00 + m_qacode (RX) : ORIGIN = 0x00000000, LENGTH = 0x00020000 + m_data (RW) : ORIGIN = 0x20000000, LENGTH = 0x00020000 + m_data2 (RW) : ORIGIN = 0x20200000, LENGTH = 0x000C0000 +} + +/* Define output sections */ +SECTIONS +{ + __NCACHE_REGION_START = ORIGIN(m_data2); + __NCACHE_REGION_SIZE = 0; + + .flash_config : + { + . = ALIGN(4); + __FLASH_BASE = .; + KEEP(* (.boot_hdr.conf)) /* flash config section */ + . = ALIGN(4); + } > m_flash_config + + ivt_begin = ORIGIN(m_flash_config) + LENGTH(m_flash_config); + + .ivt : AT(ivt_begin) + { + . = ALIGN(4); + KEEP(* (.boot_hdr.ivt)) /* ivt section */ + KEEP(* (.boot_hdr.boot_data)) /* boot section */ + KEEP(* (.boot_hdr.dcd_data)) /* dcd section */ + . = ALIGN(4); + } > m_ivt + + /* The startup code goes first into internal RAM */ + .interrupts : + { + __VECTOR_TABLE = .; + __Vectors = .; + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } > m_interrupts + + /* The program code and other data goes into internal RAM */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + KEEP (*(.init)) + KEEP (*(.fini)) + . = ALIGN(4); + } > m_text + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > m_text + + .ARM : + { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } > m_text + + .ctors : + { + __CTOR_LIST__ = .; + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __CTOR_END__ = .; + } > m_text + + .dtors : + { + __DTOR_LIST__ = .; + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __DTOR_END__ = .; + } > m_text + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } > m_text + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } > m_text + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } > m_text + + __etext = .; /* define a global symbol at end of code */ + __DATA_ROM = .; /* Symbol is used by startup for data initialization */ + + .interrupts_ram : + { + . = ALIGN(4); + __VECTOR_RAM__ = .; + __interrupts_ram_start__ = .; /* Create a global symbol at data start */ + *(.m_interrupts_ram) /* This is a user defined section */ + . += VECTOR_RAM_SIZE; + . = ALIGN(4); + __interrupts_ram_end__ = .; /* Define a global symbol at data end */ + } > m_data + + __VECTOR_RAM = DEFINED(__ram_vector_table__) ? __VECTOR_RAM__ : ORIGIN(m_interrupts); + __RAM_VECTOR_TABLE_SIZE_BYTES = DEFINED(__ram_vector_table__) ? (__interrupts_ram_end__ - __interrupts_ram_start__) : 0x0; + + .data : AT(__DATA_ROM) + { + . = ALIGN(4); + __DATA_RAM = .; + __data_start__ = .; /* create a global symbol at data start */ + *(m_usb_dma_init_data) + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + *(DataQuickAccess) /* quick access data section */ + KEEP(*(.jcr*)) + . = ALIGN(4); + __data_end__ = .; /* define a global symbol at data end */ + } > m_data + + __ram_function_flash_start = __DATA_ROM + (__data_end__ - __data_start__); /* Symbol is used by startup for TCM data initialization */ + + .ram_function : AT(__ram_function_flash_start) + { + . = ALIGN(32); + __ram_function_start__ = .; + *(CodeQuickAccess) + . = ALIGN(128); + __ram_function_end__ = .; + } > m_qacode + + __NDATA_ROM = __ram_function_flash_start + (__ram_function_end__ - __ram_function_start__); + .ncache.init : AT(__NDATA_ROM) + { + __noncachedata_start__ = .; /* create a global symbol at ncache data start */ + *(NonCacheable.init) + . = ALIGN(4); + __noncachedata_init_end__ = .; /* create a global symbol at initialized ncache data end */ + } > m_data + . = __noncachedata_init_end__; + .ncache : + { + *(NonCacheable) + . = ALIGN(4); + __noncachedata_end__ = .; /* define a global symbol at ncache data end */ + } > m_data + + __DATA_END = __NDATA_ROM + (__noncachedata_init_end__ - __noncachedata_start__); + text_end = ORIGIN(m_text) + LENGTH(m_text); + ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data") + + /* Uninitialized data section */ + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + . = ALIGN(4); + __START_BSS = .; + __bss_start__ = .; + *(m_usb_dma_noninit_data) + *(.bss) + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + __END_BSS = .; + } > m_data + + .heap : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + PROVIDE(_end = .); + __HeapBase = .; + . += HEAP_SIZE; + __HeapLimit = .; + __heap_limit = .; /* Add for _sbrk */ + __RAM_segment_used_end__ = .; + } > m_data + + .stack : + { + . = ALIGN(8); + . += STACK_SIZE; + } > m_data + + /* Initializes stack on the end of block */ + __StackTop = ORIGIN(m_data) + LENGTH(m_data); + __StackLimit = __StackTop - STACK_SIZE; + PROVIDE(__stack = __StackTop); + + .ARM.attributes 0 : { *(.ARM.attributes) } + + ASSERT(__StackLimit >= __HeapLimit, "region m_data overflowed with stack and heap") +} diff --git a/targets/NXP/MIMXRT1064-EVK/app/startup/startup_mimxrt1064.S b/targets/NXP/MIMXRT1064-EVK/app/startup/startup_mimxrt1064.S new file mode 100644 index 00000000..95442231 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/startup/startup_mimxrt1064.S @@ -0,0 +1,1142 @@ +/* ------------------------------------------------------------------------- */ +/* @file: startup_MIMXRT1064.s */ +/* @purpose: CMSIS Cortex-M7 Core Device Startup File */ +/* MIMXRT1064 */ +/* @version: 1.3 */ +/* @date: 2021-8-10 */ +/* @build: b231019 */ +/* ------------------------------------------------------------------------- */ +/* */ +/* Copyright 1997-2016 Freescale Semiconductor, Inc. */ +/* Copyright 2016-2023 NXP */ +/* SPDX-License-Identifier: BSD-3-Clause */ +/*****************************************************************************/ +/* Version: GCC for ARM Embedded Processors */ +/*****************************************************************************/ + .syntax unified + .arch armv7-m + + .section .isr_vector, "a" + .align 2 + .globl __isr_vector + .globl _vectors + .globl __Vectors + .globl __VECTOR_TABLE + .globl g_pfnVectors +__isr_vector: +_vectors: +__Vectors: +__VECTOR_TABLE: +g_pfnVectors: + .long __StackTop /* Top of Stack */ + .long Reset_Handler /* Reset Handler */ + .long NMI_Handler /* NMI Handler*/ + .long HardFault_Handler /* Hard Fault Handler*/ + .long MemManage_Handler /* MPU Fault Handler*/ + .long BusFault_Handler /* Bus Fault Handler*/ + .long UsageFault_Handler /* Usage Fault Handler*/ + .long 0 /* Reserved*/ + .long 0 /* Reserved*/ + .long 0 /* Reserved*/ + .long 0 /* Reserved*/ + .long SVC_Handler /* SVCall Handler*/ + .long DebugMon_Handler /* Debug Monitor Handler*/ + .long 0 /* Reserved*/ + .long PendSV_Handler /* PendSV Handler*/ + .long SysTick_Handler /* SysTick Handler*/ + + /* External Interrupts*/ + .long DMA0_DMA16_IRQHandler /* DMA channel 0/16 transfer complete*/ + .long DMA1_DMA17_IRQHandler /* DMA channel 1/17 transfer complete*/ + .long DMA2_DMA18_IRQHandler /* DMA channel 2/18 transfer complete*/ + .long DMA3_DMA19_IRQHandler /* DMA channel 3/19 transfer complete*/ + .long DMA4_DMA20_IRQHandler /* DMA channel 4/20 transfer complete*/ + .long DMA5_DMA21_IRQHandler /* DMA channel 5/21 transfer complete*/ + .long DMA6_DMA22_IRQHandler /* DMA channel 6/22 transfer complete*/ + .long DMA7_DMA23_IRQHandler /* DMA channel 7/23 transfer complete*/ + .long DMA8_DMA24_IRQHandler /* DMA channel 8/24 transfer complete*/ + .long DMA9_DMA25_IRQHandler /* DMA channel 9/25 transfer complete*/ + .long DMA10_DMA26_IRQHandler /* DMA channel 10/26 transfer complete*/ + .long DMA11_DMA27_IRQHandler /* DMA channel 11/27 transfer complete*/ + .long DMA12_DMA28_IRQHandler /* DMA channel 12/28 transfer complete*/ + .long DMA13_DMA29_IRQHandler /* DMA channel 13/29 transfer complete*/ + .long DMA14_DMA30_IRQHandler /* DMA channel 14/30 transfer complete*/ + .long DMA15_DMA31_IRQHandler /* DMA channel 15/31 transfer complete*/ + .long DMA_ERROR_IRQHandler /* DMA error interrupt channels 0-15 / 16-31*/ + .long CTI0_ERROR_IRQHandler /* CTI0_Error*/ + .long CTI1_ERROR_IRQHandler /* CTI1_Error*/ + .long CORE_IRQHandler /* CorePlatform exception IRQ*/ + .long LPUART1_IRQHandler /* LPUART1 TX interrupt and RX interrupt*/ + .long LPUART2_IRQHandler /* LPUART2 TX interrupt and RX interrupt*/ + .long LPUART3_IRQHandler /* LPUART3 TX interrupt and RX interrupt*/ + .long LPUART4_IRQHandler /* LPUART4 TX interrupt and RX interrupt*/ + .long LPUART5_IRQHandler /* LPUART5 TX interrupt and RX interrupt*/ + .long LPUART6_IRQHandler /* LPUART6 TX interrupt and RX interrupt*/ + .long LPUART7_IRQHandler /* LPUART7 TX interrupt and RX interrupt*/ + .long LPUART8_IRQHandler /* LPUART8 TX interrupt and RX interrupt*/ + .long LPI2C1_IRQHandler /* LPI2C1 interrupt*/ + .long LPI2C2_IRQHandler /* LPI2C2 interrupt*/ + .long LPI2C3_IRQHandler /* LPI2C3 interrupt*/ + .long LPI2C4_IRQHandler /* LPI2C4 interrupt*/ + .long LPSPI1_IRQHandler /* LPSPI1 single interrupt vector for all sources*/ + .long LPSPI2_IRQHandler /* LPSPI2 single interrupt vector for all sources*/ + .long LPSPI3_IRQHandler /* LPSPI3 single interrupt vector for all sources*/ + .long LPSPI4_IRQHandler /* LPSPI4 single interrupt vector for all sources*/ + .long CAN1_IRQHandler /* CAN1 interrupt*/ + .long CAN2_IRQHandler /* CAN2 interrupt*/ + .long FLEXRAM_IRQHandler /* FlexRAM address out of range Or access hit IRQ*/ + .long KPP_IRQHandler /* Keypad nterrupt*/ + .long TSC_DIG_IRQHandler /* TSC interrupt*/ + .long GPR_IRQ_IRQHandler /* GPR interrupt*/ + .long LCDIF_IRQHandler /* LCDIF interrupt*/ + .long CSI_IRQHandler /* CSI interrupt*/ + .long PXP_IRQHandler /* PXP interrupt*/ + .long WDOG2_IRQHandler /* WDOG2 interrupt*/ + .long SNVS_HP_WRAPPER_IRQHandler /* SRTC Consolidated Interrupt. Non TZ*/ + .long SNVS_HP_WRAPPER_TZ_IRQHandler /* SRTC Security Interrupt. TZ*/ + .long SNVS_LP_WRAPPER_IRQHandler /* ON-OFF button press shorter than 5 secs (pulse event)*/ + .long CSU_IRQHandler /* CSU interrupt*/ + .long DCP_IRQHandler /* DCP_IRQ interrupt*/ + .long DCP_VMI_IRQHandler /* DCP_VMI_IRQ interrupt*/ + .long Reserved68_IRQHandler /* Reserved interrupt*/ + .long TRNG_IRQHandler /* TRNG interrupt*/ + .long SJC_IRQHandler /* SJC interrupt*/ + .long BEE_IRQHandler /* BEE interrupt*/ + .long SAI1_IRQHandler /* SAI1 interrupt*/ + .long SAI2_IRQHandler /* SAI1 interrupt*/ + .long SAI3_RX_IRQHandler /* SAI3 interrupt*/ + .long SAI3_TX_IRQHandler /* SAI3 interrupt*/ + .long SPDIF_IRQHandler /* SPDIF interrupt*/ + .long PMU_EVENT_IRQHandler /* Brown-out event interrupt*/ + .long Reserved78_IRQHandler /* Reserved interrupt*/ + .long TEMP_LOW_HIGH_IRQHandler /* TempSensor low/high interrupt*/ + .long TEMP_PANIC_IRQHandler /* TempSensor panic interrupt*/ + .long USB_PHY1_IRQHandler /* USBPHY (UTMI0), Interrupt*/ + .long USB_PHY2_IRQHandler /* USBPHY (UTMI1), Interrupt*/ + .long ADC1_IRQHandler /* ADC1 interrupt*/ + .long ADC2_IRQHandler /* ADC2 interrupt*/ + .long DCDC_IRQHandler /* DCDC interrupt*/ + .long Reserved86_IRQHandler /* Reserved interrupt*/ + .long GPIO10_IRQHandler /* GPIO10 interrupt*/ + .long GPIO1_INT0_IRQHandler /* Active HIGH Interrupt from INT0 from GPIO*/ + .long GPIO1_INT1_IRQHandler /* Active HIGH Interrupt from INT1 from GPIO*/ + .long GPIO1_INT2_IRQHandler /* Active HIGH Interrupt from INT2 from GPIO*/ + .long GPIO1_INT3_IRQHandler /* Active HIGH Interrupt from INT3 from GPIO*/ + .long GPIO1_INT4_IRQHandler /* Active HIGH Interrupt from INT4 from GPIO*/ + .long GPIO1_INT5_IRQHandler /* Active HIGH Interrupt from INT5 from GPIO*/ + .long GPIO1_INT6_IRQHandler /* Active HIGH Interrupt from INT6 from GPIO*/ + .long GPIO1_INT7_IRQHandler /* Active HIGH Interrupt from INT7 from GPIO*/ + .long GPIO1_Combined_0_15_IRQHandler /* Combined interrupt indication for GPIO1 signal 0 throughout 15*/ + .long GPIO1_Combined_16_31_IRQHandler /* Combined interrupt indication for GPIO1 signal 16 throughout 31*/ + .long GPIO2_Combined_0_15_IRQHandler /* Combined interrupt indication for GPIO2 signal 0 throughout 15*/ + .long GPIO2_Combined_16_31_IRQHandler /* Combined interrupt indication for GPIO2 signal 16 throughout 31*/ + .long GPIO3_Combined_0_15_IRQHandler /* Combined interrupt indication for GPIO3 signal 0 throughout 15*/ + .long GPIO3_Combined_16_31_IRQHandler /* Combined interrupt indication for GPIO3 signal 16 throughout 31*/ + .long GPIO4_Combined_0_15_IRQHandler /* Combined interrupt indication for GPIO4 signal 0 throughout 15*/ + .long GPIO4_Combined_16_31_IRQHandler /* Combined interrupt indication for GPIO4 signal 16 throughout 31*/ + .long GPIO5_Combined_0_15_IRQHandler /* Combined interrupt indication for GPIO5 signal 0 throughout 15*/ + .long GPIO5_Combined_16_31_IRQHandler /* Combined interrupt indication for GPIO5 signal 16 throughout 31*/ + .long FLEXIO1_IRQHandler /* FLEXIO1 interrupt*/ + .long FLEXIO2_IRQHandler /* FLEXIO2 interrupt*/ + .long WDOG1_IRQHandler /* WDOG1 interrupt*/ + .long RTWDOG_IRQHandler /* RTWDOG interrupt*/ + .long EWM_IRQHandler /* EWM interrupt*/ + .long CCM_1_IRQHandler /* CCM IRQ1 interrupt*/ + .long CCM_2_IRQHandler /* CCM IRQ2 interrupt*/ + .long GPC_IRQHandler /* GPC interrupt*/ + .long SRC_IRQHandler /* SRC interrupt*/ + .long Reserved115_IRQHandler /* Reserved interrupt*/ + .long GPT1_IRQHandler /* GPT1 interrupt*/ + .long GPT2_IRQHandler /* GPT2 interrupt*/ + .long PWM1_0_IRQHandler /* PWM1 capture 0, compare 0, or reload 0 interrupt*/ + .long PWM1_1_IRQHandler /* PWM1 capture 1, compare 1, or reload 0 interrupt*/ + .long PWM1_2_IRQHandler /* PWM1 capture 2, compare 2, or reload 0 interrupt*/ + .long PWM1_3_IRQHandler /* PWM1 capture 3, compare 3, or reload 0 interrupt*/ + .long PWM1_FAULT_IRQHandler /* PWM1 fault or reload error interrupt*/ + .long FLEXSPI2_IRQHandler /* FlexSPI2 interrupt*/ + .long FLEXSPI_IRQHandler /* FlexSPI0 interrupt*/ + .long SEMC_IRQHandler /* SEMC interrupt*/ + .long USDHC1_IRQHandler /* USDHC1 interrupt*/ + .long USDHC2_IRQHandler /* USDHC2 interrupt*/ + .long USB_OTG2_IRQHandler /* USBO2 USB OTG2*/ + .long USB_OTG1_IRQHandler /* USBO2 USB OTG1*/ + .long ENET_IRQHandler /* ENET interrupt*/ + .long ENET_1588_Timer_IRQHandler /* ENET_1588_Timer interrupt*/ + .long XBAR1_IRQ_0_1_IRQHandler /* XBARA1 output signal 0, 1 interrupt*/ + .long XBAR1_IRQ_2_3_IRQHandler /* XBARA1 output signal 2, 3 interrupt*/ + .long ADC_ETC_IRQ0_IRQHandler /* ADCETC IRQ0 interrupt*/ + .long ADC_ETC_IRQ1_IRQHandler /* ADCETC IRQ1 interrupt*/ + .long ADC_ETC_IRQ2_IRQHandler /* ADCETC IRQ2 interrupt*/ + .long ADC_ETC_ERROR_IRQ_IRQHandler /* ADCETC Error IRQ interrupt*/ + .long PIT_IRQHandler /* PIT interrupt*/ + .long ACMP1_IRQHandler /* ACMP interrupt*/ + .long ACMP2_IRQHandler /* ACMP interrupt*/ + .long ACMP3_IRQHandler /* ACMP interrupt*/ + .long ACMP4_IRQHandler /* ACMP interrupt*/ + .long Reserved143_IRQHandler /* Reserved interrupt*/ + .long Reserved144_IRQHandler /* Reserved interrupt*/ + .long ENC1_IRQHandler /* ENC1 interrupt*/ + .long ENC2_IRQHandler /* ENC2 interrupt*/ + .long ENC3_IRQHandler /* ENC3 interrupt*/ + .long ENC4_IRQHandler /* ENC4 interrupt*/ + .long TMR1_IRQHandler /* TMR1 interrupt*/ + .long TMR2_IRQHandler /* TMR2 interrupt*/ + .long TMR3_IRQHandler /* TMR3 interrupt*/ + .long TMR4_IRQHandler /* TMR4 interrupt*/ + .long PWM2_0_IRQHandler /* PWM2 capture 0, compare 0, or reload 0 interrupt*/ + .long PWM2_1_IRQHandler /* PWM2 capture 1, compare 1, or reload 0 interrupt*/ + .long PWM2_2_IRQHandler /* PWM2 capture 2, compare 2, or reload 0 interrupt*/ + .long PWM2_3_IRQHandler /* PWM2 capture 3, compare 3, or reload 0 interrupt*/ + .long PWM2_FAULT_IRQHandler /* PWM2 fault or reload error interrupt*/ + .long PWM3_0_IRQHandler /* PWM3 capture 0, compare 0, or reload 0 interrupt*/ + .long PWM3_1_IRQHandler /* PWM3 capture 1, compare 1, or reload 0 interrupt*/ + .long PWM3_2_IRQHandler /* PWM3 capture 2, compare 2, or reload 0 interrupt*/ + .long PWM3_3_IRQHandler /* PWM3 capture 3, compare 3, or reload 0 interrupt*/ + .long PWM3_FAULT_IRQHandler /* PWM3 fault or reload error interrupt*/ + .long PWM4_0_IRQHandler /* PWM4 capture 0, compare 0, or reload 0 interrupt*/ + .long PWM4_1_IRQHandler /* PWM4 capture 1, compare 1, or reload 0 interrupt*/ + .long PWM4_2_IRQHandler /* PWM4 capture 2, compare 2, or reload 0 interrupt*/ + .long PWM4_3_IRQHandler /* PWM4 capture 3, compare 3, or reload 0 interrupt*/ + .long PWM4_FAULT_IRQHandler /* PWM4 fault or reload error interrupt*/ + .long ENET2_IRQHandler /* ENET2 interrupt*/ + .long ENET2_1588_Timer_IRQHandler /* ENET2_1588_Timer interrupt*/ + .long CAN3_IRQHandler /* CAN3 interrupt*/ + .long Reserved171_IRQHandler /* Reserved interrupt*/ + .long FLEXIO3_IRQHandler /* FLEXIO3 interrupt*/ + .long GPIO6_7_8_9_IRQHandler /* GPIO6, GPIO7, GPIO8, GPIO9 interrupt*/ + .long DefaultISR /* 174*/ + .long DefaultISR /* 175*/ + .long DefaultISR /* 176*/ + .long DefaultISR /* 177*/ + .long DefaultISR /* 178*/ + .long DefaultISR /* 179*/ + .long DefaultISR /* 180*/ + .long DefaultISR /* 181*/ + .long DefaultISR /* 182*/ + .long DefaultISR /* 183*/ + .long DefaultISR /* 184*/ + .long DefaultISR /* 185*/ + .long DefaultISR /* 186*/ + .long DefaultISR /* 187*/ + .long DefaultISR /* 188*/ + .long DefaultISR /* 189*/ + .long DefaultISR /* 190*/ + .long DefaultISR /* 191*/ + .long DefaultISR /* 192*/ + .long DefaultISR /* 193*/ + .long DefaultISR /* 194*/ + .long DefaultISR /* 195*/ + .long DefaultISR /* 196*/ + .long DefaultISR /* 197*/ + .long DefaultISR /* 198*/ + .long DefaultISR /* 199*/ + .long DefaultISR /* 200*/ + .long DefaultISR /* 201*/ + .long DefaultISR /* 202*/ + .long DefaultISR /* 203*/ + .long DefaultISR /* 204*/ + .long DefaultISR /* 205*/ + .long DefaultISR /* 206*/ + .long DefaultISR /* 207*/ + .long DefaultISR /* 208*/ + .long DefaultISR /* 209*/ + .long DefaultISR /* 210*/ + .long DefaultISR /* 211*/ + .long DefaultISR /* 212*/ + .long DefaultISR /* 213*/ + .long DefaultISR /* 214*/ + .long DefaultISR /* 215*/ + .long DefaultISR /* 216*/ + .long DefaultISR /* 217*/ + .long DefaultISR /* 218*/ + .long DefaultISR /* 219*/ + .long DefaultISR /* 220*/ + .long DefaultISR /* 221*/ + .long DefaultISR /* 222*/ + .long DefaultISR /* 223*/ + .long DefaultISR /* 224*/ + .long DefaultISR /* 225*/ + .long DefaultISR /* 226*/ + .long DefaultISR /* 227*/ + .long DefaultISR /* 228*/ + .long DefaultISR /* 229*/ + .long DefaultISR /* 230*/ + .long DefaultISR /* 231*/ + .long DefaultISR /* 232*/ + .long DefaultISR /* 233*/ + .long DefaultISR /* 234*/ + .long DefaultISR /* 235*/ + .long DefaultISR /* 236*/ + .long DefaultISR /* 237*/ + .long DefaultISR /* 238*/ + .long DefaultISR /* 239*/ + .long DefaultISR /* 240*/ + .long DefaultISR /* 241*/ + .long DefaultISR /* 242*/ + .long DefaultISR /* 243*/ + .long DefaultISR /* 244*/ + .long DefaultISR /* 245*/ + .long DefaultISR /* 246*/ + .long DefaultISR /* 247*/ + .long DefaultISR /* 248*/ + .long DefaultISR /* 249*/ + .long DefaultISR /* 250*/ + .long DefaultISR /* 251*/ + .long DefaultISR /* 252*/ + .long DefaultISR /* 253*/ + .long DefaultISR /* 254*/ + .long 0xFFFFFFFF /* Reserved for user TRIM value*/ + + .size __isr_vector, . - __isr_vector + + .text + .thumb + +#if defined (__cplusplus) +#ifdef __REDLIB__ +#error Redlib does not support C++ +#endif +#endif +/* Reset Handler */ + + .thumb_func + .align 2 + .globl Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + cpsid i /* Mask interrupts */ + .equ VTOR, 0xE000ED08 + ldr r0, =VTOR + ldr r1, =__isr_vector + str r1, [r0] + ldr r2, [r1] + msr msp, r2 +#ifndef __NO_SYSTEM_INIT + ldr r0,=SystemInit + blx r0 +#endif +/* Loop to copy data from read only memory to RAM. The ranges + * of copy from/to are specified by following symbols evaluated in + * linker script. + * __etext: End of code section, i.e., begin of data sections to copy from. + * __data_start__/__data_end__: RAM address range that data should be + * __noncachedata_start__/__noncachedata_end__ : none cachable region + * __ram_function_start__/__ram_function_end__ : ramfunction region + * copied to. Both must be aligned to 4 bytes boundary. */ + + ldr r1, =__etext + ldr r2, =__data_start__ + ldr r3, =__data_end__ + +#ifdef __PERFORMANCE_IMPLEMENTATION +/* Here are two copies of loop implementations. First one favors performance + * and the second one favors code size. Default uses the second one. + * Define macro "__PERFORMANCE_IMPLEMENTATION" in project to use the first one */ + subs r3, r2 + ble .LC1 +.LC0: + subs r3, #4 + ldr r0, [r1, r3] + str r0, [r2, r3] + bgt .LC0 +.LC1: +#else /* code size implemenation */ +.LC0: + cmp r2, r3 + ittt lt + ldrlt r0, [r1], #4 + strlt r0, [r2], #4 + blt .LC0 +#endif +#ifdef __STARTUP_INITIALIZE_RAMFUNCTION + ldr r2, =__ram_function_start__ + ldr r3, =__ram_function_end__ +#ifdef __PERFORMANCE_IMPLEMENTATION +/* Here are two copies of loop implementations. First one favors performance + * and the second one favors code size. Default uses the second one. + * Define macro "__PERFORMANCE_IMPLEMENTATION" in project to use the first one */ + subs r3, r2 + ble .LC_ramfunc_copy_end +.LC_ramfunc_copy_start: + subs r3, #4 + ldr r0, [r1, r3] + str r0, [r2, r3] + bgt .LC_ramfunc_copy_start +.LC_ramfunc_copy_end: +#else /* code size implemenation */ +.LC_ramfunc_copy_start: + cmp r2, r3 + ittt lt + ldrlt r0, [r1], #4 + strlt r0, [r2], #4 + blt .LC_ramfunc_copy_start +#endif +#endif /* __STARTUP_INITIALIZE_RAMFUNCTION */ +#ifdef __STARTUP_INITIALIZE_NONCACHEDATA + ldr r2, =__noncachedata_start__ + ldr r3, =__noncachedata_init_end__ +#ifdef __PERFORMANCE_IMPLEMENTATION +/* Here are two copies of loop implementations. First one favors performance + * and the second one favors code size. Default uses the second one. + * Define macro "__PERFORMANCE_IMPLEMENTATION" in project to use the first one */ + subs r3, r2 + ble .LC3 +.LC2: + subs r3, #4 + ldr r0, [r1, r3] + str r0, [r2, r3] + bgt .LC2 +.LC3: +#else /* code size implemenation */ +.LC2: + cmp r2, r3 + ittt lt + ldrlt r0, [r1], #4 + strlt r0, [r2], #4 + blt .LC2 +#endif +/* zero inited ncache section initialization */ + ldr r3, =__noncachedata_end__ + movs r0,0 +.LC4: + cmp r2,r3 + itt lt + strlt r0,[r2],#4 + blt .LC4 +#endif /* __STARTUP_INITIALIZE_NONCACHEDATA */ + +#ifdef __STARTUP_CLEAR_BSS +/* This part of work usually is done in C library startup code. Otherwise, + * define this macro to enable it in this startup. + * + * Loop to zero out BSS section, which uses following symbols + * in linker script: + * __bss_start__: start of BSS section. Must align to 4 + * __bss_end__: end of BSS section. Must align to 4 + */ + ldr r1, =__bss_start__ + ldr r2, =__bss_end__ + + movs r0, 0 +.LC5: + cmp r1, r2 + itt lt + strlt r0, [r1], #4 + blt .LC5 +#endif /* __STARTUP_CLEAR_BSS */ + + cpsie i /* Unmask interrupts */ +#ifndef __START +#ifdef __REDLIB__ +#define __START __main +#else +#define __START _start +#endif +#endif +#ifndef __ATOLLIC__ + ldr r0,=__START + blx r0 +#else + ldr r0,=__libc_init_array + blx r0 + ldr r0,=main + bx r0 +#endif + .pool + .size Reset_Handler, . - Reset_Handler + + .align 1 + .thumb_func + .weak DefaultISR + .type DefaultISR, %function +DefaultISR: + b DefaultISR + .size DefaultISR, . - DefaultISR + + .align 1 + .thumb_func + .weak NMI_Handler + .type NMI_Handler, %function +NMI_Handler: + ldr r0,=NMI_Handler + bx r0 + .size NMI_Handler, . - NMI_Handler + + .align 1 + .thumb_func + .weak HardFault_Handler + .type HardFault_Handler, %function +HardFault_Handler: + ldr r0,=HardFault_Handler + bx r0 + .size HardFault_Handler, . - HardFault_Handler + + .align 1 + .thumb_func + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + ldr r0,=SVC_Handler + bx r0 + .size SVC_Handler, . - SVC_Handler + + .align 1 + .thumb_func + .weak PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + ldr r0,=PendSV_Handler + bx r0 + .size PendSV_Handler, . - PendSV_Handler + + .align 1 + .thumb_func + .weak SysTick_Handler + .type SysTick_Handler, %function +SysTick_Handler: + ldr r0,=SysTick_Handler + bx r0 + .size SysTick_Handler, . - SysTick_Handler + + .align 1 + .thumb_func + .weak DMA0_DMA16_IRQHandler + .type DMA0_DMA16_IRQHandler, %function +DMA0_DMA16_IRQHandler: + ldr r0,=DMA0_DMA16_DriverIRQHandler + bx r0 + .size DMA0_DMA16_IRQHandler, . - DMA0_DMA16_IRQHandler + + .align 1 + .thumb_func + .weak DMA1_DMA17_IRQHandler + .type DMA1_DMA17_IRQHandler, %function +DMA1_DMA17_IRQHandler: + ldr r0,=DMA1_DMA17_DriverIRQHandler + bx r0 + .size DMA1_DMA17_IRQHandler, . - DMA1_DMA17_IRQHandler + + .align 1 + .thumb_func + .weak DMA2_DMA18_IRQHandler + .type DMA2_DMA18_IRQHandler, %function +DMA2_DMA18_IRQHandler: + ldr r0,=DMA2_DMA18_DriverIRQHandler + bx r0 + .size DMA2_DMA18_IRQHandler, . - DMA2_DMA18_IRQHandler + + .align 1 + .thumb_func + .weak DMA3_DMA19_IRQHandler + .type DMA3_DMA19_IRQHandler, %function +DMA3_DMA19_IRQHandler: + ldr r0,=DMA3_DMA19_DriverIRQHandler + bx r0 + .size DMA3_DMA19_IRQHandler, . - DMA3_DMA19_IRQHandler + + .align 1 + .thumb_func + .weak DMA4_DMA20_IRQHandler + .type DMA4_DMA20_IRQHandler, %function +DMA4_DMA20_IRQHandler: + ldr r0,=DMA4_DMA20_DriverIRQHandler + bx r0 + .size DMA4_DMA20_IRQHandler, . - DMA4_DMA20_IRQHandler + + .align 1 + .thumb_func + .weak DMA5_DMA21_IRQHandler + .type DMA5_DMA21_IRQHandler, %function +DMA5_DMA21_IRQHandler: + ldr r0,=DMA5_DMA21_DriverIRQHandler + bx r0 + .size DMA5_DMA21_IRQHandler, . - DMA5_DMA21_IRQHandler + + .align 1 + .thumb_func + .weak DMA6_DMA22_IRQHandler + .type DMA6_DMA22_IRQHandler, %function +DMA6_DMA22_IRQHandler: + ldr r0,=DMA6_DMA22_DriverIRQHandler + bx r0 + .size DMA6_DMA22_IRQHandler, . - DMA6_DMA22_IRQHandler + + .align 1 + .thumb_func + .weak DMA7_DMA23_IRQHandler + .type DMA7_DMA23_IRQHandler, %function +DMA7_DMA23_IRQHandler: + ldr r0,=DMA7_DMA23_DriverIRQHandler + bx r0 + .size DMA7_DMA23_IRQHandler, . - DMA7_DMA23_IRQHandler + + .align 1 + .thumb_func + .weak DMA8_DMA24_IRQHandler + .type DMA8_DMA24_IRQHandler, %function +DMA8_DMA24_IRQHandler: + ldr r0,=DMA8_DMA24_DriverIRQHandler + bx r0 + .size DMA8_DMA24_IRQHandler, . - DMA8_DMA24_IRQHandler + + .align 1 + .thumb_func + .weak DMA9_DMA25_IRQHandler + .type DMA9_DMA25_IRQHandler, %function +DMA9_DMA25_IRQHandler: + ldr r0,=DMA9_DMA25_DriverIRQHandler + bx r0 + .size DMA9_DMA25_IRQHandler, . - DMA9_DMA25_IRQHandler + + .align 1 + .thumb_func + .weak DMA10_DMA26_IRQHandler + .type DMA10_DMA26_IRQHandler, %function +DMA10_DMA26_IRQHandler: + ldr r0,=DMA10_DMA26_DriverIRQHandler + bx r0 + .size DMA10_DMA26_IRQHandler, . - DMA10_DMA26_IRQHandler + + .align 1 + .thumb_func + .weak DMA11_DMA27_IRQHandler + .type DMA11_DMA27_IRQHandler, %function +DMA11_DMA27_IRQHandler: + ldr r0,=DMA11_DMA27_DriverIRQHandler + bx r0 + .size DMA11_DMA27_IRQHandler, . - DMA11_DMA27_IRQHandler + + .align 1 + .thumb_func + .weak DMA12_DMA28_IRQHandler + .type DMA12_DMA28_IRQHandler, %function +DMA12_DMA28_IRQHandler: + ldr r0,=DMA12_DMA28_DriverIRQHandler + bx r0 + .size DMA12_DMA28_IRQHandler, . - DMA12_DMA28_IRQHandler + + .align 1 + .thumb_func + .weak DMA13_DMA29_IRQHandler + .type DMA13_DMA29_IRQHandler, %function +DMA13_DMA29_IRQHandler: + ldr r0,=DMA13_DMA29_DriverIRQHandler + bx r0 + .size DMA13_DMA29_IRQHandler, . - DMA13_DMA29_IRQHandler + + .align 1 + .thumb_func + .weak DMA14_DMA30_IRQHandler + .type DMA14_DMA30_IRQHandler, %function +DMA14_DMA30_IRQHandler: + ldr r0,=DMA14_DMA30_DriverIRQHandler + bx r0 + .size DMA14_DMA30_IRQHandler, . - DMA14_DMA30_IRQHandler + + .align 1 + .thumb_func + .weak DMA15_DMA31_IRQHandler + .type DMA15_DMA31_IRQHandler, %function +DMA15_DMA31_IRQHandler: + ldr r0,=DMA15_DMA31_DriverIRQHandler + bx r0 + .size DMA15_DMA31_IRQHandler, . - DMA15_DMA31_IRQHandler + + .align 1 + .thumb_func + .weak DMA_ERROR_IRQHandler + .type DMA_ERROR_IRQHandler, %function +DMA_ERROR_IRQHandler: + ldr r0,=DMA_ERROR_DriverIRQHandler + bx r0 + .size DMA_ERROR_IRQHandler, . - DMA_ERROR_IRQHandler + + .align 1 + .thumb_func + .weak LPUART1_IRQHandler + .type LPUART1_IRQHandler, %function +LPUART1_IRQHandler: + ldr r0,=LPUART1_DriverIRQHandler + bx r0 + .size LPUART1_IRQHandler, . - LPUART1_IRQHandler + + .align 1 + .thumb_func + .weak LPUART2_IRQHandler + .type LPUART2_IRQHandler, %function +LPUART2_IRQHandler: + ldr r0,=LPUART2_DriverIRQHandler + bx r0 + .size LPUART2_IRQHandler, . - LPUART2_IRQHandler + + .align 1 + .thumb_func + .weak LPUART3_IRQHandler + .type LPUART3_IRQHandler, %function +LPUART3_IRQHandler: + ldr r0,=LPUART3_DriverIRQHandler + bx r0 + .size LPUART3_IRQHandler, . - LPUART3_IRQHandler + + .align 1 + .thumb_func + .weak LPUART4_IRQHandler + .type LPUART4_IRQHandler, %function +LPUART4_IRQHandler: + ldr r0,=LPUART4_DriverIRQHandler + bx r0 + .size LPUART4_IRQHandler, . - LPUART4_IRQHandler + + .align 1 + .thumb_func + .weak LPUART5_IRQHandler + .type LPUART5_IRQHandler, %function +LPUART5_IRQHandler: + ldr r0,=LPUART5_DriverIRQHandler + bx r0 + .size LPUART5_IRQHandler, . - LPUART5_IRQHandler + + .align 1 + .thumb_func + .weak LPUART6_IRQHandler + .type LPUART6_IRQHandler, %function +LPUART6_IRQHandler: + ldr r0,=LPUART6_DriverIRQHandler + bx r0 + .size LPUART6_IRQHandler, . - LPUART6_IRQHandler + + .align 1 + .thumb_func + .weak LPUART7_IRQHandler + .type LPUART7_IRQHandler, %function +LPUART7_IRQHandler: + ldr r0,=LPUART7_DriverIRQHandler + bx r0 + .size LPUART7_IRQHandler, . - LPUART7_IRQHandler + + .align 1 + .thumb_func + .weak LPUART8_IRQHandler + .type LPUART8_IRQHandler, %function +LPUART8_IRQHandler: + ldr r0,=LPUART8_DriverIRQHandler + bx r0 + .size LPUART8_IRQHandler, . - LPUART8_IRQHandler + + .align 1 + .thumb_func + .weak LPI2C1_IRQHandler + .type LPI2C1_IRQHandler, %function +LPI2C1_IRQHandler: + ldr r0,=LPI2C1_DriverIRQHandler + bx r0 + .size LPI2C1_IRQHandler, . - LPI2C1_IRQHandler + + .align 1 + .thumb_func + .weak LPI2C2_IRQHandler + .type LPI2C2_IRQHandler, %function +LPI2C2_IRQHandler: + ldr r0,=LPI2C2_DriverIRQHandler + bx r0 + .size LPI2C2_IRQHandler, . - LPI2C2_IRQHandler + + .align 1 + .thumb_func + .weak LPI2C3_IRQHandler + .type LPI2C3_IRQHandler, %function +LPI2C3_IRQHandler: + ldr r0,=LPI2C3_DriverIRQHandler + bx r0 + .size LPI2C3_IRQHandler, . - LPI2C3_IRQHandler + + .align 1 + .thumb_func + .weak LPI2C4_IRQHandler + .type LPI2C4_IRQHandler, %function +LPI2C4_IRQHandler: + ldr r0,=LPI2C4_DriverIRQHandler + bx r0 + .size LPI2C4_IRQHandler, . - LPI2C4_IRQHandler + + .align 1 + .thumb_func + .weak LPSPI1_IRQHandler + .type LPSPI1_IRQHandler, %function +LPSPI1_IRQHandler: + ldr r0,=LPSPI1_DriverIRQHandler + bx r0 + .size LPSPI1_IRQHandler, . - LPSPI1_IRQHandler + + .align 1 + .thumb_func + .weak LPSPI2_IRQHandler + .type LPSPI2_IRQHandler, %function +LPSPI2_IRQHandler: + ldr r0,=LPSPI2_DriverIRQHandler + bx r0 + .size LPSPI2_IRQHandler, . - LPSPI2_IRQHandler + + .align 1 + .thumb_func + .weak LPSPI3_IRQHandler + .type LPSPI3_IRQHandler, %function +LPSPI3_IRQHandler: + ldr r0,=LPSPI3_DriverIRQHandler + bx r0 + .size LPSPI3_IRQHandler, . - LPSPI3_IRQHandler + + .align 1 + .thumb_func + .weak LPSPI4_IRQHandler + .type LPSPI4_IRQHandler, %function +LPSPI4_IRQHandler: + ldr r0,=LPSPI4_DriverIRQHandler + bx r0 + .size LPSPI4_IRQHandler, . - LPSPI4_IRQHandler + + .align 1 + .thumb_func + .weak CAN1_IRQHandler + .type CAN1_IRQHandler, %function +CAN1_IRQHandler: + ldr r0,=CAN1_DriverIRQHandler + bx r0 + .size CAN1_IRQHandler, . - CAN1_IRQHandler + + .align 1 + .thumb_func + .weak CAN2_IRQHandler + .type CAN2_IRQHandler, %function +CAN2_IRQHandler: + ldr r0,=CAN2_DriverIRQHandler + bx r0 + .size CAN2_IRQHandler, . - CAN2_IRQHandler + + .align 1 + .thumb_func + .weak SAI1_IRQHandler + .type SAI1_IRQHandler, %function +SAI1_IRQHandler: + ldr r0,=SAI1_DriverIRQHandler + bx r0 + .size SAI1_IRQHandler, . - SAI1_IRQHandler + + .align 1 + .thumb_func + .weak SAI2_IRQHandler + .type SAI2_IRQHandler, %function +SAI2_IRQHandler: + ldr r0,=SAI2_DriverIRQHandler + bx r0 + .size SAI2_IRQHandler, . - SAI2_IRQHandler + + .align 1 + .thumb_func + .weak SAI3_RX_IRQHandler + .type SAI3_RX_IRQHandler, %function +SAI3_RX_IRQHandler: + ldr r0,=SAI3_RX_DriverIRQHandler + bx r0 + .size SAI3_RX_IRQHandler, . - SAI3_RX_IRQHandler + + .align 1 + .thumb_func + .weak SAI3_TX_IRQHandler + .type SAI3_TX_IRQHandler, %function +SAI3_TX_IRQHandler: + ldr r0,=SAI3_TX_DriverIRQHandler + bx r0 + .size SAI3_TX_IRQHandler, . - SAI3_TX_IRQHandler + + .align 1 + .thumb_func + .weak SPDIF_IRQHandler + .type SPDIF_IRQHandler, %function +SPDIF_IRQHandler: + ldr r0,=SPDIF_DriverIRQHandler + bx r0 + .size SPDIF_IRQHandler, . - SPDIF_IRQHandler + + .align 1 + .thumb_func + .weak FLEXIO1_IRQHandler + .type FLEXIO1_IRQHandler, %function +FLEXIO1_IRQHandler: + ldr r0,=FLEXIO1_DriverIRQHandler + bx r0 + .size FLEXIO1_IRQHandler, . - FLEXIO1_IRQHandler + + .align 1 + .thumb_func + .weak FLEXIO2_IRQHandler + .type FLEXIO2_IRQHandler, %function +FLEXIO2_IRQHandler: + ldr r0,=FLEXIO2_DriverIRQHandler + bx r0 + .size FLEXIO2_IRQHandler, . - FLEXIO2_IRQHandler + + .align 1 + .thumb_func + .weak FLEXSPI2_IRQHandler + .type FLEXSPI2_IRQHandler, %function +FLEXSPI2_IRQHandler: + ldr r0,=FLEXSPI2_DriverIRQHandler + bx r0 + .size FLEXSPI2_IRQHandler, . - FLEXSPI2_IRQHandler + + .align 1 + .thumb_func + .weak FLEXSPI_IRQHandler + .type FLEXSPI_IRQHandler, %function +FLEXSPI_IRQHandler: + ldr r0,=FLEXSPI_DriverIRQHandler + bx r0 + .size FLEXSPI_IRQHandler, . - FLEXSPI_IRQHandler + + .align 1 + .thumb_func + .weak USDHC1_IRQHandler + .type USDHC1_IRQHandler, %function +USDHC1_IRQHandler: + ldr r0,=USDHC1_DriverIRQHandler + bx r0 + .size USDHC1_IRQHandler, . - USDHC1_IRQHandler + + .align 1 + .thumb_func + .weak USDHC2_IRQHandler + .type USDHC2_IRQHandler, %function +USDHC2_IRQHandler: + ldr r0,=USDHC2_DriverIRQHandler + bx r0 + .size USDHC2_IRQHandler, . - USDHC2_IRQHandler + + .align 1 + .thumb_func + .weak ENET_IRQHandler + .type ENET_IRQHandler, %function +ENET_IRQHandler: + ldr r0,=ENET_DriverIRQHandler + bx r0 + .size ENET_IRQHandler, . - ENET_IRQHandler + + .align 1 + .thumb_func + .weak ENET_1588_Timer_IRQHandler + .type ENET_1588_Timer_IRQHandler, %function +ENET_1588_Timer_IRQHandler: + ldr r0,=ENET_1588_Timer_DriverIRQHandler + bx r0 + .size ENET_1588_Timer_IRQHandler, . - ENET_1588_Timer_IRQHandler + + .align 1 + .thumb_func + .weak ENET2_IRQHandler + .type ENET2_IRQHandler, %function +ENET2_IRQHandler: + ldr r0,=ENET2_DriverIRQHandler + bx r0 + .size ENET2_IRQHandler, . - ENET2_IRQHandler + + .align 1 + .thumb_func + .weak ENET2_1588_Timer_IRQHandler + .type ENET2_1588_Timer_IRQHandler, %function +ENET2_1588_Timer_IRQHandler: + ldr r0,=ENET2_1588_Timer_DriverIRQHandler + bx r0 + .size ENET2_1588_Timer_IRQHandler, . - ENET2_1588_Timer_IRQHandler + + .align 1 + .thumb_func + .weak CAN3_IRQHandler + .type CAN3_IRQHandler, %function +CAN3_IRQHandler: + ldr r0,=CAN3_DriverIRQHandler + bx r0 + .size CAN3_IRQHandler, . - CAN3_IRQHandler + + .align 1 + .thumb_func + .weak FLEXIO3_IRQHandler + .type FLEXIO3_IRQHandler, %function +FLEXIO3_IRQHandler: + ldr r0,=FLEXIO3_DriverIRQHandler + bx r0 + .size FLEXIO3_IRQHandler, . - FLEXIO3_IRQHandler + + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, DefaultISR + .endm +/* Exception Handlers */ + def_irq_handler MemManage_Handler + def_irq_handler BusFault_Handler + def_irq_handler UsageFault_Handler + def_irq_handler DebugMon_Handler + def_irq_handler DMA0_DMA16_DriverIRQHandler + def_irq_handler DMA1_DMA17_DriverIRQHandler + def_irq_handler DMA2_DMA18_DriverIRQHandler + def_irq_handler DMA3_DMA19_DriverIRQHandler + def_irq_handler DMA4_DMA20_DriverIRQHandler + def_irq_handler DMA5_DMA21_DriverIRQHandler + def_irq_handler DMA6_DMA22_DriverIRQHandler + def_irq_handler DMA7_DMA23_DriverIRQHandler + def_irq_handler DMA8_DMA24_DriverIRQHandler + def_irq_handler DMA9_DMA25_DriverIRQHandler + def_irq_handler DMA10_DMA26_DriverIRQHandler + def_irq_handler DMA11_DMA27_DriverIRQHandler + def_irq_handler DMA12_DMA28_DriverIRQHandler + def_irq_handler DMA13_DMA29_DriverIRQHandler + def_irq_handler DMA14_DMA30_DriverIRQHandler + def_irq_handler DMA15_DMA31_DriverIRQHandler + def_irq_handler DMA_ERROR_DriverIRQHandler + def_irq_handler CTI0_ERROR_IRQHandler + def_irq_handler CTI1_ERROR_IRQHandler + def_irq_handler CORE_IRQHandler + def_irq_handler LPUART1_DriverIRQHandler + def_irq_handler LPUART2_DriverIRQHandler + def_irq_handler LPUART3_DriverIRQHandler + def_irq_handler LPUART4_DriverIRQHandler + def_irq_handler LPUART5_DriverIRQHandler + def_irq_handler LPUART6_DriverIRQHandler + def_irq_handler LPUART7_DriverIRQHandler + def_irq_handler LPUART8_DriverIRQHandler + def_irq_handler LPI2C1_DriverIRQHandler + def_irq_handler LPI2C2_DriverIRQHandler + def_irq_handler LPI2C3_DriverIRQHandler + def_irq_handler LPI2C4_DriverIRQHandler + def_irq_handler LPSPI1_DriverIRQHandler + def_irq_handler LPSPI2_DriverIRQHandler + def_irq_handler LPSPI3_DriverIRQHandler + def_irq_handler LPSPI4_DriverIRQHandler + def_irq_handler CAN1_DriverIRQHandler + def_irq_handler CAN2_DriverIRQHandler + def_irq_handler FLEXRAM_IRQHandler + def_irq_handler KPP_IRQHandler + def_irq_handler TSC_DIG_IRQHandler + def_irq_handler GPR_IRQ_IRQHandler + def_irq_handler LCDIF_IRQHandler + def_irq_handler CSI_IRQHandler + def_irq_handler PXP_IRQHandler + def_irq_handler WDOG2_IRQHandler + def_irq_handler SNVS_HP_WRAPPER_IRQHandler + def_irq_handler SNVS_HP_WRAPPER_TZ_IRQHandler + def_irq_handler SNVS_LP_WRAPPER_IRQHandler + def_irq_handler CSU_IRQHandler + def_irq_handler DCP_IRQHandler + def_irq_handler DCP_VMI_IRQHandler + def_irq_handler Reserved68_IRQHandler + def_irq_handler TRNG_IRQHandler + def_irq_handler SJC_IRQHandler + def_irq_handler BEE_IRQHandler + def_irq_handler SAI1_DriverIRQHandler + def_irq_handler SAI2_DriverIRQHandler + def_irq_handler SAI3_RX_DriverIRQHandler + def_irq_handler SAI3_TX_DriverIRQHandler + def_irq_handler SPDIF_DriverIRQHandler + def_irq_handler PMU_EVENT_IRQHandler + def_irq_handler Reserved78_IRQHandler + def_irq_handler TEMP_LOW_HIGH_IRQHandler + def_irq_handler TEMP_PANIC_IRQHandler + def_irq_handler USB_PHY1_IRQHandler + def_irq_handler USB_PHY2_IRQHandler + def_irq_handler ADC1_IRQHandler + def_irq_handler ADC2_IRQHandler + def_irq_handler DCDC_IRQHandler + def_irq_handler Reserved86_IRQHandler + def_irq_handler GPIO10_IRQHandler + def_irq_handler GPIO1_INT0_IRQHandler + def_irq_handler GPIO1_INT1_IRQHandler + def_irq_handler GPIO1_INT2_IRQHandler + def_irq_handler GPIO1_INT3_IRQHandler + def_irq_handler GPIO1_INT4_IRQHandler + def_irq_handler GPIO1_INT5_IRQHandler + def_irq_handler GPIO1_INT6_IRQHandler + def_irq_handler GPIO1_INT7_IRQHandler + def_irq_handler GPIO1_Combined_0_15_IRQHandler + def_irq_handler GPIO1_Combined_16_31_IRQHandler + def_irq_handler GPIO2_Combined_0_15_IRQHandler + def_irq_handler GPIO2_Combined_16_31_IRQHandler + def_irq_handler GPIO3_Combined_0_15_IRQHandler + def_irq_handler GPIO3_Combined_16_31_IRQHandler + def_irq_handler GPIO4_Combined_0_15_IRQHandler + def_irq_handler GPIO4_Combined_16_31_IRQHandler + def_irq_handler GPIO5_Combined_0_15_IRQHandler + def_irq_handler GPIO5_Combined_16_31_IRQHandler + def_irq_handler FLEXIO1_DriverIRQHandler + def_irq_handler FLEXIO2_DriverIRQHandler + def_irq_handler WDOG1_IRQHandler + def_irq_handler RTWDOG_IRQHandler + def_irq_handler EWM_IRQHandler + def_irq_handler CCM_1_IRQHandler + def_irq_handler CCM_2_IRQHandler + def_irq_handler GPC_IRQHandler + def_irq_handler SRC_IRQHandler + def_irq_handler Reserved115_IRQHandler + def_irq_handler GPT1_IRQHandler + def_irq_handler GPT2_IRQHandler + def_irq_handler PWM1_0_IRQHandler + def_irq_handler PWM1_1_IRQHandler + def_irq_handler PWM1_2_IRQHandler + def_irq_handler PWM1_3_IRQHandler + def_irq_handler PWM1_FAULT_IRQHandler + def_irq_handler FLEXSPI2_DriverIRQHandler + def_irq_handler FLEXSPI_DriverIRQHandler + def_irq_handler SEMC_IRQHandler + def_irq_handler USDHC1_DriverIRQHandler + def_irq_handler USDHC2_DriverIRQHandler + def_irq_handler USB_OTG2_IRQHandler + def_irq_handler USB_OTG1_IRQHandler + def_irq_handler ENET_DriverIRQHandler + def_irq_handler ENET_1588_Timer_DriverIRQHandler + def_irq_handler XBAR1_IRQ_0_1_IRQHandler + def_irq_handler XBAR1_IRQ_2_3_IRQHandler + def_irq_handler ADC_ETC_IRQ0_IRQHandler + def_irq_handler ADC_ETC_IRQ1_IRQHandler + def_irq_handler ADC_ETC_IRQ2_IRQHandler + def_irq_handler ADC_ETC_ERROR_IRQ_IRQHandler + def_irq_handler PIT_IRQHandler + def_irq_handler ACMP1_IRQHandler + def_irq_handler ACMP2_IRQHandler + def_irq_handler ACMP3_IRQHandler + def_irq_handler ACMP4_IRQHandler + def_irq_handler Reserved143_IRQHandler + def_irq_handler Reserved144_IRQHandler + def_irq_handler ENC1_IRQHandler + def_irq_handler ENC2_IRQHandler + def_irq_handler ENC3_IRQHandler + def_irq_handler ENC4_IRQHandler + def_irq_handler TMR1_IRQHandler + def_irq_handler TMR2_IRQHandler + def_irq_handler TMR3_IRQHandler + def_irq_handler TMR4_IRQHandler + def_irq_handler PWM2_0_IRQHandler + def_irq_handler PWM2_1_IRQHandler + def_irq_handler PWM2_2_IRQHandler + def_irq_handler PWM2_3_IRQHandler + def_irq_handler PWM2_FAULT_IRQHandler + def_irq_handler PWM3_0_IRQHandler + def_irq_handler PWM3_1_IRQHandler + def_irq_handler PWM3_2_IRQHandler + def_irq_handler PWM3_3_IRQHandler + def_irq_handler PWM3_FAULT_IRQHandler + def_irq_handler PWM4_0_IRQHandler + def_irq_handler PWM4_1_IRQHandler + def_irq_handler PWM4_2_IRQHandler + def_irq_handler PWM4_3_IRQHandler + def_irq_handler PWM4_FAULT_IRQHandler + def_irq_handler ENET2_DriverIRQHandler + def_irq_handler ENET2_1588_Timer_DriverIRQHandler + def_irq_handler CAN3_DriverIRQHandler + def_irq_handler Reserved171_IRQHandler + def_irq_handler FLEXIO3_DriverIRQHandler + def_irq_handler GPIO6_7_8_9_IRQHandler + + .end diff --git a/targets/NXP/MIMXRT1064-EVK/app/startup/tx_initialize_low_level.S b/targets/NXP/MIMXRT1064-EVK/app/startup/tx_initialize_low_level.S new file mode 100644 index 00000000..d34654b5 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/startup/tx_initialize_low_level.S @@ -0,0 +1,207 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 version. + **************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Initialize */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .global _tx_thread_system_stack_ptr + .global _tx_initialize_unused_memory + .global __RAM_segment_used_end__ + .global _tx_timer_interrupt + .global _vectors + .global __tx_NMIHandler // NMI + .global __tx_BadHandler // HardFault + .global __tx_SVCallHandler // SVCall + .global __tx_DBGHandler // Monitor + .global __tx_PendSVHandler // PendSV + .global __tx_SysTickHandler // SysTick + .global __tx_IntHandler // Int 0 + +SYSTICK_CYCLES_HW = ((600000000 / 100) - 1) // 5,999,999 cycles: 600 MHz on real silicon -> 100 Hz +SYSTICK_CYCLES_RENODE = ((72000000 / 100) - 1) // 719,999 cycles: 72 MHz in Renode NVIC -> 100 Hz + + .text + .align 4 + .syntax unified + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_initialize_low_level Cortex-M7/GNU */ +/* 6.4.0 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for any low-level processor */ +/* initialization, including setting up interrupt vectors, setting */ +/* up a periodic timer interrupt source, saving the system stack */ +/* pointer for use in ISR processing later, and finding the first */ +/* available RAM memory address for tx_application_define. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter ThreadX entry function */ +/* */ +/**************************************************************************/ + .global _tx_initialize_low_level + .thumb_func +_tx_initialize_low_level: + + /* Disable interrupts during ThreadX initialization. */ + CPSID i + + /* Set base of available memory to end of non-initialised RAM area. */ + LDR r0, =_tx_initialize_unused_memory // Build address of unused memory pointer + LDR r1, =__RAM_segment_used_end__ // Build first free address + ADD r1, r1, #4 // + STR r1, [r0] // Setup first unused memory pointer + + /* Setup Vector Table Offset Register. */ + MOV r0, #0xE000E000 // Build address of NVIC registers + LDR r1, =_vectors // Pickup address of vector table + STR r1, [r0, #0xD08] // Set vector table address + + /* Set system stack pointer from vector value. */ + LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer + LDR r1, =_vectors // Pickup address of vector table + LDR r1, [r1] // Pickup reset stack pointer + STR r1, [r0] // Save system stack pointer + + /* Enable the DWT cycle count register if DWT hardware is present (physical silicon). */ + LDR r1, =0xE000ED90 // MPU->TYPE register + LDR r1, [r1] + LSRS r1, r1, #8 + AND r1, r1, #0xFF // Extract DREGION field + CMP r1, #12 // Physical silicon has 16 regions, Renode has 8 + BLT .Lskip_dwt + LDR r0, =0xE0001000 // Build address of DWT register + LDR r1, [r0] // Pickup the current value + ORR r1, r1, #1 // Set the CYCCNTENA bit + STR r1, [r0] // Enable the cycle count register +.Lskip_dwt: + + /* Configure SysTick reload: detect Renode (72 MHz NVIC clock) vs physical silicon (600 MHz core clock). */ + LDR r1, =0xE000ED90 // MPU->TYPE register + LDR r1, [r1] + LSRS r1, r1, #8 + AND r1, r1, #0xFF // Extract DREGION field + CMP r1, #12 + BLT .Lrenode_systick + LDR r1, =SYSTICK_CYCLES_HW // 600 MHz clock -> reload for 100 Hz + B .Lset_systick +.Lrenode_systick: + LDR r1, =SYSTICK_CYCLES_RENODE // 72 MHz clock -> reload for 100 Hz +.Lset_systick: + MOV r0, #0xE000E000 // Build address of NVIC registers + STR r1, [r0, #0x14] // Setup SysTick Reload Value + MOV r1, #0x7 // Build SysTick Control Enable Value (CLKSOURCE|TICKINT|ENABLE) + STR r1, [r0, #0x10] // Setup SysTick Control + + /* Configure handler priorities (upper 4 bits implemented on Cortex-M7, mask 0xF0). */ + LDR r1, =0x00000000 // Rsrv, UsgF, BusF, MemM + STR r1, [r0, #0xD18] // Setup System Handlers 4-7 Priority Registers + LDR r1, =0xF0000000 // SVCl, Rsrv, Rsrv, Rsrv + STR r1, [r0, #0xD1C] // Setup System Handlers 8-11 Priority Registers + // Note: SVC must be lowest priority (0xF0 for 4-bit NVIC) + LDR r1, =0x40F00000 // SysT (0x40), PnSV (0xF0), Rsrv, DbgM + STR r1, [r0, #0xD20] // Setup System Handlers 12-15 Priority Registers + // Note: PnSV must be lowest priority (0xF0 for 4-bit NVIC) + + /* Return to caller. */ + BX lr + +/* Define shells for each of the unused vectors. */ + .global __tx_BadHandler + .thumb_func +__tx_BadHandler: + B __tx_BadHandler + +/* Catch HardFault */ + .global __tx_HardfaultHandler + .thumb_func +__tx_HardfaultHandler: + B __tx_HardfaultHandler + +/* Catch SVC */ + .global __tx_SVCallHandler + .thumb_func +__tx_SVCallHandler: + B __tx_SVCallHandler + +/* Generic interrupt handler template */ + .global __tx_IntHandler + .thumb_func +__tx_IntHandler: + PUSH {r0, lr} +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_enter // Call the ISR enter function +#endif + /* Do interrupt handler work here */ +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_exit // Call the ISR exit function +#endif + POP {r0, lr} + BX lr + +/* System Tick timer interrupt handler */ + .global __tx_SysTickHandler + .global SysTick_Handler + .thumb_func +__tx_SysTickHandler: + .thumb_func +SysTick_Handler: + PUSH {r0, lr} +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_enter // Call the ISR enter function +#endif + BL _tx_timer_interrupt +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_exit // Call the ISR exit function +#endif + POP {r0, lr} + BX lr + +/* NMI, DBG handlers */ + .global __tx_NMIHandler + .thumb_func +__tx_NMIHandler: + B __tx_NMIHandler + + .global __tx_DBGHandler + .thumb_func +__tx_DBGHandler: + B __tx_DBGHandler diff --git a/targets/NXP/MIMXRT1064-EVK/app/syscalls.c b/targets/NXP/MIMXRT1064-EVK/app/syscalls.c new file mode 100644 index 00000000..2411304a --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/syscalls.c @@ -0,0 +1,131 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +char *__env[1] = { 0 }; +char **environ = __env; + +void initialise_monitor_handles(void) +{ +} + +int _getpid(void) +{ + return 1; +} + +int _kill(int pid, int sig) +{ + (void)pid; + (void)sig; + errno = EINVAL; + return -1; +} + +void _exit(int status) +{ + _kill(status, -1); + while (1) {} +} + +int _close(int file) +{ + (void)file; + return -1; +} + +int _fstat(int file, struct stat *st) +{ + (void)file; + st->st_mode = S_IFCHR; + return 0; +} + +int _isatty(int file) +{ + (void)file; + return 1; +} + +int _lseek(int file, int ptr, int dir) +{ + (void)file; + (void)ptr; + (void)dir; + return 0; +} + +int _open(char *path, int flags, ...) +{ + (void)path; + (void)flags; + return -1; +} + +int _wait(int *status) +{ + (void)status; + errno = ECHILD; + return -1; +} + +int _unlink(char *name) +{ + (void)name; + errno = ENOENT; + return -1; +} + +int _times(struct tms *buf) +{ + (void)buf; + return -1; +} + +int _stat(char *file, struct stat *st) +{ + (void)file; + st->st_mode = S_IFCHR; + return 0; +} + +int _link(char *old, char *new) +{ + (void)old; + (void)new; + errno = EMLINK; + return -1; +} + +int _fork(void) +{ + errno = EAGAIN; + return -1; +} + +int _execve(char *name, char **argv, char **env) +{ + (void)name; + (void)argv; + (void)env; + errno = ENOMEM; + return -1; +} diff --git a/targets/NXP/MIMXRT1064-EVK/app/sysmem.c b/targets/NXP/MIMXRT1064-EVK/app/sysmem.c new file mode 100644 index 00000000..0f2dfe23 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/sysmem.c @@ -0,0 +1,105 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) + */ + +#include "tx_api.h" +#include +#include +#include +#include + +/** + * Pointer to the current high watermark of the heap usage + */ +static uint8_t *__sbrk_heap_end = NULL; + +/** + * Depth and interrupt posture for re-entrant newlib malloc locking + */ +static unsigned int s_malloc_lock_posture = 0; +static uint32_t s_malloc_lock_depth = 0; + +void __malloc_lock(struct _reent *reent) +{ + (void)reent; + TX_INTERRUPT_SAVE_AREA + TX_DISABLE + if (s_malloc_lock_depth == 0U) + { + s_malloc_lock_posture = interrupt_save; + } + s_malloc_lock_depth++; +} + +void __malloc_unlock(struct _reent *reent) +{ + (void)reent; + if (s_malloc_lock_depth == 0U) + { + return; + } + s_malloc_lock_depth--; + if (s_malloc_lock_depth == 0U) + { + TX_INTERRUPT_SAVE_AREA + interrupt_save = s_malloc_lock_posture; + TX_RESTORE + } +} + +/** + * @brief _sbrk() allocates memory to the newlib heap and is used by malloc. + */ +void *_sbrk(ptrdiff_t incr) +{ + extern uint8_t _end; + extern uint8_t __heap_limit; + const uint8_t *max_heap = &__heap_limit; + uint8_t *prev_heap_end; + + TX_INTERRUPT_SAVE_AREA + TX_DISABLE + + /* Initialize heap end at first call */ + if (NULL == __sbrk_heap_end) + { + __sbrk_heap_end = &_end; + } + + /* Protect heap from growing beyond linker-defined heap limit without overflow */ + if (incr > 0) + { + if ((uintptr_t)incr > (uintptr_t)(max_heap - __sbrk_heap_end)) + { + TX_RESTORE + errno = ENOMEM; + return (void *)-1; + } + } + else if (incr < 0) + { + uintptr_t dec = (uintptr_t)(-incr); + if (dec > (uintptr_t)(__sbrk_heap_end - &_end)) + { + TX_RESTORE + errno = EINVAL; + return (void *)-1; + } + } + + prev_heap_end = __sbrk_heap_end; + __sbrk_heap_end += incr; + + TX_RESTORE + return (void *)prev_heap_end; +} diff --git a/targets/NXP/MIMXRT1064-EVK/app/trng.c b/targets/NXP/MIMXRT1064-EVK/app/trng.c new file mode 100644 index 00000000..c749a5c1 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/trng.c @@ -0,0 +1,198 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) + */ + +#include "trng.h" +#include "fsl_device_registers.h" +#include "fsl_clock.h" +#include "tx_api.h" +#include + +#define TRNG_TIMEOUT_CYCLES 1000000UL +#define TRNG_ENTROPY_WORDS 16 + +/* Recommended sampling and delay parameters according to NXP Reference Manual */ +#define TRNG_SAMPLE_SIZE_DEF 2500U +#define TRNG_ENTROPY_DLY_DEF 3200U + +/* + * Static entropy pool buffer caching a full 512-bit hardware entropy block + * (16 words * 32 bits = 512 bits) read from ENT[0..15]. + */ +static uint32_t s_entropy_pool[TRNG_ENTROPY_WORDS]; +static size_t s_pool_index = TRNG_ENTROPY_WORDS; /* Initially empty */ + +/* ThreadX mutex for mutual exclusion across concurrent threads */ +static TX_MUTEX s_trng_mutex; +static bool s_trng_mutex_created = false; + +/* Helper to acquire mutex if ThreadX kernel is running */ +static inline void trng_mutex_lock(void) +{ + if (s_trng_mutex_created && (tx_thread_identify() != TX_NULL)) + { + tx_mutex_get(&s_trng_mutex, TX_WAIT_FOREVER); + } +} + +/* Helper to release mutex if ThreadX kernel is running */ +static inline void trng_mutex_unlock(void) +{ + if (s_trng_mutex_created && (tx_thread_identify() != TX_NULL)) + { + tx_mutex_put(&s_trng_mutex); + } +} + +int trng_init(void) +{ + /* Initialize ThreadX mutex once for thread-safe access */ + if (!s_trng_mutex_created) + { + if (tx_mutex_create(&s_trng_mutex, "TRNG Mutex", TX_INHERIT) == TX_SUCCESS) + { + s_trng_mutex_created = true; + } + } + + trng_mutex_lock(); + + /* 1. Enable TRNG peripheral clock in CCM */ + CLOCK_EnableClock(kCLOCK_Trng); + + /* 2. Enter Program Mode to allow programming control & delay registers */ + TRNG->MCTL |= TRNG_MCTL_PRGM_MASK; + + /* 3. Reset TRNG registers to hardware defaults (and clear ERR flag) */ + TRNG->MCTL |= TRNG_MCTL_RST_DEF_MASK; + + /* 4. Configure entropy sample size and delay parameters in SDCTL */ + TRNG->SDCTL = TRNG_SDCTL_ENT_DLY(TRNG_ENTROPY_DLY_DEF) | + TRNG_SDCTL_SAMP_SIZE(TRNG_SAMPLE_SIZE_DEF); + + /* 5. Set Von Neumann sampling mode (0b00) and un-divided oscillator (0b00) */ + TRNG->MCTL = (TRNG->MCTL & ~(TRNG_MCTL_SAMP_MODE_MASK | TRNG_MCTL_OSC_DIV_MASK)) | + TRNG_MCTL_SAMP_MODE(0) | TRNG_MCTL_OSC_DIV(0); + + /* 6. Exit Program Mode to enter Run Mode. + * In NXP hardware, transitioning PRGM from 1 to 0 actively initiates + * the entropy generation state machine. + */ + TRNG->MCTL &= ~TRNG_MCTL_PRGM_MASK; + + /* Invalidate local entropy pool */ + s_pool_index = TRNG_ENTROPY_WORDS; + + trng_mutex_unlock(); + + return 0; +} + +int trng_get_random_u32(uint32_t *random_val) +{ + uint32_t timeout; + + if (random_val == NULL) + { + return -1; + } + + /* + * Mutex serializes access among concurrent threads (e.g. multiple shell sessions), + * preventing race conditions on observing ENT_VAL and reading ENT registers. + */ + trng_mutex_lock(); + + /* If cached entropy is available, dispense immediately without hardware wait */ + if (s_pool_index < TRNG_ENTROPY_WORDS) + { + *random_val = s_entropy_pool[s_pool_index++]; + trng_mutex_unlock(); + return 0; + } + + /* If hardware reports an error, recover via documented re-initialization */ + if (TRNG->MCTL & TRNG_MCTL_ERR_MASK) + { + trng_init(); + } + + /* Wait for Entropy Valid (ENT_VAL) bit */ + timeout = TRNG_TIMEOUT_CYCLES; + while (!(TRNG->MCTL & TRNG_MCTL_ENT_VAL_MASK)) + { + if (--timeout == 0) + { + trng_mutex_unlock(); + return -2; /* Timeout waiting for entropy */ + } + } + + /* + * Read all 16 entropy registers (ENT[0] through ENT[15]). + * + * Per the NXP i.MX RT1060 Reference Manual (TRNG section): + * Reading ENT15 is the hardware signal that acknowledges and consumes the + * 512-bit entropy block, automatically clears MCTL[ENT_VAL] to 0, and + * initiates the next hardware entropy generation cycle. + */ + for (size_t i = 0; i < TRNG_ENTROPY_WORDS; i++) + { + s_entropy_pool[i] = TRNG->ENT[i]; + } + s_pool_index = 0; + + *random_val = s_entropy_pool[s_pool_index++]; + + trng_mutex_unlock(); + return 0; +} + +int trng_get_random_data(void *buffer, size_t length) +{ + uint8_t *out = (uint8_t *)buffer; + size_t offset = 0; + uint32_t rand_word; + int status; + + if (buffer == NULL) + { + return -1; + } + + /* Acquire mutex to ensure the buffer is filled contiguously without thread interleaving */ + trng_mutex_lock(); + + while (offset < length) + { + status = trng_get_random_u32(&rand_word); + if (status != 0) + { + trng_mutex_unlock(); + return status; + } + + size_t chunk = length - offset; + if (chunk > sizeof(uint32_t)) + { + chunk = sizeof(uint32_t); + } + + memcpy(out + offset, &rand_word, chunk); + offset += chunk; + } + + trng_mutex_unlock(); + + return (int)length; +} diff --git a/targets/NXP/MIMXRT1064-EVK/app/trng.h b/targets/NXP/MIMXRT1064-EVK/app/trng.h new file mode 100644 index 00000000..fbb364b6 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/app/trng.h @@ -0,0 +1,55 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) + */ + +#ifndef TRNG_H +#define TRNG_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize the on-chip True Random Number Generator (TRNG) peripheral. + * Enables TRNG peripheral clock gating and initializes default sampling parameters. + * + * @return 0 on success, non-zero on error. + */ +int trng_init(void); + +/** + * @brief Read a single 32-bit hardware random word from TRNG entropy registers. + * + * @param[out] random_val Pointer to uint32_t to receive the random word. + * @return 0 on success, non-zero on error or timeout. + */ +int trng_get_random_u32(uint32_t *random_val); + +/** + * @brief Fill a buffer with hardware random bytes from TRNG entropy registers. + * + * @param[out] buffer Output buffer to receive random bytes. + * @param[in] length Number of bytes to generate. + * @return Number of bytes filled on success, or negative on error. + */ +int trng_get_random_data(void *buffer, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif /* TRNG_H */ diff --git a/targets/NXP/MIMXRT1064-EVK/cmake/arm-gcc-cortex-m7.cmake b/targets/NXP/MIMXRT1064-EVK/cmake/arm-gcc-cortex-m7.cmake new file mode 100644 index 00000000..c22c25b3 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/cmake/arm-gcc-cortex-m7.cmake @@ -0,0 +1,20 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +# Define the CPU architecture for ThreadX +set(THREADX_ARCH "cortex_m7") +set(THREADX_TOOLCHAIN "gnu") + +# Cortex-M7 compiler options for NXP i.MX RT1064 +set(MCPU_FLAGS "-mthumb -mcpu=cortex-m7") +set(VFP_FLAGS "-mfloat-abi=hard -mfpu=fpv5-d16") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-gcc-cortex-toolchain.cmake) diff --git a/targets/NXP/MIMXRT1064-EVK/cmake/arm-gcc-cortex-toolchain.cmake b/targets/NXP/MIMXRT1064-EVK/cmake/arm-gcc-cortex-toolchain.cmake new file mode 100644 index 00000000..0fe01f90 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/cmake/arm-gcc-cortex-toolchain.cmake @@ -0,0 +1,77 @@ +# Copyright (c) Microsoft +# 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 +# +# Contributors: +# Microsoft - Initial version +# Frédéric Desbiens - 2024 version. +# Ali Eissa - 2026 version. + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR arm) +set(TARGET_TRIPLET "arm-none-eabi-") + +# Default to Debug build +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build, options are: Debug Release." FORCE) +endif() + +# Windows executable suffix handling +if(WIN32) + set(TOOLCHAIN_EXT ".exe") +else() + set(TOOLCHAIN_EXT "") +endif() + +find_program(COMPILER_ON_PATH "${TARGET_TRIPLET}gcc${TOOLCHAIN_EXT}") + +if(DEFINED ENV{ARM_GCC_PATH}) + file(TO_CMAKE_PATH $ENV{ARM_GCC_PATH} ARM_TOOLCHAIN_PATH) + message(STATUS "Using ENV variable ARM_GCC_PATH = ${ARM_TOOLCHAIN_PATH}") +elseif(COMPILER_ON_PATH) + get_filename_component(ARM_TOOLCHAIN_PATH ${COMPILER_ON_PATH} DIRECTORY) + message(STATUS "Using ARM GCC from PATH = ${ARM_TOOLCHAIN_PATH}") +else() + message(FATAL_ERROR "Unable to find ARM GCC (${TARGET_TRIPLET}gcc). Either add it to your PATH, or define ARM_GCC_PATH to the compiler directory.") +endif() + +# Perform compiler test with a static library +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +set(CMAKE_C_COMPILER ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc${TOOLCHAIN_EXT}) +set(CMAKE_CXX_COMPILER ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}g++${TOOLCHAIN_EXT}) +set(CMAKE_ASM_COMPILER ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc${TOOLCHAIN_EXT}) +set(CMAKE_LINKER ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc${TOOLCHAIN_EXT}) +set(CMAKE_SIZE_UTIL ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}size${TOOLCHAIN_EXT}) +set(CMAKE_OBJCOPY ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}objcopy${TOOLCHAIN_EXT}) +set(CMAKE_OBJDUMP ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}objdump${TOOLCHAIN_EXT}) +set(CMAKE_NM_UTIL ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc-nm${TOOLCHAIN_EXT}) +set(CMAKE_AR ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc-ar${TOOLCHAIN_EXT}) +set(CMAKE_RANLIB ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc-ranlib${TOOLCHAIN_EXT}) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +# Compiler and linker flags +set(CMAKE_COMMON_FLAGS "-g3 -ffunction-sections -fdata-sections -fno-strict-aliasing -fno-builtin -fno-common -Wall -Wdouble-promotion -Werror -Wno-unused-parameter") +set(CMAKE_C_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} ${CMAKE_COMMON_FLAGS}") +set(CMAKE_CXX_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} ${CMAKE_COMMON_FLAGS}") +set(CMAKE_ASM_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} ${CMAKE_COMMON_FLAGS}") +set(CMAKE_EXE_LINKER_FLAGS "${LD_FLAGS} --specs=nano.specs -Wl,--gc-sections,-print-memory-usage") + +set(CMAKE_C_FLAGS_DEBUG "-O0") +set(CMAKE_CXX_FLAGS_DEBUG "-O0") +set(CMAKE_ASM_FLAGS_DEBUG "") +set(CMAKE_EXE_LINKER_FLAGS_DEBUG "") + +set(CMAKE_C_FLAGS_RELEASE "-Os -flto") +set(CMAKE_CXX_FLAGS_RELEASE "-Os -flto") +set(CMAKE_ASM_FLAGS_RELEASE "") +set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-flto") diff --git a/targets/NXP/MIMXRT1064-EVK/cmake/utilities.cmake b/targets/NXP/MIMXRT1064-EVK/cmake/utilities.cmake new file mode 100644 index 00000000..0cc921f9 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/cmake/utilities.cmake @@ -0,0 +1,50 @@ +# Copyright (c) Microsoft +# 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 +# +# Contributors: +# Microsoft - Initial version +# Frédéric Desbiens - 2024 version. +# Ali Eissa - 2026 version. + +function(post_build TARGET) + if(CMAKE_C_COMPILER_ID STREQUAL "IAR") + add_custom_target(${TARGET}_bin ALL + DEPENDS ${TARGET} + COMMAND ${CMAKE_IAR_ELFTOOL} --bin ${TARGET}.elf ${TARGET}.bin) + elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") + add_custom_target(${TARGET}_bin ALL + DEPENDS ${TARGET} + COMMAND ${CMAKE_OBJCOPY} -Obinary $ $/$.bin + COMMAND ${CMAKE_OBJCOPY} -Oihex $ $/$.hex) + else() + message(FATAL_ERROR "Unknown CMAKE_C_COMPILER_ID ${CMAKE_C_COMPILER_ID}") + endif() +endfunction() + +function(set_target_linker TARGET LINKER_SCRIPT) + if(CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PRIVATE --config ${LINKER_SCRIPT}) + target_link_options(${TARGET} PRIVATE --map=${TARGET}.map) + elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PRIVATE -T${LINKER_SCRIPT}) + target_link_options(${TARGET} PRIVATE -Wl,-Map=$/$.map) + set_target_properties(${TARGET} PROPERTIES SUFFIX ".elf") + else() + message(FATAL_ERROR "Unknown CMAKE_C_COMPILER_ID ${CMAKE_C_COMPILER_ID}") + endif() +endfunction() + +macro(print_all_variables) + message(STATUS "print_all_variables------------------------------------------{") + get_cmake_property(_variableNames VARIABLES) + foreach (_variableName ${_variableNames}) + message(STATUS "${_variableName}=${${_variableName}}") + endforeach() + message(STATUS "print_all_variables------------------------------------------}") +endmacro() diff --git a/targets/NXP/MIMXRT1064-EVK/lib/bsp/CMakeLists.txt b/targets/NXP/MIMXRT1064-EVK/lib/bsp/CMakeLists.txt new file mode 100644 index 00000000..a25f1a88 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/lib/bsp/CMakeLists.txt @@ -0,0 +1,52 @@ +# 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/licenses/MIT. +# +# SPDX-License-Identifier: MIT + +# Board Support Package implementation for NXP MIMXRT1064-EVK +add_library(mimxrt1064_bsp STATIC + src/bsp_board.c + src/bsp_led.c + src/bsp_console.c + src/bsp_memory.c + src/bsp_selftest.c +) + +target_include_directories(mimxrt1064_bsp + PUBLIC + include + ${SHARED_BSP_DIR}/include +) + +target_link_libraries(mimxrt1064_bsp + PUBLIC + mimxrt1064_common + ${SDK_TARGET} + threadx +) + +# Board startup, low-level ThreadX initialization, syscalls, and hardware TRNG +add_library(board_bsp OBJECT + ${CMAKE_CURRENT_SOURCE_DIR}/../../app/startup/startup_mimxrt1064.S + ${CMAKE_CURRENT_SOURCE_DIR}/../../app/startup/tx_initialize_low_level.S + ${CMAKE_CURRENT_SOURCE_DIR}/../../app/sysmem.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../app/syscalls.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../app/trng.c +) + +target_include_directories(board_bsp + PUBLIC + include + ${SHARED_BSP_DIR}/include +) + +target_link_libraries(board_bsp + PUBLIC + mimxrt1064_common + mimxrt1064_bsp + ${SDK_TARGET} + threadx +) diff --git a/targets/NXP/MIMXRT1064-EVK/lib/bsp/include/board_config.h b/targets/NXP/MIMXRT1064-EVK/lib/bsp/include/board_config.h new file mode 100644 index 00000000..c6c9572f --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/lib/bsp/include/board_config.h @@ -0,0 +1,38 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 version. + * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) + */ + +#ifndef BOARD_CONFIG_H +#define BOARD_CONFIG_H + +#include +#include + +#define BSP_BOARD_NAME "MIMXRT1064-EVK" +#define BSP_CORE_CLOCK_HZ 600000000UL +#define BSP_CPU_CLOCK_HZ BSP_CORE_CLOCK_HZ +#define BSP_SYSTEM_CLOCK_HZ BSP_CORE_CLOCK_HZ +#define BSP_UART_BAUDRATE 115200U + +#define BSP_HAS_LED 1 +#define BSP_HAS_CONSOLE 1 + +/* Memory configuration (DTCM data RAM) */ +#define BSP_RAM_START 0x20000000UL +#define BSP_RAM_SIZE 0x00020000UL /* 128 KB DTCM */ +#define BSP_RAM_END (BSP_RAM_START + BSP_RAM_SIZE) +#define BSP_MAIN_STACK_RESERVE 0x00000400UL /* 1 KB main stack */ + +extern uint32_t SystemCoreClock; + +#endif /* BOARD_CONFIG_H */ diff --git a/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_board.c b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_board.c new file mode 100644 index 00000000..a5018a59 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_board.c @@ -0,0 +1,51 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 version. + * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) + */ + +#include "bsp/board.h" +#include "bsp/led.h" +#include "bsp/console.h" +#include "board_config.h" + +#include "board.h" +#include "pin_mux.h" +#include "clock_config.h" +#include "fsl_iomuxc.h" +#include "fsl_gpio.h" + +void bsp_board_init(void) +{ + /* 1. Configure the Memory Protection Unit if supported by hardware */ + if (((MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos) >= 12) + { + BOARD_ConfigMPU(); + } + + /* 2. Configure Pin Muxing (UART1 TX/RX pins) */ + BOARD_InitPins(); + + /* 3. Configure User LED Pin Muxing (GPIO_AD_B0_09 -> GPIO1_IO09) */ + CLOCK_EnableClock(kCLOCK_Iomuxc); + IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, 0U); + IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, 0x10B0u); + + /* 4. Configure System Clocks (600 MHz AHB core clock) */ + BOARD_BootClockRUN(); + + /* 5. Initialize User LED and Console via standard BSP interfaces */ + bsp_led_init(); + bsp_console_init(); + + /* 6. Configure Ethernet Pin Muxing (RMII and MDC/MDIO) */ + BOARD_InitENET(); +} diff --git a/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_console.c b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_console.c new file mode 100644 index 00000000..ee3910d4 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_console.c @@ -0,0 +1,166 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 version. + * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) + */ + +#include "bsp/console.h" +#include "board_config.h" + +#include "fsl_lpuart.h" +#include "board.h" +#include "tx_api.h" + +#include +#include +#include + +#if BSP_HAS_CONSOLE +static bsp_console_rx_fn volatile console_rx_handler = NULL; +static void *volatile console_rx_context = NULL; +static TX_MUTEX s_console_mutex; +static volatile int s_console_mutex_created = 0; + +static void console_putc(char c) +{ + if (c == '\n') + { + while (!(LPUART_GetStatusFlags(LPUART1) & (uint32_t)kLPUART_TxDataRegEmptyFlag)) + { + } + LPUART_WriteByte(LPUART1, (uint8_t)'\r'); + } + + while (!(LPUART_GetStatusFlags(LPUART1) & (uint32_t)kLPUART_TxDataRegEmptyFlag)) + { + } + LPUART_WriteByte(LPUART1, (uint8_t)c); +} +#endif + +void bsp_console_init(void) +{ +#if BSP_HAS_CONSOLE + lpuart_config_t config; + + LPUART_GetDefaultConfig(&config); + config.baudRate_Bps = BSP_UART_BAUDRATE; + config.enableTx = true; + config.enableRx = true; + + uint32_t uartClkSrcFreq = BOARD_DebugConsoleSrcFreq(); + LPUART_Init(LPUART1, &config, uartClkSrcFreq); + + /* Set stdout and stderr to unbuffered mode so newlib printf never + * allocates dynamic heap buffers during multi-threaded execution. */ + setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stderr, NULL, _IONBF, 0); +#endif +} + +void bsp_console_write(const char *data, size_t length) +{ +#if BSP_HAS_CONSOLE + if ((data == NULL) || (length == 0U)) + { + return; + } + + int locked = 0; + /* Only acquire mutex if ThreadX is running, in thread mode, and not inside an ISR */ + if ((__get_IPSR() == 0U) && (tx_thread_identify() != TX_NULL)) + { + if (!s_console_mutex_created) + { + TX_INTERRUPT_SAVE_AREA + TX_DISABLE + if (!s_console_mutex_created) + { + if (tx_mutex_create(&s_console_mutex, "Console Mutex", TX_NO_INHERIT) == TX_SUCCESS) + { + s_console_mutex_created = 1; + } + } + TX_RESTORE + } + + if (s_console_mutex_created) + { + if (tx_mutex_get(&s_console_mutex, TX_WAIT_FOREVER) == TX_SUCCESS) + { + locked = 1; + } + } + } + + for (size_t i = 0U; i < length; i++) + { + console_putc(data[i]); + } + + if (locked) + { + tx_mutex_put(&s_console_mutex); + } +#else + (void)data; + (void)length; +#endif +} + +void bsp_console_set_rx_handler(bsp_console_rx_fn handler, void *context) +{ +#if BSP_HAS_CONSOLE + console_rx_context = context; + console_rx_handler = handler; +#else + (void)handler; + (void)context; +#endif +} + +/* Backward compatibility wrapper for existing code calling console_write */ +void console_write(const char *str) +{ + if (str != NULL) + { + size_t len = 0; + while (str[len] != '\0') + { + len++; + } + bsp_console_write(str, len); + } +} + +/* C runtime newlib redirection */ +int _write(int file, char *ptr, int len) +{ + (void)file; + if (len > 0 && ptr != NULL) + { + bsp_console_write(ptr, (size_t)len); + } + return len; +} + +int _read(int file, char *ptr, int len) +{ + (void)file; + for (int i = 0; i < len; i++) + { + while (!(LPUART_GetStatusFlags(LPUART1) & (uint32_t)kLPUART_RxDataRegFullFlag)) + { + } + ptr[i] = (char)LPUART_ReadByte(LPUART1); + } + return len; +} diff --git a/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_led.c b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_led.c new file mode 100644 index 00000000..59ecb493 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_led.c @@ -0,0 +1,56 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 version. + * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) + */ + +#include "bsp/led.h" +#include "board_config.h" + +#include "board.h" +#include "fsl_gpio.h" + +void bsp_led_init(void) +{ +#if BSP_HAS_LED + gpio_pin_config_t led_config = { + kGPIO_DigitalOutput, + 1, /* Initial output HIGH (active-low LED D18 is OFF) */ + kGPIO_NoIntmode + }; + GPIO_PinInit(BOARD_USER_LED_GPIO, BOARD_USER_LED_GPIO_PIN, &led_config); + bsp_led_off(); +#endif +} + +void bsp_led_on(void) +{ +#if BSP_HAS_LED + /* Active-low: logic 0 turns the LED ON */ + GPIO_PinWrite(BOARD_USER_LED_GPIO, BOARD_USER_LED_GPIO_PIN, 0U); +#endif +} + +void bsp_led_off(void) +{ +#if BSP_HAS_LED + /* Active-low: logic 1 turns the LED OFF */ + GPIO_PinWrite(BOARD_USER_LED_GPIO, BOARD_USER_LED_GPIO_PIN, 1U); +#endif +} + +void bsp_led_toggle(void) +{ +#if BSP_HAS_LED + uint32_t current = GPIO_PinRead(BOARD_USER_LED_GPIO, BOARD_USER_LED_GPIO_PIN); + GPIO_PinWrite(BOARD_USER_LED_GPIO, BOARD_USER_LED_GPIO_PIN, (uint8_t)(current ^ 1U)); +#endif +} diff --git a/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_memory.c b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_memory.c new file mode 100644 index 00000000..a9aacd21 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_memory.c @@ -0,0 +1,27 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 version. + * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) + */ + +#include "bsp/memory.h" +#include "board_config.h" +#include +#include + +void bsp_ram_region(void *first_unused, void **base, size_t *size) +{ + const uintptr_t start = (uintptr_t)first_unused; + const uintptr_t end = (uintptr_t)BSP_RAM_END - (uintptr_t)BSP_MAIN_STACK_RESERVE; + + *base = first_unused; + *size = (end > start) ? (size_t)(end - start) : (size_t)0U; +} diff --git a/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_selftest.c b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_selftest.c new file mode 100644 index 00000000..22c3d81e --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_selftest.c @@ -0,0 +1,55 @@ +/* + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + * + * Contributors: + * Ali Eissa - 2026 version. + * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) + */ + +#include "bsp/selftest.h" +#include "board_config.h" +#include "fsl_common.h" +#include + +typedef struct { + bsp_selftest_report_fn report; + void *context; + unsigned failures; +} selftest_state_t; + +static void check(selftest_state_t *state, int passed, const char *message) +{ + if (passed == 0) + { + state->failures++; + } + state->report(passed, message, state->context); +} + +unsigned bsp_self_test(bsp_selftest_report_fn report, void *context) +{ + selftest_state_t state; + + if (report == NULL) + { + return 1U; + } + + state.report = report; + state.context = context; + state.failures = 0U; + + /* 1. System core clock sanity check */ + check(&state, (SystemCoreClock >= 10000000UL), "Core clock initialized"); + + /* 2. Board name verified */ + check(&state, (sizeof(BSP_BOARD_NAME) > 1), "Board identification valid"); + + return state.failures; +} diff --git a/targets/NXP/MIMXRT1064-EVK/lib/netx_driver/gnu/nx_driver_imxrt1062_low_level.S b/targets/NXP/MIMXRT1064-EVK/lib/netx_driver/gnu/nx_driver_imxrt1062_low_level.S new file mode 100644 index 00000000..88b35178 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/lib/netx_driver/gnu/nx_driver_imxrt1062_low_level.S @@ -0,0 +1,84 @@ +@/**************************************************************************/ +@/* */ +@/* Copyright (c) Microsoft Corporation. All rights reserved. */ +@/* */ +@/* This software is licensed under the Microsoft Software License */ +@/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +@/* and in the root directory of this software. */ +@/* */ +@/**************************************************************************/ +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Initialize */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +@ +@#define TX_SOURCE_CODE +@ +@ + .global nx_driver_imx_ethernet_isr + + .text 32 + .align 4 + .syntax unified +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* ENET_Transmit_IRQHandler MIMXRT1060/GCC */ +@/* 5.0 */ +@/* AUTHOR */ +@/* */ +@/* William E. Lamie, Microsoft Corporation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function is responsible for fielding the ethernet interrupts */ +@/* of the MIMXRT1060. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* nx_driver_imx_ethernet_isr NetX driver ethernet ISR */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* _tx_initialize_kernel_enter ThreadX entry function */ +@/* */ +@/* RELEASE HISTORY */ +@/* */ +@/* DATE NAME DESCRIPTION */ +@/* */ +@/* 02-01-2018 William E. Lamie Initial Version 5.0 */ +@/* */ +@/**************************************************************************/ + .global __nx_ENET_IRQHandler + .global ENET_IRQHandler + .thumb_func +__nx_ENET_IRQHandler: + .thumb_func +ENET_IRQHandler: + PUSH {r0, lr} +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_enter @ Call the ISR enter function +#endif + BL nx_driver_imx_ethernet_isr +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + BL _tx_execution_isr_exit @ Call the ISR exit function +#endif + POP {r0, lr} + BX lr diff --git a/targets/NXP/MIMXRT1064-EVK/lib/netx_driver/nx_driver_imxrt1062.c b/targets/NXP/MIMXRT1064-EVK/lib/netx_driver/nx_driver_imxrt1062.c new file mode 100644 index 00000000..1f99cc25 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/lib/netx_driver/nx_driver_imxrt1062.c @@ -0,0 +1,2870 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Ethernet device driver for IMX family micro processors */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* Indicate that driver source is being compiled. */ + +#define NX_DRIVER_SOURCE + + +/****** DRIVER SPECIFIC ****** Start of part/vendor specific include area. Include driver-specific include file here! */ + +#ifndef NX_DRIVER_IMXRT1062_H + +/* Determine if the driver uses IP deferred processing or direct ISR processing. */ + +#define NX_DRIVER_ENABLE_DEFERRED /* Define this to enable deferred ISR processing. */ + +/* #define ENET_ENHANCEDBUFFERDESCRIPTOR_MODE*/ +/* Determine if the packet transmit queue logic is required for this driver. */ + +/* No, not required for this driver. #define NX_DIRVER_INTERNAL_TRANSMIT_QUEUE */ + +/* Include driver specific include file. */ +#include "nx_driver_imxrt1062.h" + +#endif + +/****** DRIVER SPECIFIC ****** End of part/vendor specific include file area! */ + + +/* Define the driver information structure that is only available within this file. */ + +static NX_DRIVER_INFORMATION nx_driver_information; + + +/****** DRIVER SPECIFIC ****** Start of part/vendor specific data area. Include hardware-specific data here! */ + +/* Define driver specific ethernet hardware address. */ + +#ifndef NX_DRIVER_ETHERNET_MAC +UCHAR _nx_driver_hardware_address[] = {0x02, 0x11, 0x22, 0x33, 0x44, 0x52}; +#else +UCHAR _nx_driver_hardware_address[] = NX_DRIVER_ETHERNET_MAC; +#endif + + +/****** DRIVER SPECIFIC ****** End of part/vendor specific data area! */ + + +/* Define the routines for processing each driver entry request. The contents of these routines will change with + each driver. However, the main driver entry function will not change, except for the entry function name. */ + +static VOID _nx_driver_interface_attach(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_initialize(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_enable(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_disable(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_packet_send(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_multicast_join(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_multicast_leave(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_get_status(NX_IP_DRIVER *driver_req_ptr); +#ifdef NX_DRIVER_ENABLE_DEFERRED +static VOID _nx_driver_deferred_processing(NX_IP_DRIVER *driver_req_ptr); +#endif +static VOID _nx_driver_transfer_to_netx(NX_IP *ip_ptr, NX_PACKET *packet_ptr); +#ifdef NX_DIRVER_INTERNAL_TRANSMIT_QUEUE +static VOID _nx_driver_transmit_packet_enqueue(NX_PACKET *packet_ptr) +static NX_PACKET *_nx_driver_transmit_packet_dequeue(VOID) +#endif +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +static VOID _nx_driver_capability_get(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_capability_set(NX_IP_DRIVER *driver_req_ptr); +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + +/* Define the prototypes for the hardware implementation of this driver. The contents of these routines are + driver-specific. */ + +static UINT _nx_driver_hardware_initialize(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_hardware_enable(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_hardware_disable(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_hardware_packet_send(NX_PACKET *packet_ptr); +static UINT _nx_driver_hardware_multicast_join(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_hardware_multicast_leave(NX_IP_DRIVER *driver_req_ptr); +static UINT _nx_driver_hardware_get_status(NX_IP_DRIVER *driver_req_ptr); +static VOID _nx_driver_hardware_packet_transmitted(VOID); +static VOID _nx_driver_hardware_packet_received(VOID); +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +static UINT _nx_driver_hardware_capability_set(NX_IP_DRIVER *driver_req_ptr); +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_imx PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This is the entry point of the NetX Ethernet Driver. This driver */ +/* function is responsible for initializing the Ethernet controller, */ +/* enabling or disabling the controller as need, preparing */ +/* a packet for transmission, and getting status information. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr The driver request from the */ +/* IP layer. */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_interface_attach Process attach request */ +/* _nx_driver_initialize Process initialize request */ +/* _nx_driver_enable Process link enable request */ +/* _nx_driver_disable Process link disable request */ +/* _nx_driver_packet_send Process send packet requests */ +/* _nx_driver_multicast_join Process multicast join request*/ +/* _nx_driver_multicast_leave Process multicast leave req */ +/* _nx_driver_get_status Process get status request */ +/* _nx_driver_deferred_processing Drive deferred processing */ +/* */ +/* CALLED BY */ +/* */ +/* IP layer */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +/****** DRIVER SPECIFIC ****** Start of part/vendor specific global driver entry function name. */ +VOID nx_driver_imx(NX_IP_DRIVER *driver_req_ptr) +/****** DRIVER SPECIFIC ****** End of part/vendor specific global driver entry function name. */ +{ + + /* Default to successful return. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + + /* Process according to the driver request type in the IP control + block. */ + switch (driver_req_ptr -> nx_ip_driver_command) + { + + case NX_LINK_INTERFACE_ATTACH: + + /* Process link interface attach requests. */ + _nx_driver_interface_attach(driver_req_ptr); + break; + + case NX_LINK_INITIALIZE: + { + + /* Process link initialize requests. */ + _nx_driver_initialize(driver_req_ptr); + break; + } + + case NX_LINK_ENABLE: + { + + /* Process link enable requests. */ + _nx_driver_enable(driver_req_ptr); + break; + } + + case NX_LINK_DISABLE: + { + + /* Process link disable requests. */ + _nx_driver_disable(driver_req_ptr); + break; + } + + + case NX_LINK_ARP_SEND: + case NX_LINK_ARP_RESPONSE_SEND: + case NX_LINK_PACKET_BROADCAST: + case NX_LINK_RARP_SEND: + case NX_LINK_PACKET_SEND: + { + + /* Process packet send requests. */ + _nx_driver_packet_send(driver_req_ptr); + break; + } + + + case NX_LINK_MULTICAST_JOIN: + { + + /* Process multicast join requests. */ + _nx_driver_multicast_join(driver_req_ptr); + break; + } + + + case NX_LINK_MULTICAST_LEAVE: + { + + /* Process multicast leave requests. */ + _nx_driver_multicast_leave(driver_req_ptr); + break; + } + + case NX_LINK_GET_STATUS: + { + + /* Process get status requests. */ + _nx_driver_get_status(driver_req_ptr); + break; + } +#ifdef NX_DRIVER_ENABLE_DEFERRED + case NX_LINK_DEFERRED_PROCESSING: + { + + /* Process driver deferred requests. */ + + /* Process a device driver function on behave of the IP thread. */ + _nx_driver_deferred_processing(driver_req_ptr); + break; + } +#endif +#ifdef NX_ENABLE_INTERFACE_CAPABILITY + case NX_INTERFACE_CAPABILITY_GET: + { + + /* Process get capability requests. */ + _nx_driver_capability_get(driver_req_ptr); + break; + } + + case NX_INTERFACE_CAPABILITY_SET: + { + + /* Process set capability requests. */ + _nx_driver_capability_set(driver_req_ptr); + break; + } +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + default: + + /* Invalid driver request. */ + + /* Return the unhandled command status. */ + driver_req_ptr -> nx_ip_driver_status = NX_UNHANDLED_COMMAND; + + /* Default to successful return. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_interface_attach PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the interface attach request. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_interface_attach(NX_IP_DRIVER *driver_req_ptr) +{ + + + /* Setup the driver's interface. This example is for a simple one-interface + Ethernet driver. Additional logic is necessary for multiple port devices. */ + nx_driver_information.nx_driver_information_interface = driver_req_ptr -> nx_ip_driver_interface; + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY + driver_req_ptr -> nx_ip_driver_interface -> nx_interface_capability_flag = NX_DRIVER_CAPABILITY; +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + /* Return successful status. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_initialize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the initialize request. The processing */ +/* in this function is generic. All ethernet controller logic is to */ +/* be placed in _nx_driver_hardware_initialize. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_hardware_initialize Process initialize request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_initialize(NX_IP_DRIVER *driver_req_ptr) +{ + +NX_IP *ip_ptr; +NX_INTERFACE *interface_ptr; +UINT status; + + + /* Setup the IP pointer from the driver request. */ + ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* Setup interface pointer. */ + interface_ptr = driver_req_ptr -> nx_ip_driver_interface; + + /* Initialize the driver's information structure. */ + + /* Default IP pointer to NULL. */ + nx_driver_information.nx_driver_information_ip_ptr = NX_NULL; + + /* Setup the driver state to not initialized. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_NOT_INITIALIZED; + + /* Setup the default packet pool for the driver's received packets. */ + nx_driver_information.nx_driver_information_packet_pool_ptr = ip_ptr -> nx_ip_default_packet_pool; + + /* Clear the deferred events for the driver. */ + nx_driver_information.nx_driver_information_deferred_events = 0; + +#ifdef NX_DIRVER_INTERNAL_TRANSMIT_QUEUE + + /* Clear the transmit queue count and head pointer. */ + nx_driver_information.nx_driver_transmit_packets_queued = 0; + nx_driver_information.nx_driver_transmit_queue_head = NX_NULL; + nx_driver_information.nx_driver_transmit_queue_tail = NX_NULL; +#endif + + /* Call the hardware-specific ethernet controller initialization. */ + status = _nx_driver_hardware_initialize(driver_req_ptr); + + /* Determine if the request was successful. */ + if (status == NX_SUCCESS) + { + + /* Successful hardware initialization. */ + + /* Setup driver information to point to IP pointer. */ + nx_driver_information.nx_driver_information_ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* Setup the link maximum transfer unit. */ + interface_ptr -> nx_interface_ip_mtu_size = NX_DRIVER_ETHERNET_MTU - NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Setup the physical address of this IP instance. Increment the + physical address lsw to simulate multiple nodes hanging on the + ethernet. */ + interface_ptr -> nx_interface_physical_address_msw = + (ULONG)((_nx_driver_hardware_address[0] << 8) | (_nx_driver_hardware_address[1])); + interface_ptr -> nx_interface_physical_address_lsw = + (ULONG)((_nx_driver_hardware_address[2] << 24) | (_nx_driver_hardware_address[3] << 16) | + (_nx_driver_hardware_address[4] << 8) | (_nx_driver_hardware_address[5])); + + /* Indicate to the IP software that IP to physical mapping + is required. */ + interface_ptr -> nx_interface_address_mapping_needed = NX_TRUE; + + /* Move the driver's state to initialized. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_INITIALIZED; + + /* Indicate successful initialize. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } + else + { + + /* Initialization failed. Indicate that the request failed. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_enable PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the initialize request. The processing */ +/* in this function is generic. All ethernet controller logic is to */ +/* be placed in _nx_driver_hardware_enable. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_hardware_enable Process enable request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_enable(NX_IP_DRIVER *driver_req_ptr) +{ + +UINT status; + + /* See if we can honor the NX_LINK_ENABLE request. */ + if (nx_driver_information.nx_driver_information_state < NX_DRIVER_STATE_INITIALIZED) + { + + /* Mark the request as not successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + return; + } + + /* Check if it is enabled by someone already */ + if (nx_driver_information.nx_driver_information_state >= NX_DRIVER_STATE_LINK_ENABLED) + { + + /* Yes, the request has already been made. */ + driver_req_ptr -> nx_ip_driver_status = NX_ALREADY_ENABLED; + return; + } + + /* Call hardware specific enable. */ + status = _nx_driver_hardware_enable(driver_req_ptr); + + /* Was the hardware enable successful? */ + if (status == NX_SUCCESS) + { + + /* Update the driver state to link enabled. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_LINK_ENABLED; + + /* Mark request as successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + + /* Mark the IP instance as link up. */ + driver_req_ptr -> nx_ip_driver_interface -> nx_interface_link_up = NX_TRUE; + } + else + { + + /* Enable failed. Indicate that the request failed. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_disable PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the disable request. The processing */ +/* in this function is generic. All ethernet controller logic is to */ +/* be placed in _nx_driver_hardware_disable. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_hardware_disable Process disable request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_disable(NX_IP_DRIVER *driver_req_ptr) +{ + +NX_IP *ip_ptr; +UINT status; + + + /* Setup the IP pointer from the driver request. */ + ip_ptr = driver_req_ptr -> nx_ip_driver_ptr; + + /* Check if the link is enabled. */ + if (nx_driver_information.nx_driver_information_state != NX_DRIVER_STATE_LINK_ENABLED) + { + + /* The link is not enabled, so just return an error. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + return; + } + + /* Call hardware specific disable. */ + status = _nx_driver_hardware_disable(driver_req_ptr); + + /* Was the hardware disable successful? */ + if (status == NX_SUCCESS) + { + + /* Mark the IP instance as link down. */ + ip_ptr -> nx_ip_driver_link_up = NX_FALSE; + + /* Update the driver state back to initialized. */ + nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_INITIALIZED; + + /* Mark request as successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } + else + { + + /* Disable failed, return an error. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_packet_send PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the packet send request. The processing */ +/* in this function is generic. All ethernet controller packet send */ +/* logic is to be placed in _nx_driver_hardware_packet_send. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_hardware_packet_send Process packet send request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_packet_send(NX_IP_DRIVER *driver_req_ptr) +{ + +NX_PACKET *packet_ptr; +ULONG *ethernet_frame_ptr; +UINT status; + + + /* Check to make sure the link is up. */ + if (nx_driver_information.nx_driver_information_state != NX_DRIVER_STATE_LINK_ENABLED) + { + + /* Inidate an unsuccessful packet send. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + /* Link is not up, simply free the packet. */ + nx_packet_transmit_release(driver_req_ptr -> nx_ip_driver_packet); + return; + } + + /* Process driver send packet. */ + + /* Place the ethernet frame at the front of the packet. */ + packet_ptr = driver_req_ptr -> nx_ip_driver_packet; + + /* Adjust the prepend pointer. */ + packet_ptr -> nx_packet_prepend_ptr = + packet_ptr -> nx_packet_prepend_ptr - NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Setup the ethernet frame pointer to build the ethernet frame. Backup another 2 + * bytes to get 32-bit word alignment. */ + ethernet_frame_ptr = (ULONG *) (packet_ptr -> nx_packet_prepend_ptr - 2); + + /* Set up the hardware addresses in the Ethernet header. */ + *ethernet_frame_ptr = driver_req_ptr -> nx_ip_driver_physical_address_msw; + *(ethernet_frame_ptr + 1) = driver_req_ptr -> nx_ip_driver_physical_address_lsw; + + *(ethernet_frame_ptr + 2) = (driver_req_ptr -> nx_ip_driver_interface -> nx_interface_physical_address_msw << 16) | + (driver_req_ptr -> nx_ip_driver_interface -> nx_interface_physical_address_lsw >> 16); + *(ethernet_frame_ptr + 3) = (driver_req_ptr -> nx_ip_driver_interface -> nx_interface_physical_address_lsw << 16); + + /* Set up the frame type field in the Ethernet harder. */ + if ((driver_req_ptr -> nx_ip_driver_command == NX_LINK_ARP_SEND)|| + (driver_req_ptr -> nx_ip_driver_command == NX_LINK_ARP_RESPONSE_SEND)) + { + + *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_ARP; + } + else if(driver_req_ptr -> nx_ip_driver_command == NX_LINK_RARP_SEND) + { + + *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_RARP; + } + +#ifdef FEATURE_NX_IPV6 + else if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6) + { + + *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_IPV6; + } +#endif + + else + { + + *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_IP; + } + + /* Endian swapping if NX_LITTLE_ENDIAN is defined. */ + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr)); + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 1)); + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 2)); + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 3)); + + /* Determine if the packet exceeds the driver's MTU. */ + if (packet_ptr -> nx_packet_length > NX_DRIVER_ETHERNET_MTU) + { + + /* This packet exceeds the size of the driver's MTU. Simply throw it away! */ + + /* Remove the Ethernet header. */ + NX_DRIVER_ETHERNET_HEADER_REMOVE(packet_ptr); + + /* Indicate an unsuccessful packet send. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + /* Link is not up, simply free the packet. */ + nx_packet_transmit_release(packet_ptr); + return; + } + + /* Transmit the packet through the Ethernet controller low level access routine. */ + status = _nx_driver_hardware_packet_send(packet_ptr); + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + + /* Driver's hardware send packet routine failed to send the packet. */ + + /* Remove the Ethernet header. */ + NX_DRIVER_ETHERNET_HEADER_REMOVE(packet_ptr); + + /* Indicate an unsuccessful packet send. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + + /* Link is not up, simply free the packet. */ + nx_packet_transmit_release(packet_ptr); + } + else + { + + /* Set the status of the request. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_multicast_join PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the multicast join request. The processing */ +/* in this function is generic. All ethernet controller multicast join */ +/* logic is to be placed in _nx_driver_hardware_multicast_join. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_hardware_multicast_join Process multicast join request*/ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_multicast_join(NX_IP_DRIVER *driver_req_ptr) +{ + +UINT status; + + + if (nx_driver_information.nx_driver_information_state >= NX_DRIVER_STATE_INITIALIZED) + { + + /* Call hardware specific multicast join function. */ + status = _nx_driver_hardware_multicast_join(driver_req_ptr); + } + else + { + + status = NX_NOT_ENABLED; + } + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } + else + { + + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_multicast_leave PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the multicast leave request. The */ +/* processing in this function is generic. All ethernet controller */ +/* multicast leave logic is to be placed in */ +/* _nx_driver_hardware_multicast_leave. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_hardware_multicast_leave Process multicast leave req */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_multicast_leave(NX_IP_DRIVER *driver_req_ptr) +{ + +UINT status; + + if (nx_driver_information.nx_driver_information_state >= NX_DRIVER_STATE_INITIALIZED) + { + + /* Call hardware specific multicast leave function. */ + status = _nx_driver_hardware_multicast_leave(driver_req_ptr); + } + else + { + + status = NX_NOT_ENABLED; + } + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } + else + { + + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_get_status PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the get status request. The processing */ +/* in this function is generic. All ethernet controller get status */ +/* logic is to be placed in _nx_driver_hardware_get_status. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_hardware_get_status Process get status request */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_get_status(NX_IP_DRIVER *driver_req_ptr) +{ + +UINT status; + + + /* Call hardware specific get status function. */ + status = _nx_driver_hardware_get_status(driver_req_ptr); + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } + else + { + + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} + + + +#ifdef NX_ENABLE_INTERFACE_CAPABILITY +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_capability_get PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the get capability request. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-01-2014 Yuxin Zhou Initial Version 5.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_capability_get(NX_IP_DRIVER *driver_req_ptr) +{ + + /* Return the capability of the Ethernet controller. */ + *(driver_req_ptr -> nx_ip_driver_return_ptr) = NX_DRIVER_CAPABILITY; + + /* Return the success status. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_capability_set PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the set capability request. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-01-2014 Yuxin Zhou Initial Version 5.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_capability_set(NX_IP_DRIVER *driver_req_ptr) +{ + +UINT status; + + + /* Call hardware specific get status function. */ + status = _nx_driver_hardware_capability_set(driver_req_ptr); + + /* Determine if there was an error. */ + if (status != NX_SUCCESS) + { + + /* Indicate an unsuccessful request. */ + driver_req_ptr -> nx_ip_driver_status = NX_DRIVER_ERROR; + } + else + { + + /* Indicate the request was successful. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + } +} +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + + + +#ifdef NX_DRIVER_ENABLE_DEFERRED +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_deferred_processing PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing the deferred ISR action within the context */ +/* of the IP thread. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver command from the IP */ +/* thread */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_packet_transmitted Clean up after transmission */ +/* _nx_driver_packet_received Process a received packet */ +/* */ +/* CALLED BY */ +/* */ +/* Driver entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_deferred_processing(NX_IP_DRIVER *driver_req_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +ULONG deferred_events; + + + /* Disable interrupts. */ + TX_DISABLE + + /* Pickup deferred events. */ + deferred_events = nx_driver_information.nx_driver_information_deferred_events; + nx_driver_information.nx_driver_information_deferred_events = 0; + + /* Restore interrupts. */ + TX_RESTORE + + /* Check for a transmit complete event. */ + if(deferred_events & NX_DRIVER_DEFERRED_PACKET_TRANSMITTED) + { + + /* Process transmitted packet(s). */ + _nx_driver_hardware_packet_transmitted(); + } + + /* Check for recevied packet. */ + if(deferred_events & NX_DRIVER_DEFERRED_PACKET_RECEIVED) + { + + /* Process received packet(s). */ + _nx_driver_hardware_packet_received(); + } + + /* Mark request as successful. */ + driver_req_ptr->nx_ip_driver_status = NX_SUCCESS; +} +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_transfer_to_netx PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing incoming packets. This routine would */ +/* be called from the driver-specific receive packet processing */ +/* function _nx_driver_hardware_packet_received. */ +/* */ +/* INPUT */ +/* */ +/* ip_ptr Pointer to IP protocol block */ +/* packet_ptr Packet pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Error indication */ +/* */ +/* CALLS */ +/* */ +/* _nx_ip_packet_receive NetX IP packet receive */ +/* _nx_ip_packet_deferred_receive NetX IP packet receive */ +/* _nx_arp_packet_deferred_receive NetX ARP packet receive */ +/* _nx_rarp_packet_deferred_receive NetX RARP packet receive */ +/* _nx_packet_release Release packet */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_hardware_packet_received Driver packet receive function*/ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_transfer_to_netx(NX_IP *ip_ptr, NX_PACKET *packet_ptr) +{ + +USHORT packet_type; + + + packet_ptr -> nx_packet_ip_interface = nx_driver_information.nx_driver_information_interface; + + /* Pickup the packet header to determine where the packet needs to be + sent. */ + packet_type = (USHORT)(((UINT) (*(packet_ptr -> nx_packet_prepend_ptr+12))) << 8) | + ((UINT) (*(packet_ptr -> nx_packet_prepend_ptr+13))); + + /* Route the incoming packet according to its ethernet type. */ + if (packet_type == NX_DRIVER_ETHERNET_IP || packet_type == NX_DRIVER_ETHERNET_IPV6) + { + /* Note: The length reported by some Ethernet hardware includes + bytes after the packet as well as the Ethernet header. In some + cases, the actual packet length after the Ethernet header should + be derived from the length in the IP header (lower 16 bits of + the first 32-bit word). */ + + /* Clean off the Ethernet header. */ + packet_ptr -> nx_packet_prepend_ptr = + packet_ptr -> nx_packet_prepend_ptr + NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length = + packet_ptr -> nx_packet_length - NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Route to the ip receive function. */ +#ifdef NX_DRIVER_ENABLE_DEFERRED + _nx_ip_packet_deferred_receive(ip_ptr, packet_ptr); +#else + _nx_ip_packet_receive(ip_ptr, packet_ptr); +#endif + } + else if (packet_type == NX_DRIVER_ETHERNET_ARP) + { + + /* Clean off the Ethernet header. */ + packet_ptr -> nx_packet_prepend_ptr = + packet_ptr -> nx_packet_prepend_ptr + NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length = + packet_ptr -> nx_packet_length - NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Route to the ARP receive function. */ + _nx_arp_packet_deferred_receive(ip_ptr, packet_ptr); + } + else if (packet_type == NX_DRIVER_ETHERNET_RARP) + { + + /* Clean off the Ethernet header. */ + packet_ptr -> nx_packet_prepend_ptr = + packet_ptr -> nx_packet_prepend_ptr + NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length = + packet_ptr -> nx_packet_length - NX_DRIVER_ETHERNET_FRAME_SIZE; + + /* Route to the RARP receive function. */ + _nx_rarp_packet_deferred_receive(ip_ptr, packet_ptr); + } + else + { + /* Invalid ethernet header... release the packet. */ + nx_packet_release(packet_ptr); + } +} + + +#ifdef NX_DIRVER_INTERNAL_TRANSMIT_QUEUE +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_transmit_packet_enqueue PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function queues a transmit packet when the hardware transmit */ +/* queue does not have the resources (buffer descriptors, etc.) to */ +/* send the packet. The queue is maintained as a singularly linked- */ +/* list with head and tail pointers. The maximum number of packets on */ +/* the transmit queue is regulated by the constant */ +/* NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH. When this number is exceeded, */ +/* the oldest packet is discarded after the new packet is queued. */ +/* */ +/* Note: that it is assumed further driver interrupts are locked out */ +/* during the call to this driver utility. */ +/* */ +/* INPUT */ +/* */ +/* packet_ptr Packet pointer */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_packet_transmit_release Release packet */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_hardware_packet_send Driver packet send function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_transmit_packet_enqueue(NX_PACKET *packet_ptr) +{ + + /* Determine if there is anything on the queue. */ + if (nx_driver_information.nx_driver_transmit_queue_tail) + { + + /* Yes, something is on the transmit queue. Simply add the new packet to the + tail. */ + nx_driver_information.nx_driver_transmit_queue_tail -> nx_packet_queue_next = packet_ptr; + + /* Update the tail pointer. */ + nx_driver_information.nx_driver_transmit_queue_tail = packet_ptr; + } + else + { + + /* First packet on the transmit queue. */ + + /* Setup head pointers. */ + nx_driver_information.nx_driver_transmit_queue_head = packet_ptr; + nx_driver_information.nx_driver_transmit_queue_tail = packet_ptr; + + /* Set the packet's next pointer to NULL. */ + packet_ptr -> nx_packet_queue_next = NX_NULL; + } + + /* Increment the total packets queued. */ + nx_driver_information.nx_driver_transmit_packets_queued++; + + /* Determine if the total packet queued exceeds the driver's maximum transmit + queue depth. */ + if (nx_driver_information.nx_driver_transmit_packets_queued > NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH) + { + + /* Yes, remove the head packet (oldest) packet in the transmit queue and release it. */ + packet_ptr = nx_driver_information.nx_driver_transmit_queue_head; + + /* Adjust the head pointer to the next packet. */ + nx_driver_information.nx_driver_transmit_queue_head = packet_ptr -> nx_packet_queue_next; + + /* Decrement the transmit packet queued count. */ + nx_driver_information.nx_driver_transmit_packets_queued--; + + /* Remove the ethernet header. */ + NX_DRIVER_ETHERNET_HEADER_REMOVE(packet_ptr); + + /* Release the packet. */ + nx_packet_transmit_release(packet_ptr); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_transmit_packet_dequeue PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function removes the oldest transmit packet when the hardware */ +/* transmit queue has new resources (usually after a transmit complete */ +/* interrupt) to send the packet. If there are no packets in the */ +/* transmit queue, a NULL is returned. */ +/* */ +/* Note: that it is assumed further driver interrupts are locked out */ +/* during the call to this driver utility. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* packet_ptr Packet pointer */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_hardware_packet_send Driver packet send function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static NX_PACKET *_nx_driver_transmit_packet_dequeue(VOID) +{ + +NX_PACKET *packet_ptr; + + + /* Pickup the head pointer of the tranmit packet queue. */ + packet_ptr = nx_driver_information.nx_driver_transmit_queue_head; + + /* Determine if there is anything on the queue. */ + if (packet_ptr) + { + + /* Yes, something is on the transmit queue. Simply the packet from the head of the queue. */ + + /* Update the head pointer. */ + nx_driver_information.nx_driver_transmit_queue_head = packet_ptr -> nx_packet_queue_next; + + /* Clear the next pointer in the packet. */ + packet_ptr -> nx_packet_queue_next = NX_NULL; + + /* Decrement the transmit packet queued count. */ + nx_driver_information.nx_driver_transmit_packets_queued--; + } + + /* Return the packet pointer - NULL if there are no packets queued. */ + return(packet_ptr); +} + +#endif + + + +/****** DRIVER SPECIFIC ****** Start of part/vendor specific internal driver functions. */ + +typedef struct +{ + enet_mii_mode_t interface; /* Transceiver mode */ + uint8_t neg; /* FEC autoneg */ + phy_speed_t speed; /* Ethernet Speed */ + phy_duplex_t duplex; /* Ethernet Duplex */ + uint8_t mac[6]; /* Ethernet Address */ +} ENET_CONFIG_IMX; + +void enet_init_imx(ENET_CONFIG_IMX *config) +{ + /* Clear the Individual and Group Address Hash registers */ + ENET->IALR/*(ch)*/ = 0; + ENET->IAUR/*(ch)*/ = 0; + ENET->GALR/*(ch)*/ = 0; + ENET->GAUR/*(ch)*/ = 0; + + /* Set the Physical Address for the selected FEC */ + /*enet_set_address(config->ch, config->mac);*/ + ENET_SetMacAddr(ENET,config->mac); + + /* Mask all FEC interrupts */ + ENET->EIMR/*(ch)*/ = 0;/*FSL:ENET_EIMR_MASK_ALL_MASK;*/ + + /* Clear all FEC interrupt events */ + ENET->EIR/*(ch)*/ = 0xFFFFFFFF;/*FSL:ENET_EIR_CLEAR_ALL_MASK;*/ + + /* Initialize the Receive Control Register */ + ENET->RCR/*(ch)*/ = 0 + | ENET_RCR_MAX_FL(14+1500+4) /*ethernet frame head + max data+crc*/ + | ENET_RCR_MII_MODE_MASK /*always*/ + | ENET_RCR_CRCFWD_MASK; /*no CRC pad required*/ + + if ( config->interface == kENET_RmiiMode ) + { + ENET->RCR/*(ch)*/ |= ENET_RCR_RMII_MODE_MASK; + + /*only set speed in RMII mode*/ + if( config->speed == kPHY_Speed10M ) + { + ENET->RCR/*(ch)*/ |= ENET_RCR_RMII_10T_MASK; + } + }/*no need to configure MAC MII interface*/ + + ENET->TCR/*(ch)*/ = 0; + + /* Set the duplex */ + switch (config->duplex) + { + case kENET_MiiHalfDuplex: + ENET->RCR/*(ch)*/ |= ENET_RCR_DRT_MASK; + ENET->TCR/*(ch)*/ &= (uint32_t)~ENET_TCR_FDEN_MASK; + break; + case kENET_MiiFullDuplex: + default: + ENET->RCR/*(ch)*/ &= ~ENET_RCR_DRT_MASK; + ENET->TCR/*(ch)*/ |= ENET_TCR_FDEN_MASK; + break; + } + +#ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE + ENET->ECR/*(ch)*/ = ENET_ECR_EN1588_MASK; +#else + ENET->ECR/*(ch)*/ = 0; +#endif + + +#ifdef IMX_CHECKSUM_OFFLOAD + ENET->TACC = ENET_TACC_SHIFT16_MASK | + ENET_TACC_IPCHK_MASK | + ENET_TACC_PROCHK_MASK; + + ENET->TFWR = ENET_TFWR_STRFWD_MASK; + + ENET->RACC = ENET_RACC_SHIFT16_MASK | + ENET_RACC_LINEDIS_MASK | + ENET_RACC_PRODIS_MASK | + ENET_RACC_IPDIS_MASK; +#else + ENET->TACC = ENET_TACC_SHIFT16_MASK; + + ENET->RACC = ENET_RACC_SHIFT16_MASK | + ENET_RACC_LINEDIS_MASK; +#endif + +} +UINT enet_init() +{ + bool link = false; + phy_speed_t speed; + phy_duplex_t duplex; + uint32_t sysClock; + int32_t status; + ENET_CONFIG_IMX econf; + int32_t unique_id; + +#ifndef NX_DRIVER_ETHERNET_MAC + /*Use unique id as mac address*/ + unique_id = OCOTP->CFG0; + _nx_driver_hardware_address[2]=(UCHAR)unique_id; + _nx_driver_hardware_address[3]= (UCHAR)(unique_id >> 8); + _nx_driver_hardware_address[4]= (UCHAR)(unique_id >> 16); + _nx_driver_hardware_address[5]= (UCHAR)(unique_id >> 24); + +#ifdef NX_DEBUG + printf("MAC address : %x:%x:%x:%x:%x:%x\r\n", _nx_driver_hardware_address[0], + _nx_driver_hardware_address[1], + _nx_driver_hardware_address[2], + _nx_driver_hardware_address[3], + _nx_driver_hardware_address[4], + _nx_driver_hardware_address[5]); +#endif +#endif + + econf.interface = kENET_RmiiMode; + econf.neg = 0; /*autoneg on */ + econf.speed = kPHY_Speed100M; + econf.duplex = kPHY_FullDuplex; + econf.mac[0] = _nx_driver_hardware_address[0]; + econf.mac[1] = _nx_driver_hardware_address[1]; + econf.mac[2] = _nx_driver_hardware_address[2]; + econf.mac[3] = _nx_driver_hardware_address[3]; + econf.mac[4] = _nx_driver_hardware_address[4]; + econf.mac[5] = _nx_driver_hardware_address[5]; + + /* Set SMI to get PHY link status. */ + sysClock = CLOCK_GetFreq(kCLOCK_IpgClk); + status = PHY_Init(EXAMPLE_ENET, EXAMPLE_PHY, sysClock); + if (status != kStatus_Success) + { + status = PHY_Init(EXAMPLE_ENET, EXAMPLE_PHY, sysClock); + if (status != kStatus_Success) + { +#ifdef NX_DEBUG + printf("\r\nPHY Auto-negotiation failed. Please check the cable connection and link partner setting.\r\n"); +#endif + return(NX_DRIVER_ERROR); + } + } + + PHY_GetLinkStatus(EXAMPLE_ENET, EXAMPLE_PHY, &link); + if (link) + { + /* Get the actual PHY link speed. */ + PHY_GetLinkSpeedDuplex(EXAMPLE_ENET, EXAMPLE_PHY, &speed, &duplex); + /* Change the MII speed and duplex for actual link status. */ + econf.speed = (phy_speed_t)speed; + econf.duplex = (phy_duplex_t)duplex; + } + + enet_init_imx(&econf); + + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_initialize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific initialization. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR] */ +/* */ +/* CALLS */ +/* */ +/* ETH_BSP_Config Configure Ethernet */ +/* ETH_MACAddressConfig Setup MAC address */ +/* ETH_DMARxDescReceiveITConfig Enable receive descriptors */ +/* nx_packet_allocate Allocate receive packet(s) */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_initialize Driver initialize processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_initialize(NX_IP_DRIVER *driver_req_ptr) +{ + +NX_PACKET *packet_ptr; +UINT i; + + /* Default to successful return. */ + driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS; + + /* Setup indices. */ + nx_driver_information.nx_driver_information_receive_current_index = 0; + nx_driver_information.nx_driver_information_transmit_current_index = 0; + nx_driver_information.nx_driver_information_transmit_release_index = 0; + + /* Clear the number of buffers in use counter. */ + nx_driver_information.nx_driver_information_number_of_transmit_buffers_in_use = 0; + + /* Make sure there are receive packets... otherwise, return an error. */ + if (nx_driver_information.nx_driver_information_packet_pool_ptr == NULL) + { + + /* There must be receive packets. If not, return an error! */ + return(NX_DRIVER_ERROR); + } + + + if (enet_init()== NX_DRIVER_ERROR) + { + return(NX_DRIVER_ERROR); + } + + /* Initialize TX Descriptors list: Ring Mode. */ + + /* Make sure Number of Buffer Descriptors is power of 2 */ +#if (NX_DRIVER_TX_DESCRIPTORS & (NX_DRIVER_TX_DESCRIPTORS - 1)) != 0 +#error "Number of Buffer Descriptors must be power of 2" +#endif + + nx_driver_information.nx_driver_information_dma_tx_descriptors = (enet_tx_bd_struct_t*)(((UINT)nx_driver_information.nx_driver_information_dma_tx_descriptors_area + 15) & (~15)); + + /* Fill each DMATxDesc descriptor with the right values. */ + for(i = 0; i < NX_DRIVER_TX_DESCRIPTORS; i++) + { + + /* Initialize tx descriptors. */ + nx_driver_information.nx_driver_information_dma_tx_descriptors[i].control = ENET_BUFFDESCRIPTOR_TX_TRANMITCRC_MASK; + nx_driver_information.nx_driver_information_dma_tx_descriptors[i].length = 0; + +#ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE +#ifdef IMX_CHECKSUM_OFFLOAD + /* Enable tx interrupt & checksum offload. */ + nx_driver_information.nx_driver_information_dma_tx_descriptors[i].controlExtend1 = ENET_BUFFDESCRIPTOR_TX_INTERRUPT_MASK | 0x0800 | 0x1000; + #else + + /* Enable tx interrupt. */ + nx_driver_information.nx_driver_information_dma_tx_descriptors[i].controlExtend1 = ENET_BUFFDESCRIPTOR_TX_INTERRUPT_MASK; + #endif +#endif + nx_driver_information.nx_driver_information_transmit_packets[i] = NX_NULL; + + } + + /* Put the Wrap indicaiton on the last descriptor. */ + nx_driver_information.nx_driver_information_dma_tx_descriptors[NX_DRIVER_TX_DESCRIPTORS - 1].control |= ENET_BUFFDESCRIPTOR_TX_WRAP_MASK; + + /* Set Transmit Descriptor List Address Register */ + ENET->TDSR = (ULONG) nx_driver_information.nx_driver_information_dma_tx_descriptors; + + /* Initialize RX Descriptors list: Ring Mode */ + + /* Make sure Number of Buffer Descriptors is power of 2 */ +#if (NX_DRIVER_RX_DESCRIPTORS & (NX_DRIVER_RX_DESCRIPTORS - 1)) != 0 +#error "Number of Buffer Descriptors must be power of 2" +#endif + + nx_driver_information.nx_driver_information_dma_rx_descriptors = (enet_rx_bd_struct_t*)(((UINT)nx_driver_information.nx_driver_information_dma_rx_descriptors_area + 15) & (~15)); + + /* Fill each DMARxDesc descriptor with the right values */ + for(i = 0; i < NX_DRIVER_RX_DESCRIPTORS; i++) + { + + nx_driver_information.nx_driver_information_dma_rx_descriptors[i].length = 0; + + /* Allocate a packet for the receive buffers. */ + if (nx_packet_allocate(nx_driver_information.nx_driver_information_packet_pool_ptr, &packet_ptr, + NX_RECEIVE_PACKET, NX_NO_WAIT) == NX_SUCCESS) + { + + nx_driver_information.nx_driver_information_dma_rx_descriptors[i].control = ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; + +#ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE + nx_driver_information.nx_driver_information_dma_rx_descriptors[i].controlExtend2 = 0x0000; + nx_driver_information.nx_driver_information_dma_rx_descriptors[i].controlExtend1 = ENET_BUFFDESCRIPTOR_RX_BROADCAST_MASK; +#endif + nx_driver_information.nx_driver_information_dma_rx_descriptors[i].buffer = (uint8_t *)(uint32_t)packet_ptr->nx_packet_prepend_ptr; + nx_driver_information.nx_driver_information_receive_packets[i] = packet_ptr; + + } + else + { + + /* Cannot allocate packets from the packet pool. */ + return(NX_DRIVER_ERROR); + } + + } + + /* Put the Wrap indicaiton on the last descriptor. */ + nx_driver_information.nx_driver_information_dma_rx_descriptors[NX_DRIVER_RX_DESCRIPTORS - 1].control |= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK | ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; + + /* Save the size of one rx buffer. */ + nx_driver_information.nx_driver_information_rx_buffer_size = packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_data_start; + + /* Configure the Receive Buffer Size Register. */ + ENET->MRBR = nx_driver_information.nx_driver_information_rx_buffer_size; + + /* Set Receive Descriptor List Address Register. */ + ENET->RDSR = (ULONG) nx_driver_information.nx_driver_information_dma_rx_descriptors; + + for (i = 64; i; i--) + { + + nx_driver_information.nx_driver_information_multicast_count[i] = 0; + } + + /* Return success! */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_enable PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific link enable requests. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR] */ +/* */ +/* CALLS */ +/* */ + +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_enable Driver link enable processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_enable(NX_IP_DRIVER *driver_req_ptr) +{ + + /* Enable Ethernet interrupt. */ + ENET->EIMR = ENET_EIMR_RXF_MASK | ENET_EIMR_TXF_MASK; + /* Start Ethernet. */ + ENET->ECR |= ENET_ECR_ETHEREN_MASK; + + /*The buffer descriptor bytes are swapped to support little-endian devices.*/ + /*This field must be written to 1 after reset*/ + ENET->ECR|= ENET_ECR_DBSWP_MASK; + + + EnableIRQ(ENET_IRQn); + /*active rx descriptor*/ + ENET->RDAR = ENET_RDAR_RDAR_MASK; + /* Return success! */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_disable PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific link disable requests. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR] */ +/* */ +/* CALLS */ +/* */ + +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_disable Driver link disable processing*/ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_disable(NX_IP_DRIVER *driver_req_ptr) +{ + + /* Stop the Ethernet. */ + ENET->ECR &= ~ENET_ECR_ETHEREN_MASK; + + + /* Return success! */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_packet_send PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific packet send requests. */ +/* */ +/* INPUT */ +/* */ +/* packet_ptr Pointer to packet to send */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR] */ +/* */ +/* CALLS */ +/* */ +/* [_nx_driver_transmit_packet_enqueue] Optional internal transmit */ +/* packet queue routine */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_packet_send Driver packet send processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_packet_send(NX_PACKET *packet_ptr) +{ + +ULONG curIdx; +NX_PACKET *pktIdx; +ULONG bd_count = 0; +UCHAR remainder = 0; +UCHAR* src_addr; + + /* Pick up the first BD. */ + curIdx = nx_driver_information.nx_driver_information_transmit_current_index; + + /* Check if it is a free descriptor. */ + if ((nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].control & ENET_BUFFDESCRIPTOR_TX_READY_MASK) || nx_driver_information.nx_driver_information_transmit_packets[curIdx]) + { + /* Buffer is still owned by device. */ + return(NX_DRIVER_ERROR); + } + /* Set the buffer size. */ + nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].length = (packet_ptr -> nx_packet_append_ptr - packet_ptr->nx_packet_prepend_ptr + 2); + + remainder = (UCHAR )((ULONG)(packet_ptr->nx_packet_prepend_ptr - 2)& 0x07); + + if(remainder) + { + src_addr = packet_ptr->nx_packet_prepend_ptr; + + /*make sure transmit BD buffer 8byte aligment*/ + packet_ptr->nx_packet_prepend_ptr -= remainder; + + memmove(packet_ptr->nx_packet_prepend_ptr,src_addr,nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].length); + } + + /* Find the Buffer, set the Buffer pointer. */ + nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].buffer = (uint8_t *)(ULONG)(packet_ptr->nx_packet_prepend_ptr - 2); + + /* Clear the first Descriptor's LS bit. */ + nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].control &= ~ENET_BUFFDESCRIPTOR_TX_LAST_MASK; + + /* Find next packet. */ + for (pktIdx = packet_ptr -> nx_packet_next; + pktIdx != NX_NULL; + pktIdx = pktIdx -> nx_packet_next) + { + + /* Move to next descriptor. */ + curIdx = (curIdx + 1) & (NX_DRIVER_TX_DESCRIPTORS - 1); + + /* Check if it is a free descriptor. */ + if ((nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].control & ENET_BUFFDESCRIPTOR_TX_READY_MASK) || nx_driver_information.nx_driver_information_transmit_packets[curIdx]) + { + + /* No more descriptor available, return driver error status. */ + return(NX_DRIVER_ERROR); + } + + + /* Find the Buffer, set the Buffer pointer. */ + nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].buffer = (uint8_t *)(ULONG)(pktIdx->nx_packet_prepend_ptr); + + /* Set the buffer size. */ + nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].length = (pktIdx -> nx_packet_append_ptr - pktIdx->nx_packet_prepend_ptr); + + /* Clear the descriptor's LS bit. */ + nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].control &= ~ENET_BUFFDESCRIPTOR_TX_LAST_MASK; + + /* Increment the BD count. */ + bd_count++; + + } + + /* Set the last Descriptor's LS & IC & OWN bit. */ + nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].control |= (ENET_BUFFDESCRIPTOR_TX_LAST_MASK | ENET_BUFFDESCRIPTOR_TX_READY_MASK); + + /* Save the pkt pointer to release. */ + nx_driver_information.nx_driver_information_transmit_packets[curIdx] = packet_ptr; + + /* Set the current index to the next descriptor. */ + nx_driver_information.nx_driver_information_transmit_current_index = (curIdx + 1) & (NX_DRIVER_TX_DESCRIPTORS - 1); + + /* Increment the transmit buffers in use count. */ + nx_driver_information.nx_driver_information_number_of_transmit_buffers_in_use += bd_count + 1; + + /* Set OWN bit to indicate BDs are ready. */ + for (; bd_count > 0; bd_count--) + { + + /* Set OWN bit in reverse order, move to prevous BD. */ + curIdx = (curIdx - 1) & (NX_DRIVER_TX_DESCRIPTORS - 1); + + /* Set this BD's OWN bit. */ + nx_driver_information.nx_driver_information_dma_tx_descriptors[curIdx].control |= ENET_BUFFDESCRIPTOR_TX_READY_MASK; + } + + /* If the DMA transmission is suspended, resume transmission. */ + if (!ENET->TDAR) + { + + /* Resume DMA transmission. */ + ENET->TDAR = ENET_TDAR_TDAR_MASK; + } + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_crc32() PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Calculate 32bit CRC using reversed Poly for Ethernet. */ +/* */ +/* INPUT */ +/* */ +/* UCHAR dbuf[] - pointer to the data buffer. */ +/* INT length - Length of the data */ +/* */ +/* OUTPUT */ +/* */ +/* CRC value */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_hardware_multicast_join */ +/* _nx_driver_hardware_multicast_leave */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static ULONG nx_crc32(UCHAR dbuf[], INT length) +{ + +INT i; +INT bit; +ULONG crc = 0xFFFFFFFFUL; +ULONG poly = 0xEDB88320UL; +ULONG p; +ULONG data; + + + for (i = 0; i < length; i++) + { + data = ((ULONG)dbuf[i]); + + for (bit = 0; bit < 8; bit++) + { + p = (crc ^ ((ULONG)data)) & 1UL; + crc >>= 1; + if (p != 0) + crc ^= poly; + data >>= 1; + } + } + + return ~crc; +} /* nx_crc32 */ + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_multicast_join PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific multicast join requests. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR] */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_multicast_join Driver multicast join */ +/* processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_multicast_join(NX_IP_DRIVER *driver_req_ptr) +{ + +UCHAR adr[NX_DRIVER_PHYSICAL_ADDRESS_SIZE] ; +INT h_val; +ULONG crc_val; + + + /* Set up the array to pass to the hash_value function. */ + adr[0] = (UCHAR) (driver_req_ptr ->nx_ip_driver_physical_address_msw >> 8); + adr[1] = (UCHAR) (driver_req_ptr ->nx_ip_driver_physical_address_msw); + adr[2] = (UCHAR) (driver_req_ptr ->nx_ip_driver_physical_address_lsw >> 24); + adr[3] = (UCHAR) (driver_req_ptr ->nx_ip_driver_physical_address_lsw >> 16); + adr[4] = (UCHAR) (driver_req_ptr ->nx_ip_driver_physical_address_lsw >> 8); + adr[5] = (UCHAR) (driver_req_ptr ->nx_ip_driver_physical_address_lsw); + + /* Get the CRC done. */ + crc_val = nx_crc32(adr, NX_DRIVER_PHYSICAL_ADDRESS_SIZE); + + /* Use only 6 MSbs to obtain value in range 0..63. */ + crc_val >>= (32 - 6); + h_val = 63 - (int) crc_val ; /* pointer to 48 bit address */ + + if(nx_driver_information.nx_driver_information_multicast_count[h_val] == 255) + { + + return NX_NO_MORE_ENTRIES; + } + + nx_driver_information.nx_driver_information_multicast_count[h_val]++; + + if (h_val < 32) + ENET->GALR |= 1 << h_val; + else + ENET->GAUR |= 1 << (h_val - 32); + + /* Return success. */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_multicast_leave PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific multicast leave requests. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR] */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_multicast_leave Driver multicast leave */ +/* processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_multicast_leave(NX_IP_DRIVER *driver_req_ptr) +{ + +UCHAR adr[NX_DRIVER_PHYSICAL_ADDRESS_SIZE] ; +INT h_val; +ULONG crc_val; + + + /* Set up the array to pass to the hash_value function. */ + adr[0] = (UCHAR) (driver_req_ptr ->nx_ip_driver_physical_address_msw >> 8); + adr[1] = (UCHAR) (driver_req_ptr ->nx_ip_driver_physical_address_msw); + adr[2] = (UCHAR) (driver_req_ptr ->nx_ip_driver_physical_address_lsw >> 24); + adr[3] = (UCHAR) (driver_req_ptr ->nx_ip_driver_physical_address_lsw >> 16); + adr[4] = (UCHAR) (driver_req_ptr ->nx_ip_driver_physical_address_lsw >> 8); + adr[5] = (UCHAR) (driver_req_ptr ->nx_ip_driver_physical_address_lsw); + + /* Get the CRC done. */ + crc_val = nx_crc32(adr, NX_DRIVER_PHYSICAL_ADDRESS_SIZE); + + /* Use only 6 MSbs to obtain value in range 0..63. */ + crc_val >>= (32 - 6); + h_val = 63 - (int) crc_val ; /* pointer to 48 bit address */ + + if(nx_driver_information.nx_driver_information_multicast_count[h_val] == 1) + { + + if (h_val < 32) + ENET->GALR &= ~(1 << h_val); + else + ENET->GAUR &= ~(1 << (h_val - 32)); + } + else if(nx_driver_information.nx_driver_information_multicast_count[h_val] == 0) + { + + return NX_NOT_SUCCESSFUL; + } + + nx_driver_information.nx_driver_information_multicast_count[h_val]--; + + /* Return success. */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_get_status PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes hardware-specific get status requests. */ +/* */ +/* INPUT */ +/* */ +/* driver_req_ptr Driver request pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status [NX_SUCCESS|NX_DRIVER_ERROR] */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_get_status Driver get status processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static UINT _nx_driver_hardware_get_status(NX_IP_DRIVER *driver_req_ptr) +{ + + *(driver_req_ptr -> nx_ip_driver_return_ptr) = driver_req_ptr -> nx_ip_driver_interface -> nx_interface_link_up; + /* Return success. */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_packet_transmitted PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes packets transmitted by the ethernet */ +/* controller. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_packet_transmit_release Release transmitted packet */ +/* [_nx_driver_transmit_packet_dequeue] Optional transmit packet */ +/* dequeue */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_deferred_processing Deferred driver processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_hardware_packet_transmitted(VOID) +{ + +ULONG numOfBuf = nx_driver_information.nx_driver_information_number_of_transmit_buffers_in_use; +ULONG idx = nx_driver_information.nx_driver_information_transmit_release_index; + + + /* Loop through buffers in use. */ + while (numOfBuf--) + { + + /* If no packet, just examine the next packet. */ + if (nx_driver_information.nx_driver_information_transmit_packets[idx] == NX_NULL) + { + + /* No packet in use, skip to next. */ + idx = (idx + 1) & (NX_DRIVER_TX_DESCRIPTORS - 1); + continue; + } + + /* Determine if the packet has been transmitted. */ + if ((nx_driver_information.nx_driver_information_dma_tx_descriptors[idx].control & ENET_BUFFDESCRIPTOR_TX_READY_MASK) == 0) + { + + /* Yes, packet has been transmitted. */ + + /* Remove the Ethernet header and release the packet. */ + NX_DRIVER_ETHERNET_HEADER_REMOVE(nx_driver_information.nx_driver_information_transmit_packets[idx]); + + /* Release the packet. */ + nx_packet_transmit_release(nx_driver_information.nx_driver_information_transmit_packets[idx]); + + /* Clear the entry in the in-use array. */ + nx_driver_information.nx_driver_information_transmit_packets[idx] = NX_NULL; + + /* Update the transmit relesae index and number of buffers in use. */ + idx = (idx + 1) & (NX_DRIVER_TX_DESCRIPTORS - 1); + nx_driver_information.nx_driver_information_number_of_transmit_buffers_in_use = numOfBuf; + nx_driver_information.nx_driver_information_transmit_release_index = idx; + } + else + { + + /* Get out of the loop! */ + break; + } + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_driver_hardware_packet_received PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes packets received by the ethernet */ +/* controller. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_driver_transfer_to_netx Transfer packet to NetX */ +/* nx_packet_allocate Allocate receive packets */ +/* nx_packet_release Release receive packets */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_driver_deferred_processing Deferred driver processing */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +static VOID _nx_driver_hardware_packet_received(VOID) +{ + +NX_PACKET *packet_ptr; +ULONG bd_count = 0; +INT i; +ULONG idx; +ULONG temp_idx; +ULONG first_idx = nx_driver_information.nx_driver_information_receive_current_index; +NX_PACKET *received_packet_ptr = nx_driver_information.nx_driver_information_receive_packets[first_idx]; + + + /* Find out the BDs that owned by CPU. */ + for (first_idx = idx = nx_driver_information.nx_driver_information_receive_current_index; + (nx_driver_information.nx_driver_information_dma_rx_descriptors[idx].control & ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK) == 0; + idx = (idx + 1) & (NX_DRIVER_RX_DESCRIPTORS - 1)) + { + + /* Is the BD marked as the end of a frame? */ + if (nx_driver_information.nx_driver_information_dma_rx_descriptors[idx].control & ENET_BUFFDESCRIPTOR_RX_LAST_MASK) + { + + /* Yes, this BD is the last BD in the frame, set the last NX_PACKET's nx_packet_next to NULL. */ + nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_next = NX_NULL; + + /* Store the length of the packet in the first NX_PACKET. */ + + nx_driver_information.nx_driver_information_receive_packets[first_idx] -> nx_packet_length = (nx_driver_information.nx_driver_information_dma_rx_descriptors[idx].length) - 2; + + nx_driver_information.nx_driver_information_receive_packets[first_idx] -> nx_packet_prepend_ptr += 2; + + /* Adjust nx_packet_append_ptr with the size of the data in this buffer. */ + nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_append_ptr = nx_driver_information.nx_driver_information_receive_packets[idx]->nx_packet_prepend_ptr + + nx_driver_information.nx_driver_information_receive_packets[first_idx]->nx_packet_length + - bd_count * nx_driver_information.nx_driver_information_rx_buffer_size + + (bd_count > 0 ? 2 : 0); + + /* Allocate new NX_PACKETs for BDs. */ + for (i = bd_count; i >= 0; i--) + { + + temp_idx = (first_idx + i) & (NX_DRIVER_RX_DESCRIPTORS - 1); + + /* Allocate a new packet from the packet pool. */ + if (nx_packet_allocate(nx_driver_information.nx_driver_information_packet_pool_ptr, &packet_ptr, + NX_RECEIVE_PACKET, NX_NO_WAIT) == NX_SUCCESS) + { + + /* Adjust the new packet and assign it to the BD. */ + + nx_driver_information.nx_driver_information_dma_rx_descriptors[temp_idx].buffer = (uint8_t *)((uint32_t)packet_ptr->nx_packet_prepend_ptr); + nx_driver_information.nx_driver_information_dma_rx_descriptors[temp_idx].control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; + nx_driver_information.nx_driver_information_receive_packets[temp_idx] = packet_ptr; + } + else + { + + /* Allocation failed, get out of the loop. */ + break; + } + } + + if (i >= 0) + { + + /* At least one packet allocation was failed, release the received packet. */ + nx_packet_release(nx_driver_information.nx_driver_information_receive_packets[temp_idx] -> nx_packet_next); + + for (; i >= 0; i--) + { + + /* Free up the BD to ready state. */ + temp_idx = (first_idx + i) & (NX_DRIVER_RX_DESCRIPTORS - 1); + nx_driver_information.nx_driver_information_dma_rx_descriptors[temp_idx].control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; + nx_driver_information.nx_driver_information_receive_packets[temp_idx] -> nx_packet_prepend_ptr = nx_driver_information.nx_driver_information_receive_packets[temp_idx] -> nx_packet_data_start; + } + } + else + { + + /* Transfer the packet to NetX. */ + _nx_driver_transfer_to_netx(nx_driver_information.nx_driver_information_ip_ptr, received_packet_ptr); + } + + /* Set the first BD index for the next packet. */ + first_idx = (idx + 1) & (NX_DRIVER_RX_DESCRIPTORS - 1); + + /* Update the current receive index. */ + nx_driver_information.nx_driver_information_receive_current_index = first_idx; + + received_packet_ptr = nx_driver_information.nx_driver_information_receive_packets[first_idx]; + + bd_count = 0; + + } + else + { + + /* This BD is not the last BD of a frame. It is a intermediate descriptor. */ + + nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_next = nx_driver_information.nx_driver_information_receive_packets[(idx + 1) & (NX_DRIVER_RX_DESCRIPTORS - 1)]; + + nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_append_ptr = nx_driver_information.nx_driver_information_receive_packets[idx] -> nx_packet_data_end; + + bd_count++; + } + } + + /* If Rx DMA is in suspended state, resume it. */ + if (!ENET->RDAR) + { + + /* Resume DMA reception */ + ENET->RDAR = ENET_RDAR_RDAR_MASK; + } + +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_link_mode_changed PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function changes the link mode of the Ethernet. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* enet_duplex Set duplex mode */ +/* nx_packet_transmit_release Release the packet */ +/* */ +/* CALLED BY */ +/* */ +/* nx_driver_ethernet_phy_isr */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID nx_driver_link_mode_changed(VOID) +{ + +ULONG numOfBuf; +ULONG idx; + + + /* Stop the Ethernet. */ + ENET->ECR &= ~ENET_ECR_ETHEREN_MASK; + + /* Set speed for RMII mode. */ + if (nx_driver_information.nx_driver_information_link_speed == kENET_MiiSpeed10M) + { + + ENET->RCR |= ENET_RCR_RMII_10T_MASK; + } + else + { + + ENET->RCR &= ~ENET_RCR_RMII_10T_MASK; + } + + /* Set duplex mode. */ + /* Set the duplex on the selected FEC controller*/ + switch (nx_driver_information.nx_driver_information_link_duplex) + { + case kENET_MiiHalfDuplex: + ENET->RCR/*(ch)*/ |= ENET_RCR_DRT_MASK; + ENET->TCR/*(ch)*/ &= (uint32_t)~ENET_TCR_FDEN_MASK; + break; + case kENET_MiiFullDuplex: + default: + ENET->RCR/*(ch)*/ &= ~ENET_RCR_DRT_MASK; + ENET->TCR/*(ch)*/ |= ENET_TCR_FDEN_MASK; + break; + } + + if (nx_driver_information.nx_driver_information_state >= NX_DRIVER_STATE_INITIALIZED) + { + + numOfBuf = nx_driver_information.nx_driver_information_number_of_transmit_buffers_in_use; + idx = nx_driver_information.nx_driver_information_transmit_release_index; + + /* Reset indices. */ + nx_driver_information.nx_driver_information_receive_current_index = 0; + nx_driver_information.nx_driver_information_transmit_current_index = 0; + nx_driver_information.nx_driver_information_transmit_release_index = 0; + nx_driver_information.nx_driver_information_number_of_transmit_buffers_in_use = 0; + + /* Release transmit packets if any. */ + while (numOfBuf--) + { + + /* If no packet, just examine the next packet. */ + if (nx_driver_information.nx_driver_information_transmit_packets[idx] == NX_NULL) + { + + /* No packet in use, skip to next. */ + idx = (idx + 1) & (NX_DRIVER_TX_DESCRIPTORS - 1); + continue; + } + + /* Remove the Ethernet header and release the packet. */ + NX_DRIVER_ETHERNET_HEADER_REMOVE(nx_driver_information.nx_driver_information_transmit_packets[idx]); + + /* Release the packet. */ + nx_packet_transmit_release(nx_driver_information.nx_driver_information_transmit_packets[idx]); + } + + /* Free receive descriptors. */ + for (idx = 0; idx < NX_DRIVER_RX_DESCRIPTORS; idx++) + { + + nx_driver_information.nx_driver_information_dma_rx_descriptors[idx].control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; + } + } + + /* Set Transmit Descriptor List Address Register */ + ENET->TDSR = (ULONG) nx_driver_information.nx_driver_information_dma_tx_descriptors; + + /* Configure the Receive Buffer Size Register. */ + ENET->MRBR = nx_driver_information.nx_driver_information_rx_buffer_size; + + /* Set Receive Descriptor List Address Register. */ + ENET->RDSR = (ULONG) nx_driver_information.nx_driver_information_dma_rx_descriptors; + + if (nx_driver_information.nx_driver_information_state >= NX_DRIVER_STATE_LINK_ENABLED) + { + + /* Enable ethernet & start packet receiving. */ + ENET->ECR |= ENET_ECR_ETHEREN_MASK; + ENET->RDAR = ENET_RDAR_RDAR_MASK; + } +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* nx_driver_imx6ul_ethernet_isr PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processing incoming packets. This routine is */ +/* be called from the receive packet ISR and assumes that the */ +/* interrupt is saved/restored around the call by ThreadX. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ip_driver_deferred_processing IP receive packet processing */ +/* */ +/* CALLED BY */ +/* */ +/* ISR */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID nx_driver_imx_ethernet_isr(VOID) +{ +UINT status; + status = ENET->EIR; + + if(status & ENET_EIR_RXF_MASK ) + { + /* Receive packet interrupt. */ +#ifdef NX_DRIVER_ENABLE_DEFERRED + + /* Set the receive packet interrupt. */ + nx_driver_information.nx_driver_information_deferred_events |= NX_DRIVER_DEFERRED_PACKET_RECEIVED; +#else + + /* Process received packet(s). */ + _nx_driver_hardware_packet_received(); +#endif + + +#ifdef NX_DRIVER_ENABLE_DEFERRED + + /* Call NetX deferred driver processing. */ + _nx_ip_driver_deferred_processing(nx_driver_information.nx_driver_information_ip_ptr); +#endif + + /* Clear the Ethernet DMA Rx IT pending bits */ + ENET->EIR = ENET_EIR_RXF_MASK; + } + if(status & ENET_EIR_TXF_MASK) + { + + ENET->TDAR = ENET_TDAR_TDAR_MASK; + +#ifdef NX_DRIVER_ENABLE_DEFERRED + + /* Set the transmit complete bit. */ + nx_driver_information.nx_driver_information_deferred_events |= NX_DRIVER_DEFERRED_PACKET_TRANSMITTED; +#else + + /* Process transmitted packet(s). */ + _nx_driver_hardware_packet_transmitted(); +#endif + +#ifdef NX_DRIVER_ENABLE_DEFERRED + + /* Call NetX deferred driver processing. */ + _nx_ip_driver_deferred_processing(nx_driver_information.nx_driver_information_ip_ptr); +#endif + + /* Clear the Eth DMA Tx IT pending bit. */ + ENET->EIR = ENET_EIR_TXF_MASK; + } +} + +/****** DRIVER SPECIFIC ****** Start of part/vendor specific internal driver functions. */ diff --git a/targets/NXP/MIMXRT1064-EVK/lib/netx_driver/nx_driver_imxrt1062.h b/targets/NXP/MIMXRT1064-EVK/lib/netx_driver/nx_driver_imxrt1062.h new file mode 100644 index 00000000..23d30cbc --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/lib/netx_driver/nx_driver_imxrt1062.h @@ -0,0 +1,244 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Ethernet driver for IMX family of microprocessors */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifndef NX_DRIVER_IMXRT1062_H +#define NX_DRIVER_IMXRT1062_H + + +#ifdef __cplusplus + +/* Yes, C++ compiler is present. Use standard C. */ +extern "C" { +#endif + + +/* Include ThreadX header file, if not already. */ + +#ifndef TX_API_H +#include "tx_api.h" +#endif + + +/* Include NetX header file, if not already. */ + +#ifndef NX_API_H +#include "nx_api.h" +#endif + + +/* Determine if the driver's source file is being compiled. The constants and typdefs are only valid within + the driver's source file compilation. */ + +#ifdef NX_DRIVER_SOURCE + + +/****** DRIVER SPECIFIC ****** Start of part/vendor specific include area. Include any such files here! */ + +#include "fsl_enet.h" +#include "fsl_phy.h" +#include "board.h" +#include "fsl_debug_console.h" + +#include "pin_mux.h" +#include "fsl_common.h" +#include "fsl_iomuxc.h" +#include "MIMXRT1062.h" + +/****** DRIVER SPECIFIC ****** End of part/vendor specific include file area! */ + + +#define CORE_CLK_FREQ CLOCK_GetFreq(kCLOCK_AhbClk) +#define EXAMPLE_ENET ENET +#define EXAMPLE_PHY 0x02U + +/*ARM Cortex M4 implementation for interrupt priority shift*/ +#define ARM_INTERRUPT_LEVEL_BITS 4 +#define PRIORITY 6 + +/* Define generic constants and macros for all NetX Ethernet drivers. */ + +#define NX_DRIVER_ETHERNET_IP 0x0800 +#define NX_DRIVER_ETHERNET_IPV6 0x86dd +#define NX_DRIVER_ETHERNET_ARP 0x0806 +#define NX_DRIVER_ETHERNET_RARP 0x8035 + +#define NX_DRIVER_ETHERNET_MTU 1514 +#define NX_DRIVER_ETHERNET_FRAME_SIZE 14 +#define NX_DRIVER_PHYSICAL_ADDRESS_SIZE 6 + +#define NX_DRIVER_DEFERRED_PACKET_RECEIVED 1 +#define NX_DRIVER_DEFERRED_DEVICE_RESET 2 +#define NX_DRIVER_DEFERRED_PACKET_TRANSMITTED 4 + +#define NX_DRIVER_STATE_NOT_INITIALIZED 1 +#define NX_DRIVER_STATE_INITIALIZE_FAILED 2 +#define NX_DRIVER_STATE_INITIALIZED 3 +#define NX_DRIVER_STATE_LINK_ENABLED 4 + +#ifdef NX_DIRVER_INTERNAL_TRANSMIT_QUEUE +#define NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH 10 +#endif + +#define NX_DRIVER_ERROR 90 + + +#define NX_DRIVER_ETHERNET_HEADER_REMOVE(p) \ +{ \ + p -> nx_packet_prepend_ptr = p -> nx_packet_prepend_ptr + NX_DRIVER_ETHERNET_FRAME_SIZE; \ + p -> nx_packet_length = p -> nx_packet_length - NX_DRIVER_ETHERNET_FRAME_SIZE; \ +} + + +/*calculate checksum by hardware*/ + +/* +#define NX_DRIVER_CAPABILITY ( NX_INTERFACE_CAPABILITY_IPV4_TX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_IPV4_RX_CHECKSUM |\ + NX_INTERFACE_CAPABILITY_TCP_TX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_TCP_RX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_UDP_TX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_UDP_RX_CHECKSUM| \ + NX_INTERFACE_CAPABILITY_ICMPV4_TX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_ICMPV4_RX_CHECKSUM ) + // NX_INTERFACE_CAPABILITY_ICMPV6_TX_CHECKSUM | \ + // NX_INTERFACE_CAPABILITY_ICMPV6_RX_CHECKSUM ) +*/ + +/****** DRIVER SPECIFIC ****** Start of part/vendor specific constants area. Include any such constants here! */ + +/* Enable checksum offload. */ +#define IMX_CHECKSUM_OFFLOAD + +#define PHY_ADDRESS 1 +#define PHY_ICS 0x1B +#define PHY_ICS_LINKUPIE 0x0100 +#define PHY_ICS_LINKUPI 0x0001 +#define PHY_ICS_LINKDOWNIE 0x0400 +#define PHY_ICS_LINKDOWNI 0x0004 + +/* Define the number of descriptors and attached packets for transmit and receive operations. */ + +#ifndef NX_DRIVER_TX_DESCRIPTORS +#define NX_DRIVER_TX_DESCRIPTORS 64 +#endif + +#ifndef NX_DRIVER_RX_DESCRIPTORS +#define NX_DRIVER_RX_DESCRIPTORS 8 +#endif + + +/****** DRIVER SPECIFIC ****** End of part/vendor specific constant area! */ + + +/* Define basic Ethernet driver information typedef. Note that this typedefs is designed to be used only + in the driver's C file. */ + +typedef struct NX_DRIVER_INFORMATION_STRUCT +{ + /* NetX IP instance that this driver is attached to. */ + NX_IP *nx_driver_information_ip_ptr; + + /* Driver's current state. */ + ULONG nx_driver_information_state ; + + /* Packet pool used for receiving packets. */ + NX_PACKET_POOL *nx_driver_information_packet_pool_ptr; + + /* Define the driver interface association. */ + NX_INTERFACE *nx_driver_information_interface; + + /* Define the deferred event field. This will contain bits representing events + deferred from the ISR for processing in the thread context. */ + ULONG nx_driver_information_deferred_events; + + + /****** DRIVER SPECIFIC ****** Start of part/vendor specific driver information area. Include any such constants here! */ + + /* Indices to current receive/transmit descriptors. */ + UINT nx_driver_information_receive_current_index; + UINT nx_driver_information_transmit_current_index; + + /* Transmit release index. */ + UINT nx_driver_information_transmit_release_index; + + /* Define the number of transmit buffers in use. */ + UINT nx_driver_information_number_of_transmit_buffers_in_use; + + /* Define the Ethernet RX & TX DMA Descriptors. */ + UCHAR nx_driver_information_dma_rx_descriptors_area[sizeof(enet_rx_bd_struct_t) * NX_DRIVER_RX_DESCRIPTORS + 16]; + UCHAR nx_driver_information_dma_tx_descriptors_area[sizeof(enet_tx_bd_struct_t) * NX_DRIVER_TX_DESCRIPTORS + 16]; + + enet_rx_bd_struct_t *nx_driver_information_dma_rx_descriptors; + enet_tx_bd_struct_t *nx_driver_information_dma_tx_descriptors; + + /* Define the association between buffer descriptors and NetX packets. */ + NX_PACKET *nx_driver_information_transmit_packets[NX_DRIVER_TX_DESCRIPTORS]; + NX_PACKET *nx_driver_information_receive_packets[NX_DRIVER_RX_DESCRIPTORS]; + + /* Define the size of a rx buffer size. */ + ULONG nx_driver_information_rx_buffer_size; + + UCHAR nx_driver_information_multicast_count[64]; + + UINT nx_driver_information_link_speed; + UINT nx_driver_information_link_duplex; + + +#ifdef NX_DIRVER_INTERNAL_TRANSMIT_QUEUE + + /* Define the parameters in the internal driver transmit queue. The queue is maintained as a singularly + linked-list with head and tail pointers. The maximum number of packets on the queue is regulated by + the constant NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH, which is defined above. When this number is reached, + the oldest packet is discarded after the new packet is queued. */ + ULONG nx_driver_transmit_packets_queued; + NX_PACKET nx_driver_transmit_queue_head; + NX_PACKET nx_driver_transmit_queue_tail; +#endif + + + /****** DRIVER SPECIFIC ****** End of part/vendor specific driver information area. */ + +} NX_DRIVER_INFORMATION; + +#endif + + +/****** DRIVER SPECIFIC ****** Start of part/vendor specific external function prototypes. A typical NetX Ethernet driver + should expose its entry function as well as its interrupt handling function(s) here. All other + functions in the driver should have local scope, i.e., defined as static. */ + +/* Define global driver entry function. */ + +VOID nx_driver_imx(NX_IP_DRIVER *driver_req_ptr); + +/* Define global driver interrupt dispatch function. */ + + +/****** DRIVER SPECIFIC ****** End of part/vendor specific external function prototypes. */ + + +#ifdef __cplusplus +/* Yes, C++ compiler is present. Use standard C. */ + } +#endif + +#endif diff --git a/targets/NXP/MIMXRT1064-EVK/lib/netxduo/nx_user.h b/targets/NXP/MIMXRT1064-EVK/lib/netxduo/nx_user.h new file mode 100644 index 00000000..eccf436a --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/lib/netxduo/nx_user.h @@ -0,0 +1,21 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#ifndef NX_USER_H +#define NX_USER_H + +#define NX_DISABLE_IPV6 +#define NX_PHYSICAL_HEADER 16 +#define NX_ENABLE_EXTENDED_NOTIFY_SUPPORT + +#endif /* NX_USER_H */ diff --git a/targets/NXP/MIMXRT1064-EVK/lib/phyksz8081/fsl_phy.c b/targets/NXP/MIMXRT1064-EVK/lib/phyksz8081/fsl_phy.c new file mode 100644 index 00000000..af520c4d --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/lib/phyksz8081/fsl_phy.c @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "fsl_phy.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @brief Defines the timeout macro. */ +#define PHY_TIMEOUT_COUNT 100000U + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/******************************************************************************* + * Variables + ******************************************************************************/ + +/******************************************************************************* + * Code + ******************************************************************************/ + +status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz) +{ + uint32_t bssReg; + uint32_t counter = PHY_TIMEOUT_COUNT; + uint32_t idReg = 0; + status_t result = kStatus_Success; + uint32_t instance = ENET_GetInstance(base); + uint32_t timeDelay; + uint32_t ctlReg = 0; + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + /* Set SMI first. */ + CLOCK_EnableClock(s_enetClock[instance]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + ENET_SetSMI(base, srcClock_Hz, false); + + /* Initialization after PHY stars to work. */ + while ((idReg != PHY_CONTROL_ID1) && (counter != 0U)) + { + (void)PHY_Read(base, phyAddr, PHY_ID1_REG, &idReg); + counter--; + } + + if (counter == 0U) + { + return kStatus_Fail; + } + + /* Reset PHY. */ + counter = PHY_TIMEOUT_COUNT; + result = PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK); + if (result == kStatus_Success) + { +#if defined(FSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE) + uint32_t data = 0; + result = PHY_Read(base, phyAddr, PHY_CONTROL2_REG, &data); + if (result != kStatus_Success) + { + return result; + } + result = PHY_Write(base, phyAddr, PHY_CONTROL2_REG, (data | PHY_CTL2_REFCLK_SELECT_MASK)); + if (result != kStatus_Success) + { + return result; + } +#endif /* FSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE */ + + /* Set the negotiation. */ + result = PHY_Write(base, phyAddr, PHY_AUTONEG_ADVERTISE_REG, + (PHY_100BASETX_FULLDUPLEX_MASK | PHY_100BASETX_HALFDUPLEX_MASK | + PHY_10BASETX_FULLDUPLEX_MASK | PHY_10BASETX_HALFDUPLEX_MASK | 0x1U)); + if (result == kStatus_Success) + { + result = + PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, (PHY_BCTL_AUTONEG_MASK | PHY_BCTL_RESTART_AUTONEG_MASK)); + if (result == kStatus_Success) + { + /* Check auto negotiation complete. */ + while (counter-- != 0U) + { + result = PHY_Read(base, phyAddr, PHY_BASICSTATUS_REG, &bssReg); + if (result == kStatus_Success) + { + (void)PHY_Read(base, phyAddr, PHY_CONTROL1_REG, &ctlReg); + if (((bssReg & PHY_BSTATUS_AUTONEGCOMP_MASK) != 0U) && ((ctlReg & PHY_LINK_READY_MASK) != 0U)) + { + /* Wait a moment for Phy status stable. */ + for (timeDelay = 0; timeDelay < PHY_TIMEOUT_COUNT; timeDelay++) + { + __ASM("nop"); + } + break; + } + } + + if (counter == 0U) + { + return kStatus_PHY_AutoNegotiateFail; + } + } + } + } + } + + return result; +} + +status_t PHY_Write(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t data) +{ + uint32_t counter; + + /* Clear the SMI interrupt event. */ + ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK); + + /* Starts a SMI write command. */ + ENET_StartSMIWrite(base, phyAddr, phyReg, kENET_MiiWriteValidFrame, data); + + /* Wait for SMI complete. */ + for (counter = PHY_TIMEOUT_COUNT; counter > 0U; counter--) + { + if ((ENET_GetInterruptStatus(base) & ENET_EIR_MII_MASK) != 0U) + { + break; + } + } + + /* Check for timeout. */ + if (counter == 0U) + { + return kStatus_PHY_SMIVisitTimeout; + } + + /* Clear MII interrupt event. */ + ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK); + + return kStatus_Success; +} + +status_t PHY_Read(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr) +{ + assert(dataPtr); + + uint32_t counter; + + /* Clear the MII interrupt event. */ + ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK); + + /* Starts a SMI read command operation. */ + ENET_StartSMIRead(base, phyAddr, phyReg, kENET_MiiReadValidFrame); + + /* Wait for MII complete. */ + for (counter = PHY_TIMEOUT_COUNT; counter > 0U; counter--) + { + if ((ENET_GetInterruptStatus(base) & ENET_EIR_MII_MASK) != 0U) + { + break; + } + } + + /* Check for timeout. */ + if (counter == 0U) + { + return kStatus_PHY_SMIVisitTimeout; + } + + /* Get data from MII register. */ + *dataPtr = ENET_ReadSMIData(base); + + /* Clear MII interrupt event. */ + ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK); + + return kStatus_Success; +} + +status_t PHY_EnableLoopback(ENET_Type *base, uint32_t phyAddr, phy_loop_t mode, phy_speed_t speed, bool enable) +{ + status_t result; + uint32_t data = 0; + + /* Set the loop mode. */ + if (enable) + { + if (mode == kPHY_LocalLoop) + { + if (speed == kPHY_Speed100M) + { + data = PHY_BCTL_SPEED_100M_MASK | PHY_BCTL_DUPLEX_MASK | PHY_BCTL_LOOP_MASK; + } + else + { + data = PHY_BCTL_DUPLEX_MASK | PHY_BCTL_LOOP_MASK; + } + return PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, data); + } + else + { + /* First read the current status in control register. */ + result = PHY_Read(base, phyAddr, PHY_CONTROL2_REG, &data); + if (result == kStatus_Success) + { + return PHY_Write(base, phyAddr, PHY_CONTROL2_REG, (data | PHY_CTL2_REMOTELOOP_MASK)); + } + } + } + else + { + /* Disable the loop mode. */ + if (mode == kPHY_LocalLoop) + { + /* First read the current status in control register. */ + result = PHY_Read(base, phyAddr, PHY_BASICCONTROL_REG, &data); + if (result == kStatus_Success) + { + data &= ~PHY_BCTL_LOOP_MASK; + return PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, (data | PHY_BCTL_RESTART_AUTONEG_MASK)); + } + } + else + { + /* First read the current status in control one register. */ + result = PHY_Read(base, phyAddr, PHY_CONTROL2_REG, &data); + if (result == kStatus_Success) + { + return PHY_Write(base, phyAddr, PHY_CONTROL2_REG, (data & ~PHY_CTL2_REMOTELOOP_MASK)); + } + } + } + return result; +} + +status_t PHY_GetLinkStatus(ENET_Type *base, uint32_t phyAddr, bool *status) +{ + assert(status); + + status_t result = kStatus_Success; + uint32_t data; + + /* Read the basic status register. */ + result = PHY_Read(base, phyAddr, PHY_BASICSTATUS_REG, &data); + if (result == kStatus_Success) + { + if ((PHY_BSTATUS_LINKSTATUS_MASK & data) == 0U) + { + /* link down. */ + *status = false; + } + else + { + /* link up. */ + *status = true; + } + } + return result; +} + +status_t PHY_GetLinkSpeedDuplex(ENET_Type *base, uint32_t phyAddr, phy_speed_t *speed, phy_duplex_t *duplex) +{ + assert(duplex); + + status_t result = kStatus_Success; + uint32_t data, ctlReg; + + /* Read the control two register. */ + result = PHY_Read(base, phyAddr, PHY_CONTROL1_REG, &ctlReg); + if (result == kStatus_Success) + { + data = ctlReg & PHY_CTL1_SPEEDUPLX_MASK; + if ((PHY_CTL1_10FULLDUPLEX_MASK == data) || (PHY_CTL1_100FULLDUPLEX_MASK == data)) + { + /* Full duplex. */ + *duplex = kPHY_FullDuplex; + } + else + { + /* Half duplex. */ + *duplex = kPHY_HalfDuplex; + } + + data = ctlReg & PHY_CTL1_SPEEDUPLX_MASK; + if ((PHY_CTL1_100HALFDUPLEX_MASK == data) || (PHY_CTL1_100FULLDUPLEX_MASK == data)) + { + /* 100M speed. */ + *speed = kPHY_Speed100M; + } + else + { /* 10M speed. */ + *speed = kPHY_Speed10M; + } + } + + return result; +} diff --git a/targets/NXP/MIMXRT1064-EVK/lib/phyksz8081/fsl_phy.h b/targets/NXP/MIMXRT1064-EVK/lib/phyksz8081/fsl_phy.h new file mode 100644 index 00000000..692457d4 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/lib/phyksz8081/fsl_phy.h @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef _FSL_PHY_H_ +#define _FSL_PHY_H_ + +#include "fsl_enet.h" + +/*! + * @addtogroup phy_driver + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @brief PHY driver version */ +#define FSL_PHY_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */ + +/*! @brief Defines the PHY registers. */ +#define PHY_BASICCONTROL_REG 0x00U /*!< The PHY basic control register. */ +#define PHY_BASICSTATUS_REG 0x01U /*!< The PHY basic status register. */ +#define PHY_ID1_REG 0x02U /*!< The PHY ID one register. */ +#define PHY_ID2_REG 0x03U /*!< The PHY ID two register. */ +#define PHY_AUTONEG_ADVERTISE_REG 0x04U /*!< The PHY auto-negotiate advertise register. */ +#define PHY_CONTROL1_REG 0x1EU /*!< The PHY control one register. */ +#define PHY_CONTROL2_REG 0x1FU /*!< The PHY control two register. */ + +#define PHY_CONTROL_ID1 0x22U /*!< The PHY ID1*/ + +/*! @brief Defines the mask flag in basic control register. */ +#define PHY_BCTL_DUPLEX_MASK 0x0100U /*!< The PHY duplex bit mask. */ +#define PHY_BCTL_RESTART_AUTONEG_MASK 0x0200U /*!< The PHY restart auto negotiation mask. */ +#define PHY_BCTL_AUTONEG_MASK 0x1000U /*!< The PHY auto negotiation bit mask. */ +#define PHY_BCTL_SPEED_MASK 0x2000U /*!< The PHY speed bit mask. */ +#define PHY_BCTL_LOOP_MASK 0x4000U /*!< The PHY loop bit mask. */ +#define PHY_BCTL_RESET_MASK 0x8000U /*!< The PHY reset bit mask. */ +#define PHY_BCTL_SPEED_100M_MASK 0x2000U /*!< The PHY 100M speed mask. */ + +/*!@brief Defines the mask flag of operation mode in control two register*/ +#define PHY_CTL2_REMOTELOOP_MASK 0x0004U /*!< The PHY remote loopback mask. */ +#define PHY_CTL2_REFCLK_SELECT_MASK 0x0080U /*!< The PHY RMII reference clock select. */ +#define PHY_CTL1_10HALFDUPLEX_MASK 0x0001U /*!< The PHY 10M half duplex mask. */ +#define PHY_CTL1_100HALFDUPLEX_MASK 0x0002U /*!< The PHY 100M half duplex mask. */ +#define PHY_CTL1_10FULLDUPLEX_MASK 0x0005U /*!< The PHY 10M full duplex mask. */ +#define PHY_CTL1_100FULLDUPLEX_MASK 0x0006U /*!< The PHY 100M full duplex mask. */ +#define PHY_CTL1_SPEEDUPLX_MASK 0x0007U /*!< The PHY speed and duplex mask. */ +#define PHY_CTL1_ENERGYDETECT_MASK 0x10U /*!< The PHY signal present on rx differential pair. */ +#define PHY_CTL1_LINKUP_MASK 0x100U /*!< The PHY link up. */ +#define PHY_LINK_READY_MASK (PHY_CTL1_ENERGYDETECT_MASK | PHY_CTL1_LINKUP_MASK) + +/*! @brief Defines the mask flag in basic status register. */ +#define PHY_BSTATUS_LINKSTATUS_MASK 0x0004U /*!< The PHY link status mask. */ +#define PHY_BSTATUS_AUTONEGABLE_MASK 0x0008U /*!< The PHY auto-negotiation ability mask. */ +#define PHY_BSTATUS_AUTONEGCOMP_MASK 0x0020U /*!< The PHY auto-negotiation complete mask. */ + +/*! @brief Defines the mask flag in PHY auto-negotiation advertise register. */ +#define PHY_100BaseT4_ABILITY_MASK 0x200U /*!< The PHY have the T4 ability. */ +#define PHY_100BASETX_FULLDUPLEX_MASK 0x100U /*!< The PHY has the 100M full duplex ability.*/ +#define PHY_100BASETX_HALFDUPLEX_MASK 0x080U /*!< The PHY has the 100M full duplex ability.*/ +#define PHY_10BASETX_FULLDUPLEX_MASK 0x040U /*!< The PHY has the 10M full duplex ability.*/ +#define PHY_10BASETX_HALFDUPLEX_MASK 0x020U /*!< The PHY has the 10M full duplex ability.*/ + +/*! @brief Defines the PHY status. */ +enum +{ + kStatus_PHY_SMIVisitTimeout = MAKE_STATUS(kStatusGroup_PHY, 1), /*!< ENET PHY SMI visit timeout. */ + kStatus_PHY_AutoNegotiateFail = MAKE_STATUS(kStatusGroup_PHY, 2) /*!< ENET PHY AutoNegotiate Fail. */ +}; + +/*! @brief Defines the PHY link speed. This is align with the speed for ENET MAC. */ +typedef enum _phy_speed +{ + kPHY_Speed10M = 0U, /*!< ENET PHY 10M speed. */ + kPHY_Speed100M /*!< ENET PHY 100M speed. */ +} phy_speed_t; + +/*! @brief Defines the PHY link duplex. */ +typedef enum _phy_duplex +{ + kPHY_HalfDuplex = 0U, /*!< ENET PHY half duplex. */ + kPHY_FullDuplex /*!< ENET PHY full duplex. */ +} phy_duplex_t; + +/*! @brief Defines the PHY loopback mode. */ +typedef enum _phy_loop +{ + kPHY_LocalLoop = 0U, /*!< ENET PHY local loopback. */ + kPHY_RemoteLoop /*!< ENET PHY remote loopback. */ +} phy_loop_t; + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @name PHY Driver + * @{ + */ + +/*! + * @brief Initializes PHY. + * + * This function initialize the SMI interface and initialize PHY. + * The SMI is the MII management interface between PHY and MAC, which should be + * firstly initialized before any other operation for PHY. The PHY initialize with auto-negotiation. + * + * @param base ENET peripheral base address. + * @param phyAddr The PHY address. + * @param srcClock_Hz The module clock frequency - system clock for MII management interface - SMI. + * @retval kStatus_Success PHY initialize success + * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out + * @retval kStatus_PHY_AutoNegotiateFail PHY auto negotiate fail + */ +status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz); + +/*! + * @brief PHY Write function. This function write data over the SMI to + * the specified PHY register. This function is called by all PHY interfaces. + * + * @param base ENET peripheral base address. + * @param phyAddr The PHY address. + * @param phyReg The PHY register. + * @param data The data written to the PHY register. + * @retval kStatus_Success PHY write success + * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out + */ +status_t PHY_Write(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t data); + +/*! + * @brief PHY Read function. This interface read data over the SMI from the + * specified PHY register. This function is called by all PHY interfaces. + * + * @param base ENET peripheral base address. + * @param phyAddr The PHY address. + * @param phyReg The PHY register. + * @param dataPtr The address to store the data read from the PHY register. + * @retval kStatus_Success PHY read success + * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out + */ +status_t PHY_Read(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr); + +/*! + * @brief Enables/disables PHY loopback. + * + * @param base ENET peripheral base address. + * @param phyAddr The PHY address. + * @param mode The loopback mode to be enabled, please see "phy_loop_t". + * the two loopback mode should not be both set. when one loopback mode is set + * the other one should be disabled. + * @param speed PHY speed for loopback mode. + * @param enable True to enable, false to disable. + * @retval kStatus_Success PHY loopback success + * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out + */ +status_t PHY_EnableLoopback(ENET_Type *base, uint32_t phyAddr, phy_loop_t mode, phy_speed_t speed, bool enable); + +/*! + * @brief Gets the PHY link status. + * + * @param base ENET peripheral base address. + * @param phyAddr The PHY address. + * @param status The link up or down status of the PHY. + * - true the link is up. + * - false the link is down. + * @retval kStatus_Success PHY get link status success + * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out + */ +status_t PHY_GetLinkStatus(ENET_Type *base, uint32_t phyAddr, bool *status); + +/*! + * @brief Gets the PHY link speed and duplex. + * + * @param base ENET peripheral base address. + * @param phyAddr The PHY address. + * @param speed The address of PHY link speed. + * @param duplex The link duplex of PHY. + * @retval kStatus_Success PHY get link speed and duplex success + * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out + */ +status_t PHY_GetLinkSpeedDuplex(ENET_Type *base, uint32_t phyAddr, phy_speed_t *speed, phy_duplex_t *duplex); + +/* @} */ + +#if defined(__cplusplus) +} +#endif + +/*! @}*/ + +#endif /* _FSL_PHY_H_ */ diff --git a/targets/NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h b/targets/NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h new file mode 100644 index 00000000..3deb0a1e --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h @@ -0,0 +1,29 @@ +/**************************************************************************/ +/* Copyright (c) Microsoft */ +/* 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 */ +/* */ +/* Contributors: */ +/* Ali Eissa - 2026 version. */ +/**************************************************************************/ + +#ifndef TX_USER_H +#define TX_USER_H + +/* Enable hardware FPU register context switching support for Cortex-M7 */ +#define TX_ENABLE_FPU_SUPPORT + +/* System tick frequency in Hz (typically 100 or 1000) */ +#ifndef TX_TIMER_TICKS_PER_SECOND +#define TX_TIMER_TICKS_PER_SECOND 100 +#endif + +/* Enable ThreadX runtime stack checking */ +#define TX_ENABLE_STACK_CHECKING + +#endif /* TX_USER_H */ diff --git a/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl b/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl new file mode 100644 index 00000000..67acd0a6 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.repl @@ -0,0 +1,30 @@ +// 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 +// +// Contributors: +// Ali Eissa - 2026 version. + +using "platforms/boards/mimxrt1064_evk.repl" + +// User LED D18 (Green, active low, connected to GPIO1 Pin 9) +gpio1: + 9 -> user_led@0 + +user_led: Miscellaneous.LED @ gpio1 9 + invert: true + +// Ethernet Physical Layer (KSZ8081 PHY at address 2 on enet) +phy: Network.EthernetPhysicalLayer @ enet 2 + Id1: 0x0022 + Id2: 0x1560 + BasicControl: 0x3100 + BasicStatus: 0x782D + AutoNegotiationAdvertisement: 0x01E1 + AutoNegotiationLinkPartnerBasePageAbility: 0x01E1 + VendorSpecific14: 0x0116 + VendorSpecific15: 0x0080 diff --git a/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc b/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc new file mode 100644 index 00000000..acab50dc --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-evk.resc @@ -0,0 +1,45 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +:name: MIMXRT1064-EVK ThreadX Demo +:description: This script runs the Eclipse ThreadX & NetX Duo demo on NXP i.MX RT1064-EVK. + +mach create "mimxrt1064-evk" + +$platform?=$ORIGIN/mimxrt1064-evk.repl +machine LoadPlatformDescription $platform + +$bin?=$ORIGIN/../build/app/demos/netx_echo/mimxrt1064_threadx.elf + +# Create Ethernet Switch and connect ENET peripheral +emulation CreateSwitch "switch" +connector Connect sysbus.enet switch + +# Host TAP networking configuration (for ICMP ping and UDP/TCP echo from host PC): +# On Windows, install OpenVPN/TAP adapter named "renode-tap" configured with IP 192.168.0.1 / 255.255.255.0. +# On Linux, create tap interface: `sudo ip tuntap add mode tap tap0 && sudo ifconfig tap0 192.168.0.1 up` +# Uncomment below lines to bridge the simulated switch to your host TAP device: +# emulation CreateTap "renode-tap" "tap" +# connector Connect host.tap switch + +showAnalyzer sysbus.lpuart1 + +macro reset +""" + cpu VectorTableOffset 0x70002000 + sysbus LoadELF $bin + cpu PC `sysbus ReadDoubleWord 0x70002004` + cpu SP `sysbus ReadDoubleWord 0x70002000` +""" + +runMacro $reset + +start diff --git a/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc b/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc new file mode 100644 index 00000000..13b1ae9e --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-multinode.resc @@ -0,0 +1,53 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +:name: MIMXRT1064-EVK Headless Multi-Node CI Test + +$platform?=$ORIGIN/mimxrt1064-evk.repl +$bin_server?=$ORIGIN/../build/app/demos/netx_echo/mimxrt1064_threadx.elf +$bin_client?=$ORIGIN/../build/app/demos/netx_echo/mimxrt1064_client.elf + +# 1. Create Virtual Ethernet Switch +emulation CreateSwitch "switch" + +# 2. Server Machine (192.168.0.100) +mach create "server" +machine LoadPlatformDescription $platform +connector Connect sysbus.enet switch + +macro reset +""" + sysbus LoadELF $bin_server + cpu VectorTableOffset 0x70002000 + cpu PC `sysbus ReadDoubleWord 0x70002004` + cpu SP `sysbus ReadDoubleWord 0x70002000` +""" +runMacro $reset + +# 3. Client Machine (192.168.0.101) +mach create "client" +machine LoadPlatformDescription $platform +connector Connect sysbus.enet switch +showAnalyzer sysbus.lpuart1 + +macro reset +""" + sysbus LoadELF $bin_client + cpu VectorTableOffset 0x70002000 + cpu PC `sysbus ReadDoubleWord 0x70002004` + cpu SP `sysbus ReadDoubleWord 0x70002000` +""" +runMacro $reset + +# 4. Start Simulation +emulation RunFor "6" + +quit diff --git a/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc b/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc new file mode 100644 index 00000000..47caa5ce --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-headless-single.resc @@ -0,0 +1,35 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +:name: MIMXRT1064-EVK Headless Single-Node CI Test +:description: Headless single-node verification capturing LPUART1 output to log file. + +using sysbus +mach create "mimxrt1064-evk" +$platform?=$ORIGIN/mimxrt1064-evk.repl +machine LoadPlatformDescription $platform + +showAnalyzer sysbus.lpuart1 + +$bin?=$ORIGIN/../build/app/demos/threadx_basic/mimxrt1064_threadx.elf + +macro reset +""" + sysbus LoadELF $bin + cpu VectorTableOffset 0x70002000 + cpu PC `sysbus ReadDoubleWord 0x70002004` + cpu SP `sysbus ReadDoubleWord 0x70002000` +""" +runMacro $reset + +emulation RunFor "4" + +quit diff --git a/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-network-multinode.resc b/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-network-multinode.resc new file mode 100644 index 00000000..54343a1b --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-network-multinode.resc @@ -0,0 +1,62 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +:name: MIMXRT1064-EVK NetX Duo Two-Node Virtual Network Verification +:description: This script creates two MIMXRT1064-EVK nodes connected via a virtual Ethernet switch: +: - "server": Echo Server on 192.168.0.100 (ICMP Ping, UDP port 7, TCP port 7) +: - "client": Verification Client on 192.168.0.101 (tests ICMP, UDP Echo, TCP Echo) + +# 1. Create Virtual Ethernet Switch +emulation CreateSwitch "switch" + +# 2. Server Machine (192.168.0.100) +mach create "server" +machine LoadPlatformDescription $ORIGIN/mimxrt1064-evk.repl +connector Connect sysbus.enet switch +showAnalyzer sysbus.lpuart1 + +$bin_server?=$ORIGIN/../build/mimxrt1064_threadx.elf +macro reset_server +""" + cpu VectorTableOffset 0x70002000 + sysbus LoadELF $bin_server + cpu PC `sysbus ReadDoubleWord 0x70002004` + cpu SP `sysbus ReadDoubleWord 0x70002000` +""" +runMacro $reset_server + +# 3. Client Machine (192.168.0.101) +mach create "client" +machine LoadPlatformDescription $ORIGIN/mimxrt1064-evk.repl +connector Connect sysbus.enet switch +showAnalyzer sysbus.lpuart1 + +$bin_client?=$ORIGIN/../build/mimxrt1064_client.elf +macro reset_client +""" + cpu VectorTableOffset 0x70002000 + sysbus LoadELF $bin_client + cpu PC `sysbus ReadDoubleWord 0x70002004` + cpu SP `sysbus ReadDoubleWord 0x70002000` +""" +runMacro $reset_client + +# 4. Global reset macro to reset both nodes simultaneously +macro reset +""" + mach set "server" + runMacro $reset_server + mach set "client" + runMacro $reset_client +""" + +# 5. Start Simulation +start diff --git a/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-trng-console.resc b/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-trng-console.resc new file mode 100644 index 00000000..58f2465a --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/renode/mimxrt1064-trng-console.resc @@ -0,0 +1,62 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +:name: MIMXRT1064-EVK Hardware TRNG & Console Two-Node Verification +:description: This script creates two MIMXRT1064-EVK nodes connected via a virtual Ethernet switch: +: - "server": TRNG Console Server on 192.168.0.100 (TCP Port 23, ICMP Ping) +: - "client": Verification Client on 192.168.0.101 (tests TRNG entropy, LED control, Info) + +# 1. Create Virtual Ethernet Switch +emulation CreateSwitch "switch" + +# 2. Server Machine (192.168.0.100) +mach create "server" +machine LoadPlatformDescription $ORIGIN/mimxrt1064-evk.repl +connector Connect sysbus.enet switch +showAnalyzer sysbus.lpuart1 + +$bin_server?=$ORIGIN/../build/mimxrt1064_threadx.elf +macro reset_server +""" + cpu VectorTableOffset 0x70002000 + sysbus LoadELF $bin_server + cpu PC `sysbus ReadDoubleWord 0x70002004` + cpu SP `sysbus ReadDoubleWord 0x70002000` +""" +runMacro $reset_server + +# 3. Client Machine (192.168.0.101) +mach create "client" +machine LoadPlatformDescription $ORIGIN/mimxrt1064-evk.repl +connector Connect sysbus.enet switch +showAnalyzer sysbus.lpuart1 + +$bin_client?=$ORIGIN/../build/mimxrt1064_client.elf +macro reset_client +""" + cpu VectorTableOffset 0x70002000 + sysbus LoadELF $bin_client + cpu PC `sysbus ReadDoubleWord 0x70002004` + cpu SP `sysbus ReadDoubleWord 0x70002000` +""" +runMacro $reset_client + +# 4. Global reset macro to reset both nodes simultaneously +macro reset +""" + mach set "server" + runMacro $reset_server + mach set "client" + runMacro $reset_client +""" + +# 5. Start Simulation +start diff --git a/targets/NXP/MIMXRT1064-EVK/scripts/build.ps1 b/targets/NXP/MIMXRT1064-EVK/scripts/build.ps1 new file mode 100644 index 00000000..b785894f --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/scripts/build.ps1 @@ -0,0 +1,113 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +param( + [switch]$Clean, + [switch]$Rebuild, + [string]$Demo = "all" +) + +$BoardDir = Resolve-Path "$PSScriptRoot/.." +$BUILD_DIR = Join-Path $BoardDir "build" +$NUM_JOBS = 4 + +Write-Host "==========================================" +Write-Host "NXP MIMXRT1064-EVK - Build Script" +Write-Host "==========================================" +Write-Host "Board Dir: $BoardDir" +Write-Host "Build Dir: $BUILD_DIR" +Write-Host "Active Demo: $Demo" +Write-Host "" + +# Check for ARM GCC compiler +$armGcc = Get-Command "arm-none-eabi-gcc" -ErrorAction SilentlyContinue +if (!$armGcc -and !$env:ARM_GCC_PATH) { + Write-Host "[WARNING] arm-none-eabi-gcc not found on PATH and ARM_GCC_PATH not set." -ForegroundColor Yellow + Write-Host "" +} + +if ($Clean -or $Rebuild) { + Write-Host "[INFO] Cleaning build directory..." + if (Test-Path $BUILD_DIR) { + Remove-Item -Path $BUILD_DIR -Recurse -Force + } + New-Item -ItemType Directory -Path $BUILD_DIR -Force | Out-Null + Write-Host "[OK] Build directory cleaned" + Write-Host "" +} + +if (!(Test-Path $BUILD_DIR)) { + New-Item -ItemType Directory -Path $BUILD_DIR -Force | Out-Null +} + +Push-Location $BUILD_DIR + +# Reconfigure if CMakeCache.txt or build.ninja is missing, or demo changed, or if forced +$needConfig = !(Test-Path "CMakeCache.txt") -or !(Test-Path "build.ninja") -or $Rebuild +if (!$needConfig -and (Test-Path "CMakeCache.txt")) { + $cachedDemo = (Select-String -Path "CMakeCache.txt" -Pattern "^ACTIVE_DEMO:STRING=(.*)$" | ForEach-Object { $_.Matches.Groups[1].Value.Trim() }) + if ($cachedDemo -ne $Demo) { + $needConfig = $true + } +} + +if ($needConfig) { + Write-Host "[INFO] Configuring CMake for demo: $Demo..." + cmake -G Ninja ` + "-DCMAKE_BUILD_TYPE=Release" ` + "-DACTIVE_DEMO=$Demo" ` + .. + if ($LASTEXITCODE -ne 0) { + Write-Host "[ERROR] CMake configuration failed!" -ForegroundColor Red + Pop-Location + exit 1 + } + Write-Host "[OK] CMake configured" + Write-Host "" +} + +# Run build using Ninja +Write-Host "[INFO] Building target with Ninja ($NUM_JOBS parallel jobs)..." +ninja -j $NUM_JOBS +if ($LASTEXITCODE -ne 0) { + Write-Host "[ERROR] Build failed!" -ForegroundColor Red + Pop-Location + exit 1 +} + +Write-Host "" +Write-Host "[SUCCESS] Build finished successfully!" -ForegroundColor Green + +$demosToReport = @() +if ($Demo -eq "all") { + $demosToReport = @("threadx_basic", "netx_echo", "netx_trng_console") +} else { + $demosToReport = @($Demo) +} + +foreach ($d in $demosToReport) { + $demoDir = Join-Path $BUILD_DIR "app/demos/$d" + if (Test-Path $demoDir) { + Write-Host "[$d] Output Binaries in $demoDir :" -ForegroundColor Cyan + $serverElf = Join-Path $demoDir "mimxrt1064_threadx.elf" + $clientElf = Join-Path $demoDir "mimxrt1064_client.elf" + if (Test-Path $serverElf) { + Write-Host " - Server ELF: $serverElf" + Write-Host " - Server BIN: $(Join-Path $demoDir 'mimxrt1064_threadx.bin')" + } + if (Test-Path $clientElf) { + Write-Host " - Client ELF: $clientElf" + Write-Host " - Client BIN: $(Join-Path $demoDir 'mimxrt1064_client.bin')" + } + } +} + +Pop-Location diff --git a/targets/NXP/MIMXRT1064-EVK/scripts/build.sh b/targets/NXP/MIMXRT1064-EVK/scripts/build.sh new file mode 100644 index 00000000..101ac40f --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/scripts/build.sh @@ -0,0 +1,107 @@ +#!/usr/bin/env bash +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BOARD_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" +BUILD_DIR="${BOARD_DIR}/build" +NUM_JOBS=4 + +CLEAN=0 +REBUILD=0 +DEMO="all" + +# Parse arguments +while [[ "$#" -gt 0 ]]; do + case $1 in + --clean) CLEAN=1 ;; + --rebuild) REBUILD=1 ;; + -d|--demo) DEMO="$2"; shift ;; + *) echo "Unknown parameter passed: $1"; exit 1 ;; + esac + shift +done + +echo "==========================================" +echo "NXP MIMXRT1064-EVK - Build Script (POSIX)" +echo "==========================================" +echo "Board Dir: ${BOARD_DIR}" +echo "Build Dir: ${BUILD_DIR}" +echo "Active Demo: ${DEMO}" +echo "" + +# Check for ARM GCC compiler +if ! command -v arm-none-eabi-gcc &> /dev/null && [ -z "${ARM_GCC_PATH}" ]; then + echo "[WARNING] arm-none-eabi-gcc not found on PATH and ARM_GCC_PATH not set." + echo "" +fi + +if [ "${CLEAN}" -eq 1 ] || [ "${REBUILD}" -eq 1 ]; then + echo "[INFO] Cleaning build directory..." + rm -rf "${BUILD_DIR}" + mkdir -p "${BUILD_DIR}" + echo "[OK] Build directory cleaned" + echo "" +fi + +mkdir -p "${BUILD_DIR}" +cd "${BUILD_DIR}" + +# Reconfigure if CMakeCache.txt or build.ninja is missing, or demo changed, or if forced +NEED_CONFIG=0 +if [ ! -f "CMakeCache.txt" ] || [ ! -f "build.ninja" ] || [ "${REBUILD}" -eq 1 ]; then + NEED_CONFIG=1 +else + CACHED_DEMO=$(grep "^ACTIVE_DEMO:STRING=" CMakeCache.txt 2>/dev/null | cut -d'=' -f2 | tr -d '[:space:]') + if [ "${CACHED_DEMO}" != "${DEMO}" ]; then + NEED_CONFIG=1 + fi +fi + +if [ "${NEED_CONFIG}" -eq 1 ]; then + echo "[INFO] Configuring CMake for demo: ${DEMO}..." + cmake -G Ninja \ + "-DCMAKE_BUILD_TYPE=Release" \ + "-DACTIVE_DEMO=${DEMO}" \ + .. + echo "[OK] CMake configured" + echo "" +fi + +# Run build using Ninja +echo "[INFO] Building target with Ninja (${NUM_JOBS} parallel jobs)..." +ninja -j ${NUM_JOBS} + +echo "" +echo "[SUCCESS] Build finished successfully!" + +if [ "${DEMO}" = "all" ]; then + DEMOS_TO_REPORT=("threadx_basic" "netx_echo" "netx_trng_console") +else + DEMOS_TO_REPORT=("${DEMO}") +fi + +for d in "${DEMOS_TO_REPORT[@]}"; do + DEMO_DIR="${BUILD_DIR}/app/demos/${d}" + if [ -d "${DEMO_DIR}" ]; then + echo "[${d}] Output Binaries in ${DEMO_DIR}:" + if [ -f "${DEMO_DIR}/mimxrt1064_threadx.elf" ]; then + echo " - Server ELF: ${DEMO_DIR}/mimxrt1064_threadx.elf" + echo " - Server BIN: ${DEMO_DIR}/mimxrt1064_threadx.bin" + fi + if [ -f "${DEMO_DIR}/mimxrt1064_client.elf" ]; then + echo " - Client ELF: ${DEMO_DIR}/mimxrt1064_client.elf" + echo " - Client BIN: ${DEMO_DIR}/mimxrt1064_client.bin" + fi + fi +done diff --git a/targets/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 b/targets/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 new file mode 100644 index 00000000..a52ac4f8 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.ps1 @@ -0,0 +1,228 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +$ErrorActionPreference = "Stop" +$BoardDir = Resolve-Path "$PSScriptRoot/.." +$LibDir = Join-Path $BoardDir "lib/mcux-sdk" +$DeviceDir = Join-Path $LibDir "devices/MIMXRT1064" +$DriversDir = Join-Path $LibDir "drivers" +$UtilitiesDir = Join-Path $LibDir "utilities" +$ComponentsDir = Join-Path $LibDir "components" +$BoardFilesDir = Join-Path $LibDir "board" +$CmsisIncludeDest = Join-Path $LibDir "CMSIS/Include" +$TempDir = Join-Path $BoardDir "temp_fetch" + +Write-Host "==========================================" +Write-Host "NXP i.MX RT1064 Standalone Driver Fetcher" +Write-Host "==========================================" +Write-Host "Target Directory: $LibDir" +Write-Host "" + +# Clean and create target directories +if (Test-Path $LibDir) { Remove-Item -Path $LibDir -Recurse -Force } +New-Item -ItemType Directory -Path $DeviceDir -Force | Out-Null +New-Item -ItemType Directory -Path $DriversDir -Force | Out-Null +New-Item -ItemType Directory -Path $UtilitiesDir -Force | Out-Null +New-Item -ItemType Directory -Path (Join-Path $ComponentsDir "uart") -Force | Out-Null +New-Item -ItemType Directory -Path $BoardFilesDir -Force | Out-Null +New-Item -ItemType Directory -Path $CmsisIncludeDest -Force | Out-Null +$AppStartupDir = Join-Path $BoardDir "app/startup" +New-Item -ItemType Directory -Path $AppStartupDir -Force | Out-Null + +if (Test-Path $TempDir) { Remove-Item -Path $TempDir -Recurse -Force } +New-Item -ItemType Directory -Path $TempDir -Force | Out-Null + +function Clean-Temp { + if (Test-Path $TempDir) { + Remove-Item -Path $TempDir -Recurse -Force + } +} + +function Verify-Sha256 { + param( + [string]$FilePath, + [string]$ExpectedHash + ) + $actualHash = (Get-FileHash -Path $FilePath -Algorithm SHA256).Hash.ToLower() + if ($actualHash -ne $ExpectedHash.ToLower()) { + throw "SHA256 checksum mismatch for $FilePath! Expected: $ExpectedHash, Got: $actualHash" + } +} + +try { + # 1. Download official NXP MIMXRT1064 DFP pack from NXP repository (pinned v15.1.0) + $packUrl = "https://mcuxpresso.nxp.com/cmsis_pack/repo/NXP.MIMXRT1064_DFP.15.1.0.pack" + $packSha256 = "14e02f0108beba1cfe9de6b2be7b1f874695614dcc16126c452bde1b68b509f6" + $packZip = Join-Path $TempDir "dfp.zip" + $packExtract = Join-Path $TempDir "dfp_extracted" + + Write-Host "[INFO] Downloading official NXP MIMXRT1064 Device Pack (v15.1.0)..." + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + if (Get-Command curl.exe -ErrorAction SilentlyContinue) { + & curl.exe --retry 3 --retry-delay 2 -fsSL $packUrl -o $packZip + } else { + Invoke-WebRequest -Uri $packUrl -OutFile $packZip -UseBasicParsing + } + Verify-Sha256 -FilePath $packZip -ExpectedHash $packSha256 + Write-Host "[OK] NXP Device Pack verified (SHA256: $packSha256)" + + Write-Host "[INFO] Extracting Device Pack..." + Expand-Archive -Path $packZip -DestinationPath $packExtract -Force + + # Copy device register headers & system files + $deviceFiles = @( + "MIMXRT1064.h", + "MIMXRT1064_features.h", + "fsl_device_registers.h", + "system_MIMXRT1064.c", + "system_MIMXRT1064.h" + ) + foreach ($file in $deviceFiles) { + $source = Join-Path $packExtract $file + Copy-Item -Path $source -Destination $DeviceDir -Force + } + + # Copy core peripheral drivers + $driverList = @( + "fsl_clock.c", "fsl_clock.h", + "fsl_common.c", "fsl_common.h", + "fsl_common_arm.c", "fsl_common_arm.h", + "fsl_gpio.c", "fsl_gpio.h", + "fsl_lpuart.c", "fsl_lpuart.h", + "fsl_enet.c", "fsl_enet.h", + "fsl_iomuxc.h" + ) + foreach ($file in $driverList) { + $source = Join-Path $packExtract "drivers/$file" + Copy-Item -Path $source -Destination $DriversDir -Force + } + + # Copy utilities (debug console & string formatting) + $utilFiles = @( + "utilities/debug_console_lite/fsl_debug_console.h", + "utilities/debug_console_lite/fsl_debug_console.c", + "utilities/debug_console_lite/fsl_assert.c", + "utilities/debug_console/fsl_debug_console_conf.h", + "utilities/str/fsl_str.c", + "utilities/str/fsl_str.h" + ) + foreach ($file in $utilFiles) { + $source = Join-Path $packExtract $file + Copy-Item -Path $source -Destination $UtilitiesDir -Force + } + + # Copy UART component adapter + $compUartDest = Join-Path $ComponentsDir "uart" + $compUartFiles = @( + "components/uart/fsl_adapter_uart.h", + "components/uart/fsl_adapter_lpuart.c" + ) + foreach ($file in $compUartFiles) { + $source = Join-Path $packExtract $file + Copy-Item -Path $source -Destination $compUartDest -Force + } + + # Copy XIP flexspi boot header from pack + $xipSource = Join-Path $packExtract "xip" + Copy-Item -Path "$xipSource/*" -Destination $DeviceDir -Recurse -Force + Write-Host "[OK] NXP Device, Driver, Utility, and Component files copied" + Write-Host "" + + # Helper function to download with retries and SHA256 checksum verification + function Download-WithRetry { + param( + [string]$Uri, + [string]$OutFile, + [string]$ExpectedHash = "", + [int]$MaxAttempts = 4 + ) + for ($i = 1; $i -le $MaxAttempts; $i++) { + try { + if (Get-Command curl.exe -ErrorAction SilentlyContinue) { + & curl.exe --retry 3 --retry-delay 2 -fsSL $Uri -o $OutFile + if ($LASTEXITCODE -eq 0 -and (Test-Path $OutFile) -and ((Get-Item $OutFile).Length -gt 0)) { + if ($ExpectedHash) { + Verify-Sha256 -FilePath $OutFile -ExpectedHash $ExpectedHash + } + return + } + } + Invoke-WebRequest -Uri $Uri -OutFile $OutFile -UseBasicParsing -TimeoutSec 30 + if ($ExpectedHash) { + Verify-Sha256 -FilePath $OutFile -ExpectedHash $ExpectedHash + } + return + } + catch { + if ($i -eq $MaxAttempts) { throw $_ } + Start-Sleep -Seconds 2 + } + } + } + + # 2. Download EVK-MIMXRT1064 Board Support Files (pinned to commit 2a340e10 from nxp-mcuxpresso/mcuxsdk-examples) + $mcuxExamplesCommit = "2a340e10a1105bc0af8e7176bc19148911f4cf12" + $rawBase = "https://raw.githubusercontent.com/nxp-mcuxpresso/mcuxsdk-examples/$mcuxExamplesCommit/_boards/evkmimxrt1064" + $boardFiles = @( + @{ Remote = "$rawBase/board.c"; Local = "board.c"; Hash = "f28885b9ac349a06a6b38f0376f6872a25ec131ab7d37947a0576255579cd959" }, + @{ Remote = "$rawBase/board.h"; Local = "board.h"; Hash = "9c25debd61b7fc153eeedd569155dfc8f9d1349192c6de2b431742ee6f9bb17e" }, + @{ Remote = "$rawBase/project_template/clock_config.c"; Local = "clock_config.c"; Hash = "ca20b253229ef02e74a9d0041173c5e1fc0c5c3df048a53be8b44e1e4218ef03" }, + @{ Remote = "$rawBase/project_template/clock_config.h"; Local = "clock_config.h"; Hash = "52036470ef08b16daf7ed1382a8c3c0bcc123336afc2b07df807e793365b3e80" }, + @{ Remote = "$rawBase/project_template/pin_mux.c"; Local = "pin_mux.c"; Hash = "4bf784e2685555e6297adccb78a27de5754e5320911bc503b5ab563577599c39" }, + @{ Remote = "$rawBase/project_template/pin_mux.h"; Local = "pin_mux.h"; Hash = "f696267090a271e12d9c9f3ccb0e2dfb721025ddd3728b32ab33a9fb79acbc70" }, + @{ Remote = "$rawBase/dcd.c"; Local = "dcd.c"; Hash = "798cd3fffea9b3b1917d6750d40735b6bc890e770f8d8b9167238220b0fae21f" }, + @{ Remote = "$rawBase/dcd.h"; Local = "dcd.h"; Hash = "3a5268f0ccdc02aa6df55b3fca87171df35161cca0c3e15971ac082cdefde7a3" }, + @{ Remote = "$rawBase/xip/evkmimxrt1064_flexspi_nor_config.c"; Local = "evkmimxrt1064_flexspi_nor_config.c"; Hash = "f6fa3d1e3a09c1a4a9d3fc44aed23513e12341e6db96aa3427c923e6b41c6e46" }, + @{ Remote = "$rawBase/xip/evkmimxrt1064_flexspi_nor_config.h"; Local = "evkmimxrt1064_flexspi_nor_config.h"; Hash = "4073f8c6e09fccc879dcedb6fe79f679bc8c9840bb90a7f527279a9a021813d3" } + ) + + Write-Host "[INFO] Downloading EVK-MIMXRT1064 board support files (pinned: $($mcuxExamplesCommit.Substring(0,8)))..." + foreach ($item in $boardFiles) { + $dest = Join-Path $BoardFilesDir $item.Local + Download-WithRetry -Uri $item.Remote -OutFile $dest -ExpectedHash $item.Hash + } + + Write-Host "[OK] Board support files verified & downloaded" + Write-Host "" + + # 3. Fetch CMSIS Core headers (pinned ARM.CMSIS 5.9.0 release pack from ARM-software/CMSIS_5) + $cmsisVersion = "5.9.0" + $cmsisPackUrl = "https://github.com/ARM-software/CMSIS_5/releases/download/$cmsisVersion/ARM.CMSIS.$cmsisVersion.pack" + $cmsisPackSha256 = "14b366f2821ee5d32f0d3bf48ef9657ca45347261d0531263580848e9d36f8f4" + $cmsisPackZip = Join-Path $TempDir "cmsis.zip" + $cmsisExtract = Join-Path $TempDir "cmsis_extracted" + + Write-Host "[INFO] Downloading official ARM CMSIS Pack (v$cmsisVersion)..." + Download-WithRetry -Uri $cmsisPackUrl -OutFile $cmsisPackZip -ExpectedHash $cmsisPackSha256 + Write-Host "[OK] ARM CMSIS Pack verified (SHA256: $cmsisPackSha256)" + + Write-Host "[INFO] Extracting CMSIS Core headers..." + New-Item -ItemType Directory -Path $cmsisExtract -Force | Out-Null + if (Get-Command tar.exe -ErrorAction SilentlyContinue) { + & tar.exe -xf $cmsisPackZip -C $cmsisExtract "CMSIS/Core/Include" + } else { + Expand-Archive -Path $cmsisPackZip -DestinationPath $cmsisExtract -Force + } + $cmsisSource = Join-Path $cmsisExtract "CMSIS/Core/Include" + Copy-Item -Path "$cmsisSource/*" -Destination $CmsisIncludeDest -Recurse -Force + Write-Host "[OK] CMSIS Core headers copied" + Write-Host "" + + Write-Host "[INFO] Note: NetX Duo Ethernet driver and KSZ8081 PHY driver are vendored in lib/netx_driver and lib/phyksz8081." + Write-Host "" + + Write-Host "==========================================" + Write-Host "[SUCCESS] NXP i.MX RT1064 SDK dependencies successfully fetched & verified!" + Write-Host "==========================================" +} +finally { + Clean-Temp +} diff --git a/targets/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh b/targets/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh new file mode 100644 index 00000000..b27b6744 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh @@ -0,0 +1,160 @@ +#!/usr/bin/env bash +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BOARD_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" + +LIB_DIR="${BOARD_DIR}/lib/mcux-sdk" +DEVICE_DIR="${LIB_DIR}/devices/MIMXRT1064" +DRIVERS_DIR="${LIB_DIR}/drivers" +UTILITIES_DIR="${LIB_DIR}/utilities" +COMPONENTS_DIR="${LIB_DIR}/components" +BOARD_FILES_DIR="${LIB_DIR}/board" +CMSIS_INCLUDE_DEST="${LIB_DIR}/CMSIS/Include" +APP_STARTUP_DIR="${BOARD_DIR}/app/startup" +TEMP_DIR="${BOARD_DIR}/temp_fetch" + +echo "==========================================" +echo "NXP i.MX RT1064 Standalone Driver Fetcher (POSIX)" +echo "==========================================" +echo "Target Directory: ${LIB_DIR}" +echo "" + +# Helper to verify file integrity via sha256sum +verify_sha256() { + local file="$1" + local expected_sha="$2" + echo "${expected_sha} ${file}" | sha256sum --check --strict >/dev/null 2>&1 || { + echo "[ERROR] SHA256 checksum mismatch for ${file}!" >&2 + echo " Expected: ${expected_sha}" >&2 + echo " Actual: $(sha256sum "${file}" | awk '{print $1}')" >&2 + exit 1 + } +} + +# Helper to download and verify +fetch_and_verify() { + local url="$1" + local dest="$2" + local expected_sha="$3" + curl --retry 3 --retry-delay 2 -fsSL "${url}" -o "${dest}" + verify_sha256 "${dest}" "${expected_sha}" +} + +# Clean and recreate directories +rm -rf "${LIB_DIR}" +mkdir -p "${DEVICE_DIR}" +mkdir -p "${DRIVERS_DIR}" +mkdir -p "${UTILITIES_DIR}" +mkdir -p "${COMPONENTS_DIR}/uart" +mkdir -p "${BOARD_FILES_DIR}" +mkdir -p "${CMSIS_INCLUDE_DEST}" +mkdir -p "${APP_STARTUP_DIR}" + +rm -rf "${TEMP_DIR}" +mkdir -p "${TEMP_DIR}" + +clean_temp() { + if [ -d "${TEMP_DIR}" ]; then + rm -rf "${TEMP_DIR}" + fi +} +trap clean_temp EXIT + +# 1. Download official NXP MIMXRT1064 DFP pack from NXP repository (pinned v15.1.0) +PACK_URL="https://mcuxpresso.nxp.com/cmsis_pack/repo/NXP.MIMXRT1064_DFP.15.1.0.pack" +PACK_SHA256="14e02f0108beba1cfe9de6b2be7b1f874695614dcc16126c452bde1b68b509f6" +PACK_ZIP="${TEMP_DIR}/dfp.zip" +PACK_EXTRACT="${TEMP_DIR}/dfp_extracted" + +echo "[INFO] Downloading official NXP MIMXRT1064 Device Pack (v15.1.0)..." +fetch_and_verify "${PACK_URL}" "${PACK_ZIP}" "${PACK_SHA256}" +echo "[OK] NXP Device Pack verified (SHA256: ${PACK_SHA256})" + +echo "[INFO] Extracting Device Pack..." +mkdir -p "${PACK_EXTRACT}" +unzip -q "${PACK_ZIP}" -d "${PACK_EXTRACT}" + +# Copy device register headers & system files +for file in MIMXRT1064.h MIMXRT1064_features.h fsl_device_registers.h system_MIMXRT1064.c system_MIMXRT1064.h; do + cp "${PACK_EXTRACT}/${file}" "${DEVICE_DIR}/" +done + +# Copy core peripheral drivers +for file in fsl_clock.c fsl_clock.h fsl_common.c fsl_common.h fsl_common_arm.c fsl_common_arm.h fsl_gpio.c fsl_gpio.h fsl_lpuart.c fsl_lpuart.h fsl_enet.c fsl_enet.h fsl_iomuxc.h; do + cp "${PACK_EXTRACT}/drivers/${file}" "${DRIVERS_DIR}/" +done + +# Copy utilities (debug console & string formatting) +for file in utilities/debug_console_lite/fsl_debug_console.h \ + utilities/debug_console_lite/fsl_debug_console.c \ + utilities/debug_console_lite/fsl_assert.c \ + utilities/debug_console/fsl_debug_console_conf.h \ + utilities/str/fsl_str.c \ + utilities/str/fsl_str.h; do + cp "${PACK_EXTRACT}/${file}" "${UTILITIES_DIR}/" +done + +# Copy UART component adapter +for file in components/uart/fsl_adapter_uart.h components/uart/fsl_adapter_lpuart.c; do + cp "${PACK_EXTRACT}/${file}" "${COMPONENTS_DIR}/uart/" +done + +# Copy XIP flexspi boot headers +cp -r "${PACK_EXTRACT}/xip/"* "${DEVICE_DIR}/" +echo "[OK] NXP Device, Driver, Utility, and Component files copied" +echo "" + +# 2. Download EVK-MIMXRT1064 Board Support Files (pinned to commit 2a340e10 from nxp-mcuxpresso/mcuxsdk-examples) +MCUX_EXAMPLES_COMMIT="2a340e10a1105bc0af8e7176bc19148911f4cf12" +RAW_BASE="https://raw.githubusercontent.com/nxp-mcuxpresso/mcuxsdk-examples/${MCUX_EXAMPLES_COMMIT}/_boards/evkmimxrt1064" +echo "[INFO] Downloading EVK-MIMXRT1064 board support files (pinned: ${MCUX_EXAMPLES_COMMIT:0:8})..." + +fetch_and_verify "${RAW_BASE}/board.c" "${BOARD_FILES_DIR}/board.c" "f28885b9ac349a06a6b38f0376f6872a25ec131ab7d37947a0576255579cd959" +fetch_and_verify "${RAW_BASE}/board.h" "${BOARD_FILES_DIR}/board.h" "9c25debd61b7fc153eeedd569155dfc8f9d1349192c6de2b431742ee6f9bb17e" +fetch_and_verify "${RAW_BASE}/project_template/clock_config.c" "${BOARD_FILES_DIR}/clock_config.c" "ca20b253229ef02e74a9d0041173c5e1fc0c5c3df048a53be8b44e1e4218ef03" +fetch_and_verify "${RAW_BASE}/project_template/clock_config.h" "${BOARD_FILES_DIR}/clock_config.h" "52036470ef08b16daf7ed1382a8c3c0bcc123336afc2b07df807e793365b3e80" +fetch_and_verify "${RAW_BASE}/project_template/pin_mux.c" "${BOARD_FILES_DIR}/pin_mux.c" "4bf784e2685555e6297adccb78a27de5754e5320911bc503b5ab563577599c39" +fetch_and_verify "${RAW_BASE}/project_template/pin_mux.h" "${BOARD_FILES_DIR}/pin_mux.h" "f696267090a271e12d9c9f3ccb0e2dfb721025ddd3728b32ab33a9fb79acbc70" +fetch_and_verify "${RAW_BASE}/dcd.c" "${BOARD_FILES_DIR}/dcd.c" "798cd3fffea9b3b1917d6750d40735b6bc890e770f8d8b9167238220b0fae21f" +fetch_and_verify "${RAW_BASE}/dcd.h" "${BOARD_FILES_DIR}/dcd.h" "3a5268f0ccdc02aa6df55b3fca87171df35161cca0c3e15971ac082cdefde7a3" +fetch_and_verify "${RAW_BASE}/xip/evkmimxrt1064_flexspi_nor_config.c" "${BOARD_FILES_DIR}/evkmimxrt1064_flexspi_nor_config.c" "f6fa3d1e3a09c1a4a9d3fc44aed23513e12341e6db96aa3427c923e6b41c6e46" +fetch_and_verify "${RAW_BASE}/xip/evkmimxrt1064_flexspi_nor_config.h" "${BOARD_FILES_DIR}/evkmimxrt1064_flexspi_nor_config.h" "4073f8c6e09fccc879dcedb6fe79f679bc8c9840bb90a7f527279a9a021813d3" + +echo "[OK] Board support files verified & downloaded" +echo "" + +# 3. Fetch CMSIS Core headers (pinned ARM.CMSIS 5.9.0 release pack from ARM-software/CMSIS_5) +CMSIS_VERSION="5.9.0" +CMSIS_PACK_URL="https://github.com/ARM-software/CMSIS_5/releases/download/${CMSIS_VERSION}/ARM.CMSIS.${CMSIS_VERSION}.pack" +CMSIS_PACK_SHA256="14b366f2821ee5d32f0d3bf48ef9657ca45347261d0531263580848e9d36f8f4" +CMSIS_PACK_ZIP="${TEMP_DIR}/cmsis.zip" +CMSIS_EXTRACT="${TEMP_DIR}/cmsis_extracted" + +echo "[INFO] Downloading official ARM CMSIS Pack (v${CMSIS_VERSION})..." +fetch_and_verify "${CMSIS_PACK_URL}" "${CMSIS_PACK_ZIP}" "${CMSIS_PACK_SHA256}" +echo "[OK] ARM CMSIS Pack verified (SHA256: ${CMSIS_PACK_SHA256})" + +echo "[INFO] Extracting CMSIS Core headers..." +mkdir -p "${CMSIS_EXTRACT}" +unzip -q "${CMSIS_PACK_ZIP}" "CMSIS/Core/Include/*" -d "${CMSIS_EXTRACT}" +cp -r "${CMSIS_EXTRACT}/CMSIS/Core/Include/"* "${CMSIS_INCLUDE_DEST}/" +echo "[OK] CMSIS Core headers copied" +echo "" + +echo "[INFO] Note: NetX Duo Ethernet driver and KSZ8081 PHY driver are vendored in lib/netx_driver and lib/phyksz8081." +echo "" +echo "==========================================" +echo "[SUCCESS] NXP i.MX RT1064 SDK dependencies successfully fetched & verified!" +echo "==========================================" diff --git a/targets/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 b/targets/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 new file mode 100644 index 00000000..716f56db --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/scripts/simulate.ps1 @@ -0,0 +1,133 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +param( + [Alias("d")] + [string]$Demo, + [string]$Resc, + [Nullable[int]]$Seed +) + +$BoardDir = Resolve-Path "$PSScriptRoot/.." +$BuildDir = Join-Path $BoardDir "build" + +# 1. Resolve which demo to simulate +$selectedDemo = $Demo +if (-not $selectedDemo) { + # Check CMakeCache.txt for ACTIVE_DEMO + $cacheFile = Join-Path $BuildDir "CMakeCache.txt" + if (Test-Path $cacheFile) { + $match = Select-String -Path $cacheFile -Pattern "^ACTIVE_DEMO:STRING=(.*)$" + if ($match) { + $cached = $match.Matches.Groups[1].Value.Trim() + if ($cached -and $cached -ne "all") { + $selectedDemo = $cached + } + } + } +} + +# If still undetermined, check existing built demo directories or default to threadx_basic +if (-not $selectedDemo) { + if (Test-Path (Join-Path $BuildDir "app/demos/threadx_basic/mimxrt1064_threadx.elf")) { + $selectedDemo = "threadx_basic" + } elseif (Test-Path (Join-Path $BuildDir "app/demos/netx_echo/mimxrt1064_threadx.elf")) { + $selectedDemo = "netx_echo" + } elseif (Test-Path (Join-Path $BuildDir "app/demos/netx_trng_console/mimxrt1064_threadx.elf")) { + $selectedDemo = "netx_trng_console" + } else { + $selectedDemo = "threadx_basic" + } +} + +# 2. Locate firmware binaries for the selected demo +$serverElfRel = "build/app/demos/$selectedDemo/mimxrt1064_threadx.elf" +$clientElfRel = "build/app/demos/$selectedDemo/mimxrt1064_client.elf" + +# Fallback to root build dir if per-demo subfolder does not exist +if (-not (Test-Path (Join-Path $BoardDir $serverElfRel)) -and (Test-Path (Join-Path $BoardDir "build/mimxrt1064_threadx.elf"))) { + $serverElfRel = "build/mimxrt1064_threadx.elf" + $clientElfRel = "build/mimxrt1064_client.elf" +} + +$ServerElf = Join-Path $BoardDir $serverElfRel +$ClientElf = Join-Path $BoardDir $clientElfRel + +if (-not (Test-Path $ServerElf)) { + Write-Host "[ERROR] Firmware binary for demo '$selectedDemo' not found at:" -ForegroundColor Red + Write-Host " $ServerElf" -ForegroundColor Red + Write-Host "" + Write-Host "Please build the demo first using:" -ForegroundColor Yellow + Write-Host " .\scripts\build.ps1 -Demo $selectedDemo" -ForegroundColor Yellow + exit 1 +} + +# 3. Select Renode script and verification mode +if ($Resc) { + $RescRelPath = $Resc + $Mode = "Custom Script ($Resc)" +} elseif ($selectedDemo -eq "netx_trng_console") { + $RescRelPath = "renode/mimxrt1064-trng-console.resc" + $Mode = "Hardware TRNG Console (Server: 192.168.0.100, Client: 192.168.0.101)" +} elseif ($selectedDemo -eq "netx_echo") { + $RescRelPath = "renode/mimxrt1064-network-multinode.resc" + $Mode = "Multi-Node Network Echo (Server: 192.168.0.100, Client: 192.168.0.101)" +} else { + $RescRelPath = "renode/mimxrt1064-evk.resc" + $Mode = "ThreadX Core Basic Demo (Single-Node)" +} +$RescFullPath = Join-Path $BoardDir $RescRelPath + +# 4. Find Renode executable +$RenodeExe = (Get-Command renode -ErrorAction SilentlyContinue).Source +if (-not $RenodeExe -and (Test-Path "C:\Program Files\Renode\renode.exe")) { + $RenodeExe = "C:\Program Files\Renode\renode.exe" +} + +if (-not $RenodeExe) { + Write-Error "Renode was not found in PATH or at 'C:\Program Files\Renode\renode.exe'." + exit 1 +} + +Write-Host "==========================================" +Write-Host "Starting Renode Simulation" +Write-Host "==========================================" +Write-Host "Renode: $RenodeExe" +Write-Host "Demo: $selectedDemo" +Write-Host "Mode: $Mode" +Write-Host "Script: $RescFullPath" +if ($null -ne $Seed) { + Write-Host "Seed: $Seed (Deterministic)" +} +Write-Host "Server ELF: $ServerElf" +if (Test-Path $ClientElf) { + Write-Host "Client ELF: $ClientElf" +} +Write-Host "" +Write-Host "Opening Renode Monitor and LPUART1 terminal analyzer(s)..." +Write-Host "To exit Renode, type 'quit' in the Renode Monitor or close the window." +Write-Host "==========================================" + +Set-Location $BoardDir + +# 5. Build Renode execution command passing clean relative binary paths +$renodeCmd = "" +if ($null -ne $Seed) { + $renodeCmd += "emulation SetSeed $Seed; " +} +$renodeCmd += "`$bin = @`"$serverElfRel`"; `$bin_server = @`"$serverElfRel`"; " +if (Test-Path $ClientElf) { + $renodeCmd += "`$bin_client = @`"$clientElfRel`"; " +} +$renodeCmd += "include @`"$RescRelPath`"" + +# Pass relative script path with quotes to avoid tokenization errors when workspace contains spaces +& $RenodeExe -e "$renodeCmd" diff --git a/targets/NXP/MIMXRT1064-EVK/scripts/simulate.sh b/targets/NXP/MIMXRT1064-EVK/scripts/simulate.sh new file mode 100644 index 00000000..d3d3cdf1 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/scripts/simulate.sh @@ -0,0 +1,145 @@ +#!/usr/bin/env bash +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BOARD_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" +BUILD_DIR="${BOARD_DIR}/build" + +DEMO_ARG="" +RESC_ARG="" +SEED_ARG="" + +while [[ $# -gt 0 ]]; do + case $1 in + -d|--demo) + DEMO_ARG="$2" + shift 2 + ;; + -s|--seed) + SEED_ARG="$2" + shift 2 + ;; + -r|--resc) + RESC_ARG="$2" + shift 2 + ;; + *) + if [ -z "${RESC_ARG}" ] && [[ "$1" == *.resc ]]; then + RESC_ARG="$1" + else + echo "Unknown parameter: $1" + exit 1 + fi + shift + ;; + esac +done + +# 1. Resolve which demo to simulate +SELECTED_DEMO="${DEMO_ARG}" +if [ -z "${SELECTED_DEMO}" ] && [ -f "${BUILD_DIR}/CMakeCache.txt" ]; then + CACHED_DEMO=$(grep -E "^ACTIVE_DEMO:STRING=" "${BUILD_DIR}/CMakeCache.txt" | cut -d'=' -f2 | tr -d ' \r\n') + if [ -n "${CACHED_DEMO}" ] && [ "${CACHED_DEMO}" != "all" ]; then + SELECTED_DEMO="${CACHED_DEMO}" + fi +fi + +if [ -z "${SELECTED_DEMO}" ]; then + if [ -f "${BUILD_DIR}/app/demos/threadx_basic/mimxrt1064_threadx.elf" ]; then + SELECTED_DEMO="threadx_basic" + elif [ -f "${BUILD_DIR}/app/demos/netx_echo/mimxrt1064_threadx.elf" ]; then + SELECTED_DEMO="netx_echo" + elif [ -f "${BUILD_DIR}/app/demos/netx_trng_console/mimxrt1064_threadx.elf" ]; then + SELECTED_DEMO="netx_trng_console" + else + SELECTED_DEMO="threadx_basic" + fi +fi + +# 2. Locate firmware binaries for the selected demo +DEMO_DIR="${BUILD_DIR}/app/demos/${SELECTED_DEMO}" +SERVER_ELF="${DEMO_DIR}/mimxrt1064_threadx.elf" +CLIENT_ELF="${DEMO_DIR}/mimxrt1064_client.elf" + +# Fallback to root build dir if per-demo subfolder does not exist +if [ ! -f "${SERVER_ELF}" ] && [ -f "${BUILD_DIR}/mimxrt1064_threadx.elf" ]; then + SERVER_ELF="${BUILD_DIR}/mimxrt1064_threadx.elf" + CLIENT_ELF="${BUILD_DIR}/mimxrt1064_client.elf" +fi + +if [ ! -f "${SERVER_ELF}" ]; then + echo "[ERROR] Firmware binary for demo '${SELECTED_DEMO}' not found at:" + echo " ${SERVER_ELF}" + echo "" + echo "Please build the demo first using:" + echo " ./scripts/build.sh -d ${SELECTED_DEMO}" + exit 1 +fi + +# 3. Select Renode script and verification mode +if [ -n "${RESC_ARG}" ]; then + RESC_REL_PATH="${RESC_ARG}" + MODE="Custom Script (${RESC_ARG})" +elif [ "$SELECTED_DEMO" = "netx_trng_console" ]; then + RESC_REL_PATH="renode/mimxrt1064-trng-console.resc" + MODE="Hardware TRNG Console (Server: 192.168.0.100, Client: 192.168.0.101)" +elif [ "$SELECTED_DEMO" = "netx_echo" ]; then + RESC_REL_PATH="renode/mimxrt1064-network-multinode.resc" + MODE="Multi-Node Network Echo (Server: 192.168.0.100, Client: 192.168.0.101)" +else + RESC_REL_PATH="renode/mimxrt1064-evk.resc" + MODE="ThreadX Core Basic Demo (Single-Node)" +fi + +# 4. Find Renode executable +RENODE_CMD="renode" +if ! command -v renode &> /dev/null; then + if [ -f "/opt/renode/renode" ]; then + RENODE_CMD="/opt/renode/renode" + else + echo "[ERROR] Renode was not found in PATH." + exit 1 + fi +fi + +echo "==========================================" +echo "Starting Renode Simulation" +echo "==========================================" +echo "Renode: ${RENODE_CMD}" +echo "Demo: ${SELECTED_DEMO}" +echo "Mode: ${MODE}" +echo "Script: ${BOARD_DIR}/${RESC_REL_PATH}" +if [ -n "${SEED_ARG}" ]; then + echo "Seed: ${SEED_ARG} (Deterministic)" +fi +echo "Server ELF: ${SERVER_ELF}" +if [ -f "${CLIENT_ELF}" ]; then + echo "Client ELF: ${CLIENT_ELF}" +fi +echo "" + +cd "${BOARD_DIR}" + +# 5. Build Renode execution command passing explicit binary paths +RENODE_EXEC_CMD="" +if [ -n "${SEED_ARG}" ]; then + RENODE_EXEC_CMD="emulation SetSeed ${SEED_ARG}; " +fi +RENODE_EXEC_CMD="${RENODE_EXEC_CMD}\$bin = @\"${SERVER_ELF}\"; \$bin_server = @\"${SERVER_ELF}\"; " +if [ -f "${CLIENT_ELF}" ]; then + RENODE_EXEC_CMD="${RENODE_EXEC_CMD}\$bin_client = @\"${CLIENT_ELF}\"; " +fi +RENODE_EXEC_CMD="${RENODE_EXEC_CMD}include @\"${RESC_REL_PATH}\"" + +"${RENODE_CMD}" -e "${RENODE_EXEC_CMD}" diff --git a/targets/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 b/targets/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 new file mode 100644 index 00000000..64dae41a --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/scripts/test_headless.ps1 @@ -0,0 +1,35 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +param( + [string]$Demo = "threadx_basic", + [int]$TimeoutSeconds = 300, + [Nullable[int]]$Seed +) + +$scriptPath = Join-Path $PSScriptRoot "test_renode.py" + +$pythonArgs = @($scriptPath, "--demo", $Demo, "--timeout", $TimeoutSeconds) +if ($null -ne $Seed) { + $pythonArgs += @("--seed", $Seed) +} + +$pythonExe = (Get-Command python3 -ErrorAction SilentlyContinue).Source +if (-not $pythonExe) { + $pythonExe = (Get-Command python -ErrorAction SilentlyContinue).Source +} +if (-not $pythonExe) { + Write-Error "[FAIL] Python was not found in PATH." + exit 1 +} + +& $pythonExe @pythonArgs +exit $LASTEXITCODE diff --git a/targets/NXP/MIMXRT1064-EVK/scripts/test_headless.sh b/targets/NXP/MIMXRT1064-EVK/scripts/test_headless.sh new file mode 100644 index 00000000..8222ce83 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/scripts/test_headless.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +PYTHON_BIN="" +if command -v python3 &>/dev/null && python3 --version &>/dev/null; then + PYTHON_BIN="python3" +elif command -v python &>/dev/null && python --version &>/dev/null; then + PYTHON_BIN="python" +elif command -v py &>/dev/null && py -3 --version &>/dev/null; then + PYTHON_BIN="py -3" +else + echo "[FAIL] Python was not found in PATH." + exit 1 +fi + +exec ${PYTHON_BIN} "${SCRIPT_DIR}/test_renode.py" "$@" diff --git a/targets/NXP/MIMXRT1064-EVK/scripts/test_renode.py b/targets/NXP/MIMXRT1064-EVK/scripts/test_renode.py new file mode 100644 index 00000000..befabdd0 --- /dev/null +++ b/targets/NXP/MIMXRT1064-EVK/scripts/test_renode.py @@ -0,0 +1,243 @@ +#!/usr/bin/env python3 +# +# 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/licenses/MIT. +# +# SPDX-License-Identifier: MIT +# +# Contributors: +# Ali Eissa - 2026 version. +# Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) + +""" +Headless Renode Verification Test for NXP i.MX RT1064-EVK Demos. + +Runs deterministic virtual-time emulation in Antmicro Renode and asserts on +the streamed LPUART1 console output via showAnalyzer. +""" + +import argparse +import os +import queue +import shutil +import subprocess +import sys +import threading +import time + +DEMO_CONFIGS = { + "threadx_basic": { + "description": "ThreadX Core Basic Demo (Task Scheduling & GPIO LED)", + "resc": "mimxrt1064-headless-single.resc", + "multinode": False, + "marker": "Executing periodic task", + }, + "netx_echo": { + "description": "NetX Duo Multi-Node Echo Demo (ICMP, UDP, TCP)", + "resc": "mimxrt1064-headless-multinode.resc", + "multinode": True, + "marker": "[VERIFICATION SUCCESS] ALL NETWORK TESTS PASSED!", + }, + "netx_trng_console": { + "description": "NetX Duo Multi-Node Hardware TRNG & Console Demo", + "resc": "mimxrt1064-headless-multinode.resc", + "multinode": True, + "marker": "[VERIFICATION SUCCESS] ALL TRNG & CONSOLE TESTS PASSED!", + }, +} + + +def find_renode(): + renode_bin = shutil.which("renode") + if renode_bin: + return renode_bin + + candidates = [ + r"C:\Program Files\Renode\renode.exe", + os.path.expanduser(r"~\AppData\Local\Programs\Renode\renode.exe"), + os.path.expanduser(r"~/renode/renode"), + "/opt/renode/renode", + "/usr/bin/renode", + ] + for path in candidates: + if os.path.isfile(path): + return path + + return "renode" + + +def reader_thread_fn(pipe, q): + try: + for line in iter(pipe.readline, ""): + q.put(line) + except Exception: + pass + finally: + pipe.close() + + +def run_test(demo_name, seed=None, timeout_seconds=300): + if demo_name not in DEMO_CONFIGS: + print(f"[FAIL] Unknown demo: {demo_name}. Choices: {list(DEMO_CONFIGS.keys())}") + return 1 + + config = DEMO_CONFIGS[demo_name] + renode = find_renode() + + script_dir = os.path.dirname(os.path.abspath(__file__)) + board_dir = os.path.dirname(script_dir) + build_dir = os.path.join(board_dir, "build") + resc_rel = f"renode/{config['resc']}" + + # Check binary existence + demo_dir = os.path.join(build_dir, "app", "demos", demo_name) + server_elf = os.path.join(demo_dir, "mimxrt1064_threadx.elf") + if not os.path.isfile(server_elf): + fallback = os.path.join(build_dir, "mimxrt1064_threadx.elf") + if os.path.isfile(fallback): + server_elf = fallback + else: + print(f"[FAIL] Server ELF binary not found: {server_elf}") + return 1 + + if config["multinode"]: + client_elf = os.path.join(demo_dir, "mimxrt1064_client.elf") + if not os.path.isfile(client_elf): + fallback_c = os.path.join(build_dir, "mimxrt1064_client.elf") + if os.path.isfile(fallback_c): + client_elf = fallback_c + else: + print(f"[FAIL] Client ELF binary not found: {client_elf}") + return 1 + + server_elf_rel = os.path.relpath(server_elf, board_dir).replace("\\", "/") + cmd_parts = [] + if seed is not None: + cmd_parts.append(f"emulation SetSeed {seed}") + + cmd_parts.append("$platform = @renode/mimxrt1064-evk.repl") + + if config["multinode"]: + client_elf_rel = os.path.relpath(client_elf, board_dir).replace("\\", "/") + cmd_parts.append(f"$bin_server = @{server_elf_rel}") + cmd_parts.append(f"$bin_client = @{client_elf_rel}") + else: + cmd_parts.append(f"$bin = @{server_elf_rel}") + + cmd_parts.append(f"include @{resc_rel}") + renode_script_cmd = "; ".join(cmd_parts) + + cmd = [ + renode, + "--plain", + "--disable-gui", + "--port", "-1", + "-e", renode_script_cmd + ] + + print("==========================================") + print("Renode Headless CI Automated Test Runner") + print("==========================================") + print(f"Active Demo: {demo_name}") + print(f"Test Suite: {config['description']}") + print(f"Script: {config['resc']}") + if seed is not None: + print(f"Seed: {seed} (Deterministic)") + print(f"Timeout: {timeout_seconds}s") + print(f"Engine: {renode}") + print("") + print("[INFO] Launching Renode in headless mode...") + print("") + + proc = subprocess.Popen( + cmd, + cwd=board_dir, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + bufsize=1, + ) + + os.makedirs(build_dir, exist_ok=True) + log_file_path = os.path.join(build_dir, f"renode_test_{demo_name}.log") + + output_q = queue.Queue() + reader_t = threading.Thread(target=reader_thread_fn, args=(proc.stdout, output_q), daemon=True) + reader_t.start() + + found_marker = False + start_time = time.time() + + with open(log_file_path, "w", encoding="utf-8") as log_f: + try: + while time.time() - start_time < timeout_seconds: + try: + line = output_q.get(timeout=0.1) + sys.stdout.write(line) + sys.stdout.flush() + log_f.write(line) + log_f.flush() + + if config["marker"] in line: + found_marker = True + break + except queue.Empty: + if proc.poll() is not None: + # Drain remaining output + while not output_q.empty(): + line = output_q.get_nowait() + sys.stdout.write(line) + sys.stdout.flush() + log_f.write(line) + log_f.flush() + if config["marker"] in line: + found_marker = True + break + finally: + try: + proc.terminate() + proc.wait(timeout=3) + except Exception: + try: + proc.kill() + except Exception: + pass + + print("") + print("==========================================") + if found_marker: + print(f"[PASS] CI Automated Verification Succeeded for '{demo_name}'!") + print("==========================================") + return 0 + else: + print(f"[FAIL] CI Automated Verification Failed or Timed Out for '{demo_name}'!") + print(f" Expected assertion marker: '{config['marker']}'") + print("==========================================") + return 1 + + +def main(): + parser = argparse.ArgumentParser(description="NXP MIMXRT1064-EVK Headless Renode Test Runner") + parser.add_argument("-d", "--demo", default="threadx_basic", + choices=["threadx_basic", "netx_echo", "netx_trng_console"], + help="Demo application to verify") + parser.add_argument("-s", "--seed", type=int, default=None, + help="Deterministic simulation seed") + parser.add_argument("-t", "--timeout", type=int, default=300, + help="Timeout in seconds (default: 300)") + + args = parser.parse_args() + seed = args.seed + if args.demo == "netx_trng_console" and seed is None: + seed = 12345 + + ret = run_test(args.demo, seed=seed, timeout_seconds=args.timeout) + sys.exit(ret) + + +if __name__ == "__main__": + main() From 0c9f73bac97e77582301c386d3c2a83fb3054404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 16 Sep 2026 22:05:34 -0400 Subject: [PATCH 16/20] Normalized the AI disclosure in the MIMXRT1064-EVK target (#71) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The NXP target and #69 were in flight at the same time, so the target landed carrying the older per-edit disclosure that #69 replaced everywhere else. Eleven files named the product and model inside the header's Contributors block, and nine carried no disclosure at all. All twenty now carry the same fixed line every other file in the repository uses, written with the comment character already in the file. The Contributors blocks are untouched: only the AI disclosure moves, and precise attribution stays on the Assisted-by trailer where it is dated and attached to its diff. Six vendored files are deliberately excluded. startup_mimxrt1064.S, the two KSZ8081 PHY sources and the three NetX driver sources carry only their upstream NXP or Microsoft copyright, with no Eclipse ThreadX line added, so they hold no AI-generated work to disclose. tx_initialize_low_level.S and tx_user.h do carry that line and are included. Comment-only, 20 files: every removed line was a disclosure line and every added line is the fixed text, with no file left holding zero or more than one. The target builds clean with Arm GCC 14.3.Rel1. Assisted-by: Claude Code (Opus 5) Signed-off-by: Frédéric Desbiens --- targets/NXP/MIMXRT1064-EVK/app/MIMXRT1062.h | 2 ++ targets/NXP/MIMXRT1064-EVK/app/ansi_colors.h | 2 ++ targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/client_main.c | 2 ++ targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/main.c | 2 ++ .../MIMXRT1064-EVK/app/demos/netx_trng_console/client_main.c | 3 ++- targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/main.c | 3 ++- targets/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/main.c | 2 ++ .../NXP/MIMXRT1064-EVK/app/startup/tx_initialize_low_level.S | 2 ++ targets/NXP/MIMXRT1064-EVK/app/syscalls.c | 2 ++ targets/NXP/MIMXRT1064-EVK/app/sysmem.c | 3 ++- targets/NXP/MIMXRT1064-EVK/app/trng.c | 3 ++- targets/NXP/MIMXRT1064-EVK/app/trng.h | 3 ++- targets/NXP/MIMXRT1064-EVK/lib/bsp/include/board_config.h | 3 ++- targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_board.c | 3 ++- targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_console.c | 3 ++- targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_led.c | 3 ++- targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_memory.c | 3 ++- targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_selftest.c | 3 ++- targets/NXP/MIMXRT1064-EVK/lib/netxduo/nx_user.h | 2 ++ targets/NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h | 2 ++ 20 files changed, 40 insertions(+), 11 deletions(-) diff --git a/targets/NXP/MIMXRT1064-EVK/app/MIMXRT1062.h b/targets/NXP/MIMXRT1064-EVK/app/MIMXRT1062.h index 344898f4..e4e56140 100644 --- a/targets/NXP/MIMXRT1064-EVK/app/MIMXRT1062.h +++ b/targets/NXP/MIMXRT1064-EVK/app/MIMXRT1062.h @@ -11,6 +11,8 @@ * Ali Eissa - 2026 version. */ +// Portions of this file were generated with AI assistance. + /* * Compatibility header: redirects MIMXRT1062.h from stock NetX Duo driver * to MIMXRT1064 device registers without modifying vendor source files. diff --git a/targets/NXP/MIMXRT1064-EVK/app/ansi_colors.h b/targets/NXP/MIMXRT1064-EVK/app/ansi_colors.h index 5b448d0c..4c2dc6a7 100644 --- a/targets/NXP/MIMXRT1064-EVK/app/ansi_colors.h +++ b/targets/NXP/MIMXRT1064-EVK/app/ansi_colors.h @@ -11,6 +11,8 @@ * Ali Eissa - 2026 version. */ +// Portions of this file were generated with AI assistance. + #ifndef ANSI_COLORS_H #define ANSI_COLORS_H diff --git a/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/client_main.c b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/client_main.c index 745fe0e8..c54a615b 100644 --- a/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/client_main.c +++ b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/client_main.c @@ -11,6 +11,8 @@ * Ali Eissa - 2026 version. */ +// Portions of this file were generated with AI assistance. + #include #include #include diff --git a/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/main.c b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/main.c index b77f521e..81f6d801 100644 --- a/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/main.c +++ b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_echo/main.c @@ -11,6 +11,8 @@ * Ali Eissa - 2026 version. */ +// Portions of this file were generated with AI assistance. + #include #include #include diff --git a/targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/client_main.c b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/client_main.c index 42eeca31..0519705b 100644 --- a/targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/client_main.c +++ b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/client_main.c @@ -9,9 +9,10 @@ * * Contributors: * Ali Eissa - 2026 version. - * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) */ +// Portions of this file were generated with AI assistance. + #include #include #include diff --git a/targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/main.c b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/main.c index 692cab16..687d01a9 100644 --- a/targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/main.c +++ b/targets/NXP/MIMXRT1064-EVK/app/demos/netx_trng_console/main.c @@ -9,9 +9,10 @@ * * Contributors: * Ali Eissa - 2026 version. - * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) */ +// Portions of this file were generated with AI assistance. + #include #include #include diff --git a/targets/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/main.c b/targets/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/main.c index bf868eb8..26a94e7f 100644 --- a/targets/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/main.c +++ b/targets/NXP/MIMXRT1064-EVK/app/demos/threadx_basic/main.c @@ -11,6 +11,8 @@ * Ali Eissa - 2026 version. */ +// Portions of this file were generated with AI assistance. + #include #include #include diff --git a/targets/NXP/MIMXRT1064-EVK/app/startup/tx_initialize_low_level.S b/targets/NXP/MIMXRT1064-EVK/app/startup/tx_initialize_low_level.S index d34654b5..5801f2a5 100644 --- a/targets/NXP/MIMXRT1064-EVK/app/startup/tx_initialize_low_level.S +++ b/targets/NXP/MIMXRT1064-EVK/app/startup/tx_initialize_low_level.S @@ -12,6 +12,8 @@ * Ali Eissa - 2026 version. **************************************************************************/ +// Portions of this file were generated with AI assistance. + /**************************************************************************/ /**************************************************************************/ /** */ diff --git a/targets/NXP/MIMXRT1064-EVK/app/syscalls.c b/targets/NXP/MIMXRT1064-EVK/app/syscalls.c index 2411304a..187551e2 100644 --- a/targets/NXP/MIMXRT1064-EVK/app/syscalls.c +++ b/targets/NXP/MIMXRT1064-EVK/app/syscalls.c @@ -11,6 +11,8 @@ * Ali Eissa - 2026 version. */ +// Portions of this file were generated with AI assistance. + #include #include #include diff --git a/targets/NXP/MIMXRT1064-EVK/app/sysmem.c b/targets/NXP/MIMXRT1064-EVK/app/sysmem.c index 0f2dfe23..3f4671c6 100644 --- a/targets/NXP/MIMXRT1064-EVK/app/sysmem.c +++ b/targets/NXP/MIMXRT1064-EVK/app/sysmem.c @@ -9,9 +9,10 @@ * * Contributors: * Ali Eissa - 2026 version. - * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) */ +// Portions of this file were generated with AI assistance. + #include "tx_api.h" #include #include diff --git a/targets/NXP/MIMXRT1064-EVK/app/trng.c b/targets/NXP/MIMXRT1064-EVK/app/trng.c index c749a5c1..8e058eac 100644 --- a/targets/NXP/MIMXRT1064-EVK/app/trng.c +++ b/targets/NXP/MIMXRT1064-EVK/app/trng.c @@ -9,9 +9,10 @@ * * Contributors: * Ali Eissa - 2026 version. - * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) */ +// Portions of this file were generated with AI assistance. + #include "trng.h" #include "fsl_device_registers.h" #include "fsl_clock.h" diff --git a/targets/NXP/MIMXRT1064-EVK/app/trng.h b/targets/NXP/MIMXRT1064-EVK/app/trng.h index fbb364b6..19a9697e 100644 --- a/targets/NXP/MIMXRT1064-EVK/app/trng.h +++ b/targets/NXP/MIMXRT1064-EVK/app/trng.h @@ -9,9 +9,10 @@ * * Contributors: * Ali Eissa - 2026 version. - * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) */ +// Portions of this file were generated with AI assistance. + #ifndef TRNG_H #define TRNG_H diff --git a/targets/NXP/MIMXRT1064-EVK/lib/bsp/include/board_config.h b/targets/NXP/MIMXRT1064-EVK/lib/bsp/include/board_config.h index c6c9572f..ae3a6270 100644 --- a/targets/NXP/MIMXRT1064-EVK/lib/bsp/include/board_config.h +++ b/targets/NXP/MIMXRT1064-EVK/lib/bsp/include/board_config.h @@ -9,9 +9,10 @@ * * Contributors: * Ali Eissa - 2026 version. - * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) */ +// Portions of this file were generated with AI assistance. + #ifndef BOARD_CONFIG_H #define BOARD_CONFIG_H diff --git a/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_board.c b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_board.c index a5018a59..abaeb803 100644 --- a/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_board.c +++ b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_board.c @@ -9,9 +9,10 @@ * * Contributors: * Ali Eissa - 2026 version. - * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) */ +// Portions of this file were generated with AI assistance. + #include "bsp/board.h" #include "bsp/led.h" #include "bsp/console.h" diff --git a/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_console.c b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_console.c index ee3910d4..f1153c03 100644 --- a/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_console.c +++ b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_console.c @@ -9,9 +9,10 @@ * * Contributors: * Ali Eissa - 2026 version. - * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) */ +// Portions of this file were generated with AI assistance. + #include "bsp/console.h" #include "board_config.h" diff --git a/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_led.c b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_led.c index 59ecb493..83ec6472 100644 --- a/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_led.c +++ b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_led.c @@ -9,9 +9,10 @@ * * Contributors: * Ali Eissa - 2026 version. - * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) */ +// Portions of this file were generated with AI assistance. + #include "bsp/led.h" #include "board_config.h" diff --git a/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_memory.c b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_memory.c index a9aacd21..2c8af169 100644 --- a/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_memory.c +++ b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_memory.c @@ -9,9 +9,10 @@ * * Contributors: * Ali Eissa - 2026 version. - * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) */ +// Portions of this file were generated with AI assistance. + #include "bsp/memory.h" #include "board_config.h" #include diff --git a/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_selftest.c b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_selftest.c index 22c3d81e..c1dcccaa 100644 --- a/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_selftest.c +++ b/targets/NXP/MIMXRT1064-EVK/lib/bsp/src/bsp_selftest.c @@ -9,9 +9,10 @@ * * Contributors: * Ali Eissa - 2026 version. - * Assisted-by: Google DeepMind Antigravity (Gemini 3.8 Flash) */ +// Portions of this file were generated with AI assistance. + #include "bsp/selftest.h" #include "board_config.h" #include "fsl_common.h" diff --git a/targets/NXP/MIMXRT1064-EVK/lib/netxduo/nx_user.h b/targets/NXP/MIMXRT1064-EVK/lib/netxduo/nx_user.h index eccf436a..4ff84661 100644 --- a/targets/NXP/MIMXRT1064-EVK/lib/netxduo/nx_user.h +++ b/targets/NXP/MIMXRT1064-EVK/lib/netxduo/nx_user.h @@ -11,6 +11,8 @@ * Ali Eissa - 2026 version. */ +// Portions of this file were generated with AI assistance. + #ifndef NX_USER_H #define NX_USER_H diff --git a/targets/NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h b/targets/NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h index 3deb0a1e..96c13a8e 100644 --- a/targets/NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h +++ b/targets/NXP/MIMXRT1064-EVK/lib/threadx/tx_user.h @@ -12,6 +12,8 @@ /* Ali Eissa - 2026 version. */ /**************************************************************************/ +// Portions of this file were generated with AI assistance. + #ifndef TX_USER_H #define TX_USER_H From 91e185a09c77372872a24e446a7e26be0cb83a69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 16 Sep 2026 22:23:46 -0400 Subject: [PATCH 17/20] Documented the MXChip Newlib runtime glue (#68) Clarified the boundary between Newlib system calls, the BSP, ThreadX, and the ThreadX POSIX compatibility layer. Assisted-by: Codex (GPT-5) --- MXChip/AZ3166/deps/src/CMakeLists.txt | 4 ++-- MXChip/AZ3166/deps/src/newlib_nano.c | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/MXChip/AZ3166/deps/src/CMakeLists.txt b/MXChip/AZ3166/deps/src/CMakeLists.txt index 9c3e3766..85d113cd 100644 --- a/MXChip/AZ3166/deps/src/CMakeLists.txt +++ b/MXChip/AZ3166/deps/src/CMakeLists.txt @@ -16,7 +16,7 @@ set(TARGET app_common) # Initialize sources set(SOURCES "") -# Allow to disable the newlib stubbing +# Add the sample's Newlib system-call glue unless the BSP provides its own. if(NOT DEFINED DISABLE_NEWLIB_STUB) list(APPEND SOURCES newlib_nano.c @@ -32,4 +32,4 @@ target_link_libraries(${TARGET} azrtos::netxduo jsmn nanoprintf -) \ No newline at end of file +) diff --git a/MXChip/AZ3166/deps/src/newlib_nano.c b/MXChip/AZ3166/deps/src/newlib_nano.c index 98c66eb9..7b714d0e 100644 --- a/MXChip/AZ3166/deps/src/newlib_nano.c +++ b/MXChip/AZ3166/deps/src/newlib_nano.c @@ -1,6 +1,7 @@ /* * Copyright (c) Microsoft * Copyright (c) 2024 Eclipse Foundation + * 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 @@ -13,6 +14,29 @@ * Frédéric Desbiens - 2024 version. */ +// Some portions generated by Codex (GPT-5). + +/* + * Bare-metal C library integration for the MXChip sample. + * + * Newlib and newlib-nano implement the C library, but delegate services that + * normally come from an operating system to target-provided system calls. + * This file supplies the subset needed by this sample. The board console in + * app/common/console.c supplies _read() and _write() separately. + * + * These functions are not part of ThreadX or its POSIX compatibility layer. + * The exact system calls required by an application depend on the Newlib + * version and configuration, the linker specifications, and the C library + * routines that the application uses. + * + * Several functions below are minimal stubs because the sample has no file + * system or process model. The _sbrk() implementation is also sample-specific: + * it starts the C library heap at the linker-defined _end symbol, has no upper + * bound, and provides no synchronization. Applications that allocate from + * multiple threads, use a different memory layout, or require the unsupported + * services must provide suitable replacements in their BSP. + */ + #ifdef __GNUC__ #include From 72d7017aafa9c82550a5c9e1a0fa4a83a36261cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 30 Sep 2026 15:49:25 -0400 Subject: [PATCH 18/20] Updated SampleX contribution guide for board workflows (#75) The generic contributor guide omitted SampleX build, test, and submission practices. The guide now covers C99, board-specific toolchains and tests, the six Linux CI jobs, Renode verification, attribution, and release practices. Local Markdown links resolve and git diff --check passed. Build tests were not run for this documentation change. Assisted-by: Codex (GPT-6-Sol) --- CONTRIBUTING.md | 370 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 324 insertions(+), 46 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 227b104d..d39b5945 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,76 +1,354 @@ -# Contributing to Eclipse ThreadX +# Contributing to Eclipse ThreadX SampleX Thanks for your interest in this project. ## Project description -Eclipse ThreadX provides a vendor-neutral, open source, safety certified OS for -real-time applications published on under a permissive license. The Eclipse -ThreadX suite encompasses: -* ThreadX - advanced real-time operating system (RTOS) designed specifically for deeply embedded applications -* NetX Duo - advanced, industrial-grade TCP/IP network stack designed specifically for deeply embedded real-time and IoT applications -* FileX - high-performance, FAT-compatible file system that’s fully integrated with ThreadX kernel -* GUIX - provides a complete, embedded graphical user interface (GUI) library -* USBX - high-performance USB host, device, and on-the-go (OTG) embedded stack, that is fully integrated with ThreadX kernel -* LevelX - Flash Wear Leveling for FileX and stand-alone purposes -* GuiX Studio - design environment, facilitating the creation and maintenance of all graphical elements for GUIX -* TraceX - analysis tool that provides a graphical view of real-time system events to better understand the behavior of real-time systems +SampleX contains board applications and demonstrations for Eclipse ThreadX and its companion components. Targets include Arm and RISC-V boards; each board supplies its own build instructions, toolchain settings, and test path. The shared `apps/threadx_demo` source runs on both the NUCLEO-F401RE and PolarFire Icicle targets. -Project site: https://projects.eclipse.org/projects/iot.threadx +Eclipse ThreadX provides a vendor-neutral, open source, safety-certified OS for real-time applications, published under a permissive license. The Eclipse ThreadX suite encompasses: -## Repository description +* **ThreadX** - advanced real-time operating system (RTOS) designed specifically for deeply embedded applications +* **NetX Duo** - advanced, industrial-grade TCP/IP network stack designed specifically for deeply embedded real-time and IoT applications +* **FileX** - high-performance, FAT-compatible file system that is fully integrated with the ThreadX kernel +* **GUIX** - complete, embedded graphical user interface (GUI) library +* **GUIX Studio** - design environment, facilitating the creation and maintenance of all graphical elements for GUIX +* **USBX** - high-performance USB host, device, and on-the-go (OTG) embedded stack, fully integrated with the ThreadX kernel +* **LevelX** - flash wear levelling for FileX and stand-alone purposes +* **TraceX** - analysis tool that provides a graphical view of real-time system events to better understand the behaviour of real-time systems +* **ZoneX** - deterministic partitioning hypervisor for mixed-criticality embedded systems +* **SampleX** - samples and demos for the components above -This repository contains sample code aimed at developers working with development boards from various vendors. +Project websites: + +* https://threadx.io +* https://projects.eclipse.org/projects/iot.threadx + +This file describes how to contribute to **SampleX**. General contribution conventions are shared across the Eclipse ThreadX repositories; build and test instructions differ by target. ## Terms of Use -This repository is subject to the Terms of Use of the Eclipse Foundation -https://www.eclipse.org/legal/termsofuse.php +This repository is subject to the Terms of Use of the Eclipse Foundation: https://www.eclipse.org/legal/termsofuse.php -## Developer resources +## New contributors -Information regarding source code management, builds, coding standards, and more. -https://projects.eclipse.org/projects/iot.threadx/developer +Welcome. Here is the shortest path from zero to a merged pull request. -The project maintains the following source code repositories +1. **Create an Eclipse Foundation account.** https://accounts.eclipse.org/user/register -* https://github.com/eclipse-threadx/.github -* https://github.com/eclipse-threadx/cmsis-packs -* https://github.com/eclipse-threadx/filex -* https://github.com/eclipse-threadx/getting-started -* https://github.com/eclipse-threadx/guix -* https://github.com/eclipse-threadx/levelx -* https://github.com/eclipse-threadx/netxduo -* https://github.com/eclipse-threadx/rtos-docs -* https://github.com/eclipse-threadx/samples -* https://github.com/eclipse-threadx/threadx -* https://github.com/eclipse-threadx/threadx-learn-samples -* https://github.com/eclipse-threadx/tracex -* https://github.com/eclipse-threadx/usbx + The email address on that account matters: it must be the same address you use as the `Author` of your Git commits. If the two do not match, the ECA check on your pull request will fail. + +2. **Sign the Eclipse Contributor Agreement (ECA).** See the section below. This is a one-time step and covers every Eclipse Foundation project. + +
+ +3. **Configure Git accordingly.** + + ``` + git config user.name "Your Name" + git config user.email "the-address-on-your-eclipse-account@example.org" + ``` + +4. **Pick something to work on.** Open issues are fair game, including ones nobody has assigned. Please leave a comment on the issue saying you intend to work on it, so two people do not solve the same problem twice. If an issue carries a `good first issue` label, it is a reasonable starting point. + +5. **Have an idea for a new feature? Discuss it first.** Open a thread in [GitHub Discussions](https://github.com/orgs/eclipse-threadx/discussions) or raise it on the [developer mailing list](https://accounts.eclipse.org/mailing-list/threadx-dev) before writing code. A new board target or a change to a shared BSP interface can affect other samples, so discuss the shape of the feature before submitting a finished implementation. + +Bug fixes and documentation corrections need no prior discussion. Send them straight in. ## Eclipse Development Process -This Eclipse Foundation open project is governed by the Eclipse Foundation -Development Process and operates under the terms of the Eclipse IP Policy. +This Eclipse Foundation open project is governed by the Eclipse Foundation Development Process and operates under the terms of the Eclipse IP Policy. * https://eclipse.org/projects/dev_process * https://www.eclipse.org/org/documents/Eclipse_IP_Policy.pdf ## Eclipse Contributor Agreement -In order to be able to contribute to Eclipse Foundation projects you must electronically sign the Eclipse Contributor Agreement (ECA). -https://www.eclipse.org/legal/ECA.php +In order to be able to contribute to Eclipse Foundation projects you must electronically sign the Eclipse Contributor Agreement (ECA): https://www.eclipse.org/legal/ECA.php + +The ECA provides the Eclipse Foundation with a permanent record that you agree that each of your contributions will comply with the commitments documented in the Developer Certificate of Origin (DCO). Having an ECA on file associated with the email address matching the "Author" field of your contribution's Git commits fulfills the DCO's requirement that you sign-off on your contributions. + +For more information, please see the Eclipse Committer Handbook: https://www.eclipse.org/projects/handbook/#resources-commit + +## Required tooling + +There is no root build for all samples. Start with the README for the board or application you are changing. Clone with `git clone --recurse-submodules`, or run `git submodule update --init --recursive` after cloning; the repository uses ThreadX, NetX Duo, USBX, and FileX submodules. Some targets also fetch vendor SDK files through their own scripts. + +The three targets in the root CI workflow use CMake and Ninja on Ubuntu 24.04. Install the cross-compiler for the target, Python 3 for its Renode test runner, and Renode to execute its emulator tests. The CI reference versions are Arm GNU Toolchain 14.3.rel1 (`arm-none-eabi`), xPack RISC-V GCC 14.3.0-1 (`riscv-none-elf`), Python 3.11, and Renode 1.16.1. Use CMake 3.22 or later to cover the three CI targets. Other boards have their own tool and version requirements. + +Several board targets also provide PowerShell build scripts for Windows. Use the target README and its scripts for that platform; the root CI workflow currently runs on Linux. GNU cross builds use GCC assembly syntax. + +## Building and testing + +Choose the target affected by your change. These commands run from the repository root after its submodules are initialized: + +| Target | Build | Automated test | +| ------ | ----- | -------------- | +| Microchip PolarFire SoC Icicle Kit (64-bit RISC-V) | `bash targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/build.sh --rebuild` | `python3 targets/Microchip/POLARFIRE_ICICLE_RENODE/scripts/test_renode.py --app lm75` and `--app threadx_demo` | +| ST NUCLEO-F401RE (Cortex-M4) | `bash targets/STMicroelectronics/NUCLEO_F401RE/scripts/build.sh --rebuild` | `python3 targets/STMicroelectronics/NUCLEO_F401RE/scripts/test_renode.py` | +| NXP MIMXRT1064-EVK (Cortex-M7) | `bash targets/NXP/MIMXRT1064-EVK/scripts/fetch_sdk.sh`, then `bash targets/NXP/MIMXRT1064-EVK/scripts/build.sh --demo all --rebuild` | `python3 targets/NXP/MIMXRT1064-EVK/scripts/test_renode.py --demo threadx_basic`, then repeat with `netx_echo` and `netx_trng_console --seed 12345` | + +The NXP fetch script downloads and checks pinned SDK and CMSIS archives. The three Renode test runners assert on the applications' behaviour, rather than just checking that an ELF was produced. The NUCLEO-F401RE and PolarFire targets build the same portable `apps/threadx_demo/main.c` for two architectures and run it in Renode on both. A change to that shared application or its BSP interfaces needs both runs. + +Other samples, including the MXChip, OpenHW, and STM32F767ZI applications, have their own build and test instructions. Use the target README and run its relevant tests. For example, the CORE-V MCU CLI application has host-compiled command tests under `OpenHW/CORE-V-MCU/cli-test/tests/`. For a new board target, start with [the target template](templates/target/README.md); put board-independent application code under `apps/`, and keep board-specific code with its target. + +Renode execution does not establish behaviour on physical hardware. Run a changed board integration on the board when available, and state which hardware was tested in the pull request. Add or update regression tests for changed behaviour. The project targets 100% coverage; this repository's CI does not currently collect a whole-repository coverage report. + +## Continuous integration + +The root [`ci.yml`](.github/workflows/ci.yml) workflow runs on pull requests to `dev`, `main`, and `master`, on pushes to those branches and `feat/**`, and by manual dispatch. It has six Ubuntu 24.04 jobs: + +| Jobs | What they check | +| ---- | -------------- | +| `build-riscv-polarfire`, `test-polarfire-renode` | Build the PolarFire LM75 and shared ThreadX demo ELFs, then assert both under Renode. | +| `build-arm-nucleo`, `test-nucleo-renode` | Build the NUCLEO-F401RE shared ThreadX demo and assert it under Renode. | +| `build-arm-nxp`, `test-nxp-renode` | Fetch pinned NXP dependencies, build all three demos, then assert `threadx_basic`, `netx_echo`, and `netx_trng_console` under Renode. | + +These are cross-build and emulator checks. The workflow does not run the other board samples or execute on physical boards. Run additional target-specific validation for changes outside these lanes and report the result. + +## Pull request acceptance criteria + +**Pull requests must target the `dev` branch.** `main` holds the latest release in this repository; see [Release model and support](#release-model-and-support) below. A pull request opened against `main` will be asked to retarget. + +Before requesting a review, check your contribution against this list. + +**Process** + +* The branch is a feature branch based on `dev`. Never commit directly to `main` or `dev`. +* Your ECA is signed and the commit `Author` email matches your Eclipse account. +* The pull request is one logical change. Unrelated fixes belong in separate pull requests. +* Commit subject lines start with a past-tense verb, for example `Fixed the memory allocator`. +* The pull request explains what changed and why, and how you verified it. + +**Code** + +* SampleX C code is C99-compatible. +* It follows the coding style of the surrounding code. +* New functions and structures are documented in comments, as in existing code. +* MISRA C rules are followed as closely as practical, taking MISRA C 2004, 2012 and 2023 into account. Any deviation is explicit, names the rule being circumvented, and justifies it in a comment. +* `goto` is not used. +* Do not add new external dependencies. Existing component submodules and vendor SDK inputs are part of the affected targets. +* When implementing an industry standard, code is not copied from an existing implementation. Existing implementations may inform your work, but you must identify those sources clearly. +* Code is written with the suite's priorities in mind: runtime speed and small code size. +* New C and assembly files, and edited C and assembly files, carry the appropriate header and attribution (see below). + +**Verification** + +* All applicable CI checks are green on a pull request to `dev`. +* The change builds without new warnings on the reference toolchains. +* Regression tests covering the change are added or updated. The project targets 100% test coverage; a pull request with a known gap needs a stated reason. State which targets ran in Renode or on hardware, and which target-specific tests ran. +* API or behaviour changes come with a matching documentation pull request against [rtos-docs-asciidoc](https://github.com/eclipse-threadx/rtos-docs-asciidoc). + +**Security** + +If you discover a security issue while working on a change, do not describe it in a public pull request. Follow [SECURITY.md](SECURITY.md) instead. + +## AI-assisted contributions + +**AI-assisted contributions are welcome**, provided they are attributed. + +Two things are non-negotiable: + +1. **Attribution.** Mark AI-assisted C and assembly files as described below, and identify the tool and model in the commit message. +2. **Human responsibility.** The human contributor submitting the pull request is responsible for the contribution - technically and legally. Signing the ECA means *you* certify the contribution's provenance. An AI tool cannot sign the ECA and cannot hold that responsibility. Review what the tool produced, understand it, and verify that it is correct and that you have the right to contribute it. "The model wrote it" is not a defence. + +This is consistent with the Eclipse Foundation's [Generative AI Usage Guidelines](https://www.eclipse.org/projects/guidelines/genai/) and the [Eclipse Project Handbook](https://www.eclipse.org/projects/handbook/#genai). Please read them before submitting AI-assisted work. + +### Using a coding agent + +Give a coding agent this contribution guide and the README for the target it changes. Review its output against the same acceptance criteria as any other contribution. In particular, check C99 compatibility, surrounding style, test coverage, and the affected board or emulator path. + +### Header for new files + +Add this header when creating a new C or assembly (`.S`) file: + +```c +/*************************************************************************** + * Copyright (c) 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/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by (). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ +``` + +Substitute the current year, product name, and model and version. If a file was written without AI assistance, omit the AI Disclosure paragraph and use `SPDX-License-Identifier: MIT`. + +### Header for existing files + +When editing an existing C or assembly file whose copyright is from 2025 or earlier, and which does not already mention Eclipse ThreadX contributors, add this line to the header: + +```c + * Copyright (c) Eclipse ThreadX contributors +``` + +It goes *below* the older copyright. All copyright lines must stay in chronological order. For example: + +```c +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ +``` + +If the edit was AI-assisted and the file does not already carry an AI disclosure line, add this line just under the header: + +```c +// Portions of this file were generated with AI assistance. +``` + +Use the comment marker already used by the file. Keep an existing disclosure line unchanged and never add a second one. If you copy an existing file to get started on a new one, treat the result as a new file: use the new-file header, do not carry the old one over. + +### Commit attribution -The ECA provides the Eclipse Foundation with a permanent record that you agree -that each of your contributions will comply with the commitments documented in -the Developer Certificate of Origin (DCO). Having an ECA on file associated with -the email address matching the "Author" field of your contribution's Git commits -fulfills the DCO's requirement that you sign-off on your contributions. +Attribute AI assistance with an `Assisted-by` trailer in each commit that contains AI-assisted changes: -For more information, please see the Eclipse Committer Handbook: -https://www.eclipse.org/projects/handbook/#resources-commit +```text +Fixed the board console status + +The demo could report success before its console was ready. + +The board startup path now waits for console initialization. + +The affected Renode test passed all assertions. + +Assisted-by: () +``` + +Use the product's accepted name (`Claude Code`, `Copilot`, `Codex`, or `Gemini`) and the model string reported by the tool. Do not use `Co-Authored-By` for AI attribution. Commit subjects and pull request titles start with a past-tense verb and stay within 72 characters. The message body states the cause, fix, and test result in that order; wrap commit bodies at 88 characters. Pull request descriptions use one line per paragraph. + +## Release model and support + +This section summarises the project's [Release Model and Support Policy](https://github.com/eclipse-threadx/rtos-docs-asciidoc/blob/main/rtos-docs/home/modules/ROOT/pages/releases-and-support.adoc), which is the authoritative version. + +### Version numbers + +Eclipse ThreadX component releases generally follow [Semantic Versioning](https://semver.org/). SampleX tracks the component releases used by its samples. Given a component version number **X.Y.Z.Bh**, for example `6.5.0.202601a`: + +* **X** increases for a *milestone release*. Components currently stay at version 6. +* **Y** increases for a *feature release* adding a major feature. +* **Z** increases for a *maintenance release* of minor fixes and improvements. +* **B** is a *build number* identifying the quarter of publication - `202601` is Q1 2026. +* **h** denotes a *hotfix release*, identified by a letter. Hotfix releases are component-specific. + +### Release cadence + +The project adopted a predictable quarterly release model in September 2025 and has published a release every quarter since. + +Quarterly releases ship new versions of every component, whether or not that component saw code changes, so that version numbers do not drift apart between components. A release shipping no code changes for a component says so in its release notes. + +Urgent fixes between quarterly releases ship as *hotfix* releases. Those contain only security fixes, or fixes for serious problems that prevent building or testing applications. + +### Branches + +The project runs a time-based release train on trunk-based development. There are no long-term support branches and no backports to older releases. + +* `main` holds the released SampleX content. +* `dev` is the integration branch. Pull requests are merged there during the quarter. Track `dev` if you want to test new samples and fixes ahead of a release. +* A quarterly release is performed by merging `dev` into `main`. + +### Support policy + +Issues in the codebase are fixed on a best-effort basis, and pull requests fixing existing or new issues are gladly accepted. + +Security vulnerabilities disclosed confidentially are handled under the [Eclipse Foundation's security policy](https://www.eclipse.org/security/policy/). Once a candidate vulnerability is confirmed, the team works to deliver a fix as soon as possible, shipping it in the next quarterly release or as a hotfix depending on timing. Resolved vulnerabilities are disclosed immediately after a release containing the fix becomes available. The team aims to resolve newly confirmed vulnerabilities within three months; that period may be extended by the Project Leadership Chain together with the Eclipse Foundation Security team where appropriate. + +See [SECURITY.md](SECURITY.md) for how to report a vulnerability. + +### Roadmap + +The project team plans its work on a [public GitHub project board](https://github.com/orgs/eclipse-threadx/projects/2/views/2). + +### A note on older releases + +Microsoft contributed only the Azure RTOS codebase v6.x to the Eclipse Foundation. Older ThreadX releases (v5.x and lower) sold by Express Logic were never made open source, and Microsoft has discontinued sales and support for them. Users of ThreadX 5.x and lower should upgrade to the latest release of Eclipse ThreadX as soon as possible. + +## Documentation + +The documentation is published at **https://threadx.io**. PDF manuals for every component, in A4 and US Letter formats, are attached as assets to each GitHub release. + +### The stack + +Documentation is written in [AsciiDoc](https://asciidoc.org/) and built with [Antora](https://antora.org/). PDF manuals are produced by the [Antora Assembler](https://docs.antora.org/assembler/latest/) with `asciidoctor-pdf`. + +### The workflow + +1. The single source of truth is [rtos-docs-asciidoc](https://github.com/eclipse-threadx/rtos-docs-asciidoc). All documentation changes are made there, as pull requests, following the same branch rules as the code repositories. +2. At release time the site is generated from that source into [rtos-docs-html](https://github.com/eclipse-threadx/rtos-docs-html), which holds the rendered HTML and exists solely for website integration. Do not edit it by hand - your changes will be overwritten by the next build. +3. The website then serves the generated content from `rtos-docs-html`. + +The older `rtos-docs` repository, which held the documentation in Markdown, is archived and superseded by `rtos-docs-asciidoc`. Do not send changes there. + +If your contribution adds or changes an API or a feature, open a matching pull request against `rtos-docs-asciidoc`. + +## Developer resources + +Information regarding source code management, builds, coding standards, and more: https://projects.eclipse.org/projects/iot.threadx/developer + +The project maintains the following repositories: + +**Components** + +* https://github.com/eclipse-threadx/threadx +* https://github.com/eclipse-threadx/netxduo +* https://github.com/eclipse-threadx/filex +* https://github.com/eclipse-threadx/guix +* https://github.com/eclipse-threadx/usbx +* https://github.com/eclipse-threadx/levelx +* https://github.com/eclipse-threadx/tracex +* https://github.com/eclipse-threadx/zonex + +**Samples and platforms** + +* https://github.com/eclipse-threadx/samplex +* https://github.com/eclipse-threadx/supported-platforms + +**Documentation** + +* https://github.com/eclipse-threadx/rtos-docs-asciidoc +* https://github.com/eclipse-threadx/rtos-docs-html + +**Community and process** + +* https://github.com/eclipse-threadx/discussions +* https://github.com/eclipse-threadx/trustedx +* https://github.com/eclipse-threadx/.github ## Contact -Contact the project developers via the project's "dev" list. +### GitHub Discussions + +https://github.com/orgs/eclipse-threadx/discussions + +Q&A, feedback, and announcements. Decisions taken by the project team are documented here as well. This is usually the fastest way to reach both the team and other users. + +### Main ThreadX mailing list + +https://accounts.eclipse.org/mailing-list/threadx + +News and updates about the ThreadX project and the ThreadX Alliance. + +### Developer mailing list + https://accounts.eclipse.org/mailing-list/threadx-dev + +Project team conversations. Feel free to jump in and ask non-technical questions there. + +### User mailing list + +https://accounts.eclipse.org/mailing-list/threadx-users + +Ask your technical questions and discuss issues here. From 338380e6990b3a4726890732808f6839107bab36 Mon Sep 17 00:00:00 2001 From: Jaxc Date: Wed, 30 Sep 2026 22:14:47 +0200 Subject: [PATCH 19/20] Added an STM32 NUCLEO-F429ZI sample (#47) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added an STM32 NUCLEO-F429ZI sample SampleX had no NUCLEO-F429ZI target. The NUCLEO-F767ZI one was the closest thing, and a board this common being absent meant starting from a target for a different family. The new target is derived from the F767ZI one and keeps its shape: the same tasks and the same IO, moved onto STM32F4 peripherals. It brings its own startup, linker script and HAL configuration, a threadx_basic demo, the CMake toolchain files, and build and SDK fetch scripts for Linux and Windows. The F767ZI target picks up the small corrections that fell out of the comparison. The STM32F429 SVD is fetched rather than carried. It is ST's file under Apache-2.0 while this repository is MIT, and at 62106 lines it was most of the change. fetch_sdk.sh now takes it from the CMSIS device family pack with the pack version pinned and its digest checked, the way the toolchains are pinned, and NOTICE.md declares it alongside the HAL, CMSIS Device and CMSIS Core that were already fetched. Nothing is lost: the SVD is read only by the optional Segger Ozone configuration and no build consumes it. CI green. The fetch was run from a clean tree: the pack downloads, the digest matches and tools/STM32F429.svd arrives at 2118587 bytes. Assisted-by: Claude Code (Opus 5) Co-authored-by: Jacob Rosén Co-authored-by: Frédéric Desbiens --- .../STM32F429ZI-Nucleo/.gitignore | 4 + .../STM32F429ZI-Nucleo/CMakeLists.txt | 113 +++ .../STM32F429ZI-Nucleo/NOTICE.md | 118 +++ .../STM32F429ZI-Nucleo/README.md | 187 +++++ .../STM32F429ZI-Nucleo/app/ansi_colors.h | 49 ++ .../STM32F429ZI-Nucleo/app/board_init.c | 157 ++++ .../STM32F429ZI-Nucleo/app/board_init.h | 42 + .../STM32F429ZI-Nucleo/app/console.c | 70 ++ .../app/demos/threadx_basic/CMakeLists.txt | 44 ++ .../app/demos/threadx_basic/main.c | 355 +++++++++ .../STM32F429ZI-Nucleo/app/main.h | 119 +++ .../app/startup/STM32F429xx_FLASH.ld | 273 +++++++ .../app/startup/startup_stm32f429xx.s | 543 +++++++++++++ .../app/startup/system_stm32f4xx.c | 747 ++++++++++++++++++ .../app/startup/tx_initialize_low_level.S | 196 +++++ .../app/stm32f4xx_hal_conf.h | 495 ++++++++++++ .../app/stm32f4xx_hal_msp.c | 147 ++++ .../STM32F429ZI-Nucleo/app/syscalls.c | 176 +++++ .../STM32F429ZI-Nucleo/app/sysmem.c | 79 ++ .../STM32F429ZI-Nucleo/cmake/FindCMSIS.cmake | 46 ++ .../cmake/FindSTM32HAL.cmake | 86 ++ .../cmake/arm-gcc-cortex-m4.cmake | 23 + .../cmake/arm-gcc-cortex-toolchain.cmake | 78 ++ .../STM32F429ZI-Nucleo/cmake/utilities.cmake | 50 ++ .../STM32F429ZI-Nucleo/lib/threadx/tx_user.h | 19 + .../STM32F429ZI-Nucleo/scripts/build.ps1 | 84 ++ .../STM32F429ZI-Nucleo/scripts/build.sh | 89 +++ .../STM32F429ZI-Nucleo/scripts/fetch_sdk.ps1 | 88 +++ .../STM32F429ZI-Nucleo/scripts/fetch_sdk.sh | 104 +++ .../tools/STM32F429ZI_samplex.ioc | 313 ++++++++ .../tools/STM32F429ZI_threadx_basic.jdebug | 348 ++++++++ .../STM32F767ZI-Nucleo/CMakeLists.txt | 16 +- .../app/demos/threadx_basic/CMakeLists.txt | 10 +- .../app/demos/threadx_basic/main.c | 19 +- .../cmake/FindSTM32HAL.cmake | 10 +- .../STM32F767ZI-Nucleo/scripts/build.sh | 0 .../STM32F767ZI-Nucleo/scripts/fetch_sdk.ps1 | 10 +- .../STM32F767ZI-Nucleo/scripts/fetch_sdk.sh | 10 +- 38 files changed, 5278 insertions(+), 39 deletions(-) create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/.gitignore create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/CMakeLists.txt create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/NOTICE.md create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/README.md create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/app/ansi_colors.h create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/app/board_init.c create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/app/board_init.h create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/app/console.c create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/app/demos/threadx_basic/CMakeLists.txt create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/app/demos/threadx_basic/main.c create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/app/main.h create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/app/startup/STM32F429xx_FLASH.ld create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/app/startup/startup_stm32f429xx.s create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/app/startup/system_stm32f4xx.c create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/app/startup/tx_initialize_low_level.S create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/app/stm32f4xx_hal_conf.h create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/app/stm32f4xx_hal_msp.c create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/app/syscalls.c create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/app/sysmem.c create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/cmake/FindCMSIS.cmake create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/cmake/FindSTM32HAL.cmake create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/cmake/arm-gcc-cortex-m4.cmake create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/cmake/arm-gcc-cortex-toolchain.cmake create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/cmake/utilities.cmake create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/lib/threadx/tx_user.h create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/scripts/build.ps1 create mode 100755 STMicroelectronics/STM32F429ZI-Nucleo/scripts/build.sh create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/scripts/fetch_sdk.ps1 create mode 100755 STMicroelectronics/STM32F429ZI-Nucleo/scripts/fetch_sdk.sh create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/tools/STM32F429ZI_samplex.ioc create mode 100644 STMicroelectronics/STM32F429ZI-Nucleo/tools/STM32F429ZI_threadx_basic.jdebug mode change 100644 => 100755 STMicroelectronics/STM32F767ZI-Nucleo/scripts/build.sh mode change 100644 => 100755 STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.sh diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/.gitignore b/STMicroelectronics/STM32F429ZI-Nucleo/.gitignore new file mode 100644 index 00000000..5c169e0a --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/.gitignore @@ -0,0 +1,4 @@ +lib/stm32cubef4/* + +# Fetched by scripts/fetch_sdk.sh from ST's CMSIS device pack. +tools/STM32F429.svd diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/CMakeLists.txt b/STMicroelectronics/STM32F429ZI-Nucleo/CMakeLists.txt new file mode 100644 index 00000000..6dba8b41 --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/CMakeLists.txt @@ -0,0 +1,113 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) +set(CMAKE_C_STANDARD 99) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Set the toolchain if not defined +if(NOT CMAKE_TOOLCHAIN_FILE) + set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_LIST_DIR}/cmake/arm-gcc-cortex-m4.cmake") +endif() + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) + +include(utilities) + +# Define the Project +project(stm32f429_threadx C CXX ASM) + +# Select the active demo to build (threadx_basic) +set(ACTIVE_DEMO "threadx_basic" CACHE STRING "Active demo name to build: threadx_basic") + +# Set up standard paths for find modules +set(STM32_FAMILY "F4") +set(STM32Cube_DIR "${CMAKE_CURRENT_LIST_DIR}/lib/stm32cubef4") + +# Find CMSIS and HAL driver packages +find_package(CMSIS REQUIRED) +find_package(STM32HAL REQUIRED COMPONENTS cortex pwr rcc gpio uart dma) + +# Compile the STM32F4xx HAL Driver Library as an Object Library +set(HAL_TARGET stm32cubef4) +add_library(${HAL_TARGET} OBJECT ${STM32HAL_SOURCES}) + +target_compile_definitions(${HAL_TARGET} + PUBLIC + STM32F429xx + USE_HAL_DRIVER + STM32F4 +) + +target_include_directories(${HAL_TARGET} + PUBLIC + ${CMSIS_INCLUDE_DIRS} + ${STM32HAL_INCLUDE_DIR} + ${CMAKE_CURRENT_LIST_DIR}/app +) + +# Dynamic Middleware Auto-Detection +# Check if the active demo uses NetX Duo by looking for nx_user.h +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/nx_user.h") + set(USE_NETXDUO ON) + set(NX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/nx_user.h" CACHE STRING "Enable NetX Duo user configuration" FORCE) +else() + set(USE_NETXDUO OFF) +endif() + +# Check if the active demo has custom tx_user.h; otherwise fallback to app/tx_user.h +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/tx_user.h") + set(TX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}/tx_user.h" CACHE STRING "Enable TX user configuration" FORCE) + set(TX_USER_FILE_DIR "${CMAKE_CURRENT_LIST_DIR}/app/demos/${ACTIVE_DEMO}") +else() + set(TX_USER_FILE "${CMAKE_CURRENT_LIST_DIR}/lib/threadx/tx_user.h" CACHE STRING "Enable TX user configuration" FORCE) + set(TX_USER_FILE_DIR "${CMAKE_CURRENT_LIST_DIR}/lib/threadx") +endif() + +# Compile ThreadX Kernel from root shared libs submodule +set(THREADX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../libs/threadx") +add_subdirectory(${THREADX_DIR} threadx) + +# 1. Define the Board BSP static library +add_library(board_bsp OBJECT + app/startup/startup_stm32f429xx.s + app/startup/system_stm32f4xx.c + app/startup/tx_initialize_low_level.S + app/board_init.c + app/console.c + app/stm32f4xx_hal_msp.c + app/sysmem.c + app/syscalls.c +) + +# Include paths for BSP +target_include_directories(board_bsp PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/app + ${CMSIS_INCLUDE_DIRS} + ${STM32HAL_INCLUDE_DIR} + ${TX_USER_FILE_DIR} +) + +# Compile definitions for BSP +target_compile_definitions(board_bsp PRIVATE + STM32F429xx + USE_HAL_DRIVER + STM32F4 +) + +# Link libraries for BSP (HAL and CMSIS) +target_link_libraries(board_bsp PUBLIC + stm32cubef4 + threadx +) + +# 3. Add the active demo subdirectory to build the executable target +add_subdirectory(app/demos/${ACTIVE_DEMO}) diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/NOTICE.md b/STMicroelectronics/STM32F429ZI-Nucleo/NOTICE.md new file mode 100644 index 00000000..efc41ad9 --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/NOTICE.md @@ -0,0 +1,118 @@ +# Third-Party Software Notices + +This directory contains build automation scripts that download and compile third-party software components. This notice lists the licenses and copyrights applicable to those components. + +--- + +## 1. STMicroelectronics STM32F4xx HAL Driver +* **Source**: https://github.com/STMicroelectronics/stm32f4xx_hal_driver +* **License**: BSD 3-Clause + +```text +Copyright (c) 2016 STMicroelectronics. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of STMicroelectronics nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +``` + +--- + +## 2. STMicroelectronics CMSIS Device F4 +* **Source**: https://github.com/STMicroelectronics/cmsis_device_f4 +* **License**: BSD 3-Clause + +```text +Copyright (c) 2016 STMicroelectronics. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of STMicroelectronics nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +``` + +--- + +## 3. STMicroelectronics CMSIS Core +* **Source**: https://github.com/STMicroelectronics/cmsis-core +* **License**: Apache License 2.0 / BSD 3-Clause (Arm Limited / STMicroelectronics) + +```text +Copyright (c) 2009-2025 Arm Limited. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` + +--- + +## 4. STMicroelectronics STM32F429 System View Description + +Fetched by `scripts/fetch_sdk.sh` from the CMSIS device family pack and written to `tools/STM32F429.svd`. It is read only by the optional Segger Ozone debug configuration and is not part of any build. + +* **Source**: https://www.keil.com/pack/Keil.STM32F4xx_DFP.3.1.1.pack, member `CMSIS/SVD/STM32F429.svd` +* **License**: Apache-2.0 + +```text +Copyright (c) 2024 STMicroelectronics. + +SPDX-License-Identifier: Apache-2.0 + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 +``` diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/README.md b/STMicroelectronics/STM32F429ZI-Nucleo/README.md new file mode 100644 index 00000000..5f03e10d --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/README.md @@ -0,0 +1,187 @@ +# STM32F429ZI-Nucleo Board Enablement Demo + +This directory contains the Board Support Package (BSP) static library (`board_bsp`) and build configurations for running the **Eclipse ThreadX RTOS** on the **STMicroelectronics NUCLEO-F429ZI** evaluation board (ARM Cortex-M4). + +The project features a decoupled static BSP library that hides all low-level hardware initializations (clocks, GPIO, DMA descriptors, and interrupts) from the application code. + +--- + +## Supported Demos + +Use the `ACTIVE_DEMO` CMake variable to select which demo to compile: + +| Demo Name | Description | Targets | +| :--- | :--- | :--- | +| **`threadx_basic`** *(Default)* | Multi-threaded RTOS demo showcasing thread scheduling, mechanical button debouncing, message queue logging, and interrupt-driven UART ring buffers. | ThreadX | + + +## Hardware Configuration + +* **Development Board**: NUCLEO-F429ZI (Nucleo-144) +* **Microcontroller**: STM32F429ZIT6 (ARM Cortex-M4 running at 168 MHz) +* **Memory**: 2 MB Flash, 256 KB SRAM +* **Virtual COM Port**: USART3 (PD8/PD9) connected to ST-LINK debugger (115,200 baud, 8N1) +* **User Button**: PC13 (Blue button, Active High) +* **Board LEDs**: + * `LD1` (Green) - PB0: Blinks to indicate ThreadX heartbeat. + * `LD2` (Blue) - PB7 + * `LD3` (Red) - PB14 +--- + +## Demo Application Architecture + +The application runs a multi-threaded demo showcasing cooperation between ThreadX scheduling, queues, hardware interrupts, and status indicator peripherals: + +1. **Thread 1 (Green LED - Heartbeat)** (Priority 15): + * Toggles the green LED (`LD1`) continuously at `2 Hz` (250 ms active, 250 ms idle) to verify basic scheduler clock ticks. +2. **Thread 2 (User Button Scanner)** (Priority 10): + * Scans the blue User Button (`PC13`) using software-level mechanical debouncing (20 ms). + * Turns the Blue LED (`LD2`) ON when the button is held. + * Sends the current system tick count over a **ThreadX Message Queue** on a button press transition. +3. **Thread 3 (System Logger)** (Priority 10): + * Blocks efficiently on the Message Queue. + * Wakes up when a button press event is queued and prints a timestamped system log over the serial port. +4. **Thread 4 (Serial Terminal Input)** (Priority 5): + * Integrates an asynchronous, non-blocking **Interrupt Service Routine (ISR)** (`USART3_IRQHandler`) and a 256-byte volatile circular **ring buffer** to read keyboard input at 115,200 baud. + * Collects incoming characters, prints the received string on carriage return/newline, and flashes the Red LED (`LD3`) for 50 ms. + * Avoids the use of `HAL_GetTick()` to prevent CPU starvation when idle. + +--- + +## Prerequisites + +Before building, ensure you have the following cross-compilation tools installed on your system PATH: + +* **ARM GNU Toolchain** (`arm-none-eabi-gcc`) +* **CMake** (version 3.10 or higher) +* **Ninja** or **Make** +* **Git** (for downloading SDK dependencies) + +--- + +## Quick Start Guide + +### 1. Download SDK Dependencies +Run the driver fetcher script to clone official, stock STMicroelectronics HAL drivers, CMSIS files, and driver configurations locally: + +* **On Windows (PowerShell)**: + ```powershell + powershell -ExecutionPolicy Bypass -File .\scripts\fetch_sdk.ps1 + ``` +* **On Linux (Bash)**: + ```bash + chmod +x ./scripts/fetch_sdk.sh + ./scripts/fetch_sdk.sh + ``` + +### 2. Configure and Build the Project + +#### Option A: Build `threadx_basic` (Default) +```bash +# Configure CMake +cmake -DACTIVE_DEMO=threadx_basic -B build + +# Compile +cmake --build build +``` + +The raw binary files will be generated in `build/app/demos//stm32f429_threadx.bin`. + +--- + +## Deployment & Verification + +### 1. Flash the Board +1. Connect the Nucleo board to your computer using a Micro-USB cable via the ST-LINK port. +2. The board will mount as an external USB drive (e.g., named `NOD_F429ZI` or `NUCLEO`). +3. Copy the compiled raw binary output file `build/app/demos//stm32f767_threadx.bin` and paste it directly onto the board's drive. +4. The ST-LINK status LED will blink rapidly while writing, then the board will auto-reboot. + +--- +### 2. How to Run & Verify the `threadx_basic` Demo +1. Open your serial terminal program at **115,200 baud, 8N1**. +2. Flash the `threadx_basic` binary to the board. +3. **Verify Heartbeat**: The Green LED (`LD1`) will blink continuously at `2 Hz` (250ms ON, 250ms OFF). +4. **Verify Button Scanner**: Press and hold the blue User Button on the board. The Blue LED (`LD2`) will light up immediately. In your serial terminal, a log message will print showing the system tick timestamp of the button transition. +5. **Verify UART Echo**: Type a word or string into your serial terminal and press `Enter`. The board will print the string back to you and flash the Red LED (`LD3`) for 50ms. + +--- + +### Additional debugging options using Segger Ozone +This platform also supplies a configuration to use with Segger Ozone +1. Open Segger Ozone. +2. Select "Open Existing Project". +3. Navigate to the tools folder of this project, and elect the project you want to debug in the file dialog. +4. Connect with Segger Ozone and it will download the SW to the target. + +## Developer Guide: How to Add a New Demo + +The decoupled architecture of the BSP (`board_bsp`) makes adding a new application or demo extremely simple: + +### Step 1: Create the Demo Directory +Create a new folder under `app/demos/` (e.g., `app/demos/my_demo/`). + +### Step 2: Write your Application Code +Create your `main.c`. Keep it clean by using the BSP initialization calls: +```c +#include "board_init.h" +#include "tx_api.h" + +int main(void) +{ + /* Initialize MPU, Clocks, GPIOs, and Serial Console */ + board_init(); + + /* Optional: Initialize Ethernet hardware if using networking */ + // board_ethernet_init(); + + /* Enter ThreadX Kernel */ + tx_kernel_enter(); + return 0; +} +``` + +### Step 3: Create `CMakeLists.txt` +Create a `CMakeLists.txt` in your demo folder: +```cmake +add_executable(${PROJECT_NAME} + main.c +) + +# Set compile definitions +target_compile_definitions(${PROJECT_NAME} + PRIVATE + STM32F767xx + USE_HAL_DRIVER + STM32F7 +) + +# Include paths +target_include_directories(${PROJECT_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../.. +) + +# Link with BSP, ThreadX, and optionally NetX Duo +target_link_libraries(${PROJECT_NAME} + PRIVATE + board_bsp + threadx + # filex # Uncomment if using filesystem + # netxduo # Uncomment if using network + # netx_stm32_driver # Uncomment if using network + stm32cubef7 +) + +# Apply linker script and print size +set_target_linker(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/STM32F767ZITx_FLASH.ld") +post_build(${PROJECT_NAME}) +``` + +### Step 4: Run your Demo +Configure CMake and build: +```bash +cmake -DACTIVE_DEMO=my_demo -B build +cmake --build build +``` diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/app/ansi_colors.h b/STMicroelectronics/STM32F429ZI-Nucleo/app/ansi_colors.h new file mode 100644 index 00000000..c1bb61db --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/app/ansi_colors.h @@ -0,0 +1,49 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#ifndef ANSI_COLORS_H +#define ANSI_COLORS_H + +/* ANSI Terminal Escape Codes for Colored Serial Output */ +#define ANSI_RESET "\x1b[0m" +#define ANSI_BOLD "\x1b[1m" + +/* Standard Primary Colors for Banners */ +#define ANSI_RED "\x1b[31m" +#define ANSI_GREEN "\x1b[32m" +#define ANSI_YELLOW "\x1b[33m" +#define ANSI_BLUE "\x1b[34m" +#define ANSI_MAGENTA "\x1b[35m" +#define ANSI_CYAN "\x1b[36m" +#define ANSI_WHITE "\x1b[37m" + +/* Subsystem Tags: Muted Slate Gray (256-color 243) to push them into visual background */ +#define TAG_SYSTEM "\x1b[38;5;243m[System]" +#define TAG_HAL "\x1b[38;5;243m[HAL]" +#define TAG_SENSOR "\x1b[38;5;243m[Sensor Thread]" +#define TAG_LOGGER "\x1b[38;5;243m[Logger Thread]" +#define TAG_NETWORK "\x1b[38;5;243m[NetX]" +#define TAG_NET_THREAD "\x1b[38;5;243m[Network Thread]" +#define TAG_DNS "\x1b[38;5;243m[DNS]" +#define TAG_MQTT "\x1b[38;5;243m[MQTT]" +#define TAG_STATUS "\x1b[38;5;243m[Status Thread]" +#define TAG_ECHO "\x1b[38;5;243m[Echo]" + +/* Message Colors: Soft, pastel feedback colors */ +#define MSG_INFO "\x1b[38;5;250m" /* Soft White/Gray for normal logs */ +#define MSG_SUCCESS "\x1b[38;5;114m" /* Soft Pastel Green for success */ +#define MSG_WARNING "\x1b[38;5;215m" /* Muted Gold/Orange for warnings */ +#define MSG_ERROR "\x1b[38;5;203m" /* Muted Coral/Red for failures */ +#define MSG_METRIC "\x1b[38;5;111m" /* Soft Sky Blue for data/measurements */ + +#endif /* ANSI_COLORS_H */ diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/app/board_init.c b/STMicroelectronics/STM32F429ZI-Nucleo/app/board_init.c new file mode 100644 index 00000000..9d29e171 --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/app/board_init.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2026 STMicroelectronics + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + * Jacob Rosén - STM32F429ZI adaptation + */ + +#include "board_init.h" +#include + +/* Global UART handler */ +UART_HandleTypeDef huart3; + +void SystemClock_Config(void); +void MX_GPIO_Init(void); +void MX_USART3_UART_Init(void); + +/** + * @brief Initializes the board clocks, MPU, GPIOs, and serial console. + * Direct copy of the STM32CubeMX initialization sequence. + * @retval None + */ +void board_init(void) +{ + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + HAL_Init(); + + /* Configure the system clock to 168 MHz */ + SystemClock_Config(); + + /* Initialize base GPIO pins */ + MX_GPIO_Init(); + + /* Initialize USART3 console */ + MX_USART3_UART_Init(); +} + +/** + * @brief System Clock Configuration (168 MHz using 8 MHz HSE bypass) + * Un-modified copy of STM32CubeMX generated Clock Configuration. + * @retval None + */ +void SystemClock_Config(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + + /** Configure the main internal regulator output voltage + */ + __HAL_RCC_PWR_CLK_ENABLE(); + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); + + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = 4; + RCC_OscInitStruct.PLL.PLLN = 168; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = 7; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) + { + Error_Handler(); + } + + /** Initializes the CPU, AHB and APB buses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) + { + Error_Handler(); + } +} + +/** + * @brief USART3 Initialization Function + * + * @retval None + */ +void MX_USART3_UART_Init(void) +{ + huart3.Instance = USART3; + huart3.Init.BaudRate = 115200; + huart3.Init.WordLength = UART_WORDLENGTH_8B; + huart3.Init.StopBits = UART_STOPBITS_1; + huart3.Init.Parity = UART_PARITY_NONE; + huart3.Init.Mode = UART_MODE_TX_RX; + huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart3.Init.OverSampling = UART_OVERSAMPLING_16; + if (HAL_UART_Init(&huart3) != HAL_OK) + { + Error_Handler(); + } +} + +/** + * @brief GPIO Initialization Function + * + * @retval None + */ +void MX_GPIO_Init(void) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOH_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOB, LD1_Pin|LD3_Pin|LD2_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pin : USER_Btn_Pin */ + GPIO_InitStruct.Pin = USER_Btn_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(USER_Btn_GPIO_Port, &GPIO_InitStruct); + + /*Configure GPIO pins : LD1_Pin LD3_Pin LD2_Pin */ + GPIO_InitStruct.Pin = LD1_Pin|LD3_Pin|LD2_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); +} + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + __disable_irq(); + while (1) + { + } +} diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/app/board_init.h b/STMicroelectronics/STM32F429ZI-Nucleo/app/board_init.h new file mode 100644 index 00000000..e48dff8a --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/app/board_init.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2026 STMicroelectronics + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + */ + +#ifndef _BOARD_INIT_H +#define _BOARD_INIT_H + +/* Official STM32CubeMX generated header containing hardware pin defines */ +#include "main.h" + +/* Nucleo-144 User Button (active high) */ +#define BUTTON_PIN USER_Btn_Pin +#define BUTTON_IS_PRESSED ((USER_Btn_GPIO_Port->IDR & USER_Btn_Pin) != 0) + +/* Nucleo-144 User LEDs: PB0 (Green), PB7 (Blue), PB14 (Red) mapped via STM32CubeMX defines */ +#define LED1_ON() LD1_GPIO_Port->BSRR = LD1_Pin +#define LED1_OFF() LD1_GPIO_Port->BSRR = (uint32_t)LD1_Pin << 16 + +#define LED2_ON() LD2_GPIO_Port->BSRR = LD2_Pin +#define LED2_OFF() LD2_GPIO_Port->BSRR = (uint32_t)LD2_Pin << 16 + +#define LED3_ON() LD3_GPIO_Port->BSRR = LD3_Pin +#define LED3_OFF() LD3_GPIO_Port->BSRR = (uint32_t)LD3_Pin << 16 + +/* Redirect UartHandle directly to STM32CubeMX global huart3 */ +extern UART_HandleTypeDef huart3; +#define UartHandle huart3 + +/* Define prototypes. */ +void board_init(void); + +#endif // _BOARD_INIT_H diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/app/console.c b/STMicroelectronics/STM32F429ZI-Nucleo/app/console.c new file mode 100644 index 00000000..854367ab --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/app/console.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) Microsoft + * Copyright (c) 2026 Eclipse Foundation + * + * 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 + * + * Contributors: + * Microsoft - Initial version + * Frédéric Desbiens - 2024 version. + */ + +#include "stm32f4xx_hal.h" + +#include "board_init.h" + +int __io_putchar(int ch); +int __io_getchar(void); +int _read(int file, char* ptr, int len); +int _write(int file, char* ptr, int len); + +int __io_putchar(int ch) +{ + HAL_UART_Transmit(&UartHandle, (uint8_t*)&ch, 1, HAL_MAX_DELAY); + return ch; +} + +int __io_getchar(void) +{ + uint8_t ch; + HAL_UART_Receive(&UartHandle, &ch, 1, HAL_MAX_DELAY); + + /* Echo character back to console */ + HAL_UART_Transmit(&UartHandle, &ch, 1, HAL_MAX_DELAY); + + /* And cope with Windows line endings */ + if (ch == '\r') + { + uint8_t ret = '\n'; + HAL_UART_Transmit(&UartHandle, &ret, 1, HAL_MAX_DELAY); + } + + return ch; +} + +int _read(int file, char* ptr, int len) +{ + int DataIdx; + + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + *ptr++ = __io_getchar(); + } + + return len; +} + +int _write(int file, char* ptr, int len) +{ + int DataIdx; + + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + __io_putchar(*ptr++); + } + return len; +} diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/app/demos/threadx_basic/CMakeLists.txt b/STMicroelectronics/STM32F429ZI-Nucleo/app/demos/threadx_basic/CMakeLists.txt new file mode 100644 index 00000000..b4355cab --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/app/demos/threadx_basic/CMakeLists.txt @@ -0,0 +1,44 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. +# Jacob Rosén - STM32F429ZI adaptation + +add_executable(${PROJECT_NAME} + main.c +) + +# Set compile definitions for our executable +target_compile_definitions(${PROJECT_NAME} + PRIVATE + STM32F429xx + USE_HAL_DRIVER + STM32F4 +) + +# Include paths for the executable target +target_include_directories(${PROJECT_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../.. +) + +# Link libraries +target_link_libraries(${PROJECT_NAME} + PRIVATE + board_bsp + threadx + stm32cubef4 +) + +# Apply GCC linker script and print memory usage (utilities.cmake function) +set_target_linker(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/../../startup/STM32F429xx_FLASH.ld") + +# Post-build commands to generate raw .bin and .hex files +post_build(${PROJECT_NAME}) diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/app/demos/threadx_basic/main.c b/STMicroelectronics/STM32F429ZI-Nucleo/app/demos/threadx_basic/main.c new file mode 100644 index 00000000..51da20eb --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/app/demos/threadx_basic/main.c @@ -0,0 +1,355 @@ +/* + * 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 + * + * Contributors: + * Ali Eissa - 2026 version. + * Jacob Rosén - STM32F429ZI adaptation + */ + +#include "board_init.h" +#include "tx_api.h" +#include +#include "ansi_colors.h" + +/* --- ThreadX Resource Definitions --- */ + +/* 1. Green LED Blinky Thread */ +#define GREEN_THREAD_STACK_SIZE 1024 +TX_THREAD green_thread; +uint8_t green_thread_stack[GREEN_THREAD_STACK_SIZE]; + +/* 2. Button Controller Thread */ +#define BUTTON_THREAD_STACK_SIZE 1024 +TX_THREAD button_thread; +uint8_t button_thread_stack[BUTTON_THREAD_STACK_SIZE]; + +/* 3. Logger Thread */ +#define LOGGER_THREAD_STACK_SIZE 1024 +TX_THREAD logger_thread; +uint8_t logger_thread_stack[LOGGER_THREAD_STACK_SIZE]; + +/* 4. Keyboard Input Thread */ +#define INPUT_THREAD_STACK_SIZE 1024 +TX_THREAD input_thread; +uint8_t input_thread_stack[INPUT_THREAD_STACK_SIZE]; + +/* 5. ThreadX Message Queue */ +#define QUEUE_MAX_MESSAGES 16 +#define MESSAGE_SIZE_WORDS 1 +TX_QUEUE msg_queue; +ULONG queue_buffer[QUEUE_MAX_MESSAGES * MESSAGE_SIZE_WORDS]; + +/* 6. printF Mutex */ +TX_MUTEX printf_mutex; + +/* Thread Function Prototypes */ +void green_thread_entry(ULONG thread_input); +void button_thread_entry(ULONG thread_input); +void logger_thread_entry(ULONG thread_input); +void input_thread_entry(ULONG thread_input); + +/** + * @brief Standard C Main entry point. + * @retval int + */ +int main(void) +{ + board_init(); + tx_kernel_enter(); + + return 0; +} + +/** + * @brief Define ThreadX resources + * @param first_unused_memory: pointer to first free memory block in RAM + * @retval None + */ +void tx_application_define(void *first_unused_memory) +{ + (void)first_unused_memory; + + /* ThreadX Message Queue */ + tx_queue_create(&msg_queue, + "Message Queue", + MESSAGE_SIZE_WORDS, + queue_buffer, + sizeof(queue_buffer)); + + /* Thread 1: Blinks Green LED */ + tx_thread_create(&green_thread, + "Green LED Thread", + green_thread_entry, + 0, + green_thread_stack, + GREEN_THREAD_STACK_SIZE, + 15, /* Lower priority */ + 15, + TX_NO_TIME_SLICE, + TX_AUTO_START); + + /* Thread 2: Scans User Button */ + tx_thread_create(&button_thread, + "Button Thread", + button_thread_entry, + 0, + button_thread_stack, + BUTTON_THREAD_STACK_SIZE, + 10, /* Medium priority */ + 10, + TX_NO_TIME_SLICE, + TX_AUTO_START); + + /* Thread 3: Prints Logs to PC */ + tx_thread_create(&logger_thread, + "Logger Thread", + logger_thread_entry, + 0, + logger_thread_stack, + LOGGER_THREAD_STACK_SIZE, + 10, /* Medium priority */ + 10, + TX_NO_TIME_SLICE, + TX_AUTO_START); + + /* Thread 4: Monitors Keyboard Input */ + tx_thread_create(&input_thread, + "Input Thread", + input_thread_entry, + 0, + input_thread_stack, + INPUT_THREAD_STACK_SIZE, + 5, /* Higher priority */ + 5, + TX_NO_TIME_SLICE, + TX_AUTO_START); + + /* Mutex 1: Printf guard */ + tx_mutex_create(&printf_mutex, + "Printf Guard", + TX_NO_INHERIT); +} + +/** + * @brief Thread 1: Blinks the Green LED (LD1) continuously to show life. + * @param thread_input: unused + * @retval None + */ +void green_thread_entry(ULONG thread_input) +{ + (void)thread_input; + + tx_mutex_get(&printf_mutex, TX_WAIT_FOREVER); + printf(ANSI_BOLD ANSI_CYAN "\r\n==========================================\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN "ThreadX Multitasking Edge Node Demo Booted!\r\n" ANSI_RESET); + printf(ANSI_BOLD ANSI_CYAN "==========================================\r\n\r\n" ANSI_RESET); + tx_mutex_put(&printf_mutex); + + while (1) + { + /* Toggles LD1 (Green) on and off every 250 milliseconds */ + LED1_ON(); + tx_thread_sleep(25); /* 25 ticks = 250 ms at 100 Hz tick rate */ + + LED1_OFF(); + tx_thread_sleep(25); + } +} + +/** + * @brief Thread 2: Scans the user button PC13. When pressed, sends the + * current tick count over the queue to the Logger thread. + * @param thread_input: unused + * @retval None + */ +void button_thread_entry(ULONG thread_input) +{ + (void)thread_input; + uint8_t button_was_pressed = 0; + + while (1) + { + if (BUTTON_IS_PRESSED) + { + if (!button_was_pressed) + { + /* Button was just pressed */ + button_was_pressed = 1; + LED2_ON(); + ULONG current_ticks = tx_time_get(); + + /* Non-blocking send the tick count over the queue to Thread 3 */ + tx_queue_send(&msg_queue, ¤t_ticks, TX_NO_WAIT); + } + } + else + { + if (button_was_pressed) + { + /* Button was released */ + button_was_pressed = 0; + LED2_OFF(); + } + } + + /* 20ms for preventing debounce */ + tx_thread_sleep(2); + } +} + +/** + * @brief Thread 3: Listens to the message queue. When a button press message + * arrives, it prints a real-time serial status log. + * @param thread_input: unused + * @retval None + */ +void logger_thread_entry(ULONG thread_input) +{ + (void)thread_input; + ULONG received_ticks; + + while (1) + { + /* Block until a message arrives in the queue */ + if (tx_queue_receive(&msg_queue, &received_ticks, TX_WAIT_FOREVER) == TX_SUCCESS) + { + tx_mutex_get(&printf_mutex, TX_WAIT_FOREVER); + printf("\x1b[38;5;243m[LOG]" ANSI_RESET " " MSG_SUCCESS "Button Pressed! System Tick Count: %lu\r\n" ANSI_RESET, received_ticks); + tx_mutex_put(&printf_mutex); + } + } +} + +/* Circular Ring Buffer for Serial Input (USART3) */ +#define RING_BUF_SIZE 256 +volatile char ring_buf[RING_BUF_SIZE]; +volatile int ring_head = 0; +volatile int ring_tail = 0; + +/** + * @brief USART3 Interrupt Service Routine (ISR) + * This runs in hardware interrupt context. It is incredibly fast, + * has zero overhead, and bypasses ThreadX scheduling to safely + * and instantly capture incoming serial characters, eliminating + * any Overrun Error (ORE) or missing byte issues at 115200 baud. + */ +void USART3_IRQHandler(void) +{ + /* Check RXNE (Receive Data Register Not Empty) flag */ + if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_RXNE)) + { + /* Read data register directly to clear RXNE flag and get the byte */ + char ch = (char)(huart3.Instance->DR & 0xFF); + + /* Insert into circular ring buffer if not full */ + int next_head = (ring_head + 1) % RING_BUF_SIZE; + if (next_head != ring_tail) + { + ring_buf[ring_head] = ch; + ring_head = next_head; + } + } + + /* Clear any hardware error flags to prevent lockups */ + if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_ORE | UART_FLAG_FE | UART_FLAG_NE | UART_FLAG_PE)) + { + /* Hardware error clear procedure is a two step process: + * 1. Read out the SR register + * 2. Read or write to DR register + * The read of SR register is done in the condition of the if case, and the DR register + * access is done inside of the case as follows: + */ + + char ch = (char)(huart3.Instance->DR & 0xFF); + + /* Insert into circular ring buffer if not full */ + int next_head = (ring_head + 1) % RING_BUF_SIZE; + if (next_head != ring_tail) + { + ring_buf[ring_head] = ch; + ring_head = next_head; + } + } +} + +/** + * @brief Thread 4: Monitors Keyboard Input + * This thread sleeps efficiently when idle. When the background interrupt + * captures typed characters, they are processed from the ring buffer. + * Once a complete string is received (ended by \r or \n), it prints the + * result and flashes the Red LED (LD3). + * @param thread_input: unused + * @retval None + */ +void input_thread_entry(ULONG thread_input) +{ + (void)thread_input; + static char line_buffer[128]; + static int line_index = 0; + + /* Ring Buffer pointers */ + ring_head = 0; + ring_tail = 0; + + /* Clear any pending error flags and purge hardware receive register */ + __HAL_UART_CLEAR_PEFLAG(&huart3); + + /* Enable USART3 Interrupts in the Cortex-M4 NVIC */ + HAL_NVIC_SetPriority(USART3_IRQn, 6, 0); + HAL_NVIC_EnableIRQ(USART3_IRQn); + + /* Enable USART3 Hardware Receive Interrupt (RXNEIE) */ + __HAL_UART_ENABLE_IT(&huart3, UART_IT_RXNE); + + while (1) + { + /* Process all characters accumulated in the ring buffer by the ISR */ + while (ring_tail != ring_head) + { + char ch = ring_buf[ring_tail]; + ring_tail = (ring_tail + 1) % RING_BUF_SIZE; + + /* Check for end of line*/ + if (ch == '\r' || ch == '\n') + { + if (line_index > 0) + { + line_buffer[line_index] = '\0'; + tx_mutex_get(&printf_mutex, TX_WAIT_FOREVER); + printf(" -> \x1b[38;5;243m[CONSOLE]" ANSI_RESET " " MSG_INFO "Received string: \"%s\"\r\n" ANSI_RESET, line_buffer); + tx_mutex_put(&printf_mutex); + + /* Flash LD3 to signal successful reception */ + LED3_ON(); + tx_thread_sleep(5); /* 50 ms flash (yields control to other threads) */ + LED3_OFF(); + + line_index = 0; + } + } + else + { + /* Standard character: append to buffer if there is space */ + if (line_index < (int)sizeof(line_buffer) - 1) + { + line_buffer[line_index++] = ch; + } + } + } + + /* Yield/Sleep for 1 tick (10ms) when no characters are being processed. + * This allows all other threads to run smoothly. */ + tx_thread_sleep(1); + } +} + + + + + diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/app/main.h b/STMicroelectronics/STM32F429ZI-Nucleo/app/main.h new file mode 100644 index 00000000..02b7fda9 --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/app/main.h @@ -0,0 +1,119 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.h + * @brief : Header for main.c file. + * This file contains the common defines of the application. + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __MAIN_H +#define __MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ + +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ +void Error_Handler(void); + +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +/* Private defines -----------------------------------------------------------*/ +#define USER_Btn_Pin GPIO_PIN_13 +#define USER_Btn_GPIO_Port GPIOC +#define MCO_Pin GPIO_PIN_0 +#define MCO_GPIO_Port GPIOH +#define RMII_MDC_Pin GPIO_PIN_1 +#define RMII_MDC_GPIO_Port GPIOC +#define RMII_REF_CLK_Pin GPIO_PIN_1 +#define RMII_REF_CLK_GPIO_Port GPIOA +#define RMII_MDIO_Pin GPIO_PIN_2 +#define RMII_MDIO_GPIO_Port GPIOA +#define RMII_CRS_DV_Pin GPIO_PIN_7 +#define RMII_CRS_DV_GPIO_Port GPIOA +#define RMII_RXD0_Pin GPIO_PIN_4 +#define RMII_RXD0_GPIO_Port GPIOC +#define RMII_RXD1_Pin GPIO_PIN_5 +#define RMII_RXD1_GPIO_Port GPIOC +#define LD1_Pin GPIO_PIN_0 +#define LD1_GPIO_Port GPIOB +#define RMII_TXD1_Pin GPIO_PIN_13 +#define RMII_TXD1_GPIO_Port GPIOB +#define LD3_Pin GPIO_PIN_14 +#define LD3_GPIO_Port GPIOB +#define STLK_RX_Pin GPIO_PIN_8 +#define STLK_RX_GPIO_Port GPIOD +#define STLK_TX_Pin GPIO_PIN_9 +#define STLK_TX_GPIO_Port GPIOD +#define USB_PowerSwitchOn_Pin GPIO_PIN_6 +#define USB_PowerSwitchOn_GPIO_Port GPIOG +#define USB_OverCurrent_Pin GPIO_PIN_7 +#define USB_OverCurrent_GPIO_Port GPIOG +#define USB_SOF_Pin GPIO_PIN_8 +#define USB_SOF_GPIO_Port GPIOA +#define USB_VBUS_Pin GPIO_PIN_9 +#define USB_VBUS_GPIO_Port GPIOA +#define USB_ID_Pin GPIO_PIN_10 +#define USB_ID_GPIO_Port GPIOA +#define USB_DM_Pin GPIO_PIN_11 +#define USB_DM_GPIO_Port GPIOA +#define USB_DP_Pin GPIO_PIN_12 +#define USB_DP_GPIO_Port GPIOA +#define TMS_Pin GPIO_PIN_13 +#define TMS_GPIO_Port GPIOA +#define TCK_Pin GPIO_PIN_14 +#define TCK_GPIO_Port GPIOA +#define RMII_TX_EN_Pin GPIO_PIN_11 +#define RMII_TX_EN_GPIO_Port GPIOG +#define RMII_TXD0_Pin GPIO_PIN_13 +#define RMII_TXD0_GPIO_Port GPIOG +#define LD2_Pin GPIO_PIN_7 +#define LD2_GPIO_Port GPIOB + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MAIN_H */ diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/app/startup/STM32F429xx_FLASH.ld b/STMicroelectronics/STM32F429ZI-Nucleo/app/startup/STM32F429xx_FLASH.ld new file mode 100644 index 00000000..eea1dc64 --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/app/startup/STM32F429xx_FLASH.ld @@ -0,0 +1,273 @@ +/* +****************************************************************************** +** + +** File : LinkerScript.ld +** +** Author : STM32CubeMX +** +** Abstract : Linker script for STM32F429ZITx series +** 2048Kbytes FLASH and 256Kbytes RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** Distribution: The file is distributed “as is,” without any warranty +** of any kind. +** +***************************************************************************** +** @attention +** +**

© COPYRIGHT(c) 2025 STMicroelectronics

+** +** Redistribution and use in source and binary forms, with or without modification, +** are permitted provided that the following conditions are met: +** 1. Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** 3. Neither the name of STMicroelectronics nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +_vectors = g_pfnVectors; + +/* Specify the memory areas */ +MEMORY +{ +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K +CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K +FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K +} + +/* Highest address of the user mode stack */ +_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of RAM */ +_sstack = _estack - _Min_Stack_Size; +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(4); + } >FLASH + + .ARM (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + . = ALIGN(4); + } >FLASH + + .preinit_array (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); + } >FLASH + + .init_array (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + } >FLASH + + .fini_array (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + } >FLASH + + _siccmram = LOADADDR(.ccmram); + + /* CCM-RAM section + * + * IMPORTANT NOTE! + * If initialized variables will be placed in this section, + * the startup code needs to be modified to copy the init-values. + */ + .ccmram : + { + . = ALIGN(4); + _sccmram = .; /* create a global symbol at ccmram start */ + *(.ccmram) + *(.ccmram*) + + . = ALIGN(4); + _eccmram = .; /* create a global symbol at ccmram end */ + } >CCMRAM AT> FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + *(.RamFunc) /* .RamFunc sections */ + *(.RamFunc*) /* .RamFunc* sections */ + + . = ALIGN(4); + } >RAM AT> FLASH + + /* Initialized TLS data section */ + .tdata : ALIGN(4) + { + *(.tdata .tdata.* .gnu.linkonce.td.*) + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + PROVIDE(__data_end = .); + PROVIDE(__tdata_end = .); + } >RAM AT> FLASH + + PROVIDE( __tdata_start = ADDR(.tdata) ); + PROVIDE( __tdata_size = __tdata_end - __tdata_start ); + + PROVIDE( __data_start = ADDR(.data) ); + PROVIDE( __data_size = __data_end - __data_start ); + + PROVIDE( __tdata_source = LOADADDR(.tdata) ); + PROVIDE( __tdata_source_end = LOADADDR(.tdata) + SIZEOF(.tdata) ); + PROVIDE( __tdata_source_size = __tdata_source_end - __tdata_source ); + + PROVIDE( __data_source = LOADADDR(.data) ); + PROVIDE( __data_source_end = __tdata_source_end ); + PROVIDE( __data_source_size = __data_source_end - __data_source ); + /* Uninitialized data section */ + .tbss (NOLOAD) : ALIGN(4) + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.tbss .tbss.*) + . = ALIGN(4); + PROVIDE( __tbss_end = . ); + } >RAM + + PROVIDE( __tbss_start = ADDR(.tbss) ); + PROVIDE( __tbss_size = __tbss_end - __tbss_start ); + PROVIDE( __tbss_offset = ADDR(.tbss) - ADDR(.tdata) ); + + PROVIDE( __tls_base = __tdata_start ); + PROVIDE( __tls_end = __tbss_end ); + PROVIDE( __tls_size = __tls_end - __tls_base ); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1) ); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + PROVIDE( __arm64_tls_tcb_offset = MAX(16, __tls_align) ); + + .bss (NOLOAD) : ALIGN(4) + { + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + __RAM_segment_used_end__ = _ebss; + PROVIDE( __bss_end = .); + } >RAM + PROVIDE( __non_tls_bss_start = ADDR(.bss) ); + + PROVIDE( __bss_start = __tbss_start ); + PROVIDE( __bss_size = __bss_end - __bss_start ); + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack (NOLOAD) : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a:* ( * ) + libm.a:* ( * ) + libgcc.a:* ( * ) + } + +} diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/app/startup/startup_stm32f429xx.s b/STMicroelectronics/STM32F429ZI-Nucleo/app/startup/startup_stm32f429xx.s new file mode 100644 index 00000000..5c28f053 --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/app/startup/startup_stm32f429xx.s @@ -0,0 +1,543 @@ +/** + ****************************************************************************** + * @file startup_stm32f429xx.s + * @author MCD Application Team + * @brief STM32F429xx Devices vector table for GCC based toolchains. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M4 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m4 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss +/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ + +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr sp, =_estack /* set stack pointer */ + +/* Call the clock system initialization function.*/ + bl SystemInit + +/* Copy the data segment initializers from flash to SRAM */ + ldr r0, =_sdata + ldr r1, =_edata + ldr r2, =_sidata + movs r3, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +LoopCopyDataInit: + adds r4, r0, r3 + cmp r4, r1 + bcc CopyDataInit + +/* Zero fill the bss segment. */ + ldr r2, =_sbss + ldr r4, =_ebss + movs r3, #0 + b LoopFillZerobss + +FillZerobss: + str r3, [r2] + adds r2, r2, #4 + +LoopFillZerobss: + cmp r2, r4 + bcc FillZerobss + +/* Call static constructors */ + bl __libc_init_array +/* Call the application's entry point.*/ + bl main + bx lr +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * @param None + * @retval None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M3. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +*******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + +g_pfnVectors: + .word _estack + .word Reset_Handler + + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + + /* External Interrupts */ + .word WWDG_IRQHandler /* Window WatchDog */ + .word PVD_IRQHandler /* PVD through EXTI Line detection */ + .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ + .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ + .word FLASH_IRQHandler /* FLASH */ + .word RCC_IRQHandler /* RCC */ + .word EXTI0_IRQHandler /* EXTI Line0 */ + .word EXTI1_IRQHandler /* EXTI Line1 */ + .word EXTI2_IRQHandler /* EXTI Line2 */ + .word EXTI3_IRQHandler /* EXTI Line3 */ + .word EXTI4_IRQHandler /* EXTI Line4 */ + .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ + .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ + .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ + .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ + .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ + .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ + .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ + .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ + .word CAN1_TX_IRQHandler /* CAN1 TX */ + .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ + .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ + .word CAN1_SCE_IRQHandler /* CAN1 SCE */ + .word EXTI9_5_IRQHandler /* External Line[9:5]s */ + .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ + .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ + .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ + .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ + .word TIM2_IRQHandler /* TIM2 */ + .word TIM3_IRQHandler /* TIM3 */ + .word TIM4_IRQHandler /* TIM4 */ + .word I2C1_EV_IRQHandler /* I2C1 Event */ + .word I2C1_ER_IRQHandler /* I2C1 Error */ + .word I2C2_EV_IRQHandler /* I2C2 Event */ + .word I2C2_ER_IRQHandler /* I2C2 Error */ + .word SPI1_IRQHandler /* SPI1 */ + .word SPI2_IRQHandler /* SPI2 */ + .word USART1_IRQHandler /* USART1 */ + .word USART2_IRQHandler /* USART2 */ + .word USART3_IRQHandler /* USART3 */ + .word EXTI15_10_IRQHandler /* External Line[15:10]s */ + .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ + .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ + .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ + .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ + .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ + .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ + .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ + .word FMC_IRQHandler /* FMC */ + .word SDIO_IRQHandler /* SDIO */ + .word TIM5_IRQHandler /* TIM5 */ + .word SPI3_IRQHandler /* SPI3 */ + .word UART4_IRQHandler /* UART4 */ + .word UART5_IRQHandler /* UART5 */ + .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ + .word TIM7_IRQHandler /* TIM7 */ + .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ + .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ + .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ + .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ + .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ + .word ETH_IRQHandler /* Ethernet */ + .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ + .word CAN2_TX_IRQHandler /* CAN2 TX */ + .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ + .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ + .word CAN2_SCE_IRQHandler /* CAN2 SCE */ + .word OTG_FS_IRQHandler /* USB OTG FS */ + .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ + .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ + .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ + .word USART6_IRQHandler /* USART6 */ + .word I2C3_EV_IRQHandler /* I2C3 event */ + .word I2C3_ER_IRQHandler /* I2C3 error */ + .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ + .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ + .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ + .word OTG_HS_IRQHandler /* USB OTG HS */ + .word DCMI_IRQHandler /* DCMI */ + .word 0 /* Reserved */ + .word HASH_RNG_IRQHandler /* Hash and Rng */ + .word FPU_IRQHandler /* FPU */ + .word UART7_IRQHandler /* UART7 */ + .word UART8_IRQHandler /* UART8 */ + .word SPI4_IRQHandler /* SPI4 */ + .word SPI5_IRQHandler /* SPI5 */ + .word SPI6_IRQHandler /* SPI6 */ + .word SAI1_IRQHandler /* SAI1 */ + .word LTDC_IRQHandler /* LTDC_IRQHandler */ + .word LTDC_ER_IRQHandler /* LTDC_ER_IRQHandler */ + .word DMA2D_IRQHandler /* DMA2D */ + + + .size g_pfnVectors, .-g_pfnVectors + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMP_STAMP_IRQHandler + .thumb_set TAMP_STAMP_IRQHandler,Default_Handler + + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Stream0_IRQHandler + .thumb_set DMA1_Stream0_IRQHandler,Default_Handler + + .weak DMA1_Stream1_IRQHandler + .thumb_set DMA1_Stream1_IRQHandler,Default_Handler + + .weak DMA1_Stream2_IRQHandler + .thumb_set DMA1_Stream2_IRQHandler,Default_Handler + + .weak DMA1_Stream3_IRQHandler + .thumb_set DMA1_Stream3_IRQHandler,Default_Handler + + .weak DMA1_Stream4_IRQHandler + .thumb_set DMA1_Stream4_IRQHandler,Default_Handler + + .weak DMA1_Stream5_IRQHandler + .thumb_set DMA1_Stream5_IRQHandler,Default_Handler + + .weak DMA1_Stream6_IRQHandler + .thumb_set DMA1_Stream6_IRQHandler,Default_Handler + + .weak ADC_IRQHandler + .thumb_set ADC_IRQHandler,Default_Handler + + .weak CAN1_TX_IRQHandler + .thumb_set CAN1_TX_IRQHandler,Default_Handler + + .weak CAN1_RX0_IRQHandler + .thumb_set CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_SCE_IRQHandler + .thumb_set CAN1_SCE_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_TIM9_IRQHandler + .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler + + .weak TIM1_UP_TIM10_IRQHandler + .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_TIM11_IRQHandler + .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak OTG_FS_WKUP_IRQHandler + .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler + + .weak TIM8_BRK_TIM12_IRQHandler + .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler + + .weak TIM8_UP_TIM13_IRQHandler + .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler + + .weak TIM8_TRG_COM_TIM14_IRQHandler + .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler + + .weak TIM8_CC_IRQHandler + .thumb_set TIM8_CC_IRQHandler,Default_Handler + + .weak DMA1_Stream7_IRQHandler + .thumb_set DMA1_Stream7_IRQHandler,Default_Handler + + .weak FMC_IRQHandler + .thumb_set FMC_IRQHandler,Default_Handler + + .weak SDIO_IRQHandler + .thumb_set SDIO_IRQHandler,Default_Handler + + .weak TIM5_IRQHandler + .thumb_set TIM5_IRQHandler,Default_Handler + + .weak SPI3_IRQHandler + .thumb_set SPI3_IRQHandler,Default_Handler + + .weak UART4_IRQHandler + .thumb_set UART4_IRQHandler,Default_Handler + + .weak UART5_IRQHandler + .thumb_set UART5_IRQHandler,Default_Handler + + .weak TIM6_DAC_IRQHandler + .thumb_set TIM6_DAC_IRQHandler,Default_Handler + + .weak TIM7_IRQHandler + .thumb_set TIM7_IRQHandler,Default_Handler + + .weak DMA2_Stream0_IRQHandler + .thumb_set DMA2_Stream0_IRQHandler,Default_Handler + + .weak DMA2_Stream1_IRQHandler + .thumb_set DMA2_Stream1_IRQHandler,Default_Handler + + .weak DMA2_Stream2_IRQHandler + .thumb_set DMA2_Stream2_IRQHandler,Default_Handler + + .weak DMA2_Stream3_IRQHandler + .thumb_set DMA2_Stream3_IRQHandler,Default_Handler + + .weak DMA2_Stream4_IRQHandler + .thumb_set DMA2_Stream4_IRQHandler,Default_Handler + + .weak ETH_IRQHandler + .thumb_set ETH_IRQHandler,Default_Handler + + .weak ETH_WKUP_IRQHandler + .thumb_set ETH_WKUP_IRQHandler,Default_Handler + + .weak CAN2_TX_IRQHandler + .thumb_set CAN2_TX_IRQHandler,Default_Handler + + .weak CAN2_RX0_IRQHandler + .thumb_set CAN2_RX0_IRQHandler,Default_Handler + + .weak CAN2_RX1_IRQHandler + .thumb_set CAN2_RX1_IRQHandler,Default_Handler + + .weak CAN2_SCE_IRQHandler + .thumb_set CAN2_SCE_IRQHandler,Default_Handler + + .weak OTG_FS_IRQHandler + .thumb_set OTG_FS_IRQHandler,Default_Handler + + .weak DMA2_Stream5_IRQHandler + .thumb_set DMA2_Stream5_IRQHandler,Default_Handler + + .weak DMA2_Stream6_IRQHandler + .thumb_set DMA2_Stream6_IRQHandler,Default_Handler + + .weak DMA2_Stream7_IRQHandler + .thumb_set DMA2_Stream7_IRQHandler,Default_Handler + + .weak USART6_IRQHandler + .thumb_set USART6_IRQHandler,Default_Handler + + .weak I2C3_EV_IRQHandler + .thumb_set I2C3_EV_IRQHandler,Default_Handler + + .weak I2C3_ER_IRQHandler + .thumb_set I2C3_ER_IRQHandler,Default_Handler + + .weak OTG_HS_EP1_OUT_IRQHandler + .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler + + .weak OTG_HS_EP1_IN_IRQHandler + .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler + + .weak OTG_HS_WKUP_IRQHandler + .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler + + .weak OTG_HS_IRQHandler + .thumb_set OTG_HS_IRQHandler,Default_Handler + + .weak DCMI_IRQHandler + .thumb_set DCMI_IRQHandler,Default_Handler + + .weak HASH_RNG_IRQHandler + .thumb_set HASH_RNG_IRQHandler,Default_Handler + + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler + + .weak UART7_IRQHandler + .thumb_set UART7_IRQHandler,Default_Handler + + .weak UART8_IRQHandler + .thumb_set UART8_IRQHandler,Default_Handler + + .weak SPI4_IRQHandler + .thumb_set SPI4_IRQHandler,Default_Handler + + .weak SPI5_IRQHandler + .thumb_set SPI5_IRQHandler,Default_Handler + + .weak SPI6_IRQHandler + .thumb_set SPI6_IRQHandler,Default_Handler + + .weak SAI1_IRQHandler + .thumb_set SAI1_IRQHandler,Default_Handler + + .weak LTDC_IRQHandler + .thumb_set LTDC_IRQHandler,Default_Handler + + .weak LTDC_ER_IRQHandler + .thumb_set LTDC_ER_IRQHandler,Default_Handler + + .weak DMA2D_IRQHandler + .thumb_set DMA2D_IRQHandler,Default_Handler diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/app/startup/system_stm32f4xx.c b/STMicroelectronics/STM32F429ZI-Nucleo/app/startup/system_stm32f4xx.c new file mode 100644 index 00000000..7a61e9cf --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/app/startup/system_stm32f4xx.c @@ -0,0 +1,747 @@ +/** + ****************************************************************************** + * @file system_stm32f4xx.c + * @author MCD Application Team + * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File. + * + * This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32f4xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used + * by the user application to setup the SysTick + * timer or configure other parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f4xx_system + * @{ + */ + +/** @addtogroup STM32F4xx_System_Private_Includes + * @{ + */ + + +#include "stm32f4xx.h" + +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Defines + * @{ + */ + +/************************* Miscellaneous Configuration ************************/ +/*!< Uncomment the following line if you need to use external SRAM or SDRAM as data memory */ +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\ + || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) +/* #define DATA_IN_ExtSRAM */ +#endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx || STM32F469xx || STM32F479xx ||\ + STM32F412Zx || STM32F412Vx */ + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) +/* #define DATA_IN_ExtSDRAM */ +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx ||\ + STM32F479xx */ + +/* Note: Following vector table addresses must be defined in line with linker + configuration. */ +/*!< Uncomment the following line if you need to relocate the vector table + anywhere in Flash or Sram, else the vector table is kept at the automatic + remap of boot address selected */ +/* #define USER_VECT_TAB_ADDRESS */ + +#if defined(USER_VECT_TAB_ADDRESS) +/*!< Uncomment the following line if you need to relocate your vector Table + in Sram else user remap will be done in Flash. */ +/* #define VECT_TAB_SRAM */ +#if defined(VECT_TAB_SRAM) +#define VECT_TAB_BASE_ADDRESS SRAM_BASE /*!< Vector Table base address field. + This value must be a multiple of 0x200. */ +#else +#define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field. + This value must be a multiple of 0x200. */ +#endif /* VECT_TAB_SRAM */ +#if !defined(VECT_TAB_OFFSET) +#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table offset field. + This value must be a multiple of 0x200. */ +#endif /* VECT_TAB_OFFSET */ +#endif /* USER_VECT_TAB_ADDRESS */ +/******************************************************************************/ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Variables + * @{ + */ + /* This variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ +uint32_t SystemCoreClock = 16000000; +const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; +const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes + * @{ + */ + +#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) + static void SystemInit_ExtMemCtl(void); +#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system + * Initialize the FPU setting, vector table location and External memory + * configuration. + * @param None + * @retval None + */ +void SystemInit(void) +{ + /* FPU settings ------------------------------------------------------------*/ + #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ + #endif + +#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) + SystemInit_ExtMemCtl(); +#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */ + + /* Configure the Vector Table location -------------------------------------*/ +#if defined(USER_VECT_TAB_ADDRESS) + SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ +#endif /* USER_VECT_TAB_ADDRESS */ +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) + * or HSI_VALUE(*) multiplied/divided by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value + * depends on the application requirements), user has to ensure that HSE_VALUE + * is same as the real frequency of the crystal used. Otherwise, this function + * may have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * + * @param None + * @retval None + */ +void SystemCoreClockUpdate(void) +{ + uint32_t tmp, pllvco, pllp, pllsource, pllm; + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) + { + case 0x00: /* HSI used as system clock source */ + SystemCoreClock = HSI_VALUE; + break; + case 0x04: /* HSE used as system clock source */ + SystemCoreClock = HSE_VALUE; + break; + case 0x08: /* PLL used as system clock source */ + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N + SYSCLK = PLL_VCO / PLL_P + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; + pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; + + if (pllsource != 0) + { + /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + else + { + /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + + pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; + SystemCoreClock = pllvco/pllp; + break; + default: + SystemCoreClock = HSI_VALUE; + break; + } + /* Compute HCLK frequency --------------------------------------------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; + /* HCLK frequency */ + SystemCoreClock >>= tmp; +} + +#if defined (DATA_IN_ExtSRAM) && defined (DATA_IN_ExtSDRAM) +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F469xx) || defined(STM32F479xx) +/** + * @brief Setup the external memory controller. + * Called in startup_stm32f4xx.s before jump to main. + * This function configures the external memories (SRAM/SDRAM) + * This SRAM/SDRAM will be used as program data memory (including heap and stack). + * @param None + * @retval None + */ +void SystemInit_ExtMemCtl(void) +{ + __IO uint32_t tmp = 0x00; + + register uint32_t tmpreg = 0, timeout = 0xFFFF; + register __IO uint32_t index; + + /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock */ + RCC->AHB1ENR |= 0x000001F8; + + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN); + + /* Connect PDx pins to FMC Alternate function */ + GPIOD->AFR[0] = 0x00CCC0CC; + GPIOD->AFR[1] = 0xCCCCCCCC; + /* Configure PDx pins in Alternate function mode */ + GPIOD->MODER = 0xAAAA0A8A; + /* Configure PDx pins speed to 100 MHz */ + GPIOD->OSPEEDR = 0xFFFF0FCF; + /* Configure PDx pins Output type to push-pull */ + GPIOD->OTYPER = 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOD->PUPDR = 0x00000000; + + /* Connect PEx pins to FMC Alternate function */ + GPIOE->AFR[0] = 0xC00CC0CC; + GPIOE->AFR[1] = 0xCCCCCCCC; + /* Configure PEx pins in Alternate function mode */ + GPIOE->MODER = 0xAAAA828A; + /* Configure PEx pins speed to 100 MHz */ + GPIOE->OSPEEDR = 0xFFFFC3CF; + /* Configure PEx pins Output type to push-pull */ + GPIOE->OTYPER = 0x00000000; + /* No pull-up, pull-down for PEx pins */ + GPIOE->PUPDR = 0x00000000; + + /* Connect PFx pins to FMC Alternate function */ + GPIOF->AFR[0] = 0xCCCCCCCC; + GPIOF->AFR[1] = 0xCCCCCCCC; + /* Configure PFx pins in Alternate function mode */ + GPIOF->MODER = 0xAA800AAA; + /* Configure PFx pins speed to 50 MHz */ + GPIOF->OSPEEDR = 0xAA800AAA; + /* Configure PFx pins Output type to push-pull */ + GPIOF->OTYPER = 0x00000000; + /* No pull-up, pull-down for PFx pins */ + GPIOF->PUPDR = 0x00000000; + + /* Connect PGx pins to FMC Alternate function */ + GPIOG->AFR[0] = 0xCCCCCCCC; + GPIOG->AFR[1] = 0xCCCCCCCC; + /* Configure PGx pins in Alternate function mode */ + GPIOG->MODER = 0xAAAAAAAA; + /* Configure PGx pins speed to 50 MHz */ + GPIOG->OSPEEDR = 0xAAAAAAAA; + /* Configure PGx pins Output type to push-pull */ + GPIOG->OTYPER = 0x00000000; + /* No pull-up, pull-down for PGx pins */ + GPIOG->PUPDR = 0x00000000; + + /* Connect PHx pins to FMC Alternate function */ + GPIOH->AFR[0] = 0x00C0CC00; + GPIOH->AFR[1] = 0xCCCCCCCC; + /* Configure PHx pins in Alternate function mode */ + GPIOH->MODER = 0xAAAA08A0; + /* Configure PHx pins speed to 50 MHz */ + GPIOH->OSPEEDR = 0xAAAA08A0; + /* Configure PHx pins Output type to push-pull */ + GPIOH->OTYPER = 0x00000000; + /* No pull-up, pull-down for PHx pins */ + GPIOH->PUPDR = 0x00000000; + + /* Connect PIx pins to FMC Alternate function */ + GPIOI->AFR[0] = 0xCCCCCCCC; + GPIOI->AFR[1] = 0x00000CC0; + /* Configure PIx pins in Alternate function mode */ + GPIOI->MODER = 0x0028AAAA; + /* Configure PIx pins speed to 50 MHz */ + GPIOI->OSPEEDR = 0x0028AAAA; + /* Configure PIx pins Output type to push-pull */ + GPIOI->OTYPER = 0x00000000; + /* No pull-up, pull-down for PIx pins */ + GPIOI->PUPDR = 0x00000000; + +/*-- FMC Configuration -------------------------------------------------------*/ + /* Enable the FMC interface clock */ + RCC->AHB3ENR |= 0x00000001; + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); + + FMC_Bank5_6->SDCR[0] = 0x000019E4; + FMC_Bank5_6->SDTR[0] = 0x01115351; + + /* SDRAM initialization sequence */ + /* Clock enable command */ + FMC_Bank5_6->SDCMR = 0x00000011; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Delay */ + for (index = 0; index<1000; index++); + + /* PALL command */ + FMC_Bank5_6->SDCMR = 0x00000012; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Auto refresh command */ + FMC_Bank5_6->SDCMR = 0x00000073; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* MRD register program */ + FMC_Bank5_6->SDCMR = 0x00046014; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Set refresh count */ + tmpreg = FMC_Bank5_6->SDRTR; + FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1)); + + /* Disable write protection */ + tmpreg = FMC_Bank5_6->SDCR[0]; + FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF); + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) + /* Configure and enable Bank1_SRAM2 */ + FMC_Bank1->BTCR[2] = 0x00001011; + FMC_Bank1->BTCR[3] = 0x00000201; + FMC_Bank1E->BWTR[2] = 0x0fffffff; +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ +#if defined(STM32F469xx) || defined(STM32F479xx) + /* Configure and enable Bank1_SRAM2 */ + FMC_Bank1->BTCR[2] = 0x00001091; + FMC_Bank1->BTCR[3] = 0x00110212; + FMC_Bank1E->BWTR[2] = 0x0fffffff; +#endif /* STM32F469xx || STM32F479xx */ + + (void)(tmp); +} +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ +#elif defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) +/** + * @brief Setup the external memory controller. + * Called in startup_stm32f4xx.s before jump to main. + * This function configures the external memories (SRAM/SDRAM) + * This SRAM/SDRAM will be used as program data memory (including heap and stack). + * @param None + * @retval None + */ +void SystemInit_ExtMemCtl(void) +{ + __IO uint32_t tmp = 0x00; +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) +#if defined (DATA_IN_ExtSDRAM) + register uint32_t tmpreg = 0, timeout = 0xFFFF; + register __IO uint32_t index; + +#if defined(STM32F446xx) + /* Enable GPIOA, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG interface + clock */ + RCC->AHB1ENR |= 0x0000007D; +#else + /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface + clock */ + RCC->AHB1ENR |= 0x000001F8; +#endif /* STM32F446xx */ + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN); + +#if defined(STM32F446xx) + /* Connect PAx pins to FMC Alternate function */ + GPIOA->AFR[0] |= 0xC0000000; + GPIOA->AFR[1] |= 0x00000000; + /* Configure PDx pins in Alternate function mode */ + GPIOA->MODER |= 0x00008000; + /* Configure PDx pins speed to 50 MHz */ + GPIOA->OSPEEDR |= 0x00008000; + /* Configure PDx pins Output type to push-pull */ + GPIOA->OTYPER |= 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOA->PUPDR |= 0x00000000; + + /* Connect PCx pins to FMC Alternate function */ + GPIOC->AFR[0] |= 0x00CC0000; + GPIOC->AFR[1] |= 0x00000000; + /* Configure PDx pins in Alternate function mode */ + GPIOC->MODER |= 0x00000A00; + /* Configure PDx pins speed to 50 MHz */ + GPIOC->OSPEEDR |= 0x00000A00; + /* Configure PDx pins Output type to push-pull */ + GPIOC->OTYPER |= 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOC->PUPDR |= 0x00000000; +#endif /* STM32F446xx */ + + /* Connect PDx pins to FMC Alternate function */ + GPIOD->AFR[0] = 0x000000CC; + GPIOD->AFR[1] = 0xCC000CCC; + /* Configure PDx pins in Alternate function mode */ + GPIOD->MODER = 0xA02A000A; + /* Configure PDx pins speed to 50 MHz */ + GPIOD->OSPEEDR = 0xA02A000A; + /* Configure PDx pins Output type to push-pull */ + GPIOD->OTYPER = 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOD->PUPDR = 0x00000000; + + /* Connect PEx pins to FMC Alternate function */ + GPIOE->AFR[0] = 0xC00000CC; + GPIOE->AFR[1] = 0xCCCCCCCC; + /* Configure PEx pins in Alternate function mode */ + GPIOE->MODER = 0xAAAA800A; + /* Configure PEx pins speed to 50 MHz */ + GPIOE->OSPEEDR = 0xAAAA800A; + /* Configure PEx pins Output type to push-pull */ + GPIOE->OTYPER = 0x00000000; + /* No pull-up, pull-down for PEx pins */ + GPIOE->PUPDR = 0x00000000; + + /* Connect PFx pins to FMC Alternate function */ + GPIOF->AFR[0] = 0xCCCCCCCC; + GPIOF->AFR[1] = 0xCCCCCCCC; + /* Configure PFx pins in Alternate function mode */ + GPIOF->MODER = 0xAA800AAA; + /* Configure PFx pins speed to 50 MHz */ + GPIOF->OSPEEDR = 0xAA800AAA; + /* Configure PFx pins Output type to push-pull */ + GPIOF->OTYPER = 0x00000000; + /* No pull-up, pull-down for PFx pins */ + GPIOF->PUPDR = 0x00000000; + + /* Connect PGx pins to FMC Alternate function */ + GPIOG->AFR[0] = 0xCCCCCCCC; + GPIOG->AFR[1] = 0xCCCCCCCC; + /* Configure PGx pins in Alternate function mode */ + GPIOG->MODER = 0xAAAAAAAA; + /* Configure PGx pins speed to 50 MHz */ + GPIOG->OSPEEDR = 0xAAAAAAAA; + /* Configure PGx pins Output type to push-pull */ + GPIOG->OTYPER = 0x00000000; + /* No pull-up, pull-down for PGx pins */ + GPIOG->PUPDR = 0x00000000; + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F469xx) || defined(STM32F479xx) + /* Connect PHx pins to FMC Alternate function */ + GPIOH->AFR[0] = 0x00C0CC00; + GPIOH->AFR[1] = 0xCCCCCCCC; + /* Configure PHx pins in Alternate function mode */ + GPIOH->MODER = 0xAAAA08A0; + /* Configure PHx pins speed to 50 MHz */ + GPIOH->OSPEEDR = 0xAAAA08A0; + /* Configure PHx pins Output type to push-pull */ + GPIOH->OTYPER = 0x00000000; + /* No pull-up, pull-down for PHx pins */ + GPIOH->PUPDR = 0x00000000; + + /* Connect PIx pins to FMC Alternate function */ + GPIOI->AFR[0] = 0xCCCCCCCC; + GPIOI->AFR[1] = 0x00000CC0; + /* Configure PIx pins in Alternate function mode */ + GPIOI->MODER = 0x0028AAAA; + /* Configure PIx pins speed to 50 MHz */ + GPIOI->OSPEEDR = 0x0028AAAA; + /* Configure PIx pins Output type to push-pull */ + GPIOI->OTYPER = 0x00000000; + /* No pull-up, pull-down for PIx pins */ + GPIOI->PUPDR = 0x00000000; +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ + +/*-- FMC Configuration -------------------------------------------------------*/ + /* Enable the FMC interface clock */ + RCC->AHB3ENR |= 0x00000001; + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); + + /* Configure and enable SDRAM bank1 */ +#if defined(STM32F446xx) + FMC_Bank5_6->SDCR[0] = 0x00001954; +#else + FMC_Bank5_6->SDCR[0] = 0x000019E4; +#endif /* STM32F446xx */ + FMC_Bank5_6->SDTR[0] = 0x01115351; + + /* SDRAM initialization sequence */ + /* Clock enable command */ + FMC_Bank5_6->SDCMR = 0x00000011; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Delay */ + for (index = 0; index<1000; index++); + + /* PALL command */ + FMC_Bank5_6->SDCMR = 0x00000012; + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Auto refresh command */ +#if defined(STM32F446xx) + FMC_Bank5_6->SDCMR = 0x000000F3; +#else + FMC_Bank5_6->SDCMR = 0x00000073; +#endif /* STM32F446xx */ + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* MRD register program */ +#if defined(STM32F446xx) + FMC_Bank5_6->SDCMR = 0x00044014; +#else + FMC_Bank5_6->SDCMR = 0x00046014; +#endif /* STM32F446xx */ + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + timeout = 0xFFFF; + while((tmpreg != 0) && (timeout-- > 0)) + { + tmpreg = FMC_Bank5_6->SDSR & 0x00000020; + } + + /* Set refresh count */ + tmpreg = FMC_Bank5_6->SDRTR; +#if defined(STM32F446xx) + FMC_Bank5_6->SDRTR = (tmpreg | (0x0000050C<<1)); +#else + FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1)); +#endif /* STM32F446xx */ + + /* Disable write protection */ + tmpreg = FMC_Bank5_6->SDCR[0]; + FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF); +#endif /* DATA_IN_ExtSDRAM */ +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */ + +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\ + || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ + || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) + +#if defined(DATA_IN_ExtSRAM) +/*-- GPIOs Configuration -----------------------------------------------------*/ + /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */ + RCC->AHB1ENR |= 0x00000078; + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN); + + /* Connect PDx pins to FMC Alternate function */ + GPIOD->AFR[0] = 0x00CCC0CC; + GPIOD->AFR[1] = 0xCCCCCCCC; + /* Configure PDx pins in Alternate function mode */ + GPIOD->MODER = 0xAAAA0A8A; + /* Configure PDx pins speed to 100 MHz */ + GPIOD->OSPEEDR = 0xFFFF0FCF; + /* Configure PDx pins Output type to push-pull */ + GPIOD->OTYPER = 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOD->PUPDR = 0x00000000; + + /* Connect PEx pins to FMC Alternate function */ + GPIOE->AFR[0] = 0xC00CC0CC; + GPIOE->AFR[1] = 0xCCCCCCCC; + /* Configure PEx pins in Alternate function mode */ + GPIOE->MODER = 0xAAAA828A; + /* Configure PEx pins speed to 100 MHz */ + GPIOE->OSPEEDR = 0xFFFFC3CF; + /* Configure PEx pins Output type to push-pull */ + GPIOE->OTYPER = 0x00000000; + /* No pull-up, pull-down for PEx pins */ + GPIOE->PUPDR = 0x00000000; + + /* Connect PFx pins to FMC Alternate function */ + GPIOF->AFR[0] = 0x00CCCCCC; + GPIOF->AFR[1] = 0xCCCC0000; + /* Configure PFx pins in Alternate function mode */ + GPIOF->MODER = 0xAA000AAA; + /* Configure PFx pins speed to 100 MHz */ + GPIOF->OSPEEDR = 0xFF000FFF; + /* Configure PFx pins Output type to push-pull */ + GPIOF->OTYPER = 0x00000000; + /* No pull-up, pull-down for PFx pins */ + GPIOF->PUPDR = 0x00000000; + + /* Connect PGx pins to FMC Alternate function */ + GPIOG->AFR[0] = 0x00CCCCCC; + GPIOG->AFR[1] = 0x000000C0; + /* Configure PGx pins in Alternate function mode */ + GPIOG->MODER = 0x00085AAA; + /* Configure PGx pins speed to 100 MHz */ + GPIOG->OSPEEDR = 0x000CAFFF; + /* Configure PGx pins Output type to push-pull */ + GPIOG->OTYPER = 0x00000000; + /* No pull-up, pull-down for PGx pins */ + GPIOG->PUPDR = 0x00000000; + +/*-- FMC/FSMC Configuration --------------------------------------------------*/ + /* Enable the FMC/FSMC interface clock */ + RCC->AHB3ENR |= 0x00000001; + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); + /* Configure and enable Bank1_SRAM2 */ + FMC_Bank1->BTCR[2] = 0x00001011; + FMC_Bank1->BTCR[3] = 0x00000201; + FMC_Bank1E->BWTR[2] = 0x0fffffff; +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ +#if defined(STM32F469xx) || defined(STM32F479xx) + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); + /* Configure and enable Bank1_SRAM2 */ + FMC_Bank1->BTCR[2] = 0x00001091; + FMC_Bank1->BTCR[3] = 0x00110212; + FMC_Bank1E->BWTR[2] = 0x0fffffff; +#endif /* STM32F469xx || STM32F479xx */ +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx)\ + || defined(STM32F412Zx) || defined(STM32F412Vx) + /* Delay after an RCC peripheral clock enabling */ + tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN); + /* Configure and enable Bank1_SRAM2 */ + FSMC_Bank1->BTCR[2] = 0x00001011; + FSMC_Bank1->BTCR[3] = 0x00000201; + FSMC_Bank1E->BWTR[2] = 0x0FFFFFFF; +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F412Zx || STM32F412Vx */ + +#endif /* DATA_IN_ExtSRAM */ +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\ + STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx */ + (void)(tmp); +} +#endif /* DATA_IN_ExtSRAM && DATA_IN_ExtSDRAM */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/app/startup/tx_initialize_low_level.S b/STMicroelectronics/STM32F429ZI-Nucleo/app/startup/tx_initialize_low_level.S new file mode 100644 index 00000000..667c3cb2 --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/app/startup/tx_initialize_low_level.S @@ -0,0 +1,196 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Initialize */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .global _tx_thread_system_stack_ptr + .global _tx_initialize_unused_memory + .global __RAM_segment_used_end__ + .global _tx_timer_interrupt + .global __main + .global _vectors + .global __tx_NMIHandler // NMI + .global __tx_BadHandler // HardFault + .global __tx_SVCallHandler // SVCall + .global __tx_DBGHandler // Monitor + .global __tx_PendSVHandler // PendSV + .global __tx_SysTickHandler // SysTick + .global __tx_IntHandler // Int 0 + +SYSTEM_CLOCK = 168000000 +SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1) + + .text 32 + .align 4 + .syntax unified +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_initialize_low_level Cortex-Mx/GNU */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for any low-level processor */ +/* initialization, including setting up interrupt vectors, setting */ +/* up a periodic timer interrupt source, saving the system stack */ +/* pointer for use in ISR processing later, and finding the first */ +/* available RAM memory address for tx_application_define. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter ThreadX entry function */ +/* */ +/**************************************************************************/ +// VOID _tx_initialize_low_level(VOID) +// { + .global _tx_initialize_low_level + .thumb_func +_tx_initialize_low_level: + + /* Ensure that interrupts are disabled. */ + CPSID i + + /* Set base of available memory to end of non-initialised RAM area. */ + LDR r0, =_tx_initialize_unused_memory // Build address of unused memory pointer + LDR r1, =__RAM_segment_used_end__ // Build first free address + ADD r1, r1, #4 // + STR r1, [r0] // Setup first unused memory pointer + + /* Setup Vector Table Offset Register. */ + MOV r0, #0xE000E000 // Build address of NVIC registers + LDR r1, =_vectors // Pickup address of vector table + STR r1, [r0, #0xD08] // Set vector table address + + /* Set system stack pointer from vector value. */ + LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer + LDR r1, =_vectors // Pickup address of vector table + LDR r1, [r1] // Pickup reset stack pointer + STR r1, [r0] // Save system stack pointer + +#ifndef TX_NO_TIMER + /* Configure SysTick. */ + MOV r0, #0xE000E000 // Build address of NVIC registers + LDR r1, =SYSTICK_CYCLES + STR r1, [r0, #0x14] // Setup SysTick Reload Value + MOV r1, #0x7 // Build SysTick Control Enable Value + STR r1, [r0, #0x10] // Setup SysTick Control +#endif + + /* Configure handler priorities. */ + LDR r1, =0x00000000 // Rsrv, UsgF, BusF, MemM + STR r1, [r0, #0xD18] // Setup System Handlers 4-7 Priority Registers + LDR r1, =0xFF000000 // SVCl, Rsrv, Rsrv, Rsrv + STR r1, [r0, #0xD1C] // Setup System Handlers 8-11 Priority Registers + // Note: SVC must be lowest priority, which is 0xFF + LDR r1, =0x40FF0000 // SysT, PnSV, Rsrv, DbgM + STR r1, [r0, #0xD20] // Setup System Handlers 12-15 Priority Registers + // Note: PnSV must be lowest priority, which is 0xFF + + /* Return to caller. */ + BX lr +// } + +/* Define shells for each of the unused vectors. */ + .global __tx_BadHandler + .thumb_func +__tx_BadHandler: + B __tx_BadHandler + +/* added to catch the hardfault */ + .global __tx_HardfaultHandler + .thumb_func +__tx_HardfaultHandler: + B __tx_HardfaultHandler + +/* added to catch the SVC */ + .global __tx_SVCallHandler + .thumb_func +__tx_SVCallHandler: + B __tx_SVCallHandler + +/* Generic interrupt handler template */ + .global __tx_IntHandler + .thumb_func +__tx_IntHandler: +// VOID InterruptHandler (VOID) +// { + PUSH {r0, lr} +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + BL _tx_execution_isr_enter // Call the ISR enter function +#endif + /* Do interrupt handler work here */ + /* BL .... */ +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + BL _tx_execution_isr_exit // Call the ISR exit function +#endif + POP {r0, lr} + BX lr +// } + +#ifndef TX_NO_TIMER +/* System Tick timer interrupt handler */ + .global __tx_SysTickHandler + .global SysTick_Handler + .thumb_func +__tx_SysTickHandler: + .thumb_func +SysTick_Handler: +// VOID SysTick_Handler (VOID) +// { + PUSH {r0, lr} +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + BL _tx_execution_isr_enter // Call the ISR enter function +#endif + BL _tx_timer_interrupt +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + BL _tx_execution_isr_exit // Call the ISR exit function +#endif + POP {r0, lr} + BX lr +// } +#endif + +/* NMI, DBG handlers */ + .global __tx_NMIHandler + .thumb_func +__tx_NMIHandler: + B __tx_NMIHandler + + .global __tx_DBGHandler + .thumb_func +__tx_DBGHandler: + B __tx_DBGHandler diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/app/stm32f4xx_hal_conf.h b/STMicroelectronics/STM32F429ZI-Nucleo/app/stm32f4xx_hal_conf.h new file mode 100644 index 00000000..d5c4990f --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/app/stm32f4xx_hal_conf.h @@ -0,0 +1,495 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f4xx_hal_conf_template.h + * @author MCD Application Team + * @brief HAL configuration template file. + * This file should be copied to the application folder and renamed + * to stm32f4xx_hal_conf.h. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_HAL_CONF_H +#define __STM32F4xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED + + /* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_ADC_MODULE_ENABLED */ +/* #define HAL_CAN_MODULE_ENABLED */ +/* #define HAL_CRC_MODULE_ENABLED */ +/* #define HAL_CAN_LEGACY_MODULE_ENABLED */ +/* #define HAL_DAC_MODULE_ENABLED */ +/* #define HAL_DCMI_MODULE_ENABLED */ +/* #define HAL_DMA2D_MODULE_ENABLED */ +/* #define HAL_ETH_MODULE_ENABLED */ +/* #define HAL_ETH_LEGACY_MODULE_ENABLED */ +/* #define HAL_NAND_MODULE_ENABLED */ +/* #define HAL_NOR_MODULE_ENABLED */ +/* #define HAL_PCCARD_MODULE_ENABLED */ +/* #define HAL_SRAM_MODULE_ENABLED */ +/* #define HAL_SDRAM_MODULE_ENABLED */ +/* #define HAL_HASH_MODULE_ENABLED */ +/* #define HAL_I2C_MODULE_ENABLED */ +/* #define HAL_I2S_MODULE_ENABLED */ +/* #define HAL_IWDG_MODULE_ENABLED */ +/* #define HAL_LTDC_MODULE_ENABLED */ +/* #define HAL_RNG_MODULE_ENABLED */ +/* #define HAL_RTC_MODULE_ENABLED */ +/* #define HAL_SAI_MODULE_ENABLED */ +/* #define HAL_SD_MODULE_ENABLED */ +/* #define HAL_MMC_MODULE_ENABLED */ +/* #define HAL_SPI_MODULE_ENABLED */ +/* #define HAL_TIM_MODULE_ENABLED */ +#define HAL_UART_MODULE_ENABLED +/* #define HAL_USART_MODULE_ENABLED */ +/* #define HAL_IRDA_MODULE_ENABLED */ +/* #define HAL_SMARTCARD_MODULE_ENABLED */ +/* #define HAL_SMBUS_MODULE_ENABLED */ +/* #define HAL_WWDG_MODULE_ENABLED */ +/* #define HAL_PCD_MODULE_ENABLED */ +/* #define HAL_HCD_MODULE_ENABLED */ +/* #define HAL_DSI_MODULE_ENABLED */ +/* #define HAL_QSPI_MODULE_ENABLED */ +/* #define HAL_QSPI_MODULE_ENABLED */ +/* #define HAL_CEC_MODULE_ENABLED */ +/* #define HAL_FMPI2C_MODULE_ENABLED */ +/* #define HAL_FMPSMBUS_MODULE_ENABLED */ +/* #define HAL_SPDIFRX_MODULE_ENABLED */ +/* #define HAL_DFSDM_MODULE_ENABLED */ +/* #define HAL_LPTIM_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## HSE/HSI Values adaptation ##################### */ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE 32000U /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature.*/ +/** + * @brief External Low Speed oscillator (LSE) value. + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE 32768U /*!< Value of the External Low Speed oscillator in Hz */ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for I2S peripheral + * This value is used by the I2S HAL module to compute the I2S clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) + #define EXTERNAL_CLOCK_VALUE 12288000U /*!< Value of the External audio frequency in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE 3300U /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY 0U /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 1U +#define INSTRUCTION_CACHE_ENABLE 1U +#define DATA_CACHE_ENABLE 1U + +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ +#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */ +#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ +#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_FMPI2C_REGISTER_CALLBACKS 0U /* FMPI2C register callback disabled */ +#define USE_HAL_FMPSMBUS_REGISTER_CALLBACKS 0U /* FMPSMBUS register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */ +#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_PCCARD_REGISTER_CALLBACKS 0U /* PCCARD register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2U +#define MAC_ADDR1 0U +#define MAC_ADDR2 0U +#define MAC_ADDR3 0U +#define MAC_ADDR4 0U +#define MAC_ADDR5 0U + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE 1524 /* buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ +#define ETH_RXBUFNB 4U /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB 4U /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ + +/* DP83848_PHY_ADDRESS Address*/ +#define DP83848_PHY_ADDRESS +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY 0x000000FFU +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY 0x00000FFFU + +#define PHY_READ_TO 0x0000FFFFU +#define PHY_WRITE_TO 0x0000FFFFU + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ +#define PHY_SR ((uint16_t)) /*!< PHY status register Offset */ + +#define PHY_SPEED_STATUS ((uint16_t)) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)) /*!< PHY Duplex mask */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver +* Activated: CRC code is present inside driver +* Deactivated: CRC code cleaned from driver +*/ + +#define USE_SPI_CRC 0U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32f4xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32f4xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED + #include "stm32f4xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32f4xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32f4xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32f4xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32f4xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CAN_LEGACY_MODULE_ENABLED + #include "stm32f4xx_hal_can_legacy.h" +#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32f4xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32f4xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED + #include "stm32f4xx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32f4xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED + #include "stm32f4xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED + #include "stm32f4xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_ETH_LEGACY_MODULE_ENABLED + #include "stm32f4xx_hal_eth_legacy.h" +#endif /* HAL_ETH_LEGACY_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32f4xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32f4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32f4xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_PCCARD_MODULE_ENABLED + #include "stm32f4xx_hal_pccard.h" +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED + #include "stm32f4xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32f4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED + #include "stm32f4xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32f4xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32f4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED + #include "stm32f4xx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32f4xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32f4xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32f4xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED + #include "stm32f4xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32f4xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32f4xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32f4xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32f4xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32f4xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32f4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32f4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32f4xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32f4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32f4xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_DSI_MODULE_ENABLED + #include "stm32f4xx_hal_dsi.h" +#endif /* HAL_DSI_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED + #include "stm32f4xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED + #include "stm32f4xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_FMPI2C_MODULE_ENABLED + #include "stm32f4xx_hal_fmpi2c.h" +#endif /* HAL_FMPI2C_MODULE_ENABLED */ + +#ifdef HAL_FMPSMBUS_MODULE_ENABLED + #include "stm32f4xx_hal_fmpsmbus.h" +#endif /* HAL_FMPSMBUS_MODULE_ENABLED */ + +#ifdef HAL_SPDIFRX_MODULE_ENABLED + #include "stm32f4xx_hal_spdifrx.h" +#endif /* HAL_SPDIFRX_MODULE_ENABLED */ + +#ifdef HAL_DFSDM_MODULE_ENABLED + #include "stm32f4xx_hal_dfsdm.h" +#endif /* HAL_DFSDM_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED + #include "stm32f4xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED + #include "stm32f4xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_CONF_H */ diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/app/stm32f4xx_hal_msp.c b/STMicroelectronics/STM32F429ZI-Nucleo/app/stm32f4xx_hal_msp.c new file mode 100644 index 00000000..4a62f729 --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/app/stm32f4xx_hal_msp.c @@ -0,0 +1,147 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f4xx_hal_msp.c + * @brief This file provides code for the MSP Initialization + * and de-Initialization codes. + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN TD */ + +/* USER CODE END TD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN Define */ + +/* USER CODE END Define */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN Macro */ + +/* USER CODE END Macro */ + +/* Private variables ---------------------------------------------------------*/ +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* External functions --------------------------------------------------------*/ +/* USER CODE BEGIN ExternalFunctions */ + +/* USER CODE END ExternalFunctions */ + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ +/** + * Initializes the Global MSP. + */ +void HAL_MspInit(void) +{ + + /* USER CODE BEGIN MspInit 0 */ + + /* USER CODE END MspInit 0 */ + + __HAL_RCC_SYSCFG_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + + /* System interrupt init*/ + + /* USER CODE BEGIN MspInit 1 */ + + /* USER CODE END MspInit 1 */ +} + +/** + * @brief UART MSP Initialization + * This function configures the hardware resources used in this example + * @param huart: UART handle pointer + * @retval None + */ +void HAL_UART_MspInit(UART_HandleTypeDef* huart) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(huart->Instance==USART3) + { + /* USER CODE BEGIN USART3_MspInit 0 */ + + /* USER CODE END USART3_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_USART3_CLK_ENABLE(); + + __HAL_RCC_GPIOD_CLK_ENABLE(); + /**USART3 GPIO Configuration + PD8 ------> USART3_TX + PD9 ------> USART3_RX + */ + GPIO_InitStruct.Pin = STLK_RX_Pin|STLK_TX_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF7_USART3; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + /* USER CODE BEGIN USART3_MspInit 1 */ + + /* USER CODE END USART3_MspInit 1 */ + + } + +} + +/** + * @brief UART MSP De-Initialization + * This function freeze the hardware resources used in this example + * @param huart: UART handle pointer + * @retval None + */ +void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) +{ + if(huart->Instance==USART3) + { + /* USER CODE BEGIN USART3_MspDeInit 0 */ + + /* USER CODE END USART3_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USART3_CLK_DISABLE(); + + /**USART3 GPIO Configuration + PD8 ------> USART3_TX + PD9 ------> USART3_RX + */ + HAL_GPIO_DeInit(GPIOD, STLK_RX_Pin|STLK_TX_Pin); + + /* USER CODE BEGIN USART3_MspDeInit 1 */ + + /* USER CODE END USART3_MspDeInit 1 */ + } + +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/app/syscalls.c b/STMicroelectronics/STM32F429ZI-Nucleo/app/syscalls.c new file mode 100644 index 00000000..0197f26b --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/app/syscalls.c @@ -0,0 +1,176 @@ +/** + ****************************************************************************** + * @file syscalls.c + * @author Auto-generated by STM32CubeIDE + * @brief STM32CubeIDE Minimal System calls file + * + * For more information about which c-functions + * need which of these lowlevel functions + * please consult the Newlib libc-manual + ****************************************************************************** + * @attention + * + * Copyright (c) 2020-2026 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Variables */ +extern int __io_putchar(int ch) __attribute__((weak)); +extern int __io_getchar(void) __attribute__((weak)); + + +char *__env[1] = { 0 }; +char **environ = __env; + + +/* Functions */ +void initialise_monitor_handles() +{ +} + +int _getpid(void) +{ + return 1; +} + +int _kill(int pid, int sig) +{ + (void)pid; + (void)sig; + errno = EINVAL; + return -1; +} + +void _exit (int status) +{ + _kill(status, -1); + while (1) {} /* Make sure we hang here */ +} + +__attribute__((weak)) int _read(int file, char *ptr, int len) +{ + (void)file; + int DataIdx; + + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + *ptr++ = __io_getchar(); + } + + return len; +} + +__attribute__((weak)) int _write(int file, char *ptr, int len) +{ + (void)file; + int DataIdx; + + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + __io_putchar(*ptr++); + } + return len; +} + +int _close(int file) +{ + (void)file; + return -1; +} + + +int _fstat(int file, struct stat *st) +{ + (void)file; + st->st_mode = S_IFCHR; + return 0; +} + +int _isatty(int file) +{ + (void)file; + return 1; +} + +int _lseek(int file, int ptr, int dir) +{ + (void)file; + (void)ptr; + (void)dir; + return 0; +} + +int _open(char *path, int flags, ...) +{ + (void)path; + (void)flags; + /* Pretend like we always fail */ + return -1; +} + +int _wait(int *status) +{ + (void)status; + errno = ECHILD; + return -1; +} + +int _unlink(char *name) +{ + (void)name; + errno = ENOENT; + return -1; +} + +int _times(struct tms *buf) +{ + (void)buf; + return -1; +} + +int _stat(char *file, struct stat *st) +{ + (void)file; + st->st_mode = S_IFCHR; + return 0; +} + +int _link(char *old, char *new) +{ + (void)old; + (void)new; + errno = EMLINK; + return -1; +} + +int _fork(void) +{ + errno = EAGAIN; + return -1; +} + +int _execve(char *name, char **argv, char **env) +{ + (void)name; + (void)argv; + (void)env; + errno = ENOMEM; + return -1; +} diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/app/sysmem.c b/STMicroelectronics/STM32F429ZI-Nucleo/app/sysmem.c new file mode 100644 index 00000000..23ea8e02 --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/app/sysmem.c @@ -0,0 +1,79 @@ +/** + ****************************************************************************** + * @file sysmem.c + * @author Generated by STM32CubeIDE + * @brief STM32CubeIDE System Memory calls file + * + * For more information about which C functions + * need which of these lowlevel functions + * please consult the newlib libc manual + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes */ +#include +#include + +/** + * Pointer to the current high watermark of the heap usage + */ +static uint8_t *__sbrk_heap_end = NULL; + +/** + * @brief _sbrk() allocates memory to the newlib heap and is used by malloc + * and others from the C library + * + * @verbatim + * ############################################################################ + * # .data # .bss # newlib heap # MSP stack # + * # # # # Reserved by _Min_Stack_Size # + * ############################################################################ + * ^-- RAM start ^-- _end _estack, RAM end --^ + * @endverbatim + * + * This implementation starts allocating at the '_end' linker symbol + * The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack + * The implementation considers '_estack' linker symbol to be RAM end + * NOTE: If the MSP stack, at any point during execution, grows larger than the + * reserved size, please increase the '_Min_Stack_Size'. + * + * @param incr Memory size + * @return Pointer to allocated memory + */ +void *_sbrk(ptrdiff_t incr) +{ + extern uint8_t _end; /* Symbol defined in the linker script */ + extern uint8_t _estack; /* Symbol defined in the linker script */ + extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */ + const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size; + const uint8_t *max_heap = (uint8_t *)stack_limit; + uint8_t *prev_heap_end; + + /* Initialize heap end at first call */ + if (NULL == __sbrk_heap_end) + { + __sbrk_heap_end = &_end; + } + + /* Protect heap from growing into the reserved MSP stack */ + if (__sbrk_heap_end + incr > max_heap) + { + errno = ENOMEM; + return (void *)-1; + } + + prev_heap_end = __sbrk_heap_end; + __sbrk_heap_end += incr; + + return (void *)prev_heap_end; +} diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/cmake/FindCMSIS.cmake b/STMicroelectronics/STM32F429ZI-Nucleo/cmake/FindCMSIS.cmake new file mode 100644 index 00000000..33740779 --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/cmake/FindCMSIS.cmake @@ -0,0 +1,46 @@ +# Copyright (c) Microsoft +# 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 +# +# Contributors: +# Microsoft - Initial version +# Frédéric Desbiens - 2024 version. +# Ali Eissa - 2026 version. + +set(CMSIS_COMMON_HEADERS + arm_common_tables.h + arm_const_structs.h + arm_math.h + core_cmFunc.h + core_cmInstr.h + core_cmSimd.h +) + +message(STATUS "STM32F4xx library check: " ${STM32Cube_DIR}) + +list(APPEND CMSIS_COMMON_HEADERS core_cm4.h) +set(CMSIS_DEVICE_HEADERS stm32f4xx.h system_stm32f4xx.h) + +find_path(CMSIS_COMMON_INCLUDE_DIR ${CMSIS_COMMON_HEADERS} + HINTS ${STM32Cube_DIR}/Drivers/CMSIS/Include/ + CMAKE_FIND_ROOT_PATH_BOTH +) + +find_path(CMSIS_DEVICE_INCLUDE_DIR ${CMSIS_DEVICE_HEADERS} + HINTS ${STM32Cube_DIR}/Drivers/CMSIS/Device/ST/STM32${STM32_FAMILY}xx/Include + CMAKE_FIND_ROOT_PATH_BOTH +) + +set(CMSIS_INCLUDE_DIRS + ${CMSIS_DEVICE_INCLUDE_DIR} + ${CMSIS_COMMON_INCLUDE_DIR} +) + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(CMSIS DEFAULT_MSG CMSIS_INCLUDE_DIRS) diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/cmake/FindSTM32HAL.cmake b/STMicroelectronics/STM32F429ZI-Nucleo/cmake/FindSTM32HAL.cmake new file mode 100644 index 00000000..1216a9db --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/cmake/FindSTM32HAL.cmake @@ -0,0 +1,86 @@ +# Copyright (c) Microsoft +# 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 +# +# Contributors: +# Microsoft - Initial version +# Frédéric Desbiens - 2024 version. +# Ali Eissa - 2026 version. + +set(HAL_COMPONENTS adc can cec cortex crc cryp dac dcmi dma dma2d eth exti flash + flash_ramfunc fmpi2c gpio hash hcd i2c i2s irda iwdg ltdc + nand nor pccard pcd pwr qspi rcc rng rtc sai sd sdram + smartcard spdifrx spi sram tim timebase_tim uart usart wwdg) + +set(HAL_REQUIRED_COMPONENTS cortex pwr rcc) + +# Components that have _ex sources +set(HAL_EX_COMPONENTS adc cryp dac dcmi dma flash fmpi2c hash i2c i2s pcd + pwr rcc rtc sai tim) + +set(HAL_PREFIX stm32f4xx_) + +set(HAL_HEADERS + ${HAL_PREFIX}hal.h + ${HAL_PREFIX}hal_def.h +) + +set(HAL_SRCS + ${HAL_PREFIX}hal.c +) + +if(NOT STM32HAL_FIND_COMPONENTS) + set(STM32HAL_FIND_COMPONENTS ${HAL_COMPONENTS}) + message(STATUS "No STM32HAL components selected, using all: ${STM32HAL_FIND_COMPONENTS}") +else() + message(STATUS "STM32HAL components selected, using: ${STM32HAL_FIND_COMPONENTS}") +endif() + +foreach(cmp ${HAL_REQUIRED_COMPONENTS}) + list(FIND STM32HAL_FIND_COMPONENTS ${cmp} STM32HAL_FOUND_INDEX) + if(${STM32HAL_FOUND_INDEX} LESS 0) + list(APPEND STM32HAL_FIND_COMPONENTS ${cmp}) + endif() +endforeach() + +foreach(cmp ${STM32HAL_FIND_COMPONENTS}) + list(FIND HAL_COMPONENTS ${cmp} STM32HAL_FOUND_INDEX) + if(${STM32HAL_FOUND_INDEX} LESS 0) + message(FATAL_ERROR "Unknown STM32HAL component: ${cmp}. Available components: ${HAL_COMPONENTS}") + else() + list(APPEND HAL_HEADERS ${HAL_PREFIX}hal_${cmp}.h) + list(APPEND HAL_SRCS ${HAL_PREFIX}hal_${cmp}.c) + endif() + list(FIND HAL_EX_COMPONENTS ${cmp} STM32HAL_FOUND_INDEX) + if(NOT (${STM32HAL_FOUND_INDEX} LESS 0)) + list(APPEND HAL_HEADERS ${HAL_PREFIX}hal_${cmp}_ex.h) + list(APPEND HAL_SRCS ${HAL_PREFIX}hal_${cmp}_ex.c) + endif() +endforeach() + +list(REMOVE_DUPLICATES HAL_HEADERS) +list(REMOVE_DUPLICATES HAL_SRCS) + +find_path(STM32HAL_INCLUDE_DIR ${HAL_HEADERS} + HINTS ${STM32Cube_DIR}/Drivers/STM32${STM32_FAMILY}xx_HAL_Driver/Inc + CMAKE_FIND_ROOT_PATH_BOTH +) + +foreach(HAL_SRC ${HAL_SRCS}) + string(MAKE_C_IDENTIFIER "${HAL_SRC}" HAL_SRC_CLEAN) + set(HAL_${HAL_SRC_CLEAN}_FILE HAL_SRC_FILE-NOTFOUND) + find_file(HAL_${HAL_SRC_CLEAN}_FILE ${HAL_SRC} + HINTS ${STM32Cube_DIR}/Drivers/STM32${STM32_FAMILY}xx_HAL_Driver/Src + CMAKE_FIND_ROOT_PATH_BOTH + ) + list(APPEND STM32HAL_SOURCES ${HAL_${HAL_SRC_CLEAN}_FILE}) +endforeach() + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(STM32HAL DEFAULT_MSG STM32HAL_INCLUDE_DIR STM32HAL_SOURCES) diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/cmake/arm-gcc-cortex-m4.cmake b/STMicroelectronics/STM32F429ZI-Nucleo/cmake/arm-gcc-cortex-m4.cmake new file mode 100644 index 00000000..6f22d0f8 --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/cmake/arm-gcc-cortex-m4.cmake @@ -0,0 +1,23 @@ +# Copyright (c) Microsoft +# 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 +# +# Contributors: +# Microsoft - Initial version +# Frédéric Desbiens - 2024 version. +# Ali Eissa - 2026 version. + +# Define the CPU architecture for ThreadX +set(THREADX_ARCH "cortex_m4") +set(THREADX_TOOLCHAIN "gnu") + +# Cortex-M4 compiler options +set(MCPU_FLAGS "-mthumb -mcpu=cortex-m4") +set(VFP_FLAGS "-mfloat-abi=hard -mfpu=fpv4-sp-d16") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-gcc-cortex-toolchain.cmake) diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/cmake/arm-gcc-cortex-toolchain.cmake b/STMicroelectronics/STM32F429ZI-Nucleo/cmake/arm-gcc-cortex-toolchain.cmake new file mode 100644 index 00000000..b358614c --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/cmake/arm-gcc-cortex-toolchain.cmake @@ -0,0 +1,78 @@ +# Copyright (c) Microsoft +# Copyright (c) 2024 Eclipse Foundation +# +# 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 +# +# Contributors: +# Microsoft - Initial version +# Frédéric Desbiens - 2024 version. + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR arm) +set(TARGET_TRIPLET "arm-none-eabi-") + +# default to Debug build +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build, options are: Debug Release." FORCE) +endif() + +# do some windows specific logic +if(WIN32) + set(TOOLCHAIN_EXT ".exe") +else() + set(TOOLCHAIN_EXT "") +endif(WIN32) + +find_program(COMPILER_ON_PATH "${TARGET_TRIPLET}gcc${TOOLCHAIN_EXT}") + +if(DEFINED ENV{ARM_GCC_PATH}) + # use the environment variable first + file(TO_CMAKE_PATH $ENV{ARM_GCC_PATH} ARM_TOOLCHAIN_PATH) + message(STATUS "Using ENV variable ARM_GCC_PATH = ${ARM_TOOLCHAIN_PATH}") +elseif(COMPILER_ON_PATH) + # then check on the current path + get_filename_component(ARM_TOOLCHAIN_PATH ${COMPILER_ON_PATH} DIRECTORY) + message(STATUS "Using ARM GCC from path = ${ARM_TOOLCHAIN_PATH}") +else() + message(FATAL_ERROR "Unable to find ARM GCC. Either add to your PATH, or define ARM_GCC_PATH to the compiler location") +endif() + +# Perform compiler test with the static library +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +set(CMAKE_C_COMPILER ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc${TOOLCHAIN_EXT}) +set(CMAKE_CXX_COMPILER ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}g++${TOOLCHAIN_EXT}) +set(CMAKE_ASM_COMPILER ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc${TOOLCHAIN_EXT}) +set(CMAKE_LINKER ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc${TOOLCHAIN_EXT}) +set(CMAKE_SIZE_UTIL ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}size${TOOLCHAIN_EXT}) +set(CMAKE_OBJCOPY ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}objcopy${TOOLCHAIN_EXT}) +set(CMAKE_OBJDUMP ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}objdump${TOOLCHAIN_EXT}) +set(CMAKE_NM_UTIL ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc-nm${TOOLCHAIN_EXT}) +set(CMAKE_AR ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc-ar${TOOLCHAIN_EXT}) +set(CMAKE_RANLIB ${ARM_TOOLCHAIN_PATH}/${TARGET_TRIPLET}gcc-ranlib${TOOLCHAIN_EXT}) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +# Compiler and linker flags (removed -Wshadow to avoid third-party ST HAL macro bugs) +set(CMAKE_COMMON_FLAGS "-g3 -ffunction-sections -fdata-sections -fno-strict-aliasing -fno-builtin -fno-common -Wall -Wdouble-promotion -Werror -Wno-unused-parameter") +set(CMAKE_C_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} ${CMAKE_COMMON_FLAGS}") +set(CMAKE_CXX_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} ${CMAKE_COMMON_FLAGS}") +set(CMAKE_ASM_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} ${CMAKE_COMMON_FLAGS}") +set(CMAKE_EXE_LINKER_FLAGS "${LD_FLAGS} --specs=nano.specs -Wl,--gc-sections,-print-memory-usage") + +set(CMAKE_C_FLAGS_DEBUG "-O0") +set(CMAKE_CXX_ASM_FLAGS_DEBUG "-O0") +set(CMAKE_ASM_FLAGS_DEBUG "") +set(CMAKE_EXE_LINKER_FLAGS_DEBUG "") + +set(CMAKE_C_FLAGS_RELEASE "-Os -flto") +set(CMAKE_CXX_FLAGS_RELEASE "-Os -flto") +set(CMAKE_ASM_FLAGS_RELEASE "") +set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-flto") diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/cmake/utilities.cmake b/STMicroelectronics/STM32F429ZI-Nucleo/cmake/utilities.cmake new file mode 100644 index 00000000..3289374d --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/cmake/utilities.cmake @@ -0,0 +1,50 @@ +# Copyright (c) Microsoft +# Copyright (c) 2024 Eclipse Foundation +# +# 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 +# +# Contributors: +# Microsoft - Initial version +# Frédéric Desbiens - 2024 version. + +function(post_build TARGET) + if(CMAKE_C_COMPILER_ID STREQUAL "IAR") + add_custom_target(${TARGET}.bin ALL + DEPENDS ${TARGET} + COMMAND ${CMAKE_IAR_ELFTOOL} --bin ${TARGET}.elf ${TARGET}.bin) + elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") + add_custom_target(${TARGET}.bin ALL + DEPENDS ${TARGET} + COMMAND ${CMAKE_OBJCOPY} -Obinary ${TARGET}.elf ${TARGET}.bin + COMMAND ${CMAKE_OBJCOPY} -Oihex ${TARGET}.elf ${TARGET}.hex) + else() + message(FATAL_ERROR "Unknown CMAKE_C_COMPILER_ID ${CMAKE_C_COMPILER_ID}") + endif() +endfunction() + +function(set_target_linker TARGET LINKER_SCRIPT) + if(CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PRIVATE --config ${LINKER_SCRIPT}) + target_link_options(${TARGET} PRIVATE --map=${TARGET}.map) + elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PRIVATE -T${LINKER_SCRIPT}) + target_link_options(${TARGET} PRIVATE -Wl,-Map=${TARGET}.map) + set_target_properties(${TARGET} PROPERTIES SUFFIX ".elf") + + else() + message(FATAL_ERROR "Unknown CMAKE_C_COMPILER_ID ${CMAKE_C_COMPILER_ID}") + endif() +endfunction() + +macro(print_all_variables) + message(STATUS "print_all_variables------------------------------------------{") + get_cmake_property(_variableNames VARIABLES) + foreach (_variableName ${_variableNames}) + message(STATUS "${_variableName}=${${_variableName}}") + endforeach() + message(STATUS "print_all_variables------------------------------------------}") +endmacro() diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/lib/threadx/tx_user.h b/STMicroelectronics/STM32F429ZI-Nucleo/lib/threadx/tx_user.h new file mode 100644 index 00000000..82aca1eb --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/lib/threadx/tx_user.h @@ -0,0 +1,19 @@ +/**************************************************************************/ +/* Copyright (c) Microsoft */ +/* Copyright (c) 2024 Eclipse Foundation */ +/* */ +/* 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 */ +/* */ +/**************************************************************************/ + +#ifndef TX_USER_H +#define TX_USER_H + +/* Enable hardware FPU register context switching support for Cortex-M4 */ +#define TX_ENABLE_FPU_SUPPORT + +#endif diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/scripts/build.ps1 b/STMicroelectronics/STM32F429ZI-Nucleo/scripts/build.ps1 new file mode 100644 index 00000000..61b4dd5b --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/scripts/build.ps1 @@ -0,0 +1,84 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +param( + [switch]$Clean, + [switch]$Rebuild +) + +$BoardDir = Resolve-Path "$PSScriptRoot/.." +$BUILD_DIR = Join-Path $BoardDir "build" +$NUM_JOBS = 4 + +Write-Host "==========================================" +Write-Host "STM32F429ZI-Nucleo - Build Script" +Write-Host "==========================================" +Write-Host "Board Dir: $BoardDir" +Write-Host "Build Dir: $BUILD_DIR" +Write-Host "" + +# Check for ARM GCC compiler +$armGcc = Get-Command "arm-none-eabi-gcc" -ErrorAction SilentlyContinue +if (!$armGcc -and !$env:ARM_GCC_PATH) { + Write-Host "[WARNING] arm-none-eabi-gcc not found on PATH and ARM_GCC_PATH not set." -ForegroundColor Yellow + Write-Host "" +} + +if ($Clean -or $Rebuild) { + Write-Host "[INFO] Cleaning build directory..." + if (Test-Path $BUILD_DIR) { + Remove-Item -Path $BUILD_DIR -Recurse -Force + } + New-Item -ItemType Directory -Path $BUILD_DIR -Force + Write-Host "[OK] Build directory cleaned" + Write-Host "" +} + +if (!(Test-Path $BUILD_DIR)) { + New-Item -ItemType Directory -Path $BUILD_DIR -Force +} + +Push-Location $BUILD_DIR + +# Reconfigure if CMakeCache.txt or build.ninja is missing, or if forced +if (!(Test-Path "CMakeCache.txt") -or !(Test-Path "build.ninja") -or $Rebuild) { + Write-Host "[INFO] Configuring CMake..." + cmake -G Ninja ` + "-DCMAKE_BUILD_TYPE=Release" ` + .. + if ($LASTEXITCODE -ne 0) { + Write-Host "[ERROR] CMake configuration failed!" -ForegroundColor Red + Pop-Location + exit 1 + } + Write-Host "[OK] CMake configured" + Write-Host "" +} + +Write-Host "[INFO] Building with $NUM_JOBS parallel jobs..." +if (Get-Command ninja -ErrorAction SilentlyContinue) { + ninja -j $NUM_JOBS +} else { + cmake --build . --parallel $NUM_JOBS --config Release +} + +$buildExitCode = $LASTEXITCODE +Pop-Location + +if ($buildExitCode -ne 0) { + Write-Host "[ERROR] Build failed!" -ForegroundColor Red + exit 1 +} + +Write-Host "" +Write-Host "==========================================" +Write-Host "[OK] Build completed successfully!" +Write-Host "==========================================" diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/scripts/build.sh b/STMicroelectronics/STM32F429ZI-Nucleo/scripts/build.sh new file mode 100755 index 00000000..81272b7a --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/scripts/build.sh @@ -0,0 +1,89 @@ +#!/usr/bin/env bash +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +set -e + +# Parse command line options +CLEAN=false +REBUILD=false + +for arg in "$@"; do + case $arg in + --clean) + CLEAN=true + shift + ;; + --rebuild) + REBUILD=true + shift + ;; + *) + ;; + esac +done + +# Set directories +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BOARD_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" +BUILD_DIR="${BOARD_DIR}/build" +NUM_JOBS=4 + +echo "==========================================" +echo "STM32F429ZI-Nucleo - Build Script (Linux)" +echo "==========================================" +echo "Board Dir: ${BOARD_DIR}" +echo "Build Dir: ${BUILD_DIR}" +echo "" + +# Check for ARM GCC compiler toolchain +if ! command -v arm-none-eabi-gcc &> /dev/null && [ -z "${ARM_GCC_PATH}" ]; then + echo "[WARNING] arm-none-eabi-gcc not found on PATH and ARM_GCC_PATH not set." + echo "" +fi + +# Perform cleaning actions if requested +if [ "${CLEAN}" = true ] || [ "${REBUILD}" = true ]; then + echo "[INFO] Cleaning build directory..." + rm -rf "${BUILD_DIR}" + mkdir -p "${BUILD_DIR}" + echo "[OK] Build directory cleaned" + echo "" +fi + +if [ ! -d "${BUILD_DIR}" ]; then + mkdir -p "${BUILD_DIR}" +fi + +cd "${BUILD_DIR}" + +# Run CMake configuration if files are missing or a rebuild is requested +if [ ! -f "CMakeCache.txt" ] || [ ! -f "build.ninja" ] || [ "${REBUILD}" = true ]; then + echo "[INFO] Configuring CMake..." + cmake -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + .. + echo "[OK] CMake configured" + echo "" +fi + +# Execute compilation +echo "[INFO] Building with ${NUM_JOBS} parallel jobs..." +if command -v ninja &> /dev/null; then + ninja -j ${NUM_JOBS} +else + cmake --build . --parallel ${NUM_JOBS} --config Release +fi + +echo "" +echo "==========================================" +echo "[OK] Build completed successfully!" +echo "==========================================" diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/scripts/fetch_sdk.ps1 b/STMicroelectronics/STM32F429ZI-Nucleo/scripts/fetch_sdk.ps1 new file mode 100644 index 00000000..a304dea3 --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/scripts/fetch_sdk.ps1 @@ -0,0 +1,88 @@ +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +$BoardDir = Resolve-Path "$PSScriptRoot/.." +$LibDir = Join-Path $BoardDir "lib/stm32cubef4" +$DriversDir = Join-Path $LibDir "Drivers" +$HalDest = Join-Path $DriversDir "STM32F4xx_HAL_Driver" +$CmsisDeviceDest = Join-Path $DriversDir "CMSIS/Device/ST/STM32F4xx" +$CmsisIncludeDest = Join-Path $DriversDir "CMSIS/Include" + +Write-Host "==========================================" +Write-Host "STM32CubeF4 Standalone Driver Fetcher" +Write-Host "==========================================" +Write-Host "Fetching to: $LibDir" +Write-Host "" + +# Create destination directories +if (Test-Path $HalDest) { Remove-Item -Path $HalDest -Recurse -Force } +if (Test-Path $CmsisDeviceDest) { Remove-Item -Path $CmsisDeviceDest -Recurse -Force } +if (Test-Path $CmsisIncludeDest) { Remove-Item -Path $CmsisIncludeDest -Recurse -Force } + +New-Item -ItemType Directory -Path $HalDest -Force | Out-Null +New-Item -ItemType Directory -Path $CmsisDeviceDest -Force | Out-Null +New-Item -ItemType Directory -Path $CmsisIncludeDest -Force | Out-Null + +$TempDir = Join-Path $BoardDir "temp_clone" + +# Helper function to clean up temp dir if exists +function CleanTemp { + if (Test-Path $TempDir) { + Remove-Item -Path $TempDir -Recurse -Force + } +} + +CleanTemp + +# 1. Fetch HAL Drivers +Write-Host "[INFO] Cloning STM32F4xx HAL Driver (depth=1)..." +git clone --depth 1 https://github.com/STMicroelectronics/stm32f4xx_hal_driver.git $TempDir +if ($LASTEXITCODE -ne 0) { + Write-Host "[ERROR] Failed to clone HAL Driver repository!" -ForegroundColor Red + CleanTemp + exit 1 +} +Copy-Item -Path "$TempDir/Inc" -Destination $HalDest -Recurse -Force +Copy-Item -Path "$TempDir/Src" -Destination $HalDest -Recurse -Force +CleanTemp +Write-Host "[OK] HAL Drivers copied" +Write-Host "" + +# 2. Fetch CMSIS Device F4 +Write-Host "[INFO] Cloning CMSIS Device F4 (depth=1)..." +git clone --depth 1 https://github.com/STMicroelectronics/cmsis_device_f4.git $TempDir +if ($LASTEXITCODE -ne 0) { + Write-Host "[ERROR] Failed to clone CMSIS Device repository!" -ForegroundColor Red + CleanTemp + exit 1 +} +Copy-Item -Path "$TempDir/Include" -Destination $CmsisDeviceDest -Recurse -Force +Copy-Item -Path "$TempDir/Source" -Destination $CmsisDeviceDest -Recurse -Force +CleanTemp +Write-Host "[OK] CMSIS Device files copied" +Write-Host "" + +# 3. Fetch up-to-date CMSIS Core headers from ST's official repository +Write-Host "[INFO] Cloning up-to-date STM32 CMSIS Core (depth=1)..." +git clone --depth 1 https://github.com/STMicroelectronics/cmsis-core.git $TempDir +if ($LASTEXITCODE -ne 0) { + Write-Host "[ERROR] Failed to clone CMSIS Core repository!" -ForegroundColor Red + CleanTemp + exit 1 +} +Copy-Item -Path "$TempDir/CMSIS/Core/Include/*" -Destination $CmsisIncludeDest -Recurse -Force +CleanTemp +Write-Host "[OK] Up-to-date CMSIS Core Include headers copied" +Write-Host "" + +Write-Host "==========================================" +Write-Host "[SUCCESS] STM32CubeF4 drivers successfully fetched!" +Write-Host "==========================================" diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/scripts/fetch_sdk.sh b/STMicroelectronics/STM32F429ZI-Nucleo/scripts/fetch_sdk.sh new file mode 100755 index 00000000..a60589b5 --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/scripts/fetch_sdk.sh @@ -0,0 +1,104 @@ +#!/usr/bin/env bash +# 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 +# +# Contributors: +# Ali Eissa - 2026 version. + +set -e + +# Determine directory paths +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BOARD_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" + +LIB_DIR="${BOARD_DIR}/lib/stm32cubef4" +DRIVERS_DIR="${LIB_DIR}/Drivers" +HAL_DEST="${DRIVERS_DIR}/STM32F4xx_HAL_Driver" +CMSIS_DEVICE_DEST="${DRIVERS_DIR}/CMSIS/Device/ST/STM32F4xx" +CMSIS_INCLUDE_DEST="${DRIVERS_DIR}/CMSIS/Include" +TOOLS_DIR="${BOARD_DIR}/tools" + +# The SVD is only read by the optional Segger Ozone configuration, and it is +# ST's file rather than ours, so it is fetched like the rest of ST's content +# instead of being carried in the tree. The pack version is pinned and its +# digest checked, the same way the toolchains are. +SVD_PACK_VERSION="3.1.1" +SVD_PACK_URL="https://www.keil.com/pack/Keil.STM32F4xx_DFP.${SVD_PACK_VERSION}.pack" +SVD_PACK_SHA256="345231106fe697df24bbe9133aeeec1b0383d7891c4adf4f47bbb8b478e9f2f0" +SVD_MEMBER="CMSIS/SVD/STM32F429.svd" + +echo "==========================================" +echo "STM32CubeF4 Standalone Driver Fetcher (Linux)" +echo "==========================================" +echo "Fetching to: ${LIB_DIR}" +echo "" + +# Clean existing destination directories +rm -rf "${HAL_DEST}" +rm -rf "${CMSIS_DEVICE_DEST}" +rm -rf "${CMSIS_INCLUDE_DEST}" + +# Re-create directories +mkdir -p "${HAL_DEST}" +mkdir -p "${CMSIS_DEVICE_DEST}" +mkdir -p "${CMSIS_INCLUDE_DEST}" + +TEMP_DIR="${BOARD_DIR}/temp_clone" + +# Helper function to clear temp clone workspace +clean_temp() { + if [ -d "${TEMP_DIR}" ]; then + rm -rf "${TEMP_DIR}" + fi +} + +# Set up exit trap to ensure temp directory is always purged +trap clean_temp EXIT +clean_temp + +# 1. Fetch HAL Drivers +echo "[INFO] Cloning STM32F4xx HAL Driver (depth=1)..." +git clone --depth 1 https://github.com/STMicroelectronics/stm32f4xx_hal_driver.git "${TEMP_DIR}" +cp -r "${TEMP_DIR}/Inc" "${HAL_DEST}/" +cp -r "${TEMP_DIR}/Src" "${HAL_DEST}/" +clean_temp +echo "[OK] HAL Drivers copied" +echo "" + +# 2. Fetch CMSIS Device F4 +echo "[INFO] Cloning CMSIS Device F4 (depth=1)..." +git clone --depth 1 https://github.com/STMicroelectronics/cmsis_device_f4.git "${TEMP_DIR}" +cp -r "${TEMP_DIR}/Include" "${CMSIS_DEVICE_DEST}/" +cp -r "${TEMP_DIR}/Source" "${CMSIS_DEVICE_DEST}/" +clean_temp +echo "[OK] CMSIS Device files copied" +echo "" + +# 3. Fetch up-to-date CMSIS Core headers from ST's official repository +echo "[INFO] Cloning up-to-date STM32 CMSIS Core (depth=1)..." +git clone --depth 1 https://github.com/STMicroelectronics/cmsis-core.git "${TEMP_DIR}" +cp -r "${TEMP_DIR}/CMSIS/Core/Include/"* "${CMSIS_INCLUDE_DEST}/" +clean_temp +echo "[OK] Up-to-date CMSIS Core Include headers copied" +echo "" + +# 4. Fetch the STM32F429 SVD from the CMSIS device pack +echo "[INFO] Fetching STM32F429 SVD from CMSIS pack ${SVD_PACK_VERSION}..." +mkdir -p "${TOOLS_DIR}" +mkdir -p "${TEMP_DIR}" +curl -fsSL -o "${TEMP_DIR}/dfp.pack" "${SVD_PACK_URL}" +echo "${SVD_PACK_SHA256} ${TEMP_DIR}/dfp.pack" | sha256sum -c - >/dev/null +unzip -o -q "${TEMP_DIR}/dfp.pack" "${SVD_MEMBER}" -d "${TEMP_DIR}" +cp "${TEMP_DIR}/${SVD_MEMBER}" "${TOOLS_DIR}/STM32F429.svd" +clean_temp +echo "[OK] STM32F429.svd placed in tools/" +echo "" + +echo "==========================================" +echo "[SUCCESS] STM32CubeF4 drivers successfully fetched!" +echo "==========================================" diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/tools/STM32F429ZI_samplex.ioc b/STMicroelectronics/STM32F429ZI-Nucleo/tools/STM32F429ZI_samplex.ioc new file mode 100644 index 00000000..5ff2e223 --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/tools/STM32F429ZI_samplex.ioc @@ -0,0 +1,313 @@ +#MicroXplorer Configuration settings - do not modify +CAD.formats= +CAD.pinconfig= +CAD.provider= +ETH.IPParameters=MediaInterface,PHY_Name,PHY_Value,PhyAddress +ETH.MediaInterface=HAL_ETH_RMII_MODE +ETH.PHY_Name=LAN8742A_PHY_ADDRESS +ETH.PHY_Value=0 +ETH.PhyAddress=0 +File.Version=6 +KeepUserPlacement=false +Mcu.CPN=STM32F429ZIT6 +Mcu.Family=STM32F4 +Mcu.IP0=ETH +Mcu.IP1=NVIC +Mcu.IP2=RCC +Mcu.IP3=SYS +Mcu.IP4=USART3 +Mcu.IP5=USB_OTG_FS +Mcu.IPNb=6 +Mcu.Name=STM32F429ZITx +Mcu.Package=LQFP144 +Mcu.Pin0=PC13 +Mcu.Pin1=PC14/OSC32_IN +Mcu.Pin10=PC5 +Mcu.Pin11=PB0 +Mcu.Pin12=PB13 +Mcu.Pin13=PB14 +Mcu.Pin14=PD8 +Mcu.Pin15=PD9 +Mcu.Pin16=PG6 +Mcu.Pin17=PG7 +Mcu.Pin18=PA8 +Mcu.Pin19=PA9 +Mcu.Pin2=PC15/OSC32_OUT +Mcu.Pin20=PA10 +Mcu.Pin21=PA11 +Mcu.Pin22=PA12 +Mcu.Pin23=PA13 +Mcu.Pin24=PA14 +Mcu.Pin25=PG11 +Mcu.Pin26=PG13 +Mcu.Pin27=PB7 +Mcu.Pin28=VP_SYS_VS_Systick +Mcu.Pin3=PH0/OSC_IN +Mcu.Pin4=PH1/OSC_OUT +Mcu.Pin5=PC1 +Mcu.Pin6=PA1 +Mcu.Pin7=PA2 +Mcu.Pin8=PA7 +Mcu.Pin9=PC4 +Mcu.PinsNb=29 +Mcu.ThirdPartyNb=0 +Mcu.UserConstants= +Mcu.UserName=STM32F429ZITx +MxCube.Version=6.18.1 +MxDb.Version=DB.6.0.181 +NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false +NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false +NVIC.ForceEnableDMAVector=true +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false +NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false +NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false +NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 +NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false +NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:false +NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false +PA1.GPIOParameters=GPIO_Label +PA1.GPIO_Label=RMII_REF_CLK [LAN8742A-CZ-TR_REFCLK0] +PA1.Locked=true +PA1.Mode=RMII +PA1.Signal=ETH_REF_CLK +PA10.GPIOParameters=GPIO_Label +PA10.GPIO_Label=USB_ID +PA10.Locked=true +PA10.Signal=USB_OTG_FS_ID +PA11.GPIOParameters=GPIO_Label +PA11.GPIO_Label=USB_DM +PA11.Locked=true +PA11.Mode=Device_Only +PA11.Signal=USB_OTG_FS_DM +PA12.GPIOParameters=GPIO_Label +PA12.GPIO_Label=USB_DP +PA12.Locked=true +PA12.Mode=Device_Only +PA12.Signal=USB_OTG_FS_DP +PA13.GPIOParameters=GPIO_Label +PA13.GPIO_Label=TMS +PA13.Locked=true +PA13.Mode=Serial_Wire +PA13.Signal=SYS_JTMS-SWDIO +PA14.GPIOParameters=GPIO_Label +PA14.GPIO_Label=TCK +PA14.Locked=true +PA14.Mode=Serial_Wire +PA14.Signal=SYS_JTCK-SWCLK +PA2.GPIOParameters=GPIO_Label +PA2.GPIO_Label=RMII_MDIO [LAN8742A-CZ-TR_MDIO] +PA2.Locked=true +PA2.Mode=RMII +PA2.Signal=ETH_MDIO +PA7.GPIOParameters=GPIO_Label +PA7.GPIO_Label=RMII_CRS_DV [LAN8742A-CZ-TR_CRS_DV] +PA7.Locked=true +PA7.Mode=RMII +PA7.Signal=ETH_CRS_DV +PA8.GPIOParameters=GPIO_Label +PA8.GPIO_Label=USB_SOF [TP1] +PA8.Locked=true +PA8.Mode=Activate_SOF_FS +PA8.Signal=USB_OTG_FS_SOF +PA9.GPIOParameters=GPIO_Label +PA9.GPIO_Label=USB_VBUS +PA9.Locked=true +PA9.Mode=Activate_VBUS +PA9.Signal=USB_OTG_FS_VBUS +PB0.GPIOParameters=GPIO_Label +PB0.GPIO_Label=LD1 [Green] +PB0.Locked=true +PB0.Signal=GPIO_Output +PB13.GPIOParameters=GPIO_Label +PB13.GPIO_Label=RMII_TXD1 [LAN8742A-CZ-TR_TXD1] +PB13.Locked=true +PB13.Mode=RMII +PB13.Signal=ETH_TXD1 +PB14.GPIOParameters=GPIO_Label +PB14.GPIO_Label=LD3 [Red] +PB14.Locked=true +PB14.Signal=GPIO_Output +PB7.GPIOParameters=GPIO_Label +PB7.GPIO_Label=LD2 [Blue] +PB7.Locked=true +PB7.Signal=GPIO_Output +PC1.GPIOParameters=GPIO_Label +PC1.GPIO_Label=RMII_MDC [LAN8742A-CZ-TR_MDC] +PC1.Locked=true +PC1.Mode=RMII +PC1.Signal=ETH_MDC +PC13.GPIOParameters=GPIO_Label +PC13.GPIO_Label=USER_Btn [B1] +PC13.Locked=true +PC13.Signal=GPIO_Input +PC14/OSC32_IN.Locked=true +PC14/OSC32_IN.Mode=LSE-External-Oscillator +PC14/OSC32_IN.Signal=RCC_OSC32_IN +PC15/OSC32_OUT.Locked=true +PC15/OSC32_OUT.Mode=LSE-External-Oscillator +PC15/OSC32_OUT.Signal=RCC_OSC32_OUT +PC4.GPIOParameters=GPIO_Label +PC4.GPIO_Label=RMII_RXD0 [LAN8742A-CZ-TR_RXD0] +PC4.Locked=true +PC4.Mode=RMII +PC4.Signal=ETH_RXD0 +PC5.GPIOParameters=GPIO_Label +PC5.GPIO_Label=RMII_RXD1 [LAN8742A-CZ-TR_RXD1] +PC5.Locked=true +PC5.Mode=RMII +PC5.Signal=ETH_RXD1 +PCC.Bar.Display=Horizontal Bar +PCC.Checker=false +PCC.Display=Plot\: All Steps +PCC.Line=STM32F429/439 +PCC.MCU=STM32F429ZITx +PCC.PartNumber=STM32F429ZITx +PCC.SequenceTime=1.0 ms +PCC.SequenceTime.Unit=ms +PCC.Series=STM32F4 +PCC.Temperature=25 +PCC.Vdd=3.3 +PD8.GPIOParameters=GPIO_Label +PD8.GPIO_Label=STLK_RX [STM32F103CBT6_PA3] +PD8.Locked=true +PD8.Mode=Asynchronous +PD8.Signal=USART3_TX +PD9.GPIOParameters=GPIO_Label +PD9.GPIO_Label=STLK_TX [STM32F103CBT6_PA2] +PD9.Locked=true +PD9.Mode=Asynchronous +PD9.Signal=USART3_RX +PG11.GPIOParameters=GPIO_Label +PG11.GPIO_Label=RMII_TX_EN [LAN8742A-CZ-TR_TXEN] +PG11.Locked=true +PG11.Mode=RMII +PG11.Signal=ETH_TX_EN +PG13.GPIOParameters=GPIO_Label +PG13.GPIO_Label=RMII_TXD0 [LAN8742A-CZ-TR_TXD0] +PG13.Locked=true +PG13.Mode=RMII +PG13.Signal=ETH_TXD0 +PG6.GPIOParameters=GPIO_Label +PG6.GPIO_Label=USB_PowerSwitchOn [STMPS2151STR_EN] +PG6.Locked=true +PG6.Signal=GPIO_Output +PG7.GPIOParameters=GPIO_Label +PG7.GPIO_Label=USB_OverCurrent [STMPS2151STR_FAULT] +PG7.Locked=true +PG7.Signal=GPIO_Input +PH0/OSC_IN.GPIOParameters=GPIO_Label +PH0/OSC_IN.GPIO_Label=MCO [STM32F103CBT6_PA8] +PH0/OSC_IN.Locked=true +PH0/OSC_IN.Mode=HSE-External-Clock-Source +PH0/OSC_IN.Signal=RCC_OSC_IN +PH1/OSC_OUT.Mode=HSE-External-Clock-Source +PH1/OSC_OUT.Signal=RCC_OSC_OUT +PinOutPanel.RotationAngle=0 +ProjectManager.AskForMigrate=true +ProjectManager.BackupPrevious=false +ProjectManager.CompilerLinker=GCC +ProjectManager.CompilerOptimize=6 +ProjectManager.ComputerToolchain=false +ProjectManager.CoupleFile=false +ProjectManager.CustomerFirmwarePackage= +ProjectManager.DefaultFWLocation=true +ProjectManager.DeletePrevious=true +ProjectManager.DeviceId=STM32F429ZITx +ProjectManager.FirmwarePackage=STM32Cube FW_F4 V1.28.3 +ProjectManager.FreePins=false +ProjectManager.FreePinsContext= +ProjectManager.HalAssertFull=false +ProjectManager.HeapSize=0x200 +ProjectManager.KeepUserCode=true +ProjectManager.LastFirmware=true +ProjectManager.LibraryCopy=1 +ProjectManager.MainLocation=Core/Src +ProjectManager.NoMain=false +ProjectManager.PreviousToolchain= +ProjectManager.ProjectBuild=false +ProjectManager.ProjectFileName=STM32F429ZI_samplex.ioc +ProjectManager.ProjectName=STM32F429ZI_samplex +ProjectManager.ProjectStructure= +ProjectManager.RegisterCallBack= +ProjectManager.StackSize=0x400 +ProjectManager.TargetToolchain=CMake +ProjectManager.ToolChainLocation= +ProjectManager.UAScriptAfterPath= +ProjectManager.UAScriptBeforePath= +ProjectManager.UnderRoot=false +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_ETH_Init-ETH-false-HAL-true,4-MX_USART3_UART_Init-USART3-false-HAL-true,5-MX_USB_OTG_FS_PCD_Init-USB_OTG_FS-false-HAL-true +RCC.48MHZClocksFreq_Value=48000000 +RCC.ADC12outputFreq_Value=72000000 +RCC.ADC34outputFreq_Value=72000000 +RCC.AHBFreq_Value=168000000 +RCC.APB1CLKDivider=RCC_HCLK_DIV4 +RCC.APB1Freq_Value=42000000 +RCC.APB1TimFreq_Value=84000000 +RCC.APB2CLKDivider=RCC_HCLK_DIV2 +RCC.APB2Freq_Value=84000000 +RCC.APB2TimFreq_Value=168000000 +RCC.CortexFreq_Value=168000000 +RCC.EthernetFreq_Value=168000000 +RCC.FCLKCortexFreq_Value=168000000 +RCC.FamilyName=M +RCC.HCLKFreq_Value=168000000 +RCC.HSE_VALUE=8000000 +RCC.HSI_VALUE=16000000 +RCC.I2C1Freq_Value=8000000 +RCC.I2C2Freq_Value=8000000 +RCC.I2C3Freq_Value=8000000 +RCC.I2SClocksFreq_Value=192000000 +RCC.IPParameters=48MHZClocksFreq_Value,ADC12outputFreq_Value,ADC34outputFreq_Value,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimFreq_Value,CortexFreq_Value,EthernetFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,I2C1Freq_Value,I2C2Freq_Value,I2C3Freq_Value,I2SClocksFreq_Value,LCDTFTFreq_Value,LSI_VALUE,MCO1PinFreq_Value,MCO2PinFreq_Value,MCOFreq_Value,PLLCLKFreq_Value,PLLM,PLLMCOFreq_Value,PLLMUL,PLLN,PLLQ,PLLQCLKFreq_Value,PRESCALERUSB,RTCFreq_Value,RTCHSEDivFreq_Value,SAI_AClocksFreq_Value,SAI_BClocksFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,SYSCLKSourceVirtual,TIM15Freq_Value,TIM16Freq_Value,TIM17Freq_Value,TIM1Freq_Value,TIM20Freq_Value,TIM2Freq_Value,TIM3Freq_Value,TIM8Freq_Value,UART4Freq_Value,UART5Freq_Value,USART1Freq_Value,USART2Freq_Value,USART3Freq_Value,USBFreq_Value,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutput2Freq_Value,VCOOutputFreq_Value,VCOSAIOutputFreq_Value,VCOSAIOutputFreq_ValueQ,VCOSAIOutputFreq_ValueR,VcooutputI2S,VcooutputI2SQ,WatchDogFreq_Value +RCC.LCDTFTFreq_Value=24500000 +RCC.LSI_VALUE=32000 +RCC.MCO1PinFreq_Value=16000000 +RCC.MCO2PinFreq_Value=168000000 +RCC.MCOFreq_Value=72000000 +RCC.PLLCLKFreq_Value=168000000 +RCC.PLLM=4 +RCC.PLLMCOFreq_Value=72000000 +RCC.PLLMUL=RCC_PLL_MUL9 +RCC.PLLN=168 +RCC.PLLQ=7 +RCC.PLLQCLKFreq_Value=48000000 +RCC.PRESCALERUSB=RCC_USBCLKSOURCE_PLL_DIV1_5 +RCC.RTCFreq_Value=32000 +RCC.RTCHSEDivFreq_Value=4000000 +RCC.SAI_AClocksFreq_Value=24500000 +RCC.SAI_BClocksFreq_Value=24500000 +RCC.SYSCLKFreq_VALUE=168000000 +RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK +RCC.SYSCLKSourceVirtual=RCC_SYSCLKSOURCE_PLLCLK +RCC.TIM15Freq_Value=72000000 +RCC.TIM16Freq_Value=72000000 +RCC.TIM17Freq_Value=72000000 +RCC.TIM1Freq_Value=72000000 +RCC.TIM20Freq_Value=72000000 +RCC.TIM2Freq_Value=72000000 +RCC.TIM3Freq_Value=72000000 +RCC.TIM8Freq_Value=72000000 +RCC.UART4Freq_Value=36000000 +RCC.UART5Freq_Value=36000000 +RCC.USART1Freq_Value=72000000 +RCC.USART2Freq_Value=36000000 +RCC.USART3Freq_Value=36000000 +RCC.USBFreq_Value=48000000 +RCC.VCOI2SOutputFreq_Value=384000000 +RCC.VCOInputFreq_Value=2000000 +RCC.VCOOutput2Freq_Value=8000000 +RCC.VCOOutputFreq_Value=336000000 +RCC.VCOSAIOutputFreq_Value=98000000 +RCC.VCOSAIOutputFreq_ValueQ=24500000 +RCC.VCOSAIOutputFreq_ValueR=49000000 +RCC.VcooutputI2S=192000000 +RCC.VcooutputI2SQ=192000000 +RCC.WatchDogFreq_Value=32000 +USART3.IPParameters=VirtualMode +USART3.VirtualMode=VM_ASYNC +USB_OTG_FS.IPParameters=VirtualMode +USB_OTG_FS.VirtualMode=Device_Only +VP_SYS_VS_Systick.Mode=SysTick +VP_SYS_VS_Systick.Signal=SYS_VS_Systick +board=NUCLEO-F429ZI +boardIOC=true diff --git a/STMicroelectronics/STM32F429ZI-Nucleo/tools/STM32F429ZI_threadx_basic.jdebug b/STMicroelectronics/STM32F429ZI-Nucleo/tools/STM32F429ZI_threadx_basic.jdebug new file mode 100644 index 00000000..77cccf0f --- /dev/null +++ b/STMicroelectronics/STM32F429ZI-Nucleo/tools/STM32F429ZI_threadx_basic.jdebug @@ -0,0 +1,348 @@ +/********************************************************************* +* (c) SEGGER Microcontroller GmbH * +* The Embedded Experts * +* www.segger.com * +********************************************************************** + +File : samplex/STMicroelectronics/STM32F429ZI-Nucleo/tools/STM32F429ZI_samplex.jdebug +Created : 5 Aug 2026 21:34 +Ozone Version : V3.28e +*/ + +/********************************************************************* +* +* OnProjectLoad +* +* Function description +* Project load routine. Required. +* +********************************************************************** +*/ +void OnProjectLoad (void) { + // + // Dialog-generated settings + // + Project.AddPathSubstitute ("./", "$(ProjectDir)"); + Project.SetDevice ("STM32F429ZI"); + Project.SetHostIF ("USB", ""); + Project.SetTargetIF ("SWD"); + Project.SetTIFSpeed ("4 MHz"); + Project.AddSvdFile ("$(InstallDir)/Config/CPU/Cortex-M4F.svd"); + Project.AddSvdFile ("./STM32F429.svd"); + // + // User settings + // + File.Open ("../build/app/demos/threadx_basic/stm32f429_threadx.elf"); +} + +/********************************************************************* +* +* OnStartupComplete +* +* Function description +* Called when program execution has reached/passed +* the startup completion point. Optional. +* +********************************************************************** +*/ +//void OnStartupComplete (void) { +//} + +/********************************************************************* +* +* TargetReset +* +* Function description +* Replaces the default target device reset routine. Optional. +* +* Notes +* This example demonstrates the usage when +* debugging an application in RAM on a Cortex-M target device. +* +********************************************************************** +*/ +//void TargetReset (void) { +// +// unsigned int SP; +// unsigned int PC; +// unsigned int VectorTableAddr; +// +// VectorTableAddr = Elf.GetBaseAddr(); +// // +// // Set up initial stack pointer +// // +// if (VectorTableAddr != 0xFFFFFFFF) { +// SP = Target.ReadU32(VectorTableAddr); +// Target.SetReg("SP", SP); +// } +// // +// // Set up entry point PC +// // +// PC = Elf.GetEntryPointPC(); +// +// if (PC != 0xFFFFFFFF) { +// Target.SetReg("PC", PC); +// } else if (VectorTableAddr != 0xFFFFFFFF) { +// PC = Target.ReadU32(VectorTableAddr + 4); +// Target.SetReg("PC", PC); +// } else { +// Util.Error("Project file error: failed to set entry point PC", 1); +// } +//} + +/********************************************************************* +* +* BeforeTargetReset +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void BeforeTargetReset (void) { +//} + +/********************************************************************* +* +* AfterTargetReset +* +* Function description +* Event handler routine. Optional. +* The default implementation initializes SP and PC to reset values. +** +********************************************************************** +*/ +void AfterTargetReset (void) { + _SetupTarget(); +} + +/********************************************************************* +* +* DebugStart +* +* Function description +* Replaces the default debug session startup routine. Optional. +* +********************************************************************** +*/ +//void DebugStart (void) { +//} + +/********************************************************************* +* +* TargetConnect +* +* Function description +* Replaces the default target IF connection routine. Optional. +* +********************************************************************** +*/ +//void TargetConnect (void) { +//} + +/********************************************************************* +* +* BeforeTargetConnect +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void BeforeTargetConnect (void) { +//} + +/********************************************************************* +* +* AfterTargetConnect +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void AfterTargetConnect (void) { +//} + +/********************************************************************* +* +* TargetDownload +* +* Function description +* Replaces the default program download routine. Optional. +* +********************************************************************** +*/ +//void TargetDownload (void) { +//} + +/********************************************************************* +* +* BeforeTargetDownload +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void BeforeTargetDownload (void) { +//} + +/********************************************************************* +* +* AfterTargetDownload +* +* Function description +* Event handler routine. Optional. +* The default implementation initializes SP and PC to reset values. +* +********************************************************************** +*/ +void AfterTargetDownload (void) { + _SetupTarget(); +} + +/********************************************************************* +* +* BeforeTargetDisconnect +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void BeforeTargetDisconnect (void) { +//} + +/********************************************************************* +* +* AfterTargetDisconnect +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void AfterTargetDisconnect (void) { +//} + +/********************************************************************* +* +* AfterTargetHalt +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void AfterTargetHalt (void) { +//} + +/********************************************************************* +* +* BeforeTargetResume +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void BeforeTargetResume (void) { +//} + +/********************************************************************* +* +* OnSnapshotLoad +* +* Function description +* Called upon loading a snapshot. Optional. +* +* Additional information +* This function is used to restore the target state in cases +* where values cannot simply be written to the target. +* Typical use: GPIO clock needs to be enabled, before +* GPIO is configured. +* +********************************************************************** +*/ +//void OnSnapshotLoad (void) { +//} + +/********************************************************************* +* +* OnSnapshotSave +* +* Function description +* Called upon saving a snapshot. Optional. +* +* Additional information +* This function is usually used to save values of the target +* state which can either not be trivially read, +* or need to be restored in a specific way or order. +* Typically use: Memory Mapped Registers, +* such as PLL and GPIO configuration. +* +********************************************************************** +*/ +//void OnSnapshotSave (void) { +//} + +/********************************************************************* +* +* OnError +* +* Function description +* Called when an error ocurred. Optional. +* +********************************************************************** +*/ +//void OnError (void) { +//} + +/********************************************************************* +* +* AfterProjectLoad +* +* Function description +* After Project load routine. Optional. +* +********************************************************************** +*/ +//void AfterProjectLoad (void) { +//} + +/********************************************************************* +* +* _SetupTarget +* +* Function description +* Setup the target. +* Called by AfterTargetReset() and AfterTargetDownload(). +* +* Auto-generated function. May be overridden by Ozone. +* +********************************************************************** +*/ +void _SetupTarget(void) { + unsigned int SP; + unsigned int PC; + unsigned int VectorTableAddr; + + VectorTableAddr = Elf.GetBaseAddr(); + // + // Set up initial stack pointer + // + SP = Target.ReadU32(VectorTableAddr); + if (SP != 0xFFFFFFFF) { + Target.SetReg("SP", SP); + } + // + // Set up entry point PC + // + PC = Elf.GetEntryPointPC(); + if (PC != 0xFFFFFFFF) { + Target.SetReg("PC", PC); + } else { + Util.Error("Project script error: failed to set up entry point PC", 1); + } +} diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/CMakeLists.txt b/STMicroelectronics/STM32F767ZI-Nucleo/CMakeLists.txt index af6b0e7d..245639e5 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/CMakeLists.txt +++ b/STMicroelectronics/STM32F767ZI-Nucleo/CMakeLists.txt @@ -1,12 +1,12 @@ # Copyright (c) 2026 Eclipse ThreadX contributors -# -# This program and the accompanying materials are made available +# +# 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 -# -# Contributors: +# +# Contributors: # Ali Eissa - 2026 version. cmake_minimum_required(VERSION 3.10 FATAL_ERROR) @@ -128,7 +128,7 @@ if(USE_NETXDUO) lib/netxduo/nx_stm32_phy_driver.c lib/netxduo/lan8742.c ) - + # NetX driver needs its local files, HAL, CMSIS, ThreadX, NetX Duo and the active demo folder (for nx_stm32_eth_config.h and nx_user.h) target_include_directories(netx_stm32_driver PUBLIC ${CMAKE_CURRENT_LIST_DIR}/lib/netxduo @@ -137,13 +137,13 @@ if(USE_NETXDUO) ${CMSIS_INCLUDE_DIRS} ${STM32HAL_INCLUDE_DIR} ) - + target_compile_definitions(netx_stm32_driver PRIVATE STM32F767xx USE_HAL_DRIVER STM32F7 ) - + target_link_libraries(netx_stm32_driver PUBLIC netxduo stm32cubef7 diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/CMakeLists.txt b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/CMakeLists.txt index b1b76fe6..721372fc 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/CMakeLists.txt +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/CMakeLists.txt @@ -1,12 +1,12 @@ # Copyright (c) 2026 Eclipse ThreadX contributors -# -# This program and the accompanying materials are made available +# +# 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 -# -# Contributors: +# +# Contributors: # Ali Eissa - 2026 version. add_executable(${PROJECT_NAME} diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/main.c b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/main.c index 2ecd58cf..1c903973 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/main.c +++ b/STMicroelectronics/STM32F767ZI-Nucleo/app/demos/threadx_basic/main.c @@ -1,12 +1,12 @@ -/* +/* * Copyright (c) 2026 Eclipse ThreadX contributors - * - * This program and the accompanying materials are made available + * + * 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 - * + * * Contributors: * Ali Eissa - 2026 version. */ @@ -50,9 +50,6 @@ void button_thread_entry(ULONG thread_input); void logger_thread_entry(ULONG thread_input); void input_thread_entry(ULONG thread_input); -/* External console function declaration */ -int __io_getchar(void); - /** * @brief Standard C Main entry point. * @retval int @@ -138,7 +135,7 @@ void tx_application_define(void *first_unused_memory) void green_thread_entry(ULONG thread_input) { (void)thread_input; - + printf(ANSI_BOLD ANSI_CYAN "\r\n==========================================\r\n" ANSI_RESET); printf(ANSI_BOLD ANSI_CYAN "ThreadX Multitasking Edge Node Demo Booted!\r\n" ANSI_RESET); printf(ANSI_BOLD ANSI_CYAN "==========================================\r\n\r\n" ANSI_RESET); @@ -148,7 +145,7 @@ void green_thread_entry(ULONG thread_input) /* Toggles LD1 (Green) on and off every 250 milliseconds */ LED1_ON(); tx_thread_sleep(25); /* 25 ticks = 250 ms at 100 Hz tick rate */ - + LED1_OFF(); tx_thread_sleep(25); } @@ -236,7 +233,7 @@ void USART3_IRQHandler(void) { /* Read data register directly to clear RXNE flag and get the byte */ char ch = (char)(huart3.Instance->RDR & 0xFF); - + /* Insert into circular ring buffer if not full */ int next_head = (ring_head + 1) % RING_BUF_SIZE; if (next_head != ring_tail) diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/cmake/FindSTM32HAL.cmake b/STMicroelectronics/STM32F767ZI-Nucleo/cmake/FindSTM32HAL.cmake index 698754f6..7d9bce34 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/cmake/FindSTM32HAL.cmake +++ b/STMicroelectronics/STM32F767ZI-Nucleo/cmake/FindSTM32HAL.cmake @@ -1,13 +1,13 @@ # Copyright (c) Microsoft # Copyright (c) 2026 Eclipse ThreadX contributors -# -# This program and the accompanying materials are made available +# +# 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 -# -# Contributors: +# +# Contributors: # Microsoft - Initial version # Frédéric Desbiens - 2024 version. # Ali Eissa - 2026 version. diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/scripts/build.sh b/STMicroelectronics/STM32F767ZI-Nucleo/scripts/build.sh old mode 100644 new mode 100755 diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.ps1 b/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.ps1 index d0d2f0a1..4b8037dd 100644 --- a/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.ps1 +++ b/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.ps1 @@ -1,12 +1,12 @@ # Copyright (c) 2026 Eclipse ThreadX contributors -# -# This program and the accompanying materials are made available +# +# 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 -# -# Contributors: +# +# Contributors: # Ali Eissa - 2026 version. $BoardDir = Resolve-Path "$PSScriptRoot/.." diff --git a/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.sh b/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.sh old mode 100644 new mode 100755 index 82b8866e..f357435c --- a/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.sh +++ b/STMicroelectronics/STM32F767ZI-Nucleo/scripts/fetch_sdk.sh @@ -1,13 +1,13 @@ #!/usr/bin/env bash # Copyright (c) 2026 Eclipse ThreadX contributors -# -# This program and the accompanying materials are made available +# +# 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 -# -# Contributors: +# +# Contributors: # Ali Eissa - 2026 version. set -e From f85e22ed5ed808299e404dc5d8ce93c370471bba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 30 Sep 2026 16:24:54 -0400 Subject: [PATCH 20/20] Fixed CORE-V CLI host tests (#64) (#77) * Fix CORE-V CLI host test mocks * Added the licence header to the four new mock files The mocks arrived without one. Every other file in this directory carries the MIT header, and a source file entering an Eclipse project without a copyright line is the kind of omission that is cheap now and awkward later. The header is the plain MIT one rather than the AI disclosure variant the neighbouring mocks carry, because nothing here establishes how these were written and the disclosure is a statement about that. Build clean and the CLI host tests pass. Assisted-by: Claude Code (Opus 5) --------- Co-authored-by: divyanshisingh987456321 --- .../CORE-V-MCU/cli-test/tests/CMakeLists.txt | 2 + .../cli-test/tests/mock/cli_core_mock.c | 22 ++++++++ OpenHW/CORE-V-MCU/cli-test/tests/mock/gpio.h | 24 +++++++++ .../cli-test/tests/mock/hardware_mock.c | 50 +++++++++++++++++++ .../cli-test/tests/mock/uart_driver.h | 14 ++++++ .../cli-test/tests/test_cli_commands.c | 22 ++++++-- 6 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 OpenHW/CORE-V-MCU/cli-test/tests/mock/cli_core_mock.c create mode 100644 OpenHW/CORE-V-MCU/cli-test/tests/mock/gpio.h create mode 100644 OpenHW/CORE-V-MCU/cli-test/tests/mock/hardware_mock.c create mode 100644 OpenHW/CORE-V-MCU/cli-test/tests/mock/uart_driver.h diff --git a/OpenHW/CORE-V-MCU/cli-test/tests/CMakeLists.txt b/OpenHW/CORE-V-MCU/cli-test/tests/CMakeLists.txt index eacd7218..9dc5be4b 100644 --- a/OpenHW/CORE-V-MCU/cli-test/tests/CMakeLists.txt +++ b/OpenHW/CORE-V-MCU/cli-test/tests/CMakeLists.txt @@ -20,6 +20,8 @@ set(CMAKE_C_STANDARD_REQUIRED ON) add_executable(cli_tests test_cli_commands.c mock/cli_mock.c + mock/cli_core_mock.c + mock/hardware_mock.c ../app/app_commands.c ) diff --git a/OpenHW/CORE-V-MCU/cli-test/tests/mock/cli_core_mock.c b/OpenHW/CORE-V-MCU/cli-test/tests/mock/cli_core_mock.c new file mode 100644 index 00000000..5759a92e --- /dev/null +++ b/OpenHW/CORE-V-MCU/cli-test/tests/mock/cli_core_mock.c @@ -0,0 +1,22 @@ +/***************************************************************************/ +/* 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + ***************************************************************************/ + +#include "cli.h" + +void CLI_uint32_required(const char *name, uint32_t *puthere) +{ + (void)name; + *puthere = 0U; +} + +void CLI_submenu_handler(const struct cli_cmd_entry *pEntry) +{ + (void)pEntry; +} diff --git a/OpenHW/CORE-V-MCU/cli-test/tests/mock/gpio.h b/OpenHW/CORE-V-MCU/cli-test/tests/mock/gpio.h new file mode 100644 index 00000000..f888c265 --- /dev/null +++ b/OpenHW/CORE-V-MCU/cli-test/tests/mock/gpio.h @@ -0,0 +1,24 @@ +/***************************************************************************/ +/* 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + ***************************************************************************/ + +#ifndef GPIO_H +#define GPIO_H + +#include + +void gpio_setpinmux(uint8_t io_pad, uint8_t mux); +uint8_t gpio_getpinmux(uint8_t io_pad); +void gpio_set(unsigned long mask); +void gpio_clear(unsigned long mask); +void gpio_toggle(unsigned long mask); +void gpio_pin_set_dir(uint8_t pin, uint8_t mode); +uint32_t gpio_pin_read_status(uint8_t pin); + +#endif diff --git a/OpenHW/CORE-V-MCU/cli-test/tests/mock/hardware_mock.c b/OpenHW/CORE-V-MCU/cli-test/tests/mock/hardware_mock.c new file mode 100644 index 00000000..6255ac00 --- /dev/null +++ b/OpenHW/CORE-V-MCU/cli-test/tests/mock/hardware_mock.c @@ -0,0 +1,50 @@ +/***************************************************************************/ +/* 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + ***************************************************************************/ + +#include "gpio.h" + +void gpio_setpinmux(uint8_t io_pad, uint8_t mux) +{ + (void)io_pad; + (void)mux; +} + +uint8_t gpio_getpinmux(uint8_t io_pad) +{ + (void)io_pad; + return 0U; +} + +void gpio_set(unsigned long mask) +{ + (void)mask; +} + +void gpio_clear(unsigned long mask) +{ + (void)mask; +} + +void gpio_toggle(unsigned long mask) +{ + (void)mask; +} + +void gpio_pin_set_dir(uint8_t pin, uint8_t mode) +{ + (void)pin; + (void)mode; +} + +uint32_t gpio_pin_read_status(uint8_t pin) +{ + (void)pin; + return 0U; +} diff --git a/OpenHW/CORE-V-MCU/cli-test/tests/mock/uart_driver.h b/OpenHW/CORE-V-MCU/cli-test/tests/mock/uart_driver.h new file mode 100644 index 00000000..e7d532e8 --- /dev/null +++ b/OpenHW/CORE-V-MCU/cli-test/tests/mock/uart_driver.h @@ -0,0 +1,14 @@ +/***************************************************************************/ +/* 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/licenses/MIT. + * + * SPDX-License-Identifier: MIT + ***************************************************************************/ + +#ifndef UART_DRIVER_H +#define UART_DRIVER_H + +#endif diff --git a/OpenHW/CORE-V-MCU/cli-test/tests/test_cli_commands.c b/OpenHW/CORE-V-MCU/cli-test/tests/test_cli_commands.c index 93eecc53..dd5fc337 100644 --- a/OpenHW/CORE-V-MCU/cli-test/tests/test_cli_commands.c +++ b/OpenHW/CORE-V-MCU/cli-test/tests/test_cli_commands.c @@ -21,16 +21,23 @@ static int test_version_output(void) { const struct cli_cmd_entry *menu; + const struct cli_cmd_entry *misc_menu; const char *output; cli_mock_reset(); menu = app_get_menu(); - if ((menu == NULL) || (menu[0].pHandler == NULL)) + if ((menu == NULL) || (menu[0].pHandler == NULL) || (menu[0].cookie == 0)) { return 1; } - menu[0].pHandler(&menu[0]); + misc_menu = (const struct cli_cmd_entry *)(uintptr_t)menu[0].cookie; + if ((misc_menu == NULL) || (misc_menu[0].pHandler == NULL)) + { + return 1; + } + + misc_menu[0].pHandler(&misc_menu[0]); output = cli_mock_get_output(); if (strstr(output, "CORE-V MCU ThreadX") == NULL) { @@ -44,15 +51,22 @@ static int test_version_output(void) static int test_version_no_crash(void) { const struct cli_cmd_entry *menu; + const struct cli_cmd_entry *misc_menu; cli_mock_reset(); menu = app_get_menu(); - if ((menu == NULL) || (menu[0].pHandler == NULL)) + if ((menu == NULL) || (menu[0].pHandler == NULL) || (menu[0].cookie == 0)) + { + return 1; + } + + misc_menu = (const struct cli_cmd_entry *)(uintptr_t)menu[0].cookie; + if ((misc_menu == NULL) || (misc_menu[0].pHandler == NULL)) { return 1; } - menu[0].pHandler(&menu[0]); + misc_menu[0].pHandler(&misc_menu[0]); return 0; }