Skip to content
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

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open

UARTChannel #191

wants to merge 24 commits into from

Conversation

tanneberger
Copy link
Member

@tanneberger tanneberger commented Jan 16, 2025

No description provided.

Copy link
Contributor

github-actions bot commented Jan 16, 2025

Memory usage after merging this PR will be:

Memory Report

action_empty_test_c

from to increase (%)
text 60860 60863 0.00
data 752 752 0.00
bss 11360 11360 0.00
total 72972 72975 0.00

action_microstep_test_c

from to increase (%)
text 61731 61734 0.00
data 760 760 0.00
bss 11424 11424 0.00
total 73915 73918 0.00

action_overwrite_test_c

from to increase (%)
text 61568 61571 0.00
data 752 752 0.00
bss 11424 11424 0.00
total 73744 73747 0.00

action_test_c

from to increase (%)
text 61472 61475 0.00
data 760 760 0.00
bss 11424 11424 0.00
total 73656 73659 0.00

deadline_test_c

from to increase (%)
text 57102 57105 0.01
data 768 768 0.00
bss 10784 10784 0.00
total 68654 68657 0.00

delayed_conn_test_c

from to increase (%)
text 62464 62467 0.00
data 752 752 0.00
bss 10272 10272 0.00
total 73488 73491 0.00

event_payload_pool_test_c

from to increase (%)
text 18331 18331 0.00
data 624 624 0.00
bss 320 320 0.00
total 19275 19275 0.00

event_queue_test_c

from to increase (%)
text 27616 27616 0.00
data 736 736 0.00
bss 480 480 0.00
total 28832 28832 0.00

nanopb_test_c

from to increase (%)
text 42886 42886 0.00
data 904 904 0.00
bss 320 320 0.00
total 44110 44110 0.00

port_test_c

from to increase (%)
text 62412 62415 0.00
data 752 752 0.00
bss 10272 10272 0.00
total 73436 73439 0.00

reaction_queue_test_c

from to increase (%)
text 27448 27448 0.00
data 736 736 0.00
bss 480 480 0.00
total 28664 28664 0.00

request_shutdown_test_c

from to increase (%)
text 61703 61706 0.00
data 752 752 0.00
bss 11424 11424 0.00
total 73879 73882 0.00

startup_test_c

from to increase (%)
text 56801 56804 0.01
data 760 760 0.00
bss 10784 10784 0.00
total 68345 68348 0.00

tcp_channel_test_c

from to increase (%)
text 96867 96885 0.02
data 1256 1256 0.00
bss 21376 21408 0.15
total 119499 119549 0.04

timer_test_c

from to increase (%)
text 56692 56695 0.01
data 752 752 0.00
bss 10784 10784 0.00
total 68228 68231 0.00

Copy link
Contributor

github-actions bot commented Jan 16, 2025

Benchmark results after merging this PR:

Benchmark results

Performance:

PingPongUc:
Best Time: 195.903 msec
Worst Time: 209.999 msec
Median Time: 196.390 msec

PingPongC:
Best Time: 169.517 msec
Worst Time: 175.480 msec
Median Time: 170.372 msec

ReactionLatencyUc:
Best latency: 28168 nsec
Median latency: 59835 nsec
Worst latency: 376613 nsec

ReactionLatencyC:
Best latency: 37173 nsec
Median latency: 60162 nsec
Worst latency: 220327 nsec

Memory usage:

PingPongUc:
text data bss dec hex filename
40932 760 7440 49132 bfec bin/PingPongUc

PingPongC:
text data bss dec hex filename
45826 880 360 47066 b7da bin/PingPongC

ReactionLatencyUc:
text data bss dec hex filename
30737 744 2080 33561 8319 bin/ReactionLatencyUc

ReactionLatencyC:
text data bss dec hex filename
41536 848 360 42744 a6f8 bin/ReactionLatencyC

@tanneberger tanneberger changed the title [DRAFT] UARTChannel UARTChannel Jan 22, 2025
Copy link
Collaborator

@erlingrj erlingrj left a 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.

