USB-Ein-Register: isochroner Endpunkt am Beispiel eines AudiogerÀts

Bild<Bild mit

Karte und Kopfhörer> Noch niedrigere Ebene (avr-vusb): habr.com/ru/post/460815

USB -Einschaltregister : STM32L1 / STM32F1

USB -Einschaltregister: Massenendpunkt am Beispiel von Massenspeicher

USB auf Registern: Interrupt-Endpunkt am HID-Beispiel



Schauen wir uns heute den letzten Typ des Endpunkts an, der isochron ist. Es wurde entwickelt, um Daten zu ĂŒbertragen, die fĂŒr die Lieferzeit von entscheidender Bedeutung sind, garantiert jedoch nicht den Erfolg. Das klassischste Beispiel sind AudiogerĂ€te: Lautsprecher, Mikrofone.



Seltsamerweise stellte sich heraus, dass diese Art von Endpunkt am meisten Gehirn pumpt (und das nach allem, was ich mit stm'kami gesehen habe!). Trotzdem werden wir heute ein AudiogerĂ€t herstellen und gleichzeitig den Kern der USB-Bibliothek leicht fertigstellen. Wie ĂŒblich sind die Quellcodes verfĂŒgbar:

github.com/COKPOWEHEU/usb/tree/main/4.Audio_L1

github.com/COKPOWEHEU/usb/tree/main/4.Audio_F1



Kernel-Verfeinerung



Es ist notwendig, den Kernel zu verfeinern, da STM nur isochrone Punkte mit doppelter Pufferung haben kann, dh grob gesagt ist es unmöglich, 0x01 isochron und 0x81 zu steuern. Das heißt, es ist natĂŒrlich möglich, dies in den USB-Deskriptor zu schreiben, aber dies Ă€ndert nichts an der Innenseite des Controllers, und die tatsĂ€chliche Adresse des Punkts unterscheidet sich einfach von der von außen sichtbaren. Das erhöht natĂŒrlich das Fehlerrisiko, sodass wir nicht in diese Richtung pervertiert werden.



Es ist zu beachten, dass die doppelte Pufferung nicht nur fĂŒr isochrone Punkte, sondern auch fĂŒr die Masse auftritt und sich einschaltet und anders funktioniert. Wenn isochrone Punkte die Pufferung automatisch aktivieren, einfach weil sie nichts anderes können, mĂŒssen Sie fĂŒr die entsprechende Bulk-Einstellung das spezielle USB_EP_KIND-Bit verwenden, das zusammen mit der tatsĂ€chlichen Punkttypeinstellung gesetzt werden muss.



Pufferung bedeutet fĂŒr sich genommen, dass, wenn zuvor ein Punkt einem Puffer zum Senden und einem zum Empfangen entsprach, beide Puffer entweder zum Senden oder zum Empfangen arbeiten und nur zusammenarbeiten. Infolgedessen unterscheidet sich die Einstellung eines gepufferten Punkts stark von der ĂŒblichen, da Sie nicht einen Puffer, sondern zwei konfigurieren mĂŒssen. Daher werden wir keine unnötigen Bedingungen in die ĂŒbliche Initialisierung umwandeln, sondern darauf basierend eine separate Funktion usb_ep_init_double () erstellen.



Das Empfangen und Senden von Paketen unterscheidet sich nicht so sehr, obwohl es viel lĂ€nger gedauert hat, zuerst zu versuchen, zu verstehen, wie es gemĂ€ĂŸ der ST-Logik funktionieren sollte, und dann den Zauber aus dem Internet anzupassen, damit es funktioniert. Wie bereits erwĂ€hnt, sind zwei Puffer fĂŒr einen gewöhnlichen Punkt unabhĂ€ngig und unterscheiden sich in der Austauschrichtung. Bei einem gepufferten Puffer sind sie gleich und unterscheiden sich nur im Versatz. Ändern wir also die Funktionen usb_ep_write und usb_ep_read ein wenig, sodass sie keine Punktnummer, sondern eine Versatznummer akzeptieren. Das heißt, wenn diese Funktionen frĂŒher die Existenz von acht Doppelpunkten angenommen haben, jetzt - 16 Einzelpunkte. Dementsprechend ist die Nummer der neuen "halben Zeile" zum Schreiben nur die Nummer der ĂŒblichen, multipliziert mit zwei, und fĂŒr usb_ep_read muss man auch eine hinzufĂŒgen (siehe die Zuordnung der Puffer in der PMA). TatsĂ€chlich,Dies erfolgt durch die Inline-Funktionen usb_ep_write und usb_ep_read fĂŒr regulĂ€re Punkte. Aber schauen wir uns die gepufferte Logik genauer an.



GemĂ€ĂŸ der Dokumentation steht ein Puffer eines solchen Punktes fĂŒr Hardware zur VerfĂŒgung, der zweite fĂŒr Software. Dann wechseln sie und stören sich wieder nicht. FĂŒr den OUT-Punkt ist das Flag auf der Hardwareseite das USB_EP_DTOG_RX-Bit, das gelesen werden muss, um zu verstehen, welcher der Puffer gerade fertig geschrieben wurde und von wo aus die Software lesen kann. Wenn er seinen Puffer liest, mĂŒssen Sie das USB_EP_DTOG_TX-Bit ruckeln, das die Puffer tatsĂ€chlich schaltet. Ich bin mir nicht sicher, ob dies gemeint ist, aber es funktioniert zumindest.



Eine symmetrische Situation sollte mit IN-Punkten gewesen sein. In der Praxis stellte sich jedoch heraus, dass Sie USB_EP_DTOG_RX ĂŒberprĂŒfen und abrufen mĂŒssen. Warum nicht TX verstehe ich immer noch nicht ... Danke an den User kuzulis fĂŒr den Link zu github.com/dmitrystu/libusb_stm32/edit/master/src/usbd_stm32f103_devfs.c



Aufgrund der Inline-Funktion wurde außer der Initialisierung kein spezieller Overhead hinzugefĂŒgt. Aber Sie können es, wenn Sie möchten, mit den Linker-Flags wegwerfen. Oder Sie mĂŒssen es nicht wegwerfen: Es nimmt nicht so viel Platz ein und wird nur wĂ€hrend der Initialisierung aufgerufen. Dies ist keine HAL fĂŒr Sie, bei der Funktionen nicht nur schwer sind, sondern sich auch stĂ€ndig gegenseitig anrufen.



Infolgedessen haben die Endpunkte gelernt, im gepufferten Modus zu arbeiten ... wenn Sie nicht zu schwer atmen.



FĂŒr den Benutzer ist der Unterschied gering: Verwenden Sie anstelle von usb_ep_init usb_ep_init_double und anstelle von usb_ep_write und usb_ep_read usb_ep_write_double bzw. usb_ep_read_double.



AudioDevice-GerÀt



Und jetzt, als wir den technischen Rechen herausgefunden haben, gehen wir zum interessantesten ĂŒber - dem Einrichten eines AudiogerĂ€ts.



GemĂ€ĂŸ dem USB-Standard ist ein AudiogerĂ€t eine Reihe von EntitĂ€ten, die in einer bestimmten Topologie miteinander verbunden sind, durch die das Audiosignal geleitet wird. Jede EntitĂ€t hat ihre eigene eindeutige Nummer (bTerminalID, auch bekannt als UnitID), ĂŒber die andere EntitĂ€ten oder Endpunkte eine Verbindung herstellen können. Der Host verwendet sie auch, wenn er einige Parameter Ă€ndern möchte. Und er gilt als der einzige Ausweg aus dieser EntitĂ€t. Möglicherweise sind jedoch ĂŒberhaupt keine EingĂ€nge vorhanden (wenn es sich um einen Eingangsanschluss handelt), oder es gibt möglicherweise mehr als einen (bSourceID). Indem wir die Nummern der EntitĂ€ten, von denen die aktuelle EntitĂ€t ein Audiosignal empfĂ€ngt, in das bSourceID-Array schreiben, beschreiben wir die gesamte Topologie, was sich als sehr schnell herausstellen kann. Zum Beispiel werde ich die Topologie einer gekauften USB-Soundkarte angeben (die Zahlen zeigen bTerminalID / UnitID):



lsusb und seine EntschlĂŒsselung
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

      
      









Bild



Wir werden etwas Einfacheres tun (ich habe das Leerzeichen von hier genommen ):



Bild



Hier sehen Sie zwei unabhĂ€ngige Signalausbreitungszweige: entweder von USB ĂŒber eine „Funktion“ zu einem „Lautsprecher“ oder von einem „Mikrofon“ ĂŒber eine andere „Funktion“ ”Auf USB. Das Mikrofon und der Lautsprecher werden nicht nur in AnfĂŒhrungszeichen gesetzt: Sie befinden sich nicht auf meinem Debug-Board. Daher verwenden wir anstelle des Sounds selbst Tasten und LEDs. Allerdings nichts Neues. "Features" in meinem Fall tun nichts und werden mehr fĂŒr die Schönheit hinzugefĂŒgt.



Es sollte sofort klargestellt werden, dass das Signal in diesem Modell aus einem oder mehreren logischen KanĂ€len besteht. Das heißt, wenn ich zum Beispiel einen Mono-Lautsprecher in einen Stereo-Lautsprecher Ă€ndere, bleibt die Topologie selbst unverĂ€ndert, nur das Signalformat Ă€ndert sich.



Ich habe mich nicht eingehend mit den Unterschieden zwischen den Arten von "Features" und anderen EntitÀten befasst, aber ich werde es nicht verachten, eine Dokumentation erneut zu erzÀhlen.



1. Eingangsanschluss

Wie der Name schon sagt, gelangt das Audiosignal ĂŒber das Terminal in das AudiogerĂ€t. Es kann USB sein, es kann ein gewöhnliches Mikrofon, ein Headset-Mikrofon oder sogar ein Mikrofonarray sein.



2. Ausgangsanschluss

Es ist auch ziemlich offensichtlich, dass der Ton unser GerÀt verlÀsst. Es kann sich um denselben USB-Anschluss handeln, es kann sich um einen Lautsprecher, ein Headset, einen Lautsprecher im Monitor, Lautsprecher mit verschiedenen Frequenzen und eine Reihe anderer GerÀte handeln.



3. Mischereinheit

Es nimmt mehrere Eingangssignale auf, verstĂ€rkt jedes um einen vorbestimmten Betrag und addiert das Ergebnis zum Ausgangskanal. Falls gewĂŒnscht, können Sie die VerstĂ€rkung auf Null setzen, wodurch sie auf die nĂ€chste EntitĂ€t reduziert wird.



4. Selector Unit

Nimmt mehrere Eingangssignale auf und leitet eines davon zum Ausgang um.



5. Filter (Feature Unit)

Nimmt ein einzelnes Eingangssignal auf, Ă€ndert die Klangparameter (LautstĂ€rke, Ton usw.) und gibt es an den Ausgang aus. NatĂŒrlich werden alle diese Parameter auf die gleiche Weise auf das gesamte Signal angewendet, ohne dass logische KanĂ€le darin interagieren.



6. Verarbeitungseinheit

Mit dieser Funktion können Sie jedoch bereits einzelne logische KanĂ€le in jedem Eingang bearbeiten. DarĂŒber hinaus können Sie festlegen, dass die Anzahl der logischen KanĂ€le im Ausgang nicht der Anzahl im Eingang entspricht.



7. Erweiterungseinheit

Die gesamte Gruppe von nicht standardmĂ€ĂŸigen Einheiten, so dass die kranke Fantasie der GerĂ€tehersteller frei war. Dementsprechend hĂ€ngen sowohl Verhalten als auch Einstellungen von dieser Fantasie ab.



Einige EntitĂ€ten haben Parameter wie VerstĂ€rkung oder Kanalnummer, die vom Host mithilfe von setFeature / getFeature-Abfragen fĂŒr die EntitĂ€tsnummer beeinflusst werden können. Aber hier, um ehrlich zu sein, verstehe ich ĂŒberhaupt nicht, wie ich das ĂŒberprĂŒfen soll. Wahrscheinlich benötigen Sie eine spezielle Software, die ich nicht habe. Na gut, trotzdem habe ich mich darauf eingelassen, um alle Arten von Punkten zu ĂŒberprĂŒfen ... auf meinem Kopf ...



Harken Sie den Deskriptor ein



Im Gegensatz zu frĂŒheren USB-GerĂ€ten ist der Deskriptor hier komplex, vielschichtig und neigt dazu, Windows in BSOD zu erschrecken. Wie wir oben gesehen haben, kann die Topologie eines autologen GerĂ€ts sehr komplex sein und sich ausbreiten. Eine ganze Schnittstelle zeichnet sich durch ihre Beschreibung aus. Offensichtlich enthĂ€lt es keine Endpunkte, aber es enthĂ€lt eine Liste von EntitĂ€tsdeskriptoren und Beschreibungen, mit denen ihre Eingaben verbunden sind. Ich sehe hier nicht viel Sinn, es ist einfacher, sich den Code und die Dokumentation anzusehen. Ich werde nur den Hauptrechen bemerken: Hier wird beschrieben, welche Schnittstellen mit den entsprechenden Endpunkten speziell auf dieses GerĂ€t verweisen. Wenn Sie beispielsweise meine Konfiguration Ă€ndern und den Lautsprecher von dort entfernen möchten, mĂŒssen Sie nicht nur die HĂ€lfte der EntitĂ€ten löschen (dank der Makros gibt es zumindest kein Problem bei der Berechnung der LĂ€nge des Deskriptors), sondern Reduzieren Sie außerdem das Feld bInCollection auf 1,Entfernen Sie dann die Nummer der zusĂ€tzlichen Schnittstelle aus dem darauf folgenden Array bInterfaceNr.



Weiterhin gibt es Schnittstellen, die fĂŒr den Datenaustausch verantwortlich sind. In meinem Fall ist die 1. Schnittstelle fĂŒr das Mikrofon und die 2. fĂŒr den Lautsprecher verantwortlich. Es lohnt sich hier zunĂ€chst auf zwei Varianten jeder dieser Schnittstellen zu achten. Eine mit bAlternateSetting gleich 0, die zweite mit 1. Sie unterscheiden sich bei Vorhandensein eines Endpunkts. Das heißt, wenn unser GerĂ€t derzeit nicht verwendet wird, wechselt der Host einfach zu dieser alternativen Schnittstelle, die nicht mit einem Endpunkt ausgestattet ist, und verschwendet nicht mehr die Busbandbreite.



Das zweite Merkmal von Datenschnittstellen ist das Audiosignalformat. Der entsprechende Deskriptor gibt den Codierungstyp, die Anzahl der KanÀle, die Auflösung und die Abtastrate an (die durch eine 24-Bit-Nummer angegeben wird). Es gibt einige Codierungsoptionen, aber wir werden die einfachste verwenden - PCM. TatsÀchlich ist es nur eine Folge von Werten des Momentanwerts des Signals ohne Codierung, und der Wert wird als vorzeichenbehaftete Ganzzahl betrachtet . Die Signalauflösung wird an zwei Stellen festgelegt (es ist nicht klar, warum): Das Feld bSubFrameSize gibt die Anzahl der Bytes und bBitResolution die Anzahl der Bits an... Es kann wahrscheinlich darauf hingewiesen werden, dass der Bereich unserer Soundkarte nicht den gesamten Bereich des Datentyps, z. B. int16_t, erreicht und nur 10 Bit betrÀgt.



Und schließlich der Deskriptor des tatsĂ€chlichen Endpunkts. Es unterscheidet sich auch geringfĂŒgig von den ĂŒblichen, da es zum einen mehrere Synchronisationsoptionen und zum anderen die Nummer der EntitĂ€t bietet, der dieser Punkt zugeordnet ist (bTerminalLink) . Synchronisationsoptionen werden in höherwertigen Bits direkt in den Endpunkttyp geschrieben (weshalb der isochrone Punkt in der Initialisierungsfunktion in den Standardzweig verschoben wurde), aber ich habe mich nicht mit ihren Details befasst, daher kann ich es Ihnen nicht sagen irgendetwas Interessantes. Anstelle der Synchronisation verwenden wir einen regulĂ€ren Controller-Timer, der Interrupts mit ungefĂ€hr der gewĂŒnschten Frequenz erzeugt.



Oh ja, ich hÀtte fast vergessen, eine andere Reihe von BSODs zu erwÀhnen, als ich die falschen Deskriptoren getestet habe. Ich möchte Sie noch einmal daran erinnern: Die Anzahl der Datenschnittstellen muss der Anzahl der bInCollection entsprechen, und ihre Anzahl muss dem darauf folgenden Array entsprechen!

Versteckter Text
, , . --.





Die Logik des GerÀts



Wie ich bereits sagte, macht es fĂŒr Tests keinen Sinn, schwenkbare Komponenten auf der Debug-Platine einzuschließen, sodass alle Tests mit dem durchgefĂŒhrt werden, was bereits installiert wurde - Tasten und LEDs. In diesem Fall stellt dies jedoch kein Problem dar: Das "Mikrofon" kann einfach eine Sinuskurve mit einer Frequenz von beispielsweise 1 kHz erzeugen, und der "Lautsprecher" schaltet die LED ein, wenn der Schallschwellenwert ĂŒberschritten wird (z ĂŒber 10.000: Bei der angegebenen Auflösung von 16 Bit, die dem Bereich -32768 ... +32767 entspricht, ist dies ungefĂ€hr ein Drittel.



Beim Testen trat jedoch ein kleines Problem auf: Ich fand keine einfache Möglichkeit, das Signal vom Mikrofon zum Standard eines Programms umzuleiten. Es scheint, dass dies vorher einfach durch Lesen von / dev / dsp geschehen ist, aber jetzt ist etwas kaputt. Nichts kritisches, denn es gibt alle möglichen Bibliotheken fĂŒr die Interaktion mit Multimedia - SDL, SFLM und andere. Eigentlich habe ich in SFML ein einfaches Dienstprogramm zum Lesen von einem Mikrofon und zum Visualisieren des Signals geschrieben, falls erforderlich.



Ich werde besonders auf die EinschrĂ€nkungen unseres AudiogerĂ€ts achten: Soweit ich weiß, wird einmal pro Millisekunde eine isochrone IN-Anfrage gesendet (es kann jedoch viele OUTs geben), wodurch die Abtastrate begrenzt wird. Angenommen, die GrĂ¶ĂŸe des Endpunkts betrĂ€gt 64 Byte (unter BerĂŒcksichtigung der Pufferung werden 128 Byte im Speicher benötigt, der Host weiß jedoch nichts darĂŒber). Die Auflösung betrĂ€gt 16 Bit, dh es können 32 Abtastwerte gleichzeitig gesendet werden . Bei einem Intervall von 1 ms erhalten wir eine theoretische Grenze von 32 kHz fĂŒr einen Kanal. Der einfachste Weg, dies zu umgehen, besteht darin, den Endpunkt zu vergrĂ¶ĂŸern. Aber hier mĂŒssen wir uns daran erinnern, dass die GrĂ¶ĂŸe des gesamten PMA-Puffers nur 512 Bytes betrĂ€gt. AbzĂŒglich der Punktverteilungstabelle minus ep0 erhalten wir unter BerĂŒcksichtigung der Pufferung maximal 440 Bytes, dh 220 Bytes pro Einzelpunkt. Und das ist die theoretische Grenze.



Die Tatsache, dass der Host mehrere OUT-Anforderungen in einem Frame senden kann, legt nahe, dass das GerĂ€t dasselbe tun kann. Es bleibt zu verstehen, wie. Möglicherweise wird dies durch eine kompetente Synchronisationseinstellung gelöst. Aber fĂŒr mich ist diese Frage nicht mehr von Interesse: Die isochronen Punkte funktionieren, die gepufferten Punkte funktionieren, das AudiogerĂ€t funktioniert - die Aufgabe ist erledigt.



Schlussfolgerung (gemeinsam fĂŒr den Zyklus)



Nun, wir haben das USB-GerĂ€t in STM32F103- und STM32L151-Controllern (und anderen mit einer Ă€hnlichen Implementierung) kennengelernt und waren von der Logik einiger Architekturlösungen ĂŒberrascht (ich war besonders beeindruckt vom USB_EPnR-Register, aber die doppelte Pufferung bleibt auch nicht zurĂŒck hinter), untersuchte alle Arten von Endpunkten und ĂŒberprĂŒfte sie durch den Bau der entsprechenden GerĂ€te. Wir können also sagen, dass diese Artikelserie zu einem logischen Ergebnis gekommen ist. Obwohl dies natĂŒrlich nicht bedeutet, dass ich auf Controller oder USB verzichten werde: In den fernen PlĂ€nen muss ich mich immer noch mit Composite-GerĂ€ten (bisher sieht es einfach aus, aber isochrone Punkte waren auch kein gutes Zeichen) und USB auf Controllern auseinandersetzen von anderen Familien.



All Articles