Forum Discussion
Altera_Forum
Honored Contributor
16 years agoDMA - memory to memory writing problem..
hi folks,
i want to write data from one address to an other via dma like in the code below, problem is, it doesn't work. first i use the macros to set the addresses and the length and then i set the byte mask and the go mask. did i forget anything? thanks for your help ------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "sys/alt_dma.h"
#include "system.h"
#include "altera_avalon_dma_regs.h"
/* Callback function that obtains notification that the data is received.*/
int
main (void)
{
int i=0;
char sMSG_tx,sMSG_rx;
memset(sMSG_rx,0,sizeof(sMSG_rx));
memset(sMSG_tx,0x55,sizeof(sMSG_tx));
for(i=0;i<8;i++)
{
printf("%d",sMSG_tx);
}
printf("\n");
for(i=0;i<8;i++)
{
printf("%d",sMSG_rx);
}
printf("\n");
/*initialize*/
IOWR_ALTERA_AVALON_DMA_RADDRESS(DMA_RS485_BASE,(
int) sMSG_tx);
IOWR_ALTERA_AVALON_DMA_WADDRESS(DMA_RS485_BASE, (int)sMSG_rx);
IOWR_ALTERA_AVALON_DMA_LENGTH(DMA_RS485_BASE, 8);
IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_RS485_BASE, ALTERA_AVALON_DMA_CONTROL_BYTE_MSK | ALTERA_AVALON_DMA_CONTROL_GO_MSK);
while(1)
{
if(IORD_ALTERA_AVALON_DMA_STATUS(DMA_RS485_BASE) & (ALTERA_AVALON_DMA_STATUS_DONE_MSK))
{
for(i=0;i<8;i++)
{
printf("%d",sMSG_tx);
}
printf("\n");
for(i=0;i<8;i++)
{
printf("%d",sMSG_rx);
}
break;
}
}
return 0;
}
2 Replies
- Altera_Forum
Honored Contributor
1) Indent your code.
2) The nios cpu is probably repeatedly reading the data from its cache, you need to either invalidate the relevant cache lines or do uncached reads. - Altera_Forum
Honored Contributor
We solved the problem. After checking the system in Quartus, we saw, that the SD-RAM we used wasn't directly connected with the CPU1. We use an Cyclon3 with 2 CPU and it seems, that this was the Problem. After adding an On-Chip-Memmory and using this, or changing the accessed memmory to S-RAM it worked. For anybody who try to work with DMA and also has some problems dealing with the code, here is our working example without HAL.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "sys/alt_dma.h" #include "system.h" #include "altera_avalon_dma_regs.h" #include "alt_types.h" #include "sys/alt_irq.h" static int dma_done=0,TX,RX; static void doneDMA(void* context , alt_u32 id) { usleep(10); dma_done++; IOWR_ALTERA_AVALON_DMA_STATUS(DMA_RS485_BASE, 0); } int Init(void) { IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_RS485_BASE, ALTERA_AVALON_DMA_CONTROL_BYTE_MSK| ALTERA_AVALON_DMA_CONTROL_LEEN_MSK| ALTERA_AVALON_DMA_CONTROL_I_EN_MSK); alt_irq_register(DMA_RS485_IRQ,(void*) NULL,doneDMA); return 0; } void Transfer(int where,int from,int howmuch) { dma_done=0; while ((IORD_ALTERA_AVALON_DMA_STATUS(DMA_RS485_BASE) & ALTERA_AVALON_DMA_STATUS_BUSY_MSK)); IOWR_ALTERA_AVALON_DMA_STATUS(DMA_RS485_BASE, 0); IOWR_ALTERA_AVALON_DMA_LENGTH(DMA_RS485_BASE, howmuch); IOWR_ALTERA_AVALON_DMA_RADDRESS(DMA_RS485_BASE,(int) from); IOWR_ALTERA_AVALON_DMA_WADDRESS(DMA_RS485_BASE,(int) where); IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_RS485_BASE, ALTERA_AVALON_DMA_CONTROL_GO_MSK | IORD_ALTERA_AVALON_DMA_CONTROL(DMA_RS485_BASE)); } void MemInit(int base_addr,int len, int value) { int i; for (i=0;i<len;i++) IOWR_8DIRECT(base_addr,i,value); } int main(void) { MemInit((int)RX,0x10,3); MemInit((int)TX,0x10,6); Init(); Transfer((int)RX,(int)TX,16); while(!dma_done); return 0; }