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.
Dependencies: nRF51_Vdd TextLCD BME280
ChainingBlockDevice.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 "ChainingBlockDevice.h" 00018 #include "platform/mbed_critical.h" 00019 00020 00021 ChainingBlockDevice::ChainingBlockDevice(BlockDevice **bds, size_t bd_count) 00022 : _bds(bds), _bd_count(bd_count) 00023 , _read_size(0), _program_size(0), _erase_size(0), _size(0) 00024 , _erase_value(-1), _init_ref_count(0), _is_initialized(false) 00025 { 00026 } 00027 00028 static bool is_aligned(uint64_t x, uint64_t alignment) 00029 { 00030 return (x / alignment) * alignment == x; 00031 } 00032 00033 int ChainingBlockDevice::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 _read_size = 0; 00043 _program_size = 0; 00044 _erase_size = 0; 00045 _erase_value = -1; 00046 _size = 0; 00047 00048 // Initialize children block devices, find all sizes and 00049 // assert that block sizes are similar. We can't do this in 00050 // the constructor since some block devices may need to be 00051 // initialized before they know their block size/count 00052 for (size_t i = 0; i < _bd_count; i++) { 00053 err = _bds[i]->init(); 00054 if (err) { 00055 goto fail; 00056 } 00057 00058 bd_size_t read = _bds[i]->get_read_size(); 00059 if (i == 0 || (read >= _read_size && is_aligned(read, _read_size))) { 00060 _read_size = read; 00061 } else { 00062 MBED_ASSERT(_read_size > read && is_aligned(_read_size, read)); 00063 } 00064 00065 bd_size_t program = _bds[i]->get_program_size(); 00066 if (i == 0 || (program >= _program_size && is_aligned(program, _program_size))) { 00067 _program_size = program; 00068 } else { 00069 MBED_ASSERT(_program_size > program && is_aligned(_program_size, program)); 00070 } 00071 00072 bd_size_t erase = _bds[i]->get_erase_size(); 00073 if (i == 0 || (erase >= _erase_size && is_aligned(erase, _erase_size))) { 00074 _erase_size = erase; 00075 } else { 00076 MBED_ASSERT(_erase_size > erase && is_aligned(_erase_size, erase)); 00077 } 00078 00079 int value = _bds[i]->get_erase_value(); 00080 if (i == 0 || value == _erase_value) { 00081 _erase_value = value; 00082 } else { 00083 _erase_value = -1; 00084 } 00085 00086 _size += _bds[i]->size(); 00087 } 00088 00089 _is_initialized = true; 00090 return BD_ERROR_OK; 00091 00092 fail: 00093 _is_initialized = false; 00094 _init_ref_count = 0; 00095 return err; 00096 } 00097 00098 int ChainingBlockDevice::deinit() 00099 { 00100 if (!_is_initialized) { 00101 return BD_ERROR_OK; 00102 } 00103 00104 uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1); 00105 00106 if (val) { 00107 return BD_ERROR_OK; 00108 } 00109 00110 for (size_t i = 0; i < _bd_count; i++) { 00111 int err = _bds[i]->deinit(); 00112 if (err) { 00113 return err; 00114 } 00115 } 00116 00117 _is_initialized = false; 00118 return BD_ERROR_OK; 00119 } 00120 00121 int ChainingBlockDevice::sync() 00122 { 00123 if (!_is_initialized) { 00124 return BD_ERROR_DEVICE_ERROR; 00125 } 00126 00127 for (size_t i = 0; i < _bd_count; i++) { 00128 int err = _bds[i]->sync(); 00129 if (err) { 00130 return err; 00131 } 00132 } 00133 00134 return 0; 00135 } 00136 00137 int ChainingBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) 00138 { 00139 MBED_ASSERT(is_valid_read(addr, size)); 00140 if (!_is_initialized) { 00141 return BD_ERROR_DEVICE_ERROR; 00142 } 00143 00144 uint8_t *buffer = static_cast<uint8_t*>(b); 00145 00146 // Find block devices containing blocks, may span multiple block devices 00147 for (size_t i = 0; i < _bd_count && size > 0; i++) { 00148 bd_size_t bdsize = _bds[i]->size(); 00149 00150 if (addr < bdsize) { 00151 bd_size_t read = size; 00152 if (addr + read > bdsize) { 00153 read = bdsize - addr; 00154 } 00155 00156 int err = _bds[i]->read(buffer, addr, read); 00157 if (err) { 00158 return err; 00159 } 00160 00161 buffer += read; 00162 addr += read; 00163 size -= read; 00164 } 00165 00166 addr -= bdsize; 00167 } 00168 00169 return 0; 00170 } 00171 00172 int ChainingBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) 00173 { 00174 MBED_ASSERT(is_valid_program(addr, size)); 00175 if (!_is_initialized) { 00176 return BD_ERROR_DEVICE_ERROR; 00177 } 00178 00179 const uint8_t *buffer = static_cast<const uint8_t*>(b); 00180 00181 // Find block devices containing blocks, may span multiple block devices 00182 for (size_t i = 0; i < _bd_count && size > 0; i++) { 00183 bd_size_t bdsize = _bds[i]->size(); 00184 00185 if (addr < bdsize) { 00186 bd_size_t program = size; 00187 if (addr + program > bdsize) { 00188 program = bdsize - addr; 00189 } 00190 00191 int err = _bds[i]->program(buffer, addr, program); 00192 if (err) { 00193 return err; 00194 } 00195 00196 buffer += program; 00197 addr += program; 00198 size -= program; 00199 } 00200 00201 addr -= bdsize; 00202 } 00203 00204 return 0; 00205 } 00206 00207 int ChainingBlockDevice::erase(bd_addr_t addr, bd_size_t size) 00208 { 00209 MBED_ASSERT(is_valid_erase(addr, size)); 00210 if (!_is_initialized) { 00211 return BD_ERROR_DEVICE_ERROR; 00212 } 00213 00214 // Find block devices containing blocks, may span multiple block devices 00215 for (size_t i = 0; i < _bd_count && size > 0; i++) { 00216 bd_size_t bdsize = _bds[i]->size(); 00217 00218 if (addr < bdsize) { 00219 bd_size_t erase = size; 00220 if (addr + erase > bdsize) { 00221 erase = bdsize - addr; 00222 } 00223 00224 int err = _bds[i]->erase(addr, erase); 00225 if (err) { 00226 return err; 00227 } 00228 00229 addr += erase; 00230 size -= erase; 00231 } 00232 00233 addr -= bdsize; 00234 } 00235 00236 return 0; 00237 } 00238 00239 bd_size_t ChainingBlockDevice::get_read_size() const 00240 { 00241 return _read_size; 00242 } 00243 00244 bd_size_t ChainingBlockDevice::get_program_size() const 00245 { 00246 return _program_size; 00247 } 00248 00249 bd_size_t ChainingBlockDevice::get_erase_size() const 00250 { 00251 return _erase_size; 00252 } 00253 00254 bd_size_t ChainingBlockDevice::get_erase_size(bd_addr_t addr) const 00255 { 00256 if (!_is_initialized) { 00257 return 0; 00258 } 00259 00260 bd_addr_t bd_start_addr = 0; 00261 for (size_t i = 0; i < _bd_count; i++) { 00262 bd_size_t bdsize = _bds[i]->size(); 00263 if (addr < (bd_start_addr + bdsize)) { 00264 return _bds[i]->get_erase_size(addr - bd_start_addr); 00265 } 00266 bd_start_addr += bdsize; 00267 } 00268 00269 // Getting here implies an illegal address 00270 MBED_ASSERT(0); 00271 return 0; // satisfy compiler 00272 } 00273 00274 int ChainingBlockDevice::get_erase_value() const 00275 { 00276 return _erase_value; 00277 } 00278 00279 bd_size_t ChainingBlockDevice::size() const 00280 { 00281 return _size; 00282 }
Generated on Tue Jul 12 2022 15:15:41 by
