fork
Fork of nRF51822 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 "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 18:08:54 by 1.7.2