I create an extended 64 bit version of the free running timer.
But if I want to use it into some threads, I need to ensure that 2
threads reading tc4 will read the correct values;
No process interrupts the reading of the low 32 bits tc4 and the
high 32 bits tc4 sequence. I just don't want a thread reading tc4 at
the same time than an other one reading the high 32 bits.
check my routine , (inspire from Jesse Off ,messages #10), GetFRTime()
////// FreeRunningTimer.c
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/mman.h>
#include<stdio.h>
#include<fcntl.h>
#include "FreeRunningTimer.h"
int FRTimerHandle=-1;
unsigned char *FRTimerBase=NULL;
unsigned long *FRTimerLo=NULL;
unsigned long *FRTimerHi=NULL;
unsigned long FRTimerExtHi=0; // use to go behond 40 bit (extended)
/* InitFRTimer
* map physical address
* return 0 if we can't mapped
* return 1 if everything ok
*/
int InitFRTimer(void)
{
FRTimerHandle= open("/dev/mem",O_RDWR);
if(FRTimerHandle<0) return(0);
FRTimerBase =
mmap(0,getpagesize(),PROT_WRITE|PROT_READ,MAP_SHARED,FRTimerHandle,0x80810000UL);
if(FRTimerBase == NULL)
{
CloseFRTimer();
return(0);
}
FRTimerLo= (unsigned long *) (FRTimerBase + 0x60UL); // get Least
significant long
FRTimerHi= (unsigned long *) (FRTimerBase + 0x64UL); // get Most
significant long
*FRTimerHi=0x100; // start Timer
return(1);
}
/* CloseFRTimer
* release map of physical address
*/
void CloseFRTimer(void)
{
if(FRTimerHandle>=0)
{
if(FRTimerBase)
munmap(FRTimerBase,getpagesize());
close(FRTimerHandle);
}
FRTimerHandle=-1;
FRTimerBase=NULL;
FRTimerLo=NULL;
FRTimerHi=NULL;
}
/* ResetFRTimer
* Reset and enable Free running timer
*/
void ResetFRTimer(void)
{
*FRTimerHi= 0;
*FRTimerHi= 0x100; // enable free running Timer
FRTimerExtHi=0; // reset extended bit
}
/* GetFRTimer
* return current free running timer value
*/
unsigned long long GetFRTimer(void)
{
// need to be run at least once every 300 hours
// for the extended bit system to work!
unsigned long long tval;
unsigned long HiVal;
// need to disable irq here
//
// ??????
tval = *FRTimerLo;
HiVal= *FRTimerHi & 0xff;
// need to enable irq here
//
// ?????
if(HiVal < (FRTimerExtHi & 0xff))
{
// ok we got a wrapped Timer;
FRTimerExtHi += 0x100; // increment bit 40
}
FRTimerExtHi &= ~0xff;
FRTimerExtHi |= HiVal;
tval |= ((unsigned long long ) FRTimerExtHi) << 32;
return(tval);
}
////// FreeRunningTimer.h
#ifndef FREE_RUNNING_TIMER_H
#define FREE_RUNNING_TIMER_H
int InitFRTimer(void);
void CloseFRTimer(void);
void ResetFRTimer(void);
unsigned long long GetFRTimer(void);
#define FRTimerToMs(A) (((unsigned long long) A) / 984ULL)
#define MsToFRTimer(A) (((unsigned long long) A) * 984ULL)
//#define FRTimerToMs(A) ((unsigned long long) A >> 10)
//#define MsToFRTimer(A) ((unsigned long long) A << 10)
int IsFRTimerPassed(unsigned long long BaseTime,\
unsigned long long CurrentTime);
#endif
////A test program to check if the FRTimer works!
#include<stdio.h>
#include<stdlib.h>
#include "freeRunningTimer.h"
#define OUTPUT_ON 1
#define OUTPUT_OFF 0
void Output(int Value)
{
static int phy_out=0; // emulate real output
unsigned long long tcount;
tcount= GetFRTimer();
if(phy_out==OUTPUT_ON)
{
if(!Value)
{
phy_out=OUTPUT_OFF; // emulate off
printf("Output OFF at %llu
(ms)\n",FRTimerToMs(tcount));fflush(stdout);
}
}
else
{
if(Value)
{
phy_out=OUTPUT_ON; // emulate on
printf("Output ON at %llu
ms\n",FRTimerToMs(tcount));fflush(stdout);
}
}
}
int main(void)
{
int cycle;
unsigned long long basecount;
unsigned long long currentcount;
if(!InitFRTimer())
{
printf("Unable to Map Free running Timer\n");
return(1);
}
ResetFRTimer();
basecount =0;
for(cycle=0;cycle<5;cycle++)
{
printf("cycle %d\n",cycle);fflush(stdout);
while(1)
{
currentcount = GetFRTimer()- basecount;
if(FRTimerToMs(currentcount) < 1330ULL) // 1.33 seconds
Output(OUTPUT_ON);
else
Output(OUTPUT_OFF);
if(FRTimerToMs(currentcount) > 5000ULL) // 5 seconds
{
basecount += MsToFRTimer(5000ULL); // basecount to
next cycle
break;
}
}
}
printf("Done\n");
CloseFRTimer();
return(0);
}
Yahoo! Groups Links
<*> To visit your group on the web, go to:
http://groups.yahoo.com/group/ts-7000/
<*> To unsubscribe from this group, send an email to:
<*> Your use of Yahoo! Groups is subject to:
http://docs.yahoo.com/info/terms/
|