3. Initial Project

This tutorial will use a modified version of one of the sample projects contained within the SDK, \projects\target_apps\template\empty_peripheral_template, as the starting point for each individual section. To create this modified project you’ll need to make the following changes to the empty_peripheral_template project.

3.1. Application Callbacks

There are a number of system callbacks that we need to re-route to user space, to do this modify the user_app_main_loop_callbacks structure in user_callback_config.h as follows:

static const struct arch_main_loop_callbacks user_app_main_loop_callbacks = {
    .app_on_init            = user_on_init,

    // By default the watchdog timer is reloaded and resumed when the system wakes up.
    // The user has to take into account the watchdog timer handling (keep it running,
    // freeze it, reload it, resume it, etc), when the app_on_ble_powered() is being
    // called and may potentially affect the main loop.
    .app_on_ble_powered     = NULL,

    // By default the watchdog timer is reloaded and resumed when the system wakes up.
    // The user has to take into account the watchdog timer handling (keep it running,
    // freeze it, reload it, resume it, etc), when the app_on_system_powered() is being
    // called and may potentially affect the main loop.
    .app_on_system_powered  = NULL,

    .app_before_sleep       = NULL,
    .app_validate_sleep     = NULL,
    .app_going_to_sleep     = NULL,
    .app_resume_from_sleep  = NULL,
};

We also need to add some Bluetooth stack callbacks, to do this modify the user_app_callbacks structure in user_callback_config.h as follows:

static const struct app_callbacks user_app_callbacks = {
    .app_on_connection                  = user_on_connection,
    .app_on_disconnect                  = user_on_disconnect,
    .app_on_update_params_rejected      = NULL,
    .app_on_update_params_complete      = NULL,
    .app_on_set_dev_config_complete     = user_on_set_dev_config_complete,
    .app_on_adv_nonconn_complete        = NULL,
    .app_on_adv_undirect_complete       = NULL,
    .app_on_adv_direct_complete         = NULL,
    .app_on_db_init_complete            = default_app_on_db_init_complete,
    .app_on_scanning_completed          = NULL,
    .app_on_adv_report_ind              = NULL,
    .app_on_get_dev_name                = default_app_on_get_dev_name,
    .app_on_get_dev_appearance          = default_app_on_get_dev_appearance,
    .app_on_get_dev_slv_pref_params     = default_app_on_get_dev_slv_pref_params,
    .app_on_set_dev_info                = default_app_on_set_dev_info,
    .app_on_data_length_change          = NULL,
    .app_on_update_params_request       = default_app_update_params_request,
    .app_on_generate_static_random_addr = default_app_generate_static_random_addr,
    .app_on_svc_changed_cfg_ind         = NULL,
    .app_on_get_peer_features           = NULL,
#if (BLE_APP_SEC)
    .app_on_pairing_request             = default_app_on_pairing_request,
    .app_on_tk_exch                     = default_app_on_tk_exch,
    .app_on_irk_exch                    = NULL,
    .app_on_csrk_exch                   = NULL,
    .app_on_ltk_exch                    = default_app_on_ltk_exch,
    .app_on_pairing_succeeded           = NULL,
    .app_on_encrypt_ind                 = NULL,
    .app_on_encrypt_req_ind             = NULL,
    .app_on_security_req_ind            = NULL,
    .app_on_addr_solved_ind             = NULL,
    .app_on_addr_resolve_failed         = NULL,
    .app_on_ral_cmp_evt                 = NULL,
    .app_on_ral_size_ind                = NULL,
    .app_on_ral_addr_ind                = NULL,
#endif // (BLE_APP_SEC)
};

We then need to add function prototypes for the new callback functions to user_empty_peripheral_template.h as follows:

void user_on_init(void);
void user_on_set_dev_config_complete(void);

Finally we need to add the actual user space callback functions to user_empty_peripheral_template.c as follows:

void user_on_init(void)
{
   arch_printf("\n\r%s", __FUNCTION__);

   default_app_on_init();
}

void user_on_set_dev_config_complete(void)
{
    arch_printf("\n\r%s", __FUNCTION__);

    default_app_on_set_dev_config_complete();
}

