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

Altera Avalon Uart performance problem

Altera_Forum
Honored Contributor II
3,052 Views

I have been testing the Altera Avalon Uart by sending data to it from a different machine. 

A program on the other machine sends 16kB of known data out its serial port which connects to the serial port on my uKit. 

I am running the serial ports at 115200 baud. 

 

I am having a problem where after about 4kB of received data, it begans losing the chars. Usually I only receive about 4-5kB total out of the entire 16kB sent. 

My serial port is "/dev/ttyS1". If I enter "cat /dev/ttyS1 > /tmp/capture.txt", then open this file after the transfer, I can see this result. 

 

I know that this uart does not have a FIFO. I'm trying to determine if this is likely the only problem I have or if there could be a software level issue as well. 

 

I am working with a local FAE that is helping me to try a uart that does contain FIFO support, but I'm not seeing any difference in the behavior. 

 

I've also thought about using the Open Cores uart16550. Has anyone ported this into their Nios II design? Does it work seemlessly with the standard 16550 compatible uart kernel driver? 

 

I have lots of questions and I'm just wondering if anyone else has dealt with any of these issues. 

 

I don't know if it is a hardware problem, software problem, or maybe...just maybe a user problem.
0 Kudos
16 Replies
Altera_Forum
Honored Contributor II
932 Views

Hi trk_golf, 

 

Can you try the JTAG uart? It is supported in the current kernel. 

 

wentao
0 Kudos
Altera_Forum
Honored Contributor II
932 Views

The JTAG uart works ok for the console port, but I stopped using it because of the annoying CTRL-C issue with nios2-terminal. 

 

Our end application is going to be using multiple RS232 UARTs for communication with multiple external devices. All of these will be running at 115200 baud. 

I was trying to test a single port to validate the design. The Nios uart and even the FIFO-enabled Cal_Avalon_Uart that I've been working with are preferable to the Open Cores uart because of their small footprint. I just don't understand why I would be dropping characters, even with a FIFO'd uart.
0 Kudos
Altera_Forum
Honored Contributor II
932 Views

I should have made me more understandable. My suggestion is, trying your communication on JTAG, which has FIFO, to see if you still lose characters. If not, that means your problem is caused by the lack of FIFO in Nios UART. But you said you had tried a FIFO'd uart,  

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

--- Quote Start ---  

I just don&#39;t understand why I would be dropping characters, even with a FIFO&#39;d uart.[/b] 

--- Quote End ---  

 

can you tell me which UART you tried?
0 Kudos
Altera_Forum
Honored Contributor II
932 Views

wentao, 

 

Sorry for my misunderstanding. I could try the JTAG uart to see if it performs better just for reference. But, I&#39;m not sure how to interface with this port under the Cygwin environment, except for using nios2-terminal. I need to be able to have my application run and use it as a serial port. 

 

In answering your second question: 

 

The UART I tried is called a Cal_Avalon_Uart. It was designed by an Altera FAE. It is basically identical to the standard Altera_Avalon_Uart, except that it contains FIFO support. I&#39;m working with the FAE on the hardware side of things to ensure the FIFO&#39;s are working. But, he has not used it under Linux, so I&#39;m pursing the software side of things on this forum to see if there is a general limitation of the serial drivers under uClinux on the Nios II. The specification for the Cal_Avalon_Uart states that it is software compatible with the original uart, but one never knows... 

 

Thanks for your continued help.
0 Kudos
Altera_Forum
Honored Contributor II
932 Views

trk_golf 

 

If you decide to explore using the jtag_uart, you could try using nios2-terminal, in conjunction with named pipes. It&#39;s not a perfect solution, but I think it should work. It should give you the benefits of transferring data at a higher rate, as well. 

 

I know that the following works, from an SDK shell: 

 

nios2-terminal > output.log 

 

