zephyr-内核初级手册

这部分包括zephyr内核生态系统的以下四个方面:

  • System Fundamentals
  • Kernel Fundamentals
  • Application Fundamentals
  • Source Tree Structure

System Fundamentals

An application image is a binary that controls the operation of a hardware system, or of a simulated system running under QEMU. Each application image contains both the application’s code and the Zephyr kernel code needed to support it. They are compiled as a single, fully-linked binary.

应用镜像是一个控制对硬件系统或运行在QEMU之下的模拟器操作的二进制文件。每个应用镜像包含应用代码和所需的zephyr内核代码,它们都被作为独立,全链接的二进制文件被编译(翻译得可能不准,理解fully-linked的意思后再来修改)

Once an application image has been loaded onto a target system, the image takes control of the system, initializes it, and runs forever as the system’s sole application. Both application code and kernel code execute as privileged code within a single shared address space.

一旦一个应用镜像被加载到目标系统,镜像就将接受系统的控制,初始化并永远作为系统的唯一应用运行。应用代码和内核代码在一个单独的共享地址空间内斗作为特权代码运行。


An application is a set of user-supplied files that the Zephyr build system processes to generate an application image. The application consists of application-specific code, a collection of kernel configuration settings, and at least one Makefile. The application’s kernel configuration settings enable the build system to create a kernel tailor-made to meet the needs of the application and to make the best use of the system’s resources.

一个应用是一系列用户提供的用来在zephyr编译系统处理以生成应用镜像的源文件(我们通常的应用在这里指的是应用镜像)。应用包含一系列的应用特定代码,一系列的内核配置设置和至少一个Makefile文件。应用的内核配置设置使得编译系统可以创建一个内核裁剪-这符合让应用成为系统最合适的资源的需求(精简)

The Zephyr Kernel supports a variety of target systems, known as boards; each board has its own set of hardware devices and capabilities. One or more board configurations are defined for a given board; each board configuration indicates how the devices that may be present on the board are to be used by the kernel. The board and board configuration concepts make it possible to develop a single application that can be used by a set of related target systems, or even target systems based on different CPU architectures.

zephyr内核支持一系列的目标系统,比如各种开发板;每个开发板都包含它自身的硬件和能力。指定的开发板会拥有一个或多个配置;每个开发板配置都反映开发板上的设备将如何被内核使用。开发板和开发板配置思想使得开发一个可以被各种相近目标平台使用的应用成为可能,甚至目标系统基于不同的CPU架构。

(Android及现在各种操作系统应该都是这样的board+board configuration思想)


Kernel Fundamentals

这部分提供对zephyr内核的概念和能力的高层次的概览

Organization

zephyr内核的核心元素是microkernel和底层的nanokernel。内核当然也包含一系列的辅助子系统,包含设备相关的库和网络软件。

应用可以使用microkernel和nanokernel或者单独使用nanokernel作开发。

nanokernel是一个拥有基本内核特性集合的高性能,多线程可执行环境。nanokernel是一个针对低内存或只有简单多线程要求的系统的解决方案(kernel本身最少只需要2KB的空间!)。这样系统的例子有:嵌入式传感器总线,环境传感器,简单的LED可穿戴设备和商场存货清单标签。

(好像比较底层,面向于近乎硬件= =)

microkernel为nanokernel提供更为丰富的内核特性。microkernel适合拥有健壮内存的系统(50到900KB),并行通信设备(比如WIFI和低功耗蓝牙),以及并行数据处理任务。这样系统的例子有:可穿戴健身设备,智能手表和物联网无线网关。


(就是说microkernel是核心nanokernel的一个补充)

相关的章节参看:

Related sections:

  • Common Kernel Services
  • Nanokernel Services
  • Microkernel Services

Multi-threading

zephyr内核为三种可执行上下文提供多线程处理

task context是一个可抢占线程(context本质是一种线程?),通常用于处理长时间和复杂任务。任务调度基于优先级,所以高优先级任务的执行会抢占低优先级任务。内核也支持可选时间循环切片功能,所以相同优先级的任务会轮流执行,不会发生一个任务独占CPU的情况。

fiber context 是一个轻量级的非抢占线程,通常用于设备驱动和高性能要求的工作。Fiber 调度基于优先级,所以高优先级的fiber会比低优先级fiber先执行;然而,一旦一个fiber被调度,它将会一直执行,直到一个操作被触发来阻塞自身的运行。fiber的运行优先级比task高,所以仅当没有fiber被调度的时候才运行task

(阐述了fiber context 和task context的区别)

interrupt context是一种用于执行ISR终端服务程序的特殊内核context。interrupt context的优先级最高,所以仅当没有ISR需要运行的时候才运行task和fiber。


Zephyr microkernel不限制应用中使用的task和fiber的数量;然而,只使用nanokernel的应用将被限制为single task模式。

Related sections:

  • Nanokernel Fiber Services
  • Microkernel Task Services

Interrupts

zephyr 内核通过中断句柄处理支持硬件中断和软件中断,也就是ISRs。中断处理有比task和fiber更高的优先级,所以ISR会在任何需要的时候抢占当前被调度的task和fiber。

内核同样也支持嵌套的中断处理,允许高优先级的ISR中断低优先级的ISR。


nanokernel 为少量中断资源(IRQs)提供中断服务程序(ISRs),比如硬件时钟计时设备和系统控制台设备。所有中断服务资源对应的中断服务程序都以设备驱动或应用代码的方式提供。每一个中断服务程序都可以在编译的时候注册到内核中,但也可以在内核启动和运行之后再动态注册。Zephyr 支持C语言编写的中断服务程序,但也允许使用汇编语言。


当中断服务程序不能及时处理完一个中断的情况下,内核的同步机制和数据传输机制可以将剩下的处理切换给fiber或task。microkernel提供了一个任务IRQ对象类型,使得可以及时将切换流交给task以使得完全不需要设备驱动或者应用代码来支持中断服务程序。


Related sections:

  • Nanokernel Interrupt Services
  • Microkernel Interrupt Services

Clocks and Timers

内核时钟基于名为ticks的时间单元,ticks拥有一个可配置的时间周期。64位系统时钟会统计内核开始执行后流逝的ticks次数。


Zephyr也支持高分辨率的硬件时钟,可以用来测量要求sub-stick级别精度的时间。

nanockernel 允许fiber或线程基于系统时钟运行基于时间的处理。可以通过使用支持timeout参数的nanokernel API来完成,或者通过在指定ticks数目之后使用一个timer 对象来设置到期时间。


microkernel也允许tasks使用timeouts和timers来运行基于时间的处理。microkerne timers拥有nanokernel timers没有提供的额外功能,比如周期性的失效模式。

Related sections:

  • Kernel Clocks
  • Nanokernel Timer Services
  • Microkernel Timers Services

Data Passing

Zephyr内核提供6中类型的对象来允许不同的上下文交换数据。


microkernel 提供以下对象类型。这些类型被设计用于tasks,而不能用于fibers和ISRs。


一个microkernel的FIFO是一个允许tasks以异步first in, first out方式交换固定大小数据项的队列机制。

一个mailbox是一个允许tasks以同步first in, first out方式交换不定大小数据项的队列机制。Mailboxes 也支持同步交换,并且允许tasks使用同一个mailbox以匿名或不匿名的方式交换消息。

一个pipe 是一个允许task发送字节流到其他task的队列机制。pipe支持同步和异步交换。


nanokernel提供了一下对象类型。这些类型主要被设计用于fibers,只有一部分限制功能可以被用于tasks和ISRs。


一个nanokernel FIFO是一个允许上下文以异步,first-in,first-out方式交换不定大小数据项的队列机制。

一个nanokernel LIFO 是一个允许上下文 异步,last-in,first-out方式交换不定大小数据项的队列机制。

