Forum: Mikrocontroller und Digitale Elektronik STM32 USB CDC HOST Beispiel


von Marcus H. (Firma: www.harerod.de) (lungfish) Benutzerseite


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

von ewrw (Gast)


Lesenswert?


von Marcus H. (Firma: www.harerod.de) (lungfish) Benutzerseite


Lesenswert?

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.

von Road R. (mickmack)


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

von Marcus H. (Firma: www.harerod.de) (lungfish) Benutzerseite


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

von Axel R. (axlr)


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

: Bearbeitet durch User
von Thomas Z. (usbman)


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.

von Axel R. (axlr)


Angehängte Dateien:

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]

: Bearbeitet durch User
von Thomas Z. (usbman)


Angehängte Dateien:

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 :-)

von Thomas Z. (usbman)


Lesenswert?

Ich hab meine Hosts mit wenigen 100 Zeilen gebaut(CDC und MSC) 
Allerdings habe ich keine zig fancy Datenstrukturen befüllt die sowieso 
nicht gebraucht werden. CPU war bei mir CH559 von WCH.
Hier ist eine frühe Version des MSC Hosts zu sehen.
Beitrag "Re: uC für 0,20€ CH552 / CH554 von WCH Billig Micro mit USB Funktion, Chip vorstellung"

: Bearbeitet durch User
von Axel R. (axlr)


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]

: Bearbeitet durch User
von Axel R. (axlr)


Lesenswert?

https://github.com/technologiescollege/ArduinoTechnoEduc/blob/master/hardware/arduino/avr/firmwares/atmegaxxu2/arduino-usbserial/Arduino-usbserial.c

Hier schau ich jetzt mal rein. Ob mir das weiterhilft, weis ich noch 
nicht.
Das ist vom 16u2 wohl der SourceCode. (Hex File ist auch im Reposository 
enthalten)

von Thomas Z. (usbman)


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.

: Bearbeitet durch User
von Thomas Z. (usbman)


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?

von Axel R. (axlr)


Angehängte Dateien:

Lesenswert?

anbei die Descriptoren und was da noch so alles bei ist ( Bin selbst 
erstautnt, wieviel dort tatsächlich übermittlet wird.)

von Axel R. (axlr)


Angehängte Dateien:

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?

von Thomas Z. (usbman)


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

von Axel R. (axlr)


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.

von Axel R. (axlr)


Lesenswert?

Um das hier anzuschließen: Der Thread kann gern zu. Danke an 'usbman'. 
Da sich hier ja sonst niemand meldet, scheint es sowieso egal zu sein.
Besten Dank trotzdem.
Axel DG1RTO

von Rahul D. (rahul)


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.

von Martin M. (capiman)


Lesenswert?

Wenn es nicht unbedingt ein STM32 Bare Metal sein muss,
der Stromverbrauch nicht unbedingt eine Rolle spielt,
wäre vielleicht ein Linux (a la Rasberry Pi) auch eine Alternative.
Dort kann dann USB Host built-in sein und man kann es direkt benutzen.

von Axel R. (axlr)


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

: Bearbeitet durch User
von Axel R. (axlr)


Lesenswert?

+ "ich"
+ "aussieben"

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.