pico_stdio improvements (#598)
* add stdio_usb_connected() method * add PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS to allow waiting for CDC connection during init(* * add puts_raw and putchar_raw to skip any CR/LF translation
This commit is contained in:
parent
12017a07ab
commit
13be546dc3
@ -16,6 +16,9 @@ void stdio_uart_init();
|
|||||||
static inline void stdio_init_all() { stdio_uart_init(); }
|
static inline void stdio_init_all() { stdio_uart_init(); }
|
||||||
static inline void stdio_filter_driver(stdio_driver_t *driver) {}
|
static inline void stdio_filter_driver(stdio_driver_t *driver) {}
|
||||||
static inline void stdio_set_translate_crlf(stdio_driver_t *driver, bool enabled) {}
|
static inline void stdio_set_translate_crlf(stdio_driver_t *driver, bool enabled) {}
|
||||||
|
static inline bool stdio_usb_connected(void) { return true; }
|
||||||
int getchar_timeout_us(uint32_t timeout_us);
|
int getchar_timeout_us(uint32_t timeout_us);
|
||||||
|
#define puts_raw puts
|
||||||
|
#define putchar_raw putchar
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -49,6 +49,9 @@ typedef struct stdio_driver stdio_driver_t;
|
|||||||
* Call this method once you have set up your clocks to enable the stdio support for UART, USB
|
* Call this method once you have set up your clocks to enable the stdio support for UART, USB
|
||||||
* and semihosting based on the presence of the respective libraries in the binary.
|
* and semihosting based on the presence of the respective libraries in the binary.
|
||||||
*
|
*
|
||||||
|
* When stdio_usb is configured, this method can be optionally made to block, waiting for a connection
|
||||||
|
* via the variables specified in \ref stdio_usb_init (i.e. \ref PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS)
|
||||||
|
*
|
||||||
* \see stdio_uart, stdio_usb, stdio_semihosting
|
* \see stdio_uart, stdio_usb, stdio_semihosting
|
||||||
*/
|
*/
|
||||||
void stdio_init_all(void);
|
void stdio_init_all(void);
|
||||||
@ -74,7 +77,7 @@ int getchar_timeout_us(uint32_t timeout_us);
|
|||||||
/*! \brief Adds or removes a driver from the list of active drivers used for input/output
|
/*! \brief Adds or removes a driver from the list of active drivers used for input/output
|
||||||
* \ingroup pico_stdio
|
* \ingroup pico_stdio
|
||||||
*
|
*
|
||||||
* \note this method should always be called on an initialized driver
|
* \note this method should always be called on an initialized driver and is not re-entrant
|
||||||
* \param driver the driver
|
* \param driver the driver
|
||||||
* \param enabled true to add, false to remove
|
* \param enabled true to add, false to remove
|
||||||
*/
|
*/
|
||||||
@ -100,6 +103,16 @@ void stdio_filter_driver(stdio_driver_t *driver);
|
|||||||
*/
|
*/
|
||||||
void stdio_set_translate_crlf(stdio_driver_t *driver, bool translate);
|
void stdio_set_translate_crlf(stdio_driver_t *driver, bool translate);
|
||||||
|
|
||||||
|
/*! \brief putchar variant that skips any CR/LF conversion if enabled
|
||||||
|
* \ingroup pico_stdio
|
||||||
|
*/
|
||||||
|
int putchar_raw(int c);
|
||||||
|
|
||||||
|
/*! \brief puts variant that skips any CR/LF conversion if enabled
|
||||||
|
* \ingroup pico_stdio
|
||||||
|
*/
|
||||||
|
int puts_raw(const char *s);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -59,6 +59,9 @@ static bool stdout_serialize_begin(void) {
|
|||||||
static void stdout_serialize_end(void) {
|
static void stdout_serialize_end(void) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
static void stdio_out_chars_no_crlf(stdio_driver_t *driver, const char *s, int len) {
|
||||||
|
driver->out_chars(s, len);
|
||||||
|
}
|
||||||
|
|
||||||
static void stdio_out_chars_crlf(stdio_driver_t *driver, const char *s, int len) {
|
static void stdio_out_chars_crlf(stdio_driver_t *driver, const char *s, int len) {
|
||||||
#if PICO_STDIO_ENABLE_CRLF_SUPPORT
|
#if PICO_STDIO_ENABLE_CRLF_SUPPORT
|
||||||
@ -89,7 +92,7 @@ static void stdio_out_chars_crlf(stdio_driver_t *driver, const char *s, int len)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool stdio_put_string(const char *s, int len, bool newline) {
|
static bool stdio_put_string(const char *s, int len, bool newline, bool no_cr) {
|
||||||
bool serialized = stdout_serialize_begin();
|
bool serialized = stdout_serialize_begin();
|
||||||
if (!serialized) {
|
if (!serialized) {
|
||||||
#if PICO_STDIO_IGNORE_NESTED_STDOUT
|
#if PICO_STDIO_IGNORE_NESTED_STDOUT
|
||||||
@ -97,13 +100,14 @@ static bool stdio_put_string(const char *s, int len, bool newline) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (len == -1) len = (int)strlen(s);
|
if (len == -1) len = (int)strlen(s);
|
||||||
|
void (*out_func)(stdio_driver_t *, const char *, int) = no_cr ? stdio_out_chars_no_crlf : stdio_out_chars_crlf;
|
||||||
for (stdio_driver_t *driver = drivers; driver; driver = driver->next) {
|
for (stdio_driver_t *driver = drivers; driver; driver = driver->next) {
|
||||||
if (!driver->out_chars) continue;
|
if (!driver->out_chars) continue;
|
||||||
if (filter && filter != driver) continue;
|
if (filter && filter != driver) continue;
|
||||||
stdio_out_chars_crlf(driver, s, len);
|
out_func(driver, s, len);
|
||||||
if (newline) {
|
if (newline) {
|
||||||
const char c = '\n';
|
const char c = '\n';
|
||||||
stdio_out_chars_crlf(driver, &c, 1);
|
out_func(driver, &c, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (serialized) {
|
if (serialized) {
|
||||||
@ -134,13 +138,26 @@ static int stdio_get_until(char *buf, int len, absolute_time_t until) {
|
|||||||
|
|
||||||
int WRAPPER_FUNC(putchar)(int c) {
|
int WRAPPER_FUNC(putchar)(int c) {
|
||||||
char cc = (char)c;
|
char cc = (char)c;
|
||||||
stdio_put_string(&cc, 1, false);
|
stdio_put_string(&cc, 1, false, false);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WRAPPER_FUNC(puts)(const char *s) {
|
int WRAPPER_FUNC(puts)(const char *s) {
|
||||||
int len = (int)strlen(s);
|
int len = (int)strlen(s);
|
||||||
stdio_put_string(s, len, true);
|
stdio_put_string(s, len, true, false);
|
||||||
|
stdio_flush();
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int putchar_raw(int c) {
|
||||||
|
char cc = (char)c;
|
||||||
|
stdio_put_string(&cc, 1, false, true);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int puts_raw(const char *s) {
|
||||||
|
int len = (int)strlen(s);
|
||||||
|
stdio_put_string(s, len, true, true);
|
||||||
stdio_flush();
|
stdio_flush();
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@ -154,7 +171,7 @@ int _read(int handle, char *buffer, int length) {
|
|||||||
|
|
||||||
int _write(int handle, char *buffer, int length) {
|
int _write(int handle, char *buffer, int length) {
|
||||||
if (handle == 1) {
|
if (handle == 1) {
|
||||||
stdio_put_string(buffer, length, false);
|
stdio_put_string(buffer, length, false, false);
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@ -243,7 +260,7 @@ int __printflike(1, 0) WRAPPER_FUNC(printf)(const char* format, ...)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stdio_init_all() {
|
void stdio_init_all(void) {
|
||||||
// todo add explicit custom, or registered although you can call stdio_enable_driver explicitly anyway
|
// todo add explicit custom, or registered although you can call stdio_enable_driver explicitly anyway
|
||||||
// These are well known ones
|
// These are well known ones
|
||||||
#if LIB_PICO_STDIO_UART
|
#if LIB_PICO_STDIO_UART
|
||||||
|
@ -54,6 +54,16 @@
|
|||||||
#define PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE 1200
|
#define PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE 1200
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// PICO_CONFIG: PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS, Maximum number of milliseconds to wait during initialization for a CDC connection from the host (negative means indefinite) before returning, default=0, group=pico_stdio_usb
|
||||||
|
#ifndef PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS
|
||||||
|
#define PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// PICO_CONFIG: PICO_STDIO_USB_POST_CONNECT_WAIT_DELAY_MS, Number of milliseconds to wait during initialization after a host CDC connection is detected before returning (some host terminals seem to sometimes lose transmissions sent right after connection), default=50, group=pico_stdio_usb
|
||||||
|
#ifndef PICO_STDIO_USB_POST_CONNECT_WAIT_DELAY_MS
|
||||||
|
#define PICO_STDIO_USB_POST_CONNECT_WAIT_DELAY_MS 50
|
||||||
|
#endif
|
||||||
|
|
||||||
// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED, Optionally define a pin to use as bootloader activity LED when BOOTSEL mode is entered via USB (either VIA_BAUD_RATE or VIA_VENDOR_INTERFACE), type=int, min=0, max=29, group=pico_stdio_usb
|
// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED, Optionally define a pin to use as bootloader activity LED when BOOTSEL mode is entered via USB (either VIA_BAUD_RATE or VIA_VENDOR_INTERFACE), type=int, min=0, max=29, group=pico_stdio_usb
|
||||||
|
|
||||||
// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED, Whether the pin specified by PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED is fixed or can be modified by picotool over the VENDOR USB interface, type=bool, default=0, group=pico_stdio_usb
|
// PICO_CONFIG: PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED, Whether the pin specified by PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED is fixed or can be modified by picotool over the VENDOR USB interface, type=bool, default=0, group=pico_stdio_usb
|
||||||
@ -94,10 +104,22 @@ extern "C" {
|
|||||||
extern stdio_driver_t stdio_usb;
|
extern stdio_driver_t stdio_usb;
|
||||||
|
|
||||||
/*! \brief Explicitly initialize USB stdio and add it to the current set of stdin drivers
|
/*! \brief Explicitly initialize USB stdio and add it to the current set of stdin drivers
|
||||||
* \ingroup pico_stdio_uart
|
* \ingroup pico_stdio_usb
|
||||||
|
*
|
||||||
|
* \ref PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS can be set to cause this method to wait for a CDC connection
|
||||||
|
* from the host before returning, which is useful if you don't want any initial stdout output to be discarded
|
||||||
|
* before the connection is established.
|
||||||
|
*
|
||||||
|
* \return true if the USB CDC was initialized, false if an error occurred
|
||||||
*/
|
*/
|
||||||
bool stdio_usb_init(void);
|
bool stdio_usb_init(void);
|
||||||
|
|
||||||
|
/*! \brief Check if there is an active stdio CDC connection to a host
|
||||||
|
* \ingroup pico_stdio_usb
|
||||||
|
*
|
||||||
|
* \return true if stdio is connected over CDC
|
||||||
|
*/
|
||||||
|
bool stdio_usb_connected(void);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -103,9 +103,29 @@ bool stdio_usb_init(void) {
|
|||||||
bool rc = add_alarm_in_us(PICO_STDIO_USB_TASK_INTERVAL_US, timer_task, NULL, true);
|
bool rc = add_alarm_in_us(PICO_STDIO_USB_TASK_INTERVAL_US, timer_task, NULL, true);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
stdio_set_driver_enabled(&stdio_usb, true);
|
stdio_set_driver_enabled(&stdio_usb, true);
|
||||||
|
#if PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS
|
||||||
|
#if PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS > 0
|
||||||
|
absolute_time_t until = make_timeout_time_ms(PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS);
|
||||||
|
#else
|
||||||
|
absolute_time_t until = at_the_end_of_time;
|
||||||
|
#endif
|
||||||
|
do {
|
||||||
|
if (stdio_usb_connected()) {
|
||||||
|
#if PICO_STDIO_USB_POST_CONNECT_WAIT_DELAY_MS != 0
|
||||||
|
sleep_ms(PICO_STDIO_USB_POST_CONNECT_WAIT_DELAY_MS);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sleep_ms(10);
|
||||||
|
} while (!time_reached(until));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool stdio_usb_connected(void) {
|
||||||
|
return tud_cdc_connected();
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
#include "pico/stdio_usb.h"
|
#include "pico/stdio_usb.h"
|
||||||
#warning stdio USB was configured, but is being disabled as TinyUSB is explicitly linked
|
#warning stdio USB was configured, but is being disabled as TinyUSB is explicitly linked
|
||||||
|
Loading…
Reference in New Issue
Block a user