Forum: Mikrocontroller und Digitale Elektronik SD-Card an MSP die 2te


von Sebastian (Gast)


Lesenswert?

Hallo Zusammen,

Ich befasse mich seit einiger Zeit mit dem Anschluss einer SD-Card an 
den MSP. Wie in einigen anderen Threads besprochen, verwende ich die 
Appnote von TI.
Da es bei mir momentan hardwareseitig ein paar Probleme gibt, begnüge 
ich mich damit den Quelltext ein wenig durchzuarbeiten. Da mir das 
Programmieren nicht gerade in den Schoß gelegt wurde, kommen immer 
wieder ein paar Fragen auf, z.B. diese hier (ich weiß, ist recht 
speziell):

Die SD-Card wird mit HIGH deselektiert. Danach wird der Sendebefehl 
ausgeführt. Was genau soll das bewirken ? Dieser spiSendByte wird 
desöfteren an Stellen ausgeführt, wo ich das nicht nachvollziehen kann.
Ist er dafür da, dass man einfach das zuletzt gesendete Byte der SD-Card 
abfängt und in den RXBUF schreibt ?

1
 CS_HIGH();
2
    spiSendByte(0xff);


Hier noch die zugehörige Funktion:

1
 unsigned char spiSendByte(const unsigned char data)
2
{
3
  while ((IFG2&UTXIFG1) ==0); 
4
  TXBUF1 = data;               
5
  while ((IFG2&URXIFG1)==0);    
6
  return (RXBUF1);
7
}


Vielleicht findet sich ja ein Spezialist, der mir weiterhelfen kann.

Gruß

Sebastian

von Christian R. (supachris)


Lesenswert?

Ja, bei SPI muss der Master das Byte quasi beim Slave "abholen", es wird 
nur was empfangen, wenn was gesendet wird. Daher das Dummy-Bate 0xFF, 
damit schiebst du halt das von der SD-Karte bereitgestellte Byte in den 
RXBUF.

von Sebastian (Gast)


Lesenswert?

Hallo nochmal,

@Chris: Sowas in der Art habe ich mir schon gedacht. Jetzt ist auf jeden 
Fall einiges klarer.

Habe da aber noch eine entscheidene Frage bzgl. des Quelltextes. Mir ist 
nicht ganz klar woher der MSP weiß was er auf die Karte schreiben muss. 
An welcher Stelle in der "WriteFunktion" werden die zu übertragenen 
Daten aus dem Buffer gezogen auf den der Zeiger pBuffer zeigt ?

1
char mmcWriteBlock (const unsigned long address, const unsigned long count, unsigned char *pBuffer)
2
{
3
//  unsigned long i = 0;
4
  char rvalue = MMC_RESPONSE_ERROR;         // MMC_SUCCESS;
5
  //  char c = 0x00;
6
7
  // Set the block length to read
8
  if (mmcSetBlockLength (count) == MMC_SUCCESS)   // block length could be set
9
  {
10
    // SS = LOW (on)
11
    CS_LOW ();
12
    // send write command
13
    mmcSendCmd (MMC_WRITE_BLOCK,address, 0xFF);
14
15
    if (mmcGetXXResponse(MMC_R1_RESPONSE) == MMC_R1_RESPONSE)
16
    {
17
      spiSendByte(0xff);
18
      // send the data token to signify the start of the data
19
      spiSendByte(0xfe);
20
      // clock the actual data transfer and transmitt the bytes
21
      // put CRC bytes (not really needed by us, but required by MMC)
22
      spiSendByte(0xff);
23
      spiSendByte(0xff);
24
      // read the data response xxx0<status>1 : status 010: Data accepted, status 101: Data
25
      //   rejected due to a crc error, status 110: Data rejected due to a Write error.
26
      mmcCheckBusy();
27
      rvalue = MMC_SUCCESS;
28
    }
29
    else
30
    {
31
      // the MMC never acknowledge the write command
32
      rvalue = MMC_RESPONSE_ERROR;   // 2
33
    }
34
  }
35
  else
36
  {
37
    rvalue = MMC_BLOCK_SET_ERROR;   // 1
38
  }
39
  // give the MMC the required clocks to finish up what ever it needs to do
40
  //  for (i = 0; i < 9; ++i)
41
  //    spiSendByte(0xff);
42
43
  CS_HIGH ();
44
  // Send 8 Clock pulses of delay.
45
  spiSendByte(0xff);
46
  return rvalue;
47
} // mmc_write_block


Ähnlich verhält es sich ja auch beim Lesen. Wo (Buffer?) und warum 
landen die Daten. Vielleicht steckt die Information auch in den 
SD-Befehlen ?

Danke schonmal für eure Hilfe.


Gruß

Sebastian


PS: Kann man den Thread vielleicht ins MSP-Forum verschieben ?

