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++
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.

Error -In dma data transfer

Altera_Forum
Honored Contributor II
1,613 Views

hello i am newbie ,please help me. 

 

 

i have following error. 

i am using four task for displaying leds and i am using button as an interrupt,so when i press any switch button it will go to interrupt service routine ,so from there in interupt service routine i am making dma data transfer.But i have problem here- in interrupt service routine dma transfer is not working/or may be it is hanged somhow in interrupt service routine.I do not know why? 

but if i will use dma function once before the Interrupt service routine comes then i am able to use DMA in interrupt service routine. this time there is not blocking/hanging why?i do not know please help me . 

 

I am using full-featured cyclone-EP1c20 with nios 2. 

 

# include <stdio.h># include "board_diag.h"# include "alt_types.h"# include <unistd.h># include "system.h"# include "sys/alt_irq.h"# include "altera_avalon_pio_regs.h"# include <stdlib.h># include "sys/alt_dma.h" 

alt_u8 led,q; 

volatile int edge_capture; 

 

static volatile int rx_done = 0; 

/* Callback function that obtains notification that the data has 

* been received. 

*/ 

static void done (void* handle, void* data) 

rx_done++; 

int dma () 

int rc; 

alt_dma_txchan txchan; 

alt_dma_rxchan rxchan; 

alt_u32 length=32; 

void* tx_data = (void*) 0x2000010; /* pointer to data to send */ 

void* rx_buffer = (void*) 0x2010000; /* pointer to rx buffer */ 

/* Create the transmit channel */ 

if ((txchan = alt_dma_txchan_open("/dev/dma")) == NULL) 

led = 0x07; 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, led); 

usleep(4000000); 

 

exit (1); 

/* Create the receive channel */ 

if ((rxchan = alt_dma_rxchan_open("/dev/dma")) == NULL) 

led = 0x0f; 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, led); 

usleep(4000000); 

exit (1); 

/* Post the transmit request */ 

if ((rc = alt_dma_txchan_send (txchan, 

tx_data, 

length, 

NULL, 

NULL)) < 0) 

led = 0x1f; 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, led); 

usleep(4000000); 

exit (1); 

/* Post the receive request */ 

if ((rc = alt_dma_rxchan_prepare (rxchan,rx_buffer,length,done,NULL)) < 0) 

led = 0x3f; 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, led); 

usleep(4000000); 

exit (1); 

/* wait for transfer to complete */ 

while (!rx_done); 

led = 0x40; 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, led); 

usleep(4000000); 

 

/*printf ("Transfer successful!\n");*/ 

return 0; 

 

static void Task1(void) 

 

led = 0x1; 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, led); 

usleep(2000000); 

}  

static void Task2(void)  

led = 0x2; 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, led); 

usleep(2000000); 

static void Task3(void)  

led = 0x4; 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, led); 

usleep(2000000); 

}  

static void Task4(void)  

led = 0x8; 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, led); 

usleep(2000000); 

# ifdef BUTTON_PIO_BASE 

static void handle_button_interrupts(void* context, alt_u32 id) 

 

/* Cast context to edge_capture&#39;s type. It is important that this be  

* declared volatile to avoid unwanted compiler optimization. 

*/ 

volatile int* edge_capture_ptr = (volatile int*) context; 

 

/* Store the value in the Button&#39;s edge capture register in *context. */ 

 

*edge_capture_ptr = IORD_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE); 

led = 0x20; 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, led); 

usleep(2000000); 

 

/* Reset the Button&#39;s edge capture register. */ 

IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE, 0); 

/*call for dma transfer*/; 

q=dma(); 

 

/* Initialize the button_pio. */ 

 

 

static void init_button_pio() 

/* Recast the edge_capture pointer to match the alt_irq_register() function 

* prototype. */ 

void* edge_capture_ptr = (void*) &edge_capture; 

/* Enable all 4 button interrupts. */ 

IOWR_ALTERA_AVALON_PIO_IRQ_MASK(BUTTON_PIO_BASE, 0xf); 

/* Reset the edge capture register. */ 

IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE, 0x0); 

/* Register the interrupt handler. */ 

alt_irq_register( BUTTON_PIO_IRQ, edge_capture_ptr, handle_button_interrupts );  

}# endif 

 

 

 

 

int main() 

/* Initialize the button pio. */ 

int q;# ifdef BUTTON_PIO_BASE 

init_button_pio();# endif 

 

 

q=dma(); 

while(1) 

Task1(); 

Task2(); 

Task3(); 

Task4(); 

 

return(0); 

}
0 Kudos
2 Replies
Altera_Forum
Honored Contributor II
738 Views

Hi, Nirav. 

 

In my opinion your problem comes from using the DMA API calls from inside an ISR. The following excerpt from the Nios II SW programmer manual, chapter 6 should help you in understanding: 

 

 

Restricted Environment 

ISRs run in a restricted environment. A large number of the HAL API 

calls are not available from ISRs. For example, accesses to the HAL file 

system are not permitted. As a general rule, when writing your own ISR, 

never include function calls that can block waiting for an interrupt. 

In addition, you should be careful when calling ANSI C standard library 

functions inside of an ISR. No calls should be made using the C standard 

library I/O API, because calling these functions can result in deadlock 

within the system, i.e., the system can become permanently blocked 

within the ISR. In particular, you should not call printf() from within 

an ISR without careful consideration. If stdout is mapped to a device 

driver that uses interrupts for proper operation, the printf() call can 

deadlock the system waiting for an interrupt that never occurs because 

interrupts are disabled. You can use printf() from within ISRs safely, 

but only if the device driver does not use interrupts. 

 

Hope this helps. 

 

Maurizio
0 Kudos
Altera_Forum
Honored Contributor II
738 Views

but dma transfer is working fine in ISR,when i will use the dma transfer once before the  

interrupt comes, 

 

NIrav  

 

 

 

 

 

 

 

 

 

 

--- Quote Start ---  

originally posted by mpaolini@Jan 17 2006, 12:14 PM 

hi, nirav. 

 

in my opinion your problem comes from using the dma api calls from inside an isr. the following excerpt from the nios ii sw programmer manual, chapter 6 should help you in understanding: 

 

 

restricted environment 

isrs run in a restricted environment. a large number of the hal api 

calls are not available from isrs. for example, accesses to the hal file 

system are not permitted. as a general rule, when writing your own isr, 

never include function calls that can block waiting for an interrupt. 

in addition, you should be careful when calling ansi c standard library 

functions inside of an isr. no calls should be made using the c standard 

library i/o api, because calling these functions can result in deadlock 

within the system, i.e., the system can become permanently blocked 

within the isr. in particular, you should not call printf() from within 

an isr without careful consideration. if stdout is mapped to a device 

driver that uses interrupts for proper operation, the printf() call can 

deadlock the system waiting for an interrupt that never occurs because 

interrupts are disabled. you can use printf() from within isrs safely, 

but only if the device driver does not use interrupts. 

 

hope this helps. 

 

maurizio 

<div align='right'><{post_snapback}> (index.php?act=findpost&pid=12246) 

--- quote end ---  

 

--- Quote End ---  

0 Kudos
Reply