Skip to content

Commit aa0e864

Browse files
committed
mbed_error_puts: Prime STDERR_FILENO before writing
Prime the console outside the critical section, improving the chances of nice initialisation.
1 parent f2a13a8 commit aa0e864

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

platform/mbed_board.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,28 @@ void mbed_error_vprintf(const char *format, va_list arg)
7474

7575
void mbed_error_puts(const char *str)
7676
{
77+
// Writing the string to the console in a critical section is
78+
// potentially beneficial - for example in UARTSerial it
79+
// forces the "unbuffered" mode that makes sure all characters
80+
// go out now. If we made the call not in a critical section,
81+
// it would go to the software buffer and we would be reliant
82+
// on platform.stdio-flush-at-exit forcing a fsync before
83+
// entering mbed_die().
84+
//
85+
// But this may be the very first write to the console, and hence
86+
// require it to be initialized - doing this in a critical
87+
// section could be problematic. So we prime it outside the
88+
// critical section with a zero-length write - this forces
89+
// the initialization.
90+
//
91+
// It's still possible that we were in a critical section
92+
// or interrupt on entry anyway (eg if this is an error coming
93+
// from inside RTX), so in other areas of the system we suppress
94+
// things like mutex creation asserts and RTX traps while
95+
// an error is in progress, so that console initialization
96+
// may work.
97+
write(STDERR_FILENO, str, 0);
98+
7799
core_util_critical_section_enter();
78100
#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES || MBED_CONF_PLATFORM_STDIO_CONVERT_TTY_NEWLINES
79101
char stdio_out_prev = '\0';

platform/mbed_interface.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,9 @@ MBED_NORETURN void mbed_die(void);
127127
/** Print out an error message. This is typically called when
128128
* handling a crash.
129129
*
130-
* @note Synchronization level: Interrupt safe
130+
* @note Synchronization level: Interrupt safe, as long as the
131+
* FileHandle::write of the stderr device is. See mbed_error_puts
132+
* for more information.
131133
* @note This uses an internal 128-byte buffer to format the string,
132134
* so the output may be truncated. If you need to write a potentially
133135
* long string, use mbed_error_puts.
@@ -145,7 +147,9 @@ void mbed_error_printf(const char *format, ...) MBED_PRINTF(1, 2);
145147
/** Print out an error message. Similar to mbed_error_printf
146148
* but uses a va_list.
147149
*
148-
* @note Synchronization level: Interrupt safe
150+
* @note Synchronization level: Interrupt safe, as long as the
151+
* FileHandle::write of the stderr device is. See mbed_error_puts
152+
* for more information.
149153
*
150154
* @param format C string that contains data stream to be printed.
151155
* @param arg Variable arguments list
@@ -160,7 +164,13 @@ void mbed_error_vprintf(const char *format, va_list arg) MBED_PRINTF(1, 0);
160164
* length. Unlike standard puts, but like standard fputs, this does not
161165
* append a '\n' character.
162166
*
163-
* @note Synchronization level: Interrupt safe
167+
* @note Synchronization level: Interrupt safe, as long as the
168+
* FileHandle::write of the stderr device is. The default
169+
* serial console is safe, either buffered or not. If the
170+
* console has not previously been initialized, an attempt
171+
* to use this from interrupt may during console initialization.
172+
* Special handling of `mbed_error` relaxes various system traps
173+
* to increase the chance of initialization working.
164174
*
165175
* @param str C string that contains data stream to be printed.
166176
*

0 commit comments

Comments
 (0)