include/reactor-uc/network_channel.h Outdated Show resolved Hide resolved
include/reactor-uc/network_channel.h Show resolved Hide resolved
include/reactor-uc/platform/riot/uart_channel.h Outdated Show resolved Hide resolved
include/reactor-uc/network_channel.h Outdated Show resolved Hide resolved
include/reactor-uc/network_channel.h Outdated Show resolved Hide resolved
src/platform/riot/uart_channel.c Outdated Show resolved Hide resolved
src/platform/riot/uart_channel.c Outdated Show resolved Hide resolved
src/platform/riot/uart_channel.c Outdated Show resolved Hide resolved
src/platform/riot/uart_channel.c Outdated Show resolved Hide resolved
src/platform/riot/uart_channel.c Outdated Show resolved Hide resolved
@tanneberger tanneberger requested a review from erlingrj January 22, 2025 18:45
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);
Copy link
Collaborator

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?

Copy link
Member Author

@tanneberger tanneberger Jan 23, 2025

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.

Copy link
Collaborator

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

Copy link
Member Author

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.

Copy link
Collaborator

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.

Copy link
Collaborator

@erlingrj erlingrj left a 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!!

Copy link
Collaborator

@erlingrj erlingrj left a 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!

src/platform/riot/uart_channel.c Show resolved Hide resolved
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);
Copy link
Collaborator

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 Show resolved Hide resolved
#include "reactor-uc/logging.h"
#include "reactor-uc/environment.h"
#include "reactor-uc/serialization.h"
#include "led.h"
Copy link
Collaborator

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?

@tanneberger
Copy link
Member Author

@erlingrj there is not include/reactor-uc/network_channel/uart_channel.h for the platform independent uart enums.

@tanneberger tanneberger force-pushed the uart branch 2 times, most recently from 172449d to 32a700c Compare January 26, 2025 08:53
@tanneberger tanneberger requested a review from erlingrj January 27, 2025 01:16
@tanneberger tanneberger force-pushed the uart branch 3 times, most recently from 7c6471c to 7df9c6d Compare January 27, 2025 07:37
Copy link
Collaborator

@erlingrj erlingrj left a 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);
Copy link
Collaborator

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("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),
Copy link
Collaborator

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?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, STRING is also in caps.

@erlingrj
Copy link
Collaborator

I think we should add at least one test LF program before merging this, showing how the annotation looks. If you put it under test/lf/src/only_build and set platform: RIOT, we will only run code-gen on it.

As noted above, I think data_bits and stop_bits attribute parameters should be integers, not strings

@tanneberger tanneberger requested a review from erlingrj February 5, 2025 03:08
Copy link
Contributor

github-actions bot commented Feb 5, 2025

Coverage after merging uart into main will be

70.51%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
src
   action.c77.69%65.63%100%81.18%134–135, 24, 42–45, 48, 50–51, 54–56, 62–63, 70–72, 72, 72–75, 81–82, 93–94
   builtin_triggers.c90.91%70%100%96.77%14, 18, 40, 43
   connection.c77.33%51.16%100%86.73%10, 104, 11, 110, 123–124, 136–137, 14, 14, 143, 145–146, 148, 16–17, 21–22, 22, 22–23, 25, 27–28, 33, 48, 48, 48–49, 55, 60–62, 97
   environment.c82.18%60%92.31%86.76%12–13, 18, 20–21, 31, 35–36, 42–43, 59–60, 64–65, 97–99
   event.c95.35%92.86%100%96.15%14–15
   federated.c5.23%2.73%7.69%6.33%10, 100, 102, 104, 104, 104–105, 109, 11, 112–113, 113, 113–114, 116–117, 119, 123–124, 126–128, 13, 131, 133–138, 140–142, 145–147, 147, 147–148, 148, 148–149, 15, 15, 15, 150, 152, 155–156, 158–159, 16, 160–162, 164–169, 17, 171, 171, 171–174, 176, 176, 176–178, 178, 178–179, 18, 183–184, 184, 184, 187–188, 19, 19, 19, 192–194, 196, 196, 196, 198–202, 205, 205, 205–208, 211–212, 212, 212–213, 215–216, 219, 22, 220, 225–226, 226, 226–227, 229, 23, 231, 231, 231–234, 234, 234, 234, 234, 234–239, 24, 24, 24, 240–243, 243, 243–244, 246, 248–249, 25, 250–256, 26, 26, 26, 260, 263, 263, 263–265, 269, 27, 272–273, 273, 273, 273–279, 28, 280–281, 283, 289, 29, 29, 29, 290–291, 30, 30, 30, 30, 30, 303–304, 307–309, 31, 310, 312, 312, 312–313, 317–318, 318, 318, 320, 322–323, 323, 323–324, 324, 324–325, 325, 325–326, 326, 326–327, 327, 327–328, 328, 328–329, 329, 329, 33, 331, 331, 331–332, 332, 332–333, 333, 333–334, 334, 334–335, 335, 335, 337, 36, 36, 36, 36, 36–37, 41–42, 46–47, 49–52, 54, 54, 54–55, 55, 55, 57, 57, 57–59, 59, 59–61, 65–66, 70–71, 73–76, 78, 80, 80, 80–81, 81, 81–82, 82, 82–83, 83, 83, 86–87, 89–92, 94, 94, 94–97, 97, 97–98
   logging.c88.52%83.33%100%89.36%25, 38–40, 47, 60–61
   network_channel.c69.23%62.50%100%70.59%42, 42, 42, 47–50, 59
   port.c78.08%45.83%100%93.33%10, 10, 10, 16, 20, 25, 25–27, 27, 27–28, 39, 39, 39–40
   queues.c89.94%80.36%100%94.06%108, 113, 119, 21–23, 47–48, 60–61, 84–88, 91–92
   reaction.c71.19%54.55%100%79.71%15, 17, 21, 28–31, 31, 31–32, 42, 45, 47, 52–53, 53, 53–55, 55, 55–56, 73, 89–91, 91, 91–94, 94, 94–95
   reactor.c69.33%51.52%100%82.28%10, 101–102, 14–19, 22, 28, 30, 32–37, 37, 37–38, 38, 38, 43, 55, 58–59, 59, 59–60, 60, 60–61, 63, 77–78, 81–82, 82, 82–83, 83, 83–84, 86, 91
   serialization.c37.50%25%50%40%16–17, 26–27, 33–34, 34, 34–35, 37–38, 41–42, 42, 42–43, 45–46
   tag.c40.19%31.48%60%47.92%14, 14–15, 17, 17–18, 23–24, 24, 24, 24, 24–25, 27, 27, 27, 27, 27–28, 30, 30, 30–31, 33–34, 34, 34–35, 37, 37, 37, 37, 37–38, 40, 40, 40, 40, 40–41, 43, 53–54, 63, 63–64, 83–85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85–87, 89
   timer.c95%66.67%100%100%14, 25
   trigger.c100%100%100%100%
   util.c41.67%33.33%33.33%46.67%12–13, 13, 13–16, 18–20, 4–5
src/platform/posix
   posix.c53.15%30%66.67%56.58%100–101, 101, 101–103, 107, 16, 18, 20–21, 35–37, 39–41, 49–50, 55–60, 60, 60–63, 63, 63–65, 68, 74–75, 79, 82, 93–95, 95, 95–97, 99
   tcp_ip_channel.c65.16%51.42%94.12%74.44%100, 103–104, 104, 104–105, 119–120, 122, 124, 128–129, 137, 140–141, 141, 141–142, 147–148, 148, 148–149, 155–156, 156, 156–158, 172, 175, 179, 179, 179, 179, 179–180, 180, 180–181, 181, 181–182, 184, 186, 186, 186–187, 196, 203–204, 208–209, 213, 213, 213–215, 215, 215–216, 218, 218, 218–219, 219, 219, 221, 223–224, 228, 228, 228–229, 249, 262–263, 263, 263–264, 270, 275–276, 276, 276–277, <

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants