2 คะแนน โดย GN⁺ 2024-06-04 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • สรุปขั้นตอนที่จำเป็นเมื่อเริ่มสร้างอุปกรณ์ USB เป็นครั้งแรก ตั้งแต่ การเดินสายทางกายภาพ ไปจนถึง PCB, ความเร็ว USB 2.0, ชั้นโปรโตคอล และการลงมือทำกับ STM32 เพื่อให้ทำตามได้ตั้งแต่ต้นจนจบ
  • การเชื่อมต่อพื้นฐานของ USB 2.0 ใช้สายสี่เส้นคือ +5V, GND, D+, D- โดย D+ และ D- เป็นคู่สัญญาณดิฟเฟอเรนเชียลที่ร่วมกันส่งข้อมูล 1 บิต
  • บน PCB สิ่งสำคัญของคู่สัญญาณดิฟเฟอเรนเชียลคือ การทำความยาวให้เท่ากัน, การวางให้อยู่ใกล้กัน และอิมพีแดนซ์ แต่ต้นแบบแบบ full speed 12 Mbit/s มักทำงานได้ค่อนข้างผ่อนปรน
  • การลงมือทำใช้ NUCLEO-F103RB โดยตั้ง PA12 เป็น USB_DP, PA11 เป็น USB_DM แล้วสร้างอุปกรณ์ USB serial ที่ถูกมองเห็นเป็นพอร์ต COM เสมือนแบบ CDC และเปิด LED เมื่อรับอินพุต 1
  • แนวทางของ STM32CubeIDE มีภาระจากการสร้างโค้ดผ่าน UI และการผูกกับ boilerplate ส่วนการทำอุปกรณ์ USB บน Linux อาจให้ API ที่เป็นมาตรฐานกว่าและโครงสร้างที่แยกส่วนชัดเจนกว่า

ขอบเขตเมื่อลงมือทำ USB ครั้งแรก

  • เป้าหมายคือการสร้าง อุปกรณ์ USB ในรูปแบบที่เรียบง่ายที่สุดให้เสร็จจนใช้งานได้ เมื่อเสียบกับคอมพิวเตอร์แล้วถูกตรวจพบ
  • ในที่นี้อุปกรณ์หมายถึงอุปกรณ์ต่อพ่วงที่ขยายความสามารถของคอมพิวเตอร์ และคอมพิวเตอร์จะเรียกว่า host
  • ขอบเขตรวมตั้งแต่การเชื่อมต่อทางกายภาพระหว่างอุปกรณ์ USB กับ host ไปจนถึงแอปพลิเคชันอย่างง่ายที่โต้ตอบกับอุปกรณ์ USB บน host
  • เนื้อหานี้เป็นเหมือนโปรเจกต์สร้างอุปกรณ์ USB แบบ E2E ที่เรียบง่ายที่สุดและดัชนีแหล่งอ้างอิง มากกว่าคำอธิบายสเปกอย่างเป็นทางการ

แนวคิดพื้นฐานของ USB

  • USB เป็นมาตรฐานอุตสาหกรรมที่ทำให้ การแลกเปลี่ยนข้อมูล และการจ่ายไฟระหว่างอุปกรณ์อิเล็กทรอนิกส์หลายชนิดเป็นไปได้
  • USB เป็น บัสอนุกรม ดังนั้นบิตจะถูกส่งบนบัสทีละบิต ไม่ใช่ส่งแบบขนาน
  • บัสสมัยใหม่ส่วนใหญ่ใช้วิธีอนุกรม และ USB สามารถเข้าใจได้ว่าเป็นวิธีแลกเปลี่ยนบิตแบบอนุกรมระหว่าง host กับ device
  • USB ไม่ได้มีแค่ข้อกำหนดทางกายภาพสำหรับเชื่อมต่ออุปกรณ์สองตัวและรับส่งบิต แต่ยังรวมถึงโปรโตคอลการสื่อสารสำหรับการส่งข้อมูลและการส่งพลังงานด้วย
  • จุดเน้นของคำอธิบายอยู่ที่ USB 2.0

การเดินสาย USB และคู่สัญญาณดิฟเฟอเรนเชียล

  • การเชื่อมต่อ USB 2.0 ทั่วไปอธิบายได้ด้วยสายอย่างน้อยสี่เส้น
    • +5 V: สายที่ host จ่ายไฟให้ device
    • D-, D+: คู่สัญญาณดิฟเฟอเรนเชียลที่สองเส้นทำงานร่วมกันเพื่อส่ง 1 บิต
    • GND: กราวด์
  • บางการเชื่อมต่ออาจมีขาเพิ่มเติมอย่าง ID แต่การลงมือทำนี้จะใช้เฉพาะสี่เส้นข้างต้น
  • ข้อควรระวังเกี่ยวกับ USB-C

    • USB-C ก็ใช้คู่สัญญาณดิฟเฟอเรนเชียลภายในเช่นกัน แต่ต่างจากคำอธิบาย USB 2.0 ทั่วไปในหลายจุด เช่น ต้องทำงานได้แม้เสียบกลับด้าน
    • การใช้คอนเนกเตอร์ USB-C ไม่ได้เป็นตัวกำหนดความเร็วหรือเวอร์ชัน USB
    • อุปกรณ์ USB-C อาจเป็น USB 2.0 ก็ได้ หรืออาจเป็นอุปกรณ์ USB 3.0 ที่ทันสมัยกว่าก็ได้
    • ในการลงมือทำต่อจากนี้จะไม่กล่าวถึง USB-C เพิ่มเติม
  • วิธีที่คู่สัญญาณดิฟเฟอเรนเชียลช่วยลดสัญญาณรบกวน

    • สายเดี่ยวแสดงค่าบิตโดยเปรียบเทียบแรงดันกับ GND แต่ในการเชื่อมต่อแบบมีสายระยะยาว ผลกระทบจากสัญญาณรบกวนอาจเพิ่มขึ้น
    • คู่สัญญาณดิฟเฟอเรนเชียลใช้สายสองเส้น โดยเส้นหนึ่งส่ง V และอีกเส้นส่ง -V
    • ฝั่งรับจะดูความต่างแรงดันระหว่างสองเส้น
    • หากทำให้เข้าใจอย่างง่ายว่า noise Vn แบบเดียวกันถูกบวกเข้าไปในทั้งสองเส้น จะได้ (V + Vn) - (-V + Vn) = 2V ทำให้ noise ถูกหักล้าง
    • โมเดลนี้เป็นคำอธิบายที่ทำให้ง่ายมาก และสามารถดูวิดีโอ YouTube ของ Zach Peterson จาก Altium เพื่อทำความเข้าใจคู่สัญญาณดิฟเฟอเรนเชียลให้ลึกขึ้น
    • Video 15

เมื่อต้องจัดการ USB บน PCB

  • หากไม่ได้ทำฮาร์ดแวร์เองและใช้บอร์ดพัฒนา สามารถข้ามส่วน PCB ได้ แต่หลักการพื้นฐานเมื่อติดตั้งคอนเนกเตอร์ USB บน PCB ก็ยังมีประโยชน์
  • ชิ้นส่วนไลบรารีของคอนเนกเตอร์ USB จะมีขาที่กล่าวถึงข้างต้น และคู่สัญญาณดิฟเฟอเรนเชียลต้องถูก route ไปยังขาใกล้เคียงที่เกี่ยวข้องของไมโครคอนโทรลเลอร์หรือ SoC
  • หลักการพื้นฐานของการ route คู่สัญญาณดิฟเฟอเรนเชียลมีสามข้อ
    • ทำให้ ความยาว ของ trace จาก D+ ไปยังขา plus ของชิปเท่ากับ trace อีกฝั่ง
    • วาง trace ทั้งสองให้อยู่ใกล้กันมาก
    • พิจารณา อิมพีแดนซ์ ให้เหมาะกับสัญญาณ
  • เนื่องจากออกแบบให้สายสองเส้นผ่านสภาพแวดล้อมที่แทบเหมือนกัน จึงสามารถสมมติในโมเดลง่าย ๆ ข้างต้นได้ว่าสัญญาณรบกวนของทั้งสองเส้นเท่ากัน
  • การคำนวณอิมพีแดนซ์สามารถทำได้โดยใส่ค่าอิมพีแดนซ์เป้าหมาย ระยะห่างจาก ground plane ระยะระหว่างคู่สัญญาณดิฟเฟอเรนเชียล ฯลฯ ลงใน calculator ของผู้ผลิต เพื่อหาความกว้าง trace ที่ต้องใช้
  • มีวิดีโอของ Zach Peterson เกี่ยวกับคู่สัญญาณดิฟเฟอเรนเชียลและการ route USB เป็นแหล่งอ้างอิง

ความเร็วของ USB 2.0

  • การเป็น USB 2.0 ไม่ได้หมายความว่าความเร็วถูกกำหนดไว้เพียงค่าเดียว
  • USB 2.0 อาจมีระดับความเร็วได้ เช่น สองระดับต่อไปนี้
    • full speed: 12 Mbit/s
    • high speed: 480 Mbit/s
  • device และ host ต้องตัดสินใจเมื่อเชื่อมต่อว่าจะใช้ความเร็วใด
  • หากต้องการให้ high speed ทำงานได้เสถียรบน PCB การจับอิมพีแดนซ์ให้ถูกต้องเป็นสิ่งสำคัญ
  • สำหรับต้นแบบพื้นฐาน full speed 12 Mbit/s อาจเพียงพอ และหาก trace จากคอนเนกเตอร์ USB ไปยังชิปสั้น ก็อาจค่อนข้างผ่อนปรนเรื่องความกว้าง trace และอื่น ๆ ได้

โปรโตคอลและชั้นซอฟต์แวร์

  • USB ไม่ได้ต้องพิจารณาเฉพาะฮาร์ดแวร์ แต่ต้องพิจารณาชั้นซอฟต์แวร์ทั้งฝั่ง host และ device ด้วย
  • มีวิดีโอความยาวประมาณ 45 นาทีที่อธิบาย USB จากมุมมอง Linux เป็นแหล่งแนะนำ
  • วิดีโอนี้กล่าวถึง USB frame, endpoint, configuration และวิธีที่ device หนึ่งตัวสามารถทำหน้าที่ USB ได้หลายแบบ
  • มุมมองที่คิดว่า USB เป็นเหมือน เครือข่ายของอุปกรณ์ เป็นสิ่งสำคัญ
  • เนื่องจากไม่สมจริงที่ระบบปฏิบัติการของ host จะ implement ไดรเวอร์แยกสำหรับอุปกรณ์ USB ทุกตัว ระบบปฏิบัติการจึงรู้จัก USB device class หลายแบบ
    • mass storage device
    • serial device
    • และ class อื่น ๆ อีกมากมาย
  • อุปกรณ์ในตัวอย่างจะทำงานเป็นอุปกรณ์ serial port จากมุมมองของ host

สร้างอุปกรณ์ USB serial port ด้วย STM32

  • อุปกรณ์ตัวอย่างเป็นอุปกรณ์ USB อย่างง่ายที่เปิด LED เมื่อได้รับคำขอจาก host
  • host จะมองเห็นอุปกรณ์นี้เป็น serial port device
  • วิธี implement แบ่งกว้าง ๆ ได้เป็นสองแบบ
    • ใช้ไมโครคอนโทรลเลอร์ที่รองรับ USB
    • ใช้ SoC ที่รัน Linux ได้เพื่อให้ kernel จัดการงานจำนวนมาก
  • เพื่อความเรียบง่าย ตัวอย่างนี้ใช้วิธีไมโครคอนโทรลเลอร์
  • บอร์ด NUCLEO-F103RB

    • บอร์ดพัฒนาที่ใช้คือ NUCLEO-F103RB
    • ในสหรัฐฯ สามารถซื้อได้ในราคาสูงกว่า 10 ดอลลาร์เล็กน้อยจากร้านอย่าง Digikey
    • บอร์ดนี้มีโครงสร้างเป็นสองส่วนที่ต่อกันอยู่
    • ส่วนเล็กคือพื้นที่ programmer ส่วนใหญ่คือพื้นที่ main MCU ที่จะถูกโปรแกรมจริง
    • การเชื่อมต่อ USB พื้นฐานของบอร์ดไม่ได้เชื่อมกับ main MCU แต่เชื่อมกับ MCU ฝั่ง programmer
    • programmer นี้ใช้โปรโตคอล ST-LINK เพื่อรับส่งข้อความ USB กับคอมพิวเตอร์ แล้วจึงโปรแกรม main MCU
    • หากทำ PCB ที่ใช้ STM32 เอง อาจวางชิปเพียงตัวเดียวบนบอร์ด โปรแกรมผ่าน USB แล้วใช้พอร์ต USB เดียวกันนั้นกับลอจิกของอุปกรณ์ได้
    • มีวิดีโอของ Phil’s Lab เป็นแหล่งอ้างอิงเกี่ยวกับ PCB ที่ใช้ STM32 และการโปรแกรมผ่าน USB
    • Video 19
    • Video 20

การเดินสายพอร์ต USB จริง

  • เนื่องจากการเชื่อมต่อ USB พื้นฐานของบอร์ด Nucleo ไม่ได้เชื่อมกับ main MCU จึงต้องเชื่อมพอร์ต USB ของ main MCU กับ host โดยตรง
  • หลังอัปโหลดโปรแกรมแล้ว ให้ถอด ST-LINK programmer ออกจากคอมพิวเตอร์ และจ่ายไฟให้ main MCU ผ่านพอร์ต USB จริง
  • ใช้ STM32CubeIDE สำหรับเขียนซอฟต์แวร์ และใช้ STM32CubeProgrammer สำหรับอัปโหลดลงบอร์ด
  • ขาที่จำเป็นและการตั้งค่า

    • ขาที่จำเป็นในการสร้างอุปกรณ์ USB 2.0 มีสี่อย่าง
    • ไฟ 5V ที่มาจาก host
    • GND
    • D+
    • D-
    • หากต้องการให้พอร์ต USB ฝั่ง main MCU ของ NUCLEO-F103RB รับไฟ ต้องย้าย jumper JP5 เพื่อให้บอร์ดรับไฟแบบ external 5 V
    • ใน STM32CubeIDE ให้ตั้งค่าขาดังนี้
    • PA12USB_DP
    • PA11USB_DM
    • ชิปบนบอร์ดนี้ต้องใช้ ตัวต้านทาน pull-up 1.5 kΩ ภายนอก สำหรับการเชื่อมต่อ USB
    • ตัวต้านทานจะ pull-up PA12 ไปที่ 3.3V
    • ประกอบวงจรนี้ด้วย breadboard
    • ใช้สาย USB breakout cable จาก Amazon เพื่อเชื่อมต่อ MacBook Pro กับขาแยกแต่ละเส้น โดยถอด terminal block ออกเพื่อเปิดขา USB แล้วต่อด้วย jumper wire เข้ากับบอร์ด Nucleo และ breadboard
    • แม้ไม่ได้ทำตามการจับความยาวคู่สัญญาณดิฟเฟอเรนเชียลและการควบคุมอิมพีแดนซ์อย่างเคร่งครัด การทดลองนี้ก็ยังเชื่อมต่อที่ 12 Mbit/s ได้

การเขียนซอฟต์แวร์ USB CDC

  • เมื่อตั้งค่าขา USB ใน CubeIDE จะมีการแจ้งเตือนเกี่ยวกับการตั้งค่า clock และสามารถเลือกตัวเลือกให้ CubeIDE จัดการอัตโนมัติได้
  • ตั้งค่า USB_DEVICE ใต้ Middleware and Software Packs ใน Pinout & Configuration
  • โหมดที่สำคัญในการทดลองนี้คือ
Communication Device Class (Virtual Port Com)
  • ด้วยการตั้งค่านี้ บอร์ด Nucleo จะทำงานเป็นอุปกรณ์ CDC serial port จากมุมมองของ host
  • host สามารถตั้งค่าไดรเวอร์ที่เหมาะสมเพื่อสื่อสารกับ custom device ตามข้อมูล class นี้ได้
  • CubeIDE จะสร้างโค้ด C และใน main.c จะมีการเรียก initialize ต่อไปนี้
MX_USB_DEVICE_Init();
  • เพื่อเปิด LED ให้เพิ่มโค้ดต่อไปนี้ใน routine CDC_Receive_FS
/* USER CODE BEGIN 6 */
if (Buf[0] == '1') {
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, 1);
}
  • การเรียก HAL นี้จะเปิด onboard LED ที่เชื่อมกับ pin 5 ของ port A
  • วิดีโออ้างอิงแบบทีละขั้นตอนมีดังนี้

การแฟลชและการรัน

  • หลัง build ไฟล์ ELF แล้ว ให้อัปโหลดโค้ดลงบอร์ดด้วย CubeProgrammer
  • จากนั้นถอด programmer ออก และเดินสายบอร์ดโดยใช้ไฟเลี้ยง external 5V ตามวิธีที่อธิบายไว้ก่อนหน้า
  • เมื่อบอร์ดเปิด ระบบปฏิบัติการควรแสดงรายการคล้าย COM port หรือ Serial port ใน device manager
  • หากเปลี่ยนค่า Device Descriptor ในเมนู middleware USB_DEVICE ของ CubeIDE จะสามารถตั้ง custom device name ที่แสดงใน device manager ของระบบปฏิบัติการได้
  • บน Mac OS อุปกรณ์ใหม่จะปรากฏใต้ระบบไฟล์ /dev
    • ตัวอย่าง path: /dev/tty.usbmodem497A0F6739561
  • บน Linux อาจเห็นเป็นชื่ออย่าง /dev/ttyUSB0
  • ตัวอย่างการเชื่อมต่อกับ serial device ด้วย Minicom มีดังนี้
