Hi all,
my presentation is related to Cortex-M exception handling. I have found the method to extract exception information form an exception stack frame. Usually it can be done by getting the stack top by using the inline assembler as described in the post error: Hard Fault Handler. My presentation does not use the inline assembler. It will use the calling and receiving conventions of a function.
This procedure will be only valid under assumption the stack pointer is not switched. It means SPSEL bit of CONTROL register is "0".
As you know, arguments for a function will be passed via registers and the stack. In almost all case, the first 4 arguments will be passed via registers (i.e. r0, r1, r2 and r3) and as for after the 5th arguments will be passed via the stack. Therefore, for an exception handler declared as
void exception_handler(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11) { /* the body of the handler */ }
the stack contents just before calling the exception handler would be set from a4 to a11. That is,
a0 ... register r0 value a1 ... register r1 value a2 ... register r2 value a3 ... register r3 value a4 ... stacked r0 (i.e. the same as a0) a5 ... stacked r1 (i.e. the same as a1) a6 ... stacked r2 (i.e. the same as a2) a7 ... stacked r3 (i.e. the same as a3) a8 ... stacked r12 a9 ... stacked lr a10 .. stacked pc a11 .. stacked psr
a0 ... register r0 value
a1 ... register r1 value
a2 ... register r2 value
a3 ... register r3 value
a4 ... stacked r0 (i.e. the same as a0)
a5 ... stacked r1 (i.e. the same as a1)
a6 ... stacked r2 (i.e. the same as a2)
a7 ... stacked r3 (i.e. the same as a3)
a8 ... stacked r12
a9 ... stacked lr
a10 .. stacked pc
a11 .. stacked psr
If you want to get the SVCall parameter,
scv_param = *(char *)(a10 - 2);
would be able to get it in the exception handler.
If you want to change the return address,
*(short *)(&a10) = NEW_RETURN_ADDRESS;
would be realized it.
Although I have not seen it, for the compiler which had not adopted the register argument passing, it would be the a0 would be the stacked r0, the a1 would be the stacked r1, and so on.
How about my idea. Or someone had already mentioned it.
Best regards,
Yasuhiko Koumoto.
Hello Liviu,
thank you, you are right. My presentation is valid only when CONTROL.SPSEL=0, isn't it?
In Cortex-M0 case, CONTROL.SPSEL is fixed to 0. In Cortex-M0+ case, modification capability is a option but some implementation (such as Kinetis L series) fix it to 0.
Therefore I think my presentation would not be so wrong.
If you configure a separate stack (PSP) for thread mode, when the exception occurs in thread mode, the core will save a4-a11 on PSP, then enter the handler, and switch to MSP. As any C function, your function will access a4 - a11 using SP, which in handler mode is MSP, while in fact the values were stored on PSP.
Hello Livui.
can you show the case which can not be functional? I would like to know it and correct my presentation.
Although your solution may be functional for certain cases, I doubt that without the assembly logic that you already described in the other post, you can correctly identify the exception.
The recommended implementation (please see Joseph Yiu's book The Definitive Guide to ARM Cortex-M3 and Cortex-M4 Processors) is to use an assembly function to determine if you are running on MSP or PSP and then call a C function, passing a pointer to a frame and several other arguments. You should also consider portability issues.
An example of a production code using this implementation is available, for example, in GNU ARM Eclipse Plug-ins / Second Edition / [06ce04] /ilg.gnuarmeclipse.templates.core/templates/common/system/src/cor…
This code is used in the projects generated by the templates included in GNU ARM Eclipse plug-ins.