Forum: Mikrocontroller und Digitale Elektronik STM32 USB Übertragungsproblem mit Code von S.F.


von Thomas Z. (usbman)


Angehängte Dateien:

Lesenswert?

Hier nun meine neue Version des VCP mit Header Files für usb1.1 und 
vcp1.2. Das ganze ist noch nicht 100% ausgereift, funktioniert aber als 
Replacement für usb.c. Im Quelltext hab mal ein paar Stellen mit todo 
markiert, die ich noch für buggy halte.
Noch entspricht das Endpoint Management dem Original, d.h. die 
bidirektionalen  sind noch nicht implementiert.

Die entgültige Version werde ich dann vermutlich in Projekte & Code 
einstellen.

von W.S. (Gast)


Lesenswert?

Mal noch ein paar Anmerkungen meinerseits:

uint16_t UsbSetup(void)

Ein int würde ausreichen, da in diesem Treiber niemals etwas anderes als 
0 zurückgegeben wird. Wahrscheinlich täte es ein bool auch. Das ganze 
ist ne historisch gewachsene Altlast und wenn du ohnehin erhebliche 
Änderungen machst, dann wäre mMn ein bool oder gar ein void eher 
angebracht.

volatile bool receiving = false;
volatile bool transmitting = false;

Sowas setzt die Vorbelegung des RAM im Startup voraus. Ich würde die 
beiden Flags schlichtweg in UsbSetup auf null setzen, dann kann der 
Startup tun oder lassen, was er will. Ist mal wieder eine Fehlerquelle 
weniger.

void UsbStrOut(char* S)
Schmeiß es lieber ersatzlos raus. Ich hatte mich schon vor Jahren 
darüber geärgert, daß ich es überhaupt mal dort hineingesetzt hatte. 
Hab's dann nur der Kompatibilität zuliebe drin gelassen.

/* holt ein Zeichen vom USB ab */
/* Achtung: wenn nix abzuholen ist, wird 0 zurückgeliefert */
char UsbGetChar(void)
{ char c;
  c = 0;
  if (!configurationSet || suspended)
  {  return -1;
 ...

Naja, return 0 wäre mMn eher passend. Ist ja ein 8 Bit Char.

Und in UsbGetChar()
... if (!receiving)...

Wenn das denn schon im Usercode-Bereich behandelt werden soll, dann 
kommt mir dabei der kühne Gedanke, auf den Ringpuffer in Richtung 
PC-->µC ganz und gar zu verzichten. Immerhin haben wir ja Bulk_Out_A und 
Bulk_Out_B zum eventuellen Umschalten, wenn man sich diese Mühe machen 
will. Vorbereitet ist das alles schon seit langem, ich hatte es bloß 
damals nicht benutzt, weil ich eben nicht wollte, daß der Usercode in 
den Innereien des USB-Interrupts herumfuhrwerkt, sondern daß der 
Usercode sich eben damit begnügt, im zuständigen Ringpuffer 
nachzuschauen, ob's was gibt oder nicht.

W.S.

von Thomas Z. (usbman)


Lesenswert?

W.S. schrieb:
> Mal noch ein paar Anmerkungen meinerseits:

Danke, einiges was du aufzählst ist mir selbst schon aufgefallen. 
Momentan arbeite ich nur am USB Teil.
Am Usercode bzw Buffer Code ist alles noch original zu der Version von 
Stefan.

Im Moment stelle ich gerade die beiden Bulk EPs so um, dass Sie beide 
auf EP1 liegen.

Im Endausbau soll das dann so sein, das es bis zu 4 VCPs gibt VCP 1 wie 
gehabt, die restlichen auf ser. Schnittstellen umgeleitet.

von W.S. (Gast)


Lesenswert?

Thomas Z. schrieb:
> Im Endausbau soll das dann so sein, das es bis zu 4 VCPs gibt VCP 1 wie
> gehabt, die restlichen auf ser. Schnittstellen umgeleitet.

Bist du sicher, daß man das tatsächlich braucht?
Nicht alles, was man können kann, muß man auch tatsächlich tun.

Sinn und Zweck der ganzen Übung war ja ursprünglich, daß man an seinem 
µC eine Serielle per USB hat, um darüber mit dem PC kommunizieren zu 
können. Da reicht eine Serielle völlig aus.

Und ich hatte auch drauf achten wollen, daß der Treiber nicht unnötig 
umfänglich wird, damit auch diejenigen, die IAR oder Keil bis jeweils 
32K benutzen, noch genug Flash haben für ihr eigentliches Zeugs.

Vorschlag: Mach ruhig deine Vollst-Version, aber mach auch gleich drauf 
eine wieder abgespeckte Version nur für das Nötigste.

W.S.

von Thomas Z. (usbman)


Lesenswert?

W.S. schrieb:
> Vorschlag: Mach ruhig deine Vollst-Version, aber mach auch gleich drauf
> eine wieder abgespeckte Version nur für das Nötigste.

Na ja meine Idee ist es konfigurierbar zu machen im einfachsten Fall ist 
es dann funktionsgleich zum Original.

Das ist auch gleichzeitig meine Spielwiese um mit der ST Peripherie warm 
zu werden.

von Thomas Z. (usbman)


Angehängte Dateien:

Lesenswert?

Ich habe jetzt die bidirektionalen BulkEps eingebaut und auch sonst 
einiges umgestellt. Noch ist der Code funktionsgleich zum Original, 
wobei ich die Kopier Funktionen von und zum usbmem etwas verändert habe.
Es wäre gut wenn das jemand auf einem Controller gegenchecken kann der 
UMEMSHIFT=0 benötigt. Ich habe nur auf den BluePills getestet.

Der code ist momentan sogar etwas kleiner als das Original. Noch nicht 
imlementiert, aber vorbereitet ist der mehrfach VCP.

Usb2CV läuft ohne Fehler durch, im Moment funktioniert 
SetConfiguration(0) noch nicht, das wird aber nur als Hinweis gemeldet.

Ich würde mich über Rückmeldungen freuen.

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Thomas Z. schrieb:
> Es wäre gut wenn das jemand auf einem Controller
> gegenchecken kann der UMEMSHIFT=0 benötigt.
> Ich würde mich über Rückmeldungen freuen.

Funktioniert auf den ersten Blick.

von Thomas Z. (usbman)


Lesenswert?

Danke für den Test. Dann hab ich das ja soweit richtig verstanden. Ich 
hatte sowieso nur die Kopierfunktionen für EP0 geändert. Wenn ich einen 
Fehler gemacht hätte, würde Enum auf dem f303 nicht mehr funktionieren.

von Alex (Gast)


Lesenswert?

Hallo Thomas,

ich hab gestern Abend endlich wieder Zeit gefunden, um an den Modulen 
weiterzumachen. Hab deine obige Version in meinen F042 reingespielt und 
hat bei mit unter Win10 funktioniert.
Auf Win7 ging es nicht, Win behauptet dass es keinen passenden Treiber 
hat.
Der einzige Unterschied, den ich fand ist, dass mit der neuen Version 
von dir die Hardware-ID im Gerätemanager
'USB\VID_0416&PID_5011&REV_0100&MI_00'
ist.
Mit der alten Version (usb.c. von S.F.) war das MI_00 nicht dabei.

nachdem ich auf Win7 die NuvotonCDC.inf wie folgt angepasst habe, läuft 
es.
1
[Devices.NT]
2
%DESCRIPTION%  = NuvotonCDC_DEV, USB\VID_0416&PID_5011
3
%DESCRIPTION%  = NuvotonCDC_DEV, USB\VID_0416&PID_5011&MI_00
4
5
[Devices.NTamd64]
6
%DESCRIPTION%  = NuvotonCDC_DEV, USB\VID_0416&PID_5011
7
%DESCRIPTION%  = NuvotonCDC_DEV, USB\VID_0416&PID_5011&MI_00
Nur falls sonst noch jemand W7 laufen hat... :-)


Ein anderes Thema hab ich leider immer noch:
Hab die Version von dir auf einem jener Module getestet, die beim 
Runterschicken von Befehlen immer Probleme hatten (auf einem alten, 
nicht dem mit dem ich diesen Thread gestartet hab).
Die Übertragungsprobleme hab ich damit immer noch.
Manchmal verträgt es 1-2 Befehle, aber irgendwann ist Schluss mit 
Runterschicken.


Alex

von Stefan F. (Gast)


Lesenswert?

Alex schrieb:
> falls sonst noch jemand W7 laufen hat

Uff, das ist bei mir "aus den Augen, aus dem Sinn".

von W.S. (Gast)


Lesenswert?

Alex schrieb:
> Manchmal verträgt es 1-2 Befehle, aber irgendwann ist Schluss mit
> Runterschicken.

Tja, wenn ich mir all die Bemühungen anschaue, die es hier in diesem und 
in anderen Threads so gegeben hat, dann stellt sich mir das 
(generalisiert gesagt) etwa so dar:

1. Einführung von #ifdef's oder zusätzlichen Headern, um mit 1 Treiber 
mehrere STM32Fxxx abdecken zu können. Meine Ansicht: 1 Treiber für exakt 
1 Plattform gefällt offenbar manchen nicht.

2. Meine Quasi-Automatik, den Datenfluß per Timertick des USB wieder in 
Gang zu kriegen, gefällt offenbar auch nicht, deswegen die Bemühungen, 
dieses stattdessen von der 'userland'-Seite aus zu tun.

3. Änderungen bei Features und Status und Verhalten wenn nicht 
angeschlossen, zu denen ich damals keine ausreichende Dolumentation 
hatte, was aber bei mit trotzdem bislang funktioniert hatte. ( Warum 
eigentlich? Sind das Dinge, die bei einer popligen Seriellen per USB gar 
nicht wirklich relevant sind? )

4. Einführung von chipspezifischen Seriennummern.

5. Aufregung über die simple Verzögerungsschleife, obwohl das eigentlich 
recht nebensächlich (und nur GCC-spezifisch) ist.

Naja, und der Rest ist eigentlich gleich geblieben. Nun hab ich ja schon 
vor Zeiten und auch mit anderen µC so meine eigenen Tests gemacht, Daten 
von wenig bis massiv in beiden Richtungen über den USB geschickt und war 
damit eigentlich zufrieden. Eigentlich deshalb, weil ich vom Device aus 
nicht wirklich habe feststellen können, ob auf dem PC nun irgend eine 
Anwendung den seriellen Kanal geöffnet hat oder nicht - da ist eben 
immer das OS mit seinem Treiberstack und der Fileverwaltung dazwischen.

Und nun geht es bei dir nach all diesen gehabten Änderungen noch immer 
nicht - und noch immer weißt du nicht, woran es denn tatsächlich liegt.

Und ebenso noch immer kann jeder andere hier nur spekulieren über das, 
was ihm dazu so einfällt:
- Hardwarefehler
- Firmwarefehler durch Verwendung von irgendwas (Cube und Konsorten), 
das umbemerkt an irgend einer Stelle dazwischenfunkt.
- Fehler in deinem Algorithmus, die Befehle auszuwerten oder auf 
unverständliche Befehle zu reagieren
- Probleme mit dem OS auf dem PC
- Irgend etwas Unbedachtes in deiner Anwendung auf dem PC
- Irgend eine Art Synchronisationsproblem zwischen PC und µC
und so weiter.
Das alles hilft hier offenbar auch bloß nicht.
Also nochmal mein Vorschlag: alles, was der µC über den USB empfängt, 
auf einem anderen Kanal (z.B. UART) auszugeben und dort dann mal zu 
schauen, was da so kommt.

W.S.

von Thomas Z. (usbman)


Lesenswert?

@Alex
dass du eine geänderte inf umter W7 braucht liegt ganz einfach daran 
dass das Device nun ein Compound Device ist (wg IAD) der Treiber wird 
nun nicht mehr auf das Device installiert sondern auf das Interface 
(MI_00). Änderungen in der Funktionalität gibts noch keine. Es ist also 
sehr unwahrscheinlich dass dies bei deinen Übertragungsproblemen hilft.

@W.S.
mir ist klar dass dir die includes bez der spec nicht gefallen. Die 
machen aber letztendlich auch nichts anderes als defines im Quelltext. 
Es ist bei mir halt so dass diese Header files zentral in einem Ordner 
\usb liegen. Ich habe diese Dinger über die Jahre gepflegt und 
erweitert, weshalb ich die immer benutze. Es gibt aber ansonsten 
keinerlei Unterschied.

Die Feature Geschichte hab ich korrigiert weil deine Version einfach 
nicht funktionierte (TimeOut beim Request). Ursache war der Stall(1) an 
diversen Stellen. GET_LINE_CODING funktioniert übrigens auch nicht, da 
du in OnEpCtrlIn() das an der falschen Stelle auswertest.
Die Feature Geschichte geht übrigens auch beim 3fach VCP von Niklas 
nicht er antwortet aber korrekt mit einem STALL Handshake. Das sind aber 
formale USB Geschichten. Der VCP funktioniert trotzdem.

Die einzige Sache die ich bis jetzt wirklich neu gemacht habe sind die 
beiden CopyFunktionen von und USB Mem für EP0. Deshalb auch die 
Testanfrage für andere MCUs.

Eine Sache noch:
Meiner Meinung nach ist die Initialisierung der EpTable[0].TxCount mit 0 
falsch. (Ergibt nur einen 2 Byte Buffer)

von Alex (Gast)


Lesenswert?

> Also nochmal mein Vorschlag: alles, was der µC über den USB empfängt,
> auf einem anderen Kanal (z.B. UART) auszugeben und dort dann mal zu
> schauen, was da so kommt.

Das hatte ich ja schon mit dem Hello-World / Echo - Beispiel von S.F, 
dort war der Fehler reproduzierbar.


> - Hardwarefehler
Mit Sicherheit hat es was mit bestimmten Chip-Exemplaren zu tun. Der 
Fehler tritt bei manchen µCs auf, egal auf welche PCB sie gelötet sind.

> - Fehler in deinem Algorithmus, die Befehle auszuwerten oder auf
> unverständliche Befehle zu reagieren
Ist durch den Echo-test ausgeschlossen

> - Probleme mit dem OS auf dem PC
Wurde bereits ausgeschlossen. Tritt auf verschiedenen PCs und OS auf 
(W7, W10, Linux)

> - Irgend etwas Unbedachtes in deiner Anwendung auf dem PC
Wurde ausgeschlossen. Tritt auch in Terminalprogrammen auf.

> - Irgend eine Art Synchronisationsproblem zwischen PC und µC
> und so weiter.
?

> - Firmwarefehler durch Verwendung von irgendwas (Cube und Konsorten),
> das umbemerkt an irgend einer Stelle dazwischenfunkt.
Gut möglich, aber wenn ich den Codegenerator nicht anwerfe, sollte doch 
nur der Code aus meinen Files verarbeitet werden, oder?


Folgende beiden Fragen stell ich mir aktuell:
Nachdem ich ja mit wireshark schon rausgefunden habe, dass es immer dann 
auftritt, wenn auf ein Bulk_out -Paket keine Antwort von STM kommt:

a) Werden diese Antwortpaket vom STM in Hardware erzeugt, oder macht das 
die usb.c?

