Marco Zecchini
/
Example_RTOS
Rtos API example
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 { 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 Sun Jul 17 2022 08:25:21 by 1.7.2