26
26
#include < stdlib.h>
27
27
#include " BufferedBlockDevice.h"
28
28
#include " BlockDevice.h"
29
+ #include < algorithm>
29
30
30
31
#if COMPONENT_SPIF
31
32
#include " SPIFBlockDevice.h"
47
48
#include " FlashIAPBlockDevice.h"
48
49
#endif
49
50
51
+ // Debug available
52
+ #ifndef MODE_DEBUG
53
+ #define MODE_DEBUG 0
54
+ #endif
55
+
56
+ #if MODE_DEBUG
57
+ #define DEBUG_PRINTF (...) printf(__VA_ARGS__)
58
+ #else
59
+ #define DEBUG_PRINTF (...)
60
+ #endif
61
+
50
62
using namespace utest ::v1;
51
63
52
64
#define TEST_BLOCK_COUNT 10
53
65
#define TEST_ERROR_MASK 16
54
66
#define TEST_NUM_OF_THREADS 5
55
67
#define TEST_THREAD_STACK_SIZE 1024
56
68
69
+ uint8_t num_of_sectors = TEST_NUM_OF_THREADS * TEST_BLOCK_COUNT;
70
+ uint32_t sectors_addr[TEST_NUM_OF_THREADS * TEST_BLOCK_COUNT] = {0 };
71
+
57
72
const struct {
58
73
const char *name;
59
74
bd_size_t (BlockDevice::*method)() const ;
@@ -194,13 +209,9 @@ void basic_erase_program_read_test(BlockDevice *block_device, bd_size_t block_si
194
209
srand (block_seed++);
195
210
196
211
// Find a random block
197
- int threaded_rand_number = (rand () * TEST_NUM_OF_THREADS) + thread_num;
198
- bd_addr_t block = (threaded_rand_number * block_size) % block_device->size ();
199
-
200
- // Flashiap boards with inconsistent sector size will not align with random start addresses
201
- if (bd_arr[test_iteration] == flashiap) {
202
- block = 0 ;
203
- }
212
+ bd_addr_t block = sectors_addr[thread_num];
213
+ bd_size_t curr_block_size = block_device->get_erase_size (block);
214
+ block_size = std::min (block_size, curr_block_size);
204
215
205
216
// Use next random number as temporary seed to keep
206
217
// the address progressing in the pseudorandom sequence
@@ -212,14 +223,9 @@ void basic_erase_program_read_test(BlockDevice *block_device, bd_size_t block_si
212
223
write_block[i_ind] = 0xff & rand ();
213
224
}
214
225
// Write, sync, and read the block
215
- utest_printf (" test %0*llx:%llu...\n " , addrwidth, block, block_size );
226
+ DEBUG_PRINTF (" test %0*llx:%llu...\n " , addrwidth, block, curr_block_size );
216
227
217
- // Thread test for flashiap write to the same sector, so all write/read/erase actions should be locked
218
- if (bd_arr[test_iteration] != flashiap) {
219
- _mutex->unlock ();
220
- }
221
-
222
- err = block_device->erase (block, block_size);
228
+ err = block_device->erase (block, curr_block_size);
223
229
TEST_ASSERT_EQUAL (0 , err);
224
230
225
231
err = block_device->program (write_block, block, block_size);
@@ -228,10 +234,6 @@ void basic_erase_program_read_test(BlockDevice *block_device, bd_size_t block_si
228
234
err = block_device->read (read_block, block, block_size);
229
235
TEST_ASSERT_EQUAL (0 , err);
230
236
231
- if (bd_arr[test_iteration] != flashiap) {
232
- _mutex->lock ();
233
- }
234
-
235
237
// Check that the data was unmodified
236
238
srand (seed);
237
239
int val_rand;
@@ -253,11 +255,19 @@ void test_init_bd()
253
255
utest_printf (" \n Test Init block device.\n " );
254
256
255
257
block_device = get_bd_instance (test_iteration);
256
-
257
258
TEST_SKIP_UNLESS_MESSAGE (block_device != NULL , " no block device found." );
258
259
259
260
int err = block_device->init ();
260
261
TEST_ASSERT_EQUAL (0 , err);
262
+
263
+ bd_addr_t start_address = 0 ;
264
+ uint8_t i = 0 ;
265
+ for (; i < num_of_sectors && start_address < block_device->size (); i++) {
266
+ sectors_addr[i] = start_address;
267
+ DEBUG_PRINTF (" start_address = 0x%llx, sector_size = %d\n " , start_address, block_device->get_erase_size (start_address));
268
+ start_address += block_device->get_erase_size (start_address);
269
+ }
270
+ num_of_sectors = i;
261
271
}
262
272
263
273
void test_random_program_read_erase ()
@@ -289,22 +299,23 @@ void test_random_program_read_erase()
289
299
goto end;
290
300
}
291
301
292
- for (int b = 0 ; b < TEST_BLOCK_COUNT; b++) {
293
- basic_erase_program_read_test (block_device, block_size, write_block, read_block, addrwidth, 0 );
302
+ for (int b = 0 ; b < std::min (( uint8_t ) TEST_BLOCK_COUNT, num_of_sectors) ; b++) {
303
+ basic_erase_program_read_test (block_device, block_size, write_block, read_block, addrwidth, b );
294
304
}
295
305
296
306
end:
297
- delete[] write_block;
298
307
delete[] read_block;
308
+ delete[] write_block;
299
309
}
300
310
301
- static void test_thread_job (void *block_device_ptr )
311
+ static void test_thread_job ()
302
312
{
303
313
static int thread_num = 0 ;
304
314
_mutex->lock ();
305
- int block_num = thread_num++;
315
+ int block_num = thread_num++ % TEST_NUM_OF_THREADS ;
306
316
_mutex->unlock ();
307
- BlockDevice *block_device = (BlockDevice *)block_device_ptr;
317
+
318
+ uint8_t sector_per_thread = (num_of_sectors / TEST_NUM_OF_THREADS);
308
319
309
320
bd_size_t block_size = block_device->get_erase_size ();
310
321
unsigned addrwidth = ceil (log (float (block_device->size () - 1 )) / log (float (16 ))) + 1 ;
@@ -317,13 +328,13 @@ static void test_thread_job(void *block_device_ptr)
317
328
goto end;
318
329
}
319
330
320
- for (int b = 0 ; b < TEST_BLOCK_COUNT ; b++) {
321
- basic_erase_program_read_test (block_device, block_size, write_block, read_block, addrwidth, block_num);
331
+ for (int b = 0 ; b < sector_per_thread ; b++) {
332
+ basic_erase_program_read_test (block_device, block_size, write_block, read_block, addrwidth, block_num * sector_per_thread + b );
322
333
}
323
334
324
335
end:
325
- delete[] write_block;
326
336
delete[] read_block;
337
+ delete[] write_block;
327
338
}
328
339
329
340
void test_multi_threads ()
@@ -363,7 +374,7 @@ void test_multi_threads()
363
374
}
364
375
delete[] dummy;
365
376
366
- threadStatus = bd_thread[i_ind]->start (callback (test_thread_job, ( void *)block_device ));
377
+ threadStatus = bd_thread[i_ind]->start (callback (test_thread_job));
367
378
if (threadStatus != 0 ) {
368
379
utest_printf (" Thread %d Start Failed!\n " , i_ind + 1 );
369
380
break ;
@@ -398,39 +409,29 @@ void test_erase_functionality()
398
409
399
410
// Check erase value
400
411
int erase_value_int = block_device->get_erase_value ();
401
- utest_printf (" block_device->get_erase_value()=%d\n " , erase_value_int);
402
412
TEST_SKIP_UNLESS_MESSAGE (erase_value_int >= 0 , " Erase not supported in this block device. Test skipped." );
403
413
404
414
// Assuming that get_erase_value() returns byte value as documentation mentions
405
415
// "If get_erase_value() returns a non-negative byte value" for unknown case.
406
416
TEST_ASSERT (erase_value_int <= 255 );
407
417
uint8_t erase_value = (uint8_t )erase_value_int;
408
418
409
- // Determine data_buf_size
410
- bd_size_t erase_size = block_device->get_erase_size ();
411
- TEST_ASSERT (erase_size > 0 );
412
- bd_size_t data_buf_size = erase_size;
413
-
414
419
// Determine start_address
415
- bd_addr_t start_address = rand (); // low 32 bytes
416
- start_address += (uint64_t )rand () << 32 ; // high 32 bytes
417
- start_address %= block_device->size () - data_buf_size - erase_size; // fit all data + alignment reserve
418
- start_address += erase_size; // add alignment reserve
419
- start_address -= start_address % erase_size; // align with erase_block
420
+ bd_addr_t start_address = sectors_addr[rand () % num_of_sectors];
420
421
utest_printf (" start_address=0x%016" PRIx64 " \n " , start_address);
421
422
422
- // Flashiap boards with inconsistent sector size will not align with random start addresses
423
- if (bd_arr[test_iteration] == flashiap) {
424
- start_address = 0 ;
425
- }
423
+ // Determine data_buf_size
424
+ bd_size_t erase_size = block_device-> get_erase_size (start_address);
425
+ TEST_ASSERT (erase_size > 0 ) ;
426
+ bd_size_t data_buf_size = erase_size;
426
427
427
428
// Allocate buffer for write test data
428
- uint8_t *data_buf = ( uint8_t *) malloc (data_buf_size) ;
429
- TEST_SKIP_UNLESS_MESSAGE (data_buf, " Not enough memory for test. \n " );
429
+ uint8_t *data_buf = new (std::nothrow) uint8_t [data_buf_size] ;
430
+ TEST_SKIP_UNLESS_MESSAGE (data_buf != NULL , " Not enough memory for test" );
430
431
431
432
// Allocate buffer for read test data
432
- uint8_t *out_data_buf = ( uint8_t *) malloc (data_buf_size) ;
433
- TEST_SKIP_UNLESS_MESSAGE (out_data_buf, " Not enough memory for test. \n " );
433
+ uint8_t *out_data_buf = new (std::nothrow) uint8_t [data_buf_size] ;
434
+ TEST_SKIP_UNLESS_MESSAGE (out_data_buf != NULL , " Not enough memory for test" );
434
435
435
436
// First must Erase given memory region
436
437
utest_printf (" erasing given memory region\n " );
@@ -476,8 +477,8 @@ void test_erase_functionality()
476
477
TEST_ASSERT_EQUAL (erase_value, out_data_buf[i]);
477
478
}
478
479
479
- free (data_buf) ;
480
- free (out_data_buf) ;
480
+ delete[] out_data_buf ;
481
+ delete[] data_buf ;
481
482
}
482
483
483
484
void test_contiguous_erase_write_read ()
@@ -486,11 +487,6 @@ void test_contiguous_erase_write_read()
486
487
487
488
TEST_SKIP_UNLESS_MESSAGE (block_device != NULL , " no block device found." );
488
489
489
- // Flashiap boards with inconsistent sector size will not align with random start addresses
490
- if (bd_arr[test_iteration] == flashiap) {
491
- return ;
492
- }
493
-
494
490
// Test flow:
495
491
// 1. Erase whole test area
496
492
// - Tests contiguous erase
@@ -499,57 +495,30 @@ void test_contiguous_erase_write_read()
499
495
// 3. Return step 2 for whole erase region
500
496
501
497
// Test parameters
502
- bd_size_t erase_size = block_device->get_erase_size ();
503
- TEST_ASSERT (erase_size > 0 );
504
498
bd_size_t program_size = block_device->get_program_size ();
505
499
TEST_ASSERT (program_size > 0 );
506
- utest_printf (" erase_size=%" PRId64 " \n " , erase_size);
507
500
utest_printf (" program_size=%" PRId64 " \n " , program_size);
508
501
utest_printf (" block_device->size()=%" PRId64 " \n " , block_device->size ());
509
502
510
- // Determine write/read buffer size
511
- // start write_read_buf_size from 1% block_device->size()
512
- bd_size_t write_read_buf_size = block_device->size () / 100 ; // 1%, 10k=100, 100k=1k, 1MB=10k, 32MB=32k
513
- // try to limit write_read_buf_size to 10k. If program_size*2 is larger than 10k, that will be used instead.
514
- if (write_read_buf_size > 10000 ) {
515
- write_read_buf_size = 10000 ;
516
- }
517
- // 2 program_size blocks is minimum for contiguous write/read test
518
- if (write_read_buf_size < program_size * 2 ) {
519
- write_read_buf_size = program_size * 2 ; // going over 10k
520
- }
521
- bd_size_t contiguous_write_read_blocks_per_region = write_read_buf_size /
522
- program_size; // 2 is minimum to test contiguous write
523
- write_read_buf_size = contiguous_write_read_blocks_per_region * program_size;
524
- utest_printf (" contiguous_write_read_blocks_per_region=%" PRIu64 " \n " , contiguous_write_read_blocks_per_region);
525
- utest_printf (" write_read_buf_size=%" PRIu64 " \n " , write_read_buf_size);
526
-
527
- // Determine test region count
528
- int contiguous_write_read_regions = TEST_BLOCK_COUNT;
529
- utest_printf (" contiguous_write_read_regions=%d\n " , contiguous_write_read_regions);
530
-
531
- // Determine whole erase size
532
- bd_size_t contiguous_erase_size = write_read_buf_size * contiguous_write_read_regions;
533
- contiguous_erase_size -= contiguous_erase_size % erase_size; // aligned to erase_size
534
- contiguous_erase_size += erase_size; // but larger than write/read size * regions
535
- utest_printf (" contiguous_erase_size=%" PRIu64 " \n " , contiguous_erase_size);
536
-
537
- // Determine starting address
538
- bd_addr_t start_address = rand (); // low 32 bytes
539
- start_address += (uint64_t )rand () << 32 ; // high 32 bytes
540
- start_address %= block_device->size () - contiguous_erase_size - erase_size; // fit all data + alignment reserve
541
- start_address += erase_size; // add alignment reserve
542
- start_address -= start_address % erase_size; // align with erase_block
543
- bd_addr_t stop_address = start_address + write_read_buf_size * contiguous_write_read_regions;
503
+ // Determine start_address & stop_address
504
+ uint8_t sector_num = rand () % (num_of_sectors - 2 );
505
+ bd_addr_t start_address = sectors_addr[sector_num];
506
+ bd_addr_t stop_address = sectors_addr[sector_num + 2 ];
544
507
utest_printf (" start_address=0x%016" PRIx64 " \n " , start_address);
545
508
utest_printf (" stop_address=0x%016" PRIx64 " \n " , stop_address);
546
509
547
- // Allocate write/read buffer
548
- uint8_t *write_read_buf = (uint8_t *)malloc (write_read_buf_size);
549
- if (write_read_buf == NULL ) {
550
- TEST_SKIP_MESSAGE (" not enough memory for test" );
510
+ bd_size_t contiguous_erase_size = stop_address - start_address;
511
+ TEST_ASSERT (contiguous_erase_size > 0 );
512
+ utest_printf (" contiguous_erase_size=%d\n " , contiguous_erase_size);
513
+
514
+ bd_size_t write_read_buf_size = program_size;
515
+ if (contiguous_erase_size / program_size > 8 && contiguous_erase_size % (program_size * 8 ) == 0 ) {
516
+ write_read_buf_size = program_size * 8 ;
551
517
}
552
- utest_printf (" write_read_buf_size=%" PRIu64 " \n " , (uint64_t )write_read_buf_size);
518
+
519
+ // Allocate write/read buffer
520
+ uint8_t *write_read_buf = new (std::nothrow) uint8_t [write_read_buf_size];
521
+ TEST_SKIP_UNLESS_MESSAGE (contiguous_erase_size, " Not enough memory for test.\n " );
553
522
554
523
// Must Erase the whole region first
555
524
utest_printf (" erasing memory, from 0x%" PRIx64 " of size 0x%" PRIx64 " \n " , start_address, contiguous_erase_size);
@@ -562,7 +531,7 @@ void test_contiguous_erase_write_read()
562
531
for (size_t i = 0 ; i < write_read_buf_size; i++) {
563
532
write_read_buf[i] = (uint8_t )rand ();
564
533
}
565
- utest_printf (" pre-filling memory, from 0x%" PRIx64 " of size 0x%" PRIx64 " \n " , start_address + offset,
534
+ DEBUG_PRINTF (" pre-filling memory, from 0x%" PRIx64 " of size 0x%" PRIx64 " " , start_address + offset,
566
535
write_read_buf_size);
567
536
err = block_device->program ((const void *)write_read_buf, start_address + offset, write_read_buf_size);
568
537
TEST_ASSERT_EQUAL (0 , err);
@@ -576,29 +545,24 @@ void test_contiguous_erase_write_read()
576
545
// Loop through all write/read regions
577
546
int region = 0 ;
578
547
for (; start_address < stop_address; start_address += write_read_buf_size) {
579
- utest_printf (" \n region #%d start_address=0x%016" PRIx64 " \n " , region++, start_address);
580
548
581
549
// Generate test data
582
550
unsigned int seed = rand ();
583
- utest_printf (" generating test data, seed=%u\n " , seed);
584
551
srand (seed);
585
552
for (size_t i = 0 ; i < write_read_buf_size; i++) {
586
553
write_read_buf[i] = (uint8_t )rand ();
587
554
}
588
555
589
556
// Write test data
590
- utest_printf (" writing test data\n " );
591
557
err = block_device->program ((const void *)write_read_buf, start_address, write_read_buf_size);
592
558
TEST_ASSERT_EQUAL (0 , err);
593
559
594
560
// Read test data
595
561
memset (write_read_buf, 0 , (size_t )write_read_buf_size);
596
- utest_printf (" reading test data\n " );
597
562
err = block_device->read (write_read_buf, start_address, write_read_buf_size);
598
563
TEST_ASSERT_EQUAL (0 , err);
599
564
600
565
// Verify read data
601
- utest_printf (" verifying test data\n " );
602
566
srand (seed);
603
567
for (size_t i = 0 ; i < write_read_buf_size; i++) {
604
568
uint8_t expected_value = (uint8_t )rand ();
@@ -608,7 +572,6 @@ void test_contiguous_erase_write_read()
608
572
}
609
573
TEST_ASSERT_EQUAL (write_read_buf[i], expected_value);
610
574
}
611
- utest_printf (" verify OK\n " );
612
575
}
613
576
614
577
free (write_read_buf);
0 commit comments