系统时间
System Time
介绍
在前面的一篇文章中介绍了实时操作系统环境中的时间概念,以及与时间相关的设施的概念,这些设施可能与RTOS一起使用。
时钟滴答声
所有的计时设备都由一个硬件时钟驱动。这只是一个振荡器,它以固定的间隔产生一个中断。为了使定时数对应用程序有意义,必须知道振荡器的频率。
时钟中断服务程序
由硬件时钟产生的中断必须由中断服务例程(ISR)适当地处理,它实现了RTOS的所有定时功能。Nucleus SE中时钟ISR的详细信息将在以后的文章中介绍。
计时设置
Nucleus RTO和Nucleus SE包括许多计时设施:
滴答时钟-这是一个简单的计数器,由时钟ISR递增。在Nucleus RTOS和Nucleus SE中,这个计数器是32位宽的,任务可以设置和读取它的值。在Nucleus SE中,计时时钟是可选的。本章余下部分将更详细地讨论这一主题。
应用程序计时器–Nucleus RTO和Nucleus SE都支持计时器对象。
时间片调度——在Nucleus RTO中,相同优先级的任务按循环调度,但也可以应用时间片。在Nucleus SE中,时间片调度器是一个选项;这在前面的文章中详细讨论过。
任务睡眠。任务可以选择在指定的时间段内挂起(进入休眠状态)。
API调用超时-在Nucleus RTO和Nucleus SE中,许多API调用允许任务挂起,等待资源的可用性。这种暂停可以是不确定的,或者在Nucleus RTOS中,可以指定可选的超时时间。Nucleus SE不支持API调用超时。
准确度
在这一点上,简短地谈一下计时精度是值得的。
定时设备的精度完全取决于时钟振荡器的频率。例如,如果每隔10毫秒接收一个脉冲,而应用程序任务想要延迟100毫秒,则显然需要等待10个脉冲。然而,目前尚不清楚上一次脉冲发生的时间——可能是现在,也可能是近10毫秒前。因此,100毫秒的延迟可能长达(略低于)110毫秒。
解决这个问题的一个明显的方法是增加振荡器的频率。如果脉冲以1毫秒的间隔出现,100毫秒的延迟永远不会超过101毫秒。缺点是时钟ISR将花费10倍的CPU时间,这是一个开销。
系统设计者必须确定所需定时器精度和可用CPU功率之间的平衡。
配置系统时间
与Nucleus SE的大多数方面一样,系统时间的配置主要由nuse_config.h中的#define语句控制。密钥设置是NUSE_SYSTEM_TIME_SUPPORT,这将启用该功能。指定对象的数量是没有问题的-系统时间只是启用或不启用。
选择非零值是系统时间的“主启用”。这将导致定义一个数据结构,本文稍后将对此进行详细介绍。它还激活API启用设置。
API启用
Nucleus SE中的每个API函数(服务调用)在nuse_config.h中都有一个启用的#define符号。对于系统时间,这些是:
NUSE_CLOCK_SET
NUSE_CLOCK_RETRIEVE
默认情况下,这两个值都设置为FALSE,从而禁用每个服务调用并禁止包含任何实现代码。要为应用程序配置系统时间,需要选择要使用的API调用并将其启用符号设置为TRUE。
默认情况下,从配置文件nuse_config.h中提取。
#define NUSE_SYSTEM_TIME_SUPPORT FALSE /* Enables the system
tick clock */#define NUSE_CLOCK_SET FALSE /* Service call enabler */#define NUSE_CLOCK_RETRIEVE FALSE /* Service call enabler */
如果启用了系统时API函数而未启用系统时功能,则会导致编译时错误。如果您的代码使用尚未启用的API调用,则会导致链接时间错误,因为应用程序中不会包含任何实现代码。
系统时间服务调用
Nucleus RTOS支持与系统时间相关的两个服务调用,它们提供以下功能:
设置系统时间值。由Nucleus SE中的NUSE_Clock_Set()实现。
获取系统时间值。由Nucleus SE中的NUSE_Clock_Retrieve()实现。
将详细检查每个服务调用的实现。
系统时间设置和获取服务
唯一可以对系统时间值执行的操作是将其设置为一个值并获取(检索)其当前值。Nucleus RTOS和Nucleus SE各自为这些操作提供了两个基本的API调用,这里将对此进行讨论。
系统时间值的解释取决于应用程序,因为它只是对自上次重置计数器以来的时钟“滴答”次数的计数。要使用此信息,必须知道时钟振荡器的频率。
设置时间
任何任务都可以通过调用此API函数来设置系统时间。
用于设置时间的Nucleus RTOS API调用
Service call prototype:
VOID NU_Set_Clock(UNSIGNED new_value);
Parameters:
new_value – the value to which the system time is to be set
Returns:
none.
Nucleus SE API Call for Setting Time
This API call supports the key functionality of the Nucleus RTOS API.
Service call prototype:
void NUSE_Clock_Set(U32 new_value);
Parameters:
new_value – the value to which the system time is to be set
Returns:
none.
设置时间的Nucleus SE实现
代码非常简单。提供的值只是存储在一个关键部分的NUSE_Tick_时钟中。
检索时间
任务可以通过调用此API函数来获取系统时间。
用于检索时间的Nucleus RTOS API调用
Service call prototype:
UNSIGNED NU_Retrieve_Clock(VOID);
Parameters:
none
Returns:
the current system time value
Nucleus SE API Call for Retrieving Time
This API call supports the key functionality of the Nucleus RTOS API.
Service call prototype:
U32 NUSE_Clock_Retrieve(void);
Parameters:
none
Returns:
the current system time value
时间检索的Nucleus-SE实现
代码非常简单。在临界区内获得NUSE_Tick_Clock的值并返回。
数据结构
系统时间使用一种数据结构——在RAM中——它只是一个32位字。
强烈建议应用程序代码不要直接访问这个数据结构,而是使用提供的API函数。这避免了与Nucleus SE未来版本的不兼容和不必要的副作用,并简化了将应用程序移植到Nucleus RTOS的过程。这里包含数据结构的详细信息,以便更容易地理解服务调用代码的工作方式和调试。
RAM Data
The data structure is:
NUSE_Tick_Clock – This is a variable of type U32 where the system clock tick count is stored.
Nucleus SE启动时,此数据结构由NUSE_Init_Task()初始化为零。未来的文章将全面描述Nucleus SE的启动过程。
ROM数据
没有与系统时间相关联的ROM数据结构。
系统时间数据占用
与Nucleus SE的所有方面一样,系统时间所需的数据内存量是很容易预测的。
ROM数据占用为0。
RAM数据占用(字节)总是4。
未实现的API调用
所有与系统时间相关的Nucleus RTOS API调用在Nucleus SE中都是等效的。
与Nucleus PLUS兼容
对于Nucleus SE的各个方面,我的目标是尽可能保持与Nucleus RTOS的高级别应用程序代码兼容性。系统时间也不例外,而且,从用户的角度来看,它的实现方式与Nucleus RTOS中的方式大致相同。Nucleus RTOS API调用可以直接映射到Nucleus SE调用上。