嵌入式实时操作系统的设计与开发

news2024/11/16 0:42:40

时钟管理

在RTOS中,时钟具有非常重要的作用,通过时钟可实现延时任务、周期性触发任务执行、任务有限等待的计时。

大多数嵌入式系统有两种时钟源,分别为实时时钟RTC(Real-Time Clock)和定时器/计数器。
实时时钟一般是靠电池供电,即使系统断电,也可以维持日期和时间。由于实时时钟独立于操作系统,因此也被称为硬件时钟,它为整个系统提供一个时间标准。
嵌入式处理器通常集成了多个定时器或计数器,实时内核需要一个定时器作为系统时钟,并由内核控制系统时钟工作。

一般而言,实时时钟是系统时钟的基准,实时内核通过读取实时时钟来初始化系统时钟,此后,二者保持同步运行,共同维持系统时钟。
因此,系统时钟只有当系统运行起来以后才有效,并且由实时内核完全控制。

定时器一般由晶体振荡器提供周期信号源,并通过程序对其计数寄存器进行设置,让其产生固定周期的脉冲,每次脉冲的产生都触发一个时钟中断,时钟中断的频率既是系统的心跳,也称为时基或Tick,Tick的大小决定了整个系统的时间粒度。

在这里插入图片描述
晶体振荡器提供周期信号源,它通过Bus总线连接到CPU核上,开发人员设定计数寄存器的初始值,随后,每一个晶体振荡器输入信号都会导致该值增加,当计数器溢出时,就产生一个输出脉冲(Pulse),输出脉冲可以用来触发CPU核上的一个中断。
输出脉冲是RTOS的硬件基础,因为它将送到中断控制器上,产生中断信号,触发时钟中断,由时钟中断服务程序维持系统时钟的正常工作。

实时内核的时间管理以系统时钟为基础,通过Tick处理程序来实现。
定时器产生中断后,RTOS将响应并执行器中断服务程序,并在中断服务程序中调用Tick处理函数,它作为实时内核的一部分,与具体的定时器/计数器无关,由系统时钟中断服务程序调用,使内核具有对不同定时器/计数器的适应性。

在内核层初始化中,重要的一步就是通过acoral_intr_attach()将时钟中断服务程序与Ticks处理程序进行绑定。
这样,每当定时器产生一个输出脉冲(Pulse),输出脉冲就向CPU发出一个时钟中断,找到内核层对应的时钟中断号,最终将执行该中断号对应的服务程序,即Ticks处理函数aCoral_Ticks_entry()。

内核时钟管理的绝大部分工作都在aCoral_Ticks_entry()进行的,如线程延迟操作time_delay_deal()、超时处理timeout_delay_deal()、与调度策略相关的操作(如时间片轮转调度)等。

如果任务采用时间片轮转调度,则需要再Ticks处理程序中对当前正在运行的任务已执行的时间进行“+1”操作。执行完该操作后,如果任务的已执行时间同任务时间片相等,则表示任务使用完一个时间片的执行时间,需要通过acoral_sched()触发重调度。

如果开发人员在线程中调用acoral_delay_thread()对线程进行延迟操作,则会让当前运行线程从运行(Running)状态切换到挂起(Suspend)状态,并将其挂载到一个等待队列“acoral_list_t waiting”,这里的等待队列也称为时间等待链,用来存放需要延迟处理的任务。
接下来每当定时器产生一个Tick,Tick处理函数aCoral_Ticks_entry()的time_delay_deal()需要对时间等待链中线程的剩余等待时间进行“减1”操作,如果某个线程的剩余等待时间被减到了0,则将该线程从等待队列中移出,挂载到就绪队列,通过acoral_sched()触发重调度。

如,开发人员用acoral_delay_thread()将线程A、B、C、D分别延迟。
通常情况下,每当定时器产生一个Tick,time_delay_deal()会对时间等待链中的每一个结点进行“减1”操作。
若时间等待链的结点数越多,时钟中断的Tick处理函数的计算开销就比较大,从而降低系统性能。