b)
Thomas schrieb am 22.2.:
> Dann gibt es einen Bug beim Get/SetFeature bzw GetStatus liefert nicht
> das erwartete Ergebnis. (STALL oder 0).
Hier wurde ja kein relevanter Bug gefunden, oder?

Alex

von Stefan F. (Gast)


Lesenswert?

Alex, hast du mal den originalen Code von 2015 ausprobiert? Ich denke 
das wäre ein einfacher Schritt und damit würdest W.S. auch wieder 
einfangen, so dass er möglicherweise mehr Lust hat, dir zu helfen, 
anstatt die Anderungen zu kritisieren.

Siehe Beitrag "Re: STM32 USB Übertragungsproblem mit Code von S.F.", da 
habe ich seine originale Variante als Cube IDE Projekt angehängt.

von W.S. (Gast)


Lesenswert?

Alex schrieb:
> Folgende beiden Fragen stell ich mir aktuell

Also, wenn ich mich recht erinnere, dann wird bei meinem Original beim 
EpBulkOut solange der Puffer nicht geleert, bis dessen Inhalt in den 
Ringpuffer hineinpaßt. Was soll der Treiber auch anderes machen? Egal 
was man sich ausdenkt, es kommt immer die Situation, wo der Host einen 
mit Daten vollpflastert, die dann eben warten müssen, bis sie von der 
Anwendungsschicht der Firmware abgeholt werden (und wann das sein wird, 
kann der Treiber nicht wissen).

Das ist sozusagen das Gegenstück zu der Situation beim Bulk-In, wo man 
selber zusehen muß, daß man bei anstehenden Daten im Ringpuffer den 
EpBulkIn befüllen und damit den ganzen Transfer in Gang setzen muß.
Nun weiß ich nicht, ob es zum Leeren des EpBulkIn-Puffers an irgend 
einer Stelle eine Art Timeout gibt, so wie das beim Hängenlassen des 
Timerticks passiert.

Mal ne Frage an dich: Ändert sich das Verhalten deiner Firmware, wenn du 
testeshalber den Ringpuffer für die Richtung PC-->µC mal riesengroß 
machst? Mir kommt da nämlich der Verdacht, daß es irgend einen 
zeitlichen Stau geben mag, der dazu führt, daß für eine zu große 
Zeitspanne die vom PC gesendeten Daten nicht abgeholt werden und dann 
irgend ein Timeout zuschlägt, oder daß bei dem Herumschalten am 
Interruptcontroller irgend etwas verloren geht. Ja, das sind auch nur 
weitere Vermutungen, aber was soll man machen?

W.S.

von W.S. (Gast)


Lesenswert?

Nachtrag: ich seh grad, daß ich oben eigentlich EpBulkOut gemeint habe, 
also die Situation, wo der Puffer vom PC gefüllt wurde und man keinen 
Platz hat, die Daten dort raus und woanders rein schaufeln zu können.

W.S.

von J. -. (Gast)


Lesenswert?

Auf einem STM32F405 läuft es bei mir nicht. Prinzipiell habe ich die 
Clocks genauso initialisiert wie bei den Codevarianten vom MCD-Team, und 
da läuft CDC/VCP auf dem F4.
Muß noch etwas drüber grübeln, und kann meine geliebten #ifdefs leider 
noch nicht reinpfriemeln :(
heulend und schluchzend

von Stefan F. (Gast)


Lesenswert?

Jürgen S. schrieb:
> Auf einem STM32F405 läuft es bei mir nicht.

Der STM32F4 hat ein andere USB Peripherie, darauf wird der hier 
diskutierte Code niemals laufen können.

Siehe die Vergleichstabelle in 
https://www.st.com/resource/en/application_note/dm00296349-usb-hardware-and-pcb-guidelines-using-stm32-mcus-stmicroelectronics.pdf 
Seite 3.

Der Code ist nur für die Variante "A" geeignet.

von J. -. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Der STM32F4 hat ein andere USB Peripherie, darauf wird der hier
> diskutierte Code niemals laufen können.
Ja, aber ... dann muß ich ja zwei verschiedene USB-Treiber für zwei 
verschiedene Chips nehmen. Das wäre schrecklich :)
Muß mal den Code noch genauer anschauen, wo Registerzugriffe 
stattfinden, wie und welche. Der Code vom MCD-Team war bei mir schon 
ge#ifdefd und lief sowohl für den F103 und den F407 (wenn ich mich recht 
entsinne).

Edit: Danke für die Beschreibung. Schmöker ich mal durch.

von Alex (Gast)


Lesenswert?

@ W.S.
>Mal ne Frage an dich: Ändert sich das Verhalten deiner Firmware, wenn du
>testeshalber den Ringpuffer für die Richtung PC-->µC mal riesengroß
>machst?

Klingt grundsätzlich plausibel, aber es tritt der Fehler ja manchmal 
schon auf, wenn ich nur 'stop<crlf>' sende. Also nur 6 Zeichen (in einem 
einzigen BulkOut). Die Buffer sind alle deutlich größer.

Trotzdem werd ich morgen VM kurz testen, ob die Buffergrößen einen 
Einfluss haben...

Alex

von Alex (Gast)


Angehängte Dateien:

Lesenswert?

@ Stefan:
den Originalen Code von W.S. 2015 hab ich nicht probiert, da ich ja 
UMEM_SHIFT 0 habe und die Unterscheidung da ja noch nicht drin ist.
Und das selbst umzustricken ist sicher keine gute Idee...

Test zu den Buffergrößen:

Die Buffergröße hat keinen merklichen Einfluss.
Der Echo Test bleibt mal nach 10 chars stecken, mal nach 30.
Rx Buffer von 128 auf 512 erhöht -> keine Änderung.

Anbei mein main.c. von dem Test

von Alex (Gast)


Lesenswert?

Allerdings scheint es so zu sein, dass das Verhalten durch das Senden 
von einem langen String auf einmal sehr zuverlässig reproduzeirbar ist.
Und zwar unabhängig von der Buffergröße.
Schicke ich
'123456789012345678901234567890<crlf>' steht der bulkOut sofort.
'1234567890<crlf>' verträgt er mit kurzen Pausen länger.

von Alex (Gast)


Lesenswert?

Um auszuschließen, dass es durch eine der Änderungen von euch ohnehin 
behoben wurde, hab ich eben den Echo Test noch mit dem neuen Code von 
Thomas probiert. Zeigt grundsätzlich selbes Verhalten.

Ich hab das selbe .bin-file jetzt auf 2 der 'schlechten' µCs 
aufgespielt.
Der eine steigt bei 10 Zeichen reproduzierbar aus, der andere schafft 
jedesmal 40.

von Thomas Z. (usbman)


Lesenswert?

@Alex:
es könnte durchaus sein dass was mit dem UMEM Shift nicht so 
funktioniert wie es sollte. Ich hab ja alle meine Tests mit den Bluepill 
Boards gemacht. Um ehrlich zu sein habe ich den Fall mit UMEMSHIFT =0 
noch nicht näher betrachtet. Ich muss mir das mal genauer anschauen und 
mit einem Datenblatt vergleichen.

Die ganzen bisherigen Änderungen meinerseits beziehen sich im 
Wesentlichen auf die Enum und Kompatibilität zur Spec. Der einzige 
offene Punkt auf meiner Liste ist nur noch GetLineCoding was sich aber 
nicht auf die Buffer auswirkt.

von Alex (Gast)


Lesenswert?

So wies scheint ist das Risiko, dass der BulkOut steckenbleibt größer, 
je mehr Zeichen übertragen werden.
Wo im Code muss ich mich hinsetzen (breakpoint), um den Fall abzufangen, 
wo das passiert?

von Thomas Z. (usbman)


Lesenswert?

Ich denke dass irgendwas mit der EP_Table nicht stimmt. Halte die 
Funktion einfach mal in der Main an nachdem die ENum abgeschlossen ist 
und gib die Ep_Table aus. Wenn ich richtig liege stimmt dort was nicht 
mit den Einträgen.
Es ist übrigens egal ob du meine Version oder die Version von Stefan 
benutzt.
Du solltest das nur die Version angeben, da meine EP_Table etwas anders 
aussieht. (wg dem bidirktionalen EP).
Mich würde der Inhalt der TableStruct interessieren. (mindestens 64 
Bytes)

Zusatzlich solltest du sicherstellen dass die APB Freq. > 10MHz ist.

Siehe Errata:

Possible packet memory overrun/underrun at low APB 
frequencyDescriptionSome data sheet and/or reference manual revisions 
may omit the information that 10 MHz minimum APB clockfrequency is 
required to avoid USB data overrun/underrun issues.

: Bearbeitet durch User
von Thomas Z. (usbman)


Lesenswert?

Thomas Z. schrieb:
> Zusatzlich solltest du sicherstellen dass die APB Freq. > 10MHz ist.
>
> Siehe Errata:

wenn ich mir das so recht überlege passt das sehr gut zu deinem 
"Manchmal" Problem.

von Alex (Gast)


Angehängte Dateien:

Lesenswert?

Anbei ein screenshot von der EpTable,
die Basisadresse ist ja 0x40006000,
EpTableOffset 0x190

Die Clock sollte 48Mhz sein, der µC läuft auf HSI48 (SYSCLK), und HPRE 
und PPRE sind jeweils 0.

von Alex (Gast)


Lesenswert?

oops, ist 3mal das gleiche

von Alex (Gast)


Lesenswert?

Ich probier mal, die ABP clk zu halbieren, die ist laut Datenblatt auf 
48MHz maximal spezifiziert.

von Alex (Gast)


Lesenswert?

Hab den HPRE auf 2 gesetzt, SYSCLK damit auf 24MHz -> keine Änderung.

Der Screenshot der EpTable war aber im Debug-Modus gemacht, mit dem 
.bin-file konnte ich den Effekt wieder nicht reproduzieren.

von temp (Gast)


Lesenswert?

Also Alex, ich habe deine main.c und den Stand von Thomas:
Beitrag "Re: STM32 USB Übertragungsproblem mit Code von S.F."
mal zusammengebaut und auf meinem Nucleo32 mit STM32F042K6 probiert. 
Außer dass meine Finger schon blutig sind vom Tippen im hterm kann ich 
keine Auffälligkeiten feststellen.
Allerdings sehe ich folgendes:
Ich toggle im 1ms Systick einen PIN und messe bei meinem Board 505,7Hz. 
Mit anderen Worten die CSR arbeitet nicht. Wir haben dich von Anfang an 
auf den Taktpott gesetzt, ohne Reaktion. Wenn ich die Stelle mit meinen 
Code ersetze, bin ich bei 499,8Hz->CRS geht. Ich erwarte jetzt von dir, 
dass du mal deine Messwerte des Takts nennst, sonst quatschen wir bis 
Weihnachten über Endpunkte und Fehler im Code die keine sind.
1
void SystemInit(void)
2
{
3
  // Enable the Internal High Speed oscillator (HSI48)
4
       SET_BIT(RCC->CR2, RCC_CR2_HSI48ON);
5
       while (!READ_BIT(RCC->CR2, RCC_CR2_HSI48RDY));
6
7
   // switch SYSCLK to HSI48
8
       MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_HSI48);
9
       while (!READ_BIT(RCC->CFGR, RCC_CFGR_SWS_HSI48));
10
11
     //  Configure the USB clock source
12
       MODIFY_REG(RCC->CFGR3, RCC_CFGR3_USBSW, RCC_CFGR3_USBSW_HSI48);
13
14
   SystemCoreClock = 48000000;
15
16
  // Initialize system timer
17
    SysTick_Config(SystemCoreClock/1000);
18
19
  //[ALEX]
20
    SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN);
21
  while (!READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN));
22
23
  //[ALEX]
24
  SET_BIT(RCC->APB1ENR, RCC_APB1ENR_PWREN);
25
  while (!READ_BIT(RCC->APB1ENR, RCC_APB1ENR_PWREN));
26
27
  //[ALEX] remap pins for USB
28
  SYSCFG->CFGR1 |= (SYSCFG_CFGR1_PA11_PA12_RMP);
29
30
  // Setup Clock Recovery System CRS to sync with USB SOF
31
       // enable CRS
32
       SET_BIT(RCC->APB1ENR, RCC_APB1ENR_CRSEN);
33
       while (!READ_BIT(RCC->APB1ENR, RCC_APB1ENR_CRSEN));
34
//#define CRS_ORG
35
#ifdef CRS_ORG
36
       // reset CRS
37
       RCC->APB1RSTR |= (RCC_APB1RSTR_CRSRST);
38
       RCC->APB1RSTR &= ~(RCC_APB1RSTR_CRSRST);
39
40
       CRS->CFGR = CRS_CFGR_SYNCDIV_0 |       // prescaler: no divider
41
          CRS_CFGR_SYNCSRC_1 |      // source: USB SOF
42
         CRS_CFGR_SYNCPOL   |      // polarity: falling
43
         (47999U << CRS_CFGR_RELOAD_Pos) | // reload value
44
         (34 << CRS_CFGR_FELIM_Pos);   // error limit value
45
          // reload value =  f_{target} / f_{sync} - 1
46
          // reload value =  48e6/1e3 - 1 = 47999
47
          // error limit value: from cubeMx code generator
48
49
       // Adjust HSI48 oscillator smooth trimming
50
       MODIFY_REG(CRS->CR, CRS_CR_TRIM, (32 << CRS_CR_TRIM_Pos));
51
          // trim value: from cubeMx code genererator
52
53
       // START AUTOMATIC SYNCHRONIZATION
54
       SET_BIT(CRS->CR, CRS_CR_AUTOTRIMEN | CRS_CR_CEN);        // enable automatic trimming & frequency error counter
