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.
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 bd_size_t ChainingBlockDevice::get_erase_size(bd_addr_t addr) const 00215 { 00216 bd_addr_t bd_start_addr = 0; 00217 for (size_t i = 0; i < _bd_count; i++) { 00218 bd_size_t bdsize = _bds[i]->size(); 00219 if (addr < (bd_start_addr + bdsize)) { 00220 return _bds[i]->get_erase_size(addr - bd_start_addr); 00221 } 00222 bd_start_addr += bdsize; 00223 } 00224 00225 // Getting here implies an illegal address 00226 MBED_ASSERT(0); 00227 return 0; // satisfy compiler 00228 } 00229 00230 int ChainingBlockDevice::get_erase_value() const 00231 { 00232 return _erase_value; 00233 } 00234 00235 bd_size_t ChainingBlockDevice::size() const 00236 { 00237 return _size; 00238 }
Generated on Tue Jul 12 2022 14:23:31 by
