Wiznet makers

sophia

Published December 04, 2025 ©

25 UCC

6 VAR

0 Contests

0 Followers

1 Following

Original Link

Controlling STM32 & WIZnet Ethernet with Rust + Embassy(Nucleo-F446RE Example)

Rust 언어와 Embassy 프레임워크를 사용해 STM32 보드(Nucleo-F446RE)에서 WIZnet 이더넷 칩을 제어하는 방법을 소개

COMPONENTS Hardware components

WIZnet - W5500

x 1


PROJECT DESCRIPTION

Rust + Embassy로 STM32와 WIZnet Ethernet 제어하기

STM32 Nucleo-F446RE + WIZnet W5500 기반 임베디드 Rust 네트워크 스타터 프로젝트

 

프로젝트 개요 (Project Overview)

이 프로젝트는 Rust + Embassy 프레임워크를 사용하여
STM32 Nucleo-F446RE 보드와 WIZnet Ethernet 칩(W5500 등)을 제어하는 기본 네트워크 예제입니다.

  • 주요 키워드: WIZnet, W5500, W6100, W55RP20, STM32, Nucleo-F446RE, Rust, Embassy, Embedded, Ethernet, TCP/IP, Async

목표

  • C/C++ 대신 Rust로 안전한 임베디드 네트워크 코드를 작성해 보기
  • Embassy 비동기 런타임WIZnet 하드웨어 TCP/IP를 결합해 LED 깜빡이기 + Ethernet 초기화까지 구현
  • 향후 Web Server, MQTT, IoT Gateway 등으로 확장 가능한 기반 만들기

이 예제는 “Lチカ(LED Blink)” 수준에서 시작하지만,
프로젝트 구조 자체는 WIZnet Ethernet을 포함한 Rust 네트워킹 프로젝트 템플릿으로 확장 가능하도록 설계되어 있습니다.

 

프로젝트 설명 (Description)

1. 왜 Rust + Embassy + WIZnet인가?

기존의 임베디드 개발은 대부분 C/C++ + RTOS 조합에 의존합니다.
하지만 다음과 같은 한계가 있습니다.

  • 포인터/메모리 버그로 인한 디버깅 난이도
  • 같은 핀을 중복 설정하거나, 잘못된 타이머/채널을 연결해도 컴파일 시점에 에러를 못 잡는 경우
  • RTOS에서 태스크·큐·락을 직접 관리해야 하는 복잡한 동기화 코드

Rust + Embassy 조합은 이런 문제를 다음과 같이 줄여 줍니다.

  • 소유권(Ownership)과 타입 시스템으로
    • 한 번 사용한 핀을 다시 다른 역할로 생성하면 컴파일 에러
    • 하드웨어 제약(특정 타이머-핀 조합 등)을 타입으로 표현하여 잘못된 설정을 사전에 차단
  • 비동기(Async) 기반 타이머/IO를 제공하여,
    • Timer::after() 처럼 CPU를 블로킹하지 않는 딜레이 구현
    • 여러 네트워크 작업을 동시에 처리하는 구조 확장에 유리

여기에 WIZnet Ethernet 칩(W5500 / W6100 / W55RP20 등) 을 더하면:

  • MCU에서 복잡한 TCP/IP 스택을 직접 구현할 필요 없이,
  • WIZnet 하드웨어 TCP/IP 엔진이 대부분의 네트워크 처리를 담당
  • Rust는 주로 애플리케이션 로직과 프로토콜 처리에 집중할 수 있어
    • 코드가 단순해지고
    • MCU 자원(CPU/메모리)도 효율적으로 사용 가능합니다.

 

하드웨어 구성 (Hardware Setup)

