📄 virtualtimer.c
字号:
//*****************************************************************************
//
// virtualtimer.c - Virtual timer driver.
//
// Copyright (c) 2006-2007 Luminary Micro, Inc. All rights reserved.
//
// Software License Agreement
//
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
//
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws. All rights are reserved. Any use in violation
// of the foregoing restrictions may subject the user to criminal sanctions
// under applicable laws, as well as to civil liability for the breach of the
// terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 220 of sw01246.
//
//*****************************************************************************
#include "hw_ints.h"
#include "hw_memmap.h"
#include "hw_types.h"
#include "interrupt.h"
#include "timer.h"
#include "virtualtimer.h"
//*****************************************************************************
//
//! \page main_virtualtimer_intro Introduction
//!
//! The number of timers required to control the CNC machine exceeds the number
//! of hardware timers available on the LM3S615. Therefore, a virtual timer
//! mechanism is utilized to provide an "unlimited" number of timers to the
//! application (the only real limit is the amount of RAM that can be dedicated
//! to virtual timer structures).
//!
//! The virtual timer mechanism utilizes an earliest deadline first scheduler.
//! When a virtual timer expires, or a new virtual timer is added, the next
//! virtual timer to expire is determined and a real timer is set to generate
//! an interrupt at that point. This process repeats as long as there are
//! virtual timers set to expire, and when stopped it will restart again as
//! soon as a new virtual timer is added.
//!
//! The virtual timers are one-shot timers; periodic timers can be created by
//! re-adding the virtual timer (after adjusting the time-out) in the virtual
//! timer handler.
//!
//! The code for the virtual timers is contained in
//! <tt>main_micro/virtualtimer.c</tt>, with <tt>main_micro/virtualtimer.h</tt>
//! containing the API definitions for use by the remainder of the application.
//
//*****************************************************************************
//*****************************************************************************
//
//! \defgroup main_virtualtimer_api Definitions
//! @{
//
//*****************************************************************************
//*****************************************************************************
//
//! The number of virtual timers to support.
//
//*****************************************************************************
#define NUM_TIMERS 16
//*****************************************************************************
//
//! An array pointers to the currently active virtual timers. A NULL pointer
//! indicates an unused virtual timer.
//
//*****************************************************************************
static tVirtualTimer *g_psVirtualTimers[NUM_TIMERS];
//*****************************************************************************
//
//! The index of the next virtual timer to expire.
//
//*****************************************************************************
static unsigned long g_ulVirtualTimer;
//*****************************************************************************
//
//! A set of flags to indicate the state of the virtual timer driver; contains
//! the #VT_FLAG_INT_ACTIVE flag.
//
//*****************************************************************************
static unsigned long g_ulVirtualTimerFlags;
//*****************************************************************************
//
//! The bit number in #g_ulVirtualTimerFlags of the flag that is set when there
//! the real timer interrupt handler is active.
//
//*****************************************************************************
#define VT_FLAG_INT_ACTIVE 0
//*****************************************************************************
//
//! Set the real timer for the expiration of the next virtual timer.
//!
//! This function determines the next virtual timer to expire and sets the real
//! timer to interrupt at the appropriate time. If the one of more of the
//! virtual timers have already expired (such as a virtual timer expiring while
//! another virtual timer's handler is executing), that virtual timer is
//! handled directly without further delay (i.e. the real timer is not set and
//! it does not wait for an interrupt).
//!
//! \return None.
//
//*****************************************************************************
static void
VirtualTimerSchedule(void)
{
unsigned long ulIdx, ulNow, ulEarliest, ulA, ulB;
tVirtualTimer *pTimer;
//
// Loop until there are no more virtual timers or a virtual timer with an
// expiration time in the future is found.
//
while(1)
{
//
// Loop through the list of virtual timers, looking for the one with
// the earliest expiration time.
//
ulEarliest = 0xffffffff;
for(ulIdx = 0; ulIdx < NUM_TIMERS; ulIdx++)
{
//
// See if this timer is active.
//
if(g_psVirtualTimers[ulIdx] != 0)
{
//
// If this is the first virtual timer found, then it is the one
// with the earliest expiration time thus far.
//
if(ulEarliest == 0xffffffff)
{
ulEarliest = ulIdx;
}
//
// Otherwise, check to see if this virtual timer expires before
// the virtual timer that is the earliest thus far.
//
else
{
//
// Get the expiration times of the earliest and this
// virtual timer.
//
ulA = g_psVirtualTimers[ulEarliest]->ulTimeOut;
ulB = g_psVirtualTimers[ulIdx]->ulTimeOut;
//
// If this virtual timer expires before the earliest thus
// far, then make this virtual timer the one with the
// earliest expiration time.
//
if(((ulB < ulA) && ((ulA - ulB) < 0x10000000)) ||
((ulB > ulA) && ((ulB - ulA) > 0xf0000000)))
{
ulEarliest = ulIdx;
}
}
}
}
//
// If no virtual timers were found, then return without setting the
// real timer.
//
if(ulEarliest == 0xffffffff)
{
return;
}
//
// Get the present time.
//
ulNow = 0xffffffff - TimerValueGet(TIMER1_BASE, TIMER_A);
//
// See if this virtual timer has already expired.
//
if((g_psVirtualTimers[ulEarliest]->ulTimeOut - ulNow - 1) > 0xf0000000)
{
//
// Get the pointer to this virtual timer.
//
pTimer = g_psVirtualTimers[ulEarliest];
//
// Remove this virtual timer from the list.
//
g_psVirtualTimers[ulEarliest] = 0;
//
// Call the virtual timer's handler.
//
pTimer->pfnHandler();
//
// Check the list again for the earliest virtual timer.
//
continue;
}
//
// A virtual timer that expires in the future was found, so stop
// looking.
//
break;
}
//
// Save the index of the next virtual timer to expire.
//
g_ulVirtualTimer = ulEarliest;
//
// Set the real timer to expire when the virtual timer is set to expire.
//
ulNow = g_psVirtualTimers[ulEarliest]->ulTimeOut - ulNow - 1;
if(ulNow > 0xf0000000)
{
ulNow = 1;
}
TimerLoadSet(TIMER2_BASE, TIMER_A, ulNow);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -