📄 tasks.s43
字号:
// 428
// 429 /*
// 430 * When a task is created, the stack of the task is filled with a known value.
// 431 * This function determines the 'high water mark' of the task stack by
// 432 * determining how much of the stack remains at the original preset value.
// 433 */
// 434 #if ( configUSE_TRACE_FACILITY == 1 )
// 435
// 436 unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR *pucStackByte );
// 437
// 438 #endif
// 439
// 440 /*lint +e956 */
// 441
// 442
// 443
// 444
// 445
// 446 /*-----------------------------------------------------------
// 447 * TASK CREATION API documented in task.h
// 448 *----------------------------------------------------------*/
// 449
RSEG CODE:CODE:REORDER:NOROOT(1)
// 450 signed portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode, const signed portCHAR * const pcName, unsigned portSHORT usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask )
xTaskCreate:
CFI Block cfiBlock0 Using cfiCommon0
CFI Function xTaskCreate
// 451 {
FUNCALL xTaskCreate, prvAllocateTCBAndStack
LOCFRAME CSTACK, 20, STACK
FUNCALL xTaskCreate, prvInitialiseTCBVariables
LOCFRAME CSTACK, 24, STACK
FUNCALL xTaskCreate, pxPortInitialiseStack
LOCFRAME CSTACK, 26, STACK
FUNCALL xTaskCreate, prvInitialiseTaskLists
LOCFRAME CSTACK, 20, STACK
FUNCALL xTaskCreate, vListInsertEnd
LOCFRAME CSTACK, 20, STACK
FUNCALL xTaskCreate, vPortYield
LOCFRAME CSTACK, 20, STACK
PUSH.W R10
CFI R10 Frame(CFA, -4)
CFI CFA SP+4
PUSH.W R11
CFI R11 Frame(CFA, -6)
CFI CFA SP+6
PUSH.W R8
CFI R8 Frame(CFA, -8)
CFI CFA SP+8
PUSH.W R9
CFI R9 Frame(CFA, -10)
CFI CFA SP+10
PUSH.W R6
CFI R6 Frame(CFA, -12)
CFI CFA SP+12
PUSH.W R7
CFI R7 Frame(CFA, -14)
CFI CFA SP+14
PUSH.W R4
CFI R4 Frame(CFA, -16)
CFI CFA SP+16
PUSH.W R5
CFI R5 Frame(CFA, -18)
CFI CFA SP+18
PUSH.W R12
CFI CFA SP+20
MOV.W R14, R10
MOV.W 0x14(SP), R11
MOV.W 0x16(SP), R8
MOV.W 0x18(SP), R9
MOV.W 0x1a(SP), R6
// 452 signed portBASE_TYPE xReturn;
// 453 tskTCB * pxNewTCB;
// 454 static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberate - this is guarded before use. */
// 455
// 456 /* Allocate the memory required by the TCB and stack for the new task.
// 457 checking that the allocation was successful. */
// 458 pxNewTCB = prvAllocateTCBAndStack( usStackDepth );
MOV.W R11, R12
CALL #prvAllocateTCBAndStack
MOV.W R12, R4
// 459
// 460 if( pxNewTCB != NULL )
CMP.W #0x0, R4
JEQ ??xTaskCreate_0
// 461 {
// 462 portSTACK_TYPE *pxTopOfStack;
// 463
// 464 /* Setup the newly allocated TCB with the initial state of the task. */
// 465 prvInitialiseTCBVariables( pxNewTCB, usStackDepth, pcName, uxPriority );
PUSH.W R9
CFI CFA SP+22
PUSH.W R10
CFI CFA SP+24
MOV.W R11, R14
MOV.W R4, R12
CALL #prvInitialiseTCBVariables
// 466
// 467 /* Calculate the top of stack address. This depends on whether the
// 468 stack grows from high memory to low (as per the 80x86) or visa versa.
// 469 portSTACK_GROWTH is used to make the result positive or negative as
// 470 required by the port. */
// 471 #if portSTACK_GROWTH < 0
// 472 {
// 473 pxTopOfStack = pxNewTCB->pxStack + ( pxNewTCB->usStackDepth - 1 );
MOV.W 0x18(R4), R15
MOV.W 0x24(R4), R14
RLA.W R14
ADD.W R14, R15
ADD.W #0xfffe, R15
MOV.W R15, R5
// 474 }
// 475 #else
// 476 {
// 477 pxTopOfStack = pxNewTCB->pxStack;
// 478 }
// 479 #endif
// 480
// 481 /* Initialize the TCB stack to look as if the task was already running,
// 482 but had been interrupted by the scheduler. The return address is set
// 483 to the start of the task function. Once the stack has been initialised
// 484 the top of stack variable is updated. */
// 485 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pvTaskCode, pvParameters );
PUSH.W R8
CFI CFA SP+26
MOV.W 0x6(SP), R14
MOV.W R5, R12
CALL #pxPortInitialiseStack
MOV.W R12, 0(R4)
// 486
// 487 /* We are going to manipulate the task queues to add this task to a
// 488 ready list, so must make sure no interrupts occur. */
// 489 portENTER_CRITICAL();
DINT
NOP
ADD.W #0x1, &usCriticalNesting
// 490 {
// 491 uxCurrentNumberOfTasks++;
ADD.W #0x1, &uxCurrentNumberOfTasks
// 492 if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 )
ADD.W #0x6, SP
CFI CFA SP+20
CMP.W #0x1, &uxCurrentNumberOfTasks
JNE ??xTaskCreate_1
// 493 {
// 494 /* As this is the first task it must also be the current task. */
// 495 pxCurrentTCB = pxNewTCB;
MOV.W R4, &pxCurrentTCB
// 496
// 497 /* This is the first task to be created so do the preliminary
// 498 initialisation required. We will not recover if this call
// 499 fails, but we will report the failure. */
// 500 prvInitialiseTaskLists();
CALL #prvInitialiseTaskLists
JMP ??xTaskCreate_2
// 501 }
// 502 else
// 503 {
// 504 /* If the scheduler is not already running, make this task the
// 505 current task if it is the highest priority task to be created
// 506 so far. */
// 507 if( xSchedulerRunning == pdFALSE )
??xTaskCreate_1:
CMP.W #0x0, &xSchedulerRunning
JNE ??xTaskCreate_2
// 508 {
// 509 if( pxCurrentTCB->uxPriority <= uxPriority )
MOV.W &pxCurrentTCB, R15
CMP.W 0x16(R15), R9
JNC ??xTaskCreate_2
// 510 {
// 511 pxCurrentTCB = pxNewTCB;
MOV.W R4, &pxCurrentTCB
// 512 }
// 513 }
// 514 }
// 515
// 516 /* Remember the top priority to make context switching faster. Use
// 517 the priority in pxNewTCB as this has been capped to a valid value. */
// 518 if( pxNewTCB->uxPriority > uxTopUsedPriority )
??xTaskCreate_2:
CMP.W 0x16(R4), &uxTopUsedPriority
JC ??xTaskCreate_3
// 519 {
// 520 uxTopUsedPriority = pxNewTCB->uxPriority;
MOV.W 0x16(R4), &uxTopUsedPriority
// 521 }
// 522
// 523 /* Add a counter into the TCB for tracing only. */
// 524 pxNewTCB->uxTCBNumber = uxTaskNumber;
??xTaskCreate_3:
MOV.W &??uxTaskNumber, 0x1a(R4)
// 525 uxTaskNumber++;
ADD.W #0x1, &??uxTaskNumber
// 526
// 527 prvAddTaskToReadyQueue( pxNewTCB );
CMP.W 0x16(R4), &uxTopReadyPriority
JC ??xTaskCreate_4
MOV.W 0x16(R4), &uxTopReadyPriority
??xTaskCreate_4:
MOV.W R4, R14
ADD.W #0x2, R14
MOV.W #pxReadyTasksLists, R12
MOV.W 0x16(R4), R15
RLA.W R15
MOV.W R15, R13
RLA.W R15
RLA.W R15
ADD.W R13, R15
ADD.W R15, R12
CALL #vListInsertEnd
// 528
// 529 xReturn = pdPASS;
MOV.W #0x1, R7
// 530 }
// 531 portEXIT_CRITICAL();
CMP.W #0x0, &usCriticalNesting
JEQ ??xTaskCreate_5
ADD.W #0xffff, &usCriticalNesting
CMP.W #0x0, &usCriticalNesting
JNE ??xTaskCreate_5
EINT
JMP ??xTaskCreate_5
// 532 }
// 533 else
// 534 {
// 535 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
??xTaskCreate_0:
MOV.W #0xffff, R7
// 536 }
// 537
// 538 if( xReturn == pdPASS )
??xTaskCreate_5:
CMP.W #0x1, R7
JNE ??xTaskCreate_6
// 539 {
// 540 if( ( void * ) pxCreatedTask != NULL )
CMP.W #0x0, R6
JEQ ??xTaskCreate_7
// 541 {
// 542 /* Pass the TCB out - in an anonymous way. The calling function/
// 543 task can use this as a handle to delete the task later if
// 544 required.*/
// 545 *pxCreatedTask = ( xTaskHandle ) pxNewTCB;
MOV.W R4, 0(R6)
// 546 }
// 547
// 548 if( xSchedulerRunning != pdFALSE )
??xTaskCreate_7:
CMP.W #0x0, &xSchedulerRunning
JEQ ??xTaskCreate_6
// 549 {
// 550 /* If the created task is of a higher priority than the current task
// 551 then it should run now. */
// 552 if( pxCurrentTCB->uxPriority < uxPriority )
MOV.W &pxCurrentTCB, R15
CMP.W R9, 0x16(R15)
JC ??xTaskCreate_6
// 553 {
// 554 taskYIELD();
CALL #vPortYield
// 555 }
// 556 }
// 557 }
// 558
// 559 return xReturn;
??xTaskCreate_6:
MOV.W R7, R12
ADD.W #0x2, SP
CFI CFA SP+18
BR #?Epilogue8
CFI EndBlock cfiBlock0
// 560 }
RSEG DATA16_Z:DATA:SORT:NOROOT(1)
REQUIRE ?cstart_init_zero
??uxTaskNumber:
DS8 2
// 561 /*-----------------------------------------------------------*/
// 562
// 563 #if ( INCLUDE_vTaskDelete == 1 )
// 564
RSEG CODE:CODE:REORDER:NOROOT(1)
// 565 void vTaskDelete( xTaskHandle pxTaskToDelete )
vTaskDelete:
CFI Block cfiBlock1 Using cfiCommon0
CFI Function vTaskDelete
// 566 {
FUNCALL vTaskDelete, vListRemove
LOCFRAME CSTACK, 6, STACK
FUNCALL vTaskDelete, vListRemove
LOCFRAME CSTACK, 6, STACK
FUNCALL vTaskDelete, vListInsertEnd
LOCFRAME CSTACK, 6, STACK
FUNCALL vTaskDelete, vPortYield
LOCFRAME CSTACK, 6, STACK
PUSH.W R10
CFI R10 Frame(CFA, -4)
CFI CFA SP+4
PUSH.W R11
CFI R11 Frame(CFA, -6)
CFI CFA SP+6
MOV.W R12, R10
// 567 tskTCB *pxTCB;
// 568
// 569 taskENTER_CRITICAL();
DINT
NOP
ADD.W #0x1, &usCriticalNesting
// 570 {
// 571 /* If null is passed in here then we are deleting ourselves. */
// 572 pxTCB = prvGetTCBFromHandle( pxTaskToDelete );
CMP.W #0x0, R10
JNE ??vTaskDelete_0
MOV.W &pxCurrentTCB, R11
JMP ??vTaskDelete_1
??vTaskDelete_0:
MOV.W R10, R11
// 573
// 574 /* Remove task from the ready list and place in the termination list.
// 575 This will stop the task from be scheduled. The idle task will check
// 576 the termination list and free up any memory allocated by the
// 577 scheduler for the TCB and stack. */
// 578 vListRemove( &( pxTCB->xGenericListItem ) );
??vTaskDelete_1:
MOV.W R11, R12
ADD.W #0x2, R12
CALL #vListRemove
// 579
// 580 /* Is the task waiting on an event also? */
// 581 if( pxTCB->xEventListItem.pvContainer )
CMP.W #0x0, 0x14(R11)
JEQ ??vTaskDelete_2
// 582 {
// 583 vListRemove( &( pxTCB->xEventListItem ) );
MOV.W R11, R12
ADD.W #0xc, R12
CALL #vListRemove
// 584 }
// 585
// 586 vListInsertEnd( ( xList * ) &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );
??vTaskDelete_2:
MOV.W R11, R14
ADD.W #0x2, R14
MOV.W #xTasksWaitingTermination, R12
CALL #vListInsertEnd
// 587
// 588 /* Increment the ucTasksDeleted variable so the idle task knows
// 589 there is a task that has been deleted and that it should therefore
// 590 check the xTasksWaitingTermination list. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -