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.
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
-
Connect a terminal to the console/serial port, switch on the power supply
and wait for the VxWorks shell prompt to come up (maybe you have to change
the boot parameters to avoid the evaluation of a startup script).
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.
-
Verify that the address range is big enough and write down the starting
address. Issue the command:
-> *0xfff40000
at the VxWorks shell command line. The shell will output the contents of
the start/end register, which should look something like:
some_garbage = 0xfff40000: value = 50266624 = 0x2ff0200
The VME starting address is 0x02000000, the ending address 0x02ffffff,
which obviously covers the address range of the flash.
If for some reason no address range is allocated, pick a free range
of VME addresses (not used by any other VME boards) and set up the start/end
register, e.g.:
-> *0xfff40000=0x02030200
Set up the translation address / translation select register.
Assuming the flash memory sitting at local bus address 0xff800000 (on the
master running VxWorks, the jumper J22 (9/10) is not removed) and
extends to 0xff83ffff, the appropriate setting is:
-> *0xfff40008=0xff80fffc
If you are paranoid, you may calculate a 16bit checksum using this little
routine
(which must be compiled and loaded to the master). The checksum can be
verified later after programming the slaves.
-> chksum(0xff800000,0xff83ffff)
Setting Up a New Master Under 162Bug
-
Connect a terminal to the console/serial port, switch on the power supply
and wait for the 162Bug monitor/debugger prompt. Upload the bootrom code
following the ethernet procedure and write
it to the flash memory.
-
Pick a free range of VME bus addresses, large enough to cover the flash
memory address space, e.g. 0x02000000 .. 0x0203ffff and set up the start/end
register of the VMEchip2 using standard 162Bug commands:
162-Bug> mw fff40000 02030200 ; L
Map the flash memory to the VME bus setting up the translation address
/ translation select register. If the flash covers local bus addresses
0xffa00000 .. 0xffa3ffff (remember that the jumper J22 (9/10) on the newly
programmed master is still removed), issue:
162-Bug> mw fff40008 ffa0fffc ; L
If you're paranoid, calculate the flash memory's 16bit checksum and write
it down:
162-Bug> cs ffa00000 ffa3ffff
Programming the Slaves
For all slaves repeat the following steps:
-
Connect a terminal to the console/serial port.
-
Write the flash memory (assuming you had set up the master to use VME starting
address 0x02000000):
162-Bug> pflash 02000000 0203ffff ffa00000
Source Starting/Ending
Addresses
=02000000/0203FFFF
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
The paranoids among you verify the checksum against the value obtained
on the master:
162-Bug> cs ffa00000 ffa3ffff
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
-
Read the location at 0xfff40000 using the VxWorks shell command
-> *0xfff40000
The read back value should be:
<some garbage> = 0xfff40000: value = 50266624 = 0x2ff0200
Set up the translation address/select register:
-> *0xfff40008 = 0xff80fffc
Writing the slaves
On all slaves repeat the following steps:
-
Connect a terminal to the console / serial port.
-
Write the flash memory using the 162Bug firmware:
162-Bug> pflash 0x02000000 0x0203ffff 0xffa00000
Source Starting/Ending Addresses
=02000000/0203FFFF
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
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
-
MVME162FX Embedded Controller Installation and Use (delivered with the
hardware; not very useful though).
-
VxWorks on line documentation (vxhelp), especially the 'mv162' manpage,
source code (as far as available), header files.
-
MVME162FX Embedded Controller Programmer's Reference Guide (not
delivered with the hardware, hence quite useful. At least it is available
on
line at a very, very, very low transmission rate :-(
-
Programming
the MV162 Flash Memory for VxWorks using the traditional / serial port
method.