mikrocontroller.net

Forum: Compiler & IDEs Interrupt und globaler Buffer


Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
volatile unsigned char g_flag;
unsigned char g_buf[10];

ISR:
unsigned char tmpISR[10];
int cnt = 0;
...
if (flag == 0 && cnt == 10) {
   memcpy(g_buf, tmp, cnt);
   cnt = 0;
   flag = 1;
}
...


MAIN:
unsigned char tmpMain[10];
while(true) {
   if (flag == 1) {
      memcpy(tmpMain, g_buf, sizeof(g_tel));
      flag = 0;
   }
...
}

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

Danke

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sollte natürlich
volatile unsigned char flag;

heissen.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: gert (Gast)
Datum:

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

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
War leider schreibfehler : flag <-> g_flag - sorry

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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.
uint8_t new_packet_available( void )
{
  return in_packet ^ out_packet;
}


Peter

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
aber bzgl. meiner Implementierung (ohne Buffer) sollte es auch passen 
oder ?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm - aber die "interruptsperre" sollte doch mit
volatile unsigned char flag;

erledigt sein ?

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hier nochmal der code (überarbeitet):

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

ISR:
unsigned char tmpISR[10];
int cnt = 0;
...
if (g_flag == 0 && cnt == 10) {
   memcpy(g_buf, tmpISR, cnt);
   cnt = 0;
   g_flag = 1;
}
...

MAIN:
unsigned char tmpMain[10];
while(true) {
   if (g_flag == 1) {
      memcpy(tmpMain, g_buf, sizeof(tmpMain));
      g_flag = 0;
   }
...
}

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: gert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Manchmal machen Antworter auch Fehler.

Aber sie regen zum Nachdenken an :-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.