STM32 USB CDC HOST Beispiel

OP (Firma: www.harerod.de) Persönliche Seite #4282580
Lesenswert?

Hallo Zusammen,
ich habe einen COTS-Sensor auf dem Tisch liegen, das ein USB CDC Device 
"USB to UART" nachbildet. Verhält sich also wie eines der bekannten 
USB-nach-Seriell-Kabel.
Vom PC aus kann ich mich per Terminalprogramm problemlos mit dem Teil 
unterhalten.

Nun soll das Device an einen STM32F4 angeschlossen werden.
Kennt jemand ein USB CDC HOST Beispiel für den STM32F4, am besten unter 
GCC/CooCox?
Im STM32CubeF4 habe ich Treiber für CDC HOST gefunden, allerdings keine 
fertigen Beispielprojekte. Während ich mich durch die UM1720/UM1730 
hangele, wollte ich hier mal nachfragen, ob jemand dazu was passendes 
kennt.

Wenn alle Stricke reißen, zerlege ich eines der MCS/HID-Beispiele, aber 
das würde ich mir gerne sparen.

Danke Euch,
 Marcus
#4444334
Lesenswert?

Marcus H. schrieb:
> ewrw schrieb:
>> Mal bei http://mikrocontroller.bplaced.net/wordpress/?page_id=744
>> schauen.
> been there, done that, took a picture, bought the T-shirt...
>
> Dem Uwe seine Seite ist immer einen Besuch wert. :D
> Allerdings habe ich nix passendes zum Thema STM32F4 USB HOST CDC
> gefunden.
> Dito bei TM in Holland.

Hallo Marcus,
ich habe aktuell dasselbe Thema zu beackern und wollten nachfragen ob du 
schon weitergekommen bist?

Schöne Grüße,
Markus
OP (Firma: www.harerod.de) Persönliche Seite #4444523
Lesenswert?

Markus S. schrieb:
> Hallo Marcus,
> ich habe aktuell dasselbe Thema zu beackern und wollten nachfragen ob du
> schon weitergekommen bist?

Hi Markus,
nein, der eingangs beschriebene Sensor hat dann doch unseren 
Anforderungen nicht genügt.

Die letzte mir bekannte Host CDC hatte ein paar Einschränkungen, u.a. 
ist sie AFAIR nicht Hub-fähig. D.h. Du kannst an den USB-Host genau ein 
Device anschließen.

Falls da mal ein Auftrag kommt, wird das dann halt niedergekämpft.

Eine andere Baustelle: bei STM32-Device-CDC sind die gemeldeten Probleme 
bei Win8/10. Keiner meiner Kunden hat sich da bis jetzt beschwert, aber 
irgendwie hoffe ich da auf ein Statement von ST.

Grüße,
 Marcus
#7654573
Lesenswert?

Und wir haben 2024:

Ein Arduino Mega2560 hängt mit seinen sekündlichen Testausgaben am USB CDC Host eines STM32F429 ( Ein Dicovery Board seiner Zeit mit diesem TFT drauf). Ich bin nun auch nicht wirklich der embedded Profi, hab mir das also mal im CubeMX zusammengeklickt und mich zum Rest an dem Beispiel entlang oerientiert, welches man als erstes findet, wenn man nach "CDC USB HOST STM32" sucht. Hier: https://controllerstech.com/usb-cdc-device-and-host-in-stm32/ Leider gibt es keine kleine Beispiel-App von ST, die zB als Terminal konfiguriert, die empfangenen seriellen Daten auf einem Display anzeigt. Ich hab also den Debugger aktiviert und ITM_SendChar und was man so braucht. Die Klasse "2" wird auch gestartet, aber der Arduino sendet nix, weil er wohl den "linestate" nicht 'bekommt', den er aber wohl auswertet. Hier mal die Dedug-Ausgabe vom STM-USB-Host:

