RTC auf true

Committer:
kevman
Date:
Wed Mar 13 11:03:24 2019 +0000
Revision:
2:7aab896b1a3b
Parent:
0:38ceb79fef03
2019-03-13

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kevman 0:38ceb79fef03 1 /* mbed Microcontroller Library
kevman 0:38ceb79fef03 2 * Copyright (c) 2018 ARM Limited
kevman 0:38ceb79fef03 3 *
kevman 0:38ceb79fef03 4 * Licensed under the Apache License, Version 2.0 (the "License");
kevman 0:38ceb79fef03 5 * you may not use this file except in compliance with the License.
kevman 0:38ceb79fef03 6 * You may obtain a copy of the License at
kevman 0:38ceb79fef03 7 *
kevman 0:38ceb79fef03 8 * http://www.apache.org/licenses/LICENSE-2.0
kevman 0:38ceb79fef03 9 *
kevman 0:38ceb79fef03 10 * Unless required by applicable law or agreed to in writing, software
kevman 0:38ceb79fef03 11 * distributed under the License is distributed on an "AS IS" BASIS,
kevman 0:38ceb79fef03 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kevman 0:38ceb79fef03 13 * See the License for the specific language governing permissions and
kevman 0:38ceb79fef03 14 * limitations under the License.
kevman 0:38ceb79fef03 15 */
kevman 0:38ceb79fef03 16
kevman 0:38ceb79fef03 17 #include "FlashSimBlockDevice.h"
kevman 0:38ceb79fef03 18 #include "platform/mbed_assert.h"
kevman 0:38ceb79fef03 19 #include "platform/mbed_critical.h"
kevman 0:38ceb79fef03 20 #include <algorithm>
kevman 0:38ceb79fef03 21 #include <stdlib.h>
kevman 0:38ceb79fef03 22 #include <string.h>
kevman 0:38ceb79fef03 23
kevman 0:38ceb79fef03 24 static const bd_size_t min_blank_buf_size = 32;
kevman 0:38ceb79fef03 25
kevman 0:38ceb79fef03 26 static inline uint32_t align_up(bd_size_t val, bd_size_t size)
kevman 0:38ceb79fef03 27 {
kevman 0:38ceb79fef03 28 return (((val - 1) / size) + 1) * size;
kevman 0:38ceb79fef03 29 }
kevman 0:38ceb79fef03 30
kevman 0:38ceb79fef03 31 FlashSimBlockDevice::FlashSimBlockDevice(BlockDevice *bd, uint8_t erase_value) :
kevman 0:38ceb79fef03 32 _erase_value(erase_value), _blank_buf_size(0),
kevman 0:38ceb79fef03 33 _blank_buf(0), _bd(bd), _init_ref_count(0), _is_initialized(false)
kevman 0:38ceb79fef03 34 {
kevman 0:38ceb79fef03 35 }
kevman 0:38ceb79fef03 36
kevman 0:38ceb79fef03 37 FlashSimBlockDevice::~FlashSimBlockDevice()
kevman 0:38ceb79fef03 38 {
kevman 0:38ceb79fef03 39 deinit();
kevman 0:38ceb79fef03 40 delete[] _blank_buf;
kevman 0:38ceb79fef03 41 }
kevman 0:38ceb79fef03 42
kevman 0:38ceb79fef03 43 int FlashSimBlockDevice::init()
kevman 0:38ceb79fef03 44 {
kevman 0:38ceb79fef03 45 int err;
kevman 0:38ceb79fef03 46 uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1);
kevman 0:38ceb79fef03 47
kevman 0:38ceb79fef03 48 if (val != 1) {
kevman 0:38ceb79fef03 49 return BD_ERROR_OK;
kevman 0:38ceb79fef03 50 }
kevman 0:38ceb79fef03 51
kevman 0:38ceb79fef03 52 err = _bd->init();
kevman 0:38ceb79fef03 53 if (err) {
kevman 0:38ceb79fef03 54 goto fail;
kevman 0:38ceb79fef03 55 }
kevman 0:38ceb79fef03 56 _blank_buf_size = align_up(min_blank_buf_size, _bd->get_program_size());
kevman 0:38ceb79fef03 57 if (!_blank_buf) {
kevman 0:38ceb79fef03 58 _blank_buf = new uint8_t[_blank_buf_size];
kevman 0:38ceb79fef03 59 MBED_ASSERT(_blank_buf);
kevman 0:38ceb79fef03 60 }
kevman 0:38ceb79fef03 61
kevman 0:38ceb79fef03 62 _is_initialized = true;
kevman 0:38ceb79fef03 63 return BD_ERROR_OK;
kevman 0:38ceb79fef03 64
kevman 0:38ceb79fef03 65 fail:
kevman 0:38ceb79fef03 66 _is_initialized = false;
kevman 0:38ceb79fef03 67 _init_ref_count = 0;
kevman 0:38ceb79fef03 68 return err;
kevman 0:38ceb79fef03 69 }
kevman 0:38ceb79fef03 70
kevman 0:38ceb79fef03 71 int FlashSimBlockDevice::deinit()
kevman 0:38ceb79fef03 72 {
kevman 0:38ceb79fef03 73 if (!_is_initialized) {
kevman 0:38ceb79fef03 74 return BD_ERROR_OK;
kevman 0:38ceb79fef03 75 }
kevman 0:38ceb79fef03 76
kevman 0:38ceb79fef03 77 uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
kevman 0:38ceb79fef03 78
kevman 0:38ceb79fef03 79 if (val) {
kevman 0:38ceb79fef03 80 return BD_ERROR_OK;
kevman 0:38ceb79fef03 81 }
kevman 0:38ceb79fef03 82
kevman 0:38ceb79fef03 83 _is_initialized = false;
kevman 0:38ceb79fef03 84 return _bd->deinit();
kevman 0:38ceb79fef03 85 }
kevman 0:38ceb79fef03 86
kevman 0:38ceb79fef03 87 int FlashSimBlockDevice::sync()
kevman 0:38ceb79fef03 88 {
kevman 0:38ceb79fef03 89 if (!_is_initialized) {
kevman 0:38ceb79fef03 90 return BD_ERROR_DEVICE_ERROR;
kevman 0:38ceb79fef03 91 }
kevman 0:38ceb79fef03 92
kevman 0:38ceb79fef03 93 return _bd->sync();
kevman 0:38ceb79fef03 94 }
kevman 0:38ceb79fef03 95
kevman 0:38ceb79fef03 96 bd_size_t FlashSimBlockDevice::get_read_size() const
kevman 0:38ceb79fef03 97 {
kevman 0:38ceb79fef03 98 if (!_is_initialized) {
kevman 0:38ceb79fef03 99 return 0;
kevman 0:38ceb79fef03 100 }
kevman 0:38ceb79fef03 101
kevman 0:38ceb79fef03 102 return _bd->get_read_size();
kevman 0:38ceb79fef03 103 }
kevman 0:38ceb79fef03 104
kevman 0:38ceb79fef03 105 bd_size_t FlashSimBlockDevice::get_program_size() const
kevman 0:38ceb79fef03 106 {
kevman 0:38ceb79fef03 107 if (!_is_initialized) {
kevman 0:38ceb79fef03 108 return 0;
kevman 0:38ceb79fef03 109 }
kevman 0:38ceb79fef03 110
kevman 0:38ceb79fef03 111 return _bd->get_program_size();
kevman 0:38ceb79fef03 112 }
kevman 0:38ceb79fef03 113
kevman 0:38ceb79fef03 114 bd_size_t FlashSimBlockDevice::get_erase_size() const
kevman 0:38ceb79fef03 115 {
kevman 0:38ceb79fef03 116 if (!_is_initialized) {
kevman 0:38ceb79fef03 117 return 0;
kevman 0:38ceb79fef03 118 }
kevman 0:38ceb79fef03 119
kevman 0:38ceb79fef03 120 return _bd->get_erase_size();
kevman 0:38ceb79fef03 121 }
kevman 0:38ceb79fef03 122
kevman 0:38ceb79fef03 123 bd_size_t FlashSimBlockDevice::get_erase_size(bd_addr_t addr) const
kevman 0:38ceb79fef03 124 {
kevman 0:38ceb79fef03 125 if (!_is_initialized) {
kevman 0:38ceb79fef03 126 return 0;
kevman 0:38ceb79fef03 127 }
kevman 0:38ceb79fef03 128
kevman 0:38ceb79fef03 129 return _bd->get_erase_size(addr);
kevman 0:38ceb79fef03 130 }
kevman 0:38ceb79fef03 131
kevman 0:38ceb79fef03 132 bd_size_t FlashSimBlockDevice::size() const
kevman 0:38ceb79fef03 133 {
kevman 0:38ceb79fef03 134 if (!_is_initialized) {
kevman 0:38ceb79fef03 135 return 0;
kevman 0:38ceb79fef03 136 }
kevman 0:38ceb79fef03 137
kevman 0:38ceb79fef03 138 return _bd->size();
kevman 0:38ceb79fef03 139 }
kevman 0:38ceb79fef03 140
kevman 0:38ceb79fef03 141 int FlashSimBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
kevman 0:38ceb79fef03 142 {
kevman 0:38ceb79fef03 143 if (!_is_initialized) {
kevman 0:38ceb79fef03 144 return BD_ERROR_DEVICE_ERROR;
kevman 0:38ceb79fef03 145 }
kevman 0:38ceb79fef03 146
kevman 0:38ceb79fef03 147 return _bd->read(b, addr, size);
kevman 0:38ceb79fef03 148 }
kevman 0:38ceb79fef03 149
kevman 0:38ceb79fef03 150 int FlashSimBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
kevman 0:38ceb79fef03 151 {
kevman 0:38ceb79fef03 152 MBED_ASSERT(is_valid_program(addr, size));
kevman 0:38ceb79fef03 153 if (!_is_initialized) {
kevman 0:38ceb79fef03 154 return BD_ERROR_DEVICE_ERROR;
kevman 0:38ceb79fef03 155 }
kevman 0:38ceb79fef03 156
kevman 0:38ceb79fef03 157 bd_addr_t curr_addr = addr;
kevman 0:38ceb79fef03 158 bd_size_t curr_size = size;
kevman 0:38ceb79fef03 159
kevman 0:38ceb79fef03 160 const uint8_t *buf = (const uint8_t *) b;
kevman 0:38ceb79fef03 161 while (curr_size) {
kevman 0:38ceb79fef03 162 bd_size_t read_size = std::min(_blank_buf_size, curr_size);
kevman 0:38ceb79fef03 163 int ret = _bd->read(_blank_buf, curr_addr, read_size);
kevman 0:38ceb79fef03 164 if (ret) {
kevman 0:38ceb79fef03 165 return ret;
kevman 0:38ceb79fef03 166 }
kevman 0:38ceb79fef03 167 for (bd_size_t i = 0; i < read_size; i++) {
kevman 0:38ceb79fef03 168 // Allow either programming on blanks or programming the same value
kevman 0:38ceb79fef03 169 // (as real flash devices do)
kevman 0:38ceb79fef03 170 if ((_blank_buf[i] != _erase_value) && (_blank_buf[i] != *buf)) {
kevman 0:38ceb79fef03 171 return BD_ERROR_NOT_ERASED;
kevman 0:38ceb79fef03 172 }
kevman 0:38ceb79fef03 173 buf++;
kevman 0:38ceb79fef03 174 }
kevman 0:38ceb79fef03 175 curr_addr += read_size;
kevman 0:38ceb79fef03 176 curr_size -= read_size;
kevman 0:38ceb79fef03 177 }
kevman 0:38ceb79fef03 178
kevman 0:38ceb79fef03 179 return _bd->program(b, addr, size);
kevman 0:38ceb79fef03 180 }
kevman 0:38ceb79fef03 181
kevman 0:38ceb79fef03 182 int FlashSimBlockDevice::erase(bd_addr_t addr, bd_size_t size)
kevman 0:38ceb79fef03 183 {
kevman 0:38ceb79fef03 184 MBED_ASSERT(is_valid_erase(addr, size));
kevman 0:38ceb79fef03 185
kevman 0:38ceb79fef03 186 if (!_is_initialized) {
kevman 0:38ceb79fef03 187 return BD_ERROR_DEVICE_ERROR;
kevman 0:38ceb79fef03 188 }
kevman 0:38ceb79fef03 189
kevman 0:38ceb79fef03 190 bd_addr_t curr_addr = addr;
kevman 0:38ceb79fef03 191 bd_size_t curr_size = size;
kevman 0:38ceb79fef03 192
kevman 0:38ceb79fef03 193 memset(_blank_buf, _erase_value, (unsigned int) _blank_buf_size);
kevman 0:38ceb79fef03 194
kevman 0:38ceb79fef03 195 while (curr_size) {
kevman 0:38ceb79fef03 196 bd_size_t prog_size = std::min(_blank_buf_size, curr_size);
kevman 0:38ceb79fef03 197 int ret = _bd->program(_blank_buf, curr_addr, prog_size);
kevman 0:38ceb79fef03 198 if (ret) {
kevman 0:38ceb79fef03 199 return ret;
kevman 0:38ceb79fef03 200 }
kevman 0:38ceb79fef03 201 curr_addr += prog_size;
kevman 0:38ceb79fef03 202 curr_size -= prog_size;
kevman 0:38ceb79fef03 203 }
kevman 0:38ceb79fef03 204
kevman 0:38ceb79fef03 205 return BD_ERROR_OK;
kevman 0:38ceb79fef03 206 }
kevman 0:38ceb79fef03 207
kevman 0:38ceb79fef03 208 int FlashSimBlockDevice::get_erase_value() const
kevman 0:38ceb79fef03 209 {
kevman 0:38ceb79fef03 210 return _erase_value;
kevman 0:38ceb79fef03 211 }