Skip to content

Commit a034576

Browse files
Merge branch 'main' into darkwater/main
2 parents c8ab140 + 440a400 commit a034576

File tree

3 files changed

+69
-4
lines changed

3 files changed

+69
-4
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,8 @@ Initial release
723723

724724
### [defmt-rtt-next]
725725

726+
* [#1006] Fix `available_buffer_size` ignoring available buffer space when `read < write`
727+
726728
### [defmt-rtt-v1.1.0] (2025-10-09)
727729

728730
* [#968] Add `in_blocking_mode` public method
@@ -961,6 +963,7 @@ Initial release
961963
---
962964

963965
[#1007]: https://github.com/knurling-rs/defmt/pull/1007
966+
[#1006]: https://github.com/knurling-rs/defmt/pull/1006
964967
[#990]: https://github.com/knurling-rs/defmt/pull/990
965968
[#986]: https://github.com/knurling-rs/defmt/pull/986
966969
[#974]: https://github.com/knurling-rs/defmt/pull/974

defmt/tests/ui/log-missing-format-impl.stderr

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@ error[E0277]: the trait bound `Foo: Format` is not satisfied
22
--> tests/ui/log-missing-format-impl.rs:4:5
33
|
44
4 | defmt::info!("{}", Foo)
5-
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Format` is not implemented for `Foo`
5+
| ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound
66
|
7+
help: the trait `Format` is not implemented for `Foo`
8+
--> tests/ui/log-missing-format-impl.rs:1:1
9+
|
10+
1 | struct Foo;
11+
| ^^^^^^^^^^
712
= help: the following other types implement trait `Format`:
813
&T
914
&mut T

firmware/defmt-rtt/src/channel.rs

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,66 @@ impl Channel {
111111
fn available_buffer_size(read_cursor: usize, write_cursor: usize) -> usize {
112112
if read_cursor > write_cursor {
113113
read_cursor - write_cursor - 1
114-
} else if read_cursor == 0 {
115-
BUF_SIZE - write_cursor - 1
116114
} else {
117-
BUF_SIZE - write_cursor
115+
BUF_SIZE - write_cursor - 1 + read_cursor
116+
}
117+
}
118+
119+
#[cfg(test)]
120+
mod tests {
121+
use super::available_buffer_size;
122+
use crate::consts::BUF_SIZE;
123+
124+
#[test]
125+
fn test_rtt_available_buffer_size() {
126+
// Helper to simulate RTT buffer state
127+
let avail = |read: usize, write: usize| available_buffer_size(read, write);
128+
129+
// --- Case 1: Buffer is EMPTY (write == read) ---
130+
// Should have maximum available space: BUF_SIZE - 1
131+
assert_eq!(avail(0, 0), BUF_SIZE - 1);
132+
assert_eq!(avail(10, 10), BUF_SIZE - 1);
133+
assert_eq!(avail(BUF_SIZE - 1, BUF_SIZE - 1), BUF_SIZE - 1);
134+
135+
// --- Case 2: Buffer is FULL ---
136+
// Full condition: (write + 1) % BUF_SIZE == read
137+
// i.e., write == (read - 1 + BUF_SIZE) % BUF_SIZE
138+
assert_eq!(avail(0, BUF_SIZE - 1), 0); // write=BUF_SIZE-1, read=0 → full
139+
assert_eq!(avail(5, 4), 0); // write=4, read=5 → full
140+
assert_eq!(avail(1, 0), 0); // write=0, read=1 → full
141+
142+
// --- Case 3: Read ahead of Write (no wrap-around) ---
143+
// e.g., read=10, write=5 → free space = [5..9] → size = 10 - 5 - 1 = 4
144+
assert_eq!(avail(10, 5), 10 - 5 - 1);
145+
assert_eq!(avail(BUF_SIZE - 1, 0), (BUF_SIZE - 1) - 0 - 1); // = BUF_SIZE - 2
146+
147+
// --- Case 4: Write has wrapped around, Read behind (wrap-around case) ---
148+
// e.g., read=5, write=10 → free space = [10..BUF_SIZE-1] + [0..4]
149+
// size = (BUF_SIZE - 10 - 1) + (5) = BUF_SIZE - 10 - 1 + 5
150+
assert_eq!(avail(5, 10), BUF_SIZE - 10 - 1 + 5);
151+
assert_eq!(avail(0, 1), BUF_SIZE - 1 - 1 + 0); // = BUF_SIZE - 2
152+
assert_eq!(avail(1, BUF_SIZE - 1), BUF_SIZE - (BUF_SIZE - 1) - 1 + 1); // = 1
153+
154+
// --- Edge: Single byte free ---
155+
// After filling BUF_SIZE - 2 bytes from empty, 1 byte remains
156+
assert_eq!(avail(1, BUF_SIZE - 1), 1); // one byte free
157+
assert_eq!(avail(2, BUF_SIZE - 1), 2); // one byte free: only position BUF_SIZE-1 is free? No.
158+
// Actually: write=BUF_SIZE-1, read=2 → free = [BUF_SIZE-1] + [0,1] → but [0,1] is 2 bytes?
159+
// Let's recompute: total free = (BUF_SIZE - (BUF_SIZE-1) - 1) + 2 = (0) + 2 = 2 → wait.
160+
161+
// Better: use invariant
162+
// Total data in buffer = (write - read + BUF_SIZE) % BUF_SIZE
163+
// Free = BUF_SIZE - 1 - data
164+
let data_in_buffer = |read: usize, write: usize| (write + BUF_SIZE - read) % BUF_SIZE;
165+
let free_should_be = |read: usize, write: usize| BUF_SIZE - 1 - data_in_buffer(read, write);
166+
167+
// Validate our function against this invariant
168+
for read in 0..BUF_SIZE.min(64) {
169+
for write in 0..BUF_SIZE.min(64) {
170+
let expected = free_should_be(read, write);
171+
let actual = avail(read, write);
172+
assert_eq!(actual, expected, "Mismatch at read={read}, write={write}");
173+
}
174+
}
118175
}
119176
}

0 commit comments

Comments
 (0)