Ringbuffer lesen/schreiben

Gast #976950
Lesenswert?

Morgen, wir haben die Aufgabe bekommen ein Programm (auf dem8051) von 
Assembler in C zu übersetzen. Es geht dabei ums aus- und einlesen von 
Daten aus einem Ringbuffer. Insbesondere ist mir nicht klar, wie ich die 
Variablen initilisieren soll (siehe Funktion rbInit). Es wäre gut, wenn 
ihr da mal drüberschauen konntet. Danke im Voraus.
1
#include "rbLIB.h"
2

3

4
extern void rbInit( struct STRUCT_RB_CTRL *prbCtrl, char *buffer, unsigned char size )
5
{
6
  prbCtrl->rbUsed = 0;
7
  prbCtrl->rbStart = buffer;
8
  //prbCrl->rbSize = SIZE;  //geht nicht, defined in rlib.h #define size 4
9
  //prbCtrl->rbStart = 0x0  //beginnt bei xdata
10
  //prbCtrl->rbLast = 0x4  //Anfangsadresse Xdata + 4  
11
}
12

13
extern char rbState( struct STRUCT_RB_CTRL *prbCtrl )
14
{
15
  return prbCtrl->rbUsed;
16
}
17

18
extern char rbRead(struct STRUCT_RB_CTRL *prbCtrl, char *value)
19
{
20
char rc = ERR_BUF_EMPTY 
21

22
  if (prbCtrl->rbUsed > 0)  //Daten im Puffer verfügbar
23
  {
24
    value = *prbCtrl->rbReadPos--;     //Lesezeiger dekr. von aktuellen Wert
25
    if (prbCtrl->rbReadPos < prbCtrl->rbStart)  //Untere Grenze des Puffers erreicht
26
    {
27
      prbCtrl->rbReadPos = prbCtrl->rbStart;
28
    }
29
    prbCtrl->rbUsed--;
30
    rc = OK;
31
  }
32
  return rc;
33
}
34

35

36
extern char rbWrite( struct STRUCT_RB_CTRL *prbCtrl, char *value )
37
{
38
char rc = ERR_BUF_FULL;
39

40
  if( prbCtrl->rbUsed < prbCtrl->rbSize )
41
  {
42
    *prbCtrl->rbWritePos++ = value;
43
    if( prbCtrl->rbWritePos > prbCtrl->rbLast )
44
    {
45
      prbCtrl->rbWritePos = prbCtrl->rbStart;
46
    }
47
  
48
    prbCtrl->rbUsed++;
49
    rc = OK;
50
  }
51
  return rc;
52
}
53
// EOF rbLIB.c
Gast #976982
Lesenswert?

Ich würde die Variablen so initializieren wie oben in der Funktion 
angegeben.

"SIZE" habe ich wie gesagt in der Header-Datei dekl.:

#define size 4


"rbstart" ist die Startadresses des Puffers und liegt an der 
Anfangsadresse von Speicherbereich XDATA. Meine Frage ist nun wie ich 
das deklariere. Wie unterscheide ich in C zwischen diesen 
Speicherbereichen?
Gast #976988
Lesenswert?

Quatsch,

so müsste es sein.
1
extern void rbInit( struct STRUCT_RB_CTRL *prbCtrl, char *buffer, unsigned char size )
2
{
3
  prbCtrl->rbUsed = 0;
4
  prbCtrl->rbStart = buffer;
5
  //prbCrl->rbSize = SIZE;  //geht nicht, defined in rlib.h #define size 4
6
  //prbCtrl->rbLast = buffer + 4  //Anfangsadresse Xdata + 4  
7
}
Gast #976994
Lesenswert?

OK, "size" habe ich jetzt klein geschrieben Schreibefehler. Das habe ich 
nicht beachtet, weil ich vorher mit VHDL rumgemacht habe und der Prof 
schreibt Schlüsselworter und Konstneten immer groß. Ich versuche immer 
alles klein zu schreiben.
#977114
Lesenswert?

BerndS wrote:
> Morgen, wir haben die Aufgabe bekommen ein Programm (auf dem8051) von
> Assembler in C zu übersetzen.

Dann wirst Du hierfür wohl eine glatte "6" bekommen.

Du hast einfach ohne Nachzudenken von irgendwoher eine Lösung kopiert, 
die für wesentlich größere Systeme ausgelegt sind, als für nen kleinen 
8051.
Der MC wird sich erstmal schon dumm und dußlich ackern, ehe er überhaupt 
die ganzen Indirektionen aufgelöst hat.
Und zu allem Übel wird er das mit generic Pointern machen müssen, d.h. 
für jeden einzelnen Bytezugriff nen Funktionsaufruf. Es sind ja keine 
Memory-Specifier angegeben.


Ich kann mir nicht vorstellen, daß der Assemblercode auch nur entfernt 
ähnlich komplex ist.
Er wird wohl ganz einfach sein, ohne Strukturpointer, sondern mit 
direktem Memoryzugriff für genau eine FIFO im IDATA-Bereich.


