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
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.
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
Sieht mir so aus, als wäre die Schleife mit der Bedingung
1 | dir.Name[0] |
abgebrochen worden. p.s.: bitte benutze [ c ] ... [ /c ] Code-Markierungen.
Mach mal folgendes: In der while Schleife:
1 | ...
|
2 | getDirEntry(0, c++, &dir, 1); |
3 | uart_puts(PSTR("\n\ngetDataDir: \"")); |
4 | uart_puts_R(dir.Name); |
5 | uart_puts(PSTR("\"")); |
6 | }
|
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.
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.
Falls Du Deine Stringkostanten irgendwann doch im FLASH halten willst um RAM zu sparen:
1 | int memcmp_P(const void *, PGM_VOID_P, size_t); |
2 | |
3 | int memcmp_P(const void *s1, PGM_VOID_P s2, size_t n) |
4 | {
|
5 | if (n != 0) |
6 | {
|
7 | unsigned char *p1 = (unsigned char *)s1; |
8 | PGM_P p2 = (PGM_P)s2; |
9 | unsigned char c; |
10 | do
|
11 | {
|
12 | c=pgm_read_byte(p2++); |
13 | if (*p1++ != c) |
14 | {
|
15 | return (*--p1 - c); |
16 | }
|
17 | }
|
18 | while (--n != 0); |
19 | }
|
20 | return (0); |
21 | }
|
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.