Execution states and status codes¶
After delivering to the RF core, a radio operation passes several states. They are illustrated as a UML state chart in Figure 13. and explained in Table 1.. Each state performs several activities which are explained during the next sections.
Status | Description |
---|---|
IDLE | The command has not been posted to the RF core, yet. This is the default status. |
PENDING | The command is being parsed and the RF core waits for the start trigger to fire. |
ACTIVE | This state is very command-specific. The command executes until it terminates.
Some commands provide also end triggers for alternative termination.
Command execution produces a result, either of TRUE , FALSE or ABORT .
After the execution phase, both, the result value and the command condition
rule get evaluated.
Several command-specific callback events may be generated during the ACTIVE state. |
DONE* | A command-specific status code is written to status and a callback event is generated
for single commands or for the last command in a chain. |
ERROR* | Either parsing failed or command execution ended with an error. A command-specific error code is
written to status and a callback event is generated. |
SKIPPED | The command was skipped due to a skipping rule in a previous command.
command.status is set to SKIPPED . This applies only to commands in chains.
A callback is not performed. |
States marked with (*) do not exist as one explicit status code, but as
various command-specific variants. The code PROP_DONE_OK
, for instance, is
specific to proprietary commands.
Status codes are defined in
<ti/devices/${DEVICE_FAMILY}/driverlib/rf_mailbox.h>
for common radio
operations. Additional codes for proprietary commands are are defined in
<ti/devices/${DEVICE_FAMILY}/driverlib/rf_prop_mailbox.h>
.
The status is queried via the command’s status field that is available for every radio operation:
struct RF_Op {
// ...
uint16_t status; // An integer telling the status of the command. This value is
// updated by the RF core during operation and may be read by the
// system CPU at any time.
// ...
};
It is recommended to read the status only after command completion:
// Assuming that 'command' points to a valid radio operation and
// execution has completed. Volatile is needed because 'status'
// is written on another processor.
volatile RF_Op* command;
if (((volatile RF_Op*)command)->status == PROP_DONE_RXTIMEOUT) {
// ...
}
It is tempting to use the status member to synchronize to command execution, for instance, to wait until the command has actually started:
// Dangerous, don't do that!
while (((volatile RF_Op*)command)->status != ACTIVE) {}
However, this is strongly discouraged because the calling thread might get
interrupted while the command has already finished in the meantime. Hence, the
ACTIVE
state is never seen and the while
loop runs forever. Instead,
use RF driver events to synchronize to command execution, either via callbacks
or RF_pendCmd().
Whenever executing an RF operation, it is good practise to check the status code and test for possible error case. Depending whether it is a proprietary or a PHY-independent command, several various status codes apply. It is up to the application to take appropriate measures.
The following code snippet shows an example how to execute a TX operation and how to check the status:
#include <ti/devices/${DEVICE_FAMILY}/driverlib/rf_prop_mailbox.h>
// Execute the command
RF_EventMask result = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
if (result & RF_EventLastCmdDone)
{
// Ok. Expected case
}
else if (result & RF_EventCmdCancelled)
{
// Optional. Somebody cancelled the command with RF_cancelCmd().
}
// Now evaluate the status code of CMD_PROP_TX
// to see how the command finished
switch (((volatile RF_Op*)&RF_cmdPropTx)->status)
{
case PROP_DONE_OK:
// Success. Nothing to do
break;
case PROP_ERROR_NO_FS:
// Error case. Due to CMD_FS failing during power-up, CMD_PROP_TX
// could not succeed. The RF core is powered up and the synth is not running.
// One possible work-around is: Ignore it and power the RF core down
// manually. CMD_FS will be re-executed on the next RF core power-up.
RF_yield(rfHandle);
case PROP_DONE_ABORT:
case PROP_DONE_STOPPED:
// Command was aborted/stopped by RF_cancelCmd().
break;
case PROP_ERROR_PAR:
// Command was started with an illegal parameter.
break;
default:
// Unexpected status code observed.
// ...
break;
}