由点到面,各个点要各个击破:
(1)
/*
* See header file for description.
*/
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{
/* Simulate the stack frame as it would be created by a context switch
interrupt. */
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
pxTopOfStack--;
*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
return pxTopOfStack;
}
PC是啥?就是函数的地址。
嗯!!这里怎么没有SP?
那么SP是啥?就是堆栈指针,估计是Stack pointer的缩写吧。SP具体的变化情况,可以看这个文档http://blog.youkuaiyun.com/unsv29/article/details/78549303,就是临时变量等被压入栈。
那么上面这个pxPortInitialiseStack这个函数是啥?
就是在MDK仿真界面的最左面有个REgister,如下图:
至于太具体的,就有时间再说了。
( 2)
uint32_t *p1;
uint16_t *p2;
p1 = (uint32_t *) 1 + 1;
p2 = (uint32_t *) 1 + 1;
用来解释pxTopOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
(3)
关于数据内存地址
若:xTaskCreateStatic(vTaskLED1, "vTaskLED1", 512, NULL, 1, user1_puxStackBuffer, user1_pxTaskBuffer);
则执行完函数pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );后得到如下(为调试方便令static TCB_t *pxNewTCB;就是说加了个static):
上面介绍的是初始化newTask,就是执行prvInitialiseNewTask这个函数;
下面就是把newTask加入到readyList,就是执行prvAddNewTaskToReadyList这个函数。
这个函数里面第一句就是
/* Ensure interrupts don't access the task lists while the lists are being
updated. */
taskENTER_CRITICAL();
这个函数什么作用先不管他。
好吧,把整个函数内容都贴出来吧
taskENTER_CRITICAL();
{
uxCurrentNumberOfTasks++;
if( pxCurrentTCB == NULL ) {
pxCurrentTCB = pxNewTCB;
if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 ) {
prvInitialiseTaskLists();
}
} else {
if( xSchedulerRunning == pdFALSE ) {
if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority ) {
pxCurrentTCB = pxNewTCB;
}
}
}
uxTaskNumber++;
traceTASK_CREATE( pxNewTCB );
prvAddTaskToReadyList( pxNewTCB );
portSETUP_TCB( pxNewTCB );
}
taskEXIT_CRITICAL();
把注释等等都填上:
static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
{
/* Ensure interrupts don't access the task lists while the lists are being
updated. */
taskENTER_CRITICAL();
{
uxCurrentNumberOfTasks++;
if( pxCurrentTCB == NULL )
{
/* There are no other tasks, or all the other tasks are in
the suspended state - make this the current task. */
pxCurrentTCB = pxNewTCB;
if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
{
/* This is the first task to be created so do the preliminary
initialisation required. We will not recover if this call
fails, but we will report the failure. */
prvInitialiseTaskLists();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
/* If the scheduler is not already running, make this task the
current task if it is the highest priority task to be created
so far. */
if( xSchedulerRunning == pdFALSE )
{
if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
{
pxCurrentTCB = pxNewTCB;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
uxTaskNumber++;
traceTASK_CREATE( pxNewTCB );
prvAddTaskToReadyList( pxNewTCB );
portSETUP_TCB( pxNewTCB );
}
taskEXIT_CRITICAL();
if( xSchedulerRunning != pdFALSE )
{
/* If the created task is of a higher priority than the current task
then it should run now. */
if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )
{
taskYIELD_IF_USING_PREEMPTION();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}