1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-26 06:53:52 +01:00

stdio_rtt: port to new interface

This commit is contained in:
Benjamin Valentin 2023-06-13 20:05:59 +02:00
parent 7c1cdb16af
commit 76997fdd76

View File

@ -80,7 +80,7 @@
#include "mutex.h"
#include "stdio_rtt.h"
#include "thread.h"
#include "ztimer.h"
#include "ztimer/periodic.h"
/* This parameter affects the bandwidth of both input and output. Decreasing
it will significantly improve bandwidth at the cost of CPU time. */
@ -96,10 +96,9 @@
#define STDIO_RX_BUFSIZE (32)
#endif
/**
* @brief use mutex for waiting on stdin being enabled
*/
static mutex_t _rx_mutex = MUTEX_INIT;
#if !defined(MODULE_STDIN) && !defined(STDIO_RTT_DISABLE_STDIN)
#define STDIO_RTT_DISABLE_STDIN 1
#endif
/**
* @brief buffer holding stdout
@ -111,15 +110,12 @@ static char up_buffer [STDIO_TX_BUFSIZE];
*/
static char down_buffer [STDIO_RX_BUFSIZE];
/**
* @brief flag that enables stdin polling
*/
static char stdin_enabled = 0;
/**
* @brief flag that enables stdout blocking/polling
*/
static char blocking_stdout = 0;
static char blocking_stdout = IS_USED(STDIO_RTT_ENABLE_BLOCKING_STDOUT);
static ztimer_periodic_t stdin_timer;
/**
* @brief SEGGER's ring buffer implementation
@ -170,6 +166,22 @@ static segger_rtt_cb_t rtt_cb = {
{{ "Terminal", &down_buffer[0], sizeof(down_buffer), 0, 0, 0 }},
};
static int rtt_read_bytes_avail(void)
{
int16_t rd_off;
int16_t wr_off;
rd_off = rtt_cb.down[0].rd_off;
wr_off = rtt_cb.down[0].wr_off;
/* Read from current read position to wrap-around of buffer, first */
if (rd_off > wr_off) {
return rtt_cb.down[0].buf_size - rd_off;
} else {
return wr_off - rd_off;
}
}
/**
* @brief read bytes from the down buffer. This function does not block.
* The logic here is unmodified from SEGGER's reference, it is just
@ -177,7 +189,7 @@ static segger_rtt_cb_t rtt_cb = {
*
* @return the number of bytes read
*/
static int rtt_read(char* buf_ptr, uint16_t buf_size) {
static int rtt_read(uint8_t* buf_ptr, uint16_t buf_size) {
int16_t num_bytes_rem;
uint16_t num_bytes_read;
int16_t rd_off;
@ -269,61 +281,64 @@ int rtt_write(const char* buf_ptr, unsigned num_bytes) {
return num_bytes_written;
}
void stdio_init(void) {
#ifndef STDIO_RTT_DISABLE_STDIN
stdin_enabled = 1;
#endif
static bool _rtt_read_cb(void *arg)
{
int bytes = rtt_read_bytes_avail();
uint8_t buffer[STDIO_RX_BUFSIZE];
#ifdef STDIO_RTT_ENABLE_BLOCKING_STDOUT
blocking_stdout = 1;
#endif
if (bytes) {
bytes = rtt_read(buffer, sizeof(buffer));
isrpipe_write(arg, buffer, bytes);
}
/* the mutex should start locked */
mutex_lock(&_rx_mutex);
return true;
}
void rtt_stdio_enable_stdin(void) {
stdin_enabled = 1;
mutex_unlock(&_rx_mutex);
static bool _init_done;
static void _init(void) {
if (IS_USED(STDIO_RTT_DISABLE_STDIN)) {
return;
}
if (!thread_getpid()) {
/* we can't use ztimer in early init */
return;
}
ztimer_periodic_init(ZTIMER_MSEC, &stdin_timer, _rtt_read_cb, &stdin_isrpipe,
STDIO_POLL_INTERVAL_MS);
ztimer_periodic_start(&stdin_timer);
_init_done = true;
}
static void _detach(void)
{
if (!IS_USED(STDIO_RTT_DISABLE_STDIN)) {
ztimer_periodic_stop(&stdin_timer);
}
}
void rtt_stdio_enable_blocking_stdout(void) {
blocking_stdout = 1;
}
/* The reason we have this strange logic is as follows:
If we have an RTT console, we are powered, and so don't care
that polling uses a lot of power. If however, we do not
actually have an RTT console (because we are deployed on
a battery somewhere) then we REALLY don't want to poll
especially since we are not expecting to EVER get input. */
ssize_t stdio_read(void* buffer, size_t count) {
int res = rtt_read((void *)buffer, (uint16_t)count);
if (res == 0) {
if (!stdin_enabled) {
mutex_lock(&_rx_mutex);
/* We only unlock when rtt_stdio_enable_stdin is called
Note that we assume only one caller invoked this function */
}
uint32_t last_wakeup = ztimer_now(ZTIMER_MSEC);
while(1) {
ztimer_periodic_wakeup(ZTIMER_MSEC, &last_wakeup,
STDIO_POLL_INTERVAL_MS);
res = rtt_read(buffer, count);
if (res > 0)
return res;
}
}
return (ssize_t)res;
}
static ssize_t _write(const void* in, size_t len) {
const char *buffer = in;
int written = rtt_write(buffer, len);
ssize_t stdio_write(const void* in, size_t len) {
const char *buffer = (const char *)in;
int written = rtt_write(buffer, (unsigned)len);
uint32_t last_wakeup = ztimer_now(ZTIMER_MSEC);
while (blocking_stdout && ((size_t)written < len)) {
ztimer_periodic_wakeup(ZTIMER_MSEC, &last_wakeup, STDIO_POLL_INTERVAL_MS);
written += rtt_write(&buffer[written], len-written);
/* we have to postpone ztimer init */
if (!_init_done) {
_init();
}
if (blocking_stdout) {
uint32_t last_wakeup = ztimer_now(ZTIMER_MSEC);
while ((size_t)written < len) {
ztimer_periodic_wakeup(ZTIMER_MSEC, &last_wakeup, STDIO_POLL_INTERVAL_MS);
written += rtt_write(&buffer[written], len-written);
}
}
return (ssize_t)written;
}
STDIO_PROVIDER(STDIO_RTT, _init, _detach, _write)