From f9da8072d4fb33c3eebb8256f2f186e10a9a89a0 Mon Sep 17 00:00:00 2001 From: David Saada Date: Tue, 23 Jan 2018 18:01:13 -0600 Subject: [PATCH] Refactor NVStore code, following PR comments: - Add missing documentation in shared_lock and flash wrapper include files. - Fix include files (correctness and order). - Move configuration of addresses and sizes from targets.json to mbed_lib.json. - Change function parameters from pointers to references. - Remove unnecessary NVSTORE_THREAD_SAFE and NVSTORE_PROBE_ONLY defines. --- .../TESTS/nvstore/functionality/main.cpp | 136 +++++++--------- features/nvstore/mbed_lib.json | 46 +++++- features/nvstore/source/nvstore.cpp | 149 +++++++----------- features/nvstore/source/nvstore.h | 48 +++--- .../source/nvstore_int_flash_wrapper.cpp | 32 +--- .../source/nvstore_int_flash_wrapper.h | 71 +++++++-- .../nvstore/source/nvstore_shared_lock.cpp | 30 +--- features/nvstore/source/nvstore_shared_lock.h | 42 ++++- targets/targets.json | 4 +- 9 files changed, 295 insertions(+), 263 deletions(-) diff --git a/features/nvstore/TESTS/nvstore/functionality/main.cpp b/features/nvstore/TESTS/nvstore/functionality/main.cpp index f16949869c2..92bfa304c9c 100644 --- a/features/nvstore/TESTS/nvstore/functionality/main.cpp +++ b/features/nvstore/TESTS/nvstore/functionality/main.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016 ARM Limited. All rights reserved. +* Copyright (c) 2018 ARM Limited. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -16,25 +16,21 @@ #include "nvstore.h" #include "nvstore_int_flash_wrapper.h" +#include "nvstore_shared_lock.h" +#include "thread.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest/utest.h" #include #include #include -#include "../../../source/nvstore_shared_lock.h" -#include "cmsis_os2.h" -#include "rtos/thread.h" - -#include "mbed.h" -#include "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest/utest.h" +#ifndef NVSTORE_ENABLED +#error [NOT_SUPPORTED] NVSTORE needs to be enabled for this test +#endif using namespace utest::v1; -#ifndef NVSTORE_THREAD_SAFE -#define NVSTORE_THREAD_SAFE 1 -#endif - #undef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) @@ -157,10 +153,9 @@ void nvstore_basic_functionality_test() gen_random((uint8_t *) nvstore_testing_buf_set, NVSTORE_MAX_NAME_LENGTH); - result = nvstore.probe(MAX_KEYS, 0, NULL, &actual_len_bytes); + result = nvstore.probe(MAX_KEYS, 0, NULL, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_NOT_FOUND, result); -#if !SOTP_PROBE_ONLY nvstore.set_max_keys(MAX_KEYS); TEST_ASSERT_EQUAL(MAX_KEYS, nvstore.get_max_keys()); @@ -170,13 +165,13 @@ void nvstore_basic_functionality_test() result = nvstore.set(5, 18, nvstore_testing_buf_set); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); - result = nvstore.get(5, 22, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(5, 22, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(18, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)nvstore_testing_buf_set, (uint8_t*)nvstore_testing_buf_get, 15); result = nvstore.remove(5); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); - result = nvstore.get(5, 20, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(5, 20, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_NOT_FOUND, result); result = nvstore.set(11, 0, NULL); @@ -206,108 +201,108 @@ void nvstore_basic_functionality_test() result = nvstore.init(); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); - result = nvstore.get(14, 20, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(14, 20, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_NOT_FOUND, result); - result = nvstore.get(7, 0, NULL, &actual_len_bytes); + result = nvstore.get(7, 0, NULL, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(0, actual_len_bytes); - result = nvstore.get(7, 15, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(7, 15, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(0, actual_len_bytes); - result = nvstore.get(7, 0, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(7, 0, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(0, actual_len_bytes); - result = nvstore.get(9, 0, NULL, &actual_len_bytes); + result = nvstore.get(9, 0, NULL, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_BUFF_TOO_SMALL, result); - result = nvstore.get(9, 150, NULL, &actual_len_bytes); + result = nvstore.get(9, 150, NULL, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_BUFF_TOO_SMALL, result); - result = nvstore.get(9, 0, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(9, 0, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_BUFF_TOO_SMALL, result); - result = nvstore.get(10, 2048, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(10, 2048, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(2048, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)nvstore_testing_buf_set, (uint8_t*)nvstore_testing_buf_get, 2048); zero_get_array(2048); - result = nvstore.get(10, 2049, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(10, 2049, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(2048, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)nvstore_testing_buf_set, (uint8_t*)nvstore_testing_buf_get, 2048); zero_get_array(2048); - result = nvstore.get(10, 2047, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(10, 2047, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_BUFF_TOO_SMALL, result); actual_len_bytes = 0; - result = nvstore.get(64, 20, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(64, 20, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_BAD_VALUE, result); - result = nvstore.get(9, 20, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(9, 20, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(20, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[3]), (uint8_t*)nvstore_testing_buf_get, 20); zero_get_array(20); - result = nvstore.get(9, 21, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(9, 21, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(20, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[3]), (uint8_t*)nvstore_testing_buf_get, 20); zero_get_array(20); - result = nvstore.get(9, 19, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(9, 19, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_BUFF_TOO_SMALL, result); - result = nvstore.get(13, 3, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(13, 3, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(3, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[1]), (uint8_t*)nvstore_testing_buf_get, 3); - result = nvstore.get_item_size(13, &actual_len_bytes); + result = nvstore.get_item_size(13, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(3, actual_len_bytes); zero_get_array(3); - result = nvstore.get(13, 4, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(13, 4, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(3, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[1]), (uint8_t*)nvstore_testing_buf_get, 3); zero_get_array(3); - result = nvstore.get(13, 2, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(13, 2, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_BUFF_TOO_SMALL, result); result = nvstore.init(); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); // check all the expected keys actual_len_bytes = 0; - result = nvstore.get(10, 2048, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(10, 2048, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(2048, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)nvstore_testing_buf_set, (uint8_t*)nvstore_testing_buf_get, 2048); zero_get_array(2048); actual_len_bytes = 0; - result = nvstore.get(11, 2048, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(11, 2048, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(0, actual_len_bytes); actual_len_bytes = 0; - result = nvstore.get(13, 3, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(13, 3, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(3, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[1]), (uint8_t*)nvstore_testing_buf_get, 3); zero_get_array(3); actual_len_bytes = 0; - result = nvstore.get(9, 20, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(9, 20, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(20, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[3]), (uint8_t*)nvstore_testing_buf_get, 20); zero_get_array(20); actual_len_bytes = 0; - result = nvstore.get(7, 0, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(7, 0, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(0, actual_len_bytes); actual_len_bytes = 0; - result = nvstore.get(15, 15, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(15, 15, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(15, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[2]), (uint8_t*)nvstore_testing_buf_get, 15); zero_get_array(15); actual_len_bytes = 0; - result = nvstore.get(19, 12, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(19, 12, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(12, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[2]), (uint8_t*)nvstore_testing_buf_get, 12); @@ -335,47 +330,47 @@ void nvstore_basic_functionality_test() #endif actual_len_bytes = 0; - result = nvstore.get(10, 15, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(10, 15, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(15, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[4]), (uint8_t*)nvstore_testing_buf_get, 15); zero_get_array(15); actual_len_bytes = 0; - result = nvstore.get(11, 27, nvstore_testing_buf_get, &actual_len_bytes); // no care about the buf and len values + result = nvstore.get(11, 27, nvstore_testing_buf_get, actual_len_bytes); // no care about the buf and len values TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(27, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[5]), (uint8_t*)nvstore_testing_buf_get, 27); zero_get_array(27); actual_len_bytes = 0; - result = nvstore.get(13, 7, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(13, 7, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(7, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[6]), (uint8_t*)nvstore_testing_buf_get, 7); zero_get_array(7); actual_len_bytes = 0; - result = nvstore.get(9, 0, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(9, 0, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(0, actual_len_bytes); actual_len_bytes = 0; - result = nvstore.get(7, 48, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(7, 48, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(48, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[8]), (uint8_t*)nvstore_testing_buf_get, 48); zero_get_array(48); actual_len_bytes = 0; - result = nvstore.get(14, 109, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(14, 109, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(109, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[9]), (uint8_t*)nvstore_testing_buf_get, 109); zero_get_array(109); actual_len_bytes = 0; - result = nvstore.get(15, 53, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(15, 53, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(53, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[10]), (uint8_t*)nvstore_testing_buf_get, 53); @@ -385,7 +380,7 @@ void nvstore_basic_functionality_test() TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); actual_len_bytes = 0; - result = nvstore.probe(10, 15, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.probe(10, 15, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(15, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[4]), (uint8_t*)nvstore_testing_buf_get, 15); @@ -394,59 +389,58 @@ void nvstore_basic_functionality_test() TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); actual_len_bytes = 0; - result = nvstore.get(10, 15, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(10, 15, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(15, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[4]), (uint8_t*)nvstore_testing_buf_get, 15); zero_get_array(15); actual_len_bytes = 0; - result = nvstore.get(11, 27, nvstore_testing_buf_get, &actual_len_bytes); // no care about the buf and len values + result = nvstore.get(11, 27, nvstore_testing_buf_get, actual_len_bytes); // no care about the buf and len values TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(27, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[5]), (uint8_t*)nvstore_testing_buf_get, 27); zero_get_array(27); actual_len_bytes = 0; - result = nvstore.get(13, 7, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(13, 7, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(7, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[6]), (uint8_t*)nvstore_testing_buf_get, 7); zero_get_array(7); actual_len_bytes = 0; - result = nvstore.get(9, 0, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(9, 0, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(0, actual_len_bytes); actual_len_bytes = 0; - result = nvstore.get(7, 48, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(7, 48, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(48, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[8]), (uint8_t*)nvstore_testing_buf_get, 48); zero_get_array(48); actual_len_bytes = 0; - result = nvstore.get(14, 109, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(14, 109, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(109, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[9]), (uint8_t*)nvstore_testing_buf_get, 109); zero_get_array(109); actual_len_bytes = 0; - result = nvstore.get(15, 53, nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(15, 53, nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(53, actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)&(nvstore_testing_buf_set[10]), (uint8_t*)nvstore_testing_buf_get, 53); zero_get_array(53); -#endif // !PROBE_ONLY + nvstore_int_flash_deinit(); } void nvstore_chunk_iterations_test() { -#if !SOTP_PROBE_ONLY nvstore_int_flash_init(); uint32_t *data_array[MAX_KEYS]; @@ -479,7 +473,7 @@ void nvstore_chunk_iterations_test() { if (data_size_array[i] != 0) { - result = nvstore.get(i, data_size_array[i], nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(i, data_size_array[i], nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(data_size_array[i], actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)(data_array[i]), (uint8_t*)nvstore_testing_buf_get, data_size_array[i]); @@ -492,14 +486,12 @@ void nvstore_chunk_iterations_test() free(data_array[i]); } nvstore_int_flash_deinit(); -#endif // !PROBE_ONLY } void nvstore_garbage_collection_test() { -#if !SOTP_PROBE_ONLY nvstore_int_flash_init(); uint32_t nvstore_curr_size = MASTER_RECORD_SIZE; @@ -529,7 +521,7 @@ void nvstore_garbage_collection_test() result = nvstore.set(key, data_size, data_array[key]); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); data_size_array[key] = data_size; - result = nvstore.get(key, data_size_array[key], nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(key, data_size_array[key], nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(data_size_array[key], actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)(data_array[key]), (uint8_t*)nvstore_testing_buf_get, data_size_array[key]); @@ -540,7 +532,7 @@ void nvstore_garbage_collection_test() { if (data_size_array[i] != 0) { - result = nvstore.get(i, data_size_array[i], nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(i, data_size_array[i], nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(data_size_array[i], actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)(data_array[i]), (uint8_t*)nvstore_testing_buf_get, data_size_array[i]); @@ -556,7 +548,7 @@ void nvstore_garbage_collection_test() { if (data_size_array[i] != 0) { - result = nvstore.get(i, data_size_array[i], nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(i, data_size_array[i], nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(data_size_array[i], actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)(data_array[i]), (uint8_t*)nvstore_testing_buf_get, data_size_array[i]); @@ -570,7 +562,7 @@ void nvstore_garbage_collection_test() { if (data_size_array[i] != 0) { - result = nvstore.get(i, data_size_array[i], nvstore_testing_buf_get, &actual_len_bytes); + result = nvstore.get(i, data_size_array[i], nvstore_testing_buf_get, actual_len_bytes); TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result); TEST_ASSERT_EQUAL(data_size_array[i], actual_len_bytes); TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t*)(data_array[i]), (uint8_t*)nvstore_testing_buf_get, data_size_array[i]); @@ -583,12 +575,10 @@ void nvstore_garbage_collection_test() } nvstore_int_flash_deinit(); -#endif // !PROBE_ONLY } static void thread_test_check_key(uint16_t key, int check_probe) { -#if !SOTP_PROBE_ONLY uint32_t get_buff[MAX_DATA_SIZE/sizeof(uint32_t)]; int ret; uint16_t actual_len_bytes; @@ -596,10 +586,10 @@ static void thread_test_check_key(uint16_t key, int check_probe) NVStore &nvstore = NVStore::get_instance(); if (check_probe) { - ret = nvstore.probe(key, MAX_DATA_SIZE, get_buff, &actual_len_bytes); + ret = nvstore.probe(key, MAX_DATA_SIZE, get_buff, actual_len_bytes); } else { - ret = nvstore.get(key, MAX_DATA_SIZE, get_buff, &actual_len_bytes); + ret = nvstore.get(key, MAX_DATA_SIZE, get_buff, actual_len_bytes); } TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, ret); TEST_ASSERT_NOT_EQUAL(0, actual_len_bytes); @@ -629,7 +619,6 @@ static void thread_test_check_key(uint16_t key, int check_probe) // Got here - always assert TEST_ASSERT(0); -#endif // !PROBE_ONLY } void thread_test_worker() @@ -660,8 +649,6 @@ void thread_test_worker() static void run_thread_test(int num_threads) { -#if !SOTP_PROBE_ONLY - int i; uint16_t size, max_size; uint16_t key; @@ -725,7 +712,6 @@ static void run_thread_test(int num_threads) } } nvstore_int_flash_deinit(); -#endif // !PROBE_ONLY } @@ -751,9 +737,7 @@ Case cases[] = { Case("NVStore: Chunk iterations", nvstore_chunk_iterations_test, greentea_failure_handler), Case("NVStore: Garbage collection" , nvstore_garbage_collection_test, greentea_failure_handler), Case("NVStore: Single thread test", nvstore_single_thread_test, greentea_failure_handler), -#if NVSTORE_THREAD_SAFE Case("NVStore: Multiple thread test", nvstore_multi_thread_test, greentea_failure_handler), -#endif }; utest::v1::status_t greentea_test_setup(const size_t number_of_cases) { diff --git a/features/nvstore/mbed_lib.json b/features/nvstore/mbed_lib.json index 11f9e9da2d8..587a0a51004 100644 --- a/features/nvstore/mbed_lib.json +++ b/features/nvstore/mbed_lib.json @@ -1,10 +1,40 @@ { - "name": "nvstore", - "config": { - "num_types": { - "macro_name": "NVSTORE_MAX_KEYS", - "value": 16, - "help": "Maximal number of allowed NVStore keys" - } - } + "name": "nvstore", + "config": { + "num_types": { + "macro_name": "NVSTORE_MAX_KEYS", + "value": 16, + "help": "Maximal number of allowed NVStore keys" + }, + "area_1_address": { + "macro_name": "NVSTORE_AREA_1_ADDRESS", + "help": "Area 1 address" + }, + "area_1_size": { + "macro_name": "NVSTORE_AREA_1_SIZE", + "help": "Area 1 size" + }, + "area_2_address": { + "macro_name": "NVSTORE_AREA_2_ADDRESS", + "help": "Area 2 address" + }, + "area_2_size": { + "macro_name": "NVSTORE_AREA_2_SIZE", + "help": "Area 2 size" + } + }, + "target_overrides": { + "K64F": { + "area_1_address": "0xFE000", + "area_1_size" : "0x1000", + "area_2_address": "0xFF000", + "area_2_size" : "0x1000" + }, + "K82F": { + "area_1_address": "0x3E000", + "area_1_size" : "0x1000", + "area_2_address": "0x3F000", + "area_2_size" : "0x1000" + } + } } diff --git a/features/nvstore/source/nvstore.cpp b/features/nvstore/source/nvstore.cpp index 4f0b94d0f53..5ca8c81db60 100644 --- a/features/nvstore/source/nvstore.cpp +++ b/features/nvstore/source/nvstore.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 ARM Limited. All rights reserved. + * Copyright (c) 2018 ARM Limited. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -17,14 +17,15 @@ // ----------------------------------------------------------- Includes ----------------------------------------------------------- #include "nvstore.h" - +#include "nvstore_int_flash_wrapper.h" +#include "nvstore_shared_lock.h" #include "mbed_critical.h" #include "mbed_assert.h" -#include "nvstore_int_flash_wrapper.h" +#include "thread.h" #include #include -#include -#include "nvstore_shared_lock.h" + +#if NVSTORE_ENABLED // --------------------------------------------------------- Definitions ---------------------------------------------------------- @@ -75,22 +76,6 @@ typedef struct size_t size; } nvstore_area_data_t; -#ifndef NVSTORE_AREA_1_ADDRESS -#error NVSTORE_AREA_1_ADDRESS needs to be defined -#endif - -#ifndef NVSTORE_AREA_1_SIZE -#error NVSTORE_AREA_1_SIZE needs to be defined -#endif - -#ifndef NVSTORE_AREA_2_ADDRESS -#error NVSTORE_AREA_2_ADDRESS needs to be defined -#endif - -#ifndef NVSTORE_AREA_2_SIZE -#error NVSTORE_AREA_2_ADDRESS needs to be defined -#endif - const nvstore_area_data_t flash_area_params[] = { {NVSTORE_AREA_1_ADDRESS, NVSTORE_AREA_1_SIZE}, @@ -105,10 +90,6 @@ typedef enum { #define INITIAL_CRC 0xFFFFFFFF -#ifndef NVSTORE_THREAD_SAFE -#define NVSTORE_THREAD_SAFE 1 -#endif - // -------------------------------------------------- Local Functions Declaration ---------------------------------------------------- // -------------------------------------------------- Functions Implementation ---------------------------------------------------- @@ -118,14 +99,9 @@ typedef enum { // value - [IN] Pointer to variable. // size - [IN] Increment. // Return : Value after increment. -int32_t safe_increment(uint32_t* value, uint32_t increment) +int32_t safe_increment(uint32_t &value, uint32_t increment) { -#if NVSTORE_THREAD_SAFE - return core_util_atomic_incr_u32(value, increment); -#else - *value += increment; - return *value; -#endif + return core_util_atomic_incr_u32(&value, increment); } // Check whether a buffer is aligned. @@ -237,23 +213,23 @@ int NVStore::flash_erase_area(uint8_t area) // area - [IN] Flash area. // offset - [OUT] Blank chunk offset. // Return : 0 on success. Error code otherwise. -int NVStore::calc_empty_space(uint8_t area, uint32_t *offset) +int NVStore::calc_empty_space(uint8_t area, uint32_t &offset) { uint32_t buf[32]; uint8_t *chbuf; uint32_t i, j; int ret; - *offset = _size; + offset = _size; for (i = 0; i < _size / sizeof(buf); i++) { - *offset -= sizeof(buf); - ret = flash_read_area(area, *offset, sizeof(buf), buf); + offset -= sizeof(buf); + ret = flash_read_area(area, offset, sizeof(buf), buf); if (ret) return ret; chbuf = (uint8_t *) buf; for (j = sizeof(buf); j > 0; j--) { if (chbuf[j-1] != NVSTORE_BLANK_FLASH_VAL) { - *offset += j; + offset += j; return 0; } } @@ -276,8 +252,8 @@ int NVStore::calc_empty_space(uint8_t area, uint32_t *offset) // next_offset - [Out] If valid, offset of next record. // Return : NVSTORE_SUCCESS on success. Error code otherwise. int NVStore::read_record(uint8_t area, uint32_t offset, uint16_t buf_len_bytes, uint32_t *buf, - uint16_t *actual_len_bytes, int validate_only, int *valid, - uint16_t *key, uint16_t *flags, uint32_t *next_offset) + uint16_t &actual_len_bytes, int validate_only, int &valid, + uint16_t &key, uint16_t &flags, uint32_t &next_offset) { uint32_t int_buf[32]; uint32_t *buf_ptr; @@ -286,7 +262,7 @@ int NVStore::read_record(uint8_t area, uint32_t offset, uint16_t buf_len_bytes, record_header_t header; uint32_t crc = INITIAL_CRC; - *valid = 1; + valid = 1; os_ret = flash_read_area(area, offset, sizeof(header), (uint32_t *) &header); if (os_ret) { @@ -295,12 +271,12 @@ int NVStore::read_record(uint8_t area, uint32_t offset, uint16_t buf_len_bytes, crc = crc32(crc, sizeof(header) - sizeof(header.mac), (uint8_t *) &header); - *actual_len_bytes = 0; - *key = header.key_and_flags & ~HEADER_FLAG_MASK; - *flags = header.key_and_flags & HEADER_FLAG_MASK; + actual_len_bytes = 0; + key = header.key_and_flags & ~HEADER_FLAG_MASK; + flags = header.key_and_flags & HEADER_FLAG_MASK; - if ((*key >= _max_keys) && (*key != MASTER_RECORD_KEY)) { - *valid = 0; + if ((key >= _max_keys) && (key != MASTER_RECORD_KEY)) { + valid = 0; return NVSTORE_SUCCESS; } @@ -317,8 +293,8 @@ int NVStore::read_record(uint8_t area, uint32_t offset, uint16_t buf_len_bytes, else { if (data_len > buf_len_bytes) { offset += data_len; - *actual_len_bytes = data_len; - *next_offset = align_up(offset, FLASH_MINIMAL_PROG_UNIT); + actual_len_bytes = data_len; + next_offset = align_up(offset, FLASH_MINIMAL_PROG_UNIT); return NVSTORE_BUFF_TOO_SMALL; } buf_ptr = buf; @@ -336,18 +312,16 @@ int NVStore::read_record(uint8_t area, uint32_t offset, uint16_t buf_len_bytes, } if (header.mac != crc) { - *valid = 0; + valid = 0; return NVSTORE_SUCCESS; } - *actual_len_bytes = header.length; - *next_offset = align_up(offset, FLASH_MINIMAL_PROG_UNIT); + actual_len_bytes = header.length; + next_offset = align_up(offset, FLASH_MINIMAL_PROG_UNIT); return NVSTORE_SUCCESS; } -#if !NVSTORE_PROBE_ONLY - // Write a record in a given area and offset. // Parameters : // area - [IN] Flash area. @@ -359,7 +333,7 @@ int NVStore::read_record(uint8_t area, uint32_t offset, uint16_t buf_len_bytes, // next_offset - [Out] offset of next record. // Return : NVSTORE_SUCCESS on success. Error code otherwise. int NVStore::write_record(uint8_t area, uint32_t offset, uint16_t key, uint16_t flags, - uint32_t data_len, const uint32_t *data_buf, uint32_t *next_offset) + uint32_t data_len, const uint32_t *data_buf, uint32_t &next_offset) { record_header_t header; uint32_t crc = INITIAL_CRC; @@ -389,7 +363,7 @@ int NVStore::write_record(uint8_t area, uint32_t offset, uint16_t key, uint16_t offset += data_len; } - *next_offset = align_up(offset, FLASH_MINIMAL_PROG_UNIT); + next_offset = align_up(offset, FLASH_MINIMAL_PROG_UNIT); return NVSTORE_SUCCESS; } @@ -399,7 +373,7 @@ int NVStore::write_record(uint8_t area, uint32_t offset, uint16_t key, uint16_t // version - [IN] Version. // next_offset - [Out] offset of next record. // Return : NVSTORE_SUCCESS on success. Error code otherwise. -int NVStore::write_master_record(uint8_t area, uint16_t version, uint32_t *next_offset) +int NVStore::write_master_record(uint8_t area, uint16_t version, uint32_t &next_offset) { master_record_data_t master_rec; @@ -418,7 +392,7 @@ int NVStore::write_master_record(uint8_t area, uint16_t version, uint32_t *next_ // next_offset - [Out] Offset of next record in the new area. // Return : NVSTORE_SUCCESS on success. Error code otherwise. int NVStore::copy_record(uint8_t from_area, uint32_t from_offset, uint32_t to_offset, - uint32_t *next_offset) + uint32_t &next_offset) { uint32_t int_buf[32]; uint32_t data_len, chunk_len; @@ -436,7 +410,7 @@ int NVStore::copy_record(uint8_t from_area, uint32_t from_offset, uint32_t to_of // No need to copy records whose flags indicate deletion if (header.key_and_flags & DELETE_ITEM_FLAG) { - *next_offset = align_up(to_offset, FLASH_MINIMAL_PROG_UNIT); + next_offset = align_up(to_offset, FLASH_MINIMAL_PROG_UNIT); return NVSTORE_SUCCESS; } @@ -469,7 +443,7 @@ int NVStore::copy_record(uint8_t from_area, uint32_t from_offset, uint32_t to_of to_offset += chunk_len; } - *next_offset = align_up(to_offset, FLASH_MINIMAL_PROG_UNIT); + next_offset = align_up(to_offset, FLASH_MINIMAL_PROG_UNIT); return NVSTORE_SUCCESS; } @@ -491,7 +465,7 @@ int NVStore::garbage_collection(uint16_t key, uint16_t flags, uint16_t buf_len_b // otherwise we may either write it twice (if already included), or lose it in case we decide // to skip it at garbage collection phase (and the system crashes). if ((key != NO_KEY) && !(flags & DELETE_ITEM_FLAG)) { - ret = write_record(1 - _active_area, new_area_offset, key, 0, buf_len_bytes, buf, &next_offset); + ret = write_record(1 - _active_area, new_area_offset, key, 0, buf_len_bytes, buf, next_offset); if (ret != NVSTORE_SUCCESS) { PR_ERR("nvstore_garbage_collection: write_record failed with ret %d\n", ret); return ret; @@ -510,7 +484,7 @@ int NVStore::garbage_collection(uint16_t key, uint16_t flags, uint16_t buf_len_b curr_offset &= ~OFFS_BY_KEY_FLAG_MASK; if ((!curr_offset) || (curr_area != _active_area)) continue; - ret = copy_record(curr_area, curr_offset, new_area_offset, &next_offset); + ret = copy_record(curr_area, curr_offset, new_area_offset, next_offset); if (ret != NVSTORE_SUCCESS) { PR_ERR("nvstore_garbage_collection: copy_record failed with ret %d\n", ret); return ret; @@ -521,7 +495,7 @@ int NVStore::garbage_collection(uint16_t key, uint16_t flags, uint16_t buf_len_b // Now write master record, with version incremented by 1. _active_area_version++; - ret = write_master_record(1 - _active_area, _active_area_version, &next_offset); + ret = write_master_record(1 - _active_area, _active_area_version, next_offset); if (ret != NVSTORE_SUCCESS) { PR_ERR("nvstore_garbage_collection: write_master_record failed with ret %d\n", ret); return ret; @@ -548,7 +522,7 @@ int NVStore::garbage_collection(uint16_t key, uint16_t flags, uint16_t buf_len_b // actual_len_bytes - [OUT] Actual length of returned data. // validate_only - [IN] Just validate (don't return user data). // Return : NVSTORE_SUCCESS on success. Error code otherwise. -int NVStore::do_get(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_t *actual_len_bytes, +int NVStore::do_get(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_t &actual_len_bytes, int validate_only) { int ret = NVSTORE_SUCCESS; @@ -595,8 +569,8 @@ int NVStore::do_get(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_ record_offset &= ~OFFS_BY_KEY_FLAG_MASK; ret = read_record(area, record_offset, buf_len_bytes, buf, - actual_len_bytes, validate_only, &valid, - &read_type, &flags, &next_offset); + actual_len_bytes, validate_only, valid, + read_type, flags, next_offset); if ((ret == NVSTORE_SUCCESS) && valid) break; // In case area is the same as expected, GC is not in progress and we have a genuine error. @@ -614,12 +588,12 @@ int NVStore::do_get(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_ // Start of API functions -int NVStore::get(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_t *actual_len_bytes) +int NVStore::get(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_t &actual_len_bytes) { return do_get(key, buf_len_bytes, buf, actual_len_bytes, 0); } -int NVStore::get_item_size(uint16_t key, uint16_t *actual_len_bytes) +int NVStore::get_item_size(uint16_t key, uint16_t &actual_len_bytes) { return do_get(key, 0, NULL, actual_len_bytes, 1); } @@ -668,7 +642,7 @@ int NVStore::do_set(uint16_t key, uint16_t buf_len_bytes, const uint32_t *buf, u // produces an offset on which each writer can work separately, without being interrupted // by the other writer. The only mutual resource here is _free_space_offset - which // gets the correct value because of this atomic increment. - new_free_space = safe_increment(&_free_space_offset, record_size); + new_free_space = safe_increment(_free_space_offset, record_size); record_offset = new_free_space - record_size; // If we cross the area limit, we need to invoke GC. However, we should consider all the cases @@ -694,13 +668,13 @@ int NVStore::do_set(uint16_t key, uint16_t buf_len_bytes, const uint32_t *buf, u } _write_lock.shared_unlock(); } - new_free_space = safe_increment(&_free_space_offset, record_size); + new_free_space = safe_increment(_free_space_offset, record_size); record_offset = new_free_space - _free_space_offset; } } // Now write the record - ret = write_record(_active_area, record_offset, key, flags, buf_len_bytes, buf, &next_offset); + ret = write_record(_active_area, record_offset, key, flags, buf_len_bytes, buf, next_offset); if (ret != NVSTORE_SUCCESS) { _write_lock.shared_unlock(); return ret; @@ -755,12 +729,10 @@ int NVStore::init() // This handles the case that init function is called by more than one thread concurrently. // Only the one who gets the value of 1 in _init_attempts_val will proceed, while others will // wait until init is finished. - _init_attempts_val = safe_increment(&_init_attempts, 1); + _init_attempts_val = safe_increment(_init_attempts, 1); if (_init_attempts_val != 1) { -#if NVSTORE_THREAD_SAFETY while(!_init_done) - Thread::wait(MEDITATE_TIME_MS); -#endif + rtos::Thread::wait(MEDITATE_TIME_MS); return NVSTORE_SUCCESS; } @@ -786,7 +758,7 @@ int NVStore::init() // Find start of empty space at the end of the area. This serves for both // knowing whether the area is empty and for the record traversal at the end. - os_ret = calc_empty_space(area, &(free_space_offset_of_area[area])); + os_ret = calc_empty_space(area, free_space_offset_of_area[area]); MBED_ASSERT(!os_ret); if (!free_space_offset_of_area[area]) { @@ -796,8 +768,8 @@ int NVStore::init() // Check validity of master record ret = read_record(area, 0, sizeof(master_rec), (uint32_t *) &master_rec, - &actual_len_bytes, 0, &valid, - &key, &flags, &next_offset); + actual_len_bytes, 0, valid, + key, flags, next_offset); MBED_ASSERT((ret == NVSTORE_SUCCESS) || (ret == NVSTORE_BUFF_TOO_SMALL)); if (ret == NVSTORE_BUFF_TOO_SMALL) { // Buf too small error means that we have a corrupt master record - @@ -828,7 +800,7 @@ int NVStore::init() // In case we have two empty areas, arbitrarily assign 0 to the active one. if ((area_state[0] == AREA_STATE_EMPTY) && (area_state[1] == AREA_STATE_EMPTY)) { _active_area = 0; - ret = write_master_record(_active_area, 1, &_free_space_offset); + ret = write_master_record(_active_area, 1, _free_space_offset); MBED_ASSERT(ret == NVSTORE_SUCCESS); _init_done = 1; return NVSTORE_SUCCESS; @@ -849,8 +821,8 @@ int NVStore::init() // Traverse area until reaching the empty space at the end or until reaching a faulty record while (_free_space_offset < free_space_offset_of_area[_active_area]) { ret = read_record(_active_area, _free_space_offset, 0, NULL, - &actual_len_bytes, 1, &valid, - &key, &flags, &next_offset); + actual_len_bytes, 1, valid, + key, flags, next_offset); MBED_ASSERT(ret == NVSTORE_SUCCESS); // In case we have a faulty record, this probably means that the system crashed when written. @@ -934,9 +906,8 @@ int NVStore::force_garbage_collection(void) #endif -#endif // !NVSTORE_PROBE_ONLY -int NVStore::probe(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_t *actual_len_bytes) +int NVStore::probe(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_t &actual_len_bytes) { uint8_t area; @@ -956,8 +927,8 @@ int NVStore::probe(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_t for (area = 0; area < NVSTORE_NUM_AREAS; area++) { // Check validity of master record ret = read_record(area, 0, sizeof(master_rec), (uint32_t *) &master_rec, - actual_len_bytes, 0, &valid, - &read_type, &flags, &next_offset); + actual_len_bytes, 0, valid, + read_type, flags, next_offset); if (ret != NVSTORE_SUCCESS) { if (ret == NVSTORE_BUFF_TOO_SMALL) { // Buf too small error means that we have a corrupt master record - @@ -993,7 +964,7 @@ int NVStore::probe(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_t } area = (uint8_t) sel_area; - os_ret = calc_empty_space(area, &free_space_offset_of_area); + os_ret = calc_empty_space(area, free_space_offset_of_area); if (os_ret) { PR_ERR("nvstore_probe_type: calc_empty_space failed with err code 0x%lx\n", (unsigned long) os_ret); @@ -1005,8 +976,8 @@ int NVStore::probe(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_t while (curr_offset < free_space_offset_of_area) { // first just verify, then read to user buffer ret = read_record(area, curr_offset, 0, NULL, - &tmp_actual_len_bytes, 1, &valid, - &read_type, &flags, &next_offset); + tmp_actual_len_bytes, 1, valid, + read_type, flags, next_offset); if (ret != NVSTORE_SUCCESS) { PR_ERR("nvstore_probe_type: read_record failed with err code 0x%x\n", ret); return ret; @@ -1021,8 +992,8 @@ int NVStore::probe(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_t } else { save_ret = read_record(area, curr_offset, buf_len_bytes, buf, - actual_len_bytes, false, &valid, - &read_type, &flags, &next_offset); + actual_len_bytes, false, valid, + read_type, flags, next_offset); found = true; } } @@ -1035,3 +1006,5 @@ int NVStore::probe(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_t return save_ret; } + +#endif // NVSTORE_ENABLED diff --git a/features/nvstore/source/nvstore.h b/features/nvstore/source/nvstore.h index 92e35e89cd9..cef8be6c2b9 100644 --- a/features/nvstore/source/nvstore.h +++ b/features/nvstore/source/nvstore.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 ARM Limited. All rights reserved. + * Copyright (c) 2018 ARM Limited. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -17,15 +17,19 @@ #ifndef __NVSTORE_H #define __NVSTORE_H +// These addresses need to be configured according to board (in mbed_lib.json) +#if defined(NVSTORE_AREA_1_ADDRESS) && defined(NVSTORE_AREA_1_SIZE) && \ + defined(NVSTORE_AREA_2_ADDRESS) && defined(NVSTORE_AREA_2_SIZE) && \ + defined(DEVICE_FLASH) +#define NVSTORE_ENABLED 1 +#endif + +#if NVSTORE_ENABLED #include #include #include "nvstore_int_flash_wrapper.h" #include "nvstore_shared_lock.h" -#ifdef NVSTORE_TESTING -#undef NVSTORE_PROBE_ONLY -#endif - enum { NVSTORE_SUCCESS = 0, NVSTORE_READ_ERROR = -1, @@ -66,7 +70,6 @@ class NVStore { virtual ~NVStore(); -#if !NVSTORE_PROBE_ONLY /** * @brief Returns number of keys. * @@ -93,7 +96,7 @@ class NVStore { * @param [in] buf * Buffer to store data on (must be aligned to a 32 bit boundary). * - * @param [out] actual_len_bytes. + * @param [out] actual_len_bytes * Actual length of returned data * * @returns NVSTORE_SUCCESS Value was found on Flash. @@ -104,7 +107,7 @@ class NVStore { * NVSTORE_BUFF_TOO_SMALL Not enough memory in user buffer. * NVSTORE_BUFF_NOT_ALIGNED Buffer not aligned to 32 bits. */ - int get(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_t *actual_len_bytes); + int get(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_t &actual_len_bytes); /** * @brief Returns one item of data programmed on Flash, given key. @@ -112,7 +115,7 @@ class NVStore { * @param [in] key * Key of stored item. * - * @param [out] actual_len_bytes. + * @param [out] actual_len_bytes * Actual length of item * * @returns NVSTORE_SUCCESS Value was found on Flash. @@ -121,7 +124,7 @@ class NVStore { * NVSTORE_DATA_CORRUPT Data on Flash is corrupt. * NVSTORE_BAD_VALUE Bad value in any of the parameters. */ - int get_item_size(uint16_t key, uint16_t *actual_len_bytes); + int get_item_size(uint16_t key, uint16_t &actual_len_bytes); /** @@ -246,11 +249,11 @@ class NVStore { int force_garbage_collection(); #endif -#endif - /** * @brief Returns one item of data programmed on Flash, given key. - * This is the "initless" version of the function, traversing the flash if triggered. + * This is a self contained version of the get function (not requiring init), traversing the flash each time if triggered. + * This function is NOT thread safe. Its implementation is here for the case we want to minimise code size for clients + * such as boot loaders, performing minimal accesses to NVstore. In this case all other APIs can be commented out. * * @param [in] key * Key of stored item (must be between 0-15). @@ -261,7 +264,7 @@ class NVStore { * @param [in] buf * Buffer to store data on (must be aligned to a 32 bit boundary). * - * @param [out] actual_len_bytes. + * @param [out] actual_len_bytes * Actual length of returned data * * @returns NVSTORE_SUCCESS Value was found on Flash. @@ -272,7 +275,7 @@ class NVStore { * NVSTORE_BUFF_TOO_SMALL Not enough memory in user buffer. * NVSTORE_BUFF_NOT_ALIGNED Buffer not aligned to 32 bits. */ - int probe(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_t *actual_len_bytes); + int probe(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_t &actual_len_bytes); private: int _init_done; @@ -297,29 +300,30 @@ class NVStore { int flash_write_area(uint8_t area, uint32_t offset, uint32_t len_bytes, const uint32_t *buf); int flash_erase_area(uint8_t area); - int calc_empty_space(uint8_t area, uint32_t *offset); + int calc_empty_space(uint8_t area, uint32_t &offset); int read_record(uint8_t area, uint32_t offset, uint16_t buf_len_bytes, uint32_t *buf, - uint16_t *actual_len_bytes, int validate_only, int *valid, - uint16_t *key, uint16_t *flags, uint32_t *next_offset); + uint16_t &actual_len_bytes, int validate_only, int &valid, + uint16_t &key, uint16_t &flags, uint32_t &next_offset); int write_record(uint8_t area, uint32_t offset, uint16_t key, uint16_t flags, - uint32_t data_len, const uint32_t *data_buf, uint32_t *next_offset); + uint32_t data_len, const uint32_t *data_buf, uint32_t &next_offset); - int write_master_record(uint8_t area, uint16_t version, uint32_t *next_offset); + int write_master_record(uint8_t area, uint16_t version, uint32_t &next_offset); int copy_record(uint8_t from_area, uint32_t from_offset, uint32_t to_offset, - uint32_t *next_offset); + uint32_t &next_offset); int garbage_collection(uint16_t key, uint16_t flags, uint16_t buf_len_bytes, const uint32_t *buf); - int do_get(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_t *actual_len_bytes, + int do_get(uint16_t key, uint16_t buf_len_bytes, uint32_t *buf, uint16_t &actual_len_bytes, int validate_only); int do_set(uint16_t key, uint16_t buf_len_bytes, const uint32_t *buf, uint16_t flags); }; +#endif // NVSTORE_ENABLED #endif diff --git a/features/nvstore/source/nvstore_int_flash_wrapper.cpp b/features/nvstore/source/nvstore_int_flash_wrapper.cpp index 75f3a08cdf3..377f6bda7c7 100644 --- a/features/nvstore/source/nvstore_int_flash_wrapper.cpp +++ b/features/nvstore/source/nvstore_int_flash_wrapper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 ARM Limited. All rights reserved. + * Copyright (c) 2018 ARM Limited. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -18,42 +18,25 @@ // ----------------------------------------------------------- Includes ----------------------------------------------------------- -#include "mbed.h" -#include "FlashIAP.h" - #include "nvstore_int_flash_wrapper.h" - -#include -#include -#include #include "nvstore_shared_lock.h" +#include "FlashIAP.h" +#include // --------------------------------------------------------- Definitions ---------------------------------------------------------- -#define TRACE_GROUP "nvstore" - -#ifdef __cplusplus -extern "C" { -#endif - #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define MAX_PAGE_SIZE 16 -static FlashIAP flash; +static mbed::FlashIAP flash; static size_t get_page_size(void) { return MIN(flash.get_page_size(), MAX_PAGE_SIZE); } -// Program to Flash with alignments to page size -// Parameters : -// @param[in] buffer - pointer to the buffer to be written -// @param[in] size - the size of the buffer in bytes. -// @param[in] address - the address of the internal flash, must be aligned to minimum writing unit (page size). -// Return : None. static int program_flash(size_t size, uint32_t address, const uint8_t *buffer) { int ret; @@ -169,8 +152,7 @@ int nvstore_int_flash_write(size_t size, uint32_t address, const uint32_t *buffe return -1; } - while (size) - { + while (size) { chunk = MIN(sector_size - (address % sector_size), size); ret = program_flash(chunk, address, buf); if (ret) { @@ -186,7 +168,3 @@ int nvstore_int_flash_write(size_t size, uint32_t address, const uint32_t *buffe } -#ifdef __cplusplus -} -#endif - diff --git a/features/nvstore/source/nvstore_int_flash_wrapper.h b/features/nvstore/source/nvstore_int_flash_wrapper.h index f1c5cf9d7ac..13f16053dc8 100644 --- a/features/nvstore/source/nvstore_int_flash_wrapper.h +++ b/features/nvstore/source/nvstore_int_flash_wrapper.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 ARM Limited. All rights reserved. + * Copyright (c) 2018 ARM Limited. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -19,30 +19,83 @@ #ifndef __NVSTORE_INT_FLASH_WRAPPER_H #define __NVSTORE_INT_FLASH_WRAPPER_H -#include +#include -#ifdef __cplusplus -extern "C" { -#endif +/* + * This is a simple wrapper for the FlashIAP class, supplying basic flash functionality. + */ #define NVSTORE_NUM_AREAS 2 #define NVSTORE_BLANK_FLASH_VAL 0xFF +/** + * @brief Returns flash sector size, given address. + * + * @param [in] address + * Flash address. + * + * @returns sector size (bytes). + */ size_t nvstore_int_flash_get_sector_size(uint32_t address); +/** + * @brief Initialises flash. + * + * @returns 0 on success, return code otherwise. + */ int nvstore_int_flash_init(void); +/** + * @brief Deinitialises flash. + * + * @returns 0 on success, return code otherwise. + */ int nvstore_int_flash_deinit(void); +/** + * @brief Reads from flash into user buffer, given address and size. + * + * @param [in] size + * Read size + * + * @param [in] address + * Flash address. + * + * @param [in] buffer + * User buffer. + * + * @returns 0 on success, return code otherwise. + */ int nvstore_int_flash_read(size_t size, uint32_t address, uint32_t *buffer); +/** + * @brief Erases a chain of sectors, given address and size. + * + * @param [in] size + * Erase size + * + * @param [in] address + * Flash address. + * + * @returns 0 on success, return code otherwise. + */ int nvstore_int_flash_erase(uint32_t address, size_t size); +/** + * @brief Writes from user buffer to the flash, given address and size. + * + * @param [in] size + * Write size + * + * @param [in] address + * Flash address. + * + * @param [in] buffer + * User buffer. + * + * @returns 0 on success, return code otherwise. + */ int nvstore_int_flash_write(size_t size, uint32_t address, const uint32_t *buffer); -#ifdef __cplusplus -} -#endif - #endif diff --git a/features/nvstore/source/nvstore_shared_lock.cpp b/features/nvstore/source/nvstore_shared_lock.cpp index c99ef0dfd95..85b8e9ab595 100644 --- a/features/nvstore/source/nvstore_shared_lock.cpp +++ b/features/nvstore/source/nvstore_shared_lock.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 ARM Limited. All rights reserved. + * Copyright (c) 2018 ARM Limited. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -19,29 +19,14 @@ // ----------------------------------------------------------- Includes ----------------------------------------------------------- #include "nvstore_shared_lock.h" - -#include "mbed.h" - #include "mbed_critical.h" #include "rtos/thread.h" - -#include -#include #include -#ifndef NVSTORE_THREAD_SAFE -#define NVSTORE_THREAD_SAFE 1 -#endif - // --------------------------------------------------------- Definitions ---------------------------------------------------------- -#define MEDITATE_TIME_MS 100 - -typedef struct { - uint32_t ctr; - rtos::Mutex mutex; -} shared_lock_priv_t; +#define MEDITATE_TIME_MS 1 // -------------------------------------------------- Functions Implementation ---------------------------------------------------- @@ -56,53 +41,43 @@ SharedLock::~SharedLock() int SharedLock::shared_lock() { -#if NVSTORE_THREAD_SAFE mutex.lock(); core_util_atomic_incr_u32(&ctr, 1); mutex.unlock(); -#endif return NVSTORE_OS_OK; } int SharedLock::shared_unlock() { -#if NVSTORE_THREAD_SAFE int val = core_util_atomic_decr_u32(&ctr, 1); if (val < 0) { return NVSTORE_OS_RTOS_ERR; } -#endif return NVSTORE_OS_OK; } int SharedLock::exclusive_lock() { -#if NVSTORE_THREAD_SAFE mutex.lock(); while(ctr) rtos::Thread::wait(MEDITATE_TIME_MS); -#endif return NVSTORE_OS_OK; } int SharedLock::exclusive_unlock() { -#if NVSTORE_THREAD_SAFE mutex.unlock(); -#endif return NVSTORE_OS_OK; } int SharedLock::promote() { -#if NVSTORE_THREAD_SAFE - mutex.lock(); while(ctr > 1) { rtos::Thread::wait(MEDITATE_TIME_MS); @@ -113,7 +88,6 @@ int SharedLock::promote() } core_util_atomic_decr_u32(&ctr, 1); -#endif return NVSTORE_OS_OK; } diff --git a/features/nvstore/source/nvstore_shared_lock.h b/features/nvstore/source/nvstore_shared_lock.h index 699a86619f7..b924be3aaa0 100644 --- a/features/nvstore/source/nvstore_shared_lock.h +++ b/features/nvstore/source/nvstore_shared_lock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 ARM Limited. All rights reserved. + * Copyright (c) 2018 ARM Limited. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -16,8 +16,8 @@ -#ifndef __NVSTORE_OS_WRAPPER_H -#define __NVSTORE_OS_WRAPPER_H +#ifndef __NVSTORE_SHARED_LOCK_H +#define __NVSTORE_SHARED_LOCK_H #include #include "rtos/Mutex.h" @@ -29,16 +29,52 @@ enum { NVSTORE_OS_NO_MEM_ERR = -3, }; +/** + * SharedLock, implements a shared/exclusive lock (AKA RW lock). + * This class doesn't implement this kind of lock in the classic manner (having two Mutexes and a counter). + * Instead, it uses one Mutex and one atomic counter, favouring the shared usage of the exclusive one. + */ + class SharedLock { public: SharedLock(); virtual ~SharedLock(); + /** + * @brief Locks the shared lock in a shared manner. + * + * @returns 0 for success, error code otherwise. + */ int shared_lock(); + + /** + * @brief Unlocks the shared lock in a shared manner. + * + * @returns 0 for success, error code otherwise. + */ int shared_unlock(); + + /** + * @brief Locks the shared lock in an exclusive manner. + * + * @returns 0 for success, error code otherwise. + */ int exclusive_lock(); + + /** + * @brief Unlocks the shared lock in an exclusive manner. + * + * @returns 0 for success, error code otherwise. + */ int exclusive_unlock(); + + /** + * @brief Promotes the shared lock from shared to exclusive. + * + * @returns 0 for success, error code otherwise. + */ int promote(); + private: uint32_t ctr; rtos::Mutex mutex; diff --git a/targets/targets.json b/targets/targets.json index 512c364860d..0b57d23765e 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -611,7 +611,7 @@ "supported_toolchains": ["ARM", "GCC_ARM", "IAR"], "extra_labels": ["Freescale", "MCUXpresso_MCUS", "KSDK2_MCUS", "FRDM", "KPSDK_MCUS", "KPSDK_CODE", "MCU_K64F"], "is_disk_virtual": true, - "macros": ["CPU_MK64FN1M0VMD12", "FSL_RTOS_MBED", "NVSTORE_AREA_1_ADDRESS=0xFE000", "NVSTORE_AREA_1_SIZE=0x1000", "NVSTORE_AREA_2_ADDRESS=0xFF000", "NVSTORE_AREA_2_SIZE=0x1000"], + "macros": ["CPU_MK64FN1M0VMD12", "FSL_RTOS_MBED"], "inherits": ["Target"], "detect_code": ["0240"], "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "STORAGE", "TRNG", "FLASH"], @@ -688,7 +688,7 @@ "supported_toolchains": ["ARM", "GCC_ARM", "IAR"], "extra_labels": ["Freescale", "MCUXpresso_MCUS", "KSDK2_MCUS", "FRDM"], "is_disk_virtual": true, - "macros": ["CPU_MK82FN256VDC15", "FSL_RTOS_MBED", "NVSTORE_AREA_1_ADDRESS=0x3E000", "NVSTORE_AREA_1_SIZE=0x1000", "NVSTORE_AREA_2_ADDRESS=0x3F000", "NVSTORE_AREA_2_SIZE=0x1000"], + "macros": ["CPU_MK82FN256VDC15", "FSL_RTOS_MBED"], "inherits": ["Target"], "detect_code": ["0217"], "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH"],