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

news/2024/12/4 18:20:35/

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.ppmy.cn/news/1552348.html

相关文章

Nginx管理维护运维规范

Nginx管理维护运维规范 一、版本约束 软件的不同版本,在使用起来都有可能带来不可预知的影响,因此需要统一整理,固定下来,不允许轻易变更。 在Nginx开源版官网,点击右侧download可以看到各个版本的Nginx,…

第六届金盾信安杯Web题解

比赛一共4道Web题,比赛时只做出三道,那道文件上传没有做出来,所以这里是另外三道题的WP 分别是 fillllll_put hoverfly ssrf fillllll_put 涉及: 绕过exit() 死亡函数 php://filter 伪协议配合base64加解密 一句话木马 题目源码: $content参数在开头被…

Linux笔试题(自己整理,已做完,选择题)

详细Linux内容查看:day04【入门】Linux系统操作-CSDN博客 1、部分笔试题 本文的笔试题,主要是为了复习学习的day04【入门】Linux系统操作-CSDN博客的相关知识点。后续还会更新一些面试相关的题目。 欢迎一起学习

MongoDB集群分片安装部署手册

文章目录 一、集群规划1.1 集群安装规划1.2 端口规划1.3 目录创建 二、mongodb安装(三台均需要操作)2.1 下载、解压2.2 配置环境变量 三、mongodb组件配置3.1 配置config server的副本集3.1.1 config配置文件3.1.2 config server启动3.1.3 初始化config …

链表的分类以及双向链表的实现

1.链表的分类 1.1单向链表与双向链表的区别 单向链表只能从头结点遍历到尾结点。 双向链表不仅能从头结点遍历到尾结点,还能从尾结点遍历到头结点。 1.2带头链表与不带头链表的区别 1.3循环链表与不循环链表的区别(也称为带环链表与不带环链表&#x…

【嵌入式系统设计】LES3~5:Cortex-M4系统架构(上)第1节 ARM处理器,M4内核处理器,M4调试跟踪接口

关注作者了解更多 我的其他CSDN专栏 过程控制系统 工程测试技术 虚拟仪器技术 可编程控制器 工业现场总线 数字图像处理 智能控制 传感器技术 嵌入式系统 复变函数与积分变换 单片机原理 线性代数 大学物理 热工与工程流体力学 数字信号处理 光电融合集成电路…

LeetCode - #150 逆波兰表达式求值

文章目录 前言1. 描述2. 示例3. 答案关于我们 前言 我们社区陆续会将顾毅(Netflix 增长黑客,《iOS 面试之道》作者,ACE 职业健身教练。)的 Swift 算法题题解整理为文字版以方便大家学习与阅读。 LeetCode 算法到目前我们已经更新…

论文mindfulness_PTSS_COVID19(八):总结

文章目录 介绍再次提醒:计算不同维度得分的规则参考介绍 本研究的数据分析原采用SPSS软件进行处理,而本教程则选择使用R语言来重新执行数据分析,以验证研究结果的可复现性。尽管在对表3(table3 @fig-index-table3 )、表4(table4 @fig-index-table4 )和表5(table5 @fig…