Skip to content

pendsv_nlr_jump hard faults #315

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

Closed
iabdalkader opened this issue Feb 22, 2014 · 10 comments
Closed

pendsv_nlr_jump hard faults #315

iabdalkader opened this issue Feb 22, 2014 · 10 comments
Labels
bug ports Relates to multiple ports, or a new/proposed port

Comments

@iabdalkader
Copy link
Contributor

pressing Ctrl-C hard faults... example code:

While (True):
  pass

gdb backtrace

HardFault_Handler () at stm32fxxx_it.c:84
84    }
(gdb) backtrace 
#0  HardFault_Handler () at stm32fxxx_it.c:84
#1  <signal handler called>
#2  0x2001fcd0 in ?? ()
#3  0x080410f8 in PendSV_Handler () at stm32fxxx_it.c:155
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

Sometimes it takes more than one try, but calling pendsv_nlr_jump from USB IRQ handler always faults.

@dpgeorge
Copy link
Member

I have not had any issues with this. I just tried 20 times the infinite loop, and ctrl-C breaks out cleanly every time. Are you compiling with debugging (-g) enabled?

@iabdalkader
Copy link
Contributor Author

I'm compiling with BOARD=STM32F4DISC DEBUG=1 let me try this again

@dpgeorge
Copy link
Member

The pendsv handler is specific to the way the stack is organised. With DEBUG=1 it's probably different...

@iabdalkader
Copy link
Contributor Author

I will test it again with and without debugging, does the crystal freq has anything to do with it ? and do I need something specific enabled in mpconfigboard ?

@dpgeorge
Copy link
Member

I have verified that it hard faults with DEBUG=1. It's because the stack layout changes. I'll see if I can fix it.

It should just work if DEBUG is not defined. No other configuration options are needed, and xtal freq is irrelevant.

@iabdalkader
Copy link
Contributor Author

yup, it definitely faults with debugging, I've tested it twice on STM32Discovery board and my own board

dpgeorge added a commit that referenced this issue Feb 23, 2014
Stack layout is different when -g used, so need to handle the pendsv
jump differently.  Addresses Issue #315.
@dpgeorge
Copy link
Member

Okay, it's now working (for me) with DEBUG=1, and without DEBUG set.

@iabdalkader
Copy link
Contributor Author

awesome thanks :) .. while we're at it, I noticed this:

// uncaught exception
// FIXME it could be that an interrupt happens just before we disable it here
usb_vcp_set_interrupt_char(VCP_CHAR_NONE); // disable interrupt
mp_obj_print_exception((mp_obj_t)nlr.ret_val);

I could be missing something here, but why not clear the interrupt char before raising the interrupt ?

pendsv_nlr_jump(mp_const_vcp_interrupt);
interrupt_char = VCP_CHAR_NONE;

@dpgeorge
Copy link
Member

I could be missing something here, but why not clear the interrupt char before raising the interrupt ?

This is not the case that needs to be fixed. The case is: a non-CTRL-C exception occurs and control goes into the exception handler. Then, just before disabling CTRL-C, the user presses CTRL-C and VCP raises that exception. This exception is not caught and will hard fault.

@iabdalkader
Copy link
Contributor Author

iabdalkader commented Jan 23, 2020

Hi, sorry for digging up this old issue, but I recently tried to debug a firmware built with -O0 -g and noticed the pendsv IRQ is not working as expected, it doesn't return to nlr_jump on exception return when PENDSV_DEBUG is defined. For example the following code sets the pendsv_object and raises PendSV IRQ like so:

MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
pendsv_object = o;
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;

In gdb I set two breakpoints on PendSV_Handler and nlr_jump, but nlr_jump breakpoint is never hit:

(gdb) break PendSV_Handler 
Breakpoint 1 at 0x81166b8: file pendsv.c, line 129.
(gdb) break nlr_jump
Breakpoint 2 at 0x8103ac4: file ../../py/nlrthumb.c, line 90.
(gdb) c
Continuing.

Breakpoint 1, PendSV_Handler () at pendsv.c:129
129	    __asm volatile (
(gdb) c
Continuing.

I debugged a few boards with different GCC versions, and it seems the stack frame doesn't change when -g is used (so pc gets written at the wrong offset when PENDSV_DEBUG is defined). I tested boards with H7, F7 and F4 using GCC 7.3 and GCC 4.8 (gcc 4.8 was used around the time this issue was reported back in 2014) as you can see r12 for example is always stacked at the expected offset (sp[4]) as described in the exception stack frame:

Stack frame on H743, gcc 7.3, -O0 -g:

Breakpoint 1, PendSV_Handler () at pendsv.c:129
129	    __asm volatile (
(gdb) x /8x $sp
0x3003fa10:	0x0000168e	0x00000000	0x00000008	0x00000258
0x3003fa20:	0x30003aab	0x081121ad	0x081121a8	0x81000000
(gdb) p /x $r12
$1 = 0x30003aab

Stack frame on F765, gcc 7.3, -O0 -g:

Breakpoint 1, PendSV_Handler () at pendsv.c:129
129	    __asm volatile (
(gdb) x /8x $sp
0x2001fa58:	0x00000440	0x00000000	0x000001a9	0x00000258
0x2001fa68:	0x20011881	0x0810d805	0x0810d800	0x81000000
(gdb) p /x $r12
$5 = 0x20011881

Stack frame on H743,gcc 4.8, -O0 -g:

Breakpoint 1, PendSV_Handler () at pendsv.c:129
129	    __asm volatile (
(gdb) x /8x $sp
0x3003fa08:	0x00000f8b	0x00000000	0x00000142	0x00000258
0x3003fa18:	0x0000002c	0x081108c9	0x081108c4	0x81000000
(gdb) p /x $r12
$1 = 0x2c

Stack frame on F765, gcc 4.8, -O0 -g:

Breakpoint 1, PendSV_Handler () at pendsv.c:129
129	    __asm volatile (
(gdb) x /8x $sp
0x2001fa50:	0x000029ee	0x00000000	0x00000046	0x00000258
0x2001fa60:	0x0000002c	0x0810bf69	0x0810bf64	0x81000000
(gdb) p /x $r12
$1 = 0x2c

Stack frame on F427,gcc 4.8, -O0 -g:

Breakpoint 1, PendSV_Handler () at pendsv.c:129
129	    __asm volatile (
(gdb) x /8x $sp
0x1000fa50:	0x00000432	0x00000000	0x00000188	0x00000258
0x1000fa60:	0x00000007	0x08093899	0x08093894	0x81000000
(gdb) p /x $r12
$1 = 0x7

The only logical conclusion here is that the initial assumption (that the stack frame changes with -g) was wrong, which makes sense to me because the exception stacking is done by the processor (the compiler doesn't have control over this I think). Anyway, I removed PENDSV_DEBUG from the Makefile and things seem to be working as excepted. Here running the same test without PENDSV_DEBUG defined (i.e. pc written to [sp, 24]) and it breaks on nlr_jump:

(gdb) break PendSV_Handler 
Breakpoint 1 at 0x81166b8: file pendsv.c, line 129.
(gdb) break nlr_jump
Breakpoint 2 at 0x8103ac4: file ../../py/nlrthumb.c, line 90.
(gdb) c
Continuing.

Breakpoint 1, PendSV_Handler () at pendsv.c:129
129	    __asm volatile (
(gdb) c
Continuing.

Breakpoint 2, nlr_jump (val=0x3000a360) at ../../py/nlrthumb.c:90
90	NORETURN void nlr_jump(void *val) {

iabdalkader added a commit to openmv/micropython that referenced this issue Jan 23, 2020
* PENDSV_DEBUG causes pc to be stacked at the wrong offset.
* See micropython#315 (comment)
iabdalkader added a commit to openmv/openmv that referenced this issue Jan 23, 2020
* PENDSV_DEBUG causes pc to be stacked at the wrong offset.
* See micropython/micropython#315 (comment)
andrewleech pushed a commit to andrewleech/openmv that referenced this issue Sep 21, 2020
* PENDSV_DEBUG causes pc to be stacked at the wrong offset.
* See micropython/micropython#315 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug ports Relates to multiple ports, or a new/proposed port
Projects
None yet
Development

No branches or pull requests

3 participants