Lazily allocated heap-backed block device. When writing data of ROM address, heap memory is not used.

Dependents:   GR-PEACH-webcam GR-PEACH_DR_STRANGE_VR_GAME GR-Boards_WebCamera

Committer:
dkato
Date:
Tue May 16 04:24:46 2017 +0000
Revision:
0:3e16bac28356
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dkato 0:3e16bac28356 1 /* mbed Microcontroller Library
dkato 0:3e16bac28356 2 * Copyright (c) 2017 ARM Limited
dkato 0:3e16bac28356 3 *
dkato 0:3e16bac28356 4 * Licensed under the Apache License, Version 2.0 (the "License");
dkato 0:3e16bac28356 5 * you may not use this file except in compliance with the License.
dkato 0:3e16bac28356 6 * You may obtain a copy of the License at
dkato 0:3e16bac28356 7 *
dkato 0:3e16bac28356 8 * http://www.apache.org/licenses/LICENSE-2.0
dkato 0:3e16bac28356 9 *
dkato 0:3e16bac28356 10 * Unless required by applicable law or agreed to in writing, software
dkato 0:3e16bac28356 11 * distributed under the License is distributed on an "AS IS" BASIS,
dkato 0:3e16bac28356 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
dkato 0:3e16bac28356 13 * See the License for the specific language governing permissions and
dkato 0:3e16bac28356 14 * limitations under the License.
dkato 0:3e16bac28356 15 */
dkato 0:3e16bac28356 16
dkato 0:3e16bac28356 17 #include "RomRamBlockDevice.h"
dkato 0:3e16bac28356 18
dkato 0:3e16bac28356 19
dkato 0:3e16bac28356 20 RomRamBlockDevice::RomRamBlockDevice(bd_size_t size, bd_size_t block)
dkato 0:3e16bac28356 21 : _read_size(block), _program_size(block), _erase_size(block)
dkato 0:3e16bac28356 22 , _count(size / block), _blocks(0), _rom_start(0xFFFFFFFF), _rom_end(0xFFFFFFFF)
dkato 0:3e16bac28356 23 {
dkato 0:3e16bac28356 24 MBED_ASSERT(_count * _erase_size == size);
dkato 0:3e16bac28356 25 }
dkato 0:3e16bac28356 26
dkato 0:3e16bac28356 27 RomRamBlockDevice::RomRamBlockDevice(bd_size_t size, bd_size_t read, bd_size_t program, bd_size_t erase)
dkato 0:3e16bac28356 28 : _read_size(read), _program_size(program), _erase_size(erase)
dkato 0:3e16bac28356 29 , _count(size / erase), _blocks(0), _rom_start(0xFFFFFFFF), _rom_end(0xFFFFFFFF)
dkato 0:3e16bac28356 30 {
dkato 0:3e16bac28356 31 MBED_ASSERT(_count * _erase_size == size);
dkato 0:3e16bac28356 32 }
dkato 0:3e16bac28356 33
dkato 0:3e16bac28356 34 RomRamBlockDevice::~RomRamBlockDevice()
dkato 0:3e16bac28356 35 {
dkato 0:3e16bac28356 36 if (_blocks) {
dkato 0:3e16bac28356 37 for (size_t i = 0; i < _count; i++) {
dkato 0:3e16bac28356 38 free(_blocks[i]);
dkato 0:3e16bac28356 39 }
dkato 0:3e16bac28356 40
dkato 0:3e16bac28356 41 delete[] _blocks;
dkato 0:3e16bac28356 42 _blocks = 0;
dkato 0:3e16bac28356 43 }
dkato 0:3e16bac28356 44 }
dkato 0:3e16bac28356 45
dkato 0:3e16bac28356 46 void RomRamBlockDevice::SetRomAddr(uint32_t rom_start_addr, uint32_t rom_end_addr) {
dkato 0:3e16bac28356 47 _rom_start = rom_start_addr;
dkato 0:3e16bac28356 48 _rom_end = rom_end_addr;
dkato 0:3e16bac28356 49 }
dkato 0:3e16bac28356 50
dkato 0:3e16bac28356 51 int RomRamBlockDevice::init()
dkato 0:3e16bac28356 52 {
dkato 0:3e16bac28356 53 if (!_blocks) {
dkato 0:3e16bac28356 54 _blocks = new uint8_t*[_count];
dkato 0:3e16bac28356 55 for (size_t i = 0; i < _count; i++) {
dkato 0:3e16bac28356 56 _blocks[i] = 0;
dkato 0:3e16bac28356 57 }
dkato 0:3e16bac28356 58 }
dkato 0:3e16bac28356 59
dkato 0:3e16bac28356 60 return BD_ERROR_OK;
dkato 0:3e16bac28356 61 }
dkato 0:3e16bac28356 62
dkato 0:3e16bac28356 63 int RomRamBlockDevice::deinit()
dkato 0:3e16bac28356 64 {
dkato 0:3e16bac28356 65 // Heapory is lazily cleaned up in destructor to allow
dkato 0:3e16bac28356 66 // data to live across de/reinitialization
dkato 0:3e16bac28356 67 return BD_ERROR_OK;
dkato 0:3e16bac28356 68 }
dkato 0:3e16bac28356 69
dkato 0:3e16bac28356 70 bd_size_t RomRamBlockDevice::get_read_size() const
dkato 0:3e16bac28356 71 {
dkato 0:3e16bac28356 72 return _read_size;
dkato 0:3e16bac28356 73 }
dkato 0:3e16bac28356 74
dkato 0:3e16bac28356 75 bd_size_t RomRamBlockDevice::get_program_size() const
dkato 0:3e16bac28356 76 {
dkato 0:3e16bac28356 77 return _program_size;
dkato 0:3e16bac28356 78 }
dkato 0:3e16bac28356 79
dkato 0:3e16bac28356 80 bd_size_t RomRamBlockDevice::get_erase_size() const
dkato 0:3e16bac28356 81 {
dkato 0:3e16bac28356 82 return _erase_size;
dkato 0:3e16bac28356 83 }
dkato 0:3e16bac28356 84
dkato 0:3e16bac28356 85 bd_size_t RomRamBlockDevice::size() const
dkato 0:3e16bac28356 86 {
dkato 0:3e16bac28356 87 return _count * _erase_size;
dkato 0:3e16bac28356 88 }
dkato 0:3e16bac28356 89
dkato 0:3e16bac28356 90 int RomRamBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
dkato 0:3e16bac28356 91 {
dkato 0:3e16bac28356 92 MBED_ASSERT(is_valid_read(addr, size));
dkato 0:3e16bac28356 93 uint8_t *buffer = static_cast<uint8_t*>(b);
dkato 0:3e16bac28356 94
dkato 0:3e16bac28356 95 while (size > 0) {
dkato 0:3e16bac28356 96 bd_addr_t hi = addr / _erase_size;
dkato 0:3e16bac28356 97 bd_addr_t lo = addr % _erase_size;
dkato 0:3e16bac28356 98
dkato 0:3e16bac28356 99 if (_blocks[hi]) {
dkato 0:3e16bac28356 100 memcpy(buffer, &_blocks[hi][lo], _read_size);
dkato 0:3e16bac28356 101 } else {
dkato 0:3e16bac28356 102 memset(buffer, 0, _read_size);
dkato 0:3e16bac28356 103 }
dkato 0:3e16bac28356 104
dkato 0:3e16bac28356 105 buffer += _read_size;
dkato 0:3e16bac28356 106 addr += _read_size;
dkato 0:3e16bac28356 107 size -= _read_size;
dkato 0:3e16bac28356 108 }
dkato 0:3e16bac28356 109
dkato 0:3e16bac28356 110 return 0;
dkato 0:3e16bac28356 111 }
dkato 0:3e16bac28356 112
dkato 0:3e16bac28356 113 int RomRamBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
dkato 0:3e16bac28356 114 {
dkato 0:3e16bac28356 115 MBED_ASSERT(is_valid_program(addr, size));
dkato 0:3e16bac28356 116 const uint8_t *buffer = static_cast<const uint8_t*>(b);
dkato 0:3e16bac28356 117
dkato 0:3e16bac28356 118 while (size > 0) {
dkato 0:3e16bac28356 119 bd_addr_t hi = addr / _erase_size;
dkato 0:3e16bac28356 120 bd_addr_t lo = addr % _erase_size;
dkato 0:3e16bac28356 121
dkato 0:3e16bac28356 122 if (isRomAddress(buffer)) {
dkato 0:3e16bac28356 123 if (!isRomAddress(_blocks[hi])) {
dkato 0:3e16bac28356 124 free(_blocks[hi]);
dkato 0:3e16bac28356 125 }
dkato 0:3e16bac28356 126 _blocks[hi] = (uint8_t*)buffer;
dkato 0:3e16bac28356 127 } else {
dkato 0:3e16bac28356 128 if (!_blocks[hi]) {
dkato 0:3e16bac28356 129 _blocks[hi] = (uint8_t*)malloc(_erase_size);
dkato 0:3e16bac28356 130 if (!_blocks[hi]) {
dkato 0:3e16bac28356 131 return BD_ERROR_DEVICE_ERROR;
dkato 0:3e16bac28356 132 }
dkato 0:3e16bac28356 133 }
dkato 0:3e16bac28356 134 memcpy(&_blocks[hi][lo], buffer, _program_size);
dkato 0:3e16bac28356 135 }
dkato 0:3e16bac28356 136
dkato 0:3e16bac28356 137 buffer += _program_size;
dkato 0:3e16bac28356 138 addr += _program_size;
dkato 0:3e16bac28356 139 size -= _program_size;
dkato 0:3e16bac28356 140 }
dkato 0:3e16bac28356 141
dkato 0:3e16bac28356 142 return 0;
dkato 0:3e16bac28356 143 }
dkato 0:3e16bac28356 144
dkato 0:3e16bac28356 145 int RomRamBlockDevice::erase(bd_addr_t addr, bd_size_t size)
dkato 0:3e16bac28356 146 {
dkato 0:3e16bac28356 147 MBED_ASSERT(is_valid_erase(addr, size));
dkato 0:3e16bac28356 148 // TODO assert on programming unerased blocks
dkato 0:3e16bac28356 149
dkato 0:3e16bac28356 150 return 0;
dkato 0:3e16bac28356 151 }
dkato 0:3e16bac28356 152
dkato 0:3e16bac28356 153 bool RomRamBlockDevice::isRomAddress(const uint8_t *address) {
dkato 0:3e16bac28356 154 if (((uint32_t)address >= _rom_start)
dkato 0:3e16bac28356 155 && ((uint32_t)address <= (_rom_end - _erase_size + 1))) {
dkato 0:3e16bac28356 156 return true;
dkato 0:3e16bac28356 157 }
dkato 0:3e16bac28356 158 return false;
dkato 0:3e16bac28356 159 }
dkato 0:3e16bac28356 160