사용 보드 및 부품

  • MCU 보드
    • ST Nucleo-F446RE (STM32F446RE 기반)
    • 다른 STM32 Nucleo 보드로도 확장 가능 (Embassy 지원 여부에 따라)
  • WIZnet Ethernet 보드/모듈 (예시 중 택 1)
    • WIZnet W5500 이더넷 모듈 또는 이와 동일 칩 기반 이더넷 보드
    • 또는 W6100, W5100S, W55RP20-EVB-Pico / ioNIC 기반 보드 등으로 확장 가능
  • 기타
    • USB 케이블 (보드 전원 및 디버깅용)
    • 점퍼 케이블 (STM32 보드와 WIZnet 모듈 간 SPI/INT/RESET 연결용)

기본 연결 예 (STM32 Nucleo-F446RE + W5500)

아래는 대표적인 SPI 연결 예시입니다. 실제 핀은 보드 레이아웃에 따라 조정 가능합니다.

  • SPI SCK → STM32 PA5
  • SPI MISO → STM32 PA6
  • SPI MOSI → STM32 PA7
  • CS(SS) → STM32 PB6 (예시)
  • RESET → STM32 PB7 (선택 사항)
  • INT → STM32 PB8 (선택 사항, 인터럽트 기반 이벤트 처리 시)

Nucleo 보드에서 기본 LED는 보통 PA5에 연결되어 있어,
LED 깜빡이 예제는 이 핀을 출력으로 사용합니다.

 

소프트웨어 구성 (Software Setup)

개발 환경

  • OS: Ubuntu 22.04 / 24.04 (또는 Windows + WSL2)
  • IDE: Visual Studio Code
  • 개발 환경 방식: VSCode Dev Containers + Docker
  • 디버깅/플래시: probe-rs 사용

1. Dev Container 구성

프로젝트 루트에 .devcontainer 폴더를 만들고, 다음을 준비합니다.

  • Dockerfile
    • ubuntu:24.04 베이스
    • rustup으로 Rust 설치
    • probe-rs 설치
    • cargothumbv7em-none-eabihf 타깃 설정
  • docker-compose.yml
    • /dev를 컨테이너에 마운트해서 **USB 디버거(ST-LINK 등)**에 접근 가능하도록 설정
    • 워크스페이스 및 SSH 키 볼륨 마운트
  • devcontainer.json
    • 컨테이너에서 열 워크스페이스 폴더 지정 (예: /workspace)
    • rust-lang.rust-analyzer 확장 필수 설치

VSCode에서 “Dev Containers: Reopen in Container”를 실행하면
Rust + Embassy + probe-rs 개발 환경이 자동으로 올라옵니다.

2. Rust 프로젝트 및 의존성

cargo init 명령으로 새 프로젝트를 생성한 뒤, Cargo.toml에 Embassy 및 WIZnet 관련 의존성을 추가합니다.

[package] name = "stm32-wiznet-embassy" version = "0.1.0" edition = "2021"

[dependencies] embassy-stm32 = { version = "0.1", features = ["stm32f446re", "time-driver-tim2"] }
embassy-executor = { version = "0.3", features = ["arch-cortex-m", "executor-thread"] }
embassy-time = "0.3"

embassy-net = "0.2" embassy-net-wiznet = { version = "0.2", features = ["w5500"] }

defmt = "0.3" panic-probe = { version = "0.3", features = ["print-defmt"] }

버전은 예시이며, 실제 사용 시 최신 버전을 확인해 맞게 조정하면 됩니다.

추가로:

  • .cargo/config.toml에 타깃(thumbv7em-none-eabihf) 및 probe-rs runner 설정
  • rust-toolchain.toml로 팀 전체 Rust 버전 고정 (예: 1.90 등)
  • build.rs에서 Embassy 링커 스크립트 적용

 

3. 메인 예제 코드 개요

기본 예제는 다음 두 가지를 수행합니다.

  1. LED 깜빡이기 (Lチカ) – MCU 및 Embassy 환경이 정상 동작하는지 검증
  2. WIZnet Ethernet 초기화 – MAC 설정 후 DHCP로 IP 획득 (또는 Static IP 설정)

코드 구조는 대략 아래와 같습니다.

#![no_std] #![no_main]

