Advanced Topics: Files, LCP, Memory, NXJ Tools


Advanced Topics: Files, LCP, Memory, NXJ Tools

Understanding the leJOS File System

leJOS NXJ implements a file system using flash memory. The flash memory is read and written in 256-byte pages. The first two pages hold the file table (directory) and the rest of the pages hold user files. Files are held as a contiguous set of bytes – i.e they use a single range of page numbers with no gaps. This allows a file to be addressed as a region of memory.

Flash

The Flash class has methods to read and write 256-byte pages of flash memory. It should not be used by user programs.

File

The File class has static methods that manipulate the file system as a whole and instance methods that give access to specify files.

Static methods:

  • void defrag()

    removes unused pages in the file system.

  • void format()

    erases all the files and reformats the flash memory.

  • int freeMemory()

    returns the total free memory in the file system.

  • File[] listfiles()

    returns an array of files in the system

To a create a new file, you first call the constructor

  • File(String name)

then

  • create newFile();

    This method throws an IOException, so must be in a try/catch block.

To read and write data, you need to use streams. The stream constructors also throw an IOException so they also must be in a try/catch block.

The file streams read and write individual bytes, so you will usually want to use a data stream filter.

FileOutputStream

The constructors are:

  • FileOutputStream(File f)

    createa new OutputStream to write to this file, starting at the beginning of the file.methods:

  • FileOutputStream(File f, boolean append)

    create a new OutputStream to write to this file

  • void write(int b)

    write 1 byte to the file

  • void flush()

    Flushes this output stream and forces any buffered output bytes to be written

  • void close()

    Write the buffer to flash memory and update the file parameters in flash. Be sure to call this method before your program exits.

Example:


import lejos.nxt.*;

public class FileWriteTest {
  public static void main(String[] args) { 
    FileOutputStream out = null; // declare outside the try block
    File data = new File("log.dat");

    try {
      data.createNewFile();
      out = new FileOutputStream(data);
    } catch(IOException e) {}

    DataOutputStream dataOut = new DataOutputStream(out);

    float x = 1f;
    int length = 8;

    try { // write
      for(int i = 0 ; i<length; i++ ) {
        dataOut.writeFloat(x);
        LCD.drawString(" "+x,0,i);
        x = x*-2.2f; 
      }
      out.close(); // flush the buffer and write the file
    } catch (IOException e) {
      LCD.drawString("write error", 0, 3);
    }
    Sound.beep();
    Button.waitForPress();
  }
}
				

After you run this example, look for the newly created file in the Files menu.

FileInputStream

The constructor is:

  • FileInputStream( File afile)

Methods:

  • int read()

    returns a value between 0 and 255, representing a single byte

  • int available()

    returns the number of bytes available to be read.

Here is an example that reads the file


import java.io.*;
import lejos.nxt.*;

public class FileReadTest {
  public static void main(String[] args) {
    File data = new File("log.dat");
    int i = 0;

    try {
      InputStream is = new FileInputStream(data);
      DataInputStream din = new DataInputStream(is);

      while (is.available() > 3) { // at least 4 bytes left to read
        LCD.drawInt(is.available(), 4, 10, 0);
        float x = din.readFloat();

        LCD.drawString("" + x, 0, i++);
      }
      din.close();
    } catch (IOException ioe) {
      LCD.drawString("read exception", 0, 0);
    }
    Button.waitForPress();
  }
}
				

Back to top

Understanding LCP

LEGO defines a protocol called the LEGO MINDSTORMS NXT Communications Protocol (LCP) which is used to send commands to the standard LEGO firmware. The specification is available at http://mindstorms.lego.com/Overview/NXTreme.aspx in the Bluetooth Development Kit. The commands are separated into direct commands and system commands. The direct commands are described in a separate document: LEGO MINDSTORMS NXT : Direct Commands.

Direct commands are those that are designed for user programs and tools to use to control robots. The system commands are designed for tools that upload and download files and do other administrative tasks.

leJOS NXJ emulates many of the direct and systems commands so that many tools that work with the standard LEGO firmware also work with leJOS.

Many of the leJOS NXJ tools including nxj, nxjuload, nxjbrowse and nxjmonitor use LCP. leJOS NXJ has some minor additions to LCP to make its tools work better.

The implementation of LCP is in the lejos.nxt.comm.LCP class. As leJOS sensors and motors work a bit differently than the standard firmware, the semantics of LCP on leJOS are not always identical to the standard LEGO firmware.

The start-up menu – StartUpTextjava – uses LCP to support the leJOS NXJ tools and third-party tools. This means that LCP commands can be executed over Bluetooth or USB when the menu is running.

Back to top

Understanding leJOS NXJ use of memory

The NXT has 256kb of flash memory and 64kb of RAM.

Flash memory can be read like RAM (access is a bit slower) but can only be written in 256-byte pages by specific hardware instructions,. Flash memory cannot be read while a page is being written.