一个nanokernel stack 是一个允许上下文以异步,first-in,first-out方式交换32位数据项的队列机制。(为毛指定32位的数据呢?)

上面的每一个类型都有会影响在具体场合适当使用的特定的功能和限制条件。更多细节,参看每个指定对象类型的文档:

Related sections:

  • Microkernel Data Passing Services
  • Nanokernel Data Passing Services

Dynamic Memory Allocation

Zephyr 内核要求所有系统资源在编译时定义,因此只提供为动态内存分配提供有限的支持。这个支持可以被用来代替像malloc()和free()这样的C标准库调用,虽然有些地方不同。

microkernel提供两种类型的对象以允许tasks动态地分配内存块。这些对象类型不恩能够被用于fibers和ISRs。

一个memory map 是一个支持单个固定大小内存动态分配和释放的内存区域。应用可以拥有多个memory maps,这些区块(maps中的内存块)的大小和容量可以被分别指定。

一个memory pool 是一个支持多个固定大小内存动态分配和释放的内存区域。当应用请求不同大小的内存块时,这允许更加有效地使用可用内存。一个应用可以拥有多个memory pool,这些区块(pool中的内存区块)的大小和容量可以被分别指定。

nanokernel不提供动态内存分配功能。

For additional information see:

  • Microkernel Memory Maps
  • Microkernel Pools


Public and Private Microkernel Objects

Microkernel 对象,比如 semaphores,mailboxes,或者tasks,通常可以被定义为公有对象或私有对象。


一个公有对象(public object)是一个可以被应用所有部分正常访问的对象。任何包含了zephyr.h的代码都可以通过引用对象名的方式和这个对象交互。

一个私有对象(private object)是一个只允许应用特定部分使用的对象,比如一个单独的设备驱动或者子系统。这个对象的名字只在当其被编码进对象定义的文件中时才可见,通常情况下都被隐藏,除非定义这个对象的代码通过额外步骤将这个名称共享给其他文件。


除了它们定义的方式和使对象名具有不同的可见性,相同类型的公有对象和私有对象使用相同的API来进行操作。


在大多数情况下,将一个给定的microkernel对象定义为public对象还是private对象仅仅是看哪一种方便。比如,当定义一个服务器类型的子系统用来处理不同客户端的需求时,通常定义为public对象。

注意:

Nanokernel对象类型只可以被定义为private对象。这意味着一个nanokernel对象定义的时候必须用一个全局变量来允许它可以被其他文件中的代码访问。


Microkernel Server

microkernel 的很多操作,包括microkernel对象使用特定的microkernel 服务fiber,都会调用 _k_server()

(这里需要确定这个fiber到底是个什么概念,直接翻译似乎并不能表述其意思)

当一个task调用和microkernel对象类型相关的API时,比如task_fifo_put(),这个相关的操作并不会直接执行,而是通常按照以下步骤进行:

1.task创建一个命令包,命令包中包含目标操作需要的输入参数

2.task将命令包压入microkernel 服务的命令栈。然后内核抢占task并调度microkernel 服务。

3.microkernel服务将命令包从其命令栈中出栈并出发目标操作。所有操作的输出参数,比如返回代码都会保存在命令包中。

4.当命令执行完成,microkernel服务会去其当前的空命令栈中获取命令包从而被阻塞。然后内核就调度这个请求任务。

5.task处理命令包的输出参数来决定这个操作的结果


在某些情况下,实际的顺序可能会和上面的指导略有区别。比如这个操作出发了一个高优先级的任务运行,请求任务就会直到高优先级的任务被首次调度后才会被内核调度。此外也有少数的操作,包括microkernel对象的一些操作完全不需要使用命令包。


这种间接调用似乎看起来不怎么高效,但这种方式有一些很重要的好处:

1.microkernel服务的所有操作在竞态条件下天生地自由;操作被一个单独的fiber串行地处理,而不会被其他task和fiber抢占。

