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
Michal Paszta 2020-02-07 16:34:30 +02:00
parent d847f9f164
commit 10481f2f7e
7 changed files with 97 additions and 29 deletions

View File

@ -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)
{
MBED_ASSERT(is_valid_erase(addr, size));
if (!_is_initialized) {
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)) {
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)
{
MBED_ASSERT(is_valid_erase(addr, size));
if (!_is_initialized) {
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)) {
invalidate_write_cache();
}

View File

@ -138,11 +138,14 @@ 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;
}
if (!is_valid_read(addr, size)) {
return BD_ERROR_DEVICE_ERROR;
}
uint8_t *buffer = static_cast<uint8_t *>(b);
// 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)
{
MBED_ASSERT(is_valid_program(addr, size));
if (!_is_initialized) {
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);
// 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)
{
MBED_ASSERT(is_valid_erase(addr, size));
if (!_is_initialized) {
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
for (size_t i = 0; i < _bd_count && size > 0; i++) {
bd_size_t bdsize = _bds[i]->size();

View File

@ -21,13 +21,31 @@
namespace mbed {
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()
{
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()
@ -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;
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)
{
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;
if (!is_valid_program(addr, size)) {
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)
{
MBED_ASSERT(is_valid_erase(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
if (!is_valid_erase(addr, size)) {
return BD_ERROR_DEVICE_ERROR;
}
bd_size_t eu_size = get_erase_size();
while (size) {
// use an erase cycle
if (_erase_array[addr / eu_size] > 0) {
_erase_array[addr / eu_size] -= 1;
}
if (_erase_array[addr / eu_size] > 0) {
int err = _bd->erase(addr, eu_size);
if (err) {
return err;
}
_programmable_array[addr / get_erase_size()] = true;
} else {
return BD_ERROR_DEVICE_ERROR;
}
addr += eu_size;

View File

@ -158,6 +158,7 @@ public:
private:
BlockDevice *_bd;
uint32_t *_erase_array;
bool *_programmable_array;
uint32_t _erase_cycles;
uint32_t _init_ref_count;
bool _is_initialized;

View File

@ -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)
{
MBED_ASSERT(is_valid_program(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
if (!is_valid_program(addr, size)) {
return BD_ERROR_DEVICE_ERROR;
}
bd_addr_t curr_addr = addr;
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)
{
MBED_ASSERT(is_valid_erase(addr, size));
if (!_is_initialized) {
return BD_ERROR_DEVICE_ERROR;
}
if (!is_valid_erase(addr, size)) {
return BD_ERROR_DEVICE_ERROR;
}
bd_addr_t curr_addr = addr;
bd_size_t curr_size = size;

View File

@ -174,14 +174,14 @@ int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type, bd_addr_t
}
// Calculate dimensions
bd_size_t offset = ((int64_t)start < 0) ? -start : start;
bd_size_t size = bd->size();
bd_size_t size = ((int64_t)start < 0) ? -start : start;
bd_size_t offset = bd->size();
if (offset < 512) {
offset += std::max<uint32_t>(bd->get_erase_size(), 512);
if (size < 512) {
size += std::max<uint32_t>(bd->get_erase_size(), 512);
}
size -= offset;
offset -= size;
err = partition_absolute(bd, part, type, offset, size);
if (err) {
@ -336,31 +336,40 @@ int MBRBlockDevice::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;
}
if (!is_valid_read(addr, size)) {
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;
}
if (!is_valid_program(addr, size)) {
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;
}
if (!is_valid_erase(addr, size)) {
return BD_ERROR_DEVICE_ERROR;
}
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
{
if (!_is_initialized) {
return 0;
return BD_ERROR_DEVICE_ERROR;
}
return _bd->get_erase_value();

View File

@ -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)
{
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_BLOCK_DEVICE, MBED_ERROR_CODE_WRITE_PROTECTED), "ReadOnlyBlockDevice::program() not allowed", addr);
return MBED_ERROR_WRITE_PROTECTED;
}
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;
}