第4回 RTOS的一个例子

一个实例简单明了告诉你为什么要用RTOS 一个实例简单明了告诉你为什么要用RTOS 时间:2018-03-01来源:互联网作者: 标签:单片机RTOS 对于搞单片机的特别用8051系列工程师来说,谈到单片机的RTOS,很多时候会问一句:“为什么要用RTOS?单片机就这一点资源,使用RTOS能保证效率吗?” 对于这个问题,我会反问:“你用单片机的目的是什么?是为了用单片机的C编程,单片机的汇编编程甚至于用单片机的二进制... 阅读详情
 
我们马上来看看实时操作系统的内部构造.这次我们以函数wup_tsk()为例子来进行解说. 我们的目的是学习RTOS的代码的读法和处理的流程,所以我们不会一行一行的分析代码,而是把主要的代码和要点拿出来分析.

1.概要

这次我们围绕在任务之间切换调用的时候是如何处理的为主题,来看看里面的代码实现.
关于任务A和任务B的动作在下面解说.


关于任务A,内核, 任务B的动作,请看下图



【図4-1 各个任务和内核的处理流程】

现在我们来看看相对在任务A中,函数slp_tsk()调用等待后, 任务B中在函数wup_tsk调用,在回去通知任务A之前的内核的处理.也就是上图中标记颜色的部分.这次我们以掌握主要的流程为目的进行学习.
下图是wup_tsk函数在调用完返回任务A的流程的处理概要【図4-2】.


【図4-2 wup_tsk(任务A)发行后内核的处理流程】
那么就让我们来看看实际的代码把,这次我们来看图4-2的流程.

2.wup_tsk()函数调用

函数wup_tsk()的作用是:把唤醒等待状态的任务变成等待解除状态.
让我们来看看实际的代码.
132 ER
133 wup_tsk(ID tskid)
134 {
135 TCB *p_tcb;
136 ER ercd;
137 
138 LOG_WUP_TSK_ENTER(tskid); //ログをとるためのマクロ
139 CHECK_TSKCTX_UNL();  //CPUロック状態でないかどうかをチェック
140 CHECK_TSKID_SELF(tskid);  //タスクIDのチェック
141 p_tcb = get_tcb_self(tskid);  //TCBへのポインタを取り出す ⇒ ①
142 
143 t_lock_cpu();  //CPUロック状態へ ⇒ ②
144 if (TSTAT_DORMANT(p_tcb->tstat)) { //そのタスクが休止状態かどうか ⇒ ③
145 ercd = E_OBJ;
146 }
147 else if (TSTAT_WAIT_SLP(p_tcb->tstat)) { //対象タスクが起床待ち状態かどうか ⇒ ④
148 if (wait_complete(p_tcb)) {  //戻り値は,ディスパッチが必要かどうか ⇒ ⑤
149 dispatch();  //ディスパッチを行う関数 ⇒ ⑥
150 }
151 ercd = E_OK;
152 }
153 else if (!(p_tcb->wupque)) {
154 p_tcb->wupque = TRUE;
155 ercd = E_OK;
156 }
157 else {
158 ercd = E_QOVR;
159 }
160 t_unlock_cpu();
161 
162 error_exit:
163 LOG_WUP_TSK_LEAVE(ercd);
164 return(ercd);
165 }

在函数wup_tsk()中,对象任务的ID通过参数tskid来传入.
那么在理解了流程的基础上让我们来看看要点的说明.
①141行目 取出 对象任务(任务A)的TCB指针. 内容保存在指针p_tcb里面.
②143行目锁住CPU .
    函数wup_tsk()在调用过程中,会把唤醒等待状态的任务变成等待解除状态.如果对象任务是未登陆状态或者休止状态的话,就出现ERROR.这次,对象任务A是在唤醒等待状态,所以让我们来看看唤醒等待状态.