这意味着microkernel服务可以在任何操作中灵敏地处理系统中的microkernel对象,而不需要花费额外的步骤来防止其他上下文的干扰。

2.microkernel操作对中断延迟时间的影响最小;中断绝不会在重要时期被锁定,从而避免了竞态条件。

3.microkernel 服务可以很容易地通过创建额外的命令包并将其压入命令栈来将复杂操作分解成两个或多个简单操作

4.系统的总内存需求下降了;一个使用microkernel对象的task为了完成操作,仅仅需要为上面步骤的第一步提供一个栈的空间就可以(而非为上面所有的步骤)

上面主要是描述内核“用命令栈(command stack)+命令包(command packet)的方式来代替直接处理命令”的设计及其优点】

For additional information see:

  • Microkernel Server Fiber

Standard C Library

zephyr内核当前值提供内核自身所需的标准C库的最小集合,主要是字符串操作和显示。

需要使用更加丰富C库的应用可以拓展当前已经存在的库或者使用一个(当前已存在库的)替换库。


Device Driver Library

zephyr 内核支持一系列的设备驱动。指定的设备驱动程序可以由应用根据相关的硬件组件和设备驱动程序,通过配置开发板配置变量来进行使用。

当前所有已支持的开发板配置中的设备驱动程序如下:

Interrupt controller(中断控制)。nanokernel的中断管理子系统中使用到的设备驱动

Timer。内核的系统始终和硬件时钟子系统中使用到的设备驱动

Serial Communication。内核的控制台子系统中用到的设备驱动。

Random number generator。提供随机种子数的设备驱动


重要提示:当前设备驱动的实现中不产生有序值的是随机数。


Networking Library

这部分简要减少了网络子系统的框架(还没有在官网文档中补充上来,等待后续更新)



Application Fundamentals

一个zephyr 应用可以通过在一个目录下创建以下文件来得到:

Application source code files 一个应用通常提供一个或多个应用特定的文件,由C或汇编语言编写,这些文件通常在一个src子目录下。

Kernel configurations files。一个应用通常提供一个.conf文件制定一个或多个内核配置项的值。缺省情况下,会使用应用中存在的内核配置项的值,如果不存在默认值,这个默认的配置项就会被使用。

一个microkernel应用通常会提供一个额外的后缀名为.mdef的microkernel 定义文件。这个文件定义了所有的系统共有microkernel对象。这个文件在只使用nanokernel的应用中不被使用。

Make file 这个文件通常包含少数的几行来告诉编译系统从哪里去寻找上面提到的源文件和目标开发板配置以及内核类型(microkernel和nanokernel都是这样)


一旦应用被创建,它就可以通过简单的一条明路进行编译,编译结果(包括应用镜像)都在名为outdir的子目录下。

For additional information see:

  • Application Development Primer

Source Tree Structure

Zephyr 的源码树提供了一下顶级目录,每一个都可能拥有一个或多个不同深度的此处暂未介绍到子目录


arch

指定体系架构的nanokernel和平台的代码。每一个支持的体系架构都有其自己的子目录,子目录中可能包含含有以下内容的子目录:

  • architecture-specific nanokernel source files
  • architecture-specific nanokernel include files for private APIs
  • platform-specific code
boards

开发板相关的代码和配置文件

doc

Zephyr 文档相关的材料和工具

drivers

设备驱动程序

include

lib目录之外的头文件和所有公有API

kernel
Microkernel 代码及独立架构的nanokernel代码
lib
Library 代码, 包含最小体量的标准C库
misc
杂项代码
net
Networking 代码, 包括蓝牙协议栈和网络协议栈
samples
microkernel,nanokernel,蓝牙协议栈和网络协议栈的示例应用
tests
各种内核特性的 测试代码和基准
scripts
各种用于编译和测试zphyr应用的程序及其他文件

你可能感兴趣的:(zephyr)