Rtos API example

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 {
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 }