Forum: Mikrocontroller und Digitale Elektronik Problem mit MMC, bekomme immer illegal command


von Ste (Gast)


Angehängte Dateien:

Lesenswert?

Hallo!

Ich habe ein Problem mit der ansteuerung der MMC. Wenn vielleicht mal 
jemand einen Blick in den Code werfen könnte.
Die Karte ist am SPI des AtMega8 angehängt, die beschaktung sollte 
eigentlich korrekt sein (ich komme darauf, weil ich ja eine Antwort 
erhalte). Es sollte also am Programm liegen.
Wenn ich cmd0 sende, dann bekomme ich als Antwort 0x00, anstatt 0x01, 
dass sie sich jetzt im idle state befindet. Wenn ich nochmals cmd0 
sende, dann erhalte ich immer 0x05 (illegal command und in idle state), 
egal wie oft ich cmd0 sende.
Ich hab dann mal versucht cmd1 zu senden, aber natürlich kommt auch da 
nichts gescheites raus. Wenn ich sie doch nur mal initialisieren könnte 
wäre ich schon superhappy.
Mein avr läuft mit 1 Mhz, und die SPI habe ich mit 128 vorteiler am 
laufen, also überrenne ich die MMC nicht, habe auch zu testzwecken 
überall grosse Pausen eingebaut - vergebens.
Wenn jemand in den Code schaut und nicht gleich wieder wegklickt, weil 
so scheusslich, wäre ich sehr dankbar

Gruss

von E. M. (hias)


Lesenswert?

Hallo!

Ohne jetzt deinen Code genauer angeschaut zu haben, eine paar 
Anmerkungen zur Init.

Du solltest die SPI-Frequenz auf max 400KHz einstellen. Dies gult nur 
für die Initialisierungsphase.

Gibt der Karte etwas Zeit zum "Starten".
Schick ihr danach für mindestens 74cycles ein "High".
Schicke das CMD0 (0x40,0x00,0x00,0x00,0x00,0x95)
Warte einige Zeit auf eine gültige Antwort (falls in dieser Zeit keine 
Antwort kommt, abbrechen)
->>>Schicke danach sooft das CMD1 (0x41,0x00,0x00,0x00,0x00,0xff) bis du 
eine gültige Antwort bekommst. Auch hier empfehle ich nach einiger Zeit 
ohne gültige Antwort abzubrechen). Gerade beim CMD1 braucht die Karte 
eine längere Zeit.

Check mal die Dinge ab und meld dich bei Fragen.

Hias

P.S.: Dein Code ist, wie du schon gesagt hast nicht sehr einladend. 
Vielleicht kannst du die Lesbarkeit etwas verbessern. (Nicht böse 
gemeint :) )

EDIT: Hab doch mal schnell deinen Code überflogen. Die mit ->>>>> 
gekenntzeichnete Stelle könnte dein Problem sein. Du sendest nämlich nur 
einmal das CMD.


von Ste (Gast)


Lesenswert?

Ich glaube ich habe fast alles so wie du das beschrieben hast (ausser 
der Lesbarkeit des Codes)...
Was ich anders habe als du vorgeschlagen: ich sende als CRC am Schluss 
von CMD1 nicht 0xff sondern 0x95, aber das sollte keine Rolle spielen, 
da CRC deaktiviert und nur das letzte Bit eine 1 sein muss, der Rest 
dieses Bytes kommt ja, nachdem man in den SPI-Mode gewechselt hat, nicht 
mehr drauf an (wenn man CRC nicht wieder reaktiviert).

Welche Stelle im Code meinst du mit '->>>>>'? Kann sie nirgends 
finden...

Gruss und dake fürs Code ansehen

von Philipp B. (philipp_burch)


Lesenswert?

Versuch mal, bei der Initialisierung vom SPI entweder CPOL ODER CPHA zu 
setzen, möglicherweise hilft's. Oder war das nur für die SD-Karten?

von E. M. (hias)


Lesenswert?

Hi!

Mit dem '->>>>>' hab ich in meinem Post das gemeint:

->>>Schicke danach sooft das CMD1 (0x41,0x00,0x00,0x00,0x00,0xff) bis du
eine gültige Antwort bekommst. Auch hier empfehle ich nach einiger Zeit
ohne gültige Antwort abzubrechen). Gerade beim CMD1 braucht die Karte
eine längere Zeit.

Du schickst soweit ich dass auf die schnelle erkennen konnte nur einmal 
das CMD 1 und wartest dann auf die Antwort.
Probier mal das CMD1 sooft zu senden bis du eine gültige Antwort hast.

hias

von Philipp B. (philipp_burch)


Lesenswert?

Nö, das macht er schon richtig:
1
//cmd1 senden bis ready
2
not_ready:
3
ldi temp1, 1
4
rcall cmd_send
5
tst temp1
6
brne not_ready
7
//READY!!!

von E. M. (hias)


Lesenswert?

Sorry hab da nicht genau genug hingeschaut!

Noch was ist mir aufgefallen.
Bevor man der MMC Karte ein Commando schickt sollte man.
Ein paar Bits senden, wenn die Karte noch deaktiviert ist.
Ich sende ein Byte (0xff) bevor ich CS auf low ziehe.
Vielleicht bringt ja das was.

Hias

von Ste (Gast)


Lesenswert?

