📄 os_alarm.c
字号:
/**
* @file
* Alarms that trigger event flags once the alarm timer runs out.
*
* Copyright (c) 2002, 2003 Leon Woestenberg <leon.woestenberg@axon.tv>
* Copyright (c) 2002, 2003 Axon Digital Design B.V. http://www.axon.tv
* All rights reserved.
*
*/
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of Axon Digital Design B.V. nor Leon Woestenberg
* not the names of contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY AXON DIGITAL DESIGN, LEON WOESTENBERG AND
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#define OS_ALARM_GLOBALS
#include "includes.h"
#define DBG_LEVEL 0
#if DBG_LEVEL > 0
# include "debug.h"
#else
# define debug_printf
#endif
#if (OS_VERSION >= 251) && (OS_ALARM_EN > 0) && (OS_MAX_ALARMS > 0)
static void OSAlarmTime(OS_ALARM *alarm, INT32U time, INT8U *err);
/**
* Initialize the alarms.
*
* Must be called after OSInit().
*
*/
void OSAlarmInit(void)
{
#if OS_MAX_ALARMS == 1
OSAlarmFreeList = (OS_ALARM *)&OSAlarmTbl[0]; /* Only ONE alarm! */
OSAlarmFreeList->OSAlarmType = OS_ALARM_TYPE_UNUSED;
OSAlarmFreeList->OSAlarmNext = (OS_ALARM *)0;
OSAlarmFreeList->OSAlarmTime = 0;
# if (OS_ALARM_PERIODIC_EN > 0)
OSAlarmFreeList->OSAlarmPeriod = 0;
# endif
#endif
#if OS_MAX_ALARMS >= 2
INT8U i;
OS_ALARM *alarm1;
OS_ALARM *alarm2;
alarm1 = &OSAlarmTbl[0];
alarm2 = &OSAlarmTbl[1];
for (i = 0; i < (OS_MAX_ALARMS - 1); i++) {
alarm1->OSAlarmType = OS_ALARM_TYPE_UNUSED;
alarm1->OSAlarmTime = 0;
#if (OS_ALARM_PERIODIC_EN > 0)
alarm1->OSAlarmPeriod = 0;
#endif
alarm1->OSAlarmNext = (void *)alarm2;
alarm1++;
alarm2++;
}
alarm1->OSAlarmNext = (void *)0;
OSAlarmFreeList = (OS_ALARM *)&OSAlarmTbl[0];
#endif
OSAlarmActiveList = (OS_ALARM *)0;
}
/**
* Create an alarm.
*
* @param flag_group The event flag group where flags will be set when the alarm triggers.
* @param flags These flags are set in the flag_group when the alarm triggers.
* @param opt Alarm options mask,
* - OS_ALARM_PERIODIC defines a periodic alarm, which once set, retriggers after each
* period defined using OSAlarmSet(). Periodic alarms do not drift.
* - OS_ALARM_ONESHOT defines a one-shot alarm, which triggers once.
* @param err Pointer to error variable.
* - OS_NO_ERR The alarm was succesfully created.
* - OS_ERR_CREATE_ISR Called from within interrupt, which is not allowed.
* - OS_ALARM_DEPLETED No free alarms are available.
* - OS_ERR_INVALID_OPT A periodic alarm was attempted to be created while support for it was
* not available (OS_ALARM_PERIODIC_EN = 0).
*
* @note May not be called from inside an ISR.
*
*/
OS_ALARM *OSAlarmCreate(OS_FLAG_GRP *flag_group, OS_FLAGS flags, INT8U opt, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_ALARM *alarm;
#if ((OS_ARG_CHK_EN > 0) && (OS_ALARM_PERIODIC_EN == 0))
if (opt & OS_ALARM_PERIODIC)
{
/* failure, cannot create a period alarm if period alarms are disabled */
*err = OS_ERR_INVALID_OPT;
return ((OS_ALARM *)0);
}
#endif
if (OSIntNesting > 0) { /* See if called from ISR ... */
*err = OS_ERR_CREATE_ISR; /* ... can't CREATE from an ISR */
return ((OS_ALARM *)0);
}
OS_ENTER_CRITICAL();
alarm = OSAlarmFreeList; /* Get next free alarm */
if (alarm != (OS_ALARM *)0) { /* See if we have alarms available */
/* Adjust free list */
OSAlarmFreeList = (OS_ALARM *)OSAlarmFreeList->OSAlarmNext;
/* initialize alarm */
alarm->OSAlarmType = OS_ALARM_TYPE_IDLE; /* Set to alarm type */
alarm->OSAlarmFlagGrp = flag_group; /* event flag group to trigger on alarm */
alarm->OSAlarmFlags = flags;
#if (OS_ALARM_PERIODIC_EN > 0)
/* this indicates it is a period alarm type for OSAlarmSet() */
alarm->OSAlarmPeriod = (opt & OS_ALARM_PERIODIC);
#endif
alarm->OSAlarmNext = (void *)0; /* Clear list */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
/* free alarms list is empty */
} else {
OS_EXIT_CRITICAL();
*err = OS_ALARM_DEPLETED;
}
return (alarm); /* Return pointer to alarm */
}
/**
* Delete an alarm
*
* @param alarm The (idle) alarm to be deleted.
* @param err Pointer to error variable
*
* @note May not be called from inside an ISR.
* @note The alarm must be disabled. If the alarm is active, use OSAlarmDisable() first.
* @see OSAlarmDisable()
*/
void OSAlarmDel(OS_ALARM *alarm, INT8U *err)
{
#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)
/* is this a non-idle alarm? */
if (alarm->OSAlarmType != OS_ALARM_TYPE_IDLE)
{
OS_EXIT_CRITICAL();
*err = OS_ERR_ALARM_TYPE;
return;
}
#endif /* OS_ARG_CHK_EN */
/* free alarm */
alarm->OSAlarmType = OS_ALARM_TYPE_UNUSED;
/* put OSAlarm at head of freelist */
alarm->OSAlarmNext = (void *)OSAlarmFreeList;
OSAlarmFreeList = alarm;
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return;
}
/**
* Disable an active alarm
*
* @param alarm The (active) alarm to be disabled.
* @param err Pointer to error variable
* - OS_ERR_ALARM_TYPE is returned if the alarm was not active. This is not necessarily an
* error, as a one-shot alarm could have become non-active when it was triggered.
* - OS_NO_ERR The alarm is disabled.
*
* @see OSAlarmSet() to set and enable the alarm again.
*/
void OSAlarmDisable(OS_ALARM *alarm, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_ENTER_CRITICAL();
/* alarm not active, or no active alarms in list? */
if ((alarm->OSAlarmType != OS_ALARM_TYPE_ACTIVE) || (OSAlarmActiveList == (OS_ALARM *)0))
{
OS_EXIT_CRITICAL();
/* the alarm was not active */
/* this is not necessarily an error, as the alarm could have triggered
before the caller was notified through OSFlagGrp. */
*err = OS_ERR_ALARM_TYPE;
return;
}
/* alarm is head of active list? */
else if (OSAlarmActiveList == alarm)
{
/* remove from active list */
OSAlarmActiveList = alarm->OSAlarmNext;
}
/* multiple alarms on active list */
else
{
OS_ALARM *pred = OSAlarmActiveList;
/* find predecessor of this alarm */
while ((pred != (OS_ALARM *)0) && (pred->OSAlarmNext != alarm))
{
/* proceed to next in active list */
pred = pred->OSAlarmNext;
}
/* alarm is not present in alarm active list? */
if (pred == (OS_ALARM *)0)
{
OS_EXIT_CRITICAL();
/* failure, this alarm was not found in OSAlarmActiveList */
*err = OS_ERR_ALARM_TYPE;
return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -