Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ExhaustibleBlockDevice.cpp Source File

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