00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "irqsystem.h"
00027 #include "avrdevice.h"
00028 #include "funktor.h"
00029 #include "systemclock.h"
00030 #include "helper.h"
00031 #include "avrerror.h"
00032
00033 #include "application.h"
00034
00035 #include <iostream>
00036 #include <assert.h>
00037 #include <typeinfo>
00038
00039 using namespace std;
00040
00041
00042 bool enableIRQStatistic = false;
00043
00044
00045
00046
00047
00048 void IrqStatisticEntry::CalcDiffs() {
00049 setClear =flagCleared-flagSet;
00050 setStarted =handlerStarted-flagSet;
00051 setFinished =handlerFinished-flagSet;
00052 startedFinished =handlerFinished-handlerStarted;
00053 }
00054
00055 IrqStatisticPerVector::IrqStatisticPerVector() {
00056
00057
00058 IrqStatisticEntry longDummy;
00059 IrqStatisticEntry shortDummy;
00060
00061 longDummy.setClear=0xffffffffffffll;
00062 longDummy.setStarted=0xffffffffffffll;
00063 longDummy.setFinished=0xffffffffffffll;
00064 longDummy.startedFinished=0xffffffffffffll;
00065
00066 shortDummy.setClear=0;
00067 shortDummy.setStarted=0;
00068 shortDummy.setFinished=0;
00069 shortDummy.startedFinished=0;
00070
00071 long_SetClear=shortDummy;
00072 long_SetStarted=shortDummy;
00073 long_SetFinished=shortDummy;
00074 long_StartedFinished=shortDummy;
00075
00076 short_SetClear=longDummy;
00077 short_SetStarted=longDummy;
00078 short_SetFinished=longDummy;
00079 short_StartedFinished=longDummy;
00080 }
00081
00082 void IrqStatisticPerVector::CalculateStatistic() {
00083 actual.CalcDiffs();
00084
00085 if (actual.setClear< short_SetClear.setClear) {
00086 short_SetClear=actual;
00087 }
00088
00089 if (actual.setClear> long_SetClear.setClear) {
00090 long_SetClear=actual;
00091 }
00092
00093 if (actual.setStarted< short_SetStarted.setStarted) {
00094 short_SetStarted=actual;
00095 }
00096
00097 if( actual.setStarted> long_SetStarted.setStarted) {
00098 long_SetStarted=actual;
00099 }
00100
00101 if ( actual.setFinished< short_SetFinished.setFinished) {
00102 short_SetFinished= actual;
00103 }
00104
00105 if ( actual.setFinished > long_SetFinished.setFinished) {
00106 long_SetFinished= actual;
00107 }
00108
00109 if (actual.startedFinished < short_StartedFinished.startedFinished) {
00110 short_StartedFinished= actual;
00111 }
00112
00113 if (actual.startedFinished > long_StartedFinished.startedFinished) {
00114 long_StartedFinished= actual;
00115 }
00116 }
00117
00118 void IrqStatisticPerVector::CheckComplete() {
00119 if ((actual.flagSet!=0) &&
00120 (actual.flagCleared!=0) &&
00121 (actual.handlerStarted!=0) &&
00122 (actual.handlerFinished!=0))
00123 {
00124 CalculateStatistic();
00125 IrqStatisticEntry emptyDummy;
00126 actual=emptyDummy;
00127
00128 }
00129 }
00130
00131 ostream &helpHexOut(ostream &os, unsigned long long x) {
00132 #ifdef HEXOUT
00133 os << "0x";
00134 os.fill('0');
00135 os.width(16);
00136 os << hex << x << ":" ;
00137 #else
00138 os<< x << "\t" ;
00139 #endif
00140 return os;
00141 }
00142
00143 ostream& operator<<(ostream &os, const IrqStatisticEntry& ise) {
00144 os << dec<<"\t";
00145 helpHexOut(os, ise.flagSet) ;
00146 helpHexOut(os, ise.flagCleared );
00147 helpHexOut(os, ise.handlerStarted );
00148 helpHexOut(os, ise.handlerFinished );
00149 helpHexOut(os, ise.setClear );
00150 helpHexOut(os, ise.setStarted );
00151 helpHexOut(os, ise.setFinished );
00152 helpHexOut(os, ise.startedFinished );
00153
00154 return os;
00155 }
00156
00157 ostream& operator<<(ostream &os, const IrqStatisticPerVector &ispv) {
00158 os << "Set->Clear >" << ispv.long_SetClear << endl;
00159 os << "Set->Clear <" << ispv.short_SetClear << endl;
00160 os << "Set->HandlerStarted >" << ispv.long_SetStarted << endl;
00161 os << "Set->HandlerStarted <" << ispv.short_SetStarted << endl;
00162
00163 os << "Set->HandlerFinished >" << ispv.long_SetFinished << endl;
00164 os << "Set->HandlerFinished <" << ispv.short_SetFinished << endl;
00165 os << "Handler Start->Finished >" << ispv.long_StartedFinished << endl;
00166 os << "Handler Start->Finished <" << ispv.short_StartedFinished << endl;
00167
00168 return os;
00169 }
00170
00171
00172 ostream& operator<<(ostream &os, const IrqStatistic& is) {
00173 map<unsigned int, IrqStatisticPerVector>::const_iterator ii;
00174
00175 os << "IRQ STATISTIC" << endl;
00176 os << "\tFlagSet\tflagCleared\tHandlerStarted\tHandlerFinished\tSet->Clear\tSet->Started\tSet->Finished\tStarted->Finished"<<endl;
00177 for (ii=is.entries.begin(); ii!= is.entries.end(); ii++) {
00178 os << "Core: " << is.core->GetFname() <<endl;
00179 os << "Statistic for vector: 0x" << hex << ii->first << endl;
00180 os << (ii->second);
00181 }
00182
00183 return os;
00184 }
00185
00186 HWIrqSystem::HWIrqSystem(AvrDevice* _core, int bytes, int tblsize):
00187 TraceValueRegister(_core, "IRQ"),
00188 bytesPerVector(bytes),
00189 vectorTableSize(tblsize),
00190 debugInterruptTable(tblsize, (Hardware*)NULL),
00191 core(_core),
00192 irqTrace(tblsize),
00193 irqStatistic(_core)
00194 {
00195 for(int i = 0; i < vectorTableSize; i++) {
00196 TraceValue* tv = new TraceValue(1, GetTraceValuePrefix() + "VECTOR" + int2str(i));
00197 tv->set_written(0);
00198 RegisterTraceValue(tv);
00199 irqTrace[i] = tv;
00200 }
00201 }
00202
00203 unsigned int HWIrqSystem::GetNewPc(unsigned int &actualVector) {
00204 unsigned int newPC = 0xffffffff;
00205
00206 static map<unsigned int, Hardware *>::iterator ii;
00207 static map<unsigned int, Hardware *>::iterator end;
00208 end = irqPartnerList.end();
00209
00210
00211 for(ii = irqPartnerList.begin(); ii != end; ii++) {
00212 Hardware* second = ii->second;
00213 unsigned int index = ii->first;
00214 assert(index < vectorTableSize);
00215
00216 if(second->IsLevelInterrupt(index)) {
00217 second->ClearIrqFlag(index);
00218 if(second->LevelInterruptPending(index)) {
00219 actualVector = index;
00220 newPC = index * (bytesPerVector / 2);
00221 break;
00222 }
00223 } else {
00224 second->ClearIrqFlag(index);
00225 actualVector = index;
00226 newPC = index * (bytesPerVector / 2);
00227 break;
00228 }
00229 }
00230
00231 return newPC;
00232 }
00233
00234 void HWIrqSystem::SetIrqFlag(Hardware *hwp, unsigned int vector) {
00235 assert(vector < vectorTableSize);
00236 irqPartnerList[vector]=hwp;
00237 if (core->trace_on) {
00238 traceOut << core->GetFname() << " interrupt on index " << vector << " is pending" << endl;
00239 }
00240
00241 if ( irqStatistic.entries[vector].actual.flagSet==0) {
00242 irqStatistic.entries[vector].actual.flagSet=SystemClock::Instance().GetCurrentTime();
00243 }
00244 }
00245
00246 void HWIrqSystem::ClearIrqFlag(unsigned int vector) {
00247 irqPartnerList.erase(vector);
00248 if (core->trace_on) {
00249 traceOut << core->GetFname() << " interrupt on index " << vector << "cleared" << endl;
00250 }
00251
00252 if (irqStatistic.entries[vector].actual.flagCleared==0) {
00253 irqStatistic.entries[vector].actual.flagCleared=SystemClock::Instance().GetCurrentTime();
00254 }
00255
00256 irqStatistic.entries[vector].CheckComplete();
00257 }
00258
00259 void HWIrqSystem::IrqHandlerStarted(unsigned int vector) {
00260 irqTrace[vector]->change(1);
00261 if (core->trace_on) {
00262 traceOut << core->GetFname() << " IrqSystem: IrqHandlerStarted Vec: " << vector << endl;
00263 }
00264
00265 if (irqStatistic.entries[vector].actual.handlerStarted==0) {
00266 irqStatistic.entries[vector].actual.handlerStarted=SystemClock::Instance().GetCurrentTime();
00267 }
00268 irqStatistic.entries[vector].CheckComplete();
00269 }
00270
00271 void HWIrqSystem::IrqHandlerFinished(unsigned int vector) {
00272 irqTrace[vector]->change(0);
00273 if (core->trace_on) {
00274 traceOut << core->GetFname() << " IrqSystem: IrqHandler Finished Vec: " << vector << endl;
00275 }
00276
00277 if (irqStatistic.entries[vector].actual.handlerFinished==0) {
00278 irqStatistic.entries[vector].actual.handlerFinished=SystemClock::Instance().GetCurrentTime();
00279 }
00280 irqStatistic.entries[vector].CheckComplete();
00281 }
00282
00283 void HWIrqSystem::DebugVerifyInterruptVector(unsigned int vector, const Hardware* source) {
00284 assert(vector < vectorTableSize);
00285 const Hardware* existing = debugInterruptTable[vector];
00286 if(existing == NULL)
00287 debugInterruptTable[vector] = source;
00288 else
00289 assert(existing == source);
00290
00291
00292 }
00293 void HWIrqSystem::DebugDumpTable()
00294 {
00295 avr_message("Interrupt vector table (for comparison against a datasheet)\n");
00296 avr_message("Vector | Address/2 | Source Peripheral (class)\n");
00297 for(unsigned i = 0; i < debugInterruptTable.size(); i++)
00298 {
00299 const Hardware* source = debugInterruptTable[i];
00300 const char * handler = (i==0) ? "funct AvrDevice::Reset()"
00301 : source ? typeid(*source).name() : "(unsupported or not registered)";
00302 avr_message(" %3d | $%04x | %s\n", i+1, i*bytesPerVector/2, handler);
00303 }
00304 }
00305
00306 IrqStatistic::IrqStatistic (AvrDevice *c):Printable(cout), core(c) {
00307 Application::GetInstance()->RegisterPrintable(this);
00308 }
00309
00310
00311 void IrqStatistic::operator()() {
00312 if(enableIRQStatistic)
00313 out << *this;
00314 }
00315