Hallo Philipp, hallo Hias
Erstmal Danke für eure Bemühungen...
@Philipp: Ich hab das mit CPOL und CPHA zusetzen nicht versucht, weil 
der Mode0 eigentlich stimmen sollte. (siehe 
http://elm-chan.org/docs/mmc/mmc_e.html)

@Hias: Das mache ich bereits, siehe:
//mind. 74 clock cycles und DI high
ldi temp1, 20
ldi arg0, 0xff
weiter_machen:
  out SPDR, arg0
  wait
  dec temp1
brne weiter_machen

von E. M. (hias)


Lesenswert?

Ja ich mein was anderes.

Deine Funktion Befehl senden schaut so aus:

CS Low
6Bytes Befehl senden
auf Antwort warten.


Ich hab gemeint du sollst hier noch folgendes machen:

0xFF senden  (1x reicht)
CS Low
6Bytes Befehl senden
auf Antwort warten

Das einfach mal in deine cmd_send Funktion einbauen und testen.

ldi temp1, 0xff
out SPDR, temp1


Hias

von Ste (Gast)


Lesenswert?

Hallo, danke für deine Bemühungen. Habe das mal eingebaut... Jetzt 
bekomme ich nicht mehr die selben Antowrten, aber immer noch nicht das 
was ich erwarte.
Ich bin nun wieder auf der Suche auf der Hardwareseite, weil mich die 
antworten die ich empfange plötzlich zufällig erscheinen. Ich habe die 
Anbindung an den ATmega ähnlich wie bei Ulrich Radig, er hat die DO 
leitung welche die Daten zurück zum AVR bringen sollte ohne irgendwelche 
Pullups, könnte da ein Fehler sein? Ich nehme mal an, dass er die 
internen Pullups nicht eingeschltet hat, denn sonst würde ja 5V da 
anliegen, das hätte wohl ein schlechtes Ende.
übrigens die MMC lebt noch, das habe ich mit einem Kartenleser 
überprüft....

von E. M. (hias)


Lesenswert?

Hallo!

DO heißt nichts anderes als DataOut aus der Sicht der MMC.
Das heißt ein high bedeutet hier einen Pegel von 3,3V. Dein Atmel 
versteht aber auch die 3,3V als high. Des passt also so.

Hast du vielleicht vergessen, den DO_Pin am Atmel (aus der Sicht des 
Atmel also als Data in) als Eingang zu definieren?

ldi temp1, 0b11111111      //PORTB (cs) auf output
out DDRB, temp1

Du legt nämlich den ganzen PortB als Ausgang fest.

Hias

von Ste (Gast)


Lesenswert?

Die Frage ist halt ob die MMC auch wirklich 3.3V rausschickt, oder ob 
sie einfach bei low gegen Masse schaltet und bei High "loslässt" und 
wenns nicht hoch gezogen wird dann macht der Pegel irgendwas.
Eigentlich sollte doch durch einschalten des SPI dieser Pin richtig 
eingerichtet werden (also als Eingang)?!?

von E. M. (hias)


Lesenswert?

Ste wrote:
> Die Frage ist halt ob die MMC auch wirklich 3.3V rausschickt, oder ob
> sie einfach bei low gegen Masse schaltet und bei High "loslässt" und
> wenns nicht hoch gezogen wird dann macht der Pegel irgendwas.

Soweit ich weiß ist der Dataout der MMC ein PushPull Ausgang, es werden 
also die Pegel nahe an 0V und der Versorgungsspannung der MMC sein.

> Eigentlich sollte doch durch einschalten des SPI dieser Pin richtig
> eingerichtet werden (also als Eingang)?!?

Dabei bin ich mir nicht so sicher. Das lässt sich aber einfach testen, 
durch ausprobieren :).

Hias

von Ste (Gast)


Lesenswert?

Hallo!

Mit einem Pullup gegen die Betriebsspannung und mit deinem Trick mit dem 
zuerst ein Byte senden scheint es nun tatsächlich zu funktionieren, aber 
weshalb zuerst ein Byte schicken, bevor man cs low zieht? Muss er erst 
warm laufen? Woher weisst du das? Durch raten? Ich habe das Datenblatt 
einer MMC angeschaut und dort nichts gefunden....

Danke erst mal!!

von Philipp B. (philipp_burch)


Lesenswert?

Hi,

im DB der MMCs ist das irgendwo in einem Timing-Diagramm aufgeführt. Du 
kannst das Byte auch nach dem Command übertragen, spielt AFAIK keine 
Rolle. Hast du's denn jetzt nochmal ohne des probiert?

von Ste (Gast)


Lesenswert?

Ja, wenn ich es vor dem cs low weglasse gehts nicht mehr, hinterher 
senden (nach dem cs wieder high??) habe ich noch nicht probiert, werde 
ich aber noch  tun und berichten, aber hauptsache es funktioniert jetzt 
mal, danke danke danke....

von E. M. (hias)


Lesenswert?

Hallo!

Ja steht im Datenblatt, z.B. in dem von Ulrich Radigs Seite. (Ab Seite 
72)
Da wird CS aber auf low gezogen und dann die 8 bit gesendet. Bei mir war 
das anderes rum. Scheint in der Praxis egal zu sein.
Ich denke das ganze wird benutzt um die MMC auf das Empfangen 
vorzubereiten.


Ach ja, hast du jetzt den MISO Pin als Eingang deklariert?
Oder nur einen Pull-Up eingebaut?


Hias

von Ste (Gast)


Lesenswert?

Ah, ok danke, da steht auch, dass es nach einem Befehl gesendet werden 
muss, ob cs low oder high spielt auch keine Rolle...

Nein, ich habe ihn nicht als Input definiert, auf Seite 57 im AtMega8 
Datenblatt steht, dass wenn SPI als Master aktiviert wird, dass dann 
egal was in DDRB eingestellt wurde automatisch MISO als Input verwendet 
wird.
Hingegen einen Pullup ist nun drin.

Also Danke nochmals an alle Helfer...

Gruss

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.