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

UART interrupt handler

Altera_Forum
Honored Contributor II
5,039 Views

Hello! 

Please, explain me how to write interrupt handler for UART using NIOS II IDE. I can't find any information in documentation about it. Please
0 Kudos
28 Replies
Altera_Forum
Honored Contributor II
1,619 Views

I'm having the same problem. I found an App note about it that deals with the original Nios but the examples in it are not that good. 

 

It appears that the HAL already has support for interrupts but I can't figure out how to actually use it. 

 

As a side not if anyone knows how to use the hardware handshaking I would like to know. 

 

Thanks
0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

Chapter 6 of the Nios II Software Developer's Handbook is entitled Exception Handling and should help you.

0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

Hi! 

I've write small program with interrupt handler. I can't see the result ot ISR. May be somebody can explain my errors.  

 

 

char uval=0; 

 

ALTERA_AVALON_UART_INSTANCE( UART_0, uart_0 ); 

 

//---------------------------------------------------------------------------- 

void isr (void* context, alt_u32 id) 

uval++; 

IOWR_ALTERA_AVALON_PIO_DATA( PIO_1_BASE ,uval); 

//---------------------------------------------------------------------------- 

int main() 

{  

char vv=1; 

alt_sys_init(); 

alt_irq_register( UART_0_IRQ, &uart_0 , isr );  

alt_irq_enabled(); 

while(1) 

return 0; 

}
0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

Kira, 

 

There are a few things wrong with this code: 

 

1. You should not be calling alt_sys_init in main. This has already been called before main gets called. Given that this function initialises hardware calling it twice might have unwanted results. 

 

2. You are registerring for the IRQ belonging to the UART. I strongly suspect that you already have a driver in your system for the UART with it's own interrupt handler so I'm not surprised that your ISR is not getting called. 

 

3. I'm not sure why you called alt_irq_enabled this only tells you if interrupts are enabled and as you do nothing with this result the call is not very useful.
0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

Ok! I see. But there is another problem: what kind of steps I must do to enable interrupts, to define intterrupt handler? May be I must setup UART control register manually?  

Thank you.
0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

Kira, 

 

You seem to be confused. 

 

There is no need for you to write an interrupt handler for the UART, one already exists in the UART driver. 

 

If you wish to write an interrupt handler for another piece of hardware your code should be fine if remove the errors I highlighted in my previous post. You should also read the documentation which can be found in the Nios II Software Developers Handbook, there is an entire section on Exception Handling including an entire section on ISRs from page 6-5 onwards.
0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

hello  

I also have the problem about interrupt. I want to service an interrupt from the key PIO. 

I see the example project such as "count_binary",and the program i write is same as the example.but there is no jump into my ISR when I press the key. 

when debuging ,i read the register only ienable=1, the status and the ipending register is always zero. 

 

THANKS.
0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

I presume you are talking about register values read from within the interrupt handler. 

 

Within the exception handler the value of status will be 0 because its value has been zeroed by the exception. Its previous value is in estatus. 

 

As for ipending, unfortunately there is a bug in version 1.0 of the Nios II kit which means that the debugger incorrectly displays ipending as zero when single stepping. This is fixed in 1.1. 

 

To work around this you should set a breakpoint and continue - the correct value of ipending will be displayed.
0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

Hi again! 

 

I'm sorry, may be I described my problem unclear. So I'll try again. 

 

I looked through HAL files, there are following files, which define all uart functions: altera_avalon_uart.h and (*.c), altera_avalon_uart_regs.h and (*.c). How can I use functions from these files - alt_avalon_uart_irq and e.t? 

 

I just want to catch the moment, when UART receives data - rxdata. 

How can I do it using interrupt handler or something else way? 

 

Thank you
0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

code: 

 

unsigned char val=0; /---------------------------------------------------------------------------- static void handle_uart_interrupt (void* context, alt_u32 id) {  uval++;  IOWR_ALTERA_AVALON_PIO_DATA( PIO_0_BASE ,uval); } //---------------------------------------------------------------------------- //static alt_avalon_uart_dev gS;;   int main() {    IOWR_ALTERA_AVALON_UART_CONTROL ( UART_0_BASE, 0x180);    alt_irq_register( UART_0_IRQ , &uart_0, handle_uart_interrupt );      return 0; }
0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

Kira, 

 

