SylixOS里的时间【10】--- 软件定时器接口及用法

概念

很多系统都提供软件定时器,通过软件定时器可以异步的延时或周期性执行某一函数,使用延时函数也实现同样的功能,但延时函数是同步方式,等待时需要阻塞当前线程,如果要实现多个周期性动作需要创建多个线程。

无论是驱动还是应用程序,经常会用到周期查询任务,最简单高效的的实现方法就是创建一个周期性的软件定时器,在其回调函数中执行响应操作。

接口

SylixOS同样提供软件定时器,可以单次或循环模式执行,且提供普通和高速两种定时器类型。普通软件定时器在线程上下文中判定时间和执行回调,高速软件定时器则是在系统心跳中断中判定时间和执行回调。

/*********************************************************************************************************
  TIMER 创建选项
*********************************************************************************************************/
#define LW_OPTION_ITIMER                                0x00000001      /*  普通                        */
#define LW_OPTION_HTIMER                                0x00000000      /*  高速                        */
/*********************************************************************************************************
  TIMER 设置选项
*********************************************************************************************************/
#define LW_OPTION_AUTO_RESTART                          0x00000001      /*  定时器自动重载              */
#define LW_OPTION_MANUAL_RESTART                        0x00000000      /*  定时器手动重载              */
LW_API VOID             API_TimerHTicks(VOID);/*  高速定时器周期服务函数,需要在心跳中断中调用          */
LW_API ULONG            API_TimerHGetFrequency(VOID); /*  获得高速定时器频率          */
/*  建立一个定时器              */
LW_API LW_OBJECT_HANDLE API_TimerCreate(CPCHAR             pcName,//定时器名字
                                        ULONG              ulOption,//定时器类型
                                        LW_OBJECT_ID      *pulId); // 返回对象句柄    
LW_API ULONG            API_TimerDelete(LW_OBJECT_HANDLE  *pulId); /*  删除一个定时器              */
/*  启动一个定时器              */                                     
LW_API ULONG            API_TimerStart(LW_OBJECT_HANDLE         ulId,//对象句柄
                                       ULONG                    ulCounter,//定时时间,以节拍为单位
                                       ULONG                    ulOption,//选项,单次还是周期性
                                       PTIMER_CALLBACK_ROUTINE  cbTimerRoutine,//回调函数
                                       PVOID                    pvArg);//回调函数参数 
/*  启动一个定时器              */
LW_API ULONG            API_TimerStartEx(LW_OBJECT_HANDLE         ulId,//对象句柄
                                         ULONG                    ulInitCounter,//计数初始值
                                         ULONG                    ulCounter,//重复计数初始值
                                         ULONG                    ulOption,//操作选项
                                         PTIMER_CALLBACK_ROUTINE  cbTimerRoutine,//回调函数
                                         PVOID                    pvArg);//回调函数参数
                                                                        
LW_API ULONG            API_TimerCancel(LW_OBJECT_HANDLE         ulId); /*  停止一个定时器              */
LW_API ULONG            API_TimerReset(LW_OBJECT_HANDLE          ulId); /*  复位一个定时器              */
/*  获得一个定时器状态          */                                                                    
LW_API ULONG            API_TimerStatus(LW_OBJECT_HANDLE          ulId,//对象句柄
                                        BOOL                     *pbTimerRunning,//定时器是否在运行
                                        ULONG                    *pulOption,//定时器选项
                                        ULONG                    *pulCounter,//定时器当前计数值
                                        ULONG                    *pulInterval);//间隔时间, 为 0 表示单次运行
/*  获得一个定时器状态扩展接口  */                                                                        
LW_API ULONG            API_TimerStatusEx(LW_OBJECT_HANDLE          ulId,//对象句柄
                                          BOOL                     *pbTimerRunning,//定时器是否在运行
                                          ULONG                    *pulOption,//定时器选项
                                          ULONG                    *pulCounter,//定时器当前计数值
                                          ULONG                    *pulInterval,//间隔时间, 为 0 表示单次运行
                                          clockid_t                *pclockid);//POSIX 时间类型
                                                                        
LW_API ULONG            API_TimerGetName(LW_OBJECT_HANDLE  ulId, 
                                         PCHAR             pcName);     /*  获得定时器名字              */

用法举例

/*********************************************************************************************************
**
**                                    中国软件开源组织
**
**                                   嵌入式实时操作系统
**
**                                SylixOS(TM)  LW : long wing
**
**                               Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文   件   名: timerExample.c
**
** 创   建   人: Hou.JinYu (侯进宇)
**
** 文件创建日期: 2017 年 12 月 20 日
**
** 描        述: 软件定时器例程
*********************************************************************************************************/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioccom.h>
#include <pthread.h>
/*********************************************************************************************************
** 函数名称: timerCb
** 功能描述: 软件定时器回调函数
** 输    入: pvArg   回调参数
** 输    出: 无
*********************************************************************************************************/
VOID  timerCb (PVOID pvArg)
{
    int  *pcount = pvArg;

    (*pcount)++;
    /*
     * 中断中不能调用printf函数
     */
    if (!API_InterContext()) {
        printf("timer callback, count = %d\n", *pcount);
    }
}
/*********************************************************************************************************
** 函数名称: main
** 功能描述: 程序入口
** 输    入: argc   参数个数
**           argv   参数列表
** 输    出: ERROR_CODE
*********************************************************************************************************/
int main (int argc, char **argv)
{
    LW_OBJECT_HANDLE  hTimer;
    volatile  int     count = 0;
    int               err;
    int               i;
    ULONG             ulOption  = LW_OPTION_ITIMER;
    ULONG             ulCounter = API_TimeGetFrequency();

    printf("timer example start\n");
    /*
     * 根据命令参数判断是否为高速定时器,否则默认为普通定时器
     */
    if (argc == 2) {
        if (strcmp(argv[1], "h") == 0) {
            ulOption  = LW_OPTION_HTIMER;
            ulCounter = API_TimerHGetFrequency();
        }
    }
    /*
     * 创建软件定时器,指定为普通模式
     */
    hTimer = API_TimerCreate("timer", ulOption, LW_NULL);
    if (hTimer == 0) {
        printf("create timer failed\n");
        return  (PX_ERROR);
    } else {
        printf("create timer success\n");
    }
    /*
     * 启动定时器,周期为1秒,循环模式,回调函数中对计数加加处理
     */
    err = API_TimerStart(hTimer,
                         ulCounter,
                         LW_OPTION_AUTO_RESTART,
                         (PTIMER_CALLBACK_ROUTINE)timerCb,
                         (PVOID)&count);

    if (err) {
        printf("start  timer failed, err = %d\n", err);
        API_TimerDelete(&hTimer);
        return  (PX_ERROR);
    } else {
        printf("start  timer success\n");
    }
    /*
     * 每半秒复位一次软件定时器,这样10次(5秒)内软件定时器应该得不到运行
     */
    printf("reset  timer 10 times\n");
    for (i = 0; i < 10; i++) {
        API_TimeSleep(API_TimeGetFrequency() / 2);
        API_TimerReset(hTimer);
        printf("reset  timer. i = %d\n", i);
    }
    /*
     * 不再复位软件定时器,轮询count等于5时停止软件定时器
     */
    printf("wait count++ to 5\n");
    while (1) {
        if (count > 5) {
            err = API_TimerCancel(hTimer);
            if (err) {
                printf("stop   timer failed, err = %d\n", err);
                API_TimerDelete(&hTimer);
                return  (PX_ERROR);
            } else {
                printf("stop   timer success\n");
                break;
            }
        }
    }
    /*
     * 软件定时器已停止,等待5秒,期间不应该有回调运行
     */
    printf("wait 5s\n");
    for (i = 0; i < 10; i++) {
        API_TimeSleep(API_TimeGetFrequency() / 2);
        printf("wait   timer. i = %d, count = %d\n", i, count);
    }
    /*
     *
     */
    API_TimerDelete(&hTimer);
    printf("timer example finish\n");


    return  (0);
}
/*********************************************************************************************************
  END
*********************************************************************************************************/

SylixOS里的时间【10】--- 软件定时器接口及用法

SylixOS里的时间【10】--- 软件定时器接口及用法

上一篇:Windows11 安装Arch Linux WSL2 记录


下一篇:科技类、企业类网站导航