Forum: Mikrocontroller und Digitale Elektronik STM32 USART1 IT Bytes verlust


von MMM (st1234)


Lesenswert?

Bei einem H7-Disco verliert der empfang der Daten über USART1 (115kbaud) 
(mit der _IT funktion, byteweise (IT funktion mit länge 1)), ca. jedes 5 
oder 6. byte.
Mit verliert meine ich: In der ISR fülle ich einen buffer und starte die 
_IT funktion direkt neu: Beim debuggen fehlen 10-20% der bytes im 
buffer.

Auch eine reduktion der baudrate auf 9600 löst das Problem nicht. Hat 
jemand eine Ahnung an was dies liegen könnte? (Die ISR benötigt wenige 
instruktionen bis zum aufruf der neuen IT HAL funktion)

: Bearbeitet durch User
von Paul (Gast)


Lesenswert?

MMM schrieb:
> Bei einem H7-Disco verliert der empfang der Daten über USART1
> (115kbaud)
> (mit der _IT funktion, byteweise (IT funktion mit länge 1)), ca. jedes 5
> oder 6. byte.
> Mit verliert meine ich: In der ISR fülle ich einen buffer und starte die
> _IT funktion direkt neu: Beim debuggen fehlen 10-20% der bytes im
> buffer.
>
> Auch eine reduktion der baudrate auf 9600 löst das Problem nicht. Hat
> jemand eine Ahnung an was dies liegen könnte? (Die ISR benötigt wenige
> instruktionen bis zum aufruf der neuen IT HAL funktion)

Liegt an deinem Code.
Keine Ursache, ich helfe gern.

Wo wir grad beim Thema sind: Zeig doch mal deine ISR.
Sonst wird es schwierig mit der Fehlersuche.

VG Paul

von mitlesa (Gast)


Lesenswert?

MMM schrieb:
> Auch eine reduktion der baudrate auf 9600 löst das Problem nicht.

Kann nur von meinen F103 mit schlappen 72 MHz berichten. Dort
fahre ich verlustfrei im Interrupt-Receive-Modus mit 921600 Baud
ohne Fehler. Diese maximale Baudrate bietet mir mein PC bzw. das
Terminal-Programm.

Sollte der H7 eigentlich auch schaffen.

Alerdings programmiere ich mit LL-Macros und -Funktionen. Ob
das was ausmacht?

von MMM (st1234)


Lesenswert?

Danke Paul, das nicht am gleichen rechner: code kurz abgeschrieben (und 
entsprechd gekürzt, Syntax ist jedoch im orrig code korrekt)

void HAL_UART_RxCpltCallback(UART_Handle *huart)
{
if(huart==&huart1){
buf[6]=buf[5];
buf[5]=buf[4];
.
.
.
buf[0]=datain;
HAL_UART_Rreceive_IT(&huart1,&datain,1);

kurzes simples parsen des Buffers (max 100 ASM instr.)
}
}

von MMM (st1234)


Lesenswert?

mitlesa schrieb:
> Kann nur von meinen F103 mit schlappen 72 MHz berichten. Dort
> fahre ich verlustfrei im Interrupt-Receive-Modus mit 921600 Baud
> ohne Fehler. Diese maximale Baudrate bietet mir mein PC bzw. das
> Terminal-Programm.
>
> Sollte der H7 eigentlich auch schaffen.
>
> Alerdings programmiere ich mit LL-Macros und -Funktionen. Ob
> das was ausmacht?

Ich denke nicht, dass es ein performance problem ist, also die ISR 
sollte sicherlich in einer UART Transaktion ausgeführt werden. Meine 
UART ISR ist schnell, es läuft aber das standart GUI+OS drauf (an den 
Interrupt prioritäten habe ich noch nichts versucht) dennoch: Da 
9600Baud auch das problem hat, denke ich Performanceproblem = Holzweg. 
(Unter der Annahme, das das GUI+RTOS, industrieüblich, die ISRs kurz 
halten).

Noch vergessen zu erwähnen: Die UART Datenquelle ist ein anderer STM 
welcher per DMA circular die Daten ohne Pause raushaut

: Bearbeitet durch User
von Harry L. (mysth)


Lesenswert?

mitlesa schrieb:
> Alerdings programmiere ich mit LL-Macros und -Funktionen. Ob
> das was ausmacht?

Macht es nicht.
Die LL-Funktionen dienen in erster Linie dazu Speicher(Flash) zu sparen 
und oder Funktionalitäten zu realisiieren die sich mit den klassischen 
HAL-Funtionen nicht oder nur schwer abbilden lassen.