I think you're missing something here. A UART device driver is provided so that if you wish to send or receive characters over the uart you just use the standard C library calls putc, printf or any of those functions, for receiving you can use getc, scanf etc. see http://sources.redhat.com/newlib/libc.html (http://sources.redhat.com/newlib/libc.html) for the documentation. 

 

You should not really be using the functions in the uart driver directly, unless you wish to re-write the driver, if so why?
0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

I think the best thing you can do now is open the system library that the Nios II IDE should have generated for you. If you look in there, you'll see the alt_sys_init code, and the system.h file that defines all the stuff you need to know about your SOPC design. 

 

If you look at the properties of your system library, you'll find a page which shows which UART that stdin/out/err are connected to. If that's the UART you want to talk to, then you can just use the standard POSIX routines printf, scanf, putc, getc, etc. to talk to the UART. 

 

If that's not the UART you want to talk to, you can get its name from system.h. There should be a line like:#define MY_UART_NAME "/dev/my_uart"and you would then use MY_UART_NAME as a filename to pass to open(), close(), read(), write(), etc. 

 

If you're dead set on reinventing the wheel, and absolutely must write your own interrupt handlers/drivers/everything else, you want to name your main function as "alt_main" and not "main". This skips all the interrupt setup, alt_sys_init, etc. and it becomes your problem to write.
0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

 

--- Quote Start ---  

originally posted by rugbybloke@Oct 19 2004, 10:29 AM 

kira, 

 

i think you're missing something here. a uart device driver is provided so that if you wish to send or receive characters over the uart you just use the standard c library calls putc, printf or any of those functions, for receiving you can use getc, scanf etc. see http://sources.redhat.com/newlib/libc.html (http://sources.redhat.com/newlib/libc.html) for the documentation. 

 

you should not really be using the functions in the uart driver directly, unless you wish to re-write the driver, if so why? 

--- Quote End ---  

 

The supplied uart driver does not have all the functions we need, so that's why we've had to tackle it. 

1/ Enable ioctl in small driver with ALTERA_AVALON_UART_USE_IOCTL compile flag.  

2/ ioctl termios flags for expanding newlines to cr-lf and echoing input characters. 

3/ Flush output buffer 

4/ XON-XOFF 

5/ Check for received character without reading it. 

6/ Get a hook to drop RTS after the buffer transmit empties (half-duplex turnaround) 

 

scanf requires the full 70k newlib. It would be nice to have finer control over the library build so functions like this can be selectively brought in. scanf and all the above are needed to port the console interface from 8- and 16-bit embedded applications that used very little memory. 

 

I notice that the uart driver code will not work if called with a read or write length of 0 because do..while is used. Possibly 'it can't happen'? There's also a hole in (all?) the device initialisation routines, eg alt_flash_open_dev returns dev ('open' successful) during initialisation even if dev->open is null. 

 

But this Nios stuff is wonderfully useful for new products, thank you to the Altera team.
0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

Hi again! 

 

I'll repeat my problem again. 

 

I want to CATCH the moment , when UART already received data via rxd and to READ these data, character. 

 

Now I realized timer and wrote the timer interrupt handler, which allows to read status register of UART. So I see how the condition of status register is changed after receiving data.  

 

So, if the condition of status register is changed, then corresponding interrupts must appear. 

 

How can I catch this interrupt (for receiving) ? 

__I want to CATCH the moment , when UART already received data via rxd and to READ these data, character.__ 

 

 

Thank you.
0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

Hi again! 

 

I'll repeat my problem again. 

 

I want to CATCH the moment by UART interrupt handler, when UART already received data via rxd and to READ these data, character. 

 

Now I realized timer and wrote the timer interrupt handler, which allows to read status register of UART. So I see how the condition of UART status register is changed after receiving data.  

 

Here my steps: 

 

1. In the beginning I set control register 0x180. So I set IRRDY and IE bits. IRRDY - Enable interrupt for a read ready. IE - Enable interrupt for an exception. 

2. then I define alt_irq_register( UART_0_IRQ , &uart_0, handle_uart_interrupt );  

3.  

static void handle_uart_interrupt (void* context, alt_u32 id) {  uval++;  IOWR_ALTERA_AVALON_PIO_DATA( PIO_0_BASE ,uval); } 

4. When character is received via rx UART, the condition of status register become 0xE0. RRDY is 1, so the interrupt for read ready must appear. If the condition of status register is changed, then corresponding interrupts must appear. 

 

