对定时器源文件os_tmr.c进行源码阅读与注释:
// 功能:创建、删除、启动、停止、删除、初始化模块、获取定时器剩余时间、获取定时器状态、
// 创建定时器API: OS_TmrCreate
// 删除定时器API: OS_TmrDel
// 启动定时器API: OS_TmrStart
// 停止定时器API: OS_TmrStop
// 获取定时器剩余时间API: OS_TmrRemainGet
// 获取定时器状态API: OS_TmrStateGet
/*
************************************************************************************************************************
* uC/OS-III
* The Real-Time Kernel
*
* (c) Copyright 2009-2013; Micrium, Inc.; Weston, FL
* All rights reserved. Protected by international copyright laws.
*
* TIMER MANAGEMENT
*
* File : OS_TMR.C
* By : JJL
* Version : V3.04.01
*
* LICENSING TERMS:
* ---------------
* uC/OS-III is provided in source form for FREE short-term evaluation, for educational use or
* for peaceful research. If you plan or intend to use uC/OS-III in a commercial application/
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
* application/product. We provide ALL the source code for your convenience and to help you
* experience uC/OS-III. The fact that the source is provided does NOT mean that you can use
* it commercially 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 contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
************************************************************************************************************************
*/
#define MICRIUM_SOURCE
#include <os.h>
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
const CPU_CHAR *os_tmr__c = "$Id: $";
#endif
#if OS_CFG_TMR_EN > 0u
/*
************************************************************************************************************************
* CONSTANTS
************************************************************************************************************************
*/
#define OS_OPT_LINK_DLY (OS_OPT)(0u) //链接选项中的延时属性
#define OS_OPT_LINK_PERIODIC (OS_OPT)(1u) //链接选项中的周期性属性
/*
************************************************************************************************************************
* LOCAL FUNCTION PROTOTYPES
************************************************************************************************************************
*/
static void OS_TmrLock (void);
static void OS_TmrUnlock (void);
/*$PAGE*/
/*
************************************************************************************************************************
* CREATE A TIMER
*
* Description: This function is called by your application code to create a timer.
*
* Arguments : p_tmr Is a pointer to a timer control block
*
* p_name Is a pointer to an ASCII string that is used to name the timer. Names are useful for
* debugging.
*
* 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_OPT_TMR_PERIODIC' as an option, when the timer expires, it will
* automatically restart with the same period.
*
* opt Specifies either:
*
* OS_OPT_TMR_ONE_SHOT The timer counts down only once
* OS_OPT_TMR_PERIODIC The timer counts down and then reloads itself
*
* p_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 *p_tmr, void *p_arg);
*
* p_callback_arg Is an argument (a pointer) that is passed to the callback function when it is called.
*
* p_err Is a pointer to an error code. '*p_err' will contain one of the following:
*
* OS_ERR_NONE
* OS_ERR_ILLEGAL_CREATE_RUN_TIME if you are trying to create the timer after you called
* OSSafetyCriticalStart().
* OS_ERR_OBJ_CREATED if the timer has already been created
* OS_ERR_OBJ_PTR_NULL is 'p_tmr' is a NULL pointer
* OS_ERR_OBJ_TYPE if the object type is invalid
* OS_ERR_OPT_INVALID you specified an invalid option
* OS_ERR_TMR_INVALID_DLY you specified an invalid delay
* OS_ERR_TMR_INVALID_PERIOD you specified an invalid period
* OS_ERR_TMR_ISR if the call was made from an ISR
*
* Returns : none
*
* Note(s) : 1) This function only creates the timer. In other words, the timer is not started when created. To
* start the timer, call OSTmrStart().
************************************************************************************************************************
*/
// 创建一个定时器
void OSTmrCreate (OS_TMR *p_tmr, // 定时器控制块
CPU_CHAR *p_name, // 定时器名称
OS_TICK dly, // 延时时长
OS_TICK period, // 定时器周期
OS_OPT opt, // 定时器选项
OS_TMR_CALLBACK_PTR p_callback, // 定时器回调函数
void *p_callback_arg, // 定时器回调函数参数
OS_ERR *p_err) // 定时器错误代码
{
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
// 针对使用IEC61508标准的安全关键操作系统的代码
#ifdef OS_SAFETY_CRITICAL_IEC61508
if (OSSafetyCriticalStartFlag == DEF_TRUE) {
*p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
return;
}
#endif
// 检查是否在ISR中断中调用 判断中断嵌套层级 中断嵌套计数器OSIntNestingCtr大于0立即返回
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to call from an ISR */
*p_err = OS_ERR_TMR_ISR;
return;
}
#endif
// 检查参数
#if OS_CFG_ARG_CHK_EN > 0u
// 检查参数p_tmr
if (p_tmr == (OS_TMR *)0) { /* Validate 'p_tmr' */
*p_err = OS_ERR_OBJ_PTR_NULL;
return;
}
switch (opt) {
// 定时器为周期性模式则检查参数周期时间是否为0
case OS_OPT_TMR_PERIODIC:
if (period == (OS_TICK)0) {
*p_err = OS_ERR_TMR_INVALID_PERIOD;
return;
}
break;
// 定时器为一次性模式则检查参数延时时间是否为0
case OS_OPT_TMR_ONE_SHOT:
if (dly == (OS_TICK)0) {
*p_err = OS_ERR_TMR_INVALID_DLY;
return;
}
break;
// 设置定时器为无效选项
default:
*p_err = OS_ERR_OPT_INVALID;
return;
}
#endif
// 锁定定时器
OS_TmrLock();
// 初始化定时器字段
p_tmr->State = (OS_STATE )OS_TMR_STATE_STOPPED; // 设置定时器状态为停止状态
#if OS_OBJ_TYPE_REQ > 0u
p_tmr->Type = (OS_OBJ_TYPE )OS_OBJ_TYPE_TMR; // 设置对象类型为定时器
#endif
#if OS_CFG_DBG_EN > 0u
p_tmr->NamePtr = (CPU_CHAR *)p_name; // 如果调试功能被启用则设置定时器名称
#else
(void)&p_name; // 防止编译器警告
#endif
p_tmr->Dly = (OS_TICK )dly; // 设置定时器延迟时间
p_tmr->Remain = (OS_TICK )0; // 初始化定时器剩余时间为0
p_tmr->Period = (OS_TICK )period; // 设置定时器周期时间
p_tmr->Opt = (OS_OPT )opt; // 设置定时器选项
p_tmr->CallbackPtr = (OS_TMR_CALLBACK_PTR)p_callback; // 设置定时器用户回调函数
p_tmr->CallbackPtrArg = (void *)p_callback_arg; // 设置定时器用户回调函数参数
p_tmr->NextPtr = (OS_TMR *)0; // 设置定时器下一个定时器为空
p_tmr->PrevPtr = (OS_TMR *)0; // 设置定时器前一个定时器为空
#if OS_CFG_DBG_EN > 0u
OS_TmrDbgListAdd(p_tmr); // 将定时器添加到调试列表中
#endif
// 定时器数量加1
OSTmrQty++; /* Keep track of the number of timers created */
// 解锁定时器
OS_TmrUnlock();
*p_err = OS_ERR_NONE;
}
/*$PAGE*/
/*
************************************************************************************************************************
* DELETE A TIMER
*
* Description: This function is called by your application code to delete a timer.
*
* Arguments : p_tmr Is a pointer to the timer to stop and delete.
*
* p_err Is a pointer to an error code. '*p_err' will contain one of the following:
*
* OS_ERR_NONE
* OS_ERR_OBJ_TYPE 'p_tmr' is not pointing to a timer
* OS_ERR_TMR_INVALID 'p_tmr' is a NULL pointer
* 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 : DEF_TRUE if the timer was deleted
* DEF_FALSE if not or upon an error
************************************************************************************************************************
*/
// 删除定时器
#if OS_CFG_TMR_DEL_EN > 0u
CPU_BOOLEAN OSTmrDel (OS_TMR *p_tmr, // 定时器控制块指针
OS_ERR *p_err) // 定时器错误代码
{
// 定义执行成功标志
CPU_BOOLEAN success;
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return (DEF_FALSE);
}
#endif
// 检查是否在ISR中断中调用 判断中断嵌套层级 中断嵌套计数器OSIntNestingCtr大于0立即返回
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to call from an ISR */
*p_err = OS_ERR_TMR_ISR;
return (DEF_FALSE);
}
#endif
// 检查参数
#if OS_CFG_ARG_CHK_EN > 0u
if (p_tmr == (OS_TMR *)0) {
*p_err = OS_ERR_TMR_INVALID;
return (DEF_FALSE);
}
#endif
// 检查对象类型是否是定时器
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
if (p_tmr->Type != OS_OBJ_TYPE_TMR) { /* Make sure timer was created */
*p_err = OS_ERR_OBJ_TYPE;
return (DEF_FALSE);
}
#endif
// 锁定定时器
OS_TmrLock();
#if OS_CFG_DBG_EN > 0u
OS_TmrDbgListRemove(p_tmr); // 从调试列表中删除定时器
#endif
// 检查定时器状态
switch (p_tmr->State) {
// 定时器正在运行
case OS_TMR_STATE_RUNNING:
OS_TmrUnlink(p_tmr); // 从定时器链表中删除定时器
OS_TmrClr(p_tmr); // 清除定时器字段
OS_TmrUnlock(); // 解锁定时器
OSTmrQty--; // 定时器数量减1
*p_err = OS_ERR_NONE; // 设置错误代码为空
success = DEF_TRUE; // 设置执行成功标志
break;
// 定时器已经停止或定时器已经完成
case OS_TMR_STATE_STOPPED: /* Timer has not started or ... */
case OS_TMR_STATE_COMPLETED: /* ... timer has completed the ONE-SHOT time */
OS_TmrClr(p_tmr); // 清除定时器字段
OS_TmrUnlock(); // 解锁定时器
OSTmrQty--; // 定时器数量减1
*p_err = OS_ERR_NONE;
success = DEF_TRUE;
break;
// 定时器未使用
case OS_TMR_STATE_UNUSED: /* Already deleted */
OS_TmrUnlock(); // 解锁定时器
*p_err = OS_ERR_TMR_INACTIVE; // 设置错误代码为定时器未使用
success = DEF_FALSE;
break;
// 定时器状态无效
default:
OS_TmrUnlock();
*p_err = OS_ERR_TMR_INVALID_STATE; // 设置错误代码为定时器状态无效
success = DEF_FALSE;
break;
}
return (success); // 返回执行结果标志
}
#endif
/*$PAGE*/
/*
************************************************************************************************************************
* 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 : p_tmr Is a pointer to the timer to obtain the remaining time from.
*
* p_err Is a pointer to an error code. '*p_err' will contain one of the following:
*
* OS_ERR_NONE
* OS_ERR_OBJ_TYPE 'p_tmr' is not pointing to a timer
* OS_ERR_TMR_INVALID 'p_tmr' is a NULL pointer
* OS_ERR_TMR_ISR if the call was made from an ISR
* OS_ERR_TMR_INACTIVE 'p_tmr' 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
* OS_TmrTask() 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.
************************************************************************************************************************
*/
// 获取定时器剩余时间
OS_TICK OSTmrRemainGet (OS_TMR *p_tmr, // 定时器控制块指针
OS_ERR *p_err) // 定时器错误代码
{
OS_TICK remain; // 定时器剩余时间
OS_ERR err; // 定时器错误代码
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return ((OS_TICK)0);
}
#endif
// 检查是否在ISR中断中调用 判断中断嵌套层级 中断嵌套计数器OSIntNestingCtr大于0立即返回
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to call from an ISR */
*p_err = OS_ERR_TMR_ISR;
return ((OS_TICK)0);
}
#endif
// 检查参数
#if OS_CFG_ARG_CHK_EN > 0u
if (p_tmr == (OS_TMR *)0) {
*p_err = OS_ERR_TMR_INVALID;
return ((OS_TICK)0);
}
#endif
// 检查对象类型是否是定时器
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
if (p_tmr->Type != OS_OBJ_TYPE_TMR) { /* Make sure timer was created */
*p_err = OS_ERR_OBJ_TYPE;
return ((OS_TICK)0);
}
#endif
OSSchedLock(&err); // 锁定调度
(void)&err; // 忽略参数错误代码
// 检查定时器状态
switch (p_tmr->State) {
// 定时器正在运行
case OS_TMR_STATE_RUNNING:
remain = p_tmr->Remain; // 从定时器控制块获取剩余时间
*p_err = OS_ERR_NONE;
break;
// 定时器已经停止
case OS_TMR_STATE_STOPPED: /* It's assumed that the timer has not started yet */
if (p_tmr->Opt == OS_OPT_TMR_PERIODIC) { // 是周期性定时器
if (p_tmr->Dly == 0u) {
remain = p_tmr->Period; // 剩余时间为周期时间
} else {
remain = p_tmr->Dly; // 剩余时间为延迟时间
}
} else {
remain = p_tmr->Dly; // 不是周期性定时器则剩余时间为延迟时间
}
*p_err = OS_ERR_NONE;
break;
// 定时器已经完成
case OS_TMR_STATE_COMPLETED: /* Only ONE-SHOT that timed out can be in this state */
*p_err = OS_ERR_NONE;
remain = (OS_TICK)0; // 剩余时间为0
break;
// 定时器未使用
case OS_TMR_STATE_UNUSED:
*p_err = OS_ERR_TMR_INACTIVE;
remain = (OS_TICK)0; // 剩余时间为0
break;
// 定时器状态无效
default:
*p_err = OS_ERR_TMR_INVALID_STATE; // 设置错误代码为定时器状态无效
remain = (OS_TICK)0;
break;
}
// 解锁调度
OSSchedUnlock(&err);
(void)&err;
return (remain); // 返回剩余时间
}
/*$PAGE*/
/*
************************************************************************************************************************
* START A TIMER
*
* Description: This function is called by your application code to start a timer.
*
* Arguments : p_tmr Is a pointer to an OS_TMR
*
* p_err Is a pointer to an error code. '*p_err' will contain one of the following:
*
* OS_ERR_NONE
* OS_ERR_OBJ_TYPE if 'p_tmr' is not pointing to a timer
* OS_ERR_TMR_INVALID
* OS_ERR_TMR_INACTIVE if the timer was not created
* OS_ERR_TMR_INVALID_STATE the timer is in an invalid state
* OS_ERR_TMR_ISR if the call was made from an ISR
*
* Returns : DEF_TRUE is the timer was started
* DEF_FALSE if not or upon an error
*
* Note(s) : 1) When starting/restarting a timer, regardless if it is in PERIODIC or ONE-SHOT mode, the timer is
* linked to the timer list with the OS_OPT_LINK_DLY option. This option sets the initial expiration
* time for the timer. For timers in PERIODIC mode, subsequent expiration times are handled by
* the OS_TmrTask().
************************************************************************************************************************
*/
// 启动定时器
CPU_BOOLEAN OSTmrStart (OS_TMR *p_tmr,
OS_ERR *p_err)
{
OS_TMR *p_next; // 定时器控制块指针
CPU_BOOLEAN success;
CPU_SR_ALLOC(); // 申请一个变量用于保存CPU状态寄存器 变量用于进出临界区
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return (DEF_FALSE);
}
#endif
// 检查是否在ISR中断中调用 判断中断嵌套层级 中断嵌套计数器OSIntNestingCtr大于0立即返回
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to call from an ISR */
*p_err = OS_ERR_TMR_ISR;
return (DEF_FALSE);
}
#endif
// 检查参数
#if OS_CFG_ARG_CHK_EN > 0u
if (p_tmr == (OS_TMR *)0) {
*p_err = OS_ERR_TMR_INVALID;
return (DEF_FALSE);
}
#endif
// 检查对象类型是否是定时器
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
if (p_tmr->Type != OS_OBJ_TYPE_TMR) { /* Make sure timer was created */
*p_err = OS_ERR_OBJ_TYPE;
return (DEF_FALSE);
}
#endif
// 检查定时器状态
switch (p_tmr->State) {
// 定时器正在运行则重启定时器
case OS_TMR_STATE_RUNNING: /* Restart the timer */
CPU_CRITICAL_ENTER(); // 进入CPU临界区
p_tmr->Remain = p_tmr->Dly; // 设置剩余时间为延迟时间
CPU_CRITICAL_EXIT(); // 退出CPU临界区
*p_err = OS_ERR_NONE;
success = DEF_TRUE;
break;
// 定时器已经停止或已完成
case OS_TMR_STATE_STOPPED: /* Start the timer */
case OS_TMR_STATE_COMPLETED:
OS_TmrLock(); // 锁定定时器
p_tmr->State = OS_TMR_STATE_RUNNING; // 设置定时器状态为运行
if (p_tmr->Dly == (OS_TICK)0) { // 如果延迟时间为0 则剩余时间为周期时间
p_tmr->Remain = p_tmr->Period;
} else { // 否则剩余时间为延迟时间
p_tmr->Remain = p_tmr->Dly;
}
if (OSTmrListPtr == (OS_TMR *)0) { // 如果定时器列表为空
p_tmr->NextPtr = (OS_TMR *)0; // 设置定时器下一个指针为空
p_tmr->PrevPtr = (OS_TMR *)0; // 设置定时器前一个指针为空
OSTmrListPtr = p_tmr; // 设置定时器列表指针头为定时器p_tmr
OSTmrListEntries = 1u; // 设置定时器列表条目数为1
} else { // 否则从定时器列表头开始插入
p_next = OSTmrListPtr; // 暂存定时器列表头
p_tmr->NextPtr = OSTmrListPtr; // 设置定时器下一个指针为定时器列表头
p_tmr->PrevPtr = (OS_TMR *)0; // 设置定时器前一个指针为空
p_next->PrevPtr = p_tmr; // 设置定时器列表头前一个指针为定时器p_tmr
OSTmrListPtr = p_tmr; // 设置定时器列表头为定时器p_tmr
OSTmrListEntries++; // 定时器列表条目数加1
}
OS_TmrUnlock(); // 解锁定时器
*p_err = OS_ERR_NONE;
success = DEF_TRUE;
break;
// 定时器未使用
case OS_TMR_STATE_UNUSED: /* Timer not created */
*p_err = OS_ERR_TMR_INACTIVE;
success = DEF_FALSE;
break;
default:
*p_err = OS_ERR_TMR_INVALID_STATE;
success = DEF_FALSE;
break;
}
return (success);
}
/*$PAGE*/
/*
************************************************************************************************************************
* 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_SATE_RUNNING the timer is currently running
*
* Arguments : p_tmr Is a pointer to the desired timer
*
* p_err Is a pointer to an error code. '*p_err' will contain one of the following:
*
* OS_ERR_NONE
* OS_ERR_OBJ_TYPE if 'p_tmr' is not pointing to a timer
* OS_ERR_TMR_INVALID 'p_tmr' is a NULL pointer
* OS_ERR_TMR_INVALID_STATE if the timer is not in a valid state
* OS_ERR_TMR_ISR if the call was made from an ISR
*
* Returns : The current state of the timer (see description).
************************************************************************************************************************
*/
// 获取定时器状态
OS_STATE OSTmrStateGet (OS_TMR *p_tmr,
OS_ERR *p_err)
{
OS_STATE state;
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return (OS_TMR_STATE_UNUSED);
}
#endif
// 检查是否在ISR中
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to call from an ISR */
*p_err = OS_ERR_TMR_ISR;
return (OS_TMR_STATE_UNUSED);
}
#endif
// 检查参数
#if OS_CFG_ARG_CHK_EN > 0u
if (p_tmr == (OS_TMR *)0) {
*p_err = OS_ERR_TMR_INVALID;
return (OS_TMR_STATE_UNUSED);
}
#endif
// 检查对象类型是否为定时器
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
if (p_tmr->Type != OS_OBJ_TYPE_TMR) { /* Make sure timer was created */
*p_err = OS_ERR_OBJ_TYPE;
return (OS_TMR_STATE_UNUSED);
}
#endif
state = p_tmr->State; // 获取定时器状态
switch (state) {
// 状态为已知状态
case OS_TMR_STATE_UNUSED:
case OS_TMR_STATE_STOPPED:
case OS_TMR_STATE_COMPLETED:
case OS_TMR_STATE_RUNNING:
*p_err = OS_ERR_NONE;
break;
// 状态未知
default:
*p_err = OS_ERR_TMR_INVALID_STATE;
break;
}
return (state);
}
/*$PAGE*/
/*
************************************************************************************************************************
* STOP A TIMER
*
* Description: This function is called by your application code to stop a timer.
*
* Arguments : p_tmr Is a pointer to the timer to stop.
*
* opt Allows you to specify an option to this functions which can be:
*
* OS_OPT_TMR_NONE Do nothing special but stop the timer
* OS_OPT_TMR_CALLBACK Execute the callback function, pass it the callback argument
* specified when the timer was created.
* OS_OPT_TMR_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 p_tmr->OSTmrCallbackArg
*
* p_err Is a pointer to an error code. '*p_err' will contain one of the following:
* OS_ERR_NONE
* OS_ERR_OBJ_TYPE if 'p_tmr' is not pointing to a timer
* OS_ERR_OPT_INVALID if you specified an invalid option for 'opt'
* OS_ERR_TMR_INACTIVE if the timer was not created
* OS_ERR_TMR_INVALID 'p_tmr' is a NULL pointer
* OS_ERR_TMR_INVALID_STATE the timer is in an invalid state
* OS_ERR_TMR_ISR if the function was called from an ISR
* OS_ERR_TMR_NO_CALLBACK if the timer does not have a callback function defined
* OS_ERR_TMR_STOPPED if the timer was already stopped
*
* Returns : DEF_TRUE If we stopped the timer (if the timer is already stopped, we also return DEF_TRUE)
* DEF_FALSE If not
************************************************************************************************************************
*/
// 停止定时器
CPU_BOOLEAN OSTmrStop (OS_TMR *p_tmr, // 要停止的定时器
OS_OPT opt, // 停止选项
void *p_callback_arg, // opt为OS_OPT_TMR_CALLBACK_ARG传入回调函数的参数
OS_ERR *p_err) // 错误代码
{
OS_TMR_CALLBACK_PTR p_fnct;
CPU_BOOLEAN success;
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return (DEF_FALSE);
}
#endif
// 检查是否在ISR中
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if trying to call from an ISR */
*p_err = OS_ERR_TMR_ISR;
return (DEF_FALSE);
}
#endif
// 检查参数
#if OS_CFG_ARG_CHK_EN > 0u
if (p_tmr == (OS_TMR *)0) {
*p_err = OS_ERR_TMR_INVALID;
return (DEF_FALSE);
}
#endif
// 检查对象类型是否为定时器
#if OS_CFG_OBJ_TYPE_CHK_EN > 0u
if (p_tmr->Type != OS_OBJ_TYPE_TMR) { /* Make sure timer was created */
*p_err = OS_ERR_OBJ_TYPE;
return (DEF_FALSE);
}
#endif
switch (p_tmr->State) {
// 状态为运行中
case OS_TMR_STATE_RUNNING:
OS_TmrLock(); // 锁定定时器
OS_TmrUnlink(p_tmr); // 从链表中删除定时器
*p_err = OS_ERR_NONE;
// 根据选项执行回调函数
switch (opt) {
// 执行回调函数
case OS_OPT_TMR_CALLBACK:
p_fnct = p_tmr->CallbackPtr; // 获取回调函数
if (p_fnct != (OS_TMR_CALLBACK_PTR)0) { // 回调函数不为空则执行回调
(*p_fnct)((void *)p_tmr, p_tmr->CallbackPtrArg); /* Use callback arg when timer was created */
} else { // 回调函数为空则返回错误
*p_err = OS_ERR_TMR_NO_CALLBACK;
}
break;
// 执行计时器参数传递进去的回调函数
case OS_OPT_TMR_CALLBACK_ARG:
p_fnct = p_tmr->CallbackPtr; /* Execute callback function if available ... */
if (p_fnct != (OS_TMR_CALLBACK_PTR)0) {
(*p_fnct)((void *)p_tmr, p_callback_arg); /* .. using the 'callback_arg' provided in call */
} else {
*p_err = OS_ERR_TMR_NO_CALLBACK;
}
break;
// 不执行任何操作
case OS_OPT_TMR_NONE:
break;
default:
OS_TmrUnlock();
*p_err = OS_ERR_OPT_INVALID;
return (DEF_FALSE);
}
OS_TmrUnlock();
success = DEF_TRUE;
break;
// 状态为停止或完成
case OS_TMR_STATE_COMPLETED: /* Timer has already completed the ONE-SHOT or */
case OS_TMR_STATE_STOPPED: /* ... timer has not started yet. */
*p_err = OS_ERR_TMR_STOPPED;
success = DEF_TRUE;
break;
// 状态为未使用
case OS_TMR_STATE_UNUSED: /* Timer was not created */
*p_err = OS_ERR_TMR_INACTIVE;
success = DEF_FALSE;
break;
default:
*p_err = OS_ERR_TMR_INVALID_STATE;
success = DEF_FALSE;
break;
}
return (success);
}
//--------------------以下3个函数为上方API的辅助函数
/*$PAGE*/
/*
************************************************************************************************************************
* CLEAR TIMER FIELDS
*
* Description: This function is called to clear all timer fields.
*
* Argument(s): p_tmr Is a pointer to the timer to clear
* -----
*
* Returns : none
*
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
************************************************************************************************************************
*/
// 清除定时器字段
void OS_TmrClr (OS_TMR *p_tmr)
{
p_tmr->State = OS_TMR_STATE_UNUSED; // 设置状态为未使用
#if OS_OBJ_TYPE_REQ > 0u
p_tmr->Type = OS_OBJ_TYPE_NONE;
#endif
#if OS_CFG_DBG_EN > 0u
p_tmr->NamePtr = (CPU_CHAR *)((void *)"?TMR");
#endif
p_tmr->Dly = (OS_TICK )0;
p_tmr->Remain = (OS_TICK )0;
p_tmr->Period = (OS_TICK )0;
p_tmr->Opt = (OS_OPT )0;
p_tmr->CallbackPtr = (OS_TMR_CALLBACK_PTR)0;
p_tmr->CallbackPtrArg = (void *)0;
p_tmr->NextPtr = (OS_TMR *)0;
p_tmr->PrevPtr = (OS_TMR *)0;
}
/*$PAGE*/
/*
************************************************************************************************************************
* ADD/REMOVE TIMER TO/FROM DEBUG TABLE
*
* Description: These functions are called by uC/OS-III to add or remove a timer to/from a timer debug table.
*
* Arguments : p_tmr is a pointer to the timer to add/remove
*
* Returns : none
*
* Note(s) : These functions are INTERNAL to uC/OS-III and your application should not call it.
************************************************************************************************************************
*/
#if OS_CFG_DBG_EN > 0u
void OS_TmrDbgListAdd (OS_TMR *p_tmr)
{
p_tmr->DbgPrevPtr = (OS_TMR *)0;
if (OSTmrDbgListPtr == (OS_TMR *)0) {
p_tmr->DbgNextPtr = (OS_TMR *)0;
} else {
p_tmr->DbgNextPtr = OSTmrDbgListPtr;
OSTmrDbgListPtr->DbgPrevPtr = p_tmr;
}
OSTmrDbgListPtr = p_tmr;
}
void OS_TmrDbgListRemove (OS_TMR *p_tmr)
{
OS_TMR *p_tmr_next;
OS_TMR *p_tmr_prev;
p_tmr_prev = p_tmr->DbgPrevPtr;
p_tmr_next = p_tmr->DbgNextPtr;
if (p_tmr_prev == (OS_TMR *)0) {
OSTmrDbgListPtr = p_tmr_next;
if (p_tmr_next != (OS_TMR *)0) {
p_tmr_next->DbgPrevPtr = (OS_TMR *)0;
}
p_tmr->DbgNextPtr = (OS_TMR *)0;
} else if (p_tmr_next == (OS_TMR *)0) {
p_tmr_prev->DbgNextPtr = (OS_TMR *)0;
p_tmr->DbgPrevPtr = (OS_TMR *)0;
} else {
p_tmr_prev->DbgNextPtr = p_tmr_next;
p_tmr_next->DbgPrevPtr = p_tmr_prev;
p_tmr->DbgNextPtr = (OS_TMR *)0;
p_tmr->DbgPrevPtr = (OS_TMR *)0;
}
}
#endif
/*$PAGE*/
/*
************************************************************************************************************************
* INITIALIZE THE TIMER MANAGER
*
* Description: This function is called by OSInit() to initialize the timer manager module.
*
* Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
*
* OS_ERR_NONE
* OS_ERR_TMR_STK_INVALID if you didn't specify a stack for the timer task
* OS_ERR_TMR_STK_SIZE_INVALID if you didn't allocate enough space for the timer stack
* OS_ERR_PRIO_INVALID if you specified the same priority as the idle task
* OS_ERR_xxx any error code returned by OSTaskCreate()
*
* Returns : none
*
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
************************************************************************************************************************
*/
// 初始化定时器管理模块
void OS_TmrInit (OS_ERR *p_err)
{
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
#if OS_CFG_DBG_EN > 0u
OSTmrDbgListPtr = (OS_TMR *)0; // 清空调试定时器链表
#endif
OSTmrListPtr = (OS_TMR *)0; // 清空定时器链表
OSTmrListEntries = 0u; // 清空定时器数量
if (OSCfg_TmrTaskRate_Hz > (OS_RATE_HZ)0) { // 如果定时器任务频率大于0
OSTmrUpdateCnt = OSCfg_TickRate_Hz / OSCfg_TmrTaskRate_Hz; // 计算定时器任务更新频率
} else {
OSTmrUpdateCnt = OSCfg_TickRate_Hz / (OS_RATE_HZ)10;//将定时器任务更新频率设置为定时器的时钟频率除以10
}
OSTmrUpdateCtr = OSTmrUpdateCnt; //定时器更新计数器设置为定时器任务更新频率
OSTmrTickCtr = (OS_TICK)0; // 定时器计数器设置为0
OSTmrTaskTimeMax = (CPU_TS)0; // 定时器任务执行时间最大值为0
#if OS_CFG_MUTEX_EN > 0u
// 创建互斥锁
OSMutexCreate(&OSTmrMutex, /* Use a mutex to protect the timers */
"OS Tmr Mutex",
p_err);
if (*p_err != OS_ERR_NONE) {
return;
}
#endif
// 确认定时器任务堆栈有效
if (OSCfg_TmrTaskStkBasePtr == (CPU_STK*)0) {
*p_err = OS_ERR_TMR_STK_INVALID;
return;
}
// 确认定时器任务堆栈大小大于系统任务堆栈的最小值
if (OSCfg_TmrTaskStkSize < OSCfg_StkSizeMin) {
*p_err = OS_ERR_TMR_STK_SIZE_INVALID;
return;
}
// 确认定时器任务优先级有效
if (OSCfg_TmrTaskPrio >= (OS_CFG_PRIO_MAX - 1u)) {
*p_err = OS_ERR_TMR_PRIO_INVALID;
return;
}
// 创建定时器任务
OSTaskCreate((OS_TCB *)&OSTmrTaskTCB,
(CPU_CHAR *)((void *)"uC/OS-III Timer Task"),
(OS_TASK_PTR )OS_TmrTask,
(void *)0,
(OS_PRIO )OSCfg_TmrTaskPrio,
(CPU_STK *)OSCfg_TmrTaskStkBasePtr,
(CPU_STK_SIZE)OSCfg_TmrTaskStkLimit,
(CPU_STK_SIZE)OSCfg_TmrTaskStkSize,
(OS_MSG_QTY )0,
(OS_TICK )0,
(void *)0,
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR | OS_OPT_TASK_NO_TLS),
(OS_ERR *)p_err);
}
/*$PAGE*/
/*
************************************************************************************************************************
* RESET TIMER LIST PEAK DETECTOR
*
* Description: This function is used to reset the peak detector for the number of entries in the timer list
*
* Arguments : void
*
* Returns : none
*
* Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
************************************************************************************************************************
*/
// void OS_TmrResetPeak (void)
// {
// }
/*$PAGE*/
/*
************************************************************************************************************************
* REMOVE A TIMER FROM THE TIMER LIST
*
* Description: This function is called to remove the timer from the timer list.
*
* Arguments : p_tmr Is a pointer to the timer to remove.
* -----
*
* Returns : none
*
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
************************************************************************************************************************
*/
// 从定时器列表中删除定时器
void OS_TmrUnlink (OS_TMR *p_tmr)
{
OS_TMR *p_tmr1;
OS_TMR *p_tmr2;
if (OSTmrListPtr == p_tmr) { /* See if timer to remove is at the beginning of list */
p_tmr1 = (OS_TMR *)p_tmr->NextPtr;
OSTmrListPtr = (OS_TMR *)p_tmr1;
if (p_tmr1 != (OS_TMR *)0) {
p_tmr1->PrevPtr = (OS_TMR *)0;
}
} else {
p_tmr1 = (OS_TMR *)p_tmr->PrevPtr; /* Remove timer from somewhere in the list */
p_tmr2 = (OS_TMR *)p_tmr->NextPtr;
p_tmr1->NextPtr = p_tmr2;
if (p_tmr2 != (OS_TMR *)0) {
p_tmr2->PrevPtr = (OS_TMR *)p_tmr1;
}
}
p_tmr->State = OS_TMR_STATE_STOPPED;
p_tmr->NextPtr = (OS_TMR *)0;
p_tmr->PrevPtr = (OS_TMR *)0;
OSTmrListEntries--;
}
/*$PAGE*/
/*
************************************************************************************************************************
* TIMER MANAGEMENT TASK
*
* Description: This task is created by OS_TmrInit().
*
* Arguments : none
*
* Returns : none
*
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
************************************************************************************************************************
*/
// 定时器任务
void OS_TmrTask (void *p_arg)
{
OS_ERR err;
OS_TMR_CALLBACK_PTR p_fnct;
OS_TMR *p_tmr;
OS_TMR *p_tmr_next;
CPU_TS ts;
CPU_TS ts_start;
CPU_TS ts_delta;
(void)&p_arg; /* Not using 'p_arg', prevent compiler warning */
while (DEF_ON) {
// 等待信号量
(void)OSTaskSemPend((OS_TICK )0, /* Wait for signal indicating time to update tmrs */
(OS_OPT )OS_OPT_PEND_BLOCKING,
(CPU_TS *)&ts,
(OS_ERR *)&err);
// 上锁
OS_TmrLock();
ts_start = OS_TS_GET(); // 获取时间戳
OSTmrTickCtr++; // 计数器加一(因为每次Tick都会调用此函数)
p_tmr = OSTmrListPtr; // 获取定时器列表头
// 遍历定时器列表更新定时器
while (p_tmr != (OS_TMR *)0) { /* Update all the timers in the list */
OSSchedLock(&err); // 锁定操作系统调度
(void)&err;
p_tmr_next = p_tmr->NextPtr; // 暂存下一个定时器地址
p_tmr->Remain--; // 更新剩余时间自减1
if (p_tmr->Remain == 0) { // 如果剩余时间等于0
if (p_tmr->Opt == OS_OPT_TMR_PERIODIC) { // 如果是周期性定时器
p_tmr->Remain = p_tmr->Period; // 更新剩余时间为周期时间
} else { // 如果是一次性定时器
OS_TmrUnlink(p_tmr); // 从定时器列表中删除定时器
p_tmr->State = OS_TMR_STATE_COMPLETED; // 更新定时器状态为已完成
}
p_fnct = p_tmr->CallbackPtr; // 获取定时器回调函数
if (p_fnct != (OS_TMR_CALLBACK_PTR)0) { // 如果回调函数不为空
(*p_fnct)((void *)p_tmr,
p_tmr->CallbackPtrArg); // 调用回调函数
}
}
p_tmr = p_tmr_next; // 获取暂存的下一个定时器地址
OSSchedUnlock(&err); // 解锁调度
(void)&err;
}
ts_delta = OS_TS_GET() - ts_start; // 获取任务执行时间
OS_TmrUnlock(); // 解锁定时器
// 更新定时器任务组大执行时间
if (OSTmrTaskTimeMax < ts_delta) {
OSTmrTaskTimeMax = ts_delta;
}
}
}
/*$PAGE*/
/*
************************************************************************************************************************
* TIMER MANAGEMENT LOCKING MECHANISM
*
* Description: These functions are use to handle timer critical sections. The preferred method is to use a mutex in
* order to avoid locking the scheduler and also, to avoid calling callback functions while the scheduler is
* locked.
*
* Arguments : none
*
* Returns : none
*
* Note(s) : 1) These function is INTERNAL to uC/OS-III and your application MUST NOT call it.
************************************************************************************************************************
*/
// 获取定时器互斥锁
static void OS_TmrLock (void)
{
OS_ERR err;
#if OS_CFG_MUTEX_EN > 0u
CPU_TS ts;
OSMutexPend(&OSTmrMutex, /* Use a mutex to protect the timers */
0,
OS_OPT_PEND_BLOCKING,
&ts,
&err);
#else
OSSchedLock(&err); /* Lock the scheduler to protect the timers */
#endif
(void)&err;
}
// 释放定时器互斥锁
static void OS_TmrUnlock (void)
{
OS_ERR err;
#if OS_CFG_MUTEX_EN > 0u
OSMutexPost(&OSTmrMutex, /* Use a mutex to protect the timers */
OS_OPT_POST_NONE,
&err);
#else
OSSchedUnlock(&err); /* Lock the scheduler to protect the timers */
#endif
(void)&err;
}
#endif
标签:tmr,定时器,ERR,UcOs,err,TMR,源码,OS
From: https://www.cnblogs.com/lanlincmos/p/18184530