Hallo,
ich habe derzeit ein Projekt, in dem ich eine SD-Karte ansprechen will.
Meine Testumgebung ist ein MyEthernet 2.03 Board und einer UART ausgabe
zum printf debuggen via MySmartUSB.
Die Uart Ausgabe klappt auch ganz gut. Und SPI funktioniert auch soweit,
da das auslesen der MAC-Addresse vom ENC28j60 funktioniert.
Nun habe ich aber Probleme die SD-Karte anzusprechen. Laut Schaltplan
ist der Chipselect C6 und den benutze ich auch, von daher scheint hier
nicht mein Problem zu liegen.
Aber erst einmal zu meinem Problem.
Ich versuche die Karte zu Initialisieren indem ich erst 74 Clocks lang
0xFF sende und anschließend mit CMD55 und ACMD41 versuche die Karte zu
starten.
sd.h:
1
#ifndef __SDCARD__
2
#define __SDCARD__
3
4
/* Includes */
5
#include"../uart/uart.h"
6
#include"../spi/spi.h"
7
#include"config.h"
8
9
/* SPI */
10
#ifndef SPI_PORT
11
#define SPI_PORT PORTB
12
#endif
13
14
#define CS_SD PC6 //
15
16
/* Chip select for SD-Card */
17
#define cs_low() SPI_PORT &= ~(1 << CS_SD)
18
19
#define cs_high() SPI_PORT |= (1 << CS_SD)
20
21
/*Methods*/
22
voidsd_init(void);
23
voidsd_send_command();
24
#endif
sd.c:
1
#include"sd.h"
2
3
/*Methods*/
4
5
voidsd_init(){
6
cs_low();
7
/*Synchronizing SDCard and SPI by sending 74Clocks a logical 1*/
nunja in meiner main ruf ich bis jetzt nur sd_init() auf.
Meine Frage ist nun ist es überhaupt richtig die Karte so initialisieren
zu wollen?
Das was ich habe, habe ich der
Part_1_Physical_Layer_Simplified_Specification_Ver_3.01_Final_100518.pdf
entnommen und sollte meiner meinung nach stimmen, jedoch ist der
Informationsfluss momentan noch sehr hoch für mich weshalb es auch sehr
gut sein kann, dass ich mich irre.
Es wäre cool wenn mir einer ein paar tipps zur SDKarte geben könnte.
Also wie das mit den Commands ist, was ich da beachten muss und ka.
noch eine Frage wäre, ob ich immer eine Antwort im R1 Format bekomme?
mfG Flo
ok also ich hab schonma einen Fehler entdeckt ... das mit dem ENC hab
ich vorher auf nem pollin board getestet gehabt . . . auf dem MyEthernet
sind es andere Pins für Miso Mosi und SCK jetzt darf ich mir ersma UART
als SPI anschaun :P.
Hallo, da der Code nicht vollständig ist vermutet meine Glaskugel einen
der Standardfehler. Wenn der SS vom SPI nicht als Ausgang konfiguriert
wird geht gar nichts. Beim 644 glaube ich PB4. Bitte mal nachsehen!
Danke für den Hinweis ... das war Anfangs ein Fehler als es noch auf dem
anderen Board getestet wurde. Habe ich dann aber dank der Hilfe meines
Professors herausgefunden.
Jetzt lag der Fehler erst einmal daran, dass ich das Board gewechselt
habe zu MyEthernet V2.03 und die SD-Karte an dem UART1 hängt, was man ja
glücklicherweise als SPI betreiben kann.
Ich werde nun erst einmal versuchen dass ordentlich einzubinden.
Aber hier nochmal der gesamte Code:
main.c :
1
#define F_CPU 20000000L
2
#define BAUD 9600L
3
#define DEBUG
4
5
#include<avr/io.h>
6
#include<util/delay.h>
7
#include"uart/uart.h"
8
#include"spi/spi.h"
9
#include"sd/sd.h"
10
11
intmain(void){
12
USART_Init();
13
SPI_Init();
14
SPI2_Init();//ENC OR SDCard
15
16
//PORTB |= (1<<SPI_CS);
17
18
printf("Welcome to WeSa System v0.0.1a\n");
19
20
printf("starting -> SD test\n");
21
22
sd_init();
23
24
while(1){
25
26
_delay_ms(500);
27
}
28
29
return0;
30
}
spi.h:
1
/*
2
Name: spi.h
3
Author: Mathäus Sander & Florian Weinhold
4
5
Desc.: SIP function library for ATmega Prozessors
6
License: LGPL
7
*/
8
9
#include<avr/io.h>
10
11
#ifndef _SPI_H_
12
#define _SPI_H_
13
14
/*standard SPI*/
15
#define DDR_SPI0 DDRB
16
#define DD_MOSI0 DDB5
17
#define DD_SCK0 DDB7
18
#define DD_CS0 DDB4
19
20
/*UART1 as SPI*/
21
#define DDR_SPI1 DDRD
22
#define XCK1 PD4
23
24
/*chipselects*/
25
#define CS_ENC PD5
26
#define CS_SD PC6
27
28
#define SPI0_PORT PORTD
29
#define SPI1_PORT PORTC
30
31
/*methods to select */
32
#define select_enc() SPI0_PORT &= ~(1 << CS_ENC) //sets chip select for EN28j60 to 0
33
#define unselect_enc() SPI0_PORT |= (1 << CS_ENC) //sets chip select for EN28j60 to 1
34
#define select_sd() SPI1_PORT &= ~(1 << CS_SD) //sets chip select for SDCard to 0
35
#define unselect_sd() SPI1_PORT |= (1 << CS_SD) //sets chip select for SDCard to 1
36
37
// initialize
38
voidSPI_Init(void);
39
voidSPI2_Init(void);
40
// send and recive methode
41
uint8_tspi_transmit(uint8_t);
42
uint8_tspi2_transmit(uint8_t);
43
44
#endif
spi.c:
1
#include"spi.h"
2
#include"../uart/uart.h"
3
4
//Basic SPI
5
voidSPI_Init(void){
6
/* Set MOSI and SCK output, all others input */
7
DDR_SPI0=(1<<DD_MOSI0)|(1<<DD_SCK0)|(1<<DD_CS0);
8
9
/* Enable SPI, Master */
10
SPCR=(1<<SPE)|(1<<MSTR);
11
/* Set clock fck/2 */
12
SPSR=(1<<SPI2X);
13
14
#ifdef DEBUG
15
printf("SPI Initialized\n");
16
#endif
17
}
18
19
20
//Uart1 as SPI
21
voidSPI2_Init(void)
22
{
23
UBRR1=0;
24
/* Setting the XCKn port pin as output, enables master mode. */
25
DDR_SPI1|=(1<<XCK1);
26
/* Set MSPI mode of operation and SPI data mode 0. */
ich glaub das sollten alle wichtigen Quelltexte sein. Funktionieren tut
es leider immer noch nicht. Wobei ich gerade auch viel am rumprobieren
bin.
Jedenfalls habe ich das so verstanden, dass wenn ich die Karte so
initialisieren will eine 1 als Antwort bekomme bis die Karte fertig
initialisiert ist.
Jedoch kriege ich immer nur 0 raus.
Gibt es einen Wert den ich übermitteln kann, auf den ich direkt einen
bestimmten Wert als antwort bekomme?
mfG
Flo
ok hab noch einen Fehler ich schalte den Chipselect für die SD Karte
nicht auf ausgang, habe ich aber jetzt auch geändert. Funktioniert
trotzdem nicht.
Damit die Karte in den SPI-Modus wechselt muss sie erstmal ein
GO_IDLE_MODE-Kommando mit korrekter CRC empfangen, d.h. 0x40 0x00 0x00
0x00 0x00 0x95. So lange die Karte noch im SD-Modus ist wirst du auch
keine Antwort sehen, da die dort auf einer anderen Leitung als im
SPI-Modus geliefert wird.
Im SPI-Modus sind die CRCs dann egal (sofern man sie nicht wieder
einschaltet), nur bei CMD8 (SEND_IF_COND) muss immer eine korrekte CRC
mitgeliefert werden wenn man mit einer SDHC-Karte reden will.
Habe es gestern nun hin bekommen, nach diversen Änderungen an den
einzelnen Dateien. Woran genau es lag kann ich nicht sagen.
Nun habe ich jedoch noch ein oder 2 Fragen zu den SDHC cards.
Also ... ich sende CMD0 und bekomme eine 0x1 zurück. Dann sende ich
solange cmd1 bis eine 0 kommt. Dies funktioniert wunderbar. Wenn ich
jedoch die 4GB karte einlege kommt 0x5 als antwort (illegal Command).
Was ich dann so interpretier dass CMD1 nicht geht also versuch ichs wenn
keine 0x1 mehr kommt sondern 0x5 mit ACM41. Ist das richtig?
Anschließend bekomme ich nur noch 0xFF zurück ... ist die SDHC karte
dann rdy oder muss die auch irgendwann auf 0 wechseln? Notfalls hab ich
noch nen timeout eingebaut
Hier mal der Quellcode für die SD Karte sollte ausreichen glaub ich
sd.h:
1
#ifndef __SDCARD__
2
#define __SDCARD__
3
4
/* Includes */
5
#include"../uart/uart.h"
6
#include"../spi/spi.h"
7
8
#ifndef DEBUG
9
#define DEBUG //Should be only defined if Debug messages are needed
10
#endif
11
/*spi methods*/
12
#define spi_send_byte(x) spi2_transmit(x) //Method to transmit a Byte via SPI
13
#define spi_speed_low() ; //sets SPI Clockrate between 100kHz and 400kHz
14
#define spi_speed_high() ; //sets SPI Clockrate to maximum
15
16
/*defines for Hardware Initialisation*/
17
#define SD_CS_PIN PC6 //Chipselect for SD Card
18
#define SD_CS_PORT PORTC //Port of SD_CS
19
#define SD_CS_DDR DDRC //Data Direction Register for SD_CS
Flo W. schrieb:> muss ich bei SDHC karten noch irgendetwas berücksichtigen?
Nach CMD0 muss ein CMD8 mit korrekter(!) CRC und gesetztem HCS-Bit
gesendet werden. Wenn die Karte darauf mit einem Fehler antwortet ist es
eine MMC- oder 1.x-SD-Karte und definitiv keine SDHC. Bei ACMD41 muss
ebenfalls vom Host das HCS-Bit gesetzt werden (1L<<30). Wenn die Karte
danach in der Antwort auf CMD58 das passende Bit setzt ist es eine
SDHC-Karte. Die unterscheiden sich nach der Initialisierung von
MMC/SD-Karten "nur" noch darin, dass sie bei Lese- und Schreibbefehlen
keinen Byteoffset sondern eine Sektornummer (512-Byte-Sektoren) haben
wollen, was bei typischen Implementierungen bedeutet dass man für
MMC/SD-Karten in den Lese- und Schreibfunktionen die Sektornummer mit
<<9 shiftet und für SDHC-Karten den Shift weglässt.
Ein bislang recht gut funktionierendes Codebeispiel zur
SD-Initialisierung findet sich zB unter
http://www.sd2iec.de/cgi-bin/gitweb.cgi?p=newboot.git;a=blob;f=sdlight.c;h=4a074b4269df972fed0a0f43f8e763caf98beece;hb=HEAD#l166
>Ein bislang recht gut funktionierendes Codebeispiel zur>SD-Initialisierung findet sich zB unter>http://www.sd2iec.de/cgi-bin/gitweb.cgi?p=newboot....
Aus dem C Code:
goto not_sd2;
AUAUAUUUAUUAAAAA;)
holger schrieb:> Aus dem C Code:> goto not_sd2;>> AUAUAUUUAUUAAAAA;)
Oops, wie habe ich denn diese Stelle verbrochen? Fixed, der Link zeigt
allerdings auf eine spezifische Revision der Datei.
Also noch einmal schritt für Schritt so wie ich das verstanden habe
1. Warten bis Spannung der Karte bei 2.2 V
2. Speed auf 100kHz bis 400kHz setzten
3. Chipselect für Karte auf High
3. 1ms warten
4. 74+ Clocks bei kontinuierlichem senden von 1
5. CS auf low
6. CMD0, ohne Argumente und mit berechneter CRC (0x95) senden
6.1 Wenn eine 1 zurück kommt ist die Karte im IDLE mode
6.2 Wenn eine 0 zurück kommt konnte keine Karte gefunden oder erkannt
werden
7. CMD8 mit CRC (wie lautet die) und gesetztem HCS bit (heisst bit 30
das 30.bit von den argumenten her oder vom gesamten command?)
7.1 Bei Fehler ist es eine MMC / SDv1.x
7.2 Ansonsten SDv2 oder SDHC
8. CMD58 senden bei korrekter antwort haben wa dann ein SDHC
9. ACMD41 mit gesetztm SDHC bit senden (benötigen MMCs nicht CMD1?) bist
karte gesetzt oder timeout abgelaufen is
9.1 Wenn Karte auf 0 wechselt ist sie initialisiert und SDHC karten
geben dauerhaft 0xFF aus (stimmt das?).
--> Karte ist initialisiert.
10. Speed hochsetzten
11. Chipselect auf high
12. ein paar dummy signale (0xFF) zum clearen senden
is was an der Reihenfolge falsch oder muss ich was beachten?
Flo W. schrieb:> 7. CMD8 mit CRC (wie lautet die) und gesetztem HCS bit (heisst bit 30> das 30.bit von den argumenten her oder vom gesamten command?)
Es ist Bit 30 des 32-Bit-Arguments nach dem Kommandobyte. Wenn du als
Parameter 0x1aa sendet ist die passende CRC 0x87.
> 7.1 Bei Fehler ist es eine MMC / SDv1.x> 7.2 Ansonsten SDv2 oder SDHC
Stimmt so
> 8. CMD58 senden bei korrekter antwort haben wa dann ein SDHC
Wenn Bit 30 in der Antwort gesetzt ist - es kann auch eine
Nicht-SDHC-2.x-SD-Karte sein
> 9. ACMD41 mit gesetztm SDHC bit senden (benötigen MMCs nicht CMD1?) bist> karte gesetzt oder timeout abgelaufen is
Ja - die meisten MMC-Karten sagen schon nach CMD55 "kenne ich nicht",
hier liegt aber eine Sandisk-Karte die erst beim Absetzen des
darauffolgenden (A)CMD41 mit einem Fehler aussteigt - in beiden Fällen
initialisiert man einfach mit CMD1 statt ACMD41. Wenn man den Code
einfach halten möchte kann man das CMD1 auch problemlos an eine SD-Karte
senden, die sollte dann schon beim ersten mal "ok, bin initialisiert"
zurückmelden.
> 9.1 Wenn Karte auf 0 wechselt ist sie initialisiert und SDHC karten> geben dauerhaft 0xFF aus (stimmt das?).
Korrekt initialisierte SDHC-Karten geben dann auch 0 aus.
(SDXC-Karten sind mir noch zu teuer, scheinen aber nach kurzem
Überfliegen der Specs genauso initialisiert zu werden)
argh, hab grad die 0x87 als crc selber berechnet per hand aufm papier
:P. Hat ewig gedauert ^^.
aber danke shconma für die Antwort hilft mir weiter.
Also eins finde ich aber komisch
laut Spezifikation habe ich ja bei 0x05 response eine MMC oder SDCv1
nun habe ich hier vor mir nur 2 microSD Karten liegen. Eine mit 256mb wo
ich mir dachte das is bestimmt eine sd karte der version eins
und iene mit 4gb also SDCH
bei der 256mb bekomme ich R1:0x01 und restdaten: 001AAF als antwort
zurück
(ist somit also V2)
bei der 4gb bekomme ich R1:0x05 und restdaten: FFFFFF als antwort zurück
also kann meine 4GB karte das Command nicht oder wie? sollte sie doch
eigtl.
ich setze hier das HCS aber dann kommt mit der crc wieder nen fehler ...
gibs nicht irgendwo einen rechner dafür unter google find ich keinen.
achja ich schreibe 86 rein weil ich das letzte bit noch in meiner
methode setzte.
Mah ich bin am verzweifeln was die HC karten angeht.
Die 256MB karte von mir kann ich ohne probs initialisieren aber die 4GB
karte will net.
Aber ich sehe auuch gerade dass da ein CRC error kommt, ich dachte eigtl
dass bei dem ACMD41 die CRC net berücksichtig wird.
also hier der momentane code:
sd.h
1
#ifndef __SDCARD__
2
#define __SDCARD__
3
4
/* Includes */
5
#include"../uart/uart.h"
6
#include"../spi/spi.h"
7
8
#ifndef DEBUG
9
#define DEBUG //Should be only defined if Debug messages are needed
10
#endif
11
/*spi methods*/
12
#define spi_send_byte(x) spi2_transmit(x) //Method to transmit a Byte via SPI
13
#define spi_speed_low() ; //sets SPI Clockrate between 100kHz and 400kHz
14
#define spi_speed_high() ; //sets SPI Clockrate to maximum
15
16
/*defines for Hardware Initialisation*/
17
#define SD_CS_PIN PC6 //Chipselect for SD Card
18
#define SD_CS_PORT PORTC //Port of SD_CS
19
#define SD_CS_DDR DDRC //Data Direction Register for SD_CS
im Übrigend musst du nach erfolgreichem CMD8 response ACMD41 mit
folgendem Argument schicken :
0x40000000 d.h. die Karte ist ab Spezifikation 2.0 und unterstützt evtl.
das HCS bit.
Siehe Flow:
http://elm-chan.org/docs/mmc/sdinit.png
Gruss