takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers flash.cpp Source File

flash.cpp

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