Porting real-time device drivers to embedded Linux

Source: Internet
Author: User

Bill weberger, monavista Software
Linux has occupied the embedded system market like a storm. According to industry analysts, about 1/3 to 1/2 of the New 32-bit and 64-bit embedded systems are designed to use Linux. Embedded Linux has shown its advantages in many application fields, such as SOHO home network and imaging/multi-functional peripherals, and has a huge development prospect in the following aspects: (NAS/San) storage, home Digital Entertainment (HDTV/PVR/DVR/STB) and handheld devices/wireless devices, especially mobile phones.
The new embedded Linux applications will not suddenly pop up from the developer's mind as they are in the hands of the god of wisdom and technology-Raytheon. A large number of projects must use thousands of lines, or even millions of lines of old ready-made code. Hundreds of embedded projects have successfully transplanted off-the-shelf code from other platforms to Linux, such as Wind River VxWorks and PSOs, vrtx, nucleus, and other RTOS, these porting work is still valuable and practical.
So far, most documents about porting old RTOS applications to embedded Linux have been focusing on RTOS interfaces (APIS) and tasks, the scheduling mode and how to map them to the corresponding user space. In the intensive I/O space of embedded programs, it is equally important to port the RTOS application hardware interface code to a Linux device with a more standardized mode.
This article will look at several common memory ing I/O methods, which often appear in old embedded applications. They cover the scope, from special use of interrupt service routines and access to hardware by user threads, to the semi-standardized driver model that appears in some rots. It is enlightening for porting RTOS code to a Linux Device in standardized mode and introduces some methods. In particular, this article will focus on and compare the memory ing in RTOs code, Linux porting Based on I/O scheduling queues, and redefinition of rtos I/O, it can be applied in the local Linux driver and daemon.
Rtos I/O Concept
"Nonstandard" is the best word that can describe most of the I/O Based on RTOS systems. Most RTOS are designed for earlier CPUs without MMU, ignoring memory management. Even when MMU is available, it does not distinguish physical addresses from logical addresses. Most RTOS are still running in the privileged state (system mode), and the performance is enhanced on the surface. In this way, all RTOS applications and system code can access the entire machine address space, memory ing devices, and I/O commands. In fact, it is very difficult to distinguish the RTOS application code from the driver code, even if they are different.
This nonstandard structure leads to the special implementation of I/O. In many cases, there is a lack of identification of a device driver model. Based on the equality and non-stratified nature of such work, review some important concepts and practices used in RTOs-based software is of great guiding significance:
Online memory ing access
When the commercial RTOS products were available in the 1980s s, most of the embedded software included a huge main loop, the main loop contains registration I/O and interrupt service routines for strict time operations. Developers design RTOS and execution programs into their projects, mainly to enhance the synchronicity and help with multi-task synchronization, but to avoid any other constructor that has an "obstruction. Similarly, even if an RTOS provides an I/O call method, embedded programmers continue to use direct I/O operations:
# Define data_register 0xf00000f5

Char getchar (void ){

Return (* (char *) data_register);/* read from Port */
}

Void putchar (char c ){

* (Char *) data_register) = C;/* write to port */
}
Most trained developers often separate such direct I/O Code from the hardware code. However, I have also met a large number of pasta-style I/O processing codes.
When Direct Memory ing I/O is widely used, embedded developers who are exposed to Linux are always faced with porting all such code to the user space, converts the # define statement that defines the Register address to MMAP () call. this processing method is good for some types of prototype, but does not support interrupt processing, limits real-time response, especially insecure, and is not suitable for commercial release.
RTOS service interruption routine
In Linux, the interrupt service is dedicated to the kernel. In an RTOS, the interrupt service routine code is in a free form and is no different from the application code (similar to the return sequence ). Many RTOS provide system calls or macros to allow the code to detect its own switching points (such as the intcontext () of Wind River VxWorks ()). Interrupt service routines usually use standard library functions, which are accompanied by reentrant and portability issues.
Most RTOS supports registering interrupt service routine code, interrupt arbitration handle, and interrupt service routine scheduling. Some very primitive embedded execution programs only support inserting the starting address of the interrupt service routine in the hardware vector table.
Even if you try to perform read and write operations directly in the user program space, you have to put your Linux interrupt service routine into the kernel program space.
Rtos I/O subsystem
Most RTOS provides a customized Standard C Runtime Library (such as PSOs prepc), or glibc can be obtained by selecting the patched C library (libc) from the compiler of independent software developers. In this way, most RTOS supports a subset of the Standard C type I/O (open/close/read/write/IOCTL ). in most cases, these calls and the calls derived from them can be converted into very thin packages around basic I/O. What's interesting is that most? RTOS does not support file systems. These platforms do not provide abstract file storage for flash and rotating media. They often use completely different codes and/or different application interfaces (APIS) (For example, PSOs Phile ).
Wind River VxWorks is better than most other RTOS platforms in this regard. It provides a rich subset of I/O, which mainly overcomes the integration and wide generalization obstacles in network interfaces and multimedia interfaces.
Latency Processing
Many RTOS also support a mechanism called "bottom half" ("bottom half"), which is used to handle I/O latency that can be interrupted and/or can be preemptible. Other RTOS do not have such a mechanism, but instead provides a mechanism similar to interrupt nesting to achieve the same effect.
Typical RTOS application I/O Architecture
The following describes a typical I/O configuration (input only) and the path processing process for passing data to the main application in sequence as follows:
* A Hardware Interrupt triggers the execution of an interrupt service routine.
* The interrupt service routine performs basic processing and local input operations, or allows RTOS to schedule delayed processing. in some cases, the latency processing process is handled by a user process in Linux, which is a common RTOS task.
* Whenever and wherever data is obtained (interrupt service routine or delay switching), the prepared data is put into the queue (RTOS interrupt service routine can access the application queue through the application interface (API) communication with other processes (? IPC), see the following API table ).
* One or more application tasks read messages from the queue to retrieve data.
Typical I/O Comparison Between Traditional RTOS and Linux
Output is often done by a similar mechanism. Instead of using write () or similar system calls, one or more RTOS application tasks put the prepared data into the queue. the data in the queue is taken out by an I/O program or an interrupt service routine that is "prepared to send" interrupted, a system clock, or other application tasks that are blocked in the query queue, then directly execute the I/O operation (either round robin or DMA ).
Map rtos I/O to Linux
The queue-based production/consumption I/O model described above is only one of the many special methods used in traditional design. let's continue to use this direct example to discuss several implementations in Embedded Linux:
Large-scale migration to user space
For developers who barely understand the driver design details of Linux devices, or who are in a hurry, most of these queue-based design programs may be completely transplanted to the user space. In this driver ing configuration, the physical I/O port of the memory ing can be operated in the user space through the pointer provided by the MMAP () function.

# Include <sys/Mman. h>

# Define reg_size 0x4/* Device register size */
# Define reg_offset 0xfa400000
/* Physical address of device */

Void * mem_ptr;/* de-reference for memory-mapped access */
Int FD;

FD = open ("/dev/mem", o_rdwr);/* Open physical memory (must be root )*/

Mem_ptr = MMAP (void *) 0x0, reg_area_size, prot_read + prot_write,
Map_shared, FD, reg_offset );
/* Actual call to MMAP ()*/

A process-based user thread performs the same operations as RTOS-based interrupt service routines or delayed tasks, and then uses the svr4 inter-process communication function msgsnd () to put messages into the queue, wait for it to be obtained by another local thread or another process using the msgrcv () function.
This fast "dirty" processing method is a good prototype, and brings huge challenges to the establishment of publishable code. the first important thing is to scan for interruptions in the user space. the similar dos simulation (dosemu) project provides signal-based interrupt I/O with sig (silly interrupt generator), but the process of user space interrupt processing is very slow (millisecond-level interrupt latency, the replaced kernel-based interrupt service routine interrupt latency is dozens of microseconds ). furthermore, switching and scheduling in the user space cannot ensure that 100% of the I/O threads in the user space are executed in a timely manner, even if the Linux kernel and real-time scheduling policies can be preemptible.
Redesign for Linux drivers
Write at least one simple Linux driver to handle the interrupt process at the kernel level, which is more desirable. A basic character driver or block driver can directly scan application interruption data in the upper half or delay to the task queue for subsequent processing, the task queue is a kernel thread or a new working Queue (lower half) mechanism in the 2.6 kernel. one or more application threads/processes can open the device and perform simultaneous read operations, just as the RTOS application queue accepts calls at the same time. note that this method should at least record the overhead of the I/O thread using the device read activity to replace the queue to accept the operation.
Retain a queue-based I/O architecture of RTOS
To reduce the impact of porting to embedded Linux, You can retain the queue-based solution in the original place and add additional threads or daemon processes, they wait for I/O operations on the newly created device. when the data is ready, these threads or daemon processes are awakened, and data is received by queue for use by the application thread or process.
Porting Method
There is no conceptual difference between porting RTOS to embedded Linux and commercial applications. After the basic work for porting is ready (create make/build scripts and tools, compatible compilers, and specific inclusion files), code-level porting will face application architecture and applications (APIS) challenges of using problems.

