Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ChainingBlockDevice.cpp Source File

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 }