SD card: STOP_TRANSMISSION beim MULTIPLE BLOCK WRITE

OP #1578683
Hallo Leute!

Das Wichtigste vorweg: Multiple Block Write gelingt sehr gut und ich 
bekomme sagenhafte 2.5 MBytes/s! Ich tickse das FAT-System aus, indem 
ich die leere Karte mit grösseren ebenfalls leeren Dateien fülle und mit 
dem Startsektor der ersten Datei beginne. Mein Chip ist PIC24Hxxxx.

Was nicht geht, ist, den Datentransfer zu stoppen, ohne ohne die 
Brechstange zu verwenden, sprich die Karte neu initialisieren zu müssen. 
Irgendwie will die Karte weder STOP_TRANS_TOKEN (0xFD) noch CMD12 
fressen. Ich wüsste auch nicht, welchen Responce zu erwarten, wenn sie 
es fressen würde.

In so mancher Dokumentation steht geschrieben, dass STOP_TRANS_TOKEN für 
SPI-Modus angedacht, während CMD12 für dem SD-Modus bestimmt ist. Die 
anderen unterscheiden gar nicht dazwischen.

Ähm... ja...

Gruss
Dimitri
#1578699
Hallo,
ich mache das bei Multiblock so wie in der Spezifikation, und das 
klappt, wenn die Karte das halt unterstützt.

Erstmal muss das block alligned sein. Also nur nach einem 512 Byte block 
klappt das.
Dann wie folgt:
1
unsigned char cmd[]={0x40+13,0x00,0x00,0x00,0x00,0xFF}; // cmd13 response R2
2

3
mmc_write_byte(0xFD);  // stop token
4

5
mmc_wait_ready();
6

7
response=mmc_write_command (cmd); // cmd13, response R2, alles ok?
8

9
mmc_wait_ready();

denke die Funktionen sind sprechend genug :)

Grüße Daniel
OP #1578815
Hallo Daniel,

hier ist meine bis auf den Abschluss lauffähige Variante mit 
freundlicher Unterstützung von Microchip ;-) :
1
unsigned int MDD_SDSPI_SetStartSector(DWORD sector_addr)
2
{
3
    MMC_RESPONSE    response; 
4

5
    // send the cmd
6
  if (gSDMode == SD_MODE_NORMAL)
7
    response = SendMMCCmd(WRITE_MULTI_BLOCK,(sector_addr << 9));
8
  else
9
    response = SendMMCCmd(WRITE_MULTI_BLOCK,(sector_addr));
10
        
11
  // see if it was accepted
12
  if(response.r1._byte != 0x00) return 0;  // failed
13
  
14
  return 1;              // success
15
}
16

