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

pm_init() returning NRF_INTERAL_ERROR

Our nRF52832 setup is:

SDK15.0.0

S132 V6.0.0

We have a setup where we are using BLE for various purposes, in both the central and peripheral roles. We upgrade our uC via I2C rather than over the air, and when we do so we erase the flash from the address 0x1000 to 0x77000 and then write a concatenated image containing both the soft device and our application with the padded regions padded by 0xFF.

We have a situation where pm_init() is failing on a number of devices but not others. All devices have the same image written upon upgrade. A previous question mentioned that the flash became corrupt and a nrfjprog --chiperase would sort out the issue, however the nRF52832 chips is not easily accessible when in the field and performing the above upgrade does not resolve the issue.

The order of initialisation is as follows:

uint32_t ret = app_timer_init();
APP_ERROR_CHECK(ret);

ret = nrf_sdh_enable_request();
APP_ERROR_CHECK(ret);

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);

err_code = nrf_sdh_ble_enable(&ram_start);
APP_ERROR_CHECK(err_code);

NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);

/* Set the sec_mode config */
err_code = sd_ble_gap_device_name_set(&sec_mode,
                                          (const uint8_t *)"",
                                          strlen(""));

/* Set the gap_con_params config */                                          
err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
APP_ERROR_CHECK(err_code);

ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
APP_ERROR_CHECK(err_code);

/* set the conn_params_init_t config */
err_code = ble_conn_params_init(&cp_init);
APP_ERROR_CHECK(err_code);

/* Set up the UUID for a custom service which our device connects to */
err_code = sd_ble_uuid_vs_add(&base_uuid, &uuid_type);
APP_ERROR_CHECK(err_code);

err_code = pm_init(); /* This now fails on some devices */
APP_ERROR_CHECK(err_code);

All other calls to the peer manager, in particular pm_conn_secure() fails with the INVALID_STATE error.

A few questions regarding this issue:

- What is the correct flash initialisation value?

- Which section of flash needs to be erased in order to remove the bond data when performing an upgrade?

- Assuming the flash is corrupt and pm_init() fails leading to pm_peers_delete() being unusable, what is the correct way to recover from this situation?

- Is there a specific environment that pm_init() requires in order to initialise?

  • Hi,

    Flash to be used by FDS (e.g. from Peer Manager) needs to initially (on a fresh product) be in erased state. FDS will initialize flash pages from erased state by adding FDS page headers to the flash pages, and Peer Manager will then use the API provided by FDS for storing and retrieving records.

    As Peer Manager stores the bonding data through FDS, the data is stored as records somewhere in the FDS region of flash (but not at a fixed location within that region.)

    If using our DFU bootloader, the default FDS region location is directly below the bootloader. That is, leading up to the bootloader start address which can be read from UICR.NRFFW[0], also known as BOOTLOADER_START_ADDR. See Memory layout from the Bootloader and DFU modules documentation. If you use a custom bootloader then the FDS data region may be placed elsewhere, depending on the value of UICR.NRFFW[0]. If all 0xFF (erased state) the assumption is no bootloader and FDS pages are put right below the MBR parameter storage page. Otherwise (there is a value written to UICR.NRFFW[0]) the FDS data pages are placed directly below that address. Essentially, the value of UICR.NRFFW[0] tells where the application data area ends, and so instead of BOOTLOADER_START_ADDR it might as well have been named APPLICATION_DATA_END_ADDR or similar.

    Instead of deleting data manually, you should use the Peer Manager API functions pm_peer_data_delete() (for deleting data related to a specific peer) and pm_peers_delete() (for deleting data for all peers.)

    If for some reason a flash page becomes corrupt, erasing the page would be a safe way to get back to a non-corrupt, working state for FDS. Note however that this does lead to data loss (for the data that was stored on that particular page.)

    For details on Peer Manager I refer to the Peer Manager library documentation, and in particular the Usage section.

    Regards,
    Terje

Related