为了提高系统性能,减小计算开销,可采用差分时间等待链来描述延迟队列。
在这里插入图片描述
队列中某个结点的值是相对于前一个结点的时间差。
当采用查分时间等待链后,每当时钟中断产生一个Tick,只需对队列头部结点进行“减1”操作,当减到0时,就将其从等待链中取下,后续结点将成为新的头部,并且被激活。
等待链其它结点的值保持不变,无须对每一个结点进行“减1”操作,这样可减小计算开销。

如果有新线程要进行延迟操作,需要往差分时间等待链中插入新的结点,如线程E要延迟7Ticks。
只需要在线程B(3+2)和C(3+2+5)中插入线程E即可。再修改结点C的值即可(10-7)。

acoral_list_t time_delay_queue; //线程延时队列,调用线程delay相关函数的线程都会被加到这个队列上,等待一段具体时间后重新被唤醒。

acoral_list_t timeout_queue; //aCoral获取资源(互斥量)超时等待队列,即在timeout时间内获取即成功,否则超时失败。
void time_delay_deal()
{
	acoral_list_t *tmp,*tmp1,*head;
	acoral_thread_t *thread;
	head = &time_delay_queue; //获取时间等待链的头部
	if(acoral_list_empty(head))
		return;
	thread = list_entry(head->next,acoral_thread_t,waiting); //获取时间等待链头结点对应的TCB地址
	thread->delay--; //对时间等待链头结点对应线程delay成员的剩余等待时间
	for(tmp=head->next;tmp!=head;)
	{
		if(thread->delay > 0) //如果头结点线程delay成员大于0,则退出
			break;
		//delay=0,线程延迟结束
		tmp1 = tmp>next;
		acoral_list_del(&thread->waiting); //将该线程从时间等待链中删除
		tmp = tmp1;
		thread->state &= ~ACORAL_THREAD_STATE_DELAY; //将线程切换为就绪态	
		acoral_rdy_thread(thread); //将其挂到就绪队列上
	}
}

waiting成员主要用来将线程结构挂到相应链表队列,是一个双向链表结构。

struct acoral_list{
	struct acoral_list *next,*prev;
};

以就绪队列ready为例,当用户调用了acoral_rdy_thread或acoral_resume_thread接口时,就会将线程挂到就绪队列acoral_ready_queue上。
在这里插入图片描述

acoral_list_t policy_list;
void acoral_policy_delay_deal()
{
	acoral_list_t *tmp,*head;
	acoral_sched_policy_t *policy_ctrl;
	head = &policy_list;
	tmp = head;
	for(tmp=head->next;tmp!=head;tmp=tmp->next)
	{
		policy_ctrl = list_entry(tmp,acoral_sched_policy_list,list);
		if(policy_ctrl->delay_deal!=NULL)
			policy_ctrl->delay_deal();
	}
}
void period_policy_init(void)
{
	acoral_init_list(&period_delay_queue);
	period_policy.type=ACORAL_SCHED_POLICY_PERIOD;
	period_policy.policy_thread_init=period_policy_thread_init;
	period_policy.policy_thread_release=period_policy_thread_release;
	period_policy.delay_deal=period_delay_deal;
	period_policy.name="period";
	acoral_register_sched_policy(&period_policy);
}
typedef struct{
	unsigned int time; //线程周期,单位为ms
	void (*route)(void *args); //线程函数
	void *args; //线程函数的参数
}period_private_data_t; //周期线程私有数据块,用于保存自己的周期、函数体,以便在新周期重新挂载线程时使用。
acoral_list_t period_delay_queue; //周期线程专用延时队列,只要是周期线程,就会被挂载到这个队列上,
void period_delay_deal()
{
	acoral_list_t *tmp,*tmp1,*head;
	acoral_thread_t *thread;
	period_private_data_t * private_data;
	head = &period_delay_queue;
	if(acoral_list_empty(head))
		return;
	thread = list_entry(head->next,acoral_thread_t,waiting);
	thread->delay--;
	for(tmp=head->next;tmp!=head;){
		thread = list_entry(tmp,acoral_thread_t,waiting);
		if(thread->delay > 0)
			break;
		private->data = thread->private_data;
		tmp1 = tmp->next; //保存下一个周期延时队列上的结点
		acoral_list_del(&thread->waiting);
		tmp = tmp1;
		if(thread->state & ACORAL_THREAD_STATE_SUSPEND){
			thread->stack = (unsigned int *)((char *)thread->stack_buttom+thread->stack_size - 4);
			HAL_STACK_INIT(&thread->stack,private_data->route,period_thread_exit,private_data->args);
			acoral_rdy_thread(thread);
		}
		period_thread_delay(thread,private_data->time);
	}
}

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

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

