Forum: Mikrocontroller und Digitale Elektronik Frage zum Media Card Interface (LPC24xx)


von Tobias P. (hubertus)


Lesenswert?

Hallo,
ich versuche mich gerade am MCI des LPC2468.
Da ich nicht im geringsten verstehe, wie dieses MCI funktioniert, und 
auch aus dem Handbuch des Mikrocontrollers nicht wirklich schlau werde, 
habe ich mir mal das Code sample bei NXP runtergeladen und versucht zum 
Laufen zu bringen. Naja, es funktioniert so halbwegs. Ich versuche den 
ersten Sektor der Karte auszulesen (eine SD-Karte mit 128 MB von 
Panasonic, uraltes Teil), was auch klappt. Allerdings kriege ich nur die 
ersten 32 Bytes, anschliessend wird, ohne dass ich dies beabsichtige, 
der nächste Sektor ausgelesen (wieder nur 32 Bytes). Und das bringt ja 
wohl überhaupt nix - ich will doch ganze Sektoren auslesen!

So, nun 2 Fragen dazu.

1. Gibt es irgendwo ein Tutorial oder eine Beschreibung, wie man dieses 
MCI richtig programmiert? Aus dem NXP-Code werde ich nicht wirklich 
schlau.

2. Warum funktioniert der NXP-Code bei mir nicht richtig bzw. warum 
werden nur 32 Bytes gelesen?

Also, an der Karte liegt es, denke ich, nicht. Ich habe sie an meinem 
Laptop angeschlossen, der hat auch ein MCI - dort konnte ich dann 
mittels Disk-Editor den ersten Sektor der Karte lesen. Und das, was mein 
LPC2468 liest, stimmt mit dem überein - aber halt nur die ersten 32 
Bytes.

von Tobias P. (hubertus)


Lesenswert?

Weiss niemand bescheid? :o

von embedded-os (Gast)


Lesenswert?

google mal nach "MCI_LPC24xx.c" und "MCI_LPC24xx.h" - das wird dir 
vielleicht weiterhelfen. (Bestandteile der Keil RealView Run-Time 
Library).

von Tobias P. (hubertus)


Lesenswert?

Hallo,
danke erstmal.
Kannst du ansonsten die Dateien hier rein stellen?

Irgend eine Doku zu dem Media Card Interface gibt es wohl nicht, oder?
Ich kann mir nicht vorstellen, dass das wenige, was im NXP-Handbuch 
steht, ausreicht, um eine SD-Karte mittels MCI anzusprechen.
Ich verstehe einfach nicht, was der Code macht....

von Tobias P. (hubertus)


Lesenswert?

Also,
ich habe die beiden Files gefunden. Danke für den Tipp! Schauen zwar 
ziemlich ähnlich aus, wie der Example-Code den man bei NXP runterladen 
kann.
Zu diesem habe ich noch eine Frage:
er ist gespickt mit Verzögerungsschleifen, im stil von

for(i=0; i < 0x100; i++);

Dank diesen Schleifen ist der Datentransfer extrem langsam:
Mittels MCI_Read_Block lese ich sequentiell 100 Sektoren. Ungefähr so:

int i;
for(i=0; i<100; i++)
  MCI_Read_Block(i);

Das funktioniert super, aber ist sau langsam. Ich habe es wie folgt 
getestet: beim Start von MCI_Read_Block wird ein IO-Pin gesetzt, beim 
verlassen wird der Pin wieder zurück gesetzt. Auf dem Oszi kann ich 
jetzt schöne Rechteck-Impulse sehen: ca. 1 s an, und nur wenige us aus 
(ist ja klar - die Aus-Zeit dauert nur so lange wie der Jump vom Ende 
der for-Schleife bis zum Anfang).
Jetzt meine Frage dazu: Warum ist das so langsam? Wegen dieser 
Verzögerungsschleifen? Braucht es die wirklich oder kann man die nicht 
irgendwie weg optimieren?
Das kann man doch nicht ernsthaft brauchen - eine Routine, die zum 
Sektor-lesen eine Sekunde braucht!

von holger (Gast)


Lesenswert?

>und nur wenige us aus
>(ist ja klar - die Aus-Zeit dauert nur so lange wie der Jump vom Ende
>der for-Schleife bis zum Anfang).

Wieso sollte ein ARM mehrere us für einen simplen
Jump brauchen? Das ist VIEL zu lang.

von Tobias P. (hubertus)


Lesenswert?

Er läuft mit 72 MHz...
Wie lange dauert denn bei dir das Lesen eines Sektors?

Was ich auch nicht verstehe: Im Moment arbeite ich mit einem Takt (für 
die Karte) von 2 MHz. Damit funktioniert es recht zuverlässig, aber halt 
langsam. Sobald ich den Takt auch nur minimal erhöhe, z.B. auf 4 MHz, 
dann bleibt der Code an folgender Stelle stehen:

  MCI_Read_Block(0, (char*)&pBuffer);
  while ( MCI_Block_End_Flag == 1 );

Und zwar in der while-Schleife. Der Sektor ist dann auch nur zur Hälfte 
in den Puffer geschrieben.... (Achtung: ich habe MCI_Read_Block so 
geändert, dass man da einen Pointer übergeben kann, wo der Sektor 
abgelegt werden soll.).
Ausserdem ist mir nicht ganz klar, warum man zum Lesen des Fifo solche 
Assembler-Routinen benötigt, und dies nicht mittels 'normalem' C-Code 
tun kann.