55
#else
56
  // CRS einschalten
57
  RCC->APB1ENR|=RCC_APB1ENR_CRSEN;
58
  CRS->CR|=CRS_CR_AUTOTRIMEN | CRS_CR_CEN;
59
#endif
60
}

von temp (Gast)


Lesenswert?

Nachtrag: Ich habe bei mir die Werte in CSR->CFGR so gelassen wie sie 
beim Reset sind. Die passen. Dein Fehler ist das CRS_CFGR_SYNCDIV_0. Das 
bedeutet das 0. Bit und somit Division durch 2. Damit kann das nicht 
gehen.
1
#define  CRS_CFGR_SYNCDIV                    ((uint32_t)0x07000000U) /* SYNC divider                       */
2
#define  CRS_CFGR_SYNCDIV_0                  ((uint32_t)0x01000000U) /* Bit 0                              */
3
#define  CRS_CFGR_SYNCDIV_1                  ((uint32_t)0x02000000U) /* Bit 1                              */
4
#define  CRS_CFGR_SYNCDIV_2                  ((uint32_t)0x04000000U) /* Bit 2                              */
Oder du hast andere Header.

von Stefan F. (Gast)


Lesenswert?

Thomas Z. schrieb:
> es könnte durchaus sein dass was mit dem UMEM Shift nicht so
> funktioniert wie es sollte. Ich hab ja alle meine Tests mit den Bluepill
> Boards gemacht.

Ich habe allerdings mit dem STM32F303 und STM32L073 getestet. Die würden 
gar nicht funktionieren, wenn dieser Teil fehlerhaft wäre.

von Stefan F. (Gast)


Lesenswert?

Alex schrieb:
> Wo im Code muss ich mich hinsetzen (breakpoint), um den Fall abzufangen,
> wo das passiert?

Breakpoints sind ungünstig. Sobald das Programm stoppt, fällt die USB 
Verbindung aus.

Wenn du debuggen willst, dann mit Hilfe der eingebauten Text-Ausgaben 
auf SWO. Eventuell wirst du weitere Meldungen hinzufügen, um das problem 
einzukreisen.

von Alex (Gast)


Lesenswert?

Du hast recht, sas mit dem CRS schaut definitiv nach einem Fehler aus.
Ich hab zwar andere Header, aber es ist auch bei mir eine Division /2.
Diese Einstellungen hab ich aus dem Codegenerator vom Cube, bevor ich 
auf W.S.-Usb umgestellt hab, nicht auszuschließen, dass da beim 
'entfernen' der HAL Mist passiert ist.

Den Takt direkt hab ich (wie ich schon weiter oben mal geschrieben hab) 
nie exakt geprüft, weil ich kein MCO (main clock out) auf dem Package 
habe.
Allerdings tritt der Kommunikationsfehler auch mit externem TCXO auf, 
daher hatte ich die Taktsache ausgeschlossen (abgesehen von ev. zu 
großem Jitter, den ich wegen fehlendem MCO nicht prüfen kann).

Was ich nicht kapier ist, wieso das dann bei 20 Modulen funktioniert.
Und es funktioniert wochenlang mit 10 Modulen parallel ohne Fehler.
Der CRS müsste ja komplett daneben sein.

Ich fang gleich an zu testen.

von temp (Gast)


Lesenswert?

Alex schrieb:
> Den Takt direkt hab ich (wie ich schon weiter oben mal geschrieben hab)
> nie exakt geprüft, weil ich kein MCO (main clock out) auf dem Package
> habe.

Dann mach's doch wie ich, im Systick-Handler (1ms) einfach einen 
beliebigen Pin toggeln und mit dem Multimeter messen. Ich hab hier ein 
Meterman 37XR.

Alex schrieb:
> Was ich nicht kapier ist, wieso das dann bei 20 Modulen funktioniert.
> Und es funktioniert wochenlang mit 10 Modulen parallel ohne Fehler.
> Der CRS müsste ja komplett daneben sein.

Kann sein, dass die falschen CRS Einstellungen den Takt noch mehr 
verbiegen als wenn es ausgeschaltet ist. Und dass bei 20 Modulen die 
RC-Oszillatoren nicht gleich sind ist auch klar. Eventuell sind ein paar 
davon auf Kante. Die gemessenen 505,x Hz bei meinem Modul sind ja schon 
mehr als 1%. Keine Ahnung ab wann das kritisch wird. Allerdings, wenn 
man das CRS einschaltet, dann sollte es schon richtig funktionieren.
Im Netz findet man:

The USB 2.0 Specification defines the tolerances for data rates on the 
USB bus, including all drift sources.  For low-speed communications, the 
data rate is specified to be 1.5 Mbps +/- 1.5%.  For full-speed 
communications, the data rate is specified to be 12 Mbps +/- 0.25%.

If an external clock source is used as the USB clock, it must meet the 
above specifications for reliable USB communications.  The internal 
oscillator on the device family can be used for either low or full-speed 
USB.  If the internal oscillator is used for full-speed USB 
communications, 'clock recovery' must be enabled to ensure the data rate 
tolerance specification of +/- 0.25%.

Tu uns doch bitte mal den Gefallen und miss. Es würde uns alle 
interessieren ob, und wenn ja in wie weit die Module streuen.

von Alex (Gast)


Lesenswert?

Hab bei einem 'schlechten' Modul mit Echo-Test den Divider korrigiert, 
und es läuft definitiv besser. Konnte noch keinen Fehlerfall 
verursachen, auch nicht durch exterem lange Zeichenketten.
-> Diese Fehlerursache ist damit verifiziert.

Ich hab ja einen PWM-Pin an den Modulen, da hab ich die Frequenzen mal 
von mehreren Modulen (mit scope) verglichen. Jitter war deutlich zu 
erkennen, aber keine Frequenzunterschiede zwischen den Modulen.
Ich hab daraus geschlossen, dass der CRS gundsätzlich funktioniert.

Wenn aber der CRS so total falsch konfiguriert war, dürfte das ja 
garnicht sein.
Morgen Vormittag wird gemessen (das ist ein Versprechen :-)

von Alex (Gast)


Lesenswert?

Nur um Verwirrung wegen unklarer Formulierung auszuschließen:  die 
Messung mit dem Scope hatte ich vor einiger Zeit gemacht, hatte weiter 
oben darüber berichtet.

von Alex (Gast)


Lesenswert?

Messung an den PWM-Ausgängen:
Sollfrequenz = 48MHz/78 = 615,38kHz

bei 2 Modulen (davon ein 'schlechtes') am Scope die Frequenzen gemessen:
616,07 und 616,14 kHz (schwankt jeweils um +- 0,1 kHz).

die selben Module mit korrigierter CRS-Einstellung:
beide ca. 615,5kHz mit +- 0,4 kHz (schwankt deutlich mehr !?).


Ich bin bei meiner letzen Messung (post vom 24.2.) von der Annahme 
ausgegangen, dass wenn der CRS nicht funktioniert, die 
Frequenzabweichungen zwischen den Modulen deutlich zu sehen sein 
sollten. Dementsprechend hatte ich die Frequenzen der Module miteinander 
verglichen, den Absolutwerten aber keine übermäßige Bedeutung 
beigemessen. Das war offenbar ein entscheidender Fehler.
Dennoch bin ich extrem erstaunt, wie 'gut' die nicht nachgetunten 
RC-Oszillatoren sind.

von temp (Gast)


Lesenswert?

Alex schrieb:
> Messung an den PWM-Ausgängen:
> Sollfrequenz = 48MHz/78 = 615,38kHz
>
> bei 2 Modulen (davon ein 'schlechtes') am Scope die Frequenzen gemessen:
> 616,07 und 616,14 kHz (schwankt jeweils um +- 0,1 kHz).
>
> die selben Module mit korrigierter CRS-Einstellung:
> beide ca. 615,5kHz mit +- 0,4 kHz (schwankt deutlich mehr !?).

Das erscheint mir trotzdem noch komisch. Bei meinem Teil lag die 
Abweichung bei einem Prozent und es ging noch. Ob ein Oszilloskope da 
zum Messen taugt wage ich fast zu bezweifeln. Aber egal, wenn es 
geholfen hat ist's gut.

von Stefan F. (Gast)


Lesenswert?

Die Frage ist, was wir jetzt daraus lernen. Taugt das CRS nicht?

von Alex (Gast)


Lesenswert?

Das erscheint nicht nur dir komisch.

Mich ärgert vor allem, dass ich mich offensichtlich ziemlich massiv 
selbst ausgetrickst habe, bei der Fehlersuche.
Klassisches Layer-8-Problem ...

Und was es mit dem externen 24MHz TCXO auf sich hat, den ich ja 
testhalber auf eines der Module 'draufgepopelt' habe, ist mir aktuell 
auch noch nicht klar. Da muss ich ja auch irgendeinen Bock geschossen 
haben...

Jetzt hol ich mir einen Kaffee und Schokolade....

von Johannes S. (Gast)


Lesenswert?

Beim H743 gibt es auch das CRS, dummerweise funktioniert das in einigen 
Revisionen nicht, ist im Errata festgehalten. Aber so einen Boliden wird 
man sowieso mit Quarz(oszi) betreiben.

von temp (Gast)


Angehängte Dateien:

Lesenswert?

Stefan ⛄ F. schrieb:
> Die Frage ist, was wir jetzt daraus lernen. Taugt das CRS nicht?

Doch, aber halt nicht, wenn es so wie bei Alex falsch konfiguriert 
wurde.

Deinem Jittern bei deinen Messungen traue ich immer noch nicht über den 
Weg.
Hier mal 2 Oszibilder vom Toggeln im (jetzt 100µS) SystickHandler.
Das wackelt und jittert auch nichts.

von Stefan F. (Gast)


Lesenswert?

Könnte eventuell eine mangelhafte (noch nicht ganz kaputte) USB 
Verbindung zum Versagen des CRS führen?

Schlechte USB Verbindung müsste man vermutlich an unregelmäßigen SOF 
Paketen erkennen können, wenn man da mal einen I/O Pin toggelt.

von temp (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Könnte eventuell eine mangelhafte (noch nicht ganz kaputte) USB
> Verbindung zum versagen des CRS führen?

Nochmal zum Mitschreiben, der CRS Teil ist im Code von Alex falsch 
konfiguriert gewesen, und, kaum macht man's richtig -> schon geht's.

von Stefan F. (Gast)


Lesenswert?

temp schrieb:
> Nochmal zum Mitschreiben, der CRS Teil ist im Code von Alex falsch
> konfiguriert gewesen, und, kaum macht man's richtig -> schon geht's.

Aber du hast gerade erst zitiert:

> bei 2 Modulen (davon ein 'schlechtes') am Scope die Frequenzen gemessen:
> 616,07 und 616,14 kHz (schwankt jeweils um +- 0,1 kHz).

> die selben Module mit korrigierter CRS-Einstellung:
> beide ca. 615,5kHz mit +- 0,4 kHz (schwankt deutlich mehr !?).

Das war nach seiner letzten Korrektur - habe ich zumindest so 
verstanden.

von temp (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Das war nach seiner letzten Korrektur - habe ich zumindest so
> verstanden.

Was er da misst ist das eine, mit CRS auf alle Fälle die richtige 
Frequenz von 615.5kHz bei 615.38kHz Soll, was beweist dass sie 
funktioniert.
Und damit geht es ja. Er muss für sich nur klären, ob seine Messungen 
was taugen.
Oder seine Chips entsorgen. Eventuell werden die von den Chinesen auch 
schon gefälscht oder der Ausschuss verkauft.

von Alex (Gast)


Lesenswert?

Ich teste gerade die Änderungen auf mehreren Modulen,
dabei ist mit eine Kleinigkeit in der initSerial aufgefallen:
1
#define U_ID       (*(volatile uint8_t *)( 0x1FFFF7E8UL)) //for F103 only
2
3
...
4
...
5
6
     while(i > -1)    //r�ckw�rts lesen
7
     {
8
        b   = U_ID + i;
9
        *s  = toAscii(b);      s += 2;
10
        *s  = toAscii(b >> 4); s += 2;
11
        i--;
12
     }

die U_ID müsste erst nach der Summe in der Schleife dereferenziert 
werden.

Sonst haben alle die gleiche, komische Seriennummer ...


Hab grad einen ziemlichen Sauhaufen auf meinem Rechner mit 
Geister-Treibern den ich versuche aufzuräumen. Manche der Module melden 
sich jetzt zwar als COMxx an, ich kann sie aber nicht öffnen. Auch das 
Deinstallieren der Treiber hilft da nicht. So kann ich die Änderungen 
nicht mal wirklich durchtesten. Hat da jemand eine Idee, wie man das 
unter W7 aufräumt?

von Stefan F. (Gast)


Lesenswert?

Alex schrieb:
> Hat da jemand eine Idee, wie man das
> unter W7 aufräumt?

Versuche mal das Batch Script, nachdem du alle verzichtbaren COM-Ports 
aus der Systemsteuerung entfernt hast (auch die verborgenen!):
1
@echo off
2
3
for /L %%A in (1,1,300) do (
4
  echo Deleting OEM%%A.INF
5
  pnputil /d OEM%%A.INF
6
)

Es entfernt alle Treiber, die gerade nicht benutzt werden, und erzwingt 
somit bei Bedarf eine Neuinstallation dieser.

von Thomas Z. (usbman)


Lesenswert?

Alex schrieb:
> die U_ID müsste erst nach der Summe in der Schleife dereferenziert
> werden.

Ups du hast Recht, das ist Käse....

Wegen der Tests:
Es ist vermutlich sinnvoll die SerienNummer ganz auszuschalten, solange 
du am testen bist. Das verhindert dass immer neue Vom Ports angelegt 
werden.

Zum Aufräumen gibt es mehrere Möglichkeiten:
im Gerätemanager ausgeblendet Geräte anzeigen und dann löschen. Das geht 
auch unter W7.
Oder im system32\ Driver die entsprechenden PNF Dateien löschen. Oder in 
der Registry unter HKLM\system\CurrentControlset\Enum\Usb\ die 
entsprechenden Einträge löschen. Dieser Registry Zweig sollte auch unter 
W7 vorhanden sein.

von J. -. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Der Code ist nur für die Variante "A" geeignet.
Yep, verstanden. Ich habe mir auch noch das Referenzhandbuch zum F4 und 
USB_OTG_FS angeschaut, das sind alleine 140 Seiten. Das ist zuviel 
jammer
Immerhin kommt ihr dem eigentlichen Problem von Alex immer mehr auf die 
Schliche, da lernt man auch was dabei. Von CRS hab ich noch nie was 
gehört :)

von Stefan F. (Gast)


Lesenswert?

Jürgen S. schrieb:
> das sind alleine 140 Seiten. Das ist zuviel

Yepp.

Ich hatte auch kurz erwägt, mit einen F4 zu kaufen nur um den Code dafür 
anzupassen. Aber als ich dann die Doku dazu sah, fiel mir wieder ein, 
dass selbst ein L0 schon sehr viel mehr kann, als ich jemals brauchte. 
Damit hat sich das für mich wieder erledigt.

von Alex (Gast)


Lesenswert?

Die Ausgeblendeten COMs hatte ich entfernt, aber erst das Entfernen der 
'USB-Verbundgeräte' hats gelöst. :-)

