• โปรเจกต์เชิงทดลองที่นำไมโครคอนโทรลเลอร์ ARM Cortex-M0+ สมรรถนะต่ำซึ่งฝังอยู่ในบุหรี่ไฟฟ้าแบบใช้แล้วทิ้งมารันเว็บเซิร์ฟเวอร์
  • วิเคราะห์ชิป PY32F002B ของ PUYA ที่มี แฟลช 24KiB และ RAM 3KiB พร้อมสร้างการเชื่อมต่อเครือข่ายด้วยวิธี SLIP
  • ใช้ Semihosting, โปรโตคอล SLIP และสแตก uIP TCP/IP เพื่อพอร์ตการสื่อสาร TCP/IP และความสามารถของ HTTP server ผ่าน virtual tty
  • เดิมทีช้ามาก แต่หลังจาก ปรับแต่งบัฟเฟอร์ และปรับปรุงการประมวลผลข้อมูล ก็ทำให้การตอบสนองและความเร็วในการโหลดหน้าเพิ่มขึ้นอย่างมาก
  • ทำให้สามารถรันโค้ดเซิร์ฟเวอร์แบบไดนามิกและให้บริการ API endpoint ได้ แม้อยู่ในสภาพแวดล้อมที่มีหน่วยความจำต่ำ
  • มีการเผยแพร่โค้ดแล้ว และแม้จะโฮสต์ใช้งานจริงได้ แต่ก็ยังมีข้อจำกัดด้านทรัพยากรอย่างหน่วยความจำ

บทนำ

  • ขอชี้แจงก่อนว่าบทความนี้ไม่ได้ให้บริการผ่านเว็บเซิร์ฟเวอร์ที่รันอยู่บนบุหรี่ไฟฟ้าแบบใช้แล้วทิ้งโดยตรง แต่ให้บริการเนื้อหาเดียวกันผ่านเซิร์ฟเวอร์แยกต่างหาก
  • สามารถดูตัวอย่างการทำงานจริงได้ที่ http://ewaste.fka.wtf/

ที่มา

  • ตลอดหลายปีที่ผ่านมา ผู้เขียนได้รวบรวมบุหรี่ไฟฟ้าแบบใช้แล้วทิ้งจากคนรู้จักเพื่อนำ แบตเตอรี่ มาใช้ซ้ำ
  • ช่วงหลังเริ่มสนใจที่อุปกรณ์บุหรี่ไฟฟ้าแบบใช้แล้วทิ้งมีความก้าวหน้ามากขึ้นเรื่อย ๆ และเริ่มมาพร้อม USB-C และแบตเตอรี่แบบชาร์จซ้ำได้
  • ระหว่างการแยกชิ้นส่วนได้พบไมโครคอนโทรลเลอร์ ARM Cortex-M0+ ที่มีแฟลชในตัว ชื่อ PUYA ซึ่งเป็นชิปที่รู้จักกันดีในฐานะไมโครคอนโทรลเลอร์ราคาประหยัด
  • ผู้เขียนเก็บไมโครคอนโทรลเลอร์เหล่านี้มาจากหลายรุ่น และพบว่ามีการติดป้ายกำกับขาดีบักไว้ ทำให้ง่ายต่อการวิเคราะห์

ฮาร์ดแวร์ที่ใช้

  • บนชิปมีสกรีนว่า PUYA C642F15 แต่คาดว่าแท้จริงแล้วอยู่ในตระกูล PY32F002B
  • สเปกหลัก:
    • คอร์ 24MHz Cortex-M0+
    • แฟลช 24KiB
    • RAM 3KiB
    • มีอุปกรณ์ต่อพ่วงหลายอย่าง แต่ไม่ได้ใช้งานในโปรเจกต์นี้
  • แม้ประสิทธิภาพจะต่ำเมื่อเทียบกับสมาร์ตโฟนทั่วไป แต่ในสภาพแวดล้อมแบบฝังตัวก็ยังสร้างเว็บเซิร์ฟเวอร์แบบง่าย ๆ ได้เพียงพอ

