[FreeRTOS 内部实现] 创建任务 xTaskCreate函数解析

news2024/11/26 22:21:30

文章目录

    • 创建任务 xTaskCreate函数原型
      • 栈深度 usStackDepth 大小如何确定
      • 任务堆空间分配
    • 任务控制块 TCB


创建任务 xTaskCreate函数原型

BaseType_t xTaskCreate(    TaskFunction_t pxTaskCode,
            const char * const pcName,
            const configSTACK_DEPTH_TYPE usStackDepth,
            void * const pvParameters,
            UBaseType_t uxPriority,
            TaskHandle_t * const pxCreatedTask )

根据前面的文章可知,要创建一个任务需要 4个要素:运行函数,函数参数,栈,任务优先级。
在RTOS系统中创建任务函数 xTaskCreate,传入参数解析:

  • TaskFunction_t pxTaskCode :运行函数
  • const char * const pcName :函数名字
  • const configSTACK_DEPTH_TYPE usStackDepth :栈大小
  • void * const pvParameters :运行函数的参数
  • UBaseType_t uxPriority : 函数优先级
  • TaskHandle_t * const pxCreatedTask :任务控制块TCB 输出参数

栈深度 usStackDepth 大小如何确定

通过简单的示例来看下,普通的函数会产生多少栈大小,如何计算?
在这里插入图片描述
(1)PUSH {r4-r5,lr}: 将寄存器r4, r5和链接寄存器(lr)压入栈中。这是为了保存这些寄存器的值,以便函数调用结束后可以恢复它们。
(2)SUB sp,sp,#0x194: 从栈指针sp减去0x194(404),为局部变量分配栈空间。
(3)MOV r5, r1: 将r1寄存器的值移动到r5寄存器。这通常是将输入参数的一个值保存到另一个寄存器中。
(4)MOV r4, r0: 将r0寄存器的值移动到r4寄存器。同样,这可能是保存另一个输入参数。
(5)MOV r1, #0x18C: 将立即数0x18C(404)移动到r1寄存器。
(6)ADD r0, sp, #0x04: 将栈指针sp加上4,然后将结果移动到r0寄存器。
(7)BL.W 0x0800020C __aeabi_memclr4: BL.W是ARM的分支链接指令,用于远距离跳转,并在链接寄存器中保存返回地址。
(8)LDR r0, [pc, #24]: 从程序计数器pc地址加上24的位置加载数据到r0寄存器。
(9)LDR r0, [r0, #0x00]: 从r0寄存器指向的地址加载数据到r0。
(10)STR r0, [sp, #0x00]: 将r0寄存器的值存储到栈指针sp地址偏移0的位置。
(11)LDR r0, [r4, #0x00]: 从r4寄存器指向的地址加载数据到r0。
(12)STR r0, [sp, #0x190]: 将r0寄存器的值存储到栈指针sp地址偏移0x190的位置。
(13)LDR r0, [r5, #0x00]: 从r5寄存器指向的地址加载数据到r0。
(14)LDR r1, [sp, #0x190]: 从栈指针sp地址偏移0x190的位置加载数据到r1。
(15)ADD r0, r0, r1: 将r0和r1寄存器的值相加,结果存储在r0。
(16)STR r0, [sp, #0x190]: 将r0寄存器的值再次存储到栈指针sp地址偏移0x190的位置。
(17)STR r0, [r4, #0x00]: 将r0寄存器的值存储到r4寄存器指向的地址。
(18)ADD sp, sp, #0x194: 将栈指针sp加上0x194,释放之前分配的栈空间。
(19)POP {r4-r5,pc}: 从栈中弹出之前保存的r4, r5和pc值,恢复它们,并返回到调用这个函数的代码处。
在这里插入图片描述
栈大小可以根据任务中使用的临时变量估算出需要多大的栈空间,当然函数传入的栈大小要比估算的大些,以免超出越界访问。(一般为估算大小的两倍)

任务堆空间分配

在这里插入图片描述
#define configTOTAL_HEAP_SIZE ((size_t)3072)
RTOS系统中的栈是ucHeap数据,大小为3072字节
每创建一个任务都会在ucHeap堆空间申请出自己的堆空间。


任务控制块 TCB

作用:在栈中为每个任务分配一个任务控制块(TCB)。存储任务状态信息,包括指向任务上下文的指针(任务的运行时环境,包括寄存器值)。完成创建任务后,会将任务的TCB赋给 pxCreatedTask 参数

*pxCreatedTask = ( TaskHandle_t ) pxNewTCB;

结构体TCB

typedef struct tskTaskControlBlock
{
    volatile StackType_t    *pxTopOfStack;    /* 指向任务堆栈中最后一项的位置。这必须是TCB结构体的第一个成员。*/
    

    
    ListItem_t            xStateListItem;    /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
    ListItem_t            xEventListItem;        /*< Used to reference a task from an event list. */
    UBaseType_t            uxPriority;            /* 任务优先级。  0 是优先级最低的。 */
    StackType_t            *pxStack;            /* 栈的最开始指针 */
    char            pcTaskName[ configMAX_TASK_NAME_LEN ];/* 任务名称 */ 


} tskTCB;

由于任务会在栈中会以TCB结构体的形式描述,因此 xTaskCreate函数传入的参数都应该在这个结构中体现。

const char * const pcName :函数名字char pcTaskName[ configMAX_TASK_NAME_LEN ];
UBaseType_t uxPriority : 函数优先级UBaseType_t uxPriority;
const configSTACK_DEPTH_TYPE usStackDepthvolatile :栈深度StackType_t *pxTopOfStack
StackType_t *pxStack;

发现在TCB结构体中没有最重要的运行函数以及参数,而在TCB结构体中存在两个链表。
任务在创建的时候,会将PC指向函数名字,R0寄存器存的参数。在任务切换的时候,要将全部环境保存下来,当下次获得CPU使用权的时候,恢复现场运行任务。因此任务栈中保存一套任务环境。
在这里插入图片描述

StackType_t *pxStack;

pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) );
if( pxNewTCB != NULL )
{
    /* Store the stack location in the TCB. */
    pxNewTCB->pxStack = pxStack;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何用好swoole/webman/workerman/hyperf呢

Webman框架的依赖 "require": { "php": ">7.2", "workerman/webman-framework": "^1.5.0",// "monolog/monolog": "^2.0" }, 依赖的核心框架也是很久的了 webman-framework的核心依赖 &q…

高通安卓12-固件升级

下载步骤 第一步 格式化 「下载一次即可&#xff1b;能开机能下载的板子 忽略这一步&#xff0c;直接执行第二步即可」 QFIL工具配置为UFS类型&#xff0c;勾选Provision&#xff0c;如下图&#xff1a; Programmer选择prog_firehose_ddr.elf&#xff0c;Provision Xml选择prov…

【python包安装】手动安装libmr

遇到问题 再导入libmr模块时&#xff0c;导入失败 尝试使用pip install libmr安装&#xff0c;安装失败 查询原因是windows上pip安装找不到库&#xff0c;只能采取手动安装。 解决方法 下载libMR库文件 安装方法可以查看README文档 安装libmr之前需要安装Microsoft C14或…

1.2 DataX 数据同步工具详细介绍

DataX 是阿里巴巴开源的一款高效的数据同步工具&#xff0c;旨在实现多种异构数据源之间的高效数据同步。以下是对 DataX 的详细介绍&#xff1a; 架构 DataX 的架构主要包括以下几个核心组件&#xff1a; DataX Core&#xff1a;负责任务调度、插件加载、日志管理等核心功能…

应用排行榜度量维度收集

可观测的三大基础度量遥测数据是 Trace、Metric、Log (链路、指标、日志) OpenTelemetry 围绕度量遥测数据构建可视化产品&#xff0c;看板、仪表盘、大屏/大盘与监控告警。 目标 提升服务稳定性提高资源利用率&#xff0c;降低云成本(降本)业务梳理与架构治理 度量维度 Sup…

通用大模型 vs垂直大模型:AI界的“宫斗大戏”

科技圈最近可真热闹&#xff0c;AI大模型的“宫斗大戏”让人眼花缭乱。两个阵营&#xff1a;通用大模型和垂直大模型&#xff0c;正在上演一场激烈的“权力的游戏”。到底谁能笑到最后&#xff1f;咱们一起来“吃瓜”看看吧&#xff01; 首先&#xff0c;登场的是“全能王”通…

分流电阻器的原理、特性、参数要点及其与分压电阻的区别详解

分流电阻器是一种低阻值电阻器&#xff0c;设计用于在电路中并联连接&#xff0c;以提供一个低阻抗的旁路或分流路径&#xff0c;从而使得一部分电流可以通过这个路径流动。它的主要功能是测量或限制电流&#xff0c;尤其适用于大电流检测的应用场景。分流电阻通过在其两端产生…

Axios-入门

介绍 Axios对原生Ajax进行了封装&#xff0c;简化书写&#xff0c;快速开发 官网&#xff1a;Axios中文文档 | Axios中文网 (axios-http.cn) 入门 1引入Axios的js文件 <script src"js/axios.js"></script> 2使用Axios发送请求&#xff0c;并获取响应…

如果申请小程序地理位置接口权限之前刷到这一篇就好了

小程序地理位置接口有什么功能&#xff1f; 通常情况下&#xff0c;我们在开发小程序时&#xff0c;可能会用到获取用户地理位置信息的功能。小程序开发者开放平台的新规定指出&#xff0c;如果没有申请开通微信小程序地理位置接口&#xff08;getLocation&#xff09;&#xf…

STM32单片机BKP备份寄存器和RTC实时时钟详解

文章目录 1. Unix时间戳 2. UTC/GMT 3. 时间戳转换 4. BKP简介 5. BKP基本结构 6. RTC简介 7. RTC框架图 8. RTC基本结构 9. 代码示例 1. Unix时间戳 实时时钟&#xff0c;本质上是一个定时器&#xff0c;专门用来产生年月日时分秒。 Unix 时间戳&#xff08;Unix T…

骑马与砍杀战团mod制作-基础-对话制作笔记(四)

骑马与砍杀战团mod制作-基础-对话制作笔记&#xff08;四&#xff09; 资料来源 学习的资料来源&#xff1a; b站【三啸解说】手把手教你做【骑砍】MOD&#xff0c;基础篇&#xff0c;链接为&#xff1a; https://www.bilibili.com/video/BV19x411Q7No?p4&vd_sourcea507…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 局域网中的服务器个数(200分) - 三语言AC题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; &#x1f…

ARM裸机:基础了解

ARM的几种版本号 ARM内核版本号 ARMv7 ARM SoC版本号 Cortex-A8 芯片型号 S5PV210 ARM型号的发展历程 m microcontroller微控制器 就是单片机 a application应用级处理器 就是手机、平板、电脑的CPU r realtime实时处理器 响应速度快,主要用在工业、航天等领域 soc 、cpu、…

VUE3 使用 vite-plugin-svg-icons加载SVG

目录 1. 装依赖 2. 在src里面创建文件夹 3. 封装svg组件 4. vite.config.js 中配置svg 5. 引入挂载&#xff08;在main.js中&#xff09; 6. 单页面直接用 1. 装依赖 npm i vite-plugin-svg-icons -D 2. 在src里面创建文件夹 3. 封装svg组件 代码明细&#xff1a; &l…

音视频的Buffer处理

最近在做安卓下UVC的一个案子。正好之前搞过ST方案的开机广告&#xff0c;这个也是我少数最后没搞成功的项目。当时也有点客观原因&#xff0c;当时ST要退出机顶盒市场&#xff0c;所以一切的支持都停了&#xff0c;当时啃他家播放器几十万行的代码&#xff0c;而且几乎没有文档…

文件操作<C语言>

导言 平时我们在写程序时&#xff0c;在运行时申请内存空间&#xff0c;运行完时内存空间被收回&#xff0c;如果想要持久化的保存&#xff0c;我们就可以使用文件&#xff0c;所以下文将要介绍一些在程序中完成一些文件操作。 目录 导言 文件流 文件指针 文件的打开与关闭 …

Android 开发必备知识点及面试题汇总(Android+Java+算法+性能优化+四大组件……

**虚引用&#xff1a;**顾名思义&#xff0c;就是形同虚设&#xff0c;如果一个对象仅持有虚引用&#xff0c;那么它相当于没有引用&#xff0c;在任何时候都可能被垃圾回收器回收。 7.介绍垃圾回收机制 **标记回收法&#xff1a;**遍历对象图并且记录可到达的对象&#xff0c…

WPS没保存关闭了怎么恢复数据?4个方法(更新版)

想象一下&#xff0c;你正在用WPS奋笔疾书&#xff0c;灵感如泉水般涌出&#xff0c;突然间&#xff0c;电脑却跟你开了个玩笑——啪地一下&#xff0c;文档未保存就关闭了&#xff01;是不是感觉像是被泼了一盆冷水&#xff0c;所有的热情瞬间熄灭&#xff1f;别急&#xff0c…

为 Android 应用打造精良的 Chrome OS 使用体验

override fun onKeyUp(code: Int, ev: KeyEvent?): Boolean { return when (code) { KeyEvent.KEYCODE_J -> { // Do something here true } else -> super.onKeyUp(code, ev) // 重要&#xff01;&#xff01; } } 注意我们标出 “重要” 的那一行代码。这行代…

20240623 每日AI必读资讯

&#x1f916;原生鸿蒙AI浓度要爆表了&#xff01; - 一年一度华为开发者大会上&#xff0c;余承东首次揭秘“鸿蒙原生智能”Harmony Intelligence&#xff01; - 华为小艺进化成系统级智能体。 - 一句话实现跨多个应用的规划和任务执行&#xff1b;在第三方APP上随意处理文…