- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi everybody,
I think this is a common issue, but I didn't find a solution to my question, so hopefully I will get an answer here: I have a DMA controller which I want to use on an IRQ coming from a PIO. The DMA works fine and also the IRQ does. But when I try to call the DMA transfer function INSIDE the ISR from the PIO, the DMA doesn't send it's Interrupt at the end (when transfer is finished). Priority of PIO Interrupt is 7, Priority of DMA is 6 (so there should not be a priority problem). Does anyone of you know a solution to my problem? Here is my code:
volatile static int rx_done = 0;
static void done_DMA(void* handle, void* data)
{
rx_done = 1;
}
void measureIOs()
{
int rc;
alt_dma_txchan txchan;
alt_dma_rxchan rxchan;
unsigned long* tx_data = (void*) EXT_DPR_TRISTATE_INTERFACE_0_BASE; // pointer to data to send
unsigned long* rx_buffer = (void*) SDRAM_BASE + 0x100000; // pointer to rx buffer
rx_buffer = (void*) SDRAM_BASE + 0x100000;
rx_done = 0;
// Create the transmit channel
if ((txchan = alt_dma_txchan_open("/dev/dma_0")) == NULL)
{
printf ("Failed to open transmit channel\n");
exit (1);
}
// Create the receive channel
if ((rxchan = alt_dma_rxchan_open("/dev/dma_0")) == NULL)
{
printf ("Failed to open receive channel\n");
exit (1);
}
if(alt_dma_txchan_ioctl(txchan,ALT_DMA_SET_MODE_32,NULL)<0)
{
exit(1);
}
if(alt_dma_rxchan_ioctl(rxchan,ALT_DMA_SET_MODE_32,NULL)<0)
{
exit(1);
}
if(alt_dma_txchan_ioctl(txchan,ALT_DMA_TX_ONLY_OFF,NULL)<0)
{
exit(1);
}
if(alt_dma_rxchan_ioctl(rxchan,ALT_DMA_RX_ONLY_OFF,NULL)<0)
{
exit(1);
}
// Post the transmit request
if ((rc = alt_dma_txchan_send (txchan,tx_data,4096,NULL,NULL)) < 0)
{
printf ("Failed to post transmit request, reason = %i\n", rc);
exit (1);
}
// Post the receive request
if ((rc = alt_dma_rxchan_prepare (rxchan,rx_buffer,4096,done_DMA,NULL)) < 0)
{
printf ("Failed to post read request, reason = %i\n", rc);
exit (1);
}
// wait for transfer to complete
while (!rx_done);
printf ("Transfer successful!\n");
}
/* INTERRUPT VARIABLE DEFINITONS */
volatile int edge_capture;
/* **************** INTERRUPT FUNCTIONS ********************* */
# ifdef PIO_SELECTED_RAM_BASE
# ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
static void handle_ram_interrupt(void* context)
# else
static void handle_ram_interrupt(void* context, alt_u32 id)
# endif
{
/* Cast context to edge_capture'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's edge capture register in *context. */
*edge_capture_ptr = IORD_ALTERA_AVALON_PIO_EDGE_CAP(PIO_SELECTED_RAM_BASE);
/* Reset the Button's edge capture register. */
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(PIO_SELECTED_RAM_BASE, 0);
measureIOs();
/*
* Read the PIO to delay ISR exit. This is done to prevent a spurious
* interrupt in systems with high procekssor -> pio latency and fast
* interrupts.
*/
IORD_ALTERA_AVALON_PIO_EDGE_CAP(PIO_SELECTED_RAM_BASE);
}
/* Initialize the ram_pio. */
static void init_ram_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(PIO_SELECTED_RAM_BASE, 0x1);
/* Reset the edge capture register. */
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(PIO_SELECTED_RAM_BASE, 0x0);
/* Register the interrupt handler. */
# ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
alt_ic_isr_register(PIO_SELECTED_RAM_IRQ_INTERRUPT_CONTROLLER_ID,PIO_SELECTED_RAM_IRQ,
handle_ram_interrupt, edge_capture_ptr, 0x0);
# else
alt_irq_register( PIO_SELECTED_RAM_IRQ, edge_capture_ptr,
handle_ram_interrupt);
# endif
}
# endif /***************** PIO_SELECTED_RAM_BASE **********************/
int main()
{
printf("Hello from Nios II!\n");
init_ram_pio();
while(1);
return 0;
}
Thanks for all answers ! =)
Link Copied
- « Previous
-
- 1
- 2
- Next »
23 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- No, I don't forget to set I_EN. I don't enable the IRQ because I'll not use a ISR routine in my project to transmit the data from DMA to UART. --- Quote End --- Oh, sorry I forgot!:-) --- Quote Start --- Which version of Quartus and Nios EDS do you use? --- Quote End --- I use Quartus 10.0 and NIOS EDS 10.0. Both with SP1. It's really strange that you get almost correct transfer though you are using (in my opinion) the wrong address of the TXDATA register of the UART. Hmmm? No Idea yet. Sorry... Maybe you should use SignalTap for debugging. It helped us a lot! Really amazing tool. Regards
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi!
I have the same problem with Quartus 10.0 SP1 and NIOS EDS 10.0 SP1. Can you post your working code for UART to RAM transfer? Thanks! Regards- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I hope this will help you. But I am using an ISR for servicing a completed DMA-Transfer.Int32 Transmit(Char8 * pTx, Int32 lLength)
{
//softwarereset
IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_RS485_BASE, 0x1000);
IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_RS485_BASE, 0x1000);
IOWR_ALTERA_AVALON_PIO_DATA (PIO_RS485_BASE,TRANSMIT); // setting the direction of the transceiver using a PIO
IORD_ALTERA_AVALON_UART_RXDATA(UART_RS485_BASE); //dummy read to UART
IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_RS485_BASE,
ALTERA_AVALON_DMA_CONTROL_WCON_MSK|
ALTERA_AVALON_DMA_CONTROL_BYTE_MSK|
ALTERA_AVALON_DMA_CONTROL_LEEN_MSK|
ALTERA_AVALON_DMA_CONTROL_I_EN_MSK); //setzen von WCON
DmaTransfer ((Int32) IOADDR_ALTERA_AVALON_UART_TXDATA(UART_RS485_BASE),
(Int32) pTx, lLength);
return 0;
}
Int32 Receive(Char8 * pRx, Int32 lLength)
{
while (!(IORD_ALTERA_AVALON_UART_STATUS(UART_RS485_BASE)
& ALTERA_AVALON_UART_STATUS_TMT_MSK));
//softwarereset
IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_RS485_BASE, 0x1000);
IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_RS485_BASE, 0x1000);
IORD_ALTERA_AVALON_UART_RXDATA(UART_RS485_BASE); // dummy read to UART
IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_RS485_BASE,
ALTERA_AVALON_DMA_CONTROL_RCON_MSK|
ALTERA_AVALON_DMA_CONTROL_BYTE_MSK|
ALTERA_AVALON_DMA_CONTROL_LEEN_MSK|
ALTERA_AVALON_DMA_CONTROL_I_EN_MSK);
IOWR_ALTERA_AVALON_PIO_DATA (PIO_RS485_BASE,RECEIVE); // setting the direction of the transceiver using a PIO
DmaTransfer ((Int32)pRx,
(Int32)IOADDR_ALTERA_AVALON_UART_RXDATA(UART_RS485_BASE),
lLength);
return 0;
}
void DmaTransfer(Int32 lWhere, Int32 lFrom, Int32 lHowMuch)
{
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_RADDRESS (DMA_RS485_BASE,(Int32) lFrom);
IOWR_ALTERA_AVALON_DMA_WADDRESS (DMA_RS485_BASE,(Int32) lWhere);
IOWR_ALTERA_AVALON_DMA_LENGTH (DMA_RS485_BASE, lHowMuch);
IOWR_ALTERA_AVALON_DMA_CONTROL (DMA_RS485_BASE,
ALTERA_AVALON_DMA_CONTROL_GO_MSK |
IORD_ALTERA_AVALON_DMA_CONTROL(DMA_RS485_BASE));
}
Good luck!
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page
- « Previous
-
- 1
- 2
- Next »