This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Multilink central adding advertising. Error 12 on advertising_start()

Hi. I have added advertising to my multilink central project SDK15.0. Running on a nRF52840.

I get a error 12 when advertising_start(); is called on startup. I believe this means adv packet is too big.

However I don't see how this could be the case, because I copied it from another example (NUS peripheral) which works ok.

One issue may be that this project is a central that is scanning, so advertising should be non-connectable only. Not sure how to do this. My main is below.

Any help would be appreciated.

/**
 * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA
 * 
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form, except as embedded into a Nordic
 *    Semiconductor ASA integrated circuit in a product or a software update for
 *    such product, must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 * 
 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 * 
 * 4. This software, with or without modification, must only be used with a
 *    Nordic Semiconductor ASA integrated circuit.
 * 
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 * 
 * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */
/**
 * @brief BLE LED Button Service central and client application main file.
 *
 * This example can be a central for up to 8 peripherals.
 * The peripheral is called ble_app_blinky and can be found in the ble_peripheral
 * folder.
 */

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "nordic_common.h"
#include "nrf_sdh.h"
#include "nrf_sdh_ble.h"
#include "app_timer.h"
#include "bsp_btn_ble.h"
#include "ble.h"
#include "ble_hci.h"
#include "ble_advdata.h"
#include "ble_advertising.h"
#include "ble_conn_params.h"
#include "ble_db_discovery.h"
#include "ble_nus_c.h"
#include "ble_conn_state.h"
#include "nrf_ble_gatt.h"
#include "nrf_pwr_mgmt.h"
#include "nrf_drv_power.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "nrf_queue.h"
#include "nrf_delay.h"
#include "nrf_drv_saadc.h"
#include "nrf_drv_pwm.h"
#include "nrf_drv_clock.h"
#include "nrf_drv_rtc.h"
#include "lcd_driver.h"
#include "BQ25896_driver.h"
#include "temp_lookup.h"
#include "nrf_sdh_soc.h"

#define setbit(var, bit)        ((var) |= (1 << (bit)))
#define clearbit(var, bit)      ((var) &= ~(1 << (bit)))

#define DEVICE_NAME                     "TEST1"
#define APP_COMPANY_IDENTIFIER          0x0059                                  /**< Company identifier for Nordic Semiconductor ASA. as per www.bluetooth.org. */
#define APP_ADV_INTERVAL                200                                          /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */
#define APP_ADV_DURATION                18000                                       /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
#define MIN_CONN_INTERVAL               MSEC_TO_UNITS(75, UNIT_1_25_MS) //was 7.5            /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
#define MAX_CONN_INTERVAL               MSEC_TO_UNITS(100, UNIT_1_25_MS) //was 100            /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */
#define SLAVE_LATENCY                   0                                           /**< Slave latency. */
#define CONN_SUP_TIMEOUT                MSEC_TO_UNITS(4000, UNIT_10_MS)             /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */


#define APP_BLE_CONN_CFG_TAG      1                                     /**< A tag that refers to the BLE stack configuration we set with @ref sd_ble_cfg_set. Default tag is @ref APP_BLE_CONN_CFG_TAG. */
#define APP_BLE_OBSERVER_PRIO     3                                     /**< Application's BLE observer priority. You shouldn't need to modify this value. */

#define UART_TX_BUF_SIZE          256                                     /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE          256

#define NUS_SERVICE_UUID_TYPE     BLE_UUID_TYPE_VENDOR_BEGIN              /**< UUID type for the Nordic UART Service (vendor specific). */

#define BUTTON_DETECTION_DELAY    APP_TIMER_TICKS(50)                   /**< Delay from a GPIOTE event until a button is reported as pushed (in number of timer ticks). */

#define LED_G                     21
#define LED_R                     17
#define LED_B                     19
#define PUSH_BUTTON               44 //P1.12
#define EN_PIN                    23
#define MAG_SENS                  5

#define COIL_EN                   22
#define COIL_PWM                  24
#define POWER_EN                  2
#define TRIAC_3                   7
#define TRIAC_2                   9
#define TRIAC_1                   47

#define STATE_START               0
#define STATE_ASLEEP              1
#define STATE_ACTIVE              2
#define STATE_CHARGING            3

#define SCAN_INTERVAL             0x0200//0x00A0                                /**< Determines scan interval in units of 0.625 millisecond. */
#define SCAN_WINDOW               0x0050//0x0050                               /**< Determines scan window in units of 0.625 millisecond. */
#define SCAN_DURATION             0x0000                                /**< Duration of the scanning in units of 10 milliseconds. If set to 0x0000, scanning will continue until it is explicitly disabled. */

