我是靠谱客的博主 优雅牛排,最近开发中收集的这篇文章主要介绍SylixOS里的时间【1】--- 系统tick接口系统tick变量内核宏接口内核函数接口,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

系统tick变量

SylixOS中对心跳中断计数的是一个64位原子量变量,心跳周期一般是1到10毫秒,64位计数可以认为永远不会溢出。

类型定义

#ifdef __GNUC__
typedef struct {
    volatile INT64  __attribute__((aligned(8))) counter;
} atomic64_t;

#else
typedef struct {
    volatile INT64  counter;
} atomic64_t;
#endif

变量定义
位于libsylixosSylixOSkernelincludek_globalvar.h文件中

_KERNEL_EXT atomic64_t              _K_atomic64KernelTime;             /*  系统时间计数器              */

内核宏接口

更新接口

每调用一次TICK_UPDATE宏接口,心跳计数加一。

#if LW_CFG_CPU_ATOMIC64_EN > 0
#define TICK_UPDATE()                                   
        do {                                            
            __LW_ATOMIC64_INC(&_K_atomic64KernelTime);  
        } while (0)
        
#else                                                                   /*  LW_CFG_CPU_ATOMIC64_EN      */
#define TICK_UPDATE()                                   
        do {                                            
            _K_atomic64KernelTime.counter++;            
        } while (0)
#endif 

读取接口:

__KERNEL_TIME_GET_NO_SPINLOCK(time, type)   //无SPINLOCK保护
__KERNEL_TIME_GET(time, type) //带保护的实现

系统当前tick计数是通过一个64位原子量记录的,这两个宏都是要获取这个数值。
如果目标CPU支持64位原子量操作,则之间通过原子量接口获取,两个接口的实现是完全一样的,都能保证数据的完整性。
如果目标CPU不支持64位原子量操作,__KERNEL_TIME_GET_NO_SPINLOCK是直接赋值的不保证数据的完整性,__KERNEL_TIME_GET则是通过自旋锁保护实现的,能保证数据的完整性。
实现源码如下:

#if LW_CFG_CPU_ATOMIC64_EN > 0
#define __KERNEL_TIME_GET_NO_SPINLOCK(time, type)                   
        {                                                           
            time = (type)__LW_ATOMIC64_GET(&_K_atomic64KernelTime); 
        }
#define __KERNEL_TIME_GET(time, type)   
        __KERNEL_TIME_GET_NO_SPINLOCK(time, type)
#else                                                                    /*  LW_CFG_CPU_ATOMIC64_EN      */
#define __KERNEL_TIME_GET_NO_SPINLOCK(time, type)       
        {                                               
            time = (type)_K_atomic64KernelTime.counter; 
        }
#define __KERNEL_TIME_GET(time, type)                       
        {                                                   
            INTREG  iregInterLevel;                         
            LW_SPIN_KERN_LOCK_QUICK(&iregInterLevel);       
            time = (type)_K_atomic64KernelTime.counter;     
            LW_SPIN_KERN_UNLOCK_QUICK(iregInterLevel);      
        }
#endif

系统当前tick计数_K_atomic64KernelTime.counter是单调递增的,只可能在tick中断中增加,其他地方都是读取。对于tick计数的读取,内核大部分是调用的__KERNEL_TIME_GET_NO_SPINLOCK接口,个别会直接读取_K_atomic64KernelTime.counter,少数会调用__KERNEL_TIME_GET接口。

心跳频率接口

初始化定时器,计算时间,或时间类型转换都要用到心跳频率,系统提供了一个接口LW_TICK_HZ,其本质是个变量,该值会被系统同启动参数中的hz选项初始化为相应的值。

#define LW_TICK_HZ                      _K_timingKernel.TIMING_ulTickHz

内核函数接口

  • API_TimeGetFrequency:获取心跳中断频率,基于LW_TICK_HZ宏实现。
  • API_TimeGet:获取当前心跳计数,基于__KERNEL_TIME_GET宏实现。
  • API_TimeGet64:以64位形式获取当前心跳计数,,基于__KERNEL_TIME_GET宏实现。
  • API_TimeSet:设置心跳计数值。心跳计数是单调递增的,不允许修改,该函数固定返回错误。

宏定义别名接口:

#define Lw_Time_Set                             API_TimeSet
#define Lw_Time_Get                             API_TimeGet
#define Lw_Time_Get64                           API_TimeGet64
#define Lw_Time_GetFrequency                    API_TimeGetFrequency

实现源码位于libsylixosSylixOSkernelinterfaceTimeGet.c文件中,如下:

/*********************************************************************************************************
** 函数名称: API_TimeGetFrequency
** 功能描述: 获得系统时间频率
** 输 入  : 
** 输 出  : 系统时间频率
*********************************************************************************************************/
LW_API  ULONG  API_TimeGetFrequency (VOID)
{
    return  (LW_TICK_HZ);
}
/*********************************************************************************************************
** 函数名称: API_TimeGet
** 功能描述: 获得系统时间
** 输 入  : 
** 输 出  : 系统时间
*********************************************************************************************************/
LW_API  ULONG  API_TimeGet (VOID)
{
    ULONG   ulTime;
    
    __KERNEL_TIME_GET(ulTime, ULONG);
    
    return  (ulTime);
}
/*********************************************************************************************************
** 函数名称: API_TimeGet64
** 功能描述: 获得系统时间
** 输 入  : 
** 输 出  : 系统时间
*********************************************************************************************************/
LW_API  INT64  API_TimeGet64 (VOID) 
{
    INT64   i64Time;
    
    __KERNEL_TIME_GET(i64Time, INT64);
    
    return  (i64Time);
}
/*********************************************************************************************************
** 函数名称: API_TimeSet
** 功能描述: 设置系统时间
** 输 入  : ulKernenlTime                 系统时间
** 输 出  : 
*********************************************************************************************************/
LW_API  VOID  API_TimeSet (ULONG  ulKernenlTime)
{
    _ErrorHandle(ERROR_KERNEL_RUNNING);
    return;
}

下面的例子通过以上函数获取系统已经运行了多长时间。

#include <SylixOS.h>
int main (int argc, char *argv[])
{
	ULONG ulUsecPerTick;
	ULONG ulMsecTotal;
	
	ulUsecPerTick = 1000000 / Lw_Time_GetFrequency();
	ulMsecTotal = Lw_Time_Get () * ulUsecPerTick / 1000;
	
	printf("system has run for %lu ms.n", ulMsecTotal);
	
	return (0);
}

最后

以上就是优雅牛排为你收集整理的SylixOS里的时间【1】--- 系统tick接口系统tick变量内核宏接口内核函数接口的全部内容,希望文章能够帮你解决SylixOS里的时间【1】--- 系统tick接口系统tick变量内核宏接口内核函数接口所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(73)

评论列表共有 0 条评论

立即
投稿
返回
顶部