von holger (Gast)


Lesenswert?

>An welcher Stelle in der "WriteFunktion" werden die zu übertragenen
>Daten aus dem Buffer gezogen auf den der Zeiger pBuffer zeigt ?

>      // send the data token to signify the start of the data
>      spiSendByte(0xfe);
>      // clock the actual data transfer and transmitt the bytes

Die Stelle ist genau hier. Scheint aber von irgend jemand
gelöscht worden zu sein.

>      // put CRC bytes (not really needed by us, but required by MMC)
>      spiSendByte(0xff);
>      spiSendByte(0xff);

von Sebastian (Gast)


Lesenswert?

öhm ... ich habe da eigentlich nichts dran geändert. Was sollte denn 
dort stehen ?!

kramt nochmal nach dem ursprünglichen Quelltext

von holger (Gast)


Lesenswert?

>öhm ... ich habe da eigentlich nichts dran geändert. Was sollte denn
>dort stehen ?!

#ifndef withDMA
      for (i = 0; i < count; i++)
        spiSendByte(pBuffer[i]);
#else
      /* Get the block */
      /* DMA trigger is UART send */
      DMACTL0 &= ~(DMA0TSEL_15);
      DMACTL0 |= (DMA0TSEL_9);
      /* Source DMA address: the data buffer.  */
      DMA0SA = (unsigned short)pBuffer;
      /* Destination DMA address: the UART send register. */
      DMA0DA = U1TXBUF_;
      /* The size of the block to be transferred */
      DMA0SZ = count;
      /* Configure the DMA transfer*/
      DMA0CTL =
        DMAREQ  |                           /* start transfer */
        DMADT_0 |                           /* Single transfer mode */
        DMASBDB |                           /* Byte mode */
        DMAEN |                             /* Enable DMA */
        DMASRCINCR1 | DMASRCINCR0;          /* Increment the source 
address */
#endif

von Sebastian (Gast)


Lesenswert?

Du hast vollkommen Recht. :S

Mir fällt auch wieder ein warum ich den Teil mal rausgehauen hatte. 
Leider war ich beim Löschen etwas großzügig.
Wollte die Kommunikation ohne DMA-Modul realisieren.
Wenn ich das jetzt richtig verstanden habe, wird entweder der 
"withDMA"-Teil ausgeführt oder das was nach dem "else" kommt. Dabei 
sieht es eher so aus, dass letzterer Teil das DMA-Modul nutzt, oder ?


Ich würde eigentlich gerne Strom sparen und nicht das DMA-Modul nutzen.
(stellt höheren Datentransfer bereit, zieht aber auch mehr Strom, oder?)

von holger (Gast)


Lesenswert?

>Ich würde eigentlich gerne Strom sparen und nicht das DMA-Modul nutzen.
>(stellt höheren Datentransfer bereit, zieht aber auch mehr Strom, oder?)

Keine Ahnung, aber am meisten Strom sparst du wenn du deine
SD Karte gar nicht erst anschliesst ;)

von Christian R. (supachris)


Lesenswert?

Öhm, also man sollte schon wissen, was man löscht. Mit DMA kann es 
schneller gehen, wenn man große Blöcke übertragen will und der Prozessor 
noch andere Sachen zu tun hat. Einmal angestoßen läuft der DMA ohne 
Prozessorlast. Ansonsten gehts mit direkt auslesen genauso schnell. DMA 
sollte man nur benutzen, wenn man wirklich verstanden hat, wie der 
komplexe DMA-Controller funktioniert. Der kann viel, hat aber auch 
tausend Register, die man einstellen muss.

von Seb (Gast)


Lesenswert?

@Chris: Ja, das mit dem Löschen war nicht sehr clever.

@Holger:

Da hast du natürlich recht  ;-)
Die SD-Karte strebe ich auch eher als Übergangslösung an. Eigentlich 
würde ich gerne einen "nackten" NAND Flash benutzen. Davon wurde mir 
jedoch bisher im Forum abgeraten, da die Ansteuerung nicht gerade 
trivial ist.
Ich lasse mich jedoch gerne vom Gegenteil überzeugen.

von Sebastian (Gast)


Lesenswert?

So,

Die Karte läuft nun am MSP. Ich kann wunderbar schreiben und mir das 
später in Winhex ansehen. Auch die Lesefunktion scheint zu klappen, 
wobei ich mir noch nicht ganz sicher bin wie ich überprüfen kann, ob er 
denn das richtige liest. Wie habt ihr das gemacht ?

Ich versuche gerade die gelesenen Daten erneut in einen anderen Sektor 
schreiben zu lassen. Klappt aber noch nicht ganz...

von Sebastian (Gast)


Lesenswert?

Ah, nun klappt die Sache. Meine Karte liest brav und schreibt diese 
Daten in einen gewünschten Sektor.

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.