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
Hallo, Sind keine LPC Profis hier? Hat denn keiner von euch sowas schon mal gemacht? Mein Controller ist übrigens ein LPC2378.
> 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.
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...
Hallo Peter Ich stehe eben vor dem selben Problem. Hast du inzwischen eine Lösung gefunden? Gruss Stefan
Kannst du deine Registereinstellungen bzw. den entsprechenden Code-Schnipsel mal posten? Dann konnte man auf Fehlersuche gehen
>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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.