相关文章

jvm——内存模型

1.java内存模型 1.1 原子性 1.2 问题分析 这里与局部变量自增不同,局部变量调用iinc是在局部变量表槽位上进行自增。 静态变量是在操作数栈自增。 这里的主内存和工作内存时再JMM里的说法。 因为操作系统是时间片切换的多个线程轮流使用CPU. 1.3解决方法 JMM中…

2023京东酒类市场数据分析(京东数据开放平台)

根据鲸参谋平台的数据统计,今年7月份京东平台酒类环比集体下滑,接下来我们一起来看白酒、啤酒、葡萄酒的详情数据。 首先来看白酒市场。 鲸参谋数据显示,7月份京东平台白酒的销量为210万,环比下滑约49%;销售额将近19…

前端需要理解的数据结构与算法知识

1 数组 1.1 集合、列表、数组的联系与区别 集合:由一个或多个确定的元素所构成的整体。类型不一定相同、确定、无序、互异。 列表(又称线性列表):按照一定的线性顺序,排列而成的数据项的集合。类型不一定相同、有序…

opencv实现全景图像拼接

目录 部分代码展示: 效果演示 查看处理过程 历史记录 完整演示视频: 完整代码链接 部分代码展示: 效果演示 查看处理过程 历史记录 完整演示视频: 无法粘贴视频........ 完整代码链接 视频和代码都已上传百度网盘&#x…

Kafka 简介 + 学习笔记

消息队列 先说明消息队列是什么: 亚马逊: 消息队列是一种异步的服务间通信方式,适用于微服务架构。消息在被处理和删除之前一直存储在队列上。每条消息仅可被一位用户处理一次。消息队列可被用于分离重量级处理、缓冲或批处理工作以及缓解高…

机器学习基础之《分类算法(5)—朴素贝叶斯算法原理》

一、朴素贝叶斯算法 1、什么是朴素贝叶斯分类方法 之前用KNN算法,分类完直接有个结果,但是朴素贝叶斯分完之后会出现一些概率值,比如: 这六个类别,它都有一定的可能性 再比如,对文章进行分类:…

element Collapse 折叠面板 绑定事件

1. 点击面板触发事件 change <el-collapse accordion v-model"activeNames" change"handleChange"><el-collapse-item title"一致性 Consistency"><div>与现实生活一致&#xff1a;与现实生活的流程、逻辑保持一致&#xff0c…

【附安装包】Fireworks 8安装教程

软件下载 软件&#xff1a;Fireworks版本&#xff1a;8语言&#xff1a;简体中文大小&#xff1a;88.3M安装环境&#xff1a;Win11/Win10/Win8/Win7硬件要求&#xff1a;CPU2.0GHz 内存4G(或更高&#xff09;下载通道①百度网盘丨下载链接&#xff1a;https://pan.baidu.com/s…

NetMarvel机器学习促广告收益最大化,加速获客

游戏出海的竞争日益激烈&#xff0c;这并非空穴来风。 从2021年第一季度至2022年第四季度&#xff0c;iOS平台的CPI增长了88%&#xff0c;意味着厂商需要花费近两倍的钱才能获取一个新用户。与此同时数据隐私政策持续收紧&#xff0c;更加提高了营销成本。 在成本高涨的当下&…

Java 中的集合类有哪些?如何分类的?

面试回答 Java 的整个集合框架中&#xff0c;主要分为 List、Set、Queue、Stack、Map 等五种数据结构。其中&#xff0c;前四种数据结构都是单一元素的集合&#xff0c;而最后的 Map 则是以 KV 对的形式使用。 从继承关系上讲&#xff0c;List、Set、Queue都是 Collection 的子…

