Hi:
I am having trouble reading data from our FPGA ( in CS2 space) using DMA3. We interface with the FPGA through the EMIF. I have programmed the EMIF for 16 bit data and EMIF clock is half the DSP system clock. The FPGA causes an INT0 interrupt which in turn enables DMA3 channel 1 and DMA interrupts. I have programmed DMA3 channel 1 for 16 bit data, burst mode (64 bytes), constant source address (0x400006) and post increment for destination address in DARAM. The INT0 and DMA3 channel 1 interrupts occur correctly; however, the data is not correct. An examination of the data seems to indicate that the DMA3 controller is changing the source address. The reason being that we get data values like 0x9999 and 0xBBBB; however, the FPGA has fixed data 0xBBBB at address location 0x40000A and 0x9999 at address 0x400008 and not at the source address 0x400006. The source address is for a FIFO that receives data from ADCs which in turn receive signals from MEMs sensors.
If I don't use DMA3 and manually read data from the FIFO using far_peek_l, I get the correct data in the INT0 interrupt service routine, I get the correct data.
Could you please help. Below is my code.
Thanks a lot!
Mushtaq A. Syed
//Testing C5504 DMA.
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "csl_intc.h" //Mushtaq This is for dealing with interrupts.
#include "csl_general.h"
#include "extaddr.h"
#include "c5505.h"
#include "C5504_DMA3.h"
#include "FPGA_Sensors.h"
#include "dspdef.h"
extern void VECSTART(void);
void SetupEMIF(void);
void DMA_int_plug(void);
interrupt void dma_isr_test(void);
void Config_DMA3CH1_US0(void);
void FPGA_init(void);
void FPGA_reset(void);
int index_dataArray1Seg; //Mushtaq 072210 This is for testing. Remoce later.
unsigned int test_buffer[32]; //Mushtaq 072210 for testing.
unsigned int dataArray1Seg[4096];
main()
{
int i;
/* Disable all interrupts and set up vector */
*(volatile unsigned int *)IER0 = 0x0000;
*(volatile unsigned int *)IER1 = 0x0000;
*(volatile unsigned int *)IVPDaddr = IVPD_VALUE;
*(volatile unsigned int *)IVPHaddr = IVPD_VALUE;
INT_ENABLE;
for(i=0;i<4096;i++)
dataArray1Seg[i] = 0;
for(i=0;i<32;i++)
test_buffer[i] = 0;
SetupEMIF();
Config_DMA3CH1_US0(); // Mushtaq 072210 This is for testing. Move it later.
index_dataArray1Seg = 0;
DMA_int_plug(); // Mushtaq 072210 This is for testing. Remove it later.
FPGA_init(); //Mushtaq initialize the FPGA
while(1){}
}
void SetupEMIF(void)
{
int i;
EMIF_ESCR=0x00; //Set EMIF for word access.
MUX_EBSR &= 0xffdf; //EMIF pin 20 is muxed with GPIO pin 26. Select 20 as EMIF (bit 5).
//Enable system and EMIF clocks.
PCGCR_L &= 0xf7ff; //This enables the system and EMIF clocks (bits 5 and 11).
//EMIF_ECDR |= 0x0001; //EMIF clock = peripheral clock. i.e., EMIF clock = DSP System clock.
EMIF_ECDR |= 0x0000; //EMIF clock = 0.5*peripheral clock. i.e., EMIF clock = 0.5*DSP System clock.
PSRCR = 0x0050; //Count of system clock cycles for which SW reset is asserted in the next instruction.
PRCR = 0x0002; // Reset peripheral group one -- Timers and EMIF (bit 1).
for(i=0;i<50;i++){}; //Wait.
//Disable all EMIF interrupts.
//CSL_FINSR(c5504_emif_regs->EIMCR,15,0,0x003f);
EMIF_EIMCR =0x003f;
/* Config EMIF - ASYNC Regsiters */
//CSL_FINSR(c5504_emif_regs->AWCCR1,15,0,0x0000); //All wait cycles set to 0.
//CSL_FINSR(c5504_emif_regs->AWCCR2,15,0,0x001b); // All wait cycles set to 0.
EMIF_AWCCR1 = 0x0000;
EMIF_AWCCR2 = 0x001b;
/* Configure ASYNC3 Registers */
/* Configure as 16-bit data bus */
//CSL_FINSR(c5504_emif_regs->ACS2CR1,15,0,0x2095); //16 bit data. NOTE: Enter FPGA timing information later
//CSL_FINSR(c5504_emif_regs->ACS2CR2,15,0,0x0413); //Normal mode.
EMIF_ACS2CR1 = 0x2095; //0x6101;
EMIF_ACS2CR2 = 0x0412; //0x099a;
}
interrupt void fpga_isr_test(void)
{
//Clear INT0 (bit 2) interrupt flag.
*(volatile unsigned short *)IFR0 = 0x0004;
//Enable DMA interrupt.
IRQ_enable(DMA_EVENT);
//Trigger DMA3 channel 1 to acquire US0 data.
//Channel 1 enabled, src add constant, dest. add. post inc., interrupt ena., burst 64 bytes, auto reload disa., and no sync.
DMA3CH1TCR2 = 0xa0a0; //Enabling the channel will start the transfer immediately.
}
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
void DMA_int_plug(void)
{
IRQ_setVecs((Uint32)(&VECSTART));
IRQ_plug(DMA_EVENT, &dma_isr_test); //Mushtaq 072210 Remove later.
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
interrupt void dma_isr_test(void)
{
int ifrValue, i;
//*(volatile unsigned short *)IFR0 = 0x0004; //Clear INT0 (bit 2) interrupt flag.
ifrValue = DMAIFR; // Read interrupt register.
DMAIFR |= ifrValue; //Write back above value to clear interrupt.
DMA3CH1TCR2 = 0x00a0; //Disable channel and interrupt. Enabled in the FPGA interrupt.
//Store data into processing buffer.
for(i=0;i<32;i++)
{
dataArray1Seg[i + index_dataArray1Seg]=test_buffer[i];
}
index_dataArray1Seg += 32;
if (index_dataArray1Seg > 4096)
asm("\tNOP"); //
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
void Config_DMA3CH1_US0(void)
{
int j;
//Clear all DMA3 interrupt flags by writing a one. (bits 15 -12 correspond to channels 3-0).
DMAIFR |= 0xF000; //Set bits 15,14,13, and 12.
*(volatile unsigned short *)IFR0 = 0x0100; //Clear aggregate DMA (bit 8) interrupt flag.
DMAIER |= 0x2000; //Enable interrupts from DMA3 channel 1, bit 13.
//Reset DMA controllers.
PSRCR = 0x0050; //Count of system clock cycles for which SW reset is asserted in the next instruction.
PRCR = 0x0010; // Reset DMA controllers -- (bit 4).
for(j=0;j<0xf000;j++){}; //Wait.
//Enable DMA clock.
PCGCR_H &= 0x005F; //This enables the DMA3 clock (bit 5).
//DMA3CESR1 and DMA3CESR2: No synchronization events for any of the DMA3 channels.
//Procedure for calculating DMA byte addresses for source in external memory.
//1)Starting word address for CS2 is 0x400000
//2)Word address we are using for US0/IR is 0x400006.
//3)Offset = 0x400006-0x400000 = 0x000006.
//4)Shift offset left one bit to get 0x00000c.
//5)DMA byte address for CS2 is 0x2000000.
//6)Add offset 0x2000000+0x00000c = 0x200000c.
//NOTE: Address 0x4000006 is shared by US0 and IR.
DMA3CH1SSAL = 0x000c;
DMA3CH1SSAU = 0x0200;
//DMA3CH1SSAL = 0x0010;
//DMA3CH1SSAU = 0x0200;
//DMA3CH1SSAL = 0x0014;
//DMA3CH1SSAU = 0x0200;
//Procedure for calculating DMA byte addresses for destination in on-chip memory.
//1)Left shift start address by 1 bit to get address in bytes.
//2)Add offset. Offset is 0x10000 for DARAM and 0x80000 for SARAM. See Fig. 3-1 , page 12 of SPRS609B.
//3)Lower 16 bits in lower register and upper 16 in upper register.
//DMA3CH1DSAL = ((unsigned int)(us1dma)*2 + 0x10000) & 0xffff; // This is for IR
//DMA3CH1DSAU = (((unsigned int)(us1dma)*2 + 0x10000) >> 16) & 0xffff;
DMA3CH1DSAL = ((unsigned int)(test_buffer)*2 + 0x10000) & 0xffff; // This is for IR
DMA3CH1DSAU = (((unsigned int)(test_buffer)*2 + 0x10000) >> 16) & 0xffff;
//Length of data to be moved in bytes.
DMA3CH1TCR1 = 0x0040; //32 words = 64 bytes. Because FIFO length is 64 bytes.
//Channel 1 disabled, src add constant, dest. add. post inc., interrupt ena., burst 64 bytes, auto reload disa., and no sync.
DMA3CH1TCR2 = 0x00a0; //0x20a0 to enable interrupt and 0xa0a0 to enable channel and interrupt.
}
void FPGA_init(void)
{
IRQ_setVecs((Uint32)(&VECSTART));
IRQ_plug(INT0_EVENT, &fpga_isr_test); //Mushtaq 072210 Remove later.
IRQ_enable(INT0_EVENT);
FPGA_reset();
}
void FPGA_reset()
{
int i;
for(i=0;i<500;i++)
asm("\tNOP");
far_poke(0x400010, 0x04); //MUX to US0.
for(i=0;i<500;i++)
asm("\tNOP");
far_poke(0x400010, 0x00); //MUX to US0.
for(i=0;i<500;i++)
asm("\tNOP");
far_poke(0x400010, 0x04); //MUX to US0.
for(i=0;i<500;i++)
asm("\tNOP");
}