Rtos API example

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 #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