Advertising Beacon Start Gives Fatal Error

My overall goal is to update the percentage of battery left in the advertiser and then either go to a nine second sleep to conserve as much power as possible and then wake up and repeat the process.  Right now I am trying to see if using a timer event will allow the project to last long enough on a small battery (30mAH) or if I should investigate using some external circuitry to produce a wake up pulse so the battery can be separated from the micro and have minimal draw on the battery.  Any suggestions on how this can be verified would be appreciated.

In addition, I have been attempting to work with the beacon examples and have managed to introduce some kind of fatal error when I start the advertising.  The init seems to be functioning okay but I may be missing an important init step.  I am not sure if that is the case.  I have included what I think are the relevant parts of this code below.  If more is needed just let me know.

I am trying to make an undirected, non-connectable, no timeout advertising beacon with a nine second delay that updates a battery percentage parameter.

//-----------------------------------------------------------------------------
static uint8_t m_beacon_info[APP_BEACON_INFO_LENGTH] =   /**< Information advertised by the Beacon. */
{
 APP_DEVICE_TYPE,     // Manufacturer specific information. Specifies the device type in this implementation.
 APP_ADV_DATA_LENGTH, // Manufacturer specific information. Specifies the length of the
                      // manufacturer specific data in this implementation.
 APP_BEACON_UUID,     // 128 bit UUID value.
 APP_PRD_ID_OFS,      // Manufacturer specific information.  Product ID offset value.
 APP_PCB_REV,         // Manufacturer specific information.  PCB Revision Level.
 APP_FW_MAJ_VERS,     // Manufacturer specific information.  Firmware Major Version
 APP_FW_MIN_VERS,     // Manufacturer specific information.  Firmware Minor Version
 APP_MEASURED_RSSI,   // Manufacturer specific information.  The Beacon's measured TX power in this implementation.
 APP_BATT_PCNT_LVL    // Manufacturer specific information.  The Beacon's measured Battery power in percent
};

//-----------------------------------------------------------------------------
static uint8_array_t ary_beacon_info = 
{
 .size   = 0x0001,          // Number of array entries
 .p_data = m_beacon_info    // pointer to the data
};

//-----------------------------------------------------------------------------
static void advertising_init(void)
{
 uint32_t      loc_err_code;
   ble_advertising_init_t init;

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

   F_Manuf_Data.company_identifier      = APP_COMPANY_IDENTIFIER;
   F_Manuf_Data.data                    = ary_beacon_info;

   init.advdata.name_type               = BLE_ADVDATA_NO_NAME; //BLE_ADVDATA_FULL_NAME;
   init.advdata.include_appearance      = false;
   init.advdata.flags                   = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; // BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
   init.advdata.p_manuf_specific_data   = &F_Manuf_Data;

//   init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
//   init.advdata.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_interval = NON_CONNECTABLE_ADV_INTERVAL;
   init.config.ble_adv_fast_timeout  = 0;  // Never time out APP_ADV_DURATION;

   init.evt_handler = on_adv_evt;

   loc_err_code = ble_advertising_init(&m_advertising, &init);
   APP_ERROR_CHECK(loc_err_code);
}

//-----------------------------------------------------------------------------
static void advertising_start(void)
{
 ret_code_t loc_err_code;

 loc_err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
 APP_ERROR_CHECK(loc_err_code);
 NRF_LOG_INFO("  ble_advertising_start");

 loc_err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
 APP_ERROR_CHECK(loc_err_code);
 NRF_LOG_INFO("  bsp_indication_set");
}

//-----------------------------------------------------------------------------
int main(void)
{
 // Initialize.
 log_init();
 timers_init();
 leds_init();
 power_management_init();
 ble_stack_init();
 advertising_init();

 // Start execution.
 NRF_LOG_INFO("Beacon example started.");
 advertising_start();

 // Enter main loop.
 for (;;)
   {
    idle_state_handle();
   }
}

The defines that I am using are as follows:

