Low MAC Framework Callbacks

The Low MAC Framework interfaces to the MAC application in CPU Low via callback functions. The lower MAC application must implement functions and register these as callbacks. The Low MAC Framework then calls these application-supplied functions for specific MAC events at runtime.

The Low MAC Framework sets all callbacks to a null function by default. The lower MAC application must notify the framework of each callback it implements. Not all MAC applications will implement all callbacks.

The table below summarizes the callback functions supported by the Low MAC Framework.

Callback Setter
Wireless Rx wlan_mac_low_set_frame_rx_callback()
New Tx wlan_mac_low_set_handle_tx_pkt_buf_ready()
LOW_PARAM Update wlan_mac_low_set_ipc_low_param_callback()
MAC Time Update wlan_mac_low_set_mactime_change_callback()
Sample Rate Change wlan_mac_low_set_sample_rate_change_callback()
Beacon Configuration wlan_mac_low_set_beacon_txrx_config_callback()
Multicast Buffering Config wlan_mac_low_set_mcast_buffer_enable_callback()

Wireless Rx Callback

The Low MAC Framework polls the MAC Interface Core for new wireless receptions. When a new Rx event begins the Low MAC Framework runs basic sanity checks on the Rx parameters. If the new Rx passes these checks, the framework calls the application’s Rx callback to handle the new reception.

The application sets the Rx callback via wlan_mac_low_set_frame_rx_callback(). The callback function must have prototype:

/* Wireless Rx Callback
 *
 * Arguments
 *  rx_pkt_buf  - Index of the Rx packet buffer containing the newly received packet
 *  phy_details - Pointer to phy_rx_details struct containing PHY mode, MCS, and Length
 *
 * Returns
 *  u32 - Bit mask of flags indicating various results of the reception
*/
u32 frame_receive(u8 rx_pkt_buf, phy_rx_details_t* phy_details);

The application’s Rx callback is called once at the beginning of a new wireless reception. The callback is executed early in the Rx process, typically before the first MAC header bytes are received. The application can monitor the newly received bytes as the Rx PHY writes bytes to the Rx packet buffer. For example the DCF code uses this capability to monitor whether an incoming packet might require a response (CTS or ACK). When required the response packet can be prepared even as the wireless reception is ongoing. This pipelining enables fast Rx/Tx turnaround by minimizing the amount of processing required after the reception has finished.

New Tx Callback

When a new packet is ready for transmission CPU High sends a TX_PKT_BUF_READY message to CPU Low via the IPC mailbox (refer to Tx Packet Flow for details). The Low MAC Framework receives this IPC message, takes ownership of the corresponding packet buffer, then calls the MAC application’s Tx callback. The application is then responsible for preparing the packet, submitting it to the MAC Interface Core for transmission according to the MAC protocol’s rules for Tx timing.

The application sets the Rx callback via wlan_mac_low_set_handle_tx_pkt_buf_ready(). The callback function must have prototype:

/* New Tx Callback
 *
 * Arguments
 *  rx_pkt_buf  - Index of the Tx packet buffer containing the packet to transmit
 *
 * Returns
 *  int - Transmission result code
*/
int frame_transmit(u8 pkt_buf);

The framework does not require the application to transmit a new packet immediately. In the DCF, for example, the new Tx callback records the Tx packet buffer index for the new packet in a list then returns. Then in a different context the DCF manages the list of ready-to-transmit packets to select either unicast or multicast, as dictated by the current DCF MAC state.

There is a strict requirement that every TX_PKT_BUF_READY message from CPU High (i.e. execution of the New Tx Callback in CPU Low) results in a single TX_PKT_BUF_DONE message from CPU Low. The TX_PKT_BUF_DONE message can occur after an arbitrary delay and can be interleaved with other READY / DONE message pairs.

LOW_PARAM Update Callback

The wlan_exp Python framework implements a node.set_low_param(PARAM_ID, PARAM_VALS) method. This method provides a pipe for passing key/value pairs from the Python environemnt directly to CPU Low, bypassing any processing in CPU High.

LOW_PARAM IPC messages are first processed by the Low MAC Framework. If the framework does not recognize the LOW_PARAM ID value it passes the entire message to the application via the LOW_PARAM Update Callback. In this way the MAC application can implement custom LOW_PARAM values without any modifications to the Low MAC Framework or any code changes in CPU High.

The application’s LOW_PARAM Update Callback must have prototype:

/* LOW_PARAM Update Callback
 *
 * Arguments
 *  mode    - Always equal to IPC_REG_WRITE_MODE
 *  payload - Array of 32-bit integers, as provided by Python
 *             First integer (payload[0]) is LOW_PARAM_ID
 *             Array length is message-specific - Python code
 *              and application C code must agree on length
 *
 * Returns
 *  int - Callback must return 0
*/
int process_low_param(u8 mode, u32* payload);

