Skip to content

Embedded Web Server from Scratch on W5500-EVB-Pico

Hand-built embedded web server on W5500-EVB-Pico (RP2040 + W5500) in C, serving a personal blog from scratch. No frameworks, no OS.

irina

Published May 07, 2026

Original author: UltraVioletWitchOriginal source (new tab)

Embedded Web Server from Scratch on W5500-EVB-Pico

Project description

πŸ“Œ κ°œμš”

이 ν”„λ‘œμ νŠΈλŠ” WIZnet W5500-EVB-Pico λ³΄λ“œ(RP2040 + W5500 톡합)μ—μ„œ HTTP둜 개인 λΈ”λ‘œκ·Έλ₯Ό ν˜ΈμŠ€νŒ…ν•˜λŠ” μ²˜μŒλΆ€ν„° 직접 κ΅¬ν˜„ν•œ μž„λ² λ””λ“œ μ›Ήμ„œλ²„μž…λ‹ˆλ‹€. μ›Ή ν”„λ ˆμž„μ›Œν¬, RTOS, μ™ΈλΆ€ λ„€νŠΈμ›Œν¬ 라이브러리(lwIP, Mongoose λ“±) 없이 Cμ–Έμ–΄(C11)만으둜 μž‘μ„±λœ 포트폴리였 ν”„λ‘œμ νŠΈλ‘œ, μž„λ² λ””λ“œ ν•˜λ“œμ›¨μ–΄μ—μ„œ μ†ŒμΌ“ μˆ˜μ€€μ˜ λ„€νŠΈμ›Œν¬ ν”„λ‘œκ·Έλž˜λ°μ— λŒ€ν•œ κΉŠμ€ 이해λ₯Ό μ‹€μ¦ν•©λ‹ˆλ‹€.

"Embedded Web Server from Scratch" = μž„λ² λ””λ“œ μ›Ήμ„œλ²„λ₯Ό 아무 λΌμ΄λΈŒλŸ¬λ¦¬λ„ μ“°μ§€ μ•Šκ³  λ°‘λ°”λ‹₯λΆ€ν„° 직접 λ§Œλ“€μ—ˆλ‹€"

W5500-EVB-PicoλŠ” 이 ν”„λ‘œμ νŠΈμ— 졜적의 ν”Œλž«νΌμž…λ‹ˆλ‹€. RP2040 λ§ˆμ΄ν¬λ‘œμ»¨νŠΈλ‘€λŸ¬μ™€ WIZnet W5500 이더넷 μ»¨νŠΈλ‘€λŸ¬κ°€ ν•˜λ‚˜μ˜ λ³΄λ“œμ— ν†΅ν•©λ˜μ–΄ μžˆμ–΄, λ³„λ„μ˜ 이더넷 λͺ¨λ“ˆ λ°°μ„  없이 μ»΄νŒ©νŠΈν•œ νΌνŒ©ν„°λ§ŒμœΌλ‘œ μ™„μ „ν•œ μœ μ„  HTTP μ„œλ²„λ₯Ό κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

πŸ“Œ μ‹œμŠ€ν…œ μ•„ν‚€ν…μ²˜

W5500-EVB-Pico 기반 μ›Ήμ„œλ²„ 전체 μ•„ν‚€ν…μ²˜
W5500-EVB-Pico 기반 μ›Ήμ„œλ²„ 전체 μ•„ν‚€ν…μ²˜

 

πŸ“Œ μ£Όμš” κΈ°λŠ₯

  • W5500 TCP μ†ŒμΌ“μ„ μ‚¬μš©ν•΄ HTTP/1.1 μ„œλ²„ μ²˜μŒλΆ€ν„° 직접 κ΅¬ν˜„
  • μˆ˜μ‹ λœ HTTP GET μš”μ²­μ„ νŒŒμ‹±ν•˜κ³  HTML λΈ”λ‘œκ·Έ μ½˜ν…μΈ  μ„œλΉ™
  • W5500의 8개 ν•˜λ“œμ›¨μ–΄ μ†ŒμΌ“μœΌλ‘œ λ‹€μˆ˜μ˜ ν΄λΌμ΄μ–ΈνŠΈ λ™μ‹œ μ—°κ²° 처리
  • RP2040 λ² μ–΄λ©”νƒˆ μ‹€ν–‰ (OS, FreeRTOS μ—†μŒ)
  • 마이크둜컨트둀러 ν”Œλž˜μ‹œμ— 직접 λΈ”λ‘œκ·Έ μ½˜ν…μΈ λ₯Ό μ €μž₯ν•΄ μ„œλΉ™
  • LittleFS νŒŒμΌμ‹œμŠ€ν…œμœΌλ‘œ RP2040 λ‚΄μž₯ Flash 관리
  • USB μ‹œλ¦¬μ–Ό 디버그 지원 (pico_enable_stdio_usb)