17
unsigned int MDD_SDSPI_SectorMultiWriteDMA(DWORD sector_addr, BYTE* buffer, unsigned int SectorsToWrite)
18
{
19
    WORD            index, k, m, Timeout = 0;
20
    BYTE            data_response;
21
    MMC_RESPONSE    response; 
22
    //BYTE            status = TRUE, ByteToWrite, StayInTheLoop = 1;
23
  unsigned int j;
24

25
  if(MDD_SDSPI_SetStartSector(sector_addr))
26
  {
27
    for(j = 0; j < SectorsToWrite; j++)
28
    {
29
      CloseSPIM();
30
      OpenSPIM(SYNC_MODE_CRAZY);
31

32
      DMA0CONbits.CHEN = 1; 
33
      DMA3CONbits.CHEN = 1;
34
      _LATA1 = 1;
35
      // Force First word after Enabling SPI
36
        DMA0REQbits.FORCE = 1;
37
      // wait until the first transfer is finished
38
        while(DMA0CONbits.CHEN == 1);
39
      _LATA1 = 0;
40
      asm volatile("nop");
41
      asm volatile("nop");
42
      asm volatile("nop");
43
      asm volatile("nop");
44
      asm volatile("nop");
45
      asm volatile("nop");
46
      asm volatile("nop");
47
      asm volatile("nop");
48
      asm volatile("nop");
49
      asm volatile("nop");
50
      asm volatile("nop");
51
      asm volatile("nop");
52
      asm volatile("nop");
53
      asm volatile("nop");
54
      asm volatile("nop");
55
      asm volatile("nop");
56
      asm volatile("nop");
57
      asm volatile("nop");
58
      asm volatile("nop");
59
      asm volatile("nop");
60
      asm volatile("nop");
61
      asm volatile("nop");
62
      asm volatile("nop");
63
      asm volatile("nop");
64
      asm volatile("nop");
65
      asm volatile("nop");
66
      asm volatile("nop");
67
      asm volatile("nop");
68
      asm volatile("nop");
69
      asm volatile("nop");
70
      asm volatile("nop");
71
      asm volatile("nop");
72
      asm volatile("nop");
73
      asm volatile("nop");
74
      asm volatile("nop");
75
      asm volatile("nop");
76
      asm volatile("nop");
77
      asm volatile("nop");
78
      asm volatile("nop");
79
      asm volatile("nop");
80
      asm volatile("nop");
81
      asm volatile("nop");
82
      asm volatile("nop");
83
      asm volatile("nop");
84
      asm volatile("nop");
85
      asm volatile("nop");
86
      asm volatile("nop");
87
      asm volatile("nop");
88
      asm volatile("nop");
89
      asm volatile("nop");
90
      asm volatile("nop");
91
      asm volatile("nop");
92
      DMA3CONbits.CHEN = 0;
93
      
94
      CloseSPIM();
95
      OpenSPIM(SYNC_MODE_SLOW);
96

97
            data_response = MDD_SDSPI_ReadMedia();  //Read response
98
            
99
      if((data_response & 0x0F) != DATA_ACCEPTED) return(0);
100
      else
101
      {
102
        index = 0;  //using i as a timeout counter
103
        do  //Wait for write completion
104
                {
105
                    SPIBUF = 0xFF;
106
                    while(!SPISTAT_RBF);
107
                    data_response = SPIBUF;
108
                    index++;
109
                } while((data_response == 0x00) && (index != 0));
110

111
                  //if(index == 0) return(j);
112
            }
113
            //mSend8ClkCycles();
114
      //if(status == FALSE) break;
115
      
116
        }
117
  }  
118
    //SD_CS = 1;
119

120
    return(SectorsToWrite);
121
} //end SectorMultiWrite
In der ersten for-Schleife starte in den DMA-Transfer für SPI. Ich 
schicke 1 + 512 + 2 Bytes, wobei das erste Byte 
DATA_START_MULTIBLOCK_TOKEN ist, gefolgt von 512 Bytes Daten und 2 Bytes 
Pseudo-CRC. Danach wird DMA deaktiviert, damit ich SPI wieder manuell 
ansteuert kann. Ich sende eine Anfrage, ob meine Daten akzeptiert 
wurden, und bekomme eine saubere Antwort (DATA_ACCEPTED = 0b101). Dann 
wird die SPO-Leitung der Karte gepolt, bis sie wieder hochgeht. Je nach 
Alter der Karte dauert es unterschiedlich lang. Aber OK. Ich musste 
feststellen, dass ich das Dummy-Byte (mSend8ClkCycles) eigentlich nicht 
brauche, um im Geschäft zu bleiben.

Meine Frage ist nun, wo soll ich STOP_TRANS_TOKEN reinwürgen und welche 
Reaktion darauf von der Karte zu erwarten wäre. Es muss doch danach 
sofort möglich sein, SendMMCCmd(WRITE_MULTI_BLOCK,(sector_addr << 9)) zu 
senden, so dass es akzeptiert wird.

Nach jedem Block während des Schreibens geht die SPO-Leitung der Karte 
recht schnell hoch (not busy). Muss ich denn mit längeren Wartezeiten 
rechnen, wenn ich den Transfer abschliesse?

Ich sehe, Du schickst, CMD13, um den Status zu ermitteln, stimmt's?

Gruss
Dimitri

P.S. nop's sind nötig, weil offensichtlich DMA0CONbits.CHEN bereits auf 
Null gesetzt wird, noch before das letzte Byte vollständig übertragen 
wurde. Wenn ich DMA3CONbits.CHEN = 0 sofort ausführe, schneidet es mir 
die letzten Bits ab.
OP #1579102
Ich glaube, ich hab's :-)

Nachdem der letzte Block der Sequenz akzeptiert wurde und die Leitung 
wieder auf HIGH gegangen ist, macht man Folgendes:
1
WriteSPIM(STOP_TRAN_TOKEN); // 1 Byte : 0xFD
2
mSend8ClkCycles(); // <= wichtig!
3
index = 0;  //using i as a timeout counter
4
do  //Wait for write completion
5
{
6
  SPIBUF = 0xFF;
7
  while(!SPISTAT_RBF);
8
  data_response = SPIBUF;
9
  index++;
10
} while((data_response == 0x00) && (index != 0));
Wichtig ist, nach dem Senden von STOP_TRAN_TOKEN ein Dummy-Byte zu 
senden, denn erst dann geht die Leitung runter auf BUSY und kann gepolt 
werden.

Hier auf der Seite 6 bekommt man ungefähr mit, was geschieht:
http://forums.parallax.com/forums/attach.aspx?a=32012

Je nach Karte dauert's dann um 2 ms, bis die restlichen Daten geflasht 
sind.

Gruss
Dimitri
#1579134
Sieht ja spannend aus :)

Ja ich frage mit cmd13 ob die Karte alles flaschen konnte und ob alles 
Ok gelaufen ist. Das ist so weit ich weiß die korrekte Methode bei 
multiblock-write Operationen bzw. beim beenden einer solchen.

Ja, nach dem stop-tran-token müsste ein dummy byte rein.


Grüße Daniel

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 16 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.