关闭

Zephyr OS 内核篇: 执行上下文

606人阅读 评论(0) 收藏 举报
分类:

本文转载至:http://iot-fans.xyz/2016/07/28/zephyr/kernel-context/

  本文简要介绍一下 Zephyr OS 执行上下文的基本概念以及相关的 API,这是后面学习的基础。

概念

  在 Zephyr OS 中,存在三种类型的执行上下文:

  • task 上下文:task 上下文是一个可抢占的、基于优先级的线程,主要用于处理执行时间长或者比较复杂工作。task 的调度是基于优先级的,所以高优先级的 task 可以抢占低优先级的 task。Zephyr 内核支持一个可选的循环时间片功能,因此相同优先级的 task 将轮流执行,从而可以避免了某个 task 独占 CPU 的风险。
  • fiber 上下文:fiber 是一个轻量级的、不可抢占的、基于优先级的线程,主要用于设备驱动和对性能比较挑剔的工作。fiber 也是基于优先级的,因此高优先级的 fiber 比低优先级的 fiber 先被调度。不过,一个 fiber 一旦被调度,它将一直执行下去,直到它执行某个操作阻塞了自身的运行。fiber 的优先级比 task 高,因此只有在没有 fiber 的时候才会执行 task。
  • 中断上下文:中断上下文是一个特殊的上下文,用于执行中断服务程序 ISR。中断上下文的优先级比其它两种上下文的优先级都要高,所以只有在没有 ISR 时才有执行 fiber 和 task。

  其中,task 和 fiber 是线程的两种不同表现形式,但是使用相同的线程相关的数据结构和函数接口。

  所有的 task 和 fiber 都有一个唯一的线程标识符,用来唯一标识该线程。每个 task 和 fiber 也支持一个 32 位的线程自定义数据。线程自定义数据只能被 task 和 fiber 自己访问,可以被应用程序由于任何目的。默认情况下,该值为 0。

ISR 中不存在自定义数据,因为 ISR 的操作只存在共享内核中断处理上下文中。

忙等待服务

  内核允许task 或者 fiber 执行忙等待服务,即延迟一段指定的时间后再处理。这样的延迟通常使用定时器或者超时服务来完成,不需要内核执行上下文切换。

  当程序需要进行延时,但延迟的时间又很短而不能切换到其它 task 或者 fiber 的时候,就可以使用忙等待服务。在只使用超微内核的系统中,超微内核的后台task执行延迟时也需要使用忙等待服务(因为这种task不允许主动放弃CPU)。

API

sys_thread_self_get()

  该函数用于获取当前正在执行的task或者fiber的线程标识符,其函数实现如下:

1
2
3
4
nano_thread_id_t sys_thread_self_get(void)
{
return _nanokernel.current;
}

nano_thread_it_t

  返回值类型 nano_thread_it_t 定义了线程标识符的类型,其原型是 struct tcs 。struct tcs 用于描述线程的控制结构,将在下一篇《Zephyr OS 内核篇:线程模型》中介绍。

_nanokernel.current

  _nanokernel 是 Zephyr OS 定义的一个描述超微内核的全局变量,其 current 成员表示当前正在执行的上下文的线程控制结构。_nanokernel 将在《Zephyr OS 内核篇:nanokernel》中介绍。

sys_execution_context_type_get()

  该函数用于返回当前正在执行的上下文的类型:task,fiber或者是 ISR。其函数实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
nano_context_type_t sys_execution_context_type_get(void)
{
if (_IS_IN_ISR())
return NANO_CTX_ISR;
// 不是 ISR
if ((_nanokernel.current->flags & TASK) == TASK)
return NANO_CTX_TASK;
// 既不是 ISR,又不是 task,当前上下文就是 fiber。
return NANO_CTX_FIBER;
}

nano_context_type_t
  返回值类型 nano_context_type_t 定义了上下文的类型,其相关代码如下:

1
2
3
4
5
typedef int nano_context_type_t;
#define NANO_CTX_ISR (0) // 中断上下文
#define NANO_CTX_FIBER (1) // fiber 上下文
#define NANO_CTX_TASK (2) // task 上下文

_IS_IN_ISR

  通过读取 IPSR 寄存器的值来判断当前上下文是否是 ISR。在 Cortex-M3 中,IPSR 的全称是 Interrupt Program Status Register,即中断程序状态寄存器,保持了当前中断的状态。更多关于 Cortex-M3 的知识,请参考《Zephyr OS 番外篇:Cortex-M3 寄存器简介》。

_nanokernel.current->flags

  flags 记录了当前正在执行的上下文的一些标志信息,其具体描述请参考《Zephyr OS 内核篇:线程模型》。

sys_thread_custom_data_set()

  该函数用于设置当前上下文线程自定义数据,其函数实现如下:

1
2
3
4
void sys_thread_custom_data_set(void *value)
{
_nanokernel.current->custom_data = value;
}

sys_thread_custom_data_get()

  该函数返回当前上下文的线程自定义数据,其函数实现如下:

1
2
3
4
void *sys_thread_custom_data_get(void)
{
return _nanokernel.current->custom_data;
}