use embassy_executor::Spawner;
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_stm32::Config;
use embassy_time::{Timer, Duration};
use embassy_net_wiznet::WiznetSpiDevice;

#[embassy_executor::main] async fn main(_spawner: Spawner) {
    // 1. 보드 초기화
    let p = embassy_stm32::init(Config::default());

    // 2. LED 핀 설정 (예: Nucleo-F446RE의 PA5)
    let mut led = Output::new(p.PA5, Level::Low, Speed::Low);

    // 3. WIZnet SPI 디바이스 초기화 (예: W5500)
    // 실제 사용 시 SPI/CS 핀은 보드에 맞게 수정
    let spi = embassy_stm32::spi::Spi::new(
        /* ... SPI 인스턴스 및 핀들 ... */
    );

    let mut wiz = WiznetSpiDevice::new(spi).await.unwrap();

    // 4. MAC 주소 및 DHCP 설정
    wiz.set_mac_addr([0x00, 0x08, 0xdc, 0xab, 0xcd, 0xef]);
    wiz.dhcp_start().await.unwrap();

    // 5. 메인 루프: LED 토글
    loop {
        led.set_high();
        Timer::after(Duration::from_millis(500)).await;
        led.set_low();
        Timer::after(Duration::from_millis(500)).await;
    }
}

이 구조를 기반으로:

  • TCP 서버/클라이언트
  • HTTP Web Server
  • MQTT 클라이언트
    등을 Embassy + embassy-net 레이어 위에서 구현할 수 있습니다.

 

WIZnet 제품이 어떻게 사용되었는지 (How WIZnet Products Are Used)

1. 하드웨어 TCP/IP 오프로드

이 프로젝트에서 WIZnet 칩(W5500/W6100/W5100S/W55RP20 등)은:

  • 하드웨어 TCP/IP 엔진으로 동작하며
  • MCU는 단순히 소켓 오픈 / 데이터 송수신 / 상태 확인 위주의 제어만 수행합니다.

이로써:

  • MCU에서 소프트웨어 TCP/IP 스택을 구현할 때 발생하는
    • 복잡한 상태 머신
    • 방대한 코드량 및 메모리 사용
    • 네트워크 타이밍 이슈
      를 크게 줄일 수 있습니다.

2. Embassy 네트워크 계층과의 연결

embassy-net-wiznet 크레이트는 WIZnet 칩을 위한 드라이버 + 어댑터 레이어입니다.

  • SPI 기반 WIZnet Device(W5500 등)를 WiznetSpiDevice 형태로 래핑하고
  • Embassy의 네트워크 스택(embassy-net)에 붙여
    • DHCP, ARP, UDP, TCP 등 프로토콜을 Rust 코드에서 안전하게 제어할 수 있게 합니다.

3. WIZnet + Rust 조합의 의미

이 프로젝트는 다음과 같은 의미를 가집니다.

1. 기존 WIZnet C예제에서 한 단계 진화

  • C 기반 예제 위주였던 WIZnet 생태계에
  • Rust/Embassy 기반의 현대적인 임베디드 예제를 추가하여
  • 새로운 언어/패러다임에 익숙한 개발자도 쉽게 접근 가능

2. 안전한 IoT/IIoT 시스템 기반 마련

  • 산업용/보안 중요 서비스에서 메모리 안전성은 필수 요소
  • WIZnet 칩이 네트워크를 담당하고, Rust가 애플리케이션 로직을 담당함으로써
    • 안전성과 신뢰성을 동시에 확보

3. WIZnet 제품 확장성 강조

  • 동일 코드 구조로
    • W5500 → W6100(IPv4/IPv6)
    • W5100S / ioNIC(W55RP20) 기반 보드
      등으로 확장 가능
  • WIZnet 제품 포트폴리오 간 코드 재사용성과 호환성이 높다는 것을 보여주는 데에도 좋은 데모

 

이 프로젝트의 의미와 확장 아이디어 (Significance & Future Work)

