Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

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_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 }