www.mikrocontroller.net

Forum: Compiler & IDEs AVR, memcmp


Autor: Ludwig M. (laludelala)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich bin dabei, Zugriffsroutinen für eine FAT16 (MMC-Karte) zu schreiben. 
Als Mikrokontroller dient ein ATMega16.

Die Routinen sind fertig, ich kann mit ihnen am PC (x86 Programm unter 
Linux) in einer virtuellen FAT-Partition Dateien anlegen und 
reinschreiben.


Jetzt bin ich dabei, das Ganze auf den Atmel zu portieren, und mir macht 
die Hardvard-Architektur zu schaffen.


Ich möchte nämlich einen ausgelesenen Buffer (Datentyp eines "FAT 
Directory Entries") mit einer Konstanten vergleichen:

dir.Name[0] = 0xff;
while( (memcmp(dir.Name, "DATADIR    ", 11) != 0) && (dir.Name[0] != 
0x00)  )
                getDirEntry(0, c++, &dir, 1);


Debugmeldungen, welche Verzeichnisse er durchlaufen hat, liefern 
"DATADIR    " und "" ...

daraus schliesse ich, daß "memcmp" dir.Name mit einem Wert aus dem 
falschen Speicher vergleicht.


Dumm ist nur, daß ein "memcmp(dir.Name PSTR("DATADIR    "), 11)" keinen 
Effekt hat.


Die avr-libc schweigt sich darüber aus, ob memcmp die Daten aus dem RAM, 
dem Flash oder sonstwoher holt :(




Gibt es eine andere Möglichkeit, als memcmp selbst zu implementieren?






Saluti!

Ludwig

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ludwig M. wrote:

> daraus schliesse ich, daß "memcmp" dir.Name mit einem Wert aus dem
> falschen Speicher vergleicht.

Falsche Schlussfolgerung.  Du musst den Bug woanders suchen.  Mit den
paar Brocken kann meine Kristallkugel aber gerade nichts erraten.

> Dumm ist nur, daß ein "memcmp(dir.Name PSTR("DATADIR    "), 11)" keinen
> Effekt hat.

memcmp_P() ist noch nicht implementiert.

> Die avr-libc schweigt sich darüber aus, ob memcmp die Daten aus dem RAM,
> dem Flash oder sonstwoher holt :(

Immer RAM, sofern nichts anderes angegeben war.  Da dein "DATADIR    "
auch im RAM liegt, muss das memcmp() an sich erst einmal
funktionieren.

Autor: Ludwig M. (laludelala)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Vielen Dank für die Antwort. Die "paar Brocken" habe ich jetzt ergänzt, 
hier nun die gesamte Funktion. "Directory" ist ein global definierter 
Datentyp und bildet die Verzeichniseinträge in der FAT ab.

Was sich zum vorigen Auszug geändert hat, sind einige 
Debug-Informationen und eine Auswertung für den entsprechenden Return.


Was über die Serielle kommt ist dann:
  Programm gestartet, FAT initialisiert!
  getDataDir: DATADIR
  getDataDir:
  Gefundene DataDir:



Hier die Funktion:

uint16_t getDataDir(void)
{
Directory dir;
uint16_t c = 0;
        dir.Name[0]     = 0xff;
        while( (memcmp(dir.Name, "DATADIR    ", 11) != 0) && 
(dir.Name[0] != 0x00)  )
{
                getDirEntry(0, c++, &dir, 1);
uart_puts(PSTR("\n\ngetDataDir: "));
uart_puts_R(dir.Name);
}
uart_puts(PSTR("\n\nGefundene DataDir: "));
uart_puts_R(dir.Name);
        c--;
        if(dir.Name[0] != 0x00)
                return(dir.FirstClusterLO);
        else
                return(0);
}





Ich hoffe, daß Deine Kristallkugel jetzt besser erraten kann ...



Saluti!

Ludwig

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sieht mir so aus, als wäre die Schleife mit der Bedingung
dir.Name[0]
abgebrochen worden.

p.s.: bitte benutze [ c ] ... [ /c ] Code-Markierungen.

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

Bewertung
0 lesenswert
nicht lesenswert
Mach mal folgendes:
In der while Schleife:
     ...
     getDirEntry(0, c++, &dir, 1);
     uart_puts(PSTR("\n\ngetDataDir: \""));
     uart_puts_R(dir.Name);
     uart_puts(PSTR("\""));
   }

Und dann zählst du in der Ausgabe mal wieviele
Leerzeichen hinter dem in dir.Name enthaltenem
String noch drann sind. Leerzeichen in einem
Dateinamen sind meistens keine gute Idee. Vor allen
Dingen dann nicht, wenn ein String mit ihnen
beginnt oder endet.

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

Bewertung
0 lesenswert
nicht lesenswert
Falls du's nicht gesehen hast.
Mein Vorschlag ist, vor und nach der Ausgabe von dir.Name
noch zusätzliche " auszugeben, damit man in der Ausgabe
sieht wo der String anfängt und wo er aufhört.

Übrigens: Wenn du anscheined sowieso mit C-Strings
arbeitest, wieso benutzt du dann die mem... Funktionen.
Für C-strings gibts die schöne str.. Familie an
Funktionen.

Autor: psavr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falls Du Deine Stringkostanten irgendwann doch im FLASH halten willst um 
RAM zu sparen:
int memcmp_P(const void *, PGM_VOID_P, size_t); 

int memcmp_P(const void *s1, PGM_VOID_P s2, size_t n) 
{ 
  if (n != 0) 
  { 
    unsigned char *p1 = (unsigned char *)s1; 
    PGM_P p2 = (PGM_P)s2; 
    unsigned char c; 
    do 
    { 
      c=pgm_read_byte(p2++); 
      if (*p1++ != c) 
      { 
        return (*--p1 - c); 
      } 
    } 
    while (--n != 0); 
  } 
  return (0); 
} 

Autor: Ludwig M. (laludelala)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich wollt emich erstmal entschuldigen, das hier etwas totgestellt zu 
haben, ich war einige Wochen ohne Computer - Grafikkartenspeicher im 
Notebook kaputt.


@Karl-Heinz, die Leerstellen sind schon richtig, denn ich lese die FAT 
aus, und die kennt nur mit Leerzeichen aufgefüllte Zeichenketten.
Die Ausgabe erfolgt jedoch mit KEINEM Leerzeichen.
Übrigens nutze ich aus genau diesem Grund (Leerzeichen aufgefüllte 
zeichenketten) die mem... Funktionen statt der str... Funktionen - 
letztere arbeiten nur mit nullterminierten Strings, die aber die FAT 
nicht akzeptiert

@psavr, dankeschön, werde ich mir merken!



Saluti!

Ludwig

Autor: Ludwig M. (laludelala)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Das Problem ist owhl, daß der Atmel von der Flash-karte an dieser einen 
Stelle ein "0x00" statt eines "0x20" ausliest - der Rest wird aber schon 
richtig ausgelesen.

Das treibt mich gerade in den Wahnsinn ...



Saluti!

Ludwig

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.