---
title: "How to Use socket.c APIs with WIZnet W5500 on MCU Platforms?"
url: "https://maker.wiznet.io/ronpang/projects/how-to-use-socket-c-apis-with-wiznet-w5500-on-mcu-platforms/"
markdown_url: "https://maker.wiznet.io/ronpang/projects/how-to-use-socket-c-apis-with-wiznet-w5500-on-mcu-platforms/md"
type: "UCC: User Created Content"
author: "LaoZhangGong123"
author_url: "https://blog.csdn.net/weixin_42550185/article/details/150273475?spm=1001.2014.3001.5502"
editor: "WIZnet"
editor_url: "https://maker.wiznet.io/"
original_author: "LaoZhangGong123"
original_url: "https://blog.csdn.net/weixin_42550185/article/details/150273475?spm=1001.2014.3001.5502"
published: "2026-05-29"
language: "en"
likes: 0
views: 346
comments: 0
source: "WIZnet Makers (https://maker.wiznet.io/)"
---

# How to Use socket.c APIs with WIZnet W5500 on MCU Platforms?

> This education-focused project explains how WIZnet W5500 socket APIs work inside socket.c. The MCU uses SPI-accessible W5500 socket registers through functions

Original author: LaoZhangGong123 (source: https://blog.csdn.net/weixin_42550185/article/details/150273475?spm=1001.2014.3001.5502)

## Article

## How to Use socket.c APIs with WIZnet W5500 on MCU Platforms?

### Summary

This education-focused project explains how WIZnet W5500 socket APIs work inside `socket.c`. The MCU uses SPI-accessible W5500 socket registers through functions such as `socket()`, `listen()`, `connect()`, `send()`, `recv()`, `sendto()`, and `recvfrom()`. W5500’s role is to provide the wired Ethernet MAC/PHY, hardwired TCP/IP stack, socket state machine, and internal packet buffers, while the firmware learns network-stack behavior through a compact socket API.

### What the Project Does

The source article is a function-level walkthrough of W5500 `socket.c`, not a single application demo. It explains internal variables such as `sock_io_mode`, `sock_is_sending`, and `sock_remained_size`, then walks through macros and APIs that validate socket numbers, check socket mode, open sockets, close sockets, listen as a TCP server, connect as a TCP client, transmit and receive TCP data, and handle UDP/IPRAW/MACRAW datagrams.

The network-stack path starts with `socket()`. The article shows that W5500 socket protocol selection is done through the low bits of `Sn_MR`: TCP uses `Sn_MR_TCP`, UDP uses `Sn_MR_UDP`, IPRAW uses `Sn_MR_IPRAW`, and MACRAW uses `Sn_MR_MACRAW`. The same function writes the source port, issues the `OPEN` command through `Sn_CR`, waits for the command register to clear, and then checks the socket status register.

For education, this is useful because it exposes the layer between high-level examples and W5500 registers. A TCP server is not just “call listen”; it requires TCP mode, `SOCK_INIT`, a `LISTEN` command, and a transition to `SOCK_LISTEN`. A UDP receiver is not just “read data”; it must read W5500’s packet header, extract sender IP, sender port, and payload length, then issue `RECV` after consuming buffer data.

### Where WIZnet Fits

The exact WIZnet product is **W5500**. W5500 is the wired Ethernet controller and hardware TCP/IP engine between an external MCU and the LAN. WIZnet documents W5500 as a hardwired TCP/IP controller with SPI access up to 80 MHz, embedded 10/100 Ethernet MAC and PHY, TCP/UDP/IPv4 support, 8 independent sockets, and 32 KB internal memory for Tx/Rx buffers.

In this architecture, the MCU does not run the full TCP/IP stack in firmware. The MCU calls socket-layer functions, and those functions manipulate W5500 registers such as `Sn_MR`, `Sn_PORT`, `Sn_DIPR`, `Sn_DPORT`, `Sn_CR`, `Sn_SR`, `Sn_IR`, `Sn_TX_FSR`, and `Sn_RX_RSR`. W5500 handles socket state, packet buffering, and Ethernet-side TCP/IP behavior.

This makes the article a good bridge between register education and practical networking. Students can see how `socket.c` converts application intent into W5500 socket operations: TCP server listen, TCP client connect, TCP send/receive, UDP send/receive, timeout handling, nonblocking behavior, and remaining-packet tracking.

### Implementation Notes

**File: **`**Ethernet/socket.c**`
**What it configures:** socket protocol mode, source port, `OPEN` command, and internal socket bookkeeping.
**Why it matters:** this is the entry point that turns a socket number into a TCP, UDP, IPRAW, or MACRAW channel.

```plaintext
close(sn);
setSn_MR(sn, (protocol | (flag & 0xF0)));
setSn_PORT(sn, port);
setSn_CR(sn, Sn_CR_OPEN);

while(getSn_CR(sn));

sock_is_sending &= ~(1 << sn);
sock_remained_size[sn] = 0;
sock_pack_info[sn] = PACK_COMPLETED;
```

This code exists because W5500 sockets are hardware resources. The firmware must close any previous socket state, write the socket mode register, set the local port, issue the `OPEN` command, and reset software-side tracking before the socket can be used safely. The article explains the same sequence in its `socket()` function walkthrough.

**File: **`**Ethernet/socket.c**`
**What it configures:** TCP server listen flow.
**Why it matters:** TCP listening requires a valid TCP socket already in `SOCK_INIT`; otherwise the server cannot accept a connection.

```plaintext
CHECK_SOCKMODE(Sn_MR_TCP);
CHECK_SOCKINIT();

setSn_CR(sn, Sn_CR_LISTEN);
while(getSn_CR(sn));

while(getSn_SR(sn) != SOCK_LISTEN)
{
    close(sn);
    return SOCKERR_SOCKCLOSED;
}
```

This code exists to enforce the correct TCP server state transition. The function checks that the socket is in TCP mode, checks that it is initialized, issues `LISTEN`, then verifies that the W5500 status register reaches `SOCK_LISTEN`.

**File: **`**Ethernet/socket.c**`
**What it configures:** UDP/IPRAW/MACRAW receive behavior.
**Why it matters:** datagram receive is different from TCP receive because the firmware must recover sender metadata and track remaining packet length.

```plaintext
pack_len = getSn_RX_RSR(sn);

if(getSn_SR(sn) == SOCK_CLOSED)
    return SOCKERR_SOCKCLOSED;

wiz_recv_data(sn, head, 8);
setSn_CR(sn, Sn_CR_RECV);

addr[0] = head[0];
addr[1] = head[1];
addr[2] = head[2];
addr[3] = head[3];
*port = (head[4] << 8) + head[5];
```

This code exists because UDP receive data includes a W5500-provided header before the payload. The firmware reads that header, extracts sender IP and port, calculates remaining payload length, then reads the payload and issues `RECV` to release the consumed data.

### Practical Tips / Pitfalls

- Check the socket number before every operation. W5500 has 8 sockets, so invalid socket IDs should fail before touching registers.

- Do not call `listen()` before `socket()` has opened a TCP socket. The code requires TCP mode and `SOCK_INIT`.

- For TCP `send()`, verify that the socket is `SOCK_ESTABLISHED` or `SOCK_CLOSE_WAIT`, and respect `Sn_TX_FSR` so unsent data is not overwritten.

- For TCP `recv()`, read only within the configured receive-buffer size and issue `Sn_CR_RECV` after copying data.

- For UDP `recvfrom()`, parse the header first; sender IP, sender port, and packet length are not optional details.

- Clear interrupt flags intentionally. `close()` clears socket interrupt bits with `setSn_IR(sn, 0xFF)`, which prevents stale events from affecting the next socket use.

### FAQ

**Q: Why use WIZnet W5500 for teaching socket APIs?**
A: W5500 exposes a clear hardware-socket model. Students can connect API calls such as `socket()`, `listen()`, `connect()`, `send()`, and `recvfrom()` to hardware registers such as `Sn_MR`, `Sn_CR`, `Sn_SR`, `Sn_IR`, and buffer-size registers. The chip also provides hardwired TCP/IP, 8 sockets, and internal buffers, so students can study network behavior without first porting a full software TCP/IP stack.

**Q: How does W5500 connect to the MCU platform?**
A: W5500 connects to an external MCU through SPI. The MCU provides SPI read/write and chip-select control, while W5500 provides the Ethernet MAC/PHY, socket registers, and internal Tx/Rx buffers. A complete teaching board should also expose reset and interrupt pins so students can observe recovery and socket events.

**Q: What role does W5500 play in this **`**socket.c**`** project?**
A: W5500 is the hardware socket engine being controlled by `socket.c`. The C functions validate parameters, write W5500 registers, issue socket commands, check status, move data into or out of W5500 buffers, and report socket errors back to the application.

**Q: Can beginners follow this education project?**
A: Yes, if they already understand basic C, SPI, IPv4 addresses, ports, and the difference between TCP and UDP. It is lower-level than an HTTP or MQTT example, but it is a good way to learn why those examples work.

**Q: How does W5500 compare with LwIP and ENC28J60 for education?**
A: W5500 teaches hardware-offloaded socket behavior: the TCP/IP engine, sockets, and packet buffers are inside the Ethernet controller. LwIP teaches software-stack behavior; it is a small independent TCP/IP implementation designed to reduce RAM usage while still providing full TCP support on embedded systems. ENC28J60 is a 10Base-T Ethernet controller with SPI interface, so the MCU typically handles more of the TCP/IP stack than it would with W5500.

### Source

Original article: CSDN, “W5500之‘socket.c’中的相关函数,” first published on 2025-08-12 and updated on 2025-08-13. The article is marked CC 4.0 BY-SA.

WIZnet product reference: W5500 documentation and ioLibrary Driver information.

Alternative references for comparison: lwIP overview and Microchip ENC28J60 product information.

### Tags

#W5500 #WIZnet #SocketAPI #socketc #MCU #SPI #Education #NetworkStack #TCP #UDP #IPRAW #MACRAW #ioLibrary #LwIP #ENC28J60

## MCU 플랫폼에서 WIZnet W5500의 socket.c API를 사용하는 방법은?

### 요약

이 교육용 프로젝트는 WIZnet W5500의 `socket.c` 내부 소켓 API가 어떻게 동작하는지 설명합니다. MCU는 `socket()`, `listen()`, `connect()`, `send()`, `recv()`, `sendto()`, `recvfrom()` 같은 함수를 통해 SPI로 접근 가능한 W5500 소켓 레지스터를 사용합니다. W5500은 유선 Ethernet MAC/PHY, 하드웨어 TCP/IP 스택, 소켓 상태 머신, 내부 패킷 버퍼를 제공하고, 펌웨어는 간결한 소켓 API를 통해 네트워크 스택 동작을 학습합니다.

### 프로젝트가 하는 일

원문은 단일 애플리케이션 데모가 아니라 W5500 `socket.c`의 함수 단위 해설입니다. `sock_io_mode`, `sock_is_sending`, `sock_remained_size` 같은 내부 변수부터 시작해, 소켓 번호 검증, 소켓 모드 확인, 소켓 열기, 소켓 닫기, TCP 서버 listen, TCP 클라이언트 connect, TCP 데이터 송수신, UDP/IPRAW/MACRAW 데이터그램 처리를 설명합니다.

네트워크 스택 흐름은 `socket()`에서 시작합니다. 원문은 W5500의 소켓 프로토콜 선택이 `Sn_MR`의 하위 비트로 수행된다고 설명합니다. TCP는 `Sn_MR_TCP`, UDP는 `Sn_MR_UDP`, IPRAW는 `Sn_MR_IPRAW`, MACRAW는 `Sn_MR_MACRAW`를 사용합니다. 같은 함수에서 source port를 기록하고, `Sn_CR`을 통해 `OPEN` 명령을 실행하며, command register가 clear될 때까지 기다린 뒤 socket status register를 확인합니다.

교육 관점에서 이 자료는 고수준 예제와 W5500 레지스터 사이의 중간 계층을 보여준다는 점에서 유용합니다. TCP 서버는 단순히 `listen()`을 호출하는 것이 아니라 TCP 모드, `SOCK_INIT`, `LISTEN` 명령, `SOCK_LISTEN` 상태 전이가 필요합니다. UDP 수신도 단순히 데이터를 읽는 것이 아니라 W5500의 packet header를 읽고, sender IP, sender port, payload length를 추출한 뒤, buffer 데이터를 소비하고 `RECV`를 실행해야 합니다.

### WIZnet이 들어가는 위치

이 프로젝트에서 사용되는 WIZnet 제품은 **W5500**입니다. W5500은 외부 MCU와 LAN 사이에 위치하는 유선 이더넷 컨트롤러이자 하드웨어 TCP/IP 엔진입니다. WIZnet 문서 기준으로 W5500은 최대 80 MHz SPI 접근, 내장 10/100 Ethernet MAC 및 PHY, TCP/UDP/IPv4 지원, 8개 독립 소켓, 32 KB 내부 Tx/Rx 버퍼 메모리를 제공하는 하드웨어 TCP/IP 컨트롤러입니다.

이 구조에서 MCU는 전체 TCP/IP 스택을 펌웨어에서 직접 실행하지 않습니다. MCU는 소켓 계층 함수를 호출하고, 이 함수들은 `Sn_MR`, `Sn_PORT`, `Sn_DIPR`, `Sn_DPORT`, `Sn_CR`, `Sn_SR`, `Sn_IR`, `Sn_TX_FSR`, `Sn_RX_RSR` 같은 W5500 레지스터를 조작합니다. W5500은 소켓 상태, 패킷 버퍼링, Ethernet 측 TCP/IP 동작을 담당합니다.

따라서 이 자료는 레지스터 학습과 실제 네트워크 프로그래밍 사이를 연결하는 좋은 예제입니다. 학생들은 `socket.c`가 애플리케이션의 의도를 W5500 소켓 동작으로 바꾸는 과정을 볼 수 있습니다. 여기에는 TCP 서버 listen, TCP 클라이언트 connect, TCP send/receive, UDP send/receive, timeout 처리, nonblocking 동작, remaining-packet tracking이 포함됩니다.

### 구현 참고 사항

**파일: **`**Ethernet/socket.c**`
**설정 내용:** 소켓 프로토콜 모드, source port, `OPEN` 명령, 내부 소켓 상태 추적
**중요한 이유:** 이 함수는 소켓 번호를 TCP, UDP, IPRAW, MACRAW 채널로 전환하는 진입점입니다.

```plaintext
close(sn);
setSn_MR(sn, (protocol | (flag & 0xF0)));
setSn_PORT(sn, port);
setSn_CR(sn, Sn_CR_OPEN);

while(getSn_CR(sn));

sock_is_sending &= ~(1 << sn);
sock_remained_size[sn] = 0;
sock_pack_info[sn] = PACK_COMPLETED;
```

이 코드는 W5500 소켓이 하드웨어 자원이기 때문에 필요합니다. 펌웨어는 이전 소켓 상태를 닫고, socket mode register를 쓰고, local port를 설정하고, `OPEN` 명령을 실행한 뒤, 소프트웨어 측 추적 상태를 초기화해야 소켓을 안전하게 사용할 수 있습니다. 원문도 `socket()` 함수 설명에서 같은 순서를 다룹니다.

**파일: **`**Ethernet/socket.c**`
**설정 내용:** TCP 서버 listen 흐름
**중요한 이유:** TCP listen은 이미 `SOCK_INIT` 상태에 있는 유효한 TCP 소켓이 있어야 가능합니다. 그렇지 않으면 서버는 연결을 받을 수 없습니다.

```plaintext
CHECK_SOCKMODE(Sn_MR_TCP);
CHECK_SOCKINIT();

setSn_CR(sn, Sn_CR_LISTEN);
while(getSn_CR(sn));

while(getSn_SR(sn) != SOCK_LISTEN)
{
    close(sn);
    return SOCKERR_SOCKCLOSED;
}
```

이 코드는 올바른 TCP 서버 상태 전이를 강제하기 위해 존재합니다. 함수는 소켓이 TCP 모드인지 확인하고, 초기화 상태인지 확인한 뒤, `LISTEN` 명령을 실행합니다. 이후 W5500 상태 레지스터가 `SOCK_LISTEN`에 도달했는지 검증합니다.

**파일: **`**Ethernet/socket.c**`
**설정 내용:** UDP/IPRAW/MACRAW 수신 동작
**중요한 이유:** 데이터그램 수신은 TCP 수신과 다릅니다. 펌웨어는 sender metadata를 복구하고, 남은 packet length를 추적해야 합니다.

```plaintext
pack_len = getSn_RX_RSR(sn);

if(getSn_SR(sn) == SOCK_CLOSED)
    return SOCKERR_SOCKCLOSED;

wiz_recv_data(sn, head, 8);
setSn_CR(sn, Sn_CR_RECV);

addr[0] = head[0];
addr[1] = head[1];
addr[2] = head[2];
addr[3] = head[3];
*port = (head[4] << 8) + head[5];
```

이 코드는 UDP 수신 데이터에 payload 앞의 W5500-provided header가 포함되기 때문에 필요합니다. 펌웨어는 이 header를 읽고 sender IP와 port를 추출하며, 남은 payload length를 계산합니다. 이후 payload를 읽고 `RECV` 명령을 실행해 소비한 데이터를 해제합니다.

### 실무 팁 / 주의점

- 모든 동작 전에 소켓 번호를 확인해야 합니다. W5500은 8개 소켓을 제공하므로, 잘못된 socket ID는 레지스터 접근 전에 실패 처리해야 합니다.

- TCP 소켓이 `socket()`으로 열린 뒤 `SOCK_INIT` 상태가 되기 전에 `listen()`을 호출하면 안 됩니다.

- TCP `send()`에서는 소켓이 `SOCK_ESTABLISHED` 또는 `SOCK_CLOSE_WAIT` 상태인지 확인하고, `Sn_TX_FSR`을 준수해야 아직 전송되지 않은 데이터를 덮어쓰지 않습니다.

- TCP `recv()`에서는 설정된 receive-buffer 크기 안에서만 읽고, 데이터를 복사한 뒤 `Sn_CR_RECV`를 실행해야 합니다.

- UDP `recvfrom()`에서는 header를 먼저 파싱해야 합니다. sender IP, sender port, packet length는 생략 가능한 정보가 아닙니다.

- Interrupt flag는 의도적으로 clear해야 합니다. `close()`는 `setSn_IR(sn, 0xFF)`로 socket interrupt bit를 clear해 다음 소켓 사용에 stale event가 영향을 주지 않도록 합니다.

### FAQ

**Q: 소켓 API 교육에 왜 WIZnet W5500을 사용하나요?**
A: W5500은 hardware-socket model을 명확하게 보여줍니다. 학생들은 `socket()`, `listen()`, `connect()`, `send()`, `recvfrom()` 같은 API 호출이 `Sn_MR`, `Sn_CR`, `Sn_SR`, `Sn_IR`, buffer-size register 같은 하드웨어 레지스터와 어떻게 연결되는지 볼 수 있습니다. 또한 W5500은 하드웨어 TCP/IP, 8개 소켓, 내부 버퍼를 제공하므로 전체 소프트웨어 TCP/IP 스택을 먼저 포팅하지 않고도 네트워크 동작을 학습할 수 있습니다.

**Q: W5500은 MCU 플랫폼에 어떻게 연결하나요?**
A: W5500은 SPI를 통해 외부 MCU에 연결됩니다. MCU는 SPI read/write와 chip-select control을 제공하고, W5500은 Ethernet MAC/PHY, socket register, 내부 Tx/Rx buffer를 제공합니다. 완전한 교육용 보드라면 reset과 interrupt pin도 노출해 복구 동작과 socket event를 관찰할 수 있게 하는 것이 좋습니다.

**Q: 이 **`**socket.c**`** 프로젝트에서 W5500은 어떤 역할을 하나요?**
A: W5500은 `socket.c`가 제어하는 hardware socket engine입니다. C 함수들은 parameter를 검증하고, W5500 register를 쓰고, socket command를 실행하고, status를 확인하고, W5500 buffer로 데이터를 넣거나 꺼내며, socket error를 애플리케이션에 반환합니다.

**Q: 초보자도 이 교육용 프로젝트를 따라갈 수 있나요?**
A: basic C, SPI, IPv4 address, port, TCP와 UDP의 차이를 이해하고 있다면 따라갈 수 있습니다. HTTP나 MQTT 예제보다 낮은 계층을 다루지만, 그런 예제가 왜 동작하는지 배우기 좋은 자료입니다.

**Q: W5500은 교육 관점에서 LwIP 및 ENC28J60과 어떻게 다른가요?**
A: W5500은 hardware-offloaded socket behavior를 가르칩니다. TCP/IP engine, socket, packet buffer가 Ethernet controller 내부에 있습니다. LwIP는 software-stack behavior를 가르치며, 임베디드 시스템에서 RAM 사용량을 줄이면서 full TCP support를 제공하도록 설계된 작은 독립 TCP/IP 구현입니다. ENC28J60은 SPI interface를 가진 10Base-T Ethernet controller이므로, MCU가 W5500을 사용할 때보다 TCP/IP stack을 더 많이 담당하는 구조가 일반적입니다.

### 출처

Original article: CSDN, “W5500之‘socket.c’中的相关函数,” 2025-08-12 게시, 2025-08-13 업데이트, CC 4.0 BY-SA로 표시됨.
[https://blog.csdn.net/weixin_42550185/article/details/150273475?spm=1001.2014.3001.5502](https://blog.csdn.net/weixin_42550185/article/details/150273475?spm=1001.2014.3001.5502&utm_source=chatgpt.com)

WIZnet product reference: W5500 documentation and ioLibrary Driver information.
[https://docs.wiznet.io/Product/Chip/Ethernet/W5500](https://docs.wiznet.io/Product/Chip/Ethernet/W5500?utm_source=chatgpt.com)

Alternative references for comparison: lwIP overview and Microchip ENC28J60 product information.
[https://www.nongnu.org/lwip/2_1_x/index.html](https://www.nongnu.org/lwip/2_1_x/index.html?utm_source=chatgpt.com)

### 태그

#W5500 #WIZnet #SocketAPI #socketc #MCU #SPI #Education #NetworkStack #TCP #UDP #IPRAW #MACRAW #ioLibrary #LwIP #ENC28J60

---

Source: https://maker.wiznet.io/ronpang/projects/how-to-use-socket-c-apis-with-wiznet-w5500-on-mcu-platforms/
