Migration from µESB to nrf_esb

List of changes from µESB to nrf_esb

  • All functions, structs, enums and defines have been renamed from uesb_xxx to nrf_esb_xxx.
  • Events:
    • Events used to be triggered within radio interrupt context in µESB. This guaranteed that no additional radio activity would occur while the application treated the event. This would unfortunately block incoming packets. In the new nrf_esb implementation, events are triggered in software interrupt context after the radio interrupt is done. This allows packets to arrive while an event is being treated, but adds some complexity because the application can be interrupted to handle radio activity while handling an event.
    • Events in the µESB had no parameters and relayed on functions to get information about the cause of the event. As the nrf_esb is part of the SDK, the events have been changed to conform with the SDKs standard way of handling events. The event is now triggered with a struct containing data related to the event.
  • µESB used its own set of error codes. Since nrf_esb is part of the SDK most of these error codes has been removed in favor of using the equivalent errors from the softdevice headers.
  • nrf_esb only support the Enhanced ShockBurst protocol. ShockBurst has been removed from nrf_esb.
  • Addresses are now managed through a new API that better reflect the way addresses are handled in hardware, on air, and in nRF24L series devices.
    • Addresses can be set any time the module is idle without reinitializing it.
  • Various smaller changes:
    • Disabling nrf_esb is instant and will kill all ongoing radio communication. The application can wait for the state to become idle before calling disable to achieve the behavior of µESB, but in many cases it may be preferable to just stop the radio.
    • PID is now maintained separately per pipe, removing problems with packets being discarded as retransmits when communicating over several pipes simultaneously.
    • The 1Mbps BLE radio mode can be used for ESB. Useful for devices switching protocol between BLE and ESB.
    • The three write_payload functions has been combined to one and uses state and arguments to achieve the same.
    • The example applications have been completely rewritten.

Migration guide

This guide will go through the steps required to migrate an application from the µESB module available on GitHub to the nrf_esb module in the nRF5 SDK. The nrf_esb module is based on the µESB module, but some changes have been done to the API to improve the module and to make it fit the SDK. Because of similarities between them, porting from µESB to nrf_esb does not require a large structural change of the application.

Initialization and setting of radio parameters.

Initialization of the nrf_esb module is changed a lot from µESB. Many of the features that were previously located in the initialization struct have been moved to separate APIs. This mean that more calls are necessary to achieve the same result when initializing, but it also allow you to change many parameters without reinitializing.

In the config struct the app should set all fields in the same way as it did in µESB. Dynamic ack has been renamed to selective ack.

Set the base addresses and prefix through the three API calls:

nrf_esb_set_base_address_0().

nrf_esb_set_base_address_1().

nrf_esb_set_prefixes().

Also set the address length through the API call:

nrf_esb_set_address_length().

Enable pipes through the API call:

nrf_esb_enable_pipes().

Set the rf_channel through the API call:

nrf_esb_set_rf_channel().

Event handling

The changes to the event system are the ones that require the largest changes for the application. The events in µESB were very simple. They occured in radio interrupt context and all parameters where avaialble through API calls as necessary.

Events in nrf_esb have been changed to include as many parameters as possible in the event itself as a struct. This mean that the application must be altered to read these parameters from the struct instead of the old API calls.

//uesb_get_tx_attempts(&my_tx_attempts);
my_tx_attemps = p_evt->tx_attempts;

//uesb_get_clear_interrupts(&my_interrupt_flags);
//if (my_interrupt_flags & UESB_INT_RX_DR_MSK)
if (p_evt->evt_id == NRF_ESB_EVENT_RX_RECEIVED)

Events in nrf_esb are triggered in a software interrupt, allowing the radio to continue operating with higher priority than the events. This reduces the risk of losing packets because of event handling, but require more complex behaviour from the application. There might be more than one packet arriving between each event and packets may even arrive while treating the last event. This mean that for every received payload event, there can be anywhere from 0 to NRF_ESB_CORE_RX_FIFO_SIZE payloads in the FIFO.

nrf_esb_payload_t payload;
while(nrf_esb_read_rx_payload(&payload) == NRF_SUCCESS)
{
    my_rx_payload_handler(&payload);
}

Wait before disabling the radio

In µESB the disable function would wait for an idle state before disabling the radio. If the application depends on completing its radio actions before disabling, it will have to wait until the state is idle before calling disable. If the application does not depend on completing the current radio actions, disable can be called imminently and will be completed very fast.

while(!nrf_esb_is_idle())
{
    // Waiting.
}
nrf_esb_disable();

Writing payloads

In µESB there were three API calls for writing to the TX FIFO. One for packets with ack, one for packets without ack and one for packets for ack with payload. This API has been simplified in nrf_esb to only use one API call nrf_esb_write_payload(). When the module is in PRX mode all packets uploaded will be treated as packets for ack with payload. When the module is in PTX mode all packets will be uploaded with or without ack based on the value of the ack field in the payload struct.

To migrate an application from µESB to nrf_esb, replace all write_payload calls with nrf_esb_write_payload() and set the ack field in each payload.

In the listing below the migration is shown:

//uint32_t uesb_write_tx_payload(p_payload);
p_payload->noack = false;
nrf_esb_write_payload(p_payload);

//uint32_t uesb_write_tx_payload_noack(p_payload);
p_payload->noack = true;
nrf_esb_write_payload(p_payload);

//uint32_t uesb_write_ack_payload(p_payload);
nrf_esb_write_payload(p_payload);

Clearing interrupts

In nrf_esb, no manual clearing of interrupts is required. It is managed by the module itself.