Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
10 years, 8 months ago.
Best way to override error(...) for production firmware?
Hey guys. I'm working on a project will will hopefully make it's way into production at some point, but I'm hitting a roadblock with trying to override the built in error(...) definition. Since this will be a production device, spitting stuff out the UART is obviously not going to work (and will probably screw things up since I'm re-using the UART pins for other things), so I want to provide a function that will save the error string to EEPROM and reset the device. Then, a desktop tool will read that error string and phone it home later on. I've been able to override mbed_die() since it's a weak symbol, so I can reset the device, I just can't save the error first.
1 Answer
10 years, 8 months ago.
You can of course just change the mbed-src lib. Or make sure error is never called.
But error is:
#define error(...) (fprintf(stderr, __VA_ARGS__), exit(1))
So you can 'simply' redirect stderr to another location. You can make a class with the Stream class as parent, and you need to give it a name in its argument field, then you can use reopen to redirect the stderr to this class. Random lib which implements this: http://mbed.org/users/chris/code/C12832/file/7de323fa46fe/TextDisplay.cpp.
Either you can make that class simply throw it all away, or write it for example to your EEPROM. Alternatively you can also make a FATFileSystem and redirect the stream to a file on there. But that has more overhead (you can put most of it just in your flash memory, but still), and I think also harder to implement.
Thanks, but I'd like to avoid modifying the mbed-src library since that makes updating it more difficult. And the mbed-rtos library already makes calls to error(...), so I have no choice but to try to use it.
I tried creating an ErrorStream class to redirect stderr, but it doesn't appear to do anything but lock up. I've attached the code:
ErrorStream.h"
#ifndef ERROR_STREAM_H #define ERROR_STREAM_H #include "mbed.h" /** ErrorStream class. * Used to redirect error text to the EEPROM. */ class ErrorStream : public Stream { public: /** Create a new ErrorStream object, and redirect stderr to it */ ErrorStream(); protected: virtual int _getc(); virtual int _putc(int value); }; #endif
ErrorStream.cpp
#include "ErrorStream.h" ErrorStream::ErrorStream() : Stream("error") { //Try to redirect stderr to us if (freopen("/error", "w", stderr) == NULL) { //Failed, should not happen mbed_die(); } //Set up the stream buffer setvbuf(stderr, NULL, _IONBF, 1); } int ErrorStream::_getc() { return -1; } int ErrorStream::_putc(int value) { /*if (value == '\n') { _column = 0; _row++; if(_row >= rows()) { _row = 0; } } else { character(_column, _row, value); _column++; if(_column >= columns()) { _column = 0; _row++; if(_row >= rows()) { _row = 0; } } }*/ printf("Got %i\n", value); return value; }
Heh one of those small errors that can irritate you for a long time. Had this one in a similar case a bit ago, still didn't had it immediatly.
The issue is printf: ErrorStream inherits from Stream, which has a printf. So there is ambiguity: Should it take the global printf, or the printf belonging to ErrorStream's parent, and it picks that one (so: this->printf). Which then shows up at _putc. Which call this->printf, etc.
Replace it with std::printf and it works fine :).
For your homework, find out what the error message was :P
Got 65 Got 97 Got 97 Got 97 Got 97 Got 104 Got 32 Got 116 Got 104 Got 101 Got 121 Got 32 Got 97 Got 114 Got 101 Got 32 Got 99 Got 111 Got 109 Got 105 Got 110 Got 103 Got 13 Got 10
*face palm* of course... It works now, thanks!
P.S. It says "Aaaaah they are coming" :P
posted by 28 Mar 2014Might have spoken too soon, I just realized DEVICE_STDIO_MESSAGES is disabled on the LPC11U35 (for good reason, there's no interface chip to redirect it to the host), so fprintf() will never be called making the stderr redirect pointless. I'm going to start a discussion regarding this, clearly the best plan of attack is to make error() weakly linked like mbed_die().
posted by 28 Mar 2014Well you didn't tell me that you used that one :P.
Can't you simply enable that from your program? Then fprintf will be called again, and since it is redirected anyway it doesn't matter that it has no UART. Not 100% sure it works that simply though :).
I do agree it would be nice to have it a weak function.
posted by 28 Mar 2014