Forum: Compiler & IDEs Interrupt und globaler Buffer


von gert (Gast)


Lesenswert?

Habe eine ISR (Seriell) welche auf bestimmte Telegramme wartet (10 Byte 
lang).
Übergebe mir das Telegramme wie folgt an die Main (dass dabei evtl. 
Telegramme verloren gehen können wenn main zu langsam ist, ist mir klar) 
:

GLOBAL:
1
volatile unsigned char g_flag;
2
unsigned char g_buf[10];

ISR:
1
unsigned char tmpISR[10];
2
int cnt = 0;
3
...
4
if (flag == 0 && cnt == 10) {
5
   memcpy(g_buf, tmp, cnt);
6
   cnt = 0;
7
   flag = 1;
8
}
9
...


MAIN:
1
unsigned char tmpMain[10];
2
while(true) {
3
   if (flag == 1) {
4
      memcpy(tmpMain, g_buf, sizeof(g_tel));
5
      flag = 0;
6
   }
7
...
8
}

Ist diese Übergabe korrekt oder kann es zu zb. Deadlocks oder ähnlichem 
kommen ?
Welche Varianten der Übergabe würden sich noch anbieten ?

Danke

von Peter (Gast)


Lesenswert?

die Frage ist über die doppelte übegabe überhaupt sinn macht, warum 
nicht in der Main direkt die globale Variable nutzen? In beiden Fällen 
hast du das Problem das wenn die ISR während des memcopy aufgerufen wird 
dann die Daten dabei unbrauchbar werden. Du musst in der Main dafür 
sorgen das während das memcopy keine interupts aufgerufen werden.

von gert (Gast)


Lesenswert?

>>> die Frage ist über die doppelte übegabe überhaupt sinn macht,

Deshalb mache ich die doppelte Übergabe. da ich die Interrupts nicht 
ausschalten darf.

Das Überschreiben wird doch mittels g_flag == 0 in der ISR verhindert.

von gert (Gast)


Lesenswert?

Sollte natürlich
1
volatile unsigned char flag;

heissen.

von Peter D. (peda)


Lesenswert?

Diese Kopierorgien und Speicherverschwendung machen überhaupt keinen 
Sinn.

Du mußt Dir zuerst mal überlegen, wie tief Du puffern willst, d.h. 
wieviel Pakete können maximal eintreffen, während das Main ein Paket 
abarbeitet.
Und dann legst Du ne FIFO für n Pakete an.
Der Interrupt schreibt ein Paket rein und zählt seinen Paketzähler hoch.
Das Main bearbeitet das Paket und zählt danach seinen Paketzähler hoch, 
während der Interrupt ins nächste Paket reinschreibt. Und nach n-1 
Paketen gibts nen Rollover nach Paket 0.


Peter

von Peter (Gast)


Lesenswert?

gert schrieb:
> Das Überschreiben wird doch mittels g_flag == 0 in der ISR verhindert.

sollen wir das eraten oder wo soll die stellen in dem code-schnipsel 
versteckt sein?

von gert (Gast)


Lesenswert?

Es soll anfangs genau 1 Paket abgearbeitet werden; dh mit meinem Ansatz 
wird genau 1 Paket gepuffert.

von gert (Gast)


Lesenswert?

War leider schreibfehler : flag <-> g_flag - sorry