#define MIN_CONNECTION_INTERVAL   MSEC_TO_UNITS(75, UNIT_1_25_MS) //was 7.5     /**< Determines minimum connection interval in milliseconds. */
#define MAX_CONNECTION_INTERVAL   MSEC_TO_UNITS(100, UNIT_1_25_MS)  //was 10     /**< Determines maximum connection interval in milliseconds. */
#define SLAVE_LATENCY             0                                     /**< Determines slave latency in terms of connection events. */
#define SUPERVISION_TIMEOUT       MSEC_TO_UNITS(4000, UNIT_10_MS)       /**< Determines supervision time-out in units of 10 milliseconds. */

#define COMPARE_COUNTERTIME  (1)                                        /**< Get Compare event COMPARE_TIME seconds after the counter starts from 0. */
#define BAND_ARRAY_SIZE             10
#define MAX_DOWNLOAD_ARRAY_SIZE     256

#define AGE_TIMEOUT  32  //8 ticks / s = 4s it will clear the peer_Address
//i.e. SB clearing download quicker than it transmitted from the peripheral x128 = 128,000 bytes

#define BOOTLOADER_DFU_START 0xB1

const nrf_drv_rtc_t rtc = NRF_DRV_RTC_INSTANCE(2); /**< Declaring an instance of nrf_drv_rtc for RTC1. */

static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);
// Declare variables holding PWM sequence values. In this example only one channel is used 
static nrf_pwm_values_individual_t seq_values[] = {0, 0, 0, 0};
static nrf_pwm_sequence_t const seq =
{
    .values.p_individual = seq_values,
    .length          = NRF_PWM_VALUES_LENGTH(seq_values),
    .repeats         = 0,
    .end_delay       = 0
};

static uint8_t pwm_triac_count = 0;
static uint8_t connection_peer[6];

static uint8_t display_count = 0;

static uint16_t output[3] = {0x0000,0x0000,0x0000};

static uint16_t size_to_read = 0;
static uint16_t NTC_1_ave = 8000;
static uint16_t NTC_2_ave = 8000;
static uint16_t Coil_current_ave = 8000;
static uint8_t responce_i2c = 0;
#define mov_ave_divisor 8

#define BAND_MESSAGE_SIZE 240
static uint8_t message_to_band[BAND_MESSAGE_SIZE * 4];

static band_status_t band_array[BAND_ARRAY_SIZE];

#define SAMPLES_IN_BUFFER 3
static nrf_saadc_value_t m_buffer[SAMPLES_IN_BUFFER];

static bool just_sent_download_data = false;
static uint16_t dp_count = 0;

static uint8_t packets_to_send = 0;

static uint8_t test_counter = 0;


static uint16_t chg_current = 0; //0x12
static uint16_t bat_voltage = 0; //0x0E
static uint16_t sys_voltage = 0; //0x0F
static uint16_t bus_voltage = 0; //0x11

static uint8_t reg_00 = 0;
static uint8_t reg_02 = 0;
static uint8_t reg_03 = 0;
static uint8_t reg_06 = 0;
static uint8_t reg_0b = 0;
static uint8_t reg_0c = 0;
static uint8_t reg_0d = 0;

static uint8_t current_state = 0;
static uint8_t shutdown_count = 0;

static bool PG_STAT = false; //power good bit
static uint8_t CHARGE_STATE = 0;
static uint16_t IINLIM = 0;
static uint16_t IDPM_LIM = 0;
static uint16_t ICHG = 0;
static uint16_t VINDPM = 0;

#define PWM_VALUE   320
static uint16_t test_pwm = 320;



APP_TIMER_DEF(adv_timer);

NRF_BLE_GATT_DEF(m_gatt);                                               /**< GATT module instance. */
//BLE_LBS_C_ARRAY_DEF(m_lbs_c, NRF_SDH_BLE_CENTRAL_LINK_COUNT);           /**< LED Button client instances. */
BLE_NUS_C_ARRAY_DEF(m_nus_c, NRF_SDH_BLE_CENTRAL_LINK_COUNT); 
BLE_DB_DISCOVERY_ARRAY_DEF(m_db_disc, NRF_SDH_BLE_CENTRAL_LINK_COUNT);  /**< Database discovery module instances. */
BLE_ADVERTISING_DEF(m_advertising);
static ble_uuid_t m_adv_uuids[]          =                                          /**< Universally unique service identifier. */
{
    {BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}
};

static char const m_target_name[] = "SWTG1"; 

static uint8_t m_scan_buffer_data[BLE_GAP_SCAN_BUFFER_MIN]; /**< buffer where advertising reports will be stored by the SoftDevice. */

static uint16_t m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - OPCODE_LENGTH - HANDLE_LENGTH; /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */

void do_dfu(void);
void pwm_update_duty_cycle(uint16_t);
void pwm_update(uint16_t freq);
void pwm_stop(void);

/**@brief Pointer to the buffer where advertising reports will be stored by the SoftDevice. */
static ble_data_t m_scan_buffer =
{
    m_scan_buffer_data,
    BLE_GAP_SCAN_BUFFER_MIN
};

/**@brief Scan parameters requested for scanning and connection. */
static ble_gap_scan_params_t const m_scan_params =
{
    .active   = 0,  //was 0
    .interval = SCAN_INTERVAL,
    .window   = SCAN_WINDOW,

    .timeout           = SCAN_DURATION,
    .scan_phys         = BLE_GAP_PHY_1MBPS,  //BLE_GAP_PHY_CODED
    .filter_policy     = BLE_GAP_SCAN_FP_ACCEPT_ALL,

};

/**@brief NUS uuid. */
static ble_uuid_t const m_nus_uuid =
{
    .uuid = BLE_UUID_NUS_SERVICE,
    .type = NUS_SERVICE_UUID_TYPE
};

/**@brief Connection parameters requested for connection. */
static ble_gap_conn_params_t const m_connection_param =
{
    (uint16_t)MIN_CONNECTION_INTERVAL,
    (uint16_t)MAX_CONNECTION_INTERVAL,
    (uint16_t)SLAVE_LATENCY,
    (uint16_t)SUPERVISION_TIMEOUT
};


void clocks_start( void )
{
    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_HFCLKSTART = 1;

    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
}


#define DEFAULT_READ_SIZE 4 //Basic commands to dock
#define MAX_READ_SIZE 1000 


static char rx_message[256];
static bool m_send_flag = 0;


bool message_rxd = false;

bool display_toggle = false;

static void clear_LEDS()
{
    nrf_gpio_pin_clear(LED_R);
    nrf_gpio_pin_clear(LED_G);
    nrf_gpio_pin_clear(LED_B);
}

static void enter_active_mode()
{
    //TODO
}

static void enter_charging_mode()
{
    //TODO
}

static void enter_sleep_mode() //Turn most things off
{
    //TODO
}

static void charger_tasks()
{
    //TODO
}

/** @brief: Function for handling the RTC1 interrupts.
 * Triggered on TICK and COMPARE0 match.
 */
static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
{
    if (int_type == NRF_DRV_RTC_INT_COMPARE2)
    {
        if(current_state == STATE_START) nrf_gpio_pin_set(LED_B);
        else if(current_state == STATE_ACTIVE)
        {
            //TODO
        }
        else if(current_state == STATE_CHARGING) 
        {
            //TODO
        }
        else if(current_state == STATE_ASLEEP)
        {
            nrf_gpio_pin_toggle(LED_B);
        }

        charger_tasks();

/*
        if(display_toggle == false)
        {
            display_next(); //Show next image
            nrf_gpio_pin_set(EN_PIN); //Turn on LCD
            display_toggle = true;
        }
        else 
        {
            nrf_gpio_pin_clear(EN_PIN); //Turn off LCD
            display_toggle = false;
        }
        */

        nrf_drv_rtc_counter_clear(&rtc); 
        nrf_drv_rtc_int_enable(&rtc, NRF_RTC_INT_COMPARE2_MASK); 

/*
        //TODO
*/        

    }
    else if (int_type == NRF_DRV_RTC_INT_TICK)
    {
        //TODO
    }
}


/**@brief Function to handle asserts in the SoftDevice.
 *
 * @details This function will be called in case of an assert in the SoftDevice.
 *
 * @warning This handler is an example only and does not fit a final product. You need to analyze
 *          how your product is supposed to react in case of Assert.
 * @warning On assert from the SoftDevice, the system can only recover on reset.
 *
 * @param[in] line_num     Line number of the failing ASSERT call.
 * @param[in] p_file_name  File name of the failing ASSERT call.
 */
void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
{
    app_error_handler(0xDEADBEEF, line_num, p_file_name);
}


/**@brief Function for the LEDs initialization.
 *
 * @details Initializes all LEDs used by the application.
 */
static void leds_button_init(void)
{
    nrf_gpio_cfg_output(LED_G);
    nrf_gpio_cfg_output(LED_R);
    nrf_gpio_cfg_output(LED_B);
    nrf_gpio_cfg_output(EN_PIN);

    nrf_gpio_cfg_output(TRIAC_3);
    nrf_gpio_cfg_output(TRIAC_2);
    nrf_gpio_cfg_output(TRIAC_1);
    nrf_gpio_cfg_output(COIL_EN);
    nrf_gpio_cfg_output(POWER_EN);

    nrf_gpio_pin_clear(EN_PIN);
    nrf_gpio_pin_clear(TRIAC_3);
    nrf_gpio_pin_clear(TRIAC_2);
    nrf_gpio_pin_clear(TRIAC_1);
    nrf_gpio_pin_clear(COIL_EN);
    nrf_gpio_pin_clear(POWER_EN);

    nrf_gpio_cfg_input(PUSH_BUTTON,NRF_GPIO_PIN_PULLUP);
    nrf_gpio_cfg_input(MAG_SENS,NRF_GPIO_PIN_PULLUP);
}


/**@brief Function to start scanning. */
static void scan_start(void)
{
    ret_code_t ret;

    (void) sd_ble_gap_scan_stop();

    ret = sd_ble_gap_scan_start(&m_scan_params, &m_scan_buffer);
    APP_ERROR_CHECK(ret);
}

/**@brief Callback handling NUS Client events.
 *
 * @details This function is called to notify the application of NUS client events.
 *
 * @param[in]   p_ble_nus_c   NUS Client Handle. This identifies the NUS client
 * @param[in]   p_ble_nus_evt Pointer to the NUS Client event.
 */

/**@snippet [Handling events from the ble_nus_c module] */
static void ble_nus_c_evt_handler(ble_nus_c_t * p_ble_nus_c, ble_nus_c_evt_t const * p_ble_nus_evt)
{
    ret_code_t err_code;
    uint16_t i;

    switch (p_ble_nus_evt->evt_type)
    {
        case BLE_NUS_C_EVT_DISCOVERY_COMPLETE:
            NRF_LOG_INFO("NUS service discovered on conn_handle 0x%x", p_ble_nus_evt->conn_handle);
            err_code = ble_nus_c_handles_assign(p_ble_nus_c, p_ble_nus_evt->conn_handle, &p_ble_nus_evt->handles);
            APP_ERROR_CHECK(err_code);

            err_code = ble_nus_c_tx_notif_enable(p_ble_nus_c);
            APP_ERROR_CHECK(err_code);
            //NRF_LOG_INFO("Connected to device with Nordic UART Service.");

            break;

        case BLE_NUS_C_EVT_NUS_TX_EVT:

            break;

        case BLE_NUS_C_EVT_DISCONNECTED:
            NRF_LOG_INFO("NUS service disconnected on conn_handle 0x%x", p_ble_nus_evt->conn_handle);

            break;
    }
}
/**@snippet [Handling events from the ble_nus_c module] */

/**@brief Function for the GAP initialization.
 *
 * @details This function will set up all the necessary GAP (Generic Access Profile) parameters of
 *          the device. It also sets the permissions and appearance.
 */
static void gap_params_init(void)
{
    uint32_t                err_code;
    ble_gap_conn_params_t   gap_conn_params;
    ble_gap_conn_sec_mode_t sec_mode;
    ble_gap_addr_t my_address;

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);

    err_code = sd_ble_gap_device_name_set(&sec_mode,
                                          (const uint8_t *) DEVICE_NAME,
                                          strlen(DEVICE_NAME));


    APP_ERROR_CHECK(err_code);

//    sd_ble_gap_addr_get(&my_address);
//    memcpy(my_peer_address, my_address.addr, 6);

    memset(&gap_conn_params, 0, sizeof(gap_conn_params));

    gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
    gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
    gap_conn_params.slave_latency     = SLAVE_LATENCY;
    gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;

    err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
    APP_ERROR_CHECK(err_code);
}


/**@brief Function for handling the advertising report BLE event.
 *
 * @param[in] p_adv_report  Advertising report from the SoftDevice.
 */
static void on_adv_report(ble_gap_evt_adv_report_t const * p_adv_report)
{
    ret_code_t err_code;

    if (ble_advdata_name_find(p_adv_report->data.p_data, p_adv_report->data.len, m_target_name))
    {
        //TODO
    }


//TODO - Not connecting at the moment
    if(memcmp(p_adv_report->peer_addr.addr,connection_peer,6)==0)
    {
        //Now we are connecting to the peer, set connection_peer to 0x00
        memset(&connection_peer, 0x00, 6);

        NRF_LOG_INFO("Peer address is a match");
        // Name is a match, initiate connection.
        err_code = sd_ble_gap_connect(&p_adv_report->peer_addr,
                                      &m_scan_params,
                                      &m_connection_param,
                                      APP_BLE_CONN_CFG_TAG);
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Connection Request Failed, reason %d", err_code);
        }
    }
    else
    {
        //NRF_LOG_INFO("Advertisment wasn't match to %s ", p_adv_report->data.p_data);// m_target_periph_name);
        err_code = sd_ble_gap_scan_start(NULL, &m_scan_buffer);
        APP_ERROR_CHECK(err_code);
    }
}


/**@brief Function for handling BLE events.
 *
 * @param[in]   p_ble_evt   Bluetooth stack event.
 * @param[in]   p_context   Unused.
 */
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
    ret_code_t err_code;

    // For readability.
    ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;

    switch (p_ble_evt->header.evt_id)
    {
        // Upon connection, check which peripheral has connected, initiate DB
        // discovery, update LEDs status and resume scanning if necessary.
        case BLE_GAP_EVT_CONNECTED:
        {
            NRF_LOG_INFO("Connection 0x%x established, starting DB discovery.",
                         p_gap_evt->conn_handle);

            NRF_LOG_INFO("interval %d",  p_gap_evt->params.connected.conn_params.min_conn_interval);


            APP_ERROR_CHECK_BOOL(p_gap_evt->conn_handle < NRF_SDH_BLE_CENTRAL_LINK_COUNT);

            err_code = ble_nus_c_handles_assign(&m_nus_c[p_gap_evt->conn_handle],
                                                p_gap_evt->conn_handle,
                                                NULL);
            APP_ERROR_CHECK(err_code);

            err_code = ble_db_discovery_start(&m_db_disc[p_gap_evt->conn_handle],
                                              p_gap_evt->conn_handle);
            if (err_code != NRF_ERROR_BUSY)
            {
                APP_ERROR_CHECK(err_code);
            }

            scan_start();
            

        } break; // BLE_GAP_EVT_CONNECTED

        // Upon disconnection, reset the connection handle of the peer which disconnected, update
        // the LEDs status and start scanning again.
        case BLE_GAP_EVT_DISCONNECTED:
        {
            NRF_LOG_INFO("NUS central link 0x%x disconnected (reason: 0x%x)",
                         p_gap_evt->conn_handle,
                         p_gap_evt->params.disconnected.reason);



            scan_start();

        } break;

        case BLE_GAP_EVT_ADV_REPORT:
            on_adv_report(&p_gap_evt->params.adv_report);
            break;

        case BLE_GAP_EVT_TIMEOUT:
        {
            // We have not specified a timeout for scanning, so only connection attemps can timeout.
            if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
            {
                NRF_LOG_DEBUG("Connection request timed out.");
            }
            // Check if scaning times out and restart the scans
            if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_SCAN)
            {
                scan_start();
            }
        } break;

        case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
        {
            NRF_LOG_DEBUG("BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST.");
            // Accept parameters requested by peer.
            err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,
                                        &p_gap_evt->params.conn_param_update_request.conn_params);
            APP_ERROR_CHECK(err_code);
        } break;

        case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
        {
            NRF_LOG_DEBUG("PHY update request.");
            ble_gap_phys_t const phys =
            {
                .rx_phys = BLE_GAP_PHY_AUTO,
                .tx_phys = BLE_GAP_PHY_AUTO,
            };
            err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
            APP_ERROR_CHECK(err_code);
        } break;

        case BLE_GATTC_EVT_TIMEOUT:
        {
            // Disconnect on GATT Client timeout event.
            NRF_LOG_DEBUG("GATT Client Timeout.");
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
        } break;

        case BLE_GATTS_EVT_TIMEOUT:
        {
            // Disconnect on GATT Server timeout event.
            NRF_LOG_DEBUG("GATT Server Timeout.");
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
        } break;

        default:
            // No implementation needed.
            break;
    }
}

/**@brief Function for initializing the NUS Client. */
static void nus_c_init(void)
{
    ret_code_t       err_code;
    ble_nus_c_init_t nus_c_init_obj;

    nus_c_init_obj.evt_handler = ble_nus_c_evt_handler;

    for (uint32_t i = 0; i < NRF_SDH_BLE_CENTRAL_LINK_COUNT; i++)
    {
        err_code = ble_nus_c_init(&m_nus_c[i], &nus_c_init_obj);
        APP_ERROR_CHECK(err_code);
    }
}


/**@brief Function for initializing the BLE stack.
 *
 * @details Initializes the SoftDevice and the BLE event interrupts.
 */
static void ble_stack_init(void)
{
    ret_code_t err_code;

    err_code = nrf_sdh_enable_request();
    APP_ERROR_CHECK(err_code);

    // Configure the BLE stack using the default settings.
    // Fetch the start address of the application RAM.
    uint32_t ram_start = 0;
    err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
    APP_ERROR_CHECK(err_code);

    // Enable BLE stack.
    err_code = nrf_sdh_ble_enable(&ram_start);
    APP_ERROR_CHECK(err_code);

    // Register a handler for BLE events.
    NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
}

void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
}