1
USB Device Connected
2
USB Device Reset Completed
3
PID: 42h
4
VID: 2341h
5
Address (#1) assigned.
6
Manufacturer : Arduino (www.arduino.cc)
7
Product : N/A
8
Serial Number : 950323039373516021B2
9
Enumeration done.
10
This device has only 1 configuration.
11
Default configuration set.
12
Switching to Interface (#0)
13
Class    : 2h
14
SubClass : 2h
15
Protocol : 1h
16
CDC class started.

Mein "Appl_State" wechselt auch brav zwischen "Idle" und "Recieve" hin und her.

1
    if (Appli_state == APPLICATION_READY)
2
       {
3
         CDC_HANDLE();
4
       }
5
  }

und im CDC_HANDLE() mach ich dann auch nur das, was im Beispiel gemacht wird.

1
void CDC_HANDLE (void)
2
{
3
  switch (CDC_STATE)
4
  {
5
  case CDC_STATE_IDLE:
6
  {
7
      USBH_CDC_Stop(&hUsbHostHS);
8
      int len = sprintf ((char *)CDC_TX_Buffer, "DATA = %d", i);
9
      if (USBH_CDC_Transmit (&hUsbHostHS, CDC_TX_Buffer, len) == USBH_OK)
10
      {
11
        CDC_STATE = CDC_RECEIVE;
12
      }
13
      i++;
14
      break;
15
  }
16

17
  case CDC_RECEIVE:
18
  {
19
      USBH_CDC_Stop(&hUsbHostHS);
20
      usbresult = USBH_CDC_Receive(&hUsbHostHS, (uint8_t *) CDC_RX_Buffer, RX_BUFF_SIZE);
21
      HAL_Delay (500);
22
      CDC_STATE = CDC_IDLE;
23
  }
24

25
  default:
26
      break;
27
  }
28
}

Und ja: ich hab mich mit "F5, F6, F7" im CubeIDE drch die komplette USB-Enumeration geklickt ;) Schliesst man einen USB-Stick an oder einen USB-Hub werden halt andere Klassen, als die "2" zurückgegeben und die Enumeration schlägt dann fehl. Also die Erkennung der seriellen vom Arduino scheint ja zu klappen. Nur muss ich ihm 'beibrigen', dass er auch verbunden ist und nun Daten senden "darf". Ich muss wohl, zusätzlich zum Linecoding noch iwie den Linestate setzten, obgleich RTS und DTR ( mit Docklight getestet) eigentlich keine Rolle für die Ausgabe der seriellen Daten spielen (DTR lässt den Arduino resetten, was ja wohl gewollt ist) Ein "connect/Disconnect" hingegen lässt ihn umgehend mit der Ausgabe der Seriellen stoppen... Folglich brauche ich ein "Connect-Signal" dür den 16u2 auf dem Maga2560 Board. In Recherchen hierzu hab ich den Befehl 0x22 ( Set Control Line State) gefunden, unter anderm Hier: https://community.st.com/t5/stm32-mcus-embedded-software/usb-cdc-host-setcontrollinestate/td-p/169864.

Hat denn von euch jemand in letzter Zeit hiermit Erfahrungen gesammelt und kann die weitergeben? Ein STM-CDC-Device reagiert übrigens sofort. Das vielleicht noch am Schluss angemerkt.

Danke erstmal für's lesen.

Äxl

#7655030
Lesenswert?

Du hast es ja schon festgestellt: RTS und CTS spielen für die Übertragung keine Rolle. (Abgesehen davon dass CTS eben den Arduino reseten kann). Die Linestates brauchst du also nicht anzufassen. Der Empfang läuft über einen IN EP. Dieser wird vom Arduino Tx befüllt. Die Hostfirmware muss also nachschauen ob der InEp Daten hat und diese ggv auswerten. Dazu muss zuvor die verwendete Baudrate per Classrequest gesetzt werden. Ich kenne mich ehrlich gesagt nicht mit Cube aus, aber während der Konfiguration des Hosts muss irgendwo der Deskriptor Satz geparst werden um die EP Nummern für In und Out rauszubekommen. Meine Vermutung ist dass diese in der hUsbHostHS Struktur gespeichert wird. Wenn also nichts ankommt würde ich mir erst mal diese Struktur ansehen.

