Efficiency in design is the embedded developer’s Hydra, the multi-headed monster of Greek mythology. Real-time system developers are continuously confronted by the constraints of tight schedules and limited resources. In a competitive market, developers are often asked to “crank some code, fast,” but, simultaneously, they must ensure that what they deliver is bug-free and performs the maximum function using the, all too frequently, convoluted resources of a software-agnostic hardware design.
It took Herculean efforts to slay Hydra. Embedded real-time developers are unwittingly taking on the role of a hero when they must use outdated or incomplete tools to tackle a multitude of conflicting goals. Like the many-headed monster, the real-time embedded Hydra is “a persistent or multifaceted problem that cannot be eradicated by a single effort,” American Heritage Dictionary.
How does one maintain hero status without having to slay a multi-headed dragon at each sitting? This is accomplished with the use of prior knowledge and existing tools that have been successfully applied to previous projects, and by keeping it simple.
Many of today’s embedded applications require the stability and reliability of a deterministic hard real-time operating system (RTOS). Simultaneously, these embedded applications serve markets that benefit from the flexibility and extensibility of a general-purpose operating system, like Microsoft Windows XP.
There is no software platform more popular than Microsoft Windows, claiming the undisputed lion’s share of all PC installations. Windows provides access to third-party applications from specialized communication protocols to database applications and mathematical analysis tools, all of which can easily transform a dedicated data acquisition and control system into a sophisticated analysis and enterprise system resource.
Minimizing time spent developing software maximizes the efficiency of the task. A real-time system based on Microsoft Windows is able to leverage those things that Windows does best. It also makes sense that the real-time development environment for such a system should leverage existing and familiar tools.
For those applications that will run on the Windows platform, the development tool of choice is Microsoft Visual Studio .NET (VS.NET), a multi-language development environment that can be used to build and maintain a broad range of applications. The VS.NET platform is the platform of choice in a variety of markets, as the development environment for Windows applications.
Balancing the flexibility of Windows with the deterministic requirements of embedded applications often results in two distinct computing elements built into one system. This includes one piece of hardware to run Windows for the GUI, third-party applications and enterprise-related functions, and a second hardware element to host a dedicated RTOS that controls the time-critical elements of the machine.
The drawbacks to a dual platform solution are numerous. A second control computer adds substantial cost of goods and manufacturing complexity. The additional design costs, in terms of time and effort spent on engineering tools and staff, is generally sufficient justification to seek a simpler and more cost-effective solution. For this reason, real-time Windows solutions that allow two environments to share one CPU are becoming increasingly popular.
For that same reason, a single development environment that can be used to create and debug code for both parts of the solution, the deterministic real-time part and the enterprise-level Windows part, is the optimal solution.
Using Visual Studio as a real-time development tool maximizes the use of existing developer knowledge and skills and unites the two halves of a Windows real-time solution under a single IDE.
Prior to the release of VS.NET, the idea of using the Visual Studio IDE for creating and debugging anything other than a Microsoft Windows application was impractical. However, VS.NET provides hooks for third-party plug-ins, supporting extensions to this popular IDE. By utilizing Visual Studio Industry Partner (VSIP) hooks, third-party development tool providers can enhance the VS.NET IDE to include features for specific tasks beyond standard Windows applications, such as the creation of real-time embedded Windows applications.
Familiar Development Environment
The strength of the Visual Studio IDE is its level of usage and extensibility. There are over 2.5 million VS.NET developers and 225 OEMs building over 650 add-on tools for Visual Studio.
If real-time Windows applications can be edited, compiled, debugged and maintained using the Visual Studio IDE, there is no reason to purchase or learn how to use any other development tools. In order for a real-time extension to be supported from within the VS.NET IDE, it must, at the very least, satisfy the following conditions:
• Wizards should be provided to create standard code templates
• APIs must conform to standard Windows calling and naming conventions
• Real-time executables must be generated using the VS.NET compiler and linker
• The real-time execution environment must support run, halt and traps by the VS.NET debugger
• A VS.NET solution file must support simultaneous inclusion of Windows projects and real-time projects
Figure 1 shows the basic steps in the software development process. The “interface” boxes represent components that must be added to the development system and run-time to support the creation and execution of real-time Windows applications within the VS.NET IDE. The diagram shows two parallel paths of development, from editing code through debugging, both encapsulated within a single tool: Visual Studio. With proper integration these two paths can be nearly indistinguishable from one another, differentiated only by the differences in the two environments in which the application parts execute. The goal is to make the mechanics of the development process identical, in order to optimize the use of the developer’s knowledge and skills associated with a single development tool.
Project wizards, which can be integrated into the Visual Studio development environment, enable developers to quickly build real time applications. The wizards for the real-time Windows path should be designed to guide one through the many design decisions and then automatically generate usable code upon which to build the real-time parts of your application.
APIs that support communication and transfer of data between the Windows and real-time parts of the system are facilitated by header files and libraries for the Windows applications, and they must be provided in formats consistent with the various languages supported by the VS.NET IDE for the Windows environment. These consist mostly of DLLs, include files and library files that are referenced by the compiler and linker when generating object code. Of course, the real-time extension must be capable of loading and executing real-time object code generated by the VS.NET compiler; without such a requirement one could not develop and maintain a single VS.NET solution.
The most interesting component and, previously, the most difficult to provide, is the debugging component. In order to make full use of the VS.NET IDE for the development of real-time Windows applications, one must be able to use the VS.NET debugger.
Integrated Real-time Debugger and Trap Handler
A complete debugging solution must provide one with the ability to run real-time object code at full speed within the real-time Windows environment. Debugging real-time code in a simulated environment dilutes the effectiveness of your development effort. Since a simulator is not the actual run-time environment and rarely runs at full speed, it is easy to miss timing-specific problems that can only be found when running directly on the actual real-time kernel. In short, simulating a real-time Windows run-time environment is not an optimum solution.
A VS.NET debugger plug-in can be used to gain full access to breakpoints, source-level single-stepping and watch variables for real-time Windows applications. The plug-in does not delete your ability to debug standard Windows applications; it adds the ability to work with applications in an alternate run-time environment.
The VS.NET debugger plug-in can also capture and identify real-time process faults generated by divide by zero errors, bad pointer accesses, page faults, stack faults and other CPU exceptions. In order to provide these features the real-time Windows application must execute within user mode (Ring 3), not kernel mode (Ring 0), which is reserved for the kernel.
Typically, only the operating system kernel and low-level device drivers are allowed to exist in kernel mode. Standard Windows applications always execute in user mode (Ring 3), preventing them from making modifications (deliberate or unplanned) to the code and data structures belonging to other applications or the kernel. For the same reason, real-time Windows applications need to execute in user mode, otherwise you will not be able to take advantage of the full range of features present in the VS.NET debugger.
Ring 0 versus Ring 3
If you have ever tried to debug a device driver using the Windows kernel debugger you have experienced the difficulties associated with debugging kernel-mode code. There is no protection for the system when kernel-mode code goes astray. A bug in a kernel-mode thread “crashes” the entire system, not just the process to which the thread belongs. Debugging Ring 0 code is an inefficient and time-consuming process.
All of the hardware protection mechanisms provided by the CPU to maintain isolation between individual applications and between applications and the kernel can be utilized by Ring 3 real-time Windows applications, with no I/O access limitations (Figure 2). Unlike standard Windows applications, real-time Windows applications can perform direct I/O to ports and memory. By reconfiguring the process space it is possible to allow real-time Windows processes to execute the IN and OUT instructions and “map” physical addresses into the real-time process’ virtual address space. Further, the real-time threads are not restricted from manipulating the processor’s interrupt flag via the STI and CLI instructions. The result is a flexible but secure and controlled run-time environment where problems within the real-time system can be easily isolated, greatly simplifying the debugging process.
There is no performance penalty for executing real-time applications at the more reliable and protected Ring 3 operating level. Software executes at exactly the same speed in Ring 3 as it does in Ring 0. The difference between these two operating levels has only to do with the execution of certain privileged instructions, fault (trap) handling and memory protection; the very features that allow for a VS.NET real-time debugger plug-in.
Architecture is Key to Integration
The architecture of a real-time Windows extension has a strong bearing on how well it can be integrated into the VS.NET IDE. Intel’s 32-bit x86 processors (80386 through modern Pentiums) include unique hardware features that accommodate building systems that can simultaneously run multiple operating systems. A real-time extension that takes full advantage of these features to build a secure environment in which real-time processes and Windows processes are isolated and separate on the same machine, will be the optimal solution (Figure 3).
By taking full advantage of the virtual addressing hardware built into the CPU and running real-time processes as Ring 3 applications, the real-time Windows environment is able to provide the following protection and debugging mechanisms for real-time processes:
• code, data, stack and heap are in separate, non-contiguous pages
• code is placed in read-only pages for extra protection
• paging is utilized for address isolation and pointer overrun protection
Every real-time thread is assigned distinct memory pages for its CODE, DATA, STACK and HEAP memory regions. These pages are separated by non-allocated pages of memory so that pointer overruns can be easily and quickly detected. CODE pages are further protected by marking them as read-only (Figure 4).
Real-time Windows extensions that utilize these unique x86 features are able to meld deterministic, hard real-time control with the standard Windows operating system and provide complete integration with VS.NET IDE. The solution results in two isolated virtual machines on a single CPU. This “dual machine” approach provides protection from Windows “blue screen” crashes and delivers microsecond response time.
It is now possible for embedded developers to edit, compile, debug and maintain real-time and Windows code with a single development tool: Microsoft’s Visual Studio platform. If Windows threads and real-time threads run in user mode (Ring 3), the protection model of the x86 can be used to gracefully trap programming and memory errors, numeric exceptions and hardware faults that would normally crash a kernel-mode (Ring 0) real-time solution. Working in a protected operating environment also facilitates rapid and more complete testing than can be accomplished by a kernel-mode approach, adding assurance to the fact that you are delivering safe and reliable code with your system, using the most efficient methods possible.