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.
google mal nach "MCI_LPC24xx.c" und "MCI_LPC24xx.h" - das wird dir vielleicht weiterhelfen. (Bestandteile der Keil RealView Run-Time Library).
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....
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!
>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.
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.
>Wie lange dauert denn bei dir das Lesen eines Sektors?
Im SPI Mode im Millisekunden Bereich.
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?
>Beim MCI kennst du dich nicht aus, holger? Nein, ich habs mal mit LPC2138 probiert. Irgendwas machst du falsch;)
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?
>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.
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.
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
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".
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?
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.