-
Notifications
You must be signed in to change notification settings - Fork 740
capsules: virtual_uart: avoid double receive, check rx len, support custom buffer #1757
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
Conversation
Can you document when this happens? Amit noted that it happens on some boards and not others. So I want to understand that's causing that discrepancy. My read-through of the change and code suggests that it is OK, but this is something that needs a lot of testing. The virtual UART receive path is pretty tricky logic with edge cases. |
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.
Please provide a test case when this happens. I want to understand why it happens in some cases and not in others. The virtual receive logic is tricky and has to handle a bunch of edge cases. I'm worried that this patch will cause it to miss one.
One concern -- it's important that the read not happen directly in the read_done callback. I.e., a client issuing a read in its callback is not serviced immediately. The reason is that might be an outstanding shorter read. I.e.,
If the second A call stops the 2 byte read this is a bug. |
I posted this example code on slack: https://gist.github.com/pftbest/c5d89849e22d103278a104704c4624cb Compile it for desktop, no device required. It has only one reader, but every call to receive is followed by an abort call. |
One test case is just to run the process_console with no apps on master. To see the abort calls, I added this patch: diff --git a/chips/sam4l/src/usart.rs b/chips/sam4l/src/usart.rs
index e7b7fd4f4..cb82195da 100644
--- a/chips/sam4l/src/usart.rs
+++ b/chips/sam4l/src/usart.rs
@@ -12,6 +12,7 @@ use kernel::hil;
use kernel::hil::spi;
use kernel::hil::uart;
use kernel::ReturnCode;
+use kernel::debug_gpio;
use crate::dma;
use crate::pm;
@@ -865,6 +866,9 @@ impl uart::Receive<'a> for USART<'a> {
fn receive_abort(&self) -> ReturnCode {
let usart = &USARTRegManager::new(&self);
+
+ debug_gpio!(0, toggle);
+
self.disable_rx_timeout(usart);
self.abort_rx(usart, ReturnCode::ECANCEL, uart::Error::Aborted);
ReturnCode::EBUSY |
I forgot to bring an imix home when Stanford shut down. I do have a launchxl, but the instructions to build it do not work ( I think this bug fix is incorrect. I'd appreciate if the "Testing" section of the pull request reported running the UART virtualization tests. Let's call the read that comes in during the callback the new read and any that are already occurring the pending reads. The problem is that Why is it being called twice? We set the The problem is that whether you can start an underlying read is controlled by the presence of I think there's another lingering bug. If the new read is the shortest read, its length is not considered in the length of the next read to perform. So there also needs to be a line added to the So, in short, I think:
I'll try to figure out a way to get an imix. |
Ok yes that makes sense. This still needs to be addressed. However, I don't think So it seems like either:
would address the long/short receive issue. |
I think it can? The end of tock/capsules/src/virtual_uart.rs Line 157 in d7abb62
tock/capsules/src/virtual_uart.rs Line 133 in d7abb62
|
Unexpected behavior: Running the process console causes uart.receive_abort to be called after every character. Cause: start_receive gets called twice, once with a rx_buffer, and the second time without since it is being used after the first call. The first call happens because process console starts a new receive after handling its current read, and the second call happens because uart mux calls start_receive on its client's behalf after the callback. Fix: Remove the mux calling start_receive on its client's behalf.
This fixes the issue where receives issued from callbacks were always resulting in abort() calls by not replacing the underlying UART receive buffer until after all of the client callbacks ha 8000 ve finished. This "flag", in conjunction with the `completing_read` bool are what start_receive uses to determine whether to start or abort a receive. This also fixes determining the minimum length of a receive by calculating it in all cases where another receive is needed.
Without this check, the virtual uart will continue issuing reads to receive rx_len bytes, even if the buffer is not big enough to store them.
2ad8e51
to
6334749
Compare
Ok, discussed the fix with @phil-levis, and updated now. At a high level, the fix is to properly enqueue all receive requests issued during a receive callback until all of the callbacks have finished. Before, the first receive issued from a callback was improperly getting issued to the hardware. Receive requests issued at other times when there is not an active underlying receive are not enqueued, and issue immediately, as expected. |
Can you run the virtual UART test? |
I ran the virtual uart test on hail and it works just as expected. |
Pull Request Overview
Unexpected behavior: Running the process console causes uart.receive_abort to be called after every character.
Cause: start_receive gets called twice, once with a rx_buffer, and the second time without since it is being used after the first call. The first call happens because process console starts a new receive after handling its current read, and the second call happens because uart mux calls start_receive on its client's behalf after the callback.
Fix: Make sure that the buffer used by virtual_uart for underlying UART receives isn't replaced before client callbacks are completed. This causes all receives in callbacks to be queued until they have all completed and the virtual_uart receive handler can determine the shortest read to issue.
Other Changes
ESIZE
when a client issues a read.This pull request adds/changes/fixes...
Testing Strategy
Running process console on hail and verifying it works.
Added a debug statement to sam4l::usart::abort and it no longer is printed.
Tried the imix/src/test/virtual_uart_rx_test on hail and it works as expected.
TODO or Help Wanted
n/a
Documentation Updated
/docs
, or no updates are required.Formatting
make formatall
.