Zeig dochmal den Assemblercode, damit man weiß, was Du wirklich machen 
sollst.


Peter
Persönliche Seite #977124
Lesenswert?

BerndS wrote:
> OK, "size" habe ich jetzt klein geschrieben Schreibefehler. Das habe ich
> nicht beachtet, weil ich vorher mit VHDL rumgemacht habe und der Prof
> schreibt Schlüsselworter und Konstneten immer groß. Ich versuche immer
> alles klein zu schreiben.

Damit mans schlechter lesen kann? Nene die Konstanten-"Regel" gilt bei 
ziemlich vielen Programmiersprachen. Ist kein schlechter Stil das 
beizubehalten.
Gast #977286
Lesenswert?

Peter,  es ist eine Praktikumsaufgabe und die Funktionsrümpfe wurden 
vorgegeben. Der Algorithmus für das Lesen und Schreiben eines Bytes 
(generisch) wurde als Ablaufdiagramm (mit Variablen) im Heft für 
Assemblerprogrammierung vorgegeben. Dort ist auch ein einfaches Beispiel 
für die Programmierung eines Ringpuffers, was ich hier ja mal einstellen 
kann.

Diese Lösung ist nicht optimal (weil generisch). Daher sollen wir uns ja 
im nächsten Schritt überlegen, wie wir das Programm optimieren können. 
Eine Lösung ist die generischen Zeiger durch spezifische Zeiger zu 
ersetzen. Mir ist nur noch nicht klar wie...

#include "rbLIB.h"


extern void rbInit( struct STRUCT_RB_CTRL *prbCtrl, char *buffer, 
unsigned char size )
{
  prbCtrl->rbUsed = 0;
  prbCtrl->rbStart = buffer;
  prbCrl->rbSize = size;
  prbCtrl->rbLast = size + buffer -1
}

extern char rbState( struct STRUCT_RB_CTRL *prbCtrl )
{
  return prbCtrl->rbUsed;
}

extern char rbRead(struct STRUCT_RB_CTRL *prbCtrl, char *value)
{
char rc = ERR_BUF_EMPTY;

  if (prbCtrl->rbUsed > 0)  //Daten im Puffer verfügbar
  {
    *value = *prbCtrl->rbReadPos++;     //Lesezeiger dekr. von aktuellen 
Wert
    if (prbCtrl->rbReadPos < prbCtrl->rbStart)  //Untere Grenze des 
Puffers erreicht
    if (prbCtrl->rbReadPos < prbCtrl->rbLast)   //Obere Grenze des 
Puffers erreicht
    {
      prbCtrl->rbReadPos = prbCtrl->rbStart;
    }
    prbCtrl->rbUsed--;
    rc = OK;
  }
  return rc;
}


extern char rbWrite( struct STRUCT_RB_CTRL *prbCtrl, char value )
{
char rc = ERR_BUF_FULL;

  if( prbCtrl->rbUsed < prbCtrl->rbSize )
  {
    *prbCtrl->rbWritePos++ = value;
    if( prbCtrl->rbWritePos > prbCtrl->rbLast )
    {
      prbCtrl->rbWritePos = prbCtrl->rbStart;
    }

    prbCtrl->rbUsed++;
    rc = OK;
  }
  return rc;
}
// EOF rbLIB.c
#977443
Lesenswert?

BerndS wrote:
> Der Algorithmus für das Lesen und Schreiben eines Bytes
> (generisch) wurde als Ablaufdiagramm (mit Variablen) im Heft für
> Assemblerprogrammierung vorgegeben. Dort ist auch ein einfaches Beispiel
> für die Programmierung eines Ringpuffers, was ich hier ja mal einstellen
> kann.

Ja das wäre sinnvoll.


> Diese Lösung ist nicht optimal (weil generisch). Daher sollen wir uns ja
> im nächsten Schritt überlegen, wie wir das Programm optimieren können.

Der 8051 ist nicht sonderlich optimiert auf Operationen mit Zeigern auf 
Strukturen mit Zeigern (doppelte Indirektion).
Wenn der FIFO die gesamte Laufzeit gebraucht wird, ist es also 
sinnvoller seine Struktur direkt im Memory zu plazieren.
Vielleicht ab 10 FIFOs ist die Pointervariante wieder günstiger im 
Codeverbrauch.


> Eine Lösung ist die generischen Zeiger durch spezifische Zeiger zu
> ersetzen.

Das kann auch noch etwas bringen, ist aber bei Strukturen ziemlich 
haarig in der Syntax. Mal in der Keil Knowledgebase googlen.


> #include "rbLIB.h"

Wo ist denn die?
Wenn man Code postet, muß man auch alle darin verwendeten Definitionen 
mitposten.
Er muß compilierbar sein, sonst ist es sinnlos.


Peter
Gast #981502
Lesenswert?

OK, hier das komplette fehlerfreie Projekt.

Optimieren kann ich das Programm noch, indem ich die Zeiger auf den 
Speicherbereich xdata Verweise, also
1
char xdata *rbReadPos 
2
char xdata *rbWritePos
3
...
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren