init
Embed:
(wiki syntax)
Show/hide line numbers
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 00019 00020 ChainingBlockDevice::ChainingBlockDevice(BlockDevice **bds, size_t bd_count) 00021 : _bds(bds), _bd_count(bd_count) 00022 , _read_size(0), _program_size(0), _erase_size(0), _size(0) 00023 , _erase_value(-1) 00024 { 00025 } 00026 00027 static bool is_aligned(uint64_t x, uint64_t alignment) 00028 { 00029 return (x / alignment) * alignment == x; 00030 } 00031 00032 int ChainingBlockDevice::init() 00033 { 00034 _read_size = 0; 00035 _program_size = 0; 00036 _erase_size = 0; 00037 _erase_value = -1; 00038 _size = 0; 00039 00040 // Initialize children block devices, find all sizes and 00041 // assert that block sizes are similar. We can't do this in 00042 // the constructor since some block devices may need to be 00043 // initialized before they know their block size/count 00044 for (size_t i = 0; i < _bd_count; i++) { 00045 int err = _bds[i]->init(); 00046 if (err) { 00047 return err; 00048 } 00049 00050 bd_size_t read = _bds[i]->get_read_size(); 00051 if (i == 0 || (read >= _read_size && is_aligned(read, _read_size))) { 00052 _read_size = read; 00053 } else { 00054 MBED_ASSERT(_read_size > read && is_aligned(_read_size, read)); 00055 } 00056 00057 bd_size_t program = _bds[i]->get_program_size(); 00058 if (i == 0 || (program >= _program_size && is_aligned(program, _program_size))) { 00059 _program_size = program; 00060 } else { 00061 MBED_ASSERT(_program_size > program && is_aligned(_program_size, program)); 00062 } 00063 00064 bd_size_t erase = _bds[i]->get_erase_size(); 00065 if (i == 0 || (erase >= _erase_size && is_aligned(erase, _erase_size))) { 00066 _erase_size = erase; 00067 } else { 00068 MBED_ASSERT(_erase_size > erase && is_aligned(_erase_size, erase)); 00069 } 00070 00071 int value = _bds[i]->get_erase_value(); 00072 if (i == 0 || value == _erase_value) { 00073 _erase_value = value; 00074 } else { 00075 _erase_value = -1; 00076 } 00077 00078 _size += _bds[i]->size(); 00079 } 00080 00081 return 0; 00082 } 00083 00084 int ChainingBlockDevice::deinit() 00085 { 00086 for (size_t i = 0; i < _bd_count; i++) { 00087 int err = _bds[i]->deinit(); 00088 if (err) { 00089 return err; 00090 } 00091 } 00092 00093 return 0; 00094 } 00095 00096 int ChainingBlockDevice::sync() 00097 { 00098 for (size_t i = 0; i < _bd_count; i++) { 00099 int err = _bds[i]->sync(); 00100 if (err) { 00101 return err; 00102 } 00103 } 00104 00105 return 0; 00106 } 00107 00108 int ChainingBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) 00109 { 00110 MBED_ASSERT(is_valid_read(addr, size)); 00111 uint8_t *buffer = static_cast<uint8_t*>(b); 00112 00113 // Find block devices containing blocks, may span multiple block devices 00114 for (size_t i = 0; i < _bd_count && size > 0; i++) { 00115 bd_size_t bdsize = _bds[i]->size(); 00116 00117 if (addr < bdsize) { 00118 bd_size_t read = size; 00119 if (addr + read > bdsize) { 00120 read = bdsize - addr; 00121 } 00122 00123 int err = _bds[i]->read(buffer, addr, read); 00124 if (err) { 00125 return err; 00126 } 00127 00128 buffer += read; 00129 addr += read; 00130 size -= read; 00131 } 00132 00133 addr -= bdsize; 00134 } 00135 00136 return 0; 00137 } 00138 00139 int ChainingBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) 00140 { 00141 MBED_ASSERT(is_valid_program(addr, size)); 00142 const uint8_t *buffer = static_cast<const uint8_t*>(b); 00143 00144 // Find block devices containing blocks, may span multiple block devices 00145 for (size_t i = 0; i < _bd_count && size > 0; i++) { 00146 bd_size_t bdsize = _bds[i]->size(); 00147 00148 if (addr < bdsize) { 00149 bd_size_t program = size; 00150 if (addr + program > bdsize) { 00151 program = bdsize - addr; 00152 } 00153 00154 int err = _bds[i]->program(buffer, addr, program); 00155 if (err) { 00156 return err; 00157 } 00158 00159 buffer += program; 00160 addr += program; 00161 size -= program; 00162 } 00163 00164 addr -= bdsize; 00165 } 00166 00167 return 0; 00168 } 00169 00170 int ChainingBlockDevice::erase(bd_addr_t addr, bd_size_t size) 00171 { 00172 MBED_ASSERT(is_valid_erase(addr, size)); 00173 00174 // Find block devices containing blocks, may span multiple block devices 00175 for (size_t i = 0; i < _bd_count && size > 0; i++) { 00176 bd_size_t bdsize = _bds[i]->size(); 00177 00178 if (addr < bdsize) { 00179 bd_size_t erase = size; 00180 if (addr + erase > bdsize) { 00181 erase = bdsize - addr; 00182 } 00183 00184 int err = _bds[i]->erase(addr, erase); 00185 if (err) { 00186 return err; 00187 } 00188 00189 addr += erase; 00190 size -= erase; 00191 } 00192 00193 addr -= bdsize; 00194 } 00195 00196 return 0; 00197 } 00198 00199 bd_size_t ChainingBlockDevice::get_read_size() const 00200 { 00201 return _read_size; 00202 } 00203 00204 bd_size_t ChainingBlockDevice::get_program_size() const 00205 { 00206 return _program_size; 00207 } 00208 00209 bd_size_t ChainingBlockDevice::get_erase_size() const 00210 { 00211 return _erase_size; 00212 } 00213 00214 int ChainingBlockDevice::get_erase_value() const 00215 { 00216 return _erase_value; 00217 } 00218 00219 bd_size_t ChainingBlockDevice::size() const 00220 { 00221 return _size; 00222 }
Generated on Tue Jul 12 2022 13:24:34 by
1.7.2