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 to
    system mode to save the remaining system mode registers. */
    SRSDB   sp!, #SYS_MODE
    CPS     #SYS_MODE
    PUSH    {R0-R12, R14}

    /* Push the critical nesting count. */
    LDR     R2, ulCriticalNestingConst
    LDR     R1, [R2]
    PUSH    {R1}

    #if defined( __ARM_FP )
        /* Does the task have a floating point context that needs saving?  If
        ulPortTaskHasFPUContext is 0 then no. */
        LDR     R2, ulPortTaskHasFPUContextConst
        LDR     R3, [R2]
        CMP     R3, #0

        /* Save the floating point context, if any. */
        FMRXNE  R1,  FPSCR
        PUSHNE  {R1}
        VPUSHNE {D0-D15}

        /* Save ulPortTaskHasFPUContext itself. */
        PUSH    {R3}
    #endif /* __ARM_FP */

    /* Save the stack pointer in the TCB. */
    LDR     R0, pxCurrentTCBConst
    LDR     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, pxCurrentTCBConst
    LDR     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, ulPortTaskHasFPUContextConst
        POP     {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, ulCriticalNestingConst
    POP     {R1}
    STR     R1, [R0]

    /* Ensure the priority mask is correct for the critical nesting depth. */
    LDR     R2, ulICCPMRConst
    LDR     R2, [R2]
    CMP     R1, #0
    MOVEQ   R4, #255
    LDRNE   R4, ulMaxAPIPriorityMaskConst
    LDRNE   R4, [R4]
    STR     R4, [R2]

    /* Restore all system mode registers other than the SP (which is already
    being 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/928365.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

警惕开源信息成为泄密源头

文章目录 前言一、信息公开需谨慎1、警惕采购招标泄密。2、警惕信息公开泄密。3、警惕社交媒体泄密。 二、泄密风险需严防1、健全制度,明确责任。2、加强管控,严格审查。3、提高意识,谨言慎行。 前言 大数据时代,信息在网络空间发…

指针(上)

目录 内存和地址 指针变量和地址 取地址(&) 解引用(*) 大小 类型 意义 const修饰 修饰变量 修饰指针 指针运算 指针- 整数 指针-指针 指针的关系运算 野指针 概念 成因 避免 assert断言 指针的使用 strl…

常见的数据结构---队列、树与堆的深入剖析

目录 一、队列 二、树 三、堆 在现代计算机科学与工程领域,队列、树和堆是三种极其重要的基础数据结构,它们各自具有独特的特点和应用。在日常开发中,合理选择和使用这些数据结构可以显著提高程序的效率和可维护性。它们不仅奠定了算法设计…

Java 整合图片处理相关一套:传输、保存、重命名、删除、AI图片文字识别、图片映射、vue3裁剪、设置黑白色、设置负片、提高照片品质

目录 一、vue3 axios spring boot文件传输 二、Java图片保存到本地 三、Java 本地图片重命名 四、Java 删除本地图片 五、 JavaAI图片文字识别 六、Java映射图片地址,前端直接访问图片 七、vue3 图片裁剪 八、Java 设置图片黑白色 九、Java 设置图片负片 …

web三、 window对象,延时器,定时器,时间戳,location对象(地址),本地存储-localStorage,数组去重new Set

一、 window对象 window对象 是一个全局对象,也可以说是JavaScript中的 顶级对象 像document、alert()、console.log()这些都是window的属性,基本BOM的属性和方法都是window的 所有通过 var定义 在全局作用域中的 变量 、 函数 都会变成window对象的属…

【AI系统】昇腾异构计算架构 CANN

昇腾异构计算架构 CANN 本文将介绍昇腾 AI 异构计算架构 CANN(Compute Architecture for Neural Networks),这是一套为高性能神经网络计算需求专门设计和优化的架构。CANN 包括硬件层面的达芬奇架构和软件层面的全栈支持,旨在提供…

Spark和MapReduce场景应用和区别

文章目录 Spark和MapReduce场景应用和区别一、引言二、MapReduce和Spark的应用场景1. MapReduce的应用场景2. Spark的应用场景 三、MapReduce和Spark的区别1. 内存使用和性能2. 编程模型和易用性3. 实时计算支持 四、使用示例1. MapReduce代码示例2. Spark代码示例 五、总结 Sp…

CSS函数

目录 一、背景 二、函数的概念 1. var()函数 2、calc()函数 三、总结 一、背景 今天我们就来说一说,常用的两个css自定义属性,也称为css函数。本文中就成为css函数。先来看一下官方对其的定义。 自定义属性(有时候也被称作CSS 变量或者级…

【C语言】递归的内存占用过程

递归 递归是函数调用自身的一种编程技术。在C语言中,递归的实现会占用内存栈(Call Stack),每次递归调用都会在栈上分配一个新的 “栈帧(Stack Frame)”,用于存储本次调用的函数局部变量、返回地…

大数据新视界 -- 大数据大厂之 Hive 数据压缩算法对比与选择(下)(20 / 30)

💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

【golang】单元测试,以及出现undefined时的解决方案

单元测试 要对某一方法进行测试时,例如如下这一简单减法函数,选中函数名后右键->转到->测试 1)Empty test file 就是一个空文件,我们可以自己写测试的逻辑 但是直接点绿色箭头运行会出问题: 找不到包。我们要在…

ETL工具观察:ETLCloud与MDM是什么关系?

一、什么是ETLCloud ETLCloud数据中台是一款高时效的数据集成平台,专注于解决大数据量和高合规要求环境下的数据集成需求。 工具特点 1.离线与实时集成:支持离线数据集成(ETL、ELT)和变更数据捕获(CDC)实…

人形机器人训练、机器臂远程操控、VR游戏交互、影视动画制作,一副手套全部解决!

广州虚拟动力基于自研技术推出了多节点mHand Pro动捕数据手套,其最大的特点就是功能集成与高精度捕捉,可以用于人形机器人训练、机器臂远程操控、VR游戏交互、影视动画制作等多种场景。 一、人形机器人训练 mHand Pro动捕数据手套双手共装配16个9轴惯性…

IDL学习笔记(二)IDL处理卫星数据

IDL处理卫星数据 HDF文件数据集属性通用属性 常用HDF4操作函数常用的HDF5操作函数读取HDF文件的一般步骤 HDF4文件读取-----数据信息查询HDF4文件读取示例-----目标数据TIFF输出提取modis产品中数据,与某一点经纬度最接近的点有效结果,并按每行内容为日期…

动态规划-----路径问题

动态规划-----路径问题 下降最小路径和1:状态表示2:状态转移方程3 初始化4 填表顺序5 返回值6 代码实现 总结: 下降最小路径和 1:状态表示 假设:用dp[i][j]表示:到达[i,j]的最小路径 2:状态转…

Redis+Caffeine 多级缓存数据一致性解决方案

RedisCaffeine 多级缓存数据一致性解决方案 背景 之前写过一篇文章RedisCaffeine 实现两级缓存实战,文章提到了两级缓存RedisCaffeine可以解决缓存雪等问题也可以提高接口的性能,但是可能会出现缓存一致性问题。如果数据频繁的变更,可能会导…

2024年大热,Access平替升级方案,也适合Excel用户

欢迎各位看官,您来了,就对了! 您多半是Access忠实粉丝,至少是excel用户,亦或是WPS用户吧。那就对了,今天的分享肯定对您有用。 本文1100字,阅读时长2分50秒! 现实总是不尽人意&am…

解决idea使用maven打包时无法将本地lib库文件和resource目录中的资源文件打包进jar文件的问题!!!

一、问题复现 1)项目结构如下 我们看到项目中手动添加了本地lib资源,同时bootspring的配置文件和mapper文件也放在了resouces目录中。 2)上述结构的项目在使用maven打包时,最终生成的jar文件中将不包含lib库文件,甚…

PKO-LSSVM-Adaboost班翠鸟优化最小二乘支持向量机结合AdaBoost分类模型

PKO-LSSVM-Adaboost班翠鸟优化最小二乘支持向量机结合AdaBoost分类模型 目录 PKO-LSSVM-Adaboost班翠鸟优化最小二乘支持向量机结合AdaBoost分类模型效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.PKO-LSSVM-Adaboost班翠鸟优化最小二乘支持向量机结合AdaBoost分类模…

FPGA实战篇(呼吸灯实验)

1.呼吸灯简介 呼吸灯采用 PWM 的方式,在固定的频率下,通过调整占空比的方式来控制 LED 灯亮度的变化。 PWM(Pulse Width Modulation ),即脉冲宽度调制,它利用微处理器输出的 PWM 信号,实现对…