Conditional execution and chaining

Multiple radio operations can be chained and the chains are executed according to a result from the execution phase. The parameters are specified as follows:

struct RF_Op {
    // ...
   RF_Op* pNextOp;          // Pointer to the next chained operation to run.
   struct {
      uint8_t rule:4;       // Condition for running next command: Rule for how to proceed.
      uint8_t nSkip:4;      // Parameter for skipping mode if the rule involves skipping.
                            // 0: repeat same command, 1: go to next, 2: skip next, ...
   } condition;
    // ...
};

The execution phase of a radio operation always ends with a result that can be either TRUE, FALSE or ABORT and is specific for every operation. This result is evaluated together with condition.rule of the radio operation. All available rules are listet in Table 3..

Table 3. Available condition rules. The identifiers can be found in <ti/devices/${DEVICE_FAMILY}/driverlib/rf_mailbox.h>. Identifiers marked with a (*) are only available for chained commands.
Number Identifier Description
0 COND_ALWAYS Always run next command (except in case of Abort).
1 COND_NEVER Never run next command.
2 COND_STOP_ON_FALSE Proceed with next command if this command finishes with result TRUE. Stop execution if FALSE.
3 COND_STOP_ON_TRUE Proceed with next command if this command finishes with result FALSE. Stop execution if TRUE.
4 COND_SKIP_ON_FALSE Proceed with next command if this command finishes with result TRUE. Go to skipping mode if FALSE.
5 COND_SKIP_ON_TRUE Go to skipping mode if this command finishes with result TRUE. Proceed with next command if FALSE.

Based on the evaluation outcome, another command may be started which is specified by pNextOp and condition.nSkip. The latter parameter allows for instance, to re-run the command when set to 0 or to go to the next command when set to 1. It is even possible to jump to a command further in the chain when greater than 1. In this case, the status of the skipped operation is set to SKIPPED.

@startuml
scale 0.8
:Evaluating entry;
if (result) then (TRUE/FALSE)
    :next := evaluate(command, result)]
    if (next) then (is set)
         :start(next)]
    else (NULL)
        :RF_EventLastCmdDone>
    endif
else (ABORT)
    :RF_EventLastCmdDone>
endif
:RF_EventCmdDone>
:Evaluating exit;
@enduml

Figure 14. SDL diagram of the Evaluating phase that was shown in Figure 13..

The generic part of the evaluating phase is illustrated in Figure 14.. The pseudo function evaluate(command, result) depends on the condition rule and skip count and returns a pointer to the next radio operation. It is specified in Listing 1. below. The start(next) pseudo function just brings the next operation into the state PENDING.

Listing 1. Pseudo code for the evaluate() function from Figure 14..
RF_Op* evaluate(RF_OP* cmd, bool result)
    RF_Op* next = NULL

    select (cmd.condition.rule)
        case COND_ALWAYS
            next = cmd.pNextOp

        case COND_NEVER
            next = NULL

        case COND_STOP_ON_FALSE
            if (result == false)
                next = NULL
            else
                next = cmd.pNextOp

        case COND_STOP_ON_TRUE
            if (result == true)
                next = NULL
            else
                next = cmd.pNextOp

        case COND_SKIP_ON_FALSE
            if (result == false)
                next = cmd
                for i = 0 to cmd.condition.nSkip do
                    next = cmd.pNextOp

            else
                next = cmd.pNextOp

        case COND_SKIP_ON_TRUE
            if (result == true)
                next = cmd
                for i = 0 to cmd.condition.nSkip do
                    next = cmd.pNextOp

            else
                next = cmd.pNextOp

    return next

For every finished command, a RF core interrupt is raised which results in a RF_EventCmdDone callback event from the RF driver. In addition, the RF_EventLastCmdDone event is only generated:

  • for single commands
  • for the the last command in a chain
  • when the execution result is ABORT.

This is illustrated in the below sequence chart Figure 15. for two chained operations op1 and op2. Only the first operation op1 is delivered to the RF driver using either RF_postCmd() or RF_runCmd(). The RF core then executes these operations and generates a callback event RF_EventCmdDone for both and RF_EventLastCmdDone only for the last operation op2.

@startuml
scale 0.8
hide footbox

participant Application as app
participant "RF Driver" as driver
participant "RF Core" as rf

activate app
app -> driver : RF_runCmd(op1);
activate driver
driver -> rf : start op1
activate rf
driver <-- rf

...op1 executes...

driver <- rf : IRQ_CMD_DONE
activate driver
driver --> rf
deactivate driver
app <- driver : callback(RF_EventCmdDone);
activate app
app --> driver
deactivate app

...op2 executes...

driver <- rf : IRQ_CMD_DONE\n| IRQ_LAST_CMD_DONE
activate driver
driver --> rf
deactivate rf
deactivate driver
app <- driver : callback(RF_EventCmdDone\n| RF_EventLastCmdDone);
activate app
app --> driver
deactivate app

app <-- driver
deactivate driver

@enduml

Figure 15. The callback events RF_EventCmdDone and RF_EventLastCmdDone for two chained RF operations op1 and op2.