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 LinkNode-Test 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 "nrf51_bitfields.h" 00042 #include "app_util.h" 00043 00044 00045 static volatile bool m_radio_active = false; /**< TRUE if radio is active (or about to become active), FALSE otherwise. */ 00046 00047 00048 uint16_t ble_flash_crc16_compute(uint8_t * p_data, uint16_t size, uint16_t * p_crc) 00049 { 00050 uint16_t i; 00051 uint16_t crc = (p_crc == NULL) ? 0xffff : *p_crc; 00052 00053 for (i = 0; i < size; i++) 00054 { 00055 crc = (unsigned char)(crc >> 8) | (crc << 8); 00056 crc ^= p_data[i]; 00057 crc ^= (unsigned char)(crc & 0xff) >> 4; 00058 crc ^= (crc << 8) << 4; 00059 crc ^= ((crc & 0xff) << 4) << 1; 00060 } 00061 return crc; 00062 } 00063 00064 00065 /**@brief Function for erasing a page in flash. 00066 * 00067 * @param[in] p_page Pointer to first word in page to be erased. 00068 */ 00069 static void flash_page_erase(uint32_t * p_page) 00070 { 00071 // Turn on flash erase enable and wait until the NVMC is ready. 00072 NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos); 00073 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00074 { 00075 // Do nothing. 00076 } 00077 00078 // Erase page. 00079 NRF_NVMC->ERASEPAGE = (uint32_t)p_page; 00080 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00081 { 00082 // Do nothing. 00083 } 00084 00085 // Turn off flash erase enable and wait until the NVMC is ready. 00086 NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); 00087 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00088 { 00089 // Do nothing 00090 } 00091 } 00092 00093 00094 /**@brief Function for writing one word to flash. Unprotected write, which can interfere with radio communication. 00095 * 00096 * @details This function DOES NOT use the m_radio_active variable, but will force the write even 00097 * when the radio is active. To be used only from @ref ble_flash_page_write. 00098 * 00099 * @note Flash location to be written must have been erased previously. 00100 * 00101 * @param[in] p_address Pointer to flash location to be written. 00102 * @param[in] value Value to write to flash. 00103 */ 00104 static void flash_word_unprotected_write(uint32_t * p_address, uint32_t value) 00105 { 00106 // Turn on flash write enable and wait until the NVMC is ready. 00107 NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos); 00108 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00109 { 00110 // Do nothing. 00111 } 00112 *p_address = value; 00113 00114 // Wait flash write to finish 00115 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00116 { 00117 // Do nothing. 00118 } 00119 00120 // Turn off flash write enable and wait until the NVMC is ready. 00121 NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); 00122 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00123 { 00124 // Do nothing. 00125 } 00126 } 00127 00128 00129 /**@brief Function for writing one word to flash. 00130 * 00131 * @note Flash location to be written must have been erased previously. 00132 * 00133 * @param[in] p_address Pointer to flash location to be written. 00134 * @param[in] value Value to write to flash. 00135 */ 00136 static void flash_word_write(uint32_t * p_address, uint32_t value) 00137 { 00138 // If radio is active, wait for it to become inactive. 00139 while (m_radio_active) 00140 { 00141 // Do nothing (just wait for radio to become inactive). 00142 (void) sd_app_evt_wait(); 00143 } 00144 00145 // Turn on flash write enable and wait until the NVMC is ready. 00146 NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos); 00147 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00148 { 00149 // Do nothing. 00150 } 00151 00152 *p_address = value; 00153 // Wait flash write to finish 00154 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00155 { 00156 // Do nothing. 00157 } 00158 // Turn off flash write enable and wait until the NVMC is ready. 00159 NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); 00160 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00161 { 00162 // Do nothing 00163 } 00164 } 00165 00166 00167 uint32_t ble_flash_word_write(uint32_t * p_address, uint32_t value) 00168 { 00169 flash_word_write(p_address, value); 00170 return NRF_SUCCESS; 00171 } 00172 00173 00174 uint32_t ble_flash_block_write(uint32_t * p_address, uint32_t * p_in_array, uint16_t word_count) 00175 { 00176 uint16_t i; 00177 00178 for (i = 0; i < word_count; i++) 00179 { 00180 flash_word_write(p_address, p_in_array[i]); 00181 p_address++; 00182 } 00183 00184 return NRF_SUCCESS; 00185 } 00186 00187 00188 uint32_t ble_flash_page_erase(uint8_t page_num) 00189 { 00190 uint32_t * p_page = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num); 00191 flash_page_erase(p_page); 00192 00193 return NRF_SUCCESS; 00194 } 00195 00196 00197 uint32_t ble_flash_page_write(uint8_t page_num, uint32_t * p_in_array, uint8_t word_count) 00198 { 00199 int i; 00200 uint32_t * p_page; 00201 uint32_t * p_curr_addr; 00202 uint16_t in_data_crc; 00203 uint16_t flash_crc; 00204 uint32_t flash_header; 00205 00206 p_page = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num); 00207 p_curr_addr = p_page; 00208 00209 // Calculate CRC of the data to write. 00210 in_data_crc = ble_flash_crc16_compute((uint8_t *)p_in_array, 00211 word_count * sizeof(uint32_t), 00212 NULL); 00213 00214 // Compare the calculated to the one in flash. 00215 flash_header = *p_curr_addr; 00216 flash_crc = (uint16_t)flash_header; 00217 00218 if (flash_crc == in_data_crc) 00219 { 00220 // Data is the same as the data already stored in flash, return without modifying flash. 00221 return NRF_SUCCESS; 00222 } 00223 00224 // Erase flash page 00225 flash_page_erase(p_page); 00226 00227 // Reserve space for magic number (for detecting if flash content is valid). 00228 p_curr_addr++; 00229 00230 // Reserve space for saving word_count. 00231 p_curr_addr++; 00232 00233 // Write data 00234 for (i = 0; i < word_count; i++) 00235 { 00236 flash_word_unprotected_write(p_curr_addr, p_in_array[i]); 00237 p_curr_addr++; 00238 } 00239 00240 // Write number of elements. 00241 flash_word_write(p_page + 1, (uint32_t)(word_count)); 00242 00243 // Write magic number and CRC to indicate that flash content is valid. 00244 flash_header = BLE_FLASH_MAGIC_NUMBER | (uint32_t)in_data_crc; 00245 flash_word_write(p_page, flash_header); 00246 00247 return NRF_SUCCESS; 00248 } 00249 00250 00251 uint32_t ble_flash_page_read(uint8_t page_num, uint32_t * p_out_array, uint8_t * p_word_count) 00252 { 00253 int byte_count; 00254 uint32_t * p_page; 00255 uint32_t * p_curr_addr; 00256 uint32_t flash_header; 00257 uint32_t calc_header; 00258 uint16_t calc_crc; 00259 uint32_t tmp; 00260 00261 p_page = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num); 00262 p_curr_addr = p_page; 00263 00264 // Check if block is valid 00265 flash_header = *p_curr_addr; 00266 tmp = flash_header & 0xFFFF0000; 00267 if (tmp != BLE_FLASH_MAGIC_NUMBER) 00268 { 00269 *p_word_count = 0; 00270 return NRF_ERROR_NOT_FOUND; 00271 } 00272 p_curr_addr++; 00273 00274 // Read number of elements 00275 *p_word_count = (uint8_t)(*(p_curr_addr)); 00276 p_curr_addr++; 00277 00278 // Read data 00279 byte_count = (*p_word_count) * sizeof(uint32_t); 00280 memcpy(p_out_array, p_curr_addr, byte_count); 00281 00282 // Check CRC 00283 calc_crc = ble_flash_crc16_compute((uint8_t *)p_out_array, 00284 (*p_word_count) * sizeof(uint32_t), 00285 NULL); 00286 calc_header = BLE_FLASH_MAGIC_NUMBER | (uint32_t)calc_crc; 00287 00288 if (calc_header != flash_header) 00289 { 00290 return NRF_ERROR_NOT_FOUND; 00291 } 00292 00293 return NRF_SUCCESS; 00294 } 00295 00296 00297 uint32_t ble_flash_page_addr(uint8_t page_num, uint32_t ** pp_page_addr) 00298 { 00299 *pp_page_addr = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num); 00300 return NRF_SUCCESS; 00301 } 00302 00303 00304 void ble_flash_on_radio_active_evt(bool radio_active) 00305 { 00306 m_radio_active = radio_active; 00307 }
Generated on Tue Jul 12 2022 16:00:19 by