This LOW_PARAM pipe is useful for sweeping low-level MAC and PHY parameters without implementing a dedicated IPC message for updating the parameter from the CPU High C code. For example, a new LOW_PARAM could modify the Rx PHY’s packet detection thresholds to measure the effect on sensitivity. The C This parameter could then be swept from a Python script without any C code changes in CPU High or in the Low MAC Framework.

The reference C code defines a number of LOW_PARAM IDs in wlan_mac_low.h - look for the #define LOW_PARAM_... macros. New LOW_PARAM IDs must be unique.

MAC Time Update Callback

The node’s MAC Time is maintained by the MAC Time Core in the FPGA. The MAC Time base can be changed at runtime by the MAC software. For example, the STA application sets the node’s MAC Time to the timestamp value from a received beacon, thereby maintaining synchronization with the AP’s MAC Time.

The MAC Time is always set by CPU Low. The High MAC Framework and application can require MAC Time changes via the IPC_MBOX_SET_MAC_TIME IPC message. When receiving the IPC_MBOX_SET_MAC_TIME message the Low MAC Framework first updates the MAC Time, then calls the application’s MAC Time Update Callback, in case the MAC application needs to adjust its own state in response to the MAC Time change.

The MAC Time Update Callback must have prototype:

/* LOW_PARAM Update Callback
 *
 * Arguments
 *  time_delta_usec - MAC Time change in microseconds.
 *                    Negative value indicates MAC Time was decremented.
*/
void handle_mactime_change(s64 time_delta_usec);

Sample Rate Change Callback

Some hardware platforms support multiple sampling rates. The actual sampling rate change is implemented in the Low MAC Framework. However when the sampling rate changes the MAC Application may need to update its timing parameters or other behaviors.

The Low MAC Framework calls the application’s Sample Rate Change Callback after changing the PHY sampling rate. The callback must have prototype:

/* LOW_PARAM Update Callback
 *
 * Arguments
 *  phy_samp_rate - New PHY sampling rate, as ENUM defined by hardware-specific code
*/
void handle_sample_rate_change(phy_samp_rate_t phy_samp_rate);

Beacon Configuration Callback

AP and IBSS nodes periodically transmit beacons to advertise network parameters, MAC/PHY capabilities, and to synchronize members of the wireless network. Both CPUs are involved in beacon transmissions:

  • CPU High: the High MAC application (i.e. AP, IBSS) dedicates a Tx packet buffer to a Beacon Template. This template is a complete 802.11 Beacon packet except for the TIMESTAMP field. CPU High informs CPU Low that the Beacon Template is ready with the IPC_MBOX_TXRX_BEACON_CONFIG message via the IPC mailbox.
  • CPU Low: once notified by CPU High that the Beacon Template is ready, the Low MAC application (i.e. DCF) transmits the beacon packet whenever required by the MAC protocol. For the default 802.11 DCF the lower MAC transmits beacons every 102.4 usec starting at MAC Time zero. CPU Low transmits the Beacon Template as-is, only modifying the TIMESTAMP field to reflect the MAC Time of the actual beacon waveform transmission. After each beacon transmission CPU Low sends CPU High a TX_BEACON_DONE IPC message.

Lower MAC applications which do not transmit beacons (i.e. NoMAC) ignore the IPC_MBOX_TXRX_BEACON_CONFIG message.

The Low MAC Framework passes the IPC_MBOX_TXRX_BEACON_CONFIG message directly to the lower MAC application via the Beacon Configuration Callback. The callback must have prototype:

/* Beacon Configuration Callback
 *
 * Arguments
 *  beacon_txrx_config - Beacon Tx/Rx options set by MAC application in CPU High
*/
void configure_beacon_txrx(beacon_txrx_config_t* beacon_txrx_config);

Multicast Buffering Config Callback

Some MAC applications and protocols require different handling for unicast and multicast transmissions. For example an AP hosing a network with power-saving STA nodes must buffer multicast packets until immediately after a beacon transmission. The change between buffering multicast to not buffering multicast requires coordination between CPU High and CPU Low.

CPU High sends the IPC_MBOX_MCAST_BUFFER_ENABLE IPC message to change the current multicast buffering mode. The framework passes this message directly to the lower MAC application via the Multicast Buffering Config Callback.

Lower MAC applications which do not implement multicast buffering (i.e. NoMAC) ignore the IPC_MBOX_MCAST_BUFFER_ENABLE message.

The callback must have prototype:

/* Beacon Configuration Callback
 *
 * Arguments
 *  enable - 0 to disable, 1 to enable multicast buffering
*/
void handle_mcast_buffer_enable(u32 enable);