mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #7773 from davidsaada/david_fix_init_ref_count
Add some logic related to initialization to various block devicespull/7895/head
commit
928f90a7d5
|
@ -26,7 +26,7 @@ static inline uint32_t align_down(bd_size_t val, bd_size_t size)
|
|||
}
|
||||
|
||||
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();
|
||||
_flushed = true;
|
||||
|
||||
return 0;
|
||||
_is_initialized = true;
|
||||
return BD_ERROR_OK;
|
||||
}
|
||||
|
||||
int BufferedBlockDevice::deinit()
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_OK;
|
||||
}
|
||||
|
||||
uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
|
||||
|
||||
if (val) {
|
||||
|
@ -70,11 +75,16 @@ int BufferedBlockDevice::deinit()
|
|||
|
||||
delete[] _cache;
|
||||
_cache = 0;
|
||||
_is_initialized = false;
|
||||
return _bd->deinit();
|
||||
}
|
||||
|
||||
int BufferedBlockDevice::flush()
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
if (!_flushed) {
|
||||
int ret = _bd->program(_cache, _curr_aligned_addr, _bd_program_size);
|
||||
if (ret) {
|
||||
|
@ -87,6 +97,10 @@ int BufferedBlockDevice::flush()
|
|||
|
||||
int BufferedBlockDevice::sync()
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
int ret = flush();
|
||||
if (ret) {
|
||||
return ret;
|
||||
|
@ -97,6 +111,10 @@ int BufferedBlockDevice::sync()
|
|||
int BufferedBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
|
||||
{
|
||||
MBED_ASSERT(_cache);
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
bool moved_unit = false;
|
||||
|
||||
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)
|
||||
{
|
||||
MBED_ASSERT(_cache);
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
int ret;
|
||||
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)
|
||||
{
|
||||
MBED_ASSERT(is_valid_erase(addr, size));
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->erase(addr, size);
|
||||
}
|
||||
|
||||
int BufferedBlockDevice::trim(bd_addr_t addr, bd_size_t 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)) {
|
||||
_flushed = true;
|
||||
|
@ -222,20 +250,36 @@ bd_size_t BufferedBlockDevice::get_program_size() const
|
|||
|
||||
bd_size_t BufferedBlockDevice::get_erase_size() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->get_erase_size();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int BufferedBlockDevice::get_erase_value() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->get_erase_value();
|
||||
}
|
||||
|
||||
bd_size_t BufferedBlockDevice::size() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->size();
|
||||
}
|
||||
|
|
|
@ -154,6 +154,7 @@ protected:
|
|||
bool _flushed;
|
||||
uint8_t *_cache;
|
||||
uint32_t _init_ref_count;
|
||||
bool _is_initialized;
|
||||
|
||||
/** Flush data in cache
|
||||
*
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
ChainingBlockDevice::ChainingBlockDevice(BlockDevice **bds, size_t bd_count)
|
||||
: _bds(bds), _bd_count(bd_count)
|
||||
, _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 err;
|
||||
uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1);
|
||||
|
||||
if (val != 1) {
|
||||
|
@ -49,9 +50,9 @@ int ChainingBlockDevice::init()
|
|||
// the constructor since some block devices may need to be
|
||||
// initialized before they know their block size/count
|
||||
for (size_t i = 0; i < _bd_count; i++) {
|
||||
int err = _bds[i]->init();
|
||||
err = _bds[i]->init();
|
||||
if (err) {
|
||||
return err;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
bd_size_t read = _bds[i]->get_read_size();
|
||||
|
@ -85,11 +86,21 @@ int ChainingBlockDevice::init()
|
|||
_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()
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_OK;
|
||||
}
|
||||
|
||||
uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
|
||||
|
||||
if (val) {
|
||||
|
@ -103,11 +114,16 @@ int ChainingBlockDevice::deinit()
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
_is_initialized = false;
|
||||
return BD_ERROR_OK;
|
||||
}
|
||||
|
||||
int ChainingBlockDevice::sync()
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < _bd_count; i++) {
|
||||
int err = _bds[i]->sync();
|
||||
if (err) {
|
||||
|
@ -121,6 +137,10 @@ int ChainingBlockDevice::sync()
|
|||
int ChainingBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
|
||||
{
|
||||
MBED_ASSERT(is_valid_read(addr, size));
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
uint8_t *buffer = static_cast<uint8_t*>(b);
|
||||
|
||||
// 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)
|
||||
{
|
||||
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);
|
||||
|
||||
// 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)
|
||||
{
|
||||
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
|
||||
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
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
bd_addr_t bd_start_addr = 0;
|
||||
for (size_t i = 0; i < _bd_count; i++) {
|
||||
bd_size_t bdsize = _bds[i]->size();
|
||||
|
|
|
@ -176,6 +176,7 @@ protected:
|
|||
bd_size_t _size;
|
||||
int _erase_value;
|
||||
uint32_t _init_ref_count;
|
||||
bool _is_initialized;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
|
||||
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 err;
|
||||
uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1);
|
||||
|
||||
if (val != 1) {
|
||||
return BD_ERROR_OK;
|
||||
}
|
||||
|
||||
int err = _bd->init();
|
||||
err = _bd->init();
|
||||
if (err) {
|
||||
return err;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_OK;
|
||||
}
|
||||
|
||||
core_util_atomic_decr_u32(&_init_ref_count, 1);
|
||||
|
||||
if (_init_ref_count) {
|
||||
|
@ -63,16 +74,25 @@ int ExhaustibleBlockDevice::deinit()
|
|||
|
||||
// _erase_array is lazily cleaned up in destructor to allow
|
||||
// data to live across de/reinitialization
|
||||
_is_initialized = false;
|
||||
return _bd->deinit();
|
||||
}
|
||||
|
||||
int ExhaustibleBlockDevice::sync()
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->sync();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -80,6 +100,10 @@ int ExhaustibleBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_
|
|||
{
|
||||
MBED_ASSERT(is_valid_program(addr, size));
|
||||
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
if (_erase_array[addr / get_erase_size()] == 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)
|
||||
{
|
||||
MBED_ASSERT(is_valid_erase(addr, size));
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
bd_size_t eu_size = get_erase_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
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->get_read_size();
|
||||
}
|
||||
|
||||
bd_size_t ExhaustibleBlockDevice::get_program_size() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->get_program_size();
|
||||
}
|
||||
|
||||
bd_size_t ExhaustibleBlockDevice::get_erase_size() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->get_erase_size();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int ExhaustibleBlockDevice::get_erase_value() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->get_erase_value();
|
||||
}
|
||||
|
||||
bd_size_t ExhaustibleBlockDevice::size() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->size();
|
||||
}
|
||||
|
|
|
@ -155,6 +155,7 @@ private:
|
|||
uint32_t *_erase_array;
|
||||
uint32_t _erase_cycles;
|
||||
uint32_t _init_ref_count;
|
||||
bool _is_initialized;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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) :
|
||||
_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 err;
|
||||
uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1);
|
||||
|
||||
if (val != 1) {
|
||||
return BD_ERROR_OK;
|
||||
}
|
||||
|
||||
int ret = _bd->init();
|
||||
if (ret) {
|
||||
return ret;
|
||||
err = _bd->init();
|
||||
if (err) {
|
||||
goto fail;
|
||||
}
|
||||
_blank_buf_size = align_up(min_blank_buf_size, _bd->get_program_size());
|
||||
if (!_blank_buf) {
|
||||
_blank_buf = new uint8_t[_blank_buf_size];
|
||||
MBED_ASSERT(_blank_buf);
|
||||
}
|
||||
|
||||
_is_initialized = true;
|
||||
return BD_ERROR_OK;
|
||||
|
||||
fail:
|
||||
_is_initialized = false;
|
||||
_init_ref_count = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
int FlashSimBlockDevice::deinit()
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_OK;
|
||||
}
|
||||
|
||||
uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
|
||||
|
||||
if (val) {
|
||||
return BD_ERROR_OK;
|
||||
}
|
||||
|
||||
_is_initialized = false;
|
||||
return _bd->deinit();
|
||||
}
|
||||
|
||||
int FlashSimBlockDevice::sync()
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->sync();
|
||||
}
|
||||
|
||||
bd_size_t FlashSimBlockDevice::get_read_size() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->get_read_size();
|
||||
}
|
||||
|
||||
bd_size_t FlashSimBlockDevice::get_program_size() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->get_program_size();
|
||||
}
|
||||
|
||||
bd_size_t FlashSimBlockDevice::get_erase_size() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->get_erase_size();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
bd_size_t FlashSimBlockDevice::size() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->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);
|
||||
}
|
||||
|
||||
int FlashSimBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
|
||||
{
|
||||
MBED_ASSERT(is_valid_program(addr, size));
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
bd_addr_t curr_addr = addr;
|
||||
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));
|
||||
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
bd_addr_t curr_addr = addr;
|
||||
bd_size_t curr_size = size;
|
||||
|
||||
|
|
|
@ -136,6 +136,7 @@ private:
|
|||
uint8_t *_blank_buf;
|
||||
BlockDevice *_bd;
|
||||
uint32_t _init_ref_count;
|
||||
bool _is_initialized;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,14 +20,14 @@
|
|||
|
||||
HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t 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);
|
||||
}
|
||||
|
||||
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)
|
||||
, _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);
|
||||
}
|
||||
|
@ -59,11 +59,16 @@ int HeapBlockDevice::init()
|
|||
}
|
||||
}
|
||||
|
||||
_is_initialized = true;
|
||||
return BD_ERROR_OK;
|
||||
}
|
||||
|
||||
int HeapBlockDevice::deinit()
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_OK;
|
||||
}
|
||||
|
||||
uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
|
||||
|
||||
if (val) {
|
||||
|
@ -73,6 +78,7 @@ int HeapBlockDevice::deinit()
|
|||
MBED_ASSERT(_blocks != NULL);
|
||||
// Memory is lazily cleaned up in destructor to allow
|
||||
// data to live across de/reinitialization
|
||||
_is_initialized = false;
|
||||
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(is_valid_read(addr, size));
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
uint8_t *buffer = static_cast<uint8_t*>(b);
|
||||
|
||||
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(is_valid_program(addr, size));
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
const uint8_t *buffer = static_cast<const uint8_t*>(b);
|
||||
|
||||
while (size > 0) {
|
||||
|
|
|
@ -151,6 +151,7 @@ private:
|
|||
bd_size_t _count;
|
||||
uint8_t **_blocks;
|
||||
uint32_t _init_ref_count;
|
||||
bool _is_initialized;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -195,40 +195,44 @@ int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type,
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (val != 1) {
|
||||
return BD_ERROR_OK;
|
||||
}
|
||||
|
||||
int err = _bd->init();
|
||||
err = _bd->init();
|
||||
if (err) {
|
||||
return err;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// Allocate smallest buffer necessary to write MBR
|
||||
uint32_t buffer_size = std::max<uint32_t>(_bd->get_read_size(), sizeof(struct mbr_table));
|
||||
uint8_t *buffer = new uint8_t[buffer_size];
|
||||
buffer_size = std::max<uint32_t>(_bd->get_read_size(), sizeof(struct mbr_table));
|
||||
buffer = new uint8_t[buffer_size];
|
||||
|
||||
err = _bd->read(buffer, 512-buffer_size, buffer_size);
|
||||
if (err) {
|
||||
delete[] buffer;
|
||||
return err;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// Check for valid table
|
||||
struct mbr_table *table = reinterpret_cast<struct mbr_table*>(
|
||||
&buffer[buffer_size - sizeof(struct mbr_table)]);
|
||||
table = reinterpret_cast<struct mbr_table*>(&buffer[buffer_size - sizeof(struct mbr_table)]);
|
||||
if (table->signature[0] != 0x55 || table->signature[1] != 0xaa) {
|
||||
delete[] buffer;
|
||||
return BD_ERROR_INVALID_MBR;
|
||||
err = BD_ERROR_INVALID_MBR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// Check for valid entry
|
||||
|
@ -237,82 +241,130 @@ int MBRBlockDevice::init()
|
|||
if ((table->entries[_part-1].type == 0x00 ||
|
||||
table->entries[_part-1].type == 0x05 ||
|
||||
table->entries[_part-1].type == 0x0f)) {
|
||||
delete[] buffer;
|
||||
return BD_ERROR_INVALID_PARTITION;
|
||||
err = BD_ERROR_INVALID_PARTITION;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// 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;
|
||||
_offset = fromle32(table->entries[_part-1].lba_offset) * sector;
|
||||
_size = fromle32(table->entries[_part-1].lba_size) * sector;
|
||||
|
||||
// Check that block addresses are valid
|
||||
if (!_bd->is_valid_erase(_offset, _size)) {
|
||||
delete[] buffer;
|
||||
return BD_ERROR_INVALID_PARTITION;
|
||||
err = BD_ERROR_INVALID_PARTITION;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
_is_initialized = true;
|
||||
delete[] buffer;
|
||||
return 0;
|
||||
return BD_ERROR_OK;
|
||||
|
||||
fail:
|
||||
delete[] buffer;
|
||||
_is_initialized = false;
|
||||
_init_ref_count = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
int MBRBlockDevice::deinit()
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_OK;
|
||||
}
|
||||
|
||||
uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
|
||||
|
||||
if (val) {
|
||||
return BD_ERROR_OK;
|
||||
}
|
||||
|
||||
_is_initialized = false;
|
||||
return _bd->deinit();
|
||||
}
|
||||
|
||||
int MBRBlockDevice::sync()
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->sync();
|
||||
}
|
||||
|
||||
int MBRBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
|
||||
{
|
||||
MBED_ASSERT(is_valid_read(addr, size));
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->read(b, addr + _offset, size);
|
||||
}
|
||||
|
||||
int MBRBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
|
||||
{
|
||||
MBED_ASSERT(is_valid_program(addr, size));
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->program(b, addr + _offset, size);
|
||||
}
|
||||
|
||||
int MBRBlockDevice::erase(bd_addr_t addr, bd_size_t size)
|
||||
{
|
||||
MBED_ASSERT(is_valid_erase(addr, size));
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _bd->erase(addr + _offset, size);
|
||||
}
|
||||
|
||||
bd_size_t MBRBlockDevice::get_read_size() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _bd->get_read_size();
|
||||
}
|
||||
|
||||
bd_size_t MBRBlockDevice::get_program_size() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _bd->get_program_size();
|
||||
}
|
||||
|
||||
bd_size_t MBRBlockDevice::get_erase_size() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _bd->get_erase_size();
|
||||
}
|
||||
|
||||
bd_size_t MBRBlockDevice::get_erase_size(bd_addr_t addr) const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _bd->get_erase_size(_offset + addr);
|
||||
}
|
||||
|
||||
int MBRBlockDevice::get_erase_value() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _bd->get_erase_value();
|
||||
}
|
||||
|
||||
|
|
|
@ -253,6 +253,7 @@ protected:
|
|||
uint8_t _type;
|
||||
uint8_t _part;
|
||||
uint32_t _init_ref_count;
|
||||
bool _is_initialized;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue