Skip to content

Commit a069cf6

Browse files
dgarskedanielinux
authored andcommitted
Add STM32F437/F439 wolfIP port (NUCLEO-F439ZI / STM32439I-EVAL)
1 parent 146de4b commit a069cf6

10 files changed

Lines changed: 2060 additions & 0 deletions

File tree

src/port/stm32f4/stm32f4_eth.c

Lines changed: 635 additions & 0 deletions
Large diffs are not rendered by default.

src/port/stm32f4/stm32f4_eth.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/* stm32f4_eth.h
2+
*
3+
* Shared Ethernet driver for STM32F4xx (DWC GMAC legacy v1 descriptors).
4+
* Used by STM32F407/F417/F427/F437/F439/F469/F479 wolfIP ports.
5+
*
6+
* Copyright (C) 2026 wolfSSL Inc.
7+
*
8+
* This file is part of wolfIP TCP/IP stack.
9+
*
10+
* wolfIP is free software; you can redistribute it and/or modify
11+
* it under the terms of the GNU General Public License as published by
12+
* the Free Software Foundation; either version 3 of the License, or
13+
* (at your option) any later version.
14+
*
15+
* wolfIP is distributed in the hope that it will be useful,
16+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
* GNU General Public License for more details.
19+
*
20+
* You should have received a copy of the GNU General Public License
21+
* along with this program; if not, write to the Free Software
22+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
23+
*/
24+
#ifndef WOLFIP_STM32F4_ETH_H
25+
#define WOLFIP_STM32F4_ETH_H
26+
27+
#include <stdint.h>
28+
#include "wolfip.h"
29+
30+
/* Initialize the STM32F4 Ethernet MAC + DMA + PHY and hook the driver into
31+
* the wolfIP link-layer device. PHY auto-negotiation is run synchronously
32+
* with a 5-second timeout. Returns 0 on success, -2 if the PHY is reachable
33+
* but link did not come up (MAC/DMA still left running so a late link comes
34+
* up naturally), or -1 on a fatal init error.
35+
*
36+
* The caller must already have configured the RCC (ETHMAC/ETHMACTX/ETHMACRX
37+
* clocks), SYSCFG_PMC.MII_RMII_SEL, and the RMII GPIO pinmux before calling.
38+
*/
39+
int stm32f4_eth_init(struct wolfIP_ll_dev *ll, const uint8_t *mac);
40+
41+
void stm32f4_eth_get_stats(uint32_t *polls, uint32_t *pkts, uint32_t *tx_pkts,
42+
uint32_t *tx_errs);
43+
uint32_t stm32f4_eth_get_dma_status(void);
44+
void stm32f4_eth_get_mac_diag(uint32_t *mac_cfg, uint32_t *mac_dbg);
45+
46+
#endif /* WOLFIP_STM32F4_ETH_H */

