Improve stdio_write_nonblock perf and indicator printing

This commit is contained in:
Allen Hill
2026-08-19 11:37:52 -07:00
parent b9f7978d3e
commit 6ce4c2cc21
2 changed files with 19 additions and 14 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ void stdio_init(void);
// holds only '!'. In the overwrite case the buffer in front of that line is // holds only '!'. In the overwrite case the buffer in front of that line is
// truncated, so a reader MUST tolerate one malformed buffer there. The return // truncated, so a reader MUST tolerate one malformed buffer there. The return
// value is useful only for diagnostics. // value is useful only for diagnostics.
bool stdio_write_nonblock(const void *buf, size_t len); bool stdio_write_nonblock(const void *buf, uint8_t len);
#ifdef __cplusplus #ifdef __cplusplus
} }
+18 -13
View File
@@ -33,7 +33,7 @@ static int stdio_putchar(char data, FILE *stream) {
return 0; return 0;
} }
bool stdio_write_nonblock(const void *buf, size_t len) { bool stdio_write_nonblock(const void *buf, uint8_t len) {
if (len == 0) if (len == 0)
return true; return true;
@@ -51,27 +51,32 @@ bool stdio_write_nonblock(const void *buf, size_t len) {
// available space or because the ring is full. For the former case, the // available space or because the ring is full. For the former case, the
// full indicator can be appended without truncating previously queued // full indicator can be appended without truncating previously queued
// bytes. // bytes.
// Goal is for the bang-indicator to be on its own line
uint8_t tmp = head;
if (space >= 3) { if (space >= 3) {
tx0_buffer[(head + 1) & TX0_BUFFER_MASK] = '\n'; // Room for 3 normally implies the current head ends with a newline
tx0_buffer[(head + 2) & TX0_BUFFER_MASK] = '!'; // (avoids an unneeded double newline in most cases)
tx0_buffer[(head + 3) & TX0_BUFFER_MASK] = '\n'; tmp = (tmp + 1) & TX0_BUFFER_MASK;
tx0_Head = (uint8_t)((head + 3) & TX0_BUFFER_MASK); tx0_buffer[tmp] = '!';
tmp = (tmp + 1) & TX0_BUFFER_MASK;
tx0_buffer[tmp] = '\n';
tx0_Head = tmp;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { USART0.CTRLA |= USART_DREIE_bm; } ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { USART0.CTRLA |= USART_DREIE_bm; }
} else { } else {
// No room for even the indicator, so it goes over the last three queued // No room for even the indicator, so it goes over the last three queued
// bytes. `space` and the queued byte count always sum to // bytes. The ISR already drains the ring, so DREIE needs no change.
// TX0_BUFFER_MASK, so space < 3 means at least 253 bytes are queued and // Write in reverse order to more efficiently decrement
// all three writes land inside them. The ISR already drains the ring, so tx0_buffer[tmp] = '\n';
// DREIE needs no change. tmp = (tmp - 1) & TX0_BUFFER_MASK;
tx0_buffer[(head - 2) & TX0_BUFFER_MASK] = '\n'; tx0_buffer[tmp] = '!';
tx0_buffer[(head - 1) & TX0_BUFFER_MASK] = '!'; tmp = (tmp - 1) & TX0_BUFFER_MASK;
tx0_buffer[head] = '\n'; tx0_buffer[tmp] = '\n';
} }
return false; return false;
} }
const uint8_t start = (uint8_t)((head + 1) & TX0_BUFFER_MASK); const uint8_t start = (uint8_t)((head + 1) & TX0_BUFFER_MASK);
const size_t contiguous = TX0_BUFFER_SIZE - start; const uint8_t contiguous = TX0_BUFFER_SIZE - start;
if (len <= contiguous) { if (len <= contiguous) {
memcpy(&tx0_buffer[start], buf, len); memcpy(&tx0_buffer[start], buf, len);