Porting Guidelines

This section describes the steps required to run a simple application on custom hardware and highlights important things to consider when porting to that hardware. SPARK transceivers can accommodate a wide range of applications, from low-duty cycle wireless sensor nodes to full quality audio streaming. Hence, the microcontroller requirements will vary.

Here is a list of hardware features that impact the speed of execution of a given SPARK enabled application:

  • CPU core: some CPU cores (e.g. Arm Cortex-M4) may be more or less efficient than others for a given task.

  • CPU clock speed: running a given CPU core at a higher clock speed will result in faster processing time which is sometimes required for higher performance applications.

  • MCU architecture: some MCUs have hardware accelerators, multiple cores, direct memory access (DMA) buses for efficient non-blocking data transfers and faster memory zones for code execution. For example, the STM32G473 MCU on the SPARK EVK board has CCM (Core-Coupled Memory) where critical code can be copied and executed from without any wait states leading to faster response and lower execution times.

  • Amount of memory: more memory means more room for code optimization (e.g. inline functions or unrolled loops are usually executed faster but take more space).

  • Effective SPI data throughput: SPARK transceivers use SPI for all communications with the MCU, whether it is for frame transfers or configuration. SPI clock speed, byte interspacing and initial setup time (i.e. time between the falling edge of the chip select and the rising edge of the first SPI clock pulse) are all dependent on the MCU used. For a given SPI clock speed, the effective data throughput can vary.

The MCU must support the following hardware peripherals:

  • 1x GPIO pin to drive the transceiver’s reset pin

  • 1x GPIO pin to serve as the SPI chip select

  • 1x SPI bus controller configured as master

  • 1x External interrupt pin for servicing the transceiver’s IRQs

  • 1x Timer with millisecond accuracy

  • 1x GPIO pin to drive the transceiver’s shutdown pin (if feature is used)

  • 2x DMA channels for the SPI data transfers between the MCU and the transceiver (if WPS is used)

  • 1x Timer with 250 microseconds accuracy (if WPS is used)

  • 1x Software interrupt (if WPS is used)

The simplest way to start porting the SPARK SDK to a new board is to substitute the EVK board BSP with the user’s own hardware BSP and update the BSP interface.

A second way would be for the user to add their own BSP alongside the EVK BSP, then add the required files in the interface and update the STM32CubeIDE project paths. The BSP interface was made to accommodate multiple BSPs without the need to modify the application examples. The examples are not coupled directly with the EVK BSP, the interface is an abstraction layer for the hardware BSP. Therefore each application makes calls to some functions with iface_ as a prefix.

BSP and

Figure 28: Application, BSP interface and hardware BSP relationship.

The BSP interface is split in multiple source files, one for the Wireless Core, one for Audio Core, one for Pairing module and one for each application example.

The most basic application to port is Blinky, which makes use of the transceiver-level API (SR1000 API) to execute uncoordinated data exchanges. Once Blinky works, Hello World would be the next one to port. Hello World makes use of the Wireless Protocol Stack API to establish a full coordinated TDMA link and requires more BSP functions to implement. With those two applications ported, the BSP should be ready to cover most use cases. To get the most out of the custom BSP, care should be taken to optimize the SPI drivers as much as possible.

Adding a BSP alongside the EVK BSP

If the user chooses not to substitute the EVK BSP and wants to add their own hardware BSP alongside the existing one, they can do it by following the steps shown later in this section.

Below is a file structure that shows what needs to be added in order to run the example application audio_4-channel on a custom user_bsp.

Listing 1 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 user simply needs to follow these steps:

  1. Copy the interface source files *_evk.c.

  2. Rename the copied files with the user own hardware suffix.

  3. Update the function implementations with the user’s own hardware BSP functions.

Listing 2 Example of an implementation of the EVK 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 3 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);
}