mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 17 23:23:45 2019 +0000
Revision:
0:5b88d5760320
Child:
1:9db0e321a9f4
mbed-os5 only for TYBLE16

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 "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 MBED_ASSERT(_blocks != NULL);
kenjiArai 0:5b88d5760320 91 return _read_size;
kenjiArai 0:5b88d5760320 92 }
kenjiArai 0:5b88d5760320 93
kenjiArai 0:5b88d5760320 94 bd_size_t HeapBlockDevice::get_program_size() const
kenjiArai 0:5b88d5760320 95 {
kenjiArai 0:5b88d5760320 96 MBED_ASSERT(_blocks != NULL);
kenjiArai 0:5b88d5760320 97 return _program_size;
kenjiArai 0:5b88d5760320 98 }
kenjiArai 0:5b88d5760320 99
kenjiArai 0:5b88d5760320 100 bd_size_t HeapBlockDevice::get_erase_size() const
kenjiArai 0:5b88d5760320 101 {
kenjiArai 0:5b88d5760320 102 MBED_ASSERT(_blocks != NULL);
kenjiArai 0:5b88d5760320 103 return _erase_size;
kenjiArai 0:5b88d5760320 104 }
kenjiArai 0:5b88d5760320 105
kenjiArai 0:5b88d5760320 106 bd_size_t HeapBlockDevice::get_erase_size(bd_addr_t addr) const
kenjiArai 0:5b88d5760320 107 {
kenjiArai 0:5b88d5760320 108 MBED_ASSERT(_blocks != NULL);
kenjiArai 0:5b88d5760320 109 return _erase_size;
kenjiArai 0:5b88d5760320 110 }
kenjiArai 0:5b88d5760320 111
kenjiArai 0:5b88d5760320 112 bd_size_t HeapBlockDevice::size() const
kenjiArai 0:5b88d5760320 113 {
kenjiArai 0:5b88d5760320 114 MBED_ASSERT(_blocks != NULL);
kenjiArai 0:5b88d5760320 115 return _count * _erase_size;
kenjiArai 0:5b88d5760320 116 }
kenjiArai 0:5b88d5760320 117
kenjiArai 0:5b88d5760320 118 int HeapBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
kenjiArai 0:5b88d5760320 119 {
kenjiArai 0:5b88d5760320 120 MBED_ASSERT(_blocks != NULL);
kenjiArai 0:5b88d5760320 121 MBED_ASSERT(is_valid_read(addr, size));
kenjiArai 0:5b88d5760320 122 if (!_is_initialized) {
kenjiArai 0:5b88d5760320 123 return BD_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 124 }
kenjiArai 0:5b88d5760320 125
kenjiArai 0:5b88d5760320 126 uint8_t *buffer = static_cast<uint8_t *>(b);
kenjiArai 0:5b88d5760320 127
kenjiArai 0:5b88d5760320 128 while (size > 0) {
kenjiArai 0:5b88d5760320 129 bd_addr_t hi = addr / _erase_size;
kenjiArai 0:5b88d5760320 130 bd_addr_t lo = addr % _erase_size;
kenjiArai 0:5b88d5760320 131
kenjiArai 0:5b88d5760320 132 if (_blocks[hi]) {
kenjiArai 0:5b88d5760320 133 memcpy(buffer, &_blocks[hi][lo], _read_size);
kenjiArai 0:5b88d5760320 134 } else {
kenjiArai 0:5b88d5760320 135 memset(buffer, 0, _read_size);
kenjiArai 0:5b88d5760320 136 }
kenjiArai 0:5b88d5760320 137
kenjiArai 0:5b88d5760320 138 buffer += _read_size;
kenjiArai 0:5b88d5760320 139 addr += _read_size;
kenjiArai 0:5b88d5760320 140 size -= _read_size;
kenjiArai 0:5b88d5760320 141 }
kenjiArai 0:5b88d5760320 142
kenjiArai 0:5b88d5760320 143 return 0;
kenjiArai 0:5b88d5760320 144 }
kenjiArai 0:5b88d5760320 145
kenjiArai 0:5b88d5760320 146 int HeapBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
kenjiArai 0:5b88d5760320 147 {
kenjiArai 0:5b88d5760320 148 MBED_ASSERT(_blocks != NULL);
kenjiArai 0:5b88d5760320 149 MBED_ASSERT(is_valid_program(addr, size));
kenjiArai 0:5b88d5760320 150 if (!_is_initialized) {
kenjiArai 0:5b88d5760320 151 return BD_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 152 }
kenjiArai 0:5b88d5760320 153
kenjiArai 0:5b88d5760320 154 const uint8_t *buffer = static_cast<const uint8_t *>(b);
kenjiArai 0:5b88d5760320 155
kenjiArai 0:5b88d5760320 156 while (size > 0) {
kenjiArai 0:5b88d5760320 157 bd_addr_t hi = addr / _erase_size;
kenjiArai 0:5b88d5760320 158 bd_addr_t lo = addr % _erase_size;
kenjiArai 0:5b88d5760320 159
kenjiArai 0:5b88d5760320 160 if (!_blocks[hi]) {
kenjiArai 0:5b88d5760320 161 _blocks[hi] = (uint8_t *)malloc(_erase_size);
kenjiArai 0:5b88d5760320 162 if (!_blocks[hi]) {
kenjiArai 0:5b88d5760320 163 return BD_ERROR_DEVICE_ERROR;
kenjiArai 0:5b88d5760320 164 }
kenjiArai 0:5b88d5760320 165 }
kenjiArai 0:5b88d5760320 166
kenjiArai 0:5b88d5760320 167 memcpy(&_blocks[hi][lo], buffer, _program_size);
kenjiArai 0:5b88d5760320 168
kenjiArai 0:5b88d5760320 169 buffer += _program_size;
kenjiArai 0:5b88d5760320 170 addr += _program_size;
kenjiArai 0:5b88d5760320 171 size -= _program_size;
kenjiArai 0:5b88d5760320 172 }
kenjiArai 0:5b88d5760320 173
kenjiArai 0:5b88d5760320 174 return 0;
kenjiArai 0:5b88d5760320 175 }
kenjiArai 0:5b88d5760320 176
kenjiArai 0:5b88d5760320 177 int HeapBlockDevice::erase(bd_addr_t addr, bd_size_t size)
kenjiArai 0:5b88d5760320 178 {
kenjiArai 0:5b88d5760320 179 MBED_ASSERT(_blocks != NULL);
kenjiArai 0:5b88d5760320 180 MBED_ASSERT(is_valid_erase(addr, size));
kenjiArai 0:5b88d5760320 181 // TODO assert on programming unerased blocks
kenjiArai 0:5b88d5760320 182
kenjiArai 0:5b88d5760320 183 return 0;
kenjiArai 0:5b88d5760320 184 }
kenjiArai 0:5b88d5760320 185
kenjiArai 0:5b88d5760320 186 const char *HeapBlockDevice::get_type() const
kenjiArai 0:5b88d5760320 187 {
kenjiArai 0:5b88d5760320 188 return "HEAP";
kenjiArai 0:5b88d5760320 189 }
kenjiArai 0:5b88d5760320 190
kenjiArai 0:5b88d5760320 191 } // namespace mbed
kenjiArai 0:5b88d5760320 192