Advanced Topics: Files, LCP, Memory, NXJ Tools
Advanced Topics: Files, LCP, Memory, NXJ Tools

Understanding the leJOS File System

The NXT has 256kb of flash memory. A fixed section at the start of the flash memory is allocated to the system. It is used to hold the firmware, followed by the startup menu. The rest of this system area is unused. The size of the system area varies between releases.

The firmware is written in C, with some ARM assembly language. The startup menu is written in Java (in the startup project in SVN).

Flash memory is read and written in 256-byte pages. The first page after the system area is used for persistent system settings administered by the startup menu.

The rest of the flash memory is used for the user file system. 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.

The Flash class

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

The System Settings class

The SystemSettings class is used to administer the system settings page. It should not be used by user programs.

The File class

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 read and write files, you need to use streams. The stream constructors 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) - creates new OutputStream to write to this file, starting at the beginning of the file. The file is deleted if it already exists. A new file is then created. 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 java.io.*;
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 {
      out = new FileOutputStream(data);
    } catch(IOException e) {
    	System.err.println("Failed to create output stream");
    	Button.waitForPress();
    	System.exit(1);
    }

    DataOutputStream dataOut = new DataOutputStream(out);

    float x = 1f;
    int length = 8;

    try { // write
      for(int i = 0 ; i<length; i++ ) {
        dataOut.writeFloat(x);
        x = x*-2.2f; 
      }
      out.close(); // flush the buffer and write the file
    } catch (IOException e) {
      System.err.println("Failed to write to output stream");
    }
    Sound.beep();
    Button.waitForPress();
  }
}

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

You can also use the PrintStream class or the OutputStreamWriter class to write to files.

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
        float x = din.readFloat();

        System.out.println("" + x);
      }
      din.close();
    } catch (IOException ioe) {
      System.err.println("Read Exception");
    }
    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 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. 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.

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 key leJOS NXJ tools

nxjflash

In order to flash firmware to the NXT, it is necessary that the NXT is 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”.

To flash new firmware, nxjflash 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.

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. 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 or Netbeans.

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

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, and saves the results is in a cache file which it uses in preference to doing a Bluetooth inquiry when it can . 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.

nxjupload uses the apache Commons CLI command line processor.

Back to top

nxjlink

nxjlink calls the linker (class 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 verbose option 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.

Back to top