Ein Connect Signal im eigentlichen Sinne gibts nicht, auch nicht bei einer normalen seriellen Verbindung. Ein Host sendet aber immer ein LineCoding Request an das Device.

#7655217
Lesenswert?

Danke für die prompte Reaktion ;)

Die CDC-TX und CDC-RX-Buffer werden schon ordentlich bedient. Soweit funktioniert die HOST Implementation anstandsos. Ich hatte einfach ein weiters, vorhandenes, Discovery Board aufgestezt und hier den USB-CDC-Clienten zusammengeklickt. Der Host schickt Daten hin und der Client antwortet mit nem einfach Echo. In den Live-Expressions kann ich beiden Datenpuffer auswerten. Steht auch jeweils was sinnvolles drin. Aber der Arduino scheint ( hab da mal geggoelt) sehr wohl auf den linestate zu "schauen":

https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/CDC.cpp

1
size_t Serial_::write(const uint8_t *buffer, size_t size)
2
{
3
  /* only try to send bytes if the high-level CDC connection itself 
4
   is open (not just the pipe) - the OS should set lineState when the port
5
   is opened and clear lineState when the port is closed.
6
   bytes sent before the user opens the connection or after
7
   the connection is closed are lost - just like with a UART. */
8
  
9
  // TODO - ZE - check behavior on different OSes and test what happens if an
10
  // open connection isn't broken cleanly (cable is yanked out, host dies
11
  // or locks up, or host virtual serial port hangs)
12
  if (_usbLineInfo.lineState > 0)  {
13
    int r = USB_Send(CDC_TX,buffer,size);
14
    if (r > 0) {
15
      return r;
16
    } else {
17
      setWriteError();
18
      return 0;
19
    }
20
  }
21
  setWriteError();
22
  return 0;
23
}

und bei "while (!Serial) wird sich dem wohl bedient:

1
Serial_::operator bool() {
2
  bool result = false;
3
  if (_usbLineInfo.lineState > 0) 
4
    result = true;
5
  delay(10);
6
  return result;
7
}

Im USB-Sniffer sieht man auch die entsprechenden Steuerkommandos, wenn man den Ardu am TerminalProgramm anschließt.

1
t
2
 21 20 00 00 00 00 07 00                           ! ......
3
Empfänger: Interface
4
Anfrage Typ: Klasse
5
Richtung: Host->Gerät
6
Anfrage: 0x20 (Unbekannt)
7
Wert: 0
8
Index: 0
9
Länge: 0x7
10
Request Name: Set Line Coding
11
Data Terminal Rate (bits/sec): 0x0001C200
12
Stop Bits: 1 Stop bit
13
Parity: None
14
Data Bits: 0x8
15

16

17
Setup-Paket
18
 21 22 03 00 00 00 00 00                           !"......
19
Empfänger: Interface
20
Anfrage Typ: Klasse
21
Richtung: Host->Gerät
22
Anfrage: 0x22 (Unbekannt)
23
Wert: 0x3
24
Index: 0
25
Länge: 0
26
Request Name: Set Control Line State
27
DTE Present: Present
28
Carrier Control: Activate Carrier
29

30
Setup-Paket
31
 21 22 02 00 00 00 00 00                           !"......
32
Empfänger: Interface
33
Anfrage Typ: Klasse
34
Richtung: Host->Gerät
35
Anfrage: 0x22 (Unbekannt)
36
Wert: 0x2
37
Index: 0
38
Länge: 0

in der usbh_cdc.h sind die Konstanten aufgeführt, obwohl der (teure) USB-Sniffer in der Paket-Ansicht "unbekannt" schreibt. nun, im lecacy-mode stehts ja dann richtig.

1
#define CDC_SET_LINE_CODING                                     0x20U
2
#define CDC_GET_LINE_CODING                                     0x21U
3
#define CDC_SET_CONTROL_LINE_STATE                              0x22U
4

5
/* wValue for SetControlLineState*/
6
#define CDC_ACTIVATE_CARRIER_SIGNAL_RTS                         0x0002U
7
#define CDC_DEACTIVATE_CARRIER_SIGNAL_RTS                       0x0000U
8
#define CDC_ACTIVATE_SIGNAL_DTR                                 0x0001U
9
#define CDC_DEACTIVATE_SIGNAL_DTR                               0x0000U

