Chạy website trên vi điều khiển 8-bit: Một thử thách thú vị với AVR
Bài viết chia sẻ hành trình biến một vi điều khiển AVR 8-bit giá rẻ thành máy chủ web hoàn chỉnh. Tác giả đã giải quyết các vấn đề về kết nối mạng bằng giao thức SLIP và sử dụng WireGuard để đưa website lên internet công cộng.

Trong tập mới của series "những việc điên rồ để làm với vi điều khiển AVR", chúng ta sẽ cùng tìm hiểu cách biến một con chip nhỏ bé thành máy chủ web. Liệu bạn có tin rằng một thiết bị chỉ có 8kB RAM có thể "phục vụ" nội dung trên mạng toàn cầu?
Thiết bị vi điều khiển AVR
"Nạn nhân" trong dự án này là AVR64DD32, một vi điều khiển tương tự như dòng Atmega328 nổi tiếng trên Arduino nhưng hiện đại hơn. So với người tiền nhiệm, dòng AVR DD này có giá rẻ hơn cho cùng dung lượng bộ nhớ, chỉ cần một chân lập trình và các ngoại vi tốt hơn:
- CPU: Lõi AVR 8-bit đơn, tốc độ tối đa 24 MHz.
- RAM: 8 kB (bộ nhớ tĩnh).
- Flash: 64 kB.
- EEPROM: 256 byte.
- Điện áp: 1.8 - 5.5 Volts.
- Chi phí: Khoảng 1 USD.
Đó là thông số của chiếc "máy tính" khá rộng rãi, nhưng để host một website, nó cần một kết nối internet.
Sơ đồ kết nối phần cứng
Thách thức về kết nối mạng
Lựa chọn hiển nhiên là Ethernet, nhưng ngay cả phiên bản chậm nhất (10BASE-T) cũng chạy ở tốc độ 10 megabit/giây. Điều tồi tệ hơn là nó sử dụng mã hóa Manchester: một số 0 được gửi là "10" và số 1 là "01", nghĩa là 10 megabit dữ liệu thực tế là 20 megabit trên dây dẫn. Tốc độ này quá nhanh để AVR có thể tạo ra. Mặc dù CPU có thể chạy ở 24 MHz, nhưng tất cả các ngoại vi và chân IO tối đa chỉ ở xung nhịp 12 MHz.
Giải pháp đúng đắn là mua một chip Ethernet chuyên dụng, nhưng điều đó sẽ khiến dự án bị trì hoãn nhiều tuần. May mắn thay, Ethernet không phải là lựa chọn duy nhất.
Sử dụng giao thức SLIP
Serial Line Internet Protocol (RFC 1055) là một tiêu chuẩn rất cũ và rất đơn giản để chạy mạng qua cổng nối tiếp:
- Trước khi gửi gói tin, hãy bọc nó trong các byte 0xC0.
- Nếu gói tin chứa bất kỳ byte 0xC0 nào, hãy thay thế chúng bằng 0xDB 0xDC.
- Để tránh mơ hồ, bất kỳ byte 0xDB có sẵn nào được thay thế bằng 0xDB 0xDD.
Giao thức này từng được sử dụng rộng rãi để kết nối internet ngày xưa: một modem quay số tạo ra liên kết nối tiếp qua đường dây điện thoại, và máy tính sẽ xử lý phần còn lại. Điều thú vị là Linux hiện đại vẫn hỗ trợ SLIP:
# Chỉ là bộ chuyển đổi USB sang Serial bình thường
stty -F /dev/ttyUSB0 115200 raw cs8
slattach -m -F -L -p slip /dev/ttyUSB0
# ... và bây giờ nó là một giao diện mạng
Phần cứng ở phía vi điều khiển rất đơn giản. Nó hoạt động mà không cần bất kỳ linh kiện ngoài nào, nhưng tôi đã thêm một số đèn LED và một diode bảo vệ để tránh việc ngược điện nguồn. Vì nó chỉ tiêu thụ vài miliwatt, nó có thể chạy máy chủ từ đường 5 volt của bộ chuyển đổi nối tiếp: rất tiện lợi khi chỉ phải xử lý một dây cáp duy nhất.
Triển khai TCP/IP
Bây giờ nó có kết nối internet, nhưng đó chưa phải là một máy chủ. Để trang web của tôi đến được máy tính của bạn, mỗi gói tin cần có một tiêu đề IP: 40 byte chứa địa chỉ máy tính nguồn và đích, cùng một số thông tin khác. Việc triển khai điều này rất dễ dàng: chỉ cần hoán đổi nguồn và đích của gói tin nhận được để tạo tiêu đề cho phản hồi (và đặt lại bộ đếm TTL).
Giao thức khác, TCP, khó hơn nhiều. Việc triển khai nó yêu cầu vi điều khiển theo dõi trạng thái kết nối, định kỳ truyền lại các gói tin bị mất và xử lý hàng loạt trường hợp ngoại lệ. Mất vài ngày để bản triển khai tùy chỉnh của tôi hoạt động tốt, và nó vẫn còn một vài lỗi.
Còn về HTTP, tôi không triển khai nó theo cách truyền thống. Máy chủ luôn gửi lại một "phản hồi" được mã hóa cứng cho máy khách. Điều này hoạt động tốt miễn là trang web chỉ có một URL duy nhất.
Đưa website ra internet công cộng
Vấn đề là làm sao để chia sẻ nó với bạn bè? Thật không may, để các yêu cầu của họ đến được với nó, nó cần một địa chỉ IPv4 định tuyến công khai. Những địa chỉ này không chỉ đắt đỏ mà tôi cũng không thể có kết nối internet tốt tại nơi mình (Starlink cũng không phải giải pháp lý tưởng).
Tôi có một máy chủ với địa chỉ IP công cộng tại một trung tâm dữ liệu gần Helsinki, nhưng tôi không thể kéo một dây cáp nối tiếp dài đến đó.
Linux hỗ trợ WireGuard, tạo ra một liên kết mạng ảo qua internet. Điều này hoạt động ngay cả khi một trong các máy nằm sau (CG)NAT. Vấn đề được giải quyết: để hộp định tuyến Linux kết nối với VPS để có kết nối internet thích hợp.
Tuy nhiên, vi điều khiển vẫn không có địa chỉ IP của riêng nó. Thay vì chuyển tiếp mọi thứ từ địa chỉ VPS đến nó (và làm hỏng website bình thường của tôi), tôi thiết lập máy chủ để chuyển tiếp bất kỳ yêu cầu nào dưới /mcu đến máy chủ bằng khối địa chỉ cục bộ.
Điều này có nghĩa là khách truy cập không kết nối trực tiếp với ngăn xếp TCP/IP của vi điều khiển... nhưng đây là cấu hình tương tự mà "Vape Server" sử dụng và không ai phàn nàn. Nó cũng làm cho việc tấn công DDoS trở nên khó khăn hơn một chút đối với một máy chủ kết nối qua tốc độ quay số hiệu quả.
Toàn bộ vấn đề này sẽ không tồn tại nếu chúng ta có thể sử dụng IPv6, nhưng giao thức này đã tồn tại ba mươi năm và hầu hết mọi người vẫn không thể truy cập nó.
Bài viết liên quan

Công nghệ
Cerebras, đối tác thân thiết của OpenAI, sẵn sàng cho đợt IPO kỷ lục định giá tới 26,6 tỷ USD
04 tháng 5, 2026

Công nghệ
Microsoft giới thiệu Surface Pro 12 và Surface Laptop 8: Sức mạnh chip Intel, giá thành gây sốc
19 tháng 5, 2026

Phần cứng
Là lúc tôi phải gác lại chiếc iPhone Mini của mình
06 tháng 5, 2026
