mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 31 06:02:27 2019 +0000
Revision:
1:9db0e321a9f4
Parent:
0:5b88d5760320
updated based on mbed-os5.15.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:5b88d5760320 1 /* mbed Microcontroller Library
kenjiArai 0:5b88d5760320 2 * Copyright (c) 2017 ARM Limited
kenjiArai 0:5b88d5760320 3 *
kenjiArai 0:5b88d5760320 4 * Licensed under the Apache License, Version 2.0 (the "License");
kenjiArai 0:5b88d5760320 5 * you may not use this file except in compliance with the License.
kenjiArai 0:5b88d5760320 6 * You may obtain a copy of the License at
kenjiArai 0:5b88d5760320 7 *
kenjiArai 0:5b88d5760320 8 * http://www.apache.org/licenses/LICENSE-2.0
kenjiArai 0:5b88d5760320 9 *
kenjiArai 0:5b88d5760320 10 * Unless required by applicable law or agreed to in writing, software
kenjiArai 0:5b88d5760320 11 * distributed under the License is distributed on an "AS IS" BASIS,
kenjiArai 0:5b88d5760320 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kenjiArai 0:5b88d5760320 13 * See the License for the specific language governing permissions and
kenjiArai 0:5b88d5760320 14 * limitations under the License.
kenjiArai 0:5b88d5760320 15 */
kenjiArai 0:5b88d5760320 16
kenjiArai 0:5b88d5760320 17 #include "ChainingBlockDevice.h"
kenjiArai 0:5b88d5760320 18 #include "platform/mbed_atomic.h"
kenjiArai 0:5b88d5760320 19 #include "platform/mbed_assert.h"
kenjiArai 0:5b88d5760320 20
kenjiArai 0:5b88d5760320 21 namespace mbed {
kenjiArai 0:5b88d5760320 22
kenjiArai 0:5b88d5760320 23 ChainingBlockDevice::ChainingBlockDevice(BlockDevice **bds, size_t bd_count)
kenjiArai 0:5b88d5760320 24 : _bds(bds), _bd_count(bd_count)
kenjiArai 0:5b88d5760320 25 , _read_size(0), _program_size(0), _erase_size(0), _size(0)
kenjiArai 0:5b88d5760320 26 , _erase_value(-1), _init_ref_count(0), _is_initialized(false)
kenjiArai 0:5b88d5760320 27 {
kenjiArai 0:5b88d5760320 28 }
kenjiArai 0:5b88d5760320 29
kenjiArai 0:5b88d5760320 30 static bool is_aligned(uint64_t x, uint64_t alignment)
kenjiArai 0:5b88d5760320 31 {
kenjiArai 0:5b88d5760320 32 return (x / alignment) * alignment == x;
kenjiArai 0:5b88d5760320 33 }
kenjiArai 0:5b88d5760320 34
kenjiArai 0:5b88d5760320 35 int ChainingBlockDevice::init()
kenjiArai 0:5b88d5760320 36 {
kenjiArai 0:5b88d5760320 37 int err;
kenjiArai 0:5b88d5760320 38 uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1);
kenjiArai 0:5b88d5760320 39
kenjiArai 0:5b88d5760320 40 if (val != 1) {
kenjiArai 0:5b88d5760320 41 return BD_ERROR_OK;
kenjiArai 0:5b88d5760320 42 }
kenjiArai 0:5b88d5760320 43
kenjiArai 0:5b88d5760320 44 _read_size = 0;
kenjiArai 0:5b88d5760320 45 _program_size = 0;
kenjiArai 0:5b88d5760320 46 _erase_size = 0;
kenjiArai 0:5b88d5760320 47 _erase_value = -1;
kenjiArai 0:5b88d5760320 48 _size = 0;
kenjiArai 0:5b88d5760320 49
kenjiArai 0:5b88d5760320 50 // Initialize children block devices, find all sizes and
kenjiArai 0:5b88d5760320 51 // assert that block sizes are similar. We can't do this in
kenjiArai 0:5b88d5760320 52 // the constructor since some block devices may need to be
kenjiArai 0:5b88d5760320 53 // initialized before they know their block size/count
kenjiArai 0:5b88d5760320 54 for (size_t i = 0; i < _bd_count; i++) {
kenjiArai 0:5b88d5760320 55 err = _bds[i]->init();
kenjiArai 0:5b88d5760320 56 if (err) {
kenjiArai 0:5b88d5760320 57 goto fail;
kenjiArai 0:5b88d5760320 58 }
kenjiArai 0:5b88d5760320 59
kenjiArai 0:5b88d5760320 60 bd_size_t read = _bds[i]->get_read_size();
kenjiArai 0:5b88d5760320 61 if (i == 0 || (read >= _read_size && is_aligned(read, _read_size))) {
kenjiArai 0:5b88d5760320 62 _read_size = read;
kenjiArai 0:5b88d5760320 63 } else {
kenjiArai 0:5b88d5760320 64 MBED_ASSERT(_read_size > read && is_aligned(_read_size, read));
kenjiArai 0:5b88d5760320 65 }
kenjiArai 0:5b88d5760320 66
kenjiArai 0:5b88d5760320 67 bd_size_t program = _bds[i]->get_program_size();
kenjiArai 0:5b88d5760320 68 if (i == 0 || (program >= _program_size && is_aligned(program, _program_size))) {
kenjiArai 0:5b88d5760320 69 _program_size = program;
kenjiArai 0:5b88d5760320 70 } else {
kenjiArai 0:5b88d5760320 71 MBED_ASSERT(_program_size > program && is_aligned(_program_size, program));
kenjiArai 0:5b88d5760320 72 }
kenjiArai 0:5b88d5760320 73
kenjiArai 0:5b88d5760320 74 bd_size_t erase = _bds[i]->get_erase_size();
kenjiArai 0:5b88d5760320 75 if (i == 0 || (erase >= _erase_size && is_aligned(erase, _erase_size))) {
kenjiArai 0:5b88d5760320 76 _erase_size = erase;
kenjiArai 0:5b88d5760320 77 } else {
kenjiArai 0:5b88d5760320 78 MBED_ASSERT(_erase_size > erase && is_aligned(_erase_size, erase));
kenjiArai 0:5b88d5760320 79 }
kenjiArai 0:5b88d5760320 80
kenjiArai 0:5b88d5760320 81 int value = _bds[i]->get_erase_value();
kenjiArai 0:5b88d5760320 82 if (i == 0 || value == _erase_value) {
kenjiArai 0:5b88d5760320 83 _erase_value = value;
kenjiArai 0:5b88d5760320 84 } else {
kenjiArai 0:5b88d5760320 85 _erase_value = -1;
kenjiArai 0:5b88d5760320 86 }
kenjiArai 0:5b88d5760320 87
kenjiArai 0:5b88d5760320 88 _size += _bds[i]->size();
kenjiArai 0:5b88d5760320 89 }
kenjiArai 0:5b88d5760320 90
kenjiArai 0:5b88d5760320 91 _is_initialized = true;
kenjiArai 0:5b88d5760320 92 return BD_ERROR_OK;
kenjiArai 0:5b88d5760320 93
kenjiArai 0:5b88d5760320 94 fail:
kenjiArai 0:5b88d5760320 95 _is_initialized = false;
kenjiArai 0:5b88d5760320 96 _init_ref_count = 0;
kenjiArai 0:5b88d5760320 97 return err;
kenjiArai 0:5b88d5760320 98 }
kenjiArai 0:5b88d5760320 99
kenjiArai 0:5b88d5760320 100 int ChainingBlockDevice::deinit()
kenjiArai 0:5b88d5760320 101 {
kenjiArai 0:5b88d5760320 102 if (!_is_initialized) {
kenjiArai 0:5b88d5760320 103 return BD_ERROR_OK;
kenjiArai 0:5b88d5760320 104 }
kenjiArai 0:5b88d5760320 105
kenjiArai 0:5b88d5760320 106 uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
kenjiArai 0:5b88d5760320 107
kenjiArai 0:5b88d5760320 108 if (val) {
kenjiArai 0:5b88d5760320 109 return BD_ERROR_OK;
kenjiArai 0:5b88d5760320 110 }
kenjiArai 0:5b88d5760320 111
kenjiArai 0:5b88d5760320 112 for (size_t i = 0; i < _bd_count; i++) {
kenjiArai 0:5b88d5760320 113 int err = _bds[i]->deinit();
kenjiArai 0:5b88d5760320 114 if (err) {
kenjiArai 0:5b88d5760320 115 return err;
kenjiArai 0:5b88d5760320 116 }
kenjiArai 0:5b88d5760320 117 }
kenjiArai 0:5b88d5760320 118
kenjiArai 0:5b88d5760320 119 _is_initialized = false;
kenjiArai 0:5b88d5760320 120 return BD_ERROR_OK;
kenjiArai 0:5b88d5760320 121 }
kenjiArai 0:5b88d5760320 122
kenjiArai 0:5b88d5760320 123 int ChainingBlockDevice::sync()
kenjiArai 0:5b88d5760320 124 {
kenjiArai 0:5b88d5760320 125 if (!_is_initialized) {
kenjiArai 0:5b88d5760320 126 return BD_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 127 }
kenjiArai 0:5b88d5760320 128
kenjiArai 0:5b88d5760320 129 for (size_t i = 0; i < _bd_count; i++) {
kenjiArai 0:5b88d5760320 130 int err = _bds[i]->sync();
kenjiArai 0:5b88d5760320 131 if (err) {
kenjiArai 0:5b88d5760320 132 return err;
kenjiArai 0:5b88d5760320 133 }
kenjiArai 0:5b88d5760320 134 }
kenjiArai 0:5b88d5760320 135
kenjiArai 0:5b88d5760320 136 return 0;
kenjiArai 0:5b88d5760320 137 }
kenjiArai 0:5b88d5760320 138
kenjiArai 0:5b88d5760320 139 int ChainingBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
kenjiArai 0:5b88d5760320 140 {
kenjiArai 0:5b88d5760320 141 MBED_ASSERT(is_valid_read(addr, size));
kenjiArai 0:5b88d5760320 142 if (!_is_initialized) {
kenjiArai 0:5b88d5760320 143 return BD_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 144 }
kenjiArai 0:5b88d5760320 145
kenjiArai 0:5b88d5760320 146 uint8_t *buffer = static_cast<uint8_t *>(b);
kenjiArai 0:5b88d5760320 147
kenjiArai 0:5b88d5760320 148 // Find block devices containing blocks, may span multiple block devices
kenjiArai 0:5b88d5760320 149 for (size_t i = 0; i < _bd_count && size > 0; i++) {
kenjiArai 0:5b88d5760320 150 bd_size_t bdsize = _bds[i]->size();
kenjiArai 0:5b88d5760320 151
kenjiArai 0:5b88d5760320 152 if (addr < bdsize) {
kenjiArai 0:5b88d5760320 153 bd_size_t read = size;
kenjiArai 0:5b88d5760320 154 if (addr + read > bdsize) {
kenjiArai 0:5b88d5760320 155 read = bdsize - addr;
kenjiArai 0:5b88d5760320 156 }
kenjiArai 0:5b88d5760320 157
kenjiArai 0:5b88d5760320 158 int err = _bds[i]->read(buffer, addr, read);
kenjiArai 0:5b88d5760320 159 if (err) {
kenjiArai 0:5b88d5760320 160 return err;
kenjiArai 0:5b88d5760320 161 }
kenjiArai 0:5b88d5760320 162
kenjiArai 0:5b88d5760320 163 buffer += read;
kenjiArai 0:5b88d5760320 164 addr += read;
kenjiArai 0:5b88d5760320 165 size -= read;
kenjiArai 0:5b88d5760320 166 }
kenjiArai 0:5b88d5760320 167
kenjiArai 0:5b88d5760320 168 addr -= bdsize;
kenjiArai 0:5b88d5760320 169 }
kenjiArai 0:5b88d5760320 170
kenjiArai 0:5b88d5760320 171 return 0;
kenjiArai 0:5b88d5760320 172 }
kenjiArai 0:5b88d5760320 173
kenjiArai 0:5b88d5760320 174 int ChainingBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
kenjiArai 0:5b88d5760320 175 {
kenjiArai 0:5b88d5760320 176 MBED_ASSERT(is_valid_program(addr, size));
kenjiArai 0:5b88d5760320 177 if (!_is_initialized) {
kenjiArai 0:5b88d5760320 178 return BD_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 179 }
kenjiArai 0:5b88d5760320 180
kenjiArai 0:5b88d5760320 181 const uint8_t *buffer = static_cast<const uint8_t *>(b);
kenjiArai 0:5b88d5760320 182
kenjiArai 0:5b88d5760320 183 // Find block devices containing blocks, may span multiple block devices
kenjiArai 0:5b88d5760320 184 for (size_t i = 0; i < _bd_count && size > 0; i++) {
kenjiArai 0:5b88d5760320 185 bd_size_t bdsize = _bds[i]->size();
kenjiArai 0:5b88d5760320 186
kenjiArai 0:5b88d5760320 187 if (addr < bdsize) {
kenjiArai 0:5b88d5760320 188 bd_size_t program = size;
kenjiArai 0:5b88d5760320 189 if (addr + program > bdsize) {
kenjiArai 0:5b88d5760320 190 program = bdsize - addr;
kenjiArai 0:5b88d5760320 191 }
kenjiArai 0:5b88d5760320 192
kenjiArai 0:5b88d5760320 193 int err = _bds[i]->program(buffer, addr, program);
kenjiArai 0:5b88d5760320 194 if (err) {
kenjiArai 0:5b88d5760320 195 return err;
kenjiArai 0:5b88d5760320 196 }
kenjiArai 0:5b88d5760320 197
kenjiArai 0:5b88d5760320 198 buffer += program;
kenjiArai 0:5b88d5760320 199 addr += program;
kenjiArai 0:5b88d5760320 200 size -= program;
kenjiArai 0:5b88d5760320 201 }
kenjiArai 0:5b88d5760320 202
kenjiArai 0:5b88d5760320 203 addr -= bdsize;
kenjiArai 0:5b88d5760320 204 }
kenjiArai 0:5b88d5760320 205
kenjiArai 0:5b88d5760320 206 return 0;
kenjiArai 0:5b88d5760320 207 }
kenjiArai 0:5b88d5760320 208
kenjiArai 0:5b88d5760320 209 int ChainingBlockDevice::erase(bd_addr_t addr, bd_size_t size)
kenjiArai 0:5b88d5760320 210 {
kenjiArai 0:5b88d5760320 211 MBED_ASSERT(is_valid_erase(addr, size));
kenjiArai 0:5b88d5760320 212 if (!_is_initialized) {
kenjiArai 0:5b88d5760320 213 return BD_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 214 }
kenjiArai 0:5b88d5760320 215
kenjiArai 0:5b88d5760320 216 // Find block devices containing blocks, may span multiple block devices
kenjiArai 0:5b88d5760320 217 for (size_t i = 0; i < _bd_count && size > 0; i++) {
kenjiArai 0:5b88d5760320 218 bd_size_t bdsize = _bds[i]->size();
kenjiArai 0:5b88d5760320 219
kenjiArai 0:5b88d5760320 220 if (addr < bdsize) {
kenjiArai 0:5b88d5760320 221 bd_size_t erase = size;
kenjiArai 0:5b88d5760320 222 if (addr + erase > bdsize) {
kenjiArai 0:5b88d5760320 223 erase = bdsize - addr;
kenjiArai 0:5b88d5760320 224 }
kenjiArai 0:5b88d5760320 225
kenjiArai 0:5b88d5760320 226 int err = _bds[i]->erase(addr, erase);
kenjiArai 0:5b88d5760320 227 if (err) {
kenjiArai 0:5b88d5760320 228 return err;
kenjiArai 0:5b88d5760320 229 }
kenjiArai 0:5b88d5760320 230
kenjiArai 0:5b88d5760320 231 addr += erase;
kenjiArai 0:5b88d5760320 232 size -= erase;
kenjiArai 0:5b88d5760320 233 }
kenjiArai 0:5b88d5760320 234
kenjiArai 0:5b88d5760320 235 addr -= bdsize;
kenjiArai 0:5b88d5760320 236 }
kenjiArai 0:5b88d5760320 237
kenjiArai 0:5b88d5760320 238 return 0;
kenjiArai 0:5b88d5760320 239 }
kenjiArai 0:5b88d5760320 240
kenjiArai 0:5b88d5760320 241 bd_size_t ChainingBlockDevice::get_read_size() const
kenjiArai 0:5b88d5760320 242 {
kenjiArai 0:5b88d5760320 243 return _read_size;
kenjiArai 0:5b88d5760320 244 }
kenjiArai 0:5b88d5760320 245
kenjiArai 0:5b88d5760320 246 bd_size_t ChainingBlockDevice::get_program_size() const
kenjiArai 0:5b88d5760320 247 {
kenjiArai 0:5b88d5760320 248 return _program_size;
kenjiArai 0:5b88d5760320 249 }
kenjiArai 0:5b88d5760320 250
kenjiArai 0:5b88d5760320 251 bd_size_t ChainingBlockDevice::get_erase_size() const
kenjiArai 0:5b88d5760320 252 {
kenjiArai 0:5b88d5760320 253 return _erase_size;
kenjiArai 0:5b88d5760320 254 }
kenjiArai 0:5b88d5760320 255
kenjiArai 0:5b88d5760320 256 bd_size_t ChainingBlockDevice::get_erase_size(bd_addr_t addr) const
kenjiArai 0:5b88d5760320 257 {
kenjiArai 0:5b88d5760320 258 if (!_is_initialized) {
kenjiArai 0:5b88d5760320 259 return 0;
kenjiArai 0:5b88d5760320 260 }
kenjiArai 0:5b88d5760320 261
kenjiArai 0:5b88d5760320 262 bd_addr_t bd_start_addr = 0;
kenjiArai 0:5b88d5760320 263 for (size_t i = 0; i < _bd_count; i++) {
kenjiArai 0:5b88d5760320 264 bd_size_t bdsize = _bds[i]->size();
kenjiArai 0:5b88d5760320 265 if (addr < (bd_start_addr + bdsize)) {
kenjiArai 0:5b88d5760320 266 return _bds[i]->get_erase_size(addr - bd_start_addr);
kenjiArai 0:5b88d5760320 267 }
kenjiArai 0:5b88d5760320 268 bd_start_addr += bdsize;
kenjiArai 0:5b88d5760320 269 }
kenjiArai 0:5b88d5760320 270
kenjiArai 0:5b88d5760320 271 // Getting here implies an illegal address
kenjiArai 0:5b88d5760320 272 MBED_ASSERT(0);
kenjiArai 0:5b88d5760320 273 return 0; // satisfy compiler
kenjiArai 0:5b88d5760320 274 }
kenjiArai 0:5b88d5760320 275
kenjiArai 0:5b88d5760320 276 int ChainingBlockDevice::get_erase_value() const
kenjiArai 0:5b88d5760320 277 {
kenjiArai 0:5b88d5760320 278 return _erase_value;
kenjiArai 0:5b88d5760320 279 }
kenjiArai 0:5b88d5760320 280
kenjiArai 0:5b88d5760320 281 bd_size_t ChainingBlockDevice::size() const
kenjiArai 0:5b88d5760320 282 {
kenjiArai 0:5b88d5760320 283 return _size;
kenjiArai 0:5b88d5760320 284 }
kenjiArai 0:5b88d5760320 285
kenjiArai 0:5b88d5760320 286 const char *ChainingBlockDevice::get_type() const
kenjiArai 0:5b88d5760320 287 {
kenjiArai 0:5b88d5760320 288 return "CHAINING";
kenjiArai 0:5b88d5760320 289 }
kenjiArai 0:5b88d5760320 290
kenjiArai 0:5b88d5760320 291 } // namespace mbed