This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

SVCall returning to 0xdeadbeee

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

What am I doing wrong in the return?

thanks

Dan

Parents Reply Children