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
intmain(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
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.
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.
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.
>> 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.
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.
>> 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.
>> 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.
>>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?
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
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.
@ 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.
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.
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.
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.
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
charUsbGetChar(void)
2. Dein UsbTxReady() check ist redundant, da er in
1
/* sendet ein Zeichen (d.h. schreibt es in den Tx-Buffer) */
2
charUsbCharOut(charc)
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:)
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.
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"
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.
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.
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.
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.
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.
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?
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.
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.
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.
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.
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.
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.
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.
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.
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.
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?
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-loopbackhttps://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.
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.
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
D01FFFF
gegeben. Also er soll den Bereich 0..1FFFF als hexdump ausgeben. So eine
Zeile davon sieht etwa so aus:
1
00000000:F04F00204D010000750100007B010000OMu{
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.
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.
>> 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.
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 ?
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.
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?
... 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.
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.
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
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
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):
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.
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!
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.
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.
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:
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.
@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.
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?
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.
>> 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.
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.
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.
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.
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
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.
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.
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.
>> 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
>> 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.
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.
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?
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.
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?
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.
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.
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.
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?
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.
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.
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.
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?
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.
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.
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?
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.
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?
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.
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".
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.
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.
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.
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.
#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_tUsbSetup(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
elseif(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
return0;
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
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.
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.
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.
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.
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.
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.
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.
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.
>> 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.
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.
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.
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
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.
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.
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
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.
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
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.
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.
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.
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
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
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.
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.
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!
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.
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.
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.