Forum: Mikrocontroller und Digitale Elektronik USB CDC von Stefan Frings und WS


von Bernd N (Gast)


Lesenswert?

Ich beziehe mich hier auf den Code von der Seite 
http://stefanfrings.de/stm32/stm32f1.html

Hier wird ein Beispiel gezeigt unter dem Punkt "Virtueller COM-Port ohne 
Cube HAL" Ich habe mir das Projekt mal unter der Cube IDE angelegt und 
die main auf folgenden Code reduziert...
1
int main(void) {
2
  // Initialize system timer
3
  SysTick_Config(SystemCoreClock / 1000);
4
5
  init_io();
6
  UsbSetup();
7
8
  while (1) {
9
    if (UsbRxAvail() == true) {
10
      if (UsbTxReady() == true)
11
        UsbCharOut(UsbGetChar());
12
    }
13
  }
14
}
Als Terminal verwende ich TTerm. Wie zu erwarten, ich kann in das 
Terminal Text eingeben und ich erhalte die Zeichen entsprechend als Echo 
zurück. Ich prüfe also ob ein Zeichen angekommen ist und sende es, nach 
efolgter Prüfung des "UsbTxReady", zurück. Soweit so gut.

Wenn ich jetzt mittels Terminal eine Datei versende (in TTerm File Send 
File Funktion" dann hängt sich der Controller / Software auf. Ich prüfe 
ja den Empfangs und Sendepuffer bevor ich etwas empfange oder sende, ich 
verstehe nicht wieso dann die Software aussteigt. Hoffe der / die 
Autoren melden sich hierzu.

Vielen Dank

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Bernd N schrieb:
> Wenn ich jetzt mittels Terminal eine Datei versende (in TTerm File Send
> File Funktion" dann hängt sich der Controller / Software auf. Ich prüfe
> ja den Empfangs und Sendepuffer bevor ich etwas empfange oder sende, ich
> verstehe nicht wieso dann die Software aussteigt.

Kann denn TTerm während des Versands einer Datei überhaupt Zeichen 
empfangen und darstellen? Ggf. handelt es sich um ein Deadlock auf 
Seiten des Terminalprogramms, d.h. die Firmware schafft es nicht, die 
reflektierten Zeichen loszuwerden, und kann dann auch keine weiteren 
Zeichen empfangen.

von Bernd N (Gast)


Lesenswert?

Nein, TTerm macht das spielend. Der Fehler liegt auf der STM Seite, 
vermutlich Software. Wenn ich einen Transmit Delay einstelle dann 
funktioniert es einwandfrei. Ich verwende diese Art von Test immer um 
das Sizing meiner Ringbuffer bei USART Code zu prüfen.

Sobald ich volle geschwindigkeit zulasse dann hängt es und das schon bei 
9600 Baud.

von Pieter (Gast)


Lesenswert?

hmm...du feuerst also mit dem Terminal eine Datei raus.
Prüft das Terminal die Empfangsseite?

Da du im MC-USB 1Zeichen holen und 1 Zeichen senden abwartest, darfst du 
nur mit halber Zeichengeschwindigkeit senden.
Sonst darfst du UsbTxReady nicht abfragen und musst hoffen das senden 
schon fertig ist, wenn das nächste Zeichen kommt.

von Bernd N (Gast)


Lesenswert?

>> hmm...du feuerst also mit dem Terminal eine Datei raus.
>> Prüft das Terminal die Empfangsseite?

Ja. Das Terminal würde warten und nur weiter senden wenn es wieder geht.

von Pieter (Gast)


Lesenswert?

>>Wenn ich einen Transmit Delay einstelle dann
>>funktioniert es einwandfrei.

Du bestätigst meine Vermutung.

von Niklas Gürtler (Gast)


Lesenswert?

Bernd N schrieb:
> if (UsbRxAvail() == true) {
>       if (UsbTxReady() == true)
>         UsbCharOut(UsbGetChar());
>     }

Wahrscheinlich will der hostseitige CDC-Treiber erst ganz viel senden 
("OUT") und dann erst die eingehenden Daten akzeptieren ("IN"). Du 
blockiert aber den Empfang der OUT-Daten, indem du UsbGetChar nicht mehr 
aufrufst, wenn keine Daten mehr rausgehen können. Dadurch wird der 
USB-Empfangspuffer nicht wieder freigegeben, es kann nicht mehr PC->uC 
gesendet werden, und dann wird niemals der Sendepuffer abgefragt, und 
alles hängt fest. Du brauchst vermutlich einen größeren Puffer (FIFO). 
Vielleicht hängt auch UsbCharOut fest wenn der PC kein "IN" anfordert.

von Bernd N (Gast)


Lesenswert?

>> Du bestätigst meine Vermutung.
Verstehe ich nicht, sorry. Ich könnte verstehen wenn Zeichen verloren 
gehen aber das es im Nirvana endet ist definitv nicht normal. Dafür muß 
es einen Grund geben.

Kein einziger USART Code von mir versagt bei diesem simplen Test. 
Vielleicht ist das OK so aber ich würde es gerne verstehen.

von Bernd N (Gast)


Lesenswert?

>> Du blockiert aber den Empfang der OUT-Daten, indem du UsbGetChar nicht
>> mehr aufrufst, wenn keine Daten mehr rausgehen können.

Wenn ich die Bremse rausnehme passiert das Gleiche, deswegen ist sie 
drin da ich damit ausschliessen wollte das passiert, was du beschreibst.

von Pieter (Gast)


Lesenswert?

>>Transmit Delay

bedeutet Zeichen senden und eine bestimmte Zeit warten.
Richtig?
Im Transmit Delay wird das Zeichen zum MC gesendet und dort geechot.
Und das braucht seinhe Zeit.

Bei UART hast du 2 Leitungen unidirektional ( Tx - Rx ) bei USB hast du 
EINE bidirektionale Leitung.
Wie war das mit Äpfeln und Birnen?

von Niklas Gürtler (Gast)


Lesenswert?

Bernd N schrieb:
> deswegen ist sie drin da ich damit ausschliessen wollte das passiert,
> was du beschreibst.

Das ist aber ein ziemlich optimistischer Ansatz...

Bernd N schrieb:
> Kein einziger USART Code von mir versagt bei diesem simplen Test.

USB ist ja auch kein UART, sondern ein paketbasiertes Protokoll mit 
Handshakes. Die Bibliothek tut nur so, als könnte man einzelne Bytes so 
lose überragen.

Besser ist es, das ganze nicht mit einzelnen Bytes zu machen, sondern 
direkt mit ganzen Paketen (z.B. 64 Byte). Da kannst du die Daten sogar 
direkt im USB-Puffer-RAM lassen und direkt vom OUT-Endpoint an den 
IN-Endpoint übergeben. Das ganze dann über die USB-Interrupts, um solche 
möglicherweise blockierenden Schleifen zu vermeiden. Dabei würdest du 
die Puffer-Verwaltung dieser Library weglassen und es direkt machen.
Vielleicht hilft da ja auch das USB-Tutorial mit STM32

von Bernd N (Gast)


Angehängte Dateien:

Lesenswert?

Wäre es so wie du es beschreibst dann müsste doch der Fehler ab dem 
ersten Zeichen auftreten, tut es aber nicht. Es bricht mittendrin ab und 
hängt sich dann auf. Sieht für mich nach nem Buffer Problem aus.

>> bedeutet Zeichen senden und eine bestimmte Zeit warten. Richtig?
Ja

>> Bei UART hast du 2 Leitungen unidirektional ( Tx - Rx ) bei USB
>> hast du EINE bidirektionale Leitung.

Das ist ein guter Hinweis, habe ich noch nicht drüber nachgedacht.

Wie gesagt, ich würde es halt gerne verstehen. Anbei mal einen 
Screenshot bis wann es gut geht.

von Bernd N (Gast)


Lesenswert?

@ Niklas, danke auch für deine Hinweise. Es sind meine ersten Versuche 
mit USB und sicherlich fehlt mir hier sehr viel Wissen. Ich werde mir 
deinen Artikel mal vornehmen Ich hoffe das WS oder Stefan sich noch 
melden, möglicherweise wissen sie sofort was es ist.

>> Du brauchst vermutlich einen größeren Puffer (FIFO).
Das war meine erste Vermutung.

von Pieter (Gast)


Lesenswert?

Deine USB-Blockgröße ist bestimmt > 1, damit sendet USB mehrere Zeichen 
als ein Block. In TeraTrem wartest du nutzloser weise nach jedem 
Zeichen.
Sinnigerweise must du aber nach einem Block warten.
Setze die Blockgröße mal auf 1.

von Pieter (Gast)


Lesenswert?

nutzt du in TT auch die RTS/CTS Steuerung?

von Pieter (Gast)


Lesenswert?

>>meine ersten Versuche
>>mit USB und sicherlich fehlt mir hier sehr viel Wissen

dann ist der Ruf nach einem SW-Bug in USB schon ein starker Auftritt.

von Bernd N (Gast)


Lesenswert?

Jaja, es ist die Buffer Size. Ich habe diese gerade mal grßer gemacht 
und schon gehts. Das sich das Ding aufhägt ist für mich ein Bug, das 
sollte nicht passieren.

von Pieter (Gast)


Lesenswert?

mit größerem Buffer verschiebst du nur die Grenze bis es nicht mehr 
geht.
Lass von TT mal nur Zeichen senden, geht schlafen und morgen Früh hängt 
es wieder.

von Bernd N (Gast)


Lesenswert?

>> mit größerem Buffer verschiebst du nur die Grenze bis es nicht
>> mehr geht.

Ich weiss.

von Jedzia D. (Firma: Rast und Ruh) (jedzia)


Lesenswert?

1
UsbCharOut(UsbGetChar());
scheint mir auch problematisch zu sein, da (siehe "Achtung")
1
/* holt ein Zeichen vom USB ab */
2
/* Achtung: wenn nix abzuholen ist, wird 0 zurückgeliefert */
3
char UsbGetChar(void)
2. Dein UsbTxReady() check ist redundant, da er in
1
/* sendet ein Zeichen (d.h. schreibt es in den Tx-Buffer) */
2
char UsbCharOut(char c)
sowieso passiert und möglicherweise das UsbGetChar in dieser Anordnung 
blockiert.

Ich hab nur einen schnellen Blick auf den source code geworfen. Du 
solltest das mit einem Debugger untersuchen, Bernd. Viel Erfolg:)

: Bearbeitet durch User
von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

Leute,

Die Sache ist gelegentlich etwas schwieriger als gedacht. Die STM32F103 
haben - soweit ich das sehen kann - kein dediziertes Handling des NAK_BI 
und das ist ein Ärgernis.

(NAK_BI bedeutet Interrupt des Bulk-IN bei NAK-Antwort der SIE an den 
Host)

Hintergrund:
Der Host fragt alle Nase lang den Bulk-EP des Devices, ob da was zum 
Abholen vorhanden ist. Wenn nix zum Abholen im Bulk-In Puffer 
bereitsteht, dann antwortet die/der/das SIE dem Host mit einem NAK.

Normalerweise generiert die SIE dabei keinen Interrupt und das ist 
eigentlich gut so, denn in solchem Falle gäbe es so etwa alle 1..13 µs 
einen Interrupt und das ist ja doch eine ganz erhebliche Prozessorlast.

Was also passiert, wenn man den Sende-Ringpuffer ordentlich gefüllt hat? 
Dann wird dieser in 64 byte Stücken bereitgestellt und vom Host 
abgeholt. Dazu ist dann der Interrupt alle 11..13µs gut. Beim letzten 
Stück Sendedaten ist dann erstmal Schluß, man kann in den Transferpuffer 
ja nix mehr zum Senden an den Host hineintun und ihn dann aktivieren. 
Also sagt ab da die SIE zum Host NAK!

Soweit so gut. Ringpuffer ist leer, SIE belästigt den µC nicht mit 
Interrupts und alles ruht. Aber wie kriegt man das Ganze wieder in Gang, 
wenn irgendwann später wieder Zeichen im Ringpuffer landen? Wo kein 
Interrupt kommt, schaut auch keiner dort hinein.

Ich hatte das bei all den andern µC so gelöst, daß der Frametick des USB 
so alle 1 ms ganz pauschal den NAK_BI einschaltet. Folglich erzeugt die 
SIE einen Interrupt, wenn der Bulk-In Endpunkt vom Host gefragt wird, ob 
er was hat und er darauf mit NAK geantwortet hat. Dieser Interrupt führt 
dann dazu, daß der zuständige EP-Handler nachschaut und ggf. das Senden 
an den Host in Gang setzt. Der EP-Handler schaltet pauschal den NAK_BI 
wieder aus, um die CPU nicht unnötig zu belästigen.

Aber: bei den STM32F103 funktioniert das nicht, weil ich derartige 
Kommandos an die SIE nicht habe entdecken können. Also hatte ich das 
damals so gelöst, daß der Bulk-In Endpunkt einfach so immer mal 
aufgerufen wird, was bei derartiger Belastung aber offenbar zu Störungen 
führt.

Ich hab das in meiner aktuellen Version weiter eingeschränkt:
1
  if (I & SOF)                               /* Start of Frame, alle 1 ms */
2
  { USB_ISTR = ~SOF;                         /* Int löschen */
3
    if ((txr != txw) &&                      /* Tx nicht leer */
4
        (!(I & CTR)))                        /* Int ist nicht Endpoint Interrupt */
5
    { if ((USB_EpRegs(logEpBulkIn) & STAT_TX)!= VALID_BI) /* Buffer ist nicht aktiv */
6
      { I &= 0xFF00;                         /* Endpt Info nullen */
7
        I |= CTR | logEpBulkIn;              /* Int = EpBulkIn setzen */
8
      }
9
    }
10
  }
was bei mir deutlich besser läuft - aber es ist nur ein Workaround um 
den eigentlichen Mangel, daß man der SIE nicht das sagen kann, was man 
will.

So, probiert's aus, ob es damit besser läuft. Mir würde da als weitere 
Maßnahme nur einfallen, den BI auf Stall zu setzen, sobald alle Daten 
draußen sind und dann im nächsten Frame-int den BI-Int nur dann zu 
setzen, wenn BI auf Stall steht. Das ist offenbar das Einzige, was man 
bei diesem Core machen kann - es sei denn, jemand hat da eine bessere 
Idee.

W.S.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

W.S. schrieb:
> Aber wie kriegt man das Ganze wieder in Gang,
> wenn irgendwann später wieder Zeichen im Ringpuffer landen?

Einfach im EPnR die STAT_TX-Bits auf "11" (VALID) setzen. Vorher die 
Adressen des Puffers in der Deskriptor-Tabelle aktualisieren. Das geht 
von beliebigen Codestellen aus und braucht überhaupt keinen 
NAK-Interrupt.

Meine USB-CDC-Implementierung mit Umleitung auf einen "echten" UART 
macht das im UART-IDLE-Interrupt - wenn per UART keine Bytes mehr 
ankommen, werden ggf. im Puffer befindliche "einzelne" Bytes damit als 
kleines Paket (<64) abgeschickt.

"Rein zufällig" ist das genau die Funktionalität, von der du behauptet 
hattest, ich hätte sie nicht implementiert, obwohl sie nachweislich 
funktioniert, während es bei deinem Code eben nicht tut, angeblich weil 
der Controller keinen NAK-Interrupt bietet - ein Schelm wer böses dabei 
denkt...

Beitrag "Re: USB-Tutorial mit STM32"

von Stefan F. (Gast)


Lesenswert?

Tut mir leid Bernd, ich kann da mangels Know-How nicht mit helfen.

von W.S. (Gast)


Lesenswert?

Niklas G. schrieb:
> Meine USB-CDC-Implementierung mit Umleitung auf einen "echten" UART
> macht das im UART-IDLE-Interrupt

Das ist ja sehr schön für dich, aber hier handelt es sich um einen 
einzelnen USB-VCP - und der soll und muß OHNE einen "echten" UART und 
dessen Idle-Interrupt auskommen. Bleibt also die Frage, wo so ein 
Eingreifen in den VCP zu machen wäre: in main? im Timertick? im Char_Out 
der VCP-Treibers? Das würde zum einen auf eine Einzelzeichen-Übertragung 
auf dem USB hinauslaufen und zum anderen auf ein Warten, bis eine 
etwaige Übertragung erledigt ist und der EP-Puffer wieder frei ist. In 
Summe ist das nichts anderes, als das Problem woanders hin zu 
verschieben. Da ist es durchaus besser, das im USB-VCP-Idle-Interrupt zu 
tun, wie ich das eben tue. Dann bleibt die Funktionalität im USB-Treiber 
und macht keine weiteren Abhängigkeiten auf.

W.S.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

W.S. schrieb:
> im Char_Out
> der VCP-Treibers?

Da natürlich, indirekt.

W.S. schrieb:
> Dann bleibt die Funktionalität im USB-Treiber
> und macht keine weiteren Abhängigkeiten auf.

Das "Char_Out" ist sowieso vom USB-Treiber abhängig. Das kann da dann 
auch ein transmitPacket aufrufen.

W.S. schrieb:
> Das würde zum einen auf eine Einzelzeichen-Übertragung
> auf dem USB hinauslaufen und zum anderen auf ein Warten, bis eine
> etwaige Übertragung erledigt ist und der EP-Puffer wieder frei ist.

Natürlich. Wer synchrone Sende-APIs aufruft muss damit rechnen, dass sie 
blockieren. Char_Out müsste in einen Puffer schreiben, und wenn es 
feststellt, dass der voll ist, direkt ein transmitPacket aufrufen. Man 
könnte auch noch eine "Flush"-Funktion zur Verfügung stellen, welche den 
Puffer direkt abschickt, oder einen Timer für Timeouts nutzen, um 
halbvolle Puffer abzuschicken.

In meinem API habe ich eine Funktion transmitPacket, welche man 
jederzeit aufrufen kann, um ein Paket direkt abzuschicken - es sei denn, 
es wird gerade eines übertragen. Wenn das Paket fertig abgeschickt 
wurde, wird ein Callback aufgerufen. Dort kann man direkt das nächste 
Paket abschicken, muss man aber nicht - und transmitPaket irgendwann 
später aufrufen (ohne einen NAK-Interrupt).

Diese asynchrone Vorgehensweise ermöglicht maximale Kontrolle über den 
Sende-Prozess und simultanes Senden und sonstigen Programmablauf. Wenn 
man aber eine synchrone Funktion wie "Char_Out" hat welche erst 
zurückkehren soll wenn das Zeichen vom Treiber entgegengenommen wurde 
(ob im Puffer oder schon unterwegs), dann muss das eben ggf. warten.

Was soll der NAK-Interrupt überhaupt bringen? Warum das Senden erst bei 
Ankunft eines "IN" Tokens auslösen, und nicht direkt? Da kann man den 
NAK-Interrupt auch mit einem Timer simulieren, oder den SOF Interrupt 
nehmen. Es gibt wenig Zusammenhang zwischen "NAK" wurde gesendet und 
"jetzt kann ich mein Paket zum Abschicken freigeben". Man muss sich nur 
merken ob schon etwas in Übertragung ist, und wenn nicht, eben direkt 
abschicken.

von W.S. (Gast)


Lesenswert?

Niklas G. schrieb:
> Was soll der NAK-Interrupt überhaupt bringen? Warum das Senden erst bei
> Ankunft eines "IN" Tokens auslösen, und nicht direkt?

Das ist doch sehr einfach: Die USB-CDC-Treiberfunktionen, die zum 
Verkehr mit den sonstigen Teilen der Firmware dienen, arbeiten auf einen 
Puffer im USB-Treiber und sind damit entkoppelt vom gesamten Geschehen 
innerhalb des USB-Treibers. Das ist deshalb, weil das Ganze ja eben eine 
serielle Schnittstelle aus Sicht von außen sein soll - und kein 
Blockdevice. Deshalb verbietet es sich von selbst, aus der letztlich zu 
main() gehörigen Welt in die zum USB gehörige Welt so einfach 
hineinzutrampeln. Das wäre genau so, wie das Aufrufen einer ISR aus 
main() heraus. Macht man nicht, weil sich das beißt, da es zwei 
unabhängige Instanzen sind.

Also: Char_Out('X',toUSB) gehört zur Instanz von main() - und auf der 
anderen Seite des Ringpuffers sind die Endpoint-Handler, die nicht zur 
Instanz von main() gehören, sondern zum Interrupt-Handler.

Bedenke mal, daß bei einem 70 MHz Controller der Puffer im Treiber 
sowohl mal mit rund 1 Zeichen pro Sekunde (Mensch tippt am anderen Ende 
auf Tastatur) als auch mal mit 50 Zeichen oder mehr pro Mikrosekunde 
gefüllt werden kann - eben je nach den äußeren Umständen, die man im 
USB-Treiber nie vorhersagen kann. Eben deshalb SOLL es ja völlig 
asynchron gehen, was das Hineingrätschen in die inneren Gefilde der 
Endpoint-Handler einfach verbietet.

W.S.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

W.S. schrieb:
> Deshalb verbietet es sich von selbst, aus der letztlich zu
> main() gehörigen Welt in die zum USB gehörige Welt so einfach
> hineinzutrampeln

Wieso? "verbietet sich von selbst" ist keine schlüssige Argumentation. 
Man sollte nur ggf. vorher den USB-Interrupt sperren. Während eines 
hypothetischen NAK-Interrupts wären die anderen USB-Interrupts ja auch 
blockiert.

W.S. schrieb:
> Macht man nicht, weil sich das beißt, da es zwei
> unabhängige Instanzen sind.

Instanzen von was?

W.S. schrieb:
> Macht man nicht

Warum nicht? Warum ist das im UART-Interrupt oder USB-NAK-Interrupt ok, 
aber aus der main() nicht? Beide Interrupts haben mit dem tatsächlichen 
Abschicken nichts zu tun.

W.S. schrieb:
> eben je nach den äußeren Umständen, die man im
> USB-Treiber nie vorhersagen kann

Das ist kein Argument. Wenn die USB-State Machine steht, muss man sie 
irgendwie antriggern. Am Einfachsten geht das, indem man direkt 
abschickt. Man könnte sich einen "künstlichen" Interrupt auslösen (z.B. 
SysTick oder SVC), das ist aber letztlich kein Unterschied.

W.S. schrieb:
> was das Hineingrätschen in die inneren Gefilde der
> Endpoint-Handler einfach verbietet.

Die sind ja dank hoffentlich vorhandener Strukturierung des Codes 
ordentlich gekapselt. In meinem Code hauptsächlich in der 
EPBuffer-Klasse. Da funktioniert das ganze auch wie gesagt ganz 
wunderbar ohne irgendwelche Workarounds oder künstliche Interrupts.

von Bernd N (Gast)


Lesenswert?

Erst einmal vielen Dank für eure Antworten und die detailreichen 
Erklärungen. Ich verstehe leider nur sehr begrenzt alle Erklärungen und 
versuche erst einmal die Änderung umzusetzten.

Die usb.c Datei lässt sich hierbei nicht einfach so austauschen. Also 
die Änderungen im Code ist dann, wenn ich es richtig verstehe, folgender 
Abschnitt...
1
  if (I & SOF)                               /* Start of Frame, alle 1 ms */
2
  { USB_ISTR = ~SOF;                         /* Int löschen */
3
    if ((txr != txw) &&                      /* Tx nicht leer */
4
        (!(I & CTR)))                        /* Int ist nicht Endpoint Interrupt */
5
    { if ((USB_EpRegs(logEpBulkIn) & STAT_TX)!= VALID_BI) /* Buffer ist nicht aktiv */
6
      { I &= 0xFF00;                         /* Endpt Info nullen */
7
        I |= CTR | logEpBulkIn;              /* Int = EpBulkIn setzen */
8
      }
9
    }
10
  }
Hinzu kommt dann noch...
1
#define  VALID_BI   (3<<4)  /* Bulk in ist am Transferieren */

Ich habe es so in den Code eingefügt aber das Problem beszeht weiterhin. 
Habe ich hier alles beachtet ? oder irgendetwas übersehen ?

Vielen Dank für eure Hilfe.

von Stefan F. (Gast)


Lesenswert?

Bernd N schrieb:
> Habe ich hier alles beachtet ? oder irgendetwas übersehen ?

Ic schätze mal, dass du die gesamte geänderte Datei vorzeigen solltets. 
Was soll der gute W.S. sonst kontrollieren?

von Bernd N (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Stefan,

es ist die von dir bearbeitete Version + die Änderung. Wie gesagt, die 
Datei läßt sich so nicht austauschen, stellt sich die Frage was du an 
dem Original von WS geändert hast ?

Im Anhang die modifizierte Version. Vielleicht schaust du auch mal da 
hinein.

von Bernd N (Gast)


Lesenswert?

Oder pflege du doch mal die Änderung von WS bei dir ein, du hast dich ja 
mit dem Code beschäftigt.

von Stefan F. (Gast)


Lesenswert?

Bernd N schrieb:
> stellt sich die Frage was du an
> dem Original von WS geändert hast ?

Vergleiche die Dateien, dann siehst du es. Ich habe die formatiert, 
Debug Ausgaben eingefügt, ein bisschen Code zur Unterstützung anderer 
STM32 Modelle und ein paar Verbesserungen, die hier im Forum diskutiert 
wurden.

Es sind insgesamt nur wenige Zeilen verändert, wenn man die Formatierung 
nicht mit zählt.

> Vielleicht schaust du auch mal da hinein.

Ich habe gerade keine Zeit, diese Änderung zu testen.

von Bernd N (Gast)


Lesenswert?

Ich denke ich habe es schon richtig gemacht. Ich warte dann mal noch auf 
das Feedback von WS.

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Bernd N schrieb:
> Ich denke ich habe es schon richtig gemacht.

Klar, alle anderen sind zu doof zum Programmieren. Wenn Dein Programm 
nicht funktioniert, kann es nicht an Dir liegen.

von Stefan F. (Gast)


Lesenswert?

Bernd N schrieb:
> Ich denke ich habe es schon richtig gemacht.

Ich schätze, du hast den falschen Absatz ersetzt. Es hätte einer höher 
sein sollen, der mit
1
if (I & SOF) /* Start of Frame, alle 1 ms */

beginnt.

Anmerkung: fachlich habe ich davon keine Ahnung. Ich habe nur logisch 
geprüft.

von Bernd N (Gast)


Lesenswert?

Oh, man sollte spät am Abend einfach aufhören :-), danke für den 
Hinweis. Ich werde es heute Abend testen und berichten.

>> Klar, alle anderen sind zu doof zum Programmieren. Wenn Dein Programm
>> nicht funktioniert, kann es nicht an Dir liegen.

Habe ich nie behauptet, wenn du nichts anderes beizutragen hast, dann 
bleib einfach im Hintergrund. NOCH! ist dieser Thread hier nicht versaut 
wie soviele andere in diesem Forum. Ich habe einen Fehler gemacht, so 
what ?

Ich bin Dankbar für die Jungs hier die ihren Code mit uns teilen und 
hilfsbereit sind aber auf dämliche Kommentare kann ich verzichten.

Danke Stefan und WS sowie Niklas und Pieter.

von W.S. (Gast)


Lesenswert?

Niklas G. schrieb:
> W.S. schrieb:
>> Macht man nicht, weil sich das beißt, da es zwei
>> unabhängige Instanzen sind.
>
> Instanzen von was?

Mir scheint, dir fehlt das Grundverständnis. Also: In einer Firmware, 
die auch Interrupts bearbeitet, gibt er per se mehrere Instanzen:
#1: alles, was von main() ausgeht.
#2..n: alle Interrupts.

Dir ist sicherlich klar, daß die Interrupts die Instanz #1 je nach 
externem Gusto unterbrechen, weswegen man beide sozusagen als 
verschiedene Akteure ansehen muß. Hier hat es schon viele Diskussionen 
gegeben, wie man es fertig bringt, daß die sich nicht gegenseitig ins 
Gehege kommen. Atomare Zugriffe, Semaphoren und so weiter. Es hatte hier 
sogar schon Diskussionen darüber gegeben, ob man ISR im Programm (also 
aus Instanz #1 heraus) aufrufen soll oder nicht. Natürlich nicht, denn 
das führt irgendwann zum Chaos.

So, als Trennstelle zwischen Instanz #1 und der inneren 
USB-Funktionalität dienen die beiden Ringpuffer im Treiber. Der 
Char_Out(..), also der Vertreter von Instanz #1 darf den Schreib-Zeiger 
bewegen und den Lese-Zeiger lediglich lesen (um sicherzustellen, daß er 
den Puffer nicht überfüllt) - und die ISR darf den Lese-zeiger bewegen 
und den Schreib-Zeiger lediglich lesen. Beim Char_In() ist es genau 
umgekehrt. Damit sind beide Welten voneinander getrennt. Es darf nur 
keine von beiden die andere "überfahren" wollen. Also kein 
Hineingrätschen der einen Instanz in die inneren Angelegenheiten der 
anderen.

Das alles wiederum bedeutet, daß das Herumfummeln an den Registern und 
Speichern der USB-Hardware von außerhalb, also aus Instanz #1 sich von 
selbst verbietet. Um dennoch dafür sorgen zu können, daß in sinnvoller 
Zeit das Zeugs, was im Sende-Ringpuffer vor sich hinschmort, auch mal 
zum Host gesendet wird, braucht es ne Maßnahme, die möglichst wenig 
"trampelig" ist. Das Erlauben des NAK_BI wäre so etwas. Ist aber bei dem 
hier vorliegenden µC mW. nicht möglich.

W.S.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

W.S. schrieb:
> Also: In einer Firmware,
> die auch Interrupts bearbeitet, gibt er per se mehrere Instanzen:
> #1: alles, was von main() ausgeht.
> #2..n: alle Interrupts.

Das nennt man eher "Kontext". Instanzen kenne ich als Objekte, also 
Instanzen von Klassen (OOP).

W.S. schrieb:
> Damit sind beide Welten voneinander getrennt.

Diese Trennung ist aber künstlich, unnötig und in diesem Fall sogar 
hinderlich. Das Senden von USB-Paketen aus der main() heraus zu 
verbieten bringt gar nichts. Die Initialisierung des USB-Cores macht man 
ja auch aus der main() heraus.

W.S. schrieb:
> Das Erlauben des NAK_BI wäre so etwas.

Und warum ausgerechnet ein NAK-Interrupt? Warum nicht der 
SysTick-Interrupt?  Oder ein ADC-Interrupt? Alle drei haben nichts damit 
zu tun, ob jetzt gerade ein Paket gesendet werden kann, sind also alle 
drei gleich verkehrt. Sie kommen aber, falls entsprechend konfiguriert, 
regelmäßig.

von W.S. (Gast)


Lesenswert?

Niklas G. schrieb:
> Und warum ausgerechnet ein NAK-Interrupt?

Weil das ein Interrupt ist, der von der SIE erzeugt wurde. Es ist Teil 
des Interrupt-Geschehens des USB und hat rein GARNICHTS mit Systick ode 
ADC zu tun.

Ich habe es dir bereits ausführlich erläutert und damit soll es nun 
genug sein. Ich möchte das mit dir jetzt nicht weiter diskutieren.

W.S.

von W.S. (Gast)


Lesenswert?

Bernd N schrieb:
> while (1)
> { if (UsbRxAvail() == true)
>   { if (UsbTxReady() == true)
>       UsbCharOut(UsbGetChar());
>   }
> }

Mir kommt deine Schleife zu eng vor. Ja, sie sollte zwar funktionieren, 
aber versuche du mal, selbige zu trennen. Also in jedem Falle erstmal 
Rx-Daten abholen und passend zwischenspeichern. Danach erst - sobald 
Platz ist im Tx, selbige senden.

Ich habe nämlich das Gefühl, daß es erstmal nötig ist, herauszufinden, 
ob die Empfangsseite oder die Sendeseite ins Stocken kommt.

Das Senden von Daten zum Host hin ist per se nämlich langsamer als das 
Empfangen, weil bei leerem Ringpuffer das Senden erst mit dem nächsten 
Frametick wieder losgeht. Das wäre dann eine Verzögerung von bis zu 1 
ms.

Wenn dein Zwischenspeicher leerläuft, dann ist es die Empfangsrichtung, 
wenn er überläuft, dann die Senderichtung.

W.S.

von Stefan F. (Gast)


Lesenswert?

Bernd N schrieb:
> Wenn ich jetzt mittels Terminal eine Datei versende (in TTerm File Send
> File Funktion" dann hängt sich der Controller / Software auf.

> 1 while (1) {
> 2   if (UsbRxAvail() == true) {
> 3     if (UsbTxReady() == true)
> 4       UsbCharOut(UsbGetChar());
> 5   }
> 7 }


Ich bin nicht sicher, ob ich das Problem überhaupt verstanden habe. 
Könnt ihr bitte meine Annahmen bestätigen oder korrigieren?

Der Mikrocontroller findet in Zeile 2 mit 100% Sicherheit heraus, dass 
er etwas empfangen hat. Wenn der Sendepuffer in Zeile 3 voll ist, wird 
das empfangene Zeichen nicht ausgelesen, und es wird auch nicht zurück 
gesendet. Das ganze kommt erst wieder in Gang, wenn der Sendepuffer frei 
wird, was hier aber wegen einem bug (darf man das so nennen?) nicht 
passiert.

W.S. schrieb:
> Mir kommt deine Schleife zu eng vor.

Meinst du so?:

> 1 while (1) {
> 2   if (UsbRxAvail() == true) {
> 3     char c=UsbGetChar();
> 4     while (UsbTxReady() != true) {}; // wait
> 5     UsbCharOut(c);
> 6   }
> 6 }

Mir ist nicht klar, was daran besser sein soll. Jetzt wird ein Zeichen 
früher aus dem Empfangspuffer geholt. Hat das einen positiven 
Seiteneffekt auf den Sendepuffer?

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

W.S. schrieb:
> hat rein GARNICHTS mit Systick ode
> ADC zu tun.

Doch, genau wie ADC und Systick hat es nichts mit dem Senden von Paketen 
zu tun. Dass er zufällig vom USB erzeugt wird, hat nichts damit zu tun, 
ob er auch zum Senden von Paketen geeignet ist.

W.S. schrieb:
> Ich habe es dir bereits ausführlich erläutert und damit soll es nun
> genug sein.

Du erläuterst also mir etwas was bei mir funktioniert, bei dir aber 
nicht? Ahja.

Ich habe mal aus Spaß eine Loopback-Variante meines 3x-VCP gebastelt. 
Sie sendet die kompletten empfangenen Pakete direkt zurück. Kann ich 
aber gerade nicht testen. Man könnte das noch schöner machen mit 
Doppelpuffer und Vermeidung des Umkopierens zwischen USB-RAM <-> SRAM. 
Hier der Code:

https://github.com/Erlkoenig90/f1usb/tree/vcp-loopback
https://github.com/Erlkoenig90/f1usb/blob/vcp-loopback/src/vcp.cc

Das ganze natürlich asynchron ohne Warteschleifen und Blockierung. Das 
Senden wird hier sogar gar nicht aus der main() veranlasst, sondern aus 
dem USB-Empfangs-Interrupt; das ist hier aber "Zufall" und ginge auch 
anders.

von Niklas G. (erlkoenig) Benutzerseite


Angehängte Dateien:

Lesenswert?

So, konnte es jetzt testen, hat fast sofort funktioniert, brauchte nur 
eine kleine Korrektur. Im Anhang das Binary, funktioniert z.B. auf den 
Bluepills mit STM32F103C8. Dank asynchroner Programmierung hat es auch 
keine Endlosschleife und braucht wenig Strom.

von W.S. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Der Mikrocontroller findet in Zeile 2 mit 100% Sicherheit heraus, dass
> er etwas empfangen hat. Wenn der Sendepuffer in Zeile 3 voll ist, wird
> das empfangene Zeichen nicht ausgelesen, und es wird auch nicht zurück
> gesendet. Das ganze kommt erst wieder in Gang, wenn der Sendepuffer frei
> wird, was hier aber wegen einem bug (darf man das so nennen?) nicht
> passiert.

Ich bin mir nicht sicher, ob es DAS ist.

Ich habe soeben mal nen Test gemacht: Habe so ein 
STM32F103C8T6-Universalboard hergenommen, wie ich es hier schon mal 
gepostet hatte und habe per Terminalprogramm vom PC aus dem dortigen 
Kommandoprogramm den Befehl
1
D 0 1FFFF
gegeben. Also er soll den Bereich 0..1FFFF als hexdump ausgeben. So eine 
Zeile davon sieht etwa so aus:
1
00000000: F0 4F 00 20 4D 01 00 00 75 01 00 00 7B 01 00 00  O  M   u   {    
2
...

Pro Byte ergibt das also mehr als 4 Textzeichen (2 Hex, 1 Space, 1 
Char), macht also rund 1 MB aus - und die gesamte Übertragung zum PC hin 
einschließlich Scrollen im Terminalfenster dauert etwa 3 Sekunden. 
Formatfehler habe ich keine gesehen. Hab's eben auch mit D 0 3FFFF 
probiert, geht auch.

Fazit: das Senden von Datenblöcken von 1 bis 4 MB vom µC zum PC hin geht 
bei mir völlig problemlos. Die Sendeseite im STM32 tut also ihren 
Dienst. Für mich ist das damit abgehakt.

Nachtrag:
Hab das Ganze eben nochmal mit einem älteren Board probiert, wo noch die 
Altversion des usb.c drauf ist. Resultat: geht auch alles, dauert bloß 
länger, nämlich ca. 10 sekunden anstelle 3 Sekunden.



Stefan ⛄ F. schrieb:
> Mir ist nicht klar, was daran besser sein soll. Jetzt wird ein Zeichen
> früher aus dem Empfangspuffer geholt. Hat das einen positiven
> Seiteneffekt auf den Sendepuffer?

Nee, ich meine das anders. Ich hätte an der Stelle des TO versucht, 
zuerst einmal herauszukriegen, ob das nun an der Empfangsseite (PC-->µC) 
oder an der Sendeseite (µC-->PC) liegt. Dazu hätte ich auf dem STM32 in 
main mir einen recht großen Ringpuffer angelegt, halbvoll mit irgendwas 
gefüllt und in der Schleife diesen dann weiter gefüllt, sofern 
Empfangszeichen anliegen. Ebenso hätte ich unabhängig vom Empfangen 
versucht, Zeichen aus diesem Puffer zu senden. Ich hätte dann eigentlich 
3 Arten des Verhaltens erwartet:
1. Puffer läuft über --> Sendeseite schafft es nicht
2. Puffer wird leer --> Empfangsseite schafft es nicht
3. Empfangen und Senden funktionieren
OK, man kann sich auch andere Strategien ausdenken, der Sinn ist jedoch 
immer, herauszufinden, woran so ein "funktioniert nicht" eigentlich 
hängt.


Nach meinen obigen Tests vor ein paar Minuten habe ich da Zweifel, ob 
das überhaupt an der Hardware liegt. Mein Terminalprogramm ist 
selbstgeschrieben, Delphi. Und damit klappt zumindest die Sendeseite 
(µC-->PC) ersichtlichermaßen problemlos. Das legt den Verdacht nahe, daß 
es beim Terminalprogramm des TO ne Schwierigkeit geben könnte. Wenn das 
wirklich ausgeschlossen werden kann, dann bleibt noch das separate 
Ausprobieren der Übertragungsrichtungen.

Ach ja: was macht so ein TTerm eigentlich, wenn da während einer 
Dateiübertragung vom µC her massiv Zeichen hereinkommen, die eben auch 
nicht alle im ASCII Bereich liegen?

W.S.

von Bernd N (Gast)


Lesenswert?

So, ich habe eben Niklas BIN File getestet und es funktioniert perfekt.

Ich habe ebenso die Änderung von WS eingebaut, dann geht nix mehr. Der 
hängt sich bei mir direkt auf.

Sorry für den Fehler von gestern aber soweit jetzt das Ergebnis.

von Bernd N (Gast)


Lesenswert?

>> Das legt den Verdacht nahe, daß es beim Terminalprogramm des TO ne
>> Schwierigkeit geben könnte. Wenn das wirklich ausgeschlossen werden
>> kann, dann bleibt noch das separate Ausprobieren der
>> Übertragungsrichtungen.

Ich glaube das Terminal Programm ist ok. Ich werde jetzt mal ein paar 
Tests machen um es näher einzugrenzen und gehe dabei mal auf die 
originale Version zurück.

von Bernd N (Gast)


Lesenswert?

> 1 while (1) {
> 2   if (UsbRxAvail() == true) {
> 3     if (UsbTxReady() == true)
> 4       UsbCharOut(UsbGetChar());
> 5   }
> 7 }

Das ist übrigens redundant.
1
char UsbCharOut(char c)
2
{
3
    int i;
4
    i = (txw + 1) & (txLen - 1);
5
    while (!UsbTxReady())
UsbCharOut prüft bereits auf UsbTxReady.

von Bernd N (Gast)


Lesenswert?

Ich denke ich werde mich am WE mal in den Code eingraben. Ich habe jetzt 
mal ein transmit delay pro Zeile (anstatt Zeichen) eingebaut. Eine Zeile 
ist natürlich bezogen auf die Zahl der Zeichen < Buffer Size. Gibt man 
also dem Ganzen per nZeichen Zeit dann ist auch alles OK. Ich denke das 
bekomme ich auch per workaround gelöst und stellt somit kein großes 
Problem da.

Das Abarbeiten bei der Zeichen ist aber mit dem BIN File erheblich 
schneller.
@ Niklas, wo kann ich mir dein Projekt mal herunterladen ?

von Thomas Z. (usbman)


Lesenswert?

ich benutze den VCP Code von Niklas jetzt schon einige Zeit. Der 
funktioniert einwandfrei. Das einzige was mir aufgefallen ist, dass im 
Deskribtor bcdCDC auf 0.10 steht das sollte wohl 0x1000 für 1.0 sein.

von Niklas Gürtler (Gast)


Lesenswert?

Bernd N schrieb:
> @ Niklas, wo kann ich mir dein Projekt mal herunterladen ?

Hier die Loopback Variante:

https://github.com/Erlkoenig90/f1usb/tree/vcp-loopback

Normaler VCP mit Umleitung auf UART:

https://github.com/Erlkoenig90/f1usb/tree/vcp

Ausführliche dazugehörige Anleitung:
USB-Tutorial mit STM32

Thomas Z. schrieb:
> ich benutze den VCP Code von Niklas jetzt schon einige Zeit. Der
> funktioniert einwandfrei.

Schön zu hören :)

Thomas Z. schrieb:
> dass im Deskribtor bcdCDC auf 0.10 steht das sollte wohl 0x1000 für 1.0
> sein.

Danke für den Hinweis... das werd ich mir nachher mal ansehen.

von ... (Gast)


Lesenswert?

Die Beiträge von W.S. sind wieder zum fremd schämen.

Es ist interessant, dass so jemand es zustande bekommt einen USB VCP zu 
schreiben.
Oder wurde der abgeschrieben und als Eigen verkauft?

von Stefan F. (Gast)


Lesenswert?

... schrieb:
> Die Beiträge von W.S. sind wieder zum fremd schämen.

Sind sie gar nicht. Er hat für viele Mikrocontroller kostenlose USB 
Quelltexte veröffentlicht. Wie viele Leute in diesem Land sind dazu 
imstande? Mehr als 10 werden es kaum sein. Jetzt ist ein Problem 
aufgetreten, dass er nicht auf Anhieb versteht und lösen kann. Dafür 
muss man sich doch nicht schämen!

Wenn du so schlau bist, dann korrigiere den Fehler doch selbst! Dafür 
ist es Open-Source. Dadurch kannst du einen hilfreichen Beitrag zur 
Community leisten, anstatt hier herum zu mobben.

> Oder wurde der abgeschrieben und als Eigen verkauft?

Du kennst die Historie nicht, also halte doch einfach mal ....

Den Code hat W.S. vor einigen Jahren entwickelt, als er damit auch 
beruflich beschäftigt war.

von Niklas G. (erlkoenig) Benutzerseite


Angehängte Dateien:

Lesenswert?

Stefan ⛄ F. schrieb:
> Jetzt ist ein Problem
> aufgetreten, dass er nicht auf Anhieb versteht und lösen kann. Dafür
> muss man sich doch nicht schämen!

Also mein Problem mit W.S. ist hier die Art und Weise wie er mich damals 
für meinen USB-Code vollkommen sinnlos von oben herab angegangen ist:

Beitrag "Re: USB-Tutorial mit STM32"

Das war unmöglich und entbehrte jeder Grundlage. Gleichzeitig 
funktioniert der von ihm zu Unrecht bei mir bemängelte Aspekt bei ihm 
bis heute nicht - bei mir von Anfang an schon. Die Ausflüchte mit dem 
NAK-Interrupt sollen wohl die Schuld nur auf die Hardware schieben. Das 
hat er jetzt davon.

Stefan ⛄ F. schrieb:
> Wenn du so schlau bist, dann korrigiere den Fehler doch selbst! Dafür
> ist es Open-Source.

Open Source bedeutet aber nicht Freie Software. Da er keinerlei Lizenz 
angibt (z.B. MIT, BSD, GPL oder einfach public domain) darf man den Code 
rein rechtlich nichtmal nutzen, geschweige denn verändern oder weiter 
veröffentlichen. Auch das wurde schon besprochen:

Beitrag "Re: USB-Tutorial mit STM32"

Indem du den Code auf deiner Website veröffentlichst begehst du eine 
Urheberrechtsverletzung - W.S. könnte dich jederzeit verklagen. 
Allerdings gibt er auch keinen Haftungsausschluss...

Etwas schade dass trotz rechtlicher und funktionaler Probleme W.S.' Code 
hier im Forum anscheinend mehr Beachtung findet - oder vielleicht haben 
die Leute nur mehr Probleme damit :)

Thomas Z. schrieb:
> Das einzige was mir aufgefallen ist, dass im
> Deskribtor bcdCDC auf 0.10 steht das sollte wohl 0x1000 für 1.0 sein.

Ich glaube es muss 0x110 sein, so steht es auch im Beispiel-Deskriptor 
in der CDC-Spec auf S. 28 (CDC120-20101103-track.pdf). "lsusb" 
interpretiert das dann auch als 1.10 . Ich habe das in GitHub 
korrigiert; im Anhang das aktualisierte Loopback-Image.

: Bearbeitet durch User
von Bernd N (Gast)


Lesenswert?

Bitte den Thread nicht zum flamen und streiten verwenden. Ich verstehe 
die Zwistigkeiten aber ich seh es ähnlich wie Stefan. Ich bin dankbar 
für den Code und WS ist bemüht hier zu helfen. Das ist hier ein Hobby 
und nicht für Stänkereien gedacht.

>> Etwas schade dass trotz rechtlicher und funktionaler Probleme
>> W.S.' Code hier im Forum anscheinend mehr Beachtung findet

WS Code ist in C, deiner in C++. Für mich ist das ein Grund aber kein 
echter Showstopper. Möglicherweise geht es anderen auch so.

Dein Tutorial arbeite ich gerade parallel durch, so was ist wirklich 
klasse.

Also, bleibt freundlich, Danke,

Bernd

von Thomas Z. (usbman)


Lesenswert?

Stefan ⛄ F. schrieb:
> Wie viele Leute in diesem Land sind dazu
> imstande? Mehr als 10 werden es kaum sein

glaubst du das wirklich? So kompliziert ist USB nun auch wieder nicht. 
Oder du hast eine andere Definition von diesem Land.

Niklas G. schrieb:
> Etwas schade dass trotz rechtlicher und funktionaler Probleme W.S.' Code
> hier im Forum anscheinend mehr Beachtung findet

das liegt vieleicht an C++. Damit hatte ich anfangs auch Probleme 
einfach weil constexp für mich neu war. Es hat etwas gedauert bis ich 
das kapiert habe. Ich muss dazu sagen dass ich immer noch vorwiegend c 
spreche. Dein Tutorial at mir da sehr weitergeholfen.

Niklas G. schrieb:
> Ich glaube es muss 0x110 sein, so steht es auch im Beispiel-Deskriptor

die letzte spec wäre 1.30 -> 0x0130. Das ist aber vollkommen egal. Die 
Version wird von den Treibern nicht überprüft.

Thomas

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Thomas Z. schrieb:
> glaubst du das wirklich? So kompliziert ist USB nun auch wieder nicht.

Das nicht, aber nicht viele setzen sich mit solchen Details auseinander. 
Mehr als 10 sind es aber vermutlich schon...

Thomas Z. schrieb:
> Dein Tutorial at mir da sehr weitergeholfen.

Das ist doch schön :) Gerade für USB hat C++ und OOP Vorteile weil man 
die Endpoint-Behandlung so schön kapseln kann. Ursprünglich wollte ich 
das sogar in C machen, aber es war einfach so schmerzhaft die Dinge, die 
zusammen gehören, nicht vernünftig zusammen packen zu können, weshalb 
ich dann schnell wieder C++ genommen hab.

Dank C++ können die USB-UTF16-Strings bei mir so aussehen (und sind 
vollkommen unabhängig von der Kodierung der Source-Datei):
1
static constexpr auto strManufacturer = EncodeDescriptors::USB20::string (u"ACME Corp.");

Während sie in W.S.' C-Code so aussehen müssen:
1
const byte VendorStringDescriptor[] = {
2
    16,           /* bLength          */
3
    DESC_STRING, /* bDescriptorType  */
4
    'N', 0,
5
    'u', 0,
6
    'v', 0,
7
    'o', 0,
8
    't', 0,
9
    'o', 0,
10
    'n', 0
11
};

Thomas Z. schrieb:
> die letzte spec wäre 1.30 -> 0x0130. Das ist aber vollkommen egal. Die
> Version wird von den Treibern nicht überprüft.

Scheint so, hat bei mir auch immer funktioniert... Da das Gerät ja zu 
1.1 kompatibel ist kann man das auch angeben.

von ... (Gast)


Lesenswert?

Niklas G. schrieb:
> Also mein Problem mit W.S. ist hier die Art und Weise wie er mich damals
> für meinen USB-Code vollkommen sinnlos von oben herab angegangen ist

Das tut er immer hier und macht sich deswegen viele Feinde.
Hat seine Lernbetty USB?

Stefan ⛄ F. schrieb:
> Den Code hat W.S. vor einigen Jahren entwickelt, als er damit auch
> beruflich beschäftigt war.

Also von Arbeit kopiert!

von Stefan F. (Gast)


Lesenswert?

Niklas G. schrieb:
> Etwas schade dass trotz rechtlicher und funktionaler Probleme W.S.' Code
> hier im Forum anscheinend mehr Beachtung findet - oder vielleicht haben
> die Leute nur mehr Probleme damit :)

Der hauptgrund dürfte sein, dass dein Code in C++ geschrieben wurde. Das 
wollen viele nicht benutzen. Insbesondere nicht in der modernen Version, 
die dein Code voraussetzt.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Stefan ⛄ F. schrieb:
> Insbesondere nicht in der modernen Version,
> die dein Code voraussetzt.

C++11 ist jetzt auch 8,5 Jahre alt...

von Stefan F. (Gast)


Lesenswert?

Niklas G. schrieb:
> Stefan ⛄ F. schrieb:
>> Insbesondere nicht in der modernen Version,
>> die dein Code voraussetzt.
>
> C++11 ist jetzt auch 8,5 Jahre alt...

Ich weiß. Es gibt sogar Leute, die die Erweiterungen von C99 ablehnen.

von W.S. (Gast)


Lesenswert?

Nanana, Leute.

Also, der Sturm im Wasserglas hat sich von meiner Seite aus komplett 
gelegt. Ich habe nämlich das Ganze Drama mal selbst durchexerziert wie 
folgt.

Also, auf der µC-Seite eine kleine Erweiterung des Kommandoprogramms:
1
 if (match("UTEST",&Cpt))
2
 { L =  Long_In(&Cpt);
3
   while (L)
4
   { if (RxAvail(toUSB))
5
     { c = GetChar(toUSB);
6
       Char_Out(c, toUSB);
7
       --L;
8
     }
9
   }
10
   String_Out("\r\nSodele, das war es dann\r\n", toUSB);
11
   return;
12
 }

Auf der PC-Seite hatte ich zunächst genau wie der TO einfach nur ne 
Datei ohne Pause zum USB geschickt. Damit bleibt die Kommunikation 
tatsächlich nach einer eher unbestimmten Anzahl von Zeichen stecken. Bei 
mir waren es so zwischen 3 und 5 K Byte.

Insofern kann ich das im Eröffnungspost Geschilderte bestätigen.

Allerdings kam mir das fischig vor, weshalb ich in meinem kleinen 
Terminalprogramm (das ich ja in Quelle vorliegen habe) das Senden so 
abgeändert habe wie folgt:
1
procedure TAppform.BlindButtonClick(Sender: TObject);
2
type
3
  PXArray = ^TXArray;
4
  TXArray = array [0..$FFFFFF] of byte;
5
var
6
  F : File;
7
  i : longint;
8
  L : longint;
9
  Sebu: PXArray;
10
  B : Byte;
11
begin
12
  if not OpenDialog.Execute then exit;
13
  AssignFile(F, OpenDialog.FileName);
14
  Reset(F,1);
15
  L:= FileSize(F);
16
  GetMem(Sebu, L);
17
  if Sebu <> nil
18
  then begin
19
         BlockRead(F,Sebu^,L);
20
         CloseFile(F);
21
       end
22
  else begin
23
         CloseFile(F);
24
         exit;
25
       end;
26
  SendeString('UTEST ' +IntToStr(L) + #13#10);
27
28
  for i:= 0 to L-1 do
29
  begin
30
    if ComPort.InCount > 0
31
    then B:= ComPort.ReadB;  // lesen und verwerfen
32
    B:= Sebu^[i];
33
    ComPort.WriteB(B);
34
  end;
35
  FreeMem(Sebu);
36
37
end;

Der Unterschied zum Eröffnungspost ist, daß mein Terminalprogramm 
jetzt die vom µC geechoten Zeichen aus den Untiefen des Betriebssystems 
auch abholt (und hier verwirft, anstatt sie zu verwenden).

Und siehe da: das "Sodele.." kommt punktgenau und die gesamte 
Kommunikation tut was sie soll.

Also: Es ist vermutlich wie so oft: Genau die Ecke, aus der man die 
Störung nie und nimmer vermutet hätte, ist es gewesen.

Wenn man also ellenlange Dateien übertragen will, dann kann man das 
durchaus in beiden Richtungen tun, auch auf Seite des µC als Echo an den 
PC zurücksenden - aber man muß den Kruscht dann auch auf der PC-Seite 
abholen, sonst verstopft man sich den Kanal irgendwo im Terminalprogramm 
oder im Betriebssystem.


Nochwas zu diesem Thread und der hier sich anbahnenden Entgleisung:

Es gibt hier immer wieder Leute, die weder etwas dazulernen wollen, noch 
ihr Wissen und Können tatsächlich weitergeben wollen - sondern die 
offenbar herkommen, um ihr Ego dadurch aufzupolieren suchen, indem sie 
an allem und jedem herummäkeln, Leute beleidigen und böswillige 
Unterstellungen verbreiten.

Sowas hat ne sehr negative Auswirkung auf das gesamte Forum, denn es 
gibt eine Menge Leute, die durchaus gewillt wären, hier ihre Projekte zu 
posten und ihr Wissen einzubringen - aber nicht, wenn sie dafür 
beschimpft und beleidigt werden. Durch sowas geht eines auf lange Sicht 
kaputt: die freie Kommunikation.

W.S.

von Stefan F. (Gast)


Lesenswert?

@W.S. und Niklas
Vielen Dank für eure Mühe die ihr euch bei dem Thema gibt. Ich bin sehr 
froh, dass ich wegen euch nicht mit dem Code von ST herum krebsen muss.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

W.S. schrieb:
> Also: Es ist vermutlich wie so oft: Genau die Ecke, aus der man die
> Störung nie und nimmer vermutet hätte, ist es gewesen.

Mit meinem Code funktioniert es aber ohne Änderung der PC-Seite:

Bernd N schrieb:
> So, ich habe eben Niklas BIN File getestet und es funktioniert
> perfekt.

W.S. schrieb:
> um ihr Ego dadurch aufzupolieren suchen, indem sie
> an allem und jedem herummäkeln, Leute beleidigen und böswillige
> Unterstellungen verbreiten.

Du hast dein Vorgehen sehr gut zusammengefasst. Jedes Mal wenn hier 
jemand eine STM32-Frage hat kommst du her und mäkelst darüber, dass er 
die falschen Bibliotheken benutzt usw.

W.S. schrieb:
> denn es
> gibt eine Menge Leute, die durchaus gewillt wären, hier ihre Projekte zu
> posten und ihr Wissen einzubringen - aber nicht, wenn sie dafür
> beschimpft und beleidigt werden. Durch sowas geht eines auf lange Sicht
> kaputt: die freie Kommunikation.

Und warum machst du dann genau das, z.B. als ich mein Projekt 
vorgestellt hatte?

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

W.S. schrieb:
> um ihr Ego dadurch aufzupolieren suchen, indem sie
> an allem und jedem herummäkeln, Leute beleidigen und böswillige
> Unterstellungen verbreiten.

Jetz hör doch mal auf über dich zu reden.
Wer belagert denn hier das Projekte Unterforum und beschimpft die Leute 
wennse nicht so gammlig programmieren wie du deine Lernbetty?

 W.S. schrieb:
> denn es
> gibt eine Menge Leute, die durchaus gewillt wären, hier ihre Projekte zu
> posten und ihr Wissen einzubringen - aber nicht, wenn sie dafür
> beschimpft und beleidigt werden. Durch sowas geht eines auf lange Sicht
> kaputt: die freie Kommunikation.

Wie nennt man deine Krankheit eigentlich?
Das ist genau dein vorgehen im Projekteforum!
Dein Lernbettyprojekt braucht auch niemand, also hörs auf wie sauer Bier 
jeden an den Hals zu werfen.

von Bernd N (Gast)


Lesenswert?

>> Also, auf der µC-Seite eine kleine Erweiterung des Kommandoprogramms:
1
 if (match("UTEST",&Cpt))
2
 { L =  Long_In(&Cpt);
3
   while (L)
4
   { if (RxAvail(toUSB))
5
     { c = GetChar(toUSB);
6
       Char_Out(c, toUSB);
7
       --L;
8
     }
9
   }
10
   String_Out("\r\nSodele, das war es dann\r\n", toUSB);
11
   return;
12
 }

Sorry, gehört das irgendwo in deinen Code ? das erschließt sich mir 
nicht im geringsten.

Vielleicht gehen wir nochmal einen Schritt zurück. Die erste Änderung 
von dir war...
1
  if (I & SOF)                               /* Start of Frame, alle 1 ms */
2
  { USB_ISTR = ~SOF;                         /* Int löschen */
3
    if ((txr != txw) &&                      /* Tx nicht leer */
4
        (!(I & CTR)))                        /* Int ist nicht Endpoint Interrupt */
5
    { if ((USB_EpRegs(logEpBulkIn) & STAT_TX)!= VALID_BI) /* Buffer ist nicht aktiv */
6
      { I &= 0xFF00;                         /* Endpt Info nullen */
7
        I |= CTR | logEpBulkIn;              /* Int = EpBulkIn setzen */
8
      }
9
    }
10
  }
Das führt zum direkten Absturz, blockieren und funktioniert bei mir (in 
Stefans Projekt) garnicht.

Dein letzter Vorschlag bringt mir auch nichts da ich TTerm verwenden 
werde und es funktioniert bei mir seit 20 Jahren perfekt. Ebenso in dem 
USB Beispiel von Niklas. Du hast ja meine Beobachtungen bestätigt. Also 
deine Änderung auf PC Seite mag bei dir helfen aber ich suche immer noch 
nach einer Lösung in deinem MC Code, welcher in Stefans Projekt 
anzuwenden wäre.

Sorry, ich seh es nicht. Hilf mir mal auf die Sprünge.

von Stefan F. (Gast)


Lesenswert?

Mw E. schrieb:
> Wie nennt man deine Krankheit eigentlich?

Bitte, das muss nicht sein!

Könnt ihr euch beide nicht einfach weg ignorieren?

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

W.S. ist nicht wegignorierbar.

Aber es ist schon interessant, dass er hier andere bei deren Projekten 
angeht und das auf überheblichste und widerlichste Weise.
Nur er zählt! Nur sein Programmierstil! Alle haben es so zu machen wie 
bei seiner Lernbetty!

Aber wenn man mal etwas unfreundlich in seine Richtung geht, dann kommt 
sowas:
W.S. schrieb:
> denn es
> gibt eine Menge Leute, die durchaus gewillt wären, hier ihre Projekte zu
> posten und ihr Wissen einzubringen - aber nicht, wenn sie dafür
> beschimpft und beleidigt werden.

Es kommt also ein mimi wenn man mit ihm so umgeht wie er mit anderen 
umgeht.

Daher die Frage:
Mw E. schrieb:
> Wie nennt man deine Krankheit eigentlich?

Es obliegt ihm sich nicht über andere zu stellen und deren Projekte 
schlechtzureden.

von Stefan F. (Gast)


Lesenswert?

Er teilt halt gerne aus und kann nicht einstecken. Das ist uns allen 
doch lange bekannt. Es hilft niemanden, sich darüber immer wieder erneut 
aufzuregen. Wir können ihn nicht umerziehen, deswegen lieber nicht noch 
mehr Öl ins Feuer zu gießen.

Ich bin genau so ein alter Baum, den man nicht mehr biegen kann. So ist 
das eben bei uns Menschen früher oder später.

von Pieter (Gast)


Lesenswert?

na, seit ihr nun fertig?

Eine ganz andere Frage: Warum benutzt ihr die RS232/UART via USB?
Was sind die Vorteile(?) z.b. gegenüber USB-HID.

von Stefan F. (Gast)


Lesenswert?

Pieter schrieb:
> Eine ganz andere Frage: Warum benutzt ihr die RS232/UART via USB?
> Was sind die Vorteile(?) z.b. gegenüber USB-HID.

Alle Programmiersprachen (außer Java) können UART Schnittstellen 
out-of-the-box ansteuern*. Und man kann sie leicht mit einem 
Terminal-Programm manuell benutzen, um z.B. Fehler zu untersuchen. Es 
ist schlicht der direkte Nachfolger bis bisher beliebten UART UART 
Schnittstelle. Analog dazu haben wir bei Ethernet das TCP Protokoll und 
bei Bluetooth das SPP Protokoll. Man baut halt gerne auf Sachen auf, die 
sich bewährt haben.

*) Bei Java muss man die libRxTx nachrüsten.

USB-HID ist für Human Input Device gedacht, also primär für Tastaturen 
und Mäuse. Man kann das Protokoll für andere Zwecke missbrauchen, aber 
das hat dann auch seine Konsequenzen.

von ... (Gast)


Lesenswert?

W.S. schrieb:
> Sowas hat ne sehr negative Auswirkung auf das gesamte Forum

Sobald du hier weg bist hat das positive Auswirkungen auf das Forum.

von Martin H. (horo)


Lesenswert?

Stefan ⛄ F. schrieb:
> Niklas G. schrieb:
>> Stefan ⛄ F. schrieb:
>>> Insbesondere nicht in der modernen Version,
>>> die dein Code voraussetzt.
>>
>> C++11 ist jetzt auch 8,5 Jahre alt...
>
> Ich weiß. Es gibt sogar Leute, die die Erweiterungen von C99 ablehnen.

Viele kamen allmählich zu der Überzeugung, einen großen Fehler gemacht 
zu haben, als sie von den Bäumen heruntergekommen waren. Und einige 
sagten, schon die Bäume seien ein Holzweg gewesen, die Ozeane hätte man 
niemals verlassen dürfen.

(Per Anhalter durch die Galaxis)
Douglas Adams

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Stefan ⛄ F. schrieb:
> Er teilt halt gerne aus und kann nicht einstecken. Das ist uns allen
> doch lange bekannt. Es hilft niemanden, sich darüber immer wieder erneut
> aufzuregen. Wir können ihn nicht umerziehen, deswegen lieber nicht noch
> mehr Öl ins Feuer zu gießen.

Und deswegen soll ich mir sein Gestänker gefallen lassen? Nöö.

Mich juckt es sogar ein Bisschen den W.S.-Code zu debuggen und den 
Fehler zu finden, aber ohne Lizenz-Angabe ist das nunmal verboten. Es 
wäre für alle Beteiligten am Einfachsten wenn W.S. die aktuelle Version 
des Codes auf GitHub lädt und z.B. den Text der MIT-Lizenz ( 
https://opensource.org/licenses/MIT ) hinein copy & pastet. Dann könnte 
er leicht neue Versionen veröffentlichen und die Nutzer aktuell bleiben, 
und andere können auch eigene Änderungen vorschlagen. Solange er diese 5 
Minuten aber nicht investiert...

Pieter schrieb:
> Eine ganz andere Frage: Warum benutzt ihr die RS232/UART via USB?

Das ist eigentlich nur sinnvoll wenn man alte Software hat, die einen 
COM-Port sehen will, oder man eben einen Adapter für Serial-Geräte 
braucht. Rein technisch ist USB-CDC-ACM nur für Analog-Modems mit 
AT-Command-Set gedacht, praktisch wird die Zweckentfremdung als 
allgemeiner USB-Serial-Adapter gemeinhin akzeptiert und unterstützt. Ich 
hatte das nur als kleines Beispiel für das Tutorial implementiert.

Bei HID kann man außerdem nur kleine Pakete übertragen.

Für eigene Projekte, welche weder mit vorhandenen Softwares für 
COM-Ports klarkommen müssen noch wirkliche Eingabegeräte (HID) sind oder 
auf sonstige Standardklassen wie MSC passen, würde ich immer die Vendor 
Specific Class nehmen und ein komplett eigenes Protokoll bauen; dadurch 
hat man die Aufteilung der Endpoints und auch die Paketierung selbst in 
der Hand. Dank libusb und WinUSB ist die Ansteuerung von der PC-Seite 
heraus auch kein Problem; wenn man das Gerät als WinUSB Device 
deklariert braucht's auch keine signierten Treiber o.ä. Siehe:

https://www.mikrocontroller.net/articles/USB-Tutorial_mit_STM32#Eigene_Anwendung_f.C3.BCr_PC-Seite

Fehlersuche geht gut mit Wireshark, am Besten unter Linux.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Niklas G. schrieb:
> Mich juckt es sogar ein Bisschen den W.S.-Code zu debuggen und den
> Fehler zu finden,

Falls du es doch tust, ich würde die korrigierte Version gerne 
veröffentlichen. Selber korrigieren kann ich nicht, das USB Zeugs ist 
für mich zu kompliziert.

von W.S. (Gast)


Lesenswert?

Bernd N schrieb:
> Sorry, gehört das irgendwo in deinen Code ? das erschließt sich mir
> nicht im geringsten.

Also, die direkte Echo-Routine habe ich nicht wie du direkt in main 
hineingesetzt. Ich hab bei meiner Basis-Firmware nen Kommandointerpreter 
drin, so daß ich dort je nach Bedarf leicht Kommandos einpflegen kann - 
und das hab ich hier mal eben gemacht. Das Kommando nimmt eine Zahl 
entgegen und echot so viele Zeichen wie diese Zahl groß ist. 
Anschließend kommt die Fertigmeldung. Das ist alles.

> Vielleicht gehen wir nochmal einen Schritt zurück. Die erste Änderung
> von dir war...  if (I & SOF)                               /* Start of
> Frame, alle 1 ms */
>   { USB_ISTR = ~SOF;                         /* Int löschen */
>     if ((txr != txw) &&                      /* Tx nicht leer */
>         (!(I & CTR)))                        /* Int ist nicht Endpoint
> Interrupt */
>     { if ((USB_EpRegs(logEpBulkIn) & STAT_TX)!= VALID_BI) /* Buffer ist
> nicht aktiv */
>       { I &= 0xFF00;                         /* Endpt Info nullen */
>         I |= CTR | logEpBulkIn;              /* Int = EpBulkIn setzen */
>       }
>     }
>   }
> Das führt zum direkten Absturz, blockieren und funktioniert bei mir (in
> Stefans Projekt) garnicht.

Hab ich denn nicht die ganze usb.c gepostet?
Also: Wenn vom USB ein Interrupt kommt, wird zuerst getestet, ob dort 
der Frame-Int dabei ist. Wenn ja, dann wird getestet, ob der Sendepuffer 
nicht leer ist und ob nicht eine Fertigmeldung eines Endpoints vorliegt 
(die hat natürlich Vorrang und die Bits 0..3 = EP_ID sind gültig). Dann 
wird getestet, daß der In-Puffer nicht gerade noch aktiv und gültig ist. 
Wenn das alles OK ist, dann ist in den gesammelten Interrupt-Gründen 
kein Endpoint-Int dabei, es stehen Daten zum Senden herum und der 
EP-Puffer ist erledigt und kann neu gefüllt werden. Dann und nur dann 
wird der EpBulkIn eingetragen, so daß der zugehörige Handler eine Chance 
hat, sein Werk wieder aufzunehmen.

Wenn das bei Stefans Projekt zum direkten Absturz führt, dann müßtest du 
mit Stefan abklären, was er da alles geändert hat. Wie äußert sich denn 
der Absturz? Gibt's nen Hardfault oder sowas ähnliches?

W.S.

von Bernd N (Gast)


Lesenswert?

>> Hab ich denn nicht die ganze usb.c gepostet?

Hast du, macht aber keinen Unterschied. Ich glaube das man sich hier 
ersteinmal auf eine gemeinsame Code Basis einigen sollte. Entweder geht 
ihr / du auf Stefans Version ein oder sag mir bitte wo ich deine (WS) 
Version, stand heute mit deinen Änderungen, herunterladen kann. Das 
würde zumindestens mal weiterführen.

Danke

von Bernd N (Gast)


Lesenswert?

>> Wie äußert sich denn der Absturz? Gibt's nen Hardfault oder
>> sowas ähnliches?

Es kommt kein Echo zurück. Die Kommunikation findet dann garnicht mehr 
statt. Ich habs noch nicht debugged sondern bin auf die originale 
Version von Stefan zurückgekehrt.

>> Wenn das bei Stefans Projekt zum direkten Absturz führt, dann müßtest
>> du mit Stefan abklären, was er da alles geändert hat.

Hatte ich schon weiter oben. Angeblich nur anders formatiert und Debug 
Ausgaben hinzugefügt.

Wie gesagt, ich kann gerne auf deine Codebasis gehen wenn du mir sagst 
wo ich deinen funktionierenden Code herunterladen kann.

von Zeno (Gast)


Lesenswert?

Niklas G. schrieb:
> Mich juckt es sogar ein Bisschen den W.S.-Code zu debuggen und den
> Fehler zu finden, aber ohne Lizenz-Angabe ist das nunmal verboten. Es
> wäre für alle Beteiligten am Einfachsten wenn W.S. die aktuelle Version
> des Codes auf GitHub lädt und z.B. den Text der MIT-Lizenz (
> https://opensource.org/licenses/MIT ) hinein copy & pastet.

Da kannst Du lange warten. W.S. wird nichts auf Github hochladen und 
irgendwelches Lizensgedöhns wird er zu seinem Code auch nicht 
mitliefern.

Da er das, wie er schrieb, privat macht, wird er das so halten, wie ich 
das mit meinem Gedöhns auch machen würde. Wenn ich was öffentlich mache, 
dann darf es auch benutzt werden, auch ohne eine explizite Lizens. Wenn 
ich das nicht möchte dann darf ich halt auch nix posten/veröffentlichen. 
Allerdings würde ich schon erwarten, das Quelle und Autor genannt 
werden, wenn die Software nicht für den reinen persönlichen 
Privatgebrauch benutzt wird. Auch wenn ich das nicht nachprüfen kann, 
aber es gehört halt zum guten Ton sich nicht mit fremden Lorbeeren zu 
schmücken.
Ich hätte auch kein Problem damit, wenn sich jemand die Mühe macht den 
Quellcode zu debuggen um einen Fehler zu finden. Ich würde mich 
natürlich freuen, wenn er mir einen gefundenen Fehler auch mitteilen 
würde.

Am Ende muß jedem der etwas veröffentlicht klar sein, das selbiges auch 
weiter verwendet werden kann und wird, unabhängig davon ob man da eine 
Lizens angegeben wurde oder nicht. Schlußendlich kann man das auch nicht 
prüfen solange das Ganze im privaten Umfeld passiert.

von Niklas Gürtler (Gast)


Lesenswert?

Zeno schrieb:
> Wenn ich was öffentlich mache, dann darf es auch benutzt werden, auch
> ohne eine explizite Lizens

Nach deutschem Recht eben nicht. Ohne explizites Einräumen von 
Nutzungsrechten (Lizenz genannt) darf man das weder privat noch 
kommerziell nutzen. Man darf den Code ansehen, sonst nix. Und das gilt 
sogar für triviale Programme wie Hello World.

Zeno schrieb:
> Allerdings würde ich schon erwarten, das Quelle und Autor genannt
> werden, wenn die Software nicht für den reinen persönlichen
> Privatgebrauch benutzt wird.

Dann musst du das in den Lizenztext aufnehmen.

Zeno schrieb:
> Ich hätte auch kein Problem damit, wenn sich jemand die Mühe macht den
> Quellcode zu debuggen um einen Fehler zu finden

Dann musst du das explizit erlauben, über eine Lizenz.

Zeno schrieb:
> Am Ende muß jedem der etwas veröffentlicht klar sein, das selbiges auch
> weiter verwendet werden kann und wird

Ohne Lizenz wäre das aber illegal.

Wie gesagt: alles was nicht explizit erlaubt wird, ist per default 
verboten... kann sein dass das in anderen Ländern nicht so ist, in 
Deutschland aber schon. Die Lösung ist so einfach - den Text der MIT 
Lizenz (entspricht deinen Wünschen vermutlich am Ehesten) übernehmen, 
Namen eintragen und fertig, Diskussion erledigt. Warum da noch lange 
argumentieren warum es auch ohne gehen soll?

von Zeno (Gast)


Lesenswert?

Niklas Gürtler schrieb:
> Nach deutschem Recht eben nicht. Ohne explizites Einräumen von
> Nutzungsrechten (Lizenz genannt) darf man das weder privat noch
> kommerziell nutzen. Man darf den Code ansehen, sonst nix. Und das gilt
> sogar für triviale Programme wie Hello World.

Bist Du Anwalt oder Erbsenzähler?

Recht hin - Recht her, wenn man das in der Praxis so handhabt wie Du es 
in Deinem Post schreibst, dann kann das Forum hier geschlossen werden. 
Ich dürfte ja noch nicht einmal einen Quelltext ausprobieren um 
demjenigen der es verzapft hat zu helfen. Ich dürfte ja noch nicht mal 
einen Codeschnipsel mit einer Lösung posten, denn es würde meinem 
Gegenüber nicht weiter helfen, denn nach Deiner Rechtsauffassung müßte 
ich es ihm explizit erlauben. Das ist natürlich wenig praxistauglich.

Niklas Gürtler schrieb:
> Zeno schrieb:
>> Allerdings würde ich schon erwarten, das Quelle und Autor genannt
>> werden, wenn die Software nicht für den reinen persönlichen
>> Privatgebrauch benutzt wird.
>
> Dann musst du das in den Lizenztext aufnehmen.

Das man die Quelle nennt, wenn man Sachen benützt die nicht auf dem 
eigenen Mist gewachsen sind, gehört einfach nur zum guten Ton und ist 
außerdem Voraussetzung z.B bei wissenschaftlichen Arbeiten. Wenn man 
dies nicht tut dann werden einem die mit Hilfe dieser Quellen erworbenen 
akademischen Grade auch ganz schnell wieder entzogen, wenn's denn 
bekannt wird das man sich nicht an die Regeln gehalten hat.


Das Ganze ist im Privaten nicht wirklich praxistauglich. Keiner kann 
prüfen ob ich irgendwelchen Sourcecode in einem rein privaten Projekt 
benutze. OK dann hänge ich das auch nicht an die große Glocke.


Und bevor hier noch eine große Diskussion aufkommt, ja rein formal hast 
Du Recht und die Rechtslage ist nun mal so.
Dennoch würde ich keinen verklagen, wenn dieser einen von mir erstellten 
und veröffentlichten Sourcecode für seine Projekte benutzt. Wenn ich 
dies nicht möchte, dann würde ich den genau umgekehrten Weg gehen und 
die Weiterverwendung untersagen. Würde zwar auch nicht viel helfen, da 
ich von der missbräuchlichen Verwendung erst Kenntnis erlangen müßte. 
Wenn ich nicht möchte das irgendwelche geistigen Ergüsse meinerseits 
weiter verwendet werden, dann werde ich Selbige sehr wahrscheinlich 
nicht öffentlich präsentieren, denn das ist immer noch der beste Schutz 
vor unrechtmäßiger Nutzung.

von Niklas Gürtler (Gast)


Lesenswert?

Zeno schrieb:
> Bist Du Anwalt oder Erbsenzähler?

Nö, aber im Informatik Studium gibt's auch Jura Vorlesungen.

Zeno schrieb:
> Ich dürfte ja noch nicht mal einen Codeschnipsel mit einer Lösung
> posten, denn es würde meinem Gegenüber nicht weiter helfen, denn nach
> Deiner Rechtsauffassung müßte ich es ihm explizit erlauben.

Richtig. Daher haben Foren wie Stack Overflow explizit eine 
Lizenzangabe, der man beim Posten zustimmt. Foren ohne so eine Angabe 
bewegen sich in einer Grauzone; solange keiner klagt... außerdem ist das 
nicht "meine" Rechtsauffassung:

https://jaxenter.de/software-ohne-lizenz-der-anfang-vom-ende-der-open-source-ara-865

Das Fehlen einer Lizenz bedeutet im Umkehrschluss nämlich, dass die 
generellen Copyright-Gesetze gelten. Diese bestimmen, dass der 
Entwickler der Software (oder sein Arbeitgeber) alle Rechte am Code hat 
und kein anderer Entwickler ohne Erlaubnis berechtigt ist, den Code zu 
forken und weiter zu entwickeln. Denn Software ist geistiges Eigentum 
(Intellectual Property, kurz IP).

https://opensource.guide/de/legal/

Wenn Sie ein kreatives Werk erarbeiten (bspw. einen Text, ein Bild, oder 
eben Code) fällt es standardmäßig und automatisch unter das 
Urheberrecht. Das bedeutet, das von Rechts wegen Sie, der/die Autor*in 
des Werkes bestimmen dürfen, was andere damit tun dürfen.

Generell gilt, dass Niemand sonst Ihr Werk nutzen, kopieren, verbreiten, 
oder modifizieren darf, ohne Abmahnungen oder Klagen zu riskieren.

Zeno schrieb:
> Das man die Quelle nennt, wenn man Sachen benützt die nicht auf dem
> eigenen Mist gewachsen sind, gehört einfach nur zum guten Ton

Schon, aber es ging um die rechtliche Situation, nicht um den guten Ton.

Zeno schrieb:
> Keiner kann prüfen ob ich irgendwelchen Sourcecode in einem rein
> privaten Projekt benutze.

Wenn man modifizierte Versionen von Quellcodes hochlädt, ist das schon 
ziemlich offensichtlich. Und das ist eine "man darf sich nicht erwischen 
lassen" Argumentation... ob prüfbar oder nicht, verboten ist's trotzdem.

Zeno schrieb:
> Dennoch würde ich keinen verklagen, wenn dieser einen von mir erstellten
> und veröffentlichten Sourcecode für seine Projekte benutzt

Ok, aber kannst du mir garantieren dass W.S. mich nicht verklagt wenn 
ich seinen Code ohne seine Einverständnis modifiziere und weiter gebe?

von Zeno (Gast)


Lesenswert?

Niklas Gürtler schrieb:
> Ok, aber kannst du mir garantieren dass W.S. mich nicht verklagt wenn
> ich seinen Code ohne seine Einverständnis modifiziere und weiter gebe?

Dann frag doch mal W.S.
Ich behaupte jetzt mal er postet Code nicht einfach zum Selbstzweck oder 
um zu zeigen was er für ein toller Hecht ist.

Ansonsten ich will hier jetzt keine unendliche Diskussion zu 
Rechtsfragen los treten.

von Zeno (Gast)


Lesenswert?

Niklas Gürtler schrieb:
> Zeno schrieb:
>> Keiner kann prüfen ob ich irgendwelchen Sourcecode in einem rein
>> privaten Projekt benutze.
>
> Wenn man modifizierte Versionen von Quellcodes hochlädt, ist das schon
> ziemlich offensichtlich. Und das ist eine "man darf sich nicht erwischen
> lassen" Argumentation... ob prüfbar oder nicht, verboten ist's trotzdem.

Hatte ich nicht rein privat geschrieben? Also für mich gibt es da einen 
Unterschied zwischen rein privat und öffentlich hoch laden.
Aber heute ist es ja offensichtlich völlig normal, das man eigentlich 
komplett private Dinge öffentlich bei Facebook oder sonst wo 
präsentiert. Ich gehöre noch zu der Generation, wo man nicht jeden Gang 
zum Zylinder öffentlich teilen muß.

Hiermit ist jetzt für mich auch jede weitere rechtliche Diskussion 
beendet.

von 2^5 (Gast)


Lesenswert?

Niklas Gürtler schrieb:
> ach deutschem Recht eben nicht. Ohne explizites Einräumen von
> Nutzungsrechten (Lizenz genannt) darf man das weder privat noch
> kommerziell nutzen. Man darf den Code ansehen, sonst nix. Und das gilt
> sogar für triviale Programme wie Hello World.

Naja, ganz so einfach ist es ja nun auch wieder nicht. Es gibt im 
deutschen Urheberrecht den Begriff der Schöpfungshöhe 
https://de.wikipedia.org/wiki/Sch%C3%B6pfungsh%C3%B6he#Technisch-wissenschaftliche_Darstellungen

Dieser schließt triviale Programme aus. Leider ist nun nicht geklärt, 
wann ein Programm trivial ist, das Hello World Beispiel sollte es aber 
sein. W.S. USB CDC Code dürfte aber geschützt sein, und so wäre eine 
eindeutige Lizinz hilfreich, da gebe ich dir recht.

von Stefan F. (Gast)


Lesenswert?

Niklas Gürtler schrieb:
> Daher haben Foren wie Stack Overflow explizit eine
> Lizenzangabe, der man beim Posten zustimmt. Foren ohne so eine Angabe
> bewegen sich in einer Grauzone

Ich zitiere mal aus den Nutzungsbedingungen von mikrocontroller.net:

"Der Zweck dieses Forums ist der Austausch über Themen aus dem Bereich 
Elektronik, Informatik, sowie Technik und Wissenschaft im weiteren 
Sinne.
...
Mit dem Erstellen eines Beitrags erteilt der Autor dem Betreiber des 
Forums ein einfaches, zeitlich und räumlich unbeschränktes und 
unentgeltliches Recht, den Beitrag im Rahmen des Forums zu nutzen. Das 
Nutzungsrecht bleibt auch nach Kündigung der Mitgliedschaft bestehen."

So viel zur Lizenz des Codes von W.S. Wer an Jura interessiert ist, mag 
in einem spezifischen Forum diskutieren, inwiefern das Nutzungsrecht für 
die Mitglieder des Forums gilt.

Können wir uns jetzt wieder der Technik zuwenden?

von W.S. (Gast)


Lesenswert?

Also Niklas,

eigentlich sollte dieser Thread zum Abklären eines technischen Problems 
dienen. Aber du machst jetzt hier einen aus meiner Sicht völlig 
überzogenen und nicht zum Thema gehörigen Rechtsstreit daraus.

Laß das bitt sofort bleiben oder mache dafür einen separaten Thread auf.

Niklas Gürtler schrieb:
> Ok, aber kannst du mir garantieren dass W.S. mich nicht verklagt wenn
> ich seinen Code ohne seine Einverständnis modifiziere und weiter gebe?

Das ist von Anfang an völliger Unsinn, denn kein Anderer kann dir 
garantieren, was er nicht selbst beeinflussen kann. Bleibe also logisch. 
Wir sind ja hier wohl Techniker und keine Esoteriker.

So, und um diesem ganzen Gejammer ein Ende zu bereiten, muß ich mich 
hier mal selbst zitieren:

[zitat]
So, damit hier keiner wieder das Jammern kriegt:
Das ist alles (bis auf das Info-Stück in der usb.h, was von Nuvoton 
stammt) auf meinem Mist gewachsen und ein jeder, der sich dafür 
interessiert, mag es nach seinem Gusto benutzen - unter 2 
Einschränkungen:
1. Jeder soll für das, was er damit anstellt, SELBER geradestehen. Ich 
übernehme da keinerlei Verantwortung dafür.
2. Keiner soll so tun, als ob das Zeugs aus seiner eigenen Feder stammt.

W.S.
[/zitat]

Seit einem knappen Jahr nachzulesen in:
https://www.mikrocontroller.net/attachment/405187/Gesammelte_USBs.zip

Und ab jetzt will ich kein Herumgegreine darüber mehr lesen müssen.

Und nochwas, Niklas: Es geht in diesem Thread nicht um dein Projekt. 
Meine Bedenken zu diesem hatte ich dir ja schon geschrieben - und in 
magere Worte zusammengefaßt lauten diese: Du willst die Leute zu C++ 
hinführen und viele Leute wollen diesen Schritt eben nicht gehen. Lebe 
also damit, daß andere Leute ihre eigenen Ansichten haben.

W.S.

von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

So, zum eigentlichen technischen Thema:

Bernd N schrieb:
>>> Wie äußert sich denn der Absturz? Gibt's nen Hardfault oder
>>> sowas ähnliches?
>
> Es kommt kein Echo zurück. Die Kommunikation findet dann garnicht mehr
> statt.

Hmm.. das sagt noch nicht viel. Jetzt weiß ich nicht, was für ein 
Board/Schaltung du grad hast und was exakt für ein µC drauf ist. 
Hintergrund ist, ob du dort als zweiten Weg nen herausgeführten UART 
hast, über den du testeshalber mit dem µC kommunizieren kannst.

Ich hab das mit dem Board getestet, was ich dir hier mal drangehängt 
habe - ist ein STM32F103C8T6 drauf. Dort ist wegen des 
Bootlader-Anschlusses eben auch ein UART zugänglich. Aber mit so einem 
Bluepill-Board sollte das mit etwas Strippen-Löten auch gehen.

Ich schätze mal, daß nur der Datenfluß µC-->PC hängt und ansonsten der 
µC keineswegs abgestürzt ist. Aber das kann man ohne irgend einen 
zweiten Zugang nicht wirklich testen. Vielleicht hilft ne LED, die du in 
Sekundentakt blinken läßt?

Nochwas: Was passiert denn beim Einstecken, also findet das Enumerieren 
korrekt statt, so daß man dein Board in der Peripherie-Liste des OS 
korrekt sehen kann?


> Ich habs noch nicht debugged sondern bin auf die originale
> Version von Stefan zurückgekehrt.

Jetzt weiß ich nicht, ob ich da ins Leere schreibe, falls du einen 
STM32L.. oder F30x oder eben einen µC verwendest, den Stefan eingepflegt 
hat.

> Hatte ich schon weiter oben. Angeblich nur anders formatiert und Debug
> Ausgaben hinzugefügt.

Ich hab damit meine Mühen, denn Stefans Art, den Quelltext zu 
formatieren, ist mir unsäglich unleserlich, so daß mir das Vergleichen 
auf inhaltliche Differenzen ein Graus ist.

Aber die Aussage stimmt nicht, es sind nicht nur andere Formatierungen, 
sondern auch Inhaltliches. So z.B. ab Zeile 1483:
1
        else /* IN, also Paket wurde gesendet */
2
        {
3
            // Apply new device address
4
            if (DeviceAddress)
5
            {
6
                USB_SetAddress(DeviceAddress);
7
                DeviceAddress=0;
8
            }

Zumindest das ist anders als bei mir, also wird es wohl auch noch 
weitere Änderungen geben - mal abgesehen von den Fall-Unterscheidungen 
bei µC, die nicht mehr diese seltsamen Lücken in den Transfer-Puffern 
haben.


> Wie gesagt, ich kann gerne auf deine Codebasis gehen wenn du mir sagst
> wo ich deinen funktionierenden Code herunterladen kann.
Ich betreibe keine eigene Homepage etc. Man kann also von mir nix 
herunterladen - allenfalls hier aus dem Forum all das, was ich schon mal 
gepostet hatte.

Ich hänge dir mal ein paar Dateien dran - für den Fall, daß du davon was 
gebrauchen kannst/willst. Das fängt an mit config.c, was wohl für dich 
eher uninteressant ist, da du ja sowas wie Cube benutzen willst. Es geht 
weiter mit cmd.c, was für dich wohl eher interessant ist, weil es einen 
fertigen Rumpf bildet für das Ausführen von Kommandos, die du vom PC aus 
über relativ beliebige Kanäle (UART, USB) geben kannst. Dort hab ich ab 
Zeile 284 den USB-Test angesiedelt.

Die übrigen dort noch herumlungernden Kommandos haben mir für 
anderweitige Zwecke gedient, die kannst du getrost entfernen. Für cmd.c 
braucht es auch noch conv.c und gio.c. Letzteres ist eine Art 
Rangierbetrieb, damit man zum Lenken von In- und Ausgabe-Strömen einfach 
Tokens benutzen kann. Find ich sehr praktisch, da man die tatsächlichen 
I/O-Funktionen nicht mehr selber angeben muß. Damit kann man den ganzen 
Kommandokram ohne Änderung über verschiedene Kanäle benutzen. Und man 
kann auch in einen Puffer, quasi String ausgeben. Obendrein kann man 
StdIO auf einen Kanal setzen, so daß man auch außerhalb von cmd.c in 
diesen Kanal per symbolischem 'stdout' ausgeben kann.

In main wäre für dich eigentlich nur die Grundschleife und darin:

  Talk (toUART1);
  Talk (toUART2);
  Talk (toUSB);

interessant. Aber dein main wird ja ohnehin maschinell erzeugt.

Tja, und usb.c ist eben meine derzeitige Version. Die ist aber wirklich 
nur für die STM32F103 und nicht für die Chips, die Stefan eingearbeitet 
hat.

W.S.

von temp (Gast)


Lesenswert?

W.S. schrieb:
> Aber die Aussage stimmt nicht, es sind nicht nur andere Formatierungen,
> sondern auch Inhaltliches. So z.B. ab Zeile 1483:        else /* IN,
> also Paket wurde gesendet */
>         {
>             // Apply new device address
>             if (DeviceAddress)
>             {
>                 USB_SetAddress(DeviceAddress);
>                 DeviceAddress=0;
>             }
>
> Zumindest das ist anders als bei mir, also wird es wohl auch noch
> weitere Änderungen geben - mal abgesehen von den Fall-Unterscheidungen
> bei µC, die nicht mehr diese seltsamen Lücken in den Transfer-Puffern
> haben.

Wenn mich nicht alles täuscht, ist diese Änderung von mir und hatte zum 
Ziel, sämtliche Delays aus deinem Code zu entfernen. Denke das ist in 
Stefans Thread auch nachzulesen.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

2^5 schrieb:
> Dieser schließt triviale Programme au

Ok, das hatte ich anders in Erinnerung.

W.S. schrieb:
> eigentlich sollte dieser Thread zum Abklären eines technischen Problems
> dienen. Aber du machst jetzt hier einen aus meiner Sicht völlig
> überzogenen und nicht zum Thema gehörigen Rechtsstreit daraus.

Man kann das technische Problem nicht angehen, wenn man das rechtliche 
nicht geklärt hat. Da du jetzt ja endlich eine Lizenz angegeben hast, 
ist das Problem aus dem Weg.

W.S. schrieb:
> Das ist von Anfang an völliger Unsinn, denn kein Anderer kann dir
> garantieren, was er nicht selbst beeinflussen kann. Bleibe also logisch.

Ach. Genau darum ging es. Meine Argumentation ist absolut logisch, ich 
bin nicht derjenige der mit "passt schon" argumentiert.

W.S. schrieb:
> So, und um diesem ganzen Gejammer ein Ende zu bereiten, muß ich mich
> hier mal selbst zitieren:

War das so schwierig, das vorher mal einzubringen? Nicht jeder verfolgt 
alles was du irgendwo schreibst.

W.S. schrieb:
> Und ab jetzt will ich kein Herumgegreine darüber mehr lesen müssen.

Das hättest du schon viel früher haben können, aber du hast dich ja lang 
geziert.

W.S. schrieb:
> Und nochwas, Niklas: Es geht in diesem Thread nicht um dein Projekt.

Stimmt, das hatte ich nur zum Vergleich eingebracht, um festzustellen, 
dass das Problem auf µC-Seite liegt. Gut, wir wissen jetzt, dass es mit 
meinem Code funktioniert, daher brauchen wir den nicht weiter behandeln.

W.S. schrieb:
> Du willst die Leute zu C++
> hinführen

Keineswegs. Ich habe nur C++ für meinen Beispiecode gewählt. Die Leser 
meines Tutorials können ihren eigenen Code in jeder beliebigen Sprache 
verfassen. Rust wäre z.B. mal interessant.

Also, da die Lizenzfrage endlich geklärt ist:

Ich habe deinen Code in ein git-Repository eingebaut, mit der MIT-Lizenz 
sublizensiert, den gröbsten C-Missbrauch bereinigt und den Code auf 
GitHub geladen:

https://github.com/Erlkoenig90/WSusb

Das sollte zu deinem kreativ formulierten Lizenztext kompatibel sein. 
Mithilfe von JTAG-Debugging waren die Fehler leicht zu finden:

Die bisherige Annahme war ja, dass der Code nicht selbstständig mit dem 
Senden anfängt, wenn der Sendepuffer leer ist, was du damit begründest, 
dass es keinen NAK-Interrupt gibt. Tatsächlich war das im Code bereits 
so "gelöst", dass der SOF-Interrupt dafür missbraucht wird, und ständig 
auf Senden geprüft wird, genau wie schon vorgeschlagen:

Niklas G. schrieb:
> Da kann man den
> NAK-Interrupt auch mit einem Timer simulieren, oder den SOF Interrupt
> nehmen.

Funktioniert zwar, ist aber ziemlich hässlich. Ich habe den SOF 
Interrupt deaktiviert und das Abschicken einfach in UsbCharOut 
getriggert. Dazu wird in einer neuen globalen Variable gemerkt, ob 
gerade ein sendender Transfer im Gange ist.

Der eigentliche Fehler lag in der Empfangs-Seite: Wenn die 
main()-Schleife den Empfangspuffer via UsbGetChar() nicht schnell genug 
leert, läuft der irgendwann voll. Dann tritt im Empfangsinterrupt 
irgendwann dieser Fall ein:
1
    /* Bulk EP anwählen und Anzahl der Bytes ermittlen */
2
    avail = EpTable[2].RxCount & 0x3FF;
3
4
    i = rxw - rxr;
5
    if (i < 0)
6
        i += rxLen;
7
    hdroom = rxLen - i;
8
    if (hdroom <= avail)
9
        return;

Und dann wird fortan gar nichts mehr empfangen, alles bleibt stecken. 
Die Lösung ist hier analog zur Sende-Seite: Man startet das Empfangen 
nur, solange im Ringpuffer noch genug Platz für ein ganzes Paket ist (64 
Bytes). Dann kann dieser Fall niemals eintreten. Im Interrupt wird das 
Empfangen nur freigegeben wenn noch genug Platz im Fifo ist; sonst wird 
es temporär pausiert. Dazu wird in einer weiteren globalen Variable 
gemerkt, ob gerade etwas empfangen wird. Die UsbGetChar() Funktion 
prüft, ob nach dem Lesen des Zeichens genug Platz für ein weiteres Paket 
ist, und schaltet dann ggf. das Empfangen wieder frei. So kann es keinen 
Puffer-Überlauf mehr geben, und der Prozess hängt sich nicht mehr auf.

Die API-Funktionen habe ich außerdem noch mit Interrupt-Sperre versehen, 
weil sonst Inkonsistenzen mit den Fifo-Zeigern auftreten können. 
Außerdem gab es einen Bug in der USB-ISR, wo logEpBulkOut mit 
logEpBulkIn verwechselt wurde.

Hier die Änderungen an der usb.c:

https://github.com/Erlkoenig90/WSusb/commit/5bb8175989ea8c7576d8fb177c68260173a5924c#diff-3bf4bca9d530fc38765d8c9f1c0ae7c8

Bernd, kannst du prüfen ob es damit bei dir funktioniert?

: Bearbeitet durch User
von Zeno (Gast)


Lesenswert?

Niklas G. schrieb:
> Ich habe deinen Code in ein git-Repository eingebaut, mit der MIT-Lizenz
> sublizensiert

Jetzt bist bist Du aber, dafür das Du erst so einen Zirkus gemacht hast, 
sehr forsch.
W.S. hat zwar seinen Code offiziell zur Benützung frei gegeben, aber ihn 
dann schurstracks in ein für jedermann frei zugängliches Repositority zu 
stellen halte ich schon für etwas unverschämt. Es hätte wohl schon zum 
guten Ton gehört W.S. wenigstens zu fragen, was ja offensichtlich nich 
passier ist.
Desweiteren gehört es sich, zumindest wenn man den Code so öffentlich 
macht, auch einen Copyrightvermerk in den Quelltexten selbst 
anzubringen.

von Niklas Gürtler (Gast)


Lesenswert?

Zeno schrieb:
> Jetzt bist bist Du aber, dafür das Du erst so einen Zirkus gemacht hast,
> sehr forsch.

Hahaha! Ich will kein Gegreine über juristische Belange mehr hören. Ich 
bin nach meinem Gusto verfahren, wie mir explizit erlaubt wurde.

von temp (Gast)


Lesenswert?

Ich jedenfalls finde es gut wenn versucht wird die eventuellen Bugs oder 
Probleme aus dem Code zu kriegen. Ich werde mir das auch mal ansehen.

Eine Frage aber an Niklas. Hast du da jetzt globale Interruptsperren 
dazugebaut und wenn ja reicht es nicht nur den USB Interrupt zu sperren?

von Zeno (Gast)


Lesenswert?

Niklas Gürtler schrieb:
> Hahaha! Ich will kein Gegreine über juristische Belange mehr hören. Ich
> bin nach meinem Gusto verfahren, wie mir explizit erlaubt wurde.
Zwischen einer Verwendung in eigenen Projekten (nach eigenem Gusto) und 
einer Veröffentlichung im Internet ist schon noch ein Unterschied.

temp schrieb:
> Ich jedenfalls finde es gut wenn versucht wird die eventuellen Bugs oder
> Probleme aus dem Code zu kriegen. Ich werde mir das auch mal ansehen.
Darum ging es nicht. Es geht um die Art und Weise seines Vorgehens. Es 
geht auch nicht um irgendwelche rechtlichen Dinge, von denen W.S. nichts 
mehr hören will - es geht um Fairness und Anstand, was ich hier 
vermisse.

von temp (Gast)


Lesenswert?

Zeno schrieb:
> Darum ging es nicht. Es geht um die Art und Weise seines Vorgehens. Es
> geht auch nicht um irgendwelche rechtlichen Dinge, von denen W.S. nichts
> mehr hören will - es geht um Fairness und Anstand, was ich hier
> vermisse.

Dann mach den Anfang und lass es auf sich beruhen. Ist nicht schon genug 
gestänkert worden?

von Niklas Gürtler (Gast)


Lesenswert?

temp schrieb:
> Eine Frage aber an Niklas. Hast du da jetzt globale Interruptsperren
> dazugebaut und wenn ja reicht es nicht nur den USB Interrupt zu sperren?

Habe ich, ja das würde wohl auch reichen.

Zeno schrieb:
> Zwischen einer Verwendung in eigenen Projekten (nach eigenem Gusto) und
> einer Veröffentlichung im Internet ist schon noch ein Unterschied.

Wo steht dass man das nur für eigene Projekte nutzen kann? Stefan hat es 
auch im Internet veröffentlicht.

Zeno schrieb:
> es geht um Fairness und Anstand, was ich hier vermisse.

Da sind wir eh schon lange drüber hinweg. W.S. ist alles, aber nicht 
fair. Um aber Leuten wie Bernd helfen zu können, und rechtlich 
abgesichert zu sein, muss man halt die Lizenz klären. W.S. war mir und 
vielen anderen hier gegenüber auch nicht fair, also habe ich wenig 
Motivation für Fairness.

Also: Zuerst gab es gar keine Lizenzangabe. Man konnte also gar nichts 
mit dem Code machen, aber es wurde nach Hilfe mit dem Code gefragt. Nach 
viel Gemurre wurde dann endlich eine Lizenz dazu geschrieben. Unter 
Nutzung dieser habe ich eine Fehler Korrektur hochgeladen. Das ist jetzt 
auch wieder nicht richtig? Wie soll ich die Bugfixes denn sonst weiter 
geben - nachts hinterm Bahnhof im schwarzen Aktenkoffer? Ist Stefans 
Website ok, aber Github nicht? Ist in der Lizenz Github ausgenommen? 
Hätte W.S. einfach eine etablierte Open Source Lizenz wie MIT oder BSD 
oder Boost angegeben, wäre es sehr einfach gewesen zu klären was geht 
und was nicht. Hat er aber nicht, also muss man seine kreative 
Formulierung interpretieren. Für mich ist die der MIT Lizenz sehr 
ähnlich, denn Sublizensierung wird im Gegensatz zur BSD nicht 
ausgeschlossen. Also habe ich genau das gemacht und die MIT Lizenz dran 
geschrieben, damit es für alle Nutzer einfacher wird. Tatsächlich ist 
die MIT sogar restriktiver, denn der Lizenztext darf nicht entfernt 
werden. Wer den Code ohne Lizenztext weiter geben möchte, muss halt die 
Original Lizenz von W.S. nutzen, kann aber meine Korrekturen nicht 
verwenden.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

PS: Es ist auch nicht besonders fair von W.S., nirgendwo zentral eine 
"definitiv aktuelle" Version des Codes zur Verfügung zu stellen und dort 
auch Verbesserungsvorschläge entgegen zu nehmen, sondern alle 
potentiellen Nutzer des Codes auf eine Schnitzeljagd durchs Forum zu 
schicken, um den aktuellsten Beitrags-Anhang mit Code+Lizenz zu finden. 
Es ist zwar sein gutes Recht, aber er muss sich dann auch nicht wundern 
wenn jemand unter Ausnutzung der Lizenz den Code auf eine besser 
nutzbare Art online stellt, wie hier eben Github. Jedes Mal wenn eine 
neue Version auftaucht könnte ich das Github-Repository aktualisieren, 
und weitere Verbesserungsvorschläge wie z.B. das Sperren nur des 
USB-Interrupts dort auch per Pull Request einpflegen. Eigentlich gar 
nicht so unfair, die Pflege des Codes zu übernehmen...
Außerdem sind Stefan und ich anscheinend die einzigen, die diesen Code 
mit Klarnamen bearbeitet haben; alle anderen sind anonym. So von wegen 
"fair".

von W.S. (Gast)


Lesenswert?

Niklas Gürtler schrieb:
> W.S. ist alles, aber nicht fair.

OK, ich sehe, daß selbst Ermahnungen zu anständigem Verhalten dich nicht 
davon abhalten, hier ständig herumzustänkern.

Dieser Thread ist also versaut und abgestürzt - und zwar durch DICH.

Ich klinke mich hier jetzt erstmal aus. Vielleicht schaffst du es ja 
doch noch mal, zur Besinnung zu kommen.

W.S.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

W.S. schrieb:
> OK, ich sehe, daß selbst Ermahnungen zu anständigem Verhalten dich nicht
> davon abhalten, hier ständig herumzustänkern.

LOL!
Deine Selbstwahrnehmung ist echt komplett verzerrt.
Überleg doch mal wer hier imemr rumstänkert im Forum?
Du bekommst eben den Gegenwind den du gesäht hast ;)

Im Nachbarthread haste ja zum Thema Debugger wieder ausgeteilt obwohl 
hier ein gravierender Bug in deinem Code per Debugger gefunden und 
gefixt wurde.

W.S. schrieb:
> Ich klinke mich hier jetzt erstmal aus.
Würde mich freuen wenn du das in jedem Thread im Forum machen würdest.

von Bernd N (Gast)


Lesenswert?

Mein lieber Schwan, was geht denn hier ab ? ich kenne euren alten Streit 
nicht aber vermute das es schon sehr lange so geht. Ich hatte auch die 
Hoffnung das wird den Streit aussen vor lassen können.

Eines kann ich aber als großes Lob an euch aussprechen, es ist etwas 
dabei herumgekommen.

Zunächst vielen Dank an WS der mir seine gesammelten USB Codezeilen hat 
zukommen lassen. Ich finde es einfach gut das er hier sein Wissen teilt 
und für mich ist das eine echte Hilfe.

Ebenso vielen Dank an Niklas für den korrigierten Code, der funktioniert 
jetzt perfekt. Darüber habe ich mich sehr gefreut.

Wenn hier als Erkenntnis herauskommt das man gemeinsam viel hinbekommen 
kann dann sollte das Grund genug sein den Streit beizulegen.

Ich wünsche euch noch einen schönen, friedvollen Sonntag.

Besten Dank nocheinmal an Alle die hier geholfen haben.

von Zeno (Gast)


Lesenswert?

Niklas Gürtler schrieb:
> Stefan hat es
> auch im Internet veröffentlicht.
Ja, auf seiner Homepage und dort hat er auch die genaue Quelle 
angegeben, wo er den Sourcecode her hat. Wenn ich mich recht entsinne 
hat er W.S. in einem der vielen Threads zum Thema auch gefragt ob er 
dies tun dürfe.
Github ist eben auch etwas anderes als eine private Homepage. DEine 
Quellenangabe ist zudem unvollständig, da man üblicherweise auch den Ort 
der Veröffentlichung angibt.


Niklas G. schrieb:
> Es ist auch nicht besonders fair von W.S., nirgendwo zentral eine
> "definitiv aktuelle" Version des Codes zur Verfügung zu stellen

Warum sollte er seinen Code auf Github zur Verfügung stellen? Gibt es da 
irgendwo eine Verpflichtung?
Er ist auch nicht verpflichtet seine Software zu pflegen und noch 
weniger verpflichtet die aktuellen Softwarestände zu veröffentlichen.
Er hat ihn hier veröffentlicht und das ist doch erst mal völlig 
ausreichend.
Du solltest mal Deine Erwartungshaltung überprüfen.

Mw E. schrieb:
> Überleg doch mal wer hier imemr rumstänkert im Forum?
Das ist doch auch schon wieder ein anderes Paar Schuhe. Auch wenn W.S. 
hier rumstänkert ist das noch lange kein Grund dies selbst zu tun.

von temp (Gast)


Lesenswert?

@Niklas

Bei der Gelegenheit kannst du bitte gleich noch folgende Änderung 
aufnehmen:
1
/***************************  Konstanten ********************************/
2
/* Cortex-M NVIC Register */
3
#define NVIC_ISER0  (*(volatile unsigned long *)(0xE000E100)) /* Int's  0..31 */
4
#define NVIC_ISER1  (*(volatile unsigned long *)(0xE000E104)) /* Int's  32..63 */
5
#define NVIC_ISER2  (*(volatile unsigned long *)(0xE000E108)) /* Int's  64..91 */

sowie im UsbSetup:
1
uint16_t UsbSetup(void)
2
{
3
  trace("setup\n");
4
  uint32_t* P;
5
6
  P = (uint32_t*) USB_RAM; /* RAM ablöschen  */
7
  while ((uint32_t) P < (USB_RAM + 1024))
8
    *P++ = 0;
9
10
  Class_Start();            /* LineCoding-Block aufsetzen mit unseren Defaultwerten */
11
  USB_CNTR = 3;             /* Powerdown+Reset */
12
  Nop(100);                 /* warten */
13
  USB_CNTR = 1;             /* Reset  */
14
  USB_ISTR = 0;             /* spurious Ints beseitigen */
15
  Nop(1000);                /* warten */
16
  if (USB_IRQ_NUMBER>=64)
17
    NVIC_ISER2 |= (1UL << ((USB_IRQ_NUMBER-64) & 0x1f));  
18
  else if (USB_IRQ_NUMBER>=32 && USB_IRQ_NUMBER<64)
19
    NVIC_ISER1 |= (1UL << ((USB_IRQ_NUMBER-32) & 0x1f));  
20
  else
21
    NVIC_ISER0 |= (1UL << (USB_IRQ_NUMBER & 0x1f));  
22
23
  InitEndpoints();
24
  return 0;
25
}


Bei den STM32F3xx kann man im Unterschied zu STM32F103Cx CAN und USB 
gleichzeitig nutzen, dazu muss man allerdings den USB Interrupt 
remappen.
Das ist dann der USB_LP_IRQ Handler mit der Nummer 75.
Meine Änderung ist nur dazu da, dass der Code mit dieser Nummer umgehen 
kann. Das Remapping muss man aber trotzdem selbst machen, was ungefähr 
so geht:
1
  // remap USB Interrupts to 74 and 75 for STM32F303xE/D
2
  RCC->APB2ENR|=RCC_APB2ENR_SYSCFGEN;
3
  SYSCFG->CFGR1|=SYSCFG_CFGR1_USB_IT_RMP;

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

temp schrieb:
> Bei der Gelegenheit kannst du bitte gleich noch folgende Änderung
> aufnehmen:

Hab das etwas anders gemacht - NVIC_ISER als Array definiert und mit 
etwas Arithmetik auf das richtige Element und Bit zugegriffen, um die 
Fallunterscheidung zu sparen. Die Berechnung wird ja ohnehin 
wegoptimiert. Danke für den Hinweis!

Außerdem sperre ich bei der Interrupt-Sperre jetzt nur noch den 
USB-Interrupt. Habe außerdem den Startupcode, Interrupt-Vektor & 
Takt-Konfiguration von ST durch meinen eigenes ersetzt. Ist etwas 
kompakter, und dadurch spart man sich die ganzen CMSIS-Header.

Zeno schrieb:
> DEine
> Quellenangabe ist zudem unvollständig, da man üblicherweise auch den Ort
> der Veröffentlichung angibt.

Ist aber nicht rechtlich erforderlich.

Zeno schrieb:
> Warum sollte er seinen Code auf Github zur Verfügung stellen? Gibt es da
> irgendwo eine Verpflichtung?

Natürlich nicht. Aber es ging wie gesagt um "fair", nicht mehr um 
rechtliches.

Zeno schrieb:
> Er hat ihn hier veröffentlicht und das ist doch erst mal völlig
> ausreichend.

Ich und auch andere finden es enorm hinderlich, dass es keine zentrale 
Stelle für aktuelle Code-Versionen gibt; danach wurde ja auch wiederholt 
gefragt. Natürlich MUSS er keine solche angeben, aber es ist praktisch. 
Daher habe ich so eine Stelle jetzt auf Github eingerichtet. Weitere 
Verbesserungen könnte man da jetzt pflegen.

Zeno schrieb:
> Du solltest mal Deine Erwartungshaltung überprüfen.

Ein zentrales Repository und eine vernünftige etablierte Lizenz sind 
üblich im Open-Source-Bereich.

Zeno schrieb:
> Auch wenn W.S.
> hier rumstänkert ist das noch lange kein Grund dies selbst zu tun.

Ich bin nicht Jesus und halte nicht die andere Wange hin. Ich glaube, 
eine andere Sprache versteht W.S. auch nicht.

von Np R. (samweis)


Lesenswert?

Bernd N schrieb:
> Wenn hier als Erkenntnis herauskommt das man gemeinsam viel hinbekommen
> kann
Genau darum geht es bei Open Source.
Es gibt allerdings Leute, leider manchmal auch Programmierer, die den 
Wert darin nicht sehen. (Was nichts kostet kann ja nichts wert sein.)
Das wird dann gern mit "public domain" und "freeware" durcheinander 
geworfen - oder mit "mag es nach seinem Gusto benutzen".

Wenn das dann tatsächlich geschieht und der Code auf Toilettenpapier 
gedruckt wird oder als schlechtes Lehrbeispiel in Vorlesungen Verwendung 
findet - natürlich beide Male lizenzgerecht unter Nennung des Autors - 
dann fällt einem vielleicht ein, dass man noch ein paar 
Nutzungsbeschränkungen vergessen hat...

So gesehen finde ich es sehr positiv, dass Niklas dem Ganzen eine 
solide, übliche FOSS-Basis gegeben hat - einschließlich eigener Beiträge 
und Verbesserungen, wie eben bei Open Source üblich.

Open Source hat natürlich eine Eigenschaft, die manchen "unhöflich" 
erscheinen mag oder sogar sehr unangenehm ist: Manchmal ist am Ende vom 
Code des ersten Autors nicht mehr viel übrig. Er verdient dann noch 
Anerkennung für die ursprüngliche Idee, aber der "Ruhm" für die "beste 
Umsetzung" gebührt anderen.
Sich aufpumpen und herumblähen, was für ein Genius man ist, geht mit 
FOSS schlecht.
Wessen Ego damit nicht klar kommt, muss FOSS fern bleiben und seinen 
Code im Keller verstecken.
Er darf ihn jedenfalls nicht dem "Gusto" Anderer ausliefern.

Zeno schrieb:
> Auch wenn W.S.
> hier rumstänkert ist das noch lange kein Grund dies selbst zu tun.
Das allerdings ist vollkommen richtig.

von Zeno (Gast)


Lesenswert?

Niklas G. schrieb:
> Zeno schrieb:
>> DEine
>> Quellenangabe ist zudem unvollständig, da man üblicherweise auch den Ort
>> der Veröffentlichung angibt.
>
> Ist aber nicht rechtlich erforderlich.

Das mag schon so sein, aber der Anstand gebietet es - halt schlecht wenn 
man zu wenig davon.


Niklas G. schrieb:
> Zeno schrieb:
>> Auch wenn W.S.
>> hier rumstänkert ist das noch lange kein Grund dies selbst zu tun.
>
> Ich bin nicht Jesus und halte nicht die andere Wange hin. Ich glaube,
> eine andere Sprache versteht W.S. auch nicht.

Verlangt auch keiner von Dir, allerdings stellst Du Dich auf die gleiche 
Stufe, wenn Du Gleiches mit Gleichem vergiltst.


Niklas G. schrieb:
> Zeno schrieb:
>> Er hat ihn hier veröffentlicht und das ist doch erst mal völlig
>> ausreichend.
>
> Ich und auch andere finden es enorm hinderlich, dass es keine zentrale
> Stelle für aktuelle Code-Versionen gibt; danach wurde ja auch wiederholt
> gefragt. Natürlich MUSS er keine solche angeben, aber es ist praktisch.
> Daher habe ich so eine Stelle jetzt auf Github eingerichtet.

Ob Du oder andere es hinderlich finden wenn Sourcecode nicht an einer 
zentralen Stelle hinterlegt wird, ist von untergeordneten Interesse. Der 
Autor der Software wird einen Grund haben warum er dies nicht selbst 
tut, sondern seinen Code hier im Forum veröffentlicht und allen die 
diesen hier lesen ein Nutzungsrecht einräumt. Dies wiederum schließt 
nicht ein den Code an anderer Stelle ohne sein Wissen zu 
veröffentlichen. Selbst wenn es rein formalrechtlich in Ordnung ist, 
gehört es zum Anstand und zum fairen Umgang, auf den Du ja so viel Wert 
legst, zuvor zu fragen. Dazu hätte es lediglich einer kurzen Testzeile 
bedurft.

von temp (Gast)


Lesenswert?

Niklas G. schrieb:
> Hab das etwas anders gemacht - NVIC_ISER als Array definiert und mit
> etwas Arithmetik auf das richtige Element und Bit zugegriffen, um die
> Fallunterscheidung zu sparen. Die Berechnung wird ja ohnehin
> wegoptimiert. Danke für den Hinweis!
>
Danke. Wichtig war mir nur, dass der Aspekt überhaupt Berücksichtigung 
findet.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Ich habe W.S. gefragt was man mit dem Code machen kann, d.h. nach einer 
Lizenz. Diese kann angeben, wie man den Code veröffentlichen darf. Die 
vorhandene Lizenz enthält keine Einschränkungen. Also kann ich den Code 
veröffentlichen wo ich will. Ich habe die Anfrage allgemein formuliert 
und allgemein geklärt. Es ist nicht nötig, jetzt speziell für 
Einzelfälle nochmal einzeln nachzufragen.

Das ist im Open Source Bereich absolut üblich; Unmengen an Open Source 
Paketen landen an vielen Stellen im Netz und in vielen anderen 
Projekten, ohne dass der ursprüngliche Autor jedes Mal gefragt wird.

Zeno schrieb:
> Selbst wenn es rein formalrechtlich in Ordnung ist,
> gehört es zum Anstand und zum fairen Umgang, auf den Du ja so viel Wert
> legst, zuvor zu fragen.

Man soll also zwei Ebenen der Erlaubnis haben? Eine rechtliche, und eine 
"anständige"? Ist das nicht ziemlich redundant? Wäre es nicht einfacher, 
in der rechtlichen Ebene schon klar zu sagen was man will und was nicht, 
und nicht erst auf der Anstands-Ebene noch mehr Einschränkungen zu 
machen?

Zeno schrieb:
> Verlangt auch keiner von Dir, allerdings stellst Du Dich auf die gleiche
> Stufe, wenn Du Gleiches mit Gleichem vergiltst.

Danke für die moralische Belehrung. Nächstes Mal wenn ich von anonymen 
Internet-Nutzern von oben herab behandelt werde, werde ich artig "Danke" 
sagen und mich unter der Bettdecke verstecken.

von Np R. (samweis)


Lesenswert?

Zeno schrieb:
> Dies wiederum schließt
> nicht ein den Code an anderer Stelle ohne sein Wissen zu
> veröffentlichen.

Woher weißt Du das?
Es wurden nur zwei Bedingungen gemacht. Die Bedingung, den Code nicht zu 
veröffentlichen, war nicht dabei.
Ganz im Gegenteil: Die Bedingung, dass der ursprüngliche Autor genannt 
werden sollte, macht ohne eine Veröffentlichung/weitergabe überhaupt 
keinen Sinn.

von Bernd N (Gast)


Lesenswert?

Jetzt waren wir fast fertig aber ich glaube da hat sich ein neuer Fehler 
eingeschlichen.

Wenn ich jetzt den Beispiel Code von Stefan verwende, welcher in der 
main hello world ausgibt, funktioniert das mit der aktuellen Version 
nicht mehr.
1
    while (1)
2
    {
3
        // LED On
4
        WRITE_REG(GPIOC->BSRR, GPIO_BSRR_BR13);
5
        delay_ms(100);
6
7
        UsbStrOut("Hello World!\n\r");
8
9
        // LED Off
10
        WRITE_REG(GPIOC->BSRR, GPIO_BSRR_BS13);
11
        delay_ms(900);
12
    }
13
}
Ich vermute da blockiert jetzt ein disable IRQ irgendwo. Hier wird ja 
direkt jede Sekunde ein Text via UsbStrOut geschrieben und man öffnet 
das Terminal während der MC ja schon sendet. Das funktioniert so nicht 
mehr.

@ Niklas, kannst du das bitte mal testen ?
@ Stefan, hast du mal Niklas Version bei dir eingebaut und Tests gemacht 
?

Vielen Dank nochmal.

von Stefan F. (Gast)


Lesenswert?

Bernd N schrieb:
> @ Stefan, hast du mal Niklas Version bei dir eingebaut und Tests gemacht
> ?

Ich habe mit C++ auf Mikrocontroller noch keinerlei Erfahrung. Also: 
nein

Die Beschäftigung mit Niklas Code steht noch auf meine Todo Liste, aber 
niedrig priorisiert.

von Bernd N (Gast)


Lesenswert?

>> Ich habe mit C++ auf Mikrocontroller noch keinerlei Erfahrung.
Hast du nicht mitgelesen ? es geht um den Code aus deiner 
Veröffentlichung (Code von WS) den Niklas gefixed hat.

von Niklas Gürtler (Gast)


Lesenswert?

Bernd N schrieb:
> Hier wird ja direkt jede Sekunde ein Text via UsbStrOut geschrieben und
> man öffnet das Terminal während der MC ja schon sendet. Das funktioniert
> so nicht mehr.

Kanns grad nicht testen. Weil du ja schon anfängst Daten in den 
Sendepuffer zu schreiben wenn die USB-Verbindung noch gar nicht 
aufgebaut ist, läuft der Puffer schnell voll. Kann sein dass die 
Enumeration durch die ständig blockierten Interrupts dann nicht 
funktioniert. Fange besser erst dann an zu senden wenn SET_CONFIGURATION 
empfangen wurde.

von Bernd N (Gast)


Lesenswert?

OK, wie kann ich das am besten prüfen ? prüfe ich da auf
USB_ConfigDevice == true ?

Versuchsweise warte ich jetzt einfach 5 Sekunden und das gibt dem Ganzen 
genug Zeit zum starten und es funktioniert. Deine Vermutung wird wohl 
passen.

von Thomas Z. (usbman)


Lesenswert?

Niklas Gürtler schrieb:
> Fange besser erst dann an zu senden wenn SET_CONFIGURATION
> empfangen wurde.

bevor SetConfiguration erreicht ist dürfen die Buffer noch garnicht 
arbeiten. Normalerweise werden die Endpoints erst danch freigeschaltet. 
Das steht so zumindest in der Spec.
Entsprechende Bytes in der Sio müssen deshalb verworfen werden.

Thomas

von Pieter (Gast)


Lesenswert?

beim Init von USB setze ich erst den Puffercounter auf 255, der 
Sendepuffer wird so als voll deklariert.
Ist die Enumeration abgeschlossen wird der Puffercounter auf 0 gesetzt 
und es kann losgehen.
Bei mir wird mit USB_ISTR Bit9 wird ein Connect USB-PC angezeigt.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Ich habe auf GitHub einen Branch "Test-SetConfiguration" angelegt in 
welchem es jetzt eine Funktion "UsbConfigured()" gibt, welche prüft, ob 
eine Konfiguration gesetzt wurde. Man darf den VCP nur nutzen, solange 
diese "true" liefert (kann auch wieder "false" werden). Die Sende-und 
Empfangsfunktionen prüfen das jetzt auch und machen sonst gar nichts.

Das Senden sollte man dann so in der Art machen:
1
    while (1)
2
    {
3
        // LED On
4
        WRITE_REG(GPIOC->BSRR, GPIO_BSRR_BR13);
5
        delay_ms(100);
6
7
        if (UsbConfigured ())
8
            UsbStrOut("Hello World!\n\r");
9
10
        // LED Off
11
        WRITE_REG(GPIOC->BSRR, GPIO_BSRR_BS13);
12
        delay_ms(900);
13
    }

Es gibt da immer noch eine Race Condition - wenn der Host das Gerät 
wieder per SET_CONFIGURATION=0 abschaltet könnten die zuletzt 
abgesendeten Daten im Nirvana landen ohne dass die Anwendung das merkt.

Ich kann das derzeit aber nicht testen...

Bernd N schrieb:
> prüfe ich da auf
> USB_ConfigDevice == true ?

Nein das ist etwas anderes...

Pieter schrieb:
> Bei mir wird mit USB_ISTR Bit9 wird ein Connect USB-PC angezeigt.

Das ist aber das SOF-Bit. Das wird praktisch sofort nach dem Einstecken 
gesetzt, lange vor der eigentlichen Enumeration und bevor man überhaupt 
was senden darf.

: Bearbeitet durch User
von Thomas Z. (usbman)


Lesenswert?

Niklas G. schrieb:
> Es gibt da immer noch eine Race Condition - wenn der Host das Gerät
> wieder per SET_CONFIGURATION=0 abschaltet könnten die zuletzt
> abgesendeten Daten im Nirvana landen ohne dass die Anwendung das merkt.

Das ist ziemlich unwahrscheinlich. Zumindest hab ich das so unter win 
noch nie gesehen. Ich könnte mir das vorstellen bei einem Device was 
mehrere Konfigurationen hat. Solche Devices sind aber eher unüblich und 
werden von win in der Regel auch nicht unterstützt.
Wie sich das nach einem wakeup verhält müsste man untersuchen. Das ist 
aber sowieso hier nicht implementiert.

Thomas

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Thomas Z. schrieb:
> Das ist ziemlich unwahrscheinlich. Zumindest hab ich das so unter win
> noch nie gesehen.

Ist von der USB-Spezifikation halt so vorgesehen. Man könnte es 
versuchen zu provozieren indem man das eigene Gerät als 500mA 
konfiguriert und an einem Bus-Powered Hub anschließt und da danach dann 
noch irgendein weiteres Gerät ansteckt. Möglicherweise versucht der Host 
dann das eigene Gerät via SET_CONFIGURATION=0 abzuschalten um genug 
Strom für das neue Gerät zu frei zu machen, oder das neue wird gar nicht 
erst eingeschaltet. Theoretisch dürften die beiden Geräte nicht 
gleichzeitig an einem Bus-Powered Hub eingeschaltet sein.

von Thomas Z. (usbman)


Lesenswert?

Ja dazu müsstest du aber einen Hub finden der das auch richtig macht. 
Die meisten Hubs die ich kenne haben das selfpowered Bit gesetzt auch 
wenn sie buspowerd sind. Schon alleine aus dem Grund damit es beim 
Anwender keine Probleme gibt.
An einem buspowerd Hub sollten nur Geräte mit 100mA enumeriert werden.

Noch was zu mehreren Konfigurationen:

Ich hab sowas Mal testweise implementiert und kann mich noch sehr gut an 
das Gefluche der Treiberentwickler erinnern. Am Ende haben wir das 
wieder verworfen und anders implementiert.

Thomas

von Bernd N (Gast)


Lesenswert?

Hallo Niklas,

Vielen Dank für die neue Funktion, damit passt es. So langsam wirds :-) 
ich freu mich sehr darüber das dieser Fehler nun auch aufgefangen werden 
kann.

@ Stefan, nimm dir mal die Zeit und schau dir an was Niklas da gemacht 
hat, er hat den Code von WS gefixed und erweitert. Das solltest du auch 
bei deinem Code anpassen.

Danke nochmals und einen schönen Tag.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Bernd N schrieb:
> Das solltest du auch
> bei deinem Code anpassen.

Oder einfach nur noch auf mein GitHub-Repository verlinken :P

von Stefan F. (Gast)


Lesenswert?

Bernd N schrieb:
> @ Stefan, nimm dir mal die Zeit und schau dir an was Niklas da gemacht
> hat, er hat den Code von WS gefixed und erweitert. Das solltest du auch
> bei deinem Code anpassen.

Mache ich. Es wird aber ein paar Tage dauern, weil ich derzeit mit 
diesem QT Tutorial ausgelastet bin.

von temp (Gast)


Lesenswert?

Hallo Niklas,

das mit dem DisableUsbIrq() und EnableUsbIrq() solltest du noch mal 
üben. Hier dein Code vom github:
1
void UsbStrOut(char* S)
2
{
3
    DisableUsbIRQ ();
4
    if (CMD.Configuration == 0) {
5
      EnableUsbIRQ ();
6
      return;
7
    }
8
9
    while (*S)
10
        UsbCharOut(*S++);
11
}

Einmal UsbStrOut("") aufgerufen und der Usb-Interrupt wird nie wieder 
enabled.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

temp schrieb:
> das mit dem DisableUsbIrq() und EnableUsbIrq() solltest du noch mal
> üben.

Vielen Dank für den charmanten Hinweis. Normalerweise mache ich so etwas 
mit C++ und RAII, deswegen bin ich im umständliche C-Codieren nicht mehr 
geübt. Da meine Programme sowieso meistens asynchron in ISRs ohne 
main()-Schleife laufen, ist Interrupts sperren da auch nie nötig.

: Bearbeitet durch User
von Bernd N (Gast)


Lesenswert?

Hallo Niklas,

sorry das ich noch einmal nerve. Ich habe da noch ein Verständnis 
Problem. Die Funktion "UsbConfigured()" prüft ja auf eine aktive VCP 
Verbindung, verstehe ich das so Richtig ?

Also wenn ich jetzt z.B. den simplen Code aus dem Hello World Beispiel 
verwende, dann blinkt ja die LED jede Sekunde und zeigt damit auch an, 
dass main durchlaufen wird. Wenn ich jetzt die Terminalverbindung 
schließe dann hört das Blinken nach wenigen Sekunden auf. Mit anderen 
Worten, main wird nicht mehr durchlaufen.

Starte ich das Terminal erneut dann gehts weiter, alles funktioniert 
jetzt wieder.
Ich dachte das die Funktion "UsbConfigured()" auf eine aktive VCP 
Verbindung prüft und somit ja eigentlich keine Kommunikation via USB 
mehr läuft. Warum wird bei inaktiver VCP Verbindung main nicht mehr 
ausgeführt ? Wäre es möglich das Ganze so zu ändern das eine inaktive 
VCP Verbindung nicht alles blockiert ? mir würde es schon helfen wenn 
ich den USB Programmfluss mal erläutert bekäme.

Danke

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Bernd N schrieb:
> Wenn ich jetzt die Terminalverbindung
> schließe dann hört das Blinken nach wenigen Sekunden auf. Mit anderen
> Worten, main wird nicht mehr durchlaufen.

Oha, der Host kann natürlich beim Kabel rausziehen nicht noch schnell 
das Gerät per SET_CONFIGURATION abschalten. Das Code muss das Trennen 
selbst erkennen. Tatsächlich geht das gar nicht so direkt, denn "RESET" 
muss vom Host gesendet werden. Ich habe den Code so umgebaut dass 
"Suspend" und "Resume" erkannt werden. Die Funktion "UsbConfigured()" 
habe ich nach "UsbActive()" umbenannt, welche dann auch den 
Suspend-Zustand mit einbezieht. Das Gerät merkt somit nicht wirklich 
dass das Kabel getrennt wurde, sondern denkt es wäre im Standby. Das 
Senden wird dann blockiert; UsbCharOut und UsbStrOut kehren dann einfach 
sofort zurück. Du solltest dann in der main()-Schleife UsbActive() 
abfragen.
Ich habe das getestet und auf GitHub auch in den "master" Branch 
übernommen.

Bernd N schrieb:
> mir würde es schon helfen wenn
> ich den USB Programmfluss mal erläutert bekäme.

Das kannst du mit einem JTAG-Debugger gut nachvollziehen. Die 
USB-Spezifikation ist hier:
https://www.usb.org/document-library/usb-20-specification

von Bernd N (Gast)


Lesenswert?

Ich habe es getestet und das Verhalten ist genauso wie vorher. Die main 
wird nicht ausgeführt wenn ich das Terminal schließe aber wenn ich es 
erneut öffne dann gehts weiter.

Der Unterschied zu vorher ist, dass wenn keine Verbindung aufgebaut 
werden kann, also ich lasse das Programm laufen ohne das eine VCP 
Verbindung zustande kommt, dann läuft die main durch. Sobald eine VCP 
Verbindung dann steht ist auch alles wie es soll, wenn ich dann 
mittendrin das Terminal schließe dann hängt es, beim wieder starten des 
Terminals gehts weiter. Also derzeit schon einmal die halbe lösung aber 
eine Terminal Unterbrechung wird nicht gehandelt.

Aber das ist schon die richtige Richtung.

Die Idee ist es natürlich wie bei einer UART zu verfahren. Ich verstehe 
das USB etwas anderes ist und wenn das so nicht geht dann ists auch ok. 
Jedenfalls ist diese Version schon wieder eine Verbesserung.

Besten Dank soweit.

von Bernd N (Gast)


Lesenswert?

Sorry, zurück, das Verhalten ist wie zuvor. Also ich kann nicht wirklich 
eine Änderung sehen.

von Bernd N (Gast)


Lesenswert?

OK, habe es begriffen. Keine USB Verbindung, main läuft mit dieser 
Version. USB Verbindung aktiv aber Terminal geschlossen, main wird nicht 
durchlaufen. Also hat es sich verändert.

von Niklas Gürtler (Gast)


Lesenswert?

Bernd N schrieb:
> OK, habe es begriffen. Keine USB Verbindung, main läuft mit dieser
> Version. USB Verbindung aktiv aber Terminal geschlossen, main wird nicht
> durchlaufen

Ja das ist doch klar. Wenn kein Terminal offen ist holt der PC die Daten 
nicht ab. Das Gerät kann nicht feststellen ob ein Terminal läuft oder 
nicht, da kann man nichts dran machen. So etwas bekommt man nur in den 
Griff indem man seine eigene Klasse implementiert und mittels libusb 
o.ä. zugreift, und entsprechende Handshakes baut. Ein Gerät welches 
ständig Daten sendet die dann aber ins Nirvana gehen macht aus USB-Sicht 
wenig Sinn!

von Stefan F. (Gast)


Lesenswert?

Niklas Gürtler schrieb:
> Ein Gerät welches ständig Daten sendet die dann aber
> ins Nirvana gehen macht aus USB-Sicht wenig Sinn!

Sehe ich auch so.

Wenn man das halbwegs sauber abfangen wollte, müsste man einen Timeout 
festlegen, aber dann kommt die Frage auf, was den im Timeout passieren 
soll.

Da wird es dann ganz schnell Anwednungs-Spezifisch. Ich habe den Code 
von W.S. als Beispiel aufgefasst, nicht als Eierlegende Wollmilchsau. 
Wenn wir da für jede Eventualität etwas einbauen, wird es rasch klobig 
und unübersichtlich - dann kann man auch gleich die HAL von ST nehmen.

Ich denke, wir sollten es beim aktuellen Stand belassen.

von Bernd N (Gast)


Lesenswert?

Keine Sorge, das ist alle OK, ich wollte es ja nur verstehen. Der Stand, 
wie er ist, ist sehr gut und mehr als ich am Anfang überhaupt erwartet 
habe. Aber ich denke auch die Änderungen die du gemacht hast waren 
allesamt notwendig. Ich bin daher froh das ich Nerve und ne Menge Tests 
gemacht habe. Die Bugs sind jetzt raus und die Funktionalität hat doch 
gewonnen.

Nochmals besten Dank dafür.

von Stefan F. (Gast)


Lesenswert?

Ich habe die Änderungen in die vier Projekte auf meiner Homepage 
(http://stefanfrings.de) übernommen. Ich konnte Niklas Korrekturen auf 
einem Blue-Pill Board mit Debian Linux erfolgreich verifizieren.

Besten Dank Niklas, das hast du gut gemacht. Darüber freue ich mich 
sehr.

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.