This is a comprehensive Real Time Application Interface (RTAI), both for uniprocessors (UP) and for symmetric multi processors (SMP), developped at the Dipartimento di Ingegneria Aerospaziale del Politecnico di Milano (DIAPM), (www.aero.polimi.it/projects/rtai/). It allows you to use Linux kernel 2.2.xx for many hard real time applications. Note that it cannot be used for 2.0.xx. Please note also that the all stuff is based on the assumption that the Linux kernel tree starts at "/usr/src/linux" while "rtai-x.x.tgz" can be untarred wherever you want creating the directory ..../rtai-x.x. If you do not adhere to those assumptions you must change the various "Makefile"s, and "copyto" in linux-2.2.xx directory, accordingly. This version can be used for UPs PCs and for SMP as well. In the latter case task are defaulted to work on any cpu but you can assign them to any subset, or even to a single cpu, by using the function "rt_set_runnable_on_cpus". It is also possible to assign any real time interrupt service at a specific cpu by using "rt_assign_irq_to_cpu" and "rt_reset_irq_to_sym_mode". Thus a user can statically optimize his/her application if he/she believes that it can be better done than using a symmetric load distribution. The possibility of forcing any interrupts to a specific cpu is clearly not related to the SMP scheduler and can be used also with interrupt handlers alone. Note that only the real time interrupt handling is forced to a specific cpu. That means that if you check this feature by using "cat /proc/interrupts" for a real time interrupt that is chained to Linux, e.g the timer when rtl_sched is installed, you can still see some interrupts distributed to all the cpus, even if they are mostly on the assigned one. That is because Linux interrupts are kept symmetric by the RTAI dispatcher of Linux irqs. The schedulers allow to chose between a periodic and a oneshot timer, not to be used together. The periodic ticking is less flexible but, with the usual PC hardware much more efficient. So it is up to you which one to choose in relation to the applications at hand. It should be noted that in the oneshot mode the time is measured on the base of the CPU time stamp clock (TSC) and not on the 8254 chip, which is used only to generate oneshot interrupts. The periodic mode is instead timed by the 8254 chip only. In this way slow I/Os to the ISA bus are limited as much as possible with a sizable gain in efficiency. The oneshot mode has just about 15-20% more overhead than the periodic one. It is likely that local APIC timers could lead to a further improvement. Right now they are hard disabled on UPs and a preliminary experience with a single APIC timer, to be released soon for SMP, shows that there is no performance improvement for a periodic scheduling while the oneshot case gain is sizable but not so large to with respect to the present solution. In fact by using the TSC just two outb are required to reprogram the 8254, i.e 2.5 us approximatly, against almost nothing for the APIC timer. However you have to broadcast a message to all the cpus in any case, and that is at least about more than 3 us, the APIC bus is an open drain 2 wires one and is not lightning like. Note that the performance loss of the 8254 is just a fraction of the overall task switching procedure, which is always substantially heavier in the oneshot case than in periodic mode. Since the TSC is not available on 486 machines for them we use a form of emulation of the "read time stamp clock" (rdtsc) assembler instruction based on counter2 of the 8254. So you can use RTAI also on such machines. Be warned that the oneshot timer on 486 is a performance overkill because of the need of reading the tsc, i.e. 8254 counter2 in this case, twice. That can take 6-8 us, i.e. more than it takes for a full switch among many tasks while using a periodic timer. Thus only a few Khz period is viable at most for real time tasks if you want to keep Linux alive. No similar problems exist for the periodic timer that needs not to use any TSC at all. So, compared to the 20% cited above, the real time performance ratio of the oneshot/periodic timer efficiency ratio can be very low on 486 machines. Moreover it will produce far worse jitters than those caused on Pentiums and upward machines. If you really need a oneshot timer buy at least a Pentium. Instead, for a periodic timing 486s can be still more than adequate for many applications. An important remark. We have tested this option only on Pentiums, since we have no more 486s available. A feature of this RTAI implementation is that interrupt handlers preambles take care natively of the task switched (TS) flag. Thus you can freely use floating point operations in your interrupt handlers, without causing a trap fault whatever thing Linux is doing. RTAI is thus very suitable to trap interrupts without minding of Linux so that you can effectively interact with the bare PC hardware much in the same way I, and maybe many of you, liked the old good time of DOS. With RTAI you have the added advantage that Linux maintains all of its feature untouched so that you can pass to it whatever you get from your handler for logging, displaying and postprocessing, by using fifos and/or shared memory. Imagine a remote controller at 10 Khz, +-5 us interrupt uncertainty, connected through the internet, with the all the bells and wistles of X and its applications. It is an application we simulated easily. See the "examples/timer" directory in examples for some clues, without remote control however. RTAI needs to calibrate the cpu clock frequency if the oneshot scheduler is used for Pentiums and upward machines. On the contrary, as it will be clarified shortly afterward, 486s need not such a calibration. For the cpu frequency you have two choices: - the first, and less precise, is to get the cpu frequency by just typing "cat /proc/cpuinfo" and taking the value shown on the screen. - the second, and reccomanded mode, requires running the module rt_cal from the directory "cpu_freq_calibration" included in this distribution. Yuo'll get something better than in cpuinfo in about twenty seconds. If you want to get full precision let it run till the least significant digit is stabilized. See README in "cpu_freq_calibrate" for a more precise description. Note that this must be done just once for all. No calibration is needed for 486s, just set CPU_FREQ equal to 8254_FREQ (1193180 hz) in "rtai.h" in the directory "include". That's the way the various modules understand that 486s are being used. A further calibration is required, only if you intend to use the oneshot mode, for the LATENCY macro to be set in "rtai.h" file in directory "include". For that see the README file in directory "latency". Note that this version of RTAI has also some very useful system services, including: timings, semaphores, messages and remote procedure calls (RPC). That makes it easier to develop complex real time applications. RPCs are a limited form of QNX messages as they pass either just an usigned integer or a pointer to an unsigned integer for reason of efficiency. They can be easily changed to be fully compatible with QNX if you'd like. There are many examples that allow you to experiment with forcing tasks and the timer interrupt to any specific cpu, with a summary of cpus usage printed at examples rmmoding. What to do: 1 - Get a clean distribution of linux-2.2.xx kernel and follow the instructions in file INSTALL of this distribution to patch it. So far what suggested there has remained valid from 2.2.pre1 up to 2.2.6. We expect that it will be so for a long time ahead. The RTHAL/RTAI concept is so flexible that it would be easy to upgrade, should anything change in the basic kernel interfaces toward the PC hardware. However if you are lazy, do not want to learn the "where and why"s and want to use Linux kernel 2.2.6 go to directory "linux-2.2.xx", actually linux-2.2.6, and type "copyto". See the "readme" file there for an explanation. 2 - "make config" (menuconfig or xconfig) to configure the kernel. Right now you must set the SMP option also for UP machines. This entails a slight loss of performance but has eased development. Code cleanup and ifdeffing to allow avoiding SMP in UPs is underway. 3 - Carry out the compilation of the kernel by "make bzImage"; 4 - Get the cpu frequency as described above and set the macro CPU_FREQ in rtai.h in directory include, then "make clean" and "make" in directory rtai-x.x to have the "rtai" module prepared. Remember that for 486s no calibration is required but CPU_FREQ must be set to 8254_FREQ (1193180 hz), already defined in "rtai.h". 5 - Do "make clean", "make install" in the distribution subdirectories "fifos" and: "scheduler" for UP, "smpscheduler" for SMP, to prepare the fifo and appropriate scheduler modules. The file "ldmod" and "remod" can be used to insmod and rmmod all at once: rtai, fifo and scheduler modules with the default parameters. For the scheduler these are: the cpu frequency, as set in the corresponding macro CPU_FREQ in rtai.h, a periodic scheduler and Linux assumed not to use the fpu. You can change any of the above either by setting the corresponding macros in "rtai.h" or at module installation: just type the extended command: "insmod /usr/src/linux/modules/rtl_sched CpuFreq= LinuxFpu= OneShot=", where x is the cpu frequency in hz, y==0 Linux does not use the fpu y!=0 does, z==0 periodic timer z!=0 oneshot timer. Clearly you can set any combination of the above parameters. While the cpu frequency can be changed just by compiling the scheduler modules or at its installation, the functions: "rt_linux_use_fpu(int yes_no)", "rt_set_periodic_mode()", "rt_set_oneshot_mode()", can be used to set/reset the scheduler dynamically. Note that any setting of the timer mode stops any already running timer. Now you are done and can try the test cases. All the examples have some macros that allow you to experiment with forcing tasks and timer interrupts to any cpu, a summary of cpu usage is printed at module rmmoding. Be carefull in setting the macro TICK_PERIOD (nanosecs) in the various examples to a value appropriate to your machine. Those used now works for a 200Mhz PPro and can be too demanding for lower class Pentiums and 486s. In all the tests the choice of which timer, periodic or oneshot, use is done by commeting/uncommentig the macro ONE_SHOT. It is important to remark that since in all tests a oneshot timer is set specifically at module load time, any choice made at the scheduler installation is overridden. It should be also remarked that if the timer mode is chosen at module installation that must be done by adding a call to "rt_set_[oneshot/periodic]_mode()" before any time conversion or service is requested to the scheduler. Thus in the case of a multi modules application set the mode in the very first module to be loaded or in a common header file, as it is done in the digital wrist clock examples (se file "clock.h" in directories "sem_clock" and "msg_clock"). In directory "jitter_free_sw" there is an example that shows how, by loosing computer power, you can get an almost free jitter scheduling. (Thanks to Tomasz Motylesky for suggesting that idea to me and to Manoj Apte for pointing out its use in MARUTI (a hard real time FERRARI)) There are html files to document the various function calls, see the directory "doc_rtai". I'm looking forward for people joining in the development, both for a better understanding of the kernel internals, so to set a portable general RTHAL specification, and in adding features to rtai and related modules. Note that if you want to interface to the rtai substrate you need not to know the kernel deeply, so that adding new modules should be easier and safer, no kernel compilation but just your troubled code. In this spirit, since this is the first distribution of the all stuff, I'll also hope that you will not throw it in the rubbish if something goes wrong or is unclear. It has been thorougly tested on different machines, the SMP scheduler only on standard INTEL dual cpus, without any problem beside those cited in bugs_and_todo, and there are examples, see directories "sem_clock", "msg_clock" and "msgsw", that are basically fairly complex. However there are unknown bugs for sure. You will not see many copyrights in this software and you can use it as you like and want, but I would like "to be remembered" if you'll find it usefull. As usuall it is "as it is" and I assume no responsability if anything goes wrong. However, I'll repeat, comments, any feedback, and help for any further development, if you like the idea, are warmly welcomed. Email to: "mantegazza@aero.polimi.it". Many warm thanks are due to Emanuele Bianchi, Davide Martini, Lorenzo Dozio, Maurizio Quadrio and Daniele Danlugli for their cooperation, suggestions and precious help in various job using Linux for hard real time control systems. Emanuele, Davide and Lorenzo did a nice work to verify and test our RTLinux variant of NMT-RTLinux in production work for their thesis and following research works at DIAPM. The helpful html documentation is almost entireky due to Emanuele and Davide. Lorenzo played also a very important role in retrofitting our efficient oneshot timers to the then purely periodic timing control, because of the need to use them to easily pulse width modulate air jets emulating on-off control rockets. Maurizio is one of the top Linux experts at DIAPM and has been our "great saver" during some deadly disk losses. Daniele has been very very fundamental in the past scheduler development, especially in relation to fpu support. He was the first one to point out unbearable jitters when the fpu was used in RTLinux and in its DIAPM variant. Without his convincing cryes many people, including myself, would never have known that they were using the fpu just to generate troubles in their applications. It is because of that that the fpu support is included natively also for RTAI interrupt handlers.