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

📄 timer.c

📁 实时嵌入式操作系统内部关于定时器的应用
💻 C
字号:
/*
 * timer/timer.c
 *
 * Copyright (C) SGS-THOMSON Microelectronics Ltd. 1997
 *
 * Generic time handling functions for external timers
 */

#include <stddef.h>
#include <os20.h>
#include <os20i.h>
#include <task.h>
#include <c1timeri.h>
#include <c1timer.h>
#include <element.h>
#include <assert.h>
#include <debug.h>

#define FIXOFFSET(s) ((char *) s-offsetof(tdesc_t,tdesc_tlink))

list_t   timer_queue;

static void timer_enable_int(void)
{
  (*timer_enable_int_ptr)();
}

static void timer_raise_int(void)
{
  (*timer_raise_int_ptr)();
}

static void timer_disable_int(void)
{
  (*timer_disable_int_ptr)();
}

static void timer_set(int p )
{
  (*timer_set_ptr)(p);
}

static int timer_read(void)
{
  return ((*timer_read_ptr)());
}

static __inline void timer_queue_add(int Time)
{
  tdesc_t* t;
  tdesc_t* tdesc;
  element_t* elem;
  
  __optasm { 
    ldtdesc; 
    stl tdesc; 
  }
 
  tdesc->tdesc_tdelay = Time;

  elem = HEAD(&timer_queue);
  if (is_empty(&timer_queue)) { 

    add_head(&timer_queue,(element_t*) &(tdesc->tdesc_tlink));
    timer_set(Time);

  } else {

    while((elem != (element_t *) &timer_queue)) {

      t = (tdesc_t *) FIXOFFSET(elem);
      if (time_after( t->tdesc_tdelay, Time )) {

	if (HEAD(&timer_queue) == elem) {
	  add_head(&timer_queue,(element_t *) &tdesc->tdesc_tlink);
	  timer_set(Time);
	} else {
          element_t *e = (element_t *) &tdesc->tdesc_tlink;
          NEXT(PREV(elem)) = e;
          PREV(e) = PREV(elem);
          PREV(elem) = e;
          NEXT(e) = elem;
	}
        return;
      } else {
        elem = NEXT(elem);
      }	 
    }
    /* end of list */	
    add_tail(&timer_queue,(element_t *) &tdesc->tdesc_tlink);	 
  }
  return;
}

static __inline void timer_enable(void)
{
  tdesc_t* tdesc;

  __optasm {
    ldtdesc;
    stl tdesc;
  }

  timer_enable_int();                           /* enable interrupt or timer */
  if (tdesc->tdesc_tstate == ENABLING_P) 
    if (time_after(timer_read(),tdesc->tdesc_tdelay))
      timer_raise_int();                   
}

void timer_wait(const clock_t *timeout)
{
  tdesc_t *tdesc;
  INTERRUPT_DECLARE;

  /* if the timeout is not infinate we must setup an expiry time */
  if (TIMEOUT_INFINITY != timeout) {

    /* enqueue the tdesc onto the timer queue */
    INTERRUPT_LOCK();
    timer_queue_add(*timeout);
    INTERRUPT_UNLOCK();

    /* enable the timer plugins timer interrupt (and check that the timer
     * is not already due)
     */
    timer_enable();
  }

  __optasm {
    ldtdesc;
    stl tdesc;
  }

  /* block the task unless the timer has already elapsed or the semaphore
   * has already been signaled.
   *
   * this mimics the ST20-C2 behaviour since waiting for a time in the
   * past or very near future does not guarantee a deschedule.
   */
  INTERRUPT_LOCK();
  if (tdesc->tdesc_tstate == ENABLING_P) {
    tdesc->tdesc_tstate = WAITING_P;

    TIMESLICE_UNLOCK();
    __optasm {
      stop;
    }
  }
  INTERRUPT_UNLOCK();

}

static void _task_delay_until(unsigned int Time)
{
  tdesc_t* tdesc;
  __optasm {
    ldtdesc;
    stl tdesc;
  } 
  tdesc->tdesc_tstate = ENABLING_P;
  timer_wait(&Time);
} 
 
static void _task_delay(unsigned int Delay)
{
  _task_delay_until(timer_read()+Delay);
}

void timer_interrupt(void)
{
  tdesc_t* tdesc;
  element_t* elem, *next;

  FATAL_ERROR_IF(task_context_interrupt != task_context(NULL, NULL),
                 "illegal operation *not* from interrupt");

  elem = HEAD(&timer_queue);
  
  while(elem!=(element_t *) &timer_queue) {

    tdesc = (tdesc_t *) FIXOFFSET(elem);
    next = (element_t*)tdesc->tdesc_tlink;
 
    if ( time_after( timer_read(),tdesc->tdesc_tdelay)) {     

      rem_element(elem);
      if (tdesc->tdesc_tstate == WAITING_P) {
        __optasm { 
          ldl tdesc; 
          run; 
        }
      } else {
        tdesc->tdesc_tstate = READY_P;
      }

      elem = next;
    } else {   
      timer_set(tdesc->tdesc_tdelay);
      if (!time_after(timer_read(),tdesc->tdesc_tdelay)) {
        return;    
      }
    }
  }
  if (is_empty(&timer_queue))
    timer_disable_int();
  return;
}

void timer_initialize(timer_api_t *api)
{
  FATAL_ERROR_IF_NOT_TASK();
  FATAL_ERROR_IF_LOCKED();

  init_list((list_t *) &timer_queue);

  time_now_ptr = api->timer_read;
  task_delay_ptr = &_task_delay;
  task_delay_until_ptr = &_task_delay_until;

  timer_set_ptr = api->timer_set;
  timer_read_ptr = api->timer_read;
  timer_enable_int_ptr = api->timer_enable_int;
  timer_disable_int_ptr = api->timer_disable_int;
  timer_raise_int_ptr = api->timer_raise_int; 
}

⌨️ 快捷键说明

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