command: Check for reentrant calls to sendf()

Allow sendf() to be called from irq and timer context - check for the
case where sendf() is called while already in sendf() and simply
discard those messages.  This makes it safe to use output() debugging
calls even in irq and timer context.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2017-01-13 12:10:00 -05:00
parent f335045273
commit 9a44a20a9d
2 changed files with 15 additions and 4 deletions

View File

@ -105,9 +105,7 @@ output("The value of %u is %s with size %u.", x, buf, buf_len);
``` ```
The output() function is similar in usage to printf() - it is intended The output() function is similar in usage to printf() - it is intended
to generate and format arbitrary messages for human consumption. It is to generate and format arbitrary messages for human consumption.
a wrapper around sendf() and as with sendf() it should not be called
from interrupts or timers.
Declaring constants Declaring constants
------------------- -------------------

View File

@ -114,11 +114,22 @@ error:
void void
_sendf(uint8_t parserid, ...) _sendf(uint8_t parserid, ...)
{ {
static uint8_t in_sendf;
irqstatus_t flag = irq_save();
if (in_sendf) {
// This sendf call was made from an irq handler while the main
// code was already in sendf - just drop this sendf request.
irq_restore(flag);
return;
}
in_sendf = 1;
irq_restore(flag);
const struct command_encoder *cp = &command_encoders[parserid]; const struct command_encoder *cp = &command_encoders[parserid];
uint8_t max_size = READP(cp->max_size); uint8_t max_size = READP(cp->max_size);
char *buf = console_get_output(max_size + MESSAGE_MIN); char *buf = console_get_output(max_size + MESSAGE_MIN);
if (!buf) if (!buf)
return; goto done;
char *p = &buf[MESSAGE_HEADER_SIZE]; char *p = &buf[MESSAGE_HEADER_SIZE];
if (max_size) { if (max_size) {
char *maxend = &p[max_size]; char *maxend = &p[max_size];
@ -182,6 +193,8 @@ _sendf(uint8_t parserid, ...)
*p++ = crc; *p++ = crc;
*p++ = MESSAGE_SYNC; *p++ = MESSAGE_SYNC;
console_push_output(msglen); console_push_output(msglen);
done:
in_sendf = 0;
return; return;
error: error:
shutdown("Message encode error"); shutdown("Message encode error");