Noch eine Beobachtung:
Mir ist auch aufgefallen, dass die neue Version von Thomas (die mit dem 
MI_00 im descriptor) weniger 'gutmütig' bei Wackelkontakten ist.
Beispiel:
COM ist im Terminal offen, und die Verbindung wird mechanisch kurz 
unterbrochen (z.B. Wackelkontakt).
In der vorigen Version von S.F. hab ich den COM geschlossen und wieder 
geöffnet, und es ging weiter.
In der neuen muss der Port geschlossen werden, dann das Modul aus- und 
wieder Eingesteckt werden, erst dann kann ich den Port wieder öffnen.
(So war es aber auch mit der Version vor diesem Thread).
Hat das was mit der Vorbereitung zur multi-VCP zu tun?

von Thomas Z. (usbman)


Lesenswert?

Alex schrieb:
> Hat das was mit der Vorbereitung zur multi-VCP zu tun?

Der IAD ist vermutlich nicht die Ursache. Allerdings habe ich die 
Initialisierung der Bulk EPs von InitEndpoints() nach USB_ConfigDevice() 
verschoben. Die Bulk Endpoints dürfen ja erst arbeiten wenn das Device 
conigured ist. Zusätzlich habe ich bei USB_SET_INTERFACE die ToggleBits 
zurückgesetzt. Das könnte das Problem erklären. Entferne Mal die If A 
Abfragen an der Stelle.

von Stefan F. (Gast)


Lesenswert?

Ich glaube auch, dass Thomas Änderungen diesbezüglich relevant sind. Nur 
welche genau, das vermag ich nicht zu erkennen. Auch mir ist 
aufgefallen, dass das Re-connecten nach einer kurzen Unterbrechung nun 
viel zuverlässiger funktioniert.

von Thomas Z. (usbman)


Lesenswert?

Was mir dazu noch einfällt
Vielleicht werden in ClassStart nicht alle Variablen zurückgesetzt, das 
ist noch original. Beim Öffnen des Comports sollte ein USB_SET_INTERFACE 
Request kommen. Dort müsste eigendlich auch eine Abfrage der Interface 
Nummer rein. Darauf hab ich bisher verzichtet.

von Alex (Gast)


Lesenswert?

Wieder mal ein Testreport zu meinen Übertragungsproblemen.
Hab aktuell 10 Module mit der korrigierten Software, die werden das 
Wochenende über durchlaufen.

Das Korrigieren des CRS hat die Stabilität bei langen Strings erhöht, 
vollständig gelöst ist die Sache damit aber nicht.
Ich hab derzeit 3 Patienten isoliert, die auch mit der korrekten 
CRS-Einstellung Probleme machen. Auch bei sehr kurzen Strings (mein 
'stop<crlf>'-Befehl).

Bei allen ist aber die CLK gut.
Hab mit einem Counter mal die Taktraten an meinem PWM-Ausgang gemessen, 
die passen alle. Da muss noch was im Busch sein...

Nachtrag zu den Frequenzmessungen: Durch den CRS zappelt der Takt (Wert 
am Counter) deutlich mehr rum als wenn der CRS abgeschaltet ist.
Je kürzer die Gatezeit umso deutlicher wird das. Wahrscheinlich wär es 
weg, sobald die Gatezeit mit dem SOF synchronisiert würde, das muss ja 
vom nachtunen im SOF-Takt stammen.
Vielleicht könnte man das Nachstellen noch sanfter machen, aber ich 
glaub mich zu erinnern dass die Schrittweite relativ grob ist und man 
das daher nicht wirklich 'smooth' hinbekommt.

von temp (Gast)


Lesenswert?

Also, wenn du den Takt im Qszi jittern siehst, ist wohl noch was mit 
deiner Hardware im Argen. Besorg dir mal ein Nucleo32 mit dem F042 damit 
du wenigstens mal zum Vergleich etwas hast was richtig geht. Oder zeig 
uns mal ein Bild von Schaltung und Layout. Wenn du hier von PWM 
sprichst, uns aber einen andern Code vor die Füße wirfst, brauchst du 
dich nicht wundern wenn dich bald keiner mehr ernst nimmt. Fehler sucht 
man meiner Meinung nach anders. Wenn hier im Thread nicht noch an einem 
guten Code für USB gearbeitet würde wäre ich längst raus.

von Thomas Z. (usbman)


Lesenswert?

Ich habe dieses Wochenende den Code erweitert und einen 2. VCP in die 
Deskriptoren eingehängt. Dazu habe auch einige defines aktiviert und die 
Kopierroutinen für die Bulk EPs so erweitert, dass die Routinen auch mit 
anderen EPs funktionieren.

Das hat soweit funktioniert, ich kann einen zweiten VCP sehen. Leider 
habe ich mir beim Testen das einzige BluePill Board mit WCH Controller 
abgeschossen.

Ich kann also im Moment nur noch mit STM testen.
Der Bug mit der SN ist gefixt.

Vermutlich hab ich nächstes WE was vorzeigbares, dann auch mit Umleitung 
zu den ser. Schnittstellen.

von Alex (Gast)


Angehängte Dateien:

Lesenswert?

@temp
Ich versteh deinen Frust, vor allem das mit der Taktgeschichte ist 
wirklich sehr blöd gelaufen.
Von allen Seiten kamen die Hinweise mit dem Takt und wie wichtig ein 
Quarz ist bei USB.
Ich hab ehrlich nicht gedacht, dass es (noch dazu mit einem falsch 
laufenden) RC-Oszillator überhaupt möglich ist, überhaupt eine 
lauffähige Übertragung hinzubekommen, und diesen Fehler als Ursache 
ausgeschlossen.
Und ich denke, dass ich damit zumindest nicht ganz allein bin hier.

Zudem hab ich ein Modul mit einem TCXO getestet, und die 
Übertagungsprobleme hatte ich damit auch.
Da das Verhalten der 'schlechten' Module nicht immer 100%ig gleich 
reproduzierbar ist, ist ein zuverlässiger Vergleichstest immer 
schwierig.


Die Entscheidung, welche Informationen hier reinsollen und welche nicht, 
ist nicht immer ganz einfach, und führt ja nicht von ungefähr immer 
wieder zu Diskussionen. Dass es da unterschiedliche Auffasungen gibt ist 
völlig logisch.
Ich gehe eigentlich davon aus, dass die CLK-Sache jetzt passt.
(Nur um klarzustellen: meine Jitter-Aussage betraf nicht eine Messung an 
benachbarten CLK-Pulsen sondern eine optische Wahrnehmung bei Messung 
mit verzögerter Zeitbasis bzw. die Schwankung der Frequenzmessung.)

Die Board-Level Hardware würde ich eigentlich ausschließen, aber das war 
beim CRS ja ich so.... Daher Schaltungsteil und Layout anbei.

Folgendes wurde schon alles probiert:
- Abblock-Cs vergrößern
- Die 33pF an den USB Leitungen austauschen (auf 22p) (um falschen Wert 
auszuschließen)
- Die 33pF an den USB Leitungen wegnehmen
- Den Spannungsregler tauschen
- die 10R-Widerstände in den USB-Leitungen prüfen
- auf Lötfehler kontrollieren
- 3V3 prüfen
- mit und ohne Kabel betreiben
- externen TCXO auflöten
- den STM auf ein anderes Board löten (mit und ohne anderer Peripherie)
- den STM auf ein anderes Board löten (von einem 'guten' Modul)

Letzter Stand:
ein 'schlechtes' Modul, CLK wurde überprüft,
echo-Test funktioniert mit 10 Zeichen zuverlässig immer,
mit 11 Zeichen bleibts beim ersten Versuch stehen.
Die Hello Worlds kommen munter weiter.

Auch hier ist es so, dass ein längerer String dazu führt, dass die 
Übertragung zusammenbricht. War bei der CRS-Sache auch so.
Aber der CRS ist ja jetzt korrigiert und vermessen ist dieses Modul 
auch.

von Thomas Z. (usbman)


Lesenswert?

Ich reagiere bei offenen Pins immer allergisch. Zumindest den Osz In 
würde ich versuchsweise auf GND legen, oder die Pins per Programm 
anfassen.

von temp (Gast)


Lesenswert?

1. Wenn aum Ausgang des NCP700 wirklich nur 100nF sind, wundert mich 
hier überhaupt nichts mehr. "Stable with Ceramic Output Capacitors as 
low as 1µF" sagt das Datenblatt. Und dann sollte der auch >=1µF haben 
wenn 3,3V anliegen. Also ich hätte da irgendwas zwischen 2,2 und 10µF 
verwendet. Gerade bei den Spannungswandlern und Kerkos habe ich selbst 
schon genügend Lehrgeld bezahlt.

2. Die Reset Leitung offen als Antenne zu führen ist eventuell auch 
nicht optimal. Das wird zwar hier nicht das Problem sein, aber wer weiss 
das so genau.

von temp (Gast)


Lesenswert?

3. So wie ich das sehe ist im Layout am Ausgang des Sapnnunsreglers 
überhaupt kein C. Du hast zwar in gefühlt 1km Abstand und ein paar Vias 
2 C's an den 3.3V des Controllers, aber der Sapnnungsregler selbt hängt 
so gesehen in der Luft. Das solltest du unbedingt vermeiden, egal ob das 
die Ursache für deine Probleme ist oder nicht.

von Stefan F. (Gast)


Lesenswert?

Wieso kommt der Plan eigentlich erst jetzt und nicht vor 265 Beiträgen?

Und dann ist er auch noch total unspektakulär, nichts was dieses 
Staatsgeheimnis erklären würde.

von Alex (Gast)


Lesenswert?

Thx für comments,
@0 :-)
Solange der Osc-Block abgeschaltet ist, dürfts da nix geben.
@1 die Bestückung ist bei 2x1µ, aber ja, sie sind zu weit weg, vor allem 
da neben dem noise-c noch Platz gewesen wäre. Zumindest einen von denen 
werd ich direkt zum Regler setzen.
(In die Falle mit der Minimum-C. an LDOs bin ich schon öfter getappt.)
@2 der RST hat einen Pullup mit max 55k, dürfte m.E. nach bei dem kurzen 
Stück unkritisch sein.
@3 -> @1, die 3V3 sind sauber, auch bei den 'schlechten' Modulen.

von temp (Gast)


Angehängte Dateien:

Lesenswert?

Alex schrieb:
> @1 die Bestückung ist bei 2x1µ, aber ja, sie sind zu weit weg, vor allem
> da neben dem noise-c noch Platz gewesen wäre. Zumindest einen von denen
> werd ich direkt zum Regler setzen.

2x1µF ist aber auch falsch. Beim Abblocken kann man nicht davon ausgehen 
dass mehr immer nur besser ist. Ein 0,1µF C verhält sich bei hohen 
Frequenzen nun mal anders als ein 1µ oder mehr. Wenn, dann sollte der 
100nF drin bleiben und ein größerer (10µ) parallel. Und der hautnahe zum 
Spannungsregler zusätzlich, aber nicht verschieben.

Wenn du dir mal das Blockschaltbild vom STM32F042 ansiehst, wirst du 
auch sehen, dass die RC-Generatoren von Vdda gespeist werden. Da würde 
ich auch mal L und C überprüfen ob das konform mit der Spezifikation 
ist. Die schreibt insgesamt größere Kapazitäten vor.

von Alex (Gast)


Lesenswert?

> Ein 0,1µF C verhält sich bei hohen
> Frequenzen nun mal anders als ein 1µ oder mehr. Wenn, dann sollte der
> 100nF drin bleiben und ein größerer (10µ) parallel.

Nein, das ist in der Regel keine gute Idee. Die 
Hochfrequenz-Eigenschaften der Cs werden durch die Serieninduktivität 
bestimmt, die in erster Linie von der Bauteilgeometrie (also vom 
Package) abhängt.
Durch Parallelschalten von Cs unterschiedlicher Werte können sich 
Resonanzen ergeben, die in einem schmalen Frequenzbereich die 
Abblock-Wirkung deutlich reduzieren.
Wenn man unterschiedliche Werte parallel schaltet, dann sollte einer 
davon einen höheren ESR haben, um die Sache zu dämpfen.

von Alex (Gast)


Lesenswert?

Hab grad versucht an der VDDA das Rauschen zu messen, bin aber mit den 
Scope nicht weit gekommen. Rauschlevel ist etwa so groß als wenn ich den 
Tastkopf mit dem Gnd-Clip verbinde. Also nicht aussagekräftig und nicht 
größer als 1mVeff.
Konnte auch keine 48-MHz Signalkomponente im Spektrum finden.

Im Datenblatt ist ein 1µ // 10n vorgeschlagen, nachdem aber der HSI48 
nur ca. 330µA braucht und ein recht guter Ferrit davorsitzt, müssten die 
100nF leicht ausreichen.
Die überraschend gute Stabilität des RC-Osc bestätigt das ja auch.

von Alex (Gast)


Lesenswert?

Nur um die Gefühlsmäßige Abschätzung mit den 100n @ VDDA zu untermauern:

Wenn der STM im Mittel 330µA zieht, dann sind das in einer Periode des 
HSI48 knapp 7pC (330µA/48MHz).
Selbst wenn der die 7pC jetzt als Impuls aus dem 100nF rauszieht, wären 
das nur  7pC/100nF = 70µV.
Klar mess ich das nicht mit dem Scope :-)

von W.S. (Gast)


Lesenswert?

Alex schrieb:
> Im Datenblatt ist ein 1µ // 10n vorgeschlagen,

