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.
aconno_flash.cpp
00001 /** 00002 * Made by Jurica Resetar @ aconno 00003 * ResetarJurica@gmail.com 00004 * More info @ aconno.de 00005 * 00006 */ 00007 00008 /* 00009 * Copyright (c) 2017 Nordic Semiconductor ASA 00010 * All rights reserved. 00011 * 00012 * Redistribution and use in source and binary forms, with or without modification, 00013 * are permitted provided that the following conditions are met: 00014 * 00015 * 1. Redistributions of source code must retain the above copyright notice, this list 00016 * of conditions and the following disclaimer. 00017 * 00018 * 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA 00019 * integrated circuit in a product or a software update for such product, must reproduce 00020 * the above copyright notice, this list of conditions and the following disclaimer in 00021 * the documentation and/or other materials provided with the distribution. 00022 * 00023 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be 00024 * used to endorse or promote products derived from this software without specific prior 00025 * written permission. 00026 * 00027 * 4. This software, with or without modification, must only be used with a 00028 * Nordic Semiconductor ASA integrated circuit. 00029 * 00030 * 5. Any software provided in binary or object form under this license must not be reverse 00031 * engineered, decompiled, modified and/or disassembled. 00032 * 00033 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00034 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00035 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00036 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00037 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00038 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00039 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 00040 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00041 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00042 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00043 * 00044 */ 00045 00046 #if DEVICE_FLASH 00047 00048 #include "aconno_flash.h" 00049 #include "hal/flash_api.h" 00050 #include "hal/lp_ticker_api.h" 00051 00052 #include "nrf_drv_common.h" 00053 #include "nrf_nvmc.h" 00054 #include "nrf_soc.h" 00055 #include <string.h> 00056 00057 // Max. value from datasheet: 338 us 00058 // // Constant increased by the author experimentaly 00059 #define WORD_WRITE_TIMEOUT_US (1 * 100000) 00060 // Max. value from datasheet: 89.7 ms 00061 // Constant increased by the author experimentaly 00062 #define PAGE_ERASE_TIMEOUT_US (200 * 10000) 00063 00064 /* Macro for testing if the SoftDevice is active, regardless of whether the 00065 * application is build with the SoftDevice or not. 00066 */ 00067 #if defined(SOFTDEVICE_PRESENT) 00068 #include "nrf_sdm.h" 00069 00070 static uint8_t wrapper(void) { 00071 uint8_t softdevice_is_enabled; 00072 ret_code_t result = sd_softdevice_is_enabled(&softdevice_is_enabled); 00073 return ((result == NRF_SUCCESS) && (softdevice_is_enabled == 1)); 00074 } 00075 00076 #define NRF_HAL_SD_IS_ENABLED() wrapper() 00077 #else 00078 #define NRF_HAL_SD_IS_ENABLED() 0 00079 #endif 00080 00081 int32_t aconno_flash_init(flash_t *obj) 00082 { 00083 (void)(obj); 00084 00085 /* Initialize low power ticker. Used for timeouts. */ 00086 static bool first_init = true; 00087 00088 if(first_init) 00089 { 00090 first_init = false; 00091 lp_ticker_init(); 00092 } 00093 return 0; 00094 } 00095 00096 int32_t aconno_flash_free(flash_t *obj) 00097 { 00098 (void)(obj); 00099 00100 return 0; 00101 } 00102 00103 int32_t aconno_flash_erase_sector(flash_t *obj, uint32_t address) 00104 { 00105 (void)(obj); 00106 00107 /* Return value defaults to error. */ 00108 uint32_t result = NRF_ERROR_BUSY; 00109 00110 if(NRF_HAL_SD_IS_ENABLED()) 00111 { 00112 /* Convert address to page number. */ 00113 uint32_t page_number = address / NRF_FICR->CODEPAGESIZE; 00114 00115 /* Setup stop watch for timeout. */ 00116 uint32_t start_us = lp_ticker_read(); 00117 uint32_t now_us = start_us; 00118 00119 /* Retry if flash is busy until timeout is reached. */ 00120 while(((now_us - start_us) < PAGE_ERASE_TIMEOUT_US) && 00121 (result == NRF_ERROR_BUSY)){ 00122 00123 result = sd_flash_page_erase(page_number); 00124 /* Read timeout timer. */ 00125 now_us = lp_ticker_read(); 00126 } 00127 } 00128 else 00129 { 00130 /* Raw API doesn't return error code, assume success. */ 00131 nrf_nvmc_page_erase(address); 00132 result = NRF_SUCCESS; 00133 } 00134 00135 /* Convert Nordic error code to mbed HAL error code. */ 00136 return (result == NRF_SUCCESS) ? 0 : -1; 00137 } 00138 00139 int32_t aconno_flash_read(flash_t *obj, uint32_t address, uint8_t *data, uint32_t size) 00140 { 00141 memcpy(data, (const void *)address, size); 00142 return 0; 00143 } 00144 00145 int32_t aconno_flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size) 00146 { 00147 (void)(obj); 00148 00149 /* Return value defaults to error. */ 00150 uint32_t result = NRF_ERROR_BUSY; 00151 00152 /* Convert size to words. */ 00153 uint32_t words = size / sizeof(uint32_t); 00154 00155 if(NRF_HAL_SD_IS_ENABLED()){ 00156 /* Setup stop watch for timeout. */ 00157 uint32_t start_us = lp_ticker_read(); 00158 uint32_t now_us = start_us; 00159 00160 /* Retry if flash is busy until timeout is reached. */ 00161 while(((now_us - start_us) < (words * WORD_WRITE_TIMEOUT_US)) && 00162 (result == NRF_ERROR_BUSY)){ 00163 result = sd_flash_write((uint32_t *) address, (const uint32_t *) data, words); 00164 /* Read timeout timer. */ 00165 now_us = lp_ticker_read(); 00166 } 00167 } 00168 else 00169 { 00170 /* We will use *_words function to speed up flashing code. 00171 * Word means 32bit -> 4B or sizeof(uint32_t). */ 00172 nrf_nvmc_write_words(address, (const uint32_t *) data, words); 00173 result = NRF_SUCCESS; 00174 } 00175 00176 /* Convert Nordic error code to mbed HAL error code. */ 00177 return (result == NRF_SUCCESS) ? 0 : -1; 00178 } 00179 00180 uint32_t aconno_flash_get_size(const flash_t *obj) 00181 { 00182 (void)(obj); 00183 00184 /* Just count flash size. */ 00185 return NRF_FICR->CODESIZE * NRF_FICR->CODEPAGESIZE; 00186 } 00187 00188 uint32_t aconno_flash_get_sector_size(const flash_t *obj, uint32_t address) 00189 { 00190 (void)(obj); 00191 00192 /* Test if passed address is in flash space. */ 00193 if (address < aconno_flash_get_size(obj)) { 00194 return NRF_FICR->CODEPAGESIZE; 00195 } 00196 00197 /* Something goes wrong, return invalid size error code. */ 00198 return MBED_FLASH_INVALID_SIZE; 00199 } 00200 00201 uint32_t aconno_flash_get_page_size(const flash_t *obj) 00202 { 00203 (void)(obj); 00204 /* Return minimum writeable size. Note that this is 00205 different from the erase page size. */ 00206 return 4; 00207 } 00208 00209 uint32_t aconno_flash_get_start_address(const flash_t *obj) 00210 { 00211 (void)(obj); 00212 00213 return 0; 00214 } 00215 00216 /** 00217 * Just leave the following function's declarations here! 00218 * It's total mess if you try to put them somewhere else (mbed stuff...) 00219 */ 00220 void nrf_nvmc_page_erase(uint32_t address) 00221 { 00222 // Enable erase. 00223 NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een; 00224 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00225 { 00226 } 00227 00228 // Erase the page 00229 NRF_NVMC->ERASEPAGE = address; 00230 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00231 { 00232 } 00233 00234 NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren; 00235 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00236 { 00237 } 00238 } 00239 00240 void nrf_nvmc_write_byte(uint32_t address, uint8_t value) 00241 { 00242 uint32_t byte_shift = address & (uint32_t)0x03; 00243 uint32_t address32 = address & ~byte_shift; // Address to the word this byte is in. 00244 uint32_t value32 = (*(uint32_t*)address32 & ~((uint32_t)0xFF << (byte_shift << (uint32_t)3))); 00245 value32 = value32 + ((uint32_t)value << (byte_shift << 3)); 00246 00247 // Enable write. 00248 NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos); 00249 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00250 { 00251 } 00252 00253 *(uint32_t*)address32 = value32; 00254 while(NRF_NVMC->READY == NVMC_READY_READY_Busy) 00255 { 00256 } 00257 00258 NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); 00259 { 00260 } 00261 } 00262 00263 void nrf_nvmc_write_word(uint32_t address, uint32_t value) 00264 { 00265 // Enable write. 00266 NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen; 00267 while (NRF_NVMC->READY == NVMC_READY_READY_Busy){ 00268 } 00269 00270 *(uint32_t*)address = value; 00271 while (NRF_NVMC->READY == NVMC_READY_READY_Busy){ 00272 } 00273 00274 NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren; 00275 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00276 { 00277 } 00278 } 00279 00280 void nrf_nvmc_write_bytes(uint32_t address, const uint8_t * src, uint32_t num_bytes) 00281 { 00282 uint32_t i; 00283 for(i=0;i<num_bytes;i++) 00284 { 00285 nrf_nvmc_write_byte(address+i,src[i]); 00286 } 00287 } 00288 00289 void nrf_nvmc_write_words(uint32_t address, const uint32_t * src, uint32_t num_words) 00290 { 00291 uint32_t i; 00292 00293 // Enable write. 00294 NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen; 00295 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00296 { 00297 } 00298 00299 for(i=0;i<num_words;i++) 00300 { 00301 ((uint32_t*)address)[i] = src[i]; 00302 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00303 { 00304 } 00305 } 00306 00307 NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren; 00308 while (NRF_NVMC->READY == NVMC_READY_READY_Busy) 00309 { 00310 } 00311 } 00312 00313 #endif 00314 /** @}*/
Generated on Thu Jul 14 2022 20:11:16 by
1.7.2