Supporting Interrupt Latency Timing (Windows Embedded CE 6.0)
1/5/2010
Interrupt-latency timing measures the following two times:
- The time between an interrupt being generated and its interrupt service routine (ISR) being invoked.
- The time between the ISR exiting and when the interrupt service thread (IST) begins running.
**Latency timing is measured using Iltiming.exe and requires significant support from the OEM Adaptation Layer (OAL). The interrupt-latency measurement leverages the fact that timer ISRs should occur at known times, on whole milliseconds. The number of timer ticks in dwIsrTime1 measures the interval between the timer interrupt occurring and the start of its ISR.
Note
Many Microsoft-supplied board support packages (BSPs) can be built to support interrupt-latency timing. To enable interrupt-latency timing in these BSPs, compile the platform code with the ENABLE_OAL_ILTIMING environment variable set to 1.
Iltiming.exe creates an interrupt object for SYSINTR_TIMING. It obtains a kernel-mode pointer to PerfCountSinceTick using one of the IOCTL_HAL_ILTIMING calls. When the timer ISR returns with a value of SYSINTR_TIMING, the interrupt-service thread in Iltiming.exe is scheduled.**
The service thread runs in kernel mode, so it calls directly into the kernel's code space to get the current PerfCountSinceTick value. It subtracts dwIsrTime2 from this to measure the latency between when the ISR exits, presumably very close to the time the IST is scheduled, and when the IST actually starts.
In some cases, other interrupts will occur between the time the Iltiming.exe IST is scheduled and when it starts executing.
Iltiming.exe determines when this has happened by comparing dwIsrTime1 and dwIsrTime2; if an extra interrupt has occurred, dwIsrTime1 will be greater than dwIsrTime2.
Iltiming.exe can also determine if extra interrupts have occurred by examining wNumInterrupts; this is why all ISRs need to set these variables.
To support interrupt-latency timing
Implement IOCTL_HAL_ILTIMING support in OEMIoControl. This code is hardware independent and can be copied from any of the sample OAL source code. It includes the global variables fIntrTime, dwIsrTime1, dwIsrTime2, and wNumInterrupts, among others that should all be copied.
OEMInterruptEnable should return success for SYSINTR_TIMING without actually performing an action.
Implement PerfCountSinceTick and PerfCountFreq. PerfCountSinceTick is the number of counter ticks that have elapsed since the latest timer interrupt occurred. For more information, see PerfCountSinceTick and PerfCountFreq.
All ISRs must check fIntrTime, one of the global variables, at their entry point. If this variable is set, the ISR should set dwIsrTime1 to PerfCountSinceTick and increment wNumInterrupts.
If fIntrTime is set, the timer ISR should decrement dwIntrTimeCountdown and return SYSINTR_TIMING if it is zero. Otherwise, it should return SYSINTR_RESCHED or SYSINTR_NOP as normal. Once it is zero, dwIntrTimeCountdown should be reloaded from dwIntrTimeCountdownRef; this variable is initialized through an IOCTL_HAL_ILTIMING message.
When it returns SYSINTR_TIMING, the timer ISR needs to set dwIsrTime2 to PerfCountSinceTick.
The sample implementation of OEMIdle already checks fIntrTime and handles interrupt-latency timing as a special case.
To implement interrupt-latency timing
Implement support for interrupt-latency timing as described in the procedure above.
Add the following to <platform>\src\inc\ioctl_tab.h:{ IOCTL_HAL_ILTIMING, 0, OALIoCtlHalILTiming }
Add the following to <platform>\src\oal\oalexe\sources' TARGETLIBS:$(_PLATCOMMONLIB)\$(_CPUINDPATH)\oal_ilt.lib
Platforms not supporting interrupt-latency timing can instead add the following to <platform>\src\oal\oalexe\sources' TARGETLIBS:$(_PLATCOMMONLIB)\$(_CPUINDPATH)\oal_ilt_stub.lib
See Also
Tasks
How to Develop an OEM Adaptation Layer