⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_alarm.c

📁 ucos277很多朋友都在找,在这贡献出来了
💻 C
📖 第 1 页 / 共 2 页
字号:
    }
    /* alarm is present in alarm active list */
    else
    {
      /* remove from active list */
      pred->OSAlarmNext = alarm->OSAlarmNext;
    }
  } 
  /* mark as idle */
  alarm->OSAlarmType = OS_ALARM_TYPE_IDLE;
  alarm->OSAlarmTime = 0;
  /* remember that this timer is periodic */
  if (alarm->OSAlarmPeriod > 0) alarm->OSAlarmPeriod = 1;
  /* and remove successor */
  alarm->OSAlarmNext = (OS_ALARM *)0;
  OS_EXIT_CRITICAL();
  *err = OS_NO_ERR;
}

/**
 * Set an idle alarm
 *
 * @param alarm The (idle) alarm to be set. This alarm is activated and will trigger
 * after the specified number of ticks.
 * @param ticks The number of ticks (from now) after which the alarm will trigger. If this is
 * a periodic timer, this defines the period time in ticks.
 * @param err Pointer to error variable
 *
 * @return Errors are returned in the err_ptr
 * - OS_ERR_ALARM_TYPE The alarm was not idle
 *
 * @note The alarm must be idle. 
 * @see OSAlarmClear()
 */
void OSAlarmSet(OS_ALARM *alarm, INT16U ticks, INT8U *err_ptr)
{
#if OS_CRITICAL_METHOD == 3                         /* Allocate storage for CPU status register        */
    OS_CPU_SR    cpu_sr;
#endif
  OS_ENTER_CRITICAL();
#if (OS_ARG_CHK_EN > 0)
  /* alarm is not idle? */
  if (alarm->OSAlarmType != OS_ALARM_TYPE_IDLE) 
  {
    OS_EXIT_CRITICAL();
    /* failure, cannot set a non-idle alarm */
    *err_ptr = OS_ERR_ALARM_TYPE;
    return; 
  }
#endif
#if (OS_ALARM_PERIODIC_EN > 0)
  /* is this a periodic alarm? */
  if (alarm->OSAlarmPeriod > 0)
  {
    /* remember period ticks */
    alarm->OSAlarmPeriod = ticks;
  }
#endif
  /* set alarm trigger time */
  OSAlarmTime(alarm, OSTimeGet() + ticks, err_ptr);
  OS_EXIT_CRITICAL();
  return; 
}

/**
 * Activate an alarm with an absolute alarm time. This function is internal
 * and is called from OSAlarmSet() and OSAlarmTrigger() within a critical
 * section.
 *
 * @param alarm The (idle) alarm to be setup.
 * @param time The (absolute) time at which the alarm will trigger. 
 * @param err Pointer to error variable
 *
 * @return Errors are returned in the err_ptr
 * - OS_ERR_ALARM_TYPE The alarm was not idle
 *
 * @note The alarm must be idle.
 * @note No concurrent access to OSAlarm* may occur, i.e. the caller must wrap the call
 * to OSAlarmTime() with OS_ENTER_CRITICAL(), OS_EXIT_CRITICAL().
 * @see OSAlarmClear()
 */
static void OSAlarmTime(OS_ALARM *alarm, INT32U time, INT8U *err)
{
#if (OS_ARG_CHK_EN > 0)
  /* alarm is not idle? */
  if (alarm->OSAlarmType != OS_ALARM_TYPE_IDLE) 
  {
    /* failure, cannot set a non-idle alarm */
    *err = OS_ERR_ALARM_TYPE;
    return; 
  }
#endif
  /* remember absolute tick time at which this alarm triggers */
  alarm->OSAlarmTime = time;                     
  /* add alarm to OSAlarmActiveList */

  /* no active timers yet? */
  if (OSAlarmActiveList == (OS_ALARM *)0)
  {
    debug_printf("adding single alarm (%lu) in list", (unsigned long)alarm->OSAlarmTime);
    /* add alarm to OSAlarmActiveList */
    OSAlarmActiveList = alarm;
    alarm->OSAlarmNext = (OS_ALARM *)0;
  }
  /* active timers present */
  /* this is the alarm that will trigger as first in time */
  else if (alarm->OSAlarmTime < OSAlarmActiveList->OSAlarmTime)
  {
    /* add alarm as first of OSAlarmActiveList */
    alarm->OSAlarmNext = OSAlarmActiveList;
    debug_printf("adding earliest alarm (%lu) in list before (%lu)", alarm->OSAlarmTime,
      OSAlarmActiveList->OSAlarmTime);
    OSAlarmActiveList = alarm;
  }
  /* active timers present */
  /* this alarm will not trigger as first in time */
  else
  {
    OS_ALARM *pred = OSAlarmActiveList;
    /* search predecessing alarm */
    while ((pred != (OS_ALARM *)0) &&
           (pred->OSAlarmNext != (OS_ALARM *)0) &&
           (((OS_ALARM *)pred->OSAlarmNext)->OSAlarmTime <= alarm->OSAlarmTime))
    {
      pred = pred->OSAlarmNext;
    }
    /* insert in active list */
    if (pred->OSAlarmNext == 0)
    {
      debug_printf("inserting alarm (%lu) in list after (%lu)", alarm->OSAlarmTime, pred->OSAlarmTime);
    } else {
      debug_printf("inserting alarm (%lu) in list after (%lu) before (%lu)", alarm->OSAlarmTime,
        pred->OSAlarmTime, ((OS_ALARM *)pred->OSAlarmNext)->OSAlarmTime);
    }
    alarm->OSAlarmNext = pred->OSAlarmNext;
    pred->OSAlarmNext = alarm;
  }
  *err = OS_NO_ERR;
  return; 
}

