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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue