- สรุปขั้นตอนที่จำเป็นเมื่อเริ่มสร้างอุปกรณ์ 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 ให้ตั้งค่าขาดังนี้
PA12 → USB_DP
PA11 → USB_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 ความคิดเห็น
ความคิดเห็นบน Hacker News
เป็นบทความแนะนำ USB ที่ดีมาก แต่ดูเอนเอียงไปทางการใช้ ST microcontroller ค่อนข้างมาก และเมื่อเทียบกับแนวทางแบบระบบนิเวศ ESP32 ในปัจจุบันที่ต่อใช้อุปกรณ์ USB ได้ง่าย ก็รู้สึกว่ามีขั้นตอนและ toolchain มากกว่ามาก
อีกอย่าง ถ้ามองจากคนที่เคยทำบอร์ด USB เองมาหลายตัว differential pair ก็ไม่ใช่เรื่องที่มือใหม่ต้องกังวลมากนัก และจะสำคัญเป็นหลักตอนงานความเร็วสูง
USB controller IC ที่ใช้กันบ่อยบน Arduino/ESP จัดการรายละเอียดหลายอย่างให้แล้ว ดังนั้นให้คนทำอุปกรณ์ชิ้นแรกต้องมาคำนวณเองด้วยก็ดูเกินจำเป็น
เป็นโปรเจ็กต์ที่เร็วและสนุกสำหรับมือใหม่ และส่วนที่น่ารำคาญที่สุดคือการเหลาเคสไม้
แต่แทบไม่เคยคำนวณจริงเลย เพราะซอฟต์แวร์ ECAD ที่ใช้มีทั้งเครื่องมือ route differential pair และวิเคราะห์สัญญาณ impedance ให้
ถึงอย่างนั้น ถ้ารักษา trace ให้สั้นมากพอ โดยปกติก็ไม่ค่อยมีปัญหาใหญ่
ปกติผมใช้แต่ 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 จนเกินไป แค่ต่อเน็ตให้ถูกก็พอ
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
เช่น NUCLEO-F429ZI: https://www.st.com/en/evaluation-tools/nucleo-f429zi.html
มันคล้ายกับ NUCLEO-F103RB ที่ผู้เขียนใช้มาก แต่มีคอนเนกเตอร์ USB ที่ต่อเข้ากับ microcontroller โดยตรงอยู่ด้านล่าง เพิ่มจากคอนเนกเตอร์ USB ด้านบนสำหรับโปรแกรมเมอร์/ดีบักเกอร์ในตัว
ถ้าอยากดูตัวเลือกอย่างการป้องกัน ESD ก็สามารถดาวน์โหลด schematic ของบอร์ดได้ด้วย
เป็น 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
ไม่แน่ใจว่าหมายถึง STM32 รุ่นไหน แต่ stm32g4 รองรับแค่ full-speed
ปกติใช้ ESP32 เป็นหลัก แต่มีวิธีดัดแปลงราคาถูกที่เหมาะกับหลายโปรเจกต์
ถ้าต้องการคอนโทรลเลอร์แบบคัสตอมที่เร็วและง่ายมาก ก็อาจพิจารณาถอด แผงควบคุมของคีย์บอร์ด USB ที่ทิ้งแล้วมาใช้
แทนที่จะบัดกรี ก็เอาสายไปติดกับจุดสัมผัสด้วยกาวนำไฟฟ้า แล้วใช้ปืนกาวยึดให้แน่นได้
เคยทำคอนโทรลเลอร์เกมปุ่มเดียวราคาถูกแต่ค่อนข้างทน ใช้ปุ่มอาร์เคดส่งอินพุตสเปซบาร์ โดยระบบจัดการดีบาวซ์และเรื่องอื่น ๆ ให้หมด และไม่ต้องเขียนโค้ด
สงสัยว่ามี บอร์ดพัฒนาที่รองรับ USB 3 หรือไม่
กำลังจะทำต้นแบบ USB-C monitor sink แต่หาบอร์ดที่แรงพอจะรับ DisplayPort ผ่าน USB ได้ค่อนข้างยาก
โดยสมมุติว่ารับสัญญาณ DisplayPort ได้อยู่แล้ว หรือส่งต่อไปยังจอภายนอกได้
แค่ทำ USB billboard device และส่งสัญญาณ alternate mode ที่ถูกต้อง
สำหรับการทำงานจริงอาจเป็นทางเลือก แต่ถ้าจำไม่ผิดตามสเปกถือว่าจำเป็น
จากนั้นสัญญาณ DisplayPort ก็จะออกมาที่ปลั๊ก USB-C และเพียงต่อสาย AUX ที่ถูกต้องเข้ากับคอนเน็กเตอร์ DisplayPort ก็ใช้ได้
ราคาก็ดูสมเหตุสมผล
ตอนหาของคล้ายกันเมื่อ 2 ปีก่อน ราคาสูงกว่านี้อีกหนึ่งหลัก
เสียบ Raspberry Pi เข้ากับพีซีไว้ แล้วใช้ https://github.com/xairy/raw-gadget ทำ อุปกรณ์ USB เสมือน
ตอนนี้กำลังใช้เพื่อจำลองกล้อง MTP เพื่อหลอกซอฟต์แวร์ปิดซอร์สอยู่
เคยทำต้นแบบอุปกรณ์ USB อยู่บ้างด้วย Raspberry Pi Zero และ USB composite ของ Linux kernel
อย่างน้อยอุปกรณ์เก็บข้อมูลและอุปกรณ์ serial ก็ทำงานได้ค่อนข้างง่าย
ฝั่ง Raspberry Pi จะต้องมีอะไรอย่างเช่นเชลล์สคริปต์สำหรับเริ่มต้น composite kernel module และโค้ดสำเร็จรูปพวกนี้หาได้จากเอกสารของเคอร์เนล
pikvm ก็เป็นโปรเจกต์ที่น่าสนใจ
เมื่อเชื่อมต่อเข้ากับพีซีแล้ว USB connection ไม่ได้ทำงานแค่เป็นคีย์บอร์ดและเมาส์ แต่ยังอาจเป็นไดรฟ์ USB ที่ใช้ตอนบูตระบบได้ด้วย
เป็นวิธีที่น่าสนใจมากสำหรับงานติดตั้งระบบ