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;
}