src/port/stm32f439/Makefile

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
CC ?= arm-none-eabi-gcc
2+
OBJCOPY ?= arm-none-eabi-objcopy
3+
SIZE ?= arm-none-eabi-size
4+
5+
ROOT := ../../..
6+
7+
# Cortex-M4F with FPU (hardware float, single-precision). Both NUCLEO-F439ZI
8+
# and STM32439I-EVAL ship STM32F437/F439 silicon with the same FPU.
9+
CFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard
10+
CFLAGS += -Os -ffreestanding -fdata-sections -ffunction-sections
11+
CFLAGS += -g -ggdb -Wall -Wextra -Werror
12+
13+
# Include paths
14+
CFLAGS += -I. -I$(ROOT) -I$(ROOT)/src -I$(ROOT)/src/port/stm32f4
15+
16+
# Board selection. Both supported boards use STM32F437/F439 silicon (same
17+
# DWC GMAC + same register layout) but differ in PHY addr, UART pinmux,
18+
# HSE source, and RMII TXD1 pin. Set BOARD on the make command line:
19+
# BOARD=nucleo_f439zi NUCLEO-F439ZI dev board (LAN8742A, USART3, HSE 8MHz bypass)
20+
# BOARD=stm32439i_eval STM32439I-EVAL eval board (DP83848, UART4, HSE 25MHz crystal)
21+
BOARD ?= nucleo_f439zi
22+
23+
ifeq ($(BOARD),nucleo_f439zi)
24+
CFLAGS += -DBOARD_NUCLEO_F439ZI -DSTM32F4_ETH_PHY_ADDR=0
25+
else ifeq ($(BOARD),stm32439i_eval)
26+
CFLAGS += -DBOARD_STM32439I_EVAL -DSTM32F4_ETH_PHY_ADDR=1
27+
else
28+
$(error Unknown BOARD '$(BOARD)' - use nucleo_f439zi or stm32439i_eval)
29+
endif
30+
31+
EXTRA_CFLAGS ?=
32+
CFLAGS += $(EXTRA_CFLAGS)
33+
34+
# Relaxed warnings for wolfIP core (some unused-param noise on small builds)
35+
CFLAGS_EXT := $(filter-out -Werror,$(CFLAGS))
36+
CFLAGS_EXT += -Wno-unused-variable -Wno-unused-function -Wno-unused-parameter
37+
38+
LDFLAGS := -nostdlib -T target.ld -Wl,-gc-sections
39+
40+
# Application sources (strict warnings)
41+
APP_SRCS := startup.c ivt.c syscalls.c main.c \
42+
$(ROOT)/src/port/stm32f4/stm32f4_eth.c
43+
APP_OBJS := startup.o ivt.o syscalls.o main.o stm32f4_eth.o
44+
45+
# wolfIP core (relaxed warnings)
46+
WOLFIP_OBJ := wolfip.o
47+
48+
ALL_OBJS := $(APP_OBJS) $(WOLFIP_OBJ)
49+
50+
all: app.bin
51+
@echo "Built STM32F439 wolfIP port (BOARD=$(BOARD))"
52+
@$(SIZE) app.elf
53+
54+
app.elf: $(ALL_OBJS) target.ld
55+
$(CC) $(CFLAGS) $(ALL_OBJS) $(LDFLAGS) \
56+
-Wl,--start-group -lc -lm -lgcc -lnosys -Wl,--end-group -o $@
57+
58+
app.bin: app.elf
59+
$(OBJCOPY) -O binary $< $@
60+
61+
# Local sources -- strict warnings
62+
startup.o: startup.c
63+
$(CC) $(CFLAGS) -c $< -o $@
64+
ivt.o: ivt.c
65+
$(CC) $(CFLAGS) -c $< -o $@
66+
syscalls.o: syscalls.c
67+
$(CC) $(CFLAGS) -c $< -o $@
68+
main.o: main.c
69+
$(CC) $(CFLAGS) -c $< -o $@
70+
71+
# Shared F4 ETH driver (strict warnings)
72+
stm32f4_eth.o: $(ROOT)/src/port/stm32f4/stm32f4_eth.c
73+
$(CC) $(CFLAGS) -c $< -o $@
74+
75+
# wolfIP core (relaxed warnings)
76+
$(WOLFIP_OBJ): $(ROOT)/src/wolfip.c
77+
$(CC) $(CFLAGS_EXT) -c $< -o $@
78+
79+
clean:
80+
rm -f *.o app.elf app.bin
81+
82+
# Show memory usage
83+
size: app.elf
84+
@echo "=== Memory Usage ==="
85+
@$(SIZE) app.elf
86+
@echo ""
87+
@echo "Flash usage: $$($(SIZE) app.elf | awk 'NR==2{printf "%.2f%% (%d / %d bytes)", ($$1+$$2)*100/2097152, $$1+$$2, 2097152}')"
88+
@echo "RAM usage (static): $$($(SIZE) app.elf | awk 'NR==2{printf "%.2f%% (%d / %d bytes)", ($$2+$$3)*100/196608, $$2+$$3, 196608}')"
89+
90+
.PHONY: all clean size help
91+
92+
help:
93+
@echo "STM32F439 wolfIP Build System (supports F437/F439 silicon)"
94+
@echo ""
95+
@echo "Usage: make [target] [options]"
96+
@echo ""
97+
@echo "Targets:"
98+
@echo " all Build app.bin (default)"
99+
@echo " clean Remove build artifacts"
100+
@echo " size Show memory usage statistics"
101+
@echo " help Show this help"
102+
@echo ""
103+
@echo "Options:"
104+
@echo " BOARD=nucleo_f439zi NUCLEO-F439ZI (default; LAN8742A, USART3, HSE 8MHz bypass)"
105+
@echo " BOARD=stm32439i_eval STM32439I-EVAL (DP83848, UART4, HSE 25MHz crystal)"
106+
@echo " EXTRA_CFLAGS=-DDEBUG_ETH Verbose ETH driver diagnostics"
107+
@echo " CC= C compiler (default: arm-none-eabi-gcc)"
108+
@echo ""
109+
@echo "Testing:"
110+
@echo " ping <ip> # ICMP ping"
111+
@echo " echo 'hello' | nc <ip> 7 # TCP echo"

