mbed-os5 only for TYBLE16
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
features/storage/blockdevice/HeapBlockDevice.cpp@1:9db0e321a9f4, 2019-12-31 (annotated)
- 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?
User | Revision | Line number | New 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 "HeapBlockDevice.h" |
kenjiArai | 0:5b88d5760320 | 18 | #include "platform/mbed_atomic.h" |
kenjiArai | 0:5b88d5760320 | 19 | #include <stdlib.h> |
kenjiArai | 0:5b88d5760320 | 20 | #include <string.h> |
kenjiArai | 0:5b88d5760320 | 21 | |
kenjiArai | 0:5b88d5760320 | 22 | namespace mbed { |
kenjiArai | 0:5b88d5760320 | 23 | |
kenjiArai | 0:5b88d5760320 | 24 | HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t block) |
kenjiArai | 0:5b88d5760320 | 25 | : _read_size(block), _program_size(block), _erase_size(block) |
kenjiArai | 0:5b88d5760320 | 26 | , _count(size / block), _blocks(0), _init_ref_count(0), _is_initialized(false) |
kenjiArai | 0:5b88d5760320 | 27 | { |
kenjiArai | 0:5b88d5760320 | 28 | MBED_ASSERT(_count * _erase_size == size); |
kenjiArai | 0:5b88d5760320 | 29 | } |
kenjiArai | 0:5b88d5760320 | 30 | |
kenjiArai | 0:5b88d5760320 | 31 | HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t read, bd_size_t program, bd_size_t erase) |
kenjiArai | 0:5b88d5760320 | 32 | : _read_size(read), _program_size(program), _erase_size(erase) |
kenjiArai | 0:5b88d5760320 | 33 | , _count(size / erase), _blocks(0), _init_ref_count(0), _is_initialized(false) |
kenjiArai | 0:5b88d5760320 | 34 | { |
kenjiArai | 0:5b88d5760320 | 35 | MBED_ASSERT(_count * _erase_size == size); |
kenjiArai | 0:5b88d5760320 | 36 | } |
kenjiArai | 0:5b88d5760320 | 37 | |
kenjiArai | 0:5b88d5760320 | 38 | HeapBlockDevice::~HeapBlockDevice() |
kenjiArai | 0:5b88d5760320 | 39 | { |
kenjiArai | 0:5b88d5760320 | 40 | if (_blocks) { |
kenjiArai | 0:5b88d5760320 | 41 | for (size_t i = 0; i < _count; i++) { |
kenjiArai | 0:5b88d5760320 | 42 | free(_blocks[i]); |
kenjiArai | 0:5b88d5760320 | 43 | } |
kenjiArai | 0:5b88d5760320 | 44 | |
kenjiArai | 0:5b88d5760320 | 45 | delete[] _blocks; |
kenjiArai | 0:5b88d5760320 | 46 | _blocks = 0; |
kenjiArai | 0:5b88d5760320 | 47 | } |
kenjiArai | 0:5b88d5760320 | 48 | } |
kenjiArai | 0:5b88d5760320 | 49 | |
kenjiArai | 0:5b88d5760320 | 50 | int HeapBlockDevice::init() |
kenjiArai | 0:5b88d5760320 | 51 | { |
kenjiArai | 0:5b88d5760320 | 52 | uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1); |
kenjiArai | 0:5b88d5760320 | 53 | |
kenjiArai | 0:5b88d5760320 | 54 | if (val != 1) { |
kenjiArai | 0:5b88d5760320 | 55 | return BD_ERROR_OK; |
kenjiArai | 0:5b88d5760320 | 56 | } |
kenjiArai | 0:5b88d5760320 | 57 | |
kenjiArai | 0:5b88d5760320 | 58 | if (!_blocks) { |
kenjiArai | 0:5b88d5760320 | 59 | _blocks = new uint8_t *[_count]; |
kenjiArai | 0:5b88d5760320 | 60 | for (size_t i = 0; i < _count; i++) { |
kenjiArai | 0:5b88d5760320 | 61 | _blocks[i] = 0; |
kenjiArai | 0:5b88d5760320 | 62 | } |
kenjiArai | 0:5b88d5760320 | 63 | } |
kenjiArai | 0:5b88d5760320 | 64 | |
kenjiArai | 0:5b88d5760320 | 65 | _is_initialized = true; |
kenjiArai | 0:5b88d5760320 | 66 | return BD_ERROR_OK; |
kenjiArai | 0:5b88d5760320 | 67 | } |
kenjiArai | 0:5b88d5760320 | 68 | |
kenjiArai | 0:5b88d5760320 | 69 | int HeapBlockDevice::deinit() |
kenjiArai | 0:5b88d5760320 | 70 | { |
kenjiArai | 0:5b88d5760320 | 71 | if (!_is_initialized) { |
kenjiArai | 0:5b88d5760320 | 72 | return BD_ERROR_OK; |
kenjiArai | 0:5b88d5760320 | 73 | } |
kenjiArai | 0:5b88d5760320 | 74 | |
kenjiArai | 0:5b88d5760320 | 75 | uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1); |
kenjiArai | 0:5b88d5760320 | 76 | |
kenjiArai | 0:5b88d5760320 | 77 | if (val) { |
kenjiArai | 0:5b88d5760320 | 78 | return BD_ERROR_OK; |
kenjiArai | 0:5b88d5760320 | 79 | } |
kenjiArai | 0:5b88d5760320 | 80 | |
kenjiArai | 0:5b88d5760320 | 81 | MBED_ASSERT(_blocks != NULL); |
kenjiArai | 0:5b88d5760320 | 82 | // Memory is lazily cleaned up in destructor to allow |
kenjiArai | 0:5b88d5760320 | 83 | // data to live across de/reinitialization |
kenjiArai | 0:5b88d5760320 | 84 | _is_initialized = false; |
kenjiArai | 0:5b88d5760320 | 85 | return BD_ERROR_OK; |
kenjiArai | 0:5b88d5760320 | 86 | } |
kenjiArai | 0:5b88d5760320 | 87 | |
kenjiArai | 0:5b88d5760320 | 88 | bd_size_t HeapBlockDevice::get_read_size() const |
kenjiArai | 0:5b88d5760320 | 89 | { |
kenjiArai | 0:5b88d5760320 | 90 | return _read_size; |
kenjiArai | 0:5b88d5760320 | 91 | } |
kenjiArai | 0:5b88d5760320 | 92 | |
kenjiArai | 0:5b88d5760320 | 93 | bd_size_t HeapBlockDevice::get_program_size() const |
kenjiArai | 0:5b88d5760320 | 94 | { |
kenjiArai | 0:5b88d5760320 | 95 | return _program_size; |
kenjiArai | 0:5b88d5760320 | 96 | } |
kenjiArai | 0:5b88d5760320 | 97 | |
kenjiArai | 0:5b88d5760320 | 98 | bd_size_t HeapBlockDevice::get_erase_size() const |
kenjiArai | 0:5b88d5760320 | 99 | { |
kenjiArai | 0:5b88d5760320 | 100 | return _erase_size; |
kenjiArai | 0:5b88d5760320 | 101 | } |
kenjiArai | 0:5b88d5760320 | 102 | |
kenjiArai | 0:5b88d5760320 | 103 | bd_size_t HeapBlockDevice::get_erase_size(bd_addr_t addr) const |
kenjiArai | 0:5b88d5760320 | 104 | { |
kenjiArai | 0:5b88d5760320 | 105 | return _erase_size; |
kenjiArai | 0:5b88d5760320 | 106 | } |
kenjiArai | 0:5b88d5760320 | 107 | |
kenjiArai | 0:5b88d5760320 | 108 | bd_size_t HeapBlockDevice::size() const |
kenjiArai | 0:5b88d5760320 | 109 | { |
kenjiArai | 0:5b88d5760320 | 110 | return _count * _erase_size; |
kenjiArai | 0:5b88d5760320 | 111 | } |
kenjiArai | 0:5b88d5760320 | 112 | |
kenjiArai | 0:5b88d5760320 | 113 | int HeapBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) |
kenjiArai | 0:5b88d5760320 | 114 | { |
kenjiArai | 0:5b88d5760320 | 115 | if (!_is_initialized) { |
kenjiArai | 0:5b88d5760320 | 116 | return BD_ERROR_DEVICE_ERROR; |
kenjiArai | 0:5b88d5760320 | 117 | } |
kenjiArai | 1:9db0e321a9f4 | 118 | if (!is_valid_read(addr, size)) { |
kenjiArai | 1:9db0e321a9f4 | 119 | return BD_ERROR_DEVICE_ERROR; |
kenjiArai | 1:9db0e321a9f4 | 120 | } |
kenjiArai | 0:5b88d5760320 | 121 | |
kenjiArai | 0:5b88d5760320 | 122 | uint8_t *buffer = static_cast<uint8_t *>(b); |
kenjiArai | 0:5b88d5760320 | 123 | |
kenjiArai | 0:5b88d5760320 | 124 | while (size > 0) { |
kenjiArai | 0:5b88d5760320 | 125 | bd_addr_t hi = addr / _erase_size; |
kenjiArai | 0:5b88d5760320 | 126 | bd_addr_t lo = addr % _erase_size; |
kenjiArai | 0:5b88d5760320 | 127 | |
kenjiArai | 0:5b88d5760320 | 128 | if (_blocks[hi]) { |
kenjiArai | 0:5b88d5760320 | 129 | memcpy(buffer, &_blocks[hi][lo], _read_size); |
kenjiArai | 0:5b88d5760320 | 130 | } else { |
kenjiArai | 0:5b88d5760320 | 131 | memset(buffer, 0, _read_size); |
kenjiArai | 0:5b88d5760320 | 132 | } |
kenjiArai | 0:5b88d5760320 | 133 | |
kenjiArai | 0:5b88d5760320 | 134 | buffer += _read_size; |
kenjiArai | 0:5b88d5760320 | 135 | addr += _read_size; |
kenjiArai | 0:5b88d5760320 | 136 | size -= _read_size; |
kenjiArai | 0:5b88d5760320 | 137 | } |
kenjiArai | 0:5b88d5760320 | 138 | |
kenjiArai | 0:5b88d5760320 | 139 | return 0; |
kenjiArai | 0:5b88d5760320 | 140 | } |
kenjiArai | 0:5b88d5760320 | 141 | |
kenjiArai | 0:5b88d5760320 | 142 | int HeapBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) |
kenjiArai | 0:5b88d5760320 | 143 | { |
kenjiArai | 0:5b88d5760320 | 144 | if (!_is_initialized) { |
kenjiArai | 0:5b88d5760320 | 145 | return BD_ERROR_DEVICE_ERROR; |
kenjiArai | 0:5b88d5760320 | 146 | } |
kenjiArai | 1:9db0e321a9f4 | 147 | if (!is_valid_program(addr, size)) { |
kenjiArai | 1:9db0e321a9f4 | 148 | return BD_ERROR_DEVICE_ERROR; |
kenjiArai | 1:9db0e321a9f4 | 149 | } |
kenjiArai | 0:5b88d5760320 | 150 | |
kenjiArai | 0:5b88d5760320 | 151 | const uint8_t *buffer = static_cast<const uint8_t *>(b); |
kenjiArai | 0:5b88d5760320 | 152 | |
kenjiArai | 0:5b88d5760320 | 153 | while (size > 0) { |
kenjiArai | 0:5b88d5760320 | 154 | bd_addr_t hi = addr / _erase_size; |
kenjiArai | 0:5b88d5760320 | 155 | bd_addr_t lo = addr % _erase_size; |
kenjiArai | 0:5b88d5760320 | 156 | |
kenjiArai | 0:5b88d5760320 | 157 | if (!_blocks[hi]) { |
kenjiArai | 0:5b88d5760320 | 158 | _blocks[hi] = (uint8_t *)malloc(_erase_size); |
kenjiArai | 0:5b88d5760320 | 159 | if (!_blocks[hi]) { |
kenjiArai | 0:5b88d5760320 | 160 | return BD_ERROR_DEVICE_ERROR; |
kenjiArai | 0:5b88d5760320 | 161 | } |
kenjiArai | 0:5b88d5760320 | 162 | } |
kenjiArai | 0:5b88d5760320 | 163 | |
kenjiArai | 0:5b88d5760320 | 164 | memcpy(&_blocks[hi][lo], buffer, _program_size); |
kenjiArai | 0:5b88d5760320 | 165 | |
kenjiArai | 0:5b88d5760320 | 166 | buffer += _program_size; |
kenjiArai | 0:5b88d5760320 | 167 | addr += _program_size; |
kenjiArai | 0:5b88d5760320 | 168 | size -= _program_size; |
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 HeapBlockDevice::erase(bd_addr_t addr, bd_size_t size) |
kenjiArai | 0:5b88d5760320 | 175 | { |
kenjiArai | 1:9db0e321a9f4 | 176 | if (!_is_initialized) { |
kenjiArai | 1:9db0e321a9f4 | 177 | return BD_ERROR_DEVICE_ERROR; |
kenjiArai | 1:9db0e321a9f4 | 178 | } |
kenjiArai | 1:9db0e321a9f4 | 179 | if (!is_valid_erase(addr, size)) { |
kenjiArai | 1:9db0e321a9f4 | 180 | return BD_ERROR_DEVICE_ERROR; |
kenjiArai | 1:9db0e321a9f4 | 181 | } |
kenjiArai | 0:5b88d5760320 | 182 | return 0; |
kenjiArai | 0:5b88d5760320 | 183 | } |
kenjiArai | 0:5b88d5760320 | 184 | |
kenjiArai | 0:5b88d5760320 | 185 | const char *HeapBlockDevice::get_type() const |
kenjiArai | 0:5b88d5760320 | 186 | { |
kenjiArai | 0:5b88d5760320 | 187 | return "HEAP"; |
kenjiArai | 0:5b88d5760320 | 188 | } |
kenjiArai | 0:5b88d5760320 | 189 | |
kenjiArai | 0:5b88d5760320 | 190 | } // namespace mbed |