RTC auf true

Committer:
kevman
Date:
Wed Mar 13 11:03:24 2019 +0000
Revision:
2:7aab896b1a3b
2019-03-13

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kevman 2:7aab896b1a3b 1 /* mbed Microcontroller Library
kevman 2:7aab896b1a3b 2 * Copyright (c) 2018 ARM Limited
kevman 2:7aab896b1a3b 3 *
kevman 2:7aab896b1a3b 4 * Licensed under the Apache License, Version 2.0 (the "License");
kevman 2:7aab896b1a3b 5 * you may not use this file except in compliance with the License.
kevman 2:7aab896b1a3b 6 * You may obtain a copy of the License at
kevman 2:7aab896b1a3b 7 *
kevman 2:7aab896b1a3b 8 * http://www.apache.org/licenses/LICENSE-2.0
kevman 2:7aab896b1a3b 9 *
kevman 2:7aab896b1a3b 10 * Unless required by applicable law or agreed to in writing, software
kevman 2:7aab896b1a3b 11 * distributed under the License is distributed on an "AS IS" BASIS,
kevman 2:7aab896b1a3b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kevman 2:7aab896b1a3b 13 * See the License for the specific language governing permissions and
kevman 2:7aab896b1a3b 14 * limitations under the License.
kevman 2:7aab896b1a3b 15 */
kevman 2:7aab896b1a3b 16 #include "greentea-client/test_env.h"
kevman 2:7aab896b1a3b 17 #include "unity.h"
kevman 2:7aab896b1a3b 18 #include "utest.h"
kevman 2:7aab896b1a3b 19 #include "SPIFBlockDevice.h"
kevman 2:7aab896b1a3b 20 #include "mbed_trace.h"
kevman 2:7aab896b1a3b 21 #include "rtos/Thread.h"
kevman 2:7aab896b1a3b 22 #include <stdlib.h>
kevman 2:7aab896b1a3b 23
kevman 2:7aab896b1a3b 24 using namespace utest::v1;
kevman 2:7aab896b1a3b 25
kevman 2:7aab896b1a3b 26 #define TEST_BLOCK_COUNT 10
kevman 2:7aab896b1a3b 27 #define TEST_ERROR_MASK 16
kevman 2:7aab896b1a3b 28 #define SPIF_TEST_NUM_OF_THREADS 5
kevman 2:7aab896b1a3b 29
kevman 2:7aab896b1a3b 30 const struct {
kevman 2:7aab896b1a3b 31 const char *name;
kevman 2:7aab896b1a3b 32 bd_size_t (BlockDevice::*method)() const;
kevman 2:7aab896b1a3b 33 } ATTRS[] = {
kevman 2:7aab896b1a3b 34 {"read size", &BlockDevice::get_read_size},
kevman 2:7aab896b1a3b 35 {"program size", &BlockDevice::get_program_size},
kevman 2:7aab896b1a3b 36 {"erase size", &BlockDevice::get_erase_size},
kevman 2:7aab896b1a3b 37 {"total size", &BlockDevice::size},
kevman 2:7aab896b1a3b 38 };
kevman 2:7aab896b1a3b 39
kevman 2:7aab896b1a3b 40 static SingletonPtr<PlatformMutex> _mutex;
kevman 2:7aab896b1a3b 41
kevman 2:7aab896b1a3b 42 // Mutex is protecting rand() per srand for buffer writing and verification.
kevman 2:7aab896b1a3b 43 // Mutex is also protecting printouts for clear logs.
kevman 2:7aab896b1a3b 44 // Mutex is NOT protecting Block Device actions: erase/program/read - which is the purpose of the multithreaded test!
kevman 2:7aab896b1a3b 45 void basic_erase_program_read_test(SPIFBlockDevice &block_device, bd_size_t block_size, uint8_t *write_block,
kevman 2:7aab896b1a3b 46 uint8_t *read_block, unsigned addrwidth)
kevman 2:7aab896b1a3b 47 {
kevman 2:7aab896b1a3b 48 int err = 0;
kevman 2:7aab896b1a3b 49 _mutex->lock();
kevman 2:7aab896b1a3b 50 // Find a random block
kevman 2:7aab896b1a3b 51 bd_addr_t block = (rand() * block_size) % block_device.size();
kevman 2:7aab896b1a3b 52
kevman 2:7aab896b1a3b 53 // Use next random number as temporary seed to keep
kevman 2:7aab896b1a3b 54 // the address progressing in the pseudorandom sequence
kevman 2:7aab896b1a3b 55 unsigned seed = rand();
kevman 2:7aab896b1a3b 56
kevman 2:7aab896b1a3b 57 // Fill with random sequence
kevman 2:7aab896b1a3b 58 srand(seed);
kevman 2:7aab896b1a3b 59 for (bd_size_t i_ind = 0; i_ind < block_size; i_ind++) {
kevman 2:7aab896b1a3b 60 write_block[i_ind] = 0xff & rand();
kevman 2:7aab896b1a3b 61 }
kevman 2:7aab896b1a3b 62 // Write, sync, and read the block
kevman 2:7aab896b1a3b 63 utest_printf("\ntest %0*llx:%llu...", addrwidth, block, block_size);
kevman 2:7aab896b1a3b 64 _mutex->unlock();
kevman 2:7aab896b1a3b 65
kevman 2:7aab896b1a3b 66 err = block_device.erase(block, block_size);
kevman 2:7aab896b1a3b 67 TEST_ASSERT_EQUAL(0, err);
kevman 2:7aab896b1a3b 68
kevman 2:7aab896b1a3b 69 err = block_device.program(write_block, block, block_size);
kevman 2:7aab896b1a3b 70 TEST_ASSERT_EQUAL(0, err);
kevman 2:7aab896b1a3b 71
kevman 2:7aab896b1a3b 72 err = block_device.read(read_block, block, block_size);
kevman 2:7aab896b1a3b 73 TEST_ASSERT_EQUAL(0, err);
kevman 2:7aab896b1a3b 74
kevman 2:7aab896b1a3b 75 _mutex->lock();
kevman 2:7aab896b1a3b 76 // Check that the data was unmodified
kevman 2:7aab896b1a3b 77 srand(seed);
kevman 2:7aab896b1a3b 78 int val_rand;
kevman 2:7aab896b1a3b 79 for (bd_size_t i_ind = 0; i_ind < block_size; i_ind++) {
kevman 2:7aab896b1a3b 80 val_rand = rand();
kevman 2:7aab896b1a3b 81 if ((0xff & val_rand) != read_block[i_ind]) {
kevman 2:7aab896b1a3b 82 utest_printf("\n Assert Failed Buf Read - block:size: %llx:%llu \n", block, block_size);
kevman 2:7aab896b1a3b 83 utest_printf("\n pos: %llu, exp: %02x, act: %02x, wrt: %02x \n", i_ind, (0xff & val_rand), read_block[i_ind],
kevman 2:7aab896b1a3b 84 write_block[i_ind]);
kevman 2:7aab896b1a3b 85 }
kevman 2:7aab896b1a3b 86 TEST_ASSERT_EQUAL(0xff & val_rand, read_block[i_ind]);
kevman 2:7aab896b1a3b 87 }
kevman 2:7aab896b1a3b 88 _mutex->unlock();
kevman 2:7aab896b1a3b 89 }
kevman 2:7aab896b1a3b 90
kevman 2:7aab896b1a3b 91 void test_spif_random_program_read_erase()
kevman 2:7aab896b1a3b 92 {
kevman 2:7aab896b1a3b 93 utest_printf("\nTest Random Program Read Erase Starts..\n");
kevman 2:7aab896b1a3b 94
kevman 2:7aab896b1a3b 95 SPIFBlockDevice block_device(MBED_CONF_SPIF_DRIVER_SPI_MOSI, MBED_CONF_SPIF_DRIVER_SPI_MISO,
kevman 2:7aab896b1a3b 96 MBED_CONF_SPIF_DRIVER_SPI_CLK,
kevman 2:7aab896b1a3b 97 MBED_CONF_SPIF_DRIVER_SPI_CS);
kevman 2:7aab896b1a3b 98
kevman 2:7aab896b1a3b 99 int err = block_device.init();
kevman 2:7aab896b1a3b 100 TEST_ASSERT_EQUAL(0, err);
kevman 2:7aab896b1a3b 101
kevman 2:7aab896b1a3b 102 for (unsigned atr = 0; atr < sizeof(ATTRS) / sizeof(ATTRS[0]); atr++) {
kevman 2:7aab896b1a3b 103 static const char *prefixes[] = {"", "k", "M", "G"};
kevman 2:7aab896b1a3b 104 for (int i_ind = 3; i_ind >= 0; i_ind--) {
kevman 2:7aab896b1a3b 105 bd_size_t size = (block_device.*ATTRS[atr].method)();
kevman 2:7aab896b1a3b 106 if (size >= (1ULL << 10 * i_ind)) {
kevman 2:7aab896b1a3b 107 utest_printf("%s: %llu%sbytes (%llubytes)\n",
kevman 2:7aab896b1a3b 108 ATTRS[atr].name, size >> 10 * i_ind, prefixes[i_ind], size);
kevman 2:7aab896b1a3b 109 break;
kevman 2:7aab896b1a3b 110 }
kevman 2:7aab896b1a3b 111 }
kevman 2:7aab896b1a3b 112 }
kevman 2:7aab896b1a3b 113
kevman 2:7aab896b1a3b 114 bd_size_t block_size = block_device.get_erase_size();
kevman 2:7aab896b1a3b 115 unsigned addrwidth = ceil(log(float(block_device.size() - 1)) / log(float(16))) + 1;
kevman 2:7aab896b1a3b 116
kevman 2:7aab896b1a3b 117 uint8_t *write_block = new (std::nothrow) uint8_t[block_size];
kevman 2:7aab896b1a3b 118 uint8_t *read_block = new (std::nothrow) uint8_t[block_size];
kevman 2:7aab896b1a3b 119 if (!write_block || !read_block) {
kevman 2:7aab896b1a3b 120 utest_printf("\n Not enough memory for test");
kevman 2:7aab896b1a3b 121 goto end;
kevman 2:7aab896b1a3b 122 }
kevman 2:7aab896b1a3b 123
kevman 2:7aab896b1a3b 124 for (int b = 0; b < TEST_BLOCK_COUNT; b++) {
kevman 2:7aab896b1a3b 125 basic_erase_program_read_test(block_device, block_size, write_block, read_block, addrwidth);
kevman 2:7aab896b1a3b 126 }
kevman 2:7aab896b1a3b 127
kevman 2:7aab896b1a3b 128 err = block_device.deinit();
kevman 2:7aab896b1a3b 129 TEST_ASSERT_EQUAL(0, err);
kevman 2:7aab896b1a3b 130
kevman 2:7aab896b1a3b 131 end:
kevman 2:7aab896b1a3b 132 delete[] write_block;
kevman 2:7aab896b1a3b 133 delete[] read_block;
kevman 2:7aab896b1a3b 134 }
kevman 2:7aab896b1a3b 135
kevman 2:7aab896b1a3b 136 void test_spif_unaligned_erase()
kevman 2:7aab896b1a3b 137 {
kevman 2:7aab896b1a3b 138 utest_printf("\nTest Unaligned Erase Starts..\n");
kevman 2:7aab896b1a3b 139
kevman 2:7aab896b1a3b 140 SPIFBlockDevice block_device(MBED_CONF_SPIF_DRIVER_SPI_MOSI, MBED_CONF_SPIF_DRIVER_SPI_MISO,
kevman 2:7aab896b1a3b 141 MBED_CONF_SPIF_DRIVER_SPI_CLK,
kevman 2:7aab896b1a3b 142 MBED_CONF_SPIF_DRIVER_SPI_CS);
kevman 2:7aab896b1a3b 143
kevman 2:7aab896b1a3b 144 int err = block_device.init();
kevman 2:7aab896b1a3b 145 TEST_ASSERT_EQUAL(0, err);
kevman 2:7aab896b1a3b 146
kevman 2:7aab896b1a3b 147 for (unsigned atr = 0; atr < sizeof(ATTRS) / sizeof(ATTRS[0]); atr++) {
kevman 2:7aab896b1a3b 148 static const char *prefixes[] = {"", "k", "M", "G"};
kevman 2:7aab896b1a3b 149 for (int i_ind = 3; i_ind >= 0; i_ind--) {
kevman 2:7aab896b1a3b 150 bd_size_t size = (block_device.*ATTRS[atr].method)();
kevman 2:7aab896b1a3b 151 if (size >= (1ULL << 10 * i_ind)) {
kevman 2:7aab896b1a3b 152 utest_printf("%s: %llu%sbytes (%llubytes)\n",
kevman 2:7aab896b1a3b 153 ATTRS[atr].name, size >> 10 * i_ind, prefixes[i_ind], size);
kevman 2:7aab896b1a3b 154 break;
kevman 2:7aab896b1a3b 155 }
kevman 2:7aab896b1a3b 156 }
kevman 2:7aab896b1a3b 157 }
kevman 2:7aab896b1a3b 158
kevman 2:7aab896b1a3b 159 bd_addr_t addr = 0;
kevman 2:7aab896b1a3b 160 bd_size_t sector_erase_size = block_device.get_erase_size(addr);
kevman 2:7aab896b1a3b 161 unsigned addrwidth = ceil(log(float(block_device.size() - 1)) / log(float(16))) + 1;
kevman 2:7aab896b1a3b 162
kevman 2:7aab896b1a3b 163 utest_printf("\ntest %0*llx:%llu...", addrwidth, addr, sector_erase_size);
kevman 2:7aab896b1a3b 164
kevman 2:7aab896b1a3b 165 //unaligned start address
kevman 2:7aab896b1a3b 166 addr += 1;
kevman 2:7aab896b1a3b 167 err = block_device.erase(addr, sector_erase_size - 1);
kevman 2:7aab896b1a3b 168 TEST_ASSERT_EQUAL(SPIF_BD_ERROR_INVALID_ERASE_PARAMS, err);
kevman 2:7aab896b1a3b 169
kevman 2:7aab896b1a3b 170 err = block_device.erase(addr, sector_erase_size);
kevman 2:7aab896b1a3b 171 TEST_ASSERT_EQUAL(SPIF_BD_ERROR_INVALID_ERASE_PARAMS, err);
kevman 2:7aab896b1a3b 172
kevman 2:7aab896b1a3b 173 err = block_device.erase(addr, 1);
kevman 2:7aab896b1a3b 174 TEST_ASSERT_EQUAL(SPIF_BD_ERROR_INVALID_ERASE_PARAMS, err);
kevman 2:7aab896b1a3b 175
kevman 2:7aab896b1a3b 176 //unaligned end address
kevman 2:7aab896b1a3b 177 addr = 0;
kevman 2:7aab896b1a3b 178
kevman 2:7aab896b1a3b 179 err = block_device.erase(addr, 1);
kevman 2:7aab896b1a3b 180 TEST_ASSERT_EQUAL(SPIF_BD_ERROR_INVALID_ERASE_PARAMS, err);
kevman 2:7aab896b1a3b 181
kevman 2:7aab896b1a3b 182 err = block_device.erase(addr, sector_erase_size + 1);
kevman 2:7aab896b1a3b 183 TEST_ASSERT_EQUAL(SPIF_BD_ERROR_INVALID_ERASE_PARAMS, err);
kevman 2:7aab896b1a3b 184
kevman 2:7aab896b1a3b 185 //erase size exceeds flash device size
kevman 2:7aab896b1a3b 186 err = block_device.erase(addr, block_device.size() + 1);
kevman 2:7aab896b1a3b 187 TEST_ASSERT_EQUAL(SPIF_BD_ERROR_INVALID_ERASE_PARAMS, err);
kevman 2:7aab896b1a3b 188
kevman 2:7aab896b1a3b 189 // Valid erase
kevman 2:7aab896b1a3b 190 err = block_device.erase(addr, sector_erase_size);
kevman 2:7aab896b1a3b 191 TEST_ASSERT_EQUAL(SPIF_BD_ERROR_OK, err);
kevman 2:7aab896b1a3b 192
kevman 2:7aab896b1a3b 193 err = block_device.deinit();
kevman 2:7aab896b1a3b 194 TEST_ASSERT_EQUAL(0, err);
kevman 2:7aab896b1a3b 195 }
kevman 2:7aab896b1a3b 196
kevman 2:7aab896b1a3b 197 static void test_spif_thread_job(void *block_device_ptr/*, int thread_num*/)
kevman 2:7aab896b1a3b 198 {
kevman 2:7aab896b1a3b 199 static int thread_num = 0;
kevman 2:7aab896b1a3b 200 thread_num++;
kevman 2:7aab896b1a3b 201 SPIFBlockDevice *block_device = (SPIFBlockDevice *)block_device_ptr;
kevman 2:7aab896b1a3b 202 utest_printf("\n Thread %d Started \n", thread_num);
kevman 2:7aab896b1a3b 203
kevman 2:7aab896b1a3b 204 bd_size_t block_size = block_device->get_erase_size();
kevman 2:7aab896b1a3b 205 unsigned addrwidth = ceil(log(float(block_device->size() - 1)) / log(float(16))) + 1;
kevman 2:7aab896b1a3b 206
kevman 2:7aab896b1a3b 207 uint8_t *write_block = new (std::nothrow) uint8_t[block_size];
kevman 2:7aab896b1a3b 208 uint8_t *read_block = new (std::nothrow) uint8_t[block_size];
kevman 2:7aab896b1a3b 209 if (!write_block || !read_block) {
kevman 2:7aab896b1a3b 210 utest_printf("\n Not enough memory for test");
kevman 2:7aab896b1a3b 211 goto end;
kevman 2:7aab896b1a3b 212 }
kevman 2:7aab896b1a3b 213
kevman 2:7aab896b1a3b 214 for (int b = 0; b < TEST_BLOCK_COUNT; b++) {
kevman 2:7aab896b1a3b 215 basic_erase_program_read_test((*block_device), block_size, write_block, read_block, addrwidth);
kevman 2:7aab896b1a3b 216 }
kevman 2:7aab896b1a3b 217
kevman 2:7aab896b1a3b 218 end:
kevman 2:7aab896b1a3b 219 delete[] write_block;
kevman 2:7aab896b1a3b 220 delete[] read_block;
kevman 2:7aab896b1a3b 221 }
kevman 2:7aab896b1a3b 222
kevman 2:7aab896b1a3b 223 void test_spif_multi_threads()
kevman 2:7aab896b1a3b 224 {
kevman 2:7aab896b1a3b 225 utest_printf("\nTest Multi Threaded Erase/Program/Read Starts..\n");
kevman 2:7aab896b1a3b 226
kevman 2:7aab896b1a3b 227 SPIFBlockDevice block_device(MBED_CONF_SPIF_DRIVER_SPI_MOSI, MBED_CONF_SPIF_DRIVER_SPI_MISO,
kevman 2:7aab896b1a3b 228 MBED_CONF_SPIF_DRIVER_SPI_CLK,
kevman 2:7aab896b1a3b 229 MBED_CONF_SPIF_DRIVER_SPI_CS);
kevman 2:7aab896b1a3b 230
kevman 2:7aab896b1a3b 231 int err = block_device.init();
kevman 2:7aab896b1a3b 232 TEST_ASSERT_EQUAL(0, err);
kevman 2:7aab896b1a3b 233
kevman 2:7aab896b1a3b 234 for (unsigned atr = 0; atr < sizeof(ATTRS) / sizeof(ATTRS[0]); atr++) {
kevman 2:7aab896b1a3b 235 static const char *prefixes[] = {"", "k", "M", "G"};
kevman 2:7aab896b1a3b 236 for (int i_ind = 3; i_ind >= 0; i_ind--) {
kevman 2:7aab896b1a3b 237 bd_size_t size = (block_device.*ATTRS[atr].method)();
kevman 2:7aab896b1a3b 238 if (size >= (1ULL << 10 * i_ind)) {
kevman 2:7aab896b1a3b 239 utest_printf("%s: %llu%sbytes (%llubytes)\n",
kevman 2:7aab896b1a3b 240 ATTRS[atr].name, size >> 10 * i_ind, prefixes[i_ind], size);
kevman 2:7aab896b1a3b 241 break;
kevman 2:7aab896b1a3b 242 }
kevman 2:7aab896b1a3b 243 }
kevman 2:7aab896b1a3b 244 }
kevman 2:7aab896b1a3b 245
kevman 2:7aab896b1a3b 246 rtos::Thread spif_bd_thread[SPIF_TEST_NUM_OF_THREADS];
kevman 2:7aab896b1a3b 247
kevman 2:7aab896b1a3b 248 osStatus threadStatus;
kevman 2:7aab896b1a3b 249 int i_ind;
kevman 2:7aab896b1a3b 250
kevman 2:7aab896b1a3b 251 for (i_ind = 0; i_ind < SPIF_TEST_NUM_OF_THREADS; i_ind++) {
kevman 2:7aab896b1a3b 252 threadStatus = spif_bd_thread[i_ind].start(test_spif_thread_job, (void *)&block_device);
kevman 2:7aab896b1a3b 253 if (threadStatus != 0) {
kevman 2:7aab896b1a3b 254 utest_printf("\n Thread %d Start Failed!", i_ind + 1);
kevman 2:7aab896b1a3b 255 }
kevman 2:7aab896b1a3b 256 }
kevman 2:7aab896b1a3b 257
kevman 2:7aab896b1a3b 258 for (i_ind = 0; i_ind < SPIF_TEST_NUM_OF_THREADS; i_ind++) {
kevman 2:7aab896b1a3b 259 spif_bd_thread[i_ind].join();
kevman 2:7aab896b1a3b 260 }
kevman 2:7aab896b1a3b 261
kevman 2:7aab896b1a3b 262 err = block_device.deinit();
kevman 2:7aab896b1a3b 263 TEST_ASSERT_EQUAL(0, err);
kevman 2:7aab896b1a3b 264 }
kevman 2:7aab896b1a3b 265
kevman 2:7aab896b1a3b 266 // Test setup
kevman 2:7aab896b1a3b 267 utest::v1::status_t test_setup(const size_t number_of_cases)
kevman 2:7aab896b1a3b 268 {
kevman 2:7aab896b1a3b 269 GREENTEA_SETUP(60, "default_auto");
kevman 2:7aab896b1a3b 270 return verbose_test_setup_handler(number_of_cases);
kevman 2:7aab896b1a3b 271 }
kevman 2:7aab896b1a3b 272
kevman 2:7aab896b1a3b 273 Case cases[] = {
kevman 2:7aab896b1a3b 274 Case("Testing unaligned erase blocks", test_spif_unaligned_erase),
kevman 2:7aab896b1a3b 275 Case("Testing read write random blocks", test_spif_random_program_read_erase),
kevman 2:7aab896b1a3b 276 Case("Testing Multi Threads Erase Program Read", test_spif_multi_threads)
kevman 2:7aab896b1a3b 277 };
kevman 2:7aab896b1a3b 278
kevman 2:7aab896b1a3b 279 Specification specification(test_setup, cases);
kevman 2:7aab896b1a3b 280
kevman 2:7aab896b1a3b 281 int main()
kevman 2:7aab896b1a3b 282 {
kevman 2:7aab896b1a3b 283 mbed_trace_init();
kevman 2:7aab896b1a3b 284 utest_printf("MAIN STARTS\n");
kevman 2:7aab896b1a3b 285 return !Harness::run(specification);
kevman 2:7aab896b1a3b 286 }