Skip to content

Commit d7b04e7

Browse files
committed
bricks: implement mp_hal_stdout_tx_flush()
This allows waiting for stdout to be sent over the air before exiting the MicroPython runtime. This seems to help with (but not completely fix) issues like [1]. It is also a step towards standardizing the stdout buffer behavior as discussed in [2]. It only affects BLE hubs for now. [1]: pybricks/support#835 [2]: pybricks/support#305
1 parent 7933523 commit d7b04e7

File tree

10 files changed

+49
-1
lines changed

10 files changed

+49
-1
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
## [Unreleased]
66

7+
### Changed
8+
- Buffered stdout is flushed before ending user program.
9+
710
### Fixed
811
- Fixed SPIKE/MINDSTORMS hubs advertising after disconnect while user program
912
is still running ([support#849]).

bricks/_common/micropython.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,9 @@ void pbsys_main_run_program(pbsys_main_program_t *program) {
292292
}
293293
#endif // PYBRICKS_OPT_COMPILER
294294

295+
// Ensure all buffered output has been sent over the air.
296+
mp_hal_stdout_tx_flush();
297+
295298
// Clean up non-MicroPython resources used by the pybricks package.
296299
pb_package_pybricks_deinit();
297300

bricks/_common/mpconfigport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
#define MICROPY_PY_SYS_MODULES (0)
9393
#define MICROPY_PY_SYS_STDFILES (PYBRICKS_OPT_EXTRA_MOD)
9494
#define MICROPY_PY_SYS_STDIO_BUFFER (PYBRICKS_OPT_EXTRA_MOD)
95+
#define MICROPY_PY_SYS_STDIO_FLUSH (PYBRICKS_OPT_EXTRA_MOD)
9596
#define MICROPY_PY_URANDOM_EXTRA_FUNCS (PYBRICKS_OPT_EXTRA_MOD)
9697
#define MICROPY_PY_URANDOM_SEED_INIT_FUNC ({ extern uint32_t pbdrv_clock_get_us(void); pbdrv_clock_get_us(); })
9798
#define MICROPY_PY_UTIME_MP_HAL (0)

bricks/_common_stm32/mphalport.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
9797
}
9898
}
9999

100+
void mp_hal_stdout_tx_flush(void) {
101+
// currently not buffered
102+
}
103+
100104
#else // !PYBRICKS_HUB_DEBUG
101105

102106
uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
@@ -144,4 +148,10 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
144148
}
145149
}
146150

151+
void mp_hal_stdout_tx_flush(void) {
152+
while (!pbsys_bluetooth_tx_is_idle()) {
153+
MICROPY_EVENT_POLL_HOOK
154+
}
155+
}
156+
147157
#endif // PYBRICKS_HUB_DEBUG

bricks/ev3dev/ev3dev_mphal.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ void mp_hal_stdout_tx_str(const char *str) {
125125
mp_hal_stdout_tx_strn(str, strlen(str));
126126
}
127127

128+
void mp_hal_stdout_tx_flush(void) {
129+
// currently not buffered
130+
}
131+
128132
mp_uint_t mp_hal_ticks_ms(void) {
129133
return pbdrv_clock_get_ms();
130134
}

bricks/ev3rt/mphalport.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,7 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
8181
serial_wri_dat(EV3_SERIAL_BT, str, len);
8282
}
8383
}
84+
85+
void mp_hal_stdout_tx_flush(void) {
86+
// currently not buffered
87+
}

bricks/nxt/mphalport.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,7 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
9797
MICROPY_EVENT_POLL_HOOK;
9898
}
9999
}
100+
101+
void mp_hal_stdout_tx_flush(void) {
102+
// currently not buffered
103+
}

lib/pbio/include/pbsys/bluetooth.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ void pbsys_bluetooth_rx_flush(void);
3131
uint32_t pbsys_bluetooth_rx_get_available(void);
3232
pbio_error_t pbsys_bluetooth_rx(uint8_t *data, uint32_t *size);
3333
pbio_error_t pbsys_bluetooth_tx(const uint8_t *data, uint32_t *size);
34+
bool pbsys_bluetooth_tx_is_idle(void);
3435

3536
#else // PBSYS_CONFIG_BLUETOOTH
3637

@@ -45,6 +46,9 @@ static inline pbio_error_t pbsys_bluetooth_rx(uint8_t *data, uint32_t *size) {
4546
static inline pbio_error_t pbsys_bluetooth_tx(const uint8_t *data, uint32_t *size) {
4647
return PBIO_ERROR_NOT_SUPPORTED;
4748
}
49+
static inline bool pbsys_bluetooth_tx_is_idle(void) {
50+
return false;
51+
}
4852

4953
#endif // PBSYS_CONFIG_BLUETOOTH
5054

lib/pbio/sys/bluetooth.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,21 @@ pbio_error_t pbsys_bluetooth_tx(const uint8_t *data, uint32_t *size) {
149149
return PBIO_SUCCESS;
150150
}
151151

152+
/**
153+
* Tests if the Tx queue is empty and all data has been sent over the air.
154+
*
155+
* If there is no connection, this will always return @c true.
156+
*
157+
* @returns @c true if the condition is met, otherwise @c false.
158+
*/
159+
bool pbsys_bluetooth_tx_is_idle(void) {
160+
if (!pbdrv_bluetooth_is_connected(PBDRV_BLUETOOTH_CONNECTION_UART)) {
161+
return true;
162+
}
163+
164+
return !send_busy && lwrb_get_full(&uart_tx_ring) == 0;
165+
}
166+
152167
static pbio_pybricks_error_t handle_receive(pbdrv_bluetooth_connection_t connection, const uint8_t *data, uint32_t size) {
153168
if (connection == PBDRV_BLUETOOTH_CONNECTION_PYBRICKS) {
154169
return pbsys_command(data, size);

micropython

0 commit comments

Comments
 (0)