πŸ“Œ μ™œ μ²˜μŒλΆ€ν„° 직접 κ΅¬ν˜„ν–ˆλ‚˜?

이 ν”„λ‘œμ νŠΈλŠ” ν•™μŠ΅ μ€‘μ‹¬μ˜ 포트폴리였 μž‘ν’ˆμž…λ‹ˆλ‹€. lwIPλ‚˜ Mongoose 같은 라이브러리λ₯Ό μ‚¬μš©ν•˜λŠ” λŒ€μ‹  TCP μ„œλ²„, HTTP νŒŒμ„œ, 응닡 생성기λ₯Ό 직접 κ΅¬ν˜„ν•¨μœΌλ‘œμ¨ μ†ŒμΌ“ ν”„λ‘œκ·Έλž˜λ°, HTTP ν”„λ‘œν† μ½œ ꡬ쑰, μž„λ² λ””λ“œ C κ°œλ°œμ— λŒ€ν•œ μ² μ €ν•œ 이해λ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€.

μ‹€μ œ κ΅¬ν˜„λœ 핡심 μš”μ†Œ:

μš”μ†Œλ‚΄μš©
HTTP λ©”μ„œλ“œ νŒŒμ„œGET POST HEAD PUT DELETE OPTIONS TRACE CONNECT 8κ°€μ§€
HTTP 헀더 νŒŒμ„œAccept Content-Type Content-Length λ“± 47개 헀더 νƒ€μž…
μƒνƒœ μ½”λ“œ200 OK 404 Not Found λ“± 40개 reason phrase 직접 μ •μ˜
μ»€μŠ€ν…€ W5500 λ“œλΌμ΄λ²„lib/W5500/에 SPI λ ˆμ§€μŠ€ν„° μˆ˜μ€€ λ“œλΌμ΄λ²„ 직접 μž‘μ„±
HTTP ꡬ쑰체http_request http_response request_line status_line http_header http_body
λΌμš°ν„°respondHTTP() β€” URI 기반 μ½˜ν…μΈ  λΌμš°νŒ…

πŸ“Œ Hardware

ν•­λͺ©λ‚΄μš©
λ³΄λ“œWIZnet W5500-EVB-Pico (RP2040 + W5500 λ³΄λ“œ λ‚΄μž₯)
이더넷RJ45 포트 λ³΄λ“œ 직결 β€” 별도 이더넷 λͺ¨λ“ˆ λΆˆν•„μš”
μ–Έμ–΄C (C11 ν‘œμ€€)
ν”„λ ˆμž„μ›Œν¬Raspberry Pi Pico SDK 2.2.0+ (λ² μ–΄λ©”νƒˆ)
λΉŒλ“œCMake 3.12+
νŒŒμΌμ‹œμŠ€ν…œLittleFS (RP2040 λ‚΄μž₯ Flash)
디버그USB μ‹œλ¦¬μ–Ό (UART λΉ„ν™œμ„±ν™”)

πŸ“Œ HTTP 처리 흐름

πŸ“Œ HTTP 처리 흐름
HTTP μš”μ²­ 처리 흐름도 β€” parseHTTP β†’ respondHTTP β†’ sendResponse

 

πŸ“Œ μ†ŒμŠ€ ꡬ쑰
 

EmbeddedWebServer/
β”œβ”€β”€ main.c          # HTTP νŒŒμ„œ, 응닡 생성, 메인 루프
β”œβ”€β”€ web_files.h     # HTML/CSS ν”Œλž˜μ‹œ μž„λ² λ”© 헀더
β”œβ”€β”€ CMakeLists.txt  # CMake λΉŒλ“œ μ„€μ • (Pico SDK 2.2.0+)
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ W5500/      # μ»€μŠ€ν…€ W5500 SPI λ“œλΌμ΄λ²„
β”‚   └── littlefs/   # LittleFS νŒŒμΌμ‹œμŠ€ν…œ 라이브러리
└── webFiles/       # λΈ”λ‘œκ·Έ HTML/CSS μ†ŒμŠ€ 파일

링크 라이브러리: pico_stdlib · hardware_spi · lfs · W5500

핡심 ꡬ쑰체 (main.c)

