uint32_t ble_central_bondmngr_init(ble_central_bondmngr_t * p_bm, ble_central_bondmngr_init_t * p_bm_init) { uint32_t err_code; p_bm->p_sec_params = p_bm_init->p_sec_params; bond_info.keyset.keys_periph.p_enc_key = &bond_info.enc_key; if (p_bm_init->delete_bonds) { err_code = ble_flash_page_erase(BLE_CENTRAL_BONDMNGR_PAGE_NUM); if (err_code != NRF_SUCCESS) return err_code; } else { uint8_t size_to_read = sizeof(bond_info)/sizeof(uint32_t); err_code = ble_flash_page_read(BLE_CENTRAL_BONDMNGR_PAGE_NUM, (uint32_t *) &bond_info, &size_to_read); if (err_code != NRF_ERROR_NOT_FOUND && err_code != NRF_SUCCESS) return err_code; printf("Restoring data from %d, %d...\r\n", BLE_CENTRAL_BONDMNGR_PAGE_NUM, BLE_CENTRAL_BONDMNGR_PAGE_NUM*NRF_FICR->CODEPAGESIZE); } print_address(&bond_info.addr); return NRF_SUCCESS; }
uint32_t pstorage_clear(pstorage_handle_t * p_dest, pstorage_size_t size) { uint32_t page_addr; uint32_t retval; uint16_t page_count; VERIFY_MODULE_INITIALIZED(); NULL_PARAM_CHECK(p_dest); MODULE_ID_RANGE_CHECK(p_dest); page_addr = p_dest->block_id / BLE_FLASH_PAGE_SIZE; retval = NRF_SUCCESS; for (page_count = 0; page_count < m_app_table[p_dest->module_id].no_of_pages; page_count++) { retval = ble_flash_page_erase(page_addr); page_addr++; if (retval != NRF_SUCCESS) { break; } } app_notify(p_dest, NULL, PSTORAGE_CLEAR_OP_CODE, size, retval); return retval; }
void persistent_init(void) { uint8_t i, j; uint8_t buf[16], buf2[4]; uint32_t magic32 = 0xEFBEADDE; // reverse DEADBEEF uint32_t ido2Name1 = 0x326F4469; // reverse iDo2 uint32_t ido2Name2 = 0x00000000; // string end uint32_t tmp32; uint32_t buf32[64]; __debug_sizeof_persistent_page = sizeof(struct persistent_page); pidx = (uint8_t)PERSISTENT_PAGE_IDX; HalFlashRead(pidx, 0, buf, 4); HalFlashRead((pidx + 1), 0, buf2, 4); if (memcmp(buf2, PERSISTENT_MAGIC, 4) == 0) { if (memcmp(buf, PERSISTENT_MAGIC, 4) != 0) { ble_flash_page_erase(pidx); for (i = 0; i < 4; i++) { HalFlashRead((pidx + 1), (uint16_t)i * 256, (uint8_t *)buf32, 256); for (j = 0; j < 64; j++) { flash_word_unprotected_write((uint32_t *)((uint32_t)pidx * 1024 + (uint32_t)i * 256 + (uint32_t)j * 4), buf32[j]); } } } ble_flash_page_erase(pidx + 1); } else { if (memcmp(buf, PERSISTENT_MAGIC, 4) != 0) { // This is invoked before softdevice and radio ble_flash_page_erase(pidx); flash_word_unprotected_write((uint32_t *)((uint32_t)pidx * 1024), magic32); flash_word_unprotected_write((uint32_t *)((uint32_t)pidx * 1024 + 4), ido2Name1); flash_word_unprotected_write((uint32_t *)((uint32_t)pidx * 1024 + 8), ido2Name2); } } // Update boot count HalFlashRead(pidx, 24, buf, 16); boot_cnt = __persistent_mark_bit_map(buf, 16); // Write back for (i = 0; i < 4; i++) { tmp32 = ((uint32_t)buf[i * 4 + 3] << 24) | ((uint32_t)buf[i * 4 + 2] << 16) | ((uint32_t)buf[i * 4 + 1] << 8) | (uint32_t)buf[i * 4]; flash_word_unprotected_write((uint32_t *)((uint32_t)pidx * 1024 + 24 + i * 4), tmp32); } }
/**@brief This function erases flash pages that contain Bonding Information and System * Attributes. * * @return NRF_SUCCESS on success, otherwise an error code. */ static uint32_t flash_pages_erase(void) { uint32_t err_code; err_code = ble_flash_page_erase(m_bondmngr_config.flash_page_num_bond); if (err_code != NRF_SUCCESS) { return err_code; } err_code = ble_flash_page_erase(m_bondmngr_config.flash_page_num_sys_attr); if (err_code != NRF_SUCCESS) { return err_code; } return NRF_SUCCESS; }
static void bootloader_settings_save(bootloader_settings_t settings) { const bootloader_settings_t * p_bootloader_settings; bootloader_util_settings_get(&p_bootloader_settings); // Save needed data for later use. uint32_t settings_page = ((uint32_t) p_bootloader_settings) / NRF_FICR->CODEPAGESIZE; uint32_t num_of_words = sizeof(bootloader_settings_t) / sizeof(uint32_t); // Save bootloader settings. uint32_t err_code = ble_flash_page_erase(settings_page); APP_ERROR_CHECK(err_code); err_code = ble_flash_block_write((uint32_t *)p_bootloader_settings, (uint32_t *)&settings, num_of_words); APP_ERROR_CHECK(err_code); }
uint32_t bond_store_user_id(void) { uint32_t err_code; uint16_t m_crc_bond_info; uint32_t *mp_flash_bond_info; /* inialize crc check */ m_crc_bond_info = ble_flash_crc16_compute(NULL, 0, NULL); // Find pointer to start of bond information flash block err_code = ble_flash_page_addr(FLASH_PAGE_USER_ID, &mp_flash_bond_info); if (err_code != NRF_SUCCESS) { return err_code; } /*FIXME: erase a page while bluetooth connected may cause disconnect, so this maybe stored when bluetooth disconnected*/ /* Erase the whole page */ ble_flash_page_erase(FLASH_PAGE_USER_ID); // Write private bonding Information err_code = ble_flash_block_write(mp_flash_bond_info + 1, //the first word is used to store crc (uint32_t *)user_id, ((USER_ID_LENGTH - 1) / (4) + 1)); if (err_code != NRF_SUCCESS) { return err_code; } m_crc_bond_info = ble_flash_crc16_compute((uint8_t *)user_id, USER_ID_LENGTH, &m_crc_bond_info); // Write header err_code = ble_flash_word_write(mp_flash_bond_info, BLE_FLASH_MAGIC_NUMBER | m_crc_bond_info); if (err_code != NRF_SUCCESS) { return err_code; } return NRF_SUCCESS; }
uint32_t ble_central_bondmngr_store(ble_central_bondmngr_t * p_bm) { uint32_t err_code; print_address(&bond_info.addr); err_code = ble_flash_page_erase(BLE_CENTRAL_BONDMNGR_PAGE_NUM); if (err_code != NRF_SUCCESS) { return err_code; } printf("Writing %d b to %d\r\n", sizeof(bond_info)/sizeof(uint32_t), BLE_CENTRAL_BONDMNGR_PAGE_NUM); err_code = ble_flash_page_write(BLE_CENTRAL_BONDMNGR_PAGE_NUM, (uint32_t *) &bond_info, sizeof(bond_info)/sizeof(uint32_t)); if (err_code != NRF_SUCCESS) { return err_code; } return NRF_SUCCESS; }
uint32_t ble_error_log_read(ble_error_log_data_t * error_log) { uint8_t error_log_size = CEIL_DIV(sizeof(ble_error_log_data_t), sizeof(uint32_t)); uint32_t err_code = NRF_SUCCESS; err_code = ble_flash_page_read(FLASH_PAGE_ERROR_LOG, (uint32_t *) error_log, &error_log_size); // If nothing is in flash; then return NRF_SUCCESS. if (err_code == NRF_ERROR_NOT_FOUND) { return NRF_SUCCESS; } if (err_code != NRF_SUCCESS) { return err_code; } if (!error_log->failure) { return NRF_SUCCESS; } nrf_gpio_pin_set(LOG_LED_PIN_NO); // Notify that a message exists in the log. while (error_log->failure && !m_ble_log_clear_flag) { // Put breakpoint, and read data, then log->failure=false; to continue in debug mode. // In application, define how to clear the error log, // e.g. read button 6, if pressed, then clear log and continue. } nrf_gpio_pin_clear(LOG_LED_PIN_NO); err_code = ble_flash_page_erase(FLASH_PAGE_ERROR_LOG); return err_code; }
uint32_t ble_bondmngr_bonded_masters_store(void) { uint32_t err_code; int i; if (!m_is_bondmngr_initialized) { return NRF_ERROR_INVALID_STATE; } if (m_master.bond.master_handle != INVALID_MASTER_HANDLE) { // Fetch System Attributes from stack. uint16_t sys_attr_size = SYS_ATTR_BUFFER_MAX_LEN; err_code = sd_ble_gatts_sys_attr_get(m_conn_handle, m_master.sys_attr.sys_attr, &sys_attr_size); if (err_code != NRF_SUCCESS) { return err_code; } m_master.sys_attr.master_handle = m_master.bond.master_handle; m_master.sys_attr.sys_attr_size = (uint16_t)sys_attr_size; // Update current master err_code = master_update(); if (err_code != NRF_SUCCESS) { return err_code; } } // Save Bonding Information if changed if (bond_info_changed()) { // Erase flash page err_code = ble_flash_page_erase(m_bondmngr_config.flash_page_num_bond); if (err_code != NRF_SUCCESS) { return err_code; } // Store bond information for all masters m_bond_info_in_flash_count = 0; for (i = 0; i < m_masters_in_db_count; i++) { err_code = bond_info_store(&m_masters_db[i].bond); if (err_code != NRF_SUCCESS) { return err_code; } } } // Save System Attributes, if changed if (sys_attr_changed()) { // Erase flash page err_code = ble_flash_page_erase(m_bondmngr_config.flash_page_num_sys_attr); if (err_code != NRF_SUCCESS) { return err_code; } // Store System Attributes for all masters m_sys_attr_in_flash_count = 0; for (i = 0; i < m_masters_in_db_count; i++) { err_code = sys_attr_store(&m_masters_db[i].sys_attr); if (err_code != NRF_SUCCESS) { return err_code; } } } m_conn_handle = BLE_CONN_HANDLE_INVALID; m_master.bond.master_handle = INVALID_MASTER_HANDLE; m_master.sys_attr.master_handle = INVALID_MASTER_HANDLE; m_master.sys_attr.sys_attr_size = 0; return NRF_SUCCESS; }
uint32_t pstorage_update(pstorage_handle_t * p_dest, uint8_t * p_src, pstorage_size_t size, pstorage_size_t offset) { uint32_t *p_swap_addr = (uint32_t *)PSTORAGE_SWAP_ADDR; uint32_t *p_page_addr1 = (uint32_t *) PAGE_BASE_ADDR(p_dest->block_id + offset); #ifdef SUPPORT_MODULES_LARGER_THAN_PAGE uint32_t *p_page_addr2 = (uint32_t *) PAGE_BASE_ADDR(p_dest->block_id + offset + size-1); #endif uint16_t head_word_count = offset/sizeof(uint32_t); uint16_t body_word_count = size/sizeof(uint32_t); uint16_t tail_word_count; uint32_t retval; VERIFY_MODULE_INITIALIZED(); NULL_PARAM_CHECK(p_src); NULL_PARAM_CHECK(p_dest); MODULE_ID_RANGE_CHECK(p_dest); BLOCK_ID_RANGE_CHECK(p_dest); SIZE_CHECK(p_dest, size); OFFSET_CHECK(p_dest, offset, size); // Verify word alignment. if ((!is_word_aligned(p_src)) || (!is_word_aligned((void *)(uint32_t)offset))) { return NRF_ERROR_INVALID_ADDR; } // erase swap page (void) ble_flash_page_erase(PSTORAGE_SWAP_ADDR / BLE_FLASH_PAGE_SIZE); #ifdef SUPPORT_MODULES_LARGER_THAN_PAGE if (p_page_addr1 == p_page_addr2) { #endif // tail is in the same page as head tail_word_count = BLE_FLASH_PAGE_SIZE/sizeof(uint32_t) - head_word_count - body_word_count; // copy of the head if (head_word_count) { retval = ble_flash_block_write(p_swap_addr, p_page_addr1, head_word_count ); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } } // copy of the body retval = ble_flash_block_write(p_swap_addr+head_word_count, (uint32_t *)p_src, body_word_count); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } // copy of the tail if (tail_word_count) { retval = ble_flash_block_write(p_swap_addr+head_word_count+body_word_count, p_page_addr1+head_word_count+body_word_count, tail_word_count ); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } } // erase active page (void) ble_flash_page_erase((uint32_t)p_page_addr1 / BLE_FLASH_PAGE_SIZE); // restore updated page retval = ble_flash_block_write(p_page_addr1, p_swap_addr, BLE_FLASH_PAGE_SIZE/sizeof(uint32_t)); #ifdef SUPPORT_MODULES_LARGER_THAN_PAGE } else { // tail is in NOT in the same page as head - need to swap twice uint16_t body1_word_count = BLE_FLASH_PAGE_SIZE/sizeof(uint32_t) - head_word_count; uint16_t body2_word_count = body_word_count - body1_word_count; tail_word_count = BLE_FLASH_PAGE_SIZE/sizeof(uint32_t) - body2_word_count; // copy head retval = ble_flash_block_write(p_swap_addr, p_page_addr1, head_word_count ); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } // copy body1 retval = ble_flash_block_write(p_swap_addr, (uint32_t *)p_src, body1_word_count ); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } // erase active page (void) ble_flash_page_erase((uint32_t)p_page_addr1 / BLE_FLASH_PAGE_SIZE); // restore updated page1 retval = ble_flash_block_write(p_page_addr1, p_swap_addr, BLE_FLASH_PAGE_SIZE/sizeof(uint32_t)); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } // erase swap page (void) ble_flash_page_erase(PSTORAGE_SWAP_ADDR / BLE_FLASH_PAGE_SIZE); // copy body2 retval = ble_flash_block_write(p_swap_addr, (uint32_t *)p_src + body1_word_count, body2_word_count ); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } // copy tail retval = ble_flash_block_write(p_swap_addr, p_page_addr2+body2_word_count, tail_word_count ); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } // erase active page (void) ble_flash_page_erase((uint32_t)p_page_addr2 / BLE_FLASH_PAGE_SIZE); // restore updated page2 retval = ble_flash_block_write(p_page_addr2, p_swap_addr, BLE_FLASH_PAGE_SIZE/sizeof(uint32_t)); if (retval != NRF_SUCCESS) { app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; } } #endif app_notify(p_dest, p_src, PSTORAGE_UPDATE_OP_CODE, size, retval); return retval; }