Forum: Mikrocontroller und Digitale Elektronik LwIP + TCP + RTOS + netconn - unerwartetes Verhalten


von Albert F. (Gast)


Lesenswert?

Moin zusammen,

vielleicht ist jemand schlauer als ich (ganz bestimmt!).

Ich habe ein Task in RTOS der zyklisch Daten sendet, aus den Speicher 
ueber TCP. Sieht mehr oder weniger so aus (abgekuerzt):
1
while(1)
2
{
3
4
netconn_write(server_conn, (const unsigned char*)data_2, 136000, NETCONN_NOCOPY);
5
6
/** Delay ist ~ 100 ms. **/
7
8
vTaskDelay(xDelay);
9
}

Laeuft alles so gut, und TCP kann die Daten wieder aufbauen bei 
verlorene Pakete.

Nun, wenn ich eine kleine for-Schleife hinzufuege, bevor ich die Daten 
wegschicke, bricht alles ab und wird sehr langsam, als in, 10-fach 
langsamer:
1
while(1)
2
{
3
  for(i = 0; i < 10; i++){
4
    data[340 * i] = HAL_GetTick();
5
    data[340 * i + 1] = seqNumber;
6
    seqNumber++;
7
  }
8
9
  netconn_write(server_conn, (const unsigned char*)data_2, 136000, NETCONN_NOCOPY);
10
11
  vTaskDelay(xDelay);
12
}

Das wuerde mich wunder wenn die Schleife sehr gross waere, allerdings 
bei 10 finde ich das sehr komisch.

Irgendwelchen Optimierungen die da vielleicht ins Spiel kommen? Momentan 
ist die Optimierung auf Debug. Ich werde ein bisschen weiter testen.

Cheers,

Albert

von S. R. (svenska)


Lesenswert?

Kann das sein, dass die Schleife recht viel Zeit dauert und verhindert, 
dass die Datenübertragung im Hintergrund stattfindet?

Versuche mal, ein yield() in die Schleife einzubauen.

von Albert F. (Gast)


Lesenswert?

Aber die Schleife ist im gleichen Task wie die Datenuebertragung. Ein 
yield() wuerde dann beides verlangsamern.

Mittlererweile habe ich mit den Optimierungs-Settings gespielt, das 
aendert auch manches. Manchmal besser, manchmal nicht so...

Cheers,

Albert

von S. R. (svenska)


Lesenswert?

Albert F. schrieb:
> Aber die Schleife ist im gleichen Task wie die Datenuebertragung. Ein
> yield() wuerde dann beides verlangsamern.

Das stimmt, wenn dein netconn_write() synchron ist. Es kann aber auch 
sein, dass dein Netzwerktreiber (bzw. IP-Stack) in einem separaten Task 
läuft und dein netconn_write() einfach nur die Übertragung anstößt. Ich 
kenne dein System nicht.

Andere Idee: Tritt das Problem auch auf, wenn du HAL_GetTick() nicht 
aufrufst? Vielleicht ist diese Funktion einfach nur sehr langsam. Im 
Zweifelsfall kannst du mal die Zeit messen, die deine Funktion insgesamt 
braucht.

von 458iu7888766687 (Gast)


Lesenswert?

Albert F. schrieb:
> while(1)
> {
>   for(i = 0; i < 10; i++){
>     data[340 * i] = HAL_GetTick();
>     data[340 * i + 1] = seqNumber;
>     seqNumber++;
>   }
>
>   netconn_write(server_conn, (const unsigned char*)data_2, 136000,
> NETCONN_NOCOPY);
>
>   vTaskDelay(xDelay);
> }

wie groß ist data in beiden versuchen ?

in erstem fall ... ein paar bytes .. in zweitem fall ein paar tausend

je nach sendepuffer des lwip kann das ungemein ausbremsen

von 458iu7888766687 (Gast)


Lesenswert?

Albert F. schrieb:
> while(1)
> {
>   for(i = 0; i < 10; i++){
>     data[340 * i] = HAL_GetTick();
>     data[340 * i + 1] = seqNumber;
>     seqNumber++;
>   }
>
>   netconn_write(server_conn, (const unsigned char*)data_2, 136000,
> NETCONN_NOCOPY);
>
>   vTaskDelay(xDelay);
> }

zumald diese schleife keinen sinn macht ...
oder sollte es heißen :
1
while(1)
2
{
3
  for(i = 0; i < 10; i++){
4
    data[340] = HAL_GetTick();
5
    data[340 + 1] = seqNumber;
6
    seqNumber++;
7
  netconn_write(server_conn, (const unsigned char*)data_2, 136000,     NETCONN_NOCOPY);
8
  }
9
10
  vTaskDelay(xDelay);
11
}

von Markus F. (mfro)


Lesenswert?

458iu7888766687 schrieb:
> zumald diese schleife keinen sinn macht ...

Nun ja, deine Schleife macht dann aber irgendwie überhaupt gar keinen 
Sinn...

Abgesehen davon stellt sich mir die Frage, warum anscheinend data 
beschrieben und data_2 weggeschickt wird?

Ansonsten scheint mir netconn_write() lediglich die Daten in eine 
Output-Queue zu stellen (per Referenz wg. NOCOPY). Das geht also 
wahrscheinlich ziemlich flott, die eigentliche Arbeit (verschicken) 
passiert woanders.

... und nochwas: der Code scheint keine Synchronisierung zu enthalten, 
d.h. falls das nicht irgendwo im nicht gezeigten Code passiert, kann es 
sein, daß Du (für den nächsten Durchgang) an den Daten rumfummelst 
obwohl sie noch gar nicht abgeschickt sind...

von Albert F. (Gast)


Lesenswert?

Vielen Dank fuer die Antworten.

Stimmt, die Schleife macht wenig Sinn (oder keinen), die war da um diese 
Verzoegerung zu erzeugen. Wenn die Schleife weg ist (sinnvoll oder 
nicht), ging alles OK.

Im Moment ist dieses Task nicht synchronisiert, das wuerde das auch 
erklaeren. Allerdings habe ich auch festgestellt dass wenn ich die 
Optimierung auf O3 (statt Og) setze, laeuft das alles flott.

Ich werde jetzt versuchen sicherzustellen dass die Daten nicht geloescht 
werden.

Cheers,

Albert

von 458iu7888766687 (Gast)


Lesenswert?

Albert F. schrieb:
> Allerdings habe ich auch festgestellt dass wenn ich die
> Optimierung auf O3 (statt Og) setze, laeuft das alles flott.

SW4 von STM?
Cube projekt?
STMF4 oder F7?

stell auf O2 und die debug auf -g1

dann vermeide structs mit "__packed" oder
mit vielen unterschiedlichen datentypen
sortiere die, das immer 32bit voll sind ..
zur not dummy uint8_t reinwerfen

von Albert F. (Gast)


Lesenswert?

System Workbench 2.11
STM32F7
Cube Projekt.

Werde ich auch versuchen.

von Markus F. (mfro)


Lesenswert?

Albert F. schrieb:
> Allerdings habe ich auch festgestellt dass wenn ich die
> Optimierung auf O3 (statt Og) setze, laeuft das alles flott.

das ist nicht besonders verwunderlich.
Wahrscheinlich wird da die gesamte Schleife wegoptimiert...

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.