-
Notifications
You must be signed in to change notification settings - Fork 1
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
UARTChannel #191
base: main
Are you sure you want to change the base?
UARTChannel #191
Conversation
Memory usage after merging this PR will be: Memory Reportaction_empty_test_c
action_microstep_test_c
action_overwrite_test_c
action_test_c
deadline_test_c
delayed_conn_test_c
event_payload_pool_test_c
event_queue_test_c
nanopb_test_c
port_test_c
reaction_queue_test_c
request_shutdown_test_c
startup_test_c
tcp_channel_test_c
timer_test_c
|
Benchmark results after merging this PR: Benchmark resultsPerformance:PingPongUc: PingPongC: ReactionLatencyUc: ReactionLatencyC: Memory usage:PingPongUc: PingPongC: ReactionLatencyUc: ReactionLatencyC: |
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 looking very good. There is various feedback and a few potential problems (e.g. poll should read out all messages in the buffer, not just the first.
Also I think calling the buffers receive_buffer
and send_buffer
will be clearer so there is no confusion in the logic that is reading and writing to those buffers.
if (bytes_left >= 0) { | ||
int receive_buffer_index = self->receive_buffer_index; | ||
self->receive_buffer_index = bytes_left; | ||
memcpy(self->receive_buffer, self->receive_buffer + (receive_buffer_index - bytes_left), bytes_left); |
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.
For this to work, UartPollChannel_poll
must always be called within a critical section, so that interrupts are disabled. A few other places I added _locked
postfix to functions that has to be called from critical sections. Maybe this would be wise for this one as well?
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 would suggest we protect updates to the receive_buffer_index
but the receive_buffer
I would not protect.
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.
Hmm, I do not think this is safe. What happens e.g. if the interrupt occurs between line 79 and 84? Say we have parsed out a message, and that there are 4 bytes left. Well, if the interrupt occurs, then really there should be 5 bytes left, so when we do the memcpy to copy the bytes back to the beginning of the buffer, we forget the fifth byte and it is lost.
I think the memcpy has to be part of the critical section as well
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.
What I would prefer to this is turning the receive_buffer_index
into an atomic, then we could get rid of that lock.
I think only protecting the receive_buffer_index
is enough, because the interrupts are sequential so the incrementing is sequential and overwriting the receive_buffer_index
also gets sequenialized because we lock this region.
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.
If you want it lock-free I think you need to turn it into a circular buffer.
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 starting to look real good, nice progress. I pushed a few trivial fixes, but I think there still is some race condition between the ISR and the runtime. The other day we discussed lock-free queues, but the current implementation needs lock (or disabling interrupts). We could make it lock free by implementing a circular buffer between the ISR and the runtime (but we would then have to move the data from this circular buffer to a "linear" buffer before feeding it forward to the deserialization pipeline.
Also, I realized that we should expose more UART settings to the user.
Keep up the good work!!
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.
Getting there, but I think the critical section must be larger!
if (bytes_left >= 0) { | ||
int receive_buffer_index = self->receive_buffer_index; | ||
self->receive_buffer_index = bytes_left; | ||
memcpy(self->receive_buffer, self->receive_buffer + (receive_buffer_index - bytes_left), bytes_left); |
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.
Hmm, I do not think this is safe. What happens e.g. if the interrupt occurs between line 79 and 84? Say we have parsed out a message, and that there are 4 bytes left. Well, if the interrupt occurs, then really there should be 5 bytes left, so when we do the memcpy to copy the bytes back to the beginning of the buffer, we forget the fifth byte and it is lost.
I think the memcpy has to be part of the critical section as well
src/platform/riot/uart_channel.c
Outdated
#include "reactor-uc/logging.h" | ||
#include "reactor-uc/environment.h" | ||
#include "reactor-uc/serialization.h" | ||
#include "led.h" |
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.
What is the LED used for, I cant see any code that uses something LED related?
@erlingrj there is not |
172449d
to
32a700c
Compare
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.
Looks good. But perhaps changing the number of spaces should be a separate PR. Something is not correctly configured with Spotless as it does not complain on main
and you have changed every line of the code-generator. It makes it very hard to see the actual changes
if (bytes_left >= 0) { | ||
int receive_buffer_index = self->receive_buffer_index; | ||
self->receive_buffer_index = bytes_left; | ||
memcpy(self->receive_buffer, self->receive_buffer + (receive_buffer_index - bytes_left), bytes_left); |
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.
If you want it lock-free I think you need to turn it into a circular buffer.
new AttrParamSpec("name", AttrParamType.STRING, true), | ||
new AttrParamSpec("uart_device", AttrParamType.INT, true), | ||
new AttrParamSpec("baud_rate", AttrParamType.INT, true), | ||
new AttrParamSpec("data_bits", AttrParamType.STRING, true), |
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.
Should this be INT?
new AttrParamSpec("baud_rate", AttrParamType.INT, true), | ||
new AttrParamSpec("data_bits", AttrParamType.STRING, true), | ||
new AttrParamSpec("parity", AttrParamType.STRING, true), | ||
new AttrParamSpec("stop_bits", AttrParamType.STRING, true), |
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.
Should this also be INT?
No description provided.