- Merangkum alur yang dibutuhkan saat pertama kali membuat perangkat USB, mulai dari pengkabelan fisik hingga PCB, kecepatan USB 2.0, lapisan protokol, dan praktik dengan STM32, agar bisa diikuti dari awal sampai akhir
- Koneksi dasar USB 2.0 terdiri dari empat kabel: +5V, GND, D+, D-;
D+ dan D- adalah pasangan diferensial yang bersama-sama membawa 1 bit
- Pada PCB, penyesuaian panjang, penempatan yang berdekatan, dan impedansi pasangan diferensial penting, tetapi prototipe full speed 12 Mbit/s bisa bekerja dengan toleransi yang relatif longgar
- Praktik dilakukan pada NUCLEO-F103RB dengan mengatur
PA12 sebagai USB_DP dan PA11 sebagai USB_DM, membuat perangkat USB serial yang dikenali sebagai port COM virtual CDC, lalu menyalakan LED dengan input 1
- Pendekatan STM32CubeIDE cukup membebani karena menggabungkan pembuatan kode berbasis UI dan boilerplate, sedangkan implementasi perangkat USB berbasis Linux dapat menyediakan API yang lebih terstandardisasi dan struktur yang lebih terpisah
Cakupan saat pertama kali mengimplementasikan USB
- Tujuannya adalah membuat perangkat USB dalam bentuk paling sederhana sampai selesai, sehingga dikenali saat dicolokkan ke komputer
- Di sini, perangkat berarti periferal yang memperluas fungsi komputer, sedangkan komputer disebut host
- Cakupannya meliputi koneksi fisik antara perangkat USB dan host hingga aplikasi sederhana yang berinteraksi dengan perangkat USB di host
- Ini lebih mirip proyek pembuatan perangkat USB E2E paling sederhana dan indeks referensi, bukan penjelasan spesifikasi yang otoritatif
Konsep dasar USB
- USB adalah standar industri yang memungkinkan pertukaran data dan penyediaan daya di antara berbagai perangkat elektronik
- USB adalah bus serial, sehingga bit dikirimkan satu per satu di atas bus, bukan secara paralel
- Bus modern umumnya menggunakan pendekatan serial, dan USB dapat dipahami sebagai cara untuk menukar bit secara serial antara host dan device
- USB mencakup bukan hanya spesifikasi fisik untuk menghubungkan dua perangkat dan bertukar bit, tetapi juga protokol komunikasi untuk transfer data dan penyaluran daya
- Penjelasan ini berfokus pada USB 2.0
Pengkabelan USB dan pasangan diferensial
- Koneksi USB 2.0 umum dapat dijelaskan dengan minimal empat kabel
+5 V: kabel yang digunakan host untuk memasok daya ke device
D-, D+: pasangan diferensial tempat dua kabel bekerja bersama untuk membawa 1 bit
GND: ground
- Beberapa koneksi bisa memiliki pin tambahan seperti
ID, tetapi praktik ini hanya membahas empat kabel di atas
-
Catatan tentang USB-C
- USB-C juga menggunakan pasangan diferensial secara internal, tetapi berbeda dari penjelasan USB 2.0 umum dalam hal harus tetap berfungsi meski dicolokkan terbalik, dan lain-lain
- Menggunakan konektor USB-C tidak otomatis menentukan kecepatan atau versi USB
- Perangkat USB-C bisa saja USB 2.0, atau bisa juga perangkat USB 3.0 yang lebih modern
- Praktik selanjutnya tidak membahas USB-C lebih jauh
-
Cara pasangan diferensial mengurangi noise
- Satu kabel tunggal mengekspresikan nilai bit dengan membandingkan tegangannya terhadap
GND, tetapi pada koneksi kabel yang panjang, pengaruh noise bisa menjadi lebih besar
- Pasangan diferensial menggunakan dua kabel; satu kabel membawa
V, kabel lainnya membawa -V
- Sisi penerima melihat selisih tegangan antara kedua kabel
- Jika disederhanakan bahwa noise yang sama
Vn ditambahkan ke kedua kabel, maka (V + Vn) - (-V + Vn) = 2V, sehingga noise saling meniadakan
- Model ini adalah penjelasan yang sangat disederhanakan; untuk memahami pasangan diferensial lebih dalam, video YouTube Altium dari Zach Peterson bisa dijadikan referensi
- Video 15
Menangani USB pada PCB
- Jika Anda menggunakan development board tanpa membuat hardware sendiri, bagian PCB bisa dilewati, tetapi prinsip dasar saat menaruh konektor USB di PCB tetap berguna
- Komponen library konektor USB memiliki pin-pin yang disebutkan sebelumnya, dan pasangan diferensial harus dirutekan ke pin terkait yang berdekatan pada mikrokontroler atau SoC
- Prinsip dasar routing pasangan diferensial ada tiga
- Samakan panjang trace dari
D+ ke pin plus pada chip dengan trace di sisi lainnya
- Tempatkan kedua trace sangat berdekatan satu sama lain
- Pertimbangkan impedansi yang sesuai untuk sinyal
- Karena kedua kabel dibuat melewati lingkungan yang hampir sama, pada model sederhana sebelumnya dapat diasumsikan bahwa noise pada kedua kabel sama
- Perhitungan impedansi dapat ditangani dengan memasukkan impedansi target, jarak ke ground plane, jarak antar pasangan diferensial, dan sebagainya ke kalkulator dari produsen untuk mendapatkan lebar trace yang diperlukan
- Video Zach Peterson tentang pasangan diferensial dan routing USB disertakan sebagai referensi
Kecepatan USB 2.0
- USB 2.0 tidak berarti kecepatannya tetap satu macam
- USB 2.0, misalnya, dapat memiliki dua tingkat kecepatan
- full speed: 12 Mbit/s
- high speed: 480 Mbit/s
- Device dan host harus menentukan kecepatan apa yang akan digunakan saat koneksi dibuat
- Untuk mencapai high speed secara stabil di atas PCB, pencocokan impedansi penting
- Pada prototipe dasar, full speed 12 Mbit/s bisa cukup, dan jika trace dari konektor USB ke chip pendek, lebar trace dan faktor serupa bisa relatif toleran
Lapisan protokol dan software
- USB tidak hanya mempertimbangkan hardware, tetapi juga lapisan software di sisi host dan device
- Video sekitar 45 menit yang menjelaskan USB dari sudut pandang Linux disertakan sebagai referensi yang direkomendasikan
- Video ini membahas USB frame, endpoint, configuration, cara satu device dapat menjalankan beberapa fungsi USB, dan sebagainya
- Sudut pandang yang penting adalah menganggap USB sebagai jaringan perangkat
- Karena tidak realistis bagi sistem operasi host untuk mengimplementasikan driver secara terpisah untuk setiap perangkat USB, sistem operasi mengenali berbagai USB device class
- mass storage device
- serial device
- dan berbagai class lainnya
- Perangkat praktik ini berfungsi sebagai perangkat serial port dari sudut pandang host
Membuat perangkat USB serial port dengan STM32
- Perangkat praktik ini adalah perangkat USB sederhana yang menyalakan LED saat menerima permintaan dari host
- Host mengenali perangkat ini sebagai serial port device
- Cara implementasinya secara garis besar terbagi dua
- Menggunakan mikrokontroler yang mendukung USB
- Menggunakan SoC yang dapat menjalankan Linux sehingga kernel menangani banyak pekerjaan
- Praktik ini menggunakan pendekatan mikrokontroler demi kesederhanaan
-
Board NUCLEO-F103RB
- Development board yang digunakan adalah NUCLEO-F103RB
- Di AS, board ini dapat dibeli di tempat seperti Digikey dengan harga sedikit di atas 10 dolar
- Board ini memiliki struktur dua bagian yang tersambung
- Bagian kecil adalah area programmer, bagian besar adalah area main MCU yang benar-benar akan diprogram
- Koneksi USB bawaan board terhubung ke MCU di sisi programmer, bukan main MCU
- Programmer ini menggunakan protokol ST-LINK untuk bertukar pesan USB dengan komputer, lalu memprogram main MCU
- Jika membuat PCB berbasis STM32 sendiri, Anda juga bisa hanya menaruh satu chip di board, memprogramnya lewat USB, lalu memakai port USB yang sama untuk logika perangkat
- Video Phil’s Lab disertakan sebagai referensi untuk PCB berbasis STM32 dan pemrograman USB
- Video 19
- Video 20
Pengkabelan port USB sebenarnya
- Karena koneksi USB bawaan board Nucleo tidak terhubung ke main MCU, port USB pada main MCU harus dihubungkan langsung ke host
- Setelah program diunggah, lepaskan ST-LINK programmer dari komputer, lalu pasok daya ke main MCU melalui port USB sebenarnya
- STM32CubeIDE digunakan untuk menulis software, dan STM32CubeProgrammer digunakan untuk mengunggahnya ke board
-
Pin dan pengaturan yang diperlukan
- Untuk membuat perangkat USB 2.0, diperlukan empat pin
- Daya 5V yang masuk dari host
GND
D+
D-
- Agar NUCLEO-F103RB menerima daya dari port USB sisi main MCU, jumper
JP5 harus diubah agar board diatur menerima pasokan external 5 V
- Di STM32CubeIDE, atur pin sebagai berikut
PA12 → USB_DP
PA11 → USB_DM
- Chip pada board ini memerlukan resistor pull-up 1.5 kΩ eksternal untuk koneksi USB
- Resistor melakukan pull-up
PA12 ke 3.3V
- Rangkaian ini disusun menggunakan breadboard
- Untuk menghubungkan MacBook Pro dengan pin-pin terpisah, digunakan USB breakout cable dari Amazon; terminal block dilepas untuk mengekspos pin USB, lalu dihubungkan ke board Nucleo dan breadboard dengan jumper wire
- Meski tidak secara ketat mengikuti penyesuaian panjang pasangan diferensial dan kontrol impedansi, koneksi 12 Mbit/s tetap dapat dilakukan dalam praktik ini
Menulis software USB CDC
- Saat pin USB dikonfigurasi di CubeIDE, muncul notifikasi terkait pengaturan clock, dan Anda dapat memilih opsi agar CubeIDE menanganinya secara otomatis
- Di
Pinout & Configuration, konfigurasikan USB_DEVICE di bawah Middleware and Software Packs
- Mode penting dalam praktik ini adalah sebagai berikut
Communication Device Class (Virtual Port Com)
- Dengan pengaturan ini, board Nucleo berfungsi sebagai perangkat CDC serial port dari sudut pandang host
- Berdasarkan informasi class ini, host dapat menyiapkan driver yang sesuai untuk berkomunikasi dengan custom device
- CubeIDE menghasilkan kode C, dan
main.c berisi pemanggilan inisialisasi berikut
MX_USB_DEVICE_Init();
- Untuk menyalakan LED, tambahkan kode berikut ke rutin
CDC_Receive_FS
/* USER CODE BEGIN 6 */
if (Buf[0] == '1') {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, 1);
}
- Pemanggilan HAL ini menyalakan LED onboard yang terhubung ke pin 5 pada port A
- Video referensi langkah demi langkah adalah sebagai berikut
Flashing dan menjalankan
- Setelah membangun file ELF, unggah kode ke board dengan CubeProgrammer
- Setelah itu lepaskan programmer, lalu kabelkan board menggunakan pasokan external 5V seperti dijelaskan sebelumnya
- Saat board menyala, perangkat seharusnya muncul di device manager sistem operasi sebagai item yang mirip COM port atau Serial port
- Jika nilai
Device Descriptor di menu middleware USB_DEVICE CubeIDE diubah, Anda dapat menetapkan custom device name yang akan ditampilkan di device manager sistem operasi
- Di Mac OS, perangkat baru muncul di bawah filesystem
/dev
- Contoh path:
/dev/tty.usbmodem497A0F6739561
- Di Linux, perangkat dapat terlihat dengan nama seperti
/dev/ttyUSB0
- Contoh menghubungkan ke serial device dengan Minicom adalah sebagai berikut
minicom --device /dev/tty.usbmodem497A0F6739561
- Setelah terhubung, masukkan
1 dari keyboard untuk menyalakan LED hijau pada board Nucleo
Perbedaan software antara pendekatan STM32 dan Linux
- Hasil praktik ini adalah membuat USB serial port device yang dikenali oleh sistem operasi mainstream
- Pendekatan berbasis STM32CubeIDE memiliki ketidaknyamanan dari sudut pandang rekayasa software
- Harus mengklik banyak menu UI untuk menghasilkan banyak boilerplate
- Bukan pendekatan memakai library yang fleksibel dan dapat diparameterkan dari kode, seperti
InitUsbDevice(UsbClass.CDC)
- Kode yang dihasilkan sangat terikat dengan kode pengguna, sehingga code review bisa menjadi sulit
- Tidak jelas bagaimana memperbarui boilerplate saat versi baru muncul
- Pengaturan saat ini sangat terikat pada ekosistem STM32
- Cara Linux berperilaku seperti USB device dinilai sebagai pendekatan yang lebih rapi
- API Linux lebih kokoh dan terstandardisasi
- Dapat berbasis interaksi dengan pseudo-file dan system call
- User space dan kernel space terpisah
- Linux dapat dipandang seperti lapisan HAL
- Namun, jika membutuhkan perangkat USB yang ringan, murah, dan mudah diproduksi, Linux SoC bisa terlalu berat, dan dalam banyak use case bisa berlebihan
- Kesimpulannya mengarah pada keinginan adanya framework yang lebih portable dan tidak terlalu opinionated untuk pengembangan perangkat USB bare metal
1 komentar
Opini Hacker News
Sebagai tulisan pengantar USB, ini sangat bagus, tetapi cukup condong ke penggunaan mikrokontroler ST, dan dibandingkan dengan cara yang memungkinkan perangkat USB dipasang dan dipakai dengan mudah seperti ekosistem ESP32 belakangan ini, langkah dan toolchain-nya terlihat jauh lebih banyak
Selain itu, dari sudut pandang orang yang pernah membuat beberapa board USB sendiri, differential pair bukanlah hal yang perlu terlalu dikhawatirkan pemula, dan terutama menjadi penting pada pekerjaan berkecepatan tinggi
IC pengontrol USB yang umum dipakai di Arduino/ESP menangani banyak detail, jadi meminta orang yang membuat perangkat pertamanya sampai melakukan perhitungan terasa berlebihan
Itu proyek yang cepat dan menyenangkan untuk pemula, dan bagian yang paling merepotkan adalah mengukir casing kayunya
Saya hampir tidak pernah benar-benar melakukan perhitungannya, dan software ECAD yang saya pakai menyediakan alat untuk routing differential pair serta analisis sinyal impedansi
Meski begitu, kalau trace dibuat sangat pendek, biasanya tidak ada masalah besar
Biasanya saya hanya memakai mikrokontroler dengan USB bawaan
Dulu sekali saya melakukan pengujian kesesuaian USB, dan salah satu item yang sering bermasalah adalah uji arus masuk (inrush current)
Pada dasarnya kasusnya adalah terlalu banyak kapasitor bypass di sisi 5V, dan sepertinya tulisan ini tidak membahas bagian tersebut
Mudah untuk berfokus pada desain digital berkecepatan tinggi, tetapi dalam kesesuaian, kadang bagian yang tampak kurang kerenlah yang menjegal
Saya tidak tahu bagaimana perilakunya di standar terbaru, tetapi tampaknya pengujian itu masih ada, dan tulisannya sendiri bagus
https://compliance.usb.org/index.asp?UpdateFile=Electrical#:...
Kita bisa membuat pembatas arus dengan beberapa transistor, tetapi sepertinya ada solusi terintegrasi yang lebih baik dengan fitur seperti perlindungan suhu
Untuk menambahkan isi tulisan mengenai USB-C, pin CC harus dihubungkan ke resistor yang sesuai
Kalau tidak, kemungkinan besar tidak akan berfungsi
Selain itu, differential routing dan impedansi bukan perkara sebesar itu pada USB 2.0
Cukup samakan panjang trace kurang lebih, hubungkan secara langsung dengan masuk akal, dan kalau bisa letakkan berdekatan
Tidak perlu terlalu memusingkan penyesuaian halus panjang/lebar trace, kontrol impedansi, sampai praktik terbaik RF; cukup hubungkan net-nya
Banyak MCU juga memerlukan resistor seri di antara pin USB PHY dan konektor
Mungkin tidak sampai harus membuat ulang board hanya karena perlu memakai trace 20mil alih-alih 24mil, tetapi meski layout differential pair USB 2.0 bebannya relatif rendah, berusaha melakukannya dengan benar adalah latihan yang baik
Jika khawatir dengan komponen yang sulit disolder seperti prosesor ARM, sebenarnya tidak perlu memakai komponen sebesar itu
STM32 bagus saat membutuhkan performa, tetapi untuk tugas kecil, pengontrol yang lebih kecil bisa lebih cocok
Misalnya, VUSB adalah library untuk melakukan bit-banging USB pada mikrokontroler Atmel kecil: https://www.obdev.at/products/vusb/index.html
Ada juga skematik board contoh yang saya pakai saat mengajar pemrograman modul kernel Linux kepada mahasiswa: https://gitlab.cs.fau.de/i4/passt/passtboard-v2
Firmware-nya ada di http://www.poempelfox.de/ds1820tousb/ dan https://gitlab.cs.fau.de/i4/passt/ds1820tousb
Jika lebih suka pemrograman gaya Arduino, ada banyak board yang bisa dipakai seperti perangkat USB hanya dengan beberapa baris library yang disertakan, misalnya https://www.az-delivery.de/en/products/digispark-board
Contohnya NUCLEO-F429ZI: https://www.st.com/en/evaluation-tools/nucleo-f429zi.html
Ini sangat mirip dengan NUCLEO-F103RB yang dipakai penulis, tetapi selain konektor USB atas untuk programmer/debugger bawaan, di bagian bawah juga ada konektor USB yang terhubung langsung ke mikrokontroler
Jika ingin menjadikannya referensi untuk pilihan seperti proteksi ESD, skematik board-nya juga bisa diunduh
Ini TSSOP-20 dengan USB hardware, dan harga satuannya sekitar 0,81 dolar
Namun sisi software-nya mungkin sedikit lebih rumit
https://www.wch-ic.com/products/CH32V203.html?
Saya pernah menulis kode USB bare-metal di MCU, dan dibandingkan dengan protokol digital sederhana seperti SPI atau I2C, rasanya cukup mengejutkan
Lapisan fisik dan lapisan data link memang tidak jauh lebih rumit daripada CAN, tetapi setelah itu langsung berhadapan dengan tembok berupa descriptor, endpoint, dan konfigurasi driver
USB sejak awal dirancang sebagai ekosistem plug-and-play untuk PC, dan karakteristik itu sangat terasa
Jika memungkinkan, memakai sebanyak mungkin perangkat lunak yang disediakan vendor jelas merupakan jalan yang lebih baik
Tip yang samar-samar saya ingat: untuk throughput tinggi gunakan bulk transfer, dan sebaiknya jangan lirik isochronous transfer sama sekali
USB adalah protokol master/slave, jadi jika throughput maksimum tidak tercapai, biasanya penyebabnya banyak di sisi PC sebagai host
Jika lisensi LGPL sesuai dengan persyaratan, libusb cukup mudah digunakan
Jika tidak memakai driver vendor, hardware USB protocol analyzer benar-benar berguna, dan USB in a NutShell cukup bagus sebagai referensi web untuk memahami protokol: https://www.beyondlogic.org/usbnutshell/usb1.shtml
Sekalian membahas USB di STM32, saya penasaran apakah ada yang tahu cara mendukung penerimaan lebih dari 64 byte dalam satu frame
Saat ini saya memproses frame 64 byte berulang-ulang di software, tetapi saya tahu ukuran yang lebih besar itu mungkin
Sepertinya dulu maksimalnya sampai 1 MB
Masalahnya, di Reference Manual pengaturan-pengaturan ini tercantum bukan sebagai register biasa, melainkan semacam pseudo-register
Saya penasaran apakah ada workaround yang mudah
Ini untuk periferal USB non-OTG
Tidak tahu STM32 mana yang dimaksud, tetapi stm32g4 hanya mendukung full-speed
Saya terutama memakai ESP32, tetapi ada cara hacking murah yang cocok untuk berbagai proyek
Jika butuh controller kustom yang sangat cepat dan mudah dibuat, layak juga mempertimbangkan mengambil papan kontrol dari keyboard USB bekas
Alih-alih menyolder, tempelkan kabel ke kontak dengan conductive adhesive, lalu kencangkan dengan lem tembak
Saya pernah membuat controller gim 1 tombol berbasis tombol arcade yang mengirim input spacebar; murah tetapi cukup kokoh, debounce dan lainnya sudah ditangani semua, dan tidak perlu kode
Saya penasaran apakah ada development board yang mendukung USB 3
Saya ingin membuat prototipe sink monitor USB-C, tetapi sulit menemukan board yang cukup bertenaga untuk menerima DisplayPort lewat USB
Dengan asumsi perangkat sudah bisa menerima sinyal DisplayPort atau merutekannya ke monitor eksternal
Cukup implementasikan USB billboard device dan sinyalkan alternate mode yang benar
Untuk operasinya sendiri itu opsional, tetapi seingat saya diperlukan menurut spesifikasi
Setelah itu sinyal DisplayPort akan keluar di colokan USB-C, dan tinggal sambungkan jalur AUX yang tepat ke konektor DisplayPort
Harganya juga terlihat masuk akal
Saat saya mencari yang serupa 2 tahun lalu, harganya satu digit lebih mahal
Saya mencolokkan Raspberry Pi ke PC dan membuat perangkat USB virtual dengan https://github.com/xairy/raw-gadget
Saat ini saya memakainya untuk mengemulasikan kamera MTP demi mengelabui software proprietary
Saya pernah membuat prototipe beberapa perangkat USB dengan Raspberry Pi Zero dan composite USB di kernel Linux
Setidaknya perangkat penyimpanan dan perangkat serial bisa dibuat berjalan cukup mudah
Diperlukan semacam shell script untuk menginisialisasi modul kernel composite di Raspberry Pi, dan kode boilerplate bisa ditemukan di dokumentasi kernel
pikvm juga proyek yang menarik
Saat dihubungkan ke PC, koneksi USB-nya tidak hanya berfungsi seperti keyboard dan mouse, tetapi juga bisa menjadi USB drive yang dapat dipakai untuk boot sistem
Ini cara yang cukup menarik untuk pekerjaan instalasi