嵌入式实时操作系统11——操作系统内核运行原理
时间:2023-10-11 21:37:00
首先显示一个操作系统运行动态图
1.操作系统内核关键知识点
本文将用实际的工程例子来分析操作系统的核心操作原理。在此之前,让我们回顾一下之前文章中描述的关键知识点。
《嵌入式实时操作系统3-任务切换》讲述了任务切换的五个步骤:保存现场,保存栈指针,找出最高优先级任务,读取栈指针,恢复现场。
根据嵌入式实时操作系统4-任务调度,操作系统总是运行最高优先级任务。一旦有更高的优先级任务,操作系统将立即暂停当前任务运行更高级别的任务,同一优先级下的多个任务将通过时间片轮询依次运行。
根据嵌入式实时操作系统5-就绪表,操作系统的核心将在就绪表中存储就绪任务,核心总是从就绪表中找到最高优先级任务,并执行任务。
嵌入式实时操作系统8-等待表待表,当多任务系统中有任务需要延迟等待时,操作系统的核心将任务从就绪表移动到等待表待表的作用是帮助操作系统的核心管理需要延迟等待。
嵌入式实时操作系统1010-系统时钟节拍,定时器中断程序调用系统时钟节拍服务,系统时钟节拍服务完成:更新系统节拍时间,更新等待表和就绪表,处理时间片轮询,切换任务。
2.操作系统核运行原理
操作系统核心运行的本质是根据需要调度任务,在多个任务中找到最高优先级,并运行任务。
以驾校为例,驾校只有一辆教学车,多名学生和一名教练。根据不同的注册费,学生被分成VIP等级和普通等级,每个等级有几个学生。然后教练制定了两张表格:
1、就绪表:排队记录学生信息
2、等待表:记录正在休息的学生信息
教练只需关注就绪表,让就绪表中的学生上车练习。首先,教练检查就绪表中的优先级,判断VIP如果成绩中有学生,如果成绩中有学生,VIP等级有学生,教练优先VIP的学员上车练习,只有等VIP学生完成练习,放弃练习,轮到普通学生上车练习。
如果一个学生需要上厕所20分钟,教练会从就绪表中删除学生的名字,并将他的名字放入等待表中。在此期间,他不会考虑让学生上车练习。
20分钟后,当学生上完厕所回来时,教练从等待表中删除了学生的名字,并在就绪表中添加了他的名字。假设此时正在练习的是普通学生,休息的学生是VIP学生(并希望练习汽车),敬业的教练应立即让普通学生停止练习,让VIP学生优先练习。如果休息的学生有一个普通的水平,让他继续等待,同一水平的学生轮流执行。
动态如下:
3.工程描述
通过驾校的例子,我们对操作系统核心的工作原理有了初步的了解。接下来,我们将根据实际项目深入研究操作系统核心是如何工作的。
本工程是一种应用于智能家具的多功能空调面板。该面板的主要功能是控制家庭的温度和湿度。多功能面板的实物如下:
多功能空调面板工程硬件基于国内GD基于软件的系列芯片FreeRTOS操作系统。
多功能空调面板主要有LCD按键输入,温湿度检查三个功能模块。软件工程设计为以下三个任务:
1.温湿度读取任务优先级高。任务设计为每个间隔4ms读取温湿度传感器,读取温湿度数据后,将数据发送到显示任务。
2、按键任务,优先级为低。任务设计为持续扫描4个按键,监测按键是否按下,并能识别按键长按和连击,有按键触发后,将按键数据发给显示任务。
3.显示任务优先级低。任务设计为根据接收到的温湿度数据显示温湿度;根据接收到的关键数据切换显示界面。
4.操作系统运行分析
main函数中设置SysTick定时器为1ms定期创建显示任务、按键任务和温湿度读取任务。main代码如下:
/* github: liyinuo2017 author:liwei */ int32_t main(void) {
/* 配置系统时钟 */ system_clk_init(); /*显示任务*/ xTaskCreate((TaskFunction_t )display_task, (const char* )"display", (uint16_t )SIZE_512, (void* )NULL, (UBaseType_t )LOW_PRIO, (TaskHandle_t* )NULL); /*按键任务*/ xTaskCreate((TaskFunction_t )button_task, const char* )"button",
(uint16_t )SIZE_256,
(void* )NULL,
(UBaseType_t )LOW_PRIO,
(TaskHandle_t* )NULL);
/*温湿度读取任务*/
xTaskCreate((TaskFunction_t )temp_humi_task,
(const char* )"temp_humi",
(uint16_t )SIZE_256,
(void* )NULL,
(UBaseType_t )HIGH_PRIO,
(TaskHandle_t* )NULL);
/* 任务调度 */
vTaskStartScheduler();
while(1);
}
显示任务,按键任务和温湿度读取任务这3个任务的代码如下:
/* github: liyinuo2017 author:liwei */
/*lcd显示任务 */
void display_task(void *pvParameters)
{
/* 初始化 */
display_init();
for(;;)
{
/* 数据更新 ,运行 时间1ms*/
display_data_updata();
/* 显示更新 , 运行 时间1ms*/
display_handle();
}
}
/* 按键任务 */
void button_task(void *pvParameters)
{
/* 初始化 */
button_init();
for(;;)
{
/* 按键扫描 , 运行 时间1ms*/
button_scanf();
/* 按键数据发送给显示任务 , 运行 时间1ms*/
button_data_send();
}
}
/* 温湿度读取任务 */
void temp_humi_task(void *pvParameters)
{
/* 初始化 */
temp_humi_init();
for(;;)
{
/* 读取数据, 运行 时间1ms*/
data_read_calc();
/* 数据发送给显示任务 , 运行 时间1ms*/
temp_humi_data_send();
}
}
执行vTaskStartScheduler函数后,操作系统内核开始任务调度,操作系统的状态如下图:
操作系统启动运行,由于HIGH_PRIO优先级为任务最高优先级,因此操作系统内核让温度读取任务开始运行,当温度读取任务完成读取温湿度数据,并将数据发送给显示任务。
温度读取任务完成相应操作后执行延时等待,操作系统内核会将温度读取任务从就绪表中移除,将温度读取任务添加到等待表中,更新优先级表,切换任务。动态如如下:
当温度读取任务进入等待队列后,LOW_PRIO优先级为任务最高优先级,该优先级下有显示任务和按键任务,显示任务在就绪表前端,显示任务先运行。 动态如如下:
显示任务运行1ms后,定时器周期产生中断,系统时钟节拍服务被执行,更新系统时间,检查等待表,并执行时间片轮询操作,**显示任务被移动到就绪表末端,按键任务来到就绪表前端,**中断返回前执行任务切换,按键任务开始运行。
按键任务运行1ms后,定时器周期产生中断,系统时钟节拍服务被执行,更新系统时间,检查等待表,并执行时间片轮询操作,按**键任务被移动到就绪表末端,显示任务来到就绪表前端,**中断返回前执行任务切换,显示任务开始运行。动态如如下:
系统时钟节拍服务被执行后,更新系统时间,检查等待表,此时温度读取任务完成延时等待,操作系统内核会温度读取任务从等待表中移除,将温度读取任务添加到就绪表中,更新优先级表,由于HIGH_PRIO优先级为任务最高优先级,切换任务,温度读取任务开始运行。动态如如下:
软件工程运行的整个动态过程如下图:
未完待续…
实时操作系统系列将持续更新
创作不易希望朋友们点赞,转发,评论,关注。
您的点赞,转发,评论,关注将是我持续更新的动力
作者:李巍
Github:liyinuoman2017