test
Fork of nrf51-sdk by
Embed:
(wiki syntax)
Show/hide line numbers
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 15:51:26 by 1.7.2