MMM schrieb:
> void HAL_UART_RxCpltCallback(UART_Handle *huart)
> {
> if(huart==&huart1){
> buf[6]=buf[5];
> buf[5]=buf[4];
> .
> .
> .
> buf[0]=datain;
> HAL_UART_Rreceive_IT(&huart1,&datain,1);

Und das soll dein "Ringbuffer" sein?

MMM schrieb:
> denke ich Performanceproblem = Holzweg.

Das denke ich auch.

Du kannst dir ja mal meinen funktionierenden Code anschauen - vielleicht 
machts dann klick.
Beitrag "[STM32/HAL] simples U(S)ART-Library"

von MMM (st1234)


Lesenswert?

Harry L. schrieb:
> Und das soll dein "Ringbuffer" sein?

Nein, das ist mein workaround, da ich erst dachte es liegt an der Zeit 
zwischen Interrupt und restart der IT funktion. Zudem schliesst dieser 
einfache kleine schiebebuffer fehler bez. Ringbuffer aus.

von MMM (st1234)


Lesenswert?

Harry L. schrieb:
> Du kannst dir ja mal meinen funktionierenden Code anschauen - vielleicht
> machts dann klick.
> Beitrag "[STM32/HAL] simples U(S)ART-Library"

Danke, Harry. Eine schöne kleine library die du hier erstellt hast. Ich 
zögere gerade die zu probieren, da ich aktuell der starken Meinung bin 
ich erhalte die Daten (aus unbekannten Gründen) nicht zuverlässig in der 
IT funktion. Ein schöner Aufbau bezüglich der Datenweiterverarbeitung 
ist daher evtl orthogonal zum Problem.

Auch bisher habe ich mich zurückgehalten mit DMAs zu versuchen, aber 
denke das steht morgen an: DMA transfer und rumgebastel wegen den Cashes 
für 1 Byte transfer :-P.
Aber dennoch wieso verliert die IT bytes?!?
Ich habe den USART beim generierten GUI GFX code einfch reingehackt (ISR 
mit geplanter übergabe an mein C++ GUI program über globale variablen).

Hat wer ein beispiel/idee wie diese USART fachgerechter ins RTOS 
integriert wird? Also gesucht: standard GUI-GFX template mit 
eingebauten/aktiviertem USART1 für den H7-Disco.

von A. S. (Gast)


Lesenswert?

MMM schrieb:
> Zudem schliesst dieser einfache kleine schiebebuffer fehler bez.
> Ringbuffer aus.

Eigentlich nicht.

Den Puffer kannst Du doch nirgends benutzen.

Ein Ringpuffer ist da wesentlich einfacher. In Sparversion reichen da 10 
Zeilen (im Interrupt und Main zusammen)

von Harry L. (mysth)


Lesenswert?

MMM schrieb:
> Auch bisher habe ich mich zurückgehalten mit DMAs zu versuchen

Das solltest du auch besser lassen!

Erstens ist das bei UART vollkommen unnötig und meist sogar 
kontraproduktiv, und 2. handelst du dir beim H7 Probleme mit dem Cache 
ein.
Das kann man zwar alles lösen, aber, mir scheint, daß du davon noch 
ganz, ganz weit entfernt bist.

BTW. - wenn du in meinem Code den RAW-Mode nutzt, wird die 
Callback-Funktion nach jedem einzelnen empfangenen Byte aufgerufen.

: Bearbeitet durch User
von MMM (st1234)


Lesenswert?

Harry L. schrieb:
> Erstens ist das bei UART vollkommen unnötig und meist sogar
> kontraproduktiv,

Ja absolut einverstanden, ich würde sogar noch bescheuert hinzufügen :P.

Harry L. schrieb:
> und 2. handelst du dir beim H7 Probleme mit dem Cache
> ein.

ja kenne ich

Harry L. schrieb:
> Das kann man zwar alles lösen, aber, mir scheint, daß du davon noch
> ganz, ganz weit entfernt bist.

Schein kann manchmal trügen, nur weil ich gerade ein seltsames 
Grundlagenproblem habe bedeutet das nicht zwangsläufig das ich nicht 
quick and dirty in der Lage bin einen cachebereich zu invalidaten :P.

A. S. schrieb:
> Den Puffer kannst Du doch nirgends benutzen.

Doch nutze ich, für meine einfache Anwendung genügen dem parser die 
letzen bytes.

A. S. schrieb:
> Ein Ringpuffer ist da wesentlich einfacher. In Sparversion reichen da 10
> Zeilen (im Interrupt und Main zusammen)

Mein Schiebebuffer hat 6 Zeilen und ist garantiert Fehlerfrei :P. Wie 
gesagt hatte erst ja auch ein Ringbuffer drin.

von Harry L. (mysth)


Lesenswert?

MMM schrieb:
> Mein Schiebebuffer hat 6 Zeilen und ist garantiert Fehlerfrei :P. Wie
> gesagt hatte erst ja auch ein Ringbuffer drin.

Auf der Empfangsseite brauchst du einen Buffer doch nur um einen Block 
zusammen zu bauen.

Ein Rigbuffer ist eher was für den Sender.

Wenn dein Block mit einem festen EOL endet (z.b. <CR> bei Text) kannst 
du das von meinen Routinen erledigen lassen.

: Bearbeitet durch User
von MMM (st1234)


Lesenswert?

Harry L. schrieb:
> Wenn dein Block mit einem festen EOL endet (z.b. <CR> bei Text) kannst
> du das von meinen Routinen erledigen lassen.

genau, nun habe ein sonderzeichen welches ansonsten nicht vorkommen 
kann. Aber ja, für meine Anwendung genügt mein trivialer Schiebebuffer 
und macht das parsen sogar einfacher.

Anyway der Buffer ist ja nicht das Problem. Der code funktioniert ja 
grundsätzlich. Die Frage ist wieso erhalte ich nicht alle bytes?!?

von A. S. (Gast)


Lesenswert?

MMM schrieb:
> Anyway der Buffer ist ja nicht das Problem. Der code funktioniert ja
> grundsätzlich.

Nochmal: wie bekommst Du die Daten raus aus dem Puffer?

Oder anders: wie stellst Du fest, dass Daten fehlen?

von Harry L. (mysth)


Lesenswert?

MMM schrieb:
> genau, nun habe ein sonderzeichen welches ansonsten nicht vorkommen

Genau dafür gibts den data-mode in meinem Code.
Als Ergebnis bekommst du einen Pointer auf den Buffer und die Grösse in 
Bytes geliefert.
In dem Buffer sind dann ALLE empfangenen Bytes inkl. dem EOL-Char 
enthalten.

: Bearbeitet durch User
von MMM (st1234)


Lesenswert?

A. S. schrieb:
> Nochmal: wie bekommst Du die Daten raus aus dem Puffer?

SWD

A. S. schrieb:
> Oder anders: wie stellst Du fest, dass Daten fehlen?

Debug,

Einfaches bsp: sende testdaten A,B,C,D etc. und als sonderzeichen 0xFF. 
prüfe auf letzes empfangene Zeichen 0xFF und setze dann breakpoint. 
Siehe ob der buffer der reihe nach gefüllt ist. -> es fehlen vereinzelnt 
Buchstaben.

(Selbstverständlich: kein Breakpoint während des Transfers)

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

MMM schrieb:
> Harry L. schrieb:
>> Wenn dein Block mit einem festen EOL endet (z.b. <CR> bei Text) kannst
>> du das von meinen Routinen erledigen lassen.
> Anyway der Buffer ist ja nicht das Problem. Der code funktioniert ja
> grundsätzlich. Die Frage ist wieso erhalte ich nicht alle bytes?!?

Dein SW Buffer ist ja das Problem.
Du erhältst ja alle Bytes, das ist schon mal sicher.
Die werden nur nicht alle auf richtige Adressen reingeschrieben.
Warum benutzt du nicht HW FIFO, sind immerhin 16 Bytes?

von MMM (st1234)


Lesenswert?

Marc V. schrieb:
> Dein SW Buffer ist ja das Problem.

wie soll bitte der buffer das Problem sein, wenn er meistens 
funktioniert. Wenn ein zuweisungsfehler vorhanden wäre würde er nie 
korrekt funktionieren.

Marc V. schrieb:
> Du erhältst ja alle Bytes, das ist schon mal sicher.

Ach ja? Nun Aktuell siehts so aus dass nicht bei jedem Byte die ISR 
(rechtzeitig?) ausgeführt wird.

Marc V. schrieb:
> Warum benutzt du nicht HW FIFO, sind immerhin 16 Bytes?

Das ist evtl das Problem. Nun ich nutze einfach die HAL_IT funktion, und 
gebe dieser die Aufgabe jeweils 1 Byte zu empfangen. In der ISR restart. 
Dabei übergebe ich die addr einer uint_8.

Wenn natürlich die funktion ein FIFO nutzt oder zum bsp. nicht bei jedem 
Byte interrupted sondern erst das ganze 32bit Register füllt o. ä. Dann 
hätte ich genau ein Phänomen wie der beschriebene Byteverlust.

Also es geht hier nicht um eine high performance Anwendung, FIFO etc. 
sind unnötig ich möchte einfach nur bei jedem Byte meine ISR aufgerufen 
und das Byte in meiner uint_8.

Giebts beim H7 etwas spezielles zu beachten beim IOC? FIFO ein/aus etc? 
Zu beachten bei H7 USART anstelle UART?

von A. S. (Gast)


Lesenswert?

MMM schrieb:
> Siehe ob der buffer der reihe nach gefüllt ist. -> es fehlen vereinzelnt
> Buchstaben.

OK. Dann der Reihe nach:

 1. Du sendest deutlich nach Wiedereinschalten Testdaten
 2. Die Baudrate ist auf <<3% genau (also kein RC oder sowas intern, da 
würde auch 9.6 nicht laufen)
 3. Die Signale sehen gut aus (Du bist mit High und Low deutlich ober- 
und unterhalb der Umschaltschwelle)
 4. Du sperrst keine Interrupts für mehr als 100µs
 5. Der interrupt selber dauert auch nicht so lange
 6. Deine Sendequelle ist verlässlich

4 und 5 lassen sich durch niedrige Baudrate ausschließen.

Der erste Weg wäre für mich, die Uart-Infos auszuwerten. Die sagen, ob 
der Empfangspuffer überlief oder Parity/Framing falsch war.

Der zweite Weg wäre, bei immer gleichen Testdaten schauen, ob es immer 
gleiche Fehler sind.

von Sebastian (Gast)


Lesenswert?

Wenn der Schiebepuffer 6 Bytes groß ist, und manchmal jedes 6. Byte 
fehlt, dann läuft vielleicht manchmal der Schiebepuffer über ... ?

LG, Sebastian

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

MMM schrieb:
> Ach ja? Nun Aktuell siehts so aus dass nicht bei jedem Byte die ISR
> (rechtzeitig?) ausgeführt wird.

Auch bei 9600B?
Das glaubst du wohl selber nicht...

von Michael J. (jogibaer)


Lesenswert?

Hallo,

wertest Du die Error Flags der Schnittstelle auch aus?
Eventuell kannst Du daran was erkennen.
Vielleicht die ISR darum erweitern.

Jogibär

von MMM (st1234)


Lesenswert?

A. S. schrieb:
> 1. Du sendest deutlich nach Wiedereinschalten Testdaten

Genau ich sende ein Testpattern repetitiv: A, B , C ... und zum schluss 
0xFF

>  2. Die Baudrate ist auf <<3% genau (also kein RC oder sowas intern, da
> würde auch 9.6 nicht laufen)

Wird aktuell in nem FAKE F0 genereriert, gleichen Verdacht hatte ich 
auch; aber das problem besteht auch, wenn ich das Testpattern vom PC aus 
(China FTDI) sende. F0->PC Übertragungstest sieht kein Byteverlust

>  3. Die Signale sehen gut aus (Du bist mit High und Low deutlich ober-
> und unterhalb der Umschaltschwelle)

Der Fake F0 hat den high pegel etwas tief (ca. 2.8V) obwohl er mit 3.4V 
gespiesen ist.

>  4. Du sperrst keine Interrupts für mehr als 100µs

Unbekannt: Ich habe lediglich diese ISR in das gebuildete GUI template 
des H7-Disco eingebaut. Die interna des H7-Disco GFX sowie dessen RTOS, 
habe ich nicht analysiert.

>  5. Der interrupt selber dauert auch nicht so lange

Ja, usercode instruktionszahl in der ISR ist gering gegenüber den HAL 
funktionen.

>  6. Deine Sendequelle ist verlässlich

2 unterschiedliche Quellen verwendet. Beide würde ich als nicht 
zuverlässig bezeichnen. Aber beide unzuverlässigen Quellen laufen 
untereinander problemlos.
>
> 4 und 5 lassen sich durch niedrige Baudrate ausschließen.
>

9600 Baud test, zeigt das gleiche Fehlerbild

> Der erste Weg wäre für mich, die Uart-Infos auszuwerten. Die sagen, ob
> der Empfangspuffer überlief oder Parity/Framing falsch war.

Ja gute idee, da der fehler nur sporadisch auftritt: wie kann ich darauf 
geschikt breakpointen/debuggen?
>
> Der zweite Weg wäre, bei immer gleichen Testdaten schauen, ob es immer
> gleiche Fehler sind.

Genau, habe ein testpattern.

Sebastian schrieb:
> Wenn der Schiebepuffer 6 Bytes groß ist, und manchmal jedes 6. Byte
> fehlt, dann läuft vielleicht manchmal der Schiebepuffer über ... ?

Der Schiebebuffer enthält immer die letzten 6 empfangenen Bytes. In der 
ISR Prüfe ich ob das jeweils zuletzt empfangene Byte 0xFF ist. Wenn dies 
der Fall ist, dann setze ich darauf einen Breakpoint. Der Inhalt des 
Buffers muss dann entsprechend A,B,C etc. sein -> ister meistens auch -> 
nur hin und wieder fehlt einer der Buchstaben (z.b. A, C, D ...) (und da 
ein Byte weniger empfange ist in dem fall das alte 0xFF noch nicht 
überschrieben)

Marc V. schrieb:
> Auch bei 9600B?

JA
> Das glaubst du wohl selber nicht...

Eigentlich ja :-(

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

MMM schrieb:
> Marc V. schrieb:
>> Auch bei 9600B?
>
> JA
>> Das glaubst du wohl selber nicht...
>
> Eigentlich ja :-(

Bei 9600B dauert es von Byte zu Byte 1ms, selbst mit DMA.
Dass irgendein STM32 Interrupt für 2ms blockiert ist - das ist
einfach unmöglich, außer die SW sperrt es.
Also, noch einmal (meine Meinung):
Du empfängst mit Sicherheit alle Bytes, dein Problem liegt
beim schreiben ins Buffer.

von MMM (st1234)


Lesenswert?

MMM schrieb:
> Wenn dies
> der Fall ist, dann setze ich darauf einen Breakpoint.

Vergessen zu erwähnen: Testwiederholung: Breakpoint entfernen, kurz 
laufen lassen und neu setzen. Damit auch niemand auf die Idee kommt die 
verlorenen Bytes sind vom Breakpoint

von Kevin M. (arduinolover)


Lesenswert?

Warum versuchst du nicht mal mit der _IT 100 Byte (oder ähnlich) statt 1 
Byte zu empfangen und am Ende zu schauen, ob das alles korrekt ist. Wenn 
das der Fall ist, dann liegt es eindeutig an deinem Code.

Ich habe schon von F1 bis H7 mit Baudraten weit höher als das was du 
versuchen willst gearbeitet und das war nie ein Problem.

Im Übrigen haben die meisten STM (der H7 auf jeden Fall) einen Idle 
Interrupt, es ist also auch möglich der _IT Funktion eine deutlich 
größere Länge zu geben und auf den Idle der Leitung zu warten.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

MMM schrieb:
> MMM schrieb:
>> Wenn dies
>> der Fall ist, dann setze ich darauf einen Breakpoint.
>
> Vergessen zu erwähnen: Testwiederholung: Breakpoint entfernen, kurz
> laufen lassen und neu setzen. Damit auch niemand auf die Idee kommt die
> verlorenen Bytes sind vom Breakpoint

Ein kleines Programm in Visual Studio schreiben (paar Zeilen code).
Dann alle Bytes auf einmal rausfeuern, STM32 sendet empfangene Bytes
zurück nach Empfang der 0xFF.
Prüfen ob alles OK ist (kann auch Visual Studio von selbst).
Falls nötig, Abstand zwischen den Bytes vergrößern, wiederholen.

Das kannst du bis zum ersten Fehler wiederholen oder so oft du es
für nötig hältst (wenn keine Fehler auftreten)
Und brauchst nicht einmal anwesend zu sein...

von PittyJ (Gast)


Lesenswert?

Ich habe auch einen STM H743. Auf dem betreibe ich einen Uart mit 115 
Kbaud.
Auch habe ich die _IT Variante am Laufen.
Es funktioniert alles perfekt. An den HAL-Routinen liegt es nicht. Wohl 
eher an dem, wie du danach die empfangenen Bytes verteilst.

Das Forum ist leider unübersichtlich: irgendwie kann ich deinen Code 
hier nicht finden, sonst hätte ich mal geschaut.

von MMM (st1234)


Lesenswert?

Marc V. schrieb:
> Du empfängst mit Sicherheit alle Bytes, dein Problem liegt
> beim schreiben ins Buffer.


2 Fragen: wie kann dieser einfache code:

void HAL_UART_RxCpltCallback(UART_Handle *huart)
{
if(huart==&huart1){
buf[6]=buf[5];
buf[5]=buf[4];
.
.
.
buf[0]=datain;
HAL_UART_Rreceive_IT(&huart1,&datain,1);

1. falsch sein?
2. meistens funktionieren?

Das einzige wass ich denken kann:

1. kann es unter bestimmten Umständen sein, dass if(huart==&huart1) 
false ist beim empfang über USART1?

2. Die datain sowie buf Variablen von 
HAL_UART_Rreceive_IT(&huart1,&datain,1); sind uint_8, kann es unter 
irgendwelchen umständen sein (H7 HAL implementierung, bug, FIFO etc.) 
dass diese funktion abweichend von dem erwarteten Verhalten agiert (zb. 
empfang mehrer Bytes und dann übergabe als 32bit, oder als array (zb 
schreiben in nicht vorhandenes datain[1])?

3. HAL_UART_RxCpltCallback( wird nicht bei jedem byte aufgerufen?

Bestehen Fallstricke im IOC (FIFO etc, aktuell alles auf default)?

Aktuell nutze ich den CM7 und nur der NVIC des CM7 hat den USART1 
Interrupt aktiviert. CM4 ist aktuell komplett ungenutzt.

von MMM (st1234)


Lesenswert?

PittyJ schrieb:
> Es funktioniert alles perfekt. An den HAL-Routinen liegt es nicht.

zur info ich nutze ein STM32H745XI auf dem STM32H745I-DISCO und davon 
nur der CM7 core (ist ein multicore uC).

von Sebastian (Gast)


Lesenswert?

MMM schrieb:
> buf[0]=datain;

Was steht denn in datain zu diesem Zeitpunkt?

LG, Sebastian

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

MMM schrieb:
> void HAL_UART_RxCpltCallback(UART_Handle *huart)
> {
> if(huart==&huart1){
> buf[6]=buf[5];
> buf[5]=buf[4];
> .
> .
> .
> buf[0]=datain;
> HAL_UART_Rreceive_IT(&huart1,&datain,1);

1) Was ist HAL_UART_Rreceive_IT(&huart1,&datain,1);?
  Tippfehler?
2) Wie wäre es mit HAL_UART_Receive_IT(&huart1,&datain,1);
am Anfang, erst dann Buffer umkrempeln?

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


Lesenswert?

MMM schrieb:
> 2 Fragen: wie kann dieser einfache code:

ich kenne Dein Framework nicht. Was ist datain und wer setzt das?

MMM schrieb:
> Ja gute idee, da der fehler nur sporadisch auftritt: wie kann ich darauf
> geschikt breakpointen/debuggen?

Genauso wie jetzt auch. Einen "Fehlerzähler" bei jedem Fehler 
incrementieren und beim nächsten Break schauen ob es mehr sind.

MMM schrieb:
> Breakpoint entfernen, kurz
> laufen lassen und neu setzen. Damit auch niemand auf die Idee kommt die
> verlorenen Bytes sind vom Breakpoint

Das ergibt keinen Sinn. Du Sender anhalten, Debugger mit Breakpoint 
starten und dann den Sender wieder (von vorne) starten.

nochmal: Worauf triggerst Du den Breakpoint momentan?

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


Lesenswert?

MMM schrieb:
> Mein Schiebebuffer hat 6 Zeilen und ist garantiert Fehlerfrei :P. Wie
> gesagt hatte erst ja auch ein Ringbuffer drin.

Halten wir also mal fest: Deine Firmware ist der letzte Rotz, weil sie 
nicht funktioniert. Trotzdem - oder eher: deswegen - behauptest Du 
einfach, Dein Programmcode sei fehlerfrei. Ich habe schon viele Leute 
mit solch einer Einstellung gesehen, und im Allgemeinen sorgen sie damit 
für einen Teil meiner Aufträge.

Ich erinnere mich insbesondere an einen Entwickler, der genauso wenig 
wie Du zwischen Wunschvorstellungen ("Mein Code soll dieses oder jenes 
machen.") und der Realität ("Mein Code macht genau dieses oder 
jenes.") unterscheiden kann und daher lieber die Fehlerquelle bei 
Dritten sucht. Sinnvollerweise sollte man jede Zeile Code 
grundsätzlich als fehlerbehaftet ansehen, es sei denn, dass deren 
Fehlerfreiheit explizit nachgewiesen wurde, und zwar unter allen 
möglichen Bedingungen. Gerade Interruptroutinen oder ähnliche 
Programmteile, die auf dieselben Ressourcen zugreifen, müssen gegen alle 
Eventualitäten verriegelt sein.

Verwendest Du eigentlich ein RTOS auf dem Microcontroller? Dann müssen 
natürlich solche Routinen exakt dafür passend geschrieben sein.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Andreas S. schrieb:
> Ich habe schon viele Leute
> mit solch einer Einstellung gesehen, und im Allgemeinen sorgen sie damit
> für einen Teil meiner Aufträge.

Hehe.
Wir haben auch schon mehrmals dem lieben Gott an solchen
Spezialisten gedankt.

von MMM (st1234)


Lesenswert?

Sebastian schrieb:
> MMM schrieb:
>> buf[0]=datain;
>
> Was steht denn in datain zu diesem Zeitpunkt?

das empfangene Byte.

Marc V. schrieb:
> Tippfehler?

Ja tippfehler, wie schon vor langer zeit geschrieben: Code ist 
abgeschrieben, aber er compiliert ohne compiler error/warning

Marc V. schrieb:
> 2) Wie wäre es mit HAL_UART_Receive_IT(&huart1,&datain,1);
> am Anfang, erst dann Buffer umkrempeln?

schlechte idee; dann würde ich ja beginnen einen neuen transfer auf mein 
empfanenes byte zu starten bevor ich mein empfangenes byte gesichert 
habe.

HAL_UART_Receive_IT(&huart1,&datain,1); <-- dies ist der restart zum 
empfang des nächsten bytes

A. S. schrieb:
> ich kenne Dein Framework nicht. Was ist datain und wer setzt das?

datain ist eine globale uint_8 variable. Einzig 
HAL_UART_Receive_IT(&huart1,&datain,1); "schreibt" diese.

A. S. schrieb:
> nochmal: Worauf triggerst Du den Breakpoint momentan?

auf das letze empfangene byte = 0xff

Andreas S. schrieb:
> Verwendest Du eigentlich ein RTOS auf dem Microcontroller? Dann müssen
> natürlich solche Routinen exakt dafür passend geschrieben sein.

ja nutze ich, oder besser gesagt ST nutzt es für mich (TouchGFX), ich 
programiere die uart komplett am RTOS vorbei (siehe 
Diskussionshistorie).

von MMM (st1234)


Lesenswert?

Andreas S. schrieb:
> Halten wir also mal fest: Deine Firmware ist der letzte Rotz

ist zu 99.9% von ST selbst. Klar meine 10-20 reingehackten Zeilen 
beeinflussen den rotzfaktor :P

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

MMM schrieb:
> Marc V. schrieb:
>> 2) Wie wäre es mit HAL_UART_Receive_IT(&huart1,&datain,1);
>> am Anfang, erst dann Buffer umkrempeln?
>
> schlechte idee; dann würde ich ja beginnen einen neuen transfer auf mein
> empfanenes byte zu starten bevor ich mein empfangenes byte gesichert
> habe.
>
> HAL_UART_Receive_IT(&huart1,&datain,1); <-- dies ist der restart zum
> empfang des nächsten bytes

Manoman.
Probiere es erst, dann behaupte etwas.
Also, du schreibst nicht das gerade empfangene Byte ins Buffer,
sondern den Byte welches du beim letzten Aufruf empfangen hast.
Da du kein FIFO benutzt, werden alle in der Zwischenzeit empfangene
Bytes einfach überschrieben, bleibt nur das letzte empfangene Byt.
So schwer zu probieren?

: Bearbeitet durch User
von MMM (st1234)


Lesenswert?

Marc V. schrieb:
> Also, du schreibst nicht das gerade empfangene Byte ins Buffer,
> sondern den Byte welches du beim letzten Aufruf empfangen hast.


Ich schreibe das Byte wessen vollständige übertragung die ISR aufgerufen 
hat in den Buffer.
Dies bevor ich den empfang des nächsten Bytes in der gleichen ISR 
starte.

Ganz einfach: erst sichern, dann überschreiben

Und beim Schiebebuffer. Erst schieben (damit der erste platz frei wird) 
dann überschreiben.

> Da du kein FIFO benutzt, werden alle in der Zwischenzeit empfangene
> Bytes einfach überschrieben, bleibt nur das letzte empfangene Byt.

Die zwischenzeit ist ISR aufrufen, buffer schieben, daten sichern, 
danach starte ich direkt den neuen Empfang.
Klar könnte ich beschleunigen, wenn ich erst das empfangene byte 
zwischenspeichere und direkt neu starte, dann den buffer schieben und 
abspeichern. Aber an diesen paar instr. wirds wohl kaum liegen.

> So schwer zu verstehen?
?!?

von MMM (st1234)


Lesenswert?

Nun läufts (zumindest über 5 min) ohne byteverlust. Auch mit 2.25 Mbaud 
(mehr kann der F1 and diesem UART nicht).
Geändert habe ich:
USARTs über PLL2 anstelle PCLK2 versorgt.

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


Lesenswert?

MMM schrieb:
> USARTs über PLL2 anstelle PCLK2 versorgt.

also Baudrate >3% Abweichung?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

A. S. schrieb:
> MMM schrieb:
>> USARTs über PLL2 anstelle PCLK2 versorgt.
>
> also Baudrate >3% Abweichung?

Glaube aber nicht, dass dies die Ursache sein kann.
HSI hat max. 1% Fehler.
Und soweit ich mich erinnere, werden PLLs aus HSI generiert, macht
also keinen Unterschied.
Kann mich aber auch irren.

: Bearbeitet durch User
von Harry L. (mysth)


Lesenswert?

Marc V. schrieb:
> Glaube aber nicht, dass dies die Ursache sein kann.
> HSI hat max. 1% Fehler.
> Und soweit ich mich erinnere, werden PLLs aus HSI generiert, macht
> also keinen Unterschied.

Sehe ich genauso.

Marc V. schrieb:
> Kann mich aber auch irren.

Nein, du irrst dich nicht.

von A. S. (Gast)


Lesenswert?

Marc V. schrieb:
> Und soweit ich mich erinnere, werden PLLs aus HSI generiert, macht
> also keinen Unterschied.

Ich kenne den Chip nicht. Aber die geänderte Uart-Clock sollte doch auf 
den Rest der SW keine Auswirkung haben.

Ist vielleicht ein Teiler neu zu setzen mit jetzt besserer Auflösung? Es 
hat ja kaum jemand mehr einen Sio-Quarz (mit Vielfachen von 1.8432 MHz)

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

A. S. schrieb:
> Ich kenne den Chip nicht. Aber die geänderte Uart-Clock sollte doch auf
> den Rest der SW keine Auswirkung haben.

Hardware hat mit seinem fehlerhaften Empfang nichts zu tun, da bin
ich mir 99.9% sicher.
Es ist einfach unmöglich, dass STM32 bei 9600B Bytes verliert
und die HW dafür verantwortlich ist.

: Bearbeitet durch User
von Harry L. (mysth)


Lesenswert?

Marc V. schrieb:
> Es ist einfach unmöglich, dass STM32 bei 9600B Bytes verliert
> und die HW dafür verantwortlich ist.

Sehe ich genauso.
Seine Software -die er vermutlich aus gutem Grund nicht zeigt-
ist einfach völliger Murks.

: Bearbeitet durch User
von PittyJ (Gast)


Lesenswert?

Marc V. schrieb:
> A. S. schrieb:
>> Ich kenne den Chip nicht. Aber die geänderte Uart-Clock sollte doch auf
>> den Rest der SW keine Auswirkung haben.
>
> Hardware hat mit seinem fehlerhaften Empfang nichts zu tun, da bin
> ich mir 99.9% sicher.
> Es ist einfach unmöglich, dass STM32 bei 9600B Bytes verliert
> und die HW dafür verantwortlich ist.

Da wäre ich mir nicht so sicher.
Ich habe einen H743. Und bei dem habe ich letztens einen Tag daran 
gesessen, die CPU Frequenz von den Default 64 Mhz etwas zu erhöhen. Und 
dann kommt man bei der Cube-IDE auf die Konfigurationsseite mit 50 
Möglichkeiten. Dann werden intern Frequenzen generiert. Aber z.B. für 
das AD-Subsystem muss wieder etwas anderes ausgewählt werden. Da gibt es 
so viele Kombinationen, es ist nicht einfach. Die Sektion im Handbuch 
alleine dafür ist ca 100 Seiten.

Vielleicht hatte der TE einfach initial da nur ein falsches Bit gewählt, 
und es funktionierte dann nur leidlich.

von STK500-Besitzer (Gast)


Lesenswert?

PittyJ schrieb:
> Da gibt es
> so viele Kombinationen, es ist nicht einfach. Die Sektion im Handbuch
> alleine dafür ist ca 100 Seiten.

Dafür gibt es doch STM32CubeMX.

von mitlesa (Gast)


Lesenswert?

Harry L. schrieb:
> Sehe ich genauso.

Sehe ich genauso.

mitlesa schrieb:
> Kann nur von meinen F103 mit schlappen 72 MHz berichten.

von A. S. (Gast)


Lesenswert?

Marc V. schrieb:
> Hardware hat mit seinem fehlerhaften Empfang nichts zu tun,

Naja, HW hieße falsche Quarzfrequenz. Die Baudrate wird durch SW 
bestimmt. Und da sind sowohl Auflösungsprobleme (z.b. nur 14 oder 15 
möglich, nicht 14,46) als auch Off by one (TO ist Anfänger) nicht selten

von mitlesa (Gast)


Lesenswert?

A. S. schrieb:
> Naja, HW hieße falsche Quarzfrequenz.

Nein! Hardware heisst Hardware, und damit sind dann viele
verschiedene Komponenten betroffen. Quarz bzw. Taktfrequenz
ist nur eine davon.

Vom Verbindungs-Aufbau, also der Schaltung zwischen den
Übertragungspartnern hat noch keiner geredet.

von ST M. (stmmmm)


Lesenswert?

Wenn die Wahl der Clockquelle ein Packetverlustproblem auslöst sehe ich 
das problem STM intern an der paralellen Datenübergabe (clock domains).
Wäre seltsam wenn dies ST durch die latten gegangen wäre bei der 
Designfreigabe, aber HW bugs existieren leider auch immer wieder mal.

A. S. schrieb:
> also Baudrate >3% Abweichung?

bei falscher Baudrate würden andere Übertragungsprobleme auftreten

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


Lesenswert?

MMM schrieb:
> Andreas S. schrieb:
>> Halten wir also mal fest: Deine Firmware ist der letzte Rotz
>
> ist zu 99.9% von ST selbst. Klar meine 10-20 reingehackten Zeilen
> beeinflussen den rotzfaktor

Nun, ich würde das nicht so unspeziell mit "Rotz" betiteln, aber eines 
steht fest: Das Ganze ist recht unüberlegt gemacht - sowohl von ST als 
auch von dir. So etwas fängt bei deinem Grund-Entwurf an:

MMM schrieb:
> Nun läufts (zumindest über 5 min) ohne byteverlust. Auch mit 2.25 Mbaud
> (mehr kann der F1 and diesem UART nicht).

Hältst du so eine Kapriole für etwas Gutes? Es geht so manches zu 
machen, aber ob man das auch tatsächlich tun sollte, ist eine ganz 
andere Frage. Wenn du Daten mit so etwa 250 KBytes/s durch die Gegend 
schicken willst, dann wäre ein anderes Interface als UART wohl eher in 
die engere Wahl zu ziehen.

Und noch ein Wort zu UART-Treibern im µC:
Die Übertragung ist asynchron und zumindest das Empfangen hängt nicht 
vom Empfänger ab, sondern davon, ob und wann ein Sender sich dazu 
bequemt, Daten zu schicken. Folglich ist es eigentlich ganz klar, daß 
der Empfangstreiber im µC einen Zwischenpuffer vorhalten muß, um eben 
das unvorhersehbare Hereinrauschen von Daten zu entkoppeln vom 
Hauptprogramm, weil selbiges möglicherweise gerade mit anderem befaßt 
ist. Und wie groß der Puffer sein muß, hängt davon ab, wie lange es 
dauern kann, bis das Hauptprogramm wieder mal nach Daten vom UART 
nachfragt. So etwas zu bedenken, bevor man in die Tasten haut und 
Quelltext schreibt, sollte einem Programmierer eigentlich geläufig sein. 
Und wenn man dann an den Quelltexten von ST ändern muß, um sich einen 
ausreichend großen Puffer zu verschaffen, dann tut man das eben - und 
zwar bevor man hier wehklagt "es geht nicht".

W.S.

von Stefan F. (Gast)


Lesenswert?

W.S. schrieb:
> etwas zu bedenken, bevor man in die Tasten haut

widerspricht dem agilen Ansatz, der in den vergangenen Jahren als 
Heilbringer der IT propagiert wurde. In dem Umfeld ist es ziemlich still 
geworden, fällt mir gerade auf.

von Harry L. (mysth)


Lesenswert?

W.S. schrieb:
> Und wenn man dann an den Quelltexten von ST ändern muß, um sich einen
> ausreichend großen Puffer zu verschaffen, dann tut man das eben

Womit du wieder ein mal unter Beweis gestellt hast, daß du die ST-HAL 
über die du so gerne meckerst, nicht einmal im Ansatz kennst und/oder 
verstanden hast.

Die HAL selbst stellt nämlich gar keine Buffer zur Verfügung, und das 
ist auch nicht der Anspruch.

Das Buffering ist vollständig die Aufgabe des Programmierers.

Wie sowas im Fall des UART aussehen kann, habe ich hier gezeigt:
Beitrag "[STM32/HAL] simples U(S)ART-Library"

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


Lesenswert?

Harry L. schrieb:
> Die HAL selbst stellt nämlich gar keine Buffer zur Verfügung, und das
> ist auch nicht der Anspruch.
>
> Das Buffering ist vollständig die Aufgabe des Programmierers.

Und wozu dient dann das ganze Zeug, was ihr "HAL" nennt?
Wozu es für ST taugt, das ist mir klar - aber für diejenigen, die sich 
dort selbst drangenagelt haben? Ist sowas ne Art Masochismus?

Wenn man ohnehin alles selber machen soll, dann ist es besser, den 
ganzen Kram von ST wegzulassen. Das macht die ganze Firmware 
übersichtlicher und sauberer.

Aber es gibt ja auch Leute, die stolzgeschwellt hier verkünden "ich 
programmiere nicht auf Registerebene" - will sagen, er ist sich zu fein, 
selber irgend etwas zu machen, zum Beispiel ein Register der Peripherie 
seines µC zu lesen oder gar zu schreiben.

W.S.

von Harry L. (mysth)


Lesenswert?

W.S. schrieb:
> Und wozu dient dann das ganze Zeug, was ihr "HAL" nennt?

Es ist nicht meine Aufgabe, dir das zu erklären; nur so viel:
Man kann problemlos einen anderen STM32 nutzen, ohne auch nur eine Zeile 
Code ändern zu müssen.

Ansonsten bist du doch derjenige, der dauern am lautesten RTFM 
schreit.
Solltest du vielleicht selber auch mal machen!

von Stefan F. (Gast)


Lesenswert?

Harry L. schrieb:
> Man kann problemlos einen anderen STM32 nutzen, ohne auch nur eine Zeile
> Code ändern zu müssen.

Im Idealfall: ja.

In der Praxis: eher nicht, es sei denn der "andere" ist aus der gleichen 
Serie. Das würde aber auch ohne HAL fast genau so problemlos gehen.

Zweifellos kann man mit dem Code-Generator recht schnell ein neues 
Projekt starten und die mitgelieferten Bibliotheken nutzen. Zum Beispiel 
für USB, die saugt sich niemand "mal eben schnell" aus dem Ärmel.

von Harry L. (mysth)


Lesenswert?

Stefan F. schrieb:
> Harry L. schrieb:
>> Man kann problemlos einen anderen STM32 nutzen, ohne auch nur eine Zeile
>> Code ändern zu müssen.
>
> Im Idealfall: ja.

Anders herum wird ein Schuh daraus - in wenigen Ausnahmefällen geht es 
nicht so einfach.

von W.S. (Gast)


Lesenswert?

Harry L. schrieb:
> W.S. schrieb:
>> Und wozu dient dann das ganze Zeug, was ihr "HAL" nennt?
>
> Es ist nicht meine Aufgabe, dir das zu erklären; nur so viel:
> Man kann problemlos einen anderen STM32 nutzen, ohne auch nur eine Zeile
> Code ändern zu müssen.

Das ist eine doch recht dünne Argumentation. Man kann also sein "Hello 
World" ohne Quelländerung auf verschiedenen STM32 machen. Bloß dann, 
wenn man eine tatsächlich echte Firmware für ein Gerät machen will, wird 
man gezwungen sein, einen µC zu benutzen, der dazu auch in der Lage ist, 
weil er über die Peripherie/Ressourcen verfügt, die für's Projekt 
erforderlich ist. Dann ist es aus mit "man kann problemlos...".

Und wenn der Ersatz-µC dann zwar die nötige Peripherie hat, aber von 
einem anderen Hersteller ist und vielleicht nicht einmal ein Cortex-M, 
dann stehst du erstmal dumm da. Also dein Argument ist eher eine Ausrede 
als ein Argument.

> Ansonsten bist du doch derjenige, der dauern am lautesten RTFM
> schreit.
> Solltest du vielleicht selber auch mal machen!

Tu ich auch, aber vor allem das Refman zum jeweiligen Chip. Mich hatte 
es schon bei der unsäglichen ST-Lib gegraust, weil sie eben auch schon 
einen Haufen von Formalien erzeugte, ohne dabei von irgendeinem Nutzen 
zu sein.

Und ich sag's hier noch einmal: Lowlevel-Treiber sollen dem 
Programmierer die Arbeit erleichtern, indem sie ihm Schnittstellen für 
Standard-Aufgaben liefern, die eben nicht hersteller/chip-orientiert 
sind, sondern die problemorientiert sind. Und dazu gehört hier beim UART 
oder USART im gewöhnlichen Falle eben auch das sinnvolle 
Zwischenspeichern zwecks Entkopplung, wie ich das weiter oben schon 
erläutert habe.

So, und nun versuche du mal, deinen Horizont zu erweitern. Hast du 
nötig.

W.S.

von J. S. (jojos)


Lesenswert?

Viele andere OS die ohne STM HAL auskommen sind genauso aufgebaut: 
dünner HAL mit init/deinit und read/write Funktion und darauf bauen 
FIFOs / Queues usw auf.
Deine Welt ist sehr klein.

von Harry L. (mysth)


Lesenswert?

W.S. schrieb:
> So, und nun versuche du mal, deinen Horizont zu erweitern. Hast du
> nötig.

Nö!

Damals in den 80/90er hab ich auch so wie du heute noch gearbeitet, 
aber, die Welt hat sich seitdem weiter gedreht.

Du kennst die HAL nicht (s.o.), willst dir die auch nicht näher 
anschauen, aber glaubst hier weise Ratschläge geben zu können und alles 
besser zu wissen, weil du das wohl in der Steinzeit mal so gelernt hast.

Sowas ist einfach nur noch peinlich...
Das kann man nur noch unter Alters-Starrsinn verorten.

Wer nicht mit der Zeit geht, der geht eben mit der Zeit...

von Harry L. (mysth)


Lesenswert?

Und noch Eins @W.S.

Deine arrogante Art kannst du dir sonstwohin stecken!

Ich hab ähnlich wie du (vermutlich) in den 70er meine ersten 
µC-Programme mit einem selbstgebauten Eprommer (mit 18 Schaltern - 10 
für die Adresse und 8 für die Daten) in ein 2708er EPROM geschossen - 
natürlich in binär.

Also, um meinen Horizont musst du dir keine Sorgen machen.

Nur hab ich mich nicht auf meinen Lorbeeren ausgeruht, und bin sehr 
glücklich über moderne Werkzeuge, die mir meine Arbeit erheblich 
erleichtern.

HAL ist eines dieser Werkzeuge.

Dadurch kann ich mich heute auf die eigentliche Applikation 
konzentrieren und muss mich nicht mit Bitfrickelein auf unterster Ebene 
herum schlagen.

Das verkürzt die Entwicklungszeiten erheblich.

Und wenn das nen kB mehr Flash verbraucht - who cares?
Speicher kostet nix mehr.

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


Lesenswert?

Harry L. schrieb:
> Nö!
>
> Damals in den 80/90er hab ich auch so wie du heute noch gearbeitet,
> aber, die Welt hat sich seitdem weiter gedreht.

Naja, es sind all die Leute hinzugekommen, die dank Arduino von sich 
meinen, sie könnten auch mal Projekte mit einem µC machen. Das geht 
auch, wenn man genau das macht, was einem fertige Shields und dazu 
passende Bibliotheksfunktionen benutzt. Ist OK so für Leute, die damit 
bloß spielen wollen. Aber das als eine Art Höherentwicklung anzusehen, 
ist ein bissel daneben. Genauso wie das Aufkommen von Holzbastlern 
versus gelernten Zimmerleuten.

Harry L. schrieb:
> Wer nicht mit der Zeit geht, der geht eben mit der Zeit...

Naja, ich sehe das ähnlich, aber in größerem Maßstab: Wohlstand macht 
offenbar träge und wenn es irgendwann hier nur noch die Bastler gibt, 
dann spielt die Musike und der technische Fortschritt eben in anderen 
Ländern.

Harry L. schrieb:
> Und noch Eins @W.S.
> Deine arrogante Art kannst du dir sonstwohin stecken!

O ha, da gibt es 2 Sprüche dazu:
1. getroffene Hunde bellen.
2. Größe wird aus der Zwergenperspektive oft als Arroganz 
fehlinterpretiert.

Kommen wir mal auf's Thema zurück:
Der TO hat mit seinem Softwareaufbau eben deftige Datenverluste und die 
sind nach seiner Auskunft unabhängig von der Baudrate. Hätte er einen in 
sich geschlossenen und ausgetesteten Treiber für seinen UART, dann wäre 
das eben nicht so.
Aber er programmiert eben mit diesem HAL-Zeugs herum und dort hat es 
keine derartigen Treiber, sondern ST überläßt dem Programmierer der 
Firmware, sich sowas selbst zu programmieren. Und da hat er sich ganz 
offensichtlich recht ungeschickt angestellt und obendrein schleppt er 
noch HAL-Funktionen mit herum, die in erster Linie als Ballast 
fungieren, also so etwa wie ein Schäufelchen Sand im Getriebe.
Das Ganze IST eine Fehlkonstruktion und das muß man ST anlasten, denn 
die haben die Grundlage dafür geschaffen.

W.S.

von W.S. (Gast)


Lesenswert?

Nachtrag:
W.S. schrieb:
> ... Bibliotheksfunktionen benutzt.
soll heißen:
... Bibliotheksfunktionen vorgeben, benutzt.

W.S.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

W.S. schrieb:
> Aber er programmiert eben mit diesem HAL-Zeugs herum und dort hat es
> keine derartigen Treiber, sondern ST überläßt dem Programmierer der
> Firmware, sich sowas selbst zu programmieren. Und da hat er sich ganz
> offensichtlich recht ungeschickt angestellt und obendrein schleppt er
> noch HAL-Funktionen mit herum, die in erster Linie als Ballast
> fungieren, also so etwa wie ein Schäufelchen Sand im Getriebe.

Das hat etwa genauso viel Sinn wie wenn jemand über Windows
meckern würde.
Du weisst doch gar nicht, was Windoof alles macht, was überhaupt
nötig ist, um ein einfaches printf auszuführen, bzw. wie stdio
das macht.
Und es interessiert auch keine Sau, keiner kommt auf die Idee,
LL Routinen dazu zu schreiben.
Du verlässt dich einfach drauf, dass dein Compiler es schon
richtig macht.

Warum glaubst du dann, dass HAL es schlechter macht?
Weil ein paar Besserwisser es so behauptet haben?
Nur Leute die sich auf ein bestimmtes uC Typ spezialisiert haben,
können es sich leisten, mit diesen Unmengen von Registern und
dazugehörigen bits, wie das beim STM der Fall ist, direkt zu hantieren.
Als ich mit Bluepill anfing, habe ich HAL benutzt, niemals
irgendwelche Probleme gehabt, ob es aber so optimal war,
weiss ich nicht, bei der Geschwindigkeit kam es mir bestimmt nicht
auf ein paar Bytes und ns an.

: Bearbeitet durch User
von PittyJ (Gast)


Lesenswert?

W.S. schrieb:
> Aber er programmiert eben mit diesem HAL-Zeugs herum und dort hat es
> keine derartigen Treiber, sondern ST überläßt dem Programmierer der
> Firmware, sich sowas selbst zu programmieren. Und da hat er sich ganz
> offensichtlich recht ungeschickt angestellt und obendrein schleppt er
> noch HAL-Funktionen mit herum, die in erster Linie als Ballast
> fungieren, also so etwa wie ein Schäufelchen Sand im Getriebe.
> Das Ganze IST eine Fehlkonstruktion und das muß man ST anlasten, denn
> die haben die Grundlage dafür geschaffen.
>

Sorry, sehe ich genau andert herum.
Ich muss den Uart Initialisieren mit

HAL_UART_Init(&m_HandleUart);

danach kann ich den Uart benutzen mit

HAL_UART_Transmit 
(&m_HandleUart,(uint8_t*)cp_String,i_Length,HAL_MAX_DELAY);

Das sind 2 Zeilen, und alles geht. Innerhalb einer halben Stunde hat man 
den Uart am Laufen. Da brauche ich nichts mehr selber programmieren,
Bei SPI geht das fast genau so.

Ich nehme nur noch HAL.

von J. S. (jojos)


Lesenswert?

W.S. schrieb:
> Ist OK so für Leute, die damit
> bloß spielen wollen.

CubeMX/HAL wird auch von Profis in kommerziellen Projekten genutzt. Die 
Leute sind nicht so blöde wie du alle HAL Nuter hinstellst, das ist 
einfach nur hochnäsig.

W.S. schrieb:
> Kommen wir mal auf's Thema zurück:
> Der TO hat mit seinem Softwareaufbau eben deftige Datenverluste und die
> sind nach seiner Auskunft unabhängig von der Baudrate. Hätte er einen in
> sich geschlossenen und ausgetesteten Treiber für seinen UART, dann wäre
> das eben nicht so.

du verdrehst die Tatsachen bzw. hast wieder nur das Problem gelsen, aber 
nicht die Auflösung. Und die war ein falsch konfigurierter Takt. Damit 
kann man noch so viele tolle Fifos einbauen, wenn Zeichen nicht richtig 
gelesen werden, dann kommen sie auch im Fifo falsch an. Die Callbacks 
für die Fehlerbehandlung werden ja meist vernachlässigt, hier hätte man 
einen Fehlerzähler implementieren können und vermutlich Framing oder 
Parity Error hochzählen sehen können.
HAL liefert n Zeichen, ob man ein Fifo oder wasauchimmer haben möchte 
ist dem Anwender überlassen und er kann einen Fifo drausetzen wenn er 
möchte, siehe Code von Harry. In vielen Fällen funktioniert auch einfach 
das blockweise lesen mit Timeout. So habe ich über 15 Jahre mit 
verschieden SPS geschwätzt, rock solid in 24*7 Anwendungen die kein 
Spielzeug sind. Das es also nur mit direkt eingebauten Fifos gehen kann 
ist deine exklusive Meinung.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Framing Error und Parity kann man leicht auswerten. Man muß es nur 
machen.
Und bei längeren Blöcken sollte der Sender immer auf 2 Stopbits 
eingestellt werden. Dann kann der Empfänger nicht die Synchronisation 
verlieren, wenn der Sendetakt geringfügig höher ist.

von Peter D. (peda)


Lesenswert?

MMM schrieb:
> Geändert habe ich:
> USARTs über PLL2 anstelle PCLK2 versorgt.

Eine schlecht konfigurierte PLL kann mit ihrem Jitter die UART 
nachhaltig stören. Die lt. Datenblatt erlaubten Bereiche für 
Multiplikator und Teiler sollte man nie bis an die Grenzen ausnutzen, 
sondern möglichst in der Mitte bleiben.

Auch kann es Probleme geben, wenn CPU-Takt und Peripherietakt kein 
ganzzahliges Verhältnis zueinander haben. Es kann dann zu metastabilen 
Zuständen beim Datenaustausch kommen.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Peter D. schrieb:
> Eine schlecht konfigurierte PLL kann mit ihrem Jitter die UART
> nachhaltig stören.

Selbstverständlich.
Aber, dass etwas mit PLL funktioniert, aber nicht mit Takt aus
dem die PLL generiert wird, ist eine äußerst dumme Behauptung,
darum ging es.
Vor allem bei 9600B.

von W.S. (Gast)


Lesenswert?

J. S. schrieb:
> Das es also nur mit direkt eingebauten Fifos gehen kann
> ist deine exklusive Meinung.

Man kann auch pollen. Da braucht man überhaupt keinen Speicher 
dazwischen. Aber das setzt einen etwas anderen Firmwareaufbau voraus.

J. S. schrieb:
> HAL liefert n Zeichen, ob man ein Fifo oder wasauchimmer haben möchte
> ist dem Anwender überlassen

Soso, HAL liefert n Zeichen. Nein, irgend ein Sender am anderen Ende der 
Strippe sendet x Zeichen und zwar in einer zeitlichen Abfolge, wie es 
ihm gefällt - und der gesamte Empfangstrakt muß sich danach richten, 
sonst kommt es zu Überläufen oder zu Timeouts, wenn er zu ungeduldig 
ist. So herum und nicht anders. Es gibt bei einer Übertragung per UART 
keine eingebaute Flußsteuerung, weswegen es für Modemzwecke notwendig 
war, so etwas mit Zusatzsignalen nachzurüsten (CTS, RTS und Konsorten). 
Aber bei den meisten µC-Anwendungen wird so etwas nicht benutzt.

J. S. schrieb:
> In vielen Fällen funktioniert auch einfach
> das blockweise lesen mit Timeout. So habe ich über 15 Jahre mit
> verschieden SPS geschwätzt,...

Und jetzt willst du hier erzählen, daß ein UART ein blockorientiertes 
Ding ist? Tja, "tausendmal berührt, tausendmal ist nix passiert..." 
fällt mir dabei ein. Oder von Otto: "auch ich habe eine geweihte 
Christus-Plakette an meiner Orgel - und ich bin noch NIE mit einer 
anderen Orgel zusammengestoßen".

Mal ganz grundsätzlich: Übertragungen mit Einzelsynchronisierung der 
Zeichen sind von Hause aus keine Blockübertragungen.

W.S.

von sampler (Gast)


Lesenswert?

Peter D. schrieb:
> Und bei längeren Blöcken sollte der Sender immer auf 2 Stopbits
> eingestellt werden. Dann kann der Empfänger nicht die Synchronisation
> verlieren, wenn der Sendetakt geringfügig höher ist.

Das ist nicht richtig!

Die Blocklänge ist nicht relevant da jedes einzelne Byte neu
sychronisiert wird. Siehe auch Thema Oversampling bei UARTs.
Solange das einzelne Byte richtig erkannt wird ist die
Taktfrequenz nicht von Bedeutung.

Falls ich was übersehen haben sollte bitte ich um Aufklärung.

von W.S. (Gast)


Lesenswert?

Peter D. schrieb:
> Auch kann es Probleme geben, wenn CPU-Takt und Peripherietakt kein
> ganzzahliges Verhältnis zueinander haben. Es kann dann zu metastabilen
> Zuständen beim Datenaustausch kommen.

Da holst du aber weit aus, denn so etwas für die chipinternen Takte 
hinzukriegen, ist Obliegenheit des Herstellers. Ich habe sowas bei den 
Kinetis von Freeescale erlebt, wo der von der FLL (so heißt deren 'PLL') 
gelieferte Takt für den USB zu sehr jittert, weswegen der Hersteller 
rät, den internen RC-Oszillator zu verwenden, da dieser weniger jittert 
als der aus dem Quarzoszillator per FLL gewonnene Takt. Da der 
RC-Oszillator aber insgesamt nicht frequenzstabil genug ist, muß er 
zuvor anhand der Signale auf dem USB auf die richtige Frequenz gebracht 
werden. Da kommt Freude auf...

Allerdings ist das alles für einen UART herzlich unkritisch. Und die 
Probleme des TO liegen wohl an ganz anderer Stelle, siehe:

MMM schrieb:
> if(huart==&huart1){
> buf[6]=buf[5];
> buf[5]=buf[4];
> ...

Ich lasse das hier mal unkommentiert. Es spricht für sich.

W.S.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

sampler schrieb:
> Das ist nicht richtig!

Kommt darauf an.
Starbit wird bei fallender Flanke erkannt.
Deswegen gibt es auch ein Zeitpunkt bei dem Startbit von nächsten
Byte mit Sicherheit erkannt wird.
Falls Sender schneller getaktet wird als Empfänger, kann es passieren,
dass die fallende Flanke vom nächsten Startbit nicht richtig erkannt 
wird.
Äußerst selten, aber möglich, also doch richtig.

: Bearbeitet durch User
von sampler (Gast)


Lesenswert?

Marc V. schrieb:
> Kommt darauf an.

Was hat das dann mit der Blocklänge zu tun? Das nächste Byte
kann demnach (nach deiner Beschreibung, die möglich erscheint)
erkannt werden oder nicht, unabhängig von der Blocklänge. PeDa
bezieht sich ja auf längere Blöcke die anfälliger für fehler-
hafte Übertragungen sein sollen, und das ist einfach Käse.

Sind zwei oder drei Bytes schon "längere Blöcke"?

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

sampler schrieb:
> Die Blocklänge ist nicht relevant da jedes einzelne Byte neu
> sychronisiert wird.

Im Prinzip richtig, aber Blöcke werden typisch ohne Lücke zwischen den 
Bytes gesendet.
Eine UART macht typisch 3-fach Abtastung beim 8, 9 und 10. Subbit 
(1/16Bit). Erst danach kann sie das nächste Startbit (H-L-Flanke) 
erkennen. Es ist also weniger als 0,5 Bitzeit Reserve. Und da nur auf 
die Startflanke synchronisiert wird, akkumuliert sich der Fehler bei 
jedem Bit. Bei Start + 9Bit Daten + Parity + Stop sind das 12 Bitzeiten.
Ist der Sender nur etwas zu schnell, geht das nächste Startbit verloren. 
Ein weiteres Stoppbit gibt dann deutlich mehr Luft für 
Timingabweichungen.

Im ATmega8 Datenblatt ist der kritische Abschnitt sehr schön erklärt.

von sampler (Gast)


Lesenswert?

Peter D. schrieb:
> Im Prinzip richtig, aber Blöcke werden typisch ohne Lücke zwischen den
> Bytes gesendet.

sampler schrieb:
> Was hat das dann mit der Blocklänge zu tun?

Dein geschildertes Problem tritt bei jeder Blocklänge auf, nicht
nur bei "längere Blöcken".

von Peter D. (peda)


Lesenswert?

sampler schrieb:
> PeDa
> bezieht sich ja auf längere Blöcke die anfälliger für fehler-
> hafte Übertragungen sein sollen, und das ist einfach Käse.

Das Abtasten des Startbits ist ja nicht synchron zum Sender. Je länger 
lückenlos gesendet wird, umso wahrschenlicher ist es, mal in die 
kritische Zeit zu kommen. Die Blocklänge hat daher durchaus Einfluß auf 
die Fehlerhäufigkeit. Nur wenn der relative Fehler klein genug ist, 
spielt die Blocklänge keine Rolle.
Ich stelle daher die Baudrate so ein, daß der Rundungsfehler <0,5% ist. 
Z.B. bei 8MHz Quarz und 38400Baud ist der Fehler 0,16%.
Die oben genannten 3% je Teilnehmer ergeben max 6% von Sender zu 
Empfänger, sind daher völlig ungenügend.

von PittyJ (Gast)


Lesenswert?

an Herr W.S. und die anderen Oberlehrer hier.

Es fehlen wirklich Lehrer an den Schulen für Informatik, Mathematik und 
Technik.
Warum nehmt ihr nicht euer Wissen und euer Kommunikationsbedürfnis und 
geht als Lehrer an die Schulen. Dort sind bedürftige Menschen, denen das 
ganze KnowHow fehlt. Denen könnt ihr von den Basis aufwärts das gesamte 
Fachwissen vermitteln.
Und dann werden wir nie wieder Fragende in diesem Forum haben, die 
einmal einen Fehler gemacht haben.

Anstelle hier auf einzelnen Leuten herum zu reiten, bildet doch ein die 
Jugend zu besseren Programmierern aus.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

sampler schrieb:
> Marc V. schrieb:
>> Kommt darauf an.
>
> Was hat das dann mit der Blocklänge zu tun? Das nächste Byte
> kann demnach (nach deiner Beschreibung, die möglich erscheint)
> erkannt werden oder nicht, unabhängig von der Blocklänge. PeDa
> bezieht sich ja auf längere Blöcke die anfälliger für fehler-
> hafte Übertragungen sein sollen, und das ist einfach Käse.
>
> Sind zwei oder drei Bytes schon "längere Blöcke"?

Nein, aber alles darüber ist.
Aber, wie schon gesagt, solche Fälle sind äußerst selten, kommen
praktisch nur bei senden per DMA vor.
Deswegen gibt es auch zwei Flags fürs senden, einmal wenn DR empty
ist und einmal when das zu sendende Byte komplett rausgeschoben ist.
Wenn nicht per DMA gesendet wird, benutzen vorsichtige Leute Flag
für "Transmit Complete" und nicht "Data Register Empty".
Zumindest wenn die Möglichkeit besteht, dass Sender und Empfänger
nicht ganz synchron laufen.

von W.S. (Gast)


Lesenswert?

sampler schrieb:
> Peter D. schrieb:
>> Und bei längeren Blöcken sollte der Sender immer auf 2 Stopbits
>> eingestellt werden. Dann kann der Empfänger nicht die Synchronisation
>> verlieren, wenn der Sendetakt geringfügig höher ist.
>
> Das ist nicht richtig!
>
> Die Blocklänge ist nicht relevant...
> Falls ich was übersehen haben sollte bitte ich um Aufklärung.

Bittesehr. Du theoretisierst und der Peter hat Recht. Ich kann das aus 
praktischer Erfahrung mit diversen USB/Seriell-Umsetzern bestätigen.

Bedenke mal, daß die Takte von zwei voneinander unabhängigen Geräten 
niemals völlig gleich sind und wenn dann vielleicht bei einem der Takt 
aus Kostengründen nur aus einem RC-Oszillator gewonnen wird, dann ist es 
sogar relativ wahrscheinlich, daß es irgendwann mal zur 
Fehlsynchronisation führen mag, wenn genügend Bits direkt nacheinander 
gesendet werden, ohne daß es irgend eine Idle-Zeit dazwischen gibt.

W.S.

von W.S. (Gast)


Lesenswert?

Marc V. schrieb:
> Aber, wie schon gesagt, solche Fälle sind äußerst selten, kommen
> praktisch nur bei senden per DMA vor.

Gilt nicht - jedenfalls bei dem UART-Core, der bei den STM32 verwendet 
wird. Dort kommt der TX-Leer-Interrupt bereits dann, wenn das 
Vorhalte-Register vor dem eigentlichen Sende-Schieberegister leer ist. 
Man hat dadurch eine Byte-Sendezeit Vorhalt, um ein Byte nachzuschieben 
und das erfolgt auch bei gewöhnlichem Interrupt-Regime ausreichend 
rechtzeitig. Und da sendet der TX eben Bit an Bit ohne jegliche 
Wartezeit dazwischen. Und wenn beim Polling das Warten auf das vorherige 
Zeichen vor dem Schreiben des aktuellen Zeichens in den TX stattfindet, 
dann ist es auch beim Polling so.

W.S.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

W.S. schrieb:
> Dort kommt der TX-Leer-Interrupt bereits dann, wenn das
> Vorhalte-Register vor dem eigentlichen Sende-Schieberegister leer ist.

Das ist bei allen uC so, das ist "Data Register Empty" Interrupt,
deswegen gibt es auch zwei Interrupts:

Marc V. schrieb:
> Deswegen gibt es auch zwei Flags fürs senden, einmal wenn DR empty
> ist und einmal when das zu sendende Byte komplett rausgeschoben ist.
> Wenn nicht per DMA gesendet wird, benutzen vorsichtige Leute Flag
> für "Transmit Complete" und nicht "Data Register Empty".

Im Prinzip schreiben wir alle 3 dasselbe, kein Grund für
unnötige Diskussionen.

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.