Porting RTOS Device Drivers to Embedded Linux
Linux has taken the embedded marketplace by storm. According to industry analysts, one-third to one-half of new embedded 32- and 64-bit designs employ Linux. Embedded Linux already dominates multiple application spaces, including SOHO networking and imaging/multifunction peripherals, and it now is making vast strides in storage (NAS/SAN), digital home entertainment (HDTV/PVR/DVR/STB) and handheld/wireless, especially in digital mobile phones.
New embedded Linux applications do not spring, Minerva-like, from the heads of developers; a majority of projects must accommodate thousands, even millions of lines of legacy source code. Although hundreds of embedded projects have successfully ported existing code from such platforms as Wind River's VxWorks and pSOS, VRTX, Nucleus and other RTOSes to Linux, the exercise is still nontrivial.
To date, the majority of literature on migration from legacy RTOS applications to embedded Linux has focused on RTOS APIs, tasking and scheduling models and how they map to Linux user-space equivalents. Equally important in the I/O-intensive sphere of embedded programming is porting RTOS application hardware interface code to the more formal Linux device driver model.
This article surveys several common approaches to memory-mapped I/O frequently found in legacy embedded applications. These range from ad hoc use of interrupt service routines (ISRs) and user-thread hardware access to the semi-formal driver models found in some RTOS repertoires. It also presents heuristics and methodologies for transforming RTOS code into well-formed Linux device drivers. In particular, the article focuses on memory mapping in RTOS code vs. Linux, porting queue-based I/O schemes and redefining RTOS I/O for native Linux drivers and dæmons.
The word that best describes most I/O in RTOS-based systems is informal. Most RTOSes were designed for older MMU-less CPUs, so they ignore memory management even when an MMU is present and make no distinction between logical and physical addressing. Most RTOSes also execute entirely in privileged state (system mode), ostensibly to enhance performance. As such, all RTOS application and system code has access to the entire machine address space, memory-mapped devices and I/O instructions. Indeed, it is very difficult to distinguish RTOS application code from driver code even when such distinctions exist.
This informal architecture leads to ad hoc implementations of I/O and, in many cases, the complete absence of a recognizable device driver model. In light of this egalitarian non-partitioning of work, it is instructive to review a few key concepts and practices as they apply to RTOS-based software.
When commercial RTOS products became available in the mid-1980s, most embedded software consisted of big mainline loops with polled I/O and ISRs for time-critical operations. Developers designed RTOSes and executives into their projects mostly to enhance concurrency and aid in synchronization of multitasking, but they eschewed any other constructs that got in the way. As such, even when an RTOS offered I/O formalisms, embedded programmers continued to perform I/O in-line:
#define DATA_REGISTER 0xF00000F5
char getchar(void) {
return (*((char *) DATA_REGISTER));
}
void putchar(char c) {
*((char *) DATA_REGISTER) = c;
}
More disciplined developers usually segregate all such in-line I/O code from hardware-independent code, but I have encountered plenty of I/O spaghetti as well. When faced with pervasive in-line memory-mapped I/O usage, embedded developers who are new to Linux always face the temptation to port all such code as-is to user space, converting the #define of register addresses to calls to mmap(). This approach works fine for some types of prototyping, but it cannot support interrupt processing, has limited real-time responsiveness, is not particularly secure and is not suitable for commercial deployment.
In Linux, interrupt service is exclusively the domain of the kernel. With an RTOS, ISR code is free-form and often indistinguishable from application code, other than in the return sequence. Many RTOSes offer a system call or macro that lets code detect its own context, such as the Wind River VxWorks intContext(). Common also is the use of standard libraries by ISRs, with accompanying reentrancy and portability challenges.
Most RTOSes support the registration of ISR code and handle interrupt arbitration and ISR dispatch. Some primitive embedded executives, however, support only direct insertion of ISR start addresses into hardware vector tables. Even if you attempt to perform read and write operations in-line in user space, you have to put your Linux ISR into kernel space.
Today’s modular x86 servers are compute-centric, designed as a least common denominator to support a wide range of IT workloads. Those generic, virtualized IT workloads have much different resource optimization requirements than hyperscale and cloud applications. They have resulted in a “one size fits all” enterprise IT architecture that is not optimized for a specific set of IT workloads, and especially not emerging hyperscale workloads, such as web applications, big data, and object storage. In this report, you will learn how shifting the focus from traditional compute-centric IT architectures to an innovative disaggregated fabric-based architecture can optimize and scale your data center.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
| Trying to Tame the Tablet | May 08, 2013 |
| Dart: a New Web Programming Experience | May 07, 2013 |
- RSS Feeds
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- New Products
- Drupal Is a Framework: Why Everyone Needs to Understand This
- A Topic for Discussion - Open Source Feature-Richness?
- Home, My Backup Data Center
- Validate an E-Mail Address with PHP, the Right Way
- New Products
- Trying to Tame the Tablet
- Developer Poll
- enterprise
10 min 23 sec ago - not living upto the mobile revolution
3 hours 1 min ago - Deceptive Advertising and
3 hours 37 min ago - Let\'s declare that you have
3 hours 38 min ago - Alterations in Contest Due
3 hours 39 min ago - At a numbers mindset, your
3 hours 40 min ago - Do not get Just Almost any
3 hours 43 min ago - A fantastic rule-of-thumb to
3 hours 45 min ago - Keren mastah..
Penting,
4 hours 43 min ago - mini tablet compare
6 hours 1 min ago




Comments
As the author and a few
As the author and a few commenters rightfully noted you can go the easy path by mapping all VxWorks tasks to Linux user mode processes/threads. The downside is that the performance hit can be huge (see above comment about mmap overhead).
Fortunately, it looks like now there is a solution - www.femtolinux.com allows to run user processes in kernel mode, removing the user/kernel barrier. FemtoLinux processes are pretty much identical to VxWorks tasks.
Been on both sides of this
15 years as a VxWorks developer, now doing the linux side of the game. 99% of the time, the "real driver" approach is the preferred one - you get protection, etc. (I've ported almost all of my old VxWorks drivers to Linux that way) but there is the odd case - and I'm dealing with one now, where mmap() may buy you the realtime response you need - where even the interrupts are too slow.
(porting from linux to VxWorks is the easy direction - you're going from protected to unprotected,life is easy, aside from a few calls that aren't allowed.)
My catch at the moment though - on the architecture that I'm working with, is that the mmap call is expensive - more than you might think. Each access, by the time it has rolled up and unrolled the various page tables, is appearing to take 700ns - dropping memory bandwidth to less than 14MB/Sec. And that bytes. Pun intended.
Like everything, you've got to evaluate what you're doing, and why
migration kit for linux to vxworks - availablility !!
Hi all,
VxWorks-to-Linux migration kits are offered by a number of companies, including MapuSoft, LynuxWorks, MontaVista, and TimeSys.
But, y is there no such thing like,
Linux-to-VxWorks Migration Kits ????
What is the difficulty in providing such a migration kit ?
where is the problem actually ?
if there is a linux-to-vxworks migration kit available in any website or shop, do kindly let me know.
thanks and regards,
karthik bala guru
migrating a protocol from linux to vxworks - availablility !!
actually, i am porting a protocol stack developed in arm-linux into vxworks.
do let me know if there is any migration kit for this.
cheeers,
karthik bala guru
How to implement mmap() in vxWorks?
Does anybody know how to use linux mmap() like function in vxWorks?
Please info me!
hmmm
Why would you want mmap()in Vxworks? The entire memory space is yours..... :)
I am not quite sure why you need one the first place.