교육/학습 관점

  • Embedded Rust 입문용 예제로 활용 가능
  • WIZnet Ethernet + MCU + Rust 조합을 한 번에 경험할 수 있는 구성
  • C/C++ 개발자에게 “Rust로도 이렇게 쉽게 네트워크 MCU 개발이 가능하다”는 메시지를 전달

실전 응용 아이디어

  • 🌐 초간단 Web Server
    • 온도/습도 센서 값을 WIZnet 기반 Web 페이지로 실시간 제공
  • 📡 MQTT IoT Gateway
    • 센서 데이터 → WIZnet Ethernet → MQTT Broker(Cloud) 전송
  • 🧠 AIoT Edge Node (특히 W55RP20 연동)
    • RP2350 기반 W55RP20-EVB-Pico와 Embassy를 결합하여
    • 로컬 연산 + Ethernet 통신을 수행하는 AIoT 엣지 노드 구현
  • 🧩 산업용 장비 모니터링 게이트웨이
    • RS-485/Modbus 장비 상태를 수집 후
    • WIZnet Ethernet으로 상위 서버에 보고

 

마무리

이 프로젝트는 “Rust + Embassy + WIZnet Ethernet” 조합이 실제로 얼마나 강력한지 보여주는 최소 예제입니다.

  • 기존 C 기반 TCP/IP보다 더 안전하고 유지보수하기 쉬운 코드
  • WIZnet 하드웨어 TCP/IP가 제공하는 안정적이고 검증된 네트워크 구현
  • Embassy의 비동기 런타임으로 고성능·저지연 네트워크 앱으로 확장 가능한 구조

을 동시에 얻을 수 있습니다.

앞으로 maker.wiznet.io에서

  • W5500 / W6100 / W55RP20을 대상으로 한 Rust/Embassy 예제 시리즈
  • Web Server, MQTT Client, HTTP REST API 등
    을 연재 형식으로 확장해 나가도 좋습니다.


Getting Started with Rust + Embassy on STM32 and WIZnet Ethernet  

1. Hardware TCP/IP Offload

In this project, the WIZnet chip (e.g., W5500 / W6100 / W5100S / W55RP20) acts as a:

  • Hardware TCP/IP offload engine, and
  • Offloads low-level protocol handling from the MCU.

The Rust firmware:

  • Opens sockets
  • Sends / receives data
  • Monitors connection status

while the WIZnet silicon handles ARP, IP, TCP, UDP, and timing in hardware.

This:

  • Reduces firmware complexity
  • Decreases MCU flash / RAM usage
  • Improves reliability for industrial Ethernet, IoT, and IIoT scenarios

2. Integration with Embassy Network Stack

The embassy-net-wiznet crate provides:

  • A WIZnet driver layer (e.g. WiznetSpiDevice)
  • An adapter to plug the WIZnet device into Embassy’s network stack (embassy-net)

This makes Rust code able to use:

  • DHCP
  • IPv4 (and IPv6 with appropriate WIZnet chip)
  • UDP and TCP sockets

in a type-safe and async manner.

3. Why This Combination Matters

This project highlights:

1. A modern path for WIZnet users

  • Traditional C-based examples are still valuable,
  • But this Rust/Embassy example shows a modern, safe alternative for new-generation developers.

2. Safety for production IoT / IIoT systems

  • Memory safety issues are a major concern in connected devices.
  • With Rust handling application logic and WIZnet offloading Ethernet/TCP/IP,
    you can build reliable and maintainable networked devices.

3. Scalability across WIZnet product families

  • The same architectural pattern can be reused with:
    • W5500 for classic IPv4 Ethernet
    • W6100 for IPv4/IPv6
    • W55RP20 (ioNIC) for tightly integrated MCU + TCP/IP
  • This demonstrates cross-device code reuse throughout the WIZnet ecosystem.

 

Significance and Future Directions

