Lejos Platform + Haskell Interpreter: Invalid Firmware image

Post your NXJ projects, project ideas, etc here!

Moderators: 99jonathan, roger, imaqine

Lejos Platform + Haskell Interpreter: Invalid Firmware image

Postby spideyfly » Tue Jul 24, 2007 8:01 am

Hi all,

I'm trying to build on top of the Lejos platform code to get a Haskell interpreter running. After combining the platform with my interpreter sources I get a binary file that is approx 156KB at the moment, however, when I try to upload to the NXT it says

NXJ_HOME is C:\lejos_nxj
Setting fmcn to 50
Checking VM C:\lejos_nxj/bin/lejos_nxt_rom.bin ... VM OK.
Checking Menu C:\lejos_nxj/bin/StartUpText.bin ... Menu OK.
NXT device in reset mode located and opened.
Starting VM flash procedure now...
Error flashing VM: Invalid firmware image

Does anyone know what's a likely cause for a hand built binary to be invalid? I'm suspecting it's the size.

Thanks
spideyfly
New User
 
Posts: 18
Joined: Sat May 26, 2007 10:15 am

Postby CoBB » Tue Jul 24, 2007 10:32 am

You can find the answer in main_nxjflash.c, where MAX_VM_PAGES is set to 128 (kilobytes); check the call to nxt_firmware_flash(), which will in turn call nxt_firmware_validate_fd() that returns this error (there's no other way to get it). This is probably because the other 128k is reserved for the menu (or Java code in general?), and since you don't need that, you might as well set a higher value and take out the call to flash the menu. I don't see why that wouldn't work.
User avatar
CoBB
Novice
 
Posts: 73
Joined: Tue Apr 24, 2007 12:24 pm

Postby lawrie » Tue Jul 24, 2007 11:31 am

MAX_VM_PAGES is in 256 byte pages, so the limit for the VM size is 32kb.

Currently NXJ uses 32kb for the VM, 32kb for the Java StartUpText menu system, and the rest is used for the file system that stores user programs and data.

Chaning main_nxjflash.c as CoBB says should work.
lawrie
leJOS Team Member
 
Posts: 917
Joined: Mon Feb 05, 2007 1:27 pm

Postby CoBB » Tue Jul 24, 2007 12:02 pm

lawrie wrote:MAX_VM_PAGES is in 256 byte pages, so the limit for the VM size is 32kb.

In that case shouldn't you multiply it with 256 instead of 1024 in nxt_firmware_flash()? Now I see it's indeed 256 when it comes to flashing, but then the verification code should be adjusted.
User avatar
CoBB
Novice
 
Posts: 73
Joined: Tue Apr 24, 2007 12:24 pm

Postby spideyfly » Wed Jul 25, 2007 10:35 am

Hi there, thanks alot for the replies. I'm kinda stuck now trying to recompile the main_fwflash.c files for win32. I have libusb installed (win32 version) but when I compile I get error messages from running scons...

$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
gcc -o firmware.o -c -Wall -std=gnu99 -g -ggdb -D_NXT_LITTLE_ENDIAN firmware.c
In file included from firmware.c:33:
lowlevel.h:25:17: usb.h: No such file or directory
scons: *** [firmware.o] Error 1
scons: building terminated because of errors.


I can find locate the libusb source files but I'm not sure how to include them :S utter puzzlement.

Cheers
spideyfly
New User
 
Posts: 18
Joined: Sat May 26, 2007 10:15 am

Postby CoBB » Thu Jul 26, 2007 4:07 pm

By the way, if it’s still a problem, have you tried using fwflash instead? It’s available in executable form in the current nxtgcc bundle.
User avatar
CoBB
Novice
 
Posts: 73
Joined: Tue Apr 24, 2007 12:24 pm

Postby spideyfly » Fri Jul 27, 2007 12:52 pm

Oh thanks for the pointer CoBB, I did manage to get libnxt to recompile...but I had to move libusb.a into the /usr/local/lib folder and usb.h into the /usr/local/include folder...

I haven't had a chance to move forward just yet though.

Cheers
spideyfly
New User
 
Posts: 18
Joined: Sat May 26, 2007 10:15 am

Postby spideyfly » Fri Jul 27, 2007 2:25 pm

At the moment I'm loading my bin file to the brick using fwflash...but for some reason nothing is showing up on display...will need to rebuild and figure out whether something's missing...I did comment out a few things from the platform's main.c

[Edit] Oops...nevermind
spideyfly
New User
 
Posts: 18
Joined: Sat May 26, 2007 10:15 am

Postby spideyfly » Thu Aug 09, 2007 1:56 am

Hmm...here's my dilemma.

I've got firmware working that's sitting in ROM. I'd like to load my files into RAM and have the code in ROM read from the RAM locations. The idea is that I can change programs without bothering about wearing out flash and so forth.

The problem is that the NXT must be in reset mode to load into RAM or ROM if I use libnxt. Somehow I'm not able to start the code in ROM after the load is done.

Does anyone know if there's a way to load the program and then jump to starting ROM?

Thanks
spideyfly
New User
 
Posts: 18
Joined: Sat May 26, 2007 10:15 am

Postby CoBB » Fri Aug 10, 2007 10:42 am

If it needed to be in firmware update mode, the menu wouldn't work in the last release. :| I wrote this function to receive a file that's sent from the PC using the (now apparently obsolete) sendfile utility from libnxt:

Code: Select all
char *ham_bc; /* Pointer to bytecode */
U16 ham_bc_len;

extern U32 __free_ram_start__;
extern U32 __free_ram_end__;

#ifdef BYTECODE_IN_RAM
#define dataGet(t, ofs) *((t*)(ham_bc + ofs))
#else /*BYTECODE_IN_RAM*/
#define dataGet(t, ofs) *((t*)(((char*)FLASH_BASE) + ofs))
#endif /*BYTECODE_IN_RAM*/

/**
 * Wait for a file and receive it through the USB connection.
 * The wait can be aborted by pressing enter and escape simultaneously.
 *
 *
 * @return the length of the file in bytes or -1 in case of user abort
 */
int receive_file() {
  U8 buf[64];
  int bytes = 0;
  int size = 0;
  int sending = 0;
  U8 reply[32];
  int replyLen;
  int i;
  int dataLen = 0;
#ifndef BYTECODE_IN_RAM
  U8 fbuf[256];
#endif /*BYTECODE_IN_RAM*/

  udp_reset();
  ham_bc = (char*)&__free_ram_start__;

  do {
    dataLen = udp_read(buf, 64);
  } while ((dataLen == 0) && (buttons_get() != 0x09));

  if (buttons_get() == 0x09) return -1;

  do {
    for (i = 0; i < 32; i++) reply[i] = 0;
    reply[0] = 0x02;
    reply[1] = buf[1];
    replyLen = 3;
    if (sending) {
      for (i = 0; i < dataLen; i++) {
#ifdef BYTECODE_IN_RAM
        ham_bc[bytes++] = buf[i];
#else /*BYTECODE_IN_RAM*/
        fbuf[(bytes++) & 0xff] = buf[i];
        if ((bytes & 0xff) == 0) {
          flash_write_page((U32*)fbuf, (bytes >> 8) - 1);
        }
#endif /*BYTECODE_IN_RAM*/
      }
      if (bytes == size) {
        sending = 0;
        reply[2] = 0x83;
        buf[0] = 0x01;
        replyLen = 6;
      }
    } else if (buf[1] == 0x81) {
      /* Open write */
      size = buf[22];
      size += buf[23] << 8;
      size += buf[24] << 16;
      size += buf[25] << 24;
      buf[21] = 0;
      display_goto_xy(0, 2);
      display_string((char*)buf + 2);
      bytes = 0;
      replyLen = 4;
    } else if (buf[1] == 0x83) {
      /* Write */
      replyLen = 6;
      sending = 1;
    } else if (buf[1] == 0x84) {
      /* Close */
      replyLen = 4;
    }
    if (!sending && ((buf[0] & 0x80) == 0)) {
      udp_write(reply, replyLen);
    }
    systick_wait_ms(10);
    dataLen = udp_read(buf, 64);
  } while (dataLen > 0);
#ifndef BYTECODE_IN_RAM
  if ((bytes & 0xff) != 0) {
    flash_write_page((U32*)fbuf, bytes >> 8);
  }
#endif /*BYTECODE_IN_RAM*/

  display_goto_xy(0, 3);
  display_string("Bytecode: ");
  display_unsigned(bytes, 0);

#ifdef BYTECODE_IN_RAM
  ham_bc_len = bytes;
#else /*BYTECODE_IN_RAM*/
  ham_bc_len = 0;
#endif /*BYTECODE_IN_RAM*/

  return bytes;
}

It's basically a rewrite of the old StartUpText. You can use the BYTECODE_IN_RAM define to tell whether you want to put it in flash memory or RAM. The dataGet macro allows you to access the data of the given type and at the given offset afterwards.
User avatar
CoBB
Novice
 
Posts: 73
Joined: Tue Apr 24, 2007 12:24 pm

Postby spideyfly » Fri Aug 10, 2007 7:29 pm

Hi CoBB,

Thanks! I didn't think of this method before...I'll test it out.

Cheers
spideyfly
New User
 
Posts: 18
Joined: Sat May 26, 2007 10:15 am

Postby spideyfly » Sat Aug 11, 2007 9:56 pm

Hi, when I use nxt_send_file it still seems to want the NXT to be in reset mode. Was this the send_file function from libnxt you had in mind?


// Send the C program
NXT_HANDLE_ERR(nxt_send_file(nxt, 0x202000, buf, (int) sizeof(buf)), nxt, "Error Sending file");


I keep getting this error..."NXT USB interface is already claimed by another program"...if I try using nxt_send_str(nxt, buf) I get a segmentation fault. :roll:

ps. 0x202000 is the load location in RAM...do you know of any documents showing the different memory positions used?

Cheers
spideyfly
New User
 
Posts: 18
Joined: Sat May 26, 2007 10:15 am

Postby spideyfly » Mon Aug 13, 2007 4:22 am

Hi CoBB

I modified libnxt's lowlevel.c to load without having to reset. Has something to do with the nxt_open() and nxt_open0() doing checks for reset mode. Now when I execute your code snippet it works fine.

Next step: figure out how to get my program to access this bytecode data (it's expecting files...so I've done a few accessor methods). Hope it works soon.

Cheers
spideyfly
New User
 
Posts: 18
Joined: Sat May 26, 2007 10:15 am

Postby spideyfly » Wed Nov 07, 2007 4:14 pm

Small update:

I haven't gotten this to work successfully, and since I'm running out of time I decided to do something a bit different as a project...decisions decisions. If anyone out there finds out about a working Haskell NXT VM that runs on the brick...let me know :)

...Cheers.
spideyfly
New User
 
Posts: 18
Joined: Sat May 26, 2007 10:15 am

Postby CoBB » Fri Nov 09, 2007 10:26 pm

Not on the brick itself, but we are actually working on a Bluetooth remote controller driven by Yampa code, and it looks promising. We made a firmware that contains the port of the motor regulator code and is capable of regularly sending out sensor and tacho readings over the air after being told about the sensor and motor configuration.
User avatar
CoBB
Novice
 
Posts: 73
Joined: Tue Apr 24, 2007 12:24 pm


Return to NXJ Projects

Who is online

Users browsing this forum: No registered users and 0 guests

more stuff