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 polling

Altera_Forum
Honored Contributor II
2,114 Views

Hello to everybody, 

I'm developing an application made by several task. I'd like to receive data from uart in asynchronous way. So I has a main loop that continuously execute some task and sometime need to execute a gets() to capture data from uart and store them. 

The problem is due to the fact that the gets() is a blocking function and don’t return until new data arrive on uart so the mail loop is on hold. 

 

How can I resolve this problem? 

 

Regards !
0 Kudos
8 Replies
Altera_Forum
Honored Contributor II
874 Views

instead of using the FILE * 

 

try using the next code 

 

int fdterm; 

int flags= O_RDWR | O_NONBLOCK | O_NOCTTY; 

fdterm = open(uartName.c_str(),flags);  

if(0==fdterm) 

throw Execption; 

int len=read(fdterm,str,ALT_AVALON_UART_BUF_LEN);  

 

read will return 0 if there is nothing to read
0 Kudos
Altera_Forum
Honored Contributor II
874 Views

 

--- Quote Start ---  

originally posted by ilan-g7@Feb 9 2006, 12:03 PM 

instead of using the file * 

 

try using the next  code 

 

    int fdterm; 

    int flags= o_rdwr | o_nonblock | o_noctty; 

    fdterm = open(uartname.c_str(),flags);  

    if(0==fdterm) 

      throw  execption; 

    int len=read(fdterm,str,alt_avalon_uart_buf_len);   

 

read will return 0 if there is nothing to read 

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

--- quote end ---  

 

--- Quote End ---  

 

 

So i cannnot use gets() !! 

is it rigth ?
0 Kudos
Altera_Forum
Honored Contributor II
874 Views

gets() is a blocking function so you can&#39;t use it

0 Kudos
Altera_Forum
Honored Contributor II
874 Views

check HAL altera_avalon_uart.c, the read() will return at most one char only. it may return zero char in nonblocking mode.

0 Kudos
Altera_Forum
Honored Contributor II
874 Views

 

--- Quote Start ---  

originally posted by hippo@Feb 19 2006, 10:43 AM 

check hal altera_avalon_uart.c, the read() will return at most one char only. it may return zero char in nonblocking mode. 

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

--- quote end ---  

 

--- Quote End ---  

 

 

Hi, 

 

I also did some research about this UART STDIN and nonblocking mode, and was able to find a solution. 

 

I used the following code sample: 

 

#include <stdio.h> int main() {  char cmd;  if (1) {    fcntl(STDIN_FILENO,F_SETFL,O_NONBLOCK);  }  printf("Hello from Nios II!\n>");  while ( 1) {    if ( gets(cmd) == cmd ) {      printf( "%s\n>", cmd );    }  }  return 0; } 

 

While developing with JTAG_UART everything seemed to work fine even when O_NONBLOCK mode was used. Although this code example doesn&#39;t show if the nonblocking mode actually works, I had a bigger program which accessed evaluation board buttons, and with that program I was able to verify that the nonblocking mode actually worked. 

 

But when UART and target connection or real serial terminal was used, the STDIN failed to work correctly. 

 

With NIOS II 5.1 IDE&#39;s Console and target connection set to Uart (COM1), the gets() didn&#39;t return any string at all. But when real terminal was attached, I noticed that the terminal has to send LF in order to make the gets() return a string. So the IDE Console seems to use CR only, which doesn&#39;t work. I&#39;ve reported this bug to Altera already ... 

 

Another problem was the nonblocking mode, which failed to work with UART. While digging into altera_avalon_uart.c, I noticed some differenced between it and altera_avalon_jtag_uart.c. The JTAG_UART read operation returns -EWOULDBLOCK if no characters are waiting to be red, but UART returns zero. 

 

So I changed the end of alt_avalon_uart_read function (irq-version) to the following: 

 if (!block && count == 0 )    return -EWOULDBLOCK;  else    return count; 

 

(the "fast" version of the function should just return -EWOULDBLOCK instead of zero) 

 

With this change the UART became nonblocking with O_NONBLOCK flag. 

 

But with UART the gets() now returns every character as a string! With JTAG_UART everything seems to work fine! But the problem is in the gets() function, which treats the EWOULDBLOCK return as an error (i.e. EOF) and would just return that one character as a string. Fixing this would require altering gets() itself ... 

 

JTAG_UART probably works because it transmits all the characters as a string when the Enter is pressed and thus it can return all characters before it hits the blocking situation. 

 

I finally ended up writing my own character collecting into a command line with getchar(), which now with this fix works correctly in nonblocking mode. 

 

So the code would look something like this (if someone is interested): 

char cmdline; int cmd_index = 0; int ch; if ( (ch=getchar()) != EOF ) {     switch( ch ) {     case &#39;\b&#39;:  if ( cmd_index > 0 ) {      cmd_index--;  }  /*putchar( &#39;\b&#39; );*/  putchar( &#39; &#39; ); putchar( &#39;\b&#39; );  break;     default:  cmdline = ch;  cmd_index++;  break;     case &#39;\n&#39;:     case &#39;\r&#39;:  cmdline = &#39;\0&#39;;  //printf("\n%s\n>", cmdline );  handle_command( cmdline );  printf( ">" );  cmd_index = 0;  break;     } } 

 

I&#39;ve only briefly tested to code above, so beware http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/wink.gif  

 

I&#39;ve reported this to Altera and they promised to look into this and try to add this UART/EWOULDBLOCK fix into the next NIOS service pack or release. 

 

Hope this helps ... 

 

Jari
0 Kudos
Altera_Forum
Honored Contributor II
874 Views

 

--- Quote Start ---  

originally posted by fidodido@Feb 9 2006, 02:38 AM 

hello to everybody, 

i&#39;m developing an application made by several task. i&#39;d like to receive data from uart in asynchronous way. so i has a main loop that continuously execute some task and sometime need to execute a gets() to capture data from uart and store them. 

the problem is due to the fact that the gets() is a blocking function and don’t return until new data arrive on uart so the mail loop is on hold. 

 

how can i resolve this problem? 

 

regards ! 

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

--- quote end ---  

 

--- Quote End ---  

 

I&#39;m having the same problem. What&#39;s more is that if I set the O_NONBLOCK flag, a send buffer overrun occurs because it&#39;s not blocking on the output messages I&#39;m sending. I&#39;d like for it to block on send (to wait for room in the buffer), but not block on receive commands. 

 

I would expect a command like feof() to return TRUE if the receive buffer is empty, or at least have a similar function call be available to poll the buffer before a blocking receive command. But I&#39;ve found nothing. Instead, the only thing that seems to work on the receive side of things is to use the NONBLOCK option. Is there something I&#39;m missing? 

 

Thanks, 

Drew
0 Kudos
Altera_Forum
Honored Contributor II
874 Views

try to open uart twice, so you get 

one filedescriptor for non blocking input (O_NONBLOCK)  

and one for blocking output. 

 

better than blocking your system on output is to  

increase the buffer size or to have a software or  

harware (RTS/CTS) protocoll that handles it.
0 Kudos
Altera_Forum
Honored Contributor II
874 Views

 

--- Quote Start ---  

originally posted by jaris@Mar 24 2006, 04:33 AM 

so i changed the end of alt_avalon_uart_read function (irq-version) to the following: 

 if (!block && count == 0 )    return -ewouldblock;  else    return count; 

 

(the "fast" version of the function should just return -ewouldblock instead of zero) 

--- Quote End ---  

 

 

 

Thanks for posting this. This was extremely helpful, you saved me hours of frustration. 

Excellent workaround. 

http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/biggrin.gif
0 Kudos
Reply