概述
前言
这个关于定时器的,我感觉也没啥,核心就是它的轮子罢了,然后核心结构体,如下:
typedef struct os_tmr {
INT8U OSTmrType; /* Should be set to OS_TMR_TYPE */
OS_TMR_CALLBACK OSTmrCallback; /* Function to call when timer expires */
void *OSTmrCallbackArg; /* Argument to pass to function when timer expires */
void *OSTmrNext; /* Double link list pointers */
void *OSTmrPrev;
INT32U OSTmrMatch; /* Timer expires when OSTmrTime == OSTmrMatch */
INT32U OSTmrDly; /* Delay time before periodic update starts */
INT32U OSTmrPeriod; /* Period to repeat timer */
#if OS_TMR_CFG_NAME_EN > 0u
INT8U *OSTmrName; /* Name to give the timer */
#endif
INT8U OSTmrOpt; /* Options (see OS_TMR_OPT_xxx) */
INT8U OSTmrState; /* Indicates the state of the timer: */
/* OS_TMR_STATE_UNUSED */
/* OS_TMR_STATE_RUNNING */
/* OS_TMR_STATE_STOPPED */
} OS_TMR;
/*定时器管理(已看完)
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
* TIMER MANAGEMENT
*
* (c) Copyright 1992-2017; Micrium, Inc.; Weston; FL
* All Rights Reserved
*
* File : OS_TMR.C
* By : Jean J. Labrosse
* Version : V2.92.13
*
* LICENSING TERMS:
* ---------------
* uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
* If you plan on using uC/OS-II in a commercial product you need to contact Micrium to properly license
* its use in your product. We provide ALL the source code for your convenience and to help you experience
* uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a
* licensing fee.
*
* Knowledge of the source code may NOT be used to develop a similar product.
*
* Please help us continue to provide the embedded community with the finest software available.
* Your honesty is greatly appreciated.
*
* You can find our product's user manual, API reference, release notes and
* more information at https://doc.micrium.com.
* You can contact us at www.micrium.com.
*********************************************************************************************************
*/
#define MICRIUM_SOURCE
#ifndef OS_MASTER_FILE
#include <ucos_ii.h>//引入头文件
#endif
/*
*********************************************************************************************************
* NOTES(注意)
*
* 1) Your application MUST define the following #define constants:
*你的应用程序必须定义下面两种宏定义常量
* OS_TASK_TMR_PRIO The priority of the Timer management task
* 定时器管理任务的优先级
* OS_TASK_TMR_STK_SIZE The size of the Timer management task's stack
* 定时器管理任务的堆栈的大小
* 2) You must call OSTmrSignal() to notify the Timer management task that it's time to update the timers.
您必须调用OSTmrSignal()来通知计时器管理任务该更新计时器了。
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* CONSTANTS(常量)
*********************************************************************************************************
*/
//宏定义常量
#define OS_TMR_LINK_DLY 0u
#define OS_TMR_LINK_PERIODIC 1u
/*
*********************************************************************************************************
* LOCAL PROTOTYPES(本地的原型声明)
*********************************************************************************************************
*/
//是否允许定时器
#if OS_TMR_EN > 0u
//定义本地函数
static OS_TMR *OSTmr_Alloc (void);
static void OSTmr_Free (OS_TMR *ptmr);
static void OSTmr_InitTask (void);
static void OSTmr_Link (OS_TMR *ptmr, INT8U type);
static void OSTmr_Unlink (OS_TMR *ptmr);
static void OSTmr_Task (void *p_arg);
#endif
/*
*********************************************************************************************************
* CREATE A TIMER(创建一个定时器)
*
* Description: This function is called by your application code to create a timer.
*你的应用程序调用此函数来创建一个定时器
* Arguments : dly Initial delay.初始化的延迟时间
* If the timer is configured for ONE-SHOT mode, this is the timeout used.
* If the timer is configured for PERIODIC mode, this is the first timeout to
* wait for before the timer starts entering periodic mode.
* 如果定时器配置为一次性模式,这是使用的超时。如果定时器配置为周期模式,这是在定时器开始进入周期模式之前等待的第一个超时。
*
* period The 'period' being repeated for the timer.
* If you specified 'OS_TMR_OPT_PERIODIC' as an option, when the timer
* expires, it will automatically restart with the same period.
* 定时器重复的周期时长,如果你配置了OS_TMR_OPT_PERIODIC,当这个定时器失效的时候,会自动重启相同的周期
*
* opt Specifies either://选择定时器模式
* OS_TMR_OPT_ONE_SHOT The timer counts down only once 定时器仅仅进行一次定时
* OS_TMR_OPT_PERIODIC The timer counts down and then reloads itself 定时器会循环进行
*
* callback Is a pointer to a callback function that will be called when the timer expires.
* The callback function must be declared as follows:
* 指向回调函数的指针,这个回调函数会在定时器失效的时候被调用,这个回调函数必须按照如下形式声明:
* void MyCallback (OS_TMR *ptmr, void *p_arg);
*
* callback_arg Is an argument (a pointer) that is passed to the callback function when it is called.
* 这是一个参数,当调用回调函数的时候传递的参数
* pname Is a pointer to an ASCII string that is used to name the timer. Names are
* useful for debugging.
* 指向字符串的指针,用来给定时器命名,名字在debug的时候仍然可用
* perr Is a pointer to an error code. '*perr' will contain one of the following:
* OS_ERR_NONE the call was successful and the timer
* was created.
* OS_ERR_ILLEGAL_CREATE_RUN_TIME if you tried to create a timer after
* safety critical operation started.
* OS_ERR_TMR_INVALID_DLY you specified an invalid delay
* OS_ERR_TMR_INVALID_PERIOD you specified an invalid period
* OS_ERR_TMR_INVALID_OPT you specified an invalid option
* OS_ERR_TMR_ISR if the call was made from an ISR
* OS_ERR_TMR_NON_AVAIL if there are no free timers from the timer pool
*
* Returns : A pointer to an OS_TMR data structure.
* This is the 'handle' that your application will use to reference the timer created.
*返回:返回指向定时器结构的指针,这个指针是应用程序用来访问创建的定时器的句柄
*********************************************************************************************************
*/
#if OS_TMR_EN > 0u
OS_TMR *OSTmrCreate (INT32U dly,
INT32U period,
INT8U opt,
OS_TMR_CALLBACK callback,
void *callback_arg,
INT8U *pname,
INT8U *perr)
{
OS_TMR *ptmr;
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return ((OS_TMR *)0);
}
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508
if (OSSafetyCriticalStartFlag == OS_TRUE) {
OS_SAFETY_CRITICAL_EXCEPTION();
*perr = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
return ((OS_TMR *)0);
}
#endif
//参数检查
#if OS_ARG_CHK_EN > 0u
//根据传入的opt进行参数检查
switch (opt) { /* Validate arguments */
//周期型定时器
case OS_TMR_OPT_PERIODIC:
if (period == 0u) {
*perr = OS_ERR_TMR_INVALID_PERIOD;
return ((OS_TMR *)0);
}
break;
//一次性定时器
case OS_TMR_OPT_ONE_SHOT:
if (dly == 0u) {
*perr = OS_ERR_TMR_INVALID_DLY;
return ((OS_TMR *)0);
}
break;
//无效opt参数
default:
*perr = OS_ERR_TMR_INVALID_OPT;
return ((OS_TMR *)0);
}
#endif
if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
*perr = OS_ERR_TMR_ISR;
return ((OS_TMR *)0);
}
OSSchedLock();//调度器上锁,禁止进行任务调度
//从timer pool中获得一个定时器控制块
ptmr = OSTmr_Alloc(); /* Obtain a timer from the free pool */
//检查是否正确获得
if (ptmr == (OS_TMR *)0) {
OSSchedUnlock();//调度器解锁
*perr = OS_ERR_TMR_NON_AVAIL;
//无有效控制块
return ((OS_TMR *)0);
}
ptmr->OSTmrState = OS_TMR_STATE_STOPPED; /* Indicate that timer is not running yet */
ptmr->OSTmrDly = dly;
ptmr->OSTmrPeriod = period;
ptmr->OSTmrOpt = opt;
ptmr->OSTmrCallback = callback;
ptmr->OSTmrCallbackArg = callback_arg;
#if OS_TMR_CFG_NAME_EN > 0u
if (pname == (INT8U *)0) { /* Is 'pname' a NULL pointer? */
ptmr->OSTmrName = (INT8U *)(void *)"?";
} else {
ptmr->OSTmrName = pname;
}
#endif
OSSchedUnlock();
OS_TRACE_TMR_CREATE(ptmr, ptmr->OSTmrName);
*perr = OS_ERR_NONE;
return (ptmr);
}
#endif
/*
*********************************************************************************************************
* DELETE A TIMER (删除一个定时器)
*
* Description: This function is called by your application code to delete a timer.
*这个函数被你的应用程序调用,用来删除一个定时器
* Arguments : ptmr Is a pointer to the timer to stop and delete.
* 指向被删除或者停止的定时器的指针
* perr Is a pointer to an error code. '*perr' will contain one of the following:
* OS_ERR_NONE the call was successful and the timer
* was deleted.
* OS_ERR_ILLEGAL_DEL_RUN_TIME if you tried to delete a timer after safety
* critical operation started.
* OS_ERR_TMR_INVALID 'ptmr' is a NULL pointer
* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR
* OS_ERR_TMR_ISR if the function was called from an ISR
* OS_ERR_TMR_INACTIVE if the timer was not created
* OS_ERR_TMR_INVALID_STATE the timer is in an invalid state
*
* Returns : OS_TRUE If the call was successful
* OS_FALSE If not
*********************************************************************************************************
*/
#if OS_TMR_EN > 0u
BOOLEAN OSTmrDel (OS_TMR *ptmr,
INT8U *perr)
{
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return (OS_FALSE);
}
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508
if (OSSafetyCriticalStartFlag == OS_TRUE) {
OS_SAFETY_CRITICAL_EXCEPTION();
*perr = OS_ERR_ILLEGAL_DEL_RUN_TIME;
return (OS_FALSE);
}
#endif
//参数检查
#if OS_ARG_CHK_EN > 0u
if (ptmr == (OS_TMR *)0) {
*perr = OS_ERR_TMR_INVALID;
return (OS_FALSE);
}
#endif
OS_TRACE_TMR_DEL_ENTER(ptmr);
//检查传过来的指针是否指向定时器结构体
if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */
*perr = OS_ERR_TMR_INVALID_TYPE;
OS_TRACE_TMR_DEL_EXIT(*perr);
return (OS_FALSE);
}
//ISR中禁止调用此函数
if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
*perr = OS_ERR_TMR_ISR;
OS_TRACE_TMR_DEL_EXIT(*perr);
return (OS_FALSE);
}
OSSchedLock();//调度器上锁
switch (ptmr->OSTmrState) {
//当前定时器正处于运行状态
case OS_TMR_STATE_RUNNING:
//从轮子中摘除定时器
OSTmr_Unlink(ptmr); /* Remove from current wheel spoke */
//释放定时器的资源
OSTmr_Free(ptmr); /* Return timer to free list of timers */
//调度器解锁
OSSchedUnlock();
*perr = OS_ERR_NONE;
OS_TRACE_TMR_DEL_EXIT(*perr);
return (OS_TRUE);
//当定时器处于停止状态,完成状态,直接释放资源
case OS_TMR_STATE_STOPPED: /* Timer has not started or ... */
case OS_TMR_STATE_COMPLETED: /* ... timer has completed the ONE-SHOT time */
OSTmr_Free(ptmr); /* Return timer to free list of timers */
OSSchedUnlock();
*perr = OS_ERR_NONE;
OS_TRACE_TMR_DEL_EXIT(*perr);
return (OS_TRUE);
//当定时器处于未使用状态,即此时timer在timer pool中,不需要释放资源
case OS_TMR_STATE_UNUSED: /* Already deleted */
OSSchedUnlock();
*perr = OS_ERR_TMR_INACTIVE;
OS_TRACE_TMR_DEL_EXIT(*perr);
return (OS_FALSE);
default:
OSSchedUnlock();
*perr = OS_ERR_TMR_INVALID_STATE;
OS_TRACE_TMR_DEL_EXIT(*perr);
return (OS_FALSE);
}
}
#endif
/*
*********************************************************************************************************
* GET THE NAME OF A TIMER (获取定时器的名字)
*
* Description: This function is called to obtain the name of a timer.
*这个函数用来获取定时器的名字
* Arguments : ptmr Is a pointer to the timer to obtain the name for
*指向定时器控制块的指针
* pdest Is a pointer to pointer to where the name of the timer will be placed.
*指向控制块名字需要存放的地址
* perr Is a pointer to an error code. '*perr' will contain one of the following:
* OS_ERR_NONE The call was successful
* OS_ERR_TMR_INVALID_DEST 'pdest' is a NULL pointer
* OS_ERR_TMR_INVALID 'ptmr' is a NULL pointer
* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR
* OS_ERR_NAME_GET_ISR if the call was made from an ISR
* OS_ERR_TMR_INACTIVE 'ptmr' points to a timer that is not active
* OS_ERR_TMR_INVALID_STATE the timer is in an invalid state
*
* Returns : The length of the string or 0 if the timer does not exist.
返回名字的长度
*********************************************************************************************************
*/
#if OS_TMR_EN > 0u && OS_TMR_CFG_NAME_EN > 0u
INT8U OSTmrNameGet (OS_TMR *ptmr,
INT8U **pdest,
INT8U *perr)
{
INT8U len;
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return (0u);
}
#endif
//参数检查
#if OS_ARG_CHK_EN > 0u
if (pdest == (INT8U **)0) {
*perr = OS_ERR_TMR_INVALID_DEST;
return (0u);
}
if (ptmr == (OS_TMR *)0) {
*perr = OS_ERR_TMR_INVALID;
return (0u);
}
#endif
//检查是否为定时器类型
if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */
*perr = OS_ERR_TMR_INVALID_TYPE;
return (0u);
}
if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
*perr = OS_ERR_NAME_GET_ISR;
return (0u);
}
//调度器上锁
OSSchedLock();
switch (ptmr->OSTmrState) {
//如果已经有了定时器实例,则直接获取
case OS_TMR_STATE_RUNNING:
case OS_TMR_STATE_STOPPED:
case OS_TMR_STATE_COMPLETED:
*pdest = ptmr->OSTmrName;
len = OS_StrLen(*pdest);
OSSchedUnlock();
*perr = OS_ERR_NONE;
return (len);
//定时器未被创建,无效
case OS_TMR_STATE_UNUSED: /* Timer is not allocated */
OSSchedUnlock();
*perr = OS_ERR_TMR_INACTIVE;
return (0u);
default:
OSSchedUnlock();
*perr = OS_ERR_TMR_INVALID_STATE;
return (0u);
}
}
#endif
/*
*********************************************************************************************************
* GET HOW MUCH TIME IS LEFT BEFORE A TIMER EXPIRES (获取定时器距离失效的剩余时间)
*
* Description: This function is called to get the number of ticks before a timer times out.
*这个函数用来获取定时器距离失效的时钟滴答数
* Arguments : ptmr Is a pointer to the timer to obtain the remaining time from.
*指向定时器的指针
* perr Is a pointer to an error code. '*perr' will contain one of the following:
* OS_ERR_NONE
* OS_ERR_TMR_INVALID 'ptmr' is a NULL pointer
* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR
* OS_ERR_TMR_ISR if the call was made from an ISR
* OS_ERR_TMR_INACTIVE 'ptmr' points to a timer that is not active
* OS_ERR_TMR_INVALID_STATE the timer is in an invalid state
*
* Returns : The time remaining for the timer to expire. The time represents 'timer' increments.
* In other words, if OSTmr_Task() is signaled every 1/10 of a second then the returned
* value represents the number of 1/10 of a second remaining before the timer expires.
计时器到期的剩余时间。这个time表示“计时器”增量。换句话说,如果OSTmr_Task()每隔1/10秒发出一次信号,那么返回值表示计时器到期前剩余的1/10秒的数量。
*********************************************************************************************************
*/
#if OS_TMR_EN > 0u
INT32U OSTmrRemainGet (OS_TMR *ptmr,
INT8U *perr)
{
INT32U remain;
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return (0u);
}
#endif
//参数检查
#if OS_ARG_CHK_EN > 0u
if (ptmr == (OS_TMR *)0) {
*perr = OS_ERR_TMR_INVALID;
return (0u);
}
#endif
//检查定时器类型
if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */
*perr = OS_ERR_TMR_INVALID_TYPE;
return (0u);
}
if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
*perr = OS_ERR_TMR_ISR;
return (0u);
}
//调度器上锁
OSSchedLock();
switch (ptmr->OSTmrState) {
case OS_TMR_STATE_RUNNING:
remain = ptmr->OSTmrMatch - OSTmrTime; /* Determine how much time is left to timeout */
OSSchedUnlock();
*perr = OS_ERR_NONE;
return (remain);
case OS_TMR_STATE_STOPPED: /* It's assumed that the timer has not started yet */
switch (ptmr->OSTmrOpt) {
case OS_TMR_OPT_PERIODIC:
//如果定义的是周期性定时器,那么当延迟为0的时候,返回周期长度
//如果定义了延迟,那么返回延迟
if (ptmr->OSTmrDly == 0u) {
remain = ptmr->OSTmrPeriod;
} else {
remain = ptmr->OSTmrDly;
}
OSSchedUnlock();
*perr = OS_ERR_NONE;
break;
case OS_TMR_OPT_ONE_SHOT:
default:
remain = ptmr->OSTmrDly;
OSSchedUnlock();
*perr = OS_ERR_NONE;
break;
}
return (remain);
case OS_TMR_STATE_COMPLETED: /* Only ONE-SHOT that timed out can be in this state */
OSSchedUnlock();
*perr = OS_ERR_NONE;
return (0u);
case OS_TMR_STATE_UNUSED:
OSSchedUnlock();
*perr = OS_ERR_TMR_INACTIVE;
return (0u);
default:
OSSchedUnlock();
*perr = OS_ERR_TMR_INVALID_STATE;
return (0u);
}
}
#endif
/*
*********************************************************************************************************
* FIND OUT WHAT STATE A TIMER IS IN (查找定时器当前所处状态)
*
* Description: This function is called to determine what state the timer is in:
*这个函数用来查找当前定时器处于那种状态
* OS_TMR_STATE_UNUSED the timer has not been created 定时器未被创建
* OS_TMR_STATE_STOPPED the timer has been created but has not been started or has been stopped
定时器已被创建但是还没有开始计时,或者定时器被暂停了
* OS_TMR_STATE_COMPLETED the timer is in ONE-SHOT mode and has completed it's timeout
定时器处于一次性模式,并且已经完成了计时
* OS_TMR_STATE_RUNNING the timer is currently running 定时器正在计时
*
* Arguments : ptmr Is a pointer to the desired timer
*指向定时器的指针
* perr Is a pointer to an error code. '*perr' will contain one of the following:
* OS_ERR_NONE
* OS_ERR_TMR_INVALID 'ptmr' is a NULL pointer
* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR
* OS_ERR_TMR_ISR if the call was made from an ISR
* OS_ERR_TMR_INACTIVE 'ptmr' points to a timer that is not active
* OS_ERR_TMR_INVALID_STATE if the timer is not in a valid state
*
* Returns : The current state of the timer (see description).
*********************************************************************************************************
*/
#if OS_TMR_EN > 0u
INT8U OSTmrStateGet (OS_TMR *ptmr,
INT8U *perr)
{
INT8U state;
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return (0u);
}
#endif
//参数检查
#if OS_ARG_CHK_EN > 0u
if (ptmr == (OS_TMR *)0) {
*perr = OS_ERR_TMR_INVALID;
return (0u);
}
#endif
//检查控制块类型
if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */
*perr = OS_ERR_TMR_INVALID_TYPE;
return (0u);
}
if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
*perr = OS_ERR_TMR_ISR;
return (0u);
}
//调度器上锁
OSSchedLock();
//获取当前控制块的状态
state = ptmr->OSTmrState;
switch (state) {
case OS_TMR_STATE_UNUSED:
case OS_TMR_STATE_STOPPED:
case OS_TMR_STATE_COMPLETED:
case OS_TMR_STATE_RUNNING:
*perr = OS_ERR_NONE;
break;
//有效状态只有四种
default:
*perr = OS_ERR_TMR_INVALID_STATE;
break;
}
OSSchedUnlock();//调度器解锁
return (state);
}
#endif
/*
*********************************************************************************************************
* START A TIMER (开始一个定时器)
*
* Description: This function is called by your application code to start a timer.
*这个函数被用来启动一个定时器
* Arguments : ptmr Is a pointer to an OS_TMR
*
* perr Is a pointer to an error code. '*perr' will contain one of the following:
* OS_ERR_NONE
* OS_ERR_TMR_INVALID
* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR
* OS_ERR_TMR_ISR if the call was made from an ISR
* OS_ERR_TMR_INACTIVE if the timer was not created
* OS_ERR_TMR_INVALID_STATE the timer is in an invalid state
*
* Returns : OS_TRUE if the timer was started
* OS_FALSE if an error was detected
*********************************************************************************************************
*/
#if OS_TMR_EN > 0u
BOOLEAN OSTmrStart (OS_TMR *ptmr,
INT8U *perr)
{
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return (OS_FALSE);
}
#endif
//参数检查
#if OS_ARG_CHK_EN > 0u
if (ptmr == (OS_TMR *)0) {
*perr = OS_ERR_TMR_INVALID;
return (OS_FALSE);
}
#endif
OS_TRACE_TMR_START_ENTER(ptmr);
//检查控制块类型
if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */
*perr = OS_ERR_TMR_INVALID_TYPE;
OS_TRACE_TMR_START_EXIT(*perr);
return (OS_FALSE);
}
if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
*perr = OS_ERR_TMR_ISR;
OS_TRACE_TMR_START_EXIT(*perr);
return (OS_FALSE);
}
//调度器上锁
OSSchedLock();
switch (ptmr->OSTmrState) {
case OS_TMR_STATE_RUNNING: /* Restart the timer */
OSTmr_Unlink(ptmr); /* ... Stop the timer */
//将定时器插入到轮子中,重新计时,以前的match失效了
OSTmr_Link(ptmr, OS_TMR_LINK_DLY); /* ... Link timer to timer wheel */
OSSchedUnlock();
*perr = OS_ERR_NONE;
OS_TRACE_TMR_START_EXIT(*perr);
return (OS_TRUE);
case OS_TMR_STATE_STOPPED: /* Start the timer */
case OS_TMR_STATE_COMPLETED:
OSTmr_Link(ptmr, OS_TMR_LINK_DLY); /* ... Link timer to timer wheel */
OSSchedUnlock();
*perr = OS_ERR_NONE;
OS_TRACE_TMR_START_EXIT(*perr);
return (OS_TRUE);
case OS_TMR_STATE_UNUSED: /* Timer not created */
OSSchedUnlock();
*perr = OS_ERR_TMR_INACTIVE;
OS_TRACE_TMR_START_EXIT(*perr);
return (OS_FALSE);
default:
OSSchedUnlock();
*perr = OS_ERR_TMR_INVALID_STATE;
OS_TRACE_TMR_START_EXIT(*perr);
return (OS_FALSE);
}
}
#endif
/*
*********************************************************************************************************
* STOP A TIMER (停止一个定时器)
*
* Description: This function is called by your application code to stop a timer.
*这个函数用来停止一个定时器
* Arguments : ptmr Is a pointer to the timer to stop.
*指向定时器的指针
* opt Allows you to specify an option to this functions which can be:
*
* OS_TMR_OPT_NONE Do nothing special but stop the timer 仅仅只是停止定时器
* OS_TMR_OPT_CALLBACK Execute the callback function, pass it the
* callback argument specified when the timer
* was created. 执行回调函数,并传递创建的时候传递进的参数
* OS_TMR_OPT_CALLBACK_ARG Execute the callback function, pass it the
* callback argument specified in THIS function call.
* 执行回调函数,传递这个函数中所确定的参数
* callback_arg Is a pointer to a 'new' callback argument that can be passed to the callback
* function instead of the timer's callback argument. In other words, use
* 'callback_arg' passed in THIS function INSTEAD of ptmr->OSTmrCallbackArg.
*指向新的回调函数参数的指针,这个新的参数可以用来替代创建定时器时定义的参数。换句话说,这里的callback_arg可以替代
ptmr->OSTmrCallbackArg
* perr Is a pointer to an error code. '*perr' will contain one of the following:
* OS_ERR_NONE
* OS_ERR_TMR_INVALID 'ptmr' is a NULL pointer
* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR
* OS_ERR_TMR_ISR if the function was called from an ISR
* OS_ERR_TMR_INACTIVE if the timer was not created
* OS_ERR_TMR_INVALID_OPT if you specified an invalid option for 'opt'
* OS_ERR_TMR_STOPPED if the timer was already stopped
* OS_ERR_TMR_INVALID_STATE the timer is in an invalid state
* OS_ERR_TMR_NO_CALLBACK if the timer does not have a callback function defined
*
* Returns : OS_TRUE If we stopped the timer (if the timer is already stopped, we also return OS_TRUE)
* OS_FALSE If not
*********************************************************************************************************
*/
#if OS_TMR_EN > 0u
BOOLEAN OSTmrStop (OS_TMR *ptmr,
INT8U opt,
void *callback_arg,
INT8U *perr)
{
OS_TMR_CALLBACK pfnct;//定义指向回调函数的指针
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return (OS_FALSE);
}
#endif
//参数检查
#if OS_ARG_CHK_EN > 0u
if (ptmr == (OS_TMR *)0) {
*perr = OS_ERR_TMR_INVALID;
return (OS_FALSE);
}
#endif
OS_TRACE_TMR_STOP_ENTER(ptmr);
//检查控制块类型
if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */
*perr = OS_ERR_TMR_INVALID_TYPE;
OS_TRACE_TMR_STOP_EXIT(*perr);
return (OS_FALSE);
}
if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
*perr = OS_ERR_TMR_ISR;
OS_TRACE_TMR_STOP_EXIT(*perr);
return (OS_FALSE);
}
//调度器上锁
OSSchedLock();
switch (ptmr->OSTmrState) {
//如果当前定时器正在运行
case OS_TMR_STATE_RUNNING:
//将定时器从轮子中摘除
OSTmr_Unlink(ptmr); /* Remove from current wheel spoke */
*perr = OS_ERR_NONE;
switch (opt) {
case OS_TMR_OPT_CALLBACK:
//获得函数指针
pfnct = ptmr->OSTmrCallback; /* Execute callback function if available ... */
if (pfnct != (OS_TMR_CALLBACK)0) {
//调用回调函数
(*pfnct)((void *)ptmr, ptmr->OSTmrCallbackArg); /* Use callback arg when timer was created */
} else {
*perr = OS_ERR_TMR_NO_CALLBACK;
}
break;
case OS_TMR_OPT_CALLBACK_ARG:
pfnct = ptmr->OSTmrCallback; /* Execute callback function if available ... */
if (pfnct != (OS_TMR_CALLBACK)0) {
(*pfnct)((void *)ptmr, callback_arg); /* ... using the 'callback_arg' provided in call */
} else {
*perr = OS_ERR_TMR_NO_CALLBACK;
}
break;
case OS_TMR_OPT_NONE:
break;
default:
*perr = OS_ERR_TMR_INVALID_OPT;
break;
}
OSSchedUnlock();
OS_TRACE_TMR_STOP_EXIT(*perr);
return (OS_TRUE);
//如果定时器本身就已经处于未运行状态,则不用调用回调函数
case OS_TMR_STATE_COMPLETED: /* Timer has already completed the ONE-SHOT or ... */
case OS_TMR_STATE_STOPPED: /* ... timer has not started yet. */
OSSchedUnlock();
*perr = OS_ERR_TMR_STOPPED;
OS_TRACE_TMR_STOP_EXIT(*perr);
return (OS_TRUE);
case OS_TMR_STATE_UNUSED: /* Timer was not created */
OSSchedUnlock();
*perr = OS_ERR_TMR_INACTIVE;
OS_TRACE_TMR_STOP_EXIT(*perr);
return (OS_FALSE);
default:
OSSchedUnlock();
*perr = OS_ERR_TMR_INVALID_STATE;
OS_TRACE_TMR_STOP_EXIT(*perr);
return (OS_FALSE);
}
}
#endif
/*
*********************************************************************************************************
* SIGNAL THAT IT'S TIME TO UPDATE THE TIMERS (提醒,是时候更新定时器了)
*
* Description: This function is typically called by the ISR that occurs at the timer tick rate and is
* used to signal to OSTmr_Task() that it's time to update the timers.
*当时钟滴答发生的时候,这个函数被ISR调用,用来提醒OSTmr_Task更新定时器
* Arguments : none
*
* Returns : OS_ERR_NONE The call was successful and the timer task was signaled.
* OS_ERR_SEM_OVF If OSTmrSignal() was called more often than OSTmr_Task() can handle
* the timers. This would indicate that your system is heavily loaded.
* OS_ERR_EVENT_TYPE Unlikely you would get this error because the semaphore used for
* signaling is created by uC/OS-II.
* OS_ERR_PEVENT_NULL Again, unlikely you would ever get this error because the semaphore
* used for signaling is created by uC/OS-II.
*********************************************************************************************************
*/
#if OS_TMR_EN > 0u
INT8U OSTmrSignal (void)
{
INT8U err;
err = OSSemPost(OSTmrSemSignal);
return (err);
}
#endif
/*
*********************************************************************************************************
* ALLOCATE AND FREE A TIMER (获得一个控制块)
*
* Description: This function is called to allocate a timer.
*这个函数用来获得一个定时器控制块
* Arguments : none
*
* Returns : a pointer to a timer if one is available
指向控制块的指针
*********************************************************************************************************
*/
#if OS_TMR_EN > 0u
static OS_TMR *OSTmr_Alloc (void)
{
OS_TMR *ptmr;
if (OSTmrFreeList == (OS_TMR *)0) {
return ((OS_TMR *)0);
}
//如果timer的定时器控制块还有空闲的
ptmr = (OS_TMR *)OSTmrFreeList;
OSTmrFreeList = (OS_TMR *)ptmr->OSTmrNext;
//此处错误,源代码错误,强转类型应该为 (OS_TMR *)或者 (void *)
ptmr->OSTmrNext = (OS_TCB *)0;
ptmr->OSTmrPrev = (OS_TCB *)0;
OSTmrUsed++;//全局变量,用来记录控制块的使用个数
OSTmrFree--;//全局变量,用来计数可用的定时器控制块的个数
return (ptmr);//返回控制块指针
}
#endif
/*
*********************************************************************************************************
* RETURN A TIMER TO THE FREE LIST (删除一个定时器)
*
* Description: This function is called to return a timer object to the free list of timers.
*这个函数用来删除一个定时器,将定时器的资源返回给空闲链表
* Arguments : ptmr is a pointer to the timer to free
*指向将被free的定时器控制块
* Returns : none
*********************************************************************************************************
*/
#if OS_TMR_EN > 0u
static void OSTmr_Free (OS_TMR *ptmr)
{
//将定时器的状态置位
ptmr->OSTmrState = OS_TMR_STATE_UNUSED; /* Clear timer object fields */
ptmr->OSTmrOpt = OS_TMR_OPT_NONE;
ptmr->OSTmrPeriod = 0u;
ptmr->OSTmrMatch = 0u;
ptmr->OSTmrCallback = (OS_TMR_CALLBACK)0;
ptmr->OSTmrCallbackArg = (void *)0;
#if OS_TMR_CFG_NAME_EN > 0u
ptmr->OSTmrName = (INT8U *)(void *)"?";
#endif
//将定时器控制块返回给空闲链表
//此处错误,源代码错误,强转类型应该为 (OS_TMR *)或者 (void *)
ptmr->OSTmrPrev = (OS_TCB *)0; /* Chain timer to free list */
ptmr->OSTmrNext = OSTmrFreeList;
OSTmrFreeList = ptmr;
OSTmrUsed--; /* Update timer object statistics */
OSTmrFree++;
}
#endif
/*
*********************************************************************************************************
* INITIALIZATION (初始化)
* INITIALIZE THE FREE LIST OF TIMERS (初始化定时器空闲列表)
*
* Description: This function is called by OSInit() to initialize the free list of OS_TMRs.
*这个函数被OSInit调用,来初始化空闲定时器列表
* Arguments : none
*
* Returns : none
*********************************************************************************************************
*/
#if OS_TMR_EN > 0u
void OSTmr_Init (void)
{
#if OS_EVENT_NAME_EN > 0u
INT8U err;
#endif
INT16U ix;
INT16U ix_next;
OS_TMR *ptmr1;
OS_TMR *ptmr2;
OS_MemClr((INT8U *)&OSTmrTbl[0], sizeof(OSTmrTbl)); /* Clear all the TMRs */
OS_MemClr((INT8U *)&OSTmrWheelTbl[0], sizeof(OSTmrWheelTbl)); /* Clear the timer wheel */
for (ix = 0u; ix < (OS_TMR_CFG_MAX - 1u); ix++) { /* Init. list of free TMRs */
ix_next = ix + 1u;
ptmr1 = &OSTmrTbl[ix];
ptmr2 = &OSTmrTbl[ix_next];
ptmr1->OSTmrType = OS_TMR_TYPE;
ptmr1->OSTmrState = OS_TMR_STATE_UNUSED; /* Indicate that timer is inactive */
ptmr1->OSTmrNext = (void *)ptmr2; /* Link to next timer */
#if OS_TMR_CFG_NAME_EN > 0u
ptmr1->OSTmrName = (INT8U *)(void *)"?";
#endif
}
ptmr1 = &OSTmrTbl[ix];
ptmr1->OSTmrType = OS_TMR_TYPE;
ptmr1->OSTmrState = OS_TMR_STATE_UNUSED; /* Indicate that timer is inactive */
ptmr1->OSTmrNext = (void *)0; /* Last OS_TMR */
#if OS_TMR_CFG_NAME_EN > 0u
ptmr1->OSTmrName = (INT8U *)(void *)"?";
#endif
//全局变量
//定义系统时钟为0
OSTmrTime = 0u;
OSTmrUsed = 0u;
OSTmrFree = OS_TMR_CFG_MAX;
OSTmrFreeList = &OSTmrTbl[0];
//创建信号量
OSTmrSem = OSSemCreate(1u);
OSTmrSemSignal = OSSemCreate(0u);
//为信号量命名
#if OS_EVENT_NAME_EN > 0u /* Assign names to semaphores */
OSEventNameSet(OSTmrSem, (INT8U *)(void *)"uC/OS-II TmrLock", &err);
OSEventNameSet(OSTmrSemSignal, (INT8U *)(void *)"uC/OS-II TmrSignal", &err);
#endif
OSTmr_InitTask();
}
#endif
/*
*********************************************************************************************************
* INITIALIZE THE TIMER MANAGEMENT TASK (初始化定时器管理Task)
*
* Description: This function is called by OSTmrInit() to create the timer management task.
* * Arguments : none
*这个函数被OSTmrInit函数调用,来创建定时器管理Task
* Returns : none
*********************************************************************************************************
*/
#if OS_TMR_EN > 0u
static void OSTmr_InitTask (void)
{
#if OS_TASK_NAME_EN > 0u
INT8U err;
#endif
#if OS_TASK_CREATE_EXT_EN > 0u
#if OS_STK_GROWTH == 1u
(void)OSTaskCreateExt(OSTmr_Task,
(void *)0, /* No arguments passed to OSTmrTask() */
&OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1u], /* Set Top-Of-Stack */
OS_TASK_TMR_PRIO,
OS_TASK_TMR_ID,
&OSTmrTaskStk[0], /* Set Bottom-Of-Stack */
OS_TASK_TMR_STK_SIZE,
(void *)0, /* No TCB extension */
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear stack */
#else
(void)OSTaskCreateExt(OSTmr_Task,
(void *)0, /* No arguments passed to OSTmrTask() */
&OSTmrTaskStk[0], /* Set Top-Of-Stack */
OS_TASK_TMR_PRIO,
OS_TASK_TMR_ID,
&OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1u], /* Set Bottom-Of-Stack */
OS_TASK_TMR_STK_SIZE,
(void *)0, /* No TCB extension */
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear stack */
#endif
#else
#if OS_STK_GROWTH == 1u
(void)OSTaskCreate(OSTmr_Task,
(void *)0,
&OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1u],
OS_TASK_TMR_PRIO);
#else
(void)OSTaskCreate(OSTmr_Task,
(void *)0,
&OSTmrTaskStk[0],
OS_TASK_TMR_PRIO);
#endif
#endif
#if OS_TASK_NAME_EN > 0u
OSTaskNameSet(OS_TASK_TMR_PRIO, (INT8U *)(void *)"uC/OS-II Tmr", &err);
#endif
}
#endif
/*
*********************************************************************************************************
* INSERT A TIMER INTO THE TIMER WHEEL (将一个定时器插入到定时器轮子中)
*
* Description: This function is called to insert the timer into the timer wheel. The timer is always
* inserted at the beginning of the list.
*这个函数被用来调用,将定时器插入到定时器轮子中,定时器总是被插入到轮子的开头处
* Arguments : ptmr Is a pointer to the timer to insert.
*指向定时器的指针
* type Is either:两者选择其一
* OS_TMR_LINK_PERIODIC Means to re-insert the timer after a period expired
每个周期结束后都将定时器重新插入到轮子中
* OS_TMR_LINK_DLY Means to insert the timer the first time
* 第一次插入到轮子中,都是此种类型。无论是否为周期定时器
* Returns : none
*********************************************************************************************************
*/
#if OS_TMR_EN > 0u
static void OSTmr_Link (OS_TMR *ptmr,
INT8U type)
{
OS_TMR *ptmr1;
OS_TMR_WHEEL *pspoke;
INT16U spoke;
//将定时器状态改为运行态
ptmr->OSTmrState = OS_TMR_STATE_RUNNING;
//周期性插入定时器
if (type == OS_TMR_LINK_PERIODIC) { /* Determine when timer will expire */
//设定下一次定时器结束时间为当前系统时间加上定时器周期时间
ptmr->OSTmrMatch = ptmr->OSTmrPeriod + OSTmrTime;
} else {
//如果定时器延时为0,说明必然是一个周期定时器
if (ptmr->OSTmrDly == 0u) {
ptmr->OSTmrMatch = ptmr->OSTmrPeriod + OSTmrTime;
} else {
//如果定时器有延时,1.若为普通一次性定时器,则正常,2.如果为周期性定时器,则为进入周期循环的第一次不属于周期内的延迟
ptmr->OSTmrMatch = ptmr->OSTmrDly + OSTmrTime;
}
}
spoke = (INT16U)(ptmr->OSTmrMatch % OS_TMR_CFG_WHEEL_SIZE);
pspoke = &OSTmrWheelTbl[spoke];
//链表插入操作
if (pspoke->OSTmrFirst == (OS_TMR *)0) { /* Link into timer wheel */
pspoke->OSTmrFirst = ptmr;
ptmr->OSTmrNext = (OS_TMR *)0;
pspoke->OSTmrEntries = 1u;
} else {
ptmr1 = pspoke->OSTmrFirst; /* Point to first timer in the spoke */
pspoke->OSTmrFirst = ptmr;
ptmr->OSTmrNext = (void *)ptmr1;
ptmr1->OSTmrPrev = (void *)ptmr;
pspoke->OSTmrEntries++;
}
ptmr->OSTmrPrev = (void *)0; /* Timer always inserted as first node in list */
}
#endif
/*
*********************************************************************************************************
* REMOVE A TIMER FROM THE TIMER WHEEL (从定时器轮中删除指定的定时器)
*
* Description: This function is called to remove the timer from the timer wheel.
*从定时器轮中删除定时器
* Arguments : ptmr Is a pointer to the timer to remove.
*指向即将被删除的定时器
* Returns : none
*********************************************************************************************************
*/
#if OS_TMR_EN > 0u
static void OSTmr_Unlink (OS_TMR *ptmr)
{
OS_TMR *ptmr1;
OS_TMR *ptmr2;
OS_TMR_WHEEL *pspoke;
INT16U spoke;
//spoke (车轮的辐条,轮辐)
// #define OS_TMR_CFG_WHEEL_SIZE 7u /* Size of timer wheel (#Spokes) */
// Timer expires when OSTmrTime == OSTmrMatch
// 一共有七个轮子,每个轮子都有一系列定时器在转
// 获取当前定时器属于那个轮子
// 这种方法为哈希方法,链表处理哈希冲突
spoke = (INT16U)(ptmr->OSTmrMatch % OS_TMR_CFG_WHEEL_SIZE);
pspoke = &OSTmrWheelTbl[spoke];
if (pspoke->OSTmrFirst == ptmr) { /* See if timer to remove is at the beginning of list */
ptmr1 = (OS_TMR *)ptmr->OSTmrNext;
pspoke->OSTmrFirst = (OS_TMR *)ptmr1;
if (ptmr1 != (OS_TMR *)0) {
ptmr1->OSTmrPrev = (void *)0;
}
} else {
//轮子是双向链表,轮子本身提供一种入口,是定时器控制块本身为双向链表格式
ptmr1 = (OS_TMR *)ptmr->OSTmrPrev; /* Remove timer from somewhere in the list */
ptmr2 = (OS_TMR *)ptmr->OSTmrNext;
ptmr1->OSTmrNext = ptmr2;
if (ptmr2 != (OS_TMR *)0) {
ptmr2->OSTmrPrev = (void *)ptmr1;
}
}
//将定时器的状态置位
ptmr->OSTmrState = OS_TMR_STATE_STOPPED;
ptmr->OSTmrNext = (void *)0;
ptmr->OSTmrPrev = (void *)0;
pspoke->OSTmrEntries--;//轮子实体数减一
}
#endif
/*
*********************************************************************************************************
* TIMER MANAGEMENT TASK (定时器管理任务)
*
* Description: This task is created by OSTmrInit().
*
* Arguments : none
*
* Returns : none
*********************************************************************************************************
*/
//注意,此函数仅仅只是管理函数,当定时器到时间了,负责将其状态标记,至于怎么处理定时器,是创建定时器任务的事,
//此函数仅仅负责调用回调函数就行,不负责定时器的增删改查
#if OS_TMR_EN > 0u
static void OSTmr_Task (void *p_arg)
{
INT8U err;
OS_TMR *ptmr;
OS_TMR *ptmr_next;
OS_TMR_CALLBACK pfnct;
OS_TMR_WHEEL *pspoke;
INT16U spoke;
//防止编译器报错
p_arg = p_arg; /* Prevent compiler warning for not using 'p_arg' */
for (;;) {
//等待始终滴答信号量
OSSemPend(OSTmrSemSignal, 0u, &err); /* Wait for signal indicating time to update timers */
//调度器上锁,禁止任务调度
OSSchedLock();
//系统时钟自增
OSTmrTime++; /* Increment the current time */
spoke = (INT16U)(OSTmrTime % OS_TMR_CFG_WHEEL_SIZE); /* Position on current timer wheel entry */
pspoke = &OSTmrWheelTbl[spoke];
ptmr = pspoke->OSTmrFirst;
while (ptmr != (OS_TMR *)0) {
ptmr_next = (OS_TMR *)ptmr->OSTmrNext; /* Point to next timer to update because current ... */
/* ... timer could get unlinked from the wheel. */
if (OSTmrTime == ptmr->OSTmrMatch) { /* Process each timer that expires */
OS_TRACE_TMR_EXPIRED(ptmr);
OSTmr_Unlink(ptmr); /* Remove from current wheel spoke */
if (ptmr->OSTmrOpt == OS_TMR_OPT_PERIODIC) {
OSTmr_Link(ptmr, OS_TMR_LINK_PERIODIC); /* Recalculate new position of timer in wheel */
} else {
ptmr->OSTmrState = OS_TMR_STATE_COMPLETED; /* Indicate that the timer has completed */
}
pfnct = ptmr->OSTmrCallback; /* Execute callback function if available */
if (pfnct != (OS_TMR_CALLBACK)0) {
(*pfnct)((void *)ptmr, ptmr->OSTmrCallbackArg);
}
}
ptmr = ptmr_next;
}
OSSchedUnlock();
}
}
#endif
最后
以上就是谨慎鞋子为你收集整理的【 uC/OS II 】uC/OS II 源代码阅读(os_tmr.c)定时器管理的全部内容,希望文章能够帮你解决【 uC/OS II 】uC/OS II 源代码阅读(os_tmr.c)定时器管理所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复