🚀 New here? Start with howto_demonstrate.md — a complete, illustrated walkthrough to set up and show the demo end-to-end (boards, wiring P↔P/N↔N, static IP, bus scan, flashing, Click demo).
🎓 Want to learn the code by example? See docs/DEMOS.md — the index of all worked examples (GPIO/I²C/SPI/PWM, blocking vs. non-blocking, sensor→actuator), each with its own deep-dive doc and a direct link to its
.csource, ordered as a learning path from "hello world" up.✅ No build required to run: all tools are already built under
release/(statically linked.exe, plus the demo firmware package). Just run them from there. Building (below) is optional — only needed if you change the source.
A pure-C host that remote-controls LAN866x endpoints via the Remote Control Protocol (RCP) on top of the C SOME/IP stack (libsomeip). Access is via the T1S-USB adapter (EVB-LAN8670-USB) as an Ethernet bridge — or via the on-board T1S↔100BASE-T bridge firmware in firmware/t1s_100baset_bridge/, which lets the PC reach the endpoint over plain RJ45 (and runs the tools on the board itself). See chapter 9.1.
🟦 100 % C — no C++. Every tool, the RCP wrapper and the platform layer are C; they link without
libstdc++. It is single-thread (a superloop, no RTOS required), so the same code base ports to a 32-bit MCU (lwIP) by writing a single platform file — see chapter 9.📦 Self-contained: this directory contains all sources required to build. Unpack → build, no external paths.
🔌 Running on real silicon: a complete MCU port of this toolset ships in
firmware/t1s_100baset_bridge/— a 10BASE-T1S ↔ 100BASE-T Layer-2 bridge on an ATSAME54P20A (MPLAB Harmony 3) that lets a PC reach a LAN866x endpoint through the bridge and runs the host tools (discovery,diag,ledblink,clickdemo) as on-board serial commands. See its README and chapter 9.1.
- Overview
- System requirements
- 2.1 CMake 3.10 or newer
- 2.2 A C compiler
- 2.3 Hardware and driver
- 2.4 Network
- How to compile
- Running and output
- How does discovery work?
- Project structure
- Example pin mapping (LAN8660)
- RCP method IDs
- Porting to MCU32
📖 Hardware setup & full per-tool reference: see TOOLS.md — board description (what plugs where), jumper/DIP ASCII map with photos, and a detailed page for every tool. Demo walkthrough: howto_demonstrate.md.
Purpose: a Windows host prototype that doubles as a 1:1 template for a 32-bit embedded device (MCU32 + lwIP, single-thread superloop). Everything is plain C.
The tools (all build to lan866x-<name>.exe):
The tool name links to its source
.c; the 🎓 tools are worked examples documented in docs/DEMOS.md.
| Tool (→ source) | Purpose |
|---|---|
lan866x-discovery |
list reachable endpoints + type + full GetStatus / GetNetworkStatus |
lan866x-servicetest |
probe which RCP methods/services the endpoint firmware implements |
lan866x-i2cscan |
scan an endpoint's I2C bus (like i2cdetect) |
🎓 lan866x-i2cid |
read a device ID over I2C non-blocking (VCNL4200) — doc |
🎓 lan866x-proxmon |
live proximity bar (VCNL4200) over I2C, non-blocking — doc |
🎓 lan866x-lan8680 |
read the LAN8680 front-end (SBC) over its housekeeping I2C, read-only — doc |
lan866x-gpio |
set / read a GPIO pin |
🎓 lan866x-ledscan |
interactively find which GPIO drives which on-board LED (→ JSON) — doc |
🎓 lan866x-ledblink |
on-board LED running light — the "hello world" demo — doc |
🎓 lan866x-ledtoggle |
toggle one LED non-blocking (async RCP) — doc |
🎓 lan866x-gpiomax |
max-speed GPIO toggle benchmark — pipelined async SetGpio, measures commanded vs confirmed toggle rate |
🎓 lan866x-ledpwm |
"breathing" LED via PWM (non-blocking; firmware-dependent) — doc |
🎓 lan866x-proxled |
sensor→actuator app: proximity drives the LEDs (no video) — doc |
lan866x-spi |
SPI transfer (full-duplex) |
🎓 lan866x-spiid |
identify the Thumbstick (MCP3204) over SPI non-blocking — doc |
🎓 lan866x-thumbmon |
live Thumbstick (MCP3204) read over SPI, non-blocking — doc |
lan866x-adc |
read the on-chip ADC (analog input or internal temperature) |
lan866x-pwm |
drive a PWM output on a digital pin |
lan866x-boot |
reboot between main app and bootloader (non-destructive) |
lan866x-flashimg |
write ONE signed/encrypted image via the bootloader |
lan866x-flashpkg |
update an endpoint straight from an MCHPKG package |
lan866x-diag |
read & interpret T1S link quality (read-only) |
🎓 lan866x-clickdemo |
interactive MikroE Click demo (Thumbstick + Proximity → 2× RGB) — doc |
lan866x-video |
loop-play a video file on the 2× RGB displays (ffmpeg → RTP) |
lan866x-dncpmon |
passive DNCP monitor (standalone, not SOME/IP) |
lan866x-dncpdisc |
active DNCP discovery (Registry broadcast → collect Announces, read-only) |
The SOME/IP tools use src/rcp.c (RCP over libsomeip) + the platform-neutral C stub src/someip_stub.c on the narrow src/plat.h layer (src/plat_win.c is the Windows implementation); lan866x-flashpkg additionally links a bundled ZIP reader (third-party/minizip). The two DNCP tools are standalone (Winsock only — DNCP is not SOME/IP).
📖 Every tool is documented in detail — with all options, examples and the board setup it needs — in TOOLS.md.
To build, the machine needs:
(tested with CMake 4.1)
- Download: https://cmake.org/download/ → "Windows x64 Installer".
- During installation choose "Add CMake to the system PATH".
- Check:
cmake --version
(one of the two options)
Option A – MinGW-w64 (GCC) — recommended for the command line (tested GCC 16.1)
- Easiest source: WinLibs https://winlibs.com/ (UCRT variant) – unzip and add the
…\mingw64\binfolder to PATH. - Alternatively MSYS2 https://www.msys2.org/:
pacman -S mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-cmake - Check:
gcc --versionandmingw32-make --version
Option B – Visual Studio 2022
- Installer: https://visualstudio.microsoft.com/ → workload "Desktop development with C++" (also provides the MSVC C compiler and CMake). No C++ runtime is linked — the sources are C.
(only needed to run, not to build)
- EVB-LAN8670-USB (T1S-USB adapter) – shows up on Windows as a normal Ethernet NIC.
- Install the Windows driver (
EVB-LAN8670-USB_Drv_Setup.exe, from the LAN866x Remote Demo package / MicrochipDirect EV08L38A). - LAN866x endpoint(s) on the T1S bus, bus terminated, PoDL power if applicable.
(only needed to run)
- Give the USB-T1S NIC a static IP in the endpoint subnet:
192.168.0.100/24. Endpoints =192.168.0.<NodeID>. - SOME/IP-SD uses multicast
224.0.0.1(UDP 30490). Allow the tools through the Windows firewall.
ℹ️ Optional. Pre-built, statically linked executables for all tools already ship in
release/— you can run the demo straight from there without compiling anything. Build only if you modify the source.
The package contains build.bat (chooses the compiler automatically: MinGW, else VS2022):
build.bat REM build (compiler chosen automatically)
build.bat mingw REM force MinGW-w64 (GCC)
build.bat vs REM force Visual Studio 2022
build.bat clean REM delete build folderResult: out\lan866x-discovery.exe (MinGW) or out\Release\lan866x-discovery.exe (VS), and all tools copied to release\.
Always specify the generator (-G …) explicitly – otherwise CMake aborts with "CMAKE_C_COMPILER not set".
MinGW-w64 (GCC):
cmake -G "MinGW Makefiles" -B out
cmake --build outVisual Studio 2022 (MSVC):
cmake -G "Visual Studio 17 2022" -A x64 -B out
cmake --build out --config ReleaseThe out/ folder is pure build output and can be deleted at any time (remove before packaging).
out\lan866x-discovery.exePer endpoint the tool prints the full status — via GetStatus (0x1002) + GetNetworkStatus (0x1600). Example (verified live, pure C):
Devices available = 2
========================================================
Endpoint #0 - 192.168.0.101:6800 (instance 0x0001, available=1)
========================================================
Uptime: 2h 38m 18s
Application: main/app.bin
Chip Identifier: LAN8662B -> Audio Endpoint
Main Version: LAN8662-main_V1.3.0-54
Root Version: LAN866x-root_V1.2.0-53
Bootloader Version: LAN866x-bootloader_V1.3.0-54
COMO Version: 0x00020006
Service Version: 0x00010600
Keys Version: V0.0.1
StartupInformation: 0x0000000000000219 (Security Mode 1)
MAC: 8C:71:12:2B:98:7F
IPv4: 192.168.0.101
Endpoint Status: Link-Up
OASPI Status: Disabled
Arbitration: PLCA no fallback
PLCA Node Id: 1
Nothing found? Check: driver installed · NIC IP 192.168.0.x set · bus terminated · endpoints powered · firewall allowed.
out\lan866x-i2cscan.exe REM first endpoint, SDA=PA08 SCL=PA09, 400 kHz
out\lan866x-i2cscan.exe --ip 192.168.0.54
out\lan866x-i2cscan.exe --ep 1 --sda 8 --scl 9 --speed 1Probes 0x08..0x77 with a 1-byte read and prints an i2cdetect grid (uses a short ~150 ms per-probe timeout since absent addresses never reply). Example (Proximity 3 Click on the demo board):
0 1 2 3 4 5 6 7 8 9 a b c d e f
50: -- 51 -- -- -- -- -- -- -- -- -- -- -- -- -- --
1 device(s) found on the I2C bus.
Pins must match the board configuration (
--sda/--scl, PA number 0–15). The tool releases SDA/SCL beforeOpenI2Cautomatically (ReleaseDigitalPins). If I2C is not configured on that endpoint,OpenI2CreturnsRT_NOT_REACHABLE("OpenI2C failed").
Read a device ID (non-blocking):
lan866x-i2cidreads the VCNL4200's ID register (0x0E→0x1058) using the async API — the worked I²C example:out\lan866x-i2cid.exe --ip 192.168.0.54Full write-up: docs/I2CDEMO.md.
out\lan866x-gpio.exe --pin 2 --set 1 REM PA02 as output, high
out\lan866x-gpio.exe --pin 2 --get REM PA02 as input, read
out\lan866x-gpio.exe --ip 192.168.0.54 --pin 6 --set 0On-board LED "hello world": the EVB has 3 on-board LEDs on
PA02/PA06/PA10(LD1–LD3, gated by DIPSW13-1/2/3).lan866x-ledblinkcycles them as a running light over SOME/IP — the canonical blink-an-LED demo, done remotely:out\lan866x-ledblink.exe --ip 192.168.0.54 REM running light, 500 ms/step out\lan866x-ledscan.exe --ip 192.168.0.54 --all REM (re)discover the LED pins -> led_map.jsonFull write-up: docs/LEDDEMO.md.
out\lan866x-spi.exe --tx 9F0000 REM send 3 bytes, read MISO at the same time
out\lan866x-spi.exe --tx AA55 --mode 0 --speed 1000000
out\lan866x-spi.exe --miso 12 --sck 13 --cs 14 --mosi 15 --tx 0102Output: TX: … / RX: …. Default pins MISO=PA12 SCK=PA13 CS=PA14 MOSI=PA15. Pins are released before OpenSpi.
Identify the Thumbstick (non-blocking):
lan866x-spiidreads the MCP3204 joystick axes over SPI with the async API — the worked SPI example (note: the MCP3204 has no ID register, a valid 12-bit read is its fingerprint):out\lan866x-spiid.exe --ip 192.168.0.54Full write-up: docs/SPIDEMO.md.
out\lan866x-adc.exe REM single analog read, 3V3 reference
out\lan866x-adc.exe --temp REM internal temperature sensor
out\lan866x-adc.exe --vref 1 REM use the 1V1 reference
out\lan866x-adc.exe --count 10 --interval 200Reads the on-chip 12-bit ADC (0..4095) and prints the scaled voltage, e.g. raw=2048 = 1.650 V. Channel 0 = analog input, 1 = internal temperature; reference 0 = 3V3, 1 = 1V1.
out\lan866x-pwm.exe --pin 6 --freq 1000 --duty 50 REM 1 kHz, 50% on PA06
out\lan866x-pwm.exe --pin 6 --period-ns 20000000 --duty 7.5 REM servo, 1.5 ms pulse
out\lan866x-pwm.exe --pin 6 --duty 0 REM stop output (0%)
out\lan866x-pwm.exe --pin 7 --freq 500 --duty 25 --hold 5Opens a PWM channel on a digital pin. Duty cycle wire encoding: 0 = 0% .. 2^31 = 100% (the tool takes percent and converts). By default the signal is left running on the endpoint after the tool exits (the handle lives on the device); --hold <s> stops it again after N seconds. The pin is released before OpenPwm.
out\lan866x-dncpmon.exe REM listen forever (Ctrl+C to stop)
out\lan866x-dncpmon.exe --timeout 30 REM stop after 30 s without packetsDecodes DNCP packets (Dynamic Node Configuration Protocol) on UDP 65526/65527 — Announce/Registry with MAC, device id, IPv4/IPv6, state (Unconfigured/Configured) and PLCA ids. Standalone (Winsock only), not part of SOME/IP.
Purely passive: only shows DNCP traffic actually present on the bus. To trigger actively, see
lan866x-dncpdisc.
out\lan866x-dncpdisc.exe REM 3 rounds, channel 11
out\lan866x-dncpdisc.exe --channel 11 --rounds 5 --timeout 4Acts as a temporary DNCP server (per AN1891): broadcasts an empty Registry to 224.0.0.1:65527; nodes that do not find themselves in it send an Announce to 224.0.0.1:65526. Per node all Announce fields are decoded: MAC, vendor device id, IPv4 + IPv6, state, persistency, BurstFramesPerTO, protocol version and all PLCA node ids.
Read-only — assigns no PLCA ids/IPs, persists nothing. EnumChannel = default (11). Use only when no other DNCP server is active. Verified live (a LAN8662 responded).
Four further tools cover firmware management, link diagnostics and the Click demo. They are documented in full — with every option and the board setup they need — in TOOLS.md:
| Tool | One-liner | TOOLS.md |
|---|---|---|
lan866x-boot |
reboot between main app ↔ bootloader (non-destructive) | §4.9 |
lan866x-flashimg |
write one signed image via the bootloader (writes flash) | §4.10 |
lan866x-flashpkg |
update an endpoint from an .mchpkg package (writes flash) |
§4.11 |
lan866x-diag |
read & interpret T1S link quality (read-only) | §4.3 |
lan866x-clickdemo |
Thumbstick + Proximity → 2× RGB Click panels (RTP) | §4.12 |
lan866x-video |
loop-play a video file on the 2× RGB displays (ffmpeg → RTP) | §4.13 |
out\lan866x-diag.exe --ip 192.168.0.54
out\lan866x-boot.exe --to bootloader
out\lan866x-flashpkg.exe LAN8661-ws2812_V1.3.2_RELEASE_display1.mchpkg --ip 192.168.0.54
out\lan866x-clickdemo.exe --ip 192.168.0.54
out\lan866x-video.exe docs\img\clickdemo.mp4 --ip 192.168.0.54
lan866x-flashimg/-flashpkgwrite flash (recoverable from the bootloader);lan866x-clickdemoneeds the Click boards seated and the DIP switches set as in TOOLS.md §2.4/§2.5.
The tools do not know the endpoint IPs in advance – they learn them at runtime via SOME/IP Service Discovery (SD):
- Join multicast: the platform stub joins the SD group
224.0.0.1on each PC interface (the "Joined Multicast group" lines at startup). SD runs on UDP port 30490. - Request the service:
rcp_init()callsSOMEIP_Client_AddService(0xFF10, requested=true); the stack sendsFindServiceand also receives the endpoints' periodicOfferService. - Endpoints respond: every endpoint that offers
0xFF10sends anOfferServicecontaining its own IP/port (method endpoint = UDP 6800, e.g.192.168.0.101:6800). The SD event callback (on_event) stores it. - Build the list:
rcp_get_endpoints()returns the collected list. The IP comes from the endpoint, not the tool.
PC --FindService(0xFF10)--> 224.0.0.1:30490 (multicast)
EP1 --OfferService: I am 192.168.0.101:6800 --> PC
EP2 --OfferService: I am 192.168.0.102:6800 --> PC
Target endpoint: default is [0] (first found). Select with --ip <addr> or --ep <index>.
Fast start: the tools poll during discovery and return the moment the requested endpoint answers (an
OfferServicetypically arrives within tens of ms) instead of always burning the full search window. The window (a few seconds) is only an upper bound, hit when the target never replies — then the tool reports "No endpoints found" (nothing offered0xFF10) or "Target endpoint not found" (others answered, not this one).
Multiple PC interfaces: the stub joins on all of them; responses arrive only over the T1S interface (
192.168.0.x). Its NIC must have an IP in the endpoint subnet (chapter 2.4).
lan866x-tools/
├── build.bat Windows build script (chapter 3)
├── CMakeLists.txt C-only build: rcpcore lib + tool executables
├── discovery.c list endpoints + full GetStatus/GetNetworkStatus
├── servicetest.c probe which RCP methods the firmware implements
├── i2cscan.c I2C bus scanner
├── i2cid.c non-blocking I2C device-ID read (VCNL4200 example)
├── proxmon.c non-blocking live proximity monitor (VCNL4200)
├── lan8680.c read the LAN8680 front-end (SBC) over I2C (read-only)
├── gpio.c GPIO set/read
├── ledscan.c interactive GPIO->LED mapper (writes led_map.json)
├── ledblink.c on-board LED running light over SOME/IP ("hello world")
├── ledtoggle.c non-blocking single-LED toggle (async RCP API)
├── gpiomax.c max-speed GPIO toggle benchmark (pipelined async SetGpio)
├── ledpwm.c non-blocking "breathing" LED via PWM
├── proxled.c sensor->actuator app: proximity drives the LEDs
├── spi.c SPI transfer
├── spiid.c non-blocking SPI thumbstick (MCP3204) identify
├── thumbmon.c non-blocking live thumbstick monitor (MCP3204)
├── adc.c ADC read (analog / temperature)
├── pwm.c PWM output
├── boot.c reboot main app ↔ bootloader (non-destructive)
├── flashimg.c write one signed image via the bootloader
├── flashpkg.c update from an MCHPKG package (uses minizip)
├── diag.c T1S link-quality diagnostics
├── clickdemo.c MikroE Click demo (Thumbstick + Proximity → 2× RGB)
├── video.c loop-play a video file on the 2× RGB displays (ffmpeg → RTP)
├── dncpmon.c passive DNCP monitor (standalone, Winsock)
├── dncpdisc.c active DNCP discovery (standalone, Winsock)
├── ntpsync.c software NTP time sync to the bridge firmware (standalone, Winsock)
├── src/
│ ├── rcp.h / rcp.c RCP over libsomeip — typed methods + async API
│ ├── someip_stub.c platform-neutral SOMEIP_CB_* on the plat.h layer
│ ├── plat.h narrow platform interface (time, non-blocking UDP, sleep)
│ ├── plat_win.c Windows (Winsock) implementation of plat.h
│ ├── plat_lwip.c.template starting template for an lwIP/MCU port (not built)
│ └── tool_common.h tiny shared discover-and-select helper
├── include/ lan866x_common.h (RCP request/reply structs, used by rcp.c)
├── libepmicrochip/
│ └── libsomeip/ the C SOME/IP stack (src/*.c)
├── third-party/
│ └── minizip/ bundled ZIP reader (only lan866x-flashpkg uses it)
├── tools/ analysis helpers (plot_timing.py — clickdemo timing diagram)
├── wireshark/ Wireshark add-ons: SOME/IP dissector config + DNCP/RTP Lua + install guide
├── docs/
│ ├── img/ board photos + timing diagrams used by the docs
│ ├── INTEGRATION_NOTES.md RCP-on-libsomeip protocol/stack know-how
│ ├── RCP_API.md full rcp.c API reference (methods, structs, encoding)
│ ├── CLICKDEMO.md clickdemo demo/software/timing deep-dive
│ ├── LEDDEMO.md LED running-light "hello world" + GPIO->LED mapping
│ ├── I2CDEMO.md non-blocking I2C device-ID read + proximity monitor (VCNL4200)
│ ├── LAN8680.md reading the LAN8680 front-end (SBC) over housekeeping I2C
│ ├── DEMOS.md index of all worked examples (source + per-demo docs)
│ ├── SPIDEMO.md non-blocking SPI thumbstick read + monitor (MCP3204)
│ ├── COMBODEMO.md sensor->actuator app (proximity -> LEDs, proxled)
│ ├── PWMDEMO.md "breathing" LED via PWM (ledpwm; firmware-dependent)
│ └── FIRMWARE_TRAINS.md V1.3.2 vs V1.4.0 firmware diff + flash implications
├── README.md
├── TOOLS.md board guide + full per-tool reference
└── PORTING.md MCU32 port (lwIP, single-thread)
libepmicrochip/also still contains Microchip's C++ vendor sources (liblan866x,librtp,someip-stub.cpp). They are not built — this toolset uses only the Clibsomeipcore. They can be deleted for a strictly C-only tree.
The build produces a shared static lib rcpcore (rcp.c + someip_stub.c + plat_win.c + libsomeip/src/*.c) that each SOME/IP tool links; the DNCP tools link only Winsock.
🔎 Protocol analysis in Wireshark: to decode the captured traffic — SOME/IP (RCP
0xFF10) with named fields, plus DNCP and the RTP/RFC4175 video — install the add-ons inwireshark/; see wireshark/README.md.
⏱️ Time sync & bridge-delay timing: the bridge firmware runs a small software NTP service so its high-resolution clock can be disciplined to the PC's wall clock (
lan866x-ntpsync) — this lets firmware events be timestamped on the PC timebase and, with aneth0packet tap, lets you measure the bridge's one-way forwarding delay in both directions (wireshark/bridge_delay.py). Implementation + how the convergence works (PI frequency discipline, with a real run analysed): wireshark/NTP_SYNC.md; usage + the bridge-delay measurement: wireshark/NTP_TIMING.md; the theory: wireshark/NTP_TWO_NODE_CONVERGENCE.md; and the planned multi-node concept (discovery, config, 1:N sync, pin-toggle verification): wireshark/NTP_MULTINODE_SZENARIO.md.
(example configuration of a control endpoint with 1× UART / I2C / SPI each + GPIOs)
| Function | SERCOM | Pins |
|---|---|---|
| UART | SER0 | TX = PA00, RX = PA03 |
| GPIO out | – | PA02, PA06 |
| I2C | SER1 | SDA = PA04, SCL = PA05 |
| SPI | SER2 | SDI = PA08, SCK = PA09, CS_N = PA10, SDO = PA11 |
Service 0xFF10. Verified against the authoritative Microchip SOME/IP dissector table (Wireshark SOMEIP_method_event_identifiers). Each request is encoded as Fill_Header + one Fill_<field> per parameter (tag data id 0,1,2,…) + Update_Length; replies are parsed field-by-field — exactly as the C++ LAN866XClientImpl.
| Method | ID | Method | ID | |
|---|---|---|---|---|
| Reboot | 0x1000 |
OpenSpi | 0x1500 |
|
| GetStatus | 0x1002 |
CloseSpi | 0x1502 |
|
| GetNetworkStatus | 0x1600 |
WriteAndReadSpi | 0x1508 |
|
| WakeupNetwork | 0x1601 |
OpenUart | 0x1400 |
|
| ReleaseDigitalPins | 0x1105 |
WriteUart | 0x1404 |
|
| OpenGpio | 0x1300 |
ReadUart | 0x1420 |
|
| SetGpio | 0x1330 |
OpenAdc | 0x1700 |
|
| GetGpio | 0x1332 |
ReadAdc | 0x1720 |
|
| OpenI2C | 0x1200 |
OpenPwm | 0x1800 |
|
| WriteI2C | 0x1204 |
WritePwm | 0x1804 |
|
| ReadI2C | 0x1220 |
OnGpioEvents (evt) | 0x8000 |
|
| WriteAndReadI2C | 0x1208 |
OnUartReceive (evt) | 0x8010 |
Note: the Library Integration Manual prose lists
OpenI2C = 0x0100— that is a typo; the dissector table (and the live wire) use0x1200. Always trust the dissector CSV /lan866x_common.hover the prose.
📖 Per-function reference: every
rcp_*call — its method ID, request/reply struct, field semantics and the WTLV encoding rules — is documented in docs/RCP_API.md (the reference for writing your own client).
The toolset is single-thread and vanilla C on libsomeip, so the embedded port is small: you write one file, src/plat_<target>.c, implementing the six functions of the narrow src/plat.h layer — a millisecond clock, non-blocking UDP (open/send/poll-receive + multicast join + interface enumeration), and sleep/yield. Everything else stays unchanged: the tools, rcp.c/rcp.h, the platform-neutral SOME/IP stub src/someip_stub.c, and the SOME/IP core.
What stays / what you write:
| Layer | Windows | MCU |
|---|---|---|
Tools + rcp.c (RCP encode/decode) |
C | same |
SOME/IP core (libsomeip/src/*.c) |
C | same |
SOME/IP stub (SOMEIP_CB_*) |
src/someip_stub.c |
same |
Platform layer (plat.h) |
src/plat_win.c (Winsock) |
src/plat_<target>.c (lwIP) |
Time base (plat_now_ms) |
GetTickCount() |
sys_now() / xTaskGetTickCount() |
| T1S link | USB-Ethernet bridge | LAN8650/51 MAC-PHY (OA-SPI) or LAN8670 PHY (RMII) + lwIP |
Received UDP is dispatched synchronously from plat_udp_poll(), so no RTOS is required (a plain superloop works) and no locks are needed. someip-cfg.h is sized MCU-friendly (core static RAM ≈ 15 kB). A ready-to-fill starting point is in src/plat_lwip.c.template.
➡️ Details: PORTING.md.
This port is not just theory — there is a complete, running implementation in
firmware/t1s_100baset_bridge/. It runs the whole
toolset on an ATSAME54P20A over the MPLAB Harmony 3 TCP/IP stack: the one
platform file is plat_h3tcpip.c
(the six plat.h functions over TCPIP_UDP_*), while rcp.c, someip_stub.c and
libsomeip are byte-for-byte the same as on the host. On top of the port it is a
10BASE-T1S ↔ 100BASE-T Layer-2 bridge (PLCA coordinator), so a PC on Fast
Ethernet can reach a LAN866x endpoint on the T1S bus, and it exposes the host
tools (discovery, diag, ledblink, clickdemo) as on-board serial commands
plus a Wireshark SPAN port for the T1S bus.
➡️ Full firmware documentation — purpose, hardware (with order numbers), build & flash, configuration, and the SOME/IP commands — is in its own firmware/t1s_100baset_bridge/README.md.