Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
flash.cpp
00001 /* 00002 * mbed Microcontroller Library 00003 * Copyright (c) 2006-2016 ARM Limited 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 /** @file flash.cpp Test cases to flush KVs in the CFSTORE using the Flash-Journal interface. 00019 * 00020 * Please consult the documentation under the test-case functions for 00021 * a description of the individual test case. 00022 */ 00023 00024 #include "cfstore_config.h" 00025 #include "cfstore_test.h" 00026 #include "cfstore_debug.h" 00027 #include "Driver_Common.h" 00028 #include "configuration_store.h" 00029 #include "utest/utest.h" 00030 #include "unity/unity.h" 00031 #include "greentea-client/test_env.h" 00032 00033 #ifdef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED 00034 #include "flash_journal_strategy_sequential.h" 00035 #include "flash_journal.h" 00036 #include "Driver_Common.h" 00037 #endif /* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED */ 00038 00039 #ifdef YOTTA_CFG_CFSTORE_UVISOR 00040 #include "uvisor-lib/uvisor-lib.h" 00041 #endif /* YOTTA_CFG_CFSTORE_UVISOR */ 00042 00043 #include <stdio.h> 00044 #include <stdlib.h> 00045 #include <string.h> 00046 #include <inttypes.h> 00047 00048 using namespace utest::v1; 00049 00050 /* Configure secure box. */ 00051 #ifdef YOTTA_CFG_CFSTORE_UVISOR 00052 UVISOR_BOX_NAMESPACE("com.arm.mbed.cfstore.test.flash.box1"); 00053 UVISOR_BOX_CONFIG(cfstore_flash_box1, UVISOR_BOX_STACK_SIZE); 00054 #endif /* YOTTA_CFG_CFSTORE_UVISOR */ 00055 00056 00057 00058 /* shared code common to both sync and async test cases */ 00059 00060 /* 00061 * Defines 00062 * 00063 */ 00064 /// @cond CFSTORE_DOXYGEN_DISABLE 00065 #define CFSTORE_FREE free 00066 #define CFSTORE_MALLOC malloc 00067 #define CFSTORE_REALLOC realloc 00068 #define CFSTORE_FLASH_STACK_BUF_SIZE 64 00069 #define CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE 8 00070 #define CFSTORE_TEST_DATA_KEYNAME "com.arm.mbed.configurationstore.test.flush.cfstoreflushtest02" 00071 #define CFSTORE_TEST_DATA_KEYNAME_SHORT "com.arm" 00072 #define CFSTORE_TEST_DATA_VALUE_INIT "\1" 00073 #define CFSTORE_TEST_DATA_KEYNAME_SIZE (sizeof(CFSTORE_TEST_DATA_KEYNAME) - 1) 00074 #define CFSTORE_TEST_DATA_VALUE_SIZE (sizeof(CFSTORE_TEST_DATA_VALUE_INIT) - 1) 00075 #define CFSTORE_FLASH_UTEST_MSG_BUF_SIZE 256 00076 #define CFSTORE_FLASH_MTD_ASYNC_OPS_ON 1 00077 #define CFSTORE_FLASH_MTD_ASYNC_OPS_OFF 0 00078 #define CFSTORE_FLASH_CASE_TIMEOUT_MS 5000 00079 /// @endcond 00080 00081 /* 00082 * Globals 00083 */ 00084 00085 /// @cond CFSTORE_DOXYGEN_DISABLE 00086 char cfstore_flash_utest_msg_g[CFSTORE_FLASH_UTEST_MSG_BUF_SIZE]; 00087 /// @endcond 00088 00089 #ifdef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED 00090 uint16_t cfstore_flash_mtd_async_ops_g = 0; 00091 extern ARM_DRIVER_STORAGE ARM_Driver_Storage_(0); 00092 00093 /* KV data for test_01 */ 00094 static cfstore_kv_data_t cfstore_flush_test_01_kv_data[] = { 00095 { CFSTORE_TEST_DATA_KEYNAME, CFSTORE_TEST_DATA_VALUE_INIT}, 00096 { NULL, NULL}, 00097 }; 00098 00099 00100 /* @brief key value header structure defining key_name length, value length 00101 * @note 00102 * 8 bytes long */ 00103 typedef struct cfstore_area_header_t 00104 { 00105 uint32_t vlength; 00106 uint8_t klength; 00107 uint8_t perm_owner_read : 1; 00108 uint8_t perm_owner_write : 1; 00109 uint8_t perm_owner_execute : 1; 00110 uint8_t perm_other_read : 1; 00111 uint8_t perm_other_write : 1; 00112 uint8_t perm_other_execute : 1; 00113 uint8_t reserved : 2; 00114 uint8_t refcount; 00115 struct flags_t { 00116 uint8_t deleting : 1; 00117 uint8_t reserved : 7; 00118 } flags ; 00119 } cfstore_area_header_t ; 00120 00121 00122 /* @brief data structure for managing test data */ 00123 typedef struct cfstore_flash_data_blob_t { 00124 cfstore_area_header_t hdr; 00125 uint8_t data[CFSTORE_TEST_DATA_KEYNAME_SIZE + CFSTORE_TEST_DATA_VALUE_SIZE]; /* 61 bytes for key_name, 1 byte for value */ 00126 } cfstore_flash_data_blob_t; 00127 00128 /* 00129 * Defines 00130 * 00131 * CFSTORE_FLASH_AREA_SIZE_MIN 00132 * valid sizes of areas should always be greater than the size of the header, and therefore 00133 * greater than this value, which is defined as smaller than the header size 00134 */ 00135 #define CFSTORE_FLASH_AREA_SIZE_MIN (sizeof(cfstore_area_header_t) - 1) 00136 00137 /* 00138 * Shared implementation between sync and async tests 00139 */ 00140 00141 /* print key name string from area where key_name is not null terminated*/ 00142 static void cfstore_dump_key_name(uint8_t* keyname, uint8_t len, const char* tag) 00143 { 00144 char blob_data[CFSTORE_KEY_NAME_MAX_LENGTH]; 00145 00146 (void) tag; 00147 assert(keyname != NULL); 00148 assert(tag != NULL); 00149 assert(len > 0); 00150 memcpy(blob_data, keyname, len); 00151 blob_data[len] = '\0'; 00152 CFSTORE_DBGLOG("%s:keyname=%s\r\n", tag, blob_data); 00153 } 00154 00155 /* @brief test fsm states and events */ 00156 typedef enum cfstore_flash_fsm_state_t { 00157 cfstore_flash_fsm_state_initializing = 0, 00158 cfstore_flash_fsm_state_reading, 00159 cfstore_flash_fsm_state_writing, 00160 cfstore_flash_fsm_state_committing, 00161 cfstore_flash_fsm_state_max 00162 } cfstore_flash_fsm_state_t; 00163 00164 /* @brief test fsm events */ 00165 typedef enum cfstore_flash_fsm_event_t { 00166 cfstore_flash_fsm_event_init_done = 0, 00167 cfstore_flash_fsm_event_read_done, 00168 cfstore_flash_fsm_event_write_done, 00169 cfstore_flash_fsm_event_commit_done, 00170 cfstore_flash_fsm_event_max, 00171 } cfstore_flash_fsm_event_t; 00172 00173 typedef void (*cfstore_flash_fsm_handler)(void* ctx); 00174 00175 typedef struct cfstore_fsm_t 00176 { 00177 cfstore_flash_fsm_state_t state; 00178 cfstore_flash_fsm_event_t event; 00179 } cfstore_fsm_t; 00180 00181 typedef struct cfstore_flash_ctx_t 00182 { 00183 uint8_t* area_0_head; 00184 uint8_t* area_0_tail; 00185 FlashJournal_t jrnl; 00186 uint64_t expected_blob_size; 00187 cfstore_fsm_t fsm; 00188 int32_t status; 00189 FlashJournal_OpCode_t cmd_code; 00190 uint64_t expected_read_size; 00191 } cfstore_flash_ctx_t; 00192 00193 /* 00194 * Globals 00195 */ 00196 static cfstore_flash_ctx_t cfstore_flash_ctx_g; 00197 static const char* cfstore_flash_opcode_str[] = 00198 { 00199 "FLASH_JOURNAL_OPCODE_INITIALIZE", 00200 "FLASH_JOURNAL_OPCODE_GET_INFO", 00201 "FLASH_JOURNAL_OPCODE_READ_BLOB", 00202 "FLASH_JOURNAL_OPCODE_LOG_BLOB", 00203 "FLASH_JOURNAL_OPCODE_COMMIT", 00204 "FLASH_JOURNAL_OPCODE_RESET", 00205 }; 00206 00207 #ifdef CFSTORE_DEBUG 00208 static const char* cfstore_flash_state_str[] = 00209 { 00210 "initializing", 00211 "reading", 00212 "writing", 00213 "committing", 00214 "unknown" 00215 }; 00216 00217 static const char* cfstore_flash_event_str[] = 00218 { 00219 "init_done", 00220 "read_done", 00221 "write_done", 00222 "commit_done", 00223 "unknown" 00224 }; 00225 #endif /* CFSTORE_DEBUG */ 00226 00227 /* 00228 * Forward decl 00229 */ 00230 static void cfstore_fsm_state_handle_event(cfstore_fsm_t* fsm, cfstore_flash_fsm_event_t event, void* context); 00231 static void cfstore_fsm_state_set(cfstore_fsm_t* fsm, cfstore_flash_fsm_state_t new_state, void* ctx); 00232 00233 /* 00234 * context related methods 00235 */ 00236 00237 /* @brief get a pointer to the global context data structure */ 00238 static cfstore_flash_ctx_t* cfstore_flash_ctx_get(void) 00239 { 00240 return &cfstore_flash_ctx_g; 00241 } 00242 00243 00244 /* @brief flash journal asynchronous callback handler */ 00245 void cfstore_flash_test_01_callback(int32_t status, FlashJournal_OpCode_t cmd_code) 00246 { 00247 cfstore_flash_ctx_t* ctx = cfstore_flash_ctx_get(); 00248 00249 CFSTORE_FENTRYLOG("%s:entered: status=%d, cmd_code=%d (%s)\r\n", __func__, (int) status, (int) cmd_code, cfstore_flash_opcode_str[cmd_code]); 00250 switch(cmd_code) 00251 { 00252 case FLASH_JOURNAL_OPCODE_INITIALIZE: 00253 ctx->fsm.event = cfstore_flash_fsm_event_init_done; 00254 break; 00255 case FLASH_JOURNAL_OPCODE_READ_BLOB: 00256 ctx->fsm.event = cfstore_flash_fsm_event_read_done; 00257 break; 00258 case FLASH_JOURNAL_OPCODE_LOG_BLOB: 00259 ctx->fsm.event = cfstore_flash_fsm_event_write_done; 00260 break; 00261 case FLASH_JOURNAL_OPCODE_COMMIT: 00262 ctx->fsm.event = cfstore_flash_fsm_event_commit_done; 00263 break; 00264 case FLASH_JOURNAL_OPCODE_GET_INFO: 00265 case FLASH_JOURNAL_OPCODE_RESET: 00266 default: 00267 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: received asynchronous notification for opcode=%d (%s) when api call should have been synchronous", __func__, cmd_code, cmd_code <= FLASH_JOURNAL_OPCODE_RESET ? cfstore_flash_opcode_str[cmd_code] : "unknown"); 00268 TEST_ASSERT_MESSAGE(false, cfstore_flash_utest_msg_g) 00269 return; 00270 } 00271 ctx->status = status; 00272 ctx->cmd_code = cmd_code; 00273 cfstore_fsm_state_handle_event(&ctx->fsm, ctx->fsm.event, (void*) ctx); 00274 return; 00275 } 00276 00277 00278 /* @brief fsm handler called on entry to initializing state */ 00279 static void cfstore_flash_fsm_init_on_entry(void* context) 00280 { 00281 /* round up cfstore_flash_data_blob_t to nearest k64f program unit size */ 00282 const ARM_DRIVER_STORAGE *drv = &ARM_Driver_Storage_(0); 00283 FlashJournal_Info_t info; 00284 FlashJournal_Status_t status = JOURNAL_STATUS_ERROR; 00285 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00286 00287 /* check that the mtd is in synchronous mode */ 00288 CFSTORE_FENTRYLOG("%s:entered: \r\n", __func__); 00289 memset(&info, 0, sizeof(info)); 00290 00291 /* FlashJournal_initialize() is potentially asynchronous */ 00292 status = (FlashJournal_Status_t) FlashJournal_initialize(&ctx->jrnl, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, cfstore_flash_test_01_callback); 00293 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to initialize flash journaling layer (status=%d)\r\n", __func__, status); 00294 TEST_ASSERT_MESSAGE(status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00295 /* if status > 0, expect async callback, otherwise initialisation has been completed */ 00296 if(status > 0) { 00297 cfstore_flash_test_01_callback(status, FLASH_JOURNAL_OPCODE_INITIALIZE); 00298 } 00299 return; 00300 } 00301 00302 /* brief callback handler when in state initializing */ 00303 static void cfstore_flash_fsm_initializing(void* context) 00304 { 00305 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00306 00307 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00308 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: entered handler(%s) but not in initializing state (fsm->state=%d)\r\n", __func__, __func__, (int) ctx->fsm.state); 00309 TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flash_fsm_state_initializing, cfstore_flash_utest_msg_g); 00310 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: cmd_code code (%d) is not as expected (%d)\r\n", __func__, ctx->cmd_code, FLASH_JOURNAL_OPCODE_INITIALIZE); 00311 TEST_ASSERT_MESSAGE(ctx->cmd_code == FLASH_JOURNAL_OPCODE_INITIALIZE, cfstore_flash_utest_msg_g); 00312 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%d\r\n", __func__, (int) ctx->status); 00313 TEST_ASSERT_MESSAGE(ctx->status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00314 /* only change state if status > 0*/ 00315 if(ctx->status > 0){ 00316 cfstore_fsm_state_set(&ctx->fsm, cfstore_flash_fsm_state_reading, ctx); 00317 } 00318 } 00319 00320 /* static void cfstore_flash_fsm_init_on_exit(void* context){ (void) context;} */ 00321 00322 /* brief callback handler called when entering the reading state 00323 * note 00324 * flash journal has initialised successfully. now 00325 */ 00326 static void cfstore_flash_fsm_read_on_entry(void* context) 00327 { 00328 uint8_t* ptr = NULL; 00329 int32_t ret = 0; 00330 FlashJournal_Info_t info; 00331 FlashJournal_Status_t status = JOURNAL_STATUS_ERROR; 00332 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00333 00334 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00335 CFSTORE_ASSERT(ctx != NULL); 00336 /* drv->GetInfo() is synchronous */ 00337 status = FlashJournal_getInfo(&ctx->jrnl, &info); 00338 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: failed get journal info (status=%d)\r\n", __func__, (int) status); 00339 TEST_ASSERT_MESSAGE(status == JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00340 CFSTORE_DBGLOG("%s:FlashJournal_getInfo() done. info.sizeofJournaledBlob=%lu\r\n", __func__, (long unsigned int) info.sizeofJournaledBlob); 00341 00342 if(info.sizeofJournaledBlob > 0) 00343 { 00344 /* setup the expected blob size for writing 00345 * This is a multiple of program unit so the write doesnt fail due to unaligned log */ 00346 ctx->expected_blob_size = sizeof(cfstore_flash_data_blob_t); 00347 if(ctx->expected_blob_size % CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE > 0){ 00348 ctx->expected_blob_size += (CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE - (sizeof(cfstore_flash_data_blob_t) % CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE)); 00349 } 00350 /* test that a blob size is the expected size for flash data that has been written before */ 00351 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: info.sizeofJournaledBlob does not match expect size. expected_blob_size (%lu) != info.sizeofJournaledBlob (%lu)\r\n", __func__, (unsigned long int) ctx->expected_blob_size, (unsigned long int) info.sizeofJournaledBlob); 00352 TEST_ASSERT_EQUAL_INT64_MESSAGE(ctx->expected_blob_size, info.sizeofJournaledBlob, cfstore_flash_utest_msg_g); 00353 00354 /* grow the area by the size of the stored blob */ 00355 ptr = (uint8_t*) CFSTORE_REALLOC((void*) ctx->area_0_head, ctx->expected_blob_size); 00356 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:realloc failed flash blob (size=%d)\r\n", __func__, (int)info.sizeofJournaledBlob); 00357 TEST_ASSERT_MESSAGE(ptr != NULL, cfstore_flash_utest_msg_g); 00358 memset(ptr, 0, ctx->expected_blob_size); 00359 if(ptr != ctx->area_0_head){ 00360 CFSTORE_DBGLOG("%s:cfstore_ctx_g.area_0_head pointer changed (cfstore_ctx_g.area_0_head=%p, ptr=%p)\r\n", __func__, ctx->area_0_head, ptr); 00361 ctx->area_0_head = ptr; 00362 ctx->area_0_tail = ctx->area_0_head + info.sizeofJournaledBlob; 00363 } 00364 ret = FlashJournal_read(&ctx->jrnl, (void*) ctx->area_0_head, info.sizeofJournaledBlob); 00365 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: unable to read flash journal (ret=%d. info.sizeofJournaledBlob=%d)\r\n", __func__, (int) ret, (int) info.sizeofJournaledBlob); 00366 TEST_ASSERT_MESSAGE(ret >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00367 if(ret > 0){ 00368 /* read has completed synchronously*/ 00369 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: unable to read all data from flash journal (expected size=%lu, read=%d)\r\n", __func__, (unsigned long int)info.sizeofJournaledBlob, (int) ret); 00370 TEST_ASSERT_EQUAL_INT32_MESSAGE( (int32_t) info.sizeofJournaledBlob, ret, cfstore_flash_utest_msg_g); 00371 cfstore_flash_test_01_callback(ret, FLASH_JOURNAL_OPCODE_READ_BLOB); 00372 } 00373 } else { 00374 /* there is no blob, move to next state. need a +ve status value to indicate async completion 00375 * to the fsm reading state handler. use CFSTORE_FLASH_AREA_SIZE_MIN for this value */ 00376 ctx->expected_blob_size = CFSTORE_FLASH_AREA_SIZE_MIN; 00377 status = (FlashJournal_Status_t) CFSTORE_FLASH_AREA_SIZE_MIN; 00378 cfstore_flash_test_01_callback(status, FLASH_JOURNAL_OPCODE_READ_BLOB); 00379 } 00380 return; 00381 } 00382 00383 /* @brief fsm handler when in reading state */ 00384 void cfstore_flash_fsm_reading(void* context) 00385 { 00386 int32_t ret = 0; 00387 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00388 cfstore_flash_data_blob_t *blob = NULL; 00389 00390 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00391 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: entered handler(%s) but not in reading state (fsm->state=%d)\r\n", __func__, __func__, (int) ctx->fsm.state); 00392 TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flash_fsm_state_reading, cfstore_flash_utest_msg_g); 00393 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: cmd_code code (%d) is not as expected (%d)\r\n", __func__, ctx->cmd_code, FLASH_JOURNAL_OPCODE_READ_BLOB); 00394 TEST_ASSERT_MESSAGE(ctx->cmd_code == FLASH_JOURNAL_OPCODE_READ_BLOB, cfstore_flash_utest_msg_g); 00395 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%d\r\n", __func__, (int) ctx->status); 00396 TEST_ASSERT_MESSAGE(ctx->status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00397 00398 if(ctx->status > 0) 00399 { 00400 if(ctx->status > (int32_t) CFSTORE_FLASH_AREA_SIZE_MIN) 00401 { 00402 /* check the correct amount of data was read, which is the status code */ 00403 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: unable to read all data from flash journal (expected size=%lu, read=%d)\r\n", __func__, (unsigned long int) ctx->expected_blob_size, (int) ctx->status); 00404 /* ctx->status contains the status of the read that was completed */ 00405 TEST_ASSERT_EQUAL_INT64_MESSAGE(ctx->expected_blob_size, (int32_t) ctx->status, cfstore_flash_utest_msg_g); 00406 if(ctx->area_0_head != NULL) 00407 { 00408 /* check the key_name read from flash is correct */ 00409 blob = (cfstore_flash_data_blob_t*) ctx->area_0_head; 00410 cfstore_dump_key_name(blob->data, CFSTORE_TEST_DATA_KEYNAME_SIZE, __func__); 00411 ret = memcmp(blob->data, cfstore_flush_test_01_kv_data[0].key_name, strlen(cfstore_flush_test_01_kv_data[0].key_name)); 00412 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: incorrect key_name read from flash (expected 0 from memcpy(keyname, flash_data), actual was non-zero)", __func__); 00413 TEST_ASSERT_EQUAL_INT_MESSAGE(0, ret, cfstore_flash_utest_msg_g); 00414 } 00415 } 00416 cfstore_fsm_state_set(&ctx->fsm, cfstore_flash_fsm_state_writing, ctx); 00417 } 00418 } 00419 00420 /* void cfstore_flash_fsm_read_on_exit(void* context){ (void) context;} */ 00421 00422 /* @brief on entry to writing state, update value */ 00423 void cfstore_flash_fsm_write_on_entry(void* context) 00424 { 00425 uint8_t value = 0; 00426 int32_t ret = 0; 00427 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00428 cfstore_flash_data_blob_t *blob = NULL; 00429 00430 CFSTORE_FENTRYLOG("%s:entered:\r\n", __func__); 00431 /* allocate memory for data if not already done so */ 00432 if(ctx->area_0_head == NULL) 00433 { 00434 /* This is a multiple of program unit so the write doesnt fail due to unaligned log */ 00435 ctx->expected_blob_size = sizeof(cfstore_flash_data_blob_t); 00436 if(ctx->expected_blob_size % CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE > 0){ 00437 ctx->expected_blob_size += (CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE - (sizeof(cfstore_flash_data_blob_t) % CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE)); 00438 } 00439 ctx->area_0_head = (uint8_t*) CFSTORE_REALLOC((void*) ctx->area_0_head, ctx->expected_blob_size); 00440 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: unable to allocate memory for context\r\n", __func__); 00441 TEST_ASSERT_MESSAGE(ctx->area_0_head != NULL, cfstore_flash_utest_msg_g); 00442 ctx->area_0_tail = ctx->area_0_head + ctx->expected_blob_size; 00443 memset(ctx->area_0_head, 0, ctx->expected_blob_size); 00444 /* setup data to write to flash */ 00445 blob = (cfstore_flash_data_blob_t*) ctx->area_0_head; 00446 blob->hdr.klength = strlen(cfstore_flush_test_01_kv_data->key_name); 00447 blob->hdr.vlength= 1; 00448 blob->hdr.perm_owner_read = true; 00449 blob->hdr.perm_owner_write = true; 00450 blob->hdr.refcount = 1; 00451 memcpy((void*) blob->data, (const void*) cfstore_flush_test_01_kv_data->key_name, strlen(cfstore_flush_test_01_kv_data->key_name)); 00452 memcpy((void*) &blob->data[CFSTORE_TEST_DATA_KEYNAME_SIZE], (const void*) cfstore_flush_test_01_kv_data->value, strlen(cfstore_flush_test_01_kv_data->value)); 00453 } 00454 if(ctx->area_0_head != NULL) 00455 { 00456 /* data has been read */ 00457 /* check the key_name read from flash is correct */ 00458 blob = (cfstore_flash_data_blob_t*) ctx->area_0_head; 00459 value = (uint8_t) blob->data[CFSTORE_TEST_DATA_KEYNAME_SIZE]; 00460 CFSTORE_DBGLOG("INFO: value read from flash = %u\r\n", value); 00461 /* update the value */ 00462 value++; 00463 memcpy((void*) &blob->data[CFSTORE_TEST_DATA_KEYNAME_SIZE], (const void*) &value, sizeof(uint8_t)); 00464 } 00465 00466 ret = FlashJournal_log(&ctx->jrnl, (const void*) ctx->area_0_head, ctx->expected_blob_size); 00467 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: ret = JOURNAL_STATUS_SMALL_LOG_REQUEST, bailing out.", __func__); 00468 TEST_ASSERT_MESSAGE(ret != (int32_t) JOURNAL_STATUS_SMALL_LOG_REQUEST, cfstore_flash_utest_msg_g); 00469 00470 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to perform log operation to flash journal (ret=%d)\r\n", __func__, (int) ret); 00471 TEST_ASSERT_MESSAGE(ret >= 0, cfstore_flash_utest_msg_g); 00472 if(ret > 0){ 00473 /* write has completed synchronously*/ 00474 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: unable to write all data from flash journal (expected size=%lu, read=%d)\r\n", __func__, (unsigned long int) ctx->expected_blob_size, (int) ret); 00475 TEST_ASSERT_EQUAL_INT32_MESSAGE(ret, (int32_t) ctx->expected_blob_size, cfstore_flash_utest_msg_g); 00476 cfstore_flash_test_01_callback(ret, FLASH_JOURNAL_OPCODE_LOG_BLOB); 00477 } 00478 /* wait for async completion handler*/ 00479 } 00480 00481 /* @brief fsm handler when in reading state */ 00482 void cfstore_flash_fsm_writing(void* context) 00483 { 00484 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00485 00486 CFSTORE_FENTRYLOG("%s:entered:\r\n", __func__); 00487 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: entered handler(%s) but not in writing state (fsm->state=%d)\r\n", __func__, __func__, (int) ctx->fsm.state); 00488 TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flash_fsm_state_writing, cfstore_flash_utest_msg_g); 00489 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: cmd_code code (%d) is not as expected (%d)\r\n", __func__, ctx->cmd_code, FLASH_JOURNAL_OPCODE_LOG_BLOB); 00490 TEST_ASSERT_MESSAGE(ctx->cmd_code == FLASH_JOURNAL_OPCODE_LOG_BLOB, cfstore_flash_utest_msg_g); 00491 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%d\r\n", __func__, (int) ctx->status); 00492 TEST_ASSERT_MESSAGE(ctx->status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00493 00494 if(ctx->status > 0){ 00495 /* check the correct amount of data was written */ 00496 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: unable to write all data from flash journal (expected size=%lu, read=%d)\r\n", __func__, (unsigned long int) ctx->expected_blob_size, (int) ctx->status); 00497 TEST_ASSERT_EQUAL_INT64_MESSAGE(ctx->expected_blob_size, ctx->status, cfstore_flash_utest_msg_g); 00498 cfstore_fsm_state_set(&ctx->fsm, cfstore_flash_fsm_state_committing, ctx); 00499 } 00500 return; 00501 } 00502 00503 /* void cfstore_flash_fsm_write_on_exit(void* ctx){(void) ctx;} */ 00504 00505 /* @brief fsm handler when entering committing state */ 00506 void cfstore_flash_fsm_commit_on_entry(void* context) 00507 { 00508 int32_t ret = 0; 00509 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00510 00511 CFSTORE_FENTRYLOG("%s:entered:\r\n", __func__); 00512 ret = FlashJournal_commit(&ctx->jrnl); 00513 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to perform commit operation to flash journal (ret=%d)\r\n", __func__, (int) ret); 00514 TEST_ASSERT_MESSAGE(ret >= (int32_t) JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00515 /* for flash-journal-strategy-sequential version >0.4.0, commit() return no longer reports size of commit block */ 00516 if(ret > 0){ 00517 Harness::validate_callback(); 00518 } 00519 /* wait for async completion handler*/ 00520 return; 00521 } 00522 00523 00524 /* @brief fsm handler when in committing state */ 00525 void cfstore_flash_fsm_committing(void* context) 00526 { 00527 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00528 00529 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00530 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: entered handler(%s) but not in committing state (fsm->state=%d)\r\n", __func__, __func__, (int) ctx->fsm.state); 00531 TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flash_fsm_state_committing, cfstore_flash_utest_msg_g); 00532 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: cmd_code code (%d) is not as expected (%d)\r\n", __func__, ctx->cmd_code, FLASH_JOURNAL_OPCODE_COMMIT); 00533 TEST_ASSERT_MESSAGE(ctx->cmd_code == FLASH_JOURNAL_OPCODE_COMMIT, cfstore_flash_utest_msg_g); 00534 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%d\r\n", __func__, (int) ctx->status); 00535 TEST_ASSERT_MESSAGE(ctx->status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00536 00537 /* check the correct amount of data was written */ 00538 /* for flash-journal-strategy-sequential version >0.4.0, commit() return no longer reports size of commit block */ 00539 Harness::validate_callback(); 00540 } 00541 00542 /* @brief fsm handler when exiting committing state */ 00543 void cfstore_flash_fsm_commit_on_exit(void* context) 00544 { 00545 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00546 00547 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00548 /* test done. clean up*/ 00549 if(ctx->area_0_head){ 00550 CFSTORE_FREE(ctx->area_0_head); 00551 ctx->area_0_head = NULL; 00552 } 00553 Harness::validate_callback(); 00554 } 00555 00556 #define cfstore_flash_fsm_null NULL 00557 00558 /* handler functions while in state */ 00559 static cfstore_flash_fsm_handler cfstore_flash_fsm[cfstore_flash_fsm_state_max][cfstore_flash_fsm_event_max] = 00560 { 00561 /* state\event: init_done read_done write_done commit_done */ 00562 /* initialising */ {cfstore_flash_fsm_initializing, cfstore_flash_fsm_null, cfstore_flash_fsm_null, cfstore_flash_fsm_null }, 00563 /* reading */ {cfstore_flash_fsm_null, cfstore_flash_fsm_reading, cfstore_flash_fsm_null, cfstore_flash_fsm_null }, 00564 /* writing */ {cfstore_flash_fsm_null, cfstore_flash_fsm_null, cfstore_flash_fsm_writing, cfstore_flash_fsm_null }, 00565 /* committing */ {cfstore_flash_fsm_null, cfstore_flash_fsm_null, cfstore_flash_fsm_null, cfstore_flash_fsm_committing }, 00566 }; 00567 00568 00569 /* handler functions for entering the state*/ 00570 cfstore_flash_fsm_handler cfstore_flash_fsm_on_entry[cfstore_flash_fsm_state_max] = 00571 { 00572 cfstore_flash_fsm_init_on_entry, 00573 cfstore_flash_fsm_read_on_entry, 00574 cfstore_flash_fsm_write_on_entry, 00575 cfstore_flash_fsm_commit_on_entry, 00576 }; 00577 00578 /* handler functions for exiting state, currently none used */ 00579 cfstore_flash_fsm_handler cfstore_flash_fsm_on_exit[cfstore_flash_fsm_state_max] = 00580 { 00581 NULL, NULL, NULL, NULL, 00582 }; 00583 00584 00585 /* @brief inject event into fsm */ 00586 static void cfstore_fsm_state_handle_event(cfstore_fsm_t* fsm, cfstore_flash_fsm_event_t event, void* context) 00587 { 00588 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00589 00590 CFSTORE_FENTRYLOG("%s:entered: fsm=%p, event=%d (%s), ctx=%p\r\n", __func__, fsm, (int) event, cfstore_flash_event_str[event], ctx); 00591 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: invalid event (%d)\r\n", __func__, (int) event); 00592 TEST_ASSERT_MESSAGE(event < cfstore_flash_fsm_event_max, cfstore_flash_utest_msg_g); 00593 fsm->event = event; 00594 if(cfstore_flash_fsm[fsm->state][fsm->event] != NULL){ 00595 cfstore_flash_fsm[fsm->state][fsm->event](ctx); 00596 } 00597 00598 /* do not clear context data set by caller as it may be used later 00599 * fsm->event = cfstore_flash_fsm_event_max; 00600 * ctx->status = 0; 00601 * ctx->cmd_code = (FlashJournal_OpCode_t)((int) FLASH_JOURNAL_OPCODE_RESET+1); 00602 */ 00603 return; 00604 } 00605 00606 00607 /* @brief function to move to new fsm state, calling state exit function for old state and entry function for new state */ 00608 static void cfstore_fsm_state_set(cfstore_fsm_t* fsm, cfstore_flash_fsm_state_t new_state, void* ctx) 00609 { 00610 CFSTORE_FENTRYLOG("%s:entered: fsm=%p, new_state=%d, ctx=%p\r\n", __func__, fsm, (int) new_state, ctx); 00611 CFSTORE_DBGLOG("%s:FSM:REQ RX:%s:%s\r\n", __func__, cfstore_flash_state_str[fsm->state], cfstore_flash_state_str[new_state]); 00612 TEST_ASSERT_MESSAGE(fsm != NULL, "fsm is not a valid pointer"); 00613 TEST_ASSERT_MESSAGE(new_state < cfstore_flash_fsm_state_max, "new_state is not a valid state"); 00614 TEST_ASSERT_MESSAGE(ctx != NULL, "ctx is not a valid pointer"); 00615 TEST_ASSERT_MESSAGE(fsm->state < cfstore_flash_fsm_state_max, "fsm->state is not a valid state"); 00616 00617 if(cfstore_flash_fsm_on_exit[fsm->state] != NULL){ 00618 cfstore_flash_fsm_on_exit[fsm->state](ctx); 00619 } 00620 fsm->state = new_state; 00621 if(cfstore_flash_fsm_on_entry[new_state] != NULL){ 00622 cfstore_flash_fsm_on_entry[new_state](ctx); 00623 } 00624 CFSTORE_DBGLOG("%s:FSM:REQ DONE:\r\n", __func__); 00625 return; 00626 } 00627 00628 /* @brief initialize global context data structure */ 00629 static void cfstore_flash_ctx_init(cfstore_flash_ctx_t* ctx) 00630 { 00631 TEST_ASSERT_MESSAGE(ctx != NULL, "ctx is NULL"); 00632 00633 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00634 memset(&cfstore_flash_ctx_g, 0, sizeof(cfstore_flash_ctx_g)); 00635 } 00636 00637 00638 /* @brief asynchronous test 01 */ 00639 static control_t cfstore_flash_journal_async_test_01(void) 00640 { 00641 cfstore_flash_ctx_t* ctx = cfstore_flash_ctx_get(); 00642 00643 CFSTORE_FENTRYLOG("%s:entered: \r\n", __func__); 00644 cfstore_flash_mtd_async_ops_g = CFSTORE_FLASH_MTD_ASYNC_OPS_ON; 00645 cfstore_flash_ctx_init(ctx); 00646 cfstore_fsm_state_set(&ctx->fsm, cfstore_flash_fsm_state_initializing, ctx); 00647 00648 /* allow time for work to be done */ 00649 return CaseTimeout(CFSTORE_FLASH_CASE_TIMEOUT_MS); 00650 } 00651 00652 #endif /* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED */ 00653 00654 00655 /* report whether built/configured for flash sync or async mode */ 00656 static control_t cfstore_flash_test_00(const size_t call_count) 00657 { 00658 int32_t ret = ARM_DRIVER_ERROR; 00659 00660 (void) call_count; 00661 ret = cfstore_test_startup(); 00662 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to perform test startup (ret=%d).\n", __func__, (int) ret); 00663 TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flash_utest_msg_g); 00664 00665 #ifndef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED 00666 CFSTORE_LOG("INITIALIZING: BACKEND=SRAM. Skipping flash test%s", "\n"); 00667 #endif 00668 return CaseNext; 00669 } 00670 00671 /// @cond CFSTORE_DOXYGEN_DISABLE 00672 /* Specify all your test cases here */ 00673 Case cases[] = { 00674 Case("flash_journal_async_test_00", cfstore_flash_test_00), 00675 #ifdef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED 00676 Case("flash_journal_async_test_01", cfstore_flash_journal_async_test_01), 00677 #endif 00678 }; 00679 00680 00681 utest::v1::status_t greentea_setup(const size_t number_of_cases) 00682 { 00683 GREENTEA_SETUP(100, "default_auto"); 00684 return greentea_test_setup_handler(number_of_cases); 00685 } 00686 00687 /* Declare your test specification with a custom setup handler */ 00688 Specification specification(greentea_setup, cases); 00689 00690 00691 int main() 00692 { 00693 return !Harness::run(specification); 00694 } 00695 /// @endcond
Generated on Tue Jul 12 2022 13:04:59 by
1.7.2