I am trying to get an nRF52811 to do extended advertising.
I am using: nRF5_SDK_17.0.2, version 7.2.0 of s140, SEGGER Embedded Studio 4.52, Windows 10
I have stripped down the rscs example and gotten it to run on both an nRF52840 and an nRF52811. Using a modified version of the rscs_c example, I can detect extended advertisements from the nRF52840, but not from the nRF52811. It does not crash on the nRF52811, just fails to send advertisements that I can detect.
The two versions use the exact same main.c, included here:
#include <stdint.h>
#include <string.h>
#include "ble_advertising.h"
#include "nrf_sdh.h"
#include "app_timer.h"
#include "nrf_ble_gatt.h"
#include "nrf_ble_qwr.h"
#include "ble_bas.h"
#include "SEGGER_RTT.h"
#define DEVICE_NAME "nRF Ext Adv" /**< Name of device. Will be included in the advertising data. */
#define APP_ADV_INTERVAL 40 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 25 ms). */
#define APP_ADV_DURATION BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
#define APP_BLE_OBSERVER_PRIO 3 /**< Application's BLE observer priority. You shouldn't need to modify this value. */
#define APP_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */
#define MIN_CONN_INTERVAL MSEC_TO_UNITS(500, UNIT_1_25_MS) /**< Minimum acceptable connection interval (0.5 seconds). */
#define MAX_CONN_INTERVAL MSEC_TO_UNITS(1000, UNIT_1_25_MS) /**< Maximum acceptable connection interval (1 second). */
#define SLAVE_LATENCY 0 /**< Slave latency. */
#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds). */
#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */
#define DEAD_BEEF 0xDEADBEEF /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
APP_TIMER_DEF(m_rsc_meas_timer_id); /**< RSC measurement timer. */
NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */
BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */
static ble_uuid_t m_adv_uuids[] = {}; /**< Universally unique service identifiers. */
static void ble_stack_init(void);
static void gap_params_init(void);
static void gatt_init(void);
static void advertising_init(void);
static void advertising_start(bool erase_bonds);;
void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name);
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context);
static void idle_state_handle(void);
static void rsc_meas_timeout_handler(void * p_context);
static void application_timers_start(void);
static void on_adv_evt(ble_adv_evt_t ble_adv_evt);
static void timers_init();
/******************************************************************************/
/**@brief Function for application main entry.
*/
int main(void)
{
bool erase_bonds;
// Initialize.
timers_init();
ble_stack_init();
gap_params_init();
gatt_init();
advertising_init();
// Start execution.
SEGGER_RTT_WriteString(0, "Simple Extended Advertiser.\r\n");
application_timers_start();
advertising_start(erase_bonds);
// Enter main loop.
for (;;) {
idle_state_handle();
}
}
/******************************************************************************/
/**@brief Function for the Timer initialization.
*
* @details Initializes the timer module. This creates and starts application timers.
*/
static void timers_init(void)
{
ret_code_t err_code;
// Initialize timer module.
err_code = app_timer_init();
APP_ERROR_CHECK(err_code);
// Create timers.
err_code = app_timer_create(&m_rsc_meas_timer_id,
APP_TIMER_MODE_REPEATED,
rsc_meas_timeout_handler);
APP_ERROR_CHECK(err_code);
}
/******************************************************************************/
/**@brief Function for initializing the BLE stack.
*
* @details Initializes the SoftDevice and the BLE event interrupt.
*/
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);
}
/******************************************************************************/
/**@brief Function for the GAP initialization.
*
* @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
* device including the device name, appearance, and the preferred connection parameters.
*/
static void gap_params_init(void)
{
ret_code_t err_code;
ble_gap_conn_params_t gap_conn_params;
ble_gap_conn_sec_mode_t sec_mode;
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);
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 initializing the GATT module.
*/
static void gatt_init(void)
{
ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
APP_ERROR_CHECK(err_code);
}
/******************************************************************************/
/**@brief Function for initializing the Advertising functionality.
*/
static void advertising_init(void)
{
ret_code_t err_code;
ble_advertising_init_t init;
memset(&init, 0, sizeof(init));
init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
init.advdata.include_appearance = false;
init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
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_timeout = APP_ADV_DURATION;
init.config.ble_adv_primary_phy = BLE_GAP_PHY_1MBPS;
init.config.ble_adv_secondary_phy = BLE_GAP_PHY_2MBPS;
init.config.ble_adv_extended_enabled = true;
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);
}
/******************************************************************************/
/**@brief Function for starting advertising.
*/
static void advertising_start(bool erase_bonds)
{
ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
APP_ERROR_CHECK(err_code);
}
/******************************************************************************/
/**@brief Callback function for 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] 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(DEAD_BEEF, line_num, p_file_name);
}
/******************************************************************************/
/**@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 = NRF_SUCCESS;
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
{
SEGGER_RTT_WriteString(0,"PHY update request.\r\n");
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.
SEGGER_RTT_WriteString(0,"GATT Client Timeout.\r\n");
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.
SEGGER_RTT_WriteString(0,"GATT Server Timeout.\r\n");
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:
SEGGER_RTT_printf(0,"ble_evt_handler()- Unhandled event type, %d\r\n", p_ble_evt->header.evt_id);
// No implementation needed.
break;
}
}
/**@brief Function for handling the idle state (main loop).
*
* @details If there is no pending log operation, then sleep until next the next event occurs.
*/
static void idle_state_handle(void)
{
SEGGER_RTT_WriteString(0, "idle_state_handler()\r\n");
}
//====
/******************************************************************************/
/**@brief Function for handling the Running Speed and Cadence measurement timer timeout.
*
* @details This function will be called each time the running speed and cadence
* measurement timer expires.
*
* @param[in] p_context Pointer used for passing some arbitrary information (context) from the
* app_start_timer() call to the timeout handler.
*/
static void rsc_meas_timeout_handler(void * p_context)
{
ret_code_t err_code;
UNUSED_PARAMETER(p_context);
SEGGER_RTT_WriteString(0, "Measurement Timer Handler!\r\n");
}
/******************************************************************************/
/**@brief Function for starting application timers.
*/
static void application_timers_start(void)
{
ret_code_t err_code;
uint32_t rsc_meas_timer_ticks;
// Start application timers.
rsc_meas_timer_ticks = APP_TIMER_TICKS(1000); // 1Hz
err_code = app_timer_start(m_rsc_meas_timer_id, rsc_meas_timer_ticks, NULL);
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)
{
ret_code_t err_code;
SEGGER_RTT_WriteString(0, "on_adv_evt()!\r\n");
switch (ble_adv_evt)
{
case BLE_ADV_EVT_FAST:
SEGGER_RTT_WriteString(0,"Fast advertising.\r\n");
break;
case BLE_ADV_EVT_IDLE:
SEGGER_RTT_WriteString(0,"Idle.\r\n");
break;
default:
SEGGER_RTT_printf(0,"on_adv_evt() - Unhandled event, %d\r\n", ble_adv_evt);
break;
}
}
The only differences between the two .emProject files are these:
2,3c2,3 < <solution Name="ble_app_rscs_pca10056_s140" target="8" version="2"> < <project Name="ble_app_rscs_pca10056_s140"> --- > <solution Name="ble_app_rscs_pca10056e_52811_s140" target="8" version="2"> > <project Name="ble_app_rscs_pca10056e_52811_s140"> 17c17 < arm_target_device_name="nRF52840_xxAA" --- > arm_target_device_name="nRF52811_xxAA" 26c26 < NRF52840_XXAA; --- > NRF52811_XXAA; 164c164 < debug_register_definition_file="../../../../../../modules/nrfx/mdk/nrf52840.svd" --- > debug_register_definition_file="../../../../../../modules/nrfx/mdk/nrf52811.svd" 175c175 < FLASH_PH_SIZE=0x100000; --- > FLASH_PH_SIZE=0x30000; 177c177 < RAM_PH_SIZE=0x40000; --- > RAM_PH_SIZE=0x6000; 179,181c179,181 < FLASH_SIZE=0xd9000; < RAM_START=0x20002260; < RAM_SIZE=0x3dda0" --- > FLASH_SIZE=0x9000; > RAM_START=0x20002300; > RAM_SIZE=0x3d00" 216c216 < <file file_name="../../../../../../modules/nrfx/mdk/ses_startup_nrf52840.s" /> --- > <file file_name="../../../../../../modules/nrfx/mdk/ses_startup_nrf52811.s" /> 218c218 < <file file_name="../../../../../../modules/nrfx/mdk/system_nrf52840.c" /> --- > <file file_name="../../../../../../modules/nrfx/mdk/system_nrf52811.c" />
The sdk_config.h for the nRF52840 has many more *_ENABLED defines, none of which are enabled. Other than that, the only differences between the two sdk_config.h are these:
456c438 < #define NRFX_PRS_BOX_2_ENABLED 0 --- > #define NRFX_PRS_BOX_2_ENABLED 1 919c835 < #define NRF_PWR_MGMT_CONFIG_FPU_SUPPORT_ENABLED 1 --- > #define NRF_PWR_MGMT_CONFIG_FPU_SUPPORT_ENABLED 0
I would appreciate any help you can give in figuring out why this will run on the nRF52840 but not the nRF52811.
Thanks,
Craig