struct http_request {
    struct request_line rq_line;  // λ©”μ„œλ“œ, URI, HTTP 버전
    struct http_header headers[32]; // μ΅œλŒ€ 32개 헀더
    uint8_t header_cnt;
    struct http_body body;
};

struct http_response {
    struct status_line stat_line; // μƒνƒœ μ½”λ“œ, reason phrase
    struct http_header headers[32];
    uint8_t header_cnt;
    struct http_body body;
};

πŸ“Œ μ†ŒμŠ€ ꡬ쑰 λ‹€μ΄μ–΄κ·Έλž¨

μ†ŒμŠ€ ꡬ쑰 및 CMake λΉŒλ“œ ꡬ성 λ‹€μ΄μ–΄κ·Έλž¨]
μ†ŒμŠ€ ꡬ쑰 및 CMake λΉŒλ“œ ꡬ성 λ‹€μ΄μ–΄κ·Έλž¨]

λΉŒλ“œ 및 ν”Œλž˜μ‹œ

μš”κ΅¬μ‚¬ν•­:

  • Raspberry Pi Pico SDK 2.2.0 이상
  • CMake 3.12+
  • ARM GCC 툴체인
  • PICO_SDK_PATH ν™˜κ²½λ³€μˆ˜ μ„€μ •
# 1. μ €μž₯μ†Œ 클둠
git clone https://github.com/UltraVioletWitch/EmbeddedWebServer

# 2. λΉŒλ“œ 디렉토리 생성
mkdir build && cd build

# 3. CMake ꡬ성
cmake ..

# 4. λΉŒλ“œ
make -j4

# 5. ν”Œλž˜μ‹œ
# BOOTSEL λ²„νŠΌμ„ λˆ„λ₯Έ 채 USB μ—°κ²° β†’ webServer.uf2λ₯Ό λ“œλΌμ΄λΈŒμ— 볡사
cp webServer.uf2 /media/RPI-RP2/

접속 방법:

  1. W5500-EVB-Picoλ₯Ό RJ45 μΌ€μ΄λΈ”λ‘œ λ„€νŠΈμ›Œν¬μ— μ—°κ²°
  2. USB μ‹œλ¦¬μ–Ό λͺ¨λ‹ˆν„°μ—μ„œ ν• λ‹Ήλœ IP μ£Όμ†Œ 확인
  3. λΈŒλΌμš°μ €μ—μ„œ http://<ν• λ‹Ήλœ IP>/ 접속

πŸ“Œ WIZnet W5500 칩의 μ—­ν• 

μ‚¬μš© μΉ© λͺ¨λΈλͺ…: W5500 (W5500-EVB-Pico에 톡합)

이 ν”„λ‘œμ νŠΈμ—μ„œ W5500은 λ‹¨μˆœν•œ 이더넷 컨트둀러λ₯Ό λ„˜μ–΄ ν”„λ‘œμ νŠΈ μ „μ²΄μ˜ 핡심 κΈ°λ°˜μž…λ‹ˆλ‹€. W5500-EVB-Picoμ—λŠ” W5500이 λ³΄λ“œμ— 직접 ν†΅ν•©λ˜μ–΄ μžˆμ–΄ μ™ΈλΆ€ λͺ¨λ“ˆ 없이 RJ45 컀λ„₯ν„°λ§ŒμœΌλ‘œ μœ μ„  이더넷 HTTP μ„œλ²„κ°€ κ°€λŠ₯ν•©λ‹ˆλ‹€.

μ—­ν• :

  • TCP μ†ŒμΌ“ 관리: W5500의 ν•˜λ“œμ›¨μ–΄ TCP/IP μŠ€νƒμ΄ 8개 독립 μ†ŒμΌ“μ„ μ œκ³΅ν•΄ HTTP ν΄λΌμ΄μ–ΈνŠΈ 연결을 처리
  • SPI μΈν„°νŽ˜μ΄μŠ€: Pico SDK hardware_spi둜 RP2040κ³Ό W5500이 SPI 톡신
  • HTTP μ„œλ²„ λ„€νŠΈμ›Œν¬ 계측: parseHTTP() β†’ respondHTTP() β†’ sendResponse() μ „ κ³Όμ •μ˜ λ„€νŠΈμ›Œν¬ 전솑을 W5500 μ†ŒμΌ“μ΄ λ‹΄λ‹Ή
  • μ•ˆμ •μ μΈ μœ μ„  μ—°κ²°: WiFi 없이 RJ45 μœ μ„  μ—°κ²°λ‘œ 24μ‹œκ°„ λΈ”λ‘œκ·Έ ν˜ΈμŠ€νŒ…

