Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++

SGDMA Interrupts

Altera_Forum
Honored Contributor II
1,050 Views

Hi all, 

I have assembled a SGDMA in SOPC builder connected to a niosII core. The DMA runs on IRQ 0, the timer on IRQ1, the JTAG on IRQ2 and the LAN on IRQ6. 

 

The SGDMA reads from an avalon st source and maps to an on-chip memory. I have set the DMA to write in PARK mode to two, consecutive buffers on the onchip memory with the idea that I can process the buffer the DMA is not writing to.  

 

Question 1: 

how do I find out the address of the buffer the DMA is writing to (or equivalently) the address the DMA is not writing to? In other words, how can I figure out which descriptor is being executed by the DMA when operating in PARK mode? 

 

Question 2: 

I have the Real time OS with two tasks one for the lan and one to print error messages to the consol through the JTAG. It seams that when I printf a string to the screen, the DMA interrupt handlar is loosing interrupts. This is not a big deal, since I will turn off printf-s in real operation, but I am worried this might be an indicator of something more serious. 

 

Below, the relevant code. 

 

Thanks, 

Enzo 

 

 

# include <stdio.h> 

# include <string.h> 

# include <ctype.h> 

 

# include <stdio.h> 

/* Nichestack definitions */ 

# include "ipport.h" 

# include "tcpport.h" 

# include "libport.h" 

# include "osport.h" 

//#include "altera_avalon_pio_regs.h" 

 

# include <altera_avalon_sgdma.h> 

# include <altera_avalon_sgdma_descriptor.h> 

# include <altera_avalon_sgdma_regs.h> 

# include "sys/alt_cache.h" 

 

# include "tcp_server.h" 

# include "command.h" 

 

# define RXDMABASEADDR 0x06200000 

# define DESCRIPTORMEMORY 0x06240000 

 

# define NDESCRIPTORS 2 

# define BUFFER_SIZE 8192 // tx buffer size 

# define NBUF NDESCRIPTORS // Number of tx buffers 

 

static command_t cmd_list; //define command list 

static tx_buf_t buf[NBUF]; //define tx buffer 

static volatile int wx_buf; 

static volatile int rx_buf; 

static volatile alt_u32 fcounter; 

static volatile alt_u32 fcounter_old; 

 

static alt_sgdma_dev *receive_DMA; 

 

static alt_sgdma_descriptor *rx_descriptor; 

static alt_sgdma_descriptor *rx_descriptor_cpy; 

volatile alt_u32 sgdma_packet_idx = 0; 

volatile alt_u32 rx_error_count = 0; 

 

void p_swap(void *a, void *b, int bytes) 

char *pa, *pb; 

int i; 

 

pa = (char *)a; 

pb = (char *)b; 

 

for (i = 0; i < bytes; i++) pa[i] = pb[bytes - i - 1]; 

 

void sgdma_data_rdy(void * context) 

static alt_u32 dtmp; 

 

dtmp = IORD(buf[wx_buf].txbuf, 0); 

p_swap((void *)&fcounter, (void *)&dtmp, sizeof(dtmp)); 

 

wx_buf = (wx_buf+1)%NBUF; 

if(fcounter != fcounter_old+1) { 

rx_error_count++; /* main will be polling for this value being 1 */ 

fcounter_old = fcounter; 

sgdma_packet_idx++; /* main will be polling for this value being 1 */ 

 

 

void init_data_handler() //initialise data handler task 

int idx, j, dscp;  

void *dptr; 

 

wx_buf = 0; 

rx_buf = 0; 

for(j = 0; j < NBUF; j++) { 

buf[j].txbuf = (alt_u32 *)(RXDMABASEADDR + j*BUFFER_SIZE*sizeof(alt_u32)); 

for(idx = 0; idx < BUFFER_SIZE; idx++) IOWR(buf[j].txbuf, idx*sizeof(alt_u32), 0); 

buf[j].idx = 0; 

buf[j].lock = 1; 

buf[j].full = 0;  

 

// Instantiate SGDMA  

if ( (receive_DMA = alt_avalon_sgdma_open("/dev/sgdma")) == NULL ) { 

printf("Could not open the receive SG-DMA\n"); 

return; 

 

// Allocate sgdma descriptors 

dptr = (void *)DESCRIPTORMEMORY; 

rx_descriptor_cpy = (alt_sgdma_descriptor *)dptr; 

while ( (( (alt_u32)dptr) % ALTERA_AVALON_SGDMA_DESCRIPTOR_SIZE) != 0) dptr++; 

rx_descriptor = (alt_sgdma_descriptor *)dptr; 

rx_descriptor[NDESCRIPTORS].control = 0; // Clear out the null descriptor 

for(dscp = 0, j = 0; dscp < NDESCRIPTORS; dscp++, j++) { 

alt_avalon_sgdma_construct_stream_to_mem_desc(&rx_descriptor[dscp], &rx_descriptor[dscp+1],  

buf[j].txbuf, 0 , 0); 

}  

memcpy(&rx_descriptor[dscp], &rx_descriptor[0], sizeof(alt_sgdma_descriptor)); 

 

alt_dcache_flush_all(); // Clear memory cache 

 

// Instantiate SGDMA callbacl 

alt_avalon_sgdma_register_callback(receive_DMA, &sgdma_data_rdy, 

(ALTERA_AVALON_SGDMA_CONTROL_IE_GLOBAL_MSK | ALTERA_AVALON_SGDMA_CONTROL_PARK_MSK | ALTERA_AVALON_SGDMA_CONTROL_IE_DESC_COMPLETED_MSK ), 

NULL); 

 

 

// This task runs very slowly: used to debug messages 

void data_handler(void* p) packets for sending via ethernet 

 

alt_u32 sgdma_status, rx_error_count_old=0; 

printf("Data Handler Loaded\n"); //See when task actually starts 

OSTimeDlyHMSM(0,0,1,0); //wait for other tasks to start loading and to allow time to begin gnuplot(takes about 3-4 sec) 

printf("Data Handler Started\n"); //Task becomes active 

 

 

if(alt_avalon_sgdma_do_async_transfer(receive_DMA, &rx_descriptor[0]) != 0) 

printf("Writing the head of the receive descriptor list to the DMA failed\n"); 

return; 

 

while(1) {  

printf("ciao from dcb %04x (%d) %08x %08x \n", (int)sgdma_packet_idx, (int)rx_error_count, (int)sgdma_status,  

(int)fcounter ); 

rx_error_count_old = rx_error_count; 

 

OSTimeDly(1000);  

}
0 Kudos
0 Replies
Reply