Hallo zusammen,
ich sitze jetzt schon eine Weile an dem Problem, ich glaube mir fehlt
etwas Verständnis.
Ich schreibe auf eine SD-Karte mittels USART Master SPI vom
ATXMega256A3U. Das funktioniert soweit einwandfrei, das Senden ganzer
Blöcke mit DMA läuft über:
1 | /* Send a data block fast */
|
2 | static
|
3 | void xmit_spi_multi (
|
4 | const BYTE *p, /* Data block to be sent */
|
5 | UINT cnt /* Size of data block */
|
6 | )
|
7 | {
|
8 | while (DMA.CH_TX_SD.CTRLB & DMA_CH_CHBUSY_bm); // Wait for last transmission to be complete
|
9 | USART_Clear(&MMC_USART_data);
|
10 | dma_puts_sdcard( (char*) p, cnt ); // Transmit amount of bytes via DMA
|
11 | }
|
Nun möchte ich auch blockweise über DMA empfangen können, wenn z.B. das
Dateisystem eingelesen wird. Bisher geht das nur via:
1 | /* Receive a data block fast */
|
2 | static
|
3 | void rcvr_spi_multi (
|
4 | BYTE *p, /* Data read buffer */
|
5 | UINT cnt /* Size of data block */
|
6 | )
|
7 | {
|
8 | char dummyTxChr = 0xff;
|
9 | do
|
10 | {
|
11 | // Transmit dummy char
|
12 | while (DMA.CH_TX_SD.CTRLB & DMA_CH_CHBUSY_bm); // Wait for last transmission to be complete
|
13 | dma_puts_sdcard( &dummyTxChr, 1 ); // Send dummy char
|
14 |
|
15 | // Read received char
|
16 | while (!USART_RXBufferData_Available(&MMC_USART_data)); // Wait for data received
|
17 | *p++ = usart_getc(&MMC_USART_data);
|
18 | } while (--cnt);
|
19 | }
|
Dabei bringt mir der DMA natürlich keinen Zeitvorteil.
Ich möchte daher statt der do-while-Schleife Folgendes benutzen
(funktioniert nicht, hier brauch ich Hilfe):
1 | dma_putdummy_sdcard( &dummyTxChr, cnt );
|
2 | while (DMA.CH_TX_SD.CTRLB & DMA_CH_CHBUSY_bm);
|
3 | p = MMC_USART_data.buffer.RX;
|
Das funktioniert aber nicht. Ich kopiere zwar die Daten des RX-Buffers
(aus der usart_driver-Bibliothek von Atmel übrigens), aber die Daten
sind überhaupt nur 104 Byte lang statt 512 Byte (sichtbar an RX-Tail).
RX- und TX-Buffergrößen sind 512 Bytes.
Der DMA:
1 | void dma_putdummy_sdcard(char* str, uint16_t byteCount)
|
2 | {
|
3 | DMA.CH_TX_SD.ADDRCTRL |= DMA_CH_SRCDIR_FIXED_gc; // Fixed source address of dummy char
|
4 |
|
5 | DMA.CH_TX_SD.SRCADDR0 = (char)((int)str); // Source address = string address
|
6 | DMA.CH_TX_SD.SRCADDR1 = (char)((int)str >> 8);
|
7 |
|
8 | DMA.CH_TX_SD.TRFCNT = byteCount;
|
9 | DMA.CH_TX_SD.TRIGSRC |= DMA_CH_TRIGSRC_USARTE1_DRE_gc; // Trigger each time USART data reg is empty (otherwise data will get lost!!)
|
10 | DMA.CH_TX_SD.CTRLA |= DMA_CH_ENABLE_bm; // Start transmission. Gets disabled automatically when tx finished
|
11 | }
|
und
1 | // Channel 2: USART Data out to SD (USART in Master SPI mode) // Increment source address (string to transmit)
|
2 | DMA.CH_TX_SD.ADDRCTRL |= DMA_CH_DESTDIR_FIXED_gc; // Keep destination address fixed (USART)
|
3 |
|
4 | DMA.CH_TX_SD.DESTADDR0 = (char)((int)&MMC_USART_DATA_REG); // Destination address = SD Card USART data reg
|
5 | DMA.CH_TX_SD.DESTADDR1 = (char)((int)&MMC_USART_DATA_REG >> 8);
|
6 |
|
7 | DMA.CH_TX_SD.CTRLA |= DMA_CH_SINGLE_bm; // Enable single shot mode = transmit bytecount once (bytecount = stringlength)
|
8 | DMA.CH_TX_SD.TRIGSRC |= DMA_CH_TRIGSRC_USARTE1_DRE_gc; // Trigger each time USART data reg is empty (otherwise data will get lost!!)
|
--> Was übersehe ich beim Datenempfang?