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.
ExhaustibleBlockDevice.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2017 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 #include "ExhaustibleBlockDevice.h" 00018 #include "platform/mbed_critical.h" 00019 #include "platform/mbed_assert.h" 00020 00021 ExhaustibleBlockDevice::ExhaustibleBlockDevice(BlockDevice *bd, uint32_t erase_cycles) 00022 : _bd(bd), _erase_array(NULL), _erase_cycles(erase_cycles), _init_ref_count(0), _is_initialized(false) 00023 { 00024 } 00025 00026 ExhaustibleBlockDevice::~ExhaustibleBlockDevice() 00027 { 00028 delete[] _erase_array; 00029 } 00030 00031 int ExhaustibleBlockDevice::init() 00032 { 00033 int err; 00034 uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1); 00035 00036 if (val != 1) { 00037 return BD_ERROR_OK; 00038 } 00039 00040 err = _bd->init(); 00041 if (err) { 00042 goto fail; 00043 } 00044 00045 if (!_erase_array) { 00046 // can only be allocated after initialization 00047 _erase_array = new uint32_t[_bd->size() / _bd->get_erase_size()]; 00048 for (size_t i = 0; i < _bd->size() / _bd->get_erase_size(); i++) { 00049 _erase_array[i] = _erase_cycles; 00050 } 00051 } 00052 00053 _is_initialized = true; 00054 return BD_ERROR_OK; 00055 00056 fail: 00057 _is_initialized = false; 00058 _init_ref_count = 0; 00059 return err; 00060 } 00061 00062 int ExhaustibleBlockDevice::deinit() 00063 { 00064 if (!_is_initialized) { 00065 return BD_ERROR_OK; 00066 } 00067 00068 core_util_atomic_decr_u32(&_init_ref_count, 1); 00069 00070 if (_init_ref_count) { 00071 return BD_ERROR_OK; 00072 } 00073 00074 // _erase_array is lazily cleaned up in destructor to allow 00075 // data to live across de/reinitialization 00076 _is_initialized = false; 00077 return _bd->deinit(); 00078 } 00079 00080 int ExhaustibleBlockDevice::sync() 00081 { 00082 if (!_is_initialized) { 00083 return BD_ERROR_DEVICE_ERROR; 00084 } 00085 00086 return _bd->sync(); 00087 } 00088 00089 int ExhaustibleBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) 00090 { 00091 if (!_is_initialized) { 00092 return BD_ERROR_DEVICE_ERROR; 00093 } 00094 00095 return _bd->read(buffer, addr, size); 00096 } 00097 00098 int ExhaustibleBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) 00099 { 00100 MBED_ASSERT(is_valid_program(addr, size)); 00101 00102 if (!_is_initialized) { 00103 return BD_ERROR_DEVICE_ERROR; 00104 } 00105 00106 if (_erase_array[addr / get_erase_size()] == 0) { 00107 return 0; 00108 } 00109 00110 return _bd->program(buffer, addr, size); 00111 } 00112 00113 int ExhaustibleBlockDevice::erase(bd_addr_t addr, bd_size_t size) 00114 { 00115 MBED_ASSERT(is_valid_erase(addr, size)); 00116 if (!_is_initialized) { 00117 return BD_ERROR_DEVICE_ERROR; 00118 } 00119 00120 bd_size_t eu_size = get_erase_size(); 00121 while (size) { 00122 // use an erase cycle 00123 if (_erase_array[addr / eu_size] > 0) { 00124 _erase_array[addr / eu_size] -= 1; 00125 } 00126 00127 if (_erase_array[addr / eu_size] > 0) { 00128 int err = _bd->erase(addr, eu_size); 00129 if (err) { 00130 return err; 00131 } 00132 } 00133 00134 addr += eu_size; 00135 size -= eu_size; 00136 } 00137 00138 return 0; 00139 } 00140 00141 bd_size_t ExhaustibleBlockDevice::get_read_size() const 00142 { 00143 if (!_is_initialized) { 00144 return 0; 00145 } 00146 00147 return _bd->get_read_size(); 00148 } 00149 00150 bd_size_t ExhaustibleBlockDevice::get_program_size() const 00151 { 00152 if (!_is_initialized) { 00153 return 0; 00154 } 00155 00156 return _bd->get_program_size(); 00157 } 00158 00159 bd_size_t ExhaustibleBlockDevice::get_erase_size() const 00160 { 00161 if (!_is_initialized) { 00162 return 0; 00163 } 00164 00165 return _bd->get_erase_size(); 00166 } 00167 00168 bd_size_t ExhaustibleBlockDevice::get_erase_size(bd_addr_t addr) const 00169 { 00170 if (!_is_initialized) { 00171 return 0; 00172 } 00173 00174 return _bd->get_erase_size(addr); 00175 } 00176 00177 int ExhaustibleBlockDevice::get_erase_value() const 00178 { 00179 if (!_is_initialized) { 00180 return BD_ERROR_DEVICE_ERROR; 00181 } 00182 00183 return _bd->get_erase_value(); 00184 } 00185 00186 bd_size_t ExhaustibleBlockDevice::size() const 00187 { 00188 if (!_is_initialized) { 00189 return 0; 00190 } 00191 00192 return _bd->size(); 00193 }
Generated on Tue Jul 12 2022 20:52:42 by
1.7.2