Educational & Learning Value

  • A great Embedded Rust introduction for C/C++ developers
  • A real-world example combining:
    • Rust,
    • Embassy async runtime, and
    • WIZnet Ethernet hardware

This shows that:

“You can build serious networked MCUs in Rust on WIZnet hardware.”

Practical Extension Ideas

  • 🌐 Simple Web server showing sensor values over W5500/W6100
  • 📡 MQTT IoT gateway pushing telemetry to a cloud broker
  • 🧠 AIoT edge node combining:
    • Local compute (e.g., W55RP20 / RP-based boards)
    • Deterministic Ethernet communication
  • 🧩 Industrial monitoring gateway that bridges legacy field devices (e.g. RS-485, Modbus) with Ethernet

 

Adapting This Project to W55RP20-EVB-Pico (ioNIC)

The W55RP20-EVB-Pico is WIZnet’s ioNIC-based evaluation board, combining:

  • A Raspberry Pi RP2350-class MCU (dual-core ARM Cortex-M33)
  • WIZnet hardwired TCP/IP engine in a single chip (W55RP20)
  • A Pico-style form factor, compatible with many Raspberry Pi Pico accessories

Hardware Differences

Compared to “STM32 Nucleo + external W5500 module”:

  • You only need one board: W55RP20-EVB-Pico
  • The Ethernet MAC + PHY and TCP/IP engine are integrated in the W55RP20 chip
  • On-board LED, buttons, and headers are already wired, so:
    • No external SPI wiring to a separate Ethernet module
    • Simpler hardware setup for quick prototypes

Software Adaptation (Conceptual)

The overall software architecture remains the same:

  • Use an appropriate HAL / Embassy port for the RP2350 class MCU
  • Initialize clocks, GPIO, and ioNIC-specific peripherals
  • Use a WIZnet driver compatible with W55RP20 (similar to how embassy-net-wiznet works for W5500)
  • Configure MAC, start DHCP, then start async tasks as usual

Pseudo-style structure (for illustration):

 
#![no_std] #![no_main]

use embassy_executor::Spawner;
use embassy_time::{Timer, Duration};

// HAL / Embassy support for RP-based WIZnet boards (names are illustrative) use embassy_rp55::gpio::{Output, Level};
use embassy_rp55::Config;
use wiznet_ionic::W55rp20Device;

#[embassy_executor::main] async fn main(_spawner: Spawner) {
    // 1. Initialize W55RP20-EVB-Pico board
    let p = embassy_rp55::init(Config::default());

    // 2. Configure on-board LED
    let mut led = Output::new(p.LED_PIN, Level::Low);

    // 3. Initialize W55RP20 ioNIC network device
    let mut net = W55rp20Device::new(p.IONIC_PERIPHERAL).await.unwrap();

    // 4. Configure MAC and start DHCP
    net.set_mac_addr([0x00, 0x08, 0xdc, 0x55, 0x20, 0x01]);
    net.dhcp_start().await.unwrap();

    // 5. Blink LED to indicate the board is alive
    loop {
        led.set_high();
        Timer::after(Duration::from_millis(500)).await;
        led.set_low();
        Timer::after(Duration::from_millis(500)).await;
    }
}

Note: The module and type names above (embassy_rp55, wiznet_ionic, etc.) are illustrative.
Actual crate names and APIs may differ depending on the HAL and Embassy support status for W55RP20/RP2350.

Meaning of the W55RP20 Variant

Using W55RP20-EVB-Pico with Rust + Embassy is particularly interesting because:

1. Single-chip integration

  • MCU + TCP/IP in one chip simplifies board design and BOM.
  • Ideal for compact IoT and AIoT products.

2. Pico ecosystem compatibility

  • The Pico-style form factor works with many existing add-ons and carrier boards.

3. Best of both worlds

  • WIZnet’s proven hardware TCP/IP engine,
  • Combined with Rust’s memory safety and Embassy’s async model,
  • Creates a future-proof architecture for connected devices.
     
Documents
Comments Write