CIS 690, Kansas State University
Total Page:16
File Type:pdf, Size:1020Kb
LegOS Research
Ryan Simmons [email protected] CIS 690, Kansas State University Dr. Neilsen Spring 2002 Introduction
My research has primary involved legOS, an “operating system” for Lego Mindstorms computers to use. It replaces the firmware given by Lego and allows for C- like programs to be cross-compiled to the Lego brick’s Hitachi chip. The homepage for this project is at: http://legos.sourceforge.net/. This software allows for a high degree of control of what the Lego computer, or commonly referred to as the RCX, does. Threads, priority scheduling, and networking are some of the interesting features you get from this powerful addition. In the spring of 2002, my research included several different areas and findings related to legOS version 0.2.5. My findings will be presented in four different sections:
1. A fix for the generic Robotics Invention System (RIS) software 2. How to get legOS to work with a USB Infrared tower in Linux 3. Some documentation and specification information I have compiled relating to the Lego network protocol (LNP) 4. Some sample code and discussion of LNP program implementations (including some multi-thread programs)
Fix for Robotics Invention System Software
The Lego software provided in called the Robotics Invention System (RIS). It has a problem where the RIS launcher will load after every reboot of the system. To remedy this I called Lego technical support. I was informed to do the following:
1. Use Microsoft’s regedit and find the key HKEY_LOCAL_MACHINE -> SOFTWARE -> Microsoft -> Windows -> Current Version -> Run.
2. Under the section labeled “Run,” find RIS2PostReboot. Under RIS2PostReboot remove its contents. This includes the path and executable.
How to get legOS to work with the USB IR Tower in Linux
LegOS Installation notes
This installation has been tested on Redhat Linux 7.2 with the default kernel and 2.4.18. It is not an extremely easy process and it is not as fast the serial version of the tower. I believe it is because these drivers are a kind of “hack” to get it to work. Also, the software to send Lego network protocol messages does not currently work with the USB version of the tower. These instructions allow you to get a Lego USB IR tower to work with Bret Thaeler's patch and drivers. If you have any problems, feel free to email me at [email protected]. More information about testing legOS can be found at the legOS homepage at http://legos.sourceforge.net and the legOS newsgroup at http://www.lugnet.com/robotics/rcx/legos/. I have done most this as root, but there are some cases where you would not need this access. To be safe, it is easier to be root for everything because of the way the legOS software accesses hardware. Installation Instructions
Note: Commands that should be executed are in italics.
(1) Files and packages needed
Cross Compiler Resources:
http://legos.sourceforge.net/files/linux/redhat/ rcx-binutils-2.9.5.0.22-1.i386.rpm rcx-egcs-1.1.2-1.i386.rpm rcx-egcs-c++-1.1.2-1.i386.rpm
legOS source (get version 0.2.5):
http://legos.sourceforge.net/
USB Patch:
http://members.aol.com/bthaeler/linux_driver_v02.driver.tar.gz
(2) Install the RPMs
To install be sure to put them all on one line because of dependencies. Like this: rpm -ivh rcx-binutils-2.9.5.0.22-1.i386.rpm rcx-egcs-1.1.2-1.i386.rpm rcx-egcs-c++-1.1.2-1.i386.rpm
(3) Install legOS
I recommend installing in /usr/local and I will refer to installations this directory as [base] throughout the rest of the file in case you decide otherwise.
(5) Patching legOS (for USB support)
From your [base] directory:
1. untar the linux_driver 2. run "patch -p1 < linux_driver/legOS.0.2.5.patch"
(6) Fixing the Makefiles, etc.
In your [base] directory:
Edit Makefile.common -- under linux/solaris section change TOOL_PREFIX = .... to TOOL_PREFIX = /usr/bin/h8300-hitachi-hms-
In [base]/boot:
Edit .depend -- change occurences of /home/louie/project/legOS/kernel to [base]/legOS In Emacs this is easy to do: hit ESC then %; type the expression being replaced; type the expression being inserted; finally hit ! to replace all occurrences Or you can use a regular expression. (7) Driver Compilation
Note: If you are using the default Redhat 7.2 kernel, you can skip parts A and B. Also: If you are using an older kernel than specified (such as the default Red Hat 7.2 kernel); You will need to comment out or remove the last line in usb_lego_driver.c. This line says MODULE_LICENSE("GPL"); . It will not compile on some kernels with this in. The file is located in linux_driver\usb_lego.
A. Make sure you have USB support compiled as a module for your kernel.
B. This links your kernel source to your current kernel. Otherwise the usb_lego module will not properly compile. Replace /usr/src/linux with your own directory if you store your source elsewhere.
Go into /usr/include rm -rf linux Go into /usr/asm rm -rf asm Execute ln -s /usr/src/linux/include/linux linux Execute ln -s /usr/src/linux/include/asm asm
C. In [base]/legOS/linux_driver/usb_lego:
Edit Makefile -- change MODULE_DIR to point to your module directory. This is likely /lib/modules/[kernel version]/kernel/drivers/usb
D. As root: run mknod --mode=a=rw /dev/usb/lego0 c 180 200 This creates a location to the device.
E. Finally, from [base]/legOS/linux_driver/usb_lego:
run make; make install When you run make install, make sure the modprobe is successful.
Running a Test program
You can't use the default firmdl3 (firmware downloader) or dll (dynamic linker) to coordinate with the USB tower. You have to go into their individual directories and compile them.
You have to edit the Makefile.common in [base]/legOS/util:
Change LINUX_USB = ... to LINUX_USB = [base]/legOS/linux_driver/usb_lego
Then, you can run the Makefile in the [base]/legOS/util/firmdl to compile firmdl.
Make sure you have cleared the memory in the RCX block (lego robot computer). Removing one battery and then replacing it can do this. But, sometimes you have to let it sit without a battery for a while to clear it.
Once you have cleared the RCX, you can "flash" legOS onto it.
To be sure the legOS tower is properly installed either reboot or pull the USB connection out and put it back in. If the green light goes on, it should work.
From [base]/legOS/util/firmdl: execute ./firmdl3 ../../boot/legOS.srec
You should see the legOS firmware test fast downloading and then it will install the firmware in a few seconds. The USB tower should have a green light go on. If this works you should have the USB successfully working. Sometimes the connection will not work right or the firmware will not download properly. In these cases, unplug the tower and plug it back in. Also, make sure the modules are loaded after you reboot. On my machine, sometimes I receive a notice from Red Hat that the module is not fulfilling all dependencies. This is an error you can ignore because the module is not perfectly written, but it works. If you are having problems, you might run “lsmod” to make sure the USB IR tower driver is loaded. If not, run “insmod” as directed above.
Documentation on Lego Network Protocol
The Lego network protocol (LNP) specification provides powerful features for communication between RCXs, RCXs to PC, and PC to RCXs. On the PC side the LNP runs as a daemon for interpreting and sending messages. legOS has LNP features built in, the only requirement is that the LNP libraries must be loaded in the RCX code. Like many networking protocols, LNP was designed with a layering model. This table shows the layers implemented by the LNP:
Table from: http://www.informatik.uni-kiel.de/inf/von-Hanxleden/teaching/WS2001- 02/Verteilte_Echtzeitsysteme/Lectures/Lecture_14.pdf
Layers 0 and 1 are handled at low-level RCX and assembly language code. Layers 2, integrity, and 3, addressing, are the ones developers will be interested in. RCX and PC code can directly interface with these layers at a high level. This is typically done with C code. The integrity layer sends generic messages without identifying ports or the receiver. It is simpler than the addressing layer and it requires 40% less overhead than addressing [2]. This is what the packet format for the integrity layer looks like: Figure from: http://www.efd.lth.se/~d94tn/exjobb/rapport.pdf F0 is a packet header for integrity packets, LEN gives the length of the packet data, IDATA is the actual data desired to be transmitted, and the checksum tries to give the protocol some reliability [1]. Reliability is not guaranteed with LNP, erroneous packets are discarded [2]. In the addressing layer LNP code can be directed to specific ports and receivers can be identified. This is what the packet format for the integrity layer looks like:
Figure from: http://www.efd.lth.se/~d94tn/exjobb/rapport.pdf
F1 is a packet header for addressing packets, LEN gives the length of the data, DEST gives the receiver’s address, and SRC gives the sender’s address. The addressing layer is especially useful for coordinating multiple LNP clients. The ability to specific receiver and know who the sender is allows for more flexibility. This is a basic overview of the structure and specification of the LNP. In the next section, I will give some examples of code and templates that could be used in implementing LNP applications.
Creating LNP Applications
In this section I will present several code examples and explain the reasoning and implementation behind them. This section only works with the SERIAL version of the Lego IR tower. Also, I run all of these programs as “root” to work with the lnpd code. Some users will not need to be “root”; I have read that this depends on your motherboard’s chipset. I was unable to patch the LNP PC code for USB, but I believe the LNP RCX code should work. Attempting to patch the USB code proved to be very difficult. I will focus primarily on PC to RCX communication since RCX to PC is very similar and easier. Most of my ideas for this were found at the legOS HOWTO for LNP at: http://legos.sourceforge.net/HOWTO/x405.html. The LNP packages must be downloaded from http://legos.sourceforge.net/files/linux/LNPD/ and get the lnpd+liblnp.tgz package. Untar the package by typing “tar xvzf lnpd+liblnp.tgz” in /usr/local/ or a directory of your choice. Applications developed for transmitting and receiving LNP messages on the PC side will reside in the /usr/local/lnpd+liblnp/applications directory. I will refer to the sample program as pc_lnp.c. Edit the Makefile to include the name of your new program for PC to RCX communication. Add this program to the Makefile by adding (changes are in bold):
TARGET2 = pc_lnp SRCS2 = pc_lnp.c OBJS2=$(SRCS2:.c=.o)
AND
clean: rm -f *.o *~ *.bak $(TARGET1) $(TARGET2)
depend: $(MAKEDEPEND) $(SRCS1) $(SRCS2) > .depend
AND
$(TARGET2): $(OBJS2) gcc -o $(TARGET2) $(OBJS2) $(LDFLAGS) $(LIBS)
These changes should follow the same form as the original Makefile. For example, insert the $(TARGET2) section after the $(TARGET1) section.
Applications developed for RCX LNP code will reside in your legOS home directory (probably /usr/local). Create a subdirectory called pgrms (or something else) in your legOS home directory. Copy the Makefile from /usr/local/legOS/demo to /usr/local/legOS/pgrms. I will refer to the sample program as rcx_lnp.c. Edit the Makefile to include the name of your new file by changing the section “PROGRAMS=” to equal the name of your program: rcx-lnp.c. I have developed a template for sending string messages from the PC to the RCX. And I have developed another one for the RCX to interpret these messages. I am presenting these examples using the integrity layer for clarity and simplicity. I will provide some sample information on how these templates can be converted into addressing mode. Also, I am providing the information for sending strings only. I feel that strings will be the most common interface for sending data to the RCX, but additional information can be found at the legOS HOWTO on the LNP: http://legos.sourceforge.net/HOWTO/x405.html on how to work with other data types like integers. My example is based on the legOS HOWTO’s template, but I clarify sections and correct some of their errors. This is an efficient multi-threaded solution on the RCX side, so I will also explain how to implement threads in legOS. These templates provide the foundation for allowing the PC to remotely control the RCX. Reliability features can be added by having the RCX send verification to the PC that it received a command. LNP features for the RCX to send to the PC are the same as the PC to the RCX, but the lnp_init command is not needed for RCX’s to send messages. Template for PC Implementation
This is the source code for pc_lnp.c:
#include "liblnp.h" /** * Function to send the string to the RCX * from the PC. */ void printString(char *s) { int len, result; char *buffer;
len = strlen(s) + 1; buffer = malloc(len + 2); buffer[0] = 's'; //first char 's' denotes a string datatype memcpy(buffer + 1, s, len + 1); result = lnp_integrity_write(buffer,len + 2); free(buffer); } int main(int argc, char **argv) { if ( lnp_init(0,0,0,0,0) ) { //Initialize the PC for LNP perror("lnp_init"); exit(1); }
printString("Data you wish to send"); }
This code sets the PC up for transmitting a message to the RCX. The ‘s’ char at the beginning denotes that the datatype is a string. The string is then written in integrity mode. For addressing mode you might want to make definitions like:
#define DEST_HOST 0x8 #define DEST_PORT 0x7 #define DEST_PORT_2 0x8 #define DEST_ADDR ( DEST_HOST << 4 | DEST_PORT ) #define DEST_ADDR_2 ( DEST_HOST << 4 | DEST_PORT_2 ) to define what ports and hosts you want to use. On the RCX side you would want similar definitions, but you would want to “flip” the destinations and port numbers.
Template for RCX Implementation
This is the source code for rcx_lnp.c:
#include
/** * The template for the RCX to receive LNP data. */ int gNewData = 0; //flag for new data char gMessagingData[256]; //data to send int gDataLength; //length of data to sen
/** * Handles the incoming packets. */ void packet_handler(const unsigned char* data,unsigned char length, unsigned char src) {
if(gNewData == 0) { memcpy(gMessagingData, data, length); gDataLength = length; gNewData = 1; }
}
/** * When the thread awakens, return that there is new data * available. */ wakeup_t WaitForData(wakeup_t data) {
return gNewData;
}
/** * Thread to handle incoming packets. */ int PacketWatcher(int argc, char **argv) {
while(1) { wait_event(&WaitForData, 0); //wait for a message
switch(gMessagingData[0]) { //check the first char for message type 's'=string 'i'=int //checks if the message is in string format 's' case 's': cputs(gMessagingData +1); break; }
gNewData = 0; //reset new data flag
} } /** * Starts the packet handling routines. */ int main(int argc, char **argv) { lnp_integrity_set_handler(packet_handler); //sets the packet handler execi(&PacketWatcher, 0, NULL, PRIO_NORMAL, DEFAULT_STACK_SIZE); //start the message //processing thread }
This code puts the RCX in a mode where it is waiting for messages. With this specific program, it displays the messages on the screen. But, this template could easily be adapted for performing remote control. Controlling motors could make an IR controlled robot with little difficulty. The separate thread works by receiving messages whenever the gNewData flag notifies it. The execi command starts the new thread. The first parameter is the process; the second is the argc, then the argv, then the priority of the process, and then the stack size. I set it to normal priority and a default stack size. More constants for priority on threads can be found in the legOS API at http://legos.sourceforge.net. It is easy to see that legOS uses simple priority based scheduling. It is important that the program use memcpy for efficiency reasons. The RCX has limited memory (approx. 32k) and very little processing power. Also, if you plan to send integers you need to watch out for big and little endian issues. It is best to do these conversions on the PC side if possible because of RCX’s limited resources.
Running the Code
Run the Makefiles in both directories (/usr/local/legOS/pgrms and /usr/local/lnpd_liblnp/application) by typing, “make”. If there are no errors related to the programs you compiled you are ready to continue. Errors under the C++ sections of the Makefile are acceptable because we do not have any C++ files. Make sure you have downloaded the legOS firmware on the RCX. Directions on how to do this are found in the How to get legOS to work with the USB IR Tower in Linux section under “Running a Test Program.” Now you need to download the program to the RCX. From the pgrms directory type “../util/dll rcx_lnp.lx”. Downloading the program should not take long; hit the run button after you are finished. Next, you will start the LNP daemon. I recommend opening a new terminal for this. The daemon is located /usr/local/lnpd+liblnp/lnpd directory. From there, you can start the daemon in several different ways. To get a listing of these type “./lnpd –help”. I recommend either “./lnpd –debug” or “./lnpd –log=[filename]”. The debug mode makes it so the lnpd does not go into the background automatically. The log mode tells lnpd to log its information in [filename]. Also, you must make sure that the LNP daemon is not running while you are attempting to flash the RCX with the dll program. These programs do not work at the same time. A patch is available for this, but I was unable to get it to work with the legOS 0.2.5. I believe version 0.2.6 was just released, so this may have been fixed. After the LNP daemon is running, you are ready to send a message. First, make sure the RCX is running the program. Then, go to /usr/local/lnpd+liblnp/applications. From there, enter “./pc_lnp” to send the message. If successful, the RCX should display message you sent it based on the code above. It will not display the entire message because of the size of the display. You will need to divide it up into multiple “cputs” statements if you wish to see the whole thing. If you encounter problem like the RCX locking up, reset it by removing the batteries for a few seconds and reinserting them. Then, follow the steps listed above.
Resources
[1] Ervasti, Tomi and Niklasson, Torkel. SDL Programming of LEGO robots. http://www.efd.lth.se/~d94tn/exjobb/rapport.pdf
[2] Hanxleden. Communicating with the RCX Dependability. http://www.informatik.uni-kiel.de/inf/von-Hanxleden/teaching/WS2001- 02/Verteilte_Echtzeitsysteme/Lectures/Lecture_14.pdf
Cross Compiler Resources. http://legos.sourceforge.net/files/linux/redhat/
The legOS homepage. http://legos.sourceforge.net
The legOS HOWTO. http://legos.sourceforge.net/HOWTO/ (x405.html for LNP) legOS newsgroup. http://www.lugnet.com/robotics/rcx/legos/
Lego Mindstorms Homepage. http://mindstorms.lego.com/
USB Patch. http://members.aol.com/bthaeler/linux_driver_v02.driver.tar.gz