Topics

__ASSERT - transfer to error handler


kristoffer.skoien@...
 

Current implementation:

The __ASSERT macro is extensively used in the Zephyr code base and in application code for debugging during development.

In case of an ASSERT, the code jumps to __ASSERT_POST which spins the given thread in a while(1).

 

Issue:

During development and debugging, simply looping the thread will mask that the ASSERT has triggered. The only feedback the user gets of an assert is a printout.

This can be missed if e.g.:

- The RTT or Serial debug interface is down or unused

- There is too much logging so that the “ASSERTION FAIL” can be missed

 

Proposed solution:

In __ASSERT_POST provide a function call that will end up a user definable error handler. E.g. _SysFatalErrorHandler()

 

This will let the developer set given SOC pins in case of an ASSERT, ask for a specific LED pattern to be set or print further debug messages.

 

Feedback is appreciated.

 

Kind regards

Kristoffer


Paul Sokolovsky
 

Hello Kristoffer,

As a quick reply, definitely ack on the problem statement. I can say
more, I'm patiently waiting for a paradise times when on CPU exception,
assert, etc., we'll be ending up in debugger, point to the instruction
where the problem happened (or it can be seen in backtrace). (To be
exact, I'm talking about running in QEMU first of all, I actually
don't remember how that works on real hw.)

As for specific implementation, perhaps more knowledgeable people can
comment. I would just point that an obvious override point is
__ASSERT_POST macro itself. I.e. instead of defining it
unconditionally, we can have #ifdef around it, and let a user override
it before inclusion of Zephyr headers. That's the simplest, but
perhaps not the most scalable solution.


On Fri, 09 Nov 2018 01:39:34 -0800
kristoffer.skoien@... wrote:

Current implementation:

The __ASSERT macro is extensively used in the Zephyr code base and in
application code for debugging during development.

In case of an ASSERT, the code jumps to __ASSERT_POST which spins the
given thread in a while(1).

 

Issue:

During development and debugging, simply looping the thread will mask
that the ASSERT has triggered. The only feedback the user gets of an
assert is a printout.

This can be missed if e.g.:

- The RTT or Serial debug interface is down or unused

- There is too much logging so that the “ASSERTION FAIL” can be missed

 

Proposed solution:

In __ASSERT_POST provide a function call that will end up a user
definable error handler. E.g. _SysFatalErrorHandler()

 

This will let the developer set given SOC pins in case of an ASSERT,
ask for a specific LED pattern to be set or print further debug
messages.

 

Feedback is appreciated.

 

Kind regards

Kristoffer




--
Best Regards,
Paul

Linaro.org | Open source software for ARM SoCs
Follow Linaro: http://www.facebook.com/pages/Linaro
http://twitter.com/#!/linaroorg - http://www.linaro.org/linaro-blog


kristoffer.skoien@...
 

Thanks for your reply Paul.

Perhaps something simliar to this:

#if defined(CONFIG_ARCH_POSIX)
extern void posix_exit(int exit_code);
#define __ASSERT_POST posix_exit(1)
#elif defined(CONFIG_ASSERT_ERR_HANDLER)
#define __ASSERT_POST _SysFatalErrorHandler(?,?)
#else
#define __ASSERT_POST             \
for (;;) {                \
/* spin thread */ \
}
#endif


Skøien, Kristoffer <Kristoffer.Skoien@...>
 

Current implementation:

The __ASSERT macro is extensively used in the Zephyr codebase and in application code for debugging during development.

In case of an ASSERT, the code jumps to __ASSERT_POST which spins the given thread in a while(1).

 

Issue:

During development and debugging, simply looping the thread will mask that the ASSERT has triggered. The only feedback the user gets of an assert is a printout.

This can be missed if e.g.:

- The RTT or Serial debug interface is down or unused

- There is too much logging so that the “ASSERTION FAIL” can be missed

 

Proposed solution:

In __ASSERT_POST provide a function call that will end up a user definable error handler. E.g. _SysFatalErrorHandler

 

This will let the developer set given SOC pins in case of an ASSERT, ask for a specific LED pattern to be set or print further debug messages.

 

Feedback is appreciated.

 

Kind regards

Kristoffer


Boie, Andrew P
 

It's better to call k_oops() or k_panic() than _SysFatalErrorHandler() directly. You will actually get useful information about where the error occurred, instead of having to pass in a NULL exception stack frame.

 

Andrew

 

From: devel@... [mailto:devel@...] On Behalf Of Skøien, Kristoffer
Sent: Friday, November 9, 2018 12:11 AM
To: devel@...
Subject: [Zephyr-devel] __ASSERT - transfer to error handler

 

Current implementation:

The __ASSERT macro is extensively used in the Zephyr codebase and in application code for debugging during development.

In case of an ASSERT, the code jumps to __ASSERT_POST which spins the given thread in a while(1).

 

Issue:

During development and debugging, simply looping the thread will mask that the ASSERT has triggered. The only feedback the user gets of an assert is a printout.

This can be missed if e.g.:

- The RTT or Serial debug interface is down or unused

- There is too much logging so that the “ASSERTION FAIL” can be missed

 

Proposed solution:

In __ASSERT_POST provide a function call that will end up a user definable error handler. E.g. _SysFatalErrorHandler

 

This will let the developer set given SOC pins in case of an ASSERT, ask for a specific LED pattern to be set or print further debug messages.

 

Feedback is appreciated.

 

Kind regards

Kristoffer

 


Boie, Andrew P
 

I'm patiently waiting for a paradise times when on CPU exception, assert, etc.,
we'll be ending up in debugger, point to the instruction where the problem
happened (or it can be seen in backtrace).
We do dump this info to the console on a fatal CPU exception. On x86 there's even a crude stack trace.
But it would be nice, if running some application under GDB, for the exception to simply break the debugger at the offending instruction rather than go through Zephyr's exception handling path.

I'm not sure how this could work, perhaps have the Zephyr exception handler set up the stack/registers to the original context and issue a debug exception? Or would this involve some kind of Zephyr-aware extension to GDB? The problem is always that the stack layout for a CPU exception is different than a function call, and might not even be on the same stack, so you can't easily unwind through when the exception happened to the original faulting context.

Andrew