μ²˜μŒλΆ€ν„° κ΅¬ν˜„ν•œ 의미: μ»€μŠ€ν…€ W5500 λ“œλΌμ΄λ²„(lib/W5500/)λ₯Ό 직접 μž‘μ„±ν•œ 것은 W5500 칩의 SPI λ ˆμ§€μŠ€ν„° 레벨 λ™μž‘μ„ μ™„μ „νžˆ μ΄ν•΄ν•˜κ³  μ œμ–΄ν•œλ‹€λŠ” μ˜λ―Έμž…λ‹ˆλ‹€. μ΄λŠ” λ‹¨μˆœνžˆ 라이브러리λ₯Ό μ‚¬μš©ν•˜λŠ” 것과 달리 κΉŠμ€ ν•˜λ“œμ›¨μ–΄ μˆ˜μ€€μ˜ 이해λ₯Ό λ³΄μ—¬μ£ΌλŠ” 포트폴리였 μž‘ν’ˆμž…λ‹ˆλ‹€.

πŸ“Œ μ‹œμž₯ 및 ν™œμš© κ°€μΉ˜

μž„λ² λ””λ“œ μ‹œμŠ€ν…œ 포트폴리였 ν”„λ‘œμ νŠΈ, λ„€νŠΈμ›Œν¬ ν”„λ‘œκ·Έλž˜λ° ν•™μŠ΅, μ €μ „λ ₯ 개인 λΈ”λ‘œκ·Έ/μ›Ήμ„œλ²„ ꡬ좕 μ‹œλ‚˜λ¦¬μ˜€μ—μ„œ ν™œμš©λ©λ‹ˆλ‹€. W5500-EVB-PicoλŠ” μ €λΉ„μš©($10 μˆ˜μ€€)으둜 μ•ˆμ •μ μΈ μœ μ„  이더넷 HTTP μ„œλ²„λ₯Ό κ΅¬ν˜„ν•  수 μžˆμ–΄, Raspberry Piλ‚˜ ν΄λΌμš°λ“œ μ„œλ²„ 없이 마이크둜컨트둀러둜 μ›Ή ν˜ΈμŠ€νŒ…μ΄ κ°€λŠ₯함을 λ³΄μ—¬μ€λ‹ˆλ‹€.

 

πŸ“Œ WIZnet μ „λž΅μ  κ°€μΉ˜

이 ν”„λ‘œμ νŠΈλŠ” W5500-EVB-Picoκ°€ ν•™μŠ΅Β·ν¬νŠΈν΄λ¦¬μ˜€ λͺ©μ μ˜ μž„λ² λ””λ“œ μ›Ήμ„œλ²„ ν”Œλž«νΌμœΌλ‘œ μ±„νƒλœ μ‚¬λ‘€μž…λ‹ˆλ‹€. μ»€μŠ€ν…€ HTTP νŒŒμ„œμ™€ μ»€μŠ€ν…€ W5500 λ“œλΌμ΄λ²„λ₯Ό λͺ¨λ‘ 직접 μž‘μ„±ν•œ "μ²˜μŒλΆ€ν„° κ΅¬ν˜„" 접근법은 W5500 μΉ©κ³Ό W5500-EVB-Pico λ³΄λ“œμ˜ 기술적 κΉŠμ΄μ™€ ν™œμš© κ°€λŠ₯성을 잘 λ³΄μ—¬μ€λ‹ˆλ‹€. lwIPλ‚˜ ioLibrary 없이도 W5500을 μ™„μ „νžˆ μ œμ–΄ν•  수 μžˆμŒμ„ μ‹€μ¦ν•˜λŠ” λ“œλ¬Έ λ ˆνΌλŸ°μŠ€μž…λ‹ˆλ‹€.

 

πŸ“Œ μš”μ•½

W5500-EVB-Pico(RP2040 + W5500 톡합)μ—μ„œ C(C11)둜 μ²˜μŒλΆ€ν„° κ΅¬ν˜„ν•œ μž„λ² λ””λ“œ HTTP/1.1 μ›Ήμ„œλ²„μž…λ‹ˆλ‹€. HTTP νŒŒμ„œ(8λ©”μ„œλ“œ, 47헀더, 40μƒνƒœμ½”λ“œ), μ»€μŠ€ν…€ W5500 SPI λ“œλΌμ΄λ²„, LittleFS νŒŒμΌμ‹œμŠ€ν…œμ„ μ™ΈλΆ€ λ„€νŠΈμ›Œν¬ 라이브러리 없이 직접 μž‘μ„±ν•΄ 개인 λΈ”λ‘œκ·Έλ₯Ό ν˜ΈμŠ€νŒ…ν•©λ‹ˆλ‹€. Raspberry Pi Pico SDK 2.2.0+, CMake 기반 λΉŒλ“œ. κΉŠμ€ ν•˜λ“œμ›¨μ–΄Β·λ„€νŠΈμ›Œν¬ ν”„λ‘œκ·Έλž˜λ° 이해λ₯Ό λ³΄μ—¬μ£ΌλŠ” 포트폴리였 ν”„λ‘œμ νŠΈμž…λ‹ˆλ‹€.

 

