uint32_t pstorage_store(pstorage_handle_t * p_dest, uint8_t * p_src, pstorage_size_t size, pstorage_size_t offset) { 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; } uint32_t storage_addr = p_dest->block_id + offset; uint32_t retval = ble_flash_block_write((uint32_t *)storage_addr, (uint32_t *)p_src, (size /sizeof(uint32_t))); app_notify(p_dest, p_src, PSTORAGE_STORE_OP_CODE, size, retval); return retval; }
/**@brief This function stores in flash the System Attributes related to a specified master. * * @param[in] p_sys_attr System Attributes to be stored. * * @return NRF_SUCCESS on success, an error_code otherwise. */ static uint32_t sys_attr_store(master_sys_attr_t * p_sys_attr) { uint32_t err_code; // Check if flash is full. if (m_sys_attr_in_flash_count >= MAX_BONDS_IN_FLASH) { return NRF_ERROR_NO_MEM; } // Check if this is the first time any System Attributes is stored. if (m_sys_attr_in_flash_count == 0) { // Initialize CRC m_crc_sys_attr = ble_flash_crc16_compute(NULL, 0, NULL); // Find pointer to start of System Attributes flash block. err_code = ble_flash_page_addr(m_bondmngr_config.flash_page_num_sys_attr, &mp_flash_sys_attr); if (err_code != NRF_SUCCESS) { return err_code; } } // Write System Attributes in flash. err_code = ble_flash_block_write(mp_flash_sys_attr + 1, (uint32_t *)p_sys_attr, sizeof(master_sys_attr_t) / sizeof(uint32_t)); if (err_code != NRF_SUCCESS) { return err_code; } m_crc_sys_attr = ble_flash_crc16_compute((uint8_t *)p_sys_attr, sizeof(master_sys_attr_t), &m_crc_sys_attr); // Write header err_code = ble_flash_word_write(mp_flash_sys_attr, BLE_FLASH_MAGIC_NUMBER | m_crc_sys_attr); if (err_code != NRF_SUCCESS) { return err_code; } // Update flash pointer mp_flash_sys_attr += ((sizeof(master_sys_attr_t) / sizeof(uint32_t)) + 1); m_sys_attr_in_flash_count++; return NRF_SUCCESS; }
/**@brief This function stores the Bonding Information of the specified master to the flash. * * @param[in] p_bond Bonding information to be stored. * * @return NRF_SUCCESS on success, an error_code otherwise. */ static uint32_t bond_info_store(master_bond_t * p_bond) { uint32_t err_code; // Check if flash is full if (m_bond_info_in_flash_count >= MAX_BONDS_IN_FLASH) { return NRF_ERROR_NO_MEM; } // Check if this is the first bond to be stored if (m_bond_info_in_flash_count == 0) { // Initialize CRC 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(m_bondmngr_config.flash_page_num_bond, &mp_flash_bond_info); if (err_code != NRF_SUCCESS) { return err_code; } } // Write Bonding Information err_code = ble_flash_block_write(mp_flash_bond_info + 1, (uint32_t *)p_bond, sizeof(master_bond_t) / sizeof(uint32_t)); if (err_code != NRF_SUCCESS) { return err_code; } m_crc_bond_info = ble_flash_crc16_compute((uint8_t *)p_bond, sizeof(master_bond_t), &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; } // Update flash pointer mp_flash_bond_info += (sizeof(master_bond_t) / sizeof(uint32_t)) + 1; m_bond_info_in_flash_count++; 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 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; }