mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik LPC 2000: DMA und SSP zickt gewaltig.


Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
Ich versuche seit einiger Zeit SSP0 mit Hilfe von DMA anzusteuern.
Was mir bisher gelungen ist, ist beide DMA-Kanäle dem SSP zuzuweisen und 
damit ins USB RAM zu schreiben und zu lesen, wenn SSP0 der 'Flow 
Controller' ist. Ist der DMA-Block der Flow Controller, funktioniert es 
leider nicht.

ABER - Wie kann ich dann die Länge der DMA-Übertragung festlegen?
Ich möchte gern einen Block von 512 Bytes senden und empfangen, jedoch 
kann ich dem DMA das nicht mitteilen, da (laut Manual) die Längenangabe 
im Channel Control Register ignoriert wird, wenn der DMA Block die 
Übertragung nicht steuert (sondern in meinem Fall SSP0).

Ich bekomme zwar mindetens 512 Bytes, aber es wird das ganze USB RAM bis 
zum Ende vollgeschrieben. Ich nehme an, der DMA-Vorgang bricht ab, weil 
er hinter das RAM nicht mehr schreiben kann.

Ich bin für jeden Tip dankbar....

-> Peter

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
Sind keine LPC Profis hier?
Hat denn keiner von euch sowas schon mal gemacht?
Mein Controller ist übrigens ein LPC2378.

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Mein Controller ist übrigens ein LPC2378.

