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


von Peter (Gast)


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

von Peter (Gast)


Lesenswert?

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

von Andreas K. (a-k)


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.

von Peter (Gast)


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...

von Stefan W. (stefan-w)


Lesenswert?

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

von Matthias N. (vbchaos)


Lesenswert?

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

von Peter (Gast)


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
1
/* When using DMA, we must have some special RAM */
2
#ifdef USE_DMA
3
struct __DMA_MEMORY
4
{
5
  UINT8   source[512];
6
  UINT8   destination[512];
7
};
8
#pragma location = "USB_RAM"
9
static __no_init struct __DMA_MEMORY dma_memory;
10
#endif
dann, als beispiel, zwei funktionen zum lesen/schreiben eines sektors 
einer SD-karte
1
// Sector Rx
2
static BOOL ReceiveDataBlock (UINT8 *buff)
3
{
4
  UINT8   token;
5
  SIZE_T  retries = 0x800000;
6
7
  // Wait for data packet
8
  do
9
  {  
10
    token = SPI_RxTx (SPI_TX_DUMMY);
11
  } while ((token == 0xFF) && retries--);
12
  
13
  // If not valid data token, return with error 
14
  if (token != 0xFE)
15
  {
16
    return FALSE;                   
17
  }
18
19
  LastAccess = GET_MILLISEC_COUNTER_VALUE();
20
  
21
#ifdef USE_DMA
22
  
23
  /* Ch0 set for M2P transfer from memory to SSP0. */
24
  dma_memory.source[0] = 0xff;              /* Dummy byte to send */
25
  GPDMA_CH0_SRC = (unsigned long) dma_memory.source;
26
  GPDMA_CH0_DEST = (unsigned long) &SSP0DR;
27
  GPDMA_CH0_CTRL = 512 |                        /* 512 bytes */
28
                   (0x01 << 12) |                                    /* source burst size */
29
                   (0x01 << 15);                                     /* destination burst size */
30
  GPDMA_CH0_CFG = 0x1 |             /* Enable */
31
                  (0x00 << 6) |                                         /* destination is SSP0-TX */
32
                  (0x01 << 11);                                         /* memory to peripheral, FlowController is DMA */
33
34
  /* Ch1 set for P2M transfer from SSP0 to memory. */
35
  GPDMA_CH1_SRC = (unsigned long) &SSP0DR;
36
  GPDMA_CH1_DEST = (unsigned long) dma_memory.destination;
37
  GPDMA_CH1_CTRL = 512 |        /* 512 bytes */
38
                   (0x01 << 12) |                                    /* source burst size */
39
                   (0x01 << 15) |                                    /* destination burst size */
40
                   (1 << 27);
41
  GPDMA_CH1_CFG = 0x1 |             /* Enable */
42
                  (0x01 << 1) |                                         /* Source is SSP0-RX */
43
                  (0x02 << 11);                                         /* peripheral to memory, FlowController is DMA */
44
45
  /* Enable DMA TX and RX on SSP0 */
46
  SSP0DMACR = 0x03;
47
48
  /* Poll until DMA completes */
49
  while (GPDMA_ENABLED_CHNS & 3)
50
    ;
51
52
  /* Disable SSP0's DMA TX and RX */
53
  SSP0DMACR = 0;
54
55
  /* Disable DMA channels */
56
  GPDMA_CH0_CFG = 0;
57
  GPDMA_CH1_CFG = 0;
58
59
  /* Copy the packet */
60
  memcpy (buff, (void *) dma_memory.destination, 512);
61
62
#else /* USE_DMA */
63
  /* Receive the data block */
64
  SIZE_T  s;
65
  for (s = 0; s < 256; s++)
66
  {                   /* Xmit the 512 byte data block to MMC */
67
    *buff = SPI_RxTx(SPI_TX_DUMMY);
68
    buff++;
69
    *buff = SPI_RxTx(SPI_TX_DUMMY); 
70
    buff++;
71
  };
72
#endif /* USE_DMA */
73
74
  SPI_RxTx (SPI_TX_DUMMY);                      /* Discard CRC */
75
  SPI_RxTx (SPI_TX_DUMMY);
76
  return TRUE;                              /* Return with success */
77
}
78
79
// transmit one sector
80
static BOOL TransmitDataBlock(UINT8 const *buff, UINT8 token)
81
{
82
  UINT8   resp;
83
84
  if (WaitReady () != 0xFF)
85
  {
86
    return FALSE;
87
  }
88
89
  LastAccess = GET_MILLISEC_COUNTER_VALUE();
90
  
91
  SPI_RxTx (token);             /* Xmit data token */
92
93
  /* Is data token */
94
  if (token != 0xFD)
95
  {
96
#ifdef USE_DMA
97
98
    /* Copy the packet */
99
    memcpy ((void *) dma_memory.source, buff, 512);
100
    
101
    /* Ch0 set for M2P transfer from memory to SSP0. */
102
    GPDMA_CH0_SRC = (unsigned long) dma_memory.source;
103
    GPDMA_CH0_DEST = (unsigned long) &SSP0DR;
104
    GPDMA_CH0_CTRL = 512 |              /* 512 bytes */
105
                     (0x01 << 12) |                                      /* source burst size */
106
                     (0x01 << 15) |                                      /* destination burst size */
107
                     (1 << 26);
108
    GPDMA_CH0_CFG = 0x1 |                   /* Enable */
109
                    (0x00 << 6) |                                           /* destination is SSP0-TX */
110
                    (0x01 << 11);                                           /* memory to peripheral, FlowController is DMA */
111
112
    /* Ch1 set for P2M transfer from SSP0 to memory. */
113
    GPDMA_CH1_SRC = (unsigned long) &SSP0DR;
114
    GPDMA_CH1_DEST = (unsigned long) dma_memory.destination;
115
    GPDMA_CH1_CTRL = 512 |              /* 512 bytes */
116
                     (0x01 << 12) |                                      /* source burst size */
117
                     (0x01 << 15);                                       /* destination burst size */
118
    GPDMA_CH1_CFG = 0x1 |                   /* Enable */
119
                    (0x01 << 1) |                                           /* Source is SSP0-RX */
120
                    (0x02 << 11);                                           /* peripheral to memory, FlowController is DMA */
121
122
    /* Enable DMA TX and RX on SSP0 */
123
    SSP0DMACR = 0x03;
124
125
    /* Poll until DMA completes */
126
    while (GPDMA_ENABLED_CHNS & 3)
127
      ;
128
129
    /* Disable SSP0's DMA TX and RX */
130
    SSP0DMACR = 0;
131
132
    /* Disable DMA channels */
133
    GPDMA_CH0_CFG = 0;
134
    GPDMA_CH1_CFG = 0;
135
136
#else
137
    SIZE_T  s;
138
    for (s = 0; s < 256; s++)
139
    {                   /* Xmit the 512 byte data block to MMC */
140
      SPI_RxTx (*buff);
141
      buff++;
142
      SPI_RxTx (*buff);
143
      buff++;
144
    }
145
#endif
146
147
    SPI_RxTx (0xFF);                            /* CRC (Dummy) */
148
    SPI_RxTx (0xFF);
149
    resp = SPI_RxTx (SPI_TX_DUMMY);             /* Reveive data response */
150
    if ((resp & 0x1F) != 0x05)
151
    {                   /* If not accepted, return with error */
152
      // **** BEGIN Testcode ****
153
      //debug_printf ("TransmitDatablock failed");
154
      // **** END Testcode ****
155
      return FALSE;
156
    }
157
  }
158
159
  return TRUE;
160
}

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.