auch n Funktionsaufruf fürs Set_Line_Coding hab ich gefunden, aber keinen für Set_Line_Control.

1
USBH_StatusTypeDef  USBH_CDC_SetLineCoding(USBH_HandleTypeDef *phost,
2
                                           CDC_LineCodingTypeDef *linecoding);
3
USBH_StatusTypeDef  USBH_CDC_GetLineCoding(USBH_HandleTypeDef *phost,
4
                                           CDC_LineCodingTypeDef *linecoding);
5
USBH_StatusTypeDef  USBH_CDC_Transmit(USBH_HandleTypeDef *phost,
6
                                      uint8_t *pbuff,
7
                                      uint32_t length);
8
USBH_StatusTypeDef  USBH_CDC_Receive(USBH_HandleTypeDef *phost,
9
                                     uint8_t *pbuff,
10
                                     uint32_t length);
11
uint16_t            USBH_CDC_GetLastReceivedDataSize(USBH_HandleTypeDef *phost);
12
USBH_StatusTypeDef  USBH_CDC_Stop(USBH_HandleTypeDef *phost);
13
void USBH_CDC_LineCodingChanged(USBH_HandleTypeDef *phost);
14
void USBH_CDC_TransmitCallback(USBH_HandleTypeDef *phost);
15
void USBH_CDC_ReceiveCallback(USBH_HandleTypeDef *phost);

Brauch ich also als erstes ne Funktionsdefinition und deren Implementation für Set_Line_Control und dann bleibt für mich newbee die Frage, wann ich das schicken "darf". Ganz sicher nit irgendwo in der Main. Aber schon der Enumerationsprozeß bis zur Debugausgabe "Class startet"

1
USB Device Connected
2
USB Device Reset Completed
3
PID: 42h
4
VID: 2341h
5
Address (#1) assigned.
6
Manufacturer : Arduino (www.arduino.cc)
7
Product : N/A
8
Serial Number : 950323039373516021B2
9
Enumeration done.
10
This device has only 1 configuration.
11
Default configuration set.
12
Switching to Interface (#0)
13
Class    : 2h
14
SubClass : 2h
15
Protocol : 1h
16
CDC class started.

war schon ein nicht endenwollender Wust an verketteten States, die da nacheinander in Abhängigkeit gedracht, aber alle ordentlich abgearbeitet wurden, dass ich Probleme hatte, dem zu folgen. Find ich ja blöd, dass man zwar nen USB-Host aufsetzen kann, auch wenn man nicht komplett Ahnung hat, dann aber ziemlich dumm dasteht. Ich bin bei der Frage nach "Set control line state" hier fündig geworden: https://community.st.com/t5/stm32-mcus-embedded-software/usb-cdc-host-setcontrollinestate/td-p/169864

1
USBH_StatusTypeDef  USBH_CDC_SetControlLineState(USBH_HandleTypeDef *phost)
2
{
3
  phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE;
4

5
  phost->Control.setup.b.bRequest = CDC_SET_CONTROL_LINE_STATE;
6
  phost->Control.setup.b.wValue.w = 3U;
7
  phost->Control.setup.b.wIndex.w = 2;
8
  phost->Control.setup.b.wLength.w = 0;
9
  return USBH_CtlReq(phost, 0, 0);
10
}

Die Funktion ist ja ansich selbsterklärend. Einzig der Umstand, dass ich nicht weiss, WO genau ich das einbauen muss, lässt mich hier noch ne Weile wohl forschen.

BTW: ich hab das Projekt mal als achiv-File exportiert. Sollte sich dann genauso wieder importieren lassen. Fall es wen interssiert. ich hab ide Version 1.13.1 vom STM32CubeIDE

[edit] 16.9MB?!? für das Projekt ( hab ich im leben nicht mit gerechnet) [/edit]

Angehängte Dateien:
#7655241
Lesenswert?

Wie gesagt bei dem Cube Zeugs kann ich dir nicht weiterhelfen, aber die oben gezeigte Funktion USBH_CDC_SetControlLineState ist schon so richtig. allerdings sind die Werte falsch. Ich hab mal den Ausschnitt aus der spec angehängt.

1
USBH_StatusTypeDef  USBH_CDC_SetControlLineState(USBH_HandleTypeDef *phost)
2
{
3
  phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE;
4
  phost->Control.setup.b.bRequest = CDC_SET_CONTROL_LINE_STATE;
5
  phost->Control.setup.b.wValue.w = 2; // -> RTS Line 1
6
  phost->Control.setup.b.wIndex.w = 0; // -> CDC Control Interface No
7
  phost->Control.setup.b.wLength.w = 0;
8
  return USBH_CtlReq(phost, 0, 0);
9
}

Ich kann allerdings keine RTS Leitung im Schaltplan rev3 sehen die vom 16U2 zum Arduino geht.

Zum Aufruf: ich würde das direkt nach dem Setzen der Baudrate machen. Tatsächlich ist es aber egal. Dein STM ist Host und der bestimmt wann er was macht. Das Device muss sich fügen :-)

Angehängte Dateien:
#7655654
Lesenswert?

Thomas Z. schrieb:

Allerdings habe ich keine zig fancy Datenstrukturen befüllt die sowieso nicht gebraucht werden.

Da sehe ich zwar die Intention von ST, blicke aber nicht durch :).

