Fast Programming the Flash Memory of the MV162-532 / MV162-PA344E (Petra Board)

by Ralph Lange, BESSY
based on work by Till Straumann, PTB Berlin


Abstract

This document explains

Introduction

Did you ever have to program a bigger number of flash memories with the VxWorks bootrom code? Quite annoying, isn't it? Most people boot new cards with the firmware monitor/debugger in ROM, upload the flash image from a host to RAM using a serial line and finally program the flash memory.

The basic idea here is to avoid the time consuming (~6min. per card) download and use the ethernet or the VME bus instead of the serial line. The necessary steps are very easy to perform - the procedure described here is maybe even simpler than the traditional method.

If you need to program a single card (which may serve as a template to make multiple copies), you may use 162Bug firmware commands to set up the network interface of the card and to download bootrom code from a tftp server. This saves you about 6 min. downloading time and many hours of messing around with serial cabling, port and communication software setup.

If you need to have many copies of the same bootrom image, you may of course apply the ether net method to each and every card. However, there is an even more comfortable way (typing in IP addresses and filename/path info over and over again is also annoying) to obtain the copies using the VME bus. You just have to do some setup on the card containing the template image in its flash memory (this card will be called the "master" throughout this document). Programming the "slaves" (there may be plugged as many `programmees' into the VME bus crate as it can hold) comes down to attaching a terminal to each console port and issuing the PFLASH command.


Downloading a Bootrom Image Using the Ethernet Interface

Prerequisites

The bootrom image must reside on a TFTP server and be accessible by the mv162 card's network interface (i.e. physical network connection, routing, access privileges etc. must be set up correctly). Note that the bootrom image format is binary and not identical with the ascii S-Record file that is downloaded using the traditional method / serial port. The image we are talking about here is the compressed binary image (make target `bootrom'). The S-Record file is a special ASCII encoded version of the compressed binary image file, hence `bootrom' is automatically created if the make target `bootrom.hex' is made. All you have to do is copy it to the TFTP server file system.

You need to know the IP address of the tftp server as well as the absolute filename path of the bootrom image on the server. You also need the IP address of the board (which, for the moment may be any unused IP address; it is only needed during the downloading process). Furthermore you have to extract some `vector information' from the S-Record file.

Vector information

There is an important difference between the S-Record file and the compressed binary image however: When generating the S-Record `hex' file, vector information for the stack pointer (SP) and the program counter (PC) is prepended to the code section by the program that does the binary to S-Record conversion. Hence, we have to manually provide this information. Both (4-byte) values can be obtained by inspecting the first line of the S-Record file (remember: it is ascii), which looks something like this:
S10B000000020000FF8000086B
Strip the last (checksum) byte (a hex byte consists of two characters) and everything before the 9th byte counting from the end and you get the SP followed by PC; in our case
00020000FF800008
i.e. the stack pointer value is 0x20000, the PC 0xff800008. You will need this information (which is very unlikely to ever change) later.

Downloading the Image

Remove jumper J22 (pins 9/10) on the MV162-532 board or set S4.5 to OFF on the Petra board in order to boot the 162Bug firmware and plug it into the leftmost slot of the crate. Connect the board to the ether net, a terminal to its console port and power up the crate. You should now be able to talk to the 162Bug firmware.

Verify / Start the Clock

IMPORTANT NOTE: Make sure that the clock is running; the ether net driver needs it to run.
162-Bug> TIME
THU DEC 17 17:04:02.00 1998
If the clock is not running, you have to start it by setting the current time using the SET command. Type HE SET to get primitive command usage information.

Initialize the Network Interface

Use the 'NIOT' command to setup the network interface. You have to step through a configuration screen, but for most settings (except the IP addresses of the server, the client (the board itself) and maybe the subnet mask and the gateway IP address) the defaults are fine and you just should accept them by hitting the <Return> key. For our example, we assume the TFTP servers IP address to be 193.149.12.137 and we will use 193.149.12.204 for our board. Of course you have to substitute these values for your own. Note that you may have to change the subnet mask and / or the gateway information, too.
162-Bug> NIOT
Controller LUN =00?
Device LUN     =00?
Node Control Memory Address =FFE10000?
Client IP Address      =0.0.0.0? 193.149.12.204
Server IP Address      =0.0.0.0? 193.149.12.137
Subnet IP Address Mask =255.255.255.0?
Broadcast IP Address   =255.255.255.255?
Gateway IP Address     =0.0.0.0?
Boot File Name ("NULL" for None)     =?
Argument File Name ("NULL" for None) =?
Boot File Load Address         =001F0000?
Boot File Execution Address    =001F0000?
Boot File Execution Delay      =00000000?
Boot File Length               =00000000?
Boot File Byte Offset          =00000000?
BOOTP/RARP Request Retry       =00?
TFTP/ARP Request Retry         =00?
Trace Character Buffer Address =00000000?
BOOTP/RARP Request Control: Always/When-Needed (A/W)=W?
BOOTP/RARP Reply Update Control: Yes/No (Y/N)       =Y?

Update Non-Volatile RAM (Y/N)? N

Note that the only things we supplied were the IP addresses and the `N' answer to the question if the NVRAM should be updated. Maybe it's a good idea that the board does not remember these things (who knows if they still apply when you do this for the next time).

Loading the Bootrom Image

Everything is now ready to load the bootrom image. This is done by the 162Bug command 'NIOP' (NOTE: if the clock is not running, this command will fail leaving you with a nasty numerical error code that gives you no hint about the reason being the clock). The only thing you have to supply is the absolute file path name on the server and an address in RAM where you want the file to be stored.
Let's say we want to have the image loaded at the traditional address 0x100000, from where it will later be written to the flash ROM. Now remember that vector information mentioned before. The traditional S-Record file already contained the two 4-byte vectors, which is not the case for the binary image and therefore we must hack them in by hand. The vectors are located at the beginning of the memory area and this means that we have to reserve 2*4=8 bytes for the vectors and hence start loading at 0x100008. Of course, the server at your site may export the image using a different path/filename:
162-Bug> NIOP
Controller LUN =00?
Device LUN     =00?
Get/Put        =G?
File Name      =? /opt/tftpdir/IOC/vxBoot/5.2/bootrom.bin.mv162-std
Memory Address =0000E000? 100008
Length         =00000000?
Byte Offset    =00000000?

Bytes Received =&144644, Bytes Loaded =&144644
Bytes/Second   =&72322, Elapsed Time =2 Second(s)

It takes a couple of seconds for the file to be transmitted and the statistics to be printed.

Inserting Vector Information

The last thing left to do is prepending the image, now in RAM, with the vector information. We will use the SP and PC values from the example above and it is very likely that the same values apply for you, too. The vectors can be written using the 162Bug `MM' command (the `L' flag indicates that memory is to be written in units of long words). Note that you leave the `MM' command by entering a `.' (period) followed by <CR>:
 
162-Bug> MM 100000 ;L
00100000 08562C4F? 20000
00100004 2F2E0008? FF800008
00100008 610000A2? .
Finally, the image is written from RAM to the flash ROM.
162-Bug> PFLASH 100000 13ffff ffa00000
Source Starting/Ending Addresses      =00100000/0013FFFF
Destination Starting/Ending Addresses =FFA00000/FFA3FFFF
Number of Effective Bytes             =00040000 (&262144)

Program FLASH Memory (Y/N)? y
Erasing Block Number     =00 ($FFA00000)
Erasing Block Number     =01 ($FFA10000)
Erasing Block Number     =02 ($FFA20000)
Erasing Block Number     =03 ($FFA30000)
Programming Block Number =00 ($FFA00000)
Programming Block Number =01 ($FFA10000)
Programming Block Number =02 ($FFA20000)
Programming Block Number =03 ($FFA30000)
FLASH Memory Programming Complete

Congratulations, you're done. Remove power, re-install jumper J22 (or switch S4.5 back to ON) and you are ready to boot vxWorks. Note that you may have to provide appropriate boot parameters during the boot process.
If you want to program multiple boards, you already should remove J22 (pins 9/10) as well as jumper J1 from all the slave boards (the master being the one just programmed; removing J1 makes the other boards VME bus slaves) and plug them into the crate before applying power and trying to boot vxWorks. In case everything worked fine, as soon as vxWorks is up running, you may continue programming the slaves. Of course, you could program the slaves applying the ether net method over and over again, but using the VME bus is even easier.


Making Multiple Copies of a Bootrom Using the VME Bus

The first thing you need is a card which contains the code you want to copy in its flash memory (this card will be called "master"). If you don't have a master yet, just choose one card to be the master and proceed; you will have to use the ether net procedure to program its flash before copying it.

Impatient readers continue here for quick instructions.

Preparing Steps

On all cards that you want to get a copy of the master's flash, remove the jumper J1 making these cards VME bus slaves. On the slaves, remove also J22 (pins 9/10) in order to boot the 162Bug firmware from ROM. If your master is not yet programmed, you have to remove J22 (pins 9/10) on the master, too. Note that you don't have to change any jumper settings on your master, if it already contains the valid flash memory code.
Next, you install as many slaves into the crate containing the master as there are free slots and as your power supply can feed. Maybe the master should be plugged into the leftmost slot of the crate.

Note: It's a good idea to insert the slaves into slots adjacent to the master. Older backplanes are known to cause problems if there are empty slots between the master and any slave.

Setting Up the Master

On the master, the VMEchip2 must be set up correctly in order to map the address range of the flash memory on the local bus to a free VME bus address range. This requires some registers in the VMEchip2 to be configured.
Addresses on the local bus can be made available to the VME bus in chunks of 64K, aligned to 64K boundaries. There is a 32bit register at local bus address 0xfff40000 (VME slave #1), which assigns the upper 16 bits of the starting (bits 0..15 of *0xfff40000) and ending (bits 16..31 of *0xfff40000) addresses of an address range on the VME bus. If this register contains e.g. 0x02ff0200, this means that the VMEchip2 will respond to the address range 0x02000000 .. 0x02ffffff on the VME bus.

The other register of importance is available at 0xfff40008 and contains the upper 16 bits of the slave #1 translation address (bits 16..31 of *0xfff40008) and the translation select ( bits 0..15 of *0xfff40008).
The former specifies the (higher two bytes) of the starting address on the local bus which is mapped to the VME bus address range as allocated by *0xfff40000. The translation select is a bit mask, that is used to define which part of the translation address is valid. You can think of the local address to be generated in two steps: Given a VME bus address in the selected range, the higher bits which are selected by the translation select are masked out and replaced by the corresponding bits of the translation address, the lower bits are "wired through".

Now let's look at an example. We assume the two registers to contain the following values:

    *0xfff40000: 0x02ff0200
    *0xfff40008: 0xff80fffc
This maps the address range starting at 0xff800000 on the local bus to 0x02000000 .. 0x02ffffff on the VME bus. Now watch the effect of the translation select bits: accessing VME address 0x0203ffff maps to 0xff83ffff on the local bus. VME bus address 0x02040000 however wraps around to 0xff800000 on the local bus.

Setting Up an Existing Master Under VxWorks

According to the 'mv162' on line man page, when booting VxWorks for processor no. 0 (the default) an appropriate address range on the VME bus is already allocated and the onboard DRAM is mapped there.
at the VxWorks shell command line. The shell will output the contents of the start/end register, which should look something like:

Setting Up a New Master Under 162Bug

Programming the Slaves

For all slaves repeat the following steps:

Cleaning up

Remove power, reinstall all the jumpers that were removed in the first step, enjoy :-) 

Synopsis / Instructions for the Impatient

The different steps described above are summarized here assuming a default setup.  It can be seen that using the VME bus is an elegant, straightforward and fast way to copy the flash memory contents.

Prerequisites

You need a "master board", i.e. a card which is already programmed with the desired bootrom code. On all cards that need to be programmed, remove the jumpers J1, J22 (pin 9/10) and install them into the crate containing the master. There should be no empty slots between the master and any slave - older backplanes are known to cause problems if this is ignored. Boot VxWorks on the master and log in.

Setting up the master

Writing the slaves

On all slaves repeat the following steps:

When you are done

Switch power off, remove the slave boards and reinstall the jumpers previously removed. 

APPENDIX

Terminology

* The asterisk denotes the standard C-style dereferencing operator; e.g. *0xffff0000 denotes the 32 bit word at address 0xffff0000. All addresses are implicitly assumed to be '(unsigned long *)'
-> VxWorks shell prompt. This is output by the shell and not part of a command to be entered.
162-Bug> 162Bug firmware prompt. The prompt is output by the monitor and not part of  a command to be entered.

Checksum routine

The following routine implements (hopefully) the same checksum algorithm as the 162Bug firmware. It can be used to compute a 16bit checksum under VxWorks which has to be compared against a checksum calculated by 162Bug's 'cs' command (make sure 'cs' calculates the 16bit checksum - there are also options for 8 or 32 bit checksums not supported by the 'chksum()' routine below.

'chksum()' must be compiled and loaded to VxWorks. It is called by software or from the VxWorks shell command line. The syntax is: 'chksum(<start address>, <end address>)'
 

/*
 * calculate mod 0x10000 checksum
 * of shorts from start to end.
 */

unsigned short
chksum(unsigned short *start, unsigned short *end)
{
  unsigned short sum=0;

  while (start<=end) {
    if ( *start > ((unsigned short)~sum) ) sum++;
    sum+=*start++;
  }

  return sum;
}

Literature