Hallo,
leider stehe ich schon wieder vor einem neuen Problem - mir gelingt es nicht per DMA in den SDRAM zu schreiben.
Hierzu habe ich zunächst das Tutorial "AVR1312: Using the XMEGA External Bus Interface" abgearbeitet welches ohne Probleme lief.
Beim DMA-Zugriff funktioniert das leider nicht. Nach längerem Suchen ist mir dann aufgefallen, dass die Funktion DMA_SetupBlock() aus dem Tutorial "AVR1514: XMEGA-A1 Xplained Training - Direct Memory Access Controller" nur bis 16 Bit Addressen ausgeführt war. Dementsprechend habe ich die Funktion für 24-Bit Addressen modifiziert. Die erste Addresse wird auch beschrieben, aber alle weiteren Folgeaddressen bleiben per DMA unbeschrieben. Die Inkrementierung der Addressen ist im entsprechenden DMA-Kanal vorgenommen.
Hier mal ein Auszug meines Codes:
Die SDRAM zugriffe mit den vorgefertigten Funktionen funktionieren - in den Funktionen wird nochmal betont, dass GCC die 24 Bit Addressen nicht unterstützt.Code:#define SDRAM_SIZE 0x800000UL // Größe des benötigten SDRAMs #define MEMORY_BLOCK 0 // MEMORY_BLOCK = (16MB/RAM_SIZE - 1) uint32_t SDRAM_ADDR = (SDRAM_SIZE * MEMORY_BLOCK); // Addresse des SDRAM-Bereichs DMA_CH_t * SDRAMChannel = &DMA.CH0; void initSDRAM() { // Bus Pins als Ausgang, außer die Datenleitungen (DQ0-DQ3) PORTH.DIR = 0xFF; PORTK.DIR = 0xFF; PORTJ.DIR = 0xF0; EBI_Enable( EBI_SDDATAW_4BIT_gc, // Datengröße 4 Bit EBI_LPCMODE_ALE1_gc, EBI_SRMODE_ALE12_gc, EBI_IFMODE_3PORT_gc ); EBI_EnableSDRAM( EBI_CS_ASPACE_8MB_gc, /* 8 MB address space. */ SDRAM_ADDR, /* Base address. */ false, /* 2 cycle CAS Latency. */ true, /* 12 Row bits. */ EBI_SDCOL_10BIT_gc, /* 10 Column bits. */ EBI_MRDLY_2CLK_gc, /* 2 cycle Mode Register Delay. (min 2CLK) */ EBI_ROWCYCDLY_1CLK_gc, /* 1 cycle Row Cycle Delay. */ EBI_RPDLY_1CLK_gc, /* 1 cycle Row to Pre-charge Delay. (min 37ns) */ EBI_WRDLY_2CLK_gc, /* 2 cycle Write Recovery Delay. (1CLK + 7ns)*/ EBI_ESRDLY_1CLK_gc, /* 1 cycle Exit Self Refresh to Active Delay. (min 67ns) */ EBI_ROWCOLDLY_1CLK_gc, /* 1 cycle Row to Column Delay. (min 15ns) */ 0x001F, /* 31 cycle Refresh Period (max 15.625us). */ 0x00C8 ); /* 200 cycle Initialization Delay (min 100us). */ delay_us( 100 ); } void SetupSDRAMChannel( DMA_CH_t * dmaChannel ) { TCF1.CNT = 0x62; dmaChannel->SRCADDR0 = (( (uint16_t) (void *) &TCF1.CNT) >> 0*8 ) & 0xFF; dmaChannel->SRCADDR1 = (( (uint16_t) (void *) &TCF1.CNT) >> 1*8 ) & 0xFF; dmaChannel->SRCADDR2 = 0; // 24-Bit Addresse muss manuell gesetzt werden dmaChannel->DESTADDR0 = (( (uint32_t) SDRAM_ADDR) >> 0*8 ) & 0xFF; dmaChannel->DESTADDR1 = (( (uint32_t) SDRAM_ADDR) >> 1*8 ) & 0xFF; dmaChannel->DESTADDR2 = (( (uint32_t) SDRAM_ADDR) >> 2*8 ) & 0xFF; dmaChannel->ADDRCTRL = DMA_CH_SRCRELOAD_NONE_gc | DMA_CH_SRCDIR_FIXED_gc | DMA_CH_DESTRELOAD_NONE_gc | DMA_CH_DESTDIR_INC_gc; dmaChannel->TRFCNT = 1; dmaChannel->CTRLA |= DMA_CH_BURSTLEN_1BYTE_gc; DMA_EnableSingleShot( dmaChannel ); DMA_SetTriggerSource( dmaChannel, DMA_CH_TRIGSRC_TCC0_OVF_gc ); } ISR( TCC0_OVF_vect ){} ISR( TCC1_OVF_vect ){} void SetUpAllTimers( void ) { TCC1.PER = 1000; // Überlauf bei Grenzwert der zu nehmenden Samples TCC1.CNT = 48; // 0 EVSYS_SetEventSource( 0, EVSYS_CHMUX_TCC0_OVF_gc ); // Event channel 0 erfasst die Überläufe des Timers TCC1 TCC1.CTRLA = TC_CLKSEL_EVCH0_gc; // Als clock source wird der event channel 0 gesetzt TCC0.PER = 1000; // Timer Iinterupt aktivieren und Priorität setzten TCC0.INTCTRLA = TC_OVFINTLVL_MED_gc; // annährend gleichzeitiges Starten der Timer mit Prescaler von 1 TCC0.CTRLA = (TCC0.CTRLA & ~TC0_CLKSEL_gm) | TC_CLKSEL_DIV1_gc; } int main( void ) { // SDRAM initialisieren initSDRAM(); for (uint32_t i = 0; i < 5; i++) { __far_mem_write( i + SDRAM_ADDR, 0x65 ); } DMA_Enable(); // DMA-Kanäle initialisieren SetupSDRAMChannel( SDRAMChannel ); // DMA-Kanäle starten DMA_EnableChannel( SDRAMChannel ); SetUpAllTimers(); // Warten bis 10 Werte im SDRAM while( TCC1.CNT < 10){} uint8_t result; for (uint8_t i = 0; i < 5; i++) { result = __far_mem_read( i + SDRAM_ADDR ); .... // AUsgabe } ....
Ich hoffe es sieht jemand den Fehler. Ich habe hierzu schon die Application Notes durchgearbeitet - bin aber leider nicht fündig geworden.
Gruß Erik
[EDIT] Erhöhe ich den Trafficcount TRFCNT im DMA - so werden die folgenden Addressen entsprechend mit dem gleichen Wert beschrieben..
[EDIT No.2] Es tut mir leid - nach langem Suchen habe ich den Fehler gefunden. Beim Kopieren/Ändern der Funktion DMA_SetupBlock habe ich TRFCNT ausversehen auf 1 gesetzt - da muss natürlich die 0 für unendich hin.
Meinetwegen kann dieses Thema gerne wieder gelöscht werden - ich sehe hier leider keine Möglichkeit das selbst zu tun.







Zitieren

Lesezeichen