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