The first step to an efficient network reprogramming is the understanding of the current implementation of network reprogramming.
A TinyOS application is stored as an SREC file after it is compiled. The SREC file is a text representation of the binary program code and its structure is like this:

Each line of an SREC file corresponds to any of start record, data record or end record. A recod has the following format:
S<type> <length> <address> <data> <checksum>
Description of fields:
|
Field |
Internal Rep. |
Description |
|
S<type> |
m_srec[][0] |
type is one of 0, 1 or 9 and takes 1 character. 0 is for
start record, 1 for data record and 9 for end record. |
|
<length> |
m_srec[][1] |
number of bytes in address, data and checksum. It is 1
byte number consisting of two characters. |
|
<address> |
m_srec[][2], m_srec[][3] |
2 byte number representing the address of the
record. |
|
<data> |
m_srec[][4] - m_srec[][END-1] |
The actual program code. |
|
<checksum> |
m_srec[][END] |
1 byte number checksum of the record. |
Example:
|
S0 |
1B |
0000 |
75 69 6C 64 2F 6D 69 63 61 32 64 6F 74 2F 6D 61 69 6E 2E 73 72 65 63 |
E3 |
|
S1 |
13 |
0000 |
0C 94 18 02 0C 94 35 02 0C 94 35 02 0C 94 35 02 |
AD |
|
S1 |
0B |
3FF8 |
00 7D 01 A4 78 95 3F |
4E |
|
S9 |
03 |
0000 |
|
FC |
The start record (the record with type 0) is skipped. Only data records and the end record need to be transmitted.
Internally, Xnp java module stores the data and end records in m_srec[][] and CRCsrec[]. Each row of m_srec[][] corresponds to each data record or end record. CRCsrec[] contains all the records in a single row and is used to calculate the checksum of the whole program image, aka program ID.
The program image read from SREC file is transferred to motes in packets. A record of SREC file, which is also called a capsule, is sent as one TinyOS packet. The format of the packet is as follows:
|
Position |
0:1 |
2 |
3 |
4 |
5 |
6 |
7:8 |
|
11:end |
|
Field name |
Dest |
AMID |
GID |
Len |
CMD |
SUBCMD |
PID |
CID |
Data |
AMID: set to 47
CMD: type of command (e.g., download, query and etc)
PID: checksum for program code. Used for validation
CID: sequence number for capsule.
Once a mote receives program code capsules, it stores the capsules in the external flash memory. The data to and from the external flash memory is read or written in 16-byte lines. Since a capsule requires 25 bytes for 16-byte data, a capsule takes 2 lines in the external flash.

The following is the structure of the buffer (ELBuff) for EEPROM write:
|
0:1 |
2:3 |
4 |
5 |
6:7 |
8: 8+datalen-1 |
8 + datalen |
Remaining |
|
PID |
CID |
Srec type |
length |
Srec address |
Data |
checksum |
Fill |
In response to the reboot command packet (command ID: SYS_ISP_REQ), the Xnp module does some housekeeping jobs to run the boot loader. The boot loader resides in the boot flash section and has the privilege to write data bytes in the program memory. Xnp checks the program ID in the command packet and the program ID in the first record of program code stored in the external flash memory. If the two match, Xnp module calls the boot loader by passing the start address of the external flash (wEEProgStart) and the program ID (wProgramID) in registers.
Xnp network reprogramming module is written as a big state machine and is not easy to follow the flow in a straightforward way. This document illustrates the key points of Xnp module for better understanding of the program.
In response to the arrival of a message, the receive message event handler sets the next state for the state machine.
if( (msgptr->addr
== TOS_BCAST_ADDR) )
{
switch (cCommand) //was [4]
{
case CMD_RST: //REBOOT
xnp_reboot();
break;
case
CMD_START_DOWNLOAD: //Header info for a code downloaf
cNextState
= SYS_DL_START;
break;
case CMD_DOWNLOADING:
if(sSYSMState==SYSM_DOWNLOAD)
cNextState = SYS_DL_SRECWRITE;
else if (sSYSMState == SYSM_UPDATE)
cNextState
= SYS_UP_SRECWRITE;
else
cNextState
= SYS_ACK;
break;
case CMD_DOWNLOAD_COMPLETE:
cNextState
= SYS_DL_END;
break;
case CMD_ISP_EXEC:
cNextState
= SYS_ISP_REQ;
break;
case CMD_GET_CIDMISSING:
cNextState
= SYS_REQ_CIDMISSING;
break;
default:
cNextState
= SYS_ACK;
break;
//invalid command
}//switch command
sSYSState
= cNextState;
post
NPX_STATEMACHINE(); //try again
The state machine consists of a number of states. These are the states used in Xnp module:
case
SYS_REQ_CIDMISSING: //get control back
case
SYS_GET_CIDMISSING:
case
SYS_DL_START:
case
SYS_DL_START1: //get system into clean known state
case
SYS_DL_START2: //
case
SYS_DL_SRECWRITE: //write SREC in DOWNLOAD Mode
case
SYS_UP_SRECWRITE: //write SREC in UPDATE Mode
case
SYS_EEFLASH_WRITE:
case
SYS_EEFLASH_WRITEDONE:
case
SYS_DL_END:
case
SYS_DL_END_SIGNAL:
case
SYS_DL_FAIL:
case
SYS_IDLE_RENTRY: //resume idle
conditions
case
SYS_IDLE:
case
SYS_ISP_REQ:
case
SYS_ISP_REQ1:
case
SYS_GETNEXTCID: //have read 1st half
of srec from FLASH
case
SYS_ACK: //send ack to network if required and then
go idle
case
SYS_GETDONE:
case
SYS_BEACON:
default:


task void NPX_STATEMACHINE() Download End