and I think (though I&#39;ve not tested it) that the opposite should also work: 

 

cat input.txt > nios2-terminal 

 

What I&#39;m not sure about is whether or not pipes ["|"] will work or, for that matter, named pipes...in your C code. 

 

It sure would be nice if someone wrote a Windows driver (that looks like a COM port) wrapped around the calls that nios2-terminal is using, huh? 

 

- slacker
0 Kudos
Altera_Forum
Honored Contributor II
932 Views

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

--- Quote Start ---  

I&#39;m pursing the software side of things on this forum to see if there is a general limitation of the serial drivers under uClinux on the Nios II. The specification for the Cal_Avalon_Uart states that it is software compatible with the original uart, but one never knows...[/b] 

--- Quote End ---  

 

 

I am not sure, as long as your UART keeps the RRDY bit on in the status register when the FIFO is not empty, the driver should be able to take all the characters with one interrupt processing. Then it should not drop chars...
0 Kudos
Altera_Forum
Honored Contributor II
932 Views

I have begun to use SignalTap II in order to try and diagnose the Uart problem. 

 

I would also like to try to use the JTAG uart "/dev/ttyJ0" to see how it performs as a reference point.  

The problem with this is that I haven&#39;t figured out how to send data from Cygwin across the Jtag connection. 

I tried the following with no success: 

 

echo "hello" > nios2-terminal 

cat textfile > nios2-terminal 

 

On the Nios II side, I&#39;m just running "cat /dev/ttyJ0". This works fine if I run nios2-terminal and manually enter data. 

 

Anymore suggestions on how to send external data through the JTAG uart connection under Cygwin? 

 

 

I would also like to try the Opencores uart16550 to see if it has FIFO problems. This wouldn&#39;t work for our end solution, because it takes a lot more LE&#39;s compared to the NIOS uarts. But, it would allow a good comparison. Has anyone converted this to interface with an Avalon bus?
0 Kudos
Altera_Forum
Honored Contributor II
932 Views

use 2 stopbits. Its my experience with 115200 baud on the uart, any uart in fact; that many PC&#39;s , even fast neweish ones, don&#39;t work reliably unless you have 2 stopbits. This is what I see with data going into the PC. Other direction I dont know if this is an issue. Check it, its at least easy going.

0 Kudos
Altera_Forum
Honored Contributor II
932 Views

I have performed some more analysis on the standard Altera Avalon Uart as well as a Cal Avalon Uart that is the same basic design, except it contains FIFO&#39;s. 

 

Regardless of which uart I use, I see performance problems. The symptoms of these problems are dropped characters due to overflow. 

 

Using SignalTap, I&#39;ve found that a lot of interrupts are being generated. The NIOSserial.c driver is supposed to read all characters out of a FIFO (if it exists) without the need for another interrupt to be generated. I believe this basically works. However, I have found some behavior that I think might be a problem. 

 

The NIOSserial.c driver unmasks the trdy bit quite often. The effect of this is an interrupt is immediately generated by the UART. This interrupt indicates that the transmit buffer is empty and the uart is ready to receive more characters for transfer. I can understand how this would be important, but it seems like it is causing more interrupts than necessary. 

 

I would like to get some opinions on whether or not this could be fixed in the driver. 

 

I have observed the following behavior when receiving a single character with the standard Altera Avalon Uart. 

 

First, I open the port for reading 

 

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

--- Quote Start ---  

"cat /dev/ttyS1 > /tmp/dump.txt &"[/b] 

--- Quote End ---  

 

 

The following routines are called in the driver 

 

rs_open() 

startup() 

transmit_chars() 

 

Then, I use an external terminal connected to this port to send a single character. A serial cable connects ttyS1 on the external machine to ttyS1 on the ukit development board. 

 

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

--- Quote Start ---  

echo "A" > /dev/ttyS1[/b] 

--- Quote End ---  

 

 

Using printk&#39;s, I&#39;ve traced the flow to the following: 

 

receive_chars() 

transmit_chars() 

rs_write() 

transmit_chars() 

rs_write() 

transmit_chars() 

 

The only thing that can cause the transmit_chars() routine to be called is an interrupt where the trdy bit is set. 

This interrupt will only be generated by the UART when the ie_trdy bit is set (interrupt enable for trdy). 

 

It seems to me that the transmit_chars() routine is getting called way to often for this driver to be efficient. 

 

Can somebody help me out here? 

Has anybody else experienced this problem? 

 

Thanks.
0 Kudos
Altera_Forum
Honored Contributor II
932 Views

One thing should be pointed out is, the application echo you are using put an extra &#39;\n&#39; at the end with a seperate write operation, therefore, there are actually two characters sent in your example. This is also the reason why you see rs_write twice. 

 

My guess is, if you want to send X characters, the function transmit_chars will be called roughly X+1 times (one extra to disable TX interrupt when no data to send). You can easily test this with a command like "$echo 123456789 >/dev/ttyS1". 

 

For a uart with one character buffer, this is nearly the best it can do. But if you have a FIFO, you can make the hardware to generate a TX interrupt when at least a certian proportion of the FIFO is empty, and let transmit_chars send more than one characters each time, then you will see less TX interrupts.
0 Kudos
Altera_Forum
Honored Contributor II
932 Views

Thanks for the suggestion. Now that you&#39;ve mentioned this, it seems quite obvious that this would alleviate the problem. I&#39;ve already implemented this on the receive side, so that a threshod is reached before generating the interrupt. 

 

I&#39;ve verified that the receive_chars() routine will indeed read in all characters within the fifo on a single call. 

 

Will the transmit_chars() routine perform the same operation? It should be able to write characters to the transmit buffer until it is full (or nearly full). 

In looking at it, it appears that it will only send 1 character per interrupt. Am I right? 

 

Do you have some suggested ways of handling this? 

 

I can think of a possible implementation. 

 

Perform a do/while loop similar to the one in receive_chars() that will write chars to the tx fifo until it is full. 

If necessary, the uart w/ fifo support does provide new registers that allow software to see how many characters are in the fifo. 

This value could be used so the transmit_chars() routine knows when to stop writing data to the uart. 

 

If this fifo count info is important, I can add it to the serial driver. However, I do have some questions about how to add it. 

The registers below exist at offsets 6 and 7 of the uart. I&#39;m not sure how to adjust the structure to make these readable from within the driver. 

 

np_uartrxfifoused address 6 

np_uarttxfifoused address 7 

 

Am I on the right track? Does the transmit_chars() routine need to be modified? 

 

Thank you very much for you help. 

 

 

P.S. If I get all of this working, I&#39;ll add a timer-based irq event into the uart so that if there are any characters in the rx buffer, an irq will be generated every X ms. This will ensure no characters are left sitting in the receive fifo because the threshold hasn&#39;t been reached yet.
0 Kudos
Altera_Forum
Honored Contributor II
932 Views

This post is supplemental to the previous one. 

 

One thing that is causing me confusion when using the NIOSserial.c driver is the following. 

 

Even when I&#39;m not transmitting any characters, and only receiving them, the transmit_chars() routine is being called. 

 

Why does this happen? Shouldn&#39;t this routine only be called when characters are ready to be sent out? 

 

Any comments you might have in regards to these last questions will also help me out a lot. 

 

Thanks,
0 Kudos
Altera_Forum
Honored Contributor II
932 Views

 

--- Quote Start ---  

originally posted by trk_golf@Mar 1 2005, 10:15 AM 

thanks for the suggestion.  now that you&#39;ve mentioned this, it seems quite obvious that this would alleviate the problem.  i&#39;ve already implemented this on the receive side, so that a threshod is reached before generating the interrupt. 

 

i&#39;ve verified that the receive_chars() routine will indeed read in all characters within the fifo on a single call. 

 

will the transmit_chars() routine perform the same operation?  it should be able to write characters to the transmit buffer until it is full (or nearly full). 

in looking at it, it appears that it will only send 1 character per interrupt.  am i right? 

 

do you have some suggested ways of handling this? 

 

i can think of a possible implementation. 

 

perform a do/while loop similar to the one in receive_chars() that will write chars to the tx fifo until it is full. 

if necessary, the uart w/ fifo support does provide new registers that allow software to see how many characters are in the fifo. 

this value could be used so the transmit_chars() routine knows when to stop writing data to the uart. 

 

if this fifo count info is important, i can add it to the serial driver.  however, i do have some questions about how to add it. 

the registers below exist at offsets 6 and 7 of the uart.  i&#39;m not sure how to adjust the structure to make these readable from within the driver. 

 

np_uartrxfifoused  address 6 

np_uarttxfifoused  address 7 

 

am i on the right track?  does the transmit_chars() routine need to be modified? 

 

thank you very much for you help. 

 

 

p.s.  if i get all of this working, i&#39;ll add a timer-based irq event into the uart so that if there are any characters in the rx buffer, an irq will be generated every x ms.  this will ensure no characters are left sitting in the receive fifo because the threshold hasn&#39;t been reached yet. 

--- Quote End ---  

 

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

--- Quote Start ---  

In looking at it, it appears that it will only send 1 character per interrupt. Am I right?[/b] 

--- Quote End ---  

 

You are right. You have to customize it. 

 

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

--- Quote Start ---  

Perform a do/while loop similar to the one in receive_chars() that will write chars to the tx fifo until it is full. 

If necessary, the uart w/ fifo support does provide new registers that allow software to see how many characters are in the fifo. 

This value could be used so the transmit_chars() routine knows when to stop writing data to the uart.[/b] 

--- Quote End ---  

 

I don&#39;t see any problems. 

 

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

--- Quote Start ---  

If this fifo count info is important, I can add it to the serial driver. However, I do have some questions about how to add it.[/b] 

--- Quote End ---  

 

append them in the structure np_uart. 

 

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

--- Quote Start ---  

P.S. If I get all of this working, I&#39;ll add a timer-based irq event into the uart so that if there are any characters in the rx buffer, an irq will be generated every X ms. This will ensure no characters are left sitting in the receive fifo because the threshold hasn&#39;t been reached yet.[/b] 

--- Quote End ---  

 

or a kernel timer routine to check. Each RX interrupt will delay that timer further, and when there is no RX interrupt for long enough, the timer routine will be executed.
0 Kudos
Altera_Forum
Honored Contributor II
932 Views

 

--- Quote Start ---  

originally posted by trk_golf@Mar 1 2005, 02:51 PM 

this post is supplemental to the previous one. 

 

one thing that is causing me confusion when using the niosserial.c driver is the following. 

 

even when i&#39;m not transmitting any characters, and only receiving them, the transmit_chars() routine is being called. 

 

why does this happen?  shouldn&#39;t this routine only be called when characters are ready to be sent out? 

 

any comments you might have in regards to these last questions will also help me out a lot. 

 

thanks, 

--- Quote End ---  

 

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

--- Quote Start ---  

Even when I&#39;m not transmitting any characters, and only receiving them, the transmit_chars() routine is being called.[/b] 

--- Quote End ---  

 

not quite sure. Could be Xon/Xoff. You can check what was actually transmitted
0 Kudos
Altera_Forum
Honored Contributor II
932 Views

Hi all, 

 

is there a fix to this problem ? 

 

I mean, in 115200 bauds, I have a "ttyS2: 1 input overruns" when I transmit lots of data.  

 

Is the Cal avalon uart you are talking about a solution to my problem ? 

Is this fifo&#39;d uart available ? 

Is there a software fix to NIOSserial driver to solve this ? 

 

One more question : 

Did someone implement the hardware flow control in the NIOSserial driver ? 

 

Thanks in advance 

 

Best regards 

 

Pierre-Olivier
0 Kudos
Reply