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/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 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 "=========================================="