#define APP_BEACON_INFO_LENGTH          0x18                               /**< Total length of information advertised by the Beacon. */
#define APP_ADV_DATA_LENGTH             0x16                               /**< Length of manufacturer specific data in the advertisement. */
#define APP_DEVICE_TYPE                 0x02                               /**< 0x02 refers to Beacon. */
#define APP_MEASURED_RSSI               0xB3                               /**< The Beacon's measured RSSI at 1 meter distance in dBm. */
#define APP_BATT_PCNT_LVL               80                                 /**< The percentage amount of battery left. */
#define APP_COMPANY_IDENTIFIER          0x0059                             /**< Company identifier for Nordic Semiconductor ASA. as per www.bluetooth.org. */
#define APP_PRD_ID_OFS                  0x00                               /**< Product ID Offset. */
#define APP_PCB_REV                     0x00                               /**< PCB Revision Level. */
#define APP_FW_MAJ_VERS                 0x00                               /**< Firmware Major Version. */
#define APP_FW_MIN_VERS                 0x80                               /**< Firmware Minor Version. */
#define APP_BEACON_UUID                 0x01, 0x12, 0x23, 0x34, \
                                        0x45, 0x56, 0x67, 0x78, \
                                        0x89, 0x9a, 0xab, 0xbc, \
                                        0xcd, 0xde, 0xef, 0xf0            /**< Proprietary UUID for Beacon. */

I have the nRF_Log enabled and this is what I see continuously:

<info> app_timer: RTC: initialized.

<info> app: Beacon example started.

<error> app: Fatal error

<warning> app: System reset

<info> app_timer: RTC: initialized.

<info> app: Beacon example started.

<error> app: Fatal error

<warning> app: System reset

