This driver implements only non-beacon mode of operation. It supports following features:
The driver is a FSM. From API perspective it has 4 states. Most of those states contains sub-states in implementation.
receive() transmit() --------> --------> Sleep Receive Transmit <-------- | /|\<-------- sleep() | | receive() / transmitted() / busy_channel() | | energy_detection() | | energy_detected() \|/ | Energy detection
The driver is initialized in the Sleep state. The higher layer should call the receive() function to make the driver enter the Receive state and start radio operations.
In basic applications radio should be most time in a Receive state. In this state the radio receives incoming frames. Changing to any other state should be performed from Receive state.
When a frame is received in Receive state the driver notifies the higher layer by calling received() function. This function is called after reception of a broadcast frame or after sending an ACK to a unicast frame. In the promiscuous mode the higher layer is notified about all of the received frames. Even if the frame was not destined to the receiving node.
To transmit a frame the higher layer should call the transmit() function. If channel is busy the driver goes back to the Receive state and notifies the higher layer by calling the busy_channel() function. If a broadcast frame was transmitted the driver goes back to the Receive state and notifies the higher layer by calling the transmitted() function. If a unicast frame was transmitted and an ACK was received the driver goes back to the Receive state and notifies the higher layer by calling the transmitted() function. If a unicast frame was transmitted and there was no expected ACK received the higher layer shall call the receive() function after the ACK timeout to make the driver go back to the Receive state.
To perform an Energy Detection procedure the higher layer should call the energy_detection() function. When the procedure is completed the driver goes automatically back to the Receive state and notifies the higher layer with the energy_detected() function.
In this state the radio is in low power mode. It cannot transmit or receive any frame.
In this state the radio receives 802.15.4 frames. It filters out frames with invalid CRC, length, type, destination address. If the driver receives unicast frame destined to the receiving node it automatically transmits an ACK frame. According to 802.15.4 standard, an ACK frame should be delayed aTurnaroundTime (192 uS) after reception of the ACKed frame. To perform this delay the driver uses the TIFS timer in the radio peripheral. This timer requires 3 shorts to work correctly:
In this state the radio performs the CCA procedure. If channel is free the radio transmits requested frame. If an ACK was requested in the transmitted frame the driver automatically receives the ACK frame in this state. To prevent the TXIDLE peripheral state the driver uses 2 shorts in Transmit state:
In this state the radio performs the Energy Detection procedure. During this procedure the radio is busy and cannot change state to any other. The end of this procedure is notified to the higher layer by a function call.
State transitions in the FSM can be requested simultaneously by the higher layer and the IRQ handler. To prevent race conditions in the driver there is a mutex. The mutex is unlocked only in the Receive state (WaitingRxFrame substate). If there is requested state transition, the procedure shall lock the mutex before state is changed. If mutex cannot be locked, another procedure has locked it and is going to change the state. The mutex is unlocked when the driver enters Receive state.
A race condition could also occur during handle of a requests from the higher layer. Even if the receiver is stopped (TASK STOP) the END or DISABLED event can be raised for a few uS after triggering the task. To prevent interrupt of the higher layer request handler by IRQ handler, the higher layer request handlers are performend in critical sections. The critical sections are implemented as software interrupt requests with priority equal to the RADIO IRQ.