网站空间一定要买吗,如何在网站做qq群链接,c 做网站,互联网运营FreeRTOS之ARM CR5栈结构操作示意图 1 FreeRTOS源码下载地址2 ARM CR5栈结构操作宏和接口2.1 portSAVE_CONTEXT宏2.1.1 portSAVE_CONTEXT源码2.1.2 portSAVE_CONTEXT宏操作栈结构变化示意图 2.2 portRESTORE_CONTEXT宏2.2.1 portRESTORE_CONTEXT源码2.2.2 portRESTORE_CONTEXT宏… FreeRTOS之ARM CR5栈结构操作示意图 1 FreeRTOS源码下载地址2 ARM CR5栈结构操作宏和接口2.1 portSAVE_CONTEXT宏2.1.1 portSAVE_CONTEXT源码2.1.2 portSAVE_CONTEXT宏操作栈结构变化示意图 2.2 portRESTORE_CONTEXT宏2.2.1 portRESTORE_CONTEXT源码2.2.2 portRESTORE_CONTEXT宏操作栈结构变化示意图 2.3 pxPortInitialiseStack2.3.1 pxPortInitialiseStack源码3.2.2 pxPortInitialiseStack栈结构变化示意图 2.4 pxPortInitialiseStack调用关系2.5 portRESTORE_CONTEXT调用关系 3 参考文章 下面以FreeRTOS源码中arm cortex-r5处理器的栈处理为例来介绍栈结构操作前后变化。
1 FreeRTOS源码下载地址
https://www.freertos.org/
2 ARM CR5栈结构操作宏和接口
.macro portSAVE_CONTEXT.macro portRESTORE_CONTEXTpxPortInitialiseStack
2.1 portSAVE_CONTEXT宏
2.1.1 portSAVE_CONTEXT源码
.macro portSAVE_CONTEXT/* Save the LR and SPSR onto the system mode stack before switching tosystem mode to save the remaining system mode registers. */SRSDB sp!, #SYS_MODECPS #SYS_MODEPUSH {R0-R12, R14}/* Push the critical nesting count. */LDR R2, ulCriticalNestingConstLDR R1, [R2]PUSH {R1}#if defined( __ARM_FP )/* Does the task have a floating point context that needs saving? IfulPortTaskHasFPUContext is 0 then no. */LDR R2, ulPortTaskHasFPUContextConstLDR R3, [R2]CMP R3, #0/* Save the floating point context, if any. */FMRXNE R1, FPSCRPUSHNE {R1}VPUSHNE {D0-D15}/* Save ulPortTaskHasFPUContext itself. */PUSH {R3}#endif /* __ARM_FP *//* Save the stack pointer in the TCB. */LDR R0, pxCurrentTCBConstLDR R1, [R0]STR SP, [R1].endm2.1.2 portSAVE_CONTEXT宏操作栈结构变化示意图 2.2 portRESTORE_CONTEXT宏
2.2.1 portRESTORE_CONTEXT源码
.macro portRESTORE_CONTEXT/* Set the SP to point to the stack of the task being restored. */LDR R0, pxCurrentTCBConstLDR R1, [R0]LDR SP, [R1]#if defined( __ARM_FP )/** Is there a floating point context to restore? If the restored* ulPortTaskHasFPUContext is zero then no.*/LDR R0, ulPortTaskHasFPUContextConstPOP {R1}STR R1, [R0]CMP R1, #0/* Restore the floating point context, if any. */VPOPNE {D0-D15}POPNE {R0}VMSRNE FPSCR, R0#endif /* __ARM_FP *//* Restore the critical section nesting depth. */LDR R0, ulCriticalNestingConstPOP {R1}STR R1, [R0]/* Ensure the priority mask is correct for the critical nesting depth. */LDR R2, ulICCPMRConstLDR R2, [R2]CMP R1, #0MOVEQ R4, #255LDRNE R4, ulMaxAPIPriorityMaskConstLDRNE R4, [R4]STR R4, [R2]/* Restore all system mode registers other than the SP (which is alreadybeing used). */POP {R0-R12, R14}/* Return to the task code, loading CPSR on the way. */RFEIA sp!.endm2.2.2 portRESTORE_CONTEXT宏操作栈结构变化示意图 2.3 pxPortInitialiseStack
2.3.1 pxPortInitialiseStack源码
/** See header file for description.*/
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,TaskFunction_t pxCode,void * pvParameters )
{/** Setup the initial stack of the task. The stack is set exactly as* expected by the portRESTORE_CONTEXT() macro.** The fist real value on the stack is the status register, which is set for* system mode, with interrupts enabled. A few NULLs are added first to ensure* GDB does not try decoding a non-existent return address.*/*pxTopOfStack ( StackType_t ) NULL;pxTopOfStack--;*pxTopOfStack ( StackType_t ) NULL;pxTopOfStack--;*pxTopOfStack ( StackType_t ) NULL;pxTopOfStack--;*pxTopOfStack ( StackType_t ) portINITIAL_SPSR;if( ( ( uint32_t ) pxCode portTHUMB_MODE_ADDRESS ) ! 0x00UL ){/* The task will start in THUMB mode. */*pxTopOfStack | portTHUMB_MODE_BIT;}pxTopOfStack--;/* Next the return address, which in this case is the start of the task. */*pxTopOfStack ( StackType_t ) pxCode;pxTopOfStack--;/* Next all the registers other than the stack pointer. */*pxTopOfStack ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */pxTopOfStack--;*pxTopOfStack ( StackType_t ) 0x12121212; /* R12 */pxTopOfStack--;*pxTopOfStack ( StackType_t ) 0x11111111; /* R11 */pxTopOfStack--;*pxTopOfStack ( StackType_t ) 0x10101010; /* R10 */pxTopOfStack--;*pxTopOfStack ( StackType_t ) 0x09090909; /* R9 */pxTopOfStack--;*pxTopOfStack ( StackType_t ) 0x08080808; /* R8 */pxTopOfStack--;*pxTopOfStack ( StackType_t ) 0x07070707; /* R7 */pxTopOfStack--;*pxTopOfStack ( StackType_t ) 0x06060606; /* R6 */pxTopOfStack--;*pxTopOfStack ( StackType_t ) 0x05050505; /* R5 */pxTopOfStack--;*pxTopOfStack ( StackType_t ) 0x04040404; /* R4 */pxTopOfStack--;*pxTopOfStack ( StackType_t ) 0x03030303; /* R3 */pxTopOfStack--;*pxTopOfStack ( StackType_t ) 0x02020202; /* R2 */pxTopOfStack--;*pxTopOfStack ( StackType_t ) 0x01010101; /* R1 */pxTopOfStack--;*pxTopOfStack ( StackType_t ) pvParameters; /* R0 *//** The task will start with a critical nesting count of 0 as interrupts are* enabled.*/pxTopOfStack--;*pxTopOfStack portNO_CRITICAL_NESTING;#if ( configUSE_TASK_FPU_SUPPORT 1 ){/** The task will start without a floating point context.* A task that uses the floating point hardware must call* vPortTaskUsesFPU() before executing any floating point* instructions.*/pxTopOfStack--;*pxTopOfStack portNO_FLOATING_POINT_CONTEXT;}#elif ( configUSE_TASK_FPU_SUPPORT 2 ){/** The task will start with a floating point context. Leave enough* space for the registers and ensure they are initialized to 0.*/pxTopOfStack - portFPU_REGISTER_WORDS;memset( pxTopOfStack, 0x00, portFPU_REGISTER_WORDS * sizeof( StackType_t ) );pxTopOfStack--;*pxTopOfStack pdTRUE;ulPortTaskHasFPUContext pdTRUE;}#elif ( configUSE_TASK_FPU_SUPPORT ! 0 ){#error Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 0, 1, or 2.}#endif /* configUSE_TASK_FPU_SUPPORT */return pxTopOfStack;
}3.2.2 pxPortInitialiseStack栈结构变化示意图 2.4 pxPortInitialiseStack调用关系 |- xTaskCreate( pxIdleTaskFunction, ...)|- prvCreateTask|- pxStack pvPortMallocStack( ( ( ( size_t ) uxStackDepth ) * sizeof( StackType_t ) ) );|- pxNewTCB ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );|- prvInitialiseNewTask|- vListInitialiseItem( ( pxNewTCB-xStateListItem ) );|- vListInitialiseItem( ( pxNewTCB-xEventListItem ) );|- pxNewTCB-pxTopOfStack pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );2.5 portRESTORE_CONTEXT调用关系
|- vTaskStartScheduler|- prvCreateIdleTasks()|- xTaskCreate( pxIdleTaskFunction, ...)|- prvCreateTask|- pxStack pvPortMallocStack( ( ( ( size_t ) uxStackDepth ) * sizeof( StackType_t ) ) );|- pxNewTCB ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );|- prvInitialiseNewTask|- vListInitialiseItem( ( pxNewTCB-xStateListItem ) );|- vListInitialiseItem( ( pxNewTCB-xEventListItem ) );|- pxNewTCB-pxTopOfStack pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );|- *pxCreatedTask ( TaskHandle_t ) pxNewTCB;|- prvAddNewTaskToReadyList|- prvInitialiseTaskLists|- prvAddTaskToReadyList|- listINSERT_END( ( pxReadyTasksLists[ ( pxTCB )-uxPriority ] ), ( ( pxTCB )-xStateListItem ) );|- xTimerCreateTimerTask()|- xTaskCreateAffinitySet|- prvCreateTask|- pxStack pvPortMallocStack( ( ( ( size_t ) uxStackDepth ) * sizeof( StackType_t ) ) );|- pxNewTCB ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );|- prvInitialiseNewTask|- vListInitialiseItem( ( pxNewTCB-xStateListItem ) );|- vListInitialiseItem( ( pxNewTCB-xEventListItem ) );|- pxNewTCB-pxTopOfStack pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );|- *pxCreatedTask ( TaskHandle_t ) pxNewTCB;|- prvAddNewTaskToReadyList|- prvInitialiseTaskLists|- prvAddTaskToReadyList|- listINSERT_END( ( pxReadyTasksLists[ ( pxTCB )-uxPriority ] ), ( ( pxTCB )-xStateListItem ) )|- pxNewTCB-uxCoreAffinityMask uxCoreAffinityMask;|- prvAddNewTaskToReadyList( pxNewTCB );|- xPortStartScheduler()|- vPortRestoreTaskContext|- portRESTORE_CONTEXT
3 参考文章
arm汇编指令之数据块传输LDM,STM详见 arm 处理器的堆栈操作