The leJOS NXJ firmware is written in a combination of C and ARM assembler code. It consists of the initialization code, the Java VM and device drivers for all the hardware subsystems. The leJOS firmware is a complete firmware replacement and has no reliance on the standard LEGO firmware. The first 32kb of flash memory is allocated to the leJOS NXJ firmware. Most code is executed from flash memory, but a`small amount (e.g. the code that writes pages of flash memory) is copied to RAM. Read-only data is held in flash memory but read/write data is copied to RAM. The firmware uses a fixed size stack and interrupt stack.

The leJOS NXJ Java VM executes one Java program at a time. This can either be a user program or the leJOS start-up menu. One Java program can execute another. When this is done the first Java program is removed from memory, and the second one is then executed. This is how the start-up menu executes user programs.

The start-up menu occupies up to 48kb of memory that starts at address 32k (i.e. after the end of the firmware). The last word of the 48kb allocated to the start-up menu holds the size of the start-up menu).

Java programs execute from flash memory. Static read-only data is held in flash memory. Static read-write data is copied to RAM. Objects are created in a heap that starts at the top of the RAM and grows downwards. The Java stack starts at the bottom of free RAM memory and grows up. A garbage collector frees memory used by unreferenced objects when the heap becomes full.

Back to top

Understanding the leJOS NXJ tools

nxjflash

In order to flash firmware to the NXT, it was necessary that the NXT must be in firmware update mode. If you have the standard LEGO firmware installed (or if you have a very recent version of leJOS), then the nxjflash program will do this automatically for you. If not or if there is some problem with the automatic method then you will need to place the NXT into firmware update mode by pressing the reset button for 4 seconds or more. This causes the NXT to run a small boot assistant program called SAM-BA. The was written by Atmel, the maker of the ARM chipset that the NXT uses. SAM-BA includes a USB driver and accepts commands sent over the USB link. These command allows data to be uploaded to RAM and code to be executed. Early version of leJOS used this mechanism to run in RAM before there was a flash version of leJOS NXJ. The latest version of nxjflash will put the NXT into update mode if it is not already so.

On Microsoft Windows and MAC OS X, the standard LEGO USB drivers are used. These come with the LEGO software, which is why this software must be installed. On Microsoft windows, when the NXT is in firmware update mode, a USB cable is attached to your PC and the NXT is switched on (by pressing the orange button), if you go to Control Panel > System > Hardware > Device Manager you will see under “Lego Devices” an entry for the USB driver, labelled “LEGO MINDSTORMS NXT Firmware Update Mode”.

nxjflash uses the libusb library to drive the USB interface. On Linux libusb provides the USB driver. On Microsoft Windows, you need to run the libusb-win32 filter driver. This allows nxjflash to drive the LEGO MINDSTORMS NXT Firmware Update Mode USB driver.

nxjflash drives libusb via a library written by David Anderson, called libnxt. This supports SAM-BA commands. To flash new firmware, it uploads the firmware image a 256-byte page at a time and then executes a small RAM-resident routine to write the page to flash memory. In this way the leJOS NXJ firmware, lejos_nxt_rom.bin is written to flash memory. This occupies the first 32kb of flash memory.

nxjflash also uploads the leJOS NXJ start-up menu StartUpText.bin. This menu is written in Java and built like any other leJOS NXJ Java programs. It implements the leJOS NXJ menu system and supports threads for executing Lego Communication Protocol (LCP) commands over USB and Bluetooth. StartUpText.bin resides in flash memory starting at address 32k. 48kb of flash memory is reserved for it. The highest address word in the 49k. When both the firmware and the menu have been uploaded, nxjflash sends a SAM-BA command to the NXT causing it to jump to address zero and the leJOS NXJ firmware executes.

Back to top

nxjupload

nxjupload uploads programs or other files over USB or Bluetooth. It is a command line interface that is suitable for use from command windows, ant scripts, and as an external command from IDEs such as Eclipse.

nxjupload sends LCP system commands to the NXT to upload the file. The commands are OPEN_WRITE, WRITE and CLOSE.

The call of nxjupload looks like:

  • nxjupload [options] <binary-file>

By default nxjupload first looks for a NXT connected by USB. If it does not find one, it tries Bluetooth. It does a Bluetooth inquiry looking for NXTs. It it finds any it tries to connect to each one, and uploads the file to the first one it successfully connects to. This means that if you have multiple NXTs, it will upload to the one that is currently switched on.

This behaviour can be modified by the following options:

  • -b or –bluetooth: only Bluetooth is tried

  • -u or –usb: only USB is tried

  • -n or --name: the upload is done to the named NXT. A Bluetooth inquiry is done, but only the named NXT is looked for.

  • -d or –address <address>: the upload is to the device with this Bluetooth address. USB is not tried and no Bluetooth inquiry is done.

  • -r or –run: run the program after upload by sending a STARTPROGRAM LCP command.

nxjupload uses the apache Commons CLI command line processor.

Back to top

nxjlink

nxjlink call the linker (class js.tinyvm.TinyVM).

The call looks like:

  • nxjlink [options] class –o <binary file>

The -cp or --classpath option is used to specify where the linker looks for classes. Note that the linker classpath is separate to the classpath uses to execute js.tinyVM.TinyVM.

The linker first looks for the specified class in the linker classpath, and then looks for all classes that this references to form a “closure” of the classes. The linker class path should include classes.jar and all the user classes in the program. The class specified on the command line must be the one containing the main method. The Jakarta apache Byte Code Engineering Library (BCEL) is used to process the class files.

The linker omits methods that have not been referenced unless the –a or –all flag is specified. The way this is done uses a simple algorithm and does not manage to omit all unreferenced methods.

The linker produces a leJOS NXJ binary file and writes it to the file specified in the –o parameter.

nxjlink needs to know the byte order of the processor it is producing the binary for. For the NXT this is set by “–writeorder LE” for Little-Endian.

If the –v or –verbose flag is set, a list of the classes and methods in the binary is output to standard out. This is very useful for debugging.

nxjlink uses the apache Commons CLI library for command line processing.

nxj

The nxj command links and uploads the program file. It takes the same parameters as nxjlink.

nxjc

This command invokes the compiler. It takes the same parameters as standard java.

Back to top