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_MTD_K64F; 00092 00093 00094 /* KV data for test_01 */ 00095 static cfstore_kv_data_t cfstore_flush_test_01_kv_data[] = { 00096 { CFSTORE_TEST_DATA_KEYNAME, CFSTORE_TEST_DATA_VALUE_INIT}, 00097 { NULL, NULL}, 00098 }; 00099 00100 00101 /* @brief key value header structure defining key_name length, value length 00102 * @note 00103 * 8 bytes long */ 00104 typedef struct cfstore_area_header_t 00105 { 00106 uint32_t vlength; 00107 uint8_t klength; 00108 uint8_t perm_owner_read : 1; 00109 uint8_t perm_owner_write : 1; 00110 uint8_t perm_owner_execute : 1; 00111 uint8_t perm_other_read : 1; 00112 uint8_t perm_other_write : 1; 00113 uint8_t perm_other_execute : 1; 00114 uint8_t reserved : 2; 00115 uint8_t refcount; 00116 struct flags_t { 00117 uint8_t deleting : 1; 00118 uint8_t reserved : 7; 00119 } flags ; 00120 } cfstore_area_header_t ; 00121 00122 00123 /* @brief data structure for managing test data */ 00124 typedef struct cfstore_flash_data_blob_t { 00125 cfstore_area_header_t hdr; 00126 uint8_t data[CFSTORE_TEST_DATA_KEYNAME_SIZE + CFSTORE_TEST_DATA_VALUE_SIZE]; /* 61 bytes for key_name, 1 byte for value */ 00127 } cfstore_flash_data_blob_t; 00128 00129 /* 00130 * Defines 00131 * 00132 * CFSTORE_FLASH_AREA_SIZE_MIN 00133 * valid sizes of areas should always be greater than the size of the header, and therefore 00134 * greater than this value, which is defined as smaller than the header size 00135 */ 00136 #define CFSTORE_FLASH_AREA_SIZE_MIN (sizeof(cfstore_area_header_t) - 1) 00137 00138 /* 00139 * Shared implementation between sync and async tests 00140 */ 00141 00142 /* print key name string from area where key_name is not null terminated*/ 00143 static void cfstore_dump_key_name(uint8_t* keyname, uint8_t len, const char* tag) 00144 { 00145 char blob_data[CFSTORE_KEY_NAME_MAX_LENGTH]; 00146 00147 (void) tag; 00148 assert(keyname != NULL); 00149 assert(tag != NULL); 00150 assert(len > 0); 00151 memcpy(blob_data, keyname, len); 00152 blob_data[len] = '\0'; 00153 CFSTORE_DBGLOG("%s:keyname=%s\r\n", tag, blob_data); 00154 } 00155 00156 /* @brief test fsm states and events */ 00157 typedef enum cfstore_flash_fsm_state_t { 00158 cfstore_flash_fsm_state_initializing = 0, 00159 cfstore_flash_fsm_state_reading, 00160 cfstore_flash_fsm_state_writing, 00161 cfstore_flash_fsm_state_committing, 00162 cfstore_flash_fsm_state_max 00163 } cfstore_flash_fsm_state_t; 00164 00165 /* @brief test fsm events */ 00166 typedef enum cfstore_flash_fsm_event_t { 00167 cfstore_flash_fsm_event_init_done = 0, 00168 cfstore_flash_fsm_event_read_done, 00169 cfstore_flash_fsm_event_write_done, 00170 cfstore_flash_fsm_event_commit_done, 00171 cfstore_flash_fsm_event_max, 00172 } cfstore_flash_fsm_event_t; 00173 00174 typedef void (*cfstore_flash_fsm_handler)(void* ctx); 00175 00176 typedef struct cfstore_fsm_t 00177 { 00178 cfstore_flash_fsm_state_t state; 00179 cfstore_flash_fsm_event_t event; 00180 } cfstore_fsm_t; 00181 00182 typedef struct cfstore_flash_ctx_t 00183 { 00184 uint8_t* area_0_head; 00185 uint8_t* area_0_tail; 00186 FlashJournal_t jrnl; 00187 uint64_t expected_blob_size; 00188 cfstore_fsm_t fsm; 00189 int32_t status; 00190 FlashJournal_OpCode_t cmd_code; 00191 uint64_t expected_read_size; 00192 } cfstore_flash_ctx_t; 00193 00194 /* 00195 * Globals 00196 */ 00197 static cfstore_flash_ctx_t cfstore_flash_ctx_g; 00198 static const char* cfstore_flash_opcode_str[] = 00199 { 00200 "FLASH_JOURNAL_OPCODE_INITIALIZE", 00201 "FLASH_JOURNAL_OPCODE_GET_INFO", 00202 "FLASH_JOURNAL_OPCODE_READ_BLOB", 00203 "FLASH_JOURNAL_OPCODE_LOG_BLOB", 00204 "FLASH_JOURNAL_OPCODE_COMMIT", 00205 "FLASH_JOURNAL_OPCODE_RESET", 00206 }; 00207 00208 #ifdef CFSTORE_DEBUG 00209 static const char* cfstore_flash_state_str[] = 00210 { 00211 "initializing", 00212 "reading", 00213 "writing", 00214 "committing", 00215 "unknown" 00216 }; 00217 00218 static const char* cfstore_flash_event_str[] = 00219 { 00220 "init_done", 00221 "read_done", 00222 "write_done", 00223 "commit_done", 00224 "unknown" 00225 }; 00226 #endif /* CFSTORE_DEBUG */ 00227 00228 /* 00229 * Forward decl 00230 */ 00231 static void cfstore_fsm_state_handle_event(cfstore_fsm_t* fsm, cfstore_flash_fsm_event_t event, void* context); 00232 static void cfstore_fsm_state_set(cfstore_fsm_t* fsm, cfstore_flash_fsm_state_t new_state, void* ctx); 00233 00234 /* 00235 * context related methods 00236 */ 00237 00238 /* @brief get a pointer to the global context data structure */ 00239 static cfstore_flash_ctx_t* cfstore_flash_ctx_get(void) 00240 { 00241 return &cfstore_flash_ctx_g; 00242 } 00243 00244 00245 /* @brief flash journal asynchronous callback handler */ 00246 void cfstore_flash_test_01_callback(int32_t status, FlashJournal_OpCode_t cmd_code) 00247 { 00248 cfstore_flash_ctx_t* ctx = cfstore_flash_ctx_get(); 00249 00250 CFSTORE_FENTRYLOG("%s:entered: status=%d, cmd_code=%d (%s)\r\n", __func__, (int) status, (int) cmd_code, cfstore_flash_opcode_str[cmd_code]); 00251 switch(cmd_code) 00252 { 00253 case FLASH_JOURNAL_OPCODE_INITIALIZE: 00254 ctx->fsm.event = cfstore_flash_fsm_event_init_done; 00255 break; 00256 case FLASH_JOURNAL_OPCODE_READ_BLOB: 00257 ctx->fsm.event = cfstore_flash_fsm_event_read_done; 00258 break; 00259 case FLASH_JOURNAL_OPCODE_LOG_BLOB: 00260 ctx->fsm.event = cfstore_flash_fsm_event_write_done; 00261 break; 00262 case FLASH_JOURNAL_OPCODE_COMMIT: 00263 ctx->fsm.event = cfstore_flash_fsm_event_commit_done; 00264 break; 00265 case FLASH_JOURNAL_OPCODE_GET_INFO: 00266 case FLASH_JOURNAL_OPCODE_RESET: 00267 default: 00268 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"); 00269 TEST_ASSERT_MESSAGE(false, cfstore_flash_utest_msg_g) 00270 return; 00271 } 00272 ctx->status = status; 00273 ctx->cmd_code = cmd_code; 00274 cfstore_fsm_state_handle_event(&ctx->fsm, ctx->fsm.event, (void*) ctx); 00275 return; 00276 } 00277 00278 00279 /* @brief fsm handler called on entry to initializing state */ 00280 static void cfstore_flash_fsm_init_on_entry(void* context) 00281 { 00282 /* round up cfstore_flash_data_blob_t to nearest k64f program unit size */ 00283 const ARM_DRIVER_STORAGE *drv = &ARM_Driver_Storage_MTD_K64F; 00284 FlashJournal_Info_t info; 00285 FlashJournal_Status_t status = JOURNAL_STATUS_ERROR; 00286 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00287 00288 /* check that the mtd is in synchronous mode */ 00289 CFSTORE_FENTRYLOG("%s:entered: \r\n", __func__); 00290 memset(&info, 0, sizeof(info)); 00291 00292 /* FlashJournal_initialize() is potentially asynchronous */ 00293 status = (FlashJournal_Status_t) FlashJournal_initialize(&ctx->jrnl, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, cfstore_flash_test_01_callback); 00294 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); 00295 TEST_ASSERT_MESSAGE(status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00296 /* if status > 0, expect async callback, otherwise initialisation has been completed */ 00297 if(status > 0) { 00298 cfstore_flash_test_01_callback(status, FLASH_JOURNAL_OPCODE_INITIALIZE); 00299 } 00300 return; 00301 } 00302 00303 /* brief callback handler when in state initializing */ 00304 static void cfstore_flash_fsm_initializing(void* context) 00305 { 00306 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00307 00308 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00309 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); 00310 TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flash_fsm_state_initializing, cfstore_flash_utest_msg_g); 00311 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); 00312 TEST_ASSERT_MESSAGE(ctx->cmd_code == FLASH_JOURNAL_OPCODE_INITIALIZE, cfstore_flash_utest_msg_g); 00313 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); 00314 TEST_ASSERT_MESSAGE(ctx->status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00315 /* only change state if status > 0*/ 00316 if(ctx->status > 0){ 00317 cfstore_fsm_state_set(&ctx->fsm, cfstore_flash_fsm_state_reading, ctx); 00318 } 00319 } 00320 00321 /* static void cfstore_flash_fsm_init_on_exit(void* context){ (void) context;} */ 00322 00323 /* brief callback handler called when entering the reading state 00324 * note 00325 * flash journal has initialised successfully. now 00326 */ 00327 static void cfstore_flash_fsm_read_on_entry(void* context) 00328 { 00329 uint8_t* ptr = NULL; 00330 int32_t ret = 0; 00331 FlashJournal_Info_t info; 00332 FlashJournal_Status_t status = JOURNAL_STATUS_ERROR; 00333 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00334 00335 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00336 CFSTORE_ASSERT(ctx != NULL); 00337 /* drv->GetInfo() is synchronous */ 00338 status = FlashJournal_getInfo(&ctx->jrnl, &info); 00339 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); 00340 TEST_ASSERT_MESSAGE(status == JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00341 CFSTORE_DBGLOG("%s:FlashJournal_getInfo() done. info.sizeofJournaledBlob=%lu\r\n", __func__, (long unsigned int) info.sizeofJournaledBlob); 00342 00343 if(info.sizeofJournaledBlob > 0) 00344 { 00345 /* setup the expected blob size for writing 00346 * This is a multiple of program unit so the write doesnt fail due to unaligned log */ 00347 ctx->expected_blob_size = sizeof(cfstore_flash_data_blob_t); 00348 if(ctx->expected_blob_size % CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE > 0){ 00349 ctx->expected_blob_size += (CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE - (sizeof(cfstore_flash_data_blob_t) % CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE)); 00350 } 00351 /* test that a blob size is the expected size for flash data that has been written before */ 00352 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); 00353 TEST_ASSERT_EQUAL_INT64_MESSAGE(ctx->expected_blob_size, info.sizeofJournaledBlob, cfstore_flash_utest_msg_g); 00354 00355 /* grow the area by the size of the stored blob */ 00356 ptr = (uint8_t*) CFSTORE_REALLOC((void*) ctx->area_0_head, ctx->expected_blob_size); 00357 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); 00358 TEST_ASSERT_MESSAGE(ptr != NULL, cfstore_flash_utest_msg_g); 00359 memset(ptr, 0, ctx->expected_blob_size); 00360 if(ptr != ctx->area_0_head){ 00361 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); 00362 ctx->area_0_head = ptr; 00363 ctx->area_0_tail = ctx->area_0_head + info.sizeofJournaledBlob; 00364 } 00365 ret = FlashJournal_read(&ctx->jrnl, (void*) ctx->area_0_head, info.sizeofJournaledBlob); 00366 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); 00367 TEST_ASSERT_MESSAGE(ret >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00368 if(ret > 0){ 00369 /* read has completed synchronously*/ 00370 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); 00371 TEST_ASSERT_EQUAL_INT32_MESSAGE( (int32_t) info.sizeofJournaledBlob, ret, cfstore_flash_utest_msg_g); 00372 cfstore_flash_test_01_callback(ret, FLASH_JOURNAL_OPCODE_READ_BLOB); 00373 } 00374 } else { 00375 /* there is no blob, move to next state. need a +ve status value to indicate async completion 00376 * to the fsm reading state handler. use CFSTORE_FLASH_AREA_SIZE_MIN for this value */ 00377 ctx->expected_blob_size = CFSTORE_FLASH_AREA_SIZE_MIN; 00378 status = (FlashJournal_Status_t) CFSTORE_FLASH_AREA_SIZE_MIN; 00379 cfstore_flash_test_01_callback(status, FLASH_JOURNAL_OPCODE_READ_BLOB); 00380 } 00381 return; 00382 } 00383 00384 /* @brief fsm handler when in reading state */ 00385 void cfstore_flash_fsm_reading(void* context) 00386 { 00387 int32_t ret = 0; 00388 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00389 cfstore_flash_data_blob_t *blob = NULL; 00390 00391 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00392 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); 00393 TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flash_fsm_state_reading, cfstore_flash_utest_msg_g); 00394 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); 00395 TEST_ASSERT_MESSAGE(ctx->cmd_code == FLASH_JOURNAL_OPCODE_READ_BLOB, cfstore_flash_utest_msg_g); 00396 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); 00397 TEST_ASSERT_MESSAGE(ctx->status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00398 00399 if(ctx->status > 0) 00400 { 00401 if(ctx->status > (int32_t) CFSTORE_FLASH_AREA_SIZE_MIN) 00402 { 00403 /* check the correct amount of data was read, which is the status code */ 00404 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); 00405 /* ctx->status contains the status of the read that was completed */ 00406 TEST_ASSERT_EQUAL_INT64_MESSAGE(ctx->expected_blob_size, (int32_t) ctx->status, cfstore_flash_utest_msg_g); 00407 if(ctx->area_0_head != NULL) 00408 { 00409 /* check the key_name read from flash is correct */ 00410 blob = (cfstore_flash_data_blob_t*) ctx->area_0_head; 00411 cfstore_dump_key_name(blob->data, CFSTORE_TEST_DATA_KEYNAME_SIZE, __func__); 00412 ret = memcmp(blob->data, cfstore_flush_test_01_kv_data[0].key_name, strlen(cfstore_flush_test_01_kv_data[0].key_name)); 00413 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__); 00414 TEST_ASSERT_EQUAL_INT_MESSAGE(0, ret, cfstore_flash_utest_msg_g); 00415 } 00416 } 00417 cfstore_fsm_state_set(&ctx->fsm, cfstore_flash_fsm_state_writing, ctx); 00418 } 00419 } 00420 00421 /* void cfstore_flash_fsm_read_on_exit(void* context){ (void) context;} */ 00422 00423 /* @brief on entry to writing state, update value */ 00424 void cfstore_flash_fsm_write_on_entry(void* context) 00425 { 00426 uint8_t value = 0; 00427 int32_t ret = 0; 00428 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00429 cfstore_flash_data_blob_t *blob = NULL; 00430 00431 CFSTORE_FENTRYLOG("%s:entered:\r\n", __func__); 00432 /* allocate memory for data if not already done so */ 00433 if(ctx->area_0_head == NULL) 00434 { 00435 /* This is a multiple of program unit so the write doesnt fail due to unaligned log */ 00436 ctx->expected_blob_size = sizeof(cfstore_flash_data_blob_t); 00437 if(ctx->expected_blob_size % CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE > 0){ 00438 ctx->expected_blob_size += (CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE - (sizeof(cfstore_flash_data_blob_t) % CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE)); 00439 } 00440 ctx->area_0_head = (uint8_t*) CFSTORE_REALLOC((void*) ctx->area_0_head, ctx->expected_blob_size); 00441 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__); 00442 TEST_ASSERT_MESSAGE(ctx->area_0_head != NULL, cfstore_flash_utest_msg_g); 00443 ctx->area_0_tail = ctx->area_0_head + ctx->expected_blob_size; 00444 memset(ctx->area_0_head, 0, ctx->expected_blob_size); 00445 /* setup data to write to flash */ 00446 blob = (cfstore_flash_data_blob_t*) ctx->area_0_head; 00447 blob->hdr.klength = strlen(cfstore_flush_test_01_kv_data->key_name); 00448 blob->hdr.vlength= 1; 00449 blob->hdr.perm_owner_read = true; 00450 blob->hdr.perm_owner_write = true; 00451 blob->hdr.refcount = 1; 00452 memcpy((void*) blob->data, (const void*) cfstore_flush_test_01_kv_data->key_name, strlen(cfstore_flush_test_01_kv_data->key_name)); 00453 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)); 00454 } 00455 if(ctx->area_0_head != NULL) 00456 { 00457 /* data has been read */ 00458 /* check the key_name read from flash is correct */ 00459 blob = (cfstore_flash_data_blob_t*) ctx->area_0_head; 00460 value = (uint8_t) blob->data[CFSTORE_TEST_DATA_KEYNAME_SIZE]; 00461 CFSTORE_DBGLOG("INFO: value read from flash = %u\r\n", value); 00462 /* update the value */ 00463 value++; 00464 memcpy((void*) &blob->data[CFSTORE_TEST_DATA_KEYNAME_SIZE], (const void*) &value, sizeof(uint8_t)); 00465 } 00466 00467 ret = FlashJournal_log(&ctx->jrnl, (const void*) ctx->area_0_head, ctx->expected_blob_size); 00468 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__); 00469 TEST_ASSERT_MESSAGE(ret != (int32_t) JOURNAL_STATUS_SMALL_LOG_REQUEST, cfstore_flash_utest_msg_g); 00470 00471 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); 00472 TEST_ASSERT_MESSAGE(ret >= 0, cfstore_flash_utest_msg_g); 00473 if(ret > 0){ 00474 /* write has completed synchronously*/ 00475 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); 00476 TEST_ASSERT_EQUAL_INT32_MESSAGE(ret, (int32_t) ctx->expected_blob_size, cfstore_flash_utest_msg_g); 00477 cfstore_flash_test_01_callback(ret, FLASH_JOURNAL_OPCODE_LOG_BLOB); 00478 } 00479 /* wait for async completion handler*/ 00480 } 00481 00482 /* @brief fsm handler when in reading state */ 00483 void cfstore_flash_fsm_writing(void* context) 00484 { 00485 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00486 00487 CFSTORE_FENTRYLOG("%s:entered:\r\n", __func__); 00488 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); 00489 TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flash_fsm_state_writing, cfstore_flash_utest_msg_g); 00490 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); 00491 TEST_ASSERT_MESSAGE(ctx->cmd_code == FLASH_JOURNAL_OPCODE_LOG_BLOB, cfstore_flash_utest_msg_g); 00492 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); 00493 TEST_ASSERT_MESSAGE(ctx->status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00494 00495 if(ctx->status > 0){ 00496 /* check the correct amount of data was written */ 00497 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); 00498 TEST_ASSERT_EQUAL_INT64_MESSAGE(ctx->expected_blob_size, ctx->status, cfstore_flash_utest_msg_g); 00499 cfstore_fsm_state_set(&ctx->fsm, cfstore_flash_fsm_state_committing, ctx); 00500 } 00501 return; 00502 } 00503 00504 /* void cfstore_flash_fsm_write_on_exit(void* ctx){(void) ctx;} */ 00505 00506 /* @brief fsm handler when entering committing state */ 00507 void cfstore_flash_fsm_commit_on_entry(void* context) 00508 { 00509 int32_t ret = 0; 00510 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00511 00512 CFSTORE_FENTRYLOG("%s:entered:\r\n", __func__); 00513 ret = FlashJournal_commit(&ctx->jrnl); 00514 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); 00515 TEST_ASSERT_MESSAGE(ret >= (int32_t) JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00516 /* for flash-journal-strategy-sequential version >0.4.0, commit() return no longer reports size of commit block */ 00517 if(ret > 0){ 00518 Harness::validate_callback(); 00519 } 00520 /* wait for async completion handler*/ 00521 return; 00522 } 00523 00524 00525 /* @brief fsm handler when in committing state */ 00526 void cfstore_flash_fsm_committing(void* context) 00527 { 00528 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00529 00530 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00531 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); 00532 TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flash_fsm_state_committing, cfstore_flash_utest_msg_g); 00533 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); 00534 TEST_ASSERT_MESSAGE(ctx->cmd_code == FLASH_JOURNAL_OPCODE_COMMIT, cfstore_flash_utest_msg_g); 00535 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); 00536 TEST_ASSERT_MESSAGE(ctx->status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00537 00538 /* check the correct amount of data was written */ 00539 /* for flash-journal-strategy-sequential version >0.4.0, commit() return no longer reports size of commit block */ 00540 Harness::validate_callback(); 00541 } 00542 00543 /* @brief fsm handler when exiting committing state */ 00544 void cfstore_flash_fsm_commit_on_exit(void* context) 00545 { 00546 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00547 00548 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00549 /* test done. clean up*/ 00550 if(ctx->area_0_head){ 00551 CFSTORE_FREE(ctx->area_0_head); 00552 ctx->area_0_head = NULL; 00553 } 00554 Harness::validate_callback(); 00555 } 00556 00557 #define cfstore_flash_fsm_null NULL 00558 00559 /* handler functions while in state */ 00560 static cfstore_flash_fsm_handler cfstore_flash_fsm[cfstore_flash_fsm_state_max][cfstore_flash_fsm_event_max] = 00561 { 00562 /* state\event: init_done read_done write_done commit_done */ 00563 /* initialising */ {cfstore_flash_fsm_initializing, cfstore_flash_fsm_null, cfstore_flash_fsm_null, cfstore_flash_fsm_null }, 00564 /* reading */ {cfstore_flash_fsm_null, cfstore_flash_fsm_reading, cfstore_flash_fsm_null, cfstore_flash_fsm_null }, 00565 /* writing */ {cfstore_flash_fsm_null, cfstore_flash_fsm_null, cfstore_flash_fsm_writing, cfstore_flash_fsm_null }, 00566 /* committing */ {cfstore_flash_fsm_null, cfstore_flash_fsm_null, cfstore_flash_fsm_null, cfstore_flash_fsm_committing }, 00567 }; 00568 00569 00570 /* handler functions for entering the state*/ 00571 cfstore_flash_fsm_handler cfstore_flash_fsm_on_entry[cfstore_flash_fsm_state_max] = 00572 { 00573 cfstore_flash_fsm_init_on_entry, 00574 cfstore_flash_fsm_read_on_entry, 00575 cfstore_flash_fsm_write_on_entry, 00576 cfstore_flash_fsm_commit_on_entry, 00577 }; 00578 00579 /* handler functions for exiting state, currently none used */ 00580 cfstore_flash_fsm_handler cfstore_flash_fsm_on_exit[cfstore_flash_fsm_state_max] = 00581 { 00582 NULL, NULL, NULL, NULL, 00583 }; 00584 00585 00586 /* @brief inject event into fsm */ 00587 static void cfstore_fsm_state_handle_event(cfstore_fsm_t* fsm, cfstore_flash_fsm_event_t event, void* context) 00588 { 00589 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00590 00591 CFSTORE_FENTRYLOG("%s:entered: fsm=%p, event=%d (%s), ctx=%p\r\n", __func__, fsm, (int) event, cfstore_flash_event_str[event], ctx); 00592 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); 00593 TEST_ASSERT_MESSAGE(event < cfstore_flash_fsm_event_max, cfstore_flash_utest_msg_g); 00594 fsm->event = event; 00595 if(cfstore_flash_fsm[fsm->state][fsm->event] != NULL){ 00596 cfstore_flash_fsm[fsm->state][fsm->event](ctx); 00597 } 00598 00599 /* do not clear context data set by caller as it may be used later 00600 * fsm->event = cfstore_flash_fsm_event_max; 00601 * ctx->status = 0; 00602 * ctx->cmd_code = (FlashJournal_OpCode_t)((int) FLASH_JOURNAL_OPCODE_RESET+1); 00603 */ 00604 return; 00605 } 00606 00607 00608 /* @brief function to move to new fsm state, calling state exit function for old state and entry function for new state */ 00609 static void cfstore_fsm_state_set(cfstore_fsm_t* fsm, cfstore_flash_fsm_state_t new_state, void* ctx) 00610 { 00611 CFSTORE_FENTRYLOG("%s:entered: fsm=%p, new_state=%d, ctx=%p\r\n", __func__, fsm, (int) new_state, ctx); 00612 CFSTORE_DBGLOG("%s:FSM:REQ RX:%s:%s\r\n", __func__, cfstore_flash_state_str[fsm->state], cfstore_flash_state_str[new_state]); 00613 TEST_ASSERT_MESSAGE(fsm != NULL, "fsm is not a valid pointer"); 00614 TEST_ASSERT_MESSAGE(new_state < cfstore_flash_fsm_state_max, "new_state is not a valid state"); 00615 TEST_ASSERT_MESSAGE(ctx != NULL, "ctx is not a valid pointer"); 00616 TEST_ASSERT_MESSAGE(fsm->state < cfstore_flash_fsm_state_max, "fsm->state is not a valid state"); 00617 00618 if(cfstore_flash_fsm_on_exit[fsm->state] != NULL){ 00619 cfstore_flash_fsm_on_exit[fsm->state](ctx); 00620 } 00621 fsm->state = new_state; 00622 if(cfstore_flash_fsm_on_entry[new_state] != NULL){ 00623 cfstore_flash_fsm_on_entry[new_state](ctx); 00624 } 00625 CFSTORE_DBGLOG("%s:FSM:REQ DONE:\r\n", __func__); 00626 return; 00627 } 00628 00629 /* @brief initialize global context data structure */ 00630 static void cfstore_flash_ctx_init(cfstore_flash_ctx_t* ctx) 00631 { 00632 TEST_ASSERT_MESSAGE(ctx != NULL, "ctx is NULL"); 00633 00634 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00635 memset(&cfstore_flash_ctx_g, 0, sizeof(cfstore_flash_ctx_g)); 00636 } 00637 00638 00639 /* @brief asynchronous test 01 */ 00640 static control_t cfstore_flash_journal_async_test_01(void) 00641 { 00642 cfstore_flash_ctx_t* ctx = cfstore_flash_ctx_get(); 00643 00644 CFSTORE_FENTRYLOG("%s:entered: \r\n", __func__); 00645 cfstore_flash_mtd_async_ops_g = CFSTORE_FLASH_MTD_ASYNC_OPS_ON; 00646 cfstore_flash_ctx_init(ctx); 00647 cfstore_fsm_state_set(&ctx->fsm, cfstore_flash_fsm_state_initializing, ctx); 00648 00649 /* allow time for work to be done */ 00650 return CaseTimeout(CFSTORE_FLASH_CASE_TIMEOUT_MS); 00651 } 00652 00653 #endif /* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED */ 00654 00655 00656 /* report whether built/configured for flash sync or async mode */ 00657 static control_t cfstore_flash_test_00(const size_t call_count) 00658 { 00659 int32_t ret = ARM_DRIVER_ERROR; 00660 00661 (void) call_count; 00662 ret = cfstore_test_startup(); 00663 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); 00664 TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flash_utest_msg_g); 00665 00666 #ifndef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED 00667 CFSTORE_LOG("INITIALIZING: BACKEND=SRAM. Skipping flash test%s", "\n"); 00668 #endif 00669 return CaseNext; 00670 } 00671 00672 /// @cond CFSTORE_DOXYGEN_DISABLE 00673 /* Specify all your test cases here */ 00674 Case cases[] = { 00675 Case("flash_journal_async_test_00", cfstore_flash_test_00), 00676 #ifdef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED 00677 Case("flash_journal_async_test_01", cfstore_flash_journal_async_test_01), 00678 #endif 00679 }; 00680 00681 00682 utest::v1::status_t greentea_setup(const size_t number_of_cases) 00683 { 00684 GREENTEA_SETUP(100, "default_auto"); 00685 return greentea_test_setup_handler(number_of_cases); 00686 } 00687 00688 /* Declare your test specification with a custom setup handler */ 00689 Specification specification(greentea_setup, cases); 00690 00691 00692 int main() 00693 { 00694 return !Harness::run(specification); 00695 } 00696 /// @endcond
Generated on Tue Jul 12 2022 18:18:35 by
