Search This Blog

Sunday, February 13, 2011

Bootloader -- Again

    Quick recap of what's been going on.  Ordered a bunch of new stuff from Sparkfun with the fabulous gift certificate from my in-laws.  Yes, I am one of the few lucky ones who has outstanding in-laws.  One of the little gems I ordered was a Pic 18F2455.  This is a whole new ballgame in my world of microcontrollers.  I'll go on a rant about it later( like very little bank switching!!!! ya-hoo! ).  The big game changer for me is that my bootloader will not port easily.  I was going to just add on to my existing Python bootloader, but I decided to inflict some more pain on myself.  I decided I would bite the bullet and do it in Java.
  
    Ok. What could be so hard about that?  First, start with the fact that the standard Java SDK has no support for serial communication.  Luckily ( now that serial ports can't be found on computers ), they have added a serial and parallel library that actually works ( and is now, as of version 3.0, pretty portable ).  The javax.comm package was pretty straightforward to install.  I downloaded the version 3.0 package for linux.  I put the 2 .so libs in /usr/lib and made them executable with chmod a+x.  I put the comm.jar into my java libs dir along with the javax.comm.properties file.  I also installed it in my maven repo.  In my Eclipse project, I added the comm dependency to maven and put a copy of prop file in src/main/resources.  When I make the final jar executable, I'll add the comm.jar and prop file in the classpath in the Manifest.

    Now to solve the problem of doing this on my laptop with no serial ports.  I got a serial-USB converter and got it working with Python.  To do that, I had to set the sticky bit on my /usr/bin/python2.6 executable.  I've never been happy with that idea.  The other night, I started developing apps for Android on my HTC Evo.  To get that working, I had to learn about udev in Linux.  I got my phone connected and gave my user, tom, permissions with this udev rule in /etc/udev/rules.d/51-android.rules:

SUBSYSTEM=="usb", SYSFS{idVendor}=="0bb4", MODE="0666"
SUBSYSTEM=="usb", SYSFS{idVendor}=="0bb4", OWNER="tom" GROUP="users"

For the USB-serial conveter, I created a rule for /etc/udev/rules.d/51-rs232.rules:
KERNEL=="ttyUSB*", ATTRS{idVendor}=="067b", MODE:="0666", SYMLINK+="ttyPIC"
KERNEL=="ttyUSB*", ATTRS{idVendor}=="067b", OWNER:="tom" GROUP:="users"

Now, any time I plug in the converter, no matter what ttyUSB name it gets, a symlink is created for ttyPIC and tom is given read and write permission to it.  Sweet.

    I tested all of this with my version of a null cable feeding back on itself.  I tried with old Python code and a test Java file.  All works.  On to the next hurdle.

    Java developers rarely have to think about lowly, menial tasks like byte operations.  In this case, it is the mainstay of the program.  The bootloader has to do a lot of conversion of hex represented strings ( sometimes doubled ) to integers.  It then needs to convert them to bytes for transmission over the serial line.  Enter the problems.  Java only offers a signed byte ( -128 to +127 ).  The end binary result is okay, but trying to print stuff for debug can be a real picnic.  I ended up with a lot of routines like this:

        /*
*  take a string representation of a data line from an Intel hex file
*  and convert it.  First, we get each byte( 2 characters from the string ).
*  Then we convert those from hex strings to integers and cast as a byte.
*/
public byte[] makePacket( String data )
{
// first, take 2 chars at a time and make bytes
System.out.println( "Start with: " + data );
int length = data.length()/2;
byte[] bites = new byte[length];
int counter = 0;
for(int i=0; i
String val = data.substring(i,i+2);
byte dataByte = (byte) (0x000000FF & (Integer.parseInt( val, 16 ) ) );
bites[counter++] = dataByte;
}
return bites;
}

    I worked out a lot of the basics tonight.  The next little challenge is the fact that the 18F2455 reads in single bytes, writes in blocks of aligned 32 bytes and erases in aligned blocks of 64.  Unfortunately, the gpasm compiler gives line of randomly long bytes ( up to 127 potentially ) and the addresses can start at any position.  Also, I now need to be aware of data type 04 lines.  These set the upper byte of the program counter address.  I'll write more about this next.  That's all for now.