Ich wollte tatsächlich nur die ankommenden Strings in eine Liste packen, etwas "ausdünnen/manipulieren" (Prosa entfernen) und die Listmembers auf dem Display vom 429er Board untereinander darstellen.

Naja: ich hab jetzt das SetControlLine-State in mein CDC_HANDLE() mit eingebaut. Denke, das sollte man so machen können, auch wenn es sicher ansehnlicher ginge.

1
uint8_t RTS_Send = 0;
2
uint8_t i = 0;
3
void CDC_HANDLE (void)
4
{
5

6
//  USBH_UsrLog("CDC_STATE: %d", CDC_STATE);
7
  switch (CDC_STATE)
8
  {
9
  case CDC_STATE_IDLE:
10
  {
11
    if (RTS_Send == 2){
12
              USBH_CDC_Stop(&hUsbHostHS);
13
              usbresult=USBH_CDC_SetControlLineState(&hUsbHostHS, 3);
14
              USBH_UsrLog("RTS_okay: %d", usbresult);
15
              RTS_Send = 3;
16
        }
17
    if (RTS_Send == 1){
18
          USBH_CDC_Stop(&hUsbHostHS);
19
          usbresult=USBH_CDC_SetControlLineState(&hUsbHostHS, 1);
20
          USBH_UsrLog("RTS_okay: %d", usbresult);
21
          RTS_Send = 2;
22
    }
23
    if (RTS_Send == 0){
24
      USBH_CDC_Stop(&hUsbHostHS);
25
      usbresult=USBH_CDC_SetControlLineState(&hUsbHostHS, 0);
26
      USBH_UsrLog("RTS_CTS_okay: %d", usbresult);
27
      RTS_Send = 1;
28
    }
29
    USBH_CDC_Stop(&hUsbHostHS);
30
      int len = sprintf ((char *)CDC_TX_Buffer, "DATA = %d", i);
31
      if (USBH_CDC_Transmit (&hUsbHostHS, CDC_TX_Buffer, len) == USBH_OK)
32
      {
33
        CDC_STATE = CDC_RECEIVE;
34
      }
35
      i++;
36
      break;
37
  }
38

39
  case CDC_RECEIVE:
40
  {
41
      USBH_CDC_Stop(&hUsbHostHS);
42
      usbresult = USBH_CDC_Receive(&hUsbHostHS, (uint8_t *) CDC_RX_Buffer, RX_BUFF_SIZE);
43
      USBH_UsrLog("Empfang: %s", CDC_RX_Buffer);
44
      HAL_Delay (1000);
45
      CDC_STATE = CDC_IDLE;
46
      break;
47
  }
48

49
  default:
50
      break;
51
  }
52
}

