当前位置: 首页 > news >正文

FreeRTOS之ARM CR5栈结构操作示意图

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 pxPortInitialiseStack
      • 2.3.1 pxPortInitialiseStack源码
      • 3.2.2 pxPortInitialiseStack栈结构变化示意图
    • 2.4 pxPortInitialiseStack调用关系
    • 2.5 portRESTORE_CONTEXT调用关系

下面以FreeRTOS源码中arm cortex-r5处理器的栈处理为例来介绍栈结构操作前后变化。

1 FreeRTOS源码下载地址

https://www.freertos.org/
在这里插入图片描述

2 ARM CR5栈结构操作宏和接口

  • .macro portSAVE_CONTEXT
  • .macro portRESTORE_CONTEXT
  • pxPortInitialiseStack

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].endm

2.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!.endm

2.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

http://www.mrgr.cn/news/79006.html

相关文章:

  • 【NLP自然语言处理】Transformer模型的几大核心优势与应用前景
  • 单片机-LED点阵实验
  • 网络-http协议学习笔记(消息结构、请求方法、状态码等)
  • 云备份项目--服务端编写
  • 笔上云世界微服务版
  • 编译与汇编
  • MATLAB提供的窗函数
  • Alibaba Druid(简称Druid)
  • Android KEY的哪些事儿
  • CTF-PWN: WEB_and_PWN [第一届“吾杯”网络安全技能大赛 Calculator] 赛后学习(不会)
  • 链表的分类以及双向链表的实现
  • 十二、消息队列-MQ
  • 国产CPU 安装Windows可行性操作
  • Redis 之持久化
  • 将空白背景透明化
  • 【C++笔记】map和set的使用
  • 【ETCD】ETCD用户密码认证
  • Mac安装MINIO服务器实现本地上传和下载服务
  • 使用Tomcat搭建简易文件服务器
  • Ansible 运维工具
  • 零基础快速掌握——【c语言基础】数组的操作,冒泡排序,选择排序
  • 我们来学mysql -- 事务并发之脏写(原理篇)
  • HDFS 操作命令
  • Spring Boot Actuator未授权访问漏洞处理
  • 【机器学习】机器学习的基本分类-监督学习-决策树-ID3 算法
  • Unity 模拟百度地图,使用鼠标控制图片在固定区域内放大、缩小、鼠标左键拖拽移动图片