From e57c9f35a84b48b7c105430e5c6b630d9e39d584 Mon Sep 17 00:00:00 2001 From: David Saada Date: Sun, 13 Jan 2019 16:47:35 +0200 Subject: [PATCH] Fix the general block device to support better low memory boards In addition, fix prints and warnings. --- .../blockdevice/general_block_device/main.cpp | 103 ++++++++++-------- 1 file changed, 58 insertions(+), 45 deletions(-) diff --git a/features/storage/TESTS/blockdevice/general_block_device/main.cpp b/features/storage/TESTS/blockdevice/general_block_device/main.cpp index dde0ae398d..6d28ac34e3 100644 --- a/features/storage/TESTS/blockdevice/general_block_device/main.cpp +++ b/features/storage/TESTS/blockdevice/general_block_device/main.cpp @@ -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);