โฮสต์เว็บไซต์บนไมโครคอนโทรลเลอร์ 8 บิต
(maurycyz.com)- โฮสต์เว็บไซต์ได้ด้วย MCU 8 บิต AVR64DD32 เพียงตัวเดียว และทำงานได้ในสภาพแวดล้อมขนาดเล็กที่มี CPU 24MHz, RAM 8KB และ Flash 64KB
- การสร้างสัญญาณ Ethernet โดยตรงทำได้ยาก เพราะแม้แต่ 10BASE-T ก็ยังเร็วเกินไป จึงใช้ลิงก์ USB-Serial เป็นอินเทอร์เฟซเครือข่ายด้วย SLIP ที่ Linux รองรับ
- SLIP เป็นวิธีง่าย ๆ ที่ห่อแพ็กเก็ตด้วย
0xC0และ escape ไบต์พิเศษ จึงเหมาะสำหรับเชื่อมต่อ MCU เข้ากับ Linux สมัยใหม่ - ส่วนของ IP เรียบง่ายขึ้นเพราะปิดการทำ fragment แต่การทำ TCP implementation ต้องจัดการสถานะการเชื่อมต่อ การส่งซ้ำ และกรณียกเว้นต่าง ๆ จึงใช้เวลาหลายวันและยังมีบั๊กเหลืออยู่
- การเข้าถึงจากภายนอกใช้โครงสร้างอ้อมผ่าน VPS, WireGuard และพร็อกซีที่ส่งต่อเฉพาะคำขอ
/mcuโดยมีต้นทุนของ IPv4 สาธารณะและการไม่มี IPv6 เป็นข้อจำกัดหลัก
โครงสร้างการโฮสต์เว็บไซต์ด้วย AVR 8 บิต
- AVR64DD32 เป็น MCU ตระกูล AVR 8 บิต คล้ายกับ Atmega328 ที่รู้จักกันจาก Arduino แต่ถูกกว่าเมื่อเทียบที่หน่วยความจำระดับเดียวกัน และมีขาโปรแกรมเพียงขาเดียวพร้อมอุปกรณ์ต่อพ่วงที่ดีกว่า
- แกนประมวลผล AVR 8 บิตเดี่ยว สูงสุด 24MHz
- RAM แบบสแตติก 8KB, Flash 64KB, EEPROM 256 ไบต์
- ช่วงแรงดันไฟ 1.8~5.5V, ราคาอยู่ราว $1~$2
- หากต้องการเชื่อมต่ออินเทอร์เน็ตโดยตรงด้วย MCU เพียงตัวเดียว จะต้องสร้างสัญญาณ Ethernet ขึ้นมาเอง แต่แม้แต่ 10BASE-T ซึ่งช้าที่สุดก็ยังเร็วเกินไปสำหรับสภาพแวดล้อมนี้
- 10BASE-T ทำงานที่ 10Mbit/s และด้วย Manchester encoding ทำให้บนสายจริงกลายเป็น 20Mbit
- CPU ของ AVR64DD32 ทำงานได้สูงสุด 24MHz แต่เพอริเฟอรัลและขา IO รองรับสัญญาณนาฬิกาได้สูงสุด 12MHz จึงยากที่จะสร้างสัญญาณโดยตรง
- วิธีมาตรฐานคือใช้ชิป Ethernet เฉพาะทาง แต่ต้องรอของหลายสัปดาห์เพื่อให้โปรเจกต์เสร็จ
- ทางเลือกคือใช้ SLIP (Serial Line Internet Protocol, RFC 1055) เพื่อรันเครือข่ายบนลิงก์แบบอนุกรม
- ห่อหน้าและท้ายของแพ็กเก็ตด้วยไบต์
0xC0 0xC0ภายในแพ็กเก็ตจะถูกแทนเป็น0xDB 0xDCและ0xDBเดิมจะถูกแทนเป็น0xDB 0xDDเพื่อหลีกเลี่ยงความกำกวม- วิธีนี้สืบทอดมาจากยุคที่โมเด็ม dial-up สร้างลิงก์อนุกรมบนสายโทรศัพท์ แล้วคอมพิวเตอร์จึงจัดการเครือข่ายบนลิงก์นั้น
- Linux สมัยใหม่ก็ยังรองรับ SLIP และสามารถทำให้อะแดปเตอร์ USB-Serial กลายเป็นอินเทอร์เฟซเครือข่ายได้
- ตัวอย่างการใช้งานคือ
stty -F /dev/ttyUSB0 115200 raw cs8,slattach -m -F -L -p slip /dev/ttyUSB0
- ห่อหน้าและท้ายของแพ็กเก็ตด้วยไบต์
- ฮาร์ดแวร์ฝั่ง MCU นั้นเรียบง่าย และทำงานได้แม้ไม่มีชิ้นส่วนภายนอก
การทำโปรโตคอลและการจัดการการเข้าถึงสาธารณะ
- ส่วนของ IP implementation เรียบง่ายขึ้นเพราะข้อจำกัดของสภาพแวดล้อมสมัยใหม่
- เพื่อให้เว็บเพจไปถึงคอมพิวเตอร์ของผู้ใช้ แพ็กเก็ตต้องผ่านหลายเครือข่าย และแต่ละแพ็กเก็ตต้องมีส่วนหัว IP ขนาด 40 ไบต์ที่เก็บข้อมูลอย่างที่อยู่ต้นทางและปลายทาง
- IP ในอดีตมีฟีเจอร์อย่าง packet fragmentation ที่ต้องใช้หน่วยความจำมากหากจะจัดการให้ถูกต้อง
- ระบบปฏิบัติการสมัยใหม่ปิดการทำ fragment และ IPv6 ก็เอาฟีเจอร์นี้ออกไปแล้ว จึงไม่จำเป็นต้องจัดการเองโดยตรง
- เพียงสลับต้นทางและปลายทางของแพ็กเก็ตที่ได้รับ แล้วรีเซ็ตตัวนับ TTL ก็สามารถสร้างส่วนหัวของการตอบกลับได้
- การทำ TCP implementation ยากกว่ามาก เพราะต้องติดตามสถานะการเชื่อมต่อ ส่งแพ็กเก็ตที่สูญหายซ้ำ และจัดการกรณียกเว้นอีกหลายแบบ
- กว่าจะทำ TCP แบบคัสตอมให้ใช้งานได้ดีพอกินเวลาหลายวัน และยังเหลือบั๊กอยู่บางส่วน
- ไม่ได้ทำ HTTP แยกต่างหาก โดยเซิร์ฟเวอร์จะส่ง “response” ที่ฮาร์ดโค้ดไว้ให้ไคลเอนต์เสมอ
- ถ้าเป็นเว็บไซต์ที่มี URL เดียว วิธีนี้ก็เพียงพอที่จะใช้งานได้
- ขั้นตอนการโหลดดูได้ใน Video 3
- การเข้าถึงจากภายนอกต้องใช้ ที่อยู่ IPv4 สาธารณะที่ route ได้ แต่ต้นทุนและคุณภาพการเชื่อมต่ออินเทอร์เน็ตที่บ้านเป็นอุปสรรค
- เครื่องที่มีที่อยู่สาธารณะซึ่ง route ได้ ตั้งอยู่บน VPS ในดาต้าเซ็นเตอร์ใกล้ Helsinki
- ใช้ WireGuard บน Linux เพื่อสร้างลิงก์เครือข่ายเสมือนผ่านอินเทอร์เน็ต และยังทำงานได้แม้ฝั่งหนึ่งจะอยู่หลัง CGNAT
- ทำให้กลายเป็นโครงสร้างที่ Linux router box เชื่อมต่อกับ VPS เพื่อให้ได้การเชื่อมต่ออินเทอร์เน็ตที่เหมาะสมกว่า
- MCU ยังไม่มี public IP ของตัวเองอยู่ดี ดังนั้นถ้าส่งต่อทุกคำขอจากที่อยู่ของ VPS ไปทั้งหมด เว็บไซต์เดิมก็จะพัง
- จึงตั้งค่าให้เซิร์ฟเวอร์พร็อกซีเฉพาะคำขอภายใต้
/mcuไปยังเซิร์ฟเวอร์ MCU โดยใช้บล็อกที่อยู่ภายใน - ผู้เยี่ยมชมจึงไม่ได้เชื่อมต่อโดยตรงกับสแตก TCP/IP ของ MCU แต่เป็นแนวทางแบบเดียวกับ Vape Server
- แม้จะทำให้การทำลายระบบด้วยแพ็กเก็ต SYN ยากขึ้นเล็กน้อย แต่โดยพื้นฐานแล้วนี่คือเซิร์ฟเวอร์บนการเชื่อมต่อที่แทบไม่ต่างจาก dial-up จึงยังเปราะบางต่อ DDoS
- จึงตั้งค่าให้เซิร์ฟเวอร์พร็อกซีเฉพาะคำขอภายใต้
- การไม่มี IPv6 ยังคงเป็นสาเหตุรากของโครงสร้างอ้อมทั้งหมดนี้
- แม้ IPv6 จะมีมาแล้ว 30 ปี แต่คนส่วนใหญ่ก็ยังเข้าไม่ถึงอยู่ดี
- /mcu: หน้าเว็บที่โฮสต์บน MCU
- http://ewaste.fka.wtf/: Vape Server ที่โฮสต์บน MCU 32 บิตซึ่งดึงออกมาจากขยะอิเล็กทรอนิกส์
- https://lcamtuf.substack.com/p/psa-if-youre-a-fan-of-atmega-try: บทความของ lcamtuf เกี่ยวกับสาย AVR Dx
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
เมื่อกว่า 25 ปีก่อน เคยมีการแข่งขันอวดกันเพื่อสร้าง เว็บเซิร์ฟเวอร์ที่เล็กที่สุด: https://web.archive.org/web/20000815063022/http://www-ccs.cs...
คนที่ใช้ไมโครคอนโทรลเลอร์ ACE1101 เป็นคน “ชนะ” แต่หาบทความต้นฉบับไม่เจอแล้ว และยังมีอันนี้ด้วย: https://conceptlab.com/fly/
มันคือเว็บเซิร์ฟเวอร์บนแมลงวัน
กระบวนการบีบโค้ดให้เล็กลงสนุกมาก และเมื่อเอา ping ออก ก็มีที่พอจะใส่ bit-banged I2C กับการอัปโหลด UDP ไปยัง EEPROM ได้ แถมยังคงต่ำกว่า 1024 ไบต์อยู่ดี
ฉันชอบ AVR DD, EA, EB series แต่การเปิดตัวชิปล่าสุดของ Microchip ดูน่ากังวลเล็กน้อยสำหรับแฟน AVR: https://www.microchip.com/en-us/products/microcontrollers/32...
PIC32 CM มีฟีเจอร์ส่วนใหญ่ของ AVR DD ทั้ง event system, MVIO, การทำงานที่ 5V ฯลฯ แต่ให้ ARM 32-bit M0+ core ที่ใหญ่กว่าและเป็นมาตรฐานมากกว่า
เลยอดกังวลไม่ได้ว่า AVR DD อาจดูค่อนข้างล้าสมัยไปแล้ว ส่วน AVR EA และ AVR EB ดูยังปลอดภัย เพราะมี 12-bit ADC ที่มี programmable gain 16x และแม้จะมี noise อยู่บ้าง แต่ไวได้ถึงราว 50 ไมโครโวลต์ ทำให้เป็น ADC/เซ็นเซอร์กระแสที่ดีแบบเหลือเชื่อ
ในทางกลับกัน เรื่องนี้อาจทำให้ตระกูล AVR ได้รับความนิยมมากขึ้นก็ได้ ฉันสงสัยว่าการมี ARM32 Cortex M0+ ที่ pin-compatible กัน จะเพิ่มหรือลดโอกาสในการพัฒนาบนแพลตฟอร์ม AVR
ส่วนตัวฉันคิดว่า อุปกรณ์ต่อพ่วง สำคัญที่สุด AVR DD อาจกินพลังงานต่ำกว่า โดยเฉพาะการทำงานที่ 1.8V แต่ไม่แน่ใจว่านั่นจะเพียงพอหรือเปล่า
ตัวโปรเจกต์เองน่าสนใจมาก และ AVR DD ก็ยังเป็นชิปที่ยอดเยี่ยมอยู่ดี จึงดีที่ได้เห็นการนำไปใช้งานจริง
10BASE-T ทำงานที่ 10 เมกะบิต/วินาที และด้วย Manchester encoding จึงกลายเป็น 20 เมกะบิตบนสายจริง AVR EB มี x2 PLL timer ดังนั้นถ้าลองจริงจังพอ ก็อาจจะปล่อย Manchester encoding ออกมาได้
ถ้าเอา LUT, UART peripheral และวงจร timer ที่เร่งด้วย PLL มาประกอบกัน ก็น่าจะดัน Manchester encoding ความเร็วสูงออกมาได้ แต่จะถึง 20Mbit หรือไม่คงต้องคิดต่ออีกหน่อย
การเริ่มทดลองเส้นทาง Cortex-M0 อาจเป็นสัญญาณว่าไม่อยากพัฒนาแพลตฟอร์ม 8-bit รุ่นถัดจาก Dx ต่อไปแล้ว แต่ถ้าแค่นำความสามารถเดียวกันไปใส่ใน CPU core อื่น ฉันก็คิดว่าไม่เป็นไร
ชอบที่เห็น HTML ถูกสตรีมขึ้นหน้าเว็บแบบเรียลไทม์ ทำให้นึกถึงยุค dial-up ที่รูปภาพค่อย ๆ วาดจากบนลงล่าง
ที่นั่นโหลดเพลงได้หลายเพลงต่อการเชื่อมต่อหนึ่งครั้งจาก FTP และต่อมาก็จาก Napster
ตอนเห็นชื่อเรื่อง ความคิดแรกของฉันคือ “อุปกรณ์ embedded/IoT หลายตัวก็ทำอะไรแบบนี้กันเยอะนะ”
มีตัวอย่าง 8051 ที่มี 10/100 Ethernet ในตัว: https://www.asix.com.tw/public/index.php/en/product/Microcon...
มีอยู่สองอย่างที่น่าสนใจ อย่างแรกคือมี errata ปี 2025 ของ RFC 1055 ซึ่งไม่ได้อยู่ใน www.c ที่นี่ errata นั้นอธิบายได้ค่อนข้างน่าเชื่อว่าอัลกอริทึมการถอดรหัสควรเปลี่ยนอย่างไร และในกรณีนี้ปลายอีกฝั่งของลิงก์ก็คือ Linux จริง ๆ
อย่างที่สอง จุดหมายถัดไปน่าจะเป็น RFC 1144
ชุดผสม ENC28J60 + PIC18 คือคอนฟิกที่เดโมซึ่ง Microchip แจกกันทั่วไปเมื่อ 20 ปีก่อน ใช้ทำสิ่งนี้แบบตรงตัวเลย
ฉันชอบที่พร็อกซีไม่ได้เขียนทับค่า server: header ของหน้าเว็บ
ฉันเคยทำอะไรคล้าย ๆ กันด้วย Arduino Mega มาก่อน สิ่งที่น่าทึ่งคือมันสามารถดูเหมือนของจริงได้มากพอสมควร เพราะไคลเอนต์ช่วยทำงานไปเยอะ ส่วนคอนโทรลเลอร์ก็แค่ส่งคอนเทนต์จากการ์ด uSD ออกมาเท่านั้น