minicom --device /dev/tty.usbmodem497A0F6739561
  • หลังเชื่อมต่อแล้ว หากพิมพ์ 1 จากแป้นพิมพ์ LED สีเขียวบนบอร์ด Nucleo จะติด

ความแตกต่างด้านซอฟต์แวร์ระหว่างแนวทาง STM32 กับ Linux

  • ผลลัพธ์ของตัวอย่างคือการสร้าง USB serial port device ที่ระบบปฏิบัติการ mainstream ตรวจพบได้
  • แนวทางที่ใช้ STM32CubeIDE มีความไม่สะดวกในมุมมองวิศวกรรมซอฟต์แวร์
    • ต้องคลิกเมนู UI เพื่อสร้าง boilerplate จำนวนมาก
    • ไม่ใช่วิธีใช้ไลบรารีที่ parameterize ได้อย่างยืดหยุ่นจากโค้ด เช่น InitUsbDevice(UsbClass.CDC)
    • โค้ดที่สร้างขึ้นผูกกับโค้ดผู้ใช้อย่างแน่นหนา จนอาจทำให้ code review ยากขึ้น
    • ไม่ชัดเจนว่าควรอัปเดต boilerplate อย่างไรเมื่อมีเวอร์ชันใหม่ออกมา
    • การตั้งค่าปัจจุบันผูกติดกับ ecosystem ของ STM32 อย่างมาก
  • วิธีที่ Linux ทำตัวเป็น USB device ถูกประเมินว่าเป็นแนวทางที่สะอาดกว่า
    • Linux API แข็งแรงและเป็นมาตรฐานมากกว่า
    • สามารถอิงการโต้ตอบกับ pseudo-file และ system call ได้
    • user space และ kernel space แยกจากกัน
    • สามารถมอง Linux เป็นเหมือนชั้น HAL ได้
  • อย่างไรก็ตาม หากต้องการอุปกรณ์ USB ที่เบา ราคาถูก และผลิตง่าย Linux SoC อาจหนักเกินไป และใน use case จำนวนมากก็อาจเกินความจำเป็น
  • บทสรุปคือคงจะดีหากมีเฟรมเวิร์กสำหรับพัฒนาอุปกรณ์ USB แบบ bare metal ที่ portable กว่าและมีข้อกำหนดบังคับน้อยกว่า