πŸ“Œ FAQ

Q1. μ›Ήμ„œλ²„μ— W5500-EVB-Picoλ₯Ό μ„ νƒν•œ μ΄μœ λŠ”? W5500-EVB-PicoλŠ” W5500을 λ³΄λ“œμ— 직접 톡합해 μ™ΈλΆ€ 배선을 μ œκ±°ν•©λ‹ˆλ‹€. RP2040 + W5500 쑰합은 8개의 ν•˜λ“œμ›¨μ–΄ TCP/UDP μ†ŒμΌ“κ³Ό ν•˜λ“œμ›¨μ–΄ TCP/IP μŠ€νƒμ„ μ œκ³΅ν•΄, μ†Œν”„νŠΈμ›¨μ–΄ TCP/IP μ˜€λ²„ν—€λ“œ 없이 κ°„λ‹¨ν•˜κ³  μ•ˆμ •μ μΈ μž„λ² λ””λ“œ μ›Ήμ„œλ²„λ₯Ό κ΅¬ν˜„ν•˜κΈ°μ— μ΅œμ μž…λ‹ˆλ‹€.

Q2. μ§€μ›ν•˜λŠ” HTTP κΈ°λŠ₯은? μ²˜μŒλΆ€ν„° κ΅¬ν˜„ν•œ λ°©μ‹μœΌλ‘œ 정적 λΈ”λ‘œκ·Έ μ½˜ν…μΈ  μ„œλΉ™μ— ν•„μš”ν•œ HTTP/1.1 μ„œλΈŒμ…‹μ„ κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€. GET μš”μ²­ νŒŒμ‹±, 응닡 헀더(Content-Type, Content-Length), HTTP 200/404 응닡을 μ§€μ›ν•©λ‹ˆλ‹€. νŒŒμ„œ μˆ˜μ€€μ—μ„œλŠ” 8κ°€μ§€ λ©”μ„œλ“œμ™€ 47개 헀더 νƒ€μž…μ„ μ²˜λ¦¬ν•©λ‹ˆλ‹€.

Q3. λ™μ‹œ 연결을 μ²˜λ¦¬ν•  수 μžˆλ‚˜μš”? W5500은 8개의 독립적인 ν•˜λ“œμ›¨μ–΄ μ†ŒμΌ“μ„ μ œκ³΅ν•©λ‹ˆλ‹€. μ—¬λŸ¬ μ†ŒμΌ“μ„ ν™œμš©ν•΄ λ™μ‹œ ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μ²˜λ¦¬ν•  수 있으며, μ •ν™•ν•œ λ™μ‹œμ„± λͺ¨λΈμ€ κ΅¬ν˜„ 세뢀사항에 따라 λ‹€λ¦…λ‹ˆλ‹€.

Q4. μ™œ lwIPλ‚˜ Mongoose 같은 라이브러리λ₯Ό μ“°μ§€ μ•Šμ•˜λ‚˜μš”? 이 ν”„λ‘œμ νŠΈμ˜ 핡심 λͺ©ν‘œκ°€ "μ²˜μŒλΆ€ν„° 직접 κ΅¬ν˜„"μž…λ‹ˆλ‹€. 라이브러리λ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠμŒμœΌλ‘œμ¨ μ†ŒμΌ“ ν”„λ‘œκ·Έλž˜λ°, HTTP ν”„λ‘œν† μ½œ ꡬ쑰, W5500 λ ˆμ§€μŠ€ν„° λ™μž‘μ„ λͺ¨λ‘ 직접 μ΄ν•΄ν•˜κ³  κ΅¬ν˜„ν•˜λŠ” λŠ₯λ ₯을 포트폴리였둜 증λͺ…ν•©λ‹ˆλ‹€.

