📄 alarm.c
字号:
/**********************************************************************/
/* */
/* File name: alarm.c */
/* */
/* Since: 2004/09/20 */
/* */
/* Version: PICos18 v2.00 */
/* Copyright (C) 2003, 2004 Pragmatec. */
/* */
/* Author: Designed by Pragmatec S.A.R.L. www.pragmatec.net */
/* MONTAGNE Xavier [XM] xavier.montagne@pragmatec.net */
/* */
/* Purpose: The alarm manager is in charge of setting the */
/* alarm-timers or updating the alarm-counter from */
/* application layer. */
/* */
/* Distribution: This file is part of PICos18. */
/* PICos18 is free software; you can redistribute it */
/* and/or modify it under the terms of the GNU General */
/* Public License as published by the Free Software */
/* Foundation; either version 2, or (at your option) */
/* any later version. */
/* */
/* PICos18 is distributed in the hope that it will be */
/* useful, but WITHOUT ANY WARRANTY; without even the */
/* implied warranty of MERCHANTABILITY or FITNESS FOR A */
/* PARTICULAR PURPOSE. See the GNU General Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU General */
/* Public License along with gpsim; see the file */
/* COPYING.txt. If not, write to the Free Software */
/* Foundation, 59 Temple Place - Suite 330, */
/* Boston, MA 02111-1307, USA. */
/* */
/* > A special exception to the GPL can be applied should */
/* you wish to distribute a combined work that includes */
/* PICos18, without being obliged to provide the source */
/* code for any proprietary components. */
/* */
/* History: */
/* 2004/09/20 [XM] Create this file. */
/* */
/**********************************************************************/
#include "device.h"
/**********************************************************************
* Shared variables defined in other section.
**********************************************************************/
extern char id_tsk_run;
extern unsigned char stack_low, stack_high;
extern char kernelState;
extern TaskType tsk_1_state_ID;
extern EventMaskType event_1;
extern EventMaskType wait_1;
extern Counter Counter_list[];
extern Counter Counter_kernel;
extern AlarmObject Alarm_list[];
extern unsigned char ALARMNUMBER;
extern unsigned char COUNTERNUMBER;
extern unsigned long global_counter;
union Timers Tmr0;
/**********************************************************************
* ROM area of the alarm manager.
**********************************************************************/
#pragma code KERNEL_ROM
/**********************************************************************
* Program an alarm in relative mode with a number of tick to run from
* the current count value.
*
* @param ID IN ID of the alarm to update
* @param increment IN Number of ticks to run
* @param cycle IN Number of cycle to process
* @return Status E_OK if the alarm is not used
* E_OS_STATE if in USED mode
* E_OS_ID if ID is not correct
**********************************************************************/
StatusType SetRelAlarm(AlarmType ID, TickType increment, TickType cycle)
{
if (ID >= ALARMNUMBER)
return (E_OS_ID);
if (Alarm_list[ID].State == ON)
return (E_OS_STATE);
if ((increment < 0) ||
(increment > Alarm_list[ID].ptrCounter->Base.maxAllowedValue))
return (E_OS_VALUE);
if ((cycle < Alarm_list[ID].ptrCounter->Base.minCycle) ||
(cycle > Alarm_list[ID].ptrCounter->Base.maxAllowedValue))
return (E_OS_VALUE);
Alarm_list[ID].AlarmValue = Alarm_list[ID].ptrCounter->CounterValue + \
increment;
Alarm_list[ID].Cycle = cycle;
Alarm_list[ID].State = ON;
return (E_OK);
}
/**********************************************************************
* Program an alarm in absolute mode with a number of tick to run from
* the start count value.
*
* @param ID IN ID of the alarm to update
* @param start IN Nb of ticks to run from start
* @param cycle IN Number of cycle to process
* @return Status E_OK if the alarm is not used
* E_OS_STATE if in used mode
* E_OS_ID if ID is not correct
**********************************************************************/
StatusType SetAbsAlarm(AlarmType ID, TickType start, TickType cycle)
{
if (ID >= ALARMNUMBER)
return (E_OS_ID);
if (Alarm_list[ID].State == ON)
return (E_OS_STATE);
if ((start < 0) ||
(start > Alarm_list[ID].ptrCounter->Base.maxAllowedValue))
return (E_OS_VALUE);
if ((cycle < Alarm_list[ID].ptrCounter->Base.minCycle) ||
(cycle > Alarm_list[ID].ptrCounter->Base.maxAllowedValue))
return (E_OS_VALUE);
Alarm_list[ID].AlarmValue = start;
Alarm_list[ID].Cycle = cycle;
Alarm_list[ID].State = ON;
return (E_OK);
}
/**********************************************************************
* Give the number of tick to run to set the alarm.
*
* @param ID IN ID of the alarm to update
* @param Tick IN Reference of tick number
* @return Status E_OK if the alarm is in USED mode
* E_OS_NOFUNC if not used
* E_OS_ID if ID is not correct
**********************************************************************/
StatusType GetAlarm(AlarmType ID, TickRefType Tick)
{
if (ID >= ALARMNUMBER)
return (E_OS_ID);
if (Alarm_list[ID].State == OFF)
return (E_OS_NOFUNC);
*Tick = Alarm_list[ID].AlarmValue - \
Alarm_list[ID].ptrCounter->CounterValue;
return (E_OK);
}
/**********************************************************************
* Set the alarm in UNUSED mode.
*
* @param ID IN ID of the alarm to update
* @return Status E_OK if the alarm is in USE mode
* E_OS_NOFUNC if not used
* E_OS_ID if ID is not correct
**********************************************************************/
StatusType CancelAlarm(AlarmType ID)
{
if (ID >= ALARMNUMBER)
return (E_OS_ID);
if (Alarm_list[ID].State == OFF)
return (E_OS_NOFUNC);
Alarm_list[ID].State = OFF;
return (E_OK);
}
/*********************************************************************
* Give the info relative to Alarm Base.
*
* @param ID IN ID of the alarm to update
* @param Info IN Reference to the alarm base
* @return Status E_OK if the ID is correct
* E_OS_ID if not
*********************************************************************/
StatusType GetAlarmBase(AlarmType ID, AlarmBaseRefType Info)
{
if (ID >= ALARMNUMBER)
return (E_OS_ID);
Info = &(Alarm_list[ID].ptrCounter->Base);
return (E_OK);
}
/*********************************************************************
* Increment the counter in case of alarm with COUNTER mode.
*
* @param ID IN ID of the alarm to update
* @return Status E_OK if the ID is correct
* E_OS_ID if ID is not correct
*********************************************************************/
StatusType IncCounter(AlarmType ID)
{
return (E_OS_ID);
}
/*********************************************************************
* Give the current number of tick of the alarm in COUNTER mode.
* Work also with alarm in TIMER mode.
*
* @param ID IN ID of the alarm to update
* @param Tick IN Reference of tick number
* @return Status E_OK if ID is correct
* E_OS_ID if not correct
*********************************************************************/
StatusType GetCounterValue(AlarmType ID, TickRefType tick)
{
return (E_OS_ID);
}
/*********************************************************************
* Functions dedicated to the AddOneTick function.
* These permit to treat all the alarms without calling Schedule().
*
* @param ID IN ID of the task concerned by the alarm
* @param Mask IN Event to post if necessary
* @return Status E_OK if ID is correct
* E_OS_ID if not correct
*********************************************************************/
#if 0
StatusType _ActivateTask (TaskType TaskID)
{
unsigned char i;
TaskType temp;
TaskRefType ptr_task;
ptr_task = (TaskRefType)&tsk_1_state_ID;
for (i = 0; i < MAX_TASK_NB; i++)
{
temp = *ptr_task;
temp = temp & 0x1F;
if ( temp == TaskID )
{
*ptr_task &= 0x1F;
*ptr_task += READY;
return (E_OK);
}
ptr_task++;
}
return (E_OS_ID);
}
StatusType _SetEvent(TaskType TaskID, EventMaskType Mask)
{
unsigned char i;
TaskType temp;
TaskRefType ptr_task;
ptr_task = (TaskRefType)&tsk_1_state_ID;
for (i = 0; i < MAX_TASK_NB; i++, ptr_task++)
{
temp = *ptr_task;
temp = temp & 0x1F;
if ( temp == TaskID )
{
if ((*ptr_task & 0xE0) == SUSPENDED)
return (E_OS_STATE);
ptr_task = &event_1 + i;
*ptr_task |= Mask;
ptr_task = &wait_1 + i;
/* Not any task waiting for at least one event */
if ( (*ptr_task & Mask) == 0 )
return (E_OK);
else
{
ptr_task = (TaskRefType)&tsk_1_state_ID + i;
*ptr_task &= 0x1F;
*ptr_task |= READY;
return (E_OK);
}
}
}
if (i == 16)
return (E_OS_ID);
return (E_OK);
}
#endif
/**********************************************************************
* Parse the chained list of alarms (timer & counter).
* Increment timer only.
* Check if alarm event has to be treated according to AlarmTickValue
* and CurrentTickValue.
* Do it for number of cycle positive or null.
* Check if a task or event has to be activated.
* If a task is waiting the event, clear the event and wait flags
* (cf event.c) and set the task READY.
* Call the SCHEDULER at the end.
*
* @return void
**********************************************************************/
void AddOneTick (void)
{
unsigned char index, i;
StatusType done;
/* To setup 1 tick at 1ms */
TMR0H = Tmr0.bt[1];
TMR0L = Tmr0.bt[0];
INTCONbits.TMR0IF = 0;
Counter_kernel.CounterValue++;
global_counter++;
done = E_OS_VALUE;
for (index = 0; index < ALARMNUMBER; index++)
{
if (Alarm_list[index].State == OFF)
continue;
if (Alarm_list[index].ptrCounter->CounterValue ==
Alarm_list[index].AlarmValue)
{
if (Alarm_list[index].Cycle == 0)
Alarm_list[index].State = OFF;
else
{
Alarm_list[index].AlarmValue = \
Alarm_list[index].ptrCounter->CounterValue + \
Alarm_list[index].Cycle;
}
if (Alarm_list[index].EventToPost != 0)
SetEvent(Alarm_list[index].TaskID2Activate,
Alarm_list[index].EventToPost);
if ((Alarm_list[index].TaskID2Activate != 0) &&
(Alarm_list[index].EventToPost == 0))
ActivateTask(Alarm_list[index].TaskID2Activate);
if (Alarm_list[index].CallBack != 0)
Alarm_list[index].CallBack();
}
}
// Schedule();
return;
}
/* End of File : alarm.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -