How to nest svc, eg
void svcall_handler(){ if(smth_happened()){ asm volatile("svc #0"); } }
Thanks.
It works for synchronous exceptions(SVC) but wont work properly with asynchronous exceptions like PendSV because we cannot write directly to EPSR by MSR instruction. So if the processor interrupts on continuable instruction(like LDM/STM/PUSH/POP) or If/Then block it will lead to undefined behavior.
But there is another workaround: rather than restoring state manually we can delegate this work to processor using SVC instruction.
Our PendSV handler will be almost the same:
__attribute__((naked)) void ePendSV(){ asm volatile( // "push {r0,r4-r11, lr} \n" // not necessary, callee will save them // create new stack frame on the top of existing "mov r2, %0 \n" // PSR "movw r1, #:lower16:nested_pendsv_hendler \n" // PC "movt r1, #:upper16:nested_pendsv_hendler \n" "movw r0, #:lower16:pendsv_handler_return \n" // LR "movt r0, #:upper16:pendsv_handler_return \n" "push {r0, r1, r2} \n" // push {lr, pc, xPSR} "sub sp, #5*4 \n" // push {r0,r1,r2,r3,r12} - undefined values // return from exception to our handler "bx lr \n" : :"i"(xPSR_RESET_VALUE)); }
nested_pendsv_handler (just regular C/C++ function) will jump here after return:
extern "C" __attribute__((naked)) void pendsv_handler_return(){ asm volatile("svc #0"); }
and then:
extern "C" __attribute__((naked)) void eSVCall(){ asm volatile( // kill current stack frame. "add sp, #8*4 \n" // perform an EXC_RETURN - unstacking original state preserved by ePendSV earlier "bx lr \n" ); }
Priority of PendSV must be lower than SVC that PendSV will never preempt SVC otherwise it will lead to undefined behavior because of tail-chaining and late-arrival.
Thats all. Usage is quite simple too:
extern "C" nested_pendsv_hendler(){ // do some work if(must_i_reenter){ set_PendSV(); // do another work }else return; }
Why I need it? - I'm using it to build super simple stack-allocation-less preemptive asynchronous task scheduler http://www.embedded.com/design/prototyping-and-development/4025691/Build-a-Super-Simple-Tasker using modern c++11 features(templates, lambdas,...)