国庆假期学门新技术,拒绝只做crud boy, 就从操作系统开始(二)

国庆假期学门新技术,拒绝只做crud boy, 就从操作系统开始(二)_第1张图片

老板说我技术需要有长进,不能只做一个crud boy。 于是我选来选去,终于选定了,来学习操作系统。因为操作系统一直被看做是计算机软件的基石。

本系列是我学习操作系统的笔记,操作系统是以AliOS Things为例子。其他的操作系统也是差不多。

本文主要是讲操作系统的定时器管理,后面会有更多的操作系统内容介绍。

国庆假期学门新技术,拒绝只做crud boy, 就从操作系统开始 - 中断管理
 

1、背景

定时器,顾名思义,是指从指定的时刻开始,经过一个指定的时间,然后触发一个超时事件,用户可以自定义定时器的周期与频率。跟生活中的闹钟类似,我们可以设置闹钟每天什么时候响,还可以设置响的次数,是响一次还是每天都响。

在嵌入式系统中,我们往往需要跟时间相关的操作。比如任务的延时调度、任务的周期性运行等。基于对时钟精确的要求,每个运行的芯片平台都会提供相应的硬件定时机制。

操作系统中最小的时间单位是系统时钟节拍(OS Tick)。本章主要介绍基于硬件定时机制的系统时钟节拍,和基于时钟节拍的软件定时器。软件定时器是AliOS Things中的一个重要模块,使用软件定时器可以方便的实现一些与超时或周期性相关的功能。

本章也将从AliOS Things软件定时器的API入手,来分析AliOS Things软件定时器的运行机理。读完本章,我们将了解系统时钟节拍是如何产生的,并学会如何使用AliOS Things软件定时器。

定时器有硬件定时器和软件定时器之分,首先介绍硬件定时器。

2、AliOS Things 定时器管理

2.1、硬件定时器介绍

硬件定时器是芯片平台本身提供的定时功能。一般是由外部晶振作为输入时钟提供给芯片,芯片向软件模块提供可配置能力,接受控制输入,在到达设定的时间后芯片产生时钟中断,用户在中断服务函数中处理信息。芯片的外部晶振一般选用MHZ级别,所以硬件定时器的精度很高,可以达到纳秒级别。

目前芯片平台一般会提供两种定时模式,原理如下:

  1. 倒计数模式:硬件定时器提供一个count寄存器配置,设定其初始值后,其随着定时时钟的频率计数递减,递减频率即为定时器频率。当计数值为0时,定时结束,触发对应的定时处理。如果是周期模式,可以设置其每次计数为0后自动复位的count起始计数值(一般也通过寄存器设置),以此来设置触发周期。
  2. 正计数模式:硬件定时器提供两个基本的寄存器配置——count寄存器和compare寄存器配置。count寄存器的值会随着时钟频率计数递增,当其达到compare设定的值后,即触发对应的定时处理。如果是周期模式,则需要按照时钟频率和延时周期来设置后续的compare值,即在上一次的定时处理内,设置下一次的compare寄存器。

上述两种方式具体参考所使用的芯片平台手册。

2.2、系统时钟节拍工作机制

  在嵌入式系统中,通常软件定时器以系统节拍为计时单位。时钟节拍是嵌入式操作操作系统OS运行的“心跳”,任何操作系统都需要提供一个时钟节拍,用于处理所有与时间相关的事件,如任务的延时、任务的时间片轮转调度、软件定时器的超时事件等。

时钟节拍是特定的周期性中断,其本质就是基于芯片的硬件定时机制所设置的一个基础硬件定时器,定时周期一般是1~100ms。在AliOS Things中,系统节拍的长度可以根据

RHINO_CONFIG_TICKS_PER_SECOND

这个宏的定义来调整(该宏在k_config.h中有定义)。

系统时钟节拍的值等于1/RHINO_CONFIG_TICKS_PER_SECOND秒。比如:HaaS100和HaaS EDU平台上,RHINO_CONFIG_TICKS_PER_SECOND的值定义为1000,那么时钟节拍就是1/1000秒,即1ms,也就是每1ms系统会“心跳”一次,产生一个tick中断。

由于系统时钟节拍定义了系统中定时器的精度,系统可以根据实际系统CPU的处理能力和实时性需求设置合适的数值,系统节拍周期的值越小,精度越高,但是系统开销也将越大,因为在1秒中系统进入时钟中断的次数也就越多。

2.2.1、时钟节拍的实现方式