bedenke mal, daß vieles in älteren Dokumentationen noch von der Annahme 
ausgeht, daß Kondensatoren im µF Bereich Elkos sind. Die waren bis vor 
einiger Zeit ja auch die billigsten für größere Kapazitäten. Aber das 
ist vorbei. Der allgegenwärtige keramische 10µ/10V im 0805 ist seit 
Jahren der Universal-Abblocker, wenngleich er neuerdings von 0603 oder 
noch kleiner abgelöst wird. Ich hatte mich zu diesem Thema nämlich mal 
mit unserer Bestückerfirma unterhalten, als ich die letzten Tantal-Elkos 
aus den Produkten entfernt hatte. Kannst dich ja mal bei 
Wittig-Electronic in Brand-Erbisdorf nach den am besten gehenden C's 
erkundigen.

W.S.

von temp (Gast)


Lesenswert?

Alex schrieb:
> Nein, das ist in der Regel keine gute Idee.
komisch nur dass das STM so vorschreibt.

Alex schrieb:
> Die überraschend gute Stabilität des RC-Osc bestätigt das ja auch
Da stehe ich auf der Leitung. Hast du nicht weiter oben geschrieben dass 
deine Messwerte wackeln? Und auch mit CRS darf da nichts wackeln.
Hast du das ganze auch mal an einem anderen USB Port oder hinter einem 
Hub probiert?

Alex schrieb:
> Rauschlevel ist etwa so groß als wenn ich den
> Tastkopf mit dem Gnd-Clip verbinde. Also nicht aussagekräftig und nicht
> größer als 1mVeff.
Es geht auch nicht um das Rauchlevel. Schließlich haben wir hier keine 
statischen Verhältnisse. Der interessante Punkt ist dabei wie das System 
auf dynamische Laständerungen reagiert. Und das kriegt man wohl schlecht 
mit dem Draufgucken auf das Oszi mit. Da wäre es ehr angesagt das 
Speicheroszi vom Controller an den zeitlich relevanten Stellen zu 
triggern und da im zeitlichen Umfeld was festzustellen oder 
auszuschließen.
Fakt ist doch eins, deine Probleme liegen in der Hardware. Immerhin bist 
du der einzige mit solchen Problemen und dann auch noch mit 
unterschiedlichen Ergebnissen bei unterschiedlichen Platinen.

von Alex (Gast)


Lesenswert?

>> Nein, das ist in der Regel keine gute Idee.
>komisch nur dass das STM so vorschreibt.
findet man in vielen Datenblättern, ist aber Mist.
Lässt sich auch in Spice leicht zeigen, dass es Mist ist.

>> Die überraschend gute Stabilität des RC-Osc bestätigt das ja auch
>Da stehe ich auf der Leitung. Hast du nicht weiter oben geschrieben dass
>deine Messwerte wackeln? Und auch mit CRS darf da nichts wackeln.
>Hast du das ganze auch mal an einem anderen USB Port oder hinter einem
>Hub probiert?

Mit CRS muss es wackeln, schließlich schraubt der CRS jede ms mal an 
der Einstellung vom Oszillator rum. Daher wackelt es auch weniger, je 
länger die Gate-Zeit des Counters ist, weil sich die Änderungen dann 
rausmitteln.
Und wie schon öfters geschrieben, gibts das Problem unter W7, W10, Linux 
und auf verschiedenen PCs, mit und ohne Kabel usw.
Noch nicht geschriebem: mit verschiednen aktiven und passiven Hubs 
konnte ich keine Änderung im Verhalten feststellen.


> Es geht auch nicht um das Rauchlevel. Schließlich haben wir hier keine
> statischen Verhältnisse. Der interessante Punkt ist dabei wie das System
> auf dynamische Laständerungen reagiert.
Nachdem am AVDD nur der HSI48 läuft, dürfte es da kaum Lastwechsel 
geben, die mit dem Empfang über USB zu tun haben.
Wenn eine Störung von der 3V3 / 5V - Seite kommt, sollten die Ferrite 
das sehr gut abfangen. Die Messung war, um auszuschließen dass die 100nF 
zu klein sind. Daher hab ich auch speziell nach der 48MHz-Komponente im 
Rauschen gesucht.

> Fakt ist doch eins, deine Probleme liegen in der Hardware. Immerhin bist
> du der einzige mit solchen Problemen und dann auch noch mit
> unterschiedlichen Ergebnissen bei unterschiedlichen Platinen.
Richtig, aber die Probleme hängen mit bestimmten STM-Exemplaren zusammen 
und dem darauf laufenden Code zusammen. Ich hab bei allen Test bisher 
keinen Ansatzpunkt dafür gefunden, dass es an der Beschaltung liegt.
Stichwort: 'schlechten' Chip auf eine andere Platine löten usw...

Mein aktueller Ansatz:
nachdem ich ja mal beobachtet hab, dass es einen Unterschied macht, ob 
ein Programm als Debug oder als Release kompiliert ist, werd ich 
versuchen jeweil 'gutes' und ein 'schlechtes' Minimalbeispiel mit 
reproduzierbarem Ergebnis zu bekommen.

von temp (Gast)


Lesenswert?

Dein Text ist voll von "müsste" und "dürfte" und da du es sowieso besser 
weißt wie es geht nehme ich hier nichts mehr ernst.

Alex schrieb:
> Messung an den PWM-Ausgängen:
> Sollfrequenz = 48MHz/78 = 615,38kHz
>
> bei 2 Modulen (davon ein 'schlechtes') am Scope die Frequenzen gemessen:
> 616,07 und 616,14 kHz (schwankt jeweils um +- 0,1 kHz).
>
> die selben Module mit korrigierter CRS-Einstellung:
> beide ca. 615,5kHz mit +- 0,4 kHz (schwankt deutlich mehr !?).

Alex schrieb:
> Mit CRS muss es wackeln, schließlich schraubt der CRS jede ms mal an
> der Einstellung vom Oszillator rum. Daher wackelt es auch weniger, je
> länger die Gate-Zeit des Counters ist, weil sich die Änderungen dann
> rausmitteln.
Sorry, aber liest du selbe was du schreibst? +-0,4kHz bei 615,5kHz sind 
1,3% Abweichung. Welchen Sinn soll den das CRS haben wenn der Oszillator 
am Ende um 1,3% wackelt. Lies dir den entsprechend Abschnitt im Manual 
durch. Da wird nicht ständig was verändert. Es wird einmal solange 
verändert bis die Differenz in einem gewissen Fenster bleibt und danach 
ist gut. Jedenfalls solange der Oszillator nicht soweit driftet, dass es 
aus dem Fenster läuft. Das passiert aber nicht jede ms und wenn doch 
liegt da aber massiv was daneben. Temperatur und Spannung haben einen 
Einfluss, ohne Frage. Beides sollte aber so stabil sein, dass hier 
nichts wackelt. Noch dazu im ms Takt.
Ich bleibe dabei, besorg dir eine vernünftige Vergleichshardware und 
such dann deine Fehler.

von Alex (Gast)


Lesenswert?

+-0,4 von 615 sind bei mir +-0,06% Abweichung, der Bereich ist dann 
0,12% groß.
Das 'sollte' auch deiner Meinung nach genügen, oder?

von temp (Gast)


Lesenswert?

Alex schrieb:
> +-0,4 von 615 sind bei mir +-0,06% Abweichung, der Bereich ist dann
> 0,12% groß.
> Das 'sollte' auch deiner Meinung nach genügen, oder?

ok, diesmal hast du Recht und ich die Tomaten auf den Augen.

von Alex (Gast)


Lesenswert?

dann geht uns jetzt beiden wieder besser :-)

Spiel grad mit der Compiler-Optimierung rum:
sobald die Optimierung ausgeschaltet ist, läuft die Sache.
Bei -Os (size) gehts mit max. 10 chars,
bei -O3 enumeriert das device nicht korrekt.

von temp (Gast)


Lesenswert?

Alex schrieb:
> Spiel grad mit der Compiler-Optimierung rum:
> sobald die Optimierung ausgeschaltet ist, läuft die Sache.
> Bei -Os (size) gehts mit max. 10 chars,
> bei -O3 enumeriert das device nicht korrekt.

Das nützt nur leider keinem was, solange du nicht deinen Code oder das 
Projekt hier rein stellst. Das was wir bisher haben ist ja was anderes 
mit PWM u.s.w.
Also, ohne dass du da eine 1:1 Kopie rüberwachsen lässt, und wir vom 
selben Code sprechen, kann man dir softwareseitig nicht mehr helfen.

von Alex (Gast)


Angehängte Dateien:

Lesenswert?

War schon in Arbeit.
Ist der Code von S.F. Echo-Test umgemünzt auf die neuen files von 
Thomas.
Der PWM-Teil ist da jetzt wieder auskommentiert (aber noch zu sehen).

von temp (Gast)


Lesenswert?

Wir kennen deine Umgebung nicht und der Startupcode fehlt, ebenso die 
HAL. Also bitte so vervollständigen dass man ein identisches Projekt 
bauen kann.
Ich werde mir jetzt das nicht irgendwo zusammentragen.
Ich arbeite mit der Segger IDE. Also entweder du lieferst alles oder ich 
ändere es für Segger und du installierst die mal zum Vergleich.

von temp (Gast)


Lesenswert?

So hab das probiert mit allen Optimierungsleveln. Keine Auffälligkeiten. 
Das gemessene LED toggeln im Systick schwankt zwischen 499.6 und 
499.7Hz.

von temp (Gast)


Angehängte Dateien:

Lesenswert?

Hast du dir das RefManual mal durchgelesen? Da steht eindeutig: "One 
wait state, if 24 MHz < SYSCLK ≤ 48 MHz"

das FLASH->ACR Register in deinem Code ist aber 0.

Da fehlt:
1
  // Enable Prefetch Buffer and set Flash Latency 
2
  FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;

Ausser dein Gefühl sagt auch hier, scheiß egal was im Manual steht, es 
dürfte auch so gehen.

von Alex (Gast)


Angehängte Dateien:

Lesenswert?

System: CubeIDE 1.4.2

bezgl. Flash-Zugriff: Punkt für dich!!!!
Ist bei der Anpassung vom Echo-Test-Beispiel verlorengegangen.
Habs eben getestet: der Fehler ab 11 Chars bleibt.
Mein Gefühl sagt mir, es ist nicht die Ursache für den Fehler.

von Alex (Gast)


Lesenswert?

Ich bin nicht sicher, ob das eine HAL-File (stm32f0xx_it.c) ausreichend 
ist, eine Referenz auf was anderes hab ich auf die Schnelle nicht 
gesehen.

von temp (Gast)


Angehängte Dateien:

Lesenswert?

Ne, Cube und Hal, damit baue ich mir jetzt kein Projekt zusammen. Soviel 
Zeit habe ich auch nicht. Ich hänge dir aber mal mein Projekt dran. Ist 
für stm32f042f6 gebaut. Wenn du willst kannst du das ja mal bei dir 
probieren.

von Thomas Z. (usbman)


Lesenswert?

da ich im Moment einiges umbaue (mit wechselndem Erfolg) macht es nicht 
so viel Sinn eine neue Variante einzustellen.

Mir ist aber bei den EP Tables noch ein potentielles Problem aufgefallen 
welches ich noch nicht zuordnen kann. Ich hatte ja weiter oben schon mal 
die Behauptung aufgestellt dass EpTable[0].TxCount  = 0; falsch sei. Dem 
ist nicht so. Nun gibt es Stellen wo bei TxCount in reservierte Bits 
geschrieben wird.

Beispiel:  EpTable[1].TxCount = (i & 0x3FF) | EpBulkLenId;

Das ist vermutlich schon sehr lange im Code drin. Ich habe keine blassen 
Schimmer ob und wie sich das auswirkt. Aufgefallen ist mir das weil ich 
Speicher im USB Mem sparen muss, und deshalb die EP Tables kräftig 
umbauen muss.

von Alex (Gast)


Lesenswert?

@Thomas
würdest du sagen, dass ich mit dem Fehlersuchen eher warten sollte, bis 
du das 'fertig' hast?
Weil meine Fehlersuchkompetenz (besonders was C-Code anbelangt) ist ja 
nicht die Beste (da muss ich temp definitiv Recht geben !!)

von Alex (Gast)


Lesenswert?

@temp
Ich hab aus deinem Zip-File das Release-ELF in einen 'schlechten' Chip 
reingespielt. Der Fehler ist auch da, sobald ich mehr als 10 Zeichen 
runterschicke, ist Schluss mit BulkOut.
Im 'guten' Chip läufts. Verhält sich exakt so, wie bei meinen ELFs.

von temp (Gast)


Lesenswert?

Thomas Z. schrieb:
> Dem
> ist nicht so. Nun gibt es Stellen wo bei TxCount in reservierte Bits
> geschrieben wird.
>
> Beispiel:  EpTable[1].TxCount = (i & 0x3FF) | EpBulkLenId;

Beim F103 steht im Manual:
1
Bits 15:10 These bits are not used since packet size is limited by USB specifications to 1023 bytes. Their 
2
value is not considered by the USB peripheral.
3
4
Bits 9:0 COUNTn_TX[9:0]: Transmission byte count
5
These bits contain the number of bytes to be transmitted by the endpoint associated with the 
6
USB_EPnR register at the next IN token addressed to it.
Den Grund warum das W.S. so gemacht hat weiß ich nicht. Man kann das mit 
0 definieren und es geht trotzdem alles. Negative Auswirkungen würde ich 
nicht befürchten. Vielleicht hat sich da mal einer ein paar Marker in 
den Speicher gebaut zu Debugzwecken um Überschreibungen zu detectieren 
o.ä.
1
#define EpCtrlLenId 0  //  ((1<<15)|(1<<10))
2
#define EpBulkLenId 0  //  ((1<<15)|(1<<10))

Alex schrieb:
> Ich hab aus deinem Zip-File das Release-ELF in einen 'schlechten' Chip
> reingespielt. Der Fehler ist auch da, sobald ich mehr als 10 Zeichen
> runterschicke, ist Schluss mit BulkOut.
> Im 'guten' Chip läufts. Verhält sich exakt so, wie bei meinen ELFs.

Eventuell solltest du bei den schlechten Chip den Fehler mit dem Hammer 
suchen. Einmal kräftig draufhauen und du weißt genau warum er nicht mehr 
geht...
Ich traue deiner Hardware immer noch nicht. Der Software schon. Alles 
was wir hier diskutieren hat mit deinen Problemen nichts zu tun. Wo hast 
du die Chips gekauft?

