Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hook system debug messages #1613

Merged
merged 2 commits into from
Apr 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions Sming/system/OsMessageInterceptor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/****
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
* Created 2015 by Skurydin Alexey
* http://github.com/SmingHub/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
*
* OsMessageInterceptor.h
*
* author mikee47 <[email protected]> Feb 2019
*
****/

#include <OsMessageInterceptor.h>

extern void uart_debug_putc(char);

OsMessageInterceptor* OsMessageInterceptor::self;

void OsMessageInterceptor::putc(char c)
{
c = message.addChar(c);
if(c == '\n' && callback) {
callback(message);
message.clear();
}
}

void OsMessageInterceptor::begin(OsMessageCallback callback)
{
this->callback = callback;
message.clear();
self = this;
ets_install_putc1(static_putc);
system_set_os_print(true);
}

void OsMessageInterceptor::end()
{
ets_install_putc1(uart_debug_putc);
}
117 changes: 117 additions & 0 deletions Sming/system/include/LineBuffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/****
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
* Created 2015 by Skurydin Alexey
* http://github.com/SmingHub/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
*
* LineBuffer.h - support for buffering/editing a line of text
*
* author mikee47 <[email protected]> Feb 2019
*
****/

#ifndef _SYSTEM_INCLUDE_LINE_BUFFER_H_
#define _SYSTEM_INCLUDE_LINE_BUFFER_H_

#include <user_config.h>

/**
* @brief Class to enable buffering of a single line of text, with simple editing
* @note We define this as a template class for simplicity, no need for separate buffer memory management
*/
template <uint16_t BUFSIZE> class LineBuffer
{
public:
/**
* @brief Add a character to the buffer
* @retval char Character added to buffer, '\0' if ignored, '\n' if line is complete
*/
char addChar(char c);

/**
* @brief Clear contents of buffer
*/
void clear()
{
length = 0;
}

/**
* @brief Get the text, nul-terminated
*/
char* getBuffer()
{
return buffer;
}

/**
* @brief Get number of characters in the text line
*/
unsigned getLength() const
{
return length;
}

/**
* @brief Check for matching text at start of line, case-sensitive
* @param text
* @retval bool true if match found
*/
bool startsWith(const char* text) const;

/**
* @brief Check for matching text anywhere in line, case-sensitive
* @param text
* @retval bool true if match found
*/
bool contains(const char* text) const;

/**
* @brief Remove last character from buffer
* @retval bool true if character was removed, false if buffer is empty
*/
bool backspace();

private:
char buffer[BUFSIZE] = {'\0'}; ///< The text buffer
uint16_t length = 0; ///< Number of characters stored
};

template <uint16_t BUFSIZE> char LineBuffer<BUFSIZE>::addChar(char c)
{
if(c == '\n' || c == '\r') {
return '\n';
}

if(c >= 0x20 && c < 0x7f && length < (BUFSIZE - 1)) {
buffer[length++] = c;
buffer[length] = '\0';
return c;
}

return '\0';
}

template <uint16_t BUFSIZE> bool LineBuffer<BUFSIZE>::backspace()
{
if(length == 0) {
return false;
} else {
--length;
buffer[length] = '\0';
return true;
}
}

template <uint16_t BUFSIZE> bool LineBuffer<BUFSIZE>::startsWith(const char* text) const
{
auto len = strlen(text);
return memcmp(buffer, text, len) == 0;
}

template <uint16_t BUFSIZE> bool LineBuffer<BUFSIZE>::contains(const char* text) const
{
return strstr(buffer, text) != nullptr;
}

#endif /* _SYSTEM_INCLUDE_LINE_BUFFER_H_ */
102 changes: 102 additions & 0 deletions Sming/system/include/OsMessageInterceptor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/****
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
* Created 2015 by Skurydin Alexey
* http://github.com/SmingHub/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
*
* OsMessageInterceptor.h - * Support for intercepting OS debug output (calls to os_printf, etc.)
*
* author mikee47 <[email protected]> Feb 2019
*
* Provided to assist with tracking down the origin of error messages output by SDK.
* This is usually done in conjunction with the debugger or by performing a stack dump
* to establish the origin of the problem code.
*
* Example usage:

static OsMessageInterceptor osMessageInterceptor;

void handleOsMessage(OsMessage& msg)
{
debug_w("[OS] %s", msg.getBuffer());
if(msg.startsWith("E:M ")) {
// Handle memory error
} else if(msg.contains(" assert ")) {
// Handle 'assert' message
}
}

void init()
{
...

osMessageInterceptor.begin(handleOsMessage);

// Example of 'bad' system call, generates "E:M 0" message
os_malloc(0);

...
}

*
*
****/

#ifndef _SYSTEM_INCLUDE_OS_MESSAGE_INTERCEPTOR_H_
#define _SYSTEM_INCLUDE_OS_MESSAGE_INTERCEPTOR_H_

#include "LineBuffer.h"

/**
* @brief Fixed-size buffer for OS messages
*/
typedef LineBuffer<128> OsMessage;

/**
* @brief Callback to receive OS message line
* @param msg The message
* @note We don't use std::function because it produces a more elaborate stack trace without any real benefit
*/
typedef void (*OsMessageCallback)(OsMessage& message);

/**
* @brief Class to handle interception of OS messages
* @note Messages are output character-by-character so must be reassembled into lines
* before passing to callback function
*/
class OsMessageInterceptor
{
public:
~OsMessageInterceptor()
{
end();
}

/**
* @brief Enable message interception
* @param callback Function to receive messages
* @note Messages are suppressed from output during interception. If you wish to send them to
* the uart, etc. then do this in the callback.
*/
void begin(OsMessageCallback callback);

/**
* @brief Stop message interception and revert to output via uart driver
*/
void end();

protected:
void putc(char c);

static void static_putc(char c)
{
self->putc(c);
}

private:
OsMessage message;
OsMessageCallback callback = nullptr; ///< User-provided callback
static OsMessageInterceptor* self;
};

#endif /* _SYSTEM_INCLUDE_OS_MESSAGE_INTERCEPTOR_H_ */
2 changes: 1 addition & 1 deletion Sming/system/uart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,7 @@ void uart_set_pins(uart_t* uart, int tx, int rx)
}
}

static void uart_debug_putc(char c)
void uart_debug_putc(char c)
{
uart_t* uart = uart_get_uart(s_uart_debug_nr);
if(uart != nullptr) {
Expand Down
Loading