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