void saadc_init(void)
{
    ret_code_t err_code;
    nrf_saadc_channel_config_t channel_config6 
      = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN6); //P0.30 = AN6 = Coil Current
    nrf_saadc_channel_config_t channel_config4 
      = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN4); //P0.28 = AN4 = Batt 1 Temperature
    nrf_saadc_channel_config_t channel_config5 
      = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN5); //P0.29 = AN5 = Batt 2 Temperature

    err_code = nrf_drv_saadc_init(NULL, saadc_callback);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_channel_init(0, &channel_config6);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(1, &channel_config4);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(2, &channel_config5);
    APP_ERROR_CHECK(err_code);

//    err_code = nrf_drv_saadc_buffer_convert(m_buffer, SAMPLES_IN_BUFFER);
//    APP_ERROR_CHECK(err_code);
}


/**@brief Function for handling database discovery events.
 *
 * @details This function is callback function to handle events from the database discovery module.
 *          Depending on the UUIDs that are discovered, this function should forward the events
 *          to their respective services.
 *
 * @param[in] p_event  Pointer to the database discovery event.
 */
static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
{
    NRF_LOG_DEBUG("call to ble_nus_on_db_disc_evt for instance %d and link 0x%x!",
                  p_evt->conn_handle,
                  p_evt->conn_handle);
    ble_nus_c_on_db_disc_evt(&m_nus_c[p_evt->conn_handle], p_evt);
}


/** @brief Database discovery initialization.
 */
static void db_discovery_init(void)
{
    ret_code_t err_code = ble_db_discovery_init(db_disc_handler);
    APP_ERROR_CHECK(err_code);
}


/**@brief Function for initializing power management.
 */
static void power_management_init(void)
{
    ret_code_t err_code;
    err_code = nrf_pwr_mgmt_init();
    APP_ERROR_CHECK(err_code);
}


/**@brief Function for handling the idle state (main loop).
 *
 * @details Handle any pending log operation(s), then sleep until the next event occurs.
 */
static void idle_state_handle(void)
{
    if (NRF_LOG_PROCESS() == false)
    {
        nrf_pwr_mgmt_run();
    }
}


/** @brief Function for initializing the log module.
*/ 
static void log_init(void)
{
    ret_code_t err_code = NRF_LOG_INIT(NULL);
    APP_ERROR_CHECK(err_code);

    NRF_LOG_DEFAULT_BACKENDS_INIT();
}

void pwm_init(uint16_t freq)
{
    nrf_drv_pwm_config_t const config0 =
    {
        .output_pins =
        {
            COIL_PWM, // channel 0
            NRF_DRV_PWM_PIN_NOT_USED,             // channel 1
            NRF_DRV_PWM_PIN_NOT_USED,             // channel 2
            NRF_DRV_PWM_PIN_NOT_USED,             // channel 3
        },
        .irq_priority = APP_IRQ_PRIORITY_LOWEST,
        .base_clock   = NRF_PWM_CLK_4MHz,
        .count_mode   = NRF_PWM_MODE_UP,
        .top_value    = freq,
        .load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
        .step_mode    = NRF_PWM_STEP_AUTO
    };
    // Init PWM without error handler
    APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL));
}

void pwm_update(uint16_t freq)
{
    nrf_drv_pwm_uninit(&m_pwm0);
    pwm_init(freq);
    pwm_update_duty_cycle(freq / 2);
}

void pwm_stop()
{
    nrf_drv_pwm_uninit(&m_pwm0);
}

// Set duty cycle between 0 and 100%
void pwm_update_duty_cycle(uint16_t duty_cycle)
{
    seq_values->channel_0 = duty_cycle;
    
    nrf_drv_pwm_simple_playback(&m_pwm0, &seq, 1, NRF_DRV_PWM_FLAG_LOOP);
}

static void fill_adv_array(uint8_t *array)
{
        array[0] = 0;//adc_conversion(power_ave,0,6);//GET_HI_CHAR(power_ave);
        array[1] = 0;//adc_conversion(batt_ave,6144,4);//GET_LO_CHAR(power_ave);
        array[2] = 0;//
        array[3] = 99;//
        array[4] = 0;//
        array[5] = 0;//
        array[6] = 0;//
        array[7] = 0;//module_bit;
        array[8] = 0x00;//spare
        array[9] = 0;//;
//        array[10] = 0;//;
//        array[11] = 0;//
//        array[12] = 0;//
//        array[13] = 0;//pressure_conversion();//;pressure_H;
//        array[14] = 0;//temperature_H;
//        array[15] = 88;//VERSION;
//        array[16] = 0x00;
}

/**@brief Function for putting the chip into sleep mode.
 *
 * @note This function will not return.
 */
