Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of nrf51-sdk by
ble_flash.c
00001 /* 00002 * Copyright (c) Nordic Semiconductor ASA 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without modification, 00006 * are permitted provided that the following conditions are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright notice, this 00009 * list of conditions and the following disclaimer. 00010 * 00011 * 2. Redistributions in binary form must reproduce the above copyright notice, this 00012 * list of conditions and the following disclaimer in the documentation and/or 00013 * other materials provided with the distribution. 00014 * 00015 * 3. Neither the name of Nordic Semiconductor ASA nor the names of other 00016 * contributors to this software may be used to endorse or promote products 00017 * derived from this software without specific prior written permission. 00018 * 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00021 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00023 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00024 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 00027 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 * 00031 */ 00032 00033 #include "ble_flash.h " 00034 #include <stdlib.h> 00035 #include <stdint.h> 00036 #include <string.h> 00037 #include "nrf_soc.h" 00038 #include "nordic_common.h" 00039 #include "nrf_error.h" 00040 #include "nrf.h" 00041 #include "app_util.h " 00042 00043 00044 static volatile bool m_radio_active = false; /**< TRUE if radio is active (or about to become active), FALSE otherwise. */ 00045 00046 00047 uint16_t ble_flash_crc16_compute(uint8_t * p_data, uint16_t size, uint16_t * p_crc) 00048 { 00049 uint16_t i; 00050 uint16_t crc = (p_crc == NULL) ? 0xffff : *p_crc; 00051 00052 for (i = 0; i < size; i++) 00053 { 00054 crc = (unsigned char)(crc >> 8) | (crc << 8); 00055 crc ^= p_data[i]; 00056 crc ^= (unsigned char)(crc & 0xff) >> 4; 00057 crc ^= (crc << 8) << 4; 00058 crc ^= ((crc & 0xff) << 4) << 1; 00059 } 00060 return crc; 00061 } 00062 00063 00064 /**@brief Function for erasing a page in flash. 00065 * 00066 * @param[in] p_page Pointer to first word in page to be erased. 00067 */ 00068 static void flash_page_erase(uint32_t * p_page) 00069 { 00070 // Turn on flash erase enable and wait until the NVMC is ready. 00071 NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos); 00072 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00073 { 00074 // Do nothing. 00075 } 00076 00077 // Erase page. 00078 NRF_NVMC->ERASEPAGE = (uint32_t)p_page; 00079 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00080 { 00081 // Do nothing. 00082 } 00083 00084 // Turn off flash erase enable and wait until the NVMC is ready. 00085 NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); 00086 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00087 { 00088 // Do nothing 00089 } 00090 } 00091 00092 00093 /**@brief Function for writing one word to flash. Unprotected write, which can interfere with radio communication. 00094 * 00095 * @details This function DOES NOT use the m_radio_active variable, but will force the write even 00096 * when the radio is active. To be used only from @ref ble_flash_page_write. 00097 * 00098 * @note Flash location to be written must have been erased previously. 00099 * 00100 * @param[in] p_address Pointer to flash location to be written. 00101 * @param[in] value Value to write to flash. 00102 */ 00103 static void flash_word_unprotected_write(uint32_t * p_address, uint32_t value) 00104 { 00105 // Turn on flash write enable and wait until the NVMC is ready. 00106 NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos); 00107 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00108 { 00109 // Do nothing. 00110 } 00111 *p_address = value; 00112 00113 // Wait flash write to finish 00114 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00115 { 00116 // Do nothing. 00117 } 00118 00119 // Turn off flash write enable and wait until the NVMC is ready. 00120 NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); 00121 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00122 { 00123 // Do nothing. 00124 } 00125 } 00126 00127 00128 /**@brief Function for writing one word to flash. 00129 * 00130 * @note Flash location to be written must have been erased previously. 00131 * 00132 * @param[in] p_address Pointer to flash location to be written. 00133 * @param[in] value Value to write to flash. 00134 */ 00135 static void flash_word_write(uint32_t * p_address, uint32_t value) 00136 { 00137 // If radio is active, wait for it to become inactive. 00138 while (m_radio_active) 00139 { 00140 // Do nothing (just wait for radio to become inactive). 00141 (void) sd_app_evt_wait(); 00142 } 00143 00144 // Turn on flash write enable and wait until the NVMC is ready. 00145 NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos); 00146 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00147 { 00148 // Do nothing. 00149 } 00150 00151 *p_address = value; 00152 // Wait flash write to finish 00153 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00154 { 00155 // Do nothing. 00156 } 00157 // Turn off flash write enable and wait until the NVMC is ready. 00158 NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); 00159 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00160 { 00161 // Do nothing 00162 } 00163 } 00164 00165 00166 uint32_t ble_flash_word_write(uint32_t * p_address, uint32_t value) 00167 { 00168 flash_word_write(p_address, value); 00169 return NRF_SUCCESS; 00170 } 00171 00172 00173 uint32_t ble_flash_block_write(uint32_t * p_address, uint32_t * p_in_array, uint16_t word_count) 00174 { 00175 uint16_t i; 00176 00177 for (i = 0; i < word_count; i++) 00178 { 00179 flash_word_write(p_address, p_in_array[i]); 00180 p_address++; 00181 } 00182 00183 return NRF_SUCCESS; 00184 } 00185 00186 00187 uint32_t ble_flash_page_erase(uint8_t page_num) 00188 { 00189 uint32_t * p_page = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num); 00190 flash_page_erase(p_page); 00191 00192 return NRF_SUCCESS; 00193 } 00194 00195 00196 uint32_t ble_flash_page_write(uint8_t page_num, uint32_t * p_in_array, uint8_t word_count) 00197 { 00198 int i; 00199 uint32_t * p_page; 00200 uint32_t * p_curr_addr; 00201 uint16_t in_data_crc; 00202 uint16_t flash_crc; 00203 uint32_t flash_header; 00204 00205 p_page = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num); 00206 p_curr_addr = p_page; 00207 00208 // Calculate CRC of the data to write. 00209 in_data_crc = ble_flash_crc16_compute((uint8_t *)p_in_array, 00210 word_count * sizeof(uint32_t), 00211 NULL); 00212 00213 // Compare the calculated to the one in flash. 00214 flash_header = *p_curr_addr; 00215 flash_crc = (uint16_t)flash_header; 00216 00217 if (flash_crc == in_data_crc) 00218 { 00219 // Data is the same as the data already stored in flash, return without modifying flash. 00220 return NRF_SUCCESS; 00221 } 00222 00223 // Erase flash page 00224 flash_page_erase(p_page); 00225 00226 // Reserve space for magic number (for detecting if flash content is valid). 00227 p_curr_addr++; 00228 00229 // Reserve space for saving word_count. 00230 p_curr_addr++; 00231 00232 // Write data 00233 for (i = 0; i < word_count; i++) 00234 { 00235 flash_word_unprotected_write(p_curr_addr, p_in_array[i]); 00236 p_curr_addr++; 00237 } 00238 00239 // Write number of elements. 00240 flash_word_write(p_page + 1, (uint32_t)(word_count)); 00241 00242 // Write magic number and CRC to indicate that flash content is valid. 00243 flash_header = BLE_FLASH_MAGIC_NUMBER | (uint32_t)in_data_crc; 00244 flash_word_write(p_page, flash_header); 00245 00246 return NRF_SUCCESS; 00247 } 00248 00249 00250 uint32_t ble_flash_page_read(uint8_t page_num, uint32_t * p_out_array, uint8_t * p_word_count) 00251 { 00252 int byte_count; 00253 uint32_t * p_page; 00254 uint32_t * p_curr_addr; 00255 uint32_t flash_header; 00256 uint32_t calc_header; 00257 uint16_t calc_crc; 00258 uint32_t tmp; 00259 00260 p_page = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num); 00261 p_curr_addr = p_page; 00262 00263 // Check if block is valid 00264 flash_header = *p_curr_addr; 00265 tmp = flash_header & 0xFFFF0000; 00266 if (tmp != BLE_FLASH_MAGIC_NUMBER) 00267 { 00268 *p_word_count = 0; 00269 return NRF_ERROR_NOT_FOUND; 00270 } 00271 p_curr_addr++; 00272 00273 // Read number of elements 00274 *p_word_count = (uint8_t)(*(p_curr_addr)); 00275 p_curr_addr++; 00276 00277 // Read data 00278 byte_count = (*p_word_count) * sizeof(uint32_t); 00279 memcpy(p_out_array, p_curr_addr, byte_count); 00280 00281 // Check CRC 00282 calc_crc = ble_flash_crc16_compute((uint8_t *)p_out_array, 00283 (*p_word_count) * sizeof(uint32_t), 00284 NULL); 00285 calc_header = BLE_FLASH_MAGIC_NUMBER | (uint32_t)calc_crc; 00286 00287 if (calc_header != flash_header) 00288 { 00289 return NRF_ERROR_NOT_FOUND; 00290 } 00291 00292 return NRF_SUCCESS; 00293 } 00294 00295 00296 uint32_t ble_flash_page_addr(uint8_t page_num, uint32_t ** pp_page_addr) 00297 { 00298 *pp_page_addr = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num); 00299 return NRF_SUCCESS; 00300 } 00301 00302 00303 void ble_flash_on_radio_active_evt(bool radio_active) 00304 { 00305 m_radio_active = radio_active; 00306 }
Generated on Tue Jul 12 2022 14:11:18 by
