首页 > 编程语言 >UcOs-III 源码阅读: os_tmr.c

UcOs-III 源码阅读: os_tmr.c

时间:2024-05-10 15:57:58浏览次数:29  
标签:tmr 定时器 ERR UcOs err TMR 源码 OS

对定时器源文件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

相关文章

  • JDK源码阅读-------自学笔记(二十六)(java.util.Map 自定义讲解)
    一、简介Map就是用来存储“键(key)-值(value)”对的.通过键寻找value,所以键不能重复.数组的本质也是一种键值对,区别就是索引一般是数字,而Map的Key可以是任意对象(字符串,数字),相当于把数组的索引范围扩的更大,使用更方便.实际开发中较为常用.二、Map的常用方法实例(1......
  • windows下源码编译CMake项目
    Cmake项目1、安装路径和源码安装包下载地址:https://cmake.org/download/源码地址https://github.com/Kitware/CMake2、编译源码下载后会有一个CMake-master的文件夹在里面新建一个build目录打开cmake-gui可执行文件出现cmake的界面,设置source路径为刚刚的CMake-......
  • iceoryx源码阅读(八)——IPC通信机制
    目录1 整体结构2 序列化与反序列化3 类Unix系统的实现3.1 发送函数send3.2 接收函数receive4 Windows系统的实现4.1 发送函数send4.2 接收函数receive5 Roudi的监听逻辑1 整体结构通过前面的介绍,订阅者、发布者与Roudi守护进程之间也需要通信,如上文介绍的,请求Roudi守护进村创建......
  • [附源码]秦时明月6.2魔改版_搭建架设教程_附GM工具_安卓&苹果
    本教程仅限学习使用,禁止商用,一切后果与本人无关,此声明具有法律效应!!!!教程是本人亲自搭建成功的,绝对是完整可运行的,踩过的坑都给你们填上了一.演示视频 https://githubs.xyz/boot?app=50二.环境联网环境:centos7.6,放开所有端口单机环境:VM虚拟机......
  • 探索网站支付系统的奥秘,从Vue3和Spring Boot开始(入门级项目实战+在线教程)附赠项目源码
    你是否曾经在购物时,对着电脑屏幕前的“支付成功”四个字感到好奇?这背后的秘密究竟是什么?今天,让我们一起揭开支付系统的神秘面纱,探索其背后的技术实现。在这个基于Vue3和SpringBoot的支付项目实战中,我们将带你一步步了解支付系统的实现思路。这个项目不仅解决了常用支付方式的......
  • Android 源码单模块编译及调试
    以下内容基于Android12源码进行整理在整编完整个Android系统后,需要进行系统源码修改,不能每修改一次代码就对整个系统进行一次编译,这个很不现实,这时就需要对单模块进行编译并调试,下面的方法就很有用了。framework编译及替换编译自从Android12之后framework编译方式和之......
  • 27-Spring源码分析(二)
    AOP源码分析1.AOP概述AOP(AspectOrientProgramming)利用代理模式,通过代理对象对被代理的对象增加功能。所以,关键在于AOP框架自动创建AOP代理对象,代理模式分为静态代理和动态代理。AspectJ使用静态代理,编译时增强,在编译期生成代理对象;SpringAOP使用动态代理,运行时......
  • pdf.js源码分析-textLayer中的坐标计算
    在pdf.js中显示pdf内容和选择pdf文字属于不同的层,一个是canvas绘制,一个是使用dom进行布局,那么接下来先看一下在textLayer中的文字节点div是怎么计算每段文字的布局位置的吧。首先找到pdf.js源码中的text_layer.js文件,然后得到下面方法appendText方法,下面的解释是在字体没有发生旋......
  • FiddlerCore源码
    这是FiddlerCore5.0.2版本源码,支持.netframework和.netcore,百分百c#源码,功能全而且免费,无功能限制,还修复了多处bug。介绍:FiddlerCore可捕获和修改HTTP和HTTPS流量,而无需任何FiddlerUI。特点:HTTP和HTTPS流量捕获和修改。用于内容过滤和修改的强大对象模型。存......
  • JUC源码解析:深入解读偏向锁
    JUC源码解析:深入解读偏向锁本文使用jdk8几种锁状态介绍先介绍一下锁状态吧看偏向锁这一栏,它的内存存储了线程ID和Epoch,这一点尤为关键,意味着偏向锁没有内存可以存储对象头的hashCode,而其他锁是有地方存的.。也就意味着,,当锁对象被隐式(父类)或显试调用了has......