📄 timerd.c
字号:
/* -*-C-*- * * $Revision: 1.3 $ * $Author: rivimey $ * $Date: 1999/03/22 14:44:49 $ * * Copyright (c) 1996 Advanced RISC Machines Limited. * All Rights Reserved. * * Project: ANGEL * * Title: Angel Timer driver * */#ifdef TEST#define INLINE_LIST_FNSint Angel_Needschedule;#ifndef bool#define bool int#endif#ifndef NULL#define NULL 0#endif#ifndef FALSE#define FALSE 0#define TRUE 1#endif#else /* not TEST */#include "angel.h"#include "arm.h"#include "devconf.h"#include "serlock.h"#include "logging.h"#endif /* TEST */#if defined(TEST) || (defined(TIMER_SUPPORTED) && TIMER_SUPPORTED > 0)#include "timerd.h"#include "list.h"static volatile unsigned long Timer_currentTime;static bool timer_initialised;typedef struct _timer{ MinNode n; long interval; long delay; short flags; short index; union { TimerCallback fn; int taskid; } obj; int data; /* the signal or a fn arg */} angel_Timer;#include "timerlist.h"static angel_Timer angel_Timer_Pool[MAX_TIMERS];static List angel_Active_Timers;static List angel_Free_Timers;static void timer_delTimer(angel_Timer *t);static void timer_queueTimer(angel_Timer *this);#ifdef TEST_PRINTvoid timer_printList(char *str);#else#define timer_printList(s)#endif#if 0void timer_printList(char *str){ angel_Timer *tl = Timer_FirstNode(&angel_Active_Timers); LogInfo(LOG_TIMER, (str)); while(!Timer_AtEndOfList(tl)) { LogInfo(LOG_TIMER, ("[ i(%d) d(%d) %c%c%c ] ", tl->interval, tl->delay, tl->flags & TF_ALLOC ? 'A' : 'a', tl->flags & TF_SIGNALME ? 'S' : 's', tl->flags & TF_RELOAD ? 'R' : 'r')); tl = Timer_Succ(tl); } LogInfo(LOG_TIMER, ("\n"));}#endif/* * Function: Timer_CurrentTime * * Purpose: return the current time, measured in * milliseconds * * Arguments: none. * * * Return: unsigned long - the time in milliseconds * since 'some point'. * * Pre-conditions: none. * * Post-conditions: none. * */unsigned long Timer_CurrentTime(void){ return Timer_currentTime;}/* * Function: Timer_Delay * * Purpose: delay the current task for a number of milliseconds. * * * Arguments: delay - a delay in milliseconds. the routine will. * return after at least this number of milliseconds * has elapsed. (Note: the actual delay will be * rounded up to a multiple of CLK_TICK milliseconds). * * Return: none * * Pre-conditions: Only call if interrupts are enabled, Timer_Initialise * AngelOS_Initialise have been called, and the scheduler * entered. * * Post-conditions: none. * */void Timer_Delay(unsigned long delay){ int t; if ((Angel_GetCPSR() & AngelInterruptMask) != 0) { LogWarning(LOG_TIMER, ("Timer_Delay: Interrupts not enabled in Delay")); return; } t = Timer_NewTimer(delay, TF_SIGNALME, (TimerCallback)Angel_TaskID(), SIGBIT_DELAY); LogInfo(LOG_TIMER, ("Delay: Using timer %d\n", t)); Angel_Wait(SIGBIT_DELAY); LogInfo(LOG_TIMER, ("Delay: wakeup\n"));}/* * Function: Timer_Tick * * Purpose: "tick" function, which advances time. * Expects to be called regularly, preferably at * millisecond intervals * * Firstly, increment the current time variable * by CLK_TCK milliseconds. * * Second, inspect the timer list. If there are * timers, decrement the head timer delay; if it * drops to zero the timer has expired. Fire the * timer. * * The next timer could also * * Arguments: empty_stack - the empty stack value which would * be required to serialise a task. * * Return: none * * Pre-conditions: * * * * Post-conditions: * */void Timer_Tick(unsigned empty_stack){ /* increment the current time... */ Timer_currentTime += CLK_TCK; if (!IsListEmpty(&angel_Active_Timers)) { register angel_Timer *tl = Timer_FirstNode(&angel_Active_Timers); timer_printList("tick"); /* decrement the delay until the next event */ tl->delay -= CLK_TCK; while (tl != NULL && tl->delay <= 0) { /* LogInfo(LOG_TIMER, ("FireTimer: %d\n", tl->index)); */ if (tl->flags & TF_SIGNALME) { if (Angel_Signal(tl->obj.taskid, tl->data)) Angel_Needschedule = 1; } else { tl->obj.fn(tl->data, empty_stack); } /* ... delete the timer (& modify next delay if necessary) ... */ timer_delTimer(tl); /* ... if reloading, requeue the timer, else free it */ if (tl->flags & TF_RELOAD) timer_queueTimer(tl); else Timer_AddTail(&angel_Free_Timers, tl); /* and get the new timer head, to check the next delay. */ tl = Timer_FirstNode(&angel_Active_Timers); } } return;}/* * Function: Timer_Initialise * * Purpose: * * * * * Arguments: none * * Return: none * * Pre-conditions: none * * * Post-conditions: * */void Timer_Initialise(void){ int i; NewList(&angel_Active_Timers); NewList(&angel_Free_Timers); for(i = 0; i < MAX_TIMERS; i++) { angel_Timer_Pool[i].index = i; angel_Timer_Pool[i].flags = 0; angel_Timer_Pool[i].delay = 0; angel_Timer_Pool[i].interval = 0; Timer_AddTail(&angel_Free_Timers, &angel_Timer_Pool[i]); } Timer_currentTime = 0; Angel_TimerDev.timer_init(); timer_initialised = TRUE; LogInfo(LOG_TIMER, ("Timer Initialised\n")); /* set the timer going at 1ms interval */ Angel_TimerDev.timer_set_interval(CLK_TCK * 1000); Angel_TimerDev.timer_start(); LogInfo(LOG_TIMER, ("Timer Started\n"));}/* * Function: Timer_NewTimer * * Purpose: To create a new timer, which can be used to schedule * timed events, for example, the poll event, or the * SYS_TIME 1 second clock. * * Arguments: * interval - time in ms from now to event, and interval * from then to next event if RELOAD * flags - TF_SIGNALME - Signal event, else call fn * TF_RELOAD - reload timer on expiry * fn - function to call, or task id to signal * arg - arg of function, or signal bit to signal. * * Return: none * * Pre-conditions: Timer_Initialse must have been called. * * Post-conditions: * */int Timer_NewTimer(long interval, int flags, TimerCallback fn, int data){ angel_Timer *tl; int s = Angel_TimerDev.timer_critical(); LogInfo(LOG_TIMER, ("NewTimer: interval %ld, fn %p\n", interval, fn)); tl = Timer_RemHead(&angel_Free_Timers); if (tl == NULL) { Angel_TimerDev.timer_normal(s); return -1; } tl->flags = TF_ALLOC | flags; Angel_TimerDev.timer_normal(s); tl->interval = interval; tl->delay = 0; tl->data = data; if (flags & TF_SIGNALME) tl->obj.taskid = (int)fn; else tl->obj.fn = (TimerCallback)fn; timer_queueTimer(tl); LogInfo(LOG_TIMER, ("NewTimer: returning %d\n", tl->index)); timer_printList("new"); return tl->index;}/* * Function: timer_queueTimer * * Purpose: To add a new timer to the timer queue. The queue is * ordered by relative time; the sooner a timer is to * going off, the nearer the timer is to the head of the * list. The "delay" element of the timer indicates the * gap in time between the previous timer (or Now) and * this one, thus the 'tick' interrupt only has to * modify the head of the list, if any. * * Thus, if there are no timers in the list, then this * one can be added with a delay equal to the interval. * * If not, then the effective interval (that part of the * interval between now and the time a particular timer * expires) must be calculated and the interval for the * new timer compared to it. When the effective interval * becomes larger than the new interval, the new timer * can be inserted in front of the list. * * Finally, if this interval is longer than any other, * the new one must be added to the end of the list. * * * Arguments: this - a partly-initialised angel_Timer_Pool element. * it is expected that the interval, obj and data * elements are filled in. * * Return: none * * Pre-conditions: Timer head and tail initialised; "this" members obj, * data and interval initialised. * * * Post-conditions: angel_Timer_Pool element added to timer queue. * */static void timer_queueTimer(angel_Timer *this){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -