13
13
* See the License for the specific language governing permissions and
14
14
* limitations under the License.
15
15
*/
16
+ #ifndef __STDC_FORMAT_MACROS
17
+ #define __STDC_FORMAT_MACROS // Required for PRIu64
18
+ #endif
16
19
17
20
#include " mbed.h"
18
21
#include " greentea-client/test_env.h"
19
22
#include " unity.h"
20
23
#include " utest.h"
21
24
#include " mbed_trace.h"
25
+ #include < inttypes.h>
22
26
#include < stdlib.h>
23
27
24
28
using namespace utest ::v1;
@@ -209,6 +213,137 @@ void test_multi_threads()
209
213
TEST_ASSERT_EQUAL (0 , err);
210
214
}
211
215
216
+ void test_contiguous_erase_write_read ()
217
+ {
218
+ utest_printf (" \n Test Contiguous Erase/Program/Read Starts..\n " );
219
+
220
+ // Test flow:
221
+ // 1. Erase whole test area
222
+ // - Tests contiguous erase
223
+ // 2. Write smaller memory area
224
+ // - Tests contiguous sector writes
225
+ // 3. Rerun step 2 for whole erase region
226
+
227
+ BlockDevice *block_device = BlockDevice::get_default_instance ();
228
+ TEST_SKIP_UNLESS_MESSAGE (block_device != NULL , " \n no block device found.\n " );
229
+
230
+ // Initialize BlockDevice
231
+ int err = block_device->init ();
232
+ TEST_ASSERT_EQUAL (0 , err);
233
+
234
+ // Test parameters
235
+ bd_size_t erase_size = block_device->get_erase_size ();
236
+ TEST_ASSERT (erase_size > 0 );
237
+ bd_size_t program_size = block_device->get_program_size ();
238
+ TEST_ASSERT (program_size > 0 );
239
+ utest_printf (" \n erase_size=%d" , erase_size);
240
+ utest_printf (" \n program_size=%d" , program_size);
241
+ utest_printf (" \n block_device->size()=%" PRId64, block_device->size ());
242
+
243
+ // Determine write/read buffer size
244
+ // start write_read_buf_size from 1% block_device->size()
245
+ bd_size_t write_read_buf_size = block_device->size () / 100 ; // 1%, 10k=100, 100k=1k, 1MB=10k, 32MB=32k
246
+ // try to limit write_read_buf_size to 10k. If program_size*2 is larger than 10k, that will be used instead.
247
+ if (write_read_buf_size > 10000 ) {
248
+ write_read_buf_size = 10000 ;
249
+ }
250
+ // 2 program_size blocks is minimum for contiguous write/read test
251
+ if (write_read_buf_size < program_size*2 ) {
252
+ write_read_buf_size = program_size*2 ; // going over 10k
253
+ }
254
+ bd_size_t contiguous_write_read_blocks_per_region = write_read_buf_size / program_size; // 2 is minimum to test contiguous write
255
+ write_read_buf_size = contiguous_write_read_blocks_per_region * program_size;
256
+ utest_printf (" \n contiguous_write_read_blocks_per_region=%" PRIu64, contiguous_write_read_blocks_per_region);
257
+ utest_printf (" \n write_read_buf_size=%" PRIu64, write_read_buf_size);
258
+
259
+ // Determine test region count
260
+ int contiguous_write_read_regions = TEST_BLOCK_COUNT;
261
+ utest_printf (" \n contiguous_write_read_regions=%d" , contiguous_write_read_regions);
262
+
263
+ // Determine whole erase size
264
+ bd_size_t contiguous_erase_size = write_read_buf_size * contiguous_write_read_regions;
265
+ contiguous_erase_size -= contiguous_erase_size % erase_size; // aligned to erase_size
266
+ contiguous_erase_size += erase_size; // but larger than write/read size * regions
267
+ utest_printf (" \n contiguous_erase_size=%" PRIu64, contiguous_erase_size);
268
+
269
+ // Determine starting address
270
+ bd_addr_t start_address = rand (); // low 32 bytes
271
+ start_address += (uint64_t )rand () << 32 ; // high 32 bytes
272
+ start_address %= block_device->size () - contiguous_erase_size - erase_size; // fit all data + alignment reserve
273
+ start_address += erase_size; // add alignment reserve
274
+ start_address -= start_address % erase_size; // align with erase_block
275
+ bd_addr_t stop_address = start_address + write_read_buf_size * contiguous_write_read_regions;
276
+ utest_printf (" \n start_address=0x%016" PRIx64, start_address);
277
+ utest_printf (" \n stop_address=0x%016" PRIx64, stop_address);
278
+
279
+ // Allocate write/read buffer
280
+ uint8_t *write_read_buf = (uint8_t *)malloc (write_read_buf_size);
281
+ if (write_read_buf == NULL ) {
282
+ block_device->deinit ();
283
+ TEST_SKIP_MESSAGE (" \n not enough memory for test" );
284
+ }
285
+ utest_printf (" \n write_read_buf_size=%" PRIu64 " " , (uint64_t )write_read_buf_size);
286
+
287
+ // Pre-fill the to-be-erased region. By pre-filling the region,
288
+ // we can be sure the test will not pass if the erase doesn't work.
289
+ for (bd_size_t offset=0 ; start_address+offset < stop_address; offset+=write_read_buf_size) {
290
+ for (size_t i=0 ; i<write_read_buf_size; i++) {
291
+ write_read_buf[i] = (uint8_t )rand ();
292
+ }
293
+ utest_printf (" \n pre-filling memory, from 0x%" PRIx64 " of size 0x%" PRIx64, start_address+offset, write_read_buf_size);
294
+ err = block_device->program ((const void *)write_read_buf, start_address+offset, write_read_buf_size);
295
+ TEST_ASSERT_EQUAL (0 , err);
296
+ }
297
+
298
+ // Erase the whole region first
299
+ utest_printf (" \n erasing memory, from 0x%" PRIx64 " of size 0x%" PRIx64, start_address, contiguous_erase_size);
300
+ err = block_device->erase (start_address, contiguous_erase_size);
301
+ TEST_ASSERT_EQUAL (0 , err);
302
+
303
+ // Loop through all write/read regions
304
+ int region = 0 ;
305
+ for (; start_address < stop_address; start_address+=write_read_buf_size) {
306
+ utest_printf (" \n\n region #%d start_address=0x%016" PRIx64, region++, start_address);
307
+
308
+ // Generate test data
309
+ unsigned int seed = rand ();
310
+ utest_printf (" \n generating test data, seed=%u" , seed);
311
+ srand (seed);
312
+ for (size_t i=0 ; i<write_read_buf_size; i++) {
313
+ write_read_buf[i] = (uint8_t )rand ();
314
+ }
315
+
316
+ // Write test data
317
+ utest_printf (" \n writing test data" );
318
+ err = block_device->program ((const void *)write_read_buf, start_address, write_read_buf_size);
319
+ TEST_ASSERT_EQUAL (0 , err);
320
+
321
+ // Read test data
322
+ memset (write_read_buf, 0 , (size_t )write_read_buf_size);
323
+ utest_printf (" \n reading test data" );
324
+ err = block_device->read (write_read_buf, start_address, write_read_buf_size);
325
+ TEST_ASSERT_EQUAL (0 , err);
326
+
327
+ // Verify read data
328
+ utest_printf (" \n verifying test data" );
329
+ srand (seed);
330
+ for (size_t i=0 ; i<write_read_buf_size; i++) {
331
+ uint8_t expected_value = (uint8_t )rand ();
332
+ if (write_read_buf[i] != expected_value) {
333
+ utest_printf (" \n data verify failed, write_read_buf[%d]=%" PRIu8 " and not %" PRIu8 " \n " ,
334
+ i, write_read_buf[i], expected_value);
335
+ }
336
+ TEST_ASSERT_EQUAL (write_read_buf[i], expected_value);
337
+ }
338
+ utest_printf (" \n verify OK" );
339
+ }
340
+
341
+ free (write_read_buf);
342
+
343
+ // BlockDevice deinitialization
344
+ err = block_device->deinit ();
345
+ TEST_ASSERT_EQUAL (0 , err);
346
+ }
212
347
213
348
// Test setup
214
349
utest::v1::status_t test_setup (const size_t number_of_cases)
@@ -219,7 +354,8 @@ utest::v1::status_t test_setup(const size_t number_of_cases)
219
354
220
355
Case cases[] = {
221
356
Case (" Testing read write random blocks" , test_random_program_read_erase),
222
- Case (" Testing Multi Threads Erase Program Read" , test_multi_threads)
357
+ Case (" Testing Multi Threads Erase Program Read" , test_multi_threads),
358
+ Case (" Testing contiguous erase, write and read" , test_contiguous_erase_write_read)
223
359
};
224
360
225
361
Specification specification (test_setup, cases);
0 commit comments