2 poin oleh GN⁺ 2024-06-04 | 1 komentar | Bagikan ke WhatsApp
  • 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
    • PA12USB_DP
    • PA11USB_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

 
GN⁺ 2024-06-04
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

    • Baru-baru ini saya membuat macro pad hasil wiring manual dengan Arduino Pro Micro yang memakai ATmega32U4, dan tampaknya cukup populer di kalangan hobi pembuat keyboard kustom
      Itu proyek yang cepat dan menyenangkan untuk pemula, dan bagian yang paling merepotkan adalah mengukir casing kayunya
    • Menurut saya pemahaman dasar tentang differential pair dan impedansi bagus untuk dimiliki
      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
    • Saya ingin mendapat rekomendasi IC pengontrol USB
      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#:...

    • Saya penasaran komponen apa yang dipakai untuk pembatasan arus masuk
      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

    • 480Mbit/s itu sudah cukup cepat, jadi praktik terbaik dan pencocokan impedansi kira-kira dalam 10% tetap perlu diperhatikan
      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

    • Jika khawatir soal penyolderan, Anda bisa membeli development board dengan port USB mikrokontroler yang sudah terpasang dan berfungsi dengan harga yang cukup masuk akal
      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
    • Ada juga yang seperti CH32V203
      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

    • USB full-speed bulk transfer dibatasi 64 byte
      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

    • Untuk melakukan penerimaan DisplayPort lewat USB, tidak diperlukan performa besar
      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
    • Ada board seperti ini: https://octopart.com/cyusb3kit-003-cypress+semiconductor-494...
      Harganya juga terlihat masuk akal
      Saat saya mencari yang serupa 2 tahun lalu, harganya satu digit lebih mahal
    • Bisa dilakukan dengan sebagian besar FPGA yang memiliki transceiver
  • 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

    • Saya ingin mencoba membuat perangkat USB virtual seperti webcam dengan Pi
      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