|
23 | 23 |
|
24 | 24 | using namespace utest::v1;
|
25 | 25 |
|
26 |
| -/* It is not possible to build a KL25Z image with IAR including the file system if |
27 |
| - * stack tracking statistics are enabled. If this is the case, build dummy |
28 |
| - * tests. |
29 |
| - */ |
30 |
| -#if ! defined(__ICCARM__) && ! defined(TARGET_KL25Z) && ! defined(MBED_STACK_STATS_ENABLED) |
| 26 | +#define TEST_BLOCK_SIZE 512 |
| 27 | +#define TEST_BLOCK_DEVICE_SIZE 16*TEST_BLOCK_SIZE |
| 28 | +#define TEST_BLOCK_COUNT 10 |
| 29 | +#define TEST_ERROR_MASK 16 |
| 30 | + |
| 31 | +const struct { |
| 32 | + const char *name; |
| 33 | + bd_size_t (BlockDevice::*method)() const; |
| 34 | +} ATTRS[] = { |
| 35 | + {"read size", &BlockDevice::get_read_size}, |
| 36 | + {"program size", &BlockDevice::get_program_size}, |
| 37 | + {"erase size", &BlockDevice::get_erase_size}, |
| 38 | + {"total size", &BlockDevice::size}, |
| 39 | +}; |
31 | 40 |
|
32 |
| -#define BLOCK_SIZE 512 |
33 |
| -#define HEAP_BLOCK_DEVICE_TEST_01 test_read_write |
34 |
| -uint8_t write_block[BLOCK_SIZE]; |
35 |
| -uint8_t read_block[BLOCK_SIZE]; |
36 | 41 |
|
37 |
| -// Simple test which reads and writes a block |
| 42 | +// Simple test that read/writes random set of blocks |
38 | 43 | void test_read_write() {
|
39 |
| - HeapBlockDevice bd(16*BLOCK_SIZE, BLOCK_SIZE); |
| 44 | + HeapBlockDevice bd(TEST_BLOCK_DEVICE_SIZE, TEST_BLOCK_SIZE); |
40 | 45 |
|
41 | 46 | int err = bd.init();
|
42 | 47 | TEST_ASSERT_EQUAL(0, err);
|
43 | 48 |
|
44 |
| - // Fill with random sequence |
45 |
| - srand(1); |
46 |
| - for (int i = 0; i < BLOCK_SIZE; i++) { |
47 |
| - write_block[i] = 0xff & rand(); |
| 49 | + for (unsigned a = 0; a < sizeof(ATTRS)/sizeof(ATTRS[0]); a++) { |
| 50 | + static const char *prefixes[] = {"", "k", "M", "G"}; |
| 51 | + for (int i = 3; i >= 0; i--) { |
| 52 | + bd_size_t size = (bd.*ATTRS[a].method)(); |
| 53 | + if (size >= (1ULL << 10*i)) { |
| 54 | + printf("%s: %llu%sbytes (%llubytes)\n", |
| 55 | + ATTRS[a].name, size >> 10*i, prefixes[i], size); |
| 56 | + break; |
| 57 | + } |
| 58 | + } |
48 | 59 | }
|
49 | 60 |
|
50 |
| - // Write, sync, and read the block |
51 |
| - err = bd.program(write_block, 0, BLOCK_SIZE); |
52 |
| - TEST_ASSERT_EQUAL(0, err); |
53 |
| - |
54 |
| - err = bd.read(read_block, 0, BLOCK_SIZE); |
55 |
| - TEST_ASSERT_EQUAL(0, err); |
56 |
| - |
57 |
| - // Check that the data was unmodified |
58 |
| - srand(1); |
59 |
| - for (int i = 0; i < BLOCK_SIZE; i++) { |
60 |
| - TEST_ASSERT_EQUAL(0xff & rand(), read_block[i]); |
| 61 | + bd_size_t block_size = bd.get_erase_size(); |
| 62 | + uint8_t *write_block = new uint8_t[block_size]; |
| 63 | + uint8_t *read_block = new uint8_t[block_size]; |
| 64 | + uint8_t *error_mask = new uint8_t[TEST_ERROR_MASK]; |
| 65 | + unsigned addrwidth = ceil(log(float(bd.size()-1)) / log(float(16)))+1; |
| 66 | + |
| 67 | + for (int b = 0; b < TEST_BLOCK_COUNT; b++) { |
| 68 | + // Find a random block |
| 69 | + bd_addr_t block = (rand()*block_size) % bd.size(); |
| 70 | + |
| 71 | + // Use next random number as temporary seed to keep |
| 72 | + // the address progressing in the pseudorandom sequence |
| 73 | + unsigned seed = rand(); |
| 74 | + |
| 75 | + // Fill with random sequence |
| 76 | + srand(seed); |
| 77 | + for (bd_size_t i = 0; i < block_size; i++) { |
| 78 | + write_block[i] = 0xff & rand(); |
| 79 | + } |
| 80 | + |
| 81 | + // erase, program, and read the block |
| 82 | + printf("test %0*llx:%llu...\n", addrwidth, block, block_size); |
| 83 | + |
| 84 | + err = bd.erase(block, block_size); |
| 85 | + TEST_ASSERT_EQUAL(0, err); |
| 86 | + |
| 87 | + err = bd.program(write_block, block, block_size); |
| 88 | + TEST_ASSERT_EQUAL(0, err); |
| 89 | + |
| 90 | + printf("write %0*llx:%llu ", addrwidth, block, block_size); |
| 91 | + for (int i = 0; i < 16; i++) { |
| 92 | + printf("%02x", write_block[i]); |
| 93 | + } |
| 94 | + printf("...\n"); |
| 95 | + |
| 96 | + err = bd.read(read_block, block, block_size); |
| 97 | + TEST_ASSERT_EQUAL(0, err); |
| 98 | + |
| 99 | + printf("read %0*llx:%llu ", addrwidth, block, block_size); |
| 100 | + for (int i = 0; i < 16; i++) { |
| 101 | + printf("%02x", read_block[i]); |
| 102 | + } |
| 103 | + printf("...\n"); |
| 104 | + |
| 105 | + // Find error mask for debugging |
| 106 | + memset(error_mask, 0, TEST_ERROR_MASK); |
| 107 | + bd_size_t error_scale = block_size / (TEST_ERROR_MASK*8); |
| 108 | + |
| 109 | + srand(seed); |
| 110 | + for (bd_size_t i = 0; i < TEST_ERROR_MASK*8; i++) { |
| 111 | + for (bd_size_t j = 0; j < error_scale; j++) { |
| 112 | + if ((0xff & rand()) != read_block[i*error_scale + j]) { |
| 113 | + error_mask[i/8] |= 1 << (i%8); |
| 114 | + } |
| 115 | + } |
| 116 | + } |
| 117 | + |
| 118 | + printf("error %0*llx:%llu ", addrwidth, block, block_size); |
| 119 | + for (int i = 0; i < 16; i++) { |
| 120 | + printf("%02x", error_mask[i]); |
| 121 | + } |
| 122 | + printf("\n"); |
| 123 | + |
| 124 | + // Check that the data was unmodified |
| 125 | + srand(seed); |
| 126 | + for (bd_size_t i = 0; i < block_size; i++) { |
| 127 | + TEST_ASSERT_EQUAL(0xff & rand(), read_block[i]); |
| 128 | + } |
61 | 129 | }
|
62 |
| - |
| 130 | + |
63 | 131 | err = bd.deinit();
|
64 | 132 | TEST_ASSERT_EQUAL(0, err);
|
65 | 133 | }
|
66 | 134 |
|
67 |
| -#else /* ! defined(__ICCARM__) && ! defined(TARGET_KL25Z) && ! defined(MBED_STACK_STATS_ENABLED) */ |
68 |
| - |
69 |
| -#define HEAP_BLOCK_DEVICE_TEST_01 heap_block_device_test_dummy |
70 |
| - |
71 |
| -/** @brief heap_block_device_test_dummy Dummy test case for testing when KL25Z being built with stack statistics enabled. |
72 |
| - * |
73 |
| - * @return success always |
74 |
| - */ |
75 |
| -static control_t heap_block_device_test_dummy() |
76 |
| -{ |
77 |
| - printf("Null test\n"); |
78 |
| - return CaseNext; |
79 |
| -} |
80 |
| - |
81 |
| -#endif /* ! defined(__ICCARM__) && ! defined(TARGET_KL25Z) && ! defined(MBED_STACK_STATS_ENABLED) */ |
82 | 135 |
|
83 | 136 | // Test setup
|
84 | 137 | utest::v1::status_t test_setup(const size_t number_of_cases) {
|
85 |
| - GREENTEA_SETUP(10, "default_auto"); |
| 138 | + GREENTEA_SETUP(30, "default_auto"); |
86 | 139 | return verbose_test_setup_handler(number_of_cases);
|
87 | 140 | }
|
88 | 141 |
|
89 | 142 | Case cases[] = {
|
90 |
| - Case("Testing read write of a block", HEAP_BLOCK_DEVICE_TEST_01), |
| 143 | + Case("Testing read write random blocks", test_read_write), |
91 | 144 | };
|
92 | 145 |
|
93 | 146 | Specification specification(test_setup, cases);
|
|
0 commit comments