von Alex (Gast)


Lesenswert?

Chips sind von Digikey.

> Eventuell solltest du bei den schlechten Chip den Fehler mit dem Hammer
suchen.
Ich sehe du bist ein Jünger Bob Widlars :-)!!!
'to widlarize something'

Der Ansatz ist möglicherweise der einzig sinnvolle.
Bisher wars immer so, dass die Fehler sporadisch mal da waren, und dann 
wieder weg.
Lag möglicherweise an der CLK-Geschichte.
Bei einem von 3 'schlechten' ist es jetzt exakt reproduzierbar, die 
anderen hab ich jetzt nicht durchgecheckt.
Vielleicht sollte ich die Chips einfach eintüten und beschriften, wenn 
sie dann mal in der Ecke liegen wächst sowieso Gras drüber...

von Thomas Z. (usbman)


Lesenswert?

Alex schrieb:
> @Thomas
> würdest du sagen, dass ich mit dem Fehlersuchen eher warten sollte, bis
> du das 'fertig' hast?

Ich würde sagen, dass mein Code eigendlich bei dir keine Veränderung 
bringen sollte. Ich werde da am 1. VCP nichts wesentliches verändern. 
Wenn sich da was tun sollte ist es eher ein Seiteneffekt, jedenfalls 
nichts absichtliches. Der Code von W.S. ist soweit ja ok und 
funktioniert.

von Alex (Gast)


Lesenswert?

Moin Leute

Um die schlechten Chips eindeutig zu identifizieren hab ich mir 
PC-seitig ein Skript geschrieben, das in einer Schleife die Anzahl der 
Zeichen die runtergeschickt werden kontinuierlich erhöht.
Ich sehe dann, bei wievielen Zeichen der STM aussteigt.
Die 'Hello World' Zeile und die beiden Delays hab ich auskommentiert.
Bei den meisten Modulen komme ich auf 47-51 Zeichen, dann stehts.
Bei manchen komme ich auf 5, 7, mal auf 13 oder 19

Jetzt hab ich, um zu verifizieren dass das wirklich an der Hardware 
liegt, mit cube ein HAL-USB-Echo-Projekt gebaut, dass auch die Zeichen 
einfach zurückschickt.

Meine Schleife geht bis 512 Zeichen, das schafft mit dem HAL-USB auch 
jenes Modul problemlos, das mit W.S. / Thomas Code immer bei 5 
aussteigt.

Für mich schaut das schon sehr danach aus, dass da in der Programmierung 
irgendwas nicht so glatt läuft wie es sollte.
Ich weiß, die Buffer sind nicht exakt gleich groß, der HAL-Treiber nimmt 
standardmäßig 1k Buffer, aber in Thomas code sind es auch 512 Bytes.

von temp (Gast)


Lesenswert?

Dann schmeiß doch mal dein Script in die Runde, damit man das 
nachvollziehen kann.

von Alex (Gast)


Lesenswert?

