![]() |
||||
|
DOWNLOAD
|
CHANGES
|
SCREENSHOTS
|
DOCUMENTATION
| |
We'll take a simple application, 'slip', through various stages, meeting most of the features and functionality of WhatOS along the way. All code may be found in doc/slip/.
Serial Line IP (SLIP) is a simple protocol for point to point serial communication using a wire. You will find many resources on the internet explaining it. Basically, you need to transmit a packet of arbitrary data, one byte at a time. Byte 192 marks the beginning and the end of the packet. If the packet data contains the number 192, it has to be escaped so that the receiver doesn't think it's the end of the packet. I won't go in the details of the escape mechanism; in this tutorial we'll just transmit packets that don't contain 192.
A system is a group of tasks communicating through signals. Tasks are not aware of each other; they simply receive and emit signals. When a signal is emitted, it is broadcast to all tasks listening for that signal. A signal can be pure or valued. A valued signal carries with it a certain value of a certain type while a pure signal carries no value -- it's mere presence is all of the information it carries.
We'll implement a system containing a Python SLIP transmitter task (pysliptx) and a C SLIP receiver task (csliprx).
Feature: Write tasks in Python or in C with invisible communication barriers.
slip1.py - Two tasks: pysliptx and csliprx
We have created pysliptx by cloning object whatos.core.pytask and customizing it; similarly we have created csliprx by cloning object whatos.core.ctask and customizing it. Although these seem to be classes, they are actually objects. WhatOS is written using a style of programming called prototype-based programming where only objects exist (no classes) and new objects are created by cloning existing objects and customizing them.
To bypass the discussion on how to create new signal value types (documented in whatos.core) we have imported packet from whatos.embedded, a python module containing useful tasks for embedded system design. (Actually, whatos.embedded already contains the Python and C tasks for SLIP communication which we are developing in this tutorial.) wuint8 on the other hand, along with other simple integer and floating point types are standard types found in whatos.core.
Attribute process is where the state machine executes. This implementation of pysliptx is not much of a state machine at all, since it emits all bytes in one shot and doesn't change state. csliprx is a more typical state machine example. It changes state when receiving bytes. In pysliptx, method process is called with input = signal and inputval = value of signal; process is implemented directly in Python. In csliprx, process is a string containing the C code which gets executed when an input, inputval are received. accept() and reject() are exit points from this block of code, indicating that the signal was accepted or rejected. These two macros, along with emit(), await(), require(), acquire() and a few others, are defined by the source code generator (see C API internal task interface).
Let's make our system containing these two tasks. When connections between tasks are made, all task inputs and outputs with the same name are connected together by signals. Since pysliptx emits outbyte and csliprx received inbyte, we rename csliprx.inbyte to outbyte.
Feature: Customize interfaces of tasks to match together.
system1.py - System containing pysliptx and csliprx
Let's use this system in a Python interactive session. First we build the dynamic link library containing the C portion of the system (csliptx, memory allocator, scheduler, etc...), then we load this dll, and then we simulate by emitting signals. Instead of invoking the Python interpreter with a command like "python" we invoke "wospython". This is a script (bin/wospython) created by WhatOS during the installation which takes care of setting environment variables (such as PYTHONPATH, LD_LIBRARY_PATH, etc.) and then invokes "python":
$ wospython >>> from system1 import * >>> system.dllbuild() >>> system.dllload() >>> system.inpacket.emit([1, 2, 3]) inpacket([1, 2, 3]) -> pysliptx outbyte(192) -> csliprx outbyte(1) -> csliprx outbyte(2) -> csliprx outbyte(3) -> csliprx outbyte(192) -> csliprx outpacket([1, 2, 3]) -> environment
Reminder: Invoking wospython instead of invoking Python directly saves you the pain of setting environment variables and mistakenly calling the wrong Python version. Call wospython with --interactive option if using Tkinter applications; when invoked like this, wospython uses a separate thread to execute Tkinter.mainloop(), which does not block the console from executing commands interactively.
Feature: Develop and test interactively using Python.
Notice that csliprx has correctly emitted the right packet ([1, 2, 3]). This is one test case which we know is correct. After applying many more test cases like this one, we can save the output (cut and paste) and write a script which will automatically retest pysliptx and csliprx whenever we want (e.g. see Python's standard module doctest). Although most of the time it is impossible to write an exhaustive set of test cases, the more test cases you have the better the confidence in the correctness of the system.
Feature: Use Python to automate testing of written and verified code.
That covers the creation and simulation of a complete system.
Until now we have used WhatOS generated C files in the background by creating and using a Python extension module (dll) for simulation. Here we'll use the generated files wossystem.h and wossystem.c to create a stand-alone command-line application. This same procedure applies equally well when using the generated C files in an embedded system application; the generated C files contain a complete operating system including signal routing, priority scheduling and memory management. Hello WhatOS contains a complete demo session with an embedded system.
This sample stand-alone application, called sliprx, is a command-line application which receives a set of bytes (passed on the command line) and prints out a packet if those bytes form a complete packet; if the bytes do not form a complete packet it prints nothing.
system3.py - System with pysliptx and csliprx
Notice that it's ok to have Python tasks in the system; they will be ignored during the generation of the C source code files. We define the macro hook_outpacket to be executed whenever a task emits the signal outpacket. Using system3.py we generate wossystem.h and wossystem.c with the following command:
$ wospython system3.py gencode
sliprx.c - Simple slip receiver demo program
In sliprx.c we use wossystem.h and wossystem.c by adhering to the C API external interface. Let's build the executable and try it out:
$ cc -o sliprx sliprx.c wossystem.c $ ./sliprx 1 2 3 $ ./sliprx 192 1 2 3 192 [1, 2, 3]
In the first case we get no output because the sequence of bytes 1, 2, 3 do not define a packet. In the second case we get the desired output packet [1, 2, 3].
This simple example did not visibly exploit the full embedded system features like scheduling. In an interrupt driven embedded system application, parallel execution of tasks is needed for real-time applications and that is where this functionality can be fully appreciated.
Feature: Generated C files contain complete stand-alone operating system environment.
©
Mircea Hossu ( ) |
WhatOS
2.0.3 (2006 Feb 26) |