③144行目 在TCB中,根据保存任务的状态的地方(p_tcb->tstat)的值的不同,在这里判断是否解除等待,如果是休止状态的话,就返回ERROR.
④147行目  对象任务A是否处在唤醒等待状态下,如果是的话就返回TRUE
⑤148行目 确认wait_complete(p_tcb)的返回值,具体做了什么请参照wait_complete()函数的说明.是否调用dispatch就取决于这个函数的返回值.
⑥149行目 等待解除以后,如果有必要的话就呼出dispatch(),呼出dispatch()函数以后任务之间就进行切换.

3.wait_complete()函数

等待解除函数
107 wait_complete(TCB *p_tcb) 
108 {
109     wait_dequeue_tmevtb(p_tcb);
110     p_tcb->p_winfo->wercd = E_OK; // ⇒ ①
111     return(make_non_wait(p_tcb));  // ⇒ ②
①110行目 等待解除的时候在放ErrorCode的地方放入E_OK. 关于唤醒等待的管理方法,以后在进行说明.
②111行目 调用函数make_non_wait().

4.make_non_wait()函数

在等待状态里面,其实是有很多种类的状态的.关于这些等待状态的管理将在以后进行说明.在这个函数里面,对象任务处于一个什么样的状态,不是双重等待状态,而是单纯的等待状态是否可以变成执行可能状态就在这个函数里面进行确认.
 
80 Inline BOOL
81 make_non_wait(TCB *p_tcb)
82 {
83     assert(TSTAT_WAITING(p_tcb->tstat)); //待ち状態もしくは,二重待ち状態か ⇒ ①
84 
85     if (!TSTAT_SUSPENDED(p_tcb->tstat)) { //二重待ち状態でなければ(つまり待ち状態)⇒ ②
86         /*
87          *  待ち状態から実行できる状態への遷移
88          */
89         return(make_runnable(p_tcb));  // ⇒ ③
90     }
91     else {
92         /*
93          *  二重待ち状態から強制待ち状態への遷移
94          */
95         p_tcb->tstat = TS_SUSPENDED;
96         LOG_TSKSTAT(p_tcb);
97         return(FALSE);
98     }
99 }

①83行目 在这里确认是等待状态还是双重等待状态
②85行目 确认对象任务A 在单纯的等待状态而非强制等待状态下, 变成执行可能状态.
③89行目 转变成执行可能状态.详细请参照 make_runnable() .

5.make_runnable()


变成执行可能的状态.
232 BOOL
233 make_runnable(TCB *p_tcb)
234 {
235     uint_t  pri = p_tcb->priority;
236 
237     p_tcb->tstat = TS_RUNNABLE;	//対象タスクTCBの現在の状態を「実行できる状態」へ ⇒ ①
238     LOG_TSKSTAT(p_tcb);
239     queue_insert_prev(&(ready_queue[pri]), &(p_tcb->task_queue));
240     primap_set(pri);
241 
242     if (p_schedtsk == (TCB *) NULL || pri < p_schedtsk->priority) { //⇒ ②
243         p_schedtsk = p_tcb;	//⇒ ③
244         return(dspflg);		//⇒ ④
245     }
246     return(FALSE);
247 }

①237行目 把对象任务A的状态位(p_tcb->tstat)改成执行可能的状态. 
②239,240行目 把这个任务插入到等待队列的最后面.关于等待队列的构造和管理方法将在以后说明.    

重要!
 为了妥善管理好任务队列,在等待队列中把拥有最高的优先顺序的任务通过变量:p_schedtsdk来进行管理.
 
判断p_schedtsdk是否需要更新.
在任务A已经变成执行可能状态以后, 在下面两个条件下,需要更新最高优先度的指针p_schedtsdk.

②242行目
1.目前没有执行可能的任务
    p_schedtsk == (TCB *) NULL

2.对象任务A的优先度比现在最高优先度的任务还要高的时候
    pri < p_schedtsk->priority (优先度值越小越优先)

③243行目 满足条件的时候,使p_schedtsk指向对象任务A.
④244行目 对象任务A已经变成了最高优先度(p_schedtsdk已经更新),所以就有必要进行dispatch了.在这里执行了return(dspflg)以后,就回到了wup_tsk()函数中的wait_complete()函数这里. dispatch如果是保留状态的时候dspflg的值为FALSE,反之则为TRUE.在这个情况下因为disflg等于TRUE的缘故, dispatch就被调用了.关于dispatch函数将在以后的章节中说明.

这次,以函数wup_tsk()为例子,对RTOS中的一小部分的代码完成了解析.想深入学习的还要知道一些对象结构的相关知识.接下来的一章中,我们就来看看SH3结构.
TI-RTOS之初体验(1) 自从学单片机以来,陆续接触了一些嵌入式操作系统,从最开始的51单片机,叫做rtx51_tiny,就是在keil C51安装后,例程里边自带一个实时操作系统例程,可以用它来建立多个任务(函数)同时执行的应用,官方例程实现了一个交通灯控制,嘿嘿,可能90%的人都忽略了它的存在。没错,就是最普通的51单片机也是可以跑操作系统的。 到后来,学习了uc/OS II, 很经典的嵌入式操作系统,适合学习原理用,... 阅读详情

相关推荐

如何学习RTOS

RT-Thread这个系统还是有很多自己的想法在里面的,比如Finish,设备树等都是参照Linux的思想来设计的。

Maril02的博客 3817

RTOS实例

UCOS是Micrium公司出品的RTOS类实时操作系统, UCOS目前有两个版本:UCOSII和UCOSIII。UCOSIII是一个可裁剪、可剥夺型的多任务内核,而且没有任务数限制,提供了实时操作系统所需的所有功能,包括资源管理、同步、任务通信等。UCOSIII是用C和汇编来写的,其中绝大部分都是用C语言编写的,只有极少数的与处理器密切相关的部分代码才是用汇编写的, UCOSIII结构简洁,可读性很强!非常适合初次接触嵌入式实时操作系统学生、嵌入式系统开发人员和爱好者学习。什么是任务?

qq_67882143的博客 1387

RTOS系统1-基础

1、前后台系统与RTOS系统1.1.前后台 早期嵌入式开发没有嵌入式操作系统的概念 ,直接操作裸机,在裸机上写程序,比如用51单片机基本就没有操作系统的概念。通常把程序分为两部分:前台系统和后台系统。     简单的小系统通常是前后台系统,这样的程序包括一个死循环和若干个中断服务程序:应用程序是一个无限循环,循环中调用API函数完成所需的操作,这个大循环就叫做后台系统。中断服务程序用于处理系统的异...

Musing的博客 7173

linux调度--wait与complete

wait与complete机制涉及的主要数据结构为struct completion,所有的操作都围绕该数据结构来进行。 让我们来看看该数据结构的成员: struct completion { unsigned int done; wait_queue_head_t wait; } done:表示事件完成的状态,为0时表示还有任务在等待事件的发生,非0时表示所有等待的事件已

u011955950的专栏 1783

手写一个 RTOS

这篇文章剖析了一个基于STM32F103C8的简易RTOS实现,通过代码实例揭示了RTOS的核心机制: 任务本质是"可恢复的CPU现场",通过TCB记录独立栈空间和寄存器状态 关键设计包括: 创建任务时伪造异常返回栈帧 PendSV实现低优先级上下文切换 SVC启动首个任务 就绪队列+优先级调度算法 系统节拍驱动延时队列 实现了完整调度链路: 任务创建→延时阻塞→定时唤醒→上下文切换 演示了动态任务创建/删除等核心功能 存在数组越界等安全隐患需优化 该实现虽精简(约2KB内存),但清晰展

weixin_73256081的博客 356

SRAM故障排查实战:如何用Nano Prober定位6T存储单元的异常点

本文详细介绍了在SRAM故障排查中,如何运用Nano Prober(纳米探针)技术精准定位6T存储单元的内部异常。面对传统方法难以发现的电性参数漂移(如晶体管阈值电压偏移)或微小物理缺陷,Nano Prober能直接对单个6T单元内的晶体管进行I-V特性测量,结合失效模式分析,有效解决读写错误等疑难问题,是芯片失效分析的关键工具。

v5w6x的博客 668

linux kernel中的wait_for_completion和complete总结

文章目录结构体init_completioncompletewait_for_completion 结构体 struct completion { unsigned int done; wait_queue_head_t wait; }; #define UINT_MAX (~0U) init_completion #define init_completion(x) __init_completion(x) static inline void __init_completion(struct

baron-周贺贺-代码改变世界ctw 7802

龙虾 Skill 技能库|OpenClaw+Hermes 全集成 一键调用所有 AI 技能

龙虾 Skill 技能库、OpenClaw、Hermes Agent、AI 技能集成、本地 AI 自动化、办公工具、数字员工

weixin_42219287的博客 625

“RTOS:实时应用的操作系统”

程序是计算机被编程执行的一组预定的顺序活动。约翰·冯·诺依曼在 1945 年描述的现代计算机中的程序包括一系列指令,机器一次执行一个指令。应用程序通常存储在计算机可以访问的位置。第一个命令被提供给计算机,它在接收下一个命令之前执行它。指令使用的信息也可以在存储空间或内存中找到。请记住,程序是描述如何处理应用程序或用户输入的另一种独特类型的数据。就什么刺激它们以及它们如何持续运行而言,计算机程序可以分为交互式或批处理:-

yihanss的博客 1737

微信小程序 实现拼图功能

微信小程序 实现碎片拼图

weixin_45689786的博客 2251

STM32+ST7789屏实战:手把手教你打造物理按键控制的3级菜单GUI(附完整代码)

本文详细介绍了如何使用STM32和ST7789屏构建物理按键控制的3级菜单GUI系统。从硬件架构设计、SPI驱动配置到菜单状态机实现,提供了完整的代码示例和优化技巧,帮助开发者快速掌握嵌入式GUI开发的核心技术。

iii12的专栏 236

rtos在嵌入式应用概述

通过RTOS的精确定时和控制能力,嵌入式系统可以高效管理生产线,实现自动化生产。RTOS确保了生产过程中的实时响应和精确控制,提高了生产效率和质量。实际上,随着嵌入式技术的不断发展,RTOS的应用场景也在不断扩展。智能家居:在智能家居系统中,RTOS用于控制各种智能设备,如智能灯泡、智能插座、智能门锁等。医疗设备:RTOS在医疗设备中的应用也至关重要。RTOS确保了数据的实时采集、传输和处理,为医生提供准确的诊断依据。RTOS提供了高精度的定时和调度机制,确保无人机和机器人能够实时响应指令,完成各种任务。

MHD0815的博客 685

Python读取ECMWF grib数据;Anaconda配置eccodes和cfgrib环境及安装过程

python读取grib数据,eccodes,cfgrib安装。

qq_36714629的博客 2244

FreeRTOS10例程学习(一)

官网下载source-code-for-book-examples压缩包,解压后得到VS工程,打开source-code-for-book-examples\Win32-simulator-MSVC\RTOSDemo.sln后有Examples001-025。 Examples001,任务创建 包含头文件 /* FreeRTOS.org includes. */ #include &amp;quot;Fr...

FreeFO的博客 5546

Libero SoC v2021.1离线安装与IP核配置全攻略

本文详细介绍了Libero SoC v2021.1在离线环境下的完整安装与配置流程。核心内容包括如何选择正确的离线安装包、获取并配置许可证、安装与挂载MegaVault IP库,以及将ModelSim仿真器切换至免费SE模式的关键步骤。文章旨在帮助内网开发者避开常见陷阱,顺利完成FPGA开发环境的搭建。

weixin_29279101的博客 411

锐捷路由器DNS Proxy保姆级配置教程:从零到实战,手把手教你搞定内网域名解析

本文提供锐捷路由器DNS Proxy功能的详细配置教程,从基础环境搭建到实战测试,手把手教你实现内网域名解析。涵盖上游DNS设置、内网域名映射、故障排查等关键步骤,帮助网络管理员快速解决内网访问难题,提升工作效率。

weixin_29284657的博客 556

如何判断一个项目是否需要使用RTOS

本文简单介绍了什么是RTOS,并给出了系统化地权衡一个项目是否需要使用RTOS的方法,最后列举了一些国际国内主流的RTOS系统

Mooney_yuan的专栏 1658

5.6华为OD机试真题 新系统 - 匹配命令行前缀关键字 (Java/Py/C/C++/Js/Go)

5.6华为OD机试真题 新系统 - 匹配命令行前缀关键字本文整理华为 OD 机试新系统机考真题库,涵盖高频考点精析与完整题目内容,提供 C 语言、Java、C++、Python、Go、JavaScript 多语言源码实现,搭配详细解题思路讲解,并支持在线 OJ 刷题练习,助力高效备考华为 OD 机试新系统。

算法大师! 2129

自己写一个RTOS系统

自己从零到一写出来的简易RTOS系统,用于学习和记录

dalin 3436

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Linux 与 RTOS的主要区别到底是啥?

看了不少博客,浏览量最多的也是详细的介绍了这两种系统,可我对这种操作系统的界限还是很模糊(当然我知道Linux,功能更强大),我想要的答案是,为啥在Linux功能这么强大的情况下,RTOS还能有一席之地,我想这也是他们的主要区别。在经过查阅资料后,我想我得到了答案

KUNPLAYBOY的博客 3万+

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

【TDA4】源码更新编译和运行(Linux+RTOS mode)

目录说明一、下载源码二、准备文件三、设置环境(首次编译需要)四、编译PSDK Linux五、编译PSDK RTOS六、运行测试 说明 硬件平台:TI TDA4VM 开发环境:Ubuntu 20.04 SDK参考: Processor SDK Linux for J721e 08_02_00 Processor SDK RTOS J721E 08_02_00 一、下载源码 进入TI 官网,下载所需内容。链接:PROCESSOR-SDK-J721E ti-processor-sdk-linux-j7-evm

weixin_37270872的博客 7114

如何手搓一个RTOS?

两年前学过RTOS,最近找工作重新捋一遍,顺便自己写一个轻量级的RTOS,主要目的是用来学习,实现了内存管理、任务创建、延时、删除、调度,经过简单测试后可以正常运行,但是在很多地方还不够完善,或许有bug,欢迎反馈。

weixin_44543366的博客 1132

RTOS 入门(1):什么是 RTOS ?试手 FreeRTOS

需要注意的是,ESP32 并不运行 Vanilla-FreeRTOS,为了支持双核芯片,在原生 FreeRTOS 基础上进行了修改,使其支持 SMP(对称多处理)。函数创建一个任务并且只在指定的 CPU 运行,这是 ESP32 独有的函数,与 vanilla FreeRTOS 中。但是基础的语法依旧是保持一致的,所以依赖 ESP32 程序库的 FreeRTOS 直接学习也不失为一个好的选择。任务优先级从 0 开始,一直到 config 中定义的最大优先级,ESP32 默认的最大优先级是 24。

joker520522的博客 3719

用 STM32F407VET6 建一个简易 RTOS(不依赖 FreeRTOS)

本文基于STM32F407VET6和Cortex-M4架构,从寄存器层面实现一个极简RTOS,深入剖析SysTick、PendSV和上下文切换机制,揭示任务调度的底层原理。通过构建任务控制块、手动管理堆栈和实现调度器,帮助理解RTOS核心运作过程。

l3m4n的博客 683

HI3861学习笔记(4)——CMSIS-RTOS2接口

一、CMSIS-RTOS2接口简介 CMSIS是Cortex微控制器软件接口标准(Cortex Microcontroller Software Interface Standard)是ARM和一些编译器厂家以及半导体厂家共同遵循的一套标准,是由ARM专门针对Cortex-M系列提出的标准。在该标准的约定下,ARM和芯片厂商会提供一些通用的API接口来访问Cortex内核以及一些专用外设,以减少更换芯片以及开发工具等移植工作所带来的金钱以及时间上的消耗。 **CMSIS-RTOS2(CMSIS-RTOS

Leung的博客 3333

CMSIS-RTOS2简介

CMSIS-RTOS2

propor的专栏 2598
上一篇: 第18回 函数tslp_tsk的式样
下一篇: C++技术面试题目
进击的横打
博客等级 码龄19年 2万+粉丝 1299原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值