时钟节拍由芯片的硬件定时器产生,硬件定时器配置为中断触发模式。如果操作系统希望1ms能产生一次定时触发,则必须将1ms转换为定时器的cycle计数值,并将此cycle值按照实际倒计数或者正计数的模式来配置定时器的相关寄存器。

配置定时器的cycle间隔功能一般由相关芯片平台的驱动提供,不同芯片平台的配置方式略有差别,读者可参考平台适配的代码。

时钟节拍tick的处理指的是每次tick周期触发时,操作系统需要进行的处理。AliOS Things提供了统一的tick函数入口krhino_tick_proc,将此函数加入tick定时器中断处理函数,以此来达到屏蔽硬件差异的目的。

以HaaS100开发板为例,在SysTick_Handler中断处理函数中调用AliOS Things的tick调度函数krhino_tick_proc:

void SysTick_Handler(void)

{

      /* 进入中断 */

      krhino_intrpt_enter();

      /* tick isr */

      krhino_tick_proc();

    /* 退出中断 */

      krhino_intrpt_exit();

}

void krhino_tick_proc(void)

{

#if (RHINO_CONFIG_USER_HOOK > 0)

    krhino_tick_hook();

#endif

 

    tick_list_update(1);

 

#if (RHINO_CONFIG_SCHED_RR > 0)

    time_slice_update();

#endif

}

可以看到每经过一个时钟节拍,由操作系统维护的tick值(即系统时间)就会加1,同时会检查当前任务的时间片是否用完,以及是否有定时器超时。具体代码请参考k_time.c文件。

2.2.2、时钟节拍常用接口

时钟节拍(tick模块)提供了几个维测接口用来获取基本的tick信息。

函数名

描述

sys_time_t krhino_sys_tick_get(void)

返回当前的系统节拍值

单位:tick数

sys_time_t krhino_sys_time_get(void)

返回当前的系统时间

单位:ms

tick_t  krhino_ms_to_ticks(sys_time_t ms)

将当前ms数转换为tick计数

sys_time_t krhino_ticks_to_ms(tick_t ticks)

将当前tick计数转换为ms值

 2.3、软件定时器工作机制

2.3.1、软件定时器介绍

AliOS Things操作系统提供软件实现的定时器

  1. 指定时间到达后要调用回调函数(也称超时函数),用户在回调函数中处理信息。
  2. 软件定时器是由操作系统提供统一API接口供用户使用。
  3. 软件定时器要以时钟节拍(OS Tick)的时间长度为单位,定时周期必须是OS Tick的整数倍,例如AliOS Things OS Tick是10ms,那么上层软件定时器只能是10ms、20ms、100ms等,而不能定时为15ms。

AliOS Things提供的软件定时器支持单次模式和周期模式。

  1. 单次模式:当用户创建了定时器并启动了定时器后,定时时间到了,只执行一次回调函数之后,系统就将该定时器删除,不再重新执行。
  2. 周期模式:定时器会按照设置的定时时间循环执行回调函数,直到用户将定时器停止或者删除,否则将永远执行下去。

2.3.2、软件定时器工作机制

AliOS Things软件定时器模块维护着三个重要的全局变量:

  1. 当前系统经过的tick时间g_tick_count(当硬件定时器中断来临时,它将加1)。
  2. 定时器链表g_timer_head。系统新创建并激活开始运行的定时器都会以超过时间排序的方式插g_timer_head链表中。
  3. 定时器事件队列g_timer_queue,它是一个消息队列buf_queue,系统中所有软件定时器的开始、停止、改变参数、删除等事件都会发送到这个定时器事件队列中依次得到处理。

如图所示:

假设系统当前的tick值为30,在当前系统中已经创建并启动了3个定时器,分别是定时时间为50个tick的timer1、100个tick的time2和500个tick的timer3,这3个定时器分别加上系统当前时间g_tick_count=50,按照从小到大的顺序链接在g_timer_head链表中,形成如下图所示的定时器链表结构。

国庆假期学门新技术,拒绝只做crud boy, 就从操作系统开始(二)_第2张图片    

同时,g_tick_count随着硬件定时器的触发一直在增长(每次硬件定时器中断来临时,g_tick_count加1),50个tick以后,g_tick_count从30增长到80,与timer1的timeout值相等,这时会触发与timer1定时器相关联的超时处理函数,同时将timer1从g_timer_head链表上删除。同理,100个tick和500个tick过去后,与timer2和timer3定时器相关联的超时处理函数会被触发,接着将timer2和timer定时器从g_timer_head链表中删除。

如果系统当前定时器状态在10个tick后(g_tick_count=40)有一个任务新创建了一个tick值为300的timer4定时器,定时器事件队列g_timer_queue会收到这个并处理这个定时器新创建的事件,由于timer4定时器的timerout=40+300=340,因此它将被按序插入到timer2和timer3定时器中间,形成如下图所示的链表结构。

2.3.3、AliOS Things软件定时器任务

AliOS Thing会在kernel初始化的时候,创建一个优先级相对较高的软件定时器任务timer_task,这是AliOS Thing软件定时器的主处理任务,可以及时处理定时器事件,流程如下:

2.4、软件定时器使用方法

上节介绍了AliOS Things软件定时器,并对定时器的工作机制进行了介绍,本节将深入介绍定时器的各个接口,帮助用户在代码层次上理解AliOS Things软件定时器。

相应的API接口汇总如下:

定时器初始化

ktimer_init(void)

创建一个定时器

aos_timer_new

创建一个定时器

aos_timer_new_ext

删除一个定时器

aos_timer_free

开始一个定时器

aos_timer_start

停止一个定时器

aos_timer_stop

改变定时器的参数

aos_timer_change

下面具体介绍这些接口的使用。

2.4.1、软件定时器模块初始化

使用软件定时器timer模块,在系统启动时需要初始化定时器管理系统。可以通过下面的接口完成:

void  ktimer_init(void)

此接口主要完成三个工作:

  1. 初始化timer队列g_timer_head;
  2. 初始化timer定时器管理buffer队列g_timer_queue;
  3. 创建定时器基本处理任务g_timer_task。

 

2.4.2、软件定时器的创建和删除

int aos_timer_new(aos_timer_t *timer,void (*fn)(void *, void *),

void *arg, int ms, int repeat)

调用该接口后,内核首先次从动态内存堆中分配一个定时器控制块,然后对该控制块进行基本的初始化。其中的各参数和返回值说明见下表。

参数

描述

timer

软件定时器管理句柄

fn

定时器超时函数(当定时器超时时,系统会调用这个函数)

arg

定时器超时函数的入口参数(当定时器超时时,调用超时函数会把这个参数作为入口参数传递给超时函数)

ms

定时器超时时间(单位ms),即间隔多少时间执行fn

repeat

周期定时或单次定时(1:周期,0:单次)

返回

描述

0

定时器创建成功,并自动开始运行

非0

定时器创建失败

系统不再使用软件定时器时,可使用下面的函数接口。

void aos_timer_free(aos_timer_t *timer)

调用该接口后,系统会把定时器从g_timer_head链表中删除,然后释放相应的定时器控制块,其中的各参数和返回值说明见下表。

参数

描述

timer

软件定时器管理句柄,指向要删除的定时器

2.4.3、软件定时器的启动和停止

如果使用aos_timer_new_ext创建了定时器,没有启动定时器,需要在主动调用启动定时器函数接口后才能开始工作,启动定时器接口如下:

int aos_timer_start(aos_timer_t *timer)

参数描述如下表

参数

描述

timer

软件定时器管理句柄,指向要启动的定时器

返回

描述

0

定时器启动成功

非0

定时器启动失败

启动定时器后,如果要停止它,可以使用下面的函数接口:

int aos_timer_stop(aos_timer_t *timer)

参数描述如下表

参数

描述

timer

软件定时器管理句柄,指向要停止的定时器

返回

描述

0

定时器停止成功

非0

定时器停止失败

2.4.4、软件定时器的控制

AliOS Things还提供了修改定时器参数的接口

int aos_timer_change(aos_timer_t *timer, int ms)

参数描述如下表

参数

描述

timer

软件定时器管理句柄,指向要修改的定时器

ms

新的定时器超时时间(单位ms),即间隔多少时间执行定时器超时处理函数

返回

描述

0

定时器修改成功

非0

定时器修改失败

注意:需要在定时器处于未启动状态时才能修改。

3、总结

AliOS Things的定时器管理包括了硬件定时器(时钟节拍心跳机制)和软件定时器管理。其中,软件定时器的工作机制,是将所有定时器的callback事件、定时器的管理事件(创建、启动、停止、删除、改变参数)都通过内置的g_timer_queue 发送到后台的高优先级任务timer_task中去执行。

开发者技术支持

如需更多技术支持,可加入钉钉开发者群,或者关注微信公众号

更多技术与解决方案介绍,请访问阿里云AIoT首页阿里云IoT - 所知不止于感知

 

 

你可能感兴趣的:(AliOS,Things,3.3.0,python,操作系统,物联网,嵌入式)