Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
20 years ago

Error -In dma data transfer

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);

}

2 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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 ---