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

📄 virtualtimer.c

📁 CNC.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
//*****************************************************************************
//
// 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 + -