For Chinese engineers, using real-time Linux development embedded applications is one of the difficulties they face. This article takes RTLinux as an example, combined with RTAI discussions, although these two implementations exist in syntax details Difference, but the work mode is basically, so the content described is applicable to both.
In the process of communicating with the user process, some real-time applications can be run calm in the background without any user interface, however, more and more real-time applications do need a user interface and other system functions, such as files. Operation or networking, etc., all of these features must run in user space. The problem is that the user space operation is non-deterministic and is not compatible with real-time operation.
Fortunately, real-time Linux has a mechanism that can weaken real-time and non-real-time operations in time, which is a driver called real-time FIFO. When INSMOD inserts the RTL_FIFO.o driver into the Linux kernel, the driver registers itself as part of RTLinux and becomes a Linux driver. Once the Linux kernel is inserted, the user space process and real-time tasks can use real-time Linux FIFO.
Before discussing the details of real-time FIFO, some parts of the real-time application structure are reviewed (Figure 1). A effective embedded application design method is to separate the real-time portion from the inherent non-real time function (Table 1). If either of the application, such as user interfaces, graphics, databases, or networks require only soft real-time performance, it is best to write this part into user space. Then, only the part of the timing requirements must be met into real-time tasks.
Note that the latest version of RTLinux (PSC, Portal Signal Coding) and RTAI (LXRT, Linux Real-Time Extension) has employed a method of performing soft and hard real-time tasks in user space.
Any hard real task is running under the control of RTLinux, which typically performs periodic tasks, processing interrupts and communicates with the I / O device driver to collect or output simulation and digital information. When the real-time task needs to tell the user that there is an event to take this message to real-time FIFO. Each FIFO is transmitted in one direction: from real-time tasks to user space, or vice versa. Therefore, two-way communication requires two FIFOs. Any operation of any reading or writing to the real-time task is a non-module operation, so RTF_PUT () and RTF_GET () are immediately returned, regardless of the FIFO status.
From the side of the application, FIFO is like a regular file. By default, the RTLinux installer will create 64 real-time FIFO nodes in the / dev directory; if you need, you must create a new node yourself. For example, to create / dev / RTF80, you need to use the following command:
=========================
MKNOD C 150 80;
CHMOD 0666 / DEV / RTF80
=========================
Where 150 is the real-time FIFO main number, and 80 is the number of RTF80.
From the perspective of user processes, real-time FIFO executive standard file operations. From a real-time task, FIFO has two communication methods: call the RTLinux FIFO function directly, or use the FIFO as an RTLinux device driver, and use open (), close (), read (), and write () operations. To use the FIFO as a device driver, you must set the configuration variable config_rtl_posix_io in RTL_Conf.h to 1. RTF_CREATE_HANDLER () can set the handler function. Each time the Linux process reads or writes FIFO, the RTL_FIFO driver calls the handler. It should be noted that the handler resides in the Linux kernel, so when the Linux needs to be called, it is safe to make any kernel call from the handler. The best communication method between the processing program to the real-time task is to use the flag or thread synchronization. Finally, the FIFO driver must also configure the kernel memory. Therefore, RTF_create () within the real-time thread should not be called. Instead, the RTF_CREATE () function and the RTF_DESTROY () function in the cleanup_module () can be called.
For example, a list 1 gives a real-time part of a simple data acquisition application using two FIFOs. Both FIFOs are created in init_module () and give MINOR NUMBERS to 1 and 2. Before calling RTF_create (minor, size), the program calls RTF_DESTROY (Minor) in the case of created the FIFO. This is another module that is not called during the development process. Then, call RTF_CREATE_HANDLER (ID, & PD_DO_AOUT) to register with the data acquisition analog output function PD_DO_AOUT (). Note that creating real-time thread PP_THREAD_EP () is because it is periodic, and its interval is 1/100 seconds.
After each periodic thread gets the system control, it calls RTF_PUT (ID, DataPtr, Size) to insert the data into the FIFO of Minor Number 2. The Linux process opens / dev / RTF2, reads and displays the collected data from the real-time FIFO. This process also turns on / dev / RTF1 to write data into other real-time FIFOs. When the user moves the screen slider to change the analog output voltage, the process writes a new value to the FIFO. RTLINUX adjusts the PD_DO_AOUT () handler, then PD_DO_AOUT () obtains the value from the FIFO, and calls the actual hardware driver to set the voltage of the analog output. It can be seen that real-time tasks and user processes are asynchronously using FIFO.
Memorial memory sharing
FIFO provides a convenient mechanism for connections for user processes and real-time tasks, but it is more appropriate as a message queue. For example, a real-time thread can use the FIFO to record the test results, then the user process can read the result and store it into the database file.
Many data acquisition applications involve a lot of data between kernel and user space. Linux kernel V. 2.2.x does not provide any mechanism for data sharing of these spaces, but V. 2.4.0 is expected to include kiobuf structures. To solve this shortcomings of existing stable kernels, RTLinux includes MBuff drivers. The driver can utilize the named memory area of the VMALLOC (), which uses the memory allocation and page locking techniques that are used in most Linux's Frame-grabber driver.
More specifically, MBuff is locked to the actual physical memory page one page one page. Any real-time or kernel tasks, or user processes can access the memory at any time. By locking the virtual memory page to the physical memory page, MBuff ensures that the assigned page is permanently residing in physical memory, and does not happen. In other words, when a real-time or kernel process accesses allocated memories, it ensures that the VMM is not called. Note: Any call of VMM will cause system pauses due to the implementation of real-time task execution of real-time Linux. If it is accessible and is not in the virtual storage page within the physical RAM, even if the normal Linux kernel driver also causes a system failure. Since MBUFF is a Linux driver, its functionality can be implemented by device node / dev / mbuff. The node can display several entry points, including MMAP () that can map the kernel space address to the user space. It can also be controlled using an entry point IOCTL (). However, there is no need for complex structures and directly call IOCTL. Instead, MBUFF provides a parcel for ioctl () calls, and only two simple features can be configured and release shared storage buffers.
Of course, the MBuff driver cannot be called from the real-time task because the virtual memory allocation feature called by the driver is itself uncertainty. The time required to assign a shared memory depends on the memory capacity of the primary system and the existing status of the CPU speed, disk drive performance, and memory allocation. Therefore, only the shared memory can only be allocated from the Linux kernel side of the module, such as starting from the init_module () or an IOCTL () request.
So, how much memory can a shared buffer allocate? If it is not a server or graphics app, it is recommended to reserve 8MB storage space for at least Linux. In order to obtain an optimized configuration, the performance of real-time applications can be measured while limiting the memory size to determine how much storage is required.
Listing 2 gives how to access shared memories from real-time tasks and user processes. The kernel module and user task use the same function set. Of course, you must also put it in the Linux kernel. For example, MBuff_alloc ("buf_name", size) can assign symbol name buf_name to a buffer, while MBuff_Free ("buf_name", MBUF) can be released.
When MBuff_alloc () with the symbol buffer name is called, MBuff executes the actual memory allocation. When the function is called from the kernel module or user process, it simply adds the number of usage and returns the pointer to an existing buffer. Each time you call MBuff_Free () reduces the number of usage until zero, then MBuff will assign a buffer with a symbolic name. This method obtains a pointer to the same shared buffer from multiple kernel modules and user processes to solve problems. It also ensures that the shared buffer has been valid until the last application releases it. Note that is a real-time kernel or a user process executing the actual BUF1 configuration dependies on who will get control.
There is also a "stupid" method to share memory between real-time applications, kernel modules, and user applications. This method is still acceptable for embedded applications. For example, if the PC has 128MB RAM, the line search path = "MEM = 120m" can be added to the lilo.conf file (List 3). When the system with Linux kernel and RTLinux 2.3 is activated, Linux uses only 120MB of memory. OS does not have the remaining 8MB of memory (physical address is 0x7f00000 to 0x7fffffffffff), but is left to all task sharing running under OS. To get a memory address from the user process and access the reserved memory, you must use the O_RDWR access mode to open the / dev / MEM driver, and then reserved the memory (list 4) using the mmap (). From the side of the real-time module or kernel driver, IOREMAP (0x7f00000, 0x100000) must be used to obtain this 8MB (0x100000 byte) reserved memory. This method is advantageous. You cannot pass the ownership of the memory, or you cannot obtain control over a read or written. The mechanism that correctly configures and releases a lot of memory has not yet been found. In addition, the memory cannot be used for Linux regardless of whether the real-time process is required.
Perhaps the only applicable applicable applicable applicable to the memory shared method is a small embedded system customized for a specific application, as it can be miniaturized to abandon the use of the MBuff driver.
Interrupt
Rtlinux has two interrupts: hard interruption and soft interrupts. Soft interrupt is a routine Linux kernel interrupt, which has the advantage that there is no restriction using Linux kernel calls. Such interrupts as the second part of the hard interrupt process is also quite useful (more detail related to interrupt processing in the Linux environment).
Hard (real-time) interrupt is the premise of installing real-time Linux. To install an interrupt handler, call RTL_Request_irq (...) first, then call RTL_Free_irq () to release it. Depending on the different system, the delay in real-time Linux is hard (or real-time) interrupt is a level of 15μs. The faster processor has a good delay. If you want to process the same device IRQ in a real-time handler and a regular Linux driver, you must set IRQ separately for each hard interruption.
Listing 5 gives the process of installing real-time interrupt handles. RTLINUX will disable IRQ when performing a real-time interrupt handler. It should be noted that the code must call RTL_hard_enable_irq () before exiting the real-time interrupt handler before re-enable interrupts.
There are two problems affecting the Linux kernel function directly from real-time interrupt handler: kernel prohibits all interrupts and unfinition execution. It should also be noted that floating point operations cannot be performed here. Use the real-time interrupt handler to control thread execution to avoid good ways to occur. This example uses the pthread_wakeup_np () function to wake up a real-time thread. The interrupt handler can process instant work and resolve the rest of the thread.
Advantages of SMP Structure
Real-time Linux supports multiprocessor architecture. The symmetrical multiprocessor (SMP) structure has adopted a Advanced Programmable Interrupt Controller (APIC), and the Pentium-grade processor has on-screen APICs, which can be transmitted for the local processor. The SMP (or even single-handed machine boards) has I / O APICs to collect interrupt requests from peripherals, and transfer them to local APICs. The old 8259 PIC speed is very slow, and the number of interrupts treated is insufficient, forcing the device to share the interrupt, so that the interrupt treatment is slower. However, APIC can solve these problems. By setting a specific IRQ for each device, the system can reduce the interrupt delay, and the APIC can accelerate synchronization code.
Real-time Linux makes full use of APIC. In the SMP system, the real-time scheduler utilizes the APIC instead of the outdated 8254 chip to complete timing assignment. Due to the compatibility of the PC, 8254 is located on each ISA bus, and each re-programming device is called to take up the processor cycle. A Gigabo CPU is ware for hundreds of processor cycles to wait for 8MHz timers (approximately 2.5μs). The APIC works in the bus frequency, and all timer operations can be performed immediately, which means that the local APIC clock must obtain higher periodic frequencies on the AMP machine (dual P-III-500 CPU can run periodically in 100KHz. Threads without obvious performance loss). Real-time Linux can perform multi-processing tasks well, which implements a separate process for each CPU. Call pthread_create () Create a thread running on an existing CPU. It is also possible to assign the thread to a specific CPU with pthread_attr_setcpu_np () to change the thread properties. Before calling this feature, you must first initialize thread properties.
RTLINUX V. 3 includes a reserve_cpu feature, which can reserve a CPU on the SMP platform for RTLinux. It can run on a 2.4X core, and RTAI has almost the same function.
If you want to deliver your task to a particular CPU, please pay attention to the "Pset" scenario (http://isunix.it.ilstu.edu/thockin/pset/). With this kernel, an SMP processor can be specifically assigned to one user application, or even call a processor from a Linux processor group to real-time tasks.
Synchronous primitive
Early real-time Linux did not synchronize primitives. Now, POSIX type flags, mutual exclusion, and signals have appeared in the latest real-time Linux versions. Although there is still a problem in real-time design, there is still a problem, but synchronous or signal indicates that real-time tasks and user applications are very meaningful, however, this requires software developers to have superb skills, this problem has exceeded the discussion of this article range.
Quickly learn pthread_mutex_init (), pthread_mutex_lock (), pthread_mutex_trylock (), pthread_mutex_unlock (), and pthread_mutex_destroy () Sync feature is to view ./examples/mutex/mutex.c. Especially to remind ./examples/mutex/sema_test.c file is a good starting point for learning the flag.
Real-time Linux development direction
Real-time Linux is still in the continuous development like Linux. Each new version adds more features and features. Real-time Linux is moving toward better POSIX 1003.x, the latest features include real-time support, mutual exclusion, signal, flag, real-time memory management, and extended SMP support, including user space processes. If you have not yet determined which real-time system is used, you can download a real-time Linux version to find out. In fact, Linux is already a mature OS and has a real-time extension version, which is one of the best choices for embedded applications.
Dr. Alex Ivchenko is a joint electronic industrial company's R & D engineering manager, and is also one of the main developers of the company's PowerDAQ II series PCI data acquisition board. Recently, he is writing Linux drivers for the series card. You can contact him via email AIVCHENKO@ueidaq.com.
references:
Ivchenko, A. "Real-Time Linux," Embedded Systems Programming, May 2001, P. 35.
Marsh, David. "Understand Linux Device Drivers," Test & Measurement World, April 15, 2000.
Johnson, MK and EW Troan. Linux Application Developments. Reading, MA: Addison Wesley Longman, 1998.manchizza, P., E. Bianchi, L. Dozio, S. Papacharambous, S. Hughes, And D. BEAL. "RTAI: Real-time application interface. An Introduction To RTAI for Deterministic and Preemptive Real-Time Behavior for Linux, Linux Journal, April 2000.
RTLINUX website: www.rtlinux.org and www.rtlinux.com. You can download files and source code from it, and the RTLinux declaration of Victor Yodaiken is also a good starting point.
RTAI website: www.rtai.org
Other driver materials come from "Linux Document Project" (www.linuxdoc.org), especially David A. Rusling, Linux kernel and Michael K. Johnson (khg.redhat.com) is a Linux core hacker guide. Finally, it is recommended to understand the latest kernel's update www.kernelnotes.org).
Author: Alex ivchenko