IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 嵌入式工程师实现一个简单的操作系统(四) -> 正文阅读

[嵌入式]嵌入式工程师实现一个简单的操作系统(四)

一、前言

上一节我们实现了2个在任务中主动调用,实现任务切换的函数接口,其具有一下几个功能:

  1. 从一个循环的任务切换到另一个循环的任务

  2. 切换回来之后,从切换之前被打断的位置继续执行

  3. 这是函数调用做不到的,函数调用只能从函数开始位置执行

但是一个操作系统,大部分的调用场景会发生在定时器中断处理中,在中断环境下,我们还需要定义并实现中断环境的任务切换。

中断环境除了要保存任务的状态以外,中断本身也需要保存一些现场状态,因为中断对正常执行的程序来说,可能会发生在任意一个指令之间,所以为了退出中断之后程序还可以正确运行,需要在进出中断的过程中进行保护现场与恢复现场

二、中断环境下任务切换的流程

  1. 保存寄存器到当前任务的堆栈
  2. 调用中断处理函数
  3. 设置中断切换标志位、设置全局from任务信息、设置全局to任务信息
  4. 完成中断处理,准备退出中断
  5. 判断是否需要在退出中断时进行任务切换
  6. 如果不需要,从当前任务栈恢复寄存器,返回继续执行
  7. 如果需要进行任务切换
  8. 把任务栈中保存的寄存器信息恢复
  9. 把from任务的寄存器数据保存到from任务的堆栈已经任务结构体
  10. 把to任务堆栈中的寄存器状态恢复到当前寄存器中
  11. 退出异常,进入to任务

三、代码展示

aarch64 中断处理函数,在退出中断时,会根据标志变量判断是否需要进行任务切换操作

IRQInterruptHandler:
????//进入中断,保存寄存器
????saveregister
????savefloatregister

????//执行中断处理函数
????bl?handle_domain_irq

????//判断退出中断时候是否需要进行任务切换
????adr?x2,?task_thread_switch_interrupt_flag
????ldr?x3,?[x2]
????cmp?x3,?#1
????beq?exit_irq_with_task_switch

????//不需要任务切换,恢复寄存器之后退出中断
????restorefloatregister
????restoreregister
????eret

//如果标志置位,需要在退出中断的时候进行任务切换
exit_irq_with_task_switch:
????//将中断切换标志位清零
????adr?x2,?task_thread_switch_interrupt_flag
????mov?x3,?#0
????str?x3,?[x2]

????//恢复寄存器,恢复到进入中断之前的状态
????restorefloatregister
????restoreregister

????//此时的状态是进入中断之前的状态,也就是from任务的状态

????//开始进行任务切换

????//保存from任务的状态到堆栈

????//1?保存from任务通用寄存器状态
????sub?sp,?sp,?#30?*?8

????stp?x0,?x1,?[sp,?#16?*?0]
????stp?x2,?x3,?[sp,?#16?*?1]
????stp?x4,?x5,?[sp,?#16?*?2]
????stp?x6,?x7,?[sp,?#16?*?3]
????stp?x8,?x9,?[sp,?#16?*?4]
????stp?x10,?x11,?[sp,?#16?*?5]
????stp?x12,?x13,?[sp,?#16?*?6]
????stp?x14,?x15,?[sp,?#16?*?7]
????stp?x16,?x17,?[sp,?#16?*?8]
????stp?x18,?x19,?[sp,?#16?*?9]
????stp?x20,?x21,?[sp,?#16?*?10]
????stp?x22,?x23,?[sp,?#16?*?11]
????stp?x24,?x25,?[sp,?#16?*?12]
????stp?x26,?x27,?[sp,?#16?*?13]
????stp?x28,?x29,?[sp,?#16?*?14]
????str?x30,?[sp,?#16?*?15]

????//将from任务和to任务的任务信息恢复到x0、x1寄存器
????adr?x2,?task_interrupt_from_thread
????ldr?x0,?[x2]

????adr?x2,?task_interrupt_to_thread
????ldr?x1,?[x2]


????//2?保存from任务sp状态
????//获取当前任务sp状态
????//获取任务结构体中变量地址
????//保存sp地址到任务结构体中对应位置
????mov?x3,?sp
????mov?x2,?x0
????add?x2,?x2,?#8?*?0
????str?x3,?[x2]

????//3?保存from任务cpcr状态
????//获取当前任务spsr状态
????//获取任务结构体中spsr变量位置
????//保存spsr到任务结构体中对应位置
????mrs?x3,?spsr_el1
????mov?x2,?x0
????add?x2,?x2,?#8?*?1
????str?x3,?[x2]

????//4?保存from任务的返回地址
????//获取当前任务返回地址
????//获取任务结构体中变量地址
????//保存返回地址到任务结构体中对应位置
????mrs?x3,?elr_el1
????mov?x2,?x0
????add?x2,?x2,?#8?*?2
????str?x3,?[x2]

????//开始从to任务堆栈恢复to任务
????//1?恢复to任务sp寄存器
????mov?x2,?x1
????add?x2,?x2,?#8?*?0
????ldr?x3,?[x2]
????mov?sp,?x3

????//2?恢复to任务spsr状态寄存器
????mov?x2,?x1
????add?x2,?x2,?#8?*?1
????ldr?x3,?[x2]
????msr?spsr_el1,?x3

????//3?恢复to任务异常返回地址
????mov?x2,?x1
????add?x2,?x2,?#8?*?2
????ldr?x3,?[x2]
????msr?elr_el1,?x3

????//4?恢复to任务通用寄存器
????ldp?x0,?x1,?[sp,?#16?*?0]
????ldp?x2,?x3,?[sp,?#16?*?1]
????ldp?x4,?x5,?[sp,?#16?*?2]
????ldp?x6,?x7,?[sp,?#16?*?3]
????ldp?x8,?x9,?[sp,?#16?*?4]
????ldp?x10,?x11,?[sp,?#16?*?5]
????ldp?x12,?x13,?[sp,?#16?*?6]
????ldp?x14,?x15,?[sp,?#16?*?7]
????ldp?x16,?x17,?[sp,?#16?*?8]
????ldp?x18,?x19,?[sp,?#16?*?9]
????ldp?x20,?x21,?[sp,?#16?*?10]
????ldp?x22,?x23,?[sp,?#16?*?11]
????ldp?x24,?x25,?[sp,?#16?*?12]
????ldp?x26,?x27,?[sp,?#16?*?13]
????ldp?x28,?x29,?[sp,?#16?*?14]
????ldr?x30,?[sp,?#16?*?15]

????//数据从堆栈取出之后,堆栈指针移动
????add?sp,?sp,?#30?*?8

????//当前处理器状态已经切换到了to任务,异常返回之后到to任务执行
????eret

设置任务切换标志变量

.global?task_interrupt_from_thread;
.global?task_interrupt_to_thread;
.global?task_thread_switch_interrupt_flag;

.global?interrupt_task_switch_from_to
.type?interrupt_task_switch_from_to,?"function"
//?x0:?from
//?x1:?to
//设置切换标志为1,通过全局变量传递from和to任务信息
interrupt_task_switch_from_to:
????adr?x2,?task_thread_switch_interrupt_flag
????mov?x3,?#1
????str?x3,?[x2]

????adr?x2,?task_interrupt_from_thread
????mov?x3,?x0
????str?x3,?[x2]

????adr?x2,?task_interrupt_to_thread
????mov?x3,?x1
????str?x3,?[x2]

????ret

任务调度代码

void?timer_handler(struct?irq_desc?*desc)
{
????arch_timer_compare(arch_timer_frequecy());
????log_i("arch?timer_handler!");

????if((count++)?%?2?==?0)
????{
????????log_i("switch?to?taskb!");
????????interrupt_task_switch_from_to(&taska,?&taskb);
????}
????else
????{
????????log_i("switch?to?taska!");
????????interrupt_task_switch_from_to(&taskb,?&taska);
????}
}

运行结果

qemu-system-aarch64?-machine?virt,gic-version=3?-cpu?cortex-a57?-smp?1?-m?1024?-nographic?-serial?mon:stdio?-kernel?app
run?in?main!
[????0.002736]?EasyLogger?V2.2.99?is?initialize?success.
i?am?taska?run!?line:?20
i?am?taska?run!?line:?22
i?am?taska?run!?line:?20
i?am?taska?run!?line:?22
i?am?taska?run!?line:?20
i?am?taska?run!?line:?22
[????1.007194]?irq_enter
[????1.007440]?handle_domain_irq:?[30]
[????1.007831]?arch?timer_handler!
[????1.008077]?switch?to?taskb!
[????1.008260]?irq_exit
i?am?taskb?run!?line:?38
i?am?taskb?run!?line:?40
i?am?taskb?run!?line:?38
i?am?taskb?run!?line:?40
[????2.008983]?irq_enter
[????2.009176]?handle_domain_irq:?[30]
[????2.009412]?arch?timer_handler!
[????2.009574]?switch?to?taska!
[????2.009716]?irq_exit
i?am?taska?run!?line:?20
i?am?taska?run!?line:?22
i?am?taska?run!?line:?20
i?am?taska?run!?line:?22
i?am?taska?run!?line:?20
i?am?taska?run!?line:?22

四、操作系统的任务切换

在rtos系统中,会根据一些策略去选择一个任务去执行。

当前我们已经实现了在任务环境与中断环境下的任务切换功能。

接下来通过添加一些策略来选择合适的任务执行,就可以实现一个简单的根据优先级以及时间片去进行调度的小系统。

可以添加和丰富更多任务相关的资源以及功能。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-10-22 11:06:03  更:2021-10-22 11:08:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:38:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码