Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/wolfhal-stm32h563zi-nucleo.yml
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ CPPCHECK_FLAGS=--enable=warning,performance,portability,missingInclude \
--suppress=comparePointers:src/port/stm32n6/syscalls.c \
--suppress=comparePointers:src/port/va416xx/startup.c \
--suppress=comparePointers:src/port/va416xx/syscalls.c \
--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 \
Expand Down
1 change: 1 addition & 0 deletions src/port/wolfHAL/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/
49 changes: 49 additions & 0 deletions src/port/wolfHAL/Makefile
Original file line number Diff line number Diff line change
@@ -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
169 changes: 169 additions & 0 deletions src/port/wolfHAL/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# 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=<board_name>
├── 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_name>/
├── 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 |

`BOARD_SOURCE` must include at minimum:
- `startup.c`, `ivt.c`, `board.c`, `syscalls.c` from the board directory
- wolfHAL drivers: `eth/eth.c`, `eth/<platform>_eth.c`,
`eth_phy/eth_phy.c`, `eth_phy/<phy>.c`, `clock/clock.c`,
`clock/<platform>_rcc.c`, `gpio/gpio.c`, `gpio/<platform>_gpio.c`,
`timer/timer.c`, `timer/systick.c`, `uart/uart.c`,
`uart/<platform>_uart.c`, `rng/rng.c`,
`rng/<platform>_rng.c`

### 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`
Loading
Loading