On SDK16.0.0 + Mesh SDK 4.1.0
I am using a Fanstel BT840X module that has an onboard Skyworks SKY66112 PA/LNA.
I followed the Infocenter guide along with an old example (to automatically assign unused PPI and GPIOTE channels). I can see the stronger RSSI and I can provision it fine (nRF Mesh app), but then it times out on 'Requesting Composition Data'.
static ble_opt_t ble_pa_lna_opts;
static mesh_pa_lna_gpiote_params_t m_pa_lna_params;
static void pa_lna_init(uint8_t gpio_pa_pin, uint8_t gpio_lna_pin) {
nrf_ppi_channel_t m_pa_lna_set_ppi_channel;
nrf_ppi_channel_t m_pa_lna_clr_ppi_channel;
uint8_t pa_lna_gpiote_ch = NULL;
memset(&ble_pa_lna_opts, 0, sizeof(ble_opt_t));
memset(&m_pa_lna_params, 0, sizeof(mesh_pa_lna_gpiote_params_t));
// Enable BT840X SKY66112 PA/LNA
nrf_gpio_cfg_output(BT840X_CPS);
nrf_gpio_cfg_output(BT840X_CHL);
nrf_gpio_pin_set(BT840X_CHL);
nrf_gpio_pin_clear(BT840X_CPS); //low=enable, high=bypass
//Already initialized by buttons_init()
//ERROR_CHECK(nrf_drv_gpiote_init());
//Already initialized by saadc_init()
//ERROR_CHECK(nrf_drv_ppi_init());
ERROR_CHECK(nrf_drv_ppi_channel_alloc(&m_pa_lna_set_ppi_channel));
ERROR_CHECK(nrf_drv_ppi_channel_alloc(&m_pa_lna_clr_ppi_channel));
nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);
if((gpio_pa_pin == NULL) && (gpio_lna_pin == NULL)) {
ERROR_CHECK(NRF_ERROR_INVALID_PARAM);
}
if(gpio_pa_pin != NULL) {
if(pa_lna_gpiote_ch == NULL) {
ERROR_CHECK(nrf_drv_gpiote_out_init(gpio_pa_pin, &config));
pa_lna_gpiote_ch = nrf_drv_gpiote_out_task_addr_get(gpio_pa_pin);
}
// BLE PA config
ble_pa_lna_opts.common_opt.pa_lna.pa_cfg.enable = 1;
ble_pa_lna_opts.common_opt.pa_lna.pa_cfg.active_high = 1;
ble_pa_lna_opts.common_opt.pa_lna.pa_cfg.gpio_pin = gpio_pa_pin;
// MESH PA config
m_pa_lna_params.pa_cfg.enable = 1;
m_pa_lna_params.pa_cfg.active_high = 1;
m_pa_lna_params.pa_cfg.gpio_pin = gpio_pa_pin;
}
if(gpio_lna_pin != NULL) {
if(pa_lna_gpiote_ch == NULL) {
ERROR_CHECK(nrf_drv_gpiote_out_init(gpio_lna_pin, &config));
pa_lna_gpiote_ch = nrf_drv_gpiote_out_task_addr_get(gpio_lna_pin);
}
// LNA config
ble_pa_lna_opts.common_opt.pa_lna.lna_cfg.enable = 1;
ble_pa_lna_opts.common_opt.pa_lna.lna_cfg.active_high = 1;
ble_pa_lna_opts.common_opt.pa_lna.lna_cfg.gpio_pin = gpio_lna_pin;
// MESH LNA config
m_pa_lna_params.pa_cfg.enable = 1;
m_pa_lna_params.pa_cfg.active_high = 1;
m_pa_lna_params.pa_cfg.gpio_pin = gpio_lna_pin;
}
// Common BLE PA/LNA config
ble_pa_lna_opts.common_opt.pa_lna.ppi_ch_id_set = m_pa_lna_set_ppi_channel; // PPI channel used for radio pin setting
ble_pa_lna_opts.common_opt.pa_lna.ppi_ch_id_clr = m_pa_lna_clr_ppi_channel; // PPI channel used for radio pin clearing
ble_pa_lna_opts.common_opt.pa_lna.gpiote_ch_id = (pa_lna_gpiote_ch - NRF_GPIOTE_BASE) >> 2; // GPIOTE channel used for radio pin toggling
// Common MESH PA/LNA config, can use same channels as for BLE
m_pa_lna_params.ppi_ch_id_set = ble_pa_lna_opts.common_opt.pa_lna.ppi_ch_id_set;
m_pa_lna_params.ppi_ch_id_clr = ble_pa_lna_opts.common_opt.pa_lna.ppi_ch_id_clr;
m_pa_lna_params.gpiote_ch_id = ble_pa_lna_opts.common_opt.pa_lna.gpiote_ch_id;
__LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "PA/LNA PPI_SET: %u, PPI_CLR: %u, GPIOTE: %u\n", ble_pa_lna_opts.common_opt.pa_lna.ppi_ch_id_set, ble_pa_lna_opts.common_opt.pa_lna.ppi_ch_id_clr, ble_pa_lna_opts.common_opt.pa_lna.gpiote_ch_id);
//ERROR_CHECK(sd_ble_opt_set(BLE_COMMON_OPT_PA_LNA, &ble_pa_lna_opts));
}
This ends up assigning PPI channels 2 & 3 and GPIOTE channel 1. I believe this makes sense since I am using 2 PPI channels for SAADC and 1 GPIOTE channel for app_button.
I added the provisioning_sd_ble_opt_cb() callback and modified prov_start_params in start() for it.
static void provisioning_sd_ble_opt_cb(void) {
ERROR_CHECK(sd_ble_opt_set(BLE_COMMON_OPT_PA_LNA, &ble_pa_lna_opts));
}
static void start(void) {
//rtt_input_enable(app_rtt_input_handler, RTT_INPUT_POLL_PERIOD_MS);
if(!m_device_provisioned) {
static const uint8_t static_auth_data[NRF_MESH_KEY_SIZE] = STATIC_AUTH_DATA;
mesh_provisionee_start_params_t prov_start_params =
{
.p_static_data = static_auth_data,
#if ENABLE_PA_LNA
.prov_sd_ble_opt_set_cb = provisioning_sd_ble_opt_cb,
#else
.prov_sd_ble_opt_set_cb = NULL,
#endif
.prov_complete_cb = provisioning_complete_cb,
.prov_device_identification_start_cb = device_identification_start_cb,
.prov_device_identification_stop_cb = NULL,
.prov_abort_cb = provisioning_aborted_cb,
.p_device_uri = EX_URI_LS_SERVER
};
ERROR_CHECK(mesh_provisionee_prov_start(&prov_start_params));
}
else {
unicast_address_print();
}
ERROR_CHECK(mesh_stack_start());
}
Finally, I modified initialize() to add the calls before and after mesh_init() as per the guide.
static void initialize(void) {
__LOG_INIT(LOG_SRC_APP | LOG_SRC_FRIEND, LOG_LEVEL_DBG1, LOG_CALLBACK_DEFAULT);
uint32_t icRevision = NRF_FICR->INFO.VARIANT;
__LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "IC Revision: %08X (%c%c%c%c)\n", icRevision, (icRevision>>24)&0xFF, (icRevision>>16)&0xFF, (icRevision>>8)&0xFF, icRevision&0xFF);
ERROR_CHECK(app_timer_init());
hal_leds_init();
#if BUTTON_BOARD
//ERROR_CHECK(hal_buttons_init(button_event_handler));
buttons_init(); //using app_button.c
#endif
//SAADC
saadc_init();
saadc_sampling_event_init();
saadc_sampling_event_enable();
#if ENABLE_PA_LNA
pa_lna_init(BT840X_CTX, BT840X_CRX);
#endif
ble_stack_init();
#if MESH_FEATURE_GATT_ENABLED
gap_params_init();
conn_params_init();
#endif
#if ENABLE_PA_LNA
ERROR_CHECK(sd_ble_opt_set(BLE_COMMON_OPT_PA_LNA, &ble_pa_lna_opts));
#endif
mesh_init();
#if ENABLE_PA_LNA
mesh_pa_lna_gpiote_enable(&m_pa_lna_params);
#endif
}
After all this, it provisions fine, but times out on the next step where it's requesting the composition data.
Thanks.