Merge pull request #7773 from davidsaada/david_fix_init_ref_count

Add some logic related to initialization to various block devices
pull/7895/head
Martin Kojtal 2018-08-27 10:38:15 +02:00 committed by GitHub
commit 928f90a7d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 282 additions and 35 deletions

View File

@ -26,7 +26,7 @@ static inline uint32_t align_down(bd_size_t val, bd_size_t size)
} }
BufferedBlockDevice::BufferedBlockDevice(BlockDevice *bd) BufferedBlockDevice::BufferedBlockDevice(BlockDevice *bd)
: _bd(bd), _bd_program_size(0), _curr_aligned_addr(0), _flushed(true), _cache(0), _init_ref_count(0) : _bd(bd), _bd_program_size(0), _curr_aligned_addr(0), _flushed(true), _cache(0), _init_ref_count(0), _is_initialized(false)
{ {
} }
@ -57,11 +57,16 @@ int BufferedBlockDevice::init()
_curr_aligned_addr = _bd->size(); _curr_aligned_addr = _bd->size();
_flushed = true; _flushed = true;
return 0; _is_initialized = true;
return BD_ERROR_OK;
} }
int BufferedBlockDevice::deinit() int BufferedBlockDevice::deinit()
{ {
if (!_is_initialized) {
return BD_ERROR_OK;
}
uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1); uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
if (val) { if (val) {
@ -70,11 +75,16 @@ int BufferedBlockDevice::deinit()
delete[] _cache; delete[] _cache;
_cache = 0; _cache = 0;
_is_initialized = false;
return _bd->deinit(); return _bd->deinit();
} }
int BufferedBlockDevice::flush() int BufferedBlockDevice::flush()
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
if (!_flushed) { if (!_flushed) {
int ret = _bd->program(_cache, _curr_aligned_addr, _bd_program_size); int ret = _bd->program(_cache, _curr_aligned_addr, _bd_program_size);
if (ret) { if (ret) {
@ -87,6 +97,10 @@ int BufferedBlockDevice::flush()
int BufferedBlockDevice::sync() int BufferedBlockDevice::sync()
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
int ret = flush(); int ret = flush();
if (ret) { if (ret) {
return ret; return ret;
@ -97,6 +111,10 @@ int BufferedBlockDevice::sync()
int BufferedBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) int BufferedBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{ {
MBED_ASSERT(_cache); MBED_ASSERT(_cache);
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
bool moved_unit = false; bool moved_unit = false;
bd_addr_t aligned_addr = align_down(addr, _bd_program_size); bd_addr_t aligned_addr = align_down(addr, _bd_program_size);
@ -132,7 +150,10 @@ int BufferedBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
int BufferedBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) int BufferedBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{ {
MBED_ASSERT(_cache); if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
int ret; int ret;
bool moved_unit = false; bool moved_unit = false;
@ -196,12 +217,19 @@ int BufferedBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
int BufferedBlockDevice::erase(bd_addr_t addr, bd_size_t size) int BufferedBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{ {
MBED_ASSERT(is_valid_erase(addr, size)); MBED_ASSERT(is_valid_erase(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->erase(addr, size); return _bd->erase(addr, size);
} }
int BufferedBlockDevice::trim(bd_addr_t addr, bd_size_t size) int BufferedBlockDevice::trim(bd_addr_t addr, bd_size_t size)
{ {
MBED_ASSERT(is_valid_erase(addr, size)); MBED_ASSERT(is_valid_erase(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
if ((_curr_aligned_addr >= addr) && (_curr_aligned_addr <= addr + size)) { if ((_curr_aligned_addr >= addr) && (_curr_aligned_addr <= addr + size)) {
_flushed = true; _flushed = true;
@ -222,20 +250,36 @@ bd_size_t BufferedBlockDevice::get_program_size() const
bd_size_t BufferedBlockDevice::get_erase_size() const bd_size_t BufferedBlockDevice::get_erase_size() const
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_erase_size(); return _bd->get_erase_size();
} }
bd_size_t BufferedBlockDevice::get_erase_size(bd_addr_t addr) const bd_size_t BufferedBlockDevice::get_erase_size(bd_addr_t addr) const
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_erase_size(addr); return _bd->get_erase_size(addr);
} }
int BufferedBlockDevice::get_erase_value() const int BufferedBlockDevice::get_erase_value() const
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_erase_value(); return _bd->get_erase_value();
} }
bd_size_t BufferedBlockDevice::size() const bd_size_t BufferedBlockDevice::size() const
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->size(); return _bd->size();
} }

View File

@ -154,6 +154,7 @@ protected:
bool _flushed; bool _flushed;
uint8_t *_cache; uint8_t *_cache;
uint32_t _init_ref_count; uint32_t _init_ref_count;
bool _is_initialized;
/** Flush data in cache /** Flush data in cache
* *

View File

@ -21,7 +21,7 @@
ChainingBlockDevice::ChainingBlockDevice(BlockDevice **bds, size_t bd_count) ChainingBlockDevice::ChainingBlockDevice(BlockDevice **bds, size_t bd_count)
: _bds(bds), _bd_count(bd_count) : _bds(bds), _bd_count(bd_count)
, _read_size(0), _program_size(0), _erase_size(0), _size(0) , _read_size(0), _program_size(0), _erase_size(0), _size(0)
, _erase_value(-1), _init_ref_count(0) , _erase_value(-1), _init_ref_count(0), _is_initialized(false)
{ {
} }
@ -32,6 +32,7 @@ static bool is_aligned(uint64_t x, uint64_t alignment)
int ChainingBlockDevice::init() int ChainingBlockDevice::init()
{ {
int err;
uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1); uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1);
if (val != 1) { if (val != 1) {
@ -49,9 +50,9 @@ int ChainingBlockDevice::init()
// the constructor since some block devices may need to be // the constructor since some block devices may need to be
// initialized before they know their block size/count // initialized before they know their block size/count
for (size_t i = 0; i < _bd_count; i++) { for (size_t i = 0; i < _bd_count; i++) {
int err = _bds[i]->init(); err = _bds[i]->init();
if (err) { if (err) {
return err; goto fail;
} }
bd_size_t read = _bds[i]->get_read_size(); bd_size_t read = _bds[i]->get_read_size();
@ -85,11 +86,21 @@ int ChainingBlockDevice::init()
_size += _bds[i]->size(); _size += _bds[i]->size();
} }
return 0; _is_initialized = true;
return BD_ERROR_OK;
fail:
_is_initialized = false;
_init_ref_count = 0;
return err;
} }
int ChainingBlockDevice::deinit() int ChainingBlockDevice::deinit()
{ {
if (!_is_initialized) {
return BD_ERROR_OK;
}
uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1); uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
if (val) { if (val) {
@ -103,11 +114,16 @@ int ChainingBlockDevice::deinit()
} }
} }
return 0; _is_initialized = false;
return BD_ERROR_OK;
} }
int ChainingBlockDevice::sync() int ChainingBlockDevice::sync()
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
for (size_t i = 0; i < _bd_count; i++) { for (size_t i = 0; i < _bd_count; i++) {
int err = _bds[i]->sync(); int err = _bds[i]->sync();
if (err) { if (err) {
@ -121,6 +137,10 @@ int ChainingBlockDevice::sync()
int ChainingBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) int ChainingBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{ {
MBED_ASSERT(is_valid_read(addr, size)); MBED_ASSERT(is_valid_read(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
uint8_t *buffer = static_cast<uint8_t*>(b); uint8_t *buffer = static_cast<uint8_t*>(b);
// Find block devices containing blocks, may span multiple block devices // Find block devices containing blocks, may span multiple block devices
@ -152,6 +172,10 @@ int ChainingBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
int ChainingBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) int ChainingBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{ {
MBED_ASSERT(is_valid_program(addr, size)); MBED_ASSERT(is_valid_program(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
const uint8_t *buffer = static_cast<const uint8_t*>(b); const uint8_t *buffer = static_cast<const uint8_t*>(b);
// Find block devices containing blocks, may span multiple block devices // Find block devices containing blocks, may span multiple block devices
@ -183,6 +207,9 @@ int ChainingBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
int ChainingBlockDevice::erase(bd_addr_t addr, bd_size_t size) int ChainingBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{ {
MBED_ASSERT(is_valid_erase(addr, size)); MBED_ASSERT(is_valid_erase(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
// Find block devices containing blocks, may span multiple block devices // Find block devices containing blocks, may span multiple block devices
for (size_t i = 0; i < _bd_count && size > 0; i++) { for (size_t i = 0; i < _bd_count && size > 0; i++) {
@ -226,6 +253,10 @@ bd_size_t ChainingBlockDevice::get_erase_size() const
bd_size_t ChainingBlockDevice::get_erase_size(bd_addr_t addr) const bd_size_t ChainingBlockDevice::get_erase_size(bd_addr_t addr) const
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
bd_addr_t bd_start_addr = 0; bd_addr_t bd_start_addr = 0;
for (size_t i = 0; i < _bd_count; i++) { for (size_t i = 0; i < _bd_count; i++) {
bd_size_t bdsize = _bds[i]->size(); bd_size_t bdsize = _bds[i]->size();

View File

@ -176,6 +176,7 @@ protected:
bd_size_t _size; bd_size_t _size;
int _erase_value; int _erase_value;
uint32_t _init_ref_count; uint32_t _init_ref_count;
bool _is_initialized;
}; };

View File

@ -20,7 +20,7 @@
ExhaustibleBlockDevice::ExhaustibleBlockDevice(BlockDevice *bd, uint32_t erase_cycles) ExhaustibleBlockDevice::ExhaustibleBlockDevice(BlockDevice *bd, uint32_t erase_cycles)
: _bd(bd), _erase_array(NULL), _erase_cycles(erase_cycles), _init_ref_count(0) : _bd(bd), _erase_array(NULL), _erase_cycles(erase_cycles), _init_ref_count(0), _is_initialized(false)
{ {
} }
@ -31,15 +31,16 @@ ExhaustibleBlockDevice::~ExhaustibleBlockDevice()
int ExhaustibleBlockDevice::init() int ExhaustibleBlockDevice::init()
{ {
int err;
uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1); uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1);
if (val != 1) { if (val != 1) {
return BD_ERROR_OK; return BD_ERROR_OK;
} }
int err = _bd->init(); err = _bd->init();
if (err) { if (err) {
return err; goto fail;
} }
if (!_erase_array) { if (!_erase_array) {
@ -50,11 +51,21 @@ int ExhaustibleBlockDevice::init()
} }
} }
return 0; _is_initialized = true;
return BD_ERROR_OK;
fail:
_is_initialized = false;
_init_ref_count = 0;
return err;
} }
int ExhaustibleBlockDevice::deinit() int ExhaustibleBlockDevice::deinit()
{ {
if (!_is_initialized) {
return BD_ERROR_OK;
}
core_util_atomic_decr_u32(&_init_ref_count, 1); core_util_atomic_decr_u32(&_init_ref_count, 1);
if (_init_ref_count) { if (_init_ref_count) {
@ -63,16 +74,25 @@ int ExhaustibleBlockDevice::deinit()
// _erase_array is lazily cleaned up in destructor to allow // _erase_array is lazily cleaned up in destructor to allow
// data to live across de/reinitialization // data to live across de/reinitialization
_is_initialized = false;
return _bd->deinit(); return _bd->deinit();
} }
int ExhaustibleBlockDevice::sync() int ExhaustibleBlockDevice::sync()
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->sync(); return _bd->sync();
} }
int ExhaustibleBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) int ExhaustibleBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->read(buffer, addr, size); return _bd->read(buffer, addr, size);
} }
@ -80,6 +100,10 @@ int ExhaustibleBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_
{ {
MBED_ASSERT(is_valid_program(addr, size)); MBED_ASSERT(is_valid_program(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
if (_erase_array[addr / get_erase_size()] == 0) { if (_erase_array[addr / get_erase_size()] == 0) {
return 0; return 0;
} }
@ -90,6 +114,9 @@ int ExhaustibleBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_
int ExhaustibleBlockDevice::erase(bd_addr_t addr, bd_size_t size) int ExhaustibleBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{ {
MBED_ASSERT(is_valid_erase(addr, size)); MBED_ASSERT(is_valid_erase(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
bd_size_t eu_size = get_erase_size(); bd_size_t eu_size = get_erase_size();
while (size) { while (size) {
@ -114,30 +141,54 @@ int ExhaustibleBlockDevice::erase(bd_addr_t addr, bd_size_t size)
bd_size_t ExhaustibleBlockDevice::get_read_size() const bd_size_t ExhaustibleBlockDevice::get_read_size() const
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_read_size(); return _bd->get_read_size();
} }
bd_size_t ExhaustibleBlockDevice::get_program_size() const bd_size_t ExhaustibleBlockDevice::get_program_size() const
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_program_size(); return _bd->get_program_size();
} }
bd_size_t ExhaustibleBlockDevice::get_erase_size() const bd_size_t ExhaustibleBlockDevice::get_erase_size() const
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_erase_size(); return _bd->get_erase_size();
} }
bd_size_t ExhaustibleBlockDevice::get_erase_size(bd_addr_t addr) const bd_size_t ExhaustibleBlockDevice::get_erase_size(bd_addr_t addr) const
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_erase_size(addr); return _bd->get_erase_size(addr);
} }
int ExhaustibleBlockDevice::get_erase_value() const int ExhaustibleBlockDevice::get_erase_value() const
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_erase_value(); return _bd->get_erase_value();
} }
bd_size_t ExhaustibleBlockDevice::size() const bd_size_t ExhaustibleBlockDevice::size() const
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->size(); return _bd->size();
} }

View File

@ -155,6 +155,7 @@ private:
uint32_t *_erase_array; uint32_t *_erase_array;
uint32_t _erase_cycles; uint32_t _erase_cycles;
uint32_t _init_ref_count; uint32_t _init_ref_count;
bool _is_initialized;
}; };

View File

@ -30,7 +30,7 @@ static inline uint32_t align_up(bd_size_t val, bd_size_t size)
FlashSimBlockDevice::FlashSimBlockDevice(BlockDevice *bd, uint8_t erase_value) : FlashSimBlockDevice::FlashSimBlockDevice(BlockDevice *bd, uint8_t erase_value) :
_erase_value(erase_value), _blank_buf_size(0), _erase_value(erase_value), _blank_buf_size(0),
_blank_buf(0), _bd(bd), _init_ref_count(0) _blank_buf(0), _bd(bd), _init_ref_count(0), _is_initialized(false)
{ {
} }
@ -42,73 +42,118 @@ FlashSimBlockDevice::~FlashSimBlockDevice()
int FlashSimBlockDevice::init() int FlashSimBlockDevice::init()
{ {
int err;
uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1); uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1);
if (val != 1) { if (val != 1) {
return BD_ERROR_OK; return BD_ERROR_OK;
} }
int ret = _bd->init(); err = _bd->init();
if (ret) { if (err) {
return ret; goto fail;
} }
_blank_buf_size = align_up(min_blank_buf_size, _bd->get_program_size()); _blank_buf_size = align_up(min_blank_buf_size, _bd->get_program_size());
if (!_blank_buf) { if (!_blank_buf) {
_blank_buf = new uint8_t[_blank_buf_size]; _blank_buf = new uint8_t[_blank_buf_size];
MBED_ASSERT(_blank_buf); MBED_ASSERT(_blank_buf);
} }
_is_initialized = true;
return BD_ERROR_OK; return BD_ERROR_OK;
fail:
_is_initialized = false;
_init_ref_count = 0;
return err;
} }
int FlashSimBlockDevice::deinit() int FlashSimBlockDevice::deinit()
{ {
if (!_is_initialized) {
return BD_ERROR_OK;
}
uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1); uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
if (val) { if (val) {
return BD_ERROR_OK; return BD_ERROR_OK;
} }
_is_initialized = false;
return _bd->deinit(); return _bd->deinit();
} }
int FlashSimBlockDevice::sync() int FlashSimBlockDevice::sync()
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->sync(); return _bd->sync();
} }
bd_size_t FlashSimBlockDevice::get_read_size() const bd_size_t FlashSimBlockDevice::get_read_size() const
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_read_size(); return _bd->get_read_size();
} }
bd_size_t FlashSimBlockDevice::get_program_size() const bd_size_t FlashSimBlockDevice::get_program_size() const
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_program_size(); return _bd->get_program_size();
} }
bd_size_t FlashSimBlockDevice::get_erase_size() const bd_size_t FlashSimBlockDevice::get_erase_size() const
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_erase_size(); return _bd->get_erase_size();
} }
bd_size_t FlashSimBlockDevice::get_erase_size(bd_addr_t addr) const bd_size_t FlashSimBlockDevice::get_erase_size(bd_addr_t addr) const
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_erase_size(addr); return _bd->get_erase_size(addr);
} }
bd_size_t FlashSimBlockDevice::size() const bd_size_t FlashSimBlockDevice::size() const
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->size(); return _bd->size();
} }
int FlashSimBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) int FlashSimBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->read(b, addr, size); return _bd->read(b, addr, size);
} }
int FlashSimBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) int FlashSimBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{ {
MBED_ASSERT(is_valid_program(addr, size)); MBED_ASSERT(is_valid_program(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
bd_addr_t curr_addr = addr; bd_addr_t curr_addr = addr;
bd_size_t curr_size = size; bd_size_t curr_size = size;
@ -138,6 +183,10 @@ int FlashSimBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{ {
MBED_ASSERT(is_valid_erase(addr, size)); MBED_ASSERT(is_valid_erase(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
bd_addr_t curr_addr = addr; bd_addr_t curr_addr = addr;
bd_size_t curr_size = size; bd_size_t curr_size = size;

View File

@ -136,6 +136,7 @@ private:
uint8_t *_blank_buf; uint8_t *_blank_buf;
BlockDevice *_bd; BlockDevice *_bd;
uint32_t _init_ref_count; uint32_t _init_ref_count;
bool _is_initialized;
}; };
#endif #endif

View File

@ -20,14 +20,14 @@
HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t block) HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t block)
: _read_size(block), _program_size(block), _erase_size(block) : _read_size(block), _program_size(block), _erase_size(block)
, _count(size / block), _blocks(0), _init_ref_count(0) , _count(size / block), _blocks(0), _init_ref_count(0), _is_initialized(false)
{ {
MBED_ASSERT(_count * _erase_size == size); MBED_ASSERT(_count * _erase_size == size);
} }
HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t read, bd_size_t program, bd_size_t erase) HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t read, bd_size_t program, bd_size_t erase)
: _read_size(read), _program_size(program), _erase_size(erase) : _read_size(read), _program_size(program), _erase_size(erase)
, _count(size / erase), _blocks(0), _init_ref_count(0) , _count(size / erase), _blocks(0), _init_ref_count(0), _is_initialized(false)
{ {
MBED_ASSERT(_count * _erase_size == size); MBED_ASSERT(_count * _erase_size == size);
} }
@ -59,11 +59,16 @@ int HeapBlockDevice::init()
} }
} }
_is_initialized = true;
return BD_ERROR_OK; return BD_ERROR_OK;
} }
int HeapBlockDevice::deinit() int HeapBlockDevice::deinit()
{ {
if (!_is_initialized) {
return BD_ERROR_OK;
}
uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1); uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
if (val) { if (val) {
@ -73,6 +78,7 @@ int HeapBlockDevice::deinit()
MBED_ASSERT(_blocks != NULL); MBED_ASSERT(_blocks != NULL);
// Memory is lazily cleaned up in destructor to allow // Memory is lazily cleaned up in destructor to allow
// data to live across de/reinitialization // data to live across de/reinitialization
_is_initialized = false;
return BD_ERROR_OK; return BD_ERROR_OK;
} }
@ -110,6 +116,10 @@ int HeapBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{ {
MBED_ASSERT(_blocks != NULL); MBED_ASSERT(_blocks != NULL);
MBED_ASSERT(is_valid_read(addr, size)); MBED_ASSERT(is_valid_read(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
uint8_t *buffer = static_cast<uint8_t*>(b); uint8_t *buffer = static_cast<uint8_t*>(b);
while (size > 0) { while (size > 0) {
@ -134,6 +144,10 @@ int HeapBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{ {
MBED_ASSERT(_blocks != NULL); MBED_ASSERT(_blocks != NULL);
MBED_ASSERT(is_valid_program(addr, size)); MBED_ASSERT(is_valid_program(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
const uint8_t *buffer = static_cast<const uint8_t*>(b); const uint8_t *buffer = static_cast<const uint8_t*>(b);
while (size > 0) { while (size > 0) {

View File

@ -151,6 +151,7 @@ private:
bd_size_t _count; bd_size_t _count;
uint8_t **_blocks; uint8_t **_blocks;
uint32_t _init_ref_count; uint32_t _init_ref_count;
bool _is_initialized;
}; };

View File

@ -195,40 +195,44 @@ int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type,
} }
MBRBlockDevice::MBRBlockDevice(BlockDevice *bd, int part) MBRBlockDevice::MBRBlockDevice(BlockDevice *bd, int part)
: _bd(bd), _part(part), _init_ref_count(0) : _bd(bd), _offset(0), _size(0), _type(0), _part(part), _init_ref_count(0), _is_initialized(false)
{ {
MBED_ASSERT(_part >= 1 && _part <= 4); MBED_ASSERT(_part >= 1 && _part <= 4);
} }
int MBRBlockDevice::init() int MBRBlockDevice::init()
{ {
uint32_t buffer_size;
uint8_t *buffer = 0;
struct mbr_table *table;
bd_size_t sector;
int err;
uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1); uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1);
if (val != 1) { if (val != 1) {
return BD_ERROR_OK; return BD_ERROR_OK;
} }
int err = _bd->init(); err = _bd->init();
if (err) { if (err) {
return err; goto fail;
} }
// Allocate smallest buffer necessary to write MBR // Allocate smallest buffer necessary to write MBR
uint32_t buffer_size = std::max<uint32_t>(_bd->get_read_size(), sizeof(struct mbr_table)); buffer_size = std::max<uint32_t>(_bd->get_read_size(), sizeof(struct mbr_table));
uint8_t *buffer = new uint8_t[buffer_size]; buffer = new uint8_t[buffer_size];
err = _bd->read(buffer, 512-buffer_size, buffer_size); err = _bd->read(buffer, 512-buffer_size, buffer_size);
if (err) { if (err) {
delete[] buffer; goto fail;
return err;
} }
// Check for valid table // Check for valid table
struct mbr_table *table = reinterpret_cast<struct mbr_table*>( table = reinterpret_cast<struct mbr_table*>(&buffer[buffer_size - sizeof(struct mbr_table)]);
&buffer[buffer_size - sizeof(struct mbr_table)]);
if (table->signature[0] != 0x55 || table->signature[1] != 0xaa) { if (table->signature[0] != 0x55 || table->signature[1] != 0xaa) {
delete[] buffer; err = BD_ERROR_INVALID_MBR;
return BD_ERROR_INVALID_MBR; goto fail;
} }
// Check for valid entry // Check for valid entry
@ -237,82 +241,130 @@ int MBRBlockDevice::init()
if ((table->entries[_part-1].type == 0x00 || if ((table->entries[_part-1].type == 0x00 ||
table->entries[_part-1].type == 0x05 || table->entries[_part-1].type == 0x05 ||
table->entries[_part-1].type == 0x0f)) { table->entries[_part-1].type == 0x0f)) {
delete[] buffer; err = BD_ERROR_INVALID_PARTITION;
return BD_ERROR_INVALID_PARTITION; goto fail;
} }
// Get partition attributes // Get partition attributes
bd_size_t sector = std::max<uint32_t>(_bd->get_erase_size(), 512); sector = std::max<uint32_t>(_bd->get_erase_size(), 512);
_type = table->entries[_part-1].type; _type = table->entries[_part-1].type;
_offset = fromle32(table->entries[_part-1].lba_offset) * sector; _offset = fromle32(table->entries[_part-1].lba_offset) * sector;
_size = fromle32(table->entries[_part-1].lba_size) * sector; _size = fromle32(table->entries[_part-1].lba_size) * sector;
// Check that block addresses are valid // Check that block addresses are valid
if (!_bd->is_valid_erase(_offset, _size)) { if (!_bd->is_valid_erase(_offset, _size)) {
delete[] buffer; err = BD_ERROR_INVALID_PARTITION;
return BD_ERROR_INVALID_PARTITION; goto fail;
} }
_is_initialized = true;
delete[] buffer; delete[] buffer;
return 0; return BD_ERROR_OK;
fail:
delete[] buffer;
_is_initialized = false;
_init_ref_count = 0;
return err;
} }
int MBRBlockDevice::deinit() int MBRBlockDevice::deinit()
{ {
if (!_is_initialized) {
return BD_ERROR_OK;
}
uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1); uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
if (val) { if (val) {
return BD_ERROR_OK; return BD_ERROR_OK;
} }
_is_initialized = false;
return _bd->deinit(); return _bd->deinit();
} }
int MBRBlockDevice::sync() int MBRBlockDevice::sync()
{ {
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->sync(); return _bd->sync();
} }
int MBRBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) int MBRBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{ {
MBED_ASSERT(is_valid_read(addr, size)); MBED_ASSERT(is_valid_read(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->read(b, addr + _offset, size); return _bd->read(b, addr + _offset, size);
} }
int MBRBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) int MBRBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{ {
MBED_ASSERT(is_valid_program(addr, size)); MBED_ASSERT(is_valid_program(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->program(b, addr + _offset, size); return _bd->program(b, addr + _offset, size);
} }
int MBRBlockDevice::erase(bd_addr_t addr, bd_size_t size) int MBRBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{ {
MBED_ASSERT(is_valid_erase(addr, size)); MBED_ASSERT(is_valid_erase(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
return _bd->erase(addr + _offset, size); return _bd->erase(addr + _offset, size);
} }
bd_size_t MBRBlockDevice::get_read_size() const bd_size_t MBRBlockDevice::get_read_size() const
{ {
if (!_is_initialized) {
return 0;
}
return _bd->get_read_size(); return _bd->get_read_size();
} }
bd_size_t MBRBlockDevice::get_program_size() const bd_size_t MBRBlockDevice::get_program_size() const
{ {
if (!_is_initialized) {
return 0;
}
return _bd->get_program_size(); return _bd->get_program_size();
} }
bd_size_t MBRBlockDevice::get_erase_size() const bd_size_t MBRBlockDevice::get_erase_size() const
{ {
if (!_is_initialized) {
return 0;
}
return _bd->get_erase_size(); return _bd->get_erase_size();
} }
bd_size_t MBRBlockDevice::get_erase_size(bd_addr_t addr) const bd_size_t MBRBlockDevice::get_erase_size(bd_addr_t addr) const
{ {
if (!_is_initialized) {
return 0;
}
return _bd->get_erase_size(_offset + addr); return _bd->get_erase_size(_offset + addr);
} }
int MBRBlockDevice::get_erase_value() const int MBRBlockDevice::get_erase_value() const
{ {
if (!_is_initialized) {
return 0;
}
return _bd->get_erase_value(); return _bd->get_erase_value();
} }

View File

@ -253,6 +253,7 @@ protected:
uint8_t _type; uint8_t _type;
uint8_t _part; uint8_t _part;
uint32_t _init_ref_count; uint32_t _init_ref_count;
bool _is_initialized;
}; };