3.2. Sleep Mode

By default the project does not use sleep mode and so we need to perform the following modification to ensure the device enters sleep mode whenever possible. We can do this by modifying app_default_sleep_mode in user_config.h as follows:

static const sleep_state_t app_default_sleep_mode = ARCH_EXT_SLEEP_ON;

3.3. SPI Flash

A number of the following chapters use the SPI interface to access the flash memory found on the development kits. On both the PRO and USB kits the flash memory is connected to the following DA14531 pins:

  • SPI Flash MISO: P0_3

  • SPI Flash MOSI: P0_0

  • SPI Flash CLK: P0_4

  • SPI Flash CS: P0_1

First add definitions for these pin mappings to the file user_periph_setup.h as follows:

/****************************************************************************************/
/* SPI configuration                                                                    */
/****************************************************************************************/
#define SPI_EN_PORT                     GPIO_PORT_0
#define SPI_EN_PIN                      GPIO_PIN_1
#define SPI_CLK_PORT                    GPIO_PORT_0
#define SPI_CLK_PIN                     GPIO_PIN_4
#define SPI_DO_PORT                     GPIO_PORT_0
#define SPI_DO_PIN                      GPIO_PIN_0
#define SPI_DI_PORT                     GPIO_PORT_0
#define SPI_DI_PIN                      GPIO_PIN_3

Next we need to reserve these pins so that the SDK can check for duplicate assignments. To do this add the following code to the GPIO_reservations function that can be found in the user_periph_setup.c file:

RESERVE_GPIO(SPI_FLASH_CS, SPI_EN_PORT, SPI_EN_PIN, PID_SPI_EN);
RESERVE_GPIO(SPI_FLASH_CLK, SPI_CLK_PORT, SPI_CLK_PIN, PID_SPI_CLK);
RESERVE_GPIO(SPI_FLASH_DO, SPI_DO_PORT, SPI_DO_PIN, PID_SPI_DO);
RESERVE_GPIO(SPI_FLASH_DI, SPI_DI_PORT, SPI_DI_PIN, PID_SPI_DI);

Now configure the pins to have the relevant SPI function by adidng the following to the set_pad_functions function:

GPIO_ConfigurePin(SPI_EN_PORT, SPI_EN_PIN, OUTPUT, PID_SPI_EN, true);
GPIO_ConfigurePin(SPI_CLK_PORT, SPI_CLK_PIN, OUTPUT, PID_SPI_CLK, false);
GPIO_ConfigurePin(SPI_DO_PORT, SPI_DO_PIN, OUTPUT, PID_SPI_DO, false);
GPIO_ConfigurePin(SPI_DI_PORT, SPI_DI_PIN, INPUT, PID_SPI_DI, false);

3.4. Serial Debug

We will now enable serial debug capability so that a terminal emulator (such as Tera Term etc.) can be used to view debug information output by the application running on the DA14531.

3.4.1. Enabling the Serial Port

We can enable the UART with a simple modification to the configuration file: da1458x_config_basic.h. Scroll down and find the #undef CFG_PRINTF statement and change it to:

#define CFG_PRINTF

Note

There are two #undef CFG_PRINTF statements in the file, one for the DA14585/6 and one for the DA14531, make sure to change one related to the device you are working on!

In user_periph_setup.h change the GPIO used as the UART transmit output by the DA14531 devkit PRO and USB to P0_5 as follows:

#define UART2_TX_PIN            GPIO_PIN_5

This will automatically select and configure the proper GPIO for the UART TX. In order to give ourselves access to a more user friendly API, we will add the following include statement to user_empty_peripheral_template.c:

#include "arch_console.h"

We can now use the following functions:

  • arch_puts(), to transmit a simple string via the UART

  • arch_printf(), to format and transmit a string via the UART

3.4.2. Testing the Serial Port

Configure your Terminal Emulator as follows:

  • Baud Rate: 115200

  • Data: 8 bits

  • Parity: None

  • Stop Bits: 1

  • Flow Control: None

Build the project and load it onto target.

When you run the application using the debugger you should see the following be transmitted via the UART:

_images/init_uart_test.png

Fig. 5 UART output from initial example project