sys_thread_busy_wait

  该函数用于设置当前上下文的忙等待时间。由于不用切换上下文,该函数的实现很简单:在一个“死”循环里,每循环一次就判断一下时间是否到期,如果没到期则继续循环,如果到期则退出循环。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void sys_thread_busy_wait(uint32_t usec_to_wait)
{
uint32_t cycles_to_wait = (uint32_t)(
(uint64_t)usec_to_wait *
(uint64_t)sys_clock_hw_cycles_per_sec /
(uint64_t)USEC_PER_SEC
);
uint32_t start_cycles = sys_cycle_get_32();
for (;;) {
uint32_t current_cycles = sys_cycle_get_32();
// 有个疑问:cycle 可能溢出,但似乎没考虑到。
if ((current_cycles - start_cycles) >= cycles_to_wait) {
break;
}
}
}

usec_to_wait

输入参数,用于设置需要等待的时间,单位是微秒(microsecond)。

cycles_to_wait
将标准时间单位(ms)的输入参数usec_to_wait转换为硬件的时间单位(cycle)的cycles_to_wait。

注意,usec_to_wait 与 sys_clock_hw_cycles_per_sec 相乘时,会产生一个很大的数。
为了防止乘积溢出,先将其转换为uint64_t,待做完除法后再转回为 uint32_t。

sys_cycle_get_32()
该函数用于获取系统当前的硬件cycle数。

关于标准时间与硬件时间的转换关系,请参考博客《Zephyr OS 内核篇:时钟和定时器》


0
0
查看评论

Zephyr OS 系列博客索引目录

Zephyr OS 系列博客目录索引
  • tidyjiang
  • tidyjiang
  • 2016-07-29 14:14
  • 1440

Zephyr OS 内核篇:系统启动 - C 准备阶段(二)

/**  *  * @brief Prepare to and run C code  *  * This routine prepares for the execution of and runs C code.  *  * @retu...
  • lbaihao
  • lbaihao
  • 2017-08-19 21:08
  • 166

Zephyr OS之内核调度

第2章    内核调度 2.1    线程调度概念        zephyr内核是基于优先级抢占,时间片分配的实时操作系统。每当调度程序切换线程或当ISR打断当前线程运行时,内...
  • lbaihao
  • lbaihao
  • 2017-04-24 22:17
  • 310

Zephyr OS 基础篇: 系统简介

本文主要介绍在 Linux、Windows和 Mac OS上搭建开发环境的方法,并介绍如何编译应用程序、设置环境变量、使用 QEMU 仿真的方法。
  • tidyjiang
  • tidyjiang
  • 2016-07-28 22:25
  • 1496

Zephyr OS 内核篇: 内核链表

Zephyr OS 所有的学习笔记已托管到 Github,CSDN 博客里的内容只是 Github 里内容的拷贝,因此链接会有错误,请谅解。 最新的学习笔记请移步 GitHub:https://github.com/tidyjiang8/zephyr-inside 本文先简单地介绍了一些内...
  • tidyjiang
  • tidyjiang
  • 2016-10-07 17:12
  • 502

Zephyr OS 驱动篇之设备初始化顺序

Zephyr OS 驱动篇之设备初始化顺序 在前面的 Zephyr OS 驱动篇之设备驱动模型 中已讲解了 Zephyr OS 中的设备驱动模型。Zephyr OS 将设备分为 PRIMARY、SECONDARY、NANOKERNEL 等五个等级,并在系统启动的相应阶段初始化该等级内的所有设备。那...
  • lbaihao
  • lbaihao
  • 2017-08-18 23:17
  • 220

Zephyr OS 内核篇:系统启动 - C 准备阶段

在上一节的最后,代码已经跳转到 _PrepC(): void _PrepC(void) {         relocate_vector_table();       ...
  • lbaihao
  • lbaihao
  • 2017-08-18 22:56
  • 163

Zephyr OS 基础篇:系统简介

简单介绍 Zephyr OS 的概念、特征、目录结构以及学习资料。
  • tidyjiang
  • tidyjiang
  • 2016-07-28 20:42
  • 3203

Zephyr-项目介绍

Zephyr kernel是一个为资源有限系统设计的一个为内核:从简单的嵌入式环境检测传感器、LED穿戴设备到复杂的智能手表和物联网无限网关。 Zephyr被设计支持多体系架构,包含ARM Cortex-M,intel X86和ARC等等: Supported Boards The follo...
  • d_uanrock
  • d_uanrock
  • 2016-02-22 11:58
  • 1130

Zephyr OS nano 内核篇: 等待队列 wait_q

Zephyr OS 所有的学习笔记已托管到 Github,CSDN 博客里的内容只是 Github 里内容的拷贝,因此链接会有错误,请谅解。 最新的学习笔记请移步 GitHub:https://github.com/tidyjiang8/zephyr-inside 本文先描述 Zephyr...
  • tidyjiang
  • tidyjiang
  • 2016-10-07 17:13
  • 609
    个人资料
    • 访问:2747853次
    • 积分:31085
    • 等级:
    • 排名:第184名
    • 原创:433篇
    • 转载:1011篇
    • 译文:147篇
    • 评论:102条
    技术链接
    最新评论