1 ความคิดเห็น

 
GN⁺ 2024-06-04
ความคิดเห็นบน Hacker News
  • เป็นบทความแนะนำ USB ที่ดีมาก แต่ดูเอนเอียงไปทางการใช้ ST microcontroller ค่อนข้างมาก และเมื่อเทียบกับแนวทางแบบระบบนิเวศ ESP32 ในปัจจุบันที่ต่อใช้อุปกรณ์ USB ได้ง่าย ก็รู้สึกว่ามีขั้นตอนและ toolchain มากกว่ามาก
    อีกอย่าง ถ้ามองจากคนที่เคยทำบอร์ด USB เองมาหลายตัว differential pair ก็ไม่ใช่เรื่องที่มือใหม่ต้องกังวลมากนัก และจะสำคัญเป็นหลักตอนงานความเร็วสูง
    USB controller IC ที่ใช้กันบ่อยบน Arduino/ESP จัดการรายละเอียดหลายอย่างให้แล้ว ดังนั้นให้คนทำอุปกรณ์ชิ้นแรกต้องมาคำนวณเองด้วยก็ดูเกินจำเป็น

    • ไม่นานมานี้ผมทำ macro pad เดินสายมือโดยใช้ Arduino Pro Micro ที่มี ATmega32U4 ติดมาด้วย และดูเหมือนจะค่อนข้างนิยมในกลุ่มคนที่ทำคีย์บอร์ดคัสตอมเป็นงานอดิเรก
      เป็นโปรเจ็กต์ที่เร็วและสนุกสำหรับมือใหม่ และส่วนที่น่ารำคาญที่สุดคือการเหลาเคสไม้
    • ผมคิดว่ามีความเข้าใจพื้นฐานเรื่อง differential pair และ impedance ไว้ก็ดี
      แต่แทบไม่เคยคำนวณจริงเลย เพราะซอฟต์แวร์ ECAD ที่ใช้มีทั้งเครื่องมือ route differential pair และวิเคราะห์สัญญาณ impedance ให้
      ถึงอย่างนั้น ถ้ารักษา trace ให้สั้นมากพอ โดยปกติก็ไม่ค่อยมีปัญหาใหญ่
    • อยากได้คำแนะนำเรื่อง USB controller IC
      ปกติผมใช้แต่ microcontroller ที่มี USB ในตัว
  • เมื่อนานมาแล้วผมเคยทำการทดสอบความสอดคล้องตามข้อกำหนด USB และหนึ่งในหัวข้อที่เจอปัญหาบ่อยคือ การทดสอบกระแสกระชากตอนเริ่มต้น
    โดยพื้นฐานแล้วมักเกิดจากมี bypass capacitor ฝั่ง 5V มากเกินไป ซึ่งเหมือนบทความจะไม่ได้พูดถึงจุดนี้
    มันง่ายที่จะโฟกัสกับการออกแบบดิจิทัลความเร็วสูง แต่ในการทดสอบความสอดคล้อง บางทีเรื่องที่ดูไม่หวือหวากลับเป็นตัวฉุด
    ผมไม่แน่ใจว่ามาตรฐานล่าสุดทำงานอย่างไร แต่ดูเหมือนยังมีการทดสอบนี้อยู่ และตัวบทความเองก็เขียนได้ดี
    https://compliance.usb.org/index.asp?UpdateFile=Electrical#:...

    • สงสัยว่าเขาใช้อุปกรณ์อะไรสำหรับ จำกัดกระแสกระชาก
      จะทำ current limiter ด้วยทรานซิสเตอร์ไม่กี่ตัวก็ได้ แต่คิดว่าน่าจะมีโซลูชันแบบรวมวงจรที่ดีกว่าและมีฟังก์ชันอย่างการป้องกันอุณหภูมิด้วย
  • ขอเสริมจากเนื้อหาในบทความเกี่ยวกับ USB-C ว่าต้องต่อ ขา CC เข้ากับตัวต้านทานที่เหมาะสม
    ไม่อย่างนั้นก็น่าจะมีโอกาสสูงที่จะไม่ทำงาน
    และเรื่อง differential routing กับ impedance สำหรับ USB 2.0 ก็ไม่ได้เป็นเรื่องใหญ่ขนาดนั้น
    แค่ทำให้ความยาว trace ใกล้เคียงกัน ต่อแบบตรงไปตรงมาอย่างสมเหตุสมผล และถ้าเป็นไปได้ก็วางให้อยู่ใกล้กันก็พอ
    ไม่จำเป็นต้องกังวลเกินเหตุเรื่องการจูนความยาวกับความกว้าง trace แบบละเอียด การควบคุม impedance หรือแนวปฏิบัติ RF จนเกินไป แค่ต่อเน็ตให้ถูกก็พอ

    • 480Mbit/s ถือว่าเร็วพอสมควร ดังนั้นก็ควรใส่ใจแนวปฏิบัติที่ดีและการแมตช์ impedance ให้อยู่ในช่วงประมาณ 10%
      MCU หลายตัวก็ต้องมีตัวต้านทานอนุกรมระหว่างขา USB PHY กับคอนเนกเตอร์ด้วย
      คงไม่ถึงขั้นต้องทำบอร์ดใหม่เพียงเพราะต้องใช้ trace 20mil แทน 24mil แต่ถึง USB 2.0 differential pair layout จะเป็นงานที่แรงกดดันไม่สูงนัก การพยายามทำให้ถูกต้องก็เป็นการฝึกที่ดี
  • ถ้ากังวลเรื่องชิ้นส่วนที่บัดกรียากอย่างโปรเซสเซอร์ ARM ก็ไม่จำเป็นต้องใช้ชิ้นใหญ่ขนาดนั้นเสมอไป
    STM32 เหมาะเมื่อคุณต้องการประสิทธิภาพ แต่สำหรับงานเล็ก ๆ คอนโทรลเลอร์ที่เล็กกว่าน่าจะเหมาะกว่า
    ตัวอย่างเช่น VUSB เป็นไลบรารีสำหรับทำ USB แบบ bit-banging บน Atmel microcontroller ขนาดเล็ก: https://www.obdev.at/products/vusb/index.html
    ยังมี schematic ของบอร์ดตัวอย่างที่เคยใช้สอนนักศึกษาเรื่องการเขียน Linux kernel module ด้วย: https://gitlab.cs.fau.de/i4/passt/passtboard-v2
    เฟิร์มแวร์อยู่ที่ http://www.poempelfox.de/ds1820tousb/ และ https://gitlab.cs.fau.de/i4/passt/ds1820tousb
    ถ้าชอบการเขียนโปรแกรมสไตล์ Arduino ก็มีบอร์ดหลายตัวที่ใช้ไลบรารีไม่กี่บรรทัดก็ทำตัวเหมือนอุปกรณ์ USB ได้ เช่น https://www.az-delivery.de/en/products/digispark-board

    • ถ้ากังวลเรื่องการบัดกรี ก็สามารถซื้อ development board ที่มีพอร์ต USB ของ microcontroller ติดมาและใช้งานได้เลยในราคาค่อนข้างสมเหตุสมผล
      เช่น NUCLEO-F429ZI: https://www.st.com/en/evaluation-tools/nucleo-f429zi.html
      มันคล้ายกับ NUCLEO-F103RB ที่ผู้เขียนใช้มาก แต่มีคอนเนกเตอร์ USB ที่ต่อเข้ากับ microcontroller โดยตรงอยู่ด้านล่าง เพิ่มจากคอนเนกเตอร์ USB ด้านบนสำหรับโปรแกรมเมอร์/ดีบักเกอร์ในตัว
      ถ้าอยากดูตัวเลือกอย่างการป้องกัน ESD ก็สามารถดาวน์โหลด schematic ของบอร์ดได้ด้วย
    • ยังมีอย่าง CH32V203 ด้วย
      เป็น TSSOP-20 ที่มีฮาร์ดแวร์ USB ในตัว และราคาซื้อแยกอยู่ราว 0.81 ดอลลาร์
      แต่ฝั่งซอฟต์แวร์อาจจะยุ่งยากกว่าเล็กน้อย
      https://www.wch-ic.com/products/CH32V203.html?
  • เคยลองเขียน โค้ด USB แบบ bare-metal บน MCU แล้วรู้สึกช็อกพอสมควรเมื่อเทียบกับโปรโตคอลดิจิทัลเรียบง่ายอย่าง SPI หรือ I2C
    ชั้นกายภาพและชั้น data link ไม่ได้ซับซ้อนกว่า CAN มากนัก แต่หลังจากนั้นก็เจอกำแพงเรื่อง descriptor, endpoint และการตั้งค่าไดรเวอร์ทันที
    USB ถูกออกแบบมาเป็นระบบนิเวศ plug-and-play สำหรับพีซีตั้งแต่แรก และลักษณะนั้นก็ชัดเจนมาก
    ถ้าเป็นไปได้ การใช้ซอฟต์แวร์ที่ผู้ผลิตจัดมาให้ให้มากที่สุดถือว่าเป็นทางที่ดีกว่าอย่างชัดเจน
    ทิปที่จำได้ลาง ๆ คือ ถ้าต้องการ throughput สูงให้ใช้ bulk transfer และไม่ควรแตะ isochronous transfer เลยจะดีกว่า
    USB เป็นโปรโตคอลแบบ master/slave ดังนั้นถ้าได้ throughput ไม่เต็ม สาเหตุมักอยู่ฝั่งโฮสต์คือพีซี
    ถ้าไลเซนส์ LGPL ตรงกับความต้องการ libusb ก็ใช้งานได้ค่อนข้างง่าย
    ถ้าไม่ได้ใช้ไดรเวอร์ของผู้ผลิต ตัววิเคราะห์โปรโตคอล USB แบบฮาร์ดแวร์มีประโยชน์มาก และ USB in a NutShell ก็เป็นเว็บอ้างอิงที่ดีสำหรับทำความเข้าใจโปรโตคอล: https://www.beyondlogic.org/usbnutshell/usb1.shtml

  • ไหน ๆ ก็พูดถึง USB บน STM32 แล้ว อยากถามว่ามีใครรู้ไหมว่าจะรองรับการ รับข้อมูลเกิน 64 ไบต์ ในหนึ่งเฟรมได้อย่างไร
    ตอนนี้กำลังจัดการเฟรมขนาด 64 ไบต์ซ้ำ ๆ ในซอฟต์แวร์อยู่ แต่รู้ว่าสามารถทำให้ใหญ่กว่านี้ได้
    น่าจะสูงสุดประมาณ 1MB
    ปัญหาคือใน Reference Manual การตั้งค่าเหล่านี้ไม่ได้แสดงเป็นรีจิสเตอร์ปกติ แต่เป็นเหมือน pseudo-register บางอย่าง
    เลยสงสัยว่ามีวิธีเลี่ยงที่ง่ายกว่านี้ไหม
    หมายถึงอุปกรณ์ต่อพ่วง USB ที่ไม่ใช่ OTG

    • USB full-speed bulk transfer ถูกจำกัดไว้ที่ 64 ไบต์
      ไม่แน่ใจว่าหมายถึง STM32 รุ่นไหน แต่ stm32g4 รองรับแค่ full-speed
  • ปกติใช้ ESP32 เป็นหลัก แต่มีวิธีดัดแปลงราคาถูกที่เหมาะกับหลายโปรเจกต์
    ถ้าต้องการคอนโทรลเลอร์แบบคัสตอมที่เร็วและง่ายมาก ก็อาจพิจารณาถอด แผงควบคุมของคีย์บอร์ด USB ที่ทิ้งแล้วมาใช้
    แทนที่จะบัดกรี ก็เอาสายไปติดกับจุดสัมผัสด้วยกาวนำไฟฟ้า แล้วใช้ปืนกาวยึดให้แน่นได้
    เคยทำคอนโทรลเลอร์เกมปุ่มเดียวราคาถูกแต่ค่อนข้างทน ใช้ปุ่มอาร์เคดส่งอินพุตสเปซบาร์ โดยระบบจัดการดีบาวซ์และเรื่องอื่น ๆ ให้หมด และไม่ต้องเขียนโค้ด

  • สงสัยว่ามี บอร์ดพัฒนาที่รองรับ USB 3 หรือไม่
    กำลังจะทำต้นแบบ USB-C monitor sink แต่หาบอร์ดที่แรงพอจะรับ DisplayPort ผ่าน USB ได้ค่อนข้างยาก

    • การ รับ DisplayPort ผ่าน USB ไม่ต้องใช้ประสิทธิภาพสูงมาก
      โดยสมมุติว่ารับสัญญาณ DisplayPort ได้อยู่แล้ว หรือส่งต่อไปยังจอภายนอกได้
      แค่ทำ USB billboard device และส่งสัญญาณ alternate mode ที่ถูกต้อง
      สำหรับการทำงานจริงอาจเป็นทางเลือก แต่ถ้าจำไม่ผิดตามสเปกถือว่าจำเป็น
      จากนั้นสัญญาณ DisplayPort ก็จะออกมาที่ปลั๊ก USB-C และเพียงต่อสาย AUX ที่ถูกต้องเข้ากับคอนเน็กเตอร์ DisplayPort ก็ใช้ได้
    • มีบอร์ดแบบนี้อยู่: https://octopart.com/cyusb3kit-003-cypress+semiconductor-494...
      ราคาก็ดูสมเหตุสมผล
      ตอนหาของคล้ายกันเมื่อ 2 ปีก่อน ราคาสูงกว่านี้อีกหนึ่งหลัก
    • ทำได้ด้วย FPGA ส่วนใหญ่ที่มี transceiver
  • เสียบ Raspberry Pi เข้ากับพีซีไว้ แล้วใช้ https://github.com/xairy/raw-gadget ทำ อุปกรณ์ USB เสมือน
    ตอนนี้กำลังใช้เพื่อจำลองกล้อง MTP เพื่อหลอกซอฟต์แวร์ปิดซอร์สอยู่

  • เคยทำต้นแบบอุปกรณ์ USB อยู่บ้างด้วย Raspberry Pi Zero และ USB composite ของ Linux kernel
    อย่างน้อยอุปกรณ์เก็บข้อมูลและอุปกรณ์ serial ก็ทำงานได้ค่อนข้างง่าย
    ฝั่ง Raspberry Pi จะต้องมีอะไรอย่างเช่นเชลล์สคริปต์สำหรับเริ่มต้น composite kernel module และโค้ดสำเร็จรูปพวกนี้หาได้จากเอกสารของเคอร์เนล

    • อยากลองทำ อุปกรณ์ USB เสมือน อย่างเว็บแคมด้วย Pi
      pikvm ก็เป็นโปรเจกต์ที่น่าสนใจ
      เมื่อเชื่อมต่อเข้ากับพีซีแล้ว USB connection ไม่ได้ทำงานแค่เป็นคีย์บอร์ดและเมาส์ แต่ยังอาจเป็นไดรฟ์ USB ที่ใช้ตอนบูตระบบได้ด้วย
      เป็นวิธีที่น่าสนใจมากสำหรับงานติดตั้งระบบ