Q5. LittleFSλŠ” μ–΄λ–»κ²Œ μ‚¬μš©ν•˜λ‚˜μš”? RP2040 λ‚΄μž₯ Flash에 LittleFSλ₯Ό λ§ˆμš΄νŠΈν•΄ μ›Ή νŒŒμΌμ„ μ €μž₯ν•©λ‹ˆλ‹€. lib/littlefs/ 디렉토리에 ν¬ν•¨λœ LittleFS 라이브러리λ₯Ό CMake둜 λ§ν¬ν•©λ‹ˆλ‹€. μ›Ή μ½˜ν…μΈ λŠ” web_files.h에 C λ°°μ—΄λ‘œλ„ μž„λ² λ”©λ©λ‹ˆλ‹€.

Q6. μ›Ή μ½˜ν…μΈ λ₯Ό μˆ˜μ •ν•˜λ €λ©΄? webFiles/ λ””λ ‰ν† λ¦¬μ˜ HTML/CSS νŒŒμΌμ„ μˆ˜μ •ν•˜κ³  web_files.hλ₯Ό μž¬μƒμ„±ν•œ ν›„ λ‹€μ‹œ λΉŒλ“œΒ·ν”Œλž˜μ‹œν•˜λ©΄ λ©λ‹ˆλ‹€.

Q7. IP μ£Όμ†ŒλŠ” μ–΄λ–»κ²Œ ν™•μΈν•˜λ‚˜μš”? pico_enable_stdio_usb=1 μ„€μ •μœΌλ‘œ USB μ‹œλ¦¬μ–Ό λͺ¨λ‹ˆν„°μ—μ„œ λΆ€νŒ… μ‹œ 좜λ ₯λ˜λŠ” DHCP ν• λ‹Ή IPλ₯Ό ν™•μΈν•©λ‹ˆλ‹€. κ³ μ • IP도 W5500 λ“œλΌμ΄λ²„ μ΄ˆκΈ°ν™”μ—μ„œ μ„€μ • κ°€λŠ₯ν•©λ‹ˆλ‹€.

Q8. Pico SDK 2.2.0이 λ°˜λ“œμ‹œ ν•„μš”ν•œκ°€μš”? CMakeLists.txt에 λͺ…μ‹œμ μœΌλ‘œ μš”κ΅¬ν•©λ‹ˆλ‹€. μ΄ν•˜ λ²„μ „μ—μ„œλŠ” λΉŒλ“œκ°€ μ‹€νŒ¨ν•©λ‹ˆλ‹€.

Q9. μ»€μŠ€ν…€ W5500 λ“œλΌμ΄λ²„λŠ” μ–΄λ–»κ²Œ λ™μž‘ν•˜λ‚˜μš”? lib/W5500/의 λ“œλΌμ΄λ²„λŠ” Pico SDK hardware_spi둜 W5500 SPI λ ˆμ§€μŠ€ν„°μ— 직접 μ ‘κ·Όν•©λ‹ˆλ‹€. μ†ŒμΌ“ μ—΄κΈ°/λ‹«κΈ°, 데이터 μ†‘μˆ˜μ‹ , μ—°κ²° μƒνƒœ 확인 등을 λ ˆμ§€μŠ€ν„° μˆ˜μ€€μ—μ„œ μ œμ–΄ν•˜λ©°, WIZnet 곡식 ioLibrary 없이 λ°μ΄ν„°μ‹œνŠΈ 기반으둜 μž‘μ„±λμŠ΅λ‹ˆλ‹€.

Q10. 이 ν”„λ‘œμ νŠΈλ‘œ 무엇을 배울 수 μžˆλ‚˜μš”? TCP μ†ŒμΌ“ ν”„λ‘œκ·Έλž˜λ°, HTTP/1.1 ν”„λ‘œν† μ½œ ꡬ쑰, SPI λ“œλΌμ΄λ²„ μž‘μ„±, LittleFS νŒŒμΌμ‹œμŠ€ν…œ 톡합, CMake λΉŒλ“œ μ‹œμŠ€ν…œ, λ² μ–΄λ©”νƒˆ RP2040 κ°œλ°œμ„ ν•˜λ‚˜μ˜ μ‹€μ œ λ™μž‘ν•˜λŠ” ν”„λ‘œμ νŠΈλ‘œ ν•™μŠ΅ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

πŸ“Œ μ°Έκ³  링크


πŸ“Œ Overview

This is a from-scratch embedded web server running on the WIZnet W5500-EVB-Pico board (RP2040 + W5500 integrated), serving a personal blog over HTTP. Written entirely in C (C11) with no web frameworks, no RTOS, and no external network libraries (lwIP, Mongoose, etc.), this portfolio project demonstrates deep understanding of network programming at the socket level on embedded hardware.

