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

📄 freq.cpp

📁 PCI的一个测试程序,可以测试PCI driver和BOARD的功能.
💻 CPP
字号:
#include "stdafx.h"
#include <Winbase.h>
#include <time.h>
#include "Freq.h"

int     nCPUFreq = 0;


int     CPU_Frequency(void); //MHz

class CTestFreq
{
private:
    time_t          tmStart;
    __int64         tscStart;
    
public:
    CTestFreq()
    {
        int temp_nCPUFREQ_i, MAX_nCPUFREQ=0;
        for (temp_nCPUFREQ_i = 0; temp_nCPUFREQ_i <10;++temp_nCPUFREQ_i)
        {
            nCPUFreq = CPU_Frequency();
            if (nCPUFreq > MAX_nCPUFREQ)
                MAX_nCPUFREQ = nCPUFreq;
        }

        nCPUFreq = MAX_nCPUFREQ ;

        time(&tmStart);
        GetCurrentTSC(tscStart);
    }
    ~CTestFreq()
    {
        _RepairTime();
    }

    void    _RepairTime();
};

void    CTestFreq::_RepairTime()
{
    time_t          tmNow;
    __int64         tscNow;

    GetCurrentTSC(tscNow);

    tmNow = tmStart + ((tscNow - tscStart) / nCPUFreq) / 1000000;

    struct  tm  tNow;
    tNow = *localtime(&tmNow);

    SYSTEMTIME  sysTime;

    sysTime.wYear           = tNow.tm_year + 1900;
    sysTime.wMonth          = tNow.tm_mon  + 1;
    sysTime.wDayOfWeek      = tNow.tm_wday;
    sysTime.wDay            = tNow.tm_mday;
    sysTime.wHour           = tNow.tm_hour;
    sysTime.wMinute         = tNow.tm_min;
    sysTime.wSecond         = tNow.tm_sec;
    sysTime.wMilliseconds   = 0;

//    SetLocalTime(&sysTime);
}

static CTestFreq tmpTestFreqObj;
/*
Operating Frequency

With the introduction of the Time-Stamp Counter, it is possible for software operating in real
mode or protected mode with ring 0 privilege to calculate the actual operating frequency of the
processor. To calculate the operating frequency, the software needs a reference period. The
reference period can be a periodic interrupt, or another timer that is based on time, and not based
on a system clock. Software needs to read the Time-Stamp Counter (TSC) at the beginning and
ending of the reference period. Software can read the TSC by executing the RDTSC instruction,
or by setting the ECX register to 10h and executing the RDMSR instruction. Both instructions
copy the current 64-bit TSC into the EDX:EAX register pair.
To determine the operating frequency of the processor, software performs the following steps.
The assembly language program frequenc.asm (see Example 6) demonstrates the frequency
detection algorithm.
1. Execute the CPUID instruction with an input value of EAX=0 and ensure the vendor-ID
string returned is “GenuineIntel”.
2. Execute the CPUID instruction with EAX=1 to load the EDX register with the feature flags.
3. Ensure that the TSC feature flag (EDX bit 4) is set. This indicates the processor supports the
Time-Stamp Counter and RDTSC instruction.
4. Read the TSC at the beginning of the reference period.
5. Read the TSC at the end of the reference period.
6. Compute the TSC delta from the beginning and ending of the reference period.
7. Compute the actual frequency by dividing the TSC delta by the reference period.
Actual frequency = (Ending TSC value – Beginning TSC value) / reference period
Note: The measured accuracy is dependent on the accuracy of the reference period. A longer
reference period produces a more accurate result. In addition, repeating the calculation
multiple times may also improve accuracy.

*/
int CPU_Frequency(void) //MHz
{
    LARGE_INTEGER CurrTicks, TicksCount;
    __int64 iStartCounter, iStopCounter;

    DWORD dwOldProcessP = GetPriorityClass(GetCurrentProcess());
    DWORD dwOldThreadP = GetThreadPriority(GetCurrentThread());

    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);

    QueryPerformanceFrequency(&TicksCount);
    QueryPerformanceCounter(&CurrTicks);

    TicksCount.QuadPart /= 16;
    TicksCount.QuadPart += CurrTicks.QuadPart;

    _asm rdtsc
    _asm mov DWORD PTR iStartCounter, EAX
    _asm mov DWORD PTR (iStartCounter+4), EDX

    while(CurrTicks.QuadPart<TicksCount.QuadPart)
        QueryPerformanceCounter(&CurrTicks);

    _asm rdtsc
    _asm mov DWORD PTR iStopCounter, EAX
    _asm mov DWORD PTR (iStopCounter + 4), EDX

    SetThreadPriority(GetCurrentThread(), dwOldThreadP);
    SetPriorityClass(GetCurrentProcess(), dwOldProcessP);

    return (int)((iStopCounter-iStartCounter)/62500);
}

void    GetCurrentTSC(__int64& TicksCount)
{
//	Inportb(0x378+1);
    __int64 tmpCounter;

    _asm rdtsc
    _asm mov DWORD PTR tmpCounter, EAX
    _asm mov DWORD PTR (tmpCounter+4), EDX

    TicksCount = tmpCounter;
}

void    RepairTime()
{
    tmpTestFreqObj._RepairTime();
}

⌨️ 快捷键说明

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