<gambar dengan papan dan headphone>
Bahkan tingkat yang lebih rendah (avr-vusb): habr.com/ru/post/460815
USB pada register: STM32L1 / STM32F1
USB pada register: titik akhir massal menggunakan contoh
USB Penyimpanan Massal pada register: titik akhir interupsi pada contoh HID
Hari ini, mari kita lihat jenis endpoint terakhir, isochronous. Ini dirancang untuk mentransfer data yang penting untuk waktu pengiriman, tetapi tidak menjamin keberhasilannya. Contoh paling klasik adalah perangkat audio: speaker, mikrofon.
Anehnya, jenis titik akhir ini ternyata yang paling memompa otak (dan ini setelah semua yang saya lihat dengan stm'kami!). Namun demikian, hari ini kami akan membuat perangkat audio dan pada saat yang sama menyelesaikan sedikit inti dari perpustakaan USB. Seperti biasa, kode sumber tersedia:
github.com/COKPOWEHEU/usb/tree/main/4.Audio_L1
github.com/COKPOWEHEU/usb/tree/main/4.Audio_F1
Perbaikan kernel
Hal ini diperlukan untuk menyempurnakan kernel karena STM hanya dapat memiliki poin isochronous dengan buffering ganda, yaitu, secara kasar, tidak mungkin membuat 0x01 isochronous, dan kontrol 0x81. Yaitu, tentu saja, mungkin untuk menulis ini di deskriptor USB, tetapi ini tidak akan mengubah bagian dalam pengontrol, dan alamat sebenarnya dari titik hanya akan berbeda dari yang terlihat dari luar. Yang tentunya akan meningkatkan resiko kesalahan, agar kita tidak tersesat ke arah ini.
Perlu dicatat bahwa buffering ganda terjadi tidak hanya untuk titik-titik isochronous, tetapi juga untuk bulk, dan ini menyala serta bekerja secara berbeda. Jika titik isochronous mengaktifkan buffering secara otomatis, hanya karena tidak dapat dilakukan sebaliknya, maka untuk pengaturan massal yang sesuai, Anda harus menggunakan bit USB_EP_KIND khusus, yang harus diatur bersama dengan pengaturan jenis titik yang sebenarnya.
Dengan sendirinya, buffering berarti bahwa jika sebelumnya satu titik berhubungan dengan satu buffer untuk transmisi dan satu untuk penerimaan, sekarang kedua buffer akan bekerja baik untuk transmisi atau penerimaan, dan mereka hanya akan bekerja sama. Akibatnya, pengaturan titik buffer sangat berbeda dari biasanya, karena Anda perlu mengkonfigurasi bukan hanya satu buffer, tetapi dua. Oleh karena itu, kami tidak akan memahat kondisi yang tidak perlu menjadi inisialisasi biasa, tetapi membuat fungsi terpisah usb_ep_init_double () berdasarkan itu.
Penerimaan dan transmisi paket tidak berbeda jauh, meskipun butuh waktu lebih lama untuk mencoba memahami bagaimana seharusnya bekerja sesuai dengan logika ST, kemudian menyesuaikan mantra dari Internet untuk membuatnya berfungsi. Seperti yang disebutkan sebelumnya, jika untuk titik biasa dua buffer tidak bergantung dan berbeda dalam arah pertukaran, maka untuk buffered keduanya sama dan hanya berbeda dalam offset. Jadi mari kita ubah sedikit fungsi usb_ep_write dan usb_ep_read sehingga mereka tidak menerima nomor poin, tetapi nomor offset. Artinya, jika sebelumnya fungsi-fungsi ini mengasumsikan keberadaan delapan titik ganda, sekarang - 16 titik tunggal. Karenanya, jumlah "setengah baris" baru untuk menulis hanya jumlah yang biasa, dikalikan dua, dan untuk usb_ep_read juga harus ditambah satu (lihat alokasi buffer di PMA). Sebenarnya,ini dilakukan oleh fungsi sebaris usb_ep_write dan usb_ep_read untuk poin reguler. Tapi mari kita lihat lebih dekat logika buffer.
Menurut dokumentasi, satu buffer dari titik seperti itu tersedia untuk perangkat keras, yang kedua untuk perangkat lunak. Kemudian mereka beralih dan sekali lagi tidak saling mengganggu. Untuk titik OUT, bendera di sisi perangkat keras adalah bit USB_EP_DTOG_RX, yang perlu dibaca untuk memahami buffer mana yang baru saja selesai menulis dan dari mana perangkat lunak dapat membaca, masing-masing. Ketika dia membaca buffernya, Anda perlu menyentak bit USB_EP_DTOG_TX, yang sebenarnya mengganti buffer. Tidak yakin apakah ini yang dimaksud, tetapi setidaknya berhasil.
Situasi simetris seharusnya dengan poin IN. Namun dalam praktiknya, ternyata Anda perlu memeriksa dan menarik USB_EP_DTOG_RX. Kenapa tidak TX Saya masih belum mengerti ... Terima kasih kepada pengguna kuzulis untuk tautannya github.com/dmitrystu/libusb_stm32/edit/master/src/usbd_stm32f103_devfs.c
Karena fungsi sebaris, tidak ada overhead khusus yang ditambahkan, selain dari inisialisasi. Tapi Anda bisa, jika mau, membuangnya dengan flag linker. Atau Anda tidak perlu membuangnya: tidak memakan banyak ruang, dan dipanggil hanya selama inisialisasi. Ini bukan HAL untuk Anda, di mana fungsinya tidak hanya berat, tetapi juga saling memanggil sepanjang waktu.
Hasilnya, titik akhir telah belajar untuk bekerja dalam mode buffer ... jika Anda tidak menghirupnya terlalu keras.
Untuk pengguna, perbedaannya kecil: alih-alih usb_ep_init, gunakan usb_ep_init_double, dan alih-alih usb_ep_write dan usb_ep_read, gunakan masing-masing usb_ep_write_double dan usb_ep_read_double.
Perangkat AudioDevice
Dan sekarang, ketika kita mengetahui penggaruk teknisnya, mari beralih ke hal yang paling menarik - menyiapkan perangkat audio.
Menurut standar USB, perangkat audio adalah sekumpulan entitas yang terhubung satu sama lain dalam topologi tertentu, yang dilalui sinyal audio. Setiap entitas memiliki nomor uniknya sendiri (bTerminalID, alias UnitID), yang dengannya entitas atau titik akhir lain dapat terhubung dengannya, host juga menggunakannya jika ingin mengubah beberapa parameter. Dan dia dianggap satu-satunya jalan keluar dari entitas ini. Tetapi mungkin tidak ada input sama sekali (jika itu adalah terminal input), atau mungkin ada lebih dari satu (bSourceID). Sebenarnya, dengan menulis nomor entitas yang menerima sinyal audio saat ini ke array bSourceID, kami mendeskripsikan keseluruhan topologi, yang hasilnya bisa menjadi sangat cepat. Misalnya, saya akan memberikan topologi kartu suara USB yang dibeli (angka menunjukkan bTerminalID / UnitID):
lsusb dan dekripsinya
Bus 001 Device 014: ID 0d8c:013c C-Media Electronics, Inc. CM108 Audio Controller
#
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x0d8c C-Media Electronics, Inc.
idProduct 0x013c CM108 Audio Controller
bcdDevice 1.00
iManufacturer 1
iProduct 2
iSerial 0
bNumConfigurations 1
#
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x00fd
bNumInterfaces 4 #
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 100mA
# 0 -
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 1 Audio
bInterfaceSubClass 1 Control Device
bInterfaceProtocol 0
iInterface 0
AudioControl Interface Descriptor:
bLength 10
bDescriptorType 36
bDescriptorSubtype 1 (HEADER)
bcdADC 1.00
wTotalLength 0x0064
bInCollection 2 # ! (2)
baInterfaceNr(0) 1 #
baInterfaceNr(1) 2 #
##### #####
# 1 InputTerminal (USB, )
AudioControl Interface Descriptor:
bLength 12
bDescriptorType 36
bDescriptorSubtype 2 (INPUT_TERMINAL)
bTerminalID 1 #
wTerminalType 0x0101 USB Streaming
bAssocTerminal 0
bNrChannels 2 #
wChannelConfig 0x0003 # -
Left Front (L)
Right Front (R)
iChannelNames 0
iTerminal 0
# 2 InputTerminal ()
AudioControl Interface Descriptor:
bLength 12
bDescriptorType 36
bDescriptorSubtype 2 (INPUT_TERMINAL)
bTerminalID 2
wTerminalType 0x0201 Microphone
bAssocTerminal 0
bNrChannels 1
wChannelConfig 0x0001
Left Front (L)
iChannelNames 0
iTerminal 0
# 6 OutputTerminal (), 9
AudioControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 3 (OUTPUT_TERMINAL)
bTerminalID 6
wTerminalType 0x0301 Speaker
bAssocTerminal 0
bSourceID 9 #
iTerminal 0
# 7 OutputTerminal (USB), 8
AudioControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 3 (OUTPUT_TERMINAL)
bTerminalID 7
wTerminalType 0x0101 USB Streaming
bAssocTerminal 0
bSourceID 8
iTerminal 0
# 8 Selector, 10
AudioControl Interface Descriptor:
bLength 7
bDescriptorType 36
bDescriptorSubtype 5 (SELECTOR_UNIT)
bUnitID 8
bNrInPins 1 #
baSourceID(0) 10 #
iSelector 0
# 9 Feature, 15
AudioControl Interface Descriptor:
bLength 10
bDescriptorType 36
bDescriptorSubtype 6 (FEATURE_UNIT)
bUnitID 9
bSourceID 15
bControlSize 1
bmaControls(0) 0x01
Mute Control
bmaControls(1) 0x02
Volume Control
bmaControls(2) 0x02
Volume Control
iFeature 0
# 10 Feature, 2
AudioControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 6 (FEATURE_UNIT)
bUnitID 10
bSourceID 2
bControlSize 1
bmaControls(0) 0x43
Mute Control
Volume Control
Automatic Gain Control
bmaControls(1) 0x00
iFeature 0
# 13 Feature, 2
AudioControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 6 (FEATURE_UNIT)
bUnitID 13
bSourceID 2
bControlSize 1
bmaControls(0) 0x03
Mute Control
Volume Control
bmaControls(1) 0x00
iFeature 0
# 15 Mixer, 1 13
AudioControl Interface Descriptor:
bLength 13
bDescriptorType 36
bDescriptorSubtype 4 (MIXER_UNIT)
bUnitID 15
bNrInPins 2 #
baSourceID(0) 1 #
baSourceID(1) 13
bNrChannels 2
wChannelConfig 0x0003
Left Front (L)
Right Front (R)
iChannelNames 0
bmControls(0) 0x00
iMixer 0
##### #####
# 1 () -
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 0
# 1 () -
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 1
bNumEndpoints 1
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 0
AudioStreaming Interface Descriptor:
bLength 7
bDescriptorType 36
bDescriptorSubtype 1 (AS_GENERAL)
bTerminalLink 1
bDelay 1 frames
wFormatTag 0x0001 PCM
AudioStreaming Interface Descriptor:
bLength 14
bDescriptorType 36
bDescriptorSubtype 2 (FORMAT_TYPE)
bFormatType 1 (FORMAT_TYPE_I)
bNrChannels 2
bSubframeSize 2
bBitResolution 16
bSamFreqType 2 Discrete
tSamFreq[ 0] 48000
tSamFreq[ 1] 44100
Endpoint Descriptor:
bLength 9
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 9
Transfer Type Isochronous
Synch Type Adaptive
Usage Type Data
wMaxPacketSize 0x00c8 1x 200 bytes
bInterval 1
bRefresh 0
bSynchAddress 0
AudioStreaming Endpoint Descriptor:
bLength 7
bDescriptorType 37
bDescriptorSubtype 1 (EP_GENERAL)
bmAttributes 0x01
Sampling Frequency
bLockDelayUnits 1 Milliseconds
wLockDelay 0x0001
# 2 () -
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 2
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 0
# 2 ()
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 2
bAlternateSetting 1
bNumEndpoints 1
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 0
AudioStreaming Interface Descriptor:
bLength 7
bDescriptorType 36
bDescriptorSubtype 1 (AS_GENERAL)
bTerminalLink 7
bDelay 1 frames
wFormatTag 0x0001 PCM
AudioStreaming Interface Descriptor:
bLength 14
bDescriptorType 36
bDescriptorSubtype 2 (FORMAT_TYPE)
bFormatType 1 (FORMAT_TYPE_I)
bNrChannels 1
bSubframeSize 2
bBitResolution 16
bSamFreqType 2 Discrete
tSamFreq[ 0] 48000
tSamFreq[ 1] 44100
Endpoint Descriptor:
bLength 9
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 9
Transfer Type Isochronous
Synch Type Adaptive
Usage Type Data
wMaxPacketSize 0x0064 1x 100 bytes
bInterval 1
bRefresh 0
bSynchAddress 0
AudioStreaming Endpoint Descriptor:
bLength 7
bDescriptorType 37
bDescriptorSubtype 1 (EP_GENERAL)
bmAttributes 0x01
Sampling Frequency
bLockDelayUnits 0 Undefined
wLockDelay 0x0000
##### #####
# 3 " " ( )
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 3
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.00
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 60
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x87 EP 7 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0004 1x 4 bytes
bInterval 2
Kami akan melakukan sesuatu yang lebih sederhana (saya kosongkan dari sini ):
Di sini Anda dapat melihat dua cabang propagasi sinyal independen: baik dari USB melalui "fitur" ke "speaker", atau dari "mikrofon" melalui "fitur lain" Ke USB. Mikrofon dan speaker tidak hanya diberi tanda kutip: mereka tidak ada di papan debug saya, jadi alih-alih suaranya sendiri, kami akan menggunakan tombol dan LED. Namun, bukan hal baru. "Fitur" dalam kasus saya tidak melakukan apa-apa dan ditambahkan lebih banyak untuk kecantikan.
Ini harus diklarifikasi segera bahwa sinyal dalam model ini dianggap terdiri dari satu atau lebih saluran logis. Artinya, jika, misalnya, saya mengubah speaker mono ke stereo, topologinya sendiri tidak akan berubah, hanya format sinyal yang akan berubah.
Saya tidak menggali jauh ke dalam perbedaan antara jenis "fitur" dan entitas lain, tetapi saya tidak akan meremehkan untuk menceritakan kembali sebuah dokumentasi.
1. Terminal Input
Seperti namanya, melalui itu sinyal audio memasuki perangkat audio. Bisa berupa USB, bisa berupa mikrofon biasa, mikrofon headset, bahkan rangkaian mikrofon.
2. Terminal Output
Hal ini juga cukup jelas - bahwa melalui mana suara meninggalkan perangkat kita. Bisa berupa USB yang sama, bisa berupa speaker, headset, speaker di monitor, speaker berbagai frekuensi, dan banyak perangkat lain.
3. Unit Pengaduk
Dibutuhkan beberapa sinyal masukan, memperkuat masing-masing dengan jumlah yang telah ditentukan, dan menambahkan hasilnya ke saluran keluaran. Jika diinginkan, Anda dapat mengatur keuntungan menjadi nol, yang akan menguranginya ke entitas berikutnya.
4. Unit Selektor
Mengambil beberapa sinyal input dan mengarahkan salah satunya ke output.
5. Filter (Unit Fitur)
Mengambil sinyal input tunggal, mengubah parameter suara (volume, nada, dll.) Dan mengeluarkannya ke output. Secara alami, semua parameter ini diterapkan ke seluruh sinyal dengan cara yang sama, tanpa interaksi saluran logis di dalamnya
6. Unit Pemrosesan
Tetapi hal ini sudah memungkinkan Anda untuk memanipulasi saluran logis individu dalam setiap masukan. Selain itu, ini memungkinkan Anda untuk membuat jumlah saluran logis di output tidak sama dengan angka di input.
7. Unit Ekstensi
Seluruh rangkaian entitas non-standar, sehingga fantasi sakit dari produsen peralatan itu gratis. Karenanya, baik perilaku maupun latar akan bergantung pada fantasi ini.
Beberapa entitas memiliki parameter seperti perolehan atau nomor saluran, yang dapat dipengaruhi oleh host menggunakan kueri setFeature / getFeature pada nomor entitas. Tapi di sini, sejujurnya, saya sama sekali tidak mengerti bagaimana cara memeriksanya. Mungkin, Anda memerlukan perangkat lunak khusus, yang tidak saya miliki. Yah, oke, bagaimanapun aku masuk ke dalamnya hanya untuk memeriksa semua jenis poin ... di kepalaku ...
Rake deskriptor
Tidak seperti perangkat USB sebelumnya, deskripsi di sini rumit, berlapis-lapis dan cenderung menakut-nakuti Windows menjadi BSOD. Seperti yang kita lihat di atas, topologi perangkat autologus bisa sangat kompleks dan menyebar. Seluruh antarmuka menonjol karena deskripsinya. Jelas, itu tidak akan berisi titik akhir, tetapi akan berisi daftar deskriptor entitas dan deskripsi tentang apa input mereka terhubung. Saya tidak melihat banyak arti di sini, lebih mudah untuk melihat kode dan dokumentasinya. Saya hanya akan mencatat penggaruk utama: di sini dijelaskan antarmuka mana dengan titik akhir yang sesuai merujuk secara khusus ke perangkat ini. Misalnya, jika Anda ingin mengubah konfigurasi saya dan menghapus speaker dari sana, Anda tidak hanya perlu menghapus setengah dari entitas (terima kasih makro, setidaknya tidak akan ada masalah dengan menghitung panjang deskriptor), tetapi juga kurangi bidang bInCollection menjadi 1,kemudian hapus nomor antarmuka ekstra dari larik bInterfaceNr yang mengikutinya.
Selanjutnya ada antarmuka yang bertanggung jawab untuk pertukaran data. Dalam kasus saya, antarmuka pertama bertanggung jawab untuk mikrofon, dan yang kedua untuk speaker. Perlu diperhatikan di sini, pertama-tama, dua varian dari masing-masing antarmuka ini. Satu dengan bAlternateSetting sama dengan 0, yang kedua dengan 1. Keduanya berbeda dalam keberadaan titik akhir. Artinya, jika perangkat kami sedang tidak digunakan, host hanya beralih ke antarmuka alternatif tersebut, yang tidak dilengkapi dengan titik akhir, dan tidak lagi membuang bandwidth bus padanya.
Fitur kedua dari antarmuka data adalah format sinyal audio. Deskriptor terkait menentukan jenis pengkodean, jumlah saluran, resolusi dan laju pengambilan sampel (yang ditentukan oleh nomor 24-bit). Ada beberapa opsi pengkodean, tetapi kami akan menggunakan yang paling sederhana - PCM. Faktanya, ini hanyalah urutan nilai dari nilai sesaat sinyal tanpa pengkodean apa pun, dan nilainya dianggap sebagai bilangan bulat bertanda . Resolusi sinyal disetel di dua tempat (tidak jelas mengapa): bidang bSubFrameSize menentukan jumlah byte , dan bBitResolution menentukan jumlah bit... Mungkin dapat ditunjukkan bahwa kisaran kartu suara kita tidak mencapai seluruh jenis data, katakanlah int16_t dan hanya 10 bit.
Dan akhirnya, deskripsi titik akhir yang sebenarnya. Ini juga sedikit berbeda dari yang biasa, karena menyediakan, pertama, beberapa opsi sinkronisasi, dan kedua, jumlah entitas yang terkait dengan titik ini (bTerminalLink) . Opsi sinkronisasi ditulis dalam bit orde tinggi langsung ke jenis titik akhir (itulah sebabnya titik isochronous telah dipindahkan ke cabang default dalam fungsi inisialisasi), tetapi saya belum membahas detailnya, jadi saya tidak dapat memberi tahu Anda ada yang menarik. Alih-alih sinkronisasi, kita akan menggunakan pengatur waktu pengontrol biasa, yang akan menghasilkan interupsi kira-kira pada frekuensi yang diinginkan.
Oh ya, saya hampir lupa menyebutkan sekelompok BSOD lain saat menguji deskriptor yang salah. Izinkan saya mengingatkan Anda lagi: jumlah antarmuka data harus sesuai dengan jumlah bInCollection, dan jumlahnya harus sesuai dengan larik yang mengikutinya!
Teks tersembunyi
, , . --.
Logika perangkat
Seperti yang sudah saya katakan, untuk pengujian tidak masuk akal untuk menyertakan komponen berengsel pada papan debug, jadi semua pengujian akan dilakukan dengan apa yang telah dipasang - tombol dan LED. Namun, dalam kasus ini, ini bukan merupakan masalah: "mikrofon" dapat dengan mudah menghasilkan sinusoid dengan frekuensi, katakanlah, 1 kHz, dan "speaker" menyalakan LED ketika nilai ambang batas suara terlampaui (misalnya , di atas 10.000: dengan resolusi 16 bit yang ditentukan, yang sesuai dengan kisaran -32768 ... +32767, ini sekitar sepertiga).
Tetapi dengan pengujian, masalah kecil muncul: Saya tidak menemukan cara mudah untuk mengarahkan sinyal dari mikrofon ke stdin dari beberapa program. Tampaknya sebelumnya ini dilakukan hanya dengan membaca / dev / dsp, tetapi sekarang ada sesuatu yang rusak. Namun, tidak ada yang kritis, karena ada berbagai macam perpustakaan untuk interaksi dengan multimedia - SDL, SFLM dan lainnya. Sebenarnya di SFML saya menulis utilitas sederhana untuk membaca dari mikrofon dan, jika perlu, memvisualisasikan sinyalnya.
Saya akan memberi perhatian khusus pada batasan perangkat audio kami: sejauh yang saya mengerti, permintaan IN isochronous dikirim sekali per milidetik (tetapi mungkin ada banyak OUT), yang membatasi laju pengambilan sampel. Katakanlah ukuran titik akhir adalah 64 byte (dengan mempertimbangkan buffering, dibutuhkan 128 byte dalam memori, tetapi tuan rumah tidak mengetahuinya), resolusinya adalah 16 bit, yaitu 32 sampel dapat dikirim sekaligus . Diberikan interval 1 ms, kami mendapatkan batas teoritis 32 kHz untuk satu saluran. Cara termudah untuk menyiasatinya adalah dengan meningkatkan ukuran titik akhir. Namun disini harus kita ingat bahwa ukuran total buffer PMA hanya 512 bytes. Dikurangi tabel distribusi titik, dikurangi ep0, kami mendapatkan maksimum 440 byte, yaitu 220 byte per titik tunggal, dengan mempertimbangkan buffering. Dan ini adalah batas teoritis.
Tetapi fakta bahwa tuan rumah dapat mengirim beberapa permintaan KELUAR dalam satu bingkai menunjukkan bahwa perangkat dapat melakukan hal yang sama. Masih harus dipahami bagaimana caranya. Mungkin ini diselesaikan dengan pengaturan sinkronisasi yang kompeten. Tetapi bagi saya pertanyaan ini tidak lagi menarik: titik isochronous berfungsi, titik buffer berfungsi, perangkat audio berfungsi - tugas selesai.
Kesimpulan (umum untuk siklus)
Nah, kami berkenalan dengan perangkat USB di pengontrol STM32F103 dan STM32L151 (dan lainnya dengan implementasi serupa), terkejut dengan logika beberapa solusi arsitektur (saya sangat terkesan dengan register USB_EPnR, namun, buffering ganda juga tidak tertinggal belakang), memeriksa semua jenis titik akhir dan memeriksanya, dengan membangun perangkat yang sesuai. Jadi kita dapat mengatakan bahwa rangkaian artikel ini telah sampai pada kesimpulan yang logis. Meskipun ini, tentu saja, tidak berarti bahwa saya akan meninggalkan pengontrol atau USB: dalam rencana yang jauh, saya masih harus berurusan dengan perangkat komposit (sejauh ini terlihat mudah, tetapi poin isochronous juga bukan pertanda baik) dan USB pada pengontrol keluarga lain.