Forum Discussion
Altera Avalon Uart performance problem
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.16 Replies
- Altera_Forum
Honored Contributor
Hi trk_golf,
Can you try the JTAG uart? It is supported in the current kernel. wentao - Altera_Forum
Honored Contributor
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. - Altera_Forum
Honored Contributor
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't understand why I would be dropping characters, even with a FIFO'd uart.[/b] --- Quote End --- can you tell me which UART you tried? - Altera_Forum
Honored Contributor
wentao,
Sorry for my misunderstanding. I could try the JTAG uart to see if it performs better just for reference. But, I'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'm working with the FAE on the hardware side of things to ensure the FIFO's are working. But, he has not used it under Linux, so I'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. - Altera_Forum
Honored Contributor
trk_golf
If you decide to explore using the jtag_uart, you could try using nios2-terminal, in conjunction with named pipes. It'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've not tested it) that the opposite should also work: cat input.txt > nios2-terminal What I'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 - Altera_Forum
Honored Contributor
<div class='quotetop'>QUOTE </div>
--- Quote Start --- I'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... - Altera_Forum
Honored Contributor
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'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'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't work for our end solution, because it takes a lot more LE's compared to the NIOS uarts. But, it would allow a good comparison. Has anyone converted this to interface with an Avalon bus? - Altera_Forum
Honored Contributor
use 2 stopbits. Its my experience with 115200 baud on the uart, any uart in fact; that many PC's , even fast neweish ones, don'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.
- Altera_Forum
Honored Contributor
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'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'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's, I'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. - Altera_Forum
Honored Contributor
One thing should be pointed out is, the application echo you are using put an extra '\n' 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.