static void sleep_mode_enter(void)
{
    uint32_t err_code;
    //uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE);
    //APP_ERROR_CHECK(err_code);

    // Prepare wakeup buttons.
    //err_code = bsp_btn_ble_sleep_mode_prepare();
    //APP_ERROR_CHECK(err_code);

    // Go to system-off mode (this function will not return; wakeup will cause a reset).
    err_code = sd_power_system_off();
    APP_ERROR_CHECK(err_code);
}

/**@brief Function for handling advertising events.
 *
 * @details This function will be called for advertising events which are passed to the application.
 *
 * @param[in] ble_adv_evt  Advertising event.
 */
static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
{
    uint32_t err_code;

    switch (ble_adv_evt)
    {
        case BLE_ADV_EVT_FAST:
            //err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
            //APP_ERROR_CHECK(err_code);
            break;
        case BLE_ADV_EVT_IDLE:
            sleep_mode_enter();
            break;
        default:
            break;
    }
}

/**@brief Function for initializing the Advertising functionality.
 */
static void advertising_init(void)
{
    uint32_t               err_code;
    ble_advertising_init_t init;

    memset(&init, 0, sizeof(init));

    uint8_t advData[1];
    //fill_adv_array(advData);

    ble_advdata_manuf_data_t manuf_specific_data;
    manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER;
    manuf_specific_data.data.p_data = advData;
    manuf_specific_data.data.size   = sizeof(advData);

    init.advdata.name_type          = BLE_ADVDATA_FULL_NAME;
    init.advdata.include_appearance = false;
    init.advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
    init.advdata.p_manuf_specific_data = &manuf_specific_data;
    init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
    init.srdata.uuids_complete.p_uuids  = m_adv_uuids;
    init.config.ble_adv_fast_enabled  = true;
    init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
    init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;
    init.evt_handler = on_adv_evt;

    err_code = ble_advertising_init(&m_advertising, &init);
    APP_ERROR_CHECK(err_code);

    ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);

    err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, m_advertising.adv_handle, 0);
    APP_ERROR_CHECK(err_code); 
}

/**@brief Function for starting advertising.
 */
static void advertising_start(void)
{
    uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
    APP_ERROR_CHECK(err_code);   
}

void advertising_idle(void)
{
    uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_IDLE);
    APP_ERROR_CHECK(err_code);   
}


/** @brief Function for initializing the timer.
 */
static void timer_init(void)
{
    ret_code_t err_code = app_timer_init();
    APP_ERROR_CHECK(err_code);

//    err_code = app_timer_start(adv_timer,65000,NULL);
    //NRF_LOG_INFO("error %d", err_code);
//    APP_ERROR_CHECK(err_code);
}

/**@brief Function for handling events from the GATT library. */
void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
{
    if (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)
    {
        NRF_LOG_INFO("ATT MTU exchange completed.");

        m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
        NRF_LOG_INFO("Ble NUS max data length set to 0x%X(%d)", m_ble_nus_max_data_len, m_ble_nus_max_data_len);
    }
}


/**@brief Function for initializing the GATT module.
 */
static void gatt_init(void)
{
    ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
//    ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
    APP_ERROR_CHECK(err_code);
}

/** @brief Function initialization and configuration of RTC driver instance.
 */
static void rtc_config(void)
{
    uint32_t err_code;

    //Initialize RTC instance
    nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG;
    config.prescaler = 1023; //32 a second
    err_code = nrf_drv_rtc_init(&rtc, &config, rtc_handler);
    APP_ERROR_CHECK(err_code);

    //Enable tick event & interrupt
    nrf_drv_rtc_tick_enable(&rtc,true);

    //Set compare channel to trigger interrupt after COMPARE_COUNTERTIME seconds
    err_code = nrf_drv_rtc_cc_set(&rtc,2,COMPARE_COUNTERTIME * 32,true);
    APP_ERROR_CHECK(err_code);

    //Power on RTC instance
    nrf_drv_rtc_enable(&rtc);
}

void do_dfu(void)
{
    uint32_t err_code;

    //NRF_LOG_DEBUG("In ble_dfu_buttonless_bootloader_start_finalize\r\n");

    err_code = sd_power_gpregret_clr(0, 0xffffffff);
    VERIFY_SUCCESS(err_code);

    err_code = sd_power_gpregret_set(0, BOOTLOADER_DFU_START);
    VERIFY_SUCCESS(err_code);

    // Signal that DFU mode is to be enter to the power management module
    nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_DFU);

    //return NRF_SUCCESS;
}