To facilitate the following discussion, we assume that the "application" section (all Code except for I/O) will be transplanted from the RTOs-based system to a separate Linux Process; RTOS tasks are mapped to Linux threads, while inter-process communication (IPC) in tasks is mapped to equivalent processes and threads in Linux.

Map RTOS tasks to process-based threads in Linux
The basic concepts of porting are easy to understand, and problems occur in details. The most obvious is how the RTOS application interface in the application can be retained to the Linux structure for continued use.
Overall analysis-Reconstruction
If your project does not have a tight schedule, and you can use the portability code repeatedly for future projects, you will analyze the current RTOS application structure based on the time, and how to map them to the Linux structure. For RTOS application code, you need to consider ing RTOS tasks one by one to the viability of Linux Process-based threads, and whether to re-allocate RTOS applications to multiple Linux processes. Depending on the choice, you will reconsider the RTOS inter-process communication (IPC) in use and adopt an appropriate inter-process or intra-process communication mechanism.
At the driver level, you must convert nonstandard embedded RTOS code into appropriate drivers. If your old applications have been well divided, use the rtos I/O application interface, or separate them at different layers. Your work will be very easy. If the special I/O code is very scattered across your old application, you will face a huge workload.
API-Based Method
Developers eager to get rid of the old RTOS, or try to integrate the prototype together, are more likely to try to map many RTOS APIs or convert them to a location equivalent to Linux. The general interface of the program body is almost transparent (compatible API, IPC, system data type, etc ). You can use # define to redefine and use macros for the remaining parts. The rest needs to be re-encoded as part of the complete abstraction layer.
By using the simulation library-many commercial embedded Linux libraries (such as our simulation libraries for Wind River VxWorks and PSOs), or using the API ing packages provided by third-party companies, such as mapusoft, this enables you to have a good start when porting API-based programs.

How to port RTOS code and APIs to Linux
Most projects use a hybrid method to map all compatible or easy-to-convert APIs and reconfigure the parts that have requirements on the running speed, and recode the remaining parts like moles until the compilation passes and runs.
Available APIs in the kernel and user space
For API methods that urgently require reconstruction and "faster and more dirty", You have to reassign RTOS applications and I/O Code as examples of Linux kernel and user null.
The result of hierarchical privileged access in Linux is that only the kernel code (driver) can access the physical memory, and other user code must have the root user permission to access it.
Generally, the user space code is isolated from the Linux kernel. It can be directly "seen" only when the kernel export information appears in/proc/ksyms ". Further, the system calls displayed in the kernel cannot be called directly, but can be called through the user library. In Linux, this separation is intended to enhance stability and security.
On the contrary, a driver is written. The drivers with static links belong to the entire kernel namespace (not the egress), but are completely invisible to the user space based on process symbols and entry points. In addition, when You encapsulate the driver into a Dynamically Loaded module, your program uses the displayed interface in the kernel through the export_symbol macro.

Network Driver porting
As mentioned above, porting character and block drivers to Linux is a straightforward practice. Porting network drivers is much more difficult.
Looking back at the growth of Linux along with TCP/IP, most RTOS did not consider the network until the end of 1990s. Even so, old network storage often only has basic functions. For example, you can only process a single session, access only one port at the same time, or support only physical interfaces of a single network media. In some cases, the network structure can be implemented only after multiple interfaces and physical connections are allowed (such as Wind River VxWorks MUX code)
The bad message is that you have to rewrite most or all of the ready-made network interfaces. The good news is that it is not too difficult to reclassify Linux, and there are a large number of open-source network device drivers to choose from.
Your porting task will be to use the appropriate Encapsulation Format and interface code to assemble the bottom area of the following chart:
Linux Network Driver
Writing network drivers is not a matter for beginners, because many RTOS network drivers actually evolved from the GPL Linux interface program. You may find that the program is easy to use through the Code itself. Furthermore, there are a large number of growing systems integration and consulting communities that focus on helping embedded developers migrate their applications to Linux with reasonable fees.
Summary
This article deeply analyzes the challenges and benefits of embedded developers when migrating the entire software from the old RTOS to Linux. A few words or more is too simple for in-depth research on the details of many driver porting (bus interface driver API, address conversion, etc ), however, a wide range of Open-Source GPL driver code can be used as documents and templates for your porting process. as a guide, this article will certainly be helpful for your team when porting RTOS to Linux, and inspire you to re-plan the code for the best embedded Linux.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.