The W5500-EVB-Pico is the perfect platform for this project. The RP2040 microcontroller paired with an onboard WIZnet W5500 Ethernet controller delivers a complete wired HTTP server in a compact form factor β€” with no external Ethernet module or wiring required.

πŸ“Œ System Architecture

πŸ“Œ System Architecture

πŸ“Œ Key Features

  • Implements an HTTP/1.1 server from scratch using W5500 TCP sockets
  • Parses incoming HTTP GET requests and serves HTML blog content
  • Handles multiple client connections using W5500's 8 hardware sockets
  • Runs on RP2040 bare-metal (no OS, no FreeRTOS)
  • Blog content served directly from the microcontroller's flash
  • LittleFS filesystem for RP2040 onboard Flash management
  • USB serial debug support (pico_enable_stdio_usb)

πŸ“Œ Why Build from Scratch?

This is a learning-focused portfolio project. Implementing the TCP server, HTTP parser, and response builder from scratch β€” rather than using a library like lwIP or Mongoose β€” demonstrates thorough knowledge of socket programming, HTTP protocol structure, and embedded C development.

Core elements implemented directly:

ElementDetails
HTTP method parserGET POST HEAD PUT DELETE OPTIONS TRACE CONNECT β€” all 8
HTTP header parser47 header types including Accept, Content-Type, Content-Length
Status codes40 reason phrases including 200 OK, 404 Not Found β€” defined directly
Custom W5500 driverSPI register-level driver written from scratch in lib/W5500/
HTTP structshttp_request, http_response, request_line, status_line, http_header, http_body
RouterrespondHTTP() β€” URI-based content routing

πŸ“Œ Hardware

ItemDetails
BoardWIZnet W5500-EVB-Pico (RP2040 + W5500 integrated on-board)
EthernetRJ45 port on-board β€” no external Ethernet module needed
LanguageC (C11 standard)
FrameworkRaspberry Pi Pico SDK 2.2.0+ (bare-metal)
BuildCMake 3.12+
FilesystemLittleFS (RP2040 onboard Flash)
DebugUSB serial (UART disabled)

πŸ“Œ HTTP Request Processing Flow

πŸ“Œ HTTP Request Processing Flow

πŸ“Œ Source Structure

EmbeddedWebServer/
β”œβ”€β”€ main.c          β€” HTTP parser, routing, response builder, main loop (457 lines)
β”œβ”€β”€ web_files.h     β€” HTML/CSS embedded as C arrays
β”œβ”€β”€ CMakeLists.txt  β€” CMake build config (Pico SDK 2.2.0+)
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ W5500/      β€” Custom W5500 SPI driver (written from scratch)
β”‚   └── littlefs/   β€” LittleFS filesystem library
└── webFiles/       β€” Blog HTML/CSS source (about me, projects, etc.)

Linked libraries: pico_stdlib Β· hardware_spi Β· lfs Β· W5500

Core structs in main.c:

struct http_request {
    struct request_line rq_line;    // method, URI, HTTP version
    struct http_header headers[32]; // up to 32 headers
    uint8_t header_cnt;
    struct http_body body;
};

struct http_response {
    struct status_line stat_line;   // status code, reason phrase
    struct http_header headers[32];
    uint8_t header_cnt;
    struct http_body body;
};

πŸ“Œ Source Structure Diagram

πŸ“Œ Source Structure Diagram

πŸ“Œ Build Workflow

Requirements:

  • Raspberry Pi Pico SDK 2.2.0 or later
  • CMake 3.12+
  • ARM GCC toolchain
  • PICO_SDK_PATH environment variable set
# 1. Clone
git clone https://github.com/UltraVioletWitch/EmbeddedWebServer

# 2. Create build directory and configure
mkdir build && cd build
cmake ..

# 3. Build
make -j4

# 4. Flash
# Hold BOOTSEL while connecting USB
# β†’ drag and drop webServer.uf2 to the Pico USB drive

# 5. Access
# Check assigned IP from USB serial monitor
# β†’ open http://<IP>/ in a browser

πŸ“Œ Role and Application of the WIZnet's Chip

Chip model: W5500 (integrated on W5500-EVB-Pico)

In this project, the W5500 goes beyond a simple Ethernet controller β€” it is the foundation of the entire network layer. Integrated at board level on the W5500-EVB-Pico, the W5500 handles all network communication for the HTTP server.

Core roles of the W5500:

  • Hardware TCP/IP stack β€” RP2040 uses TCP sockets directly without software TCP/IP overhead
  • 8 independent hardware sockets β€” supports simultaneous HTTP client connections
  • SPI interface β€” communicates with RP2040 via Pico SDK hardware_spi
  • On-board RJ45 β€” no external Ethernet module needed, wiring minimized
  • Network transport layer β€” handles all network transmission across the full parseHTTP() β†’ respondHTTP() β†’ sendResponse() pipeline

What the custom driver means: Writing the W5500 driver from scratch in lib/W5500/ means directly understanding and controlling the W5500 chip at the SPI register level. Unlike using the WIZnet official ioLibrary, this is a datasheet-driven implementation demonstrating deep hardware understanding β€” covering socket open/close, data send/receive, and connection state checking at the register level.


πŸ“Œ Market & Application Value

  • Portfolio project β€” proves embedded C, socket programming, and HTTP protocol implementation skills in a single working project
  • Low-cost web hosting proof of concept β€” demonstrates that a microcontroller alone can serve a web server without Raspberry Pi or cloud infrastructure
  • Educational reference β€” provides a fully functional from-scratch implementation for embedded networking learners
  • W5500-EVB-Pico platform reference β€” validates the practical utility of the integrated board as a WIZnet ecosystem showcase

πŸ“Œ WIZnet Strategic Value

This project demonstrates W5500-EVB-Pico adopted as an embedded web server platform for learning and portfolio purposes. Writing both a custom HTTP parser and a custom W5500 driver from scratch shows the technical depth and versatility of the W5500 chip and the W5500-EVB-Pico board. It is a rare reference implementation proving that W5500 can be fully controlled without lwIP or ioLibrary β€” driven directly from a datasheet.


πŸ“Œ Summary

A from-scratch embedded HTTP/1.1 web server implemented in C (C11) on the W5500-EVB-Pico (RP2040 + W5500 integrated). An HTTP parser (8 methods, 47 header types, 40 status codes), a custom W5500 SPI driver, and a LittleFS filesystem were all written without any external network library to host a personal blog. The W5500's hardware TCP/IP stack simplifies socket-level programming while the RP2040 provides ample processing power β€” making this a compelling embedded web hosting platform. Built with Raspberry Pi Pico SDK 2.2.0+ and CMake. A portfolio project demonstrating deep understanding of socket programming, HTTP protocol structure, and embedded C development.


πŸ“Œ FAQ

Q1. Why use W5500-EVB-Pico for a web server? The W5500-EVB-Pico integrates W5500 directly on the board, eliminating external wiring. The RP2040 + W5500 combination provides 8 hardware TCP/UDP sockets and a hardware TCP/IP stack β€” making it well-suited for a simple but reliable embedded web server without software TCP/IP overhead.

Q2. What HTTP features are supported? Targeting the minimal HTTP/1.1 subset needed for serving static blog content: GET request parsing, response headers (Content-Type, Content-Length), and HTTP 200/404 responses. At the parser level, 8 methods and 47 header types are handled.

Q3. Can this handle multiple simultaneous connections? The W5500 provides 8 independent hardware sockets. Multiple sockets can be used to handle concurrent clients β€” the exact concurrency model depends on the implementation details.

Q4. Why not use a library like lwIP or Mongoose? The core goal of this project is "build from scratch." Not using a library means directly understanding and implementing socket programming, HTTP protocol structure, and W5500 register behavior β€” proving that ability as a portfolio piece.

Q5. How is LittleFS used? LittleFS is mounted on the RP2040's onboard Flash to store web files. The lib/littlefs/ library is linked via CMake. Web content is also embedded as C arrays in web_files.h.

Q6. How do I modify the blog content? Edit the HTML/CSS files in the webFiles/ directory, regenerate web_files.h, then rebuild and reflash.

Q7. How do I find the IP address? The DHCP-assigned IP is printed at boot via the USB serial monitor (pico_enable_stdio_usb=1). A static IP can also be set in the W5500 driver initialization.

Q8. Is Pico SDK 2.2.0 strictly required? Yes β€” explicitly required in CMakeLists.txt. Builds will fail on earlier versions.

Q9. How does the custom W5500 driver work? The driver in lib/W5500/ accesses W5500 SPI registers directly using Pico SDK hardware_spi. It controls socket open/close, data send/receive, and connection state at the register level β€” written from the datasheet without the WIZnet official ioLibrary.

Q10. What can I learn from this project? TCP socket programming, HTTP/1.1 protocol structure, SPI driver implementation, LittleFS filesystem integration, CMake build system, and bare-metal RP2040 development β€” all in one working project.


πŸ“Œ Reference Links

Comments

Similar projects you might like

Comments