But I didn’t see the results of handle_uart_interrupt function.  

 

How can I catch this UART interrupt (for receiving) ? 

 

Thank you.
0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

Hi, 

 

like 'rugbybloke' I'm a bit confused about exactly what it is you're trying to do, however it sounds like you want to write you're own device driver for the UART. Assuming that's the case, a good starting point for your own driver is the existing one. 

 

If you copy the contents of altera_avalon_uart/HAL/src and altera_avalon_uart/HAL/inc into your system library project then this copy will be used in preference to the original. You can then modify the driver to provide additional functionality as you see fit. 

 

If you find that manipulating the device through the ANSI C API, e.g. fopen(), fwrite(), printf() etc., is too much of an overhead for your application, then you can instead talk to the device using the underlying 'UNIX style' API, e.g. open(), read(), write() etc. This is a less sophisticated interface, but that's the trade off between the two options. 

 

Hopefully that isn't at a complete tangent to what you're trying to do. If it is, can you have another stab at trying to explain the problem you're trying to solve?
0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

Hello all! 

 

Thank you for all your answers and efforts to help me. 

 

I received the result I wanted. There were not any troubles - I just increased the period of simulation from 500 us to 900 us and I saw the result of my interrupt handler function. 

 

Thanks to all.
0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

 

--- Quote Start ---  

originally posted by mike desimone@Oct 20 2004, 12:53 AM 

i think the best thing you can do now is open the system library that the nios ii ide should have generated for you.  if you look in there, you'll see the alt_sys_init code, and the system.h file that defines all the stuff you need to know about your sopc design. 

 

if you look at the properties of your system library, you'll find a page which shows which uart that stdin/out/err are connected to.  if that's the uart you want to talk to, then you can just use the standard posix routines printf, scanf, putc, getc, etc. to talk to the uart. 

 

if that's not the uart you want to talk to, you can get its name from system.h.  there should be a line like:#define my_uart_name "/dev/my_uart"and you would then use my_uart_name as a filename to pass to open(), close(), read(), write(), etc. 

 

if you're dead set on reinventing the wheel, and absolutely must write your own interrupt handlers/drivers/everything else, you want to name your main function as "alt_main" and not "main".  this skips all the interrupt setup, alt_sys_init, etc. and it becomes your problem to write. 

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

--- Quote End ---  

 

 

 

I do like what you talk, but when I call "open(MY_UART_NAME,O_RDONLY)", the error message is that "O_RDONLY is undeclared ". can you tell me why and how to use open() function? if I can not open UART with open() function , I can not use the other function such as read(), write() and close(), and I can not communicate with nonblocking mode, right?
0 Kudos
Altera_Forum
Honored Contributor II
1,619 Views

 

--- Quote Start ---  

originally posted by kira@Oct 21 2004, 07:43 AM 

hello all! 

 

thank you for all your answers and efforts to help me. 

 

i received the result i wanted. there were not  any troubles -  i just increased the period of simulation from 500 us to 900 us and i saw the result of my interrupt handler function. 

 

thanks to all. 

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

--- quote end ---  

 

--- Quote End ---  

 

 

 

Hi Kira, 

 

I&#39;m having exactly the same problem as you, can you please tell me how you solved it. 

Thanks a lot
0 Kudos
Altera_Forum
Honored Contributor II
1,433 Views

This is the better disussion on interrupt over UART, so I won&#39;t open a new one. 

 

I understand that there is device driver provided in system librairy, and you can use it with open(), read(), write(), ... or fopen(), fread(), fwrite(), fprintf(), fscanf(),... 

 

I understand that you can re write device driver and interrupt handler. 

 

I think interrupt are driven RTS, CTS signals if hardware flow control is done. 

I think datas are in Rx and Tx buffers of UART driver at the interrupt time. 

 

When you read Rx buffer through read() function, I think it&#39;s not an interrupt. 

Interrupt just fill the Rx buffer, read() function take data stored into the Rx buffer, no ? 

 

What happens if you don&#39;t get datas into Rx buffer before the buffer is full ? I think the circular buffer continue, and datas are lost ? Is there a signal or something telling the buffer is almost full ? 

 

How getting datas at interrupts time ? (I&#39;m working at 921Kbds..) 

 

Is it necessary to rewrite the driver and the interrupt handler ?
0 Kudos
Reply