-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Rx fifo latency fix #4328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Rx fifo latency fix #4328
Changes from 6 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
2400e74
Add a new resetmethod_menu_all macro to give the choice of all the re…
mribble 8fe2727
Change reset menu from all to extra. This gets rid of duplicated code
mribble 666de32
Merge with upstream
mribble 0cb9617
Fix boards.txt
mribble a4e1b91
Flush the rx fifo when checking available bytes in fifo. This gives …
mribble 0e04ea3
Merge branch 'master' into rx-fifo-latency-fix
devyte 42d4cb3
Merge branch 'master' of https://github.com/esp8266/Arduino
mribble f23c4b0
Merge branch 'master' of https://github.com/mribble/Arduino-1 into rx…
mribble aa16f80
Merge branch 'rx-fifo-latency-fix' of https://github.com/mribble/Ardu…
mribble d1d17d2
When rx_avaiable is checked return rx_buffer plus rx_fifo. Then duri…
mribble f4a62c0
Clean up early out case.
mribble 7d4f7e0
Merge branch 'master' into rx-fifo-latency-fix
mribble 0d3d43f
Merge branch 'master' of https://github.com/esp8266/Arduino into rx-f…
mribble 001be65
Merge branch 'rx-fifo-latency-fix' of https://github.com/mribble/Ardu…
mribble e97a9fa
Merge branch 'master' of https://github.com/esp8266/Arduino into rx-f…
mribble c527a76
Set the rx full fifo ISR to trigger a little sooner. This makes the …
mribble ff7983f
Merge branch 'master' into rx-fifo-latency-fix
devyte File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this modification, bytes which do not fit into rx_buffer will be dropped when calling uart_rx_available, which is a bit unexpected. Effectively, this reduces the total FIFO size from the (hardware FIFO size) + (software FIFO size) to just (software FIFO size), if uart_rx_available is called.
Shouldn't uart_rx_available meerly be checking the number of bytes in hardware FIFO and adding it to the size of rx_buffer? Actual copying can happen in uart_read_char function, if the rx_buffer is empty.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@igrr you are right. However, I suspect that the objective of the hw buffer is to accumulate what is coming in before it's handed off upwards (i.e.: driven by the rate of incoming bytes), while the software buffer's objective is to accumulate before it's handed off to the application (driven by the app's rate of service).
The issue described is that, if the interrupt is being triggered only when the FIFO is full, then it is essentially behaving like the overflow interrupt. In other words, the interrupt is triggered only when the hw FIFO is completely full, and the next byte would drop data. The following has to happen to avoid dropping bytes at hardware level:
If it happens that the fifo is full and the interrupts are off for the moment because of something else, then the next incoming byte(s) can be dropped.
Per the document reference above, the trigger is when the number of bytes in the FIFO is greater than the configured threshold. I understand from that reading that changing that threshold doesn't change the size of the FIFO. In other words, if the threshold is set to something lower than the full FIFO size of 0x7F, it will trigger the interrupt more often, but also allow buffer space for bytes coming for the latency between interrupt trigger and isr execution.
I think that explains @mribble 's original test that seemed to work:
If that 127 is the threshold, then it is currently set to the full FIFO size.
A question: what happens when the number of bytes that come in is smaller than the threshold? It seems to me that the isr isn't called, so do those bytes just sit in the hw FIFO?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is correct!
There is a timeout feature — set by UCTOE and UCTOT fields. When FIFO is not empty, and no new bytes arrive in given amount of time, an interrupt fires.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@devyte - There is also a timeout check called UCTOT. Our code sets that to 2. I couldn't find any document that tells me the units for that 2, but I think 2 milliseconds make sense so maybe that's it. That pdf says the timeout threshold is measured just for inactivity so if my ms guess is correct that means if you don't write anything to the uart then after 2ms that timeout occurs and the rx fifo would be drained by the isr.
@igrr You make a good point about the buffer overflowing. However, I don't think just checking the bytes of data in fifo is correct. Then if you were actually trying to read those bytes you'd get the wrong results because you'd be trying to read bytes that haven't been moved into the software buffer yet.
OPTION_1
I think the simplest fix would be to copy over however many bytes from the fifo that can fit into the software buffer and then return however many bytes are in the software buffer. This means the largest number of available bytes that could be returned is 256.
Here's an example. Let's say you have 250 bytes in the software buffer and 50 bytes in the hw fifo. In the available check you'd move 6 bytes from the fifo (now has 44 bytes) and the software buffer would have 256 bytes which is what we'd report back to the user.
OPTION_2
Another option would be to return the total number of bytes in the fifo and sw buffer. However, then in read and peek functions you'd need to add code to get from the fifo if there is data there.
I think I like option 2 better. @igrr if you agree I can code up Option 2 and have you review it. Here is a summary of how I'd implement it:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also like the 2nd option. I think the copying loop can be moved to a separate inline function, and called from ISR and read/peek functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm inclined to agree. Here is my take on what is needed:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks guys. I'll work on a change an upload it soon.
@devyte, we don't need to reduce the fifo size because the interrupt happens either when the fifo is full or when there is that timeout. So that code should work as it is now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mribble this is the sequence that I think is problematic:
Per my understanding of the document that you referenced, reducing the number from 127 to 107 doesn't reduce the FIFO size. It only changes when the isr is called. In other words, the isr is called when the FIFO has 107 bytes instead of 127 bytes. With this reduction, the problem sequence becomes this:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@devyte - That's true of any of the stream hardware protocols (spi, i2c, uart) so you might want to consider how all those work too. In other systems I've worked with, you require IRS to both be short enough and infrequent enough that they don't cause the problem you described.
That said what you are saying seems like it would make things more robust in some case. I don't contribute much to this project though so I won't try to decide how this should be handled. @igrr is very involved so maybe he'll have an opinion. That said, this is a different feature than what I'm working on here so if you do that I think it should be done with a seperate push request.