Rtos API example

Committer:
marcozecchini
Date:
Sat Feb 23 12:13:36 2019 +0000
Revision:
0:9fca2b23d0ba
final commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
marcozecchini 0:9fca2b23d0ba 1 /* mbed Microcontroller Library
marcozecchini 0:9fca2b23d0ba 2 * Copyright (c) 2017 ARM Limited
marcozecchini 0:9fca2b23d0ba 3 *
marcozecchini 0:9fca2b23d0ba 4 * Licensed under the Apache License, Version 2.0 (the "License");
marcozecchini 0:9fca2b23d0ba 5 * you may not use this file except in compliance with the License.
marcozecchini 0:9fca2b23d0ba 6 * You may obtain a copy of the License at
marcozecchini 0:9fca2b23d0ba 7 *
marcozecchini 0:9fca2b23d0ba 8 * http://www.apache.org/licenses/LICENSE-2.0
marcozecchini 0:9fca2b23d0ba 9 *
marcozecchini 0:9fca2b23d0ba 10 * Unless required by applicable law or agreed to in writing, software
marcozecchini 0:9fca2b23d0ba 11 * distributed under the License is distributed on an "AS IS" BASIS,
marcozecchini 0:9fca2b23d0ba 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
marcozecchini 0:9fca2b23d0ba 13 * See the License for the specific language governing permissions and
marcozecchini 0:9fca2b23d0ba 14 * limitations under the License.
marcozecchini 0:9fca2b23d0ba 15 */
marcozecchini 0:9fca2b23d0ba 16
marcozecchini 0:9fca2b23d0ba 17 #include "ChainingBlockDevice.h"
marcozecchini 0:9fca2b23d0ba 18
marcozecchini 0:9fca2b23d0ba 19
marcozecchini 0:9fca2b23d0ba 20 ChainingBlockDevice::ChainingBlockDevice(BlockDevice **bds, size_t bd_count)
marcozecchini 0:9fca2b23d0ba 21 : _bds(bds), _bd_count(bd_count)
marcozecchini 0:9fca2b23d0ba 22 , _read_size(0), _program_size(0), _erase_size(0), _size(0)
marcozecchini 0:9fca2b23d0ba 23 {
marcozecchini 0:9fca2b23d0ba 24 }
marcozecchini 0:9fca2b23d0ba 25
marcozecchini 0:9fca2b23d0ba 26 static bool is_aligned(uint64_t x, uint64_t alignment)
marcozecchini 0:9fca2b23d0ba 27 {
marcozecchini 0:9fca2b23d0ba 28 return (x / alignment) * alignment == x;
marcozecchini 0:9fca2b23d0ba 29 }
marcozecchini 0:9fca2b23d0ba 30
marcozecchini 0:9fca2b23d0ba 31 int ChainingBlockDevice::init()
marcozecchini 0:9fca2b23d0ba 32 {
marcozecchini 0:9fca2b23d0ba 33 _read_size = 0;
marcozecchini 0:9fca2b23d0ba 34 _program_size = 0;
marcozecchini 0:9fca2b23d0ba 35 _erase_size = 0;
marcozecchini 0:9fca2b23d0ba 36 _size = 0;
marcozecchini 0:9fca2b23d0ba 37
marcozecchini 0:9fca2b23d0ba 38 // Initialize children block devices, find all sizes and
marcozecchini 0:9fca2b23d0ba 39 // assert that block sizes are similar. We can't do this in
marcozecchini 0:9fca2b23d0ba 40 // the constructor since some block devices may need to be
marcozecchini 0:9fca2b23d0ba 41 // initialized before they know their block size/count
marcozecchini 0:9fca2b23d0ba 42 for (size_t i = 0; i < _bd_count; i++) {
marcozecchini 0:9fca2b23d0ba 43 int err = _bds[i]->init();
marcozecchini 0:9fca2b23d0ba 44 if (err) {
marcozecchini 0:9fca2b23d0ba 45 return err;
marcozecchini 0:9fca2b23d0ba 46 }
marcozecchini 0:9fca2b23d0ba 47
marcozecchini 0:9fca2b23d0ba 48 bd_size_t read = _bds[i]->get_read_size();
marcozecchini 0:9fca2b23d0ba 49 if (i == 0 || (read >= _read_size && is_aligned(read, _read_size))) {
marcozecchini 0:9fca2b23d0ba 50 _read_size = read;
marcozecchini 0:9fca2b23d0ba 51 } else {
marcozecchini 0:9fca2b23d0ba 52 MBED_ASSERT(_read_size > read && is_aligned(_read_size, read));
marcozecchini 0:9fca2b23d0ba 53 }
marcozecchini 0:9fca2b23d0ba 54
marcozecchini 0:9fca2b23d0ba 55 bd_size_t program = _bds[i]->get_program_size();
marcozecchini 0:9fca2b23d0ba 56 if (i == 0 || (program >= _program_size && is_aligned(program, _program_size))) {
marcozecchini 0:9fca2b23d0ba 57 _program_size = program;
marcozecchini 0:9fca2b23d0ba 58 } else {
marcozecchini 0:9fca2b23d0ba 59 MBED_ASSERT(_program_size > program && is_aligned(_program_size, program));
marcozecchini 0:9fca2b23d0ba 60 }
marcozecchini 0:9fca2b23d0ba 61
marcozecchini 0:9fca2b23d0ba 62 bd_size_t erase = _bds[i]->get_erase_size();
marcozecchini 0:9fca2b23d0ba 63 if (i == 0 || (erase >= _erase_size && is_aligned(erase, _erase_size))) {
marcozecchini 0:9fca2b23d0ba 64 _erase_size = erase;
marcozecchini 0:9fca2b23d0ba 65 } else {
marcozecchini 0:9fca2b23d0ba 66 MBED_ASSERT(_erase_size > erase && is_aligned(_erase_size, erase));
marcozecchini 0:9fca2b23d0ba 67 }
marcozecchini 0:9fca2b23d0ba 68
marcozecchini 0:9fca2b23d0ba 69 _size += _bds[i]->size();
marcozecchini 0:9fca2b23d0ba 70 }
marcozecchini 0:9fca2b23d0ba 71
marcozecchini 0:9fca2b23d0ba 72 return 0;
marcozecchini 0:9fca2b23d0ba 73 }
marcozecchini 0:9fca2b23d0ba 74
marcozecchini 0:9fca2b23d0ba 75 int ChainingBlockDevice::deinit()
marcozecchini 0:9fca2b23d0ba 76 {
marcozecchini 0:9fca2b23d0ba 77 for (size_t i = 0; i < _bd_count; i++) {
marcozecchini 0:9fca2b23d0ba 78 int err = _bds[i]->deinit();
marcozecchini 0:9fca2b23d0ba 79 if (err) {
marcozecchini 0:9fca2b23d0ba 80 return err;
marcozecchini 0:9fca2b23d0ba 81 }
marcozecchini 0:9fca2b23d0ba 82 }
marcozecchini 0:9fca2b23d0ba 83
marcozecchini 0:9fca2b23d0ba 84 return 0;
marcozecchini 0:9fca2b23d0ba 85 }
marcozecchini 0:9fca2b23d0ba 86
marcozecchini 0:9fca2b23d0ba 87 int ChainingBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
marcozecchini 0:9fca2b23d0ba 88 {
marcozecchini 0:9fca2b23d0ba 89 MBED_ASSERT(is_valid_read(addr, size));
marcozecchini 0:9fca2b23d0ba 90 uint8_t *buffer = static_cast<uint8_t*>(b);
marcozecchini 0:9fca2b23d0ba 91
marcozecchini 0:9fca2b23d0ba 92 // Find block devices containing blocks, may span multiple block devices
marcozecchini 0:9fca2b23d0ba 93 for (size_t i = 0; i < _bd_count && size > 0; i++) {
marcozecchini 0:9fca2b23d0ba 94 bd_size_t bdsize = _bds[i]->size();
marcozecchini 0:9fca2b23d0ba 95
marcozecchini 0:9fca2b23d0ba 96 if (addr < bdsize) {
marcozecchini 0:9fca2b23d0ba 97 bd_size_t read = size;
marcozecchini 0:9fca2b23d0ba 98 if (addr + read > bdsize) {
marcozecchini 0:9fca2b23d0ba 99 read = bdsize - addr;
marcozecchini 0:9fca2b23d0ba 100 }
marcozecchini 0:9fca2b23d0ba 101
marcozecchini 0:9fca2b23d0ba 102 int err = _bds[i]->read(buffer, addr, read);
marcozecchini 0:9fca2b23d0ba 103 if (err) {
marcozecchini 0:9fca2b23d0ba 104 return err;
marcozecchini 0:9fca2b23d0ba 105 }
marcozecchini 0:9fca2b23d0ba 106
marcozecchini 0:9fca2b23d0ba 107 buffer += read;
marcozecchini 0:9fca2b23d0ba 108 addr += read;
marcozecchini 0:9fca2b23d0ba 109 size -= read;
marcozecchini 0:9fca2b23d0ba 110 }
marcozecchini 0:9fca2b23d0ba 111
marcozecchini 0:9fca2b23d0ba 112 addr -= bdsize;
marcozecchini 0:9fca2b23d0ba 113 }
marcozecchini 0:9fca2b23d0ba 114
marcozecchini 0:9fca2b23d0ba 115 return 0;
marcozecchini 0:9fca2b23d0ba 116 }
marcozecchini 0:9fca2b23d0ba 117
marcozecchini 0:9fca2b23d0ba 118 int ChainingBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
marcozecchini 0:9fca2b23d0ba 119 {
marcozecchini 0:9fca2b23d0ba 120 MBED_ASSERT(is_valid_program(addr, size));
marcozecchini 0:9fca2b23d0ba 121 const uint8_t *buffer = static_cast<const uint8_t*>(b);
marcozecchini 0:9fca2b23d0ba 122
marcozecchini 0:9fca2b23d0ba 123 // Find block devices containing blocks, may span multiple block devices
marcozecchini 0:9fca2b23d0ba 124 for (size_t i = 0; i < _bd_count && size > 0; i++) {
marcozecchini 0:9fca2b23d0ba 125 bd_size_t bdsize = _bds[i]->size();
marcozecchini 0:9fca2b23d0ba 126
marcozecchini 0:9fca2b23d0ba 127 if (addr < bdsize) {
marcozecchini 0:9fca2b23d0ba 128 bd_size_t program = size;
marcozecchini 0:9fca2b23d0ba 129 if (addr + program > bdsize) {
marcozecchini 0:9fca2b23d0ba 130 program = bdsize - addr;
marcozecchini 0:9fca2b23d0ba 131 }
marcozecchini 0:9fca2b23d0ba 132
marcozecchini 0:9fca2b23d0ba 133 int err = _bds[i]->program(buffer, addr, program);
marcozecchini 0:9fca2b23d0ba 134 if (err) {
marcozecchini 0:9fca2b23d0ba 135 return err;
marcozecchini 0:9fca2b23d0ba 136 }
marcozecchini 0:9fca2b23d0ba 137
marcozecchini 0:9fca2b23d0ba 138 buffer += program;
marcozecchini 0:9fca2b23d0ba 139 addr += program;
marcozecchini 0:9fca2b23d0ba 140 size -= program;
marcozecchini 0:9fca2b23d0ba 141 }
marcozecchini 0:9fca2b23d0ba 142
marcozecchini 0:9fca2b23d0ba 143 addr -= bdsize;
marcozecchini 0:9fca2b23d0ba 144 }
marcozecchini 0:9fca2b23d0ba 145
marcozecchini 0:9fca2b23d0ba 146 return 0;
marcozecchini 0:9fca2b23d0ba 147 }
marcozecchini 0:9fca2b23d0ba 148
marcozecchini 0:9fca2b23d0ba 149 int ChainingBlockDevice::erase(bd_addr_t addr, bd_size_t size)
marcozecchini 0:9fca2b23d0ba 150 {
marcozecchini 0:9fca2b23d0ba 151 MBED_ASSERT(is_valid_erase(addr, size));
marcozecchini 0:9fca2b23d0ba 152
marcozecchini 0:9fca2b23d0ba 153 // Find block devices containing blocks, may span multiple block devices
marcozecchini 0:9fca2b23d0ba 154 for (size_t i = 0; i < _bd_count && size > 0; i++) {
marcozecchini 0:9fca2b23d0ba 155 bd_size_t bdsize = _bds[i]->size();
marcozecchini 0:9fca2b23d0ba 156
marcozecchini 0:9fca2b23d0ba 157 if (addr < bdsize) {
marcozecchini 0:9fca2b23d0ba 158 bd_size_t erase = size;
marcozecchini 0:9fca2b23d0ba 159 if (addr + erase > bdsize) {
marcozecchini 0:9fca2b23d0ba 160 erase = bdsize - addr;
marcozecchini 0:9fca2b23d0ba 161 }
marcozecchini 0:9fca2b23d0ba 162
marcozecchini 0:9fca2b23d0ba 163 int err = _bds[i]->erase(addr, erase);
marcozecchini 0:9fca2b23d0ba 164 if (err) {
marcozecchini 0:9fca2b23d0ba 165 return err;
marcozecchini 0:9fca2b23d0ba 166 }
marcozecchini 0:9fca2b23d0ba 167
marcozecchini 0:9fca2b23d0ba 168 addr += erase;
marcozecchini 0:9fca2b23d0ba 169 size -= erase;
marcozecchini 0:9fca2b23d0ba 170 }
marcozecchini 0:9fca2b23d0ba 171
marcozecchini 0:9fca2b23d0ba 172 addr -= bdsize;
marcozecchini 0:9fca2b23d0ba 173 }
marcozecchini 0:9fca2b23d0ba 174
marcozecchini 0:9fca2b23d0ba 175 return 0;
marcozecchini 0:9fca2b23d0ba 176 }
marcozecchini 0:9fca2b23d0ba 177
marcozecchini 0:9fca2b23d0ba 178 bd_size_t ChainingBlockDevice::get_read_size() const
marcozecchini 0:9fca2b23d0ba 179 {
marcozecchini 0:9fca2b23d0ba 180 return _read_size;
marcozecchini 0:9fca2b23d0ba 181 }
marcozecchini 0:9fca2b23d0ba 182
marcozecchini 0:9fca2b23d0ba 183 bd_size_t ChainingBlockDevice::get_program_size() const
marcozecchini 0:9fca2b23d0ba 184 {
marcozecchini 0:9fca2b23d0ba 185 return _program_size;
marcozecchini 0:9fca2b23d0ba 186 }
marcozecchini 0:9fca2b23d0ba 187
marcozecchini 0:9fca2b23d0ba 188 bd_size_t ChainingBlockDevice::get_erase_size() const
marcozecchini 0:9fca2b23d0ba 189 {
marcozecchini 0:9fca2b23d0ba 190 return _erase_size;
marcozecchini 0:9fca2b23d0ba 191 }
marcozecchini 0:9fca2b23d0ba 192
marcozecchini 0:9fca2b23d0ba 193 bd_size_t ChainingBlockDevice::size() const
marcozecchini 0:9fca2b23d0ba 194 {
marcozecchini 0:9fca2b23d0ba 195 return _size;
marcozecchini 0:9fca2b23d0ba 196 }