von gert (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Der Interrupt schreibt ein Paket rein und zählt seinen Paketzähler hoch.
>
> Das Main bearbeitet das Paket und zählt danach seinen Paketzähler hoch,
>
> während der Interrupt ins nächste Paket reinschreibt. Und nach n-1
>
> Paketen gibts nen Rollover nach Paket 0.

Aber die Main braucht dann immer noch eine Synchronisation damit sie 
informiert wird, ob es ein neues Paket gibt.

von Peter D. (peda)


Lesenswert?

gert schrieb:
> Aber die Main braucht dann immer noch eine Synchronisation damit sie
> informiert wird, ob es ein neues Paket gibt.

Dazu sind ja die 2 Paketzähler da. Sind sie gleich, ist nichts mehr im 
FIFO.
Und beim FIFO kleiner 256 Pakete kann dieser Zähler 8bit sein, d.h. ist 
atomar lesbar/schreibbar und nirgends muß der Interupt gesperrt werden.
1
uint8_t new_packet_available( void )
2
{
3
  return in_packet ^ out_packet;
4
}


Peter

von gert (Gast)


Lesenswert?

aber bzgl. meiner Implementierung (ohne Buffer) sollte es auch passen 
oder ?

von Peter D. (peda)


Lesenswert?

gert schrieb:
> aber bzgl. meiner Implementierung (ohne Buffer) sollte es auch passen
> oder ?

Du benutzt 3 Buffer und das memcpy im Main muß unter Interruptsperre 
erfolgen.

Wenn man nicht ständig umkopiert, sondern mit Zeigern arbeitet, wird der 
Code übersichtlicher, schneller und kleiner.


Peter

von gert (Gast)


Lesenswert?

Hm - aber die "interruptsperre" sollte doch mit
1
volatile unsigned char flag;

erledigt sein ?

von gert (Gast)


Lesenswert?

hier nochmal der code (überarbeitet):

GLOBAL:
1
volatile unsigned char g_flag;
2
unsigned char g_buf[10];

ISR:
1
unsigned char tmpISR[10];
2
int cnt = 0;
3
...
4
if (g_flag == 0 && cnt == 10) {
5
   memcpy(g_buf, tmpISR, cnt);
6
   cnt = 0;
7
   g_flag = 1;
8
}
9
...

MAIN:
1
unsigned char tmpMain[10];
2
while(true) {
3
   if (g_flag == 1) {
4
      memcpy(tmpMain, g_buf, sizeof(tmpMain));
5
      g_flag = 0;
6
   }
7
...
8
}

von gert (Gast)


Lesenswert?

Muss ich hier dann wirklich auch noch eine Interruptsperre in MAIN 
einbauen ? Das sollte doch mittels g_flag schon vor Überschreiben 
gesichert sein ?

Danke

von Karl H. (kbuchegg)


Lesenswert?

gert schrieb:
> Muss ich hier dann wirklich auch noch eine Interruptsperre in MAIN
> einbauen ? Das sollte doch mittels g_flag schon vor Überschreiben
> gesichert sein ?

Wie ist deine Meinung zu diesem Thema und womit begründest du sie?
Was kann alles passieren (Interruptmässig) und wie handhabst du das im 
Code?


Irgendwann musst du auch mal ins kalte Wasser springen :-)

von gert (Gast)


Lesenswert?

Die Frage war nur, ob das Sichern gegen Überschreiben des Puffers g_buf 
mittels g_flag - ohne jetzt ein FIFO zu verwenden - richtig programmiert 
wurde.

von Karl H. (kbuchegg)


Lesenswert?

gert schrieb:
> Die Frage war nur, ob das Sichern gegen Überschreiben des Puffers g_buf
> mittels g_flag - ohne jetzt ein FIFO zu verwenden - richtig programmiert
> wurde.

Genau deshalb frage ich DICH zu diesem Thema.
Wie ist deine Meinung und warum hast du diese Meinung?

Irgendwann musst auch du anfangen Verantwortung für deinen Code zu 
übenehmen. Ich kann auch nicht jemand anderen fragen, ob ich gewisse 
Dinge richtig oder falsch gemacht habe sondern muss selbst dafür grade 
stehen.

von gert (Gast)


Lesenswert?

Ich bin der Meinung dass es so richtig programmiert wurde.

Leider habe ich hier im Forum die Info bekommen, dass das memcpy im Main 
unter Interruptsperre erfolgen muss - daher die Nachfrage (vielleicht 
habe ich ja etwas übersehen).

von Karl H. (kbuchegg)


Lesenswert?

gert schrieb:
> Ich bin der Meinung dass es so richtig programmiert wurde.

Gut

> Leider habe ich hier im Forum die Info bekommen, dass das memcpy im Main
> unter Interruptsperre erfolgen muss - daher die Nachfrage (vielleicht
> habe ich ja etwas übersehen).

Manchmal machen Antworter auch Fehler.

von gert (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Manchmal machen Antworter auch Fehler.

Aber sie regen zum Nachdenken an :-)

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.