BSP Interface (iface)

The BSP Interface (iface) is a platform abstraction layer. Its purpose is to decouple the application examples and Cores BSP so that they can run on any hardware. The figure below illustrates that there is no direct link between the Application Layer and the BSP. Applications must pass through the BSP interface layer to gain access to the BSP functions.

../../_images/bsp_interface.png

Figure 54: Position of the BSP Interface layer in the system

With the BSP Interface, applications interact with systems and not individual peripheral functions. Thus, the function names are action oriented.

For example, a function such as iface_tx_conn_status is used to communicate connection status. The function could toggle a LED in one BSP or activate a buzzer in another BSP. The peripheral action is not called directly. With this approach, the application layer can be smaller, better organized, and more portable.

The BSP interface layer is segmented into four main components:

  • Application specifics

  • Audio Core

  • Pairing module

  • Wireless Core

Note

Every BSP interface function starts with the prefix iface_ regardless of the component.

Listing 4 BSP interface location within the SDK.
sdk_spark_vx.y.z/
└───bsp/
    ├───hardware/
    └───interface/
        ├───app/
        ├───audio_core/
        ├───pairing/
        └───wireless_core/

Each component provides an <.h> file with function prototypes. Every function prototype will need to be populated with new ported elements.

To help with the porting, users are encouraged to look at the SPARK SDK structure, where each element is implemented for the SPARK EVK1.4 hardware. Ported elements will result in a similar structure. The new structure will make it possible to build the SDK for a new hardware variant.

Tip

We highly recommend users to copy the EVK implementation files, rename and edit them for their own hardware BSP.

  • App Specifics

    There is one interface per application example in the SDK. They regroup all specific functionalities that use the underlying hardware BSP functions. Depending on the application, functions could vary, most common are the following:

    • Common drivers initialization: GPIO, clock, DMA, SPI, etc.

    • Audio peripherals initialization: SAI and onboard audio codec.

    • LED and button handling for transmission activities, volume handling or pairing commands.

  • Audio Core

    This interface contains functions configuring the Audio Core endpoints. It maps the audio_endpoint_interface_t callback structure with the BSP implementation.

    • Audio Codec Producer

    • Audio Codec Consumer

    The endpoint uses the I2S peripheral since the EVK board has an onboard I2S hardware codec. User implementation could vary depending on the type of endpoint the user hardware needs.

  • Pairing Module

    The Pairing Module is used to automate address assignment, a necessary function when establishing a communication link between two transceivers.

    Implementation details can be found in the Pairing Basic and Pairing Gaming Hub application examples.

  • Wireless Core Interface

    This interface contains functions that configure the Wireless Core. It maps the swc_hal_t callback structure with the BSP implementation. It is important for the user BSP to implement these functions with respect to the callback structure interface. See the Wireless Core Porting Article for details of these functions.

Adding a New BSP

The ported BSP can co-exist alongside existing ones. The file structure shown below shows what needs to be added to run the Audio 4-Channel application example on a ported BSP.

Listing 5 New files or folders are displayed with the marker ** *_user_bsp **
sdk_spark_vx.y.z/
└───bsp/
    ├───hardware/
    │   ├───evk/
    |   └─── **user_bsp/**
    └───interface/
        ├───wireless_core/
        |   ├───iface_wireless.h
        |   ├───iface_wireless_evk.c
        |   └─── **iface_wireless_user_bsp.c**
        ├───audio_core/
        |   ├───iface_audio.h
        |   ├───iface_audio_evk.c
        |   └─── **iface_audio_user_bsp.c**
        └───app/
            └───audio_4-channel/
                ├───iface_audio_4-channel.h
                ├───iface_audio_4-channel_evk.c
                └─── **iface_audio_4-channel_user_bsp.c**

The procedure is as follows:

  1. Add the new BSP drivers in the sdk_spark_vx.y.z/bsp/hardware folder.

  2. Make a copy of the EVK1.4 interface files for the cores and applications, then rename them with a new suffix matching the new BSP name:

    • wireless_core/iface_wireless_evk.c -> wireless_core/iface_wireless_{user_bsp}.c

    • audio_core/iface_audio_evk.c -> audio_core/iface_audio_{user_bsp}.c

    • app/{app_name}/iface_{app_name}_evk.c -> app/{app_name}/iface_{app_name}_{user_bsp}.c

  3. Modify the function implementations with the new hardware BSP functions.

Listing 6 Example of implementation of an EVK1.4 interface function.
void iface_audio_dma_complete_callbacks(void(*tx_callback)(void), void(*rx_callback)(void))
{
    evk_audio_set_sai_tx_dma_cplt_callback((irq_callback)tx_callback);
    evk_audio_set_sai_rx_dma_cplt_callback((irq_callback)rx_callback);
}
Listing 7 Example of an implementation of the user hardware BSP interface function.
void iface_audio_dma_complete_callbacks(void(*tx_callback)(void), void(*rx_callback)(void))
{
    user_bsp_set_sai_tx_dma_cplt_callback((irq_callback)tx_callback);
    user_bsp_set_sai_rx_dma_cplt_callback((irq_callback)rx_callback);
}