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.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
FlashIAPBlockDevice.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2016 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #if DEVICE_FLASH 00018 00019 #include "FlashIAPBlockDevice.h" 00020 #include "mbed_atomic.h" 00021 #include "mbed_error.h" 00022 00023 using namespace mbed; 00024 #include <inttypes.h> 00025 00026 #define FLASHIAP_READ_SIZE 1 00027 00028 // Debug available 00029 #ifndef FLASHIAP_DEBUG 00030 #define FLASHIAP_DEBUG 0 00031 #endif 00032 00033 #if FLASHIAP_DEBUG 00034 #define DEBUG_PRINTF(...) printf(__VA_ARGS__) 00035 #else 00036 #define DEBUG_PRINTF(...) 00037 #endif 00038 00039 FlashIAPBlockDevice::FlashIAPBlockDevice(uint32_t address, uint32_t size) 00040 : _flash(), _base(address), _size(size), _is_initialized(false), _init_ref_count(0) 00041 { 00042 if ((address == 0xFFFFFFFF) || (size == 0)) { 00043 MBED_ERROR(MBED_ERROR_INVALID_ARGUMENT, 00044 "Base address and size need to be set in flashiap-block-device configuration in order to use default constructor"); 00045 } 00046 } 00047 00048 FlashIAPBlockDevice::~FlashIAPBlockDevice() 00049 { 00050 deinit(); 00051 } 00052 00053 int FlashIAPBlockDevice::init() 00054 { 00055 DEBUG_PRINTF("init\r\n"); 00056 00057 if (!_is_initialized) { 00058 _init_ref_count = 0; 00059 } 00060 00061 uint32_t val = core_util_atomic_incr_u32 (&_init_ref_count, 1); 00062 00063 if (val != 1) { 00064 return BD_ERROR_OK; 00065 } 00066 00067 int ret = _flash.init(); 00068 00069 if (ret) { 00070 core_util_atomic_decr_u32 (&_init_ref_count, 1); 00071 return ret; 00072 } 00073 00074 if (_size + _base > _flash.get_flash_size() + _flash.get_flash_start()) { 00075 core_util_atomic_decr_u32 (&_init_ref_count, 1); 00076 return BD_ERROR_DEVICE_ERROR; 00077 } 00078 00079 if (_base < _flash.get_flash_start()) { 00080 core_util_atomic_decr_u32 (&_init_ref_count, 1); 00081 return BD_ERROR_DEVICE_ERROR; 00082 } 00083 00084 if (!_base) { 00085 _base = _flash.get_flash_start(); 00086 } 00087 00088 if (!_size) { 00089 _size = _flash.get_flash_size() - (_base - _flash.get_flash_start()); 00090 } 00091 00092 _is_initialized = true; 00093 return ret; 00094 } 00095 00096 int FlashIAPBlockDevice::deinit() 00097 { 00098 DEBUG_PRINTF("deinit\r\n"); 00099 00100 if (!_is_initialized) { 00101 _init_ref_count = 0; 00102 return 0; 00103 } 00104 00105 uint32_t val = core_util_atomic_decr_u32 (&_init_ref_count, 1); 00106 00107 if (val) { 00108 return 0; 00109 } 00110 00111 _is_initialized = false; 00112 00113 return _flash.deinit(); 00114 } 00115 00116 int FlashIAPBlockDevice::read(void *buffer, 00117 bd_addr_t virtual_address, 00118 bd_size_t size) 00119 { 00120 DEBUG_PRINTF("read: %" PRIX64 " %" PRIX64 "\r\n", virtual_address, size); 00121 00122 /* Default to error return code; success must be set explicitly. */ 00123 int result = BD_ERROR_DEVICE_ERROR; 00124 00125 /* Check that the address and size are properly aligned and fit. */ 00126 if (_is_initialized && is_valid_read(virtual_address, size)) { 00127 00128 /* Convert virtual address to the physical address for the device. */ 00129 bd_addr_t physical_address = _base + virtual_address; 00130 00131 /* Read data using the internal flash driver. */ 00132 result = _flash.read(buffer, physical_address, size); 00133 00134 DEBUG_PRINTF("physical: %" PRIX64 "\r\n", physical_address); 00135 } 00136 00137 return result; 00138 } 00139 00140 int FlashIAPBlockDevice::program(const void *buffer, 00141 bd_addr_t virtual_address, 00142 bd_size_t size) 00143 { 00144 DEBUG_PRINTF("program: %" PRIX64 " %" PRIX64 "\r\n", virtual_address, size); 00145 00146 /* Default to error return code; success must be set explicitly. */ 00147 int result = BD_ERROR_DEVICE_ERROR; 00148 00149 /* Check that the address and size are properly aligned and fit. */ 00150 if (_is_initialized && is_valid_program(virtual_address, size)) { 00151 00152 /* Convert virtual address to the physical address for the device. */ 00153 bd_addr_t physical_address = _base + virtual_address; 00154 00155 /* Write data using the internal flash driver. */ 00156 result = _flash.program(buffer, physical_address, size); 00157 00158 DEBUG_PRINTF("physical: %" PRIX64 " %" PRIX64 "\r\n", 00159 physical_address, 00160 size); 00161 } 00162 00163 return result; 00164 } 00165 00166 int FlashIAPBlockDevice::erase(bd_addr_t virtual_address, 00167 bd_size_t size) 00168 { 00169 DEBUG_PRINTF("erase: %" PRIX64 " %" PRIX64 "\r\n", virtual_address, size); 00170 00171 /* Default to error return code; success must be set explicitly. */ 00172 int result = BD_ERROR_DEVICE_ERROR; 00173 00174 /* Check that the address and size are properly aligned and fit. */ 00175 if (_is_initialized && is_valid_erase(virtual_address, size)) { 00176 00177 /* Convert virtual address to the physical address for the device. */ 00178 bd_addr_t physical_address = _base + virtual_address; 00179 00180 /* Erase sector */ 00181 result = _flash.erase(physical_address, size); 00182 } 00183 00184 return result; 00185 } 00186 00187 bd_size_t FlashIAPBlockDevice::get_read_size() const 00188 { 00189 DEBUG_PRINTF("get_read_size: %d\r\n", FLASHIAP_READ_SIZE); 00190 00191 return FLASHIAP_READ_SIZE; 00192 } 00193 00194 bd_size_t FlashIAPBlockDevice::get_program_size() const 00195 { 00196 if (!_is_initialized) { 00197 return 0; 00198 } 00199 00200 uint32_t page_size = _flash.get_page_size(); 00201 00202 DEBUG_PRINTF("get_program_size: %" PRIX32 "\r\n", page_size); 00203 00204 return page_size; 00205 } 00206 00207 bd_size_t FlashIAPBlockDevice::get_erase_size() const 00208 { 00209 if (!_is_initialized) { 00210 return 0; 00211 } 00212 00213 uint32_t erase_size = _flash.get_sector_size(_base); 00214 00215 DEBUG_PRINTF("get_erase_size: %" PRIX32 "\r\n", erase_size); 00216 00217 return erase_size; 00218 } 00219 00220 bd_size_t FlashIAPBlockDevice::get_erase_size(bd_addr_t addr) const 00221 { 00222 if (!_is_initialized) { 00223 return 0; 00224 } 00225 00226 uint32_t erase_size = _flash.get_sector_size(_base + addr); 00227 00228 DEBUG_PRINTF("get_erase_size: %" PRIX32 "\r\n", erase_size); 00229 00230 return erase_size; 00231 } 00232 00233 int FlashIAPBlockDevice::get_erase_value() const 00234 { 00235 if (!_is_initialized) { 00236 return -1; 00237 } 00238 00239 uint8_t erase_val = _flash.get_erase_value(); 00240 00241 DEBUG_PRINTF("get_erase_value: %" PRIX8 "\r\n", erase_val); 00242 00243 return erase_val; 00244 } 00245 00246 00247 bd_size_t FlashIAPBlockDevice::size() const 00248 { 00249 DEBUG_PRINTF("size: %" PRIX64 "\r\n", _size); 00250 00251 return _size; 00252 } 00253 00254 const char *FlashIAPBlockDevice::get_type() const 00255 { 00256 return "FLASHIAP"; 00257 } 00258 00259 bool FlashIAPBlockDevice::is_valid_erase(bd_addr_t addr, bd_size_t size) const 00260 { 00261 /* Calculate address alignment for the full flash */ 00262 bd_addr_t base_addr = addr + (_base - _flash.get_flash_start()); 00263 00264 return ( 00265 addr + size <= this->size() && 00266 base_addr % get_erase_size(addr) == 0 && 00267 (base_addr + size) % get_erase_size(addr + size - 1) == 0); 00268 } 00269 #endif /* DEVICE_FLASH */
Generated on Tue Jul 12 2022 13:54:22 by
1.7.2