Any help identifying the fatal error or figuring out why it cannot get past ble_advertising_start would be greatly appreciated.

  • I did what you asked and changed NRF_SDH_BLE_PERIPHERAL_LINK_COUNT to a 1.  It was at 0.  I ran the debugger and yes the RAM_START and the RAM_SIZE needed to be changed so I changed them to match what the debugger came back with on the warning messages.  After doing that, I recompiled and ran the debugger again.  This time I got past the memory issues but now I am getting:

    <info> app_timer: RTC: initialized.

    <info> app: Beacon example started.

    <error> app: ERROR 5 [NRF_ERROR_NOT_FOUND]

    PC at: 0x0002EAD1

    <error> app: End of error report

    This error is occurring at the same place in the code ( loc_err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); ) that used to give me ERROR 18.

  • I think you should start with a different ble_peripheral example, because some of the errors you have here is simply because you are starting from scratch, instead of for instance start with a working ble peripheral examples such as \ble_app_beacon or \ble_app_blinky example in nRF5 SDK v17.1.

    To answer your current problem:

    If you enter into ble_advertising_start() you can find there are 4 places 'return ****' is called. Our of the 4 'return' only sd_ble_gap_adv_start() seems from ble_gap.h can return this error code. The error is due to:

     * @retval ::NRF_ERROR_NOT_FOUND          conn_cfg_tag not found.

    Likely you are missing a proper implementation of ble_stack_init() in main().

  • Actually, I did start with nRF5 v17.1.0 SDK ble_app_beacon.  Once I verified that it was working through nRFConnect, I began to modify it so I could update the advertising packet by way of the manufacturer specific data located within the beacon data that is transmitted.  I added a fixed battery percent value to the struct and bumped up the length counts and verified it on the nRFConnect Raw and saw the update had worked.  After that, I began adding a RTC timer for the dynamic update of the beacon data and the other parts needed to perform the update when the update event occurred.  Also, I am trying to accomplish only sending out a few advertising beacons during the update and then going back to sleep so I can get some kind of current consumption readings over the event cycling.

    So for grins, I made a backup copy of my main.c and took a copy of ble_app_beacon's main.c and stepped on mine.  Recompiled in debug mode.  No issues.  Placed it on the DK board. Verified it was running by a terminal window and could see it on nRFConnect.  All of that checks out.  Next, I will start to modify the advertising beacon data as fixed data entries and verify that as well.  After that, I will go back and add the RTC timer so the data can be updated by RTC event trigger.  I am hoping to get back to that point of development today.  If you have any suggestions for the modifications I am describing, please let me know.

  • I believe the ERROR was occurring because I was trying to use some of the ble_advertising from the ble_beacon_app and then I found case number 262316 as an example of some of the ideas of things to try for dynamic update of the advertising beacon.

    So, to update where I managed to get to, I now have a basic advertising beacon and the event is being triggered.  I can see the advertising beacon on the nRFConnect app.  Here is what does not make sense now.

    1. It is appearing as a connectable device on nRFConnect.

    2. The expected manuf_specific_data is not showing up in the raw advertising beacon data stream.

    Below is the updated code for advertising_init and advertising_start routines:

    //#define cst_ORG_EXAMPLE
    
    
    #define APP_BLE_CONN_CFG_TAG            1                                  /**< A tag identifying the SoftDevice BLE configuration. */
    
    //#define NON_CONNECTABLE_ADV_INTERVAL    MSEC_TO_UNITS(100, UNIT_0_625_MS)  /**< The advertising interval for non-connectable advertisement (100 ms). This value can vary between 100ms to 10.24s). */
    #define NON_CONNECTABLE_ADV_INTERVAL    MSEC_TO_UNITS(5000, UNIT_0_625_MS)  /**< The advertising interval for non-connectable advertisement (100 ms). This value can vary between 100ms to 10.24s). */
    
    #define APP_BEACON_INFO_LENGTH          0x18                               /**< Total length of information advertised by the Beacon. */
    #define APP_ADV_DATA_LENGTH             0x16                               /**< Length of manufacturer specific data in the advertisement. */
    #define APP_DEVICE_TYPE                 0x02                               /**< 0x02 refers to Beacon. */
    #define APP_MEASURED_RSSI               0xC3                               /**< The Beacon's measured RSSI at 1 meter distance in dBm. */
    #define APP_BATT_PCNT_LVL               80                                 /**< The percentage amount of battery left. */
    #define APP_COMPANY_IDENTIFIER          0x0059                             /**< Company identifier for Nordic Semiconductor ASA. as per www.bluetooth.org. */
    #define APP_PRD_ID_OFS                  0x00                               /**< Product ID Offset. */
    #define APP_PCB_REV                     0x00                               /**< PCB Revision Level. */
    #define APP_FW_MAJ_VERS                 0x00                               /**< Firmware Major Version. */
    #define APP_FW_MIN_VERS                 0x80                               /**< Firmware Minor Version. */
    #define APP_BEACON_UUID                 0x01, 0x12, 0x23, 0x34, \
                                            0x45, 0x56, 0x67, 0x78, \
                                            0x89, 0x9a, 0xab, 0xbc, \
                                            0xcd, 0xde, 0xef, 0xf0            /**< Proprietary UUID for Beacon. */
    
    #define DEAD_BEEF                       0xDEADBEEF                         /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
    
    #ifndef cst_ORG_EXAMPLE
    //-----------------------------------------------------------------------------
    // From case number 262316
    
      // data structure intialization
      BLE_ADVERTISING_DEF(pw_advertising);        //< Advertising module instance. 
    
      typedef struct{
    
        ble_advdata_manuf_data_t  manuf_specific_data;
        ble_advertising_init_t    pw_init; 
    
      }pw_ble_adv_data_t;
    
      static pw_ble_adv_data_t         pw_ble_data;
    
      static ble_advdata_manuf_data_t  f_manuf_data;
    
    #endif
    
    //-----------------------------------------------------------------------------
    // From ble_beacon_app example
    
    #ifdef cst_ORG_EXAMPLE
    
      #if defined(USE_UICR_FOR_MAJ_MIN_VALUES)
        #define MAJ_VAL_OFFSET_IN_BEACON_INFO   18                                 /**< Position of the MSB of the Major Value in m_beacon_info array. */
        #define UICR_ADDRESS                    0x10001080                         /**< Address of the UICR register used by this example. The major and minor versions to be encoded into the advertising data will be picked up from this location. */
      #endif
    
      static ble_gap_adv_params_t m_adv_params;                                  /**< Parameters to be passed to the stack when starting advertising. */
      static uint8_t              m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; /**< Advertising handle used to identify an advertising set. */
      static uint8_t              m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX];  /**< Buffer for storing an encoded advertising set. */
    
      //-----------------------------------------------------------------------------
      /**@brief Struct that contains pointers to the encoded advertising data. */
      //-----------------------------------------------------------------------------
      static ble_gap_adv_data_t    m_adv_data =
      {
       .adv_data =
         {
          .p_data = m_enc_advdata,
          .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
         },
    
       .scan_rsp_data =
         {
          .p_data = NULL,
          .len    = 0
         }
      };
    #endif // cst_ORG_EXAMPLE
    
    //-----------------------------------------------------------------------------
    static uint8_t m_beacon_info[APP_BEACON_INFO_LENGTH] =  /**< Information advertised by the Beacon. */
    {
     APP_DEVICE_TYPE,     // Manufacturer specific information. Specifies the device type in this
                          // implementation.
     APP_ADV_DATA_LENGTH, // Manufacturer specific information. Specifies the length of the
                          // manufacturer specific data in this implementation.
     APP_BEACON_UUID,     // 128 bit UUID value.
     APP_PRD_ID_OFS,      // Manufacturer specific information.  Product ID offset value.
     APP_PCB_REV,         // Manufacturer specific information.  PCB Revision Level.
     APP_FW_MAJ_VERS,     // Manufacturer specific information.  Firmware Major Version
     APP_FW_MIN_VERS,     // Manufacturer specific information.  Firmware Minor Version
     APP_MEASURED_RSSI,   // Manufacturer specific information. The Beacon's measured TX power in this implementation.
     APP_BATT_PCNT_LVL    // Manufacturer specific information.  The Beacon's measured Battery power in percent
    };
    
    //-----------------------------------------------------------------------------
    #ifndef cst_ORG_EXAMPLE
    
      static uint8_array_t ary_beacon_info = 
        {
         .size   = 0x0001,          // Number of array entries
         .p_data = m_beacon_info    // pointer to the data
        };
    
    #endif // !cst_ORG_EXAMPLE
    
    
    //-----------------------------------------------------------------------------
    /**@brief Function for initializing the Advertising functionality.
     *
     * @details Encodes the required advertising data and passes it to the stack.
     *          Also builds a structure to be passed to the stack when starting advertising.
     */
    //-----------------------------------------------------------------------------
    static void advertising_init(void)
    {
     uint32_t      err_code;
    
     NRF_LOG_INFO("advertising_init");
    
     #ifdef cst_ORG_EXAMPLE
    
     ble_advdata_t advdata;
     uint8_t       flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
    
     ble_advdata_manuf_data_t manuf_specific_data;
    
     manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER;
    
    #if defined(USE_UICR_FOR_MAJ_MIN_VALUES)
        // If USE_UICR_FOR_MAJ_MIN_VALUES is defined, the major and minor values will be read from the
        // UICR instead of using the default values. The major and minor values obtained from the UICR
        // are encoded into advertising data in big endian order (MSB First).
        // To set the UICR used by this example to a desired value, write to the address 0x10001080
        // using the nrfjprog tool. The command to be used is as follows.
        // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val <your major/minor value>
        // For example, for a major value and minor value of 0xabcd and 0x0102 respectively, the
        // the following command should be used.
        // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val 0xabcd0102
        uint16_t major_value = ((*(uint32_t *)UICR_ADDRESS) & 0xFFFF0000) >> 16;
        uint16_t minor_value = ((*(uint32_t *)UICR_ADDRESS) & 0x0000FFFF);
    
        uint8_t index = MAJ_VAL_OFFSET_IN_BEACON_INFO;
    
        m_beacon_info[index++] = MSB_16(major_value);
        m_beacon_info[index++] = LSB_16(major_value);
    
        m_beacon_info[index++] = MSB_16(minor_value);
        m_beacon_info[index++] = LSB_16(minor_value);
    #endif
    
     manuf_specific_data.data.p_data = (uint8_t *) m_beacon_info;
     manuf_specific_data.data.size   = APP_BEACON_INFO_LENGTH;
    
     // Build and set advertising data.
     memset(&advdata, 0, sizeof(advdata));
    
     advdata.name_type             = BLE_ADVDATA_NO_NAME;
     advdata.flags                 = flags;
     advdata.p_manuf_specific_data = &manuf_specific_data;
    
     // Initialize advertising parameters (used when starting advertising).
     memset(&m_adv_params, 0, sizeof(m_adv_params));
    
     m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
     m_adv_params.p_peer_addr     = NULL;    // Undirected advertisement.
     m_adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
     m_adv_params.interval        = NON_CONNECTABLE_ADV_INTERVAL;
     m_adv_params.duration        = 0;       // Never time out.
    
     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 = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params);
     APP_ERROR_CHECK(err_code);
    
    #else
    
     //-----------------------------------------------------------------------------
     // From case number 262316 
     //-----------------------------------------------------------------------------
    
     f_manuf_data.company_identifier      = APP_COMPANY_IDENTIFIER;
     f_manuf_data.data                    = ary_beacon_info;
    
     memset(&pw_ble_data, 0, sizeof(pw_ble_data));
    
     pw_ble_data.pw_init.advdata.name_type             = BLE_ADVDATA_NO_NAME;
     pw_ble_data.pw_init.advdata.include_appearance    = false;
     pw_ble_data.pw_init.advdata.flags                 = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
     pw_ble_data.pw_init.advdata.p_manuf_specific_data = &f_manuf_data;
     pw_ble_data.pw_init.evt_handler                   = on_adv_evt;
    
     pw_ble_data.pw_init.config.ble_adv_fast_enabled   = true;
     pw_ble_data.pw_init.config.ble_adv_fast_interval  = NON_CONNECTABLE_ADV_INTERVAL;
     pw_ble_data.pw_init.config.ble_adv_fast_timeout   = 0;  // Never timeout
    
     err_code = ble_advertising_init(&pw_advertising, &pw_ble_data.pw_init);
     APP_ERROR_CHECK(err_code);
    
     ble_advertising_conn_cfg_tag_set(&pw_advertising, APP_BLE_CONN_CFG_TAG);
    
    #endif
    }
    
    //-----------------------------------------------------------------------------
    /**@brief Function for starting advertising.
     */
    //-----------------------------------------------------------------------------
    static void advertising_start(void)
    {
     ret_code_t err_code;
    
     NRF_LOG_INFO("advertising_start");
    
     #ifdef cst_ORG_EXAMPLE
    
       err_code = sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG);
       APP_ERROR_CHECK(err_code);
    
       err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
       APP_ERROR_CHECK(err_code);
    
     #else
    
       pw_advertising.adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
       pw_advertising.adv_params.p_peer_addr     = NULL;    // Undirected advertisement.
       pw_advertising.adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
       pw_advertising.adv_params.interval        = NON_CONNECTABLE_ADV_INTERVAL;
       pw_advertising.adv_params.duration        = 0;       // Never time out.
    
       err_code = ble_advertising_start(&pw_advertising, BLE_ADV_MODE_FAST);
       APP_ERROR_CHECK(err_code);
    
     #endif
    }
    
    

    cst_ORG_CODE when defined will bring back the ble_beacon_app.  When not defined, will change the code to remove the ble_beacon_app advertising_init and advertising_start sections of original code and replace it with the updated ble_advertising runtime update capability.  At least that is what I am trying to accomplish.

    Any suggestions on the above two items would be apprciated.

Related