takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HeapBlockDevice.cpp Source File

HeapBlockDevice.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2017 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "HeapBlockDevice.h"
00018 #include "mbed_critical.h"
00019 
00020 
00021 HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t block)
00022     : _read_size(block), _program_size(block), _erase_size(block)
00023     , _count(size / block), _blocks(0), _init_ref_count(0), _is_initialized(false)
00024 {
00025     MBED_ASSERT(_count * _erase_size == size);
00026 }
00027 
00028 HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t read, bd_size_t program, bd_size_t erase)
00029     : _read_size(read), _program_size(program), _erase_size(erase)
00030     , _count(size / erase), _blocks(0), _init_ref_count(0), _is_initialized(false)
00031 {
00032     MBED_ASSERT(_count * _erase_size == size);
00033 }
00034 
00035 HeapBlockDevice::~HeapBlockDevice()
00036 {
00037     if (_blocks) {
00038         for (size_t i = 0; i < _count; i++) {
00039             free(_blocks[i]);
00040         }
00041 
00042         delete[] _blocks;
00043         _blocks = 0;
00044     }
00045 }
00046 
00047 int HeapBlockDevice::init()
00048 {
00049     uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1);
00050 
00051     if (val != 1) {
00052         return BD_ERROR_OK;
00053     }
00054 
00055     if (!_blocks) {
00056         _blocks = new uint8_t*[_count];
00057         for (size_t i = 0; i < _count; i++) {
00058             _blocks[i] = 0;
00059         }
00060     }
00061 
00062     _is_initialized = true;
00063     return BD_ERROR_OK;
00064 }
00065 
00066 int HeapBlockDevice::deinit()
00067 {
00068     if (!_is_initialized) {
00069         return BD_ERROR_OK;
00070     }
00071 
00072     uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
00073 
00074     if (val) {
00075         return BD_ERROR_OK;
00076     }
00077 
00078     MBED_ASSERT(_blocks != NULL);
00079     // Memory is lazily cleaned up in destructor to allow
00080     // data to live across de/reinitialization
00081     _is_initialized = false;
00082     return BD_ERROR_OK;
00083 }
00084 
00085 bd_size_t HeapBlockDevice::get_read_size() const
00086 {
00087     MBED_ASSERT(_blocks != NULL);
00088     return _read_size;
00089 }
00090 
00091 bd_size_t HeapBlockDevice::get_program_size() const
00092 {
00093     MBED_ASSERT(_blocks != NULL);
00094     return _program_size;
00095 }
00096 
00097 bd_size_t HeapBlockDevice::get_erase_size() const
00098 {
00099     MBED_ASSERT(_blocks != NULL);
00100     return _erase_size;
00101 }
00102 
00103 bd_size_t HeapBlockDevice::get_erase_size(bd_addr_t addr) const
00104 {
00105     MBED_ASSERT(_blocks != NULL);
00106     return _erase_size;
00107 }
00108 
00109 bd_size_t HeapBlockDevice::size() const
00110 {
00111     MBED_ASSERT(_blocks != NULL);
00112     return _count * _erase_size;
00113 }
00114 
00115 int HeapBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
00116 {
00117     MBED_ASSERT(_blocks != NULL);
00118     MBED_ASSERT(is_valid_read(addr, size));
00119     if (!_is_initialized) {
00120         return BD_ERROR_DEVICE_ERROR;
00121     }
00122 
00123     uint8_t *buffer = static_cast<uint8_t*>(b);
00124 
00125     while (size > 0) {
00126         bd_addr_t hi = addr / _erase_size;
00127         bd_addr_t lo = addr % _erase_size;
00128 
00129         if (_blocks[hi]) {
00130             memcpy(buffer, &_blocks[hi][lo], _read_size);
00131         } else {
00132             memset(buffer, 0, _read_size);
00133         }
00134 
00135         buffer += _read_size;
00136         addr += _read_size;
00137         size -= _read_size;
00138     }
00139 
00140     return 0;
00141 }
00142 
00143 int HeapBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
00144 {
00145     MBED_ASSERT(_blocks != NULL);
00146     MBED_ASSERT(is_valid_program(addr, size));
00147     if (!_is_initialized) {
00148         return BD_ERROR_DEVICE_ERROR;
00149     }
00150 
00151     const uint8_t *buffer = static_cast<const uint8_t*>(b);
00152 
00153     while (size > 0) {
00154         bd_addr_t hi = addr / _erase_size;
00155         bd_addr_t lo = addr % _erase_size;
00156 
00157         if (!_blocks[hi]) {
00158             _blocks[hi] = (uint8_t*)malloc(_erase_size);
00159             if (!_blocks[hi]) {
00160                 return BD_ERROR_DEVICE_ERROR;
00161             }
00162         }
00163 
00164         memcpy(&_blocks[hi][lo], buffer, _program_size);
00165 
00166         buffer += _program_size;
00167         addr += _program_size;
00168         size -= _program_size;
00169     }
00170 
00171     return 0;
00172 }
00173 
00174 int HeapBlockDevice::erase(bd_addr_t addr, bd_size_t size)
00175 {
00176     MBED_ASSERT(_blocks != NULL);
00177     MBED_ASSERT(is_valid_erase(addr, size));
00178     // TODO assert on programming unerased blocks
00179 
00180     return 0;
00181 }
00182