Wenn hilft:
Matlab:
1
s = serial('COM3','InputBufferSize', 2^16');
2
fopen(s);
3
string = [];
4
for i2 = 1:512
5
    disp (i2);
6
    
7
    string = [string '0']; 
8
    fwrite(s, string);
9
    
10
    pause(0.3);
11
    if (s.BytesAvailable > 0)
12
        char(fread(s, s.BytesAvailable)');
13
    end;            
14
end;
15
fclose(s);

Wenn der STM aussteigt, dann kommt der Fehler beim Schreiben:
1
Error using serial/fwrite (line 199)
2
Unsuccessful write: An error occurred during writing.

von W.S. (Gast)


Lesenswert?

Alex schrieb:
> Ich weiß, die Buffer sind nicht exakt gleich groß, der HAL-Treiber nimmt
> standardmäßig 1k Buffer, aber in Thomas code sind es auch 512 Bytes.

Mir kommt da ein übler Verdacht auf:

Für die Richtung µC-->PC hatte ich ja den Wiederanlauf per Timertick 
gemacht, von euch wurde das in den Userbereich mit "flush.." verschoben, 
aber immerhin ist für diese Richtung ja etwas da, was der Datenfluß in 
Gang hält bzw. wieder in Gang bringt. Diese Richtung sollte also 
abgehakt sein, denke ich mir mal...

ABER: für die umgekehrte Richtung, also PC-->µC, ist da nichts 
vorgesehen, weil da eigentlich der PC immer wieder dran erinnert, daß 
der Transferpuffer entleert werden soll.

Kann das also sein, daß bei dir diese wiederholten Interrupts 
ausbleiben, während der Ringpuffer noch zu voll ist, um den 
Transferpuffer in ihn auszuleeren? Daß das also einfach ein Effekt von 
zu langsamem oder zu spätem Abholen der eintreffenden Zeichen ist, der 
die Situation aufkommen läßt, wo der Ringpuffer leer ist, der 
Transferpuffer von EpBulkOut noch nicht entleert ist und sich NIEMAND 
drum kümmert, ihn zu entleeren?

Vielleicht sollte man sich doch überlegen, all die Eingriffe vom 
Userland in den USB wieder zurückzubauen und stattdessen beim 1ms 
Timertick grundsätzlich beide (bzw. alle) Bulk-EP's nachzuschauen, ob 
es da etwas zu leeren oder zu füllen gibt.

W.S.

von Stefan F. (Gast)


Lesenswert?

Bedenke, dass andere Leute den Code erfolgreich getestet haben, auch mit 
vollen Puffern.

von W.S. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Bedenke,...

Ja was kann/soll man sich denn sonst noch als Szenario für die Probleme 
des TO ausdenken, wenn bereits alles ausprobiert worden ist?

Mir ist da durchaus klar, daß die krampfhafte Suche nach irgend etwas, 
wo man annimmt, daß vielleicht noch keiner dran gedacht hat, irgendwann 
mal in die Irre gehen muß.

Also, wenn's nicht daran liegt, dann war dieser Gedanke umsonst und kann 
abgehakt werden.

W.S.

von Alex (Gast)


Lesenswert?

Ich hab jetzt den minimalen Echo-Test mit debuglevel -g1 und 
optimization -Os kompiliert, auf diese Weise ist der Fehler noch 
reproduzierbar und ich kann Breakpoints setzen.
Hab als ersten Versuch einen Breakpoint im OnEpBulkOut in die Zeile
1
avail = EpTable[1].RxCount & 0x3FF;
gesetzt.
Wenn ich nur ein Zeichen sende, dann komm ich an den Breakpoint,
wenn ich zu viele schicke dann kommt das Programm dort nicht hin.

von Alex (Gast)


Lesenswert?

Hab in der ISR ein
1
if (I & ~SOF_)
eingebaut und einen BP reingesetzt, um alle IRQs außer den SOF zu 
erkennen.

Hier ist es auch so, dass der BP nicht erreicht wird, wenn viele Zeichen 
geschickt werden.

von temp (Gast)


Angehängte Dateien:

Lesenswert?

Ich glaube ich kann noch was zur allgemeinen Verwirrung beitragen.
Gestern habe ich ein kleines Tool geschrieben das ungefähr das macht was 
Alex sein Script auch macht. Mit dem Ergebnis, dass es bei mir mit dem 
STM32F042 und STM32F103 nicht stabil läuft. Irgendwann steht die 
Geschichte immer.
Warum hat das noch keiner gemerkt? Weil niemand so etwas im realen Leben 
macht:
1
  while (1)
2
    {
3
        // Send echo of received characters back
4
        while (UsbRxAvail())
5
        {
6
            char c=UsbGetChar();
7
            UsbCharOut(c);
8
        }
9
    }

Bei mir geht das immer so: Packet hin als Commando, Packet zurück. Bei 
den SLCAN-Interfaces z.B. auch nur mit Längen < 64Byte. So etwas macht 
keine Probleme. Ich hänge das Programm mal hier dran und würde mich über 
Testergebnisse von anderen freuen. Einfach nur aufrufen "usbcdctest 
comx" oder ./usbcdctest /dev/ttyACM0
Bei mir ist es häufig aber nicht immer so, das die es bis 63 Byte geht 
und ab 64 klemmt es. Deshalb wartet das Programm vor der 64 auf Enter.
Wenn man sich da die Ringbuffer Variablen ansieht, sieht man, dass die 
alle genau die 64Byte weiterzählen, und trotzdem kommt nichts mehr am 
Host an.
Ich habe auch einige Versionsstände probiert, aber keine hat den Test 
bestanden. Ich habe das unter Windows und unter Linux (Raspi) probiert 
mit dem gleichen Ergebnis.
Wenn ich den Test nur bis 63Byte mache, läuft es stundenlang ohne 
Probleme.

Bitte keine Kommentare zur Qualität des Testprogramms. Das ist mit 
heißer Nadel zusammengebaut, aber so einfach, dass jeder selbst 
Änderungen machen kann.

von temp (Gast)


Lesenswert?

ups, da war was doppelt. Eins kann ja ein freundlicher Moderator ja 
löschen.

von Stefan F. (Gast)


Lesenswert?

temp schrieb:
> Eins kann ja ein freundlicher Moderator ja löschen.

Lohnt sich nicht, das File ist erfrischen klein.

Ich mache alles unter Linux, deswegen werde ich es nicht ausprobieren.
Ich habe aber eigene Tests unter Linuc gemacht, die liefen gut.

Die Zahl 63/64 macht mich allerdings stutzig. Ist das nicht die maximale 
Größe, die per USB am Stück übertragen werden? Dazwischen wird es wohl 
kleine Pause geben, wo das Programm warten muss.

von temp (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ich mache alles unter Linux, deswegen werde ich es nicht ausprobieren.
> Ich habe aber eigene Tests unter Linuc gemacht, die liefen gut.

Es ist doch eine Linux Version dabei? Auf build.sh kannst du doch noch 
drücken?

von Stefan F. (Gast)


Lesenswert?

temp schrieb:
> Es ist doch eine Linux Version dabei? Auf build.sh kannst du doch noch
> drücken?

Huch! Dann mache ich das mal am Wochenende

von Thomas Z. (usbman)


Lesenswert?

Stefan ⛄ F. schrieb:
> Die Zahl 63/64 macht mich allerdings stutzig. Ist das nicht die maximale
> Größe, die per USB am Stück übertragen werden?

Das ist richtig alles kleiner 64 ist ein sogenannter short Transfer (bei 
USB1.1) und beendet die Übertragung bei 64 Bytes gehen die Treiber davon 
aus dass es weiter geht. Das ist zum Beispiel ein wesentlicher 
Unterschied zu den FTDI Protokollen, die haben immer nur 62 Bytes 
Nutzdaten + 2 Statusbytes.

Ich habe auf dem Control EP etwas ganz ähnliches erlebt als ich die 
EP0_SIZE auf 8 reduziert habe, weil mir der Speicher im USB Mem knapp 
wurde. Da waren plötzlich Vendor und Device String weg weil diese genau 
ein vielfaches von 8 waren.

Da könnte durchaus noch ein Bug vergraben sein. Noch habe ich mich 
allerdings nicht mit den Bulkdetails beschäftigt, da muss ich auch noch 
Mal in der Spec nachlesen, aber möglicherweise muss bei genau 64 Bytes 
ein ZLP hinterher kommen.

von temp (Gast)


Lesenswert?

Es ist nur leider so ein geht/geht nicht Fehler.
Ich habe noch was interessantes. Mit dem Code von Stefans Webseite läuft 
der Test auf dem f042 bei mir jetzt durch. Da waren aber die Änderungen 
von Thomas glaube ich nicht drin. Irgendwann blickt man durch die vielen 
Versionen nicht mehr durch.

von temp (Gast)


Angehängte Dateien:

Lesenswert?

Hier nochmal für Alex das Testprojekt für den STM32F042 das hier schon 
seit einer halben Stunde vor sich hin schnurrt.

von Stefan F. (Gast)


Lesenswert?

temp schrieb:
> Da waren aber die Änderungen von Thomas glaube ich nicht drin.

Doch teilweise schon. Zumindest die, wo er meinte, dass sie akute Fehler 
korrigieren.

Später kamen dann Erweiterungen für neue Funktionen dazu, die habe ich 
nicht mehr übernommen.

von Thomas Z. (usbman)


Lesenswert?

Ein paar Änderungen sind auch in Stefans Version von mir drin. Das 
bedeutet aber doch ganz einfach dass sich in meinen Versionen noch ein 
dicker Bug befindet....
Der kann dann ja nur in einer der beiden Copy Funktionen für die Bulk 
EPs stecken...

Ich schau mir das nochmal an.

von Stefan F. (Gast)


Lesenswert?

Thomas Z. schrieb:
> Ich schau mir das nochmal an.

Das finde ich super Thomas, du bist echt nett.

von temp (Gast)


Lesenswert?

@Thomas
Der Fehler ist mit deiner Version vom 12.3. rein gekommen. Mit der vom 
4.3. geht es bei mir auch noch.
Alex hatte die vom 12.3. verwendet, mit der Version von Alex hatte ich 
meine Tests mit dem stm32f042 gemacht und so ist die Falle zugeschnappt.

von Thomas Z. (usbman)


Lesenswert?

@temp danke für den Hinweis. Das hatte ich schon vermutet da in der 
Version neue Bulkcopy Funktionen eingebaut habe...
Hier hab ich die schon wieder verworfen. Ich bitte also um etwas Geduld.
Andere Frage:
Ich glaube du warst es der gefragt hat ob man irgendwie erkennen kann 
wenn der Host den Port geöffnet hat oder?
Ich glaube ich hab da eine Lösung mit Hilfe des SetLineCoding requests 
sollte man das realisieren können. Ich hab hier ein Test laufen der beim 
Öffnen eine LED in Main toggelt. Es gibt manchmal noch Fehlanzeigen, da 
muss ich wohl noch ein paar Extras einweben. Darauf bin ich beim 
Überprüfen der Class Requests gekommen.

von temp (Gast)


Lesenswert?

Thomas Z. schrieb:
> Ich glaube du warst es der gefragt hat ob man irgendwie erkennen kann
> wenn der Host den Port geöffnet hat oder?
> Ich glaube ich hab da eine Lösung mit Hilfe des SetLineCoding requests
> sollte man das realisieren können.

Das habe ich auch schon mal geprüft. Beim Öffnen wird SetLineCoding 
gerufen, beim Schließen nicht.
Ich hab das aber für mich mit der DTR Leitung gelöst.

von Stefan F. (Gast)


Lesenswert?

temp schrieb:
> usbcdctest /dev/ttyACM0

Hallo temp,
ich habe dein Testprogramm mit meinem Projekt 
http://stefanfrings.de/stm32/STM32F303CC_usb_test.zip getestet, aber 
davon abweichend folgende Hauptschleife:
1
    while (1)
2
    {
3
        char c;
4
        if (UsbGetChar(&c, 10)) // warte max. 10ms
5
        {
6
            UsbSendChar(c, 10); // warte max. 10ms
7
        }
8
    }

Es läuft sowohl unter Debian 11 als auch Windows 10 tadellos durch.

UsbRxAvail() funktioniert auch.

Unter Windows sehe die Eingabeaufforderung "please press enter" nicht. 
Braucht Windows vielleicht ein "\r\n" am Ende der Zeile? Ach egal, 
scheiß drauf.

von temp (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> ich habe dein Testprogramm mit meinem Projekt
> http://stefanfrings.de/stm32/STM32F303CC_usb_test.zip getestet

Vielen Dank.

Stefan ⛄ F. schrieb:
> Es läuft sowohl unter Debian 11 als auch Windows 10 tadellos durch.
>
> UsbRxAvail() funktioniert auch.
>
> Unter Windows sehe die Eingabeaufforderung "please press enter" nicht.
> Braucht Windows vielleicht ein "\r\n" am Ende der Zeile? Ach egal,
> scheiß drauf.

Das bestätigt meine Beobachtung.

Stefan ⛄ F. schrieb:
> Unter Windows sehe die Eingabeaufforderung "please press enter" nicht.
> Braucht Windows vielleicht ein "\r\n" am Ende der Zeile? Ach egal,
> scheiß drauf.

Am besten die gesamte Eingabeaufforderung auskommentieren. Das ist ja 
nur für den speziellen Fall gedacht den ich hatte.

von temp (Gast)


Lesenswert?

temp schrieb:
> Am besten die gesamte Eingabeaufforderung auskommentieren.

So, ich habe noch einen Nachtrag. Und zwar mache ich seit Gestern 
Dauertests.  Die Eingabeaufforderung aus dem Testprogramm habe ich raus 
geschmissen. Mir war gestern schon mal aufgefallen, dass der Code von 
Stefans Webseite original mit Stm32Cube auch Hänger hat (release Mode 
-O3). Hier mal 4 Beispiele
1
send 409 bytes
2
  -read 345 bytes
3
timeout, read 345 bytes, ges: 59212613 bytes
4
5
send 420 bytes
6
  -read 356 bytes
7
timeout, read 356 bytes, ges: 62487578 bytes
8
9
send 174 bytes
10
  -read 110 bytes
11
timeout, read 110 bytes, ges: 48809529 bytes
12
13
send 493 bytes
14
  -read 429 bytes
15
timeout, read 429 bytes, ges: 28770411 bytes
Mit anderen Worten, da steckt noch ein Bug drin.
Ich selbst baue seit geraumer Zeit an meiner eigenen Version des ganzen. 
Die hat von Gestern zu Heute ein paar GB durchgespült ohne Hänger. Die 
Variante von Stefan (und die anderen davor sicher auch) schafften nicht 
mal 100MB. Im realen Leben dürfte das keine große Rolle spielen, aber 
ich gebe mich erst dann zufrieden wenn so etwas nicht mehr auftritt. Wie 
man an den Zahlen aber schön sehen kann, fehlen immer 64Byte am Ende.

von temp (Gast)


Lesenswert?

Thomas Z. schrieb:
> Das ist richtig alles kleiner 64 ist ein sogenannter short Transfer (bei
> USB1.1) und beendet die Übertragung bei 64 Bytes gehen die Treiber davon
> aus dass es weiter geht. Das ist zum Beispiel ein wesentlicher
> Unterschied zu den FTDI Protokollen, die haben immer nur 62 Bytes
> Nutzdaten + 2 Statusbytes.

Das vermute ich auch als Ursache. Änderungsvorschlag wäre entweder alle 
Pakete auf < 64 zu begrenzen oder nur das letzte.
1
void EpBulkBeginTransmit(void)
2
{
3
    int i, n;
4
    UMEM_FAKEWIDTH L, A;
5
    UMEM_FAKEWIDTH* P;
6
7
    P = (UMEM_FAKEWIDTH*) EP1TxABuffer;
8
    i = txw - txr;
9
    if (i < 0)
10
    {
11
        i += USB_TXLEN; // i = number of bytes to send
12
    }
13
    if (i > EpBulkMaxLen)
14
    {
15
        i = EpBulkMaxLen;
16
    }
17
    // verhindern, dass als letztes! Packet eines mit 64byte gesendet wird
18
    else if (i==EpBulkMaxLen)
19
    {
20
      i=EpBulkMaxLen-2;
21
    }
Hier besteht aber noch das Restrisiko, wenn aus dem Userland jemand den 
tx- Ringbuffer genau nach diesem Zeitpunkt löscht, fehlt wieder das 
letzte kurze Paket.

von Thomas Z. (usbman)


Lesenswert?

Ich habe gestern die halbe Nacht nach einem Fehler gesucht der mir bei 
den Classrequests aufgefallen ist. Nichts was ich probiert habe hat 
funktioniert. Das war wie wenn ich das Programmieren verlernt hätte.

Irgendwo gibt's noch ein prinzipielles Problem im Code, oder im 
Verständniss des USB cores. Um auszuschliesen dass ich mir selbst ein 
Bein stelle bin ich dabei bis zurück zum Original von W.S. gegangen.

Gefunden hab ich bis jetzt nichts. Am WE geht's weiter.

von temp (Gast)


Lesenswert?

Mit meinen oben genannten Änderungen läuft der Test seit gestern Abend 
problemlos durch.

von Bernd N. (_bn_)


Angehängte Dateien:

Lesenswert?

temp schrieb:
> Ich glaube ich kann noch was zur allgemeinen Verwirrung beitragen.
> Gestern habe ich ein kleines Tool geschrieben das ungefähr das macht was
> Alex sein Script auch macht. Mit dem Ergebnis, dass es bei mir mit dem
> STM32F042 und STM32F103 nicht stabil läuft. Irgendwann steht die
> Geschichte immer.

Ich habe jetzt ebenfalls ein Minimal Beispiel für das Bluepill gebaut 
und habe das Projekt ausgegraben was ich vor einiger Zeit hier 
getriggert hatte, siehe auch 
Beitrag "USB CDC von Stefan Frings und WS"

Dann habe ich dein kleine Testprogramm verwendet und dies läuft ohne 
irgendwelche Probleme durch, kein einziger hänger.

Ich vermute das mit all den verschiedenen Versionen Chaos entsteht aber 
das wurde ja alles schon einmal aufgeräumt. Im Anhang mal ein Testfile 
für deine Versuche. Lass mich wissen ob es damit Probleme gibt dann 
grabe ich mal weiter. Ich glaube aber das funktioniert ohne Probleme. 
Dank gilt hierfür Niklas.

von Stefan F. (Gast)


Lesenswert?

Für mich sieht die Lage nicht so eindeutig aus, wie ich es gerne hätte. 
Ich hasse solche "Fehler" zutiefst.

Ich habe ja am Donnerstag berichtet, das ich den Fehler nicht 
reproduzieren konnte. Doch da hatte ich das Testprogramm nur wenige 
Minuten laufen lassen. Die Anmerkungen von temp animierten mich jedoch 
dazu nochmal genauer hin zu schauen, was ich heute morgen tat.

Nach nur 5 Minuten hatte ich den ersten Aussetzer. Der nächste ließ 
allerdings satte 4 Stunden auf sich warten. Dann hatte ich wieder einen 
quasi sofort nach nur wenigen Sekunden.

Also muss ich meine vorherige Aussage revidieren, ich kann das Problem 
doch reproduzieren. Und ja, auch bei mir fehlten immer genau 64 Bytes.

Nun habe ich die drei Zeilen Workaround in den Quelltext eingefügt und 
teste seit dem wieder. Das ist nun zwei Stunden her, ohne Aussetzer. Ich 
werde es wohl auch mindestens bis morgen laufen lassen, um Gewissheit zu 
bekommen.

Ich frage mich, ob temp hier auf einen Hardware-Bug gestoßen ist?

Frage an die 3-4 Kollegen, die sich mit USB auskennen: Wenn der µC die 
letzten 64 Zeichen an den PC sendet und sie dort (warum auch immer) 
nicht ankommen, wie funktioniert da der Wiederhol-Mechanismus?

von temp (Gast)


Lesenswert?

Bernd N. schrieb:
> Dann habe ich dein kleine Testprogramm verwendet und dies läuft ohne
> irgendwelche Probleme durch, kein einziger hänger.

Fakt ist eins, der Bug ist da noch drin. Ich habe das gesamte Projekt 
von Stefans Seite so genommen wie es ist. Optimierung O3. Wenn du was 
anderes hast, brauchen wir nicht drüber reden. Und Laufen lassen heisst 
ein paar Stunden und nicht 10s.

Es ist genau so wie Thomas es beschreibt. Werden vom STM genau 64 Byte 
in einem Usb-Endpoint-Paket verschickt und der PC will genau 64 Byte 
lesen steht die Geschichte augenblicklich. Sendet der STM fröhlich 
weiter, wird diese Klippe übersprungen. Verkleiner der STM das Packet 
auf 63 und 1 Byte im nächsten Usb-Endpoint-Paket tritt das Problem nicht 
auf.

Was die Fehlersuche an dieser Stelle erschwert ist die Tatsache, dass im 
STM-Testprogramm alles Byteweise abgehandelt wird.
1
   while (1)
2
      {
3
      char c;
4
      if (UsbGetChar(&c, 10)) // warte max. 10ms
5
        {
6
        UsbSendChar(c, 10); // warte max. 10ms
7
        }
8
      }
Hier wird im UsbSendChar() auch das Triggern des Endpointtransfers 
angestoßen. Somit ist es in Verbindung mit dem PC-Testprogramm völlig 
zufällig, was für Packetgrößen wirklich per USB übertragen werden. Die 
Wahrscheinlichkeit ist sogar ziemlich gering, dass das Device 64Byte am 
Block und noch dazu im letzten Block sendet und der PC genau auf diese 
64 Byte wartet. Hier spielt dann auch die Abhängigkeit von der 
Optimierung eine Rolle. Mit einem angepassten Testprogramm ist das mit 
dem ersten Senden reproduzierbar. Dieser Bug ist schon von der ersten 
W.S. Version drin. Zusätzlich einer der in den Endpoint schreibt, obwohl 
der noch den STAT_TX 0x03 hat. Das hat dann Niklas mit viel Gedöhns und 
Flags und Verlagern von Teilen in den Usercode gefixt. Nicht elegant, 
aber es half.

Ihr könnt das glauben oder nicht, ich habe damit kein Problem. Ich habe 
aber auch keinen Bock für jeden einzelnen noch ein Demoprogramm zu 
schreiben. Es war schon nervig genug den STMCubeMx Kram nur für die 
Spielerein hier zu installieren.

Bernd N. schrieb:
> Dank gilt hierfür Niklas
Niklas hat erst die Vermischung von User- und Interruptcode hier rein 
gebracht. Dafür gibt es von mir keinen Dank.

von temp (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ich frage mich, ob temp hier auf einen Hardware-Bug gestoßen ist?

Nein, das ist Spezifikation USB1.1 lt. Thomas. Wenn ein Endpoint-Packet 
genau 64Byte lang ist, geht der Host davon aus es kommt noch was und 
liefert die Daten noch nicht an das Userprogramm weiter. Also ist mein 
Trick, wenn der Ringbuffer noch genau 64 Byte hat, sende ich nur 62 und 
die nächsten 2 im nächsten Endpointpaket. Damit sind dann alle 
zufrieden.

von Bernd N. (_bn_)


Lesenswert?

temp schrieb:
> Fakt ist eins, der Bug ist da noch drin. Ich habe das gesamte Projekt
> von Stefans Seite so genommen wie es ist

Ich nicht, deswegen habe ich das Angebot gemacht. Probier es aus oder 
lass es, ich teste seit Stunden ohne Aussetzer.

von temp (Gast)


Lesenswert?

Bernd N. schrieb:
> Ich nicht, deswegen habe ich das Angebot gemacht. Probier es aus oder
> lass es, ich teste seit Stunden ohne Aussetzer.

Sorry, du kannst testen soviel wie du willst. Es ist mir auch Wumpe was 
du für Ergenisse erziehlst. Und ich will auch niemandem bekehren. Fakt 
ist, der Code hat diesen Bug, da er die o.g. Besonderheit der Spec nicht 
berücksichtigt. Mir reicht diese Erkenntnis für mich, und nur das ist 
mir wichtig. Ich wüsste auch nicht was mich deine Projekte interessieren 
sollten. Mehr als meine Erkenntnisse und Erfahrungen bringe ich hier 
nicht ein, und wer's nicht hören will, des lässt es halt bleiben. Punkt.

von temp (Gast)


Lesenswert?

Bernd N. schrieb:
> Ich nicht,
Genau das ist das Problem. Es spielen in dieser Konstellation zu viele 
Zufälliglkeiten rein und auch definitiv die Abhängikeit von der 
Optimierungsstufe.
Und nicht weil da falscher Code raus kommt, sondern weil er sich 
zeitlich anders verhält und bei dieser Testkonstellation der Bug nur 
selten auftritt.

Stefan ⛄ F. schrieb:
> Nach nur 5 Minuten hatte ich den ersten Aussetzer. Der nächste ließ
> allerdings satte 4 Stunden auf sich warten. Dann hatte ich wieder einen
> quasi sofort nach nur wenigen Sekunden.

Danke Stefan, das bestätigt, dass ich nicht an geistiger Umnachtung 
leide.

Ich habe vorhin schon geschrieben, dass ein passender Test das sofort 
reproduzieren kann. Ich wüsste nur nicht warum ich hier mit jemanden 
darum streiten sollte. Was das Problem ist habe ich geschildert. Wer es 
nicht glaubt baut sich bitte seine Tests selber oder denkt weiter es ist 
alles ok.
Und ja, viele realen Anwendungen, auch meine, laufen mit dem Bug ohne 
Probleme. Jedenfalls solange nicht jemand auf ein letztes Paket mit 64 
Byte wartet.

von Stefan F. (Gast)


Lesenswert?

temp schrieb:
> Es spielen in dieser Konstellation zu viele
> Zufälliglkeiten rein und auch definitiv die Abhängikeit von der
> Optimierungsstufe.

Ich konnte den Fehler auch mit -O1 reproduzieren.

Mit der Korrektur von temp lief es seit gestern ca 14:00 ohne Stopp 
durch. Selbst wenn sich heraus stellen sollte, dass die Änderung noch 
keine 100% Lösung ist, so macht sie zumindest nichts kaputt.

Ich habe die Downloads auf meine Homepage (unter 
http://stefanfrings.de/stm32/index.html) entsprechend aktualisiert.

von Bernd N. (_bn_)


Lesenswert?

Ich will hier nicht streiten sondern herausfinden was da falsch läuft.

temp schrieb:
> Ich habe vorhin schon geschrieben, dass ein passender Test das sofort
> reproduzieren kann.

Also dann her mit dem Test, kostet dich das Testen nur ne halbe Minute. 
Ich teste es auch gerne selbst.

von temp (Gast)


Angehängte Dateien:

Lesenswert?

Bernd N. schrieb:
> Also dann her mit dem Test

Das hört sich etwas dummdreißt an...

trotzdem in die usb.c am Ende muss eine neue Methode:
1
bool UsbSendCharBlock(const char *pc, int len)
2
{
3
  for (int n=0; n<len; n++)
4
    {
5
  // check space
6
    int i = (txw + 1) & (USB_TXLEN - 1);
7
    if (i == txr)
8
      {
9
        return false;
10
      }
11
12
    // write into the buffer
13
    UsbTxBuf[txw] = pc[n];
14
    txw = i;
15
    }
16
  DisableUsbIRQ();
17
  EpBulkBeginTransmit();
18
  EnableUsbIRQ();
19
  return true;
20
}
Die füllt zuerst den Ringbuffer und triggert danach erst das 
EpBulkBeginTransmit an. Damit landen dann auch bis max 64byte im ersten 
Bulktransfer.

Die main sieht dann so aus:
1
bool UsbSendCharBlock(const char *pc, int len);
2
int main()
3
{
4
  init_clock();
5
  init_io();
6
  UsbSetup();
7
  // Initialize system timer
8
  SysTick_Config(SystemCoreClock/1000);
9
  while (1)
10
    {
11
    char buf[65];
12
    int n=0;
13
    while (n<64)
14
      {
15
      char c;
16
      if (UsbGetChar(&c, 10))
17
        {
18
        buf[n]=c;
19
        n++;
20
        }
21
      }
22
    UsbSendCharBlock(buf, 64);
23
    }
24
}
Mit anderen Worten, ich warte bis ich genau 64 Byte vom Host kriege, und 
sende die dann im Block zurück. Das angepasste PC Testprogramm ist im 
Anhang. Ohne meine Änderung kommt nicht mal der erste Block beim PC 
wieder an.
Im Anhang das frisch von Stefans Seite geladene Projekt mit den o.g. 
Änderungen. Die Zeile 1351 in usb.c ist auskommentiert um den Fehler zu 
zeigen. Wird der Kommentar entfernt funtioniert es.

von temp (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Selbst wenn sich heraus stellen sollte, dass die Änderung noch
> keine 100% Lösung ist, so macht sie zumindest nichts kaputt.

Mittlerweile weiss ich was die 100% Lösung ist. Nachdem das letzte Paket 
mit 64byte raus ist und der Ringbuffer leer, muss ein weiteres leeres 
Paket an den Endpoint gesendet werden. Das funktioniert in meinem Code 
auch schon. Allerdings basiert der mehr auf der W.S. Version. In der 
Version von Stefan sind die ganzen Änderungen von Niklas drin, da ist es 
etwas schwieriger zu realisieren. Da wir nun die Ursache und Lösung des 
Problems kennen, können sie die Herren über dieser Version dem ja 
annehmen. Oder mit der 2.besten Lösung leben.

von Stefan F. (Gast)


Lesenswert?

temp schrieb:
> Mittlerweile weiss ich was die 100% Lösung ist.

Das du davon überzeugt bist, hast du bereits glaubwürdig rüber gebracht. 
Danke, dass du dich da so tief rein gehängt hast.

Interessant ist, dass der Code nach so vielen (weit über 5) Jahren immer 
noch reproduzierbare Bugs enthält. Selbst der HAL Code scheint nicht 
unproblematisch zu sein und Arduinos mit integriertem USB zicken auch 
herum.

Mich stört noch, dass die USB Schnittstelle sofort ausfällt, wenn ich 
das Programm im Debugger anhalte. Das schränkt den Nutzen des Debuggers 
massiv ein. Doch gerade das bessere (und damals erheblich billigere) 
Debugging war für mich der Hauptgrund, mir die STM32 überhaupt 
anzuschauen.

Was ich daraus für mich lerne ist, dass die externen USB-UART Chips noch 
lange nicht obsolet geworden sind.

von temp (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Mich stört noch, dass die USB Schnittstelle sofort ausfällt, wenn ich
> das Programm im Debugger anhalte. Das schränkt den Nutzen des Debuggers
> massiv ein.

Das Problem mit dem Debugger ist, meistens bleiben die nach dem Start in 
der main() stehen. Das kann man sicher anders konfigurieren. Wenn die 
USB Enumerierung einmal durch ist, kann man auf einem Breakpoint stehen 
bleiben ohne dass der USB-Kram ausfällt.
Bei den Bluepill-Boards mache ich immer folgendes. Vor der 
main()-Methode konfiguriere ich den PA12 (der mit dem 1.5k Widerstand) 
als OpenDrain Ausgang und auf LOW. Wenn der Debugger in der main anhält 
wird das USB-Device im PC entfernt. Nach dem USBInit() o.ä. Wird dann 
A12 wieder auf FloatInput gesetzt und ab da erst beginnt die 
Enumeration. Bei dir würde das so aussehen:
1
void SystemInit()
2
{
3
  // GPIOA12 auf OpenDrain und Low setzen
4
  SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN);
5
  MODIFY_REG(GPIOA->CRH, GPIO_CRH_CNF12 + GPIO_CRH_MODE12, GPIO_CRH_CNF12_0 + GPIO_CRH_MODE12_1);
6
  WRITE_REG(GPIOA->BRR, GPIO_BRR_BR12);
7
}
8
9
int main()
10
{
11
  init_clock();
12
  init_io();
13
  UsbSetup();
14
15
  // Initialize system timer
16
  SysTick_Config(SystemCoreClock/1000);
17
18
  MODIFY_REG(GPIOA->CRH, GPIO_CRH_CNF12 + GPIO_CRH_MODE12, GPIO_CRH_CNF12_0);

von Stefan F. (Gast)


Lesenswert?

temp schrieb:
> Wenn die USB Enumerierung einmal durch ist, kann man auf einem
> Breakpoint stehen bleiben ohne dass der USB-Kram ausfällt.

Aber wenn ich das Programm anhalte beantwortet er die SOF Interrupts 
nicht mehr. Das wertet der PC als Disconnect. Oder habe ich da etwas 
übersehen?

von temp (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Aber wenn ich das Programm anhalte beantwortet er die SOF Interrupts
> nicht mehr. Das wertet der PC als Disconnect. Oder habe ich da etwas
> übersehen?

Das Beantworten des SOF macht die Hardware, das hat nichts mit dem 
Interrupt zu tun. Der wird nur zur Information gerufen. Ebenso wie ESOF. 
Probiers doch aus und setze im laufenden Betrieb auf das
1
UsbSendChar(c, 10); // warte max. 10ms
einen Breakpoint. Da hängt sich nichts auf, auch wenn du ein paar 
Sekunden da stehen bleibst. Klar das PC-Programm geht irgendwann in den 
Timeout, aber selbst wenn das passiert kann man es neu starten und der 
USB Stack hängt sich nicht auf.
Kritisch ist bei mir immer nur die Enumeration am Anfang. Wenn da 
zeitlich was klemmt kommt es zu Fehlern. Deshalb der Trick die 
Enumeration nicht gleich beim Reset zu starten.

von Stefan F. (Gast)


Lesenswert?

temp schrieb:
> Da hängt sich nichts auf, auch wenn du ein paar
> Sekunden da stehen bleibst.
> Kritisch ist bei mir immer nur die Enumeration am Anfang.

Hmm, letztes Jahr hatte ich die vielen Trace-Meldungen eingebaut weil 
das Enumerieren nicht klappte.

Das war damals der Part, den ich Debuggen wollte. Darüber sind wir ja 
schon lange hinweg. Ich würde gerne mein Anwendungsprogramm debuggen. 
Habe ich danach gar nicht mehr versucht. Da hatte ich wohl ein Brett 
vorm Kopf.

von Thomas Z. (usbman)


Lesenswert?

Stefan ⛄ F. schrieb:
> Interessant ist, dass der Code nach so vielen (weit über 5) Jahren immer
> noch reproduzierbare Bugs enthält

Bugs lassen sich fast immer finden. Das ist aber auch kein Problem, es 
gibt keinen fehlerfreien Code. Der Code von W.S. war ja ursprünglich für 
eine ganz bestimmte Aufgabe gedacht, und das hat er ja auch gemacht. Im 
Laufe der Zeit sind viele zusätzliche Anforderungen und Wünsche dazu 
gekommen. So ist mir aufgefallen dass die Classrequests nicht arbeiten, 
was aber erst wichtig wird wenn man eine richtige ser. Schnittstelle 
ansprechen will.

Stefan ⛄ F. schrieb:
> Was ich daraus für mich lerne ist, dass die externen USB-UART Chips noch
> lange nicht obsolet geworden sind.

Ja dass ist sicherlich die einfachste Lösung. Wenn man aber sowieso 
einen USB fähigen Controller hat, kann der das gleich miterledigen. Ich 
mache das schon viele Jahre so. Ich gebe aber zu, dass ich bisher noch 
sehr wenig mit ARM gemacht habe. Was ich anfangs nicht erkannt habe ist 
die schlechte Umsetzung von USB bei den STMs und speziell den F103. 
Selbst die pobligen CH552 schaffen es einen internen Connect Widerstand 
auf den Bus zu legen, und bieten DMA von und zum USB core. Da ist z.B 
ein FX2 geradezu übersichtlich.

Ich jedenfalls habe mir fest vorgenommen wenn meine Umsetzung fertig 
ist, das gleiche auch mal auf einem F407 auf dem Discovery Board from 
Scratch zu probieren.

Noch ein Update zu meinem VCP:
Ich hab das Ding hier soweit am laufen, bis zu 3 VCPs sind möglich mehr 
gibt das USB Mem nicht her. Der erste arbeitet wie bisher, die anderen 
gehen auf 2 Comports. Ich arbeite gerade an den ser. Schnittstellen.
Parallel baue ich das gleiche auch für die WCH CH552.

von Stefan F. (Gast)


Lesenswert?

Thomas Z. schrieb:
> Ich jedenfalls habe mir fest vorgenommen wenn meine Umsetzung fertig
> ist, das gleiche auch mal auf einem F407 auf dem Discovery Board from
> Scratch zu probieren.

Über das Ergebnis würden sich bestimmt viele Leute freuen, falls du es 
veröffentlichst. Ich werde die F4 in diesem Leben wohl nicht mehr 
einsetzen, da mir die kleineren schon mehr als ausreichend sind.

von Alex (Gast)


Lesenswert?

ich hatt gestern endlich wieder die Möglichkeit, an dem USB 
weiterzuwerkeln.

Wenn ich euch richtig verstanden habe, betrifft die 64-Byte-Geschichte 
ja den EpBulkIn (µC -> PC).

Der Fehler bei mir (Breakpoint-Test, Posting vom 25.3. ) ist ja beim 
EpBulkOut, der µC empfängt die Daten dann ja garnicht richtig.
Konnte dieses Verhalten schon irgend jemand von euch reproduzieren?

Ich hab die Version von temp vom 28.3. ( mit Zeile 1351 in der usb.c) 
jetzt mal auf einem Problemkandidaten laufen lassen:

Der µC wartet ja, bis 64 chars beisammen sind, und schickt die wieder 
hoch.
Das funktioniert auch, wenn die einzelnen EpBulkOut-Transfers nur wenige 
Zeichen lang sind.
Sobald ich einmal einen Block mit 30 Zeichen runterschicke, ist es 
vorbei.

Da muss noch irgendwas anderes drinstecken, das verhindert dass ein 
EpBulkOut IRQ kommt.

von temp (Gast)


Lesenswert?

Alex schrieb:
> Sobald ich einmal einen Block mit 30 Zeichen runterschicke, ist es
> vorbei.

Ich denke wir können dir hier nicht mehr weiterhelfen. Mehrere Leute 
haben unabhängig von einander den Test so gemacht wie du ihn uns 
beschrieben hast. Dabei wurde ein Problem erkannt und gefixt was schon 
lange im Code geschlummert hat und nur bei bestimmten Konstellationen 
auftritt, die häufig niemals eintreffen. Dazu musste das Testprogramm 
auch noch teilweise stundenlang laufen. Nach meiner Änderung traten 
keine Probleme mehr auf.

Das hat mit deinen Problemen nichts zu tun denke ich. Irgendetwas ist 
bei dir anders. Wenn du willst, kannst du mir ja mal eins von deinen 
sowieso schlechten Modulen zum Testen überlassen.

Hast du die Tests mit dem Testprogramm von mir auch mal gemacht?

von Alex (Gast)


Lesenswert?

hab dein Programm jetzt auch mal kurz drüberlaufen lassen.
Bei einem guten Modul läufts, kommen Ausgaben, scheinen ok zu sein.
Bei einem schlechten stehts, keine Ausgab (nicht eine Zeile).

Ist im Grunde das, was nach meinen Tests auch zu erwarten ist, oder 
nicht?
Dein Testprogramm schickt sofort 64 bytes runter, die kommen unten dann 
nicht an (kein IRQ).

von temp (Gast)


Lesenswert?

Alex schrieb:
> Ist im Grunde das, was nach meinen Tests auch zu erwarten ist, oder
> nicht?
> Dein Testprogramm schickt sofort 64 bytes runter, die kommen unten dann
> nicht an (kein IRQ).

Wie gesagt, ich wüsste nicht wie man dir noch helfen kann. Vor allem 
weil du der einzige seit Jahren mit so einem Problem bist.

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