src/port/stm32f439/README.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# wolfIP on STM32F437/F439
2+
3+
Bare-metal wolfIP port for STMicro STM32F437/F439 silicon. Supports two
4+
boards from one source tree, selected at compile time via `BOARD=`:
5+
6+
| Board | MCU | PHY | VCP UART | HSE | RMII TXD1 |
7+
|------------------|--------------|-----------|------------------------|----------------------------|-----------|
8+
| `nucleo_f439zi` | STM32F439ZIT | LAN8742A | USART3 (PD8/PD9, AF7) | 8 MHz BYPASS (ST-LINK MCO) | PB13 |
9+
| `stm32439i_eval` | STM32F437IIH | DP83848 | UART4 (PC10/PC11, AF8) | 25 MHz crystal | PG14 |
10+
11+
Brings up Ethernet (RMII), runs DHCP, and exposes a TCP echo server on
12+
port 7 plus ICMP ping.
13+
14+
**Status:** `nucleo_f439zi` has been booted end-to-end on hardware (no
15+
cable -- clocks/UART/MAC/MDIO/PHY-ID verified; link-up + DHCP path not
16+
yet exercised). `stm32439i_eval` is compile-tested only; the build
17+
artifact has not yet been validated on the STM32439I-EVAL hardware.
18+
19+
## Hardware
20+
21+
- MCU: Cortex-M4F @ 168 MHz, 2 MB flash, 256 KB RAM (192 KB main SRAM +
22+
64 KB CCM; this port keeps everything in main SRAM since the GMAC DMA
23+
cannot reach CCM).
24+
- Clock: HSE -> PLL -> SYSCLK 168 MHz, HCLK 168 MHz, PCLK1 42 MHz,
25+
PCLK2 84 MHz. PLL pre-divider differs per board (PLLM=8 for NUCLEO
26+
HSE_BYPASS 8 MHz, PLLM=25 for EVAL 25 MHz crystal); the post-divider
27+
chain and SYSCLK target are identical.
28+
- Ethernet: Synopsys DWC GMAC (legacy 16-byte descriptors, ATDS=0) in
29+
RMII mode. Driver in `src/port/stm32f4/`.
30+
31+
## RMII pin map (shared, with the per-board TXD1 noted)
32+
33+
| Signal | Pin | AF |
34+
|------------------|--------------------------------|-----|
35+
| ETH_RMII_REF_CLK | PA1 | 11 |
36+
| ETH_MDIO | PA2 | 11 |
37+
| ETH_RMII_CRS_DV | PA7 | 11 |
38+
| ETH_MDC | PC1 | 11 |
39+
| ETH_RMII_RXD0 | PC4 | 11 |
40+
| ETH_RMII_RXD1 | PC5 | 11 |
41+
| ETH_RMII_TX_EN | PG11 | 11 |
42+
| ETH_RMII_TXD0 | PG13 | 11 |
43+
| ETH_RMII_TXD1 | PB13 (NUCLEO) / PG14 (EVAL) | 11 |
44+
45+
## Build
46+
47+
```
48+
make clean
49+
make # default: BOARD=nucleo_f439zi
50+
make BOARD=stm32439i_eval # for the STM32439I-EVAL
51+
```
52+
53+
Outputs `app.bin` (raw binary for ST-LINK) and `app.elf` (with debug
54+
info for GDB / addr2line).
55+
56+
Verbose ETH bring-up diagnostics:
57+
58+
```
59+
make clean
60+
make EXTRA_CFLAGS=-DDEBUG_ETH
61+
```
62+
63+
Memory usage report:
64+
65+
```
66+
make size
67+
```
68+
69+
## Flash
70+
71+
Via ST-LINK CLI:
72+
73+
```
74+
st-flash write app.bin 0x08000000
75+
```
76+
77+
If multiple ST-LINKs are connected, target a specific probe by serial:
78+
79+
```
80+
st-flash --serial <ST-LINK-serial> --reset write app.bin 0x08000000
81+
```
82+
83+
Or via STM32CubeProgrammer with the onboard ST-LINK/V2-1.
84+
85+
## Expected UART output
86+
87+
```
88+
=== wolfIP STM32F437/F439 (NUCLEO-F439ZI) ===
89+
Build: <date> <time>
90+
SYSCLK = 168000000 Hz, HCLK = 168000000 Hz, ...
91+
Initializing Ethernet (RMII + LAN8742A)...
92+
PHY ID at addr 0: 0x0007 / 0xC131
93+
PHY link: UP, AN: complete
94+
Starting DHCP...
95+
DHCP bound:
96+
IP: <ip>
97+
Mask: <mask>
98+
GW: <gw>
99+
TCP echo server on port 7
100+
Ready! Test with:
101+
ping <ip>
102+
echo 'hello' | nc <ip> 7
103+
```
104+
105+
Every 10 s the main loop prints a diagnostic line with packet counters
106+
and MAC/DMA register snapshots (useful when the link isn't coming up):
107+
108+
```
109+
[30] rx=0 tx=3/343030 maccr=0x0000848C macdbg=0x01120000 dmasr=0x00260400
110+
```
111+
112+
For the EVAL build, the banner shows `STM32439I-EVAL` and `DP83848` /
113+
PHY addr 1 instead.
114+
115+
## Test
116+
117+
From a host on the same subnet as the device:
118+
119+
```
120+
ping <ip>
121+
echo 'hello' | nc <ip> 7
122+
```
123+
124+
## Out of scope (milestone 1)
125+
126+
- TLS / HTTPS / SSH / MQTT (the H563 port shows the wolfSSL hook-in
127+
pattern; can be ported here once basic eth works).
128+
- wolfBoot / TFTP partition update.
129+
- FreeRTOS.
130+
- IRQ-driven RX (this port uses poll mode like the VA416xx milestone-1).

src/port/stm32f439/config.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/* config.h
2+
*
3+
* wolfIP build-time configuration for the STM32F437 port (STM32439I-EVAL).
4+
*
5+
* Copyright (C) 2026 wolfSSL Inc.
6+
*
7+
* This file is part of wolfIP TCP/IP stack.
8+
*
9+
* wolfIP is free software; you can redistribute it and/or modify
10+
* it under the terms of the GNU General Public License as published by
11+
* the Free Software Foundation; either version 3 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* wolfIP is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU General Public License
20+
* along with this program; if not, write to the Free Software
21+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
22+
*/
23+
#ifndef WOLF_CONFIG_H
24+
#define WOLF_CONFIG_H
25+
26+
#ifndef CONFIG_IPFILTER
27+
#define CONFIG_IPFILTER 0
28+
#endif
29+
30+
#define ETHERNET
31+
#define LINK_MTU 1536
32+
33+
/* STM32F437IIHx has 256KB RAM (192KB main SRAM + 64KB CCM). We have
34+
* plenty of room compared to the VA416xx port. Keep the socket count
35+
* modest for milestone-1 bring-up. */
36+
#define MAX_TCPSOCKETS 2 /* listen + 1 client */
37+
#define MAX_UDPSOCKETS 1 /* DHCP */
38+
#define MAX_ICMPSOCKETS 1
39+
#define RXBUF_SIZE LINK_MTU
40+
#define TXBUF_SIZE LINK_MTU
41+
42+
#define MAX_NEIGHBORS 4
43+
#define WOLFIP_ARP_PENDING_MAX 2
44+
45+
#ifndef WOLFIP_MAX_INTERFACES
46+
#define WOLFIP_MAX_INTERFACES 1
47+
#endif
48+
49+
#ifndef WOLFIP_ENABLE_FORWARDING
50+
#define WOLFIP_ENABLE_FORWARDING 0
51+
#endif
52+
53+
#ifndef WOLFIP_ENABLE_LOOPBACK
54+
#define WOLFIP_ENABLE_LOOPBACK 0
55+
#endif
56+
57+
#ifndef WOLFIP_ENABLE_DHCP
58+
#define WOLFIP_ENABLE_DHCP 1
59+
#endif
60+
61+
/* Static IP fallback (used when DHCP is disabled or times out) */
62+
#define WOLFIP_IP "192.168.12.37"
63+
#define WOLFIP_NETMASK "255.255.255.0"
64+
#define WOLFIP_GW "192.168.12.1"
65+
#define WOLFIP_STATIC_DNS_IP "8.8.8.8"
66+
67+
#if WOLFIP_ENABLE_DHCP
68+
#define DHCP
69+
#endif
70+
71+
#endif /* WOLF_CONFIG_H */

0 commit comments

Comments
 (0)