You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
4.9 KiB
201 lines
4.9 KiB
|
|
extern "C" { |
|
// AVR LibC Includes |
|
#include "WConstants.h" |
|
} |
|
|
|
#include "APM_PerfMon.h" |
|
|
|
// don't know why i need these |
|
// see http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=410870 |
|
int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);}; |
|
void __cxa_guard_release (__guard *g) {*(char *)g = 1;}; |
|
void __cxa_guard_abort (__guard *) {}; |
|
|
|
// static class variable definitions |
|
int APM_PerfMon::nextFuncNum; |
|
char APM_PerfMon::functionNames[PERFMON_MAX_FUNCTIONS][PERFMON_FUNCTION_NAME_LENGTH]; |
|
unsigned long APM_PerfMon::time[PERFMON_MAX_FUNCTIONS]; |
|
unsigned long APM_PerfMon::numCalls[PERFMON_MAX_FUNCTIONS]; |
|
unsigned long APM_PerfMon::allStartTime; |
|
unsigned long APM_PerfMon::allEndTime; |
|
APM_PerfMon* APM_PerfMon::lastCreated = NULL; |
|
|
|
// constructor |
|
APM_PerfMon::APM_PerfMon(int funcNum) |
|
{ |
|
// stop recording time from parent |
|
if( lastCreated != NULL ) |
|
lastCreated->stop(); |
|
|
|
// check global start time |
|
if( allStartTime == 0 ) |
|
allStartTime = micros(); |
|
|
|
_funcNum = funcNum; // record which function we should assign time to |
|
_parent = lastCreated; // add pointer to parent |
|
lastCreated = this; // record myself as the last created instance |
|
|
|
numCalls[_funcNum]++; // record that this function has been called |
|
start(); // start recording time spent in this function |
|
} |
|
|
|
// destructor |
|
APM_PerfMon::~APM_PerfMon() |
|
{ |
|
stop(); // stop recording time spent in this function |
|
lastCreated = _parent; // make my parent the last created instance |
|
|
|
// restart recording time for parent |
|
if( lastCreated != NULL ) |
|
lastCreated->start(); |
|
} |
|
|
|
// stop recording time |
|
void APM_PerfMon::stop() |
|
{ |
|
time[_funcNum] += (micros()-_startTime); |
|
} |
|
|
|
// stop recording time |
|
void APM_PerfMon::start() |
|
{ |
|
_startTime = micros(); // restart recording time spent in this function |
|
} |
|
|
|
// record function name in static list |
|
int APM_PerfMon::recordFunctionName(const char funcName[]) |
|
{ |
|
int nextNum = nextFuncNum++; |
|
int i; |
|
|
|
// clear existing function name (if any) |
|
functionNames[nextNum][0] = 0; |
|
|
|
// store function name |
|
for( i=0; i<PERFMON_FUNCTION_NAME_LENGTH-1 && funcName[i] != 0; i++ ) |
|
{ |
|
functionNames[nextNum][i] = funcName[i]; |
|
} |
|
functionNames[nextNum][i] = 0; |
|
|
|
return nextNum; |
|
} |
|
|
|
// ClearAll - clears all data from static members |
|
void APM_PerfMon::ClearAll() |
|
{ |
|
int i; |
|
APM_PerfMon *p = lastCreated; |
|
|
|
for(i=0; i<PERFMON_MAX_FUNCTIONS; i++) |
|
{ |
|
time[i] = 0; // reset times |
|
numCalls[i] = 0; // reset num times called |
|
} |
|
|
|
// reset start time to now |
|
allStartTime = micros(); |
|
allEndTime = 0; |
|
|
|
// reset start times of any active counters |
|
while( p != NULL ) { |
|
p->_startTime = allStartTime; |
|
p = p->_parent; |
|
} |
|
} |
|
|
|
// ClearAll - clears all data from static members |
|
void APM_PerfMon::DisplayResults(HardwareSerial* aSerial) |
|
{ |
|
int i,j,k,padding,changed; |
|
float hz; |
|
float pct; |
|
unsigned long totalTime; |
|
unsigned long sumOfTime = 0; |
|
unsigned long unExplainedTime; |
|
int order[PERFMON_MAX_FUNCTIONS]; |
|
APM_PerfMon* p = lastCreated; |
|
|
|
// record end time |
|
if( allEndTime == 0 ) |
|
allEndTime = micros(); |
|
|
|
// turn off any time recording |
|
if( lastCreated != NULL ) |
|
lastCreated->stop(); |
|
|
|
// reorder results |
|
for(i=0; i<nextFuncNum; i++) |
|
order[i] = i; |
|
changed=0; |
|
do{ |
|
changed = 0; |
|
for(i=0; i<nextFuncNum-1; i++) |
|
if(time[order[i]]<time[order[i+1]]) |
|
{ |
|
j = order[i]; |
|
order[i] = order[i+1]; |
|
order[i+1] = j; |
|
changed = 1; |
|
} |
|
}while(changed != 0); |
|
// sort results |
|
|
|
totalTime = allEndTime - allStartTime; |
|
|
|
aSerial->print("PerfMon start:"); |
|
aSerial->print(allStartTime/1000); |
|
aSerial->print(" (mils) end:"); |
|
aSerial->print(allEndTime/1000); |
|
aSerial->print(" (mils) elapsed:"); |
|
aSerial->print(totalTime/1000); |
|
aSerial->print(" (mils)"); |
|
aSerial->println(); |
|
aSerial->println("PerfMon: \tcpu%\tmils\t#called\tHz"); |
|
for( i=0; i<nextFuncNum; i++ ) |
|
{ |
|
j=order[i]; |
|
sumOfTime += time[j]; |
|
hz = numCalls[j]/(totalTime/1000000); |
|
pct = ((float)time[j] / (float)totalTime) * 100.0; |
|
padding = PERFMON_FUNCTION_NAME_LENGTH - strLen(functionNames[j]); |
|
|
|
aSerial->print(functionNames[j]); |
|
for(k=0;k<padding;k++) |
|
aSerial->print(" "); |
|
aSerial->print("\t"); |
|
aSerial->print(pct); |
|
aSerial->print("%\t"); |
|
aSerial->print(time[j]/1000); |
|
aSerial->print("\t"); |
|
aSerial->print(numCalls[j]); |
|
aSerial->print("\t"); |
|
aSerial->print(hz,0); |
|
aSerial->print("hz"); |
|
aSerial->println(); |
|
} |
|
// display unexplained time |
|
if( sumOfTime >= totalTime ) |
|
unExplainedTime = 0; |
|
else |
|
unExplainedTime = totalTime - sumOfTime; |
|
pct = ((float)unExplainedTime / (float)totalTime) * 100.0; |
|
aSerial->print("unexplained \t"); |
|
aSerial->print(pct); |
|
aSerial->print("%\t"); |
|
aSerial->print(unExplainedTime/1000); |
|
aSerial->println(); |
|
|
|
// turn back on any time recording |
|
if( lastCreated != NULL ) |
|
lastCreated->start(); |
|
} |
|
|
|
int APM_PerfMon::strLen(char* str) |
|
{ |
|
int i = 0; |
|
while( str[i] != 0 ) |
|
i++; |
|
return i; |
|
} |