Document directory
- Interrupt architecture in Microsoft Windows CE. net
Interrupt architecture in Microsoft Windows CE. net
Released on: 7/23/2004 | updated on: 7/23/2004
Nat Framton (Windows Embedded MVP
Real Time Development Corp. President)
Applicable:
Microsoft Windows CE. Net with Microsoft platform Builder 4.0
Content on this page
Overview
Interrupt Architecture
Oal isr Processing
Installable ISR
Ist interrupt handling
Cause of Delay
Summary
Overview
Microsoft Windows CE. Net has upgraded the interrupt architecture of Windows CE. The ability of the Operating System (OS) to handle shared interruptions greatly extends the capability of Windows CE. Net to support many interrupt architectures. This article discusses how to handle interruptions from the perspectives of OEMs and application developers. This article also discusses the OEM adaptation layer (oal) interrupt service routine (ISR) processing; provides installable ISR, including a simple entry-level shell program; introduces the interrupt service thread (IST) interrupt Processing, and an initialization and execution template is provided. Finally, this article analyzes the root cause of ISR and ist latency.
Back to Top
Interrupt Architecture
The first step to explore the Microsoft Windows CE. Net interrupt architecture is to define the overall model of hardware, kernel, oal, and thread interaction during the interrupt process. This section describes the responsibilities of different levels and the transition of status changes.
Figure1.
This figure illustrates the main conversions during the interruption process, with the time increasing sequentially from left to right. The lowest layer in the figure is the status of the hardware and interrupt controller. The lower layer is the kernel interaction during service interruption. OAL describes the responsibilities of the motherboard support package (BSP. The top layer describes the application or driver thread interaction required for service interruption. This figure illustrates the interaction in a single interrupt process; it indicates that Windows CE. Net has the new capability of shared interrupt.
The activity starts from the interruption in a straight line at the leftmost part of the graph. An exception is generated, causing the kernel ISR vector to be loaded into the processor. Kernel ISR interacts with hardware to disable all interrupts with the same and lower priority on all processors (except for the arm and strong arm architecture ). The kernel then advances to the oal ISR that has been registered for the specific interrupt. After that, oal ISR can directly handle interruptions, or use nkcallintchain to traverse the list of installed ISR instances. The primary ISR or any installed ISR subsequently performs any work and returns a sysing interrupt named sysintr for the device. If the ISR determines that its related device does not cause this interruption, the ISR will return sysintr_chain, which causesNkcallintchain ()Traverse the ISR list to reach the next interrupt in the chain. ISR is called according to their installation order (they will create a priority in the call list during installation ).
After a single ISR or its related ISR chain is called, the returned value may be one of the following values:
Return Value
Operation
Sysintr_nop
Interruption is not associated with any registered ISR of the device. The kernel enables all other interrupts.
Sysintr
Disconnect from a known registered ISR and device.
Sysintr_resched
The interruption is caused by the expiration of the timer requesting the OS to reschedule.
Sysintr return values are the focus of our discussion. Once ISR is complete, the kernel re-enables all interrupts on the processor, except identified ones. Then, the kernel notifies the events associated with the sysintr value.
Then, the ist of the driver or application will be able to run (assuming it is the highest priority thread that is ready to run ). Ist will communicate with the relevant device and read all necessary data from the device that completes its interrupted interaction. Then, ist uses the associated sysintr value to callInterruptdone ()To notify it that it has been completed.
When the kernel receives the sysintr value interruptdone, the specified interrupt is re-enabled. Other device interruptions can be received only from this moment.
This is just a rough introduction to the interrupt sequence of Windows CE. net internal activities. Now we will take a closer look at each of the above components and their responsibilities.
Back to Top
Oal isr Processing
Oal isr is a basic Interrupt Processing Program of the platform. The following is the actual ISR of the X86 platform. Configuration Analysis and iltiming support have been deleted. X86 ISR represents all Windows CE-based platforms. It demonstrates a single ISR that can handle all interruptions in the system.
The target of this ISR is to return the sysintr Number of the device that caused the interruption to the kernel. ISR executes the following activity sequence.
•
SlavePicgetcurrentinterrupt(PIC) to obtain the current hardware interruption
•
If the interrupt isIntr_timer0(System timer)
•
Update OSCurmsecRetention Time
•
Check and confirm whether the restart address has been registered (Reboothandler)
•
If the interrupt isIntr_rtc
•
ISR check and confirm whether the alarm has expired (Sysintr_rtc_alarm)
•
If the interrupt is lessIntr_maximum
•
Call interrupt chain (Nkcallintrchain)
•
SetNkcallintrchainThe return value is set to this return value.
•
If the interrupt chain does not contain an interrupt :(Sysintr_chain)
Ing current hardware interrupt (Oemtranslateirq)
If the interrupt is registeredOeminitInHookinterrupt
SlaveOemtranslateirqReturnSyintrValue
If the interrupt is not registered, returnSysintr_nop
•
Enable all interrupts except the current one. (Picenableinterrupt}
•
Completion of proper interrupted work for notificationPICInterrupted (EOI)
•
ISR returns one of the following values:
•
Sysintr_nop-No ISR contains the interrupt
•
Sysintr_resched-The rescheduling timer has expired.
•
Sysintr-ISR already contains the interrupt.
•
Sysintr_rtc_alarm-The alarm has expired.
ULONG PeRPISR(void){ULONG ulRet = SYSINTR_NOP;UCHAR ucCurrentInterrupt;ucCurrentInterrupt = PICGetCurrentInterrupt();if (ucCurrentInterrupt == INTR_TIMER0) { CurMSec += SYSTEM_TICK_MS; CurTicks.QuadPart += TIMER_COUNT; if ((int) (CurMSec - dwReschedTime) >= 0) ulRet = SYSINTR_RESCHED; } // // Check if a reboot was requested. // if (dwRebootAddress) { RebootHandler(); } } else if (ucCurrentInterrupt == INTR_RTC) { UCHAR cStatusC; // Check to see if this was an alarm interrupt cStatusC = CMOS_Read( RTC_STATUS_C); if((cStatusC & (RTC_SRC_IRQ)) == (RTC_SRC_IRQ)) ulRet = SYSINTR_RTC_ALARM; } else if (ucCurrentInterrupt <= INTR_MAXIMUM) { // We have a physical interrupt ID, return a SYSINTR_ID // Call interrupt chain to see if any installed ISRs handle this // interrupt ulRet = NKCallIntChain(ucCurrentInterrupt); if (ulRet == SYSINTR_CHAIN) { ulRet = OEMTranslateIrq(ucCurrentInterrupt); if (ulRet != -1) PICEnableInterrupt(ucCurrentInterrupt, FALSE); else ulRet = SYSINTR_NOP; } else { PICEnableInterrupt(ucCurrentInterrupt, FALSE); } } if (ucCurrentInterrupt > 7 || ucCurrentInterrupt == -2) { __asm { mov al, 020h ; Nonspecific EOI out 0A0h, al } } __asm { mov al, 020h ; Nonspecific EOI out 020h, al } return ulRet;}
If the ISR does not interrupt the installation of hookinterrupt initialization in oeminit of oal, the ISR will return an appropriate sysintr value.
NoteIf you can only use ist interaction to provide services for devices, you do not need to interrupt the installation of installable ISR. ThroughOALOfOeminitInHookinterruptCall to enable interrupt.
ISR code is a very small and fast code. Its execution time will directly affect the interruption delay in the entire system. The change to the interrupt architecture introduced in Windows CE 3.0 isNested interrupt. When you enter the oal ISR, all interruptions with a higher priority have been enabled. ISR may be preemptible. If the internal timing of the ISR is critical, you may need to disable interruption within this period of time. Just like the ISR execution time, the downtime will increase the platform's worst-case latency.
When ISR returns sysintr related to a specific device, the kernel will notify ist to wake up. The ist interrupt that processes the driver or the internal code of the application ends the interrupt interaction.
Back to Top
Installable ISR
The installable ISR is created in response to the openness brought by Windows CE. net to the embedded space. OEMs no longer have to take full responsibility for the platform and application code. Currently, both platform providers and application developers can work in the field of embedded space. If an application developer adds a new device to the open bus on a Windows CE 3.0 platform, the OEM will have to persuade the OEM to add the ISR to the platform.
To install ISR on the platform, you need to complete two steps:
•
Call the loadintchainhandler function to load the DLL containing ISR code.
•
The ISR must be encoded as a response using sysintr _..., just like in oal ISR.
The loadintchainhandler function loads the ISR dynamic link library (DLL) to the address space of the kernel. This means that the Code cannot call any non-kernel functions, including any Runtime library functions in the C language. Remember, some structure-to-structure assignments are downgraded to memcpy calls and all code must be checked to ensure that no external libraries are required, even if these libraries are created by the compiler ).
The following source code example illustrates a basic shell program used to create an installable ISR. There are four functions:
•
Dllentry-Receive additional messages from processes and threads
•
Infocopy-Copy routine used for assigning values to any structure
•
Iocontrol-Any useKernellibiocontrolThe handler called by ist.
•
Isrhandler-Actual ISR
BOOL __stdcall DllEntry( HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved ){ if (dwReason == DLL_PROCESS_ATTACH) {} if (dwReason == DLL_PROCESS_DETACH) {} return TRUE;}// The compiler generates a call to memcpy() for assignments of large objects.// Since this library is not linked to the CRT, define our own copy routine.void InfoCopy( PVOID dst, PVOID src, DWORD size ){ while (size--) {*((PBYTE)dst)++ = *((PBYTE)src)++;}}BOOL IOControl( DWORD InstanceIndex, DWORD IoControlCode, LPVOID pInBuf, DWORD InBufSize, LPVOID pOutBuf, DWORD OutBufSize, LPDWORD pBytesReturned ) {switch (IoControlCode) { case IOCTL_DEMO_DRIVER: // Your I/O Code Here return TRUE; break; default: // Invalid IOCTL return FALSE;} return TRUE;}DWORD ISRHandler( DWORD InstanceIndex ){ BYTE Value;Value = READ_PORT_UCHAR((PUCHAR)IntrAddress );// If interrupt bit set, return corresponding SYSINTRif ( Value & 0x01 ){ return SYSINTR_DEMO;}else{ return SYSINTR_CHAIN;}}
The ISR handler Code uses port I/O calls to check the device status. Your solution may require a much more complex query. If the device is not the interrupt source, the return value is sysintr_chain. This return value tells the nkchainintr function that the device is not an interruption source and other ISRs in the chain should be evaluated. If ISR returns a valid sysintr, nkchainintr returns immediately without calling any other ISR in the list. This will provide priority sorting. The first installable ISR to be loaded is first loaded to the list (or has the highest priority), and then the subsequent installable ISR is added to the bottom of the list. Because of the priority and execution speed, you should first install ISR with the highest priority in the chain.
Back to Top
Ist interrupt handling
Two steps are required to handle interruptions from an application or driver. First, you must use the associated event to initialize the interrupt. Second, the IST must wait for the interrupt event to respond to the interrupt in the kernel.
Interrupt Initialization
The following sample code sets the IST and associates the IST with a specific center break. Key steps to initialize the interrupt include:
•
Create event
•
Obtain the system interrupt Number of IRO.
•
CreateSuspendedInterrupt thread (IST)
•
CallInterruptinitializeTo create an association between IRQ and events
•
Creating an unsuspended ist may causeInterruptinitializeFailed because the event is already in the waiting status
•
Set the thread priority to the corresponding priority.
•
Restore ist
Void SetupInterrupt( void ){// Create an event//g_hevInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL);if (g_hevInterrupt == NULL) { RETAILMSG(1, (TEXT("DEMO: Event creation failed!!!\r\n"))); return;}// Have the OAL Translate the IRQ to a system irq//fRetVal = KernelIoControl( IOCTL_HAL_TRANSLATE_IRQ, &dwIrq, sizeof( dwIrq ), &g_dwSysInt, sizeof( g_dwSysInt ), NULL );// Create a thread that waits for signaling//g_fRun = TRUE;g_htIST = CreateThread(NULL, // Security 0, // No Stack Size ThreadIST, // Interrupt Thread NULL, // No Parameters Create_SUSPENDED, // Create Suspended &dwThreadID // Thread Id );// Set the thread priority – arbitrarily 5//m_nISTPriority = 5;if( !CeSetThreadPriority( g_htIST, m_nISTPriority )){ RETAILMSG(1,(TEXT("DEMO: Failed setting Thread Priority.\r\n"))); return;}// Initialize the interrupt//if ( !InterruptInitialize(g_dwSysInt,g_hevInterrupt,NULL,0) ) { RETAILMSG (1, (TEXT("DEMO: InterruptInitialize failed!!!\r\n"))); return;}// Get the thread started//ResumeThread( g_htIST );}
It should be noted that interruptinitialize calls only use sysintr values and events as parameters. The kernel does not know or care about the thread that will wait for the event. In this way, you can build a variety of application and driver architectures. The simple main loop of the application can initialize the interrupt and immediately wait for the event. An interruption can only be associated with one event, and the event cannot be used in a call to waitformultipleobjects. We will observe a simple thread that provides service interruption. This is a standard solution in most implementations.
Ist-service interruption routine
This section provides sample code for an ist. Key components of the IST thread include:
•
Wait for the interruption event.
•
Confirm there is a pulsating event from the OS
•
Perform any necessary board-level interrupt processing to complete the interrupt. In this example, we will confirm the interruption.
•
Handle the interrupt in the shortest time
•
Create celogdata for viewing in kernel tracker.
•
Check and confirm whetherG_fprrunningFlag, and then setG_hevprstartEvent.
•
Call interruptdone ().
•
Before interruptdone is called, the OS does not provide other interruptions on this IRQ.
•
Wait for the interruption event again.
DWORD WINAPI ThreadIST( LPVOID lpvParam ){ DWORD dwStatus; BOOL fState = TRUE; // Always chec the running flag // while( g_fRun ) { dwStatus = WaitForSingleObject(g_hevInterrupt, INFINITE); // Check to see if we are finished // if(!g_fRun ) return 0; // Make sure we have the object // if( dwStatus == WAIT_OBJECT_0 ) { // Do all interrupt processing to complete the interaction // with the board so we can receive another interrupt. // if (!( READ_REGISTER_ULONG(g_pBoard Register) & INTR_MASK)) { RETAILMSG(1, (TEXT("DEMO: Interrupt..."))); g_dwInterruptCount ++; } // Finish the interrupt // InterruptDone( g_dwSysInt ); } } return 0;}
This example reads a ulong register to determine the interrupt status. You only need to replace the code snippet with your code. The key point is to make ist processing as simple as possible. If you need to process data from this device in the future:
•
Obtain data from this device as quickly as possible in ist.
•
Create an event to notify a thread with a lower priority to complete the task.
•
Use interruptdone to return immediately from the ist.
•
Let lower-priority threads further process data.
•
Place FIFO between ist and lower-priority threads to handle overflow.
Back to Top
Cause of Delay
From the interrupt architecture in Windows CE. net, you can understand the interaction between hardware, kernel, oal, and driver/Application threads. Microsoft has provided a variety of tools (including iltiming, ceming, and kernel tracker) to help you evaluate the performance of Windows CE. net on the platform. Understanding the factors that lead to ISR and ist latency helps identify the fields of investigation.
ISR latency
As you mentioned earlier in this articleInterrupt ArchitectureAs you can see in, ISR latency is defined as the time from the interruption to the first execution of oal ISR. When the interrupt is disabled, the interrupt will not cause exceptions in the processor. Therefore, the first cause of delay is the total time the interrupt is disabled in the system. When each machine command starts to be executed, it will check whether there is any processor interruption. If the long string movement command is called, the interrupt will be locked, resulting in the second delay source, that is, the amount of time the bus accesses to lock the processor. The third factor is the amount of time the kernel takes to direct the oal ISR processing program. This is a process context switch. In short, factors that cause ISR latency include:
•
The time when the interruption is disabled.
•
The time when the bus command locks the processor.
•
The execution time of the kernel ISR plus the time directed to the oal ISR.
Ist Delay
The previous architecture in this article shows that the IST latency is the amount of time between the interruption occurrence and the execution of the first line of code in the ist. This is different from the Microsoft Measurement Tool Output in Windows CE. net. Microsoft tool defines ist latency as the time from the end of oal ISR execution to the beginning of ist. Because the standard ISR takes very little time, you need to add up the ISR latency and the IST latency obtained by the Microsoft measurement tool to get the IST latency defined in the interrupt architecture.
The first cause of ist latency is the ISR latency defined earlier in this article. The second factor is the ISR execution time. The duration varies depending on the length of the shared interrupt call chain. In case of low latency, there is no need to interrupt calls that will never be shared.Nkcallintchain.
Kernel functions (such as scheduler) in Windows CE are called kcall. During the execution of these kcalls, a software flag is set up to let the scheduler know that it cannot be interrupted at this time. ISR will still be called, but the return value for rescheduling OS or scheduling ist will be delayed until the kcall is completed. This unavailable time is the third cause of ist delay. Finally, the kernel must schedule the ist. This context switch is the last cause of latency. In short, factors that cause ist latency include:
•
ISR Delay Time
•
Oal isr execution time
•
Time when the OS executes kcall
•
Time when the IST is scheduled
Back to Top
Summary
Microsoft has upgraded the Windows CE interrupt architecture through Windows CE. net. The OS's ability to handle shared interruptions greatly extends Windows CE. Net's ability to support many interrupt architectures. This fragmented architecture knowledge can greatly speed up the investigation of drivers and latency issues. The operating system interaction model is the key to understanding the architecture. Shared interruptions have greatly improved the openness of Windows CE. NET and supported solutions for platform providers and application developers across different companies and within the company. Understanding the root cause of latency will help diagnose drivers and real-time problems. The interrupt structure in Windows CE. NET is well-defined and easy to understand. In short, "It's not a magic !"