From e53c6dea0daf81d4935e6f56deea239fd0dcb7a4 Mon Sep 17 00:00:00 2001 From: Alex Lanzano Date: Tue, 7 Apr 2026 10:55:31 -0400 Subject: [PATCH 1/2] Add generic wolfHAL Ethernet port with STM32H563ZI Nucleo board support --- .../workflows/wolfhal-stm32h563zi-nucleo.yml | 37 +++ Makefile | 2 + src/port/wolfHAL/.gitignore | 1 + src/port/wolfHAL/Makefile | 49 ++++ src/port/wolfHAL/README.md | 160 ++++++++++++ .../wolfHAL/boards/stm32h563zi_nucleo/board.c | 242 ++++++++++++++++++ .../wolfHAL/boards/stm32h563zi_nucleo/board.h | 189 ++++++++++++++ .../boards/stm32h563zi_nucleo/board.mk | 43 ++++ .../wolfHAL/boards/stm32h563zi_nucleo/ivt.c | 59 +++++ .../boards/stm32h563zi_nucleo/linker.ld | 92 +++++++ .../boards/stm32h563zi_nucleo/startup.c | 47 ++++ .../boards/stm32h563zi_nucleo/syscalls.c | 121 +++++++++ src/port/wolfHAL/main.c | 148 +++++++++++ src/port/wolfHAL/wolfhal_eth.c | 96 +++++++ src/port/wolfHAL/wolfhal_eth.h | 107 ++++++++ 15 files changed, 1393 insertions(+) create mode 100644 .github/workflows/wolfhal-stm32h563zi-nucleo.yml create mode 100644 src/port/wolfHAL/.gitignore create mode 100644 src/port/wolfHAL/Makefile create mode 100644 src/port/wolfHAL/README.md create mode 100644 src/port/wolfHAL/boards/stm32h563zi_nucleo/board.c create mode 100644 src/port/wolfHAL/boards/stm32h563zi_nucleo/board.h create mode 100644 src/port/wolfHAL/boards/stm32h563zi_nucleo/board.mk create mode 100644 src/port/wolfHAL/boards/stm32h563zi_nucleo/ivt.c create mode 100644 src/port/wolfHAL/boards/stm32h563zi_nucleo/linker.ld create mode 100644 src/port/wolfHAL/boards/stm32h563zi_nucleo/startup.c create mode 100644 src/port/wolfHAL/boards/stm32h563zi_nucleo/syscalls.c create mode 100644 src/port/wolfHAL/main.c create mode 100644 src/port/wolfHAL/wolfhal_eth.c create mode 100644 src/port/wolfHAL/wolfhal_eth.h diff --git a/.github/workflows/wolfhal-stm32h563zi-nucleo.yml b/.github/workflows/wolfhal-stm32h563zi-nucleo.yml new file mode 100644 index 00000000..bef4af18 --- /dev/null +++ b/.github/workflows/wolfhal-stm32h563zi-nucleo.yml @@ -0,0 +1,37 @@ +name: wolfHAL STM32H563ZI Nucleo Build + +on: + push: + branches: [ 'master', 'main', 'release/**' ] + pull_request: + branches: [ '*' ] + +jobs: + wolfhal_stm32h563zi_nucleo_build: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v4 + + - name: Install ARM toolchain + run: | + set -euo pipefail + sudo apt-get update + sudo apt-get install -y gcc-arm-none-eabi + + - name: Clone wolfHAL + run: | + set -euo pipefail + git clone --depth 1 https://github.com/wolfSSL/wolfHAL.git ../wolfHAL + + - name: Build wolfHAL port + run: | + set -euo pipefail + make -C src/port/wolfHAL BOARD=stm32h563zi_nucleo + + - name: Verify binary + run: | + set -euo pipefail + test -f src/port/wolfHAL/build/stm32h563zi_nucleo/app.bin + arm-none-eabi-size src/port/wolfHAL/build/stm32h563zi_nucleo/app.elf diff --git a/Makefile b/Makefile index ba1760bb..eae093a5 100644 --- a/Makefile +++ b/Makefile @@ -150,6 +150,8 @@ CPPCHECK_FLAGS=--enable=warning,performance,portability,missingInclude \ --suppress=comparePointers:src/port/rp2350_cyw43439/syscalls.c \ --suppress=unknownMacro:src/port/stm32h563/dot1x_client.c \ --suppress=preprocessorErrorDirective:src/supplicant/supplicant_features.h \ + --suppress=comparePointers:src/port/wolfHAL/boards/stm32h563zi_nucleo/startup.c \ + --suppress=comparePointers:src/port/wolfHAL/boards/stm32h563zi_nucleo/syscalls.c \ --disable=style \ --std=c99 --language=c \ --platform=unix64 \ diff --git a/src/port/wolfHAL/.gitignore b/src/port/wolfHAL/.gitignore new file mode 100644 index 00000000..567609b1 --- /dev/null +++ b/src/port/wolfHAL/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/src/port/wolfHAL/Makefile b/src/port/wolfHAL/Makefile new file mode 100644 index 00000000..977f6a6c --- /dev/null +++ b/src/port/wolfHAL/Makefile @@ -0,0 +1,49 @@ +ROOT = $(CURDIR)/../../.. +PORT_DIR = $(ROOT)/src/port/wolfHAL + +BOARD_DIR = $(PORT_DIR)/boards/$(BOARD) + +ifeq ($(BOARD),) + ifeq ($(MAKECMDGOALS),clean) + clean: + rm -rf build + .PHONY: clean + else + $(error BOARD is required. Usage: make BOARD=stm32h563zi_nucleo) + endif +else +include $(BOARD_DIR)/board.mk + +SOURCE = $(PORT_DIR)/main.c +SOURCE += $(PORT_DIR)/wolfhal_eth.c +SOURCE += $(ROOT)/src/wolfip.c +SOURCE += $(BOARD_SOURCE) + +BUILD_DIR = build/$(BOARD) +OBJECTS = $(patsubst %.c,$(BUILD_DIR)/%.o,$(SOURCE)) +DEPENDS = $(OBJECTS:.o=.d) + +all: $(BUILD_DIR)/app.bin + +$(BUILD_DIR)/%.o: %.c Makefile + @mkdir -p $(dir $@) + $(GCC) $(CFLAGS) -c -o $@ $< + +.SECONDARY: +$(BUILD_DIR)/%.elf: $(OBJECTS) $(LINKER_SCRIPT) + @mkdir -p $(dir $@) + $(GCC) $(CFLAGS) $(LDFLAGS) -T $(LINKER_SCRIPT) -o $@ $(OBJECTS) $(LDLIBS) + +$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf + $(OBJCOPY) $^ -O binary $@ + +.PHONY: clean size +clean: + rm -rf build + +size: $(BUILD_DIR)/app.elf + $(GCC_PATH)arm-none-eabi-size $< + +-include $(DEPENDS) + +endif diff --git a/src/port/wolfHAL/README.md b/src/port/wolfHAL/README.md new file mode 100644 index 00000000..0900fba9 --- /dev/null +++ b/src/port/wolfHAL/README.md @@ -0,0 +1,160 @@ +# wolfHAL Port for wolfIP + +Generic wolfIP port that uses the wolfHAL Ethernet API (`whal_Eth` / +`whal_EthPhy`). Users create a wolfHAL board and the port handles the +rest — bridging wolfHAL's Ethernet MAC/PHY drivers to wolfIP's +link-layer device interface. + +## Supported Boards + +| Board | MCU | PHY | Directory | +|-------|-----|-----|-----------| +| NUCLEO-H563ZI | STM32H563ZI | LAN8742A | `boards/stm32h563zi_nucleo` | + +## Directory Structure + +``` +src/port/wolfHAL/ +├── Makefile # Top-level build: make BOARD= +├── main.c # Generic main: board_init -> wolfhal_eth_init -> wolfIP_poll loop +├── wolfhal_eth.h # Port API and wolfhal_eth_ctx struct +├── wolfhal_eth.c # Bridges wolfIP_ll_dev poll/send to whal_Eth_Recv/whal_Eth_Send +└── boards/ + └── / + ├── board.mk # Toolchain, CFLAGS, wolfHAL driver sources + ├── board.h # Board API declarations and device externs + ├── board.c # Clock, GPIO, Ethernet, PHY, UART, timer setup + ├── startup.c # Reset_Handler: copies .data, zeros .bss, calls main() + ├── ivt.c # Interrupt vector table + ├── syscalls.c # libc stubs (_write, _sbrk, etc.) + └── linker.ld # Memory layout (FLASH/RAM regions) +``` + +## Building + +``` +cd src/port/wolfHAL +make BOARD=stm32h563zi_nucleo +``` + +Override the wolfHAL location (defaults to `../../../wolfHAL` relative to +the wolfip root, i.e. a sibling directory): + +``` +make BOARD=stm32h563zi_nucleo WOLFHAL_ROOT=/path/to/wolfHAL +``` + +Override IP configuration or MAC address at build time: + +``` +make BOARD=stm32h563zi_nucleo \ + CFLAGS+='-DWOLFIP_IP=\"10.0.0.2\" -DWOLFIP_NETMASK=\"255.255.255.0\" -DWOLFIP_GW=\"10.0.0.1\"' +``` + +``` +make BOARD=stm32h563zi_nucleo \ + CFLAGS+='-DBOARD_MAC_ADDR={0x02,0xAA,0xBB,0xCC,0xDD,0xEE}' +``` + +## Adding a New Board + +Create a new directory under `boards/` with the following files: + +### board.h + +Must declare the following: + +#### Required Device Externs + +| Variable | Type | Description | +|----------|------|-------------| +| `g_whalEth` | `whal_Eth` | Initialized Ethernet MAC device | +| `g_whalEthPhy` | `whal_EthPhy` | Initialized Ethernet PHY device | +| `g_whalUart` | `whal_Uart` | Initialized UART device (used by `_write` syscall for printf) | +| `g_whalRng` | `whal_Rng` | Initialized RNG device (used by `wolfIP_getrandom`) | + +These names are required — `main.c`, `wolfhal_eth.c`, and `syscalls.c` +reference them directly. + +#### Required Functions + +| Function | Signature | Description | +|----------|-----------|-------------| +| `board_init` | `whal_Error board_init(void)` | Initialize all board hardware. Must call `whal_Eth_Init`, `whal_EthPhy_Init`, `whal_Uart_Init`, and start the system timer before returning. Returns `WHAL_SUCCESS` on success. | +| `board_deinit` | `whal_Error board_deinit(void)` | Tear down board hardware in reverse order. | +| `board_get_tick` | `uint32_t board_get_tick(void)` | Return a millisecond tick counter. Used by `wolfhal_eth_init` for link timeout and by `wolfIP_poll` for stack timing. | + +### board.c + +Implements the functions above. Typical `board_init` sequence: + +1. Initialize clocks (PLL, peripheral clocks) +2. Initialize GPIO (UART pins, Ethernet pins) +3. Initialize UART (`whal_Uart_Init`) +4. Initialize Ethernet MAC (`whal_Eth_Init`) +5. Initialize Ethernet PHY (`whal_EthPhy_Init`) +6. Initialize and start system timer + +The `whal_Eth` device must have its `macAddr` field set — this is +where wolfIP reads the interface MAC address from. + +### board.mk + +Provides build configuration. Must set: + +| Variable | Description | +|----------|-------------| +| `WOLFHAL_ROOT` | Path to wolfHAL (use `?=` so it's overridable) | +| `GCC` | Cross-compiler path (e.g. `arm-none-eabi-gcc`) | +| `OBJCOPY` | Objcopy tool | +| `CFLAGS` | Compiler flags (architecture, warnings, includes) | +| `LDFLAGS` | Linker flags | +| `LDLIBS` | Libraries to link (libc, libgcc, etc.) | +| `LINKER_SCRIPT` | Path to the board's linker script | +| `BOARD_SOURCE` | List of board + wolfHAL driver source files | + +### syscalls.c + +Must provide: +- Standard libc stubs: `_write`, `_read`, `_sbrk`, `_close`, `_fstat`, + `_isatty`, `_lseek`, `_exit`, `_kill`, `_getpid` +- `_write` should route to `whal_Uart_Send(&g_whalUart, ...)` so that + `printf` outputs to UART +- `uint32_t wolfIP_getrandom(void)` is provided by `main.c` using + `whal_Rng_Generate(&g_whalRng, ...)` + +### startup.c, ivt.c, linker.ld + +Standard bare-metal files for your target architecture. See the +`stm32h563zi_nucleo` board for a reference implementation. + +## Port API + +The port exposes a single function: + +```c +#include "wolfhal_eth.h" + +struct wolfhal_eth_ctx ctx = { + .eth = &g_whalEth, + .phy = &g_whalEthPhy, +}; + +int ret = wolfhal_eth_init(wolfIP_getdev(ipstack), &ctx); +``` + +`wolfhal_eth_init` will: +1. Poll `whal_EthPhy_GetLinkState` until link comes up (5s timeout, + configurable via `WOLFHAL_ETH_LINK_TIMEOUT_MS`) +2. Start the MAC with negotiated speed/duplex +3. Copy `eth->macAddr` to the wolfIP device +4. Register poll/send callbacks that bridge to `whal_Eth_Recv`/`whal_Eth_Send` + +## Naming Conventions + +- All port functions and variables use `snake_case` +- Board functions use `board_` prefix: `board_init`, `board_get_tick` +- Port functions use `wolfhal_` prefix: `wolfhal_eth_init` +- wolfHAL API calls retain their own naming (`whal_Eth_Init`, etc.) +- Global device instances use `g_whal` prefix: `g_whalEth`, `g_whalEthPhy`, `g_whalUart`, `g_whalRng` +- Macros use `UPPER_SNAKE_CASE` diff --git a/src/port/wolfHAL/boards/stm32h563zi_nucleo/board.c b/src/port/wolfHAL/boards/stm32h563zi_nucleo/board.c new file mode 100644 index 00000000..2e52e81b --- /dev/null +++ b/src/port/wolfHAL/boards/stm32h563zi_nucleo/board.c @@ -0,0 +1,242 @@ +/* board.c + * + * Copyright (C) 2024-2026 wolfSSL Inc. + * + * Minimal board configuration for STM32H563ZI Nucleo-144 + * Only sets up what's needed for wolfIP: clocks, GPIO, Ethernet, PHY, RNG. + * + * This file is part of wolfIP TCP/IP stack. + * + * wolfIP is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfIP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include +#include +#include "board.h" +#include +#include + +/* SysTick timing */ +volatile uint32_t g_tick = 0; + +void SysTick_Handler(void) +{ + g_tick++; +} + +uint32_t board_get_tick(void) +{ + return g_tick; +} + +whal_Timeout g_whalTimeout = { + .timeoutTicks = 1000, + .GetTick = board_get_tick, +}; + +/* Peripheral clocks enabled before bringing up the peripherals (ETH clocks + * are enabled separately, after RMII mode is selected in SBS). */ +static const whal_Stm32h5_Rcc_PeriphClk g_periphClks[] = { + {WHAL_STM32H563_GPIOA_CLOCK}, + {WHAL_STM32H563_GPIOB_CLOCK}, + {WHAL_STM32H563_GPIOC_CLOCK}, + {WHAL_STM32H563_GPIOD_CLOCK}, + {WHAL_STM32H563_GPIOG_CLOCK}, + {WHAL_STM32H563_USART3_CLOCK}, + {WHAL_STM32H563_RNG_CLOCK}, + {WHAL_STM32H563_SBS_CLOCK}, +}; +#define PERIPH_CLK_COUNT (sizeof(g_periphClks) / sizeof(g_periphClks[0])) + +static const whal_Stm32h5_Rcc_PeriphClk g_ethClocks[] = { + {WHAL_STM32H563_ETH_CLOCK}, + {WHAL_STM32H563_ETHTX_CLOCK}, + {WHAL_STM32H563_ETHRX_CLOCK}, +}; +#define ETH_CLOCK_COUNT (sizeof(g_ethClocks) / sizeof(g_ethClocks[0])) + +/* Ethernet descriptor rings + buffer pool. Referenced by the ETH singleton's + * cfg (WHAL_CFG_STM32H5_ETH_DEV in board.h), so these must be global. */ +whal_Stm32h5_Eth_TxDesc ethTxDescs[BOARD_ETH_TX_DESC_COUNT] + __attribute__((aligned(16))); +whal_Stm32h5_Eth_RxDesc ethRxDescs[BOARD_ETH_RX_DESC_COUNT] + __attribute__((aligned(16))); +uint8_t ethTxBufs[BOARD_ETH_TX_DESC_COUNT * BOARD_ETH_TX_BUF_SIZE] + __attribute__((aligned(4))); +uint8_t ethRxBufs[BOARD_ETH_RX_DESC_COUNT * BOARD_ETH_RX_BUF_SIZE] + __attribute__((aligned(4))); + +/* UART: USART3 on the ST-Link VCP (caller-allocated, multi-instance driver) */ +whal_Uart g_whalUart = { + .base = WHAL_STM32H563_USART3_BASE, + /* .driver: direct API mapping */ + .cfg = &(whal_Stm32h5_Uart_Cfg) { + .brr = WHAL_STM32H5_UART_BRR(168000000, 115200), + .timeout = &g_whalTimeout, + }, +}; + +/* + * FLASH_ACR (0x40022000): LATENCY[3:0] = 5 wait states for 168 MHz, + * WRHIGHFREQ[5:4] = 2. Must be set before raising the clock. + */ +#define FLASH_ACR_ADDR 0x40022000 +#define FLASH_ACR_LATENCY_168MHZ ((2 << 4) | 5) + +/* RMII mode select lives in SBS_PMCR (0x44000500), bits [23:21] = 0b100. */ +#define SBS_PMCR (*(volatile uint32_t *)0x44000500) +#define SBS_PMCR_ETH_SEL_Msk (7UL << 21) +#define SBS_PMCR_ETH_SEL_RMII (4UL << 21) + +whal_Error board_init(void) +{ + whal_Error err; + size_t i; + + /* Set flash latency before increasing clock speed */ + *(volatile uint32_t *)FLASH_ACR_ADDR = FLASH_ACR_LATENCY_168MHZ; + + /* HSI 64 MHz -> PLL1 (HSI/8 * 63 / 3 = 168 MHz) -> SYSCLK = PLL1 */ + + /* RCC_CR.HSIDIV resets to /4 (16 MHz) on H5, not /1. Force it back to + * /1 so the PLL sees 64 MHz; otherwise the divider chain below silently + * lands on 42 MHz instead of 168 MHz. */ + err = whal_Stm32h5_Rcc_SetHsiDiv(0); + if (err) + return err; + + err = whal_Stm32h5_Rcc_EnableOsc( + &(whal_Stm32h5_Rcc_OscCfg){WHAL_STM32H5_RCC_HSI_CFG}); + if (err) + return err; + + err = whal_Stm32h5_Rcc_EnablePll1(&(whal_Stm32h5_Rcc_PllCfg){ + .clkSrc = WHAL_STM32H5_RCC_PLLCLK_SRC_HSI, + .m = 8, .n = 62, .p = 2, .q = 2, .r = 2, + }); + if (err) + return err; + + err = whal_Stm32h5_Rcc_SetSysClock(WHAL_STM32H5_RCC_SYSCLK_SRC_PLL1); + if (err) + return err; + + /* Enable peripheral clocks (ETH excluded — needs SBS RMII config first) */ + for (i = 0; i < PERIPH_CLK_COUNT; i++) { + err = whal_Stm32h5_Rcc_EnablePeriphClk(&g_periphClks[i]); + if (err) + return err; + } + + /* Select RMII mode before enabling the ETH clocks */ + SBS_PMCR = (SBS_PMCR & ~SBS_PMCR_ETH_SEL_Msk) | SBS_PMCR_ETH_SEL_RMII; + + for (i = 0; i < ETH_CLOCK_COUNT; i++) { + err = whal_Stm32h5_Rcc_EnablePeriphClk(&g_ethClocks[i]); + if (err) + return err; + } + + /* Enable HSI48 for the RNG kernel clock */ + err = whal_Stm32h5_Rcc_EnableOsc( + &(whal_Stm32h5_Rcc_OscCfg){WHAL_STM32H5_RCC_HSI48_CFG}); + if (err) + return err; + + err = whal_Gpio_Init(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Uart_Init(&g_whalUart); + if (err) + return err; + + err = whal_Rng_Init(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Timer_Init(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Timer_Start(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Eth_Init(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_EthPhy_Init(WHAL_INTERNAL_DEV); + if (err) + return err; + + return WHAL_SUCCESS; +} + +whal_Error board_deinit(void) +{ + whal_Error err; + size_t i; + + err = whal_Timer_Stop(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Timer_Deinit(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_EthPhy_Deinit(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Eth_Deinit(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Rng_Deinit(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Uart_Deinit(&g_whalUart); + if (err) + return err; + + err = whal_Gpio_Deinit(WHAL_INTERNAL_DEV); + if (err) + return err; + + for (i = 0; i < ETH_CLOCK_COUNT; i++) { + err = whal_Stm32h5_Rcc_DisablePeriphClk(&g_ethClocks[i]); + if (err) + return err; + } + + for (i = 0; i < PERIPH_CLK_COUNT; i++) { + err = whal_Stm32h5_Rcc_DisablePeriphClk(&g_periphClks[i]); + if (err) + return err; + } + + err = whal_Stm32h5_Rcc_SetSysClock(WHAL_STM32H5_RCC_SYSCLK_SRC_HSI); + if (err) + return err; + err = whal_Stm32h5_Rcc_DisablePll1(); + if (err) + return err; + + return WHAL_SUCCESS; +} diff --git a/src/port/wolfHAL/boards/stm32h563zi_nucleo/board.h b/src/port/wolfHAL/boards/stm32h563zi_nucleo/board.h new file mode 100644 index 00000000..b0ed12d0 --- /dev/null +++ b/src/port/wolfHAL/boards/stm32h563zi_nucleo/board.h @@ -0,0 +1,189 @@ +/* board.h + * + * Copyright (C) 2024-2026 wolfSSL Inc. + * + * Minimal board configuration for STM32H563ZI Nucleo-144 + * + * This file is part of wolfIP TCP/IP stack. + * + * wolfIP is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfIP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef BOARD_H +#define BOARD_H + +#include +#include +#include +#include +#include + +/* Caller-allocated devices (multi-instance drivers). */ +extern whal_Uart g_whalUart; + +extern whal_Timeout g_whalTimeout; +extern volatile uint32_t g_tick; + +/* The generic wolfIP port (main.c, wolfhal_eth.c) references the board's + * Ethernet, PHY, and RNG devices through these names. Under the current + * wolfHAL API these are single-instance drivers whose device structs live + * in the driver translation units (built from the WHAL_CFG_*_DEV + * initializers below), so we alias the documented g_whal* names onto those + * driver singletons. */ +#define g_whalEth (*(whal_Eth *)&whal_Stm32h5_Eth_Dev) +#define g_whalEthPhy (*(whal_EthPhy *)&whal_Lan8742a_Dev) +#define g_whalRng (*(whal_Rng *)&whal_Stm32h5_Rng_Dev) + +/* Ethernet PHY: LAN8742A on MDIO address 0 */ +#define BOARD_ETH_PHY_ADDR 0 + +enum { + UART_TX_PIN, + UART_RX_PIN, + ETH_RMII_REF_CLK_PIN, + ETH_RMII_MDIO_PIN, + ETH_RMII_MDC_PIN, + ETH_RMII_CRS_DV_PIN, + ETH_RMII_RXD0_PIN, + ETH_RMII_RXD1_PIN, + ETH_RMII_TX_EN_PIN, + ETH_RMII_TXD0_PIN, + ETH_RMII_TXD1_PIN, + PIN_COUNT, +}; + +/* GPIO dev initializer — singleton defined in the gpio driver TU. + * Only the USART3 (ST-Link VCP) and Ethernet RMII pins are configured. */ +#define WHAL_CFG_STM32H5_GPIO_DEV { \ + .base = WHAL_STM32H563_GPIO_BASE, \ + .cfg = (void *)&(const whal_Stm32h5_Gpio_Cfg){ \ + .pinCfg = (const whal_Stm32h5_Gpio_PinCfg[PIN_COUNT]){ \ + /* USART3 TX on PD8, AF7 (ST-Link VCP) */ \ + [UART_TX_PIN] = WHAL_STM32H5_GPIO_PIN( \ + WHAL_STM32H5_GPIO_PORT_D, 8, WHAL_STM32H5_GPIO_MODE_ALTFN, \ + WHAL_STM32H5_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32H5_GPIO_SPEED_FAST, \ + WHAL_STM32H5_GPIO_PULL_UP, 7), \ + /* USART3 RX on PD9, AF7 (ST-Link VCP) */ \ + [UART_RX_PIN] = WHAL_STM32H5_GPIO_PIN( \ + WHAL_STM32H5_GPIO_PORT_D, 9, WHAL_STM32H5_GPIO_MODE_ALTFN, \ + WHAL_STM32H5_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32H5_GPIO_SPEED_FAST, \ + WHAL_STM32H5_GPIO_PULL_UP, 7), \ + [ETH_RMII_REF_CLK_PIN] = WHAL_STM32H5_GPIO_PIN( \ + WHAL_STM32H5_GPIO_PORT_A, 1, WHAL_STM32H5_GPIO_MODE_ALTFN, \ + WHAL_STM32H5_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32H5_GPIO_SPEED_HIGH, \ + WHAL_STM32H5_GPIO_PULL_NONE, 11), \ + [ETH_RMII_MDIO_PIN] = WHAL_STM32H5_GPIO_PIN( \ + WHAL_STM32H5_GPIO_PORT_A, 2, WHAL_STM32H5_GPIO_MODE_ALTFN, \ + WHAL_STM32H5_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32H5_GPIO_SPEED_HIGH, \ + WHAL_STM32H5_GPIO_PULL_NONE, 11), \ + [ETH_RMII_MDC_PIN] = WHAL_STM32H5_GPIO_PIN( \ + WHAL_STM32H5_GPIO_PORT_C, 1, WHAL_STM32H5_GPIO_MODE_ALTFN, \ + WHAL_STM32H5_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32H5_GPIO_SPEED_HIGH, \ + WHAL_STM32H5_GPIO_PULL_NONE, 11), \ + [ETH_RMII_CRS_DV_PIN] = WHAL_STM32H5_GPIO_PIN( \ + WHAL_STM32H5_GPIO_PORT_A, 7, WHAL_STM32H5_GPIO_MODE_ALTFN, \ + WHAL_STM32H5_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32H5_GPIO_SPEED_HIGH, \ + WHAL_STM32H5_GPIO_PULL_NONE, 11), \ + [ETH_RMII_RXD0_PIN] = WHAL_STM32H5_GPIO_PIN( \ + WHAL_STM32H5_GPIO_PORT_C, 4, WHAL_STM32H5_GPIO_MODE_ALTFN, \ + WHAL_STM32H5_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32H5_GPIO_SPEED_HIGH, \ + WHAL_STM32H5_GPIO_PULL_NONE, 11), \ + [ETH_RMII_RXD1_PIN] = WHAL_STM32H5_GPIO_PIN( \ + WHAL_STM32H5_GPIO_PORT_C, 5, WHAL_STM32H5_GPIO_MODE_ALTFN, \ + WHAL_STM32H5_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32H5_GPIO_SPEED_HIGH, \ + WHAL_STM32H5_GPIO_PULL_NONE, 11), \ + [ETH_RMII_TX_EN_PIN] = WHAL_STM32H5_GPIO_PIN( \ + WHAL_STM32H5_GPIO_PORT_G, 11, WHAL_STM32H5_GPIO_MODE_ALTFN, \ + WHAL_STM32H5_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32H5_GPIO_SPEED_HIGH, \ + WHAL_STM32H5_GPIO_PULL_NONE, 11), \ + [ETH_RMII_TXD0_PIN] = WHAL_STM32H5_GPIO_PIN( \ + WHAL_STM32H5_GPIO_PORT_G, 13, WHAL_STM32H5_GPIO_MODE_ALTFN, \ + WHAL_STM32H5_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32H5_GPIO_SPEED_HIGH, \ + WHAL_STM32H5_GPIO_PULL_NONE, 11), \ + [ETH_RMII_TXD1_PIN] = WHAL_STM32H5_GPIO_PIN( \ + WHAL_STM32H5_GPIO_PORT_B, 15, WHAL_STM32H5_GPIO_MODE_ALTFN, \ + WHAL_STM32H5_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32H5_GPIO_SPEED_HIGH, \ + WHAL_STM32H5_GPIO_PULL_NONE, 11), \ + }, \ + .pinCount = PIN_COUNT, \ + }, \ +} + +/* RNG dev initializer — singleton defined in the rng driver TU. */ +#define WHAL_CFG_STM32H5_RNG_DEV { \ + .base = WHAL_STM32H563_RNG_BASE, \ + .cfg = (void *)&(const whal_Stm32h5_Rng_Cfg){ \ + .timeout = &g_whalTimeout, \ + }, \ +} + +/* ETH descriptor rings + buffer pool — defined in board.c, captured by the + * ETH singleton's cfg below (expanded in the eth driver TU). */ +#define BOARD_ETH_TX_DESC_COUNT 4 +#define BOARD_ETH_RX_DESC_COUNT 4 +#define BOARD_ETH_TX_BUF_SIZE 1536 +#define BOARD_ETH_RX_BUF_SIZE 1536 + +extern whal_Stm32h5_Eth_TxDesc ethTxDescs[BOARD_ETH_TX_DESC_COUNT]; +extern whal_Stm32h5_Eth_RxDesc ethRxDescs[BOARD_ETH_RX_DESC_COUNT]; +extern uint8_t ethTxBufs[BOARD_ETH_TX_DESC_COUNT * BOARD_ETH_TX_BUF_SIZE]; +extern uint8_t ethRxBufs[BOARD_ETH_RX_DESC_COUNT * BOARD_ETH_RX_BUF_SIZE]; + +#ifndef BOARD_MAC_ADDR +#define BOARD_MAC_ADDR {0x00, 0x80, 0xE1, 0x00, 0x00, 0x01} +#endif + +/* ETH dev initializer — singleton defined in the eth driver TU. */ +#define WHAL_CFG_STM32H5_ETH_DEV { \ + .base = WHAL_STM32H563_ETH_BASE, \ + .macAddr = BOARD_MAC_ADDR, \ + .cfg = (void *)&(const whal_Stm32h5_Eth_Cfg){ \ + .txDescs = ethTxDescs, \ + .txBufs = ethTxBufs, \ + .txDescCount = BOARD_ETH_TX_DESC_COUNT, \ + .txBufSize = BOARD_ETH_TX_BUF_SIZE, \ + .rxDescs = ethRxDescs, \ + .rxBufs = ethRxBufs, \ + .rxDescCount = BOARD_ETH_RX_DESC_COUNT, \ + .rxBufSize = BOARD_ETH_RX_BUF_SIZE, \ + .mdioCr = 4, /* HCLK 168 MHz -> MDC = 168/102 ~= 1.6 MHz */ \ + .timeout = &g_whalTimeout, \ + }, \ +} + +/* LAN8742A PHY dev initializer — singleton defined in the phy driver TU. */ +#define WHAL_CFG_LAN8742A_DEV { \ + .eth = NULL, \ + .addr = BOARD_ETH_PHY_ADDR, \ + .cfg = (void *)&(const whal_Lan8742a_Cfg){ \ + .timeout = &g_whalTimeout, \ + }, \ +} + +/* SysTick dev initializer — singleton defined in the systick driver TU. */ +#define WHAL_CFG_SYSTICK_DEV { \ + .base = WHAL_CORTEX_M33_SYSTICK_BASE, \ + .cfg = (void *)&(const whal_SysTick_Cfg){ \ + .cyclesPerTick = 168000000 / 1000, \ + .clkSrc = WHAL_SYSTICK_CLKSRC_SYSCLK, \ + .tickInt = WHAL_SYSTICK_TICKINT_ENABLED, \ + }, \ +} + +whal_Error board_init(void); +whal_Error board_deinit(void); +uint32_t board_get_tick(void); + +#endif /* BOARD_H */ diff --git a/src/port/wolfHAL/boards/stm32h563zi_nucleo/board.mk b/src/port/wolfHAL/boards/stm32h563zi_nucleo/board.mk new file mode 100644 index 00000000..95a121e4 --- /dev/null +++ b/src/port/wolfHAL/boards/stm32h563zi_nucleo/board.mk @@ -0,0 +1,43 @@ +_WOLFIP_BOARD_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) + +WOLFHAL_ROOT ?= $(ROOT)/../wolfHAL + +GCC = $(GCC_PATH)arm-none-eabi-gcc +LD = $(GCC_PATH)arm-none-eabi-ld +OBJCOPY = $(GCC_PATH)arm-none-eabi-objcopy + +CFLAGS += -Wall -Werror -g3 -ffreestanding -nostdlib -mcpu=cortex-m33 -Os +CFLAGS += -DPLATFORM_STM32H5 -MMD -MP +CFLAGS += -DWHAL_CFG_STM32H5_GPIO_DIRECT_API_MAPPING +CFLAGS += -DWHAL_CFG_STM32H5_RCC_PLL_DRIVER +CFLAGS += -DWHAL_CFG_STM32H5_RCC_DIRECT_API_MAPPING +CFLAGS += -DWHAL_CFG_STM32H5_UART_DIRECT_API_MAPPING +CFLAGS += -DWHAL_CFG_STM32H5_RNG_DIRECT_API_MAPPING +CFLAGS += -DWHAL_CFG_STM32H5_ETH_DIRECT_API_MAPPING +CFLAGS += -DWHAL_CFG_LAN8742A_ETH_PHY_DIRECT_API_MAPPING +CFLAGS += -DWHAL_CFG_STM32H5_FLASH_DIRECT_API_MAPPING +CFLAGS += -DWHAL_CFG_SYSTICK_TIMER_DIRECT_API_MAPPING +CFLAGS += -I$(WOLFHAL_ROOT) -I$(_WOLFIP_BOARD_DIR) +CFLAGS += -I$(ROOT) -I$(ROOT)/src -I$(PORT_DIR) + +CFLAGS += -fdata-sections -ffunction-sections + +LDFLAGS = -nostdlib -Wl,-gc-sections +LDLIBS = -Wl,--start-group -lc -lm -lgcc -lnosys -Wl,--end-group +LINKER_SCRIPT ?= $(_WOLFIP_BOARD_DIR)/linker.ld + +BOARD_SOURCE = $(_WOLFIP_BOARD_DIR)/startup.c +BOARD_SOURCE += $(_WOLFIP_BOARD_DIR)/ivt.c +BOARD_SOURCE += $(_WOLFIP_BOARD_DIR)/board.c +BOARD_SOURCE += $(_WOLFIP_BOARD_DIR)/syscalls.c + +# wolfHAL drivers +# Domains with WHAL_CFG_*_API_MAPPING_* set include only the driver TU; +# the generic dispatch TU would redefine the top-level symbols. +BOARD_SOURCE += $(WOLFHAL_ROOT)/src/reg.c +BOARD_SOURCE += $(WOLFHAL_ROOT)/src/eth/stm32h5_eth.c +BOARD_SOURCE += $(WOLFHAL_ROOT)/src/eth_phy/lan8742a_eth_phy.c +BOARD_SOURCE += $(WOLFHAL_ROOT)/src/gpio/stm32h5_gpio.c +BOARD_SOURCE += $(WOLFHAL_ROOT)/src/uart/stm32h5_uart.c +BOARD_SOURCE += $(WOLFHAL_ROOT)/src/rng/stm32h5_rng.c +BOARD_SOURCE += $(WOLFHAL_ROOT)/src/timer/systick.c diff --git a/src/port/wolfHAL/boards/stm32h563zi_nucleo/ivt.c b/src/port/wolfHAL/boards/stm32h563zi_nucleo/ivt.c new file mode 100644 index 00000000..050ee86d --- /dev/null +++ b/src/port/wolfHAL/boards/stm32h563zi_nucleo/ivt.c @@ -0,0 +1,59 @@ +/* ivt.c + * + * Copyright (C) 2024-2026 wolfSSL Inc. + * + * Interrupt vector table for Cortex-M33 (STM32H563) + * + * This file is part of wolfIP TCP/IP stack. + * + * wolfIP is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfIP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +#include + +extern void Reset_Handler(void); +extern unsigned long _estack; + +static void default_handler(void) +{ + while (1) { } +} + +void NMI_Handler(void) __attribute__((weak, alias("default_handler"))); +void HardFault_Handler(void) __attribute__((weak, alias("default_handler"))); +void MemManage_Handler(void) __attribute__((weak, alias("default_handler"))); +void BusFault_Handler(void) __attribute__((weak, alias("default_handler"))); +void UsageFault_Handler(void) __attribute__((weak, alias("default_handler"))); +void SVC_Handler(void) __attribute__((weak, alias("default_handler"))); +void DebugMon_Handler(void) __attribute__((weak, alias("default_handler"))); +void PendSV_Handler(void) __attribute__((weak, alias("default_handler"))); +void SysTick_Handler(void) __attribute__((weak, alias("default_handler"))); + +__attribute__((section(".isr_vector"))) +const uint32_t vector_table[16 + 96] = { + [0] = (uint32_t)&_estack, + [1] = (uint32_t)&Reset_Handler, + [2] = (uint32_t)&NMI_Handler, + [3] = (uint32_t)&HardFault_Handler, + [4] = (uint32_t)&MemManage_Handler, + [5] = (uint32_t)&BusFault_Handler, + [6] = (uint32_t)&UsageFault_Handler, + [7] = 0, [8] = 0, [9] = 0, [10] = 0, + [11] = (uint32_t)&SVC_Handler, + [12] = (uint32_t)&DebugMon_Handler, + [13] = 0, + [14] = (uint32_t)&PendSV_Handler, + [15] = (uint32_t)&SysTick_Handler, + [16 ... 111] = (uint32_t)&default_handler, +}; diff --git a/src/port/wolfHAL/boards/stm32h563zi_nucleo/linker.ld b/src/port/wolfHAL/boards/stm32h563zi_nucleo/linker.ld new file mode 100644 index 00000000..e7115549 --- /dev/null +++ b/src/port/wolfHAL/boards/stm32h563zi_nucleo/linker.ld @@ -0,0 +1,92 @@ +/* STM32H563ZI Linker Script + * + * Memory Map: + * FLASH: 2MB @ 0x08000000 + * SRAM: 640KB @ 0x20000000 (contiguous SRAM1+SRAM2+SRAM3) + */ + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 640K +} + +_estack = ORIGIN(RAM) + LENGTH(RAM); +_sidata = LOADADDR(.data); + +_Min_Heap_Size = 0x10000; /* 64KB heap */ +_Min_Stack_Size = 0x8000; /* 32KB stack */ +_heap_limit = _estack - _Min_Stack_Size; + +SECTIONS +{ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) + . = ALIGN(4); + } > FLASH + + .text : + { + . = ALIGN(4); + *(.text*) + *(.rodata*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + . = ALIGN(4); + } > FLASH + + .preinit_array : + { + __preinit_array_start = .; + KEEP(*(.preinit_array*)) + __preinit_array_end = .; + } > FLASH + + .init_array : + { + __init_array_start = .; + KEEP(*(.init_array*)) + __init_array_end = .; + } > FLASH + + .fini_array : + { + __fini_array_start = .; + KEEP(*(.fini_array*)) + __fini_array_end = .; + } > FLASH + + .data : + { + . = ALIGN(4); + _sdata = .; + *(.data*) + . = ALIGN(4); + _edata = .; + } > RAM AT > FLASH + + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + } > RAM + + ._user_heap_stack (NOLOAD) : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } > RAM +} diff --git a/src/port/wolfHAL/boards/stm32h563zi_nucleo/startup.c b/src/port/wolfHAL/boards/stm32h563zi_nucleo/startup.c new file mode 100644 index 00000000..45c4f0f3 --- /dev/null +++ b/src/port/wolfHAL/boards/stm32h563zi_nucleo/startup.c @@ -0,0 +1,47 @@ +/* startup.c + * + * Copyright (C) 2024-2026 wolfSSL Inc. + * + * Cortex-M startup: copies .data, zeros .bss, calls main(). + * + * This file is part of wolfIP TCP/IP stack. + * + * wolfIP is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfIP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +#include + +extern uint32_t _sidata; +extern uint32_t _sdata; +extern uint32_t _edata; +extern uint32_t _sbss; +extern uint32_t _ebss; +extern void __libc_init_array(void); + +int main(void); + +void Reset_Handler(void) +{ + uint32_t *src; + uint32_t *dst; + + src = &_sidata; + for (dst = &_sdata; dst < &_edata; ) + *dst++ = *src++; + for (dst = &_sbss; dst < &_ebss; ) + *dst++ = 0u; + __libc_init_array(); + (void)main(); + while (1) { } +} diff --git a/src/port/wolfHAL/boards/stm32h563zi_nucleo/syscalls.c b/src/port/wolfHAL/boards/stm32h563zi_nucleo/syscalls.c new file mode 100644 index 00000000..6fd78f7c --- /dev/null +++ b/src/port/wolfHAL/boards/stm32h563zi_nucleo/syscalls.c @@ -0,0 +1,121 @@ +/* syscalls.c + * + * Copyright (C) 2024-2026 wolfSSL Inc. + * + * Minimal libc stubs and wolfIP platform hooks for bare-metal. + * + * This file is part of wolfIP TCP/IP stack. + * + * wolfIP is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfIP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +#include +#include +#include +#include +#include +extern uint32_t _ebss; +extern uint32_t _heap_limit; +extern whal_Uart g_whalUart; + +static char *heap_end; + +int _write(int file, const char *ptr, int len) +{ + (void)file; + if (len > 0) + whal_Uart_Send(&g_whalUart, ptr, (size_t)len); + return len; +} + +int _close(int file) +{ + (void)file; + return -1; +} + +int _fstat(int file, struct stat *st) +{ + (void)file; + if (st == NULL) { + errno = EINVAL; + return -1; + } + 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 _read(int file, char *ptr, int len) +{ + (void)file; + (void)ptr; + (void)len; + return 0; +} + +void *_sbrk(ptrdiff_t incr) +{ + char *prev; + if (heap_end == 0) + heap_end = (char *)&_ebss; + prev = heap_end; + if ((heap_end + incr) >= (char *)&_heap_limit) { + errno = ENOMEM; + return (void *)-1; + } + heap_end += incr; + return prev; +} + +void _exit(int status) +{ + (void)status; + while (1) { } +} + +int _kill(int pid, int sig) +{ + (void)pid; + (void)sig; + errno = EINVAL; + return -1; +} + +int _getpid(void) +{ + return 1; +} + +void _init(void) +{ +} + +void _fini(void) +{ +} + diff --git a/src/port/wolfHAL/main.c b/src/port/wolfHAL/main.c new file mode 100644 index 00000000..a046b059 --- /dev/null +++ b/src/port/wolfHAL/main.c @@ -0,0 +1,148 @@ +/* main.c + * + * Copyright (C) 2024-2026 wolfSSL Inc. + * + * Generic wolfHAL main for wolfIP — works with any wolfHAL board that + * provides whal_Eth and whal_EthPhy. + * + * This file is part of wolfIP TCP/IP stack. + * + * wolfIP is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfIP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include +#include +#include +#include "wolfip.h" +#include "wolfhal_eth.h" +#include "board.h" + +#ifndef WOLFIP_IP +#define WOLFIP_IP "192.168.1.100" +#endif +#ifndef WOLFIP_NETMASK +#define WOLFIP_NETMASK "255.255.255.0" +#endif +#ifndef WOLFIP_GW +#define WOLFIP_GW "192.168.1.1" +#endif + +#define ECHO_PORT 7 + +static int listen_fd = -1; + +static void echo_cb(int sockfd, uint16_t events, void *arg) +{ + struct wolfIP *s = (struct wolfIP *)arg; + uint8_t buf[512]; + int ret; + + if ((events & CB_EVENT_CLOSED) && sockfd != listen_fd) { + wolfIP_sock_close(s, sockfd); + return; + } + + if (events & CB_EVENT_READABLE) { + if (sockfd == listen_fd) { + wolfIP_sock_accept(s, listen_fd, NULL, NULL); + } else { + ret = wolfIP_sock_read(s, sockfd, buf, sizeof(buf)); + if (ret > 0) + wolfIP_sock_write(s, sockfd, buf, ret); + else if (ret == 0) + wolfIP_sock_close(s, sockfd); + } + } +} + +uint32_t wolfIP_getrandom(void) +{ + uint32_t val = 0; + whal_Rng_Generate(&g_whalRng, &val, sizeof(val)); + return val; +} + +uint64_t wolfip_get_time_ms(void) +{ + return (uint64_t)board_get_tick(); +} + +int main(void) +{ + struct wolfIP_ll_dev *ll; + struct wolfIP_sockaddr_in addr; + struct wolfIP *ipstack; + struct wolfhal_eth_ctx eth_ctx; + uint8_t up, speed, duplex; + int ret; + + ret = board_init(); + if (ret != WHAL_SUCCESS) { + printf("board_init failed\r\n"); + return 1; + } + + eth_ctx.eth = &g_whalEth; + eth_ctx.phy = &g_whalEthPhy; + + printf("\r\n=== wolfIP + wolfHAL ===\r\n"); + + printf("Initializing wolfIP stack...\r\n"); + wolfIP_init_static(&ipstack); + + printf("Initializing Ethernet (waiting for link)...\r\n"); + ll = wolfIP_getdev(ipstack); + ret = wolfhal_eth_init(ll, ð_ctx); + if (ret == -4) { + printf("PHY link timeout\r\n"); + return 1; + } else if (ret < 0) { + printf("wolfhal_eth_init failed (%d)\r\n", ret); + return 1; + } + + ret = whal_EthPhy_GetLinkState(eth_ctx.phy, &up, &speed, &duplex); + if (ret == WHAL_SUCCESS) + printf("Link up: %d Mbps %s duplex\r\n", speed, + duplex ? "full" : "half"); + else + printf("Link up (could not read speed/duplex)\r\n"); + + printf("Setting IP: %s\r\n", WOLFIP_IP); + wolfIP_ipconfig_set(ipstack, + atoip4(WOLFIP_IP), + atoip4(WOLFIP_NETMASK), + atoip4(WOLFIP_GW)); + + printf("Starting TCP echo server on port %d...\r\n", ECHO_PORT); + listen_fd = wolfIP_sock_socket(ipstack, AF_INET, IPSTACK_SOCK_STREAM, 0); + wolfIP_register_callback(ipstack, listen_fd, echo_cb, ipstack); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = ee16(ECHO_PORT); + addr.sin_addr.s_addr = 0; + wolfIP_sock_bind(ipstack, listen_fd, + (struct wolfIP_sockaddr *)&addr, sizeof(addr)); + wolfIP_sock_listen(ipstack, listen_fd, 1); + + printf("Ready.\r\n"); + + for (;;) { + wolfIP_poll(ipstack, board_get_tick()); + } + + return 0; +} diff --git a/src/port/wolfHAL/wolfhal_eth.c b/src/port/wolfHAL/wolfhal_eth.c new file mode 100644 index 00000000..463b8522 --- /dev/null +++ b/src/port/wolfHAL/wolfhal_eth.c @@ -0,0 +1,96 @@ +/* wolfhal_eth.c + * + * Copyright (C) 2024-2026 wolfSSL Inc. + * + * Generic wolfHAL Ethernet port for wolfIP + * + * This file is part of wolfIP TCP/IP stack. + * + * wolfIP is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfIP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include "wolfhal_eth.h" +#include "board.h" +#include + +#ifndef WOLFHAL_ETH_LINK_TIMEOUT_MS +#define WOLFHAL_ETH_LINK_TIMEOUT_MS 5000 +#endif + +static int wolfhal_eth_poll(struct wolfIP_ll_dev *dev, void *buf, uint32_t len) +{ + struct wolfhal_eth_ctx *ctx = (struct wolfhal_eth_ctx *)dev->priv; + size_t recv_len = (size_t)len; + whal_Error err; + + err = whal_Eth_Recv(ctx->eth, buf, &recv_len); + if (err == WHAL_ENOTREADY) + return 0; + if (err != WHAL_SUCCESS) + return -1; + + return (int)recv_len; +} + +static int wolfhal_eth_send(struct wolfIP_ll_dev *dev, void *buf, uint32_t len) +{ + struct wolfhal_eth_ctx *ctx = (struct wolfhal_eth_ctx *)dev->priv; + whal_Error err; + + err = whal_Eth_Send(ctx->eth, buf, (size_t)len); + if (err != WHAL_SUCCESS) + return -1; + + return (int)len; +} + +int wolfhal_eth_init(struct wolfIP_ll_dev *ll, struct wolfhal_eth_ctx *ctx) +{ + uint8_t link_up, speed, duplex; + whal_Error err; + uint32_t start; + + if (ll == NULL || ctx == NULL || ctx->eth == NULL || ctx->phy == NULL) + return -1; + + /* Wait for PHY link to come up */ + link_up = 0; + start = board_get_tick(); + do { + err = whal_EthPhy_GetLinkState(ctx->phy, &link_up, &speed, &duplex); + if (err != WHAL_SUCCESS) + return -2; + if (link_up) + break; + } while ((board_get_tick() - start) < WOLFHAL_ETH_LINK_TIMEOUT_MS); + + if (!link_up) + return -4; + + /* Start the MAC with negotiated link parameters */ + err = whal_Eth_Start(ctx->eth, speed, duplex); + if (err != WHAL_SUCCESS) + return -3; + + /* Configure wolfIP device */ + memcpy(ll->mac, ctx->eth->macAddr, 6); + strncpy(ll->ifname, "eth0", sizeof(ll->ifname) - 1); + ll->ifname[sizeof(ll->ifname) - 1] = '\0'; + ll->poll = wolfhal_eth_poll; + ll->send = wolfhal_eth_send; + ll->priv = ctx; + + return 0; +} diff --git a/src/port/wolfHAL/wolfhal_eth.h b/src/port/wolfHAL/wolfhal_eth.h new file mode 100644 index 00000000..9c9be923 --- /dev/null +++ b/src/port/wolfHAL/wolfhal_eth.h @@ -0,0 +1,107 @@ +/* wolfhal_eth.h + * + * Copyright (C) 2024-2026 wolfSSL Inc. + * + * Generic wolfHAL Ethernet port for wolfIP + * + * This file is part of wolfIP TCP/IP stack. + * + * wolfIP is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfIP is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/** + * @file wolfhal_eth.h + * @brief Generic wolfHAL Ethernet port for wolfIP + * + * This port bridges wolfIP's link-layer device interface to wolfHAL's + * Ethernet MAC and PHY APIs. It works with any board that provides a + * configured whal_Eth and whal_EthPhy — no platform-specific code needed. + * + * ## Quick Start + * + * @code + * #include "wolfip.h" + * #include "wolfhal_eth.h" + * #include "board.h" + * + * int main(void) + * { + * struct wolfIP *ipstack; + * + * board_init(); + * + * struct wolfhal_eth_ctx eth_ctx = { + * .eth = &g_whalEth, + * .phy = &g_whalEthPhy, + * }; + * + * wolfIP_init_static(&ipstack); + * wolfhal_eth_init(wolfIP_getdev(ipstack), ð_ctx); + * wolfIP_ipconfig_set(ipstack, + * atoip4("192.168.1.100"), + * atoip4("255.255.255.0"), + * atoip4("192.168.1.1")); + * + * while (1) { + * wolfIP_poll(ipstack, board_get_tick()); + * } + * } + * @endcode + */ + +#ifndef WOLFIP_WOLFHAL_ETH_H +#define WOLFIP_WOLFHAL_ETH_H + +#include +#include "wolfip.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct wolfhal_eth_ctx { + whal_Eth *eth; + whal_EthPhy *phy; +}; + +/** + * @brief Initialize the wolfHAL Ethernet port for wolfIP + * + * Queries the PHY for link state, starts the MAC with the negotiated + * speed and duplex, and registers poll/send callbacks on the wolfIP + * device. + * + * Prerequisites: + * - board_init() (or equivalent) has already called whal_Eth_Init() + * and whal_EthPhy_Init() to set up the hardware. + * + * @param ll Pointer to wolfIP low-level device (from wolfIP_getdev()) + * @param ctx Caller-owned context with eth and phy already set + * + * @return 0 on success + * @return -1 if any argument is NULL + * @return -2 if PHY link state query fails + * @return -3 if MAC start fails + * @return -4 if PHY link did not come up within timeout + */ +int wolfhal_eth_init(struct wolfIP_ll_dev *ll, struct wolfhal_eth_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* WOLFIP_WOLFHAL_ETH_H */ From 2e9c1f4df30018deaeeb73a994fa9763a30519a9 Mon Sep 17 00:00:00 2001 From: Alex Lanzano Date: Thu, 9 Jul 2026 15:37:41 -0400 Subject: [PATCH 2/2] Move wolfHAL integration into existing stm32h5 port --- .../workflows/wolfhal-stm32h563zi-nucleo.yml | 9 +- Makefile | 4 +- src/port/stm32h563/Makefile | 68 ++++++- .../boards/stm32h563zi_nucleo/board.c | 14 +- .../boards/stm32h563zi_nucleo/board.h | 40 ++-- .../boards/stm32h563zi_nucleo/board.mk | 31 ++++ .../boards/stm32h563zi_nucleo/ivt.c | 0 .../boards/stm32h563zi_nucleo/linker.ld | 0 .../boards/stm32h563zi_nucleo/startup.c | 0 .../boards/stm32h563zi_nucleo/syscalls.c | 2 +- src/port/stm32h563/main.c | 101 ++++++++++ src/port/wolfHAL/.gitignore | 1 - src/port/wolfHAL/Makefile | 49 ----- src/port/wolfHAL/README.md | 172 ++++-------------- .../boards/stm32h563zi_nucleo/board.mk | 43 ----- src/port/wolfHAL/main.c | 148 --------------- 16 files changed, 270 insertions(+), 412 deletions(-) rename src/port/{wolfHAL => stm32h563}/boards/stm32h563zi_nucleo/board.c (94%) rename src/port/{wolfHAL => stm32h563}/boards/stm32h563zi_nucleo/board.h (83%) create mode 100644 src/port/stm32h563/boards/stm32h563zi_nucleo/board.mk rename src/port/{wolfHAL => stm32h563}/boards/stm32h563zi_nucleo/ivt.c (100%) rename src/port/{wolfHAL => stm32h563}/boards/stm32h563zi_nucleo/linker.ld (100%) rename src/port/{wolfHAL => stm32h563}/boards/stm32h563zi_nucleo/startup.c (100%) rename src/port/{wolfHAL => stm32h563}/boards/stm32h563zi_nucleo/syscalls.c (96%) delete mode 100644 src/port/wolfHAL/.gitignore delete mode 100644 src/port/wolfHAL/Makefile delete mode 100644 src/port/wolfHAL/boards/stm32h563zi_nucleo/board.mk delete mode 100644 src/port/wolfHAL/main.c diff --git a/.github/workflows/wolfhal-stm32h563zi-nucleo.yml b/.github/workflows/wolfhal-stm32h563zi-nucleo.yml index bef4af18..5abf421e 100644 --- a/.github/workflows/wolfhal-stm32h563zi-nucleo.yml +++ b/.github/workflows/wolfhal-stm32h563zi-nucleo.yml @@ -25,13 +25,14 @@ jobs: set -euo pipefail git clone --depth 1 https://github.com/wolfSSL/wolfHAL.git ../wolfHAL - - name: Build wolfHAL port + - name: Build STM32H563 port with the wolfHAL driver backend run: | set -euo pipefail - make -C src/port/wolfHAL BOARD=stm32h563zi_nucleo + make -C src/port/stm32h563 ENABLE_WOLFHAL=1 BOARD=stm32h563zi_nucleo \ + CC=arm-none-eabi-gcc OBJCOPY=arm-none-eabi-objcopy - name: Verify binary run: | set -euo pipefail - test -f src/port/wolfHAL/build/stm32h563zi_nucleo/app.bin - arm-none-eabi-size src/port/wolfHAL/build/stm32h563zi_nucleo/app.elf + test -f src/port/stm32h563/app.bin + arm-none-eabi-size src/port/stm32h563/app.elf diff --git a/Makefile b/Makefile index eae093a5..7a2fcf0d 100644 --- a/Makefile +++ b/Makefile @@ -150,8 +150,8 @@ CPPCHECK_FLAGS=--enable=warning,performance,portability,missingInclude \ --suppress=comparePointers:src/port/rp2350_cyw43439/syscalls.c \ --suppress=unknownMacro:src/port/stm32h563/dot1x_client.c \ --suppress=preprocessorErrorDirective:src/supplicant/supplicant_features.h \ - --suppress=comparePointers:src/port/wolfHAL/boards/stm32h563zi_nucleo/startup.c \ - --suppress=comparePointers:src/port/wolfHAL/boards/stm32h563zi_nucleo/syscalls.c \ + --suppress=comparePointers:src/port/stm32h563/boards/stm32h563zi_nucleo/startup.c \ + --suppress=comparePointers:src/port/stm32h563/boards/stm32h563zi_nucleo/syscalls.c \ --disable=style \ --std=c99 --language=c \ --platform=unix64 \ diff --git a/src/port/stm32h563/Makefile b/src/port/stm32h563/Makefile index 41003368..4d26bfb9 100644 --- a/src/port/stm32h563/Makefile +++ b/src/port/stm32h563/Makefile @@ -7,6 +7,14 @@ ROOT := ../../.. # Default is TZEN=0 (TrustZone disabled) TZEN ?= 0 +# wolfHAL driver backend: set ENABLE_WOLFHAL=1 to build the port on top of +# the wolfHAL HAL (Ethernet MAC/PHY, RNG, UART, GPIO, clocks) instead of the +# in-tree bare-metal drivers. Selects the self-contained board directory +# boards/$(BOARD). First cut supports TZEN=0 and FREERTOS=0 only. +ENABLE_WOLFHAL ?= 0 +BOARD ?= stm32h563zi_nucleo +WOLFHAL_ROOT ?= $(ROOT)/../wolfHAL + # TLS support: set ENABLE_TLS=1 to include wolfSSL TLS server # Requires wolfSSL cloned alongside wolfip (or set WOLFSSL_ROOT) ENABLE_TLS ?= 0 @@ -122,6 +130,44 @@ CFLAGS_WOLFSSL := $(filter-out -Werror,$(CFLAGS_WOLFSSL)) CFLAGS_WOLFSSL += -Wno-unused-variable -Wno-unused-function CFLAGS_WOLFSSL += $(EXTRA_CFLAGS_WOLFSSL) +ifeq ($(ENABLE_WOLFHAL),1) +# ----------------------------------------------------------------------------- +# wolfHAL driver backend +# ----------------------------------------------------------------------------- +# board_init() programs the PLL directly and the wolfHAL SysTick driver owns +# the SysTick handler, so the wolfBoot-launched (TZEN=1) clock flow and the +# FreeRTOS SysTick are not supported in this first cut. +ifeq ($(TZEN),1) + $(error ENABLE_WOLFHAL=1 does not support TZEN=1 yet (board_init owns the PLL, which conflicts with the wolfBoot-launched NS clock flow)) +endif +ifeq ($(FREERTOS),1) + $(error ENABLE_WOLFHAL=1 does not support FREERTOS=1 yet (wolfHAL SysTick conflicts with the FreeRTOS SysTick handler)) +endif + +ifeq ($(wildcard $(WOLFHAL_ROOT)/wolfHAL/wolfHAL.h),) + $(error wolfHAL not found at $(WOLFHAL_ROOT). Clone it alongside wolfip: git clone https://github.com/wolfSSL/wolfHAL.git (or set WOLFHAL_ROOT)) +endif + +BOARD_DIR := boards/$(BOARD) + +CFLAGS += -DENABLE_WOLFHAL -DTZEN_ENABLED=0 +CFLAGS += -I$(WOLFHAL_ROOT) -I$(BOARD_DIR) -I$(ROOT)/src/port/wolfHAL + +LDSCRIPT := $(BOARD_DIR)/linker.ld + +# The board dir carries its own wolfHAL-specific startup/ivt/syscalls; the +# bare-metal stm32_eth.c driver is replaced by board.c (BSP bringup) plus the +# generic wolfhal_eth.c bridge. +SRCS := $(BOARD_DIR)/startup.c $(BOARD_DIR)/ivt.c $(BOARD_DIR)/syscalls.c +SRCS += main.c $(BOARD_DIR)/board.c $(ROOT)/src/port/wolfHAL/wolfhal_eth.c +SRCS += $(ROOT)/src/wolfip.c + +# wolfHAL driver selection (WHAL_CFG_* defines) + wolfHAL driver TUs. +include $(BOARD_DIR)/board.mk +else +# ----------------------------------------------------------------------------- +# In-tree bare-metal drivers (default) +# ----------------------------------------------------------------------------- # Select linker script based on TZEN setting ifeq ($(TZEN),1) LDSCRIPT := target_tzen.ld @@ -131,11 +177,12 @@ else CFLAGS += -DTZEN_ENABLED=0 endif -LDFLAGS := -nostdlib -T $(LDSCRIPT) -Wl,-gc-sections - # Base source files SRCS := startup.c ivt.c syscalls.c SRCS += main.c $(ROOT)/src/port/stm32/stm32_eth.c $(ROOT)/src/wolfip.c +endif + +LDFLAGS := -nostdlib -T $(LDSCRIPT) -Wl,-gc-sections ifeq ($(FREERTOS),1) ifeq ($(wildcard $(FREERTOS_PATH)/include/FreeRTOS.h),) @@ -515,7 +562,7 @@ endif OBJS := $(patsubst %.c,%.o,$(SRCS)) all: app.bin - @echo "Built with TZEN=$(TZEN) ENABLE_TLS=$(ENABLE_TLS) ENABLE_TLS_CLIENT=$(ENABLE_TLS_CLIENT) ENABLE_HTTPS=$(ENABLE_HTTPS) ENABLE_SSH=$(ENABLE_SSH) ENABLE_MQTT=$(ENABLE_MQTT) ENABLE_MQTT_BROKER=$(ENABLE_MQTT_BROKER) FREERTOS=$(FREERTOS)" + @echo "Built with TZEN=$(TZEN) ENABLE_WOLFHAL=$(ENABLE_WOLFHAL) ENABLE_TLS=$(ENABLE_TLS) ENABLE_TLS_CLIENT=$(ENABLE_TLS_CLIENT) ENABLE_HTTPS=$(ENABLE_HTTPS) ENABLE_SSH=$(ENABLE_SSH) ENABLE_MQTT=$(ENABLE_MQTT) ENABLE_MQTT_BROKER=$(ENABLE_MQTT_BROKER) FREERTOS=$(FREERTOS)" ifeq ($(ENABLE_TLS),1) @echo " wolfSSL: $(WOLFSSL_ROOT)" endif @@ -576,6 +623,11 @@ factory: factory.bin $(WOLFSSL_ROOT)/%.o: $(WOLFSSL_ROOT)/%.c $(CC) $(CFLAGS_WOLFSSL) -DWOLFSSL_USER_SETTINGS $(if $(filter 1,$(ENABLE_SSH)),-DENABLE_SSH -DWOLFSSL_WOLFSSH) $(if $(filter 1,$(ENABLE_MQTT_BROKER)),-DENABLE_MQTT_BROKER) $(if $(filter 1,$(ENABLE_DOT1X)),-DHAVE_PBKDF2 -DHAVE_AES_KEYWRAP) -I$(WOLFSSL_ROOT) -c $< -o $@ +# wolfHAL driver objects: first-party HAL, but built with -Werror relaxed +# since the port's -Wextra is stricter than wolfHAL's own build. +$(WOLFHAL_ROOT)/%.o: $(WOLFHAL_ROOT)/%.c + $(CC) $(filter-out -Werror,$(CFLAGS)) -c $< -o $@ + clean: rm -f *.o app.elf app.bin rm -f app_v1_signed.bin factory.bin wolfboot_padded.bin @@ -584,6 +636,10 @@ clean: rm -f $(ROOT)/src/port/stm32/*.o rm -f $(ROOT)/src/port/freeRTOS/*.o rm -f $(ROOT)/src/supplicant/*.o +ifeq ($(ENABLE_WOLFHAL),1) + rm -f boards/$(BOARD)/*.o + rm -f $(WOLFHAL_ROOT)/src/*.o $(WOLFHAL_ROOT)/src/*/*.o +endif ifeq ($(FREERTOS),1) rm -f $(FREERTOS_PATH)/*.o rm -f $(FREERTOS_PATH)/portable/MemMang/*.o @@ -614,7 +670,7 @@ verify: app.bin @strings app.bin | grep -q "MQTT Broker: Initializing" && echo " ✓ MQTT broker enabled" || echo " ✗ MQTT broker disabled" @echo "" @echo "Binary size: $$(ls -lh app.bin | awk '{print $$5}')" - @echo "Build flags: TZEN=$(TZEN) ENABLE_TLS=$(ENABLE_TLS) ENABLE_HTTPS=$(ENABLE_HTTPS) ENABLE_SSH=$(ENABLE_SSH) ENABLE_MQTT=$(ENABLE_MQTT) ENABLE_MQTT_BROKER=$(ENABLE_MQTT_BROKER) FREERTOS=$(FREERTOS)" + @echo "Build flags: TZEN=$(TZEN) ENABLE_WOLFHAL=$(ENABLE_WOLFHAL) ENABLE_TLS=$(ENABLE_TLS) ENABLE_HTTPS=$(ENABLE_HTTPS) ENABLE_SSH=$(ENABLE_SSH) ENABLE_MQTT=$(ENABLE_MQTT) ENABLE_MQTT_BROKER=$(ENABLE_MQTT_BROKER) FREERTOS=$(FREERTOS)" # Show memory usage size: app.elf @@ -643,6 +699,8 @@ help: @echo "" @echo "Options:" @echo " TZEN=1 Enable TrustZone support" + @echo " ENABLE_WOLFHAL=1 Use the wolfHAL driver backend (requires wolfHAL; TZEN=0, FREERTOS=0)" + @echo " BOARD= Board under boards/ (default: stm32h563zi_nucleo)" @echo " ENABLE_TLS=1 Enable TLS server (requires wolfSSL)" @echo " ENABLE_TLS_CLIENT=1 Enable TLS client test (Google)" @echo " ENABLE_HTTPS=1 Enable HTTPS web server (requires TLS)" @@ -655,11 +713,13 @@ help: @echo " WOLFSSL_ROOT= Path to wolfSSL (default: ../wolfssl)" @echo " WOLFSSH_ROOT= Path to wolfSSH (default: ../wolfssh)" @echo " WOLFMQTT_ROOT= Path to wolfMQTT (default: ../wolfmqtt)" + @echo " WOLFHAL_ROOT= Path to wolfHAL (default: ../wolfHAL)" @echo " CC= C compiler (default: arm-none-eabi-gcc)" @echo " OBJCOPY= Objcopy tool (default: arm-none-eabi-objcopy)" @echo "" @echo "Examples:" @echo " make # Basic TCP echo (port 7)" + @echo " make ENABLE_WOLFHAL=1 # Basic TCP echo via the wolfHAL driver backend" @echo " make ENABLE_TLS=1 # TLS echo server (port 8443)" @echo " make ENABLE_TLS=1 ENABLE_HTTPS=1 # TLS + HTTPS web (port 443)" @echo " make ENABLE_TLS=1 ENABLE_SSH=1 # TLS + SSH shell (port 22)" diff --git a/src/port/wolfHAL/boards/stm32h563zi_nucleo/board.c b/src/port/stm32h563/boards/stm32h563zi_nucleo/board.c similarity index 94% rename from src/port/wolfHAL/boards/stm32h563zi_nucleo/board.c rename to src/port/stm32h563/boards/stm32h563zi_nucleo/board.c index 2e52e81b..cf9712ee 100644 --- a/src/port/wolfHAL/boards/stm32h563zi_nucleo/board.c +++ b/src/port/stm32h563/boards/stm32h563zi_nucleo/board.c @@ -78,16 +78,6 @@ uint8_t ethTxBufs[BOARD_ETH_TX_DESC_COUNT * BOARD_ETH_TX_BUF_SIZE] uint8_t ethRxBufs[BOARD_ETH_RX_DESC_COUNT * BOARD_ETH_RX_BUF_SIZE] __attribute__((aligned(4))); -/* UART: USART3 on the ST-Link VCP (caller-allocated, multi-instance driver) */ -whal_Uart g_whalUart = { - .base = WHAL_STM32H563_USART3_BASE, - /* .driver: direct API mapping */ - .cfg = &(whal_Stm32h5_Uart_Cfg) { - .brr = WHAL_STM32H5_UART_BRR(168000000, 115200), - .timeout = &g_whalTimeout, - }, -}; - /* * FLASH_ACR (0x40022000): LATENCY[3:0] = 5 wait states for 168 MHz, * WRHIGHFREQ[5:4] = 2. Must be set before raising the clock. @@ -159,7 +149,7 @@ whal_Error board_init(void) if (err) return err; - err = whal_Uart_Init(&g_whalUart); + err = whal_Uart_Init(WHAL_INTERNAL_DEV); if (err) return err; @@ -211,7 +201,7 @@ whal_Error board_deinit(void) if (err) return err; - err = whal_Uart_Deinit(&g_whalUart); + err = whal_Uart_Deinit(WHAL_INTERNAL_DEV); if (err) return err; diff --git a/src/port/wolfHAL/boards/stm32h563zi_nucleo/board.h b/src/port/stm32h563/boards/stm32h563zi_nucleo/board.h similarity index 83% rename from src/port/wolfHAL/boards/stm32h563zi_nucleo/board.h rename to src/port/stm32h563/boards/stm32h563zi_nucleo/board.h index b0ed12d0..6e8c4f96 100644 --- a/src/port/wolfHAL/boards/stm32h563zi_nucleo/board.h +++ b/src/port/stm32h563/boards/stm32h563zi_nucleo/board.h @@ -30,21 +30,19 @@ #include #include -/* Caller-allocated devices (multi-instance drivers). */ -extern whal_Uart g_whalUart; - extern whal_Timeout g_whalTimeout; extern volatile uint32_t g_tick; -/* The generic wolfIP port (main.c, wolfhal_eth.c) references the board's - * Ethernet, PHY, and RNG devices through these names. Under the current - * wolfHAL API these are single-instance drivers whose device structs live - * in the driver translation units (built from the WHAL_CFG_*_DEV +/* The generic wolfIP port (main.c, wolfhal_eth.c, syscalls.c) references the + * board's Ethernet, PHY, RNG, and UART devices through these names. Under the + * current wolfHAL API these are single-instance drivers whose device structs + * live in the driver translation units (built from the WHAL_CFG_*_DEV * initializers below), so we alias the documented g_whal* names onto those - * driver singletons. */ + * driver-owned device structs. */ #define g_whalEth (*(whal_Eth *)&whal_Stm32h5_Eth_Dev) #define g_whalEthPhy (*(whal_EthPhy *)&whal_Lan8742a_Dev) #define g_whalRng (*(whal_Rng *)&whal_Stm32h5_Rng_Dev) +#define g_whalUart (*(whal_Uart *)&whal_Stm32h5_Uart_Dev) /* Ethernet PHY: LAN8742A on MDIO address 0 */ #define BOARD_ETH_PHY_ADDR 0 @@ -64,7 +62,7 @@ enum { PIN_COUNT, }; -/* GPIO dev initializer — singleton defined in the gpio driver TU. +/* GPIO dev initializer — device struct defined in the gpio driver code. * Only the USART3 (ST-Link VCP) and Ethernet RMII pins are configured. */ #define WHAL_CFG_STM32H5_GPIO_DEV { \ .base = WHAL_STM32H563_GPIO_BASE, \ @@ -121,7 +119,7 @@ enum { }, \ } -/* RNG dev initializer — singleton defined in the rng driver TU. */ +/* RNG dev initializer — device struct defined in the rng driver code. */ #define WHAL_CFG_STM32H5_RNG_DEV { \ .base = WHAL_STM32H563_RNG_BASE, \ .cfg = (void *)&(const whal_Stm32h5_Rng_Cfg){ \ @@ -129,9 +127,21 @@ enum { }, \ } +/* UART dev initializer — device struct defined in the UART driver code. Named + * WHAL_CFG_STM32WB_UART_DEV (not _STM32H5_) because the STM32H5 USART reuses + * the shared STM32WB UART driver, which instantiates the device from that + * exact name. USART3 on the ST-Link VCP; BRR for PCLK 168 MHz @ 115200. */ +#define WHAL_CFG_STM32WB_UART_DEV { \ + .base = WHAL_STM32H563_USART3_BASE, \ + .cfg = (void *)&(const whal_Stm32h5_Uart_Cfg){ \ + .brr = WHAL_STM32H5_UART_BRR(168000000, 115200), \ + .timeout = &g_whalTimeout, \ + }, \ +} + /* ETH descriptor rings + buffer pool — defined in board.c, captured by the - * ETH singleton's cfg below (expanded in the eth driver TU). */ -#define BOARD_ETH_TX_DESC_COUNT 4 + * ETH device's cfg below (expanded in the eth driver code). */ +#define BOARD_ETH_TX_DESC_COUNT 3 #define BOARD_ETH_RX_DESC_COUNT 4 #define BOARD_ETH_TX_BUF_SIZE 1536 #define BOARD_ETH_RX_BUF_SIZE 1536 @@ -145,7 +155,7 @@ extern uint8_t ethRxBufs[BOARD_ETH_RX_DESC_COUNT * BOARD_ETH_RX_BUF_SIZE]; #define BOARD_MAC_ADDR {0x00, 0x80, 0xE1, 0x00, 0x00, 0x01} #endif -/* ETH dev initializer — singleton defined in the eth driver TU. */ +/* ETH dev initializer — device struct defined in the eth driver code. */ #define WHAL_CFG_STM32H5_ETH_DEV { \ .base = WHAL_STM32H563_ETH_BASE, \ .macAddr = BOARD_MAC_ADDR, \ @@ -163,7 +173,7 @@ extern uint8_t ethRxBufs[BOARD_ETH_RX_DESC_COUNT * BOARD_ETH_RX_BUF_SIZE]; }, \ } -/* LAN8742A PHY dev initializer — singleton defined in the phy driver TU. */ +/* LAN8742A PHY dev initializer — device struct defined in the phy driver code. */ #define WHAL_CFG_LAN8742A_DEV { \ .eth = NULL, \ .addr = BOARD_ETH_PHY_ADDR, \ @@ -172,7 +182,7 @@ extern uint8_t ethRxBufs[BOARD_ETH_RX_DESC_COUNT * BOARD_ETH_RX_BUF_SIZE]; }, \ } -/* SysTick dev initializer — singleton defined in the systick driver TU. */ +/* SysTick dev initializer — device struct defined in the systick driver code. */ #define WHAL_CFG_SYSTICK_DEV { \ .base = WHAL_CORTEX_M33_SYSTICK_BASE, \ .cfg = (void *)&(const whal_SysTick_Cfg){ \ diff --git a/src/port/stm32h563/boards/stm32h563zi_nucleo/board.mk b/src/port/stm32h563/boards/stm32h563zi_nucleo/board.mk new file mode 100644 index 00000000..a0c65d2b --- /dev/null +++ b/src/port/stm32h563/boards/stm32h563zi_nucleo/board.mk @@ -0,0 +1,31 @@ +# wolfHAL-specific build settings for the STM32H563ZI Nucleo board. +# +# Included by the port Makefile only when ENABLE_WOLFHAL=1. The port +# Makefile owns the toolchain, base CFLAGS, include paths, and linker +# script; this fragment contributes only the wolfHAL driver selection +# and the wolfHAL driver translation units. WOLFHAL_ROOT is set by the +# port Makefile. + +# Direct-API-mapping driver selection: one concrete driver TU per domain, +# no generic dispatch layer (which would redefine the top-level symbols). +CFLAGS += -DPLATFORM_STM32H5 +CFLAGS += -DWHAL_CFG_STM32H5_GPIO_DIRECT_API_MAPPING +CFLAGS += -DWHAL_CFG_STM32H5_RCC_PLL_DRIVER +CFLAGS += -DWHAL_CFG_STM32H5_RCC_DIRECT_API_MAPPING +CFLAGS += -DWHAL_CFG_STM32H5_UART_DIRECT_API_MAPPING +CFLAGS += -DWHAL_CFG_STM32H5_UART_SINGLE_INSTANCE +CFLAGS += -DWHAL_CFG_STM32H5_RNG_DIRECT_API_MAPPING +CFLAGS += -DWHAL_CFG_STM32H5_ETH_DIRECT_API_MAPPING +CFLAGS += -DWHAL_CFG_LAN8742A_ETH_PHY_DIRECT_API_MAPPING +CFLAGS += -DWHAL_CFG_STM32H5_FLASH_DIRECT_API_MAPPING +CFLAGS += -DWHAL_CFG_SYSTICK_TIMER_DIRECT_API_MAPPING + +# wolfHAL driver translation units. Built with relaxed warnings via the +# port Makefile's $(WOLFHAL_ROOT)/%.o rule. +SRCS += $(WOLFHAL_ROOT)/src/reg.c +SRCS += $(WOLFHAL_ROOT)/src/eth/stm32h5_eth.c +SRCS += $(WOLFHAL_ROOT)/src/eth_phy/lan8742a_eth_phy.c +SRCS += $(WOLFHAL_ROOT)/src/gpio/stm32h5_gpio.c +SRCS += $(WOLFHAL_ROOT)/src/uart/stm32h5_uart.c +SRCS += $(WOLFHAL_ROOT)/src/rng/stm32h5_rng.c +SRCS += $(WOLFHAL_ROOT)/src/timer/systick.c diff --git a/src/port/wolfHAL/boards/stm32h563zi_nucleo/ivt.c b/src/port/stm32h563/boards/stm32h563zi_nucleo/ivt.c similarity index 100% rename from src/port/wolfHAL/boards/stm32h563zi_nucleo/ivt.c rename to src/port/stm32h563/boards/stm32h563zi_nucleo/ivt.c diff --git a/src/port/wolfHAL/boards/stm32h563zi_nucleo/linker.ld b/src/port/stm32h563/boards/stm32h563zi_nucleo/linker.ld similarity index 100% rename from src/port/wolfHAL/boards/stm32h563zi_nucleo/linker.ld rename to src/port/stm32h563/boards/stm32h563zi_nucleo/linker.ld diff --git a/src/port/wolfHAL/boards/stm32h563zi_nucleo/startup.c b/src/port/stm32h563/boards/stm32h563zi_nucleo/startup.c similarity index 100% rename from src/port/wolfHAL/boards/stm32h563zi_nucleo/startup.c rename to src/port/stm32h563/boards/stm32h563zi_nucleo/startup.c diff --git a/src/port/wolfHAL/boards/stm32h563zi_nucleo/syscalls.c b/src/port/stm32h563/boards/stm32h563zi_nucleo/syscalls.c similarity index 96% rename from src/port/wolfHAL/boards/stm32h563zi_nucleo/syscalls.c rename to src/port/stm32h563/boards/stm32h563zi_nucleo/syscalls.c index 6fd78f7c..302e5503 100644 --- a/src/port/wolfHAL/boards/stm32h563zi_nucleo/syscalls.c +++ b/src/port/stm32h563/boards/stm32h563zi_nucleo/syscalls.c @@ -25,9 +25,9 @@ #include #include #include +#include "board.h" /* g_whalUart singleton alias (single-instance UART) */ extern uint32_t _ebss; extern uint32_t _heap_limit; -extern whal_Uart g_whalUart; static char *heap_end; diff --git a/src/port/stm32h563/main.c b/src/port/stm32h563/main.c index 421be6c4..535f8d20 100644 --- a/src/port/stm32h563/main.c +++ b/src/port/stm32h563/main.c @@ -24,7 +24,14 @@ #include #include "config.h" #include "wolfip.h" +#ifdef ENABLE_WOLFHAL +#include "board.h" +#include "wolfhal_eth.h" +#include +#include +#else #include "stm32_eth.h" +#endif #ifdef WOLFIP_USE_FREERTOS #include "FreeRTOS.h" @@ -306,6 +313,7 @@ static int client_fd = -1; static uint8_t rx_buf[RX_BUF_SIZE]; #endif +#ifndef ENABLE_WOLFHAL static void rng_init(void) { uint32_t rng_cr; @@ -364,9 +372,15 @@ static int rng_get_word(uint32_t *out) *out = RNG_DR; return 0; } +#endif /* !ENABLE_WOLFHAL */ int custom_rand_gen_block(unsigned char *output, unsigned int sz) { +#ifdef ENABLE_WOLFHAL + if (whal_Rng_Generate(&g_whalRng, output, (size_t)sz) != WHAL_SUCCESS) + return -1; + return 0; +#else uint32_t word; while (sz >= 4u) { @@ -392,14 +406,22 @@ int custom_rand_gen_block(unsigned char *output, unsigned int sz) } return 0; +#endif /* ENABLE_WOLFHAL */ } uint32_t wolfIP_getrandom(void) { +#ifdef ENABLE_WOLFHAL + uint32_t word = 0u; + + (void)whal_Rng_Generate(&g_whalRng, &word, sizeof(word)); + return word; +#else uint32_t word = 0u; (void)rng_get_word(&word); return word; +#endif } /* Simple delay */ @@ -446,6 +468,7 @@ static void led_toggle(void) #define USART3_CR3 (*(volatile uint32_t *)(USART3_BASE + 0x08u)) #define USART3_PRESC (*(volatile uint32_t *)(USART3_BASE + 0x2Cu)) +#ifndef ENABLE_WOLFHAL /* Initialize USART3 for debug output (115200 baud @ 64MHz HSI) */ static void uart_init(void) { @@ -486,19 +509,41 @@ static void uart_init(void) USART3_CR1 |= (1u << 0); /* UE */ delay(100); } +#endif /* !ENABLE_WOLFHAL */ static void uart_putc(char c) { +#ifdef ENABLE_WOLFHAL + (void)whal_Uart_Send(&g_whalUart, &c, 1); +#else while ((USART3_ISR & (1u << 7)) == 0) { } /* Wait for TXE */ USART3_TDR = (uint32_t)c; +#endif } void uart_puts(const char *s) { +#ifdef ENABLE_WOLFHAL + /* Send whole runs between newlines in a single wolfHAL call, translating + * LF -> CRLF at run boundaries (matching the per-char path below). */ + while (*s) { + size_t len = 0; + while (s[len] && s[len] != '\n') + len++; + if (len) + (void)whal_Uart_Send(&g_whalUart, s, len); + if (s[len] == '\n') { + (void)whal_Uart_Send(&g_whalUart, "\r\n", 2); + len++; + } + s += len; + } +#else while (*s) { if (*s == '\n') uart_putc('\r'); uart_putc(*s++); } +#endif } void wolfssl_tls13_dbg_hex(const char *tag, const unsigned char *buf, @@ -627,6 +672,7 @@ static void uart_putip4(ip4 ip) uart_putdec(ip & 0xFF); } +#ifndef ENABLE_WOLFHAL /* Configure GPIO pin for Ethernet alternate function (AF11) */ static void gpio_eth_pin(uint32_t base, uint32_t pin) { @@ -702,6 +748,7 @@ static void eth_gpio_init(void) gpio_eth_pin(GPIOG_BASE, 11); /* TX_EN */ gpio_eth_pin(GPIOG_BASE, 13); /* TXD0 */ } +#endif /* !ENABLE_WOLFHAL */ #ifdef ENABLE_TLS_CLIENT /* Callback for TLS client responses */ @@ -808,6 +855,17 @@ int main(void) uint64_t tick = 0; int ret; +#ifdef ENABLE_WOLFHAL + /* wolfHAL BSP owns all clock + peripheral bringup: clocks, GPIO, UART, + * RNG, system timer, Ethernet MAC + PHY. */ + if (board_init() != WHAL_SUCCESS) { + while (1) { } + } + + /* PF4 debug LED stays a driver-independent register poke. */ + led_init(); + led_on(); /* LED ON = Reset_Handler ran, main() started */ +#else #if TZEN_ENABLED revert_sysclk_to_hsi(); #endif @@ -819,6 +877,7 @@ int main(void) /* Initialize UART for debug output */ uart_init(); rng_init(); +#endif /* Blink to show UART init done */ led_off(); @@ -849,6 +908,32 @@ int main(void) uart_puts("Initializing wolfIP stack...\n"); wolfIP_init_static(&IPStack); +#ifdef ENABLE_WOLFHAL + /* MAC + PHY are already brought up by board_init(). Wait for link, + * start the MAC at the negotiated speed/duplex, and bind the wolfIP + * device to the wolfHAL Ethernet bridge. */ + uart_puts("Initializing Ethernet (wolfHAL, waiting for link)...\n"); + ll = wolfIP_getdev(IPStack); + { + static struct wolfhal_eth_ctx eth_ctx; + eth_ctx.eth = &g_whalEth; + eth_ctx.phy = &g_whalEthPhy; + ret = wolfhal_eth_init(ll, ð_ctx); + } + if (ret < 0) { + uart_puts(" ERROR: wolfhal_eth_init failed ("); + uart_puthex((uint32_t)ret); + uart_puts(")\n"); + } else { + int mi; + uart_puts(" MAC: "); + for (mi = 0; mi < 6; mi++) { + if (mi > 0) uart_puts(":"); + uart_puthex8(ll->mac[mi]); + } + uart_puts("\n"); + } +#else /* Initialize GPIO pins for RMII - MUST happen before Ethernet clocks! */ uart_puts("Configuring GPIO for RMII...\n"); eth_gpio_init(); @@ -900,6 +985,7 @@ int main(void) } uart_puts("\n"); } +#endif /* ENABLE_WOLFHAL */ #ifdef ENABLE_DOT1X /* Wired IEEE 802.1X EAP-TLS: authenticate at layer 2 (EAPOL/0x888E) @@ -968,7 +1054,11 @@ int main(void) } else { uart_puts(" DHCP discover sent, waiting for lease...\n"); /* Wait for DHCP to complete - poll frequently */ +#ifdef ENABLE_WOLFHAL + dhcp_start_tick = board_get_tick(); +#else dhcp_start_tick = tick; +#endif #ifdef DEBUG_H5_ETH { uint32_t dbg_polls = 0, dbg_pkts = 0; @@ -1002,12 +1092,18 @@ int main(void) } #endif while (!dhcp_bound(IPStack) && dhcp_client_is_running(IPStack)) { +#ifdef ENABLE_WOLFHAL + /* Real millisecond tick from the SysTick BSP. */ + tick = board_get_tick(); + (void)wolfIP_poll(IPStack, tick); +#else /* Poll the stack - this processes received packets and sends pending data */ (void)wolfIP_poll(IPStack, tick); /* Increment tick counter (approximate 1ms per iteration at 64MHz HSI) * volatile loop ~8 cycles/iter: 8000 * 8 / 64MHz = 1ms */ tick++; delay(8000); +#endif #ifdef DEBUG_H5_ETH if ((tick - dhcp_start_tick) % 500 == 0) { uint32_t dbg_polls = 0, dbg_pkts = 0; @@ -1233,7 +1329,12 @@ int main(void) #endif for (;;) { +#ifdef ENABLE_WOLFHAL + tick = board_get_tick(); + (void)wolfIP_poll(IPStack, tick); +#else (void)wolfIP_poll(IPStack, tick++); +#endif #ifdef ENABLE_HTTPS /* Update HTTPS server status info for handler */ diff --git a/src/port/wolfHAL/.gitignore b/src/port/wolfHAL/.gitignore deleted file mode 100644 index 567609b1..00000000 --- a/src/port/wolfHAL/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build/ diff --git a/src/port/wolfHAL/Makefile b/src/port/wolfHAL/Makefile deleted file mode 100644 index 977f6a6c..00000000 --- a/src/port/wolfHAL/Makefile +++ /dev/null @@ -1,49 +0,0 @@ -ROOT = $(CURDIR)/../../.. -PORT_DIR = $(ROOT)/src/port/wolfHAL - -BOARD_DIR = $(PORT_DIR)/boards/$(BOARD) - -ifeq ($(BOARD),) - ifeq ($(MAKECMDGOALS),clean) - clean: - rm -rf build - .PHONY: clean - else - $(error BOARD is required. Usage: make BOARD=stm32h563zi_nucleo) - endif -else -include $(BOARD_DIR)/board.mk - -SOURCE = $(PORT_DIR)/main.c -SOURCE += $(PORT_DIR)/wolfhal_eth.c -SOURCE += $(ROOT)/src/wolfip.c -SOURCE += $(BOARD_SOURCE) - -BUILD_DIR = build/$(BOARD) -OBJECTS = $(patsubst %.c,$(BUILD_DIR)/%.o,$(SOURCE)) -DEPENDS = $(OBJECTS:.o=.d) - -all: $(BUILD_DIR)/app.bin - -$(BUILD_DIR)/%.o: %.c Makefile - @mkdir -p $(dir $@) - $(GCC) $(CFLAGS) -c -o $@ $< - -.SECONDARY: -$(BUILD_DIR)/%.elf: $(OBJECTS) $(LINKER_SCRIPT) - @mkdir -p $(dir $@) - $(GCC) $(CFLAGS) $(LDFLAGS) -T $(LINKER_SCRIPT) -o $@ $(OBJECTS) $(LDLIBS) - -$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf - $(OBJCOPY) $^ -O binary $@ - -.PHONY: clean size -clean: - rm -rf build - -size: $(BUILD_DIR)/app.elf - $(GCC_PATH)arm-none-eabi-size $< - --include $(DEPENDS) - -endif diff --git a/src/port/wolfHAL/README.md b/src/port/wolfHAL/README.md index 0900fba9..ec5aac29 100644 --- a/src/port/wolfHAL/README.md +++ b/src/port/wolfHAL/README.md @@ -1,142 +1,42 @@ -# wolfHAL Port for wolfIP +# wolfHAL Ethernet bridge for wolfIP -Generic wolfIP port that uses the wolfHAL Ethernet API (`whal_Eth` / -`whal_EthPhy`). Users create a wolfHAL board and the port handles the -rest — bridging wolfHAL's Ethernet MAC/PHY drivers to wolfIP's -link-layer device interface. - -## Supported Boards - -| Board | MCU | PHY | Directory | -|-------|-----|-----|-----------| -| NUCLEO-H563ZI | STM32H563ZI | LAN8742A | `boards/stm32h563zi_nucleo` | - -## Directory Structure +Generic, board-agnostic glue between wolfIP's link-layer device interface +and the wolfHAL Ethernet API (`whal_Eth` / `whal_EthPhy`). This directory +holds only the bridge: ``` src/port/wolfHAL/ -├── Makefile # Top-level build: make BOARD= -├── main.c # Generic main: board_init -> wolfhal_eth_init -> wolfIP_poll loop -├── wolfhal_eth.h # Port API and wolfhal_eth_ctx struct -├── wolfhal_eth.c # Bridges wolfIP_ll_dev poll/send to whal_Eth_Recv/whal_Eth_Send -└── boards/ - └── / - ├── board.mk # Toolchain, CFLAGS, wolfHAL driver sources - ├── board.h # Board API declarations and device externs - ├── board.c # Clock, GPIO, Ethernet, PHY, UART, timer setup - ├── startup.c # Reset_Handler: copies .data, zeros .bss, calls main() - ├── ivt.c # Interrupt vector table - ├── syscalls.c # libc stubs (_write, _sbrk, etc.) - └── linker.ld # Memory layout (FLASH/RAM regions) +├── wolfhal_eth.h # Port API and wolfhal_eth_ctx struct +└── wolfhal_eth.c # Bridges wolfIP_ll_dev poll/send to whal_Eth_Recv/whal_Eth_Send ``` -## Building +There is no platform code here — the bridge works with any board that +provides a configured `whal_Eth` and `whal_EthPhy`. Board bringup +(clocks, GPIO, MAC/PHY/RNG/UART init) and the bare-metal scaffolding +live in the chip port under `src/port//boards//`. -``` -cd src/port/wolfHAL -make BOARD=stm32h563zi_nucleo -``` - -Override the wolfHAL location (defaults to `../../../wolfHAL` relative to -the wolfip root, i.e. a sibling directory): - -``` -make BOARD=stm32h563zi_nucleo WOLFHAL_ROOT=/path/to/wolfHAL -``` +## Reference integration -Override IP configuration or MAC address at build time: +`src/port/stm32h563/` integrates this bridge as an opt-in driver backend +for the NUCLEO-H563ZI board: ``` -make BOARD=stm32h563zi_nucleo \ - CFLAGS+='-DWOLFIP_IP=\"10.0.0.2\" -DWOLFIP_NETMASK=\"255.255.255.0\" -DWOLFIP_GW=\"10.0.0.1\"' +make -C src/port/stm32h563 ENABLE_WOLFHAL=1 ``` -``` -make BOARD=stm32h563zi_nucleo \ - CFLAGS+='-DBOARD_MAC_ADDR={0x02,0xAA,0xBB,0xCC,0xDD,0xEE}' -``` - -## Adding a New Board - -Create a new directory under `boards/` with the following files: - -### board.h - -Must declare the following: - -#### Required Device Externs - -| Variable | Type | Description | -|----------|------|-------------| -| `g_whalEth` | `whal_Eth` | Initialized Ethernet MAC device | -| `g_whalEthPhy` | `whal_EthPhy` | Initialized Ethernet PHY device | -| `g_whalUart` | `whal_Uart` | Initialized UART device (used by `_write` syscall for printf) | -| `g_whalRng` | `whal_Rng` | Initialized RNG device (used by `wolfIP_getrandom`) | - -These names are required — `main.c`, `wolfhal_eth.c`, and `syscalls.c` -reference them directly. - -#### Required Functions - -| Function | Signature | Description | -|----------|-----------|-------------| -| `board_init` | `whal_Error board_init(void)` | Initialize all board hardware. Must call `whal_Eth_Init`, `whal_EthPhy_Init`, `whal_Uart_Init`, and start the system timer before returning. Returns `WHAL_SUCCESS` on success. | -| `board_deinit` | `whal_Error board_deinit(void)` | Tear down board hardware in reverse order. | -| `board_get_tick` | `uint32_t board_get_tick(void)` | Return a millisecond tick counter. Used by `wolfhal_eth_init` for link timeout and by `wolfIP_poll` for stack timing. | - -### board.c - -Implements the functions above. Typical `board_init` sequence: - -1. Initialize clocks (PLL, peripheral clocks) -2. Initialize GPIO (UART pins, Ethernet pins) -3. Initialize UART (`whal_Uart_Init`) -4. Initialize Ethernet MAC (`whal_Eth_Init`) -5. Initialize Ethernet PHY (`whal_EthPhy_Init`) -6. Initialize and start system timer - -The `whal_Eth` device must have its `macAddr` field set — this is -where wolfIP reads the interface MAC address from. - -### board.mk - -Provides build configuration. Must set: - -| Variable | Description | -|----------|-------------| -| `WOLFHAL_ROOT` | Path to wolfHAL (use `?=` so it's overridable) | -| `GCC` | Cross-compiler path (e.g. `arm-none-eabi-gcc`) | -| `OBJCOPY` | Objcopy tool | -| `CFLAGS` | Compiler flags (architecture, warnings, includes) | -| `LDFLAGS` | Linker flags | -| `LDLIBS` | Libraries to link (libc, libgcc, etc.) | -| `LINKER_SCRIPT` | Path to the board's linker script | -| `BOARD_SOURCE` | List of board + wolfHAL driver source files | - -### syscalls.c - -Must provide: -- Standard libc stubs: `_write`, `_read`, `_sbrk`, `_close`, `_fstat`, - `_isatty`, `_lseek`, `_exit`, `_kill`, `_getpid` -- `_write` should route to `whal_Uart_Send(&g_whalUart, ...)` so that - `printf` outputs to UART -- `uint32_t wolfIP_getrandom(void)` is provided by `main.c` using - `whal_Rng_Generate(&g_whalRng, ...)` - -### startup.c, ivt.c, linker.ld - -Standard bare-metal files for your target architecture. See the -`stm32h563zi_nucleo` board for a reference implementation. +`ENABLE_WOLFHAL=1` selects `boards/stm32h563zi_nucleo/` (its own +`startup.c`/`ivt.c`/`syscalls.c`/`linker.ld` plus `board.c`/`board.h`/`board.mk`), +pulls the wolfHAL STM32H5 driver TUs from a sibling wolfHAL checkout +(`WOLFHAL_ROOT ?= ../wolfHAL`), and compiles the port's `main.c` against +wolfHAL drivers instead of the hand-rolled bare-metal ones. ## Port API -The port exposes a single function: - ```c #include "wolfhal_eth.h" struct wolfhal_eth_ctx ctx = { - .eth = &g_whalEth, + .eth = &g_whalEth, /* configured by board_init() */ .phy = &g_whalEthPhy, }; @@ -145,16 +45,22 @@ int ret = wolfhal_eth_init(wolfIP_getdev(ipstack), &ctx); `wolfhal_eth_init` will: 1. Poll `whal_EthPhy_GetLinkState` until link comes up (5s timeout, - configurable via `WOLFHAL_ETH_LINK_TIMEOUT_MS`) -2. Start the MAC with negotiated speed/duplex -3. Copy `eth->macAddr` to the wolfIP device -4. Register poll/send callbacks that bridge to `whal_Eth_Recv`/`whal_Eth_Send` - -## Naming Conventions - -- All port functions and variables use `snake_case` -- Board functions use `board_` prefix: `board_init`, `board_get_tick` -- Port functions use `wolfhal_` prefix: `wolfhal_eth_init` -- wolfHAL API calls retain their own naming (`whal_Eth_Init`, etc.) -- Global device instances use `g_whal` prefix: `g_whalEth`, `g_whalEthPhy`, `g_whalUart`, `g_whalRng` -- Macros use `UPPER_SNAKE_CASE` + configurable via `WOLFHAL_ETH_LINK_TIMEOUT_MS`). +2. Start the MAC with the negotiated speed/duplex. +3. Copy `eth->macAddr` to the wolfIP device. +4. Register poll/send callbacks that bridge to `whal_Eth_Recv`/`whal_Eth_Send`. + +## What a board must provide + +The bridge needs the hardware already brought up. A board's `board.c` +(see `src/port/stm32h563/boards/stm32h563zi_nucleo/board.c`) must, before +`wolfhal_eth_init` is called: + +- Initialize clocks and GPIO, then call `whal_Eth_Init` / `whal_EthPhy_Init` + (typically from `board_init()`). +- Set the `whal_Eth` device's `macAddr` field — wolfIP reads the interface + MAC from there. +- Expose the devices the port references by name: `g_whalEth`, `g_whalEthPhy`, + and (for the port's `printf`/RNG hooks) `g_whalUart`, `g_whalRng`. +- Provide `uint32_t board_get_tick(void)` — a millisecond counter used both + for the `wolfhal_eth_init` link timeout and for `wolfIP_poll` timing. diff --git a/src/port/wolfHAL/boards/stm32h563zi_nucleo/board.mk b/src/port/wolfHAL/boards/stm32h563zi_nucleo/board.mk deleted file mode 100644 index 95a121e4..00000000 --- a/src/port/wolfHAL/boards/stm32h563zi_nucleo/board.mk +++ /dev/null @@ -1,43 +0,0 @@ -_WOLFIP_BOARD_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) - -WOLFHAL_ROOT ?= $(ROOT)/../wolfHAL - -GCC = $(GCC_PATH)arm-none-eabi-gcc -LD = $(GCC_PATH)arm-none-eabi-ld -OBJCOPY = $(GCC_PATH)arm-none-eabi-objcopy - -CFLAGS += -Wall -Werror -g3 -ffreestanding -nostdlib -mcpu=cortex-m33 -Os -CFLAGS += -DPLATFORM_STM32H5 -MMD -MP -CFLAGS += -DWHAL_CFG_STM32H5_GPIO_DIRECT_API_MAPPING -CFLAGS += -DWHAL_CFG_STM32H5_RCC_PLL_DRIVER -CFLAGS += -DWHAL_CFG_STM32H5_RCC_DIRECT_API_MAPPING -CFLAGS += -DWHAL_CFG_STM32H5_UART_DIRECT_API_MAPPING -CFLAGS += -DWHAL_CFG_STM32H5_RNG_DIRECT_API_MAPPING -CFLAGS += -DWHAL_CFG_STM32H5_ETH_DIRECT_API_MAPPING -CFLAGS += -DWHAL_CFG_LAN8742A_ETH_PHY_DIRECT_API_MAPPING -CFLAGS += -DWHAL_CFG_STM32H5_FLASH_DIRECT_API_MAPPING -CFLAGS += -DWHAL_CFG_SYSTICK_TIMER_DIRECT_API_MAPPING -CFLAGS += -I$(WOLFHAL_ROOT) -I$(_WOLFIP_BOARD_DIR) -CFLAGS += -I$(ROOT) -I$(ROOT)/src -I$(PORT_DIR) - -CFLAGS += -fdata-sections -ffunction-sections - -LDFLAGS = -nostdlib -Wl,-gc-sections -LDLIBS = -Wl,--start-group -lc -lm -lgcc -lnosys -Wl,--end-group -LINKER_SCRIPT ?= $(_WOLFIP_BOARD_DIR)/linker.ld - -BOARD_SOURCE = $(_WOLFIP_BOARD_DIR)/startup.c -BOARD_SOURCE += $(_WOLFIP_BOARD_DIR)/ivt.c -BOARD_SOURCE += $(_WOLFIP_BOARD_DIR)/board.c -BOARD_SOURCE += $(_WOLFIP_BOARD_DIR)/syscalls.c - -# wolfHAL drivers -# Domains with WHAL_CFG_*_API_MAPPING_* set include only the driver TU; -# the generic dispatch TU would redefine the top-level symbols. -BOARD_SOURCE += $(WOLFHAL_ROOT)/src/reg.c -BOARD_SOURCE += $(WOLFHAL_ROOT)/src/eth/stm32h5_eth.c -BOARD_SOURCE += $(WOLFHAL_ROOT)/src/eth_phy/lan8742a_eth_phy.c -BOARD_SOURCE += $(WOLFHAL_ROOT)/src/gpio/stm32h5_gpio.c -BOARD_SOURCE += $(WOLFHAL_ROOT)/src/uart/stm32h5_uart.c -BOARD_SOURCE += $(WOLFHAL_ROOT)/src/rng/stm32h5_rng.c -BOARD_SOURCE += $(WOLFHAL_ROOT)/src/timer/systick.c diff --git a/src/port/wolfHAL/main.c b/src/port/wolfHAL/main.c deleted file mode 100644 index a046b059..00000000 --- a/src/port/wolfHAL/main.c +++ /dev/null @@ -1,148 +0,0 @@ -/* main.c - * - * Copyright (C) 2024-2026 wolfSSL Inc. - * - * Generic wolfHAL main for wolfIP — works with any wolfHAL board that - * provides whal_Eth and whal_EthPhy. - * - * This file is part of wolfIP TCP/IP stack. - * - * wolfIP is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * wolfIP is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA - */ - -#include -#include -#include -#include "wolfip.h" -#include "wolfhal_eth.h" -#include "board.h" - -#ifndef WOLFIP_IP -#define WOLFIP_IP "192.168.1.100" -#endif -#ifndef WOLFIP_NETMASK -#define WOLFIP_NETMASK "255.255.255.0" -#endif -#ifndef WOLFIP_GW -#define WOLFIP_GW "192.168.1.1" -#endif - -#define ECHO_PORT 7 - -static int listen_fd = -1; - -static void echo_cb(int sockfd, uint16_t events, void *arg) -{ - struct wolfIP *s = (struct wolfIP *)arg; - uint8_t buf[512]; - int ret; - - if ((events & CB_EVENT_CLOSED) && sockfd != listen_fd) { - wolfIP_sock_close(s, sockfd); - return; - } - - if (events & CB_EVENT_READABLE) { - if (sockfd == listen_fd) { - wolfIP_sock_accept(s, listen_fd, NULL, NULL); - } else { - ret = wolfIP_sock_read(s, sockfd, buf, sizeof(buf)); - if (ret > 0) - wolfIP_sock_write(s, sockfd, buf, ret); - else if (ret == 0) - wolfIP_sock_close(s, sockfd); - } - } -} - -uint32_t wolfIP_getrandom(void) -{ - uint32_t val = 0; - whal_Rng_Generate(&g_whalRng, &val, sizeof(val)); - return val; -} - -uint64_t wolfip_get_time_ms(void) -{ - return (uint64_t)board_get_tick(); -} - -int main(void) -{ - struct wolfIP_ll_dev *ll; - struct wolfIP_sockaddr_in addr; - struct wolfIP *ipstack; - struct wolfhal_eth_ctx eth_ctx; - uint8_t up, speed, duplex; - int ret; - - ret = board_init(); - if (ret != WHAL_SUCCESS) { - printf("board_init failed\r\n"); - return 1; - } - - eth_ctx.eth = &g_whalEth; - eth_ctx.phy = &g_whalEthPhy; - - printf("\r\n=== wolfIP + wolfHAL ===\r\n"); - - printf("Initializing wolfIP stack...\r\n"); - wolfIP_init_static(&ipstack); - - printf("Initializing Ethernet (waiting for link)...\r\n"); - ll = wolfIP_getdev(ipstack); - ret = wolfhal_eth_init(ll, ð_ctx); - if (ret == -4) { - printf("PHY link timeout\r\n"); - return 1; - } else if (ret < 0) { - printf("wolfhal_eth_init failed (%d)\r\n", ret); - return 1; - } - - ret = whal_EthPhy_GetLinkState(eth_ctx.phy, &up, &speed, &duplex); - if (ret == WHAL_SUCCESS) - printf("Link up: %d Mbps %s duplex\r\n", speed, - duplex ? "full" : "half"); - else - printf("Link up (could not read speed/duplex)\r\n"); - - printf("Setting IP: %s\r\n", WOLFIP_IP); - wolfIP_ipconfig_set(ipstack, - atoip4(WOLFIP_IP), - atoip4(WOLFIP_NETMASK), - atoip4(WOLFIP_GW)); - - printf("Starting TCP echo server on port %d...\r\n", ECHO_PORT); - listen_fd = wolfIP_sock_socket(ipstack, AF_INET, IPSTACK_SOCK_STREAM, 0); - wolfIP_register_callback(ipstack, listen_fd, echo_cb, ipstack); - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = ee16(ECHO_PORT); - addr.sin_addr.s_addr = 0; - wolfIP_sock_bind(ipstack, listen_fd, - (struct wolfIP_sockaddr *)&addr, sizeof(addr)); - wolfIP_sock_listen(ipstack, listen_fd, 1); - - printf("Ready.\r\n"); - - for (;;) { - wolfIP_poll(ipstack, board_get_tick()); - } - - return 0; -}