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++
12686 Discussions

printf("") in an interrupt handler

Altera_Forum
Honored Contributor II
2,735 Views

For debugging, printf's are such a useful tool, that I would like to try to circumvent the troubles associated with its use in irq routines. 

 

it says in the Nios II Software Developer’s manual that  

<div class='quotetop'>QUOTE </div> 

--- Quote Start ---  

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 nterrupts.[/b] 

--- Quote End ---  

 

 

How to determine if the UART is using interrupt or not? Is is simply a matter of assigning a level in the SOPC or not?  

 

Does it make a difference what ticks are selected in the library settings (reduced device divers, small C library)? 

 

What if the UART IRQ is at a high priority IRQ level (smaller number), higher than my irq, say PIO_IRQ, which would be using the printf(""), and in the PIO_IRQ handler make sure that the printf() is encllosed in alt_irq_interruptible(); alt_irq_non_interruptible(); sequence as the follwing code snippet indicates.. 

static void handle_button_interrupts(void* context, alt_u32 id) {  /* cast the context pointer to an integer. */  int* edge_capture_ptr = (int*) context;   // Read the edge capture register on the button PIO.  *edge_capture_ptr = IORD_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE);  /* Write to the edge capture register to reset it. */  IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE, 0);  /* reset interrupt capability for the Button PIO. */  IOWR_ALTERA_AVALON_PIO_IRQ_MASK(BUTTON_PIO_BASE, 0xf);  alt_irq_interruptible(); // Enable higher priority irq levels, in particular the UART serving printf&#39;s  printf("pio mask is = %d\n",*edge_capture_ptr );  alt_irq_non_interruptible(); } 

 

would that be a workable solution? 

Its clear that there can be significant overhead in printing. But sometimes this cost is worth the benefit. 

 

A side question: can the handle_button_interrupts() routine access global variables? In that case the context parameter could be ignored and edge_capture accessed directly. Hmm, maybe a matter of taste. 

 

regards 

henning
0 Kudos
2 Replies
Altera_Forum
Honored Contributor II
1,715 Views

larsen, 

 

The UART driver will use interrupts unless you tick the reduced drivers option in the system library config page, or you define ALTERA_AVALON_UART_SMALL. 

 

In answer to your other questions using printfs in the ISR if you have an interrupt driven UART driver is just asking for trouble so just use the polled driver as described above.
0 Kudos
Altera_Forum
Honored Contributor II
1,715 Views

If you don&#39;t want to slow your interrupt you can also create a virtual bottom half using alarms. 

 

sprintf your debug info. 

schedule an alarm with the string as the handler&#39;s context. 

 

in the alarm handler (which is the bottom half) disable the alarm (so that it doesn&#39;t call it again). 

I would set a local variable to the context so that if another alarm is scheduled by the irq handler it doesn&#39;t overwrite the first context. 

enable interrupts. 

print the debug info. 

disable interrupts. 

return. 

 

You will definately need to think about reducing your debug output as the serial interface won&#39;t keep up and your alarm handlers may have sychronization issues (more than one executing at a time), but if it&#39;s just for debug you may not really care. But be warned that depending on the frequency of your interrupts and the amount of debug output synchronization and throughput could be a big issue.
0 Kudos
Reply