การเชื่อมต่อเครือข่าย

  • แม้ไม่ใช่แนวคิดใหม่ทั้งหมด แต่ผู้เขียนเกิดไอเดียในการรันเว็บเซิร์ฟเวอร์ระหว่างทดลองแนวคิด semihosting
  • Semihosting คือวิธีจำลอง syscall บนระบบ ARM แบบฝังตัว
    • เมื่อนำค่า/พอยน์เตอร์ใส่ไว้ในรีจิสเตอร์แล้วเรียก breakpoint ดีบักเกอร์จะตีความและจัดการการทำงานให้
    • โดยทั่วไปใช้เพื่อส่งล็อก แต่ก็สามารถทำการสื่อสารข้อมูลแบบสองทางได้
  • อุปกรณ์ USB serial รองรับโปรโตคอล SLIP(Serial Line Internet Protocol) จึงนำมาใช้เป็นอินเทอร์เฟซเครือข่าย
  • บน Linux (และบางส่วนของ macOS) สามารถสร้างสภาพแวดล้อม เครือข่าย SLIP ผ่าน virtual tty ด้วย slattach และ socat เป็นต้น
    pyocd gdb -S -O semihost_console_type=telnet -T $(PORT) $(PYOCDFLAGS) &  
    socat PTY,link=$(TTY),raw,echo=0 TCP:localhost:$(PORT),nodelay &  
    sudo slattach -L -p slip -s 115200 $(TTY) &  
    sudo ip addr add 192.168.190.1 peer 192.168.190.2/24 dev sl0  
    sudo ip link set mtu 1500 up dev sl0  
    
  • เลือกใช้ uIP เป็นสแตก TCP/IP เพราะมีขนาดเล็กมาก ไม่ต้องใช้ RTOS และพอร์ตได้ง่าย
  • จากตัวอย่างของ uIP ได้นำ HTTP server มาใช้ และพอร์ตโค้ด SLIP ให้เข้ากับวิธี semihosting จนสามารถเปิดใช้งานเว็บเซิร์ฟเวอร์ได้สำเร็จ
  • เนื่องจากสถาปัตยกรรม ARM มีปัญหาเรื่องการจัดแนว 16 บิต จึงได้แก้ไขสคริปต์สร้าง filesystem และแปลงผลด้วย Perl

การปรับความเร็วให้เหมาะสม

  • ในช่วงแรกมีความเร็วตอบสนองช้ามาก โดย ping 1.5 วินาที, packet loss 50% และโหลดหน้าเว็บนานเกิน 20 วินาที
  • สาเหตุคือโอเวอร์เฮดที่สูงมากของการรับส่งข้อมูลแบบไบต์ต่อไบต์
  • จึงใช้ RAM 3KiB อย่างเต็มที่ เพิ่ม ring buffer และปรับให้ฟังก์ชัน SLIP ป้อนข้อมูลเป็นชุด
  • ฝั่งการเขียนก็แบ่งส่งเป็นแบตช์เช่นกัน เพื่อให้การส่งข้อมูลและการล้างสถานะทำได้รวดเร็ว
  • หลังการปรับแต่งสามารถทำได้ถึง ping 20ms, ไม่สูญหาย, โหลดหน้า 160ms
  • การใช้ RAM และแฟลชทั้งหมด:
    • แฟลช: 5,116B จาก 24KB (20.82%)
    • RAM: 1,380B จาก 3KB (44.92%)
  • มีพื้นที่เพียงพอสำหรับให้บริการคอนเทนต์บล็อกทั้งหมดได้สบาย และยังสามารถรันโค้ด C ฝั่งเซิร์ฟเวอร์ได้อีกด้วย

ฟีเจอร์อื่น ๆ และบทสรุป

  • ผู้เขียนได้สร้าง API endpoint เอง เพื่อส่งคืนจำนวนครั้งที่มีการร้องขอหน้าแรกและ unique ID ของไมโครคอนโทรลเลอร์
  • นี่เป็นการทดลองที่สร้างได้ถึงเว็บเซิร์ฟเวอร์แบบไดนามิกและ API บนฮาร์ดแวร์สเปกต่ำสุดขั้วและหน่วยความจำระดับน้อยมาก

อ้างอิง

ยังไม่มีความคิดเห็น

ยังไม่มีความคิดเห็น