Hallo W.S.
Ich habe eine Frage zu deiner USB CDC Implementierung, die du hier schon
ein paar mal veröffentlicht hast.
Und zwar habe ich den µC mit einem Netzteil versorgt. Der Pull-Up
Widerstand an D+ ist fest mit 3,3V verbunden (Blue-Pill Board).
Das Programm sende jede Sekunde "Hello World" an den PC. Dann trenne ich
das USB kabel im laufenden Betrieb. Nach einer gewissen Zeit hängt das
Programm bei UsbCharOut() weil der Sendepuffer voll ist und voll bleibt.
Wenn ich dann das USB Kabel wieder mit dem PC verbinde kommt aber keine
Neue Kommunikation mehr zustande. Der virtuelle COM Port wird nicht
sichtbar, entsprechend kann ich ihn mit dem Terminalprogramm auch nicht
wieder öffnen.
Hast du einen heissen Tip, wie ich es hinbekommen kann, dass ich das USB
kabel später erneut verbinden kann ohne den µC resetten zu müssen?
Fuer deinen uP weisz ich nicht, aber bei mir (Cypress PSOC5LP) hatte ich
genau dieses problem. Der DTR MUSZ von PC aus gesetzt werden musz bei
die oefnung der Virtual Serial Port (CDC).
Also im PC programm (bei mir C#)
> Der DTR MUSZ von PC aus gesetzt werden
Mein Problem ist, dass der Reconnect gar nicht funktioniert. Also gibt
es auch keinen DTR. Die Sache mit dem DTR kenne ich bereits von der CDC
Implementierung in Arduino.
> dieser link beschreibt genau das gleiche problem
Nein, da geht es auch um die DTR Leitung. Mein Problem ist, das der USB
Reconnect nicht funktioniert.
Offensichtlich besteht hier ein Missverständnis.
Nach dem ersten Anstecken des USB Kabels funktioniert die Kommunikation
zum PC.
Aber wenn ich das Kabel abstecke und dann nach längerer Zeit (5min) erst
wieder anstecke, dann kommt keine neue Verbindung mehr zustande. Der
virtuelle COM Port wird nicht angelegt.
Wenn ich das Kabel jedoch nur für kurze Zeit abstecke oder keine "Hello
World" texte sende während es unterbrochen ist, funktioniert der
Reconnect ohne Probleme.
Ich habe das Experiment nochmal wiederholt und muss meine
Fehlerbeschreibung ergänzen.
Wenn ich den virtuellen COM Port im Terminalprogramm schließe, bevor ich
das USB kabel abziehe, wird er beim Reconnect wieder neu bereit gestellt
und funktioniert dann auch.
Wenn ich es so lange abgesteckt lasse, dass der Sendepuffer voll läuft,
funktioniert der Reconnect aus Windows Sicht auch (das hatte ich oben
falsch geschrieben). Aber das Programm auf dem µC bleibt weiterhin
hängen. Die LED blinkt nicht und das Terminalprogramm empfängt keine
Daten.
Ich habe inzwischen mal den Debugger eingesetzt, um zu prüfen, dass der
µC wirklich in UsbCharOut() hängt. jetzt kommt der Witz: Mit der
Optimierung -O0 tritt der Fehler nicht mehr auf!
Dafür meldet Windows jetzt bei -O1 und -O2 grundsätzlich bei jedem
Anstecken, dass das Gerät nicht ordnungsgemäß funktioniert.
Mein eigentliches Problem mit dem Reconnect ist so gar nicht mehr
nachvollziehbar. Dafür habe ich neues größeres Problem bekommen. Grmpf!
Einen Hardwaredefekt habe ich ausgeschlossen, mit Arduino und Cube HAL
läuft es zuverlässig.
Ich habe die Lösung für beide Probleme gefunden. Bin total Happy!
1) Wegen dem Reconnect: Die Variablen vom Puffer müssen volatile sein.
1
/* die Transfer-Puffer für zeichenweises In und Out über den USB */
2
#define txLen 256
3
volatilecharUsbTxBuf[txLen];
4
volatileinttxr,txw;
5
6
#define rxLen 256
7
volatilecharUsbRxBuf[rxLen];
8
volatileintrxr,rxw;
2) Die Verzögerungsschleife mit dem NOP war zu klein:
1
voidNop(dwordcount)
2
{
3
while(count)
4
{
5
asmvolatile("nop");
6
asmvolatile("nop");
7
asmvolatile("nop");
8
asmvolatile("nop");
9
asmvolatile("nop");
10
asmvolatile("nop");
11
asmvolatile("nop");
12
asmvolatile("nop");
13
asmvolatile("nop");
14
asmvolatile("nop");
15
asmvolatile("nop");
16
asmvolatile("nop");
17
--count;
18
}
19
}
Bei 48Mhz Systemtakt habe ich herausgefunden, dass ich mindestens 9 nops
brauche. Sicherhaltshalber habe ich paar mehr genommen. Klappt auch mit
72Mhz.
Tja, das gleiche Problem mit der wackligen delay-Implementierung hatte
ich hier auch schon paar mal berichtet. Alle Versuche W.S. zu einem
Statement zu überreden endeten ohne Antwort. Es wird so sein wie ich
schon vermutet habe, hier freut sich einer wenn andere Leiden.
> Kannst es ja auch mal so probieren
Das wären 16 Nops pro Durchlauf + 16 mal so oft dekrementieren. Das ist
viel mehr als meine bereits großzügig gewählten 12 Nops.
Ich hatte irgendwo mal gelesen, dass nur ein volatiles NOP in die
Schleife rein muss weil sie sonst weg optimiert wird. Nun stellt sich
heraus, dass das viel zu wenig war.
Egal, es läuft jetzt stabil. Ich denke, alle hier vorgeschlagenen Lösung
funktionieren.
Stefan U. schrieb:> Egal, es läuft jetzt stabil. Ich denke, alle hier vorgeschlagenen Lösung> funktionieren.
Eine schlanke Alternative zu STs USB-Code hört sich interessant an :)
Stefan U. schrieb:> Das wären 16 Nops pro Durchlauf + 16 mal so oft dekrementieren. Das ist> viel mehr als meine bereits großzügig gewählten 12 Nops.
Darum stand ja auch "anpassen" im Kommentar. Das __NOP() aus core_cm3.h
hat den Vorteil, dass es je nach Compiler die richtige Implementierung
macht. Beim gcc ist das dann:
1
static__INLINEvoid__NOP(){__ASMvolatile("nop");}
Damit ist der Code dann auch unter Keil übersetzbar, der mit der gcc
Syntax "asm volatile" nichts anfangen kann.
Allerdings, diese Lösung ist ziemlich schlank.
Deswegen interessiere ich mich dafür. Liegt vielleicht auch daran, dass
mein Einstieg in µC Programmierung mit 1kB Flash und 64 Bytes RAM
begann.
Das delay sieht irgendwie eher wie nen Hack aus. Das sind da später im
Code 25us Pause bei 48MHz(12*100/48).
Gibt es da eventuell irgendwo nen Ready-bit was man Abfragen kann?