LitePAC technical overview ========================== Instead of introduction ----------------------- First of all LitePAC is not a product, it is a set of technologies that help to make our life somehow easier. These technologies help us to solve real world problems particularly it is the automation of some processes. LitePAC consists of some programs that help to deploy small automation projects. They work within a Linux operating system under different hardware architectures. It means that it possible to run LitePAC on relative cheap hardware that makes automation solutions more accessible and less expensive. For easiness we divide programs into some groups: - Toolchain for developing control programs; - Runtime programs. - Protocol and hardware modules. Toolchain for developing ------------------------ This group includes _four_ programs, _one_ helpfull script and a set of useful library calls. We put all descriptions for each item in separate sections. Programs for development ~~~~~~~~~~~~~~~~~~~~~~~~ Programs are presented in the order they suppose to be called to get an executable file from a source file: - _vmlang_ is a C-like language complier. As input it takes a source code file that is written on LitePAC C-like language, as output it returns an assembler listing. The assembler listing consists of lines of low-level instructions, that are special for the LitePAC runtime environment. The language also have some special syntactic constructions to address inputs and outputs areas. A user absolutely doesn't need to know how the output file looks inside. ------------------------------- $ vmlang -o source.vS source.vm ------------------------------- where *source.vm* is an input source file and *source.vS* is an output assembler listing. - _vmasm_ is an assembler. The result of _vmlang_ is an assembler listing. It supposes to be processed by _vmasm_. So as input it takes the assembler listing, as output it returns a binary object file. It is still not the final executable file but it is a half-finished product. The generated object file can wait a symbol relocation or linking with other objects files. ------------------------------ $ vmasm -o source.vo source.vS ------------------------------ where *source.vS* is an input assembler listing and *source.vo* is an output object file. - _vmlink_ is a linker. As input it takes one or several object files, that were produced by _vmasm_, as output it returns the final executable file. The main goal of the linker is to resolve all unknown symbol names in object files. It means, for example, it is possible in one source file call functions from another source files. Moreover this mechanism is always used when we try to link our object files againts library call object files. ------------------------------------------ $ vmlink -o source.v source1.vo source2.vo ------------------------------------------ where *source1.vo*, *source2.vo* are input object files and *source.v* is an output executable file. [NOTE] It should be noticed that _vmlang_ and _vmasm_ take only one input file at one time but _vmlink_ can take one or more files. Though all programs have only single file as output. As you can see the process of creating an executable file is delegated to _three_ programs. It is done this way following one UNIX tradition that one tool should perfoms one single task. It makes each program easier for extending and understanding. There is a standart sequence of calls to build a common programm: _cc -> as -> ld_ When a user build a program in LitePAC, he calls programs in the next order: _vmlang -> vmasm -> vmlink_ - _vmobjdump_ is a helpfull program to examine the internal structure of object and executable files. With this tool you can check all headers and get a disassembling listing. Additional information about the internal structure of object and executable files or instructions can be found in another papers. Building script ~~~~~~~~~~~~~~~~ During the process of development we usually recompile our programs many times when we correct errors or add something new. So it would be quite inconvenient to run all programs one by one to get a final executable file. Special for this purpose programs are wrapped with a script _vmc_. - _vmc_ is a wrapper around all programs. It makes a life easier and hides consecutive calls of _vmlang_, _vmasm_, and _vmlink_. It perfoms all calls for a user, as input it takes a source file, as output it returns an executable file. --------------------------------------- $ vmc -o source.v source1.vm source2.vo --------------------------------------- where *source1.vm* and *source2.vo* are input files and *source.v* is an output executable file, as you can see in the example that an input file can be a source file and/or an object file. Library calls ~~~~~~~~~~~~~ Calls are splitted into groups according to their functionality. Each group consists of _three_ files: - a header file that the _vmlang_ program uses to resolve symbol names in a source file. A user uses an *include* preprocessor derective to include new API. The header file has the *.vh* extension. - a shared object file for the LitePAC runtime environment. It is a real implementation of calls. This file has the *.so* extension. The LitePAC runtime environment locates this file in a predefined directory. - a LitePAC object file, you can check the internal structure with _vmobjdump_. This file is used during the linking stage (with the _vmlink_ program). This file has the *.vo* extension. Let look at the example. Assume a user needs working with strings functions. First of all he needs to include a headed file. He has to write in a source file: -------------------- #include -------------------- The header file __ is a text file and you can find all function prototypes there. Let say that a user needs to find the length of a string. For this purpose there is the function _strlen()_. Somewhere in the source file a user calls this function: ------------------- int len; len = strlen(str); ------------------- Now we need to compile a source file and don't forget that we need linking our code against *string.vo* (an object file). We can do it with help of _vmc_: ---------------------------------- $ vmc -e main -o file.v file.vm string.vo ---------------------------------- where *file.vm* is a user source file, *string.vo* is an object file that comes with a library, *file.v* is the executable file. Runtime programs ----------------- - _libvmrt_ is a library that we use to create an instance of a virtual machine, to execute a byte code, to call library functions. - _libhal_ is a library that helps to synchronize inputs and outputs images. The hal protocol is a text base protocol. For more information about the hal protocol see a special paper. - _vmachined_ is a program that supports some types of tasks, has a simple FIFO scheduler, has a mechanism to handle interrupts with priority. _vmachined_ synchronizes inputs and outputs images with _hal-mgr_ each cycle time. - _hal-mgr_ is an image manager, the manager polls protocol and hardware modules to build final images and synchronizes final inputs and outputs images with _vmachined_. Tasks ~~~~~ _vmachined_ works with the following taks: * a cycle task; * a background task; * interrupt tasks. The cycle and background tasks are single tasks, the number of interrupt task can be up to 32 (0 is the highest priority, 31 is the lowest priority). The cycle task is always presented, the background task is optional task, interrupt tasks are also optional tasks. If the background task is presented it is always active until the cycle task or an interrupt task want to be run. If the current task is a cycle task and a new interrupt task wants to run, the cycle task will be stoped and the interupt task will become a current task. If the current task is an interrupt, then a new interrupt task with a higher priority will displace the current interrupt task. All tasks are developed with a LitePAC toolchain. Cycle timer ~~~~~~~~~~~ _vmachined_ has a cycle timer. When a cycle timer is elapsed, it means _vmachined_ has to run a cycle task. Before _vmachined_ wants to get the final inputs image from _hal-mgr_. _vmachined_ requests it with a hal command. Then _hal-mgr_ polls all protocol and hardware modules, build the final inputs image and sends it back to _vmachined_. At this moment _vmachined_ runs a cycle task. The result of cycle task is the updated output image. Now it is time to spread it back to all modules. _vmachined_ writes the final outputs image to _hal-mgr_, then _hal-mgr_ in its order spreads it by part to protocols and hardware modules. So the result of the cycle is updating outputs in modules. Virtual controller ~~~~~~~~~~~~~~~~~~ Lets think about _vmachined_ as about a virtual controller. The main task of the controller is to control inputs and to write something to outputs but inputs and outputs images look local. Indeed the whole system can be distributed as much as a user wants. All parts of the system are separate programs. Protocol and hardware modules ----------------------------- At present the main goal of project is not to support as many devices and protocols as possible but create a right designed core that can be easely extended with new modules but we have some test modules. All modules are passive and work with _hal-mgr_. The manager first has to connect to all modules and to know how inputs and outputs images are big. _hal-mgr_ reads inputs at the beginning of the cycle task and write outputs at the end of the cycle task. All modules synchronize their images using the hal protocol. Now we have two module: * _lincond_ is a daemon that works with ICPDAS Lincon controller. It reads and writes states of analog and discreet IO cards. * _modbusd_ is a modbus server that works the same way as _lincond_, it doesn't support all modbus commands but it has enogh to work with (now it is not in the source tree).