uniapp 微信小程序:RecorderManager 录音DEMO

uniapp 微信小程序&#xff1a;RecorderManager 录音DEMO 简介index.vue参考资料 简介 使用 RecorderManager 实现录音。及相关的基本操作。&#xff08;获取文件信息&#xff0c;上传文件&#xff09; 此图包含Demo中用于上传测试的服务端程序upload.exe&#xff0c;下载后用…

基于Java+SpringBoot+vue前后端分离体育馆使用预约平台设计实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

Tensor-动手学深度学习-李沐_笔记

介绍 Tensor&#xff0c;又称"张量"&#xff0c;其实就是n维度数组。不同维度的Tensor示意图如下&#xff1a; 关于Tensor.reshape reshape函数可以处理总元素个数相同的任何新形状&#xff0c;【3&#xff0c;2&#xff0c;5】->【3&#xff0c;10】->【5&a…

论文笔记: One Fits All:Power General Time Series Analysis by Pretrained LM

1 intro 时间序列领域预训练模型/foundation 模型的研究还不是很多 主要挑战是缺乏大量的数据来训练用于时间序列分析的基础模型——>论文利用预训练的语言模型进行通用的时间序列分析 为各种时间序列任务提供了一个统一的框架 论文还调查了为什么从语言领域预训练的Transf…

GEE/PIE遥感大数据处理与典型案例丨数据整合Reduce、云端数据可视化、数据导入导出及资产管理、机器学习算法等

目录 ​专题一&#xff1a;初识GEE和PIE遥感云平台 专题二&#xff1a;GEE和PIE影像大数据处理基础 专题三&#xff1a;数据整合Reduce 专题四&#xff1a;云端数据可视化 专题五&#xff1a;数据导入导出及资产管理 专题六&#xff1a;机器学习算法 专题七&#xff1a;…

Spring Cloud Nacos详解

目录 1、Spring Cloud Nacos详细介绍2、Spring Cloud Nacos具体案列 Spring Cloud Nacos 是一个由阿里巴巴集团开发的开源分布式系统服务发现、配置管理和服务管理的平台。Nacos 支持多种服务发现方式&#xff0c;包括 DNS 方式、HTTP 和 RPC 方式&#xff0c;同时提供了灵活的…

GFPGAN 集成Flask 接口化改造

GFPGAN是一款腾讯开源的人脸高清修复模型&#xff0c;基于github上提供的demo&#xff0c;可以简单的集成Flask以实现功能接口化。 GFPGAN的安装&#xff0c;Flask的安装请参见其他文章。 如若使用POSTMAN进行测试&#xff0c;需使用POST方式&#xff0c;form-data的请求体&am…

camshift, pca,协方差

最近复习opencv的东西&#xff0c; 看到camshift https://www.youtube.com/watch?va9KZjQ4e6IA&listPL6Yc5OUgcoTmTGACTa__vnifNA744Cz-q&index30 https://medium.com/claudio.vindimian/understanding-and-implementing-the-camshift-object-tracking-algorithm-pyt…

【现场问题】oracle 11g 和12c 使用jdbc链接,兼容的问题

oracle不同版本 问题是什么寻找解决方式首先Oracle的jdbc链接有几种形式?Oracle 11g的链接是什么呢Oracle 12C的链接是什么呢我的代码是哪种&#xff01;&#xff1f;发现问题没 解决问题代码 问题是什么 项目上建立Oracle数据源&#xff0c;以前大部分都是&#xff0c;11g的…

树模型与集成学习:LightGBM

目录 树模型与集成学习 LightGBM 的贡献 LightGBM 的贡献&#xff1a;单边梯度抽样算法 LightGBM 的贡献&#xff1a;直方图算法 LightGBM 的贡献&#xff1a;互斥特征捆绑算法 LightGBM 的贡献&#xff1a;深度限制的 Leaf-wise 算法 树模型与集成学习 树模型是非常好的…