asm volatile()

in GCC/MSP430FR5969/port.c [76:222]


    asm volatile (  "pushm.a #12, r15                 \n\t"  \
                    "movx.w &usCriticalNesting, r14   \n\t"  \
                    "pushm.a #1, r14                  \n\t"  \
                    "movx.a &pxCurrentTCB, r12        \n\t"  \
                    "movx.a sp, 0(r12)                \n\t"  \
                );
#else
#define portSAVE_CONTEXT()                                   \
    asm volatile (  "pushm.w #12, r15                 \n\t"  \
                    "mov.w &usCriticalNesting, r14    \n\t"  \
                    "push.w r14                       \n\t"  \
                    "mov.w &pxCurrentTCB, r12         \n\t"  \
                    "mov.w sp, 0(r12)                 \r\t"  \
                );
#endif

/*
 * Macro to restore a task context from the task stack.  This is effectively
 * the reverse of portSAVE_CONTEXT().  First the stack pointer value is
 * loaded from the task control block.  Next the value for usCriticalNesting
 * used by the task is retrieved from the stack - followed by the value of all
 * the general purpose msp430 registers.
 *
 */
#ifdef __LARGE_DATA_MODEL__
#define portRESTORE_CONTEXT()                                \
    asm volatile (  "movx.a &pxCurrentTCB, r12        \n\t"  \
                    "movx.a @r12, sp                  \n\t"  \
                    "popm.a #1, r15                   \n\t"  \
                    "movx.w r15, &usCriticalNesting   \n\t"  \
                    "popm.a #12, r15                  \n\t"  \
                    "nop                              \n\t"  \
                    "pop.w sr                         \n\t"  \
                    "nop                              \n\t"  \
                    "reta                             \n\t"  \
                );
#else
#define portRESTORE_CONTEXT()                                \
    asm volatile (  "mov.w  &pxCurrentTCB, r12       \n\t"   \
                    "mov.w @r12, sp                  \n\t"   \
                    "pop.w r15                       \n\t"   \
                    "mov.w r15, &usCriticalNesting   \n\t"   \
                    "popm.w #12, r15                 \n\t"   \
                    "nop                             \n\t"   \
                    "pop.w sr                        \n\t"   \
                    "nop                             \n\t"   \
                    "ret                             \n\t"   \
                );
#endif
/*-----------------------------------------------------------*/

/*
 * Sets up the periodic ISR used for the RTOS tick.  This uses timer 0, but
 * could have alternatively used the watchdog timer or timer 1.
 */
static void prvSetupTimerInterrupt( void );
/*-----------------------------------------------------------*/

/*
 * Initialise the stack of a task to look exactly as if a call to
 * portSAVE_CONTEXT had been called.
 *
 * See the header file portable.h.
 */

StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{
    uint16_t *pusTopOfStack;
    uint32_t *pulTopOfStack, ulTemp;

    /*
        Place a few bytes of known values on the bottom of the stack.
        This is just useful for debugging and can be included if required.

        *pxTopOfStack = ( StackType_t ) 0x1111;
        pxTopOfStack--;
        *pxTopOfStack = ( StackType_t ) 0x2222;
        pxTopOfStack--;
        *pxTopOfStack = ( StackType_t ) 0x3333;
        pxTopOfStack--;
    */

    /* Data types are need either 16 bits or 32 bits depending on the data
    and code model used. */
    if( sizeof( pxCode ) == sizeof( uint16_t ) )
    {
        pusTopOfStack = ( uint16_t * ) pxTopOfStack;
        ulTemp = ( uint32_t ) pxCode;
        *pusTopOfStack = ( uint16_t ) ulTemp;
    }
    else
    {
        /* Make room for a 20 bit value stored as a 32 bit value. */
        pusTopOfStack = ( uint16_t * ) pxTopOfStack;
        pusTopOfStack--;
        pulTopOfStack = ( uint32_t * ) pusTopOfStack;
        *pulTopOfStack = ( uint32_t ) pxCode;
    }

    pusTopOfStack--;
    *pusTopOfStack = portFLAGS_INT_ENABLED;
    pusTopOfStack -= ( sizeof( StackType_t ) / 2 );

    /* From here on the size of stacked items depends on the memory model. */
    pxTopOfStack = ( StackType_t * ) pusTopOfStack;

    /* Next the general purpose registers. */
    #ifdef PRELOAD_REGISTER_VALUES
        *pxTopOfStack = ( StackType_t ) 0xffff;
        pxTopOfStack--;
        *pxTopOfStack = ( StackType_t ) 0xeeee;
        pxTopOfStack--;
        *pxTopOfStack = ( StackType_t ) 0xdddd;
        pxTopOfStack--;
        *pxTopOfStack = ( StackType_t ) pvParameters;
        pxTopOfStack--;
        *pxTopOfStack = ( StackType_t ) 0xbbbb;
        pxTopOfStack--;
        *pxTopOfStack = ( StackType_t ) 0xaaaa;
        pxTopOfStack--;
        *pxTopOfStack = ( StackType_t ) 0x9999;
        pxTopOfStack--;
        *pxTopOfStack = ( StackType_t ) 0x8888;
        pxTopOfStack--;
        *pxTopOfStack = ( StackType_t ) 0x7777;
        pxTopOfStack--;
        *pxTopOfStack = ( StackType_t ) 0x6666;
        pxTopOfStack--;
        *pxTopOfStack = ( StackType_t ) 0x5555;
        pxTopOfStack--;
        *pxTopOfStack = ( StackType_t ) 0x4444;
        pxTopOfStack--;
    #else
        pxTopOfStack -= 3;
        *pxTopOfStack = ( StackType_t ) pvParameters;
        pxTopOfStack -= 9;
    #endif

    /* A variable is used to keep track of the critical section nesting.
    This variable has to be stored as part of the task context and is
    initially set to zero. */
    *pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;

    /* Return a pointer to the top of the stack we have generated so this can
    be stored in the task control block for the task. */
    return pxTopOfStack;
}