int main(void)
{
    ble_gap_addr_t my_address;
    ret_code_t ret;

    current_state = STATE_START;

    log_init(); //TODO - remove this and test for side effects
    leds_button_init();

    memset(&connection_peer, 0x00, 6);
    
    //Test LEDs
    nrf_gpio_pin_set(LED_R);
    nrf_delay_ms(200);
    nrf_gpio_pin_clear(LED_R);
    nrf_gpio_pin_set(LED_G);
    nrf_delay_ms(200);
    nrf_gpio_pin_clear(LED_G);
    nrf_gpio_pin_set(LED_B);
    nrf_delay_ms(200);
    nrf_gpio_pin_clear(LED_B);

    bq25896_initial_code();
    lcd_initial_code();

    display_logo();
    nrf_gpio_pin_set(EN_PIN);
    nrf_delay_ms(2000);
    nrf_gpio_pin_clear(EN_PIN);

    timer_init();
    rtc_config();
    saadc_init();
    nrf_drv_saadc_calibrate_offset();
    pwm_update(PWM_VALUE);
    //pwm_update_duty_cycle(80);

    ret = nrf_drv_clock_init();
    APP_ERROR_CHECK(ret);

    //TODO - try removing next 3 lines
    NRF_LOG_INFO("USBD BLE UART example started.");
    ret = NRF_LOG_INIT(NULL);
    APP_ERROR_CHECK(ret);

    // Initialize.

    ble_stack_init();
    gatt_init();
    gap_params_init();
    db_discovery_init();
    nus_c_init();
    ble_conn_state_init();
    advertising_init();
    advertising_start();

    //Get peer address of this device
    sd_ble_gap_addr_get(&my_address);

    //NOTE - Had to add this to stop PWM jitter
    sd_clock_hfclk_request();

    //blank off band records age = 0xFF
    for (uint8_t i=0;i<BAND_ARRAY_SIZE;i++)
    {
        //set the age to 0xFF = blank record
        band_array[i].age = 0xFF;
    }


//fix for multiple connections
    for (uint16_t i=0;i<NRF_SDH_BLE_CENTRAL_LINK_COUNT;i++)
    {
        m_db_disc[i].conn_handle=BLE_CONN_HANDLE_INVALID;
    }

    // Start execution.
    scan_start();

    for (;;)
    {
        idle_state_handle();
    }
}

Parents
  • Hi. 

    In order to set the advertising type as non-connectable, you have to change the advertising event properties (ref. ble_gap.h, line: 663). 

    You can take a look how the advertising type is set in the ble_app_blinky example (ref. main.c, line: 242). 

    Refer to ble_gap.h, line:360 for the different GAP Advertising types.

    Best regards, 
    Joakim

  • Thanks Joakim.

    The advertising init is totally different to that in the NUS example, doesn't seem to be consistent across the examples. I managed to update my code so it uses the adv init function from blinky.

    However I now can't get the power output function to work.

    How would I modify the blinky example below to change the adv transmit power output? The below doesn't work, gives a 3004 error.

    err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, &m_adv_handle, 8);
    APP_ERROR_CHECK(err_code);

    Thanks

    static void advertising_init(void)
    {
        ret_code_t    err_code;
        ble_advdata_t advdata;
        ble_advdata_t srdata;
    
        uint8_t testData[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 };
    
        ble_advdata_manuf_data_t manuf_specific_data;
        manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER;
        manuf_specific_data.data.p_data = testData;
        manuf_specific_data.data.size   = 0x08;
    
        ble_uuid_t adv_uuids[] = {{LBS_UUID_SERVICE, m_lbs.uuid_type}};
    
        // Build and set advertising data.
        memset(&advdata, 0, sizeof(advdata));
    
        advdata.name_type          = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance = true;
        advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
        advdata.p_manuf_specific_data = &manuf_specific_data;
    
        memset(&srdata, 0, sizeof(srdata));
        srdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
        srdata.uuids_complete.p_uuids  = adv_uuids;
    
        err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
        APP_ERROR_CHECK(err_code);
    
        err_code = ble_advdata_encode(&srdata, m_adv_data.scan_rsp_data.p_data, &m_adv_data.scan_rsp_data.len);
        APP_ERROR_CHECK(err_code);
    
        ble_gap_adv_params_t adv_params;
    
        // Set advertising parameters.
        memset(&adv_params, 0, sizeof(adv_params));
    
        adv_params.primary_phy     = BLE_GAP_PHY_1MBPS;
        adv_params.duration        = APP_ADV_DURATION;
        adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
        adv_params.p_peer_addr     = NULL;
        adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
        adv_params.interval        = APP_ADV_INTERVAL;
    
        err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &adv_params);
        APP_ERROR_CHECK(err_code);
    }

  • Thanks for the info.

    Non connectable is not a massive deal for this application, would be nice to get it working but might give up on this for now as it is causing knock on issues else where.

Reply Children
No Data
Related