BrickOS (legOS)
description
Transcript of BrickOS (legOS)
BrickOS (legOS)
Presentation byJeff Bargmann
Quick Intro: What is it?
• Full-out operating system for our Brick!
• Allows for running compiled C/C++ on the RCX
• As will discuss later: Cross-Compiled with GCC compiler for uploading to RCX
• API/reference docs for 3 types of intended users:– C developers (me)– C++ developers (me)– Kernel architects (not me, but could be you!)
Quick History
• First released in July 2000
• Renamed from ‘legOS’ to ‘BrickOS’ in July 2002, however many documents out there still refer to its previous name.
• Last update: v0.9, January 2005
BrickOS: The Brick… Operating System
• BrickOS: Not just an interpreter, a full Operating System for your RCX!
• Programs that are uploaded run natively to the processor (Hitachi H8/3292) onboard the RCX.
• BrickOS’s kernel manages the running programs (scheduling, etc) while the OS provides hardware interfacing, runtime environment, etc.
The BrickOS Kernel
• Capable of managing threads
• 32k of memory available, not 32 variables!• Can use doubles and floats• Can store up to 8 programs on the RCX• Can generate random numbers
• OS still has control ; run button can be used to control/kill execution, On/Off button always works.
• Remote-control compatible.
• Installed with ‘firmdl3’ program: firmdl3 --tty=USB ../boot/brickOS.srec
Cross Compilation
• Cross Compiling a program means compiling it on one platform for use on another.
• Build platform: where the compiling happens• Host platform: where the compiled program
runs
• Here, that means compiling on Windows / Linux / etc, to object-bytecode that is native for the RCX’s processor
Cross Compilation (2)
• It’s tricky to setup
• On Windows:1. Download Cygwin, a Linux-like environment
for Windows
2. In Cygwin, build (or just download) the Hitachi-H8 cross compiler
3. Install brickOS, then from within Cygwin perform scripted operation to build/config it.
Working with BrickOS…the easy way (Windows)
Bricx Command Center (+ Cygwin)
Coding for BrickOS
• Setup for use with C/C++ code.• No fancy tricks! Plain ‘ol C/C++.
– (And everything that comes with it ; inheritance, virtual methods, new/delete, etc possible w/ C++)
• API reference for utilizing the runtime available for either language.
• Library is very robust (…for an RCX…), and even allows for such things as networking.
The Display
Display functions:– #include <conio.h> //The necessary include– lcd_int( int x ); //Write int to screen– lcd_digit( int d ); //Display digit next to man– lcd_clear(); //Clears entire screen– cls(); //Clears digits from screen– cputs(char *string); //Shows 5-char string
Motor Controls, Overview
• When working in C:– Basic functions available to control speed, direction.– State accessed via external variables maintained by the
OS.– (#include <dmotor.h>)
• When working in C++:– Motor() and MotorPair(left, right) classes available– Control single motor, or more complex operations on two.– C++ object-oriented interaction made possible.– (#include<Motor.h>, #include<MotorPair.h>)
Motor Controls, Sample
C Sample
motor_a_dir(fwd); //set motor A to forward. ‘fwd’ is a MotorDirection enum.
motor_a_speed(MAX_SPEED); //run motor A at full speed
lcd_int(dm_a.dir); //displays motor A’s direction, ‘1’
msleep(500); //sleeps 500ms
motor_a_dir(rev); //set motor A moving in reverse
lcd_int(dm_a.dir); //displays motor A’s new direction, ‘2’
msleep(500); //sleeps 500ms
motor_a_dir(off); //turn motor A off. (just cuts power;
use ‘break’ to stop hard)
cls(); //clears the display
Motor Controls, Sample
C++ Sample
MotorPair m(Motor::A, Motor::C); //define a pair of wheels (left,right)
cputs ("Go"); //update display
m.forward(255); //both forward at full power (0-255 scale)
sleep(2); //sleep 2 seconds
cputs ("Turn"); //update display
m.pivotLeft(); //rotate about left wheel, at the current speed
sleep(2); //sleep 2 seconds
cputs ("Done"); //update display
m.break(500); //apply breaks to both motors and delay 500ms
lcd_clear(); //clear the screen
Sensors: Push & Light
• Accessed in C by defined macros, that refer to external variables maintained by the OS.
• Push sensors
– Boolean: 1=pushed, 0=not
– TOUCH_1, TOUCH_2, TOUCH_3
• Light sensors– Scaled value between LIGHT_RAW_WHITE (0x5080)
and LIGHT_RAW_BLACK (0xffc0).
– LIGHT_1, LIGHT_2, LIGHT_3
Sensors, etc:Rotation and others
• Rotation sensors– ds_active(&SENSOR_1); //required to activate sensor
– ds_rotation_on(&SENSOR_1); //turns sensor 1 on
– ds_rotation_off(&SENSOR_1); //turns sensor 1 off
– ds_rotation_set(&SENSOR_1, pos); //sets sensor value to pos (an int)
– Read with: ROTATION_1, ROTATION_2, ROTATION_3 (int)
• Battery level– An int, read by the BATTERY macro.
• Front buttons– Check for pressed boolean state with macro:
PRESSED( dbutton(), BUTTON_VIEW ); //checks the ‘view’ button’s state
Sensors, Code
C Sample
while (!shutdown_requested()){
if(TOUCH_1)
break;
lcd_int(LIGHT_2);
sleep(10);
}
C++ Sample
TouchSensor t(TouchSensor::S1);
LightSensor l(LightSensor::S2);
while (!shutdown_requested()){
if(t.pressed())
break;
lcd_int(l.sample());
sleep(10);
}
Sound
• Some sound functions:– dsound_stop(); //stop current sound– dsound_playing(); //query: ‘is playing sound?’– dsound_finished(); //returns non-zero when
sound playback has finished
– dsound_set_durration( int length ); //sets length in ms of a 16thnote
– dsound_play( note_t *notes );• Plays a song defined an array of pitches and lengths
Sound
#include <dsound.h>
static const note_t our_song[] = {
{ PITCH_G4, QUARTER }, { PITCH_G4, QUARTER },
… //(omitted middle of song)
{ PITCH_PAUSE, HALF },
{ PITCH_F4, HALF }, { PITCH_E4, HALF },
{ PITCH_END, 0 }
};
int main(int argc,char *argv[]) {
dsound_set_duration(40); //speed up the song
while (!shutdown_requested()) { //continue playing until ‘stop’ button pressed
if (wait_event(dsound_finished,0) != 0) //only play when no other is currently playing
dsound_play(our_song); //play our song
sleep(1); //sleep for one second
}
return 0;
}
Advanced BrickOS Features
• Threading
• Events
• Synchronization
• Networking
Threading
• Thread created and executed by the call:
tid_t thread = execi( int(int, char**) *funct,int argc,char ** argv,priority_t priority,size_t stack_size);
• Exampleint WatchButton(int argc, char *argv[]);execi(&WatchButton, 0, NULL, 1, DEFAULT_STACK_SIZE);Starts function WatchButton as a thread, with no parameters passed, with the lowest priority (0-20 scale), and with the default stack size (512).
Threading
• Thread Functions:– void exit( int ret_code ); //exits current thread– void kill( tid_t tid ); //terminates thread tid– void killall( priority_t p ); //kills all threads w/ priority < p– (apparently no built-in ‘join’ available, nor a universal workaround)
– void yield( ); //yields control to other threads– int sleep( int sec ); //sleeps for sec seconds– int msleep( int msec ); //sleeps for msec milliseconds
Events: ‘wait for this…’
• Events are an integrated part of the BrickOS kernel’s scheduler.
• Upon switching context from another it will check ‘should-wake’ status of waiting threads.
• You give it a function and a parameter ; your thread resumes when the function returns non-zero.
• wakeup_t wait_event (wakeup_t(wakeup_t) *wakeup_func, wakeup_t data);
– (wakeup_t is typedef’d as a unsigned long)
Events Sample
Entry point
#define DARK_THRESH 0x40
#define NORMAL_SPEED (2*MAX_SPEED/3)
void main() {
motor_a_speed(NORMAL_SPEED);
motor_c_speed(NORMAL_SPEED);
motor_a_dir(fwd);
motor_c_dir(fwd);
wait_event(dark_found, DARK_THRESH);
cputs ("Found");
motor_a_dir(off);
motor_c_dir(off);
}
‘dark_found’ wait function
wakeup_t dark_found(wakeup_t data)
{
return (LIGHT_2<(unsigned short)data));
}
Synchronization
• Counting-semaphores are provided by OS; uses classical Dijkstra definition of semaphores.
• Along with basic sem_wait and sem_post (signal) operations, sem_trywait, sem_timedwait, and sem_getvalue are also available.
• Implemented using events.
• First-checked-first-awoken applies in the case of a signal with multiple threads waiting.
LNP (LegOS Networking Protocol)
• Allows for communication between robot and PC via IR connection
• Requires additional tools:– LNPd: deamon that runs on PC– Liblnp: the library required to build applications for the PC to
work with the deamon
• Documentation on even BrickOS’s own site is…sparse.For a little better luck, try:http://www.cs.brown.edu/courses/cs148/brickOS/ref/lnp.html
LNP, Basics
• The Process– Create buffer– Transmit buffer, to address or broadcast
• Some Functions Broadcasting:
– int lnp_logical_write(const void *buf, size_t len); – void lnp_logical_fflush();
To An Address:– int lnp_addressing_write(const void * data,
unsigned char length, unsigned char dest_address_and_port, unsigned char src_reply_to_port);
Incoming Traffic:– void lnp_addressing_set_handler ( unsigned char port,
lnp_addressing_handler_t handler );
• Some sample code at:http://www.ee.adfa.edu.au/staff/hrp/teaching/LegoMindstorm/testlnp.c
LNP, Other uses
• Using the ‘Message’ buttons on the remote#include <remote.h>
int main() {
lr_init();
lr_set_handler(RemoteEvent);
cputs("wait");
}
int RemoteEvent(unsigned int etype, unsigned int key){
if ((etype == LREVT_KEYON) && (key == LRKEY_M1)) {
cputs("msg1!");
//do something useful!!
}
}
Finally,something else cool
• Know C#?
• http://www.dcl.hpi.uni-potsdam.de/research/lego.NET/
Logo.NET
• Research project, a GCC Compiler for C# to compile for use on BrickOS– First release Oct ’04, v1.2 released April ’05, v1.3 “upcoming”
• What it can do so far– Floats, doubles, string literals, all your basic types
– Delegates
– Arrays
– Classes, including static/instance attributes, properties, and consts
– Control flow operations
• What’s not, yet– Strings (advanced), Multi-Deminsional Arrays, Interfaces, Exceptions, Most
all pre-defined classes
• Are they still working on it?– Maybe?
Logo.NET,Sample Program
using System;using brickOS;
namespace LineTracker { class LineTrackRunner {
const short bright = 42; const short dark = 30;
static void Main() { // Activate light sensor dsensor.ds_active(dsensor.SENSOR_2); // "3-2-1" Count down for (short i = 0; i < 3; i++) { dsound.dsound_system(
dsound.DSOUND_BEEP); unistd.msleep(500); }
Go(); //begin! }
static void Go() { //Start the dmotor.motor_a_speed(
dmotor.MAX_SPEED); dmotor.motor_c_speed( dmotor.MAX_SPEED);
// Main loop while (true){ if (dsensor.LIGHT_2 > bright) { dmotor.motor_a_dir(dmotor.rev); dmotor.motor_c_dir(dmotor.fwd); } else if (dsensor.LIGHT_2 < dark) { dmotor.motor_a_dir(dmotor.fwd); dmotor.motor_c_dir(dmotor.rev); } else { dmotor.motor_a_dir(dmotor.fwd); dmotor.motor_c_dir(dmotor.fwd); } } } }
Conclusion
• BrickOS is a great solution for comfortable C/C++ programmers, and fun for kernel or compiler writers.– Great for those looking to explore the wealth of power and
raw ‘experiment-ability’ the RCX offers!
• After the painful setup…– Quick development and testing– Stable and predictable– Comfortable language-environment– Powerful. Allows making full use out of the hardware
Oh, and…
• Char: 1 byte
• Int: 2 bytes• Short Int: 2 bytes• Long Int: 4 bytes
• Float: 4 bytes• Double: 4 bytes
• …and…
• Despite best efforts, couldn’t get STL to work. Not much information out there. But maybe you’ll be the first!
References / Resources
• BrickOS– http://brickos.sourceforge.net/
• BrickOS Windows Installation Guide– http://www2.acae.cuhk.edu.hk/~tliu/LegOS_install/legOS_install.htm
• BrickOS Debian/GNU Linux Installation Guide– http://brickos.sourceforge.net/docs/install-Debian.html
• logOS How-To– http://legos.sourceforge.net/HOWTO/
• Programming Lego Mindstorms using BrickOS– http://www.it.uu.se/edu/course/homepage/realtid/h05/ass2/
References / Resources(Continued)
• Quick LNP Reference– http://www.cs.brown.edu/courses/cs148/brickOS/ref/lnp.html
• Bricx Command Center (v1.3)– http://bricxcc.sourceforge.net/
• Cygwin: Linux-like environment for windows– http://www.cygwin.com