|
| 1 | +# wolfHAL Port for wolfIP |
| 2 | + |
| 3 | +Generic wolfIP port that uses the wolfHAL Ethernet API (`whal_Eth` / |
| 4 | +`whal_EthPhy`). Users create a wolfHAL board and the port handles the |
| 5 | +rest — bridging wolfHAL's Ethernet MAC/PHY drivers to wolfIP's |
| 6 | +link-layer device interface. |
| 7 | + |
| 8 | +## Supported Boards |
| 9 | + |
| 10 | +| Board | MCU | PHY | Directory | |
| 11 | +|-------|-----|-----|-----------| |
| 12 | +| NUCLEO-H563ZI | STM32H563ZI | LAN8742A | `boards/stm32h563zi_nucleo` | |
| 13 | + |
| 14 | +## Directory Structure |
| 15 | + |
| 16 | +``` |
| 17 | +src/port/wolfHAL/ |
| 18 | +├── Makefile # Top-level build: make BOARD=<board_name> |
| 19 | +├── main.c # Generic main: board_init -> wolfhal_eth_init -> wolfIP_poll loop |
| 20 | +├── wolfhal_eth.h # Port API and wolfhal_eth_ctx struct |
| 21 | +├── wolfhal_eth.c # Bridges wolfIP_ll_dev poll/send to whal_Eth Recv/Send |
| 22 | +└── boards/ |
| 23 | + └── <board_name>/ |
| 24 | + ├── board.mk # Toolchain, CFLAGS, wolfHAL driver sources |
| 25 | + ├── board.h # Board API declarations and device externs |
| 26 | + ├── board.c # Clock, GPIO, Ethernet, PHY, UART, timer setup |
| 27 | + ├── startup.c # Reset_Handler: copies .data, zeros .bss, calls main() |
| 28 | + ├── ivt.c # Interrupt vector table |
| 29 | + ├── syscalls.c # libc stubs (_write, _sbrk, etc.) and wolfIP_getrandom |
| 30 | + └── linker.ld # Memory layout (FLASH/RAM regions) |
| 31 | +``` |
| 32 | + |
| 33 | +## Building |
| 34 | + |
| 35 | +``` |
| 36 | +cd src/port/wolfHAL |
| 37 | +make BOARD=stm32h563zi_nucleo |
| 38 | +``` |
| 39 | + |
| 40 | +Override the wolfHAL location (defaults to `../../../wolfHAL` relative to |
| 41 | +the wolfip root, i.e. a sibling directory): |
| 42 | + |
| 43 | +``` |
| 44 | +make BOARD=stm32h563zi_nucleo WOLFHAL_ROOT=/path/to/wolfHAL |
| 45 | +``` |
| 46 | + |
| 47 | +Override IP configuration at build time: |
| 48 | + |
| 49 | +``` |
| 50 | +make BOARD=stm32h563zi_nucleo \ |
| 51 | + CFLAGS+='-DWOLFIP_IP=\"10.0.0.2\" -DWOLFIP_NETMASK=\"255.255.255.0\" -DWOLFIP_GW=\"10.0.0.1\"' |
| 52 | +``` |
| 53 | + |
| 54 | +## Adding a New Board |
| 55 | + |
| 56 | +Create a new directory under `boards/` with the following files: |
| 57 | + |
| 58 | +### board.h |
| 59 | + |
| 60 | +Must declare the following: |
| 61 | + |
| 62 | +#### Required Device Externs |
| 63 | + |
| 64 | +| Variable | Type | Description | |
| 65 | +|----------|------|-------------| |
| 66 | +| `g_whalEth` | `whal_Eth` | Initialized Ethernet MAC device | |
| 67 | +| `g_whalEthPhy` | `whal_EthPhy` | Initialized Ethernet PHY device | |
| 68 | +| `g_whalUart` | `whal_Uart` | Initialized UART device (used by `_write` syscall for printf) | |
| 69 | + |
| 70 | +These names are required — `main.c`, `wolfhal_eth.c`, and `syscalls.c` |
| 71 | +reference them directly. |
| 72 | + |
| 73 | +#### Required Functions |
| 74 | + |
| 75 | +| Function | Signature | Description | |
| 76 | +|----------|-----------|-------------| |
| 77 | +| `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. | |
| 78 | +| `board_deinit` | `whal_Error board_deinit(void)` | Tear down board hardware in reverse order. | |
| 79 | +| `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. | |
| 80 | + |
| 81 | +### board.c |
| 82 | + |
| 83 | +Implements the functions above. Typical `board_init` sequence: |
| 84 | + |
| 85 | +1. Initialize clocks (PLL, peripheral clocks) |
| 86 | +2. Initialize GPIO (UART pins, Ethernet pins) |
| 87 | +3. Initialize UART (`whal_Uart_Init`) |
| 88 | +4. Initialize Ethernet MAC (`whal_Eth_Init`) |
| 89 | +5. Initialize Ethernet PHY (`whal_EthPhy_Init`) |
| 90 | +6. Initialize and start system timer |
| 91 | + |
| 92 | +The `whal_Eth` device must have its `macAddr` field set — this is |
| 93 | +where wolfIP reads the interface MAC address from. |
| 94 | + |
| 95 | +### board.mk |
| 96 | + |
| 97 | +Provides build configuration. Must set: |
| 98 | + |
| 99 | +| Variable | Description | |
| 100 | +|----------|-------------| |
| 101 | +| `WOLFHAL_ROOT` | Path to wolfHAL (use `?=` so it's overridable) | |
| 102 | +| `GCC` | Cross-compiler path (e.g. `arm-none-eabi-gcc`) | |
| 103 | +| `OBJCOPY` | Objcopy tool | |
| 104 | +| `CFLAGS` | Compiler flags (architecture, warnings, includes) | |
| 105 | +| `LDFLAGS` | Linker flags | |
| 106 | +| `LDLIBS` | Libraries to link (libc, libgcc, etc.) | |
| 107 | +| `LINKER_SCRIPT` | Path to the board's linker script | |
| 108 | +| `BOARD_SOURCE` | List of board + wolfHAL driver source files | |
| 109 | + |
| 110 | +`BOARD_SOURCE` must include at minimum: |
| 111 | +- `startup.c`, `ivt.c`, `board.c`, `syscalls.c` from the board directory |
| 112 | +- wolfHAL drivers: `eth/eth.c`, `eth/<platform>_eth.c`, |
| 113 | + `eth_phy/eth_phy.c`, `eth_phy/<phy>.c`, `clock/clock.c`, |
| 114 | + `clock/<platform>_rcc.c`, `gpio/gpio.c`, `gpio/<platform>_gpio.c`, |
| 115 | + `timer/timer.c`, `timer/systick.c`, `uart/uart.c`, |
| 116 | + `uart/<platform>_uart.c` |
| 117 | + |
| 118 | +### syscalls.c |
| 119 | + |
| 120 | +Must provide: |
| 121 | +- Standard libc stubs: `_write`, `_read`, `_sbrk`, `_close`, `_fstat`, |
| 122 | + `_isatty`, `_lseek`, `_exit`, `_kill`, `_getpid` |
| 123 | +- `_write` should route to `whal_Uart_Send(&g_whalUart, ...)` so that |
| 124 | + `printf` outputs to UART |
| 125 | +- `uint32_t wolfIP_getrandom(void)` — wolfIP's random number hook |
| 126 | + |
| 127 | +### startup.c, ivt.c, linker.ld |
| 128 | + |
| 129 | +Standard bare-metal files for your target architecture. See the |
| 130 | +`stm32h563zi_nucleo` board for a reference implementation. |
| 131 | + |
| 132 | +## Port API |
| 133 | + |
| 134 | +The port exposes a single function: |
| 135 | + |
| 136 | +```c |
| 137 | +#include "wolfhal_eth.h" |
| 138 | + |
| 139 | +struct wolfhal_eth_ctx ctx = { |
| 140 | + .eth = &g_whalEth, |
| 141 | + .phy = &g_whalEthPhy, |
| 142 | +}; |
| 143 | + |
| 144 | +int ret = wolfhal_eth_init(wolfIP_getdev(ipstack), &ctx); |
| 145 | +``` |
| 146 | + |
| 147 | +`wolfhal_eth_init` will: |
| 148 | +1. Poll `whal_EthPhy_GetLinkState` until link comes up (5s timeout, |
| 149 | + configurable via `WOLFHAL_ETH_LINK_TIMEOUT_MS`) |
| 150 | +2. Start the MAC with negotiated speed/duplex |
| 151 | +3. Copy `eth->macAddr` to the wolfIP device |
| 152 | +4. Register poll/send callbacks that bridge to `whal_Eth_Recv`/`whal_Eth_Send` |
| 153 | + |
| 154 | +## Naming Conventions |
| 155 | + |
| 156 | +- All port functions and variables use `snake_case` |
| 157 | +- Board functions use `board_` prefix: `board_init`, `board_get_tick` |
| 158 | +- Port functions use `wolfhal_` prefix: `wolfhal_eth_init` |
| 159 | +- wolfHAL API calls retain their own naming (`whal_Eth_Init`, etc.) |
| 160 | +- Global device instances use `g_whal` prefix: `g_whalEth`, `g_whalEthPhy`, `g_whalUart` |
| 161 | +- Macros use `UPPER_SNAKE_CASE` |
0 commit comments