Forum: Mikrocontroller und Digitale Elektronik MMC karte adressieren 32bit will nicht


von Robert (Gast)


Lesenswert?

Hallo miteinander

Ich habe jetzt nach 3 Tagen endlich meine 32mb MMC karte angesteuert 
bekommen. Ich benutze einen ATmega32. Ich habe die lib von roland riegel 
verwendet und versuche nun mit sd_raw_read immer 1024 byte Päckchen 
auszulesen.

Aber irgendwie habe ich das Gefühl, dass er mit nach 64 päckchen wieder 
von vorne anfängt, so als ob das offset nur 16 bit wäre. Hier die Stelle 
im Code:

...
offset_t frame;
for(frame=0;1;frame+=1024){

  if(sd_raw_read(frame,mmc_buf,1024) == 0)
    usart_write_str("rfail\r\n");
...

Ich habe als for-Bedingung provisorisch 1 eingetragen, um das als 
Problem auszuschließen.

offset_t ist im nicht-SDHC Modus als uint32_t definiert.

Hier der Prototyp der raw_read:

uint8_t sd_raw_read(offset_t offset, uint8_t* buffer, uintptr_t length);

Ich hoffe ihr wisst was! Danke Schonmal!

von Jonas M. (jonen)


Lesenswert?

ich hatte mal ein ähnliches problem, da war der compiler schuld. versuch 
mal ne andere optimierung (-O0  -O2  -Os). hatte schon code/avr-gcc 
versionen, da ging 32bit code mit -O2 nicht und sogar auch schon, dass 
es mit -O0 nicht ging aber mit -O2.

vielleicht startet auch der watchdog nach ner zeit neu?

von 1.8T-Passat (Gast)


Lesenswert?

Robert schrieb:
> for(frame=0;1;frame+=1024){

Überprüf mal die for-Schleife. Meiner Meinung nach hast Du da eine 
Endlosschleife, da Du in der Abbruchbedingung eine konstante stehen 
hast.

von Robert (Gast)


Lesenswert?

Ah Danke, das mit der Compileroption kann sein, hab -Os drin. Bin grad 
nicht bei meiner Hardware, das kann also sein.

Ich hab n UART dran hängen und bekomm debug ausgaben, der watchdog und 
somit ein Neustart ist es nicht.

Ich probier das nachher mal aus.

von Robert (Gast)


Lesenswert?

Hmm also irgendwas stimmt da nicht. Hab die Optimierung jetzt ganz aus 
gemacht. Das ding ist von 3 auf 14kb gewachsen dadurch.

Ich hab jetzt mal die Warnungen durchgeschaut. Hier z.B. mal was 
auffälliges:

sd_raw.c: In function 'sd_raw_send_command':
sd_raw.c:404: warning: right shift count >= width of type
sd_raw.c:405: warning: right shift count >= width of type

Die Stelle im Code:

uint8_t sd_raw_send_command(uint8_t command, uint32_t arg)
{
    uint8_t response;

    /* wait some clock cycles */
    sd_raw_rec_byte();

    /* send command via SPI */
    sd_raw_send_byte(0x40 | command);
--> sd_raw_send_byte((arg >> 24) & 0xff);
--> sd_raw_send_byte((arg >> 16) & 0xff);
    sd_raw_send_byte((arg >> 8) & 0xff);
    sd_raw_send_byte((arg >> 0) & 0xff);
    switch(command)

macht sinn, dass da keine höheren Adressen ankommen dann...
Aber das ist ja ne 32 bit!

Jemand ne Idee?

von Robert (Gast)


Lesenswert?

Also ich hab jetzt alle Optimierungsoptionen durchprobiert, und auch 
ganz ohne das selbe Ergebnis, nur dass es sau langsam ist.

Genau nach 64 Päckchen a 1024 Byte fängt er einfach wieder von vorne an.

Ich wäre sehr dankbar für jegliche Hilfe.

von Robert (Gast)


Lesenswert?

Obwohl die variable arg schon uint32_t ist, hab ich mal versucht,
1
sd_raw_send_byte((((uint32_t)arg) >> 24) & 0xff);
2
    sd_raw_send_byte((((uint32_t)arg) >> 16) & 0xff);

zu machen. Selbes Ergebnis, selbe Warnmeldungen.

Ich weiß nicht mehr weiter.

von Hc Z. (mizch)


Lesenswert?

Du bist sicher, dass nirgends in Deinem Code etwas der Art
1
#define uint32_t unsigned int
steht (wie es für andere Architekturen passen würde und manchmal auch zu 
sehen ist)?  Ist ein
1
#include <stdint.h>
in derselben Datei?  Falls nicht, mach den mal rein.

von Werner B. (werner-b)


Lesenswert?

Du kannst dir in sd_raw_send_command einmal die sizeof(uint32_t) 
ausgeben lassen.

von Robert (Gast)


Lesenswert?

1
#include <stdint.h>
ist in der Header-Datei der c-Datei wo die sd_raw_send_command drin 
steht und in der main.h enthalten.

also uint32_t wird nicht neu definiert, nur das, was ich verwende, also 
offset_t, wird so definiert:
1
#if SD_RAW_SDHC
2
    typedef uint64_t offset_t;
3
#else
4
    typedef uint32_t offset_t;
5
#endif

sizeof(uint32_t) gibt 2 zurück. Das ist wohl das Problem. Was nun ?

von Hc Z. (mizch)


Lesenswert?

Falsche <stdint.h>?  Sind auf der Kommandozeile -I - Anweisungen, die 
die stdint.h des Systems einbinden?

von Robert (Gast)


Lesenswert?

Ich benutze code:blocks als IDE. Wo kann ich herausfinden, was genau 
ausgeführt wurde, um den code zu compilen ?

von Werner B. (werner-b)


Lesenswert?

Ist bei den Compileroptionen ein "-mint8" dabei?

von Hc Z. (mizch)


Lesenswert?

Robert schrieb:
> Ich benutze code:blocks als IDE. Wo kann ich herausfinden, was genau
> ausgeführt wurde, um den code zu compilen ?

Zeigt diese IDE die Kommandozeile nicht?  Das würde ich als ziemlich 
daneben empfinden.  Wird das Kommando nicht in dem Fenster angezeigt, wo 
auch die Fehlermeldungen erscheinen?  Vielleicht kann jemand etwas dazu 
sagen, der dieselbe IDE verwendet.

(Option -mint8 kann es nicht sein.  Da brauchst Du nicht zu suchen, denn 
die hat mit der Größe einer uint32_t nix am Hut.)

von Hc Z. (mizch)


Lesenswert?

Was Du auch machen könntest:  Schreibe in Deinen Code rein:
1
typedef unsigned long int uint32_t;
Dann sollte Dir der gcc sagen, woher er die andere Definition hat (mit 
der es dann kollidiert).

von Torsten S. (tse)


Lesenswert?

32MB MMC Karte?

Die ist bestimmt mit FAT12 anstatt FAT16 formatiert.

von Hc Z. (mizch)


Lesenswert?

Torsten S. schrieb:
> 32MB MMC Karte?
>
> Die ist bestimmt mit FAT12 anstatt FAT16 formatiert.

Die ist bestimmt nicht mit FAT12 formatiert, denn das kann höchstens 
16 MiB verwalten.

von Frank K. (fchk)


Lesenswert?

Robert schrieb:

> uint8_t sd_raw_send_command(uint8_t command, uint32_t arg)
> {
>     uint8_t response;
>
>     /* wait some clock cycles */
>     sd_raw_rec_byte();
>
>     /* send command via SPI */
>     sd_raw_send_byte(0x40 | command);
> --> sd_raw_send_byte((arg >> 24) & 0xff);
> --> sd_raw_send_byte((arg >> 16) & 0xff);
>     sd_raw_send_byte((arg >> 8) & 0xff);
>     sd_raw_send_byte((arg >> 0) & 0xff);

Probier das mal:

union
{
  uint32_t long;
  uint8_8 byte[4];
} addr;

addr.long=arg;
sd_raw_send_byte(0x40 | command);
// eventuell die Reihenfolge ändern, je nach endianess
sd_raw_send_byte(addr.byte[0]);
sd_raw_send_byte(addr.byte[1]);
sd_raw_send_byte(addr.byte[2]);
sd_raw_send_byte(addr.byte[3]);

von Hc Z. (mizch)


Lesenswert?

Frank K. schrieb:
> union
> {
>   uint32_t long;
>   uint8_8 byte[4];
> } addr;

Wenn sizeof(uint32_t) = 2 ist wie oben geschrieben, wird diese Union 
nichts daran ändern und nichts nützen.

von holger (Gast)


Lesenswert?

>Wenn sizeof(uint32_t) = 2 ist wie oben geschrieben, wird diese Union
>nichts daran ändern und nichts nützen.

Richtig. Was steht denn in der stdint.h für uint32_t?
Dann könnte man mal in der Compilerhilfe nachsehen
was der denn da so anbietet;)

von Hc Z. (mizch)


Lesenswert?

Deshalb ja mein Vorschlag, einen typedef für uint32_t einfach mal so 
reinzuschreiben.  Dann wird der Compiler schon zeigen, wo er die erste 
Definition gefunden hat und man kann sie nachprüfen.

In der <stdint.h> der avr-libc ist uint32_t ein typedef nach unsigned 
long.

von Torsten S. (tse)


Lesenswert?

Bei mir funktioniert der sd-reader des o.g. Autors sehr zuverlässig 
schon über Jahre. Sowohl mit SD als auch SDHC. Warum man nur die 
sd_raw-Funktionen nutzen möchte verstehe ich nicht ganz.

Der GCC spuckt bei mir keine einzige Warnung aus. Vielleicht ist es eine 
gute Idee, das ganze Projekt als solches zuerst mal auszuprobieren. Beim 
copy&paste kann man schnell etwas übersehen.

von Robert (Gast)


Lesenswert?

Also auf die MMC-Karte schreibe ich einfach mit dd direkt meine Daten 
rein, das reicht mir. Mit FAT hab ich es zuerst probiert, in der 
live-shell hat ls aber nur Müll angezeigt. Ich dachte zuerst ich hätte 
was falsch formatiert und wollte deshalb das raw nehmen, da weiß ich, wo 
ich dran bin. Außerdem ist der Code viel kleiner und wahrscheinlich auch 
schneller.
Ich denke aber, dass der Müll bei ls am selben Problem liegt.

In der stdint.h habe ich schon selbst nachgeschaut, da steht korrekt 
unsigned long int drin.
1
typedef unsigned long int uint32_t;

Ich versuch jetzt mal das im code typedefinieren.

von Robert (Gast)


Lesenswert?

Ok, ich glaube ich habe den fehler:
1
main.h:16: error: conflicting types for 'uint32_t'
2
/usr/include/stdint.h:52: note: previous declaration of 'uint32_t' was here

anstatt in /usr/avr/include nimmt er die normalen. Mal schauen, wo ich 
das ändern kann.

von Robert (Gast)


Lesenswert?

Ok habs. Man konnte auch einstellen, ob man nur ne "task description" 
oder die ganze commandline haben will. Jetzt sehe ich auch die Befehle.
Dass der avr mit den Libs aus /usr/libs funktioniert hat wundert mich 
allerdings ein wenig. Aber macht ja durchaus Sinn, soviel Unterschied 
sollte es da ja nicht geben. Wo er bei den eingestellten Pfaden 
allerdings die richtige stdio mit den Port-Definitionen herbekommen hat 
ist mir dann aber ein Rätsel.

Ich hab mein uC Board grad nicht in der Nähe, aber die Compilerwarnung 
mit den zu kleinen Variablen beim Shiften ist jetzt weg. Ich denke, das 
Problem ist behoben.

Vielen Dank an alle! Hier wird einem wirklich gut geholfen (war mein 
erstes Mal hier).

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.