usbresult (also:USBH_CtlReq() ) gibt mir aber "USB_BUSY" zurück. Offensichtlich antwortet der 16u2 vom Arduino Mega2560 nicht oder kann mit der Anfrage so nichts anfangen. Keine Ahnung...

1
USBH_StatusTypeDef  USBH_CDC_SetControlLineState(USBH_HandleTypeDef *phost, uint8_t ctrl)
2
{
3
  phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE;
4
  phost->Control.setup.b.bRequest = CDC_SET_CONTROL_LINE_STATE;
5
  phost->Control.setup.b.wValue.w = ctrl; // -> RTS Line 1, CTS Line 2
6
  phost->Control.setup.b.wIndex.w = 0; // -> CDC Control Interface No
7
  phost->Control.setup.b.wLength.w = 0; // <-- Laenge "0"?nicht "1"?
8
  return USBH_CtlReq(phost, NULL, 0);
9
}

danke fürs lesen

[edit] USBH_CDC_SetControlLineState(&hUsbHostHS, 0); mit 0,1,2,3 als zweiten Parameter hab ich mal rumgespielt, aber es ist egal was man ich welcher Reihenfolge schickt, wahrscheinlich solange "USB_BUSY" zurückgegeben wird. [/edit]

#7655706
Lesenswert?

Axel R. schrieb:

Offensichtlich antwortet der 16u2 vom Arduino Mega2560 nicht oder kann mit der Anfrage so nichts anfangen. Keine Ahnung...

busy sollte bedeuten dass der Request in einen Timeout reinläuft weil z.b die Status Stage fehlt. Das könnte aber auch auf einen FW Bug im 16U2 hindeuten.

Dieser Request ist ohne Datastage (wLenth=0) -> [Setup(class)] [StatusStage] im Gegensatz Linecoding -> [Setup(class)] [Datastage 7byte] [Status]

Ein falscher Request wird mit einem CTL_STALL beantwortet. Du kannst ja mal testhalber USB_REQ_RECIPIENT_DEVICE anstelle USB_REQ_RECIPIENT_INTERFACE setzen, dann sollte der STALL kommen

Falls es ein FW Bug ist sollte am PD7 (DTR, Pin13 16U2) trotzdem eine Änderung zu messen sein wenn du DTR betätigst.

Im Source des 16U2 kann man sehen dass nur DTR bedient wird nicht RTS.

#7655724
Lesenswert?

Ich habe leider kein Arduino Board mit dem 16U2 sondern nur Nachbauten mit fixen USB Serial Bausteinen. Kann hier also keine Tests machen wie sich der 16U2 genau verhält. Ich würde den Artuino ja einfach mal an HTerm hängen und die Control Leitungen dort betätigen. Kannst du mal die Dskriptoren deines Boards mit USBDeviceTreeView (www.uwe-sieber.de) posten?

#7655838
Lesenswert?

Dann hab ich noch ne (angebliche) CSV-Datei, (sind wohl tabs zur trennung drin), die das DeviceMonitoringStudio von https://www.hhdsoftware.com/ abgelegt hat. Hier ist Connect <--> Disconnect zu sehen mit einigen Ausgaben vom Arduino auf seiner seriellen. Bitteschön Am Ende hängt das Bord einfach nur im Reset fest, wenn es am STM Host angeschlossen wurde.

@all mal unter uns: ist noch niemand auf die Idee gekommen, einen Arduino Mega2560 an einen STM-CDC-Host zu "hängen"? Wahrscheinlich schliesst die eine klientel die andere aus. Ich derweil, bedanke mich beim Thomas für seine Mühe und Geduld. Was kann ich tun, um das Interesse bei den anderen Forenteilnehmenr zu wecken?

Angehängte Dateien:
#7655854
Lesenswert?

Also die Deskriptoren sehen gut aus. Wichtig war mir zu sehen dass Control wirklich auf Interface 0 liegt und Data auf Interface 1. Ich hab schon zu viele kaputte Deskriptoren gesehen. Ein Paar Kleinigkeiten:

  • StrId 2 ist nicht definiert
  • bcdCDC steht auf 10.1 sollten wohl 1.1 werden LSB / MSB vertauscht
  • bei CDC ist eigentlich der Compountdeskriptor mantory

Den Compount Deskriptor haben die wohl weggelassen weil OSx das lange Zeit nicht konnte. Also nichts was eine Funktion des CDC behindert

#7656338
Lesenswert?

Super, Danke fürs drüberschauen. Ich hab jetzt keine weitere Idee mehr. Hab leider auch keinen Telefonjoker, nur hier unsere Communitiy, der ich seit 2004 angehöre. Vielleicht stell ich die Frage mal im englischen Raum, ob es dort jemanden gab, der eine funktionierendes Terminal mit nem Mega2560 als "Gast/Device" am USB-Host umgesetzt hat und hier die Richtung ausfzeigt. Entsprechende Google-Suchergebnisse verweisen immer auf ein Arduino-USB-Host-Shield mit diesem Maxim Schaltkreis. Das ist ja aber nicht das, was ich suche. ächste möglichkeit wäre mal bei ST selbst anzufragen, ob die mit dieser Aufgabe schon einmal konfrontiert wurden. Komisch, nichtmal ne VT100 Emulation in den Beispielen oder vergleichbares. Massenspeicher ist hingegen gut erklärt. Auch Schade, dass hier niemand weiter Bock hat, sich das mal anzusehen. Aber hey: zuZeiten des STM32F429 Dicovery-Boards gab es wohl noch kein Arduino-Kram und wer sowas in den FIngern hat, wird sicher kein STM'429er Bord haben. Die Schnittmenge ist hiernach recht klein. Verstehe ich auch. Ein Arduino UNO hat, nebenher bemerkt, auch seinen USB als separaten Chip. Der verhält sich sicher auch so, wie der Mega 2560. Kann jemand auf diese Konstellation zurückgreifen? Als USB-Hub könnte ja auch ein Blue-Pill/Black-Pill gehen. Probier ich mal aus. Vielleicht erziele ich damit mehr Reichweite und jemand kann mir das connect<->disconnect Handling erörtern. Naja - im Moment fängt es mir an, keinen Spaß mehr zu machen. Danke für Zuwendung und Geduld derweil.

#7657562
Lesenswert?

Axel R. schrieb:

Da sich hier ja sonst niemand meldet, scheint es sowieso egal zu sein.

Der Weg über ein "handelsübliches" UART ist doch viel einfacher. Einen USB-Sensor mit einem µC auszuwerten ist doch eher exotisch. Wer das schon mal gemacht hat, wird das sicherlich nicht privat, sondern kommerziell gemacht haben, wodurch dieses Wissen an die Firma gebunden ist...

Interessant finde ich das Thema trotzdem.

#7659642
Lesenswert?

Abschlussbericht: "geht jetzt"

Problem war das "Henne<->Ei" Prinzip.

Während der Initialisierung gibts irgendwann einen "ClassRequest". Dort wird ein "Get_Line_Coding" augerufen. Sehr sinnvoll, wenn man weis, also man sich den Quellcode vom Ardummnino angesehen hat, dass der sich einfach die sieben Bytes vom Linecoding nimmt und zurückschickt. ÄH? da kam noch garnichts vom Host, diesbezüglich. Folglich werden DTEDataRate, Paritiy unsw. Mit "0" initilalisiert. Also kann der Atmega16u2 seine Baudratenregister auch garnicht setzen und mit dem Atmega2560 kommunizieren. Ich hab nun also beim "Class_Request" aus dem "Get_Line_Coding" eine "Set_Line_Coding" gemacht und da ich nirgendwo eine Initialsierung für die Linecoding Struct fand, diese vorab zur Laufzeit mit sinnvollen Werten (9k6, 8N1), kann man ja noch auf 115200 ändern, belegt. Die Rückantwort kann sich das Device gern schenken. Einen Einsprung für eine evetuelles "Get_Line_Coding" hab ich mir gespart, da ja eh das gleiche zurückkommt, was gesendet wurde. "Get_Last_Linecoding_Change" hab ich drin gelassen. Und ja: wenn man im CubeMX die Clock oder was anderes ändert, ist alles wieder weg. So einen gesicherten User-Block gibt es in dem Bereich nämlich nicht. Hier noch die Änderungen an dieser Stelle im Quellcode:usbh_cdc.c (Quasi auch als Backup für mich. müsste man sich ja glatt als Anhang hier wegspeichern. Ist zwar kein Bild vom Probenraum; Anhänge überleben hier aber anscheinend alles, wie der Bernd ja allwöchentlch probiert ;) lieben Gruß nach F'hausen an dieser Stelle)

1
static USBH_StatusTypeDef USBH_CDC_ClassRequest(USBH_HandleTypeDef *phost)
2
{
3
  USBH_StatusTypeDef status;
4
  CDC_HandleTypeDef *CDC_Handle = (CDC_HandleTypeDef *) phost->pActiveClass->pData;
5

6
  /* Issue the get line coding request */
7
  /* ja nee: SET line Coding Request!! AR 05.05.2024*/
8
  CDC_Handle->LineCoding.b.dwDTERate =9600UL;
9
  CDC_Handle->LineCoding.b.bCharFormat =0UL;
10
  CDC_Handle->LineCoding.b.bParityType =0UL;
11
  CDC_Handle->LineCoding.b.bDataBits =8UL;
12

13
  status = SetLineCoding(phost, &CDC_Handle->LineCoding);
14
  if (status == USBH_OK)
15
  {
16
    phost->pUser(phost, HOST_USER_CLASS_ACTIVE);
17
  }
18
  else if (status == USBH_NOT_SUPPORTED)
19
  {
20
    USBH_ErrLog("Control error: CDC: Device Get Line Coding configuration failed");
21
  }
22
  else
23
  {
24
    /* .. */
25
  }
26

27
  return status;
28
}

Find ich mal richtig schwach von ST für das 429er Bord keine ordentliche Implementation abzuliefern. Wer sich da nicht zu 100% auskennt, ist komplett am Arsch. Für die H7-Reihe gibts da tatsächlich ein lauffähiges Example,

https://github.com/STMicroelectronics/STM32CubeH7/blob/master/Projects/STM32H743I-EVAL/Applications/USB_Host/CDC_Standalone/Src/cdc_configuration.c

was aber auch wieder derart aufgebort ist, das man nur mit Mühe und Inselteilhochbegabung durchsteigt, sofern man sowas nicht in der Fachhochschule als Leistungskurs belegt hat.

Und ja: natürlich, ein Raspberry liegt hier und man hätte auch eine USB-Shield für einen Arduino kaufen können, einen Laptop daneben stellen können oder einen ESP32 als USB-HOst einrichten können. ICH wollte das aber mit dem 429er Board, welches bislang als Oszi und LIN-Bus Sniffer (Frontscheinwerfer im Ford Mondeo MK4 war zu dunkel) diente, dafür hernehmen. In der Zeit hätte ich mir auch die "zu filternden Ausgaben" des Atmega2560 ansehen können und das dort im Atmega2560 (Arduino Mega) im Quellcode bereinigen. Na - wollte ich aber nicht. Spannend wird es jetzt noch, mal einen Arduino Micro oder Nano mit einemm 32u4 ausuprobieren. Hier werkeln ja nicht zwei Schaltkreise, die über ihre RX TX Leitungen kommunzieren müssen; hier findet ja alles in einem Chip statt. Aber nicht jetzt ;) Jetzt muss [edit] ich [/edit] den RX-Buffer nach den letzten, empfangegen Strings durchsuchen, alles in eine Liste kippen und das "Geschwafel" (wie kann man nur soviel Prosa in den RAM packen?) [edit] aussieben [/edit], die Nutzdaten filtern und untereinander auf dem Display zur Anzeige bringen. Das, denke ich, bekomme ich selbst hin.

Dank geht raus an "usbman" und an Dr. Schröder für seine Motovation. Und beste Grüße an die Community

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren