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

📄 alarm.c

📁 PICOS18 V2.10 基于PIC18的实时操作系统
💻 C
字号:
/**********************************************************************/
/*                                                                    */
/* File name: alarm.c                                                 */
/*                                                                    */
/* Since:     2004-Sept-20                                            */
/*                                                                    */
/* Version:   PICos18 v2.10                                           */
/*            Copyright (C) 2003, 2004, 2005 Pragmatec.               */
/*                                                                    */
/* Author:    Designed by Pragmatec S.A.R.L.        www.pragmatec.net */
/*            MONTAGNE Xavier [XM]      xavier.montagne@pragmatec.net */
/*            NIELSEN  Peter  [PN]                   pnielsen@tuug.fi */
/*                                                                    */
/* 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.                                 */
/* 2005/04/01 [XM]  Suppress "kernelState |= SERVICES;" at the end of */
/*                  the file to avoid a systematic switch context.    */
/* 2006/01/18 [XM]  Removed functions like _SetEvent.                 */
/*                  Completed IncCounter and GetCounter functions.    */
/*                  Added "kernelState |= SERVICES;" in AddOneTick(). */
/* 2007/01/01 [PN]  Improved alarm accuracy in TMR0 ISR.              */
/*                                                                    */
/**********************************************************************/

#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 > 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 > 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_ACCESS if counter is OFF
 *                   E_OS_ID if ID is not correct
 *********************************************************************/
StatusType IncCounter(AlarmType ID)
{
  if (ID >= ALARMNUMBER)
    return (E_OS_ID);

  if (Alarm_list[ID].State == OFF)
    return(E_OS_ACCESS);

  Alarm_list[ID].ptrCounter->CounterValue++;
  if (Alarm_list[ID].ptrCounter->CounterValue == 
      Alarm_list[ID].AlarmValue)
  {
    if (Alarm_list[ID].Cycle == 0)
      Alarm_list[ID].State = OFF;
    else
    {
      Alarm_list[ID].AlarmValue = \
        Alarm_list[ID].ptrCounter->CounterValue + \
        Alarm_list[ID].Cycle;
    }
    if (Alarm_list[ID].EventToPost != 0)
      SetEvent(Alarm_list[ID].TaskID2Activate, 
               Alarm_list[ID].EventToPost);
    if ((Alarm_list[ID].TaskID2Activate != 0) &&
        (Alarm_list[ID].EventToPost == 0))
      ActivateTask(Alarm_list[ID].TaskID2Activate);
    if (Alarm_list[ID].CallBack != 0)
      Alarm_list[ID].CallBack();
  }
  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_ACCESS if counter is OFF
 *                   E_OS_ID if not correct
 *********************************************************************/
StatusType GetCounterValue(AlarmType ID, TickRefType tick)
{
  if (ID >= ALARMNUMBER)
    return (E_OS_ID);

  if (Alarm_list[ID].State == OFF)
    return(E_OS_ACCESS);

  *tick = Alarm_list[ID].ptrCounter->CounterValue;
  return (E_OK);
}

/**********************************************************************
 * 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;

  /* To setup 1 tick at 1ms */
  /*TMR0H = Tmr0.bt[1];*/
  /*TMR0L = Tmr0.bt[0];*/
  
  /* To setup 1 tick at 1ms (improved no-drag version) */ 
  union Timers tmr; /* Temp for holding timer value */ 
  tmr.bt[0] = TMR0L; /* Read TMR0 */ 
  tmr.bt[1] = TMR0H; 
  tmr.lt += Tmr0.lt; /* Add offset value to TMR0 */ 
  TMR0H = tmr.bt[1]; 
  TMR0L = tmr.bt[0]; /* Update TMR0 */ 


  INTCONbits.TMR0IF = 0;
  Counter_kernel.CounterValue++;
  global_counter++;
  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();
    }
  }

  kernelState |= SERVICES;
  return;
}


/* End of File : alarm.c */

⌨️ 快捷键说明

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