Fix the general block device to support better low memory boards

In addition, fix prints and warnings.
pull/9370/head
David Saada 2019-01-13 16:47:35 +02:00 committed by adbridge
parent 05eb6c59bd
commit e57c9f35a8
1 changed files with 58 additions and 45 deletions

View File

@ -65,7 +65,7 @@ void basic_erase_program_read_test(BlockDevice *block_device, bd_size_t block_si
write_block[i_ind] = 0xff & rand();
}
// Write, sync, and read the block
utest_printf("\ntest %0*llx:%llu...", addrwidth, block, block_size);
utest_printf("test %0*llx:%llu...\n", addrwidth, block, block_size);
_mutex->unlock();
err = block_device->erase(block, block_size);
@ -100,7 +100,7 @@ void test_random_program_read_erase()
BlockDevice *block_device = BlockDevice::get_default_instance();
TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "\nno block device found.\n");
TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "no block device found.");
int err = block_device->init();
TEST_ASSERT_EQUAL(0, err);
@ -123,7 +123,7 @@ void test_random_program_read_erase()
uint8_t *write_block = new (std::nothrow) uint8_t[block_size];
uint8_t *read_block = new (std::nothrow) uint8_t[block_size];
if (!write_block || !read_block) {
utest_printf("\n Not enough memory for test");
utest_printf("Not enough memory for test\n");
goto end;
}
@ -152,7 +152,7 @@ static void test_thread_job(void *block_device_ptr)
uint8_t *read_block = new (std::nothrow) uint8_t[block_size];
if (!write_block || !read_block) {
utest_printf("\n Not enough memory for test");
utest_printf("Not enough memory for test\n");
goto end;
}
@ -173,6 +173,10 @@ void test_multi_threads()
TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "\nno block device found.\n");
char *dummy = new (std::nothrow) char[TEST_NUM_OF_THREADS * OS_STACK_SIZE];
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory for test.\n");
delete[] dummy;
int err = block_device->init();
TEST_ASSERT_EQUAL(0, err);
@ -196,7 +200,7 @@ void test_multi_threads()
for (i_ind = 0; i_ind < TEST_NUM_OF_THREADS; i_ind++) {
threadStatus = bd_thread[i_ind].start(callback(test_thread_job, (void *)block_device));
if (threadStatus != 0) {
utest_printf("\n Thread %d Start Failed!", i_ind + 1);
utest_printf("Thread %d Start Failed!\n", i_ind + 1);
}
}
@ -219,15 +223,15 @@ void test_get_erase_value()
// 3. Read erased region and compare with get_erase_value()
BlockDevice *block_device = BlockDevice::get_default_instance();
TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "\nno block device found.\n");
TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "no block device found.");
int err = block_device->init();
TEST_ASSERT_EQUAL(0, err);
// Check erase value
int erase_value_int = block_device->get_erase_value();
utest_printf("\nblock_device->get_erase_value()=%d", erase_value_int);
TEST_SKIP_UNLESS_MESSAGE(erase_value_int >= 0, "\nerase value is negative which means the erase value is unknown\n");
utest_printf("block_device->get_erase_value()=%d\n", erase_value_int);
TEST_SKIP_UNLESS_MESSAGE(erase_value_int >= 0, "Erase not supported in this block device. Test skipped.");
// Assuming that get_erase_value() returns byte value as documentation mentions
// "If get_erase_value() returns a non-negative byte value" for unknown case.
@ -245,33 +249,33 @@ void test_get_erase_value()
start_address %= block_device->size() - data_buf_size - erase_size; // fit all data + alignment reserve
start_address += erase_size; // add alignment reserve
start_address -= start_address % erase_size; // align with erase_block
utest_printf("\nstart_address=0x%016" PRIx64, start_address);
utest_printf("start_address=0x%016" PRIx64 "\n", start_address);
// Allocate buffer for read test data
uint8_t *data_buf = (uint8_t *)malloc(data_buf_size);
TEST_ASSERT_NOT_NULL(data_buf);
TEST_SKIP_UNLESS_MESSAGE(data_buf, "Not enough memory for test.\n");
// Write random data to selected region to make sure data is not accidentally set to "erased" value.
// With this pre-write, the test case will fail even if block_device->erase() is broken.
for (bd_size_t i = 0; i < data_buf_size; i++) {
data_buf[i] = (uint8_t) rand();
}
utest_printf("\nwriting given memory region");
utest_printf("writing given memory region\n");
err = block_device->program((const void *)data_buf, start_address, data_buf_size);
TEST_ASSERT_EQUAL(0, err);
// Erase given memory region
utest_printf("\nerasing given memory region");
utest_printf("erasing given memory region\n");
err = block_device->erase(start_address, data_buf_size);
TEST_ASSERT_EQUAL(0, err);
// Read erased memory region
utest_printf("\nreading erased memory region");
utest_printf("reading erased memory region\n");
err = block_device->read((void *)data_buf, start_address, data_buf_size);
TEST_ASSERT_EQUAL(0, err);
// Verify erased memory region
utest_printf("\nverifying erased memory region");
utest_printf("verifying erased memory region\n");
for (bd_size_t i = 0; i < data_buf_size; i++) {
TEST_ASSERT_EQUAL(erase_value, data_buf[i]);
}
@ -295,7 +299,7 @@ void test_contiguous_erase_write_read()
// 3. Return step 2 for whole erase region
BlockDevice *block_device = BlockDevice::get_default_instance();
TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "\nno block device found.\n");
TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "no block device found.");
// Initialize BlockDevice
int err = block_device->init();
@ -306,9 +310,9 @@ void test_contiguous_erase_write_read()
TEST_ASSERT(erase_size > 0);
bd_size_t program_size = block_device->get_program_size();
TEST_ASSERT(program_size > 0);
utest_printf("\nerase_size=%d", erase_size);
utest_printf("\nprogram_size=%d", program_size);
utest_printf("\nblock_device->size()=%" PRId64, block_device->size());
utest_printf("erase_size=%" PRId64 "\n", erase_size);
utest_printf("program_size=%" PRId64 "\n", program_size);
utest_printf("block_device->size()=%" PRId64 "\n", block_device->size());
// Determine write/read buffer size
// start write_read_buf_size from 1% block_device->size()
@ -324,18 +328,18 @@ void test_contiguous_erase_write_read()
bd_size_t contiguous_write_read_blocks_per_region = write_read_buf_size /
program_size; // 2 is minimum to test contiguous write
write_read_buf_size = contiguous_write_read_blocks_per_region * program_size;
utest_printf("\ncontiguous_write_read_blocks_per_region=%" PRIu64, contiguous_write_read_blocks_per_region);
utest_printf("\nwrite_read_buf_size=%" PRIu64, write_read_buf_size);
utest_printf("contiguous_write_read_blocks_per_region=%" PRIu64 "\n", contiguous_write_read_blocks_per_region);
utest_printf("write_read_buf_size=%" PRIu64 "\n", write_read_buf_size);
// Determine test region count
int contiguous_write_read_regions = TEST_BLOCK_COUNT;
utest_printf("\ncontiguous_write_read_regions=%d", contiguous_write_read_regions);
utest_printf("contiguous_write_read_regions=%d\n", contiguous_write_read_regions);
// Determine whole erase size
bd_size_t contiguous_erase_size = write_read_buf_size * contiguous_write_read_regions;
contiguous_erase_size -= contiguous_erase_size % erase_size; // aligned to erase_size
contiguous_erase_size += erase_size; // but larger than write/read size * regions
utest_printf("\ncontiguous_erase_size=%" PRIu64, contiguous_erase_size);
utest_printf("contiguous_erase_size=%" PRIu64 "\n", contiguous_erase_size);
// Determine starting address
bd_addr_t start_address = rand(); // low 32 bytes
@ -344,16 +348,16 @@ void test_contiguous_erase_write_read()
start_address += erase_size; // add alignment reserve
start_address -= start_address % erase_size; // align with erase_block
bd_addr_t stop_address = start_address + write_read_buf_size * contiguous_write_read_regions;
utest_printf("\nstart_address=0x%016" PRIx64, start_address);
utest_printf("\nstop_address=0x%016" PRIx64, stop_address);
utest_printf("start_address=0x%016" PRIx64 "\n", start_address);
utest_printf("stop_address=0x%016" PRIx64 "\n", stop_address);
// Allocate write/read buffer
uint8_t *write_read_buf = (uint8_t *)malloc(write_read_buf_size);
if (write_read_buf == NULL) {
block_device->deinit();
TEST_SKIP_MESSAGE("\nnot enough memory for test");
TEST_SKIP_MESSAGE("not enough memory for test");
}
utest_printf("\nwrite_read_buf_size=%" PRIu64 "", (uint64_t)write_read_buf_size);
utest_printf("write_read_buf_size=%" PRIu64 "\n", (uint64_t)write_read_buf_size);
// Pre-fill the to-be-erased region. By pre-filling the region,
// we can be sure the test will not pass if the erase doesn't work.
@ -361,53 +365,53 @@ void test_contiguous_erase_write_read()
for (size_t i = 0; i < write_read_buf_size; i++) {
write_read_buf[i] = (uint8_t)rand();
}
utest_printf("\npre-filling memory, from 0x%" PRIx64 " of size 0x%" PRIx64, start_address + offset,
utest_printf("pre-filling memory, from 0x%" PRIx64 " of size 0x%" PRIx64 "\n", start_address + offset,
write_read_buf_size);
err = block_device->program((const void *)write_read_buf, start_address + offset, write_read_buf_size);
TEST_ASSERT_EQUAL(0, err);
}
// Erase the whole region first
utest_printf("\nerasing memory, from 0x%" PRIx64 " of size 0x%" PRIx64, start_address, contiguous_erase_size);
utest_printf("erasing memory, from 0x%" PRIx64 " of size 0x%" PRIx64 "\n", start_address, contiguous_erase_size);
err = block_device->erase(start_address, contiguous_erase_size);
TEST_ASSERT_EQUAL(0, err);
// Loop through all write/read regions
int region = 0;
for (; start_address < stop_address; start_address += write_read_buf_size) {
utest_printf("\n\nregion #%d start_address=0x%016" PRIx64, region++, start_address);
utest_printf("\nregion #%d start_address=0x%016" PRIx64 "\n", region++, start_address);
// Generate test data
unsigned int seed = rand();
utest_printf("\ngenerating test data, seed=%u", seed);
utest_printf("generating test data, seed=%u\n", seed);
srand(seed);
for (size_t i = 0; i < write_read_buf_size; i++) {
write_read_buf[i] = (uint8_t)rand();
}
// Write test data
utest_printf("\nwriting test data");
utest_printf("writing test data\n");
err = block_device->program((const void *)write_read_buf, start_address, write_read_buf_size);
TEST_ASSERT_EQUAL(0, err);
// Read test data
memset(write_read_buf, 0, (size_t)write_read_buf_size);
utest_printf("\nreading test data");
utest_printf("reading test data\n");
err = block_device->read(write_read_buf, start_address, write_read_buf_size);
TEST_ASSERT_EQUAL(0, err);
// Verify read data
utest_printf("\nverifying test data");
utest_printf("verifying test data\n");
srand(seed);
for (size_t i = 0; i < write_read_buf_size; i++) {
uint8_t expected_value = (uint8_t)rand();
if (write_read_buf[i] != expected_value) {
utest_printf("\ndata verify failed, write_read_buf[%d]=%" PRIu8 " and not %" PRIu8 "\n",
utest_printf("data verify failed, write_read_buf[%d]=%" PRIu8 " and not %" PRIu8 "\n",
i, write_read_buf[i], expected_value);
}
TEST_ASSERT_EQUAL(write_read_buf[i], expected_value);
}
utest_printf("\nverify OK");
utest_printf("verify OK\n");
}
free(write_read_buf);
@ -423,22 +427,34 @@ void test_program_read_small_data_sizes()
BlockDevice *bd = BlockDevice::get_default_instance();
TEST_SKIP_UNLESS_MESSAGE(bd != NULL, "\nno block device found.\n");
TEST_SKIP_UNLESS_MESSAGE(bd != NULL, "no block device found.");
int err = bd->init();
TEST_ASSERT_EQUAL(0, err);
bd_size_t erase_size = bd->get_erase_size();
bd_size_t program_size = bd->get_program_size();
bd_size_t read_size = bd->get_read_size();
TEST_ASSERT(program_size > 0);
err = bd->deinit();
TEST_ASSERT_EQUAL(0, err);
// See that we have enough memory for buffered block device
char *dummy = new (std::nothrow) char[program_size + read_size];
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory for test.\n");
delete[] dummy;
// use BufferedBlockDevice for better handling of block devices program and read
BufferedBlockDevice *block_device = new BufferedBlockDevice(bd);
// BlockDevice initialization
int err = block_device->init();
err = block_device->init();
TEST_ASSERT_EQUAL(0, err);
const char write_buffer[] = "1234567";
char read_buffer[7] = {};
bd_size_t erase_size = block_device->get_erase_size();
bd_size_t program_size = block_device->get_program_size();
TEST_ASSERT(program_size > 0);
// Determine starting address
bd_addr_t start_address = 0;
@ -469,10 +485,7 @@ void test_program_read_small_data_sizes()
void test_get_type_functionality()
{
BlockDevice *block_device = BlockDevice::get_default_instance();
if (block_device == NULL) {
TEST_SKIP_MESSAGE("No block device component is defined for this target");
return;
}
TEST_SKIP_UNLESS_MESSAGE(block_device, "No block device component is defined for this target");
const char *bd_type = block_device->get_type();
TEST_ASSERT_NOT_EQUAL(0, bd_type);