bugfix for duplicate symbol
Fork of nRF51822 by
Embed:
(wiki syntax)
Show/hide line numbers
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:20:23 by 1.7.2