Hi,
I am developing for an ARM Cortex-M7 core (NXP iMIMXRT1062 chip), which is a Thumb only processor. I am using MCUXpressoIDE 11.1 which is based on Eclipse.
I have a problem returning from SVCall. When free running, it usually ends up at address 0xdeadbeee (0xdeadbeef with last bit removed), or can be caught in the HardFault_Handler. When I step through using a debugger (GDB) it appears to work correctly.
in excep.S
SVC_Handler: // This call follows the ARM Architecture Procedure Calling Standard (AAPCS) // which pushes the following onto the stack from the calling function. // {r0-r3}, r12, LR, PC, xPSR // The LR currently set is the EXC_RETURN value which will cause the stack to // be unwound and the registers set to the initial values. .syntax unified // stack contains r0, r1, r2, r3 which are used as function arguments // Check whether we are using PSP or MSP (Handler mode always uses MSP) TST LR, #4 // Test EXC_RETURN to see which stack is expected. ITE EQ MOVEQ r1, sp // MSP in use MRSNE r1, psp // PSP in use LDR r3, [r1, #0x18] // excavate pc from stack // No need to check Thumb state LDRH r0, [r3,#-2] // Yes: Load halfword and... BIC r0, r0, #0xFF00 // ...extract comment field STMFD sp!, {LR} // push LR onto stack before call BL SVC_Handler_C // Call main part of handler LDMIA sp!, {LR} // retrieve LR from stack // Put r0 (return value) into stack as return value from this function. stm sp, {r0} // Set PC to LR (which contains EXC_RETURN value), which will unwind the // stack and restore the registers BX LR .syntax divided.endfunc
in excep_handlers.h
/** @brief Enumeration of operations performed by SVC. * The operation IDs need to fit into a uint8_t. */typedef enum{ C4_SVC_Reserved, C4_SVC_PRINT, C4_SVC_ADD, C4_SVC_USER,}C4_SVC_Op_t;
in excep_handlers.c
void *SVC_Handler_C(uint8_t SVC_type, void **args){ switch (SVC_type) { case C4_SVC_PRINT: printf((char *)*args, (int) *(args+1)); break; case C4_SVC_ADD: return (void *)((int)*args + (int)*(args+1)); break; case C4_SVC_USER: break; default: { pointer expt_frm_ptr = 0; // Get PSP - should this test whether to get PSP or MSP asm volatile ("MRS %0, psp" : "=r" (expt_frm_ptr) ); expt_frm_dump(expt_frm_ptr); // C4_PRINT_ERR_STRING is safe here as the exception handler is already executing in privileged // state so does not need to use the exception call mechanism. C4_PRINT_ERR_STRING("Unhandled option in %s(%d)\n", __PRETTY_FUNCTION__, SVC_type); while(1) {} } } return NULL;}
It is called like this:
int a1 = 3;int a2 = 5;int res = 0;asm("MOV r0, %1\n\tMOV r1, %2\n\tSVC %3\n\tMOV %0, r0\n\t":"=r"(res): \ "r"(a1), "r"(a2), "I" (C4_SVC_ADD));
The value of LR is 0xFFFF_FFF1 which is the expectd value of EXC_RETURN
0xFFFF_FFF1
EXC_RETURN
What am I doing wrong in the return?
thanks
Dan
Hi tobermory,
thanks for your replies.
I am using NXP MCUXpresso, which is based on Eclipse, to debug. By step through the code, I mean that if I am debugging and am stopped just before the line
__asm__( "svc #0\n" );
If I use the "step over" button, then I get the fault expressed.
If I use the "step into" button, then I can step through the handler code line by line (either in C or in assembly language). In fact, I can use the "step return" button directly after entering the SVC_Handler and the code will run as expected.
Thanks also for your test. I had been assuming that since an exception could return to Handler mode (LR = 0xFFFF_FFF1) as well as to thread mode (0xFFFF_FFF9 or 0xFFFF_FFFD) that this permitted nested calls.
dan