Der ist noch nicht so häufig. Wohl auch deshalb, weil die 2300er 
ausserhalb von Demoboards so gut nicht nicht zu kriegen sein sollen. Und 
die älteren LPC2000er haben kein DMA.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Andreas, danke für deine Antwort.
Na schade :-(
Ich hab' jedenfalls den EBV-Menschen angemailt, von dem ich das Board 
habe (ist übrigens dieser hier 
http://www.ebv.com/en/products/highlights/chameleonarm.html )
Vielleicht kann der mir weiterhelfen...

Autor: Stefan Wüthrich (stefan-w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter
Ich stehe eben vor dem selben Problem. Hast du inzwischen eine Lösung 
gefunden?
Gruss Stefan

Autor: Matthias Nix (vbchaos)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kannst du deine Registereinstellungen bzw. den entsprechenden 
Code-Schnipsel mal posten? Dann konnte man auf Fehlersuche gehen

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Hallo Peter
>Ich stehe eben vor dem selben Problem. Hast du inzwischen eine Lösung
>gefunden?
ja hab' ich:
erstmal: speicher im USB ram reservieren
/* When using DMA, we must have some special RAM */
#ifdef USE_DMA
struct __DMA_MEMORY
{
  UINT8   source[512];
  UINT8   destination[512];
};
#pragma location = "USB_RAM"
static __no_init struct __DMA_MEMORY dma_memory;
#endif
dann, als beispiel, zwei funktionen zum lesen/schreiben eines sektors 
einer SD-karte
// Sector Rx
static BOOL ReceiveDataBlock (UINT8 *buff)
{
  UINT8   token;
  SIZE_T  retries = 0x800000;

  // Wait for data packet
  do
  {  
    token = SPI_RxTx (SPI_TX_DUMMY);
  } while ((token == 0xFF) && retries--);
  
  // If not valid data token, return with error 
  if (token != 0xFE)
  {
    return FALSE;                   
  }

  LastAccess = GET_MILLISEC_COUNTER_VALUE();
  
#ifdef USE_DMA
  
  /* Ch0 set for M2P transfer from memory to SSP0. */
  dma_memory.source[0] = 0xff;              /* Dummy byte to send */
  GPDMA_CH0_SRC = (unsigned long) dma_memory.source;
  GPDMA_CH0_DEST = (unsigned long) &SSP0DR;
  GPDMA_CH0_CTRL = 512 |                        /* 512 bytes */
                   (0x01 << 12) |                                    /* source burst size */
                   (0x01 << 15);                                     /* destination burst size */
  GPDMA_CH0_CFG = 0x1 |             /* Enable */
                  (0x00 << 6) |                                         /* destination is SSP0-TX */
                  (0x01 << 11);                                         /* memory to peripheral, FlowController is DMA */

  /* Ch1 set for P2M transfer from SSP0 to memory. */
  GPDMA_CH1_SRC = (unsigned long) &SSP0DR;
  GPDMA_CH1_DEST = (unsigned long) dma_memory.destination;
  GPDMA_CH1_CTRL = 512 |        /* 512 bytes */
                   (0x01 << 12) |                                    /* source burst size */
                   (0x01 << 15) |                                    /* destination burst size */
                   (1 << 27);
  GPDMA_CH1_CFG = 0x1 |             /* Enable */
                  (0x01 << 1) |                                         /* Source is SSP0-RX */
                  (0x02 << 11);                                         /* peripheral to memory, FlowController is DMA */

  /* Enable DMA TX and RX on SSP0 */
  SSP0DMACR = 0x03;

  /* Poll until DMA completes */
  while (GPDMA_ENABLED_CHNS & 3)
    ;

  /* Disable SSP0's DMA TX and RX */
  SSP0DMACR = 0;

  /* Disable DMA channels */
  GPDMA_CH0_CFG = 0;
  GPDMA_CH1_CFG = 0;

  /* Copy the packet */
  memcpy (buff, (void *) dma_memory.destination, 512);

#else /* USE_DMA */
  /* Receive the data block */
  SIZE_T  s;
  for (s = 0; s < 256; s++)
  {                   /* Xmit the 512 byte data block to MMC */
    *buff = SPI_RxTx(SPI_TX_DUMMY);
    buff++;
    *buff = SPI_RxTx(SPI_TX_DUMMY); 
    buff++;
  };
#endif /* USE_DMA */

  SPI_RxTx (SPI_TX_DUMMY);                      /* Discard CRC */
  SPI_RxTx (SPI_TX_DUMMY);
  return TRUE;                              /* Return with success */
}

// transmit one sector
static BOOL TransmitDataBlock(UINT8 const *buff, UINT8 token)
{
  UINT8   resp;

  if (WaitReady () != 0xFF)
  {
    return FALSE;
  }

  LastAccess = GET_MILLISEC_COUNTER_VALUE();
  
  SPI_RxTx (token);             /* Xmit data token */

  /* Is data token */
  if (token != 0xFD)
  {
#ifdef USE_DMA

    /* Copy the packet */
    memcpy ((void *) dma_memory.source, buff, 512);
    
    /* Ch0 set for M2P transfer from memory to SSP0. */
    GPDMA_CH0_SRC = (unsigned long) dma_memory.source;
    GPDMA_CH0_DEST = (unsigned long) &SSP0DR;
    GPDMA_CH0_CTRL = 512 |              /* 512 bytes */
                     (0x01 << 12) |                                      /* source burst size */
                     (0x01 << 15) |                                      /* destination burst size */
                     (1 << 26);
    GPDMA_CH0_CFG = 0x1 |                   /* Enable */
                    (0x00 << 6) |                                           /* destination is SSP0-TX */
                    (0x01 << 11);                                           /* memory to peripheral, FlowController is DMA */

    /* Ch1 set for P2M transfer from SSP0 to memory. */
    GPDMA_CH1_SRC = (unsigned long) &SSP0DR;
    GPDMA_CH1_DEST = (unsigned long) dma_memory.destination;
    GPDMA_CH1_CTRL = 512 |              /* 512 bytes */
                     (0x01 << 12) |                                      /* source burst size */
                     (0x01 << 15);                                       /* destination burst size */
    GPDMA_CH1_CFG = 0x1 |                   /* Enable */
                    (0x01 << 1) |                                           /* Source is SSP0-RX */
                    (0x02 << 11);                                           /* peripheral to memory, FlowController is DMA */

    /* Enable DMA TX and RX on SSP0 */
    SSP0DMACR = 0x03;

    /* Poll until DMA completes */
    while (GPDMA_ENABLED_CHNS & 3)
      ;

    /* Disable SSP0's DMA TX and RX */
    SSP0DMACR = 0;

    /* Disable DMA channels */
    GPDMA_CH0_CFG = 0;
    GPDMA_CH1_CFG = 0;

#else
    SIZE_T  s;
    for (s = 0; s < 256; s++)
    {                   /* Xmit the 512 byte data block to MMC */
      SPI_RxTx (*buff);
      buff++;
      SPI_RxTx (*buff);
      buff++;
    }
#endif

    SPI_RxTx (0xFF);                            /* CRC (Dummy) */
    SPI_RxTx (0xFF);
    resp = SPI_RxTx (SPI_TX_DUMMY);             /* Reveive data response */
    if ((resp & 0x1F) != 0x05)
    {                   /* If not accepted, return with error */
      // **** BEGIN Testcode ****
      //debug_printf ("TransmitDatablock failed");
      // **** END Testcode ****
      return FALSE;
    }
  }

  return TRUE;
}

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.