von holger (Gast)


Lesenswert?

>Wie lange dauert denn bei dir das Lesen eines Sektors?

Im SPI Mode im Millisekunden Bereich.

von Tobias P. (hubertus)


Lesenswert?

Wow! dann hat ja der Multimedia-Mode oder wie der auch immer heisst gar 
keine Vorteile.
Hmm, wenn ich noch SPI-Schnittstellen frei hätte, würde ich das schnell 
umstricken....

Beim MCI kennst du dich nicht aus, holger?

von holger (Gast)


Lesenswert?

>Beim MCI kennst du dich nicht aus, holger?

Nein, ich habs mal mit LPC2138 probiert.
Irgendwas machst du falsch;)

von Tobias P. (hubertus)


Lesenswert?

Kannst du mir nicht ein bisschen Hilfestellung bieten ;)

Könnte es ein Problem sein, dass mein Pufferspeicher im externen SDRAM 
liegt?

Wie war das bei dir mit diesen Verzögerungsloops im Code? Hattest du die 
auch drin?

Und hattest du deinen MCI Code selber gemacht oder auch den von NXP bzw. 
Keil benutzt?

von holger (Gast)


Lesenswert?

>Und hattest du deinen MCI Code selber gemacht oder auch den von NXP bzw.
>Keil benutzt?

Ja, SPI Code selber gemacht. Der LPC2138 hat kein MCI.

von Tobias P. (hubertus)


Lesenswert?

Ah okay. Was meinst du, könnte es eine Software-SPI auch auf einen 
brauchbaren Datendurchsatz bringen?
Die eine Sekunde, die das Lesen eines Sektors dauert, ist mir definitiv 
zu lange. Was allerdings interessant ist: Beim ersten Lesevorgang geht 
es sehr schnell. Wird dann sequentiell weiter gelesen, wird es immer 
langsamer.

von Tobias P. (hubertus)


Lesenswert?

holger,
falls es dich interessiert: ich habe den Fehler gefunden. Der Pointer, 
welcher auf den Speicherbereich zeigt, wo die Daten hin sollen, war 
nicht auf den korrekten Speicherbereich initialisiert. Schreibt man in 
den falschen Speicher, dann dauert das sehr lange, was zu diesem 
seltsamen Effekt führt, dass das Lesen so lange dauert. Jetzt sind es 
nur wenige 100 us, bis ein Sektor ausgelesen ist (jedenfalls < 1 ms, 
wenn ich mich recht erinnere.)

Gruss
   Tobias

von Frank G. (embedded-os)


Lesenswert?

Also SPI sowie MCI können maximal mit 25MHz bei SD2.00 Karten verwendet 
werden (MMC+ bis zu 50MHz). Durch die Busbreite von SPI / SD ergibt das 
25Mbit/s bei SPI und 12,5MByte/s als theoretisches Maximum.
Um einen Blick in die Std.'s zu nehmen google mal zu SD-Karten 
"SD_Simplified_Physical_Layer_Spec.pdf" oder über "www.sdcard.org" und 
zu MMC-Karten "JESD84-B42.pdf".

von Tobias P. (hubertus)


Lesenswert?

Hi Leute,
ich versuche mich grade darin, die MCI_LPC24xx.c von Keil zum Laufen zu 
bringen.
Und zwar habe ich mir als Toolchain eine Testversion von IAR EWARM 
besorgt, da dieser direkt mit dem J-Link zusammen arbeiten kann (was 
übrigens sehr angenehm ist - endlich kein Ruckeln und Stocken mehr wie 
bei Rowley).
So, nun habe ich also diese MCI_LPC24xx.h und .c-Dateien. Ich bin schon 
mal so weit, dass die Funktion mci_init() TRUE zurückgibt, wenn eine 
Karte eingesteckt ist und ein Clock ausgegeben wird. Soweit so gut, nun 
dachte ich mir, dass das Lesen eines Sektors relativ einfach sei mittels

mci_read_sect(dwSectorNbr, pBuffer, 1);

auch da werden alle Befehle korrekt ausgeführt (alles liefert TRUE 
zurück), allerdings schlägt der DMA irgendwie fehl. Es wird kein 
einziges Byte an Daten transferiert, und dementsprechend ist der 
Rückgabewert von mci_read_sect dann auch FALSE....

Frage: könnt ihr mir weiterhelfen? Muss ich noch irgendwas weiteres 
initialisieren? Ich mache nach dem Reset nichts anderes als:

- PLL auf 72 MHz einstellen
- VIC initialisieren
- Interrupts aktivieren
- EMC aktivieren -> Heap und Stack liegen im externen SDRAM (64 MBytes)
- danach wird mci_init aufgerufen, welche dann selber den DMA 
initialisiert sowie die nötigen Pins für das MCI
- mci_init erkennt die Karte korrekt, stellt korrekt auch auf das 4 Bit 
Interface um
- danach wird mci_read_sect aufgerufen und liefert FALSE.

Wo liegt der Fehler?

von Tobias P. (hubertus)


Lesenswert?

Weiss niemand bescheid?

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.