The original V1 API required single buffers for all update and load
operations. This proved unduly restrictive, especially when installing
a new code image obtained over a network, because there would be no
guarantee that a single buffer of the required size could be
dynamically allocated when required. Hence the API was extended for V2
with vector functions, allowing the code and data to be spread over
multiple buffers, and with transaction functions, allowing new code
images to be installed a piece at a time.
Vector Functions
The three vector functions rbl_update_codeV,
rbl_update_dataV and
rbl_load_dataV work in terms of a series of
buffers rather than a single buffer. For example
rbl_load_data is equivalent to:
Obviously the vector functions become rather more useful for counts
greater than 1. The update functions still require that all of the new
images are resident in memory, but they no longer have to be in a
single contiguous buffer.
When updating some flash drivers may impose limitations on the sizes.
For example if the target hardware has a single 16-bit wide flash
device then the flash driver may require that all flash write
operations happen in multiples of 2 bytes, and the entries in the
sizesV array should satisfy this requirement.
Transaction Functions
The transaction functions begin/block/end allow RBL operations to be
performed in stages. For example rbl_load_dataV
is equivalent to:
cyg_bool
rbl_load_dataV(cyg_uint32 count, cyg_uint8* whereV[], cyg_uint32 sizesV[])
{
cyg_uint32 i;
if (! rbl_load_data_begin()) {
return false;
}
for (i = 0; i < count; i++) {
if (! rbl_load_data_block(whereV[i], sizesV[i])) {
return false;
}
}
return rbl_load_data_end();
}
The begin function must be called at the start of a function. At any
one time there can be only one code update, one data update, and one
data load in progress, and the begin function will block if another
thread is performing a conflicting RBL operation. Once the transaction
is started the application can perform one or more block operations,
and the transaction should normally be committed with an end function
call. For an update the begin function will erase the appropriate
flash blocks, the block function will write data to the flash, and the
end function will write trailer data containing size, checksum and
sequence number. At that point the image becomes the new primary code
or data RBL block.
As an additional restriction, rbl_update_data_end
will block if some other thread is currently loading data. This avoids
confusion since otherwise that thread would end up loading data that
is no longer primary, and it also avoids problems if another update
operation is started immediately.
Unlike the simple or vector update functions, the transaction
functions do not require that all of the new image is present in
memory at the same time. Instead it is possible to begin a
transaction, fetch the first part of the image over the network and
install that, fetch the next part, and so on. If the application is
unable to complete an update, for example because the network
connection is lost, then there should be a call to the abort function
instead of to the end function. When a transaction is aborted no
trailer gets written to flash so the new image remains invalid and the
old image stays as the primary.
As with the vector operations the flash driver may impose limitations
on the size arguments to rbl_update_code_block
and rbl_update_block. For example if the target
hardware uses a 16-bit wide flash chip then the size argument may have
to be a multiple of two bytes.
Error Conditions
All of the RBL functions return a simple boolean to indicate failure.
In reality failures are unlikely, but can be caused by the following:
The currently installed RedBoot was built without RBL functionality so
there is no code in the system to keep track of RBL images and install
new ones.
RedBoot uses a different version of the RBL protocol, for example V1
when the application has been built with V2.
The RedBoot RBL code was unable to initialize the system. This can
happen if the actual hardware does not match the RedBoot
configuration, for example if the flash chips actually present are
smaller than expected and cannot hold all the code and data blocks
specified by the CYGDAT_RBL_RESERVED_FLASH_BLOCKS,
CYGNUM_RBL_CODE_BLOCKS and
CYGNUM_RBL_DATA_BLOCKS configuration options.
An attempt is made to load or update data when RedBoot has been
configured with zero RBL data blocks,
An attempt is made to load more data than is actually present in the
current data image, or to install a new image that does not fit in the
number of configured flash blocks.
An unexpected error occurs inside the flash driver, for example an
attempt to erase a flash block fails.
For the transaction functions, if an error occurs then the transaction
is automatically aborted. There is no need for the application to
call rbl_update_code_abort or
rbl_update_data_abort explicitly, or to end a
load operation.