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:
	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
    }
....
 Die SDRAM zugriffe mit den vorgefertigten Funktionen funktionieren - in den Funktionen wird nochmal betont, dass GCC die 24 Bit Addressen nicht unterstützt.
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.
						
					
Lesezeichen