mirror of https://github.com/ARMmbed/mbed-os.git
BlockDevice: multiple fixes to BlockDevice classes
Incorrect addresses only cause error return values instead of assertion. ExhaustibleBlockDevice has working get/set_erase_cycle functions and an array preventing programming without erase. Fixed MBRBlockDevice partitioning function.pull/12398/head
parent
d847f9f164
commit
10481f2f7e
|
@ -271,11 +271,14 @@ 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));
|
|
||||||
if (!_is_initialized) {
|
if (!_is_initialized) {
|
||||||
return BD_ERROR_DEVICE_ERROR;
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_valid_erase(addr, size)) {
|
||||||
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if ((_write_cache_addr >= addr) && (_write_cache_addr <= addr + size)) {
|
if ((_write_cache_addr >= addr) && (_write_cache_addr <= addr + size)) {
|
||||||
invalidate_write_cache();
|
invalidate_write_cache();
|
||||||
}
|
}
|
||||||
|
@ -284,11 +287,14 @@ int BufferedBlockDevice::erase(bd_addr_t addr, bd_size_t 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));
|
|
||||||
if (!_is_initialized) {
|
if (!_is_initialized) {
|
||||||
return BD_ERROR_DEVICE_ERROR;
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_valid_erase(addr, size)) {
|
||||||
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if ((_write_cache_addr >= addr) && (_write_cache_addr <= addr + size)) {
|
if ((_write_cache_addr >= addr) && (_write_cache_addr <= addr + size)) {
|
||||||
invalidate_write_cache();
|
invalidate_write_cache();
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,11 +138,14 @@ 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));
|
|
||||||
if (!_is_initialized) {
|
if (!_is_initialized) {
|
||||||
return BD_ERROR_DEVICE_ERROR;
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_valid_read(addr, size)) {
|
||||||
|
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
|
||||||
|
@ -173,11 +176,14 @@ 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));
|
|
||||||
if (!_is_initialized) {
|
if (!_is_initialized) {
|
||||||
return BD_ERROR_DEVICE_ERROR;
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_valid_program(addr, size)) {
|
||||||
|
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
|
||||||
|
@ -208,11 +214,14 @@ 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));
|
|
||||||
if (!_is_initialized) {
|
if (!_is_initialized) {
|
||||||
return BD_ERROR_DEVICE_ERROR;
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_valid_erase(addr, size)) {
|
||||||
|
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++) {
|
||||||
bd_size_t bdsize = _bds[i]->size();
|
bd_size_t bdsize = _bds[i]->size();
|
||||||
|
|
|
@ -21,13 +21,31 @@
|
||||||
namespace mbed {
|
namespace mbed {
|
||||||
|
|
||||||
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), _is_initialized(false)
|
: _bd(bd), _erase_array(NULL), _programmable_array(NULL), _erase_cycles(erase_cycles),
|
||||||
|
_init_ref_count(0), _is_initialized(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ExhaustibleBlockDevice::~ExhaustibleBlockDevice()
|
ExhaustibleBlockDevice::~ExhaustibleBlockDevice()
|
||||||
{
|
{
|
||||||
delete[] _erase_array;
|
delete[] _erase_array;
|
||||||
|
delete[] _programmable_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ExhaustibleBlockDevice::get_erase_cycles(bd_addr_t addr) const
|
||||||
|
{
|
||||||
|
if (!_is_initialized) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return _erase_array[addr / get_erase_size()];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExhaustibleBlockDevice::set_erase_cycles(bd_addr_t addr, uint32_t cycles)
|
||||||
|
{
|
||||||
|
if (!_is_initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_erase_array[addr / get_erase_size()] = cycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ExhaustibleBlockDevice::init()
|
int ExhaustibleBlockDevice::init()
|
||||||
|
@ -52,6 +70,13 @@ int ExhaustibleBlockDevice::init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_programmable_array) {
|
||||||
|
_programmable_array = new bool[_bd->size() / _bd->get_erase_size()];
|
||||||
|
for (size_t i = 0; i < _bd->size() / _bd->get_erase_size(); i++) {
|
||||||
|
_programmable_array[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_is_initialized = true;
|
_is_initialized = true;
|
||||||
return BD_ERROR_OK;
|
return BD_ERROR_OK;
|
||||||
|
|
||||||
|
@ -99,38 +124,53 @@ int ExhaustibleBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
|
||||||
|
|
||||||
int ExhaustibleBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
|
int ExhaustibleBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
|
||||||
{
|
{
|
||||||
MBED_ASSERT(is_valid_program(addr, size));
|
|
||||||
|
|
||||||
if (!_is_initialized) {
|
if (!_is_initialized) {
|
||||||
return BD_ERROR_DEVICE_ERROR;
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_erase_array[addr / get_erase_size()] == 0) {
|
if (!is_valid_program(addr, size)) {
|
||||||
return 0;
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _bd->program(buffer, addr, size);
|
if (_erase_array[addr / get_erase_size()] == 0) {
|
||||||
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_programmable_array[addr / get_erase_size()]) {
|
||||||
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = _bd->program(buffer, addr, size);
|
||||||
|
|
||||||
|
if (ret == BD_ERROR_OK) {
|
||||||
|
_programmable_array[addr / get_erase_size()] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
|
||||||
if (!_is_initialized) {
|
if (!_is_initialized) {
|
||||||
return BD_ERROR_DEVICE_ERROR;
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_valid_erase(addr, size)) {
|
||||||
|
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) {
|
||||||
// use an erase cycle
|
// use an erase cycle
|
||||||
if (_erase_array[addr / eu_size] > 0) {
|
if (_erase_array[addr / eu_size] > 0) {
|
||||||
_erase_array[addr / eu_size] -= 1;
|
_erase_array[addr / eu_size] -= 1;
|
||||||
}
|
|
||||||
|
|
||||||
if (_erase_array[addr / eu_size] > 0) {
|
|
||||||
int err = _bd->erase(addr, eu_size);
|
int err = _bd->erase(addr, eu_size);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
_programmable_array[addr / get_erase_size()] = true;
|
||||||
|
} else {
|
||||||
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr += eu_size;
|
addr += eu_size;
|
||||||
|
|
|
@ -158,6 +158,7 @@ public:
|
||||||
private:
|
private:
|
||||||
BlockDevice *_bd;
|
BlockDevice *_bd;
|
||||||
uint32_t *_erase_array;
|
uint32_t *_erase_array;
|
||||||
|
bool *_programmable_array;
|
||||||
uint32_t _erase_cycles;
|
uint32_t _erase_cycles;
|
||||||
uint32_t _init_ref_count;
|
uint32_t _init_ref_count;
|
||||||
bool _is_initialized;
|
bool _is_initialized;
|
||||||
|
|
|
@ -153,11 +153,14 @@ int FlashSimBlockDevice::read(void *b, bd_addr_t addr, bd_size_t 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));
|
|
||||||
if (!_is_initialized) {
|
if (!_is_initialized) {
|
||||||
return BD_ERROR_DEVICE_ERROR;
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_valid_program(addr, size)) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
@ -185,12 +188,14 @@ int FlashSimBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
|
||||||
|
|
||||||
int FlashSimBlockDevice::erase(bd_addr_t addr, bd_size_t size)
|
int FlashSimBlockDevice::erase(bd_addr_t addr, bd_size_t size)
|
||||||
{
|
{
|
||||||
MBED_ASSERT(is_valid_erase(addr, size));
|
|
||||||
|
|
||||||
if (!_is_initialized) {
|
if (!_is_initialized) {
|
||||||
return BD_ERROR_DEVICE_ERROR;
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_valid_erase(addr, size)) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
|
@ -174,14 +174,14 @@ int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type, bd_addr_t
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate dimensions
|
// Calculate dimensions
|
||||||
bd_size_t offset = ((int64_t)start < 0) ? -start : start;
|
bd_size_t size = ((int64_t)start < 0) ? -start : start;
|
||||||
bd_size_t size = bd->size();
|
bd_size_t offset = bd->size();
|
||||||
|
|
||||||
if (offset < 512) {
|
if (size < 512) {
|
||||||
offset += std::max<uint32_t>(bd->get_erase_size(), 512);
|
size += std::max<uint32_t>(bd->get_erase_size(), 512);
|
||||||
}
|
}
|
||||||
|
|
||||||
size -= offset;
|
offset -= size;
|
||||||
|
|
||||||
err = partition_absolute(bd, part, type, offset, size);
|
err = partition_absolute(bd, part, type, offset, size);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -336,31 +336,40 @@ int MBRBlockDevice::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));
|
|
||||||
if (!_is_initialized) {
|
if (!_is_initialized) {
|
||||||
return BD_ERROR_DEVICE_ERROR;
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_valid_read(addr, size)) {
|
||||||
|
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));
|
|
||||||
if (!_is_initialized) {
|
if (!_is_initialized) {
|
||||||
return BD_ERROR_DEVICE_ERROR;
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_valid_program(addr, size)) {
|
||||||
|
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));
|
|
||||||
if (!_is_initialized) {
|
if (!_is_initialized) {
|
||||||
return BD_ERROR_DEVICE_ERROR;
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_valid_erase(addr, size)) {
|
||||||
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
return _bd->erase(addr + _offset, size);
|
return _bd->erase(addr + _offset, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,7 +412,7 @@ bd_size_t MBRBlockDevice::get_erase_size(bd_addr_t addr) const
|
||||||
int MBRBlockDevice::get_erase_value() const
|
int MBRBlockDevice::get_erase_value() const
|
||||||
{
|
{
|
||||||
if (!_is_initialized) {
|
if (!_is_initialized) {
|
||||||
return 0;
|
return BD_ERROR_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _bd->get_erase_value();
|
return _bd->get_erase_value();
|
||||||
|
|
|
@ -61,13 +61,11 @@ int ReadOnlyBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
|
||||||
|
|
||||||
int ReadOnlyBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
|
int ReadOnlyBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
|
||||||
{
|
{
|
||||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_BLOCK_DEVICE, MBED_ERROR_CODE_WRITE_PROTECTED), "ReadOnlyBlockDevice::program() not allowed", addr);
|
|
||||||
return MBED_ERROR_WRITE_PROTECTED;
|
return MBED_ERROR_WRITE_PROTECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadOnlyBlockDevice::erase(bd_addr_t addr, bd_size_t size)
|
int ReadOnlyBlockDevice::erase(bd_addr_t addr, bd_size_t size)
|
||||||
{
|
{
|
||||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_BLOCK_DEVICE, MBED_ERROR_CODE_WRITE_PROTECTED), "ReadOnlyBlockDevice::erase() not allowed", addr);
|
|
||||||
return MBED_ERROR_WRITE_PROTECTED;
|
return MBED_ERROR_WRITE_PROTECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue