RTFM is a set of languages and tools developed to facilitate both concurrent programming in general and embedded real-time software development in particular. There are two languages in RTFM, core and cOOre.
Below is a short introduction to developing applications in the cOOre and the core language.
cOOre is an object-oriented language based on the -core language. The main goal is to provide a light-weight object-oriented model for concurrent programming.
coore:
classDef*
classDef:
| "class" ID "<" classArgs ">" extern? "{" classDecl* "}"
classArgs:
| classArg ("," classArgs)*
classArg:
| pType ID
| pType (mSig) ID
mSig:
| pType ("," mArgs)*
classDecl:
| pType ID ":=" expr ";"
| ID "<" params ">" ID ";"
| pType ID "(" mArgs ")" "{" stmt* "}"
| "Task" ID "(" mArgs ")" "{" stmt* "}"
| "Reset" "{" stmt* "}"
| "Idle" "{" stmt* "}"
mArgs:
| mArg ("," mArgs)*
mArg:
| pType ID
pType:
| INT | CHAR | BOOL | STRING | VOID
params:
| expr ("," params)*
expr:
| "async" after? before? ids "(" params ")" (* async expression *)
| ids LP params RP (* id expression *)
| ids LP params RP (* sync expresion *)
| INTVAL (* integer value *)
| CHARVAL (* character value *)
| BOOLVAL (* boolean value *)
| "RT_rand" "(" expr ")" (* RT built ins *)
| "RT_getc" "(" ")"
ids:
| ID "." ID
| ID
after:
| "after" time
before:
| "before" time
time:
| INTVAL tunit?
tuint:
| "us" | "ms" | "s"
External bindings are implemented according to A candidate cOOre module system.
Since RTFM is to be used in small embedded systems there is a chance that the system will need to communicate with some other system via internet. For this purpose the "library" Websocket.core can be used:
// Example showing the use of websocket send/receive
class Root<> extern "Websocket.core" {
extern void ws_send(int);
Task client_receive(char msg) {
RT_printf("client wrote : %c\n", msg);
}
Reset {
RT_printf("Reset!");
}
Idle {
ws_send(2); // Send number 2 on websocket
idle_websocket();
}
}To compile an application using websockets use PTCORE/RTFM-SRC/wscooremake.
Gives a visual overview of the class declarations and their tasks and functions.
To use, run cOOre compiler flag with flag -gv_obj obj.gv.
Gives a visual overview of the class instances and their tasks and functions.
To use, run cOOre compiler flag with flag -gv_inst inst.gv.
Gives a visual overview of the task/function calls between class instances.
To use, run cOOre compiler flag with flag -gv_task task.gv.
To generate the pdf files;
dot -Tpdf task.gv -o task.pdf
Tested on OSX Mavericks (10.9) and OSX Yosemite (10.10).
- XCode (Latest XCode command line tools)
$ brew install ocaml opam graphviz graphviz-gui
$ opam init # The OPAM system needs to be initially configured
$ opam config env # Run after OPAM init to configure the environment
$ opam install menhir # Our Parser generator (installs ocamlfind also)
Tested on Ubuntu 12.04/14.04 and Linux Mint but should work on any modern linux distribution, you may need to change apt-get to your package manager though.
$ sudo add-apt-repository ppa:avsm/ppa # Add OPAM repository
$ sudo apt-get update # Update the repository tree
$ sudo apt-get install python-software-properties ocaml opam m4 graphviz graphviz-gui
$ opam init # The OPAM system needs to be initially configured
$ opam config env # Run after OPAM init to configure the environment
$ opam install menhir # Our Parser generator (installs ocamlfind also)
Tested on Windows 7, 8 and 8.1. All 64-bit. (tested also on win8.1 32-bit)
- Download wodi 32bit graphical installer: http://wodi.forge.ocamlcore.org/download.html
- Install at standard location (C:\wodi32), standard location is important!
- During Cygwin setup add the following under devel:
binutilsclanggcc-coregcc-g++gdb
- Run "Wodi32 Package Manager", search for menhir and select it for installation
- Install menhir by clicking on "Apply"
- Download graphviz for Windows: http://www.graphviz.org/Download_windows.php
- Run the installer package
graphviz-X.XX.msi. - Place it under
C:\GraphvizX.XX\(N.B. NO spaces in the path!) - Add
C:\GraphvizX.XX\binto path.
- under Cygwin: run
source fix_common_link.sh
$ cd RTFM-core-compiler && make rtfm_core
$ cd RTFM-cOOre-compiler && make rtfm_coore
The test suite is using sstephenson/bats to automate the testing of the type checker in the cOOre compiler. In order to run the tests, start by installing bats:
$ brew install batsSee Installing bats from source.
$ chmod u+x RTFM-cOOre-compiler/test/test_runner
$ cd RTFM-cOOre-compiler/test && ./test_runneror
$ cd RTFM-cOOre-compiler/test && bats .$ bats test_operators.batsTests are written as .bats files which basically is bash extended with the light testing framework sstephenson/bats. The file test_helper.bash should be loaded in each file since it adds some extra functions to make the tests more slim as well as making sure the compiler is compiled before all tests are run.
#!/usr/bin/env bats
load test_helper
@test "perform addition correctly" {
compile_inline "int a := 2 + 3;"
assert_success
assert_last_line "Passed type checking."
}
compile takes a filename as argument and will compile the file and then check the result.
compile_inline takes a small piece of cOOre code that will be compiled and then checks the result.
assert_success asserts that the exit status flag is set to success.
assert_failure asserts that the exit status flag is not set to success.
assert_equal will check whether the two arguments that are given are euqal and report the difference if they aren't.
assert_last_line will check whether the last line of the output is equal to given string.
To demonstrate an example application written in cOOre with websockets there is an application written simulating the countdown timer from the TV series Lost. The specification can be found at http://lostpedia.wikia.com/wiki/Countdown_timer.
In order to test the timer start by compiling the cOOre program PTCORE/RTFM-SRC/counter.coore:
$ cd PTCORE/RTFM-SRC && ./wscooremake counter.cooreThen in order to run the application do
$ sudo PTCORE/bin/counterTo demonstrate the websockets part a web application has been created that uses Javascript and Websockets to connect to the application. The web application can be found under lost-counter/. Open index.html after you have started the binary and click the button "Connect" in order to connect to the application and start receiving data. If the correct password (4 8 15 16 23 42) is entered the timer will be reset.
- Sometimes the correct code must be entered twice in order for the timer to be reset correctly, not sure why.
- If 90 seconds are reached the entire screen should start blinking red, this is to simulate the "beeping" in the real Lost countdown timer.
- The web application has been developed in the latest version of Google Chrome and will probably run best in that browser although it should work correctly with all modern web browsers.