/**
 * For any alarm that triggers, set its event flags and reset the alarm.
 *
 * Any triggered one-shot alarm becomes idle. Any periodic alarm is restarted.
 *
 * @note Periodic timers behave real-time correct with respect to their period. There
 * is no clock skew as long as OSAlarmTrigger() is called within the smallest alarm
 * period in the system.
 *
 */
void OSAlarmTrigger()
{
#if OS_CRITICAL_METHOD == 3                         /* Allocate storage for CPU status register        */
    OS_CPU_SR    cpu_sr;
#endif
  INT8U err;
  INT32U time = OSTimeGet();
  OS_ALARM *alarm;
  /* enter our critical section protecting the alarms list */
  OS_ENTER_CRITICAL();
  /* iterate through all alarms that should trigger now */
  while ((OSAlarmActiveList != (OS_ALARM *)0) && (OSAlarmActiveList->OSAlarmTime <= time))
  {
    /* pick first active alarm */
    alarm = OSAlarmActiveList;
    /* remove alarm from head of active list */
    OSAlarmActiveList = OSAlarmActiveList->OSAlarmNext;
    alarm->OSAlarmNext = (OS_ALARM *)0;
    /* idle this alarm */
    alarm->OSAlarmType = OS_ALARM_TYPE_IDLE;
    debug_printf("removing alarm (%lu) from list", alarm->OSAlarmTime);
#if (OS_ALARM_PERIODIC_EN > 0)
    /* periodic alarm? */
    if (alarm->OSAlarmPeriod > 0)
    {
      /* reset alarm to trigger on next period */
      OSAlarmTime(alarm, alarm->OSAlarmTime + alarm->OSAlarmPeriod, &err);
    }
    /* one-shot alarm */
    else
#endif
    {
      /* not necessary, but maybe helpful in debugging */
      alarm->OSAlarmTime = 0;
    }

    /* set the event flags (i.e. trigger) */
    /* note that we are already in a critical section when entering OSFlagPost().
     * OSFlagPost() enters and leaves a critical section AS WELL. For critical
     * section implementation method 1 this will LEAVE our critical section as well,
     * as that method does not respect nesting critical sections.
     * We deal with this correctly for all cases after this call returns */
    OSFlagPost(alarm->OSAlarmFlagGrp, alarm->OSAlarmFlags, OS_FLAG_SET, &err);
     
    /* effectively does nothing for method 1.
     * leaves our critical section for other methods */
    OS_EXIT_CRITICAL();
    /* re-enter our critical section protecting the alarms list */
    OS_ENTER_CRITICAL();
  }
  /* leave our critical section */
  OS_EXIT_CRITICAL();
}
/**
 * Checks if the earliest alarm time is reached.
 *
 * This function is to be called in OSTimeTickHook() which runs in interrupt context. The
 * function is minimal with O(1) execution time.
 *
 * If it returns >0, a subsequent call to OSAlarmTrigger() is needed to actually trigger
 * any alarms. This may be done from outside OSTimeTickHook() to minimize interrupt time.
 *
 * @return >0 if the earliest alarm time is reached. A subsequent call to OSAlarmTrigger() is
 * needed to trigger this alarm, and possibly other simultaneously triggered alarms.
 * 
 */
INT8U OSAlarmCheck()
{
  /* any alarms active AND earliest alarm time reached? */
  return ((OSAlarmActiveList != (OS_ALARM *)0) && (OSAlarmActiveList->OSAlarmTime <= OSTimeGet()));
}

#if 0
#include "page.h"
void OSAlarmDebug()
  page_printf("\f");
  OS_ALARM *blaat = OSAlarmActiveList;
  while (blaat)
  {
    page_printf("%u->", blaat->OSAlarmTime);      
    blaat = blaat->OSAlarmNext;
  }
  page_printf("NULL\n");
}
#endif

#endif /* #if (OS_VERSION >= 251) && (OS_ALARM_EN > 0) && (OS_MAX_ALARMS > 0) */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -