Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers flush.cpp Source File

flush.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 flush.cpp Test cases to flush KVs in the CFSTORE using the drv->Flush() interface.
00019  *
00020  * Please consult the documentation under the test-case functions for
00021  * a description of the individual test case.
00022  */
00023 
00024 #if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
00025 
00026 
00027 #include "mbed.h"
00028 #include "cfstore_config.h"
00029 #include "Driver_Common.h"
00030 #include "cfstore_debug.h"
00031 #include "cfstore_test.h"
00032 #include "configuration_store.h"
00033 #include "utest/utest.h"
00034 #include "unity/unity.h"
00035 #include "greentea-client/test_env.h"
00036 #ifdef YOTTA_CFG_CFSTORE_UVISOR
00037 #include "uvisor-lib/uvisor-lib.h"
00038 #include "cfstore_uvisor.h"
00039 #endif /* YOTTA_CFG_CFSTORE_UVISOR */
00040 
00041 #include <stdio.h>
00042 #include <stdlib.h>
00043 #include <string.h>
00044 #include <inttypes.h>
00045 
00046 using namespace utest::v1;
00047 
00048 static control_t cfstore_flush_test_00(const size_t call_count)
00049 {
00050     (void) call_count;
00051     CFSTORE_LOG("%s:Not implemented for ARM toolchain\n", __func__);
00052     return CaseNext;
00053 }
00054 
00055 
00056 utest::v1::status_t greentea_setup(const size_t number_of_cases)
00057 {
00058     GREENTEA_SETUP(100, "default_auto");
00059     return greentea_test_setup_handler(number_of_cases);
00060 }
00061 
00062 Case cases[] = {
00063            /*          1         2         3         4         5         6        7  */
00064            /* 1234567890123456789012345678901234567890123456789012345678901234567890 */
00065         Case("FLUSH_test_00", cfstore_flush_test_00),
00066 };
00067 
00068 
00069 /* Declare your test specification with a custom setup handler */
00070 Specification specification(greentea_setup, cases);
00071 
00072 int main()
00073 {
00074     return !Harness::run(specification);
00075 }
00076 
00077 
00078 #else
00079 
00080 
00081 
00082 #include "mbed.h"
00083 #include "cfstore_config.h"
00084 #include "cfstore_test.h"
00085 #include "cfstore_debug.h"
00086 #include "Driver_Common.h"
00087 #include "configuration_store.h"
00088 #include "utest/utest.h"
00089 #include "unity/unity.h"
00090 #include "greentea-client/test_env.h"
00091 #ifdef YOTTA_CFG_CFSTORE_UVISOR
00092 #include "uvisor-lib/uvisor-lib.h"
00093 #endif /* YOTTA_CFG_CFSTORE_UVISOR */
00094 
00095 #include <stdio.h>
00096 #include <stdlib.h>
00097 #include <string.h>
00098 #include <inttypes.h>
00099 
00100 using namespace utest::v1;
00101 
00102 /*
00103  * Defines
00104  */
00105 /// @cond CFSTORE_DOXYGEN_DISABLE
00106 #define CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE                256
00107 #define cfstore_flush_fsm_null                          NULL
00108 #define CFSTORE_FLUSH_CASE_TIMEOUT_MS                   10000
00109 #define CFSTORE_FLUSH_FSM_LOOPS                         20
00110 
00111 #ifdef CFSTORE_DEBUG
00112 #define CFSTORE_FLUSH_GREENTEA_TIMEOUT_S     360
00113 #else
00114 #define CFSTORE_FLUSH_GREENTEA_TIMEOUT_S     60
00115 #endif
00116 
00117 /*
00118  * Globals
00119  *
00120  * cfstore_flush_utest_msg_g
00121  *  buffer for storing TEST_ASSERT_xxx_MESSAGE messages
00122  */
00123 char cfstore_flush_utest_msg_g[CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE];
00124 
00125 /* Configure secure box. */
00126 #ifdef YOTTA_CFG_CFSTORE_UVISOR
00127 UVISOR_BOX_NAMESPACE("com.arm.mbed.cfstore.test.flush.box1");
00128 UVISOR_BOX_CONFIG(cfstore_flush_box1, UVISOR_BOX_STACK_SIZE);
00129 #endif /* YOTTA_CFG_CFSTORE_UVISOR */
00130 
00131 
00132 
00133 
00134 #ifdef TARGET_LIKE_X86_LINUX_NATIVE
00135 
00136 /** @brief  basic Flush() test
00137  *
00138  * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
00139  */
00140 int32_t cfstore_flush_test_01_x86_sync(void)
00141 {
00142     int32_t ret = ARM_DRIVER_ERROR;
00143     ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
00144 
00145     ret = drv->Initialize(NULL, NULL);
00146     if(ret != ARM_DRIVER_OK){
00147         CFSTORE_ERRLOG("%s:Initialize() call failed (ret=%d).\r\n", __func__, (int) ret);
00148         goto out0;
00149     }
00150     ret = drv->Flush();
00151     if(ret != ARM_DRIVER_OK){
00152         CFSTORE_ERRLOG("%s:Flush() call failed (ret=%d).\r\n", __func__, (int) ret);
00153     }
00154     ret = drv->Uninitialize();
00155     if(ret != ARM_DRIVER_OK){
00156         CFSTORE_ERRLOG("%s:Initialize() call failed to Uninitialise(ret=%d).\r\n", __func__, (int) ret);
00157         goto out0;
00158     }
00159  out0:
00160     return ret;
00161 }
00162 #endif /* TARGET_LIKE_X86_LINUX_NATIVE */
00163 
00164 /* KV data for test_03 */
00165 static cfstore_kv_data_t cfstore_flush_test_02_kv_data[] = {
00166         { "com.arm.mbed.configurationstore.test.flush.cfstoreflushtest02", "1"},
00167         /*          1         2         3         4         5         6        7  */
00168         /* 1234567890123456789012345678901234567890123456789012345678901234567890 */
00169         { NULL, NULL},
00170 };
00171 
00172 
00173 /* async test version */
00174 
00175 /* @brief  test fsm states and events */
00176 typedef enum cfstore_flush_fsm_state_t {
00177     cfstore_flush_fsm_state_stopped = 0,
00178     cfstore_flush_fsm_state_initializing,
00179     cfstore_flush_fsm_state_flushing,
00180     cfstore_flush_fsm_state_uninitializing,
00181     cfstore_flush_fsm_state_max
00182 } cfstore_flush_fsm_state_t;
00183 
00184 /* @brief  test fsm events */
00185 typedef enum cfstore_flush_fsm_event_t {
00186     cfstore_flush_fsm_event_init_done = 0,
00187     cfstore_flush_fsm_event_flush_done,
00188     cfstore_flush_fsm_event_uninit_done,
00189     cfstore_flush_fsm_event_max,
00190 } cfstore_flush_fsm_event_t;
00191 
00192 typedef void (*cfstore_flush_fsm_handler)(void* ctx);
00193 
00194 /// @cond CFSTORE_DOXYGEN_DISABLE
00195 typedef struct cfstore_fsm_t
00196 {
00197     cfstore_flush_fsm_state_t state;
00198     cfstore_flush_fsm_event_t event;
00199 } cfstore_fsm_t;
00200 /// @endcond
00201 
00202 /// @cond CFSTORE_DOXYGEN_DISABLE
00203 typedef struct cfstore_flush_ctx_t
00204 {
00205     int32_t loops_done;
00206     cfstore_fsm_t fsm;
00207     int32_t status;
00208     ARM_CFSTORE_OPCODE cmd_code;
00209 } cfstore_flush_ctx_t;
00210 /// @endcond
00211 
00212 
00213 /*
00214  * Globals
00215  */
00216 static cfstore_flush_ctx_t cfstore_flush_ctx_g;
00217 
00218 #ifdef CFSTORE_DEBUG
00219 static const char* cfstore_flush_state_str[] =
00220 {
00221     "stopped",
00222     "initializing",
00223     "flushing",
00224     "uninitializing",
00225     "unknown"
00226 };
00227 
00228 static const char* cfstore_flush_event_str[] =
00229 {
00230     "init_done",
00231     "flush_done",
00232     "uninit_done",
00233     "unknown"
00234 };
00235 #endif
00236 
00237 /// @endcond
00238 
00239 /*
00240  * Forward decl
00241  */
00242 static void cfstore_flush_fsm_state_handle_event(cfstore_fsm_t* fsm, cfstore_flush_fsm_event_t event, void* context);
00243 static void cfstore_flush_fsm_state_set(cfstore_fsm_t* fsm, cfstore_flush_fsm_state_t new_state, void* ctx);
00244 /*
00245  * context related methods
00246  */
00247 
00248 /* @brief   get a pointer to the global context data structure */
00249 static cfstore_flush_ctx_t* cfstore_flush_ctx_get(void)
00250 {
00251     return &cfstore_flush_ctx_g;
00252 }
00253 
00254 /* @brief   initialize global context data structure */
00255 static void cfstore_flush_ctx_init(cfstore_flush_ctx_t* ctx)
00256 {
00257     TEST_ASSERT_MESSAGE(ctx != NULL, "ctx is NULL");
00258 
00259     CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
00260     memset(&cfstore_flush_ctx_g, 0, sizeof(cfstore_flush_ctx_g));
00261 }
00262 
00263 
00264 /* @brief   cfstore asynchronous callback handler */
00265 void cfstore_flush_test_01_callback(int32_t status, ARM_CFSTORE_OPCODE cmd_code, void *client_context, ARM_CFSTORE_HANDLE  handle)
00266 {
00267     cfstore_flush_ctx_t* ctx = (cfstore_flush_ctx_t*) client_context;
00268 
00269     CFSTORE_FENTRYLOG("%s:entered: status=%d, cmd_code=%d (%s) ctx=%p, handle=%p\r\n", __func__, (int) status, (int) cmd_code, cfstore_test_opcode_str[cmd_code], ctx, handle);
00270     (void) handle;
00271     switch(cmd_code)
00272     {
00273     case CFSTORE_OPCODE_INITIALIZE:
00274         ctx->fsm.event = cfstore_flush_fsm_event_init_done;
00275         break;
00276     case CFSTORE_OPCODE_FLUSH:
00277         ctx->fsm.event = cfstore_flush_fsm_event_flush_done;
00278         break;
00279     case CFSTORE_OPCODE_UNINITIALIZE:
00280         ctx->fsm.event = cfstore_flush_fsm_event_uninit_done;
00281         break;
00282     case CFSTORE_OPCODE_CLOSE:
00283     case CFSTORE_OPCODE_CREATE:
00284     case CFSTORE_OPCODE_DELETE:
00285     case CFSTORE_OPCODE_FIND:
00286     case CFSTORE_OPCODE_GET_KEY_NAME:
00287     case CFSTORE_OPCODE_GET_STATUS:
00288     case CFSTORE_OPCODE_GET_VALUE_LEN:
00289     case CFSTORE_OPCODE_OPEN:
00290     case CFSTORE_OPCODE_POWER_CONTROL:
00291     case CFSTORE_OPCODE_READ:
00292     case CFSTORE_OPCODE_RSEEK:
00293     case CFSTORE_OPCODE_WRITE:
00294     default:
00295         CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:WARN: received asynchronous notification for opcode=%d (%s) when api call should have been synchronous", __func__, cmd_code, cmd_code < CFSTORE_OPCODE_MAX ? cfstore_test_opcode_str[cmd_code] : "unknown");
00296         CFSTORE_DBGLOG("%s:WARN: received asynchronous notification for opcode=%d (%s) when api call should have been synchronous", __func__, cmd_code, cmd_code < CFSTORE_OPCODE_MAX ? cfstore_test_opcode_str[cmd_code] : "unknown");
00297         /* TEST_ASSERT_MESSAGE(false, cfstore_flush_utest_msg_g) */
00298         return;
00299     }
00300     ctx->status = status;
00301     ctx->cmd_code = cmd_code;
00302     cfstore_flush_fsm_state_handle_event(&ctx->fsm, ctx->fsm.event, client_context);
00303     return;
00304 }
00305 
00306 /* @brief  fsm handler called on entry to stopping state */
00307 static void cfstore_flush_fsm_stop_on_entry(void* context)
00308 {
00309     (void) context;
00310     CFSTORE_FENTRYLOG("%s:entered:\r\n", __func__);
00311     Harness::validate_callback();
00312     return;
00313 }
00314 
00315 /* @brief  fsm handler called on entry to initializing state */
00316 static void cfstore_flush_fsm_init_on_entry(void* context)
00317 {
00318     int32_t ret = ARM_DRIVER_ERROR;
00319     cfstore_flush_ctx_t* ctx = (cfstore_flush_ctx_t*) context;
00320     const ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
00321 
00322     /* check that the mtd is in synchronous mode */
00323     CFSTORE_FENTRYLOG("%s:entered: callback=%p, ctx=%p\r\n", __func__, cfstore_flush_test_01_callback, ctx);
00324     ret = drv->Initialize(cfstore_flush_test_01_callback, ctx);
00325     CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to initialize CFSTORE (ret=%d)\r\n", __func__, (int) ret);
00326     TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
00327     CFSTORE_DBGLOG("%s:debug: ret=%d\r\n", __func__, (int) ret);
00328     return;
00329 }
00330 
00331 /* brief    callback handler when in state initializing */
00332 static void cfstore_flush_fsm_initializing(void* context)
00333 {
00334     cfstore_flush_ctx_t* ctx = (cfstore_flush_ctx_t*) context;
00335 
00336     CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
00337     CFSTORE_FENTRYLOG("%s:entered: status = %d\r\n", __func__, (int) ctx->status);
00338     CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_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);
00339     TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flush_fsm_state_initializing, cfstore_flush_utest_msg_g);
00340     CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: cmd_code code (%d) is not as expected (%d)\r\n", __func__, ctx->cmd_code, CFSTORE_OPCODE_INITIALIZE);
00341     TEST_ASSERT_MESSAGE(ctx->cmd_code == CFSTORE_OPCODE_INITIALIZE, cfstore_flush_utest_msg_g);
00342     CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%d\r\n", __func__, (int) ctx->status);
00343     TEST_ASSERT_MESSAGE(ctx->status >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
00344     /* only change state if status >= 0*/
00345     if(ctx->status >= 0){
00346         cfstore_flush_fsm_state_set(&ctx->fsm, cfstore_flush_fsm_state_flushing, ctx);
00347     }
00348     return;
00349 }
00350 
00351 /* static void cfstore_flush_fsm_init_on_exit(void* context){ (void) context;} */
00352 
00353 
00354 /* @brief  fsm handler called on entry to flushing state */
00355 static void cfstore_flush_fsm_flush_on_entry(void* context)
00356 {
00357     bool bfound = false;
00358     int32_t ivalue = 0;
00359     int32_t ret = ARM_DRIVER_ERROR;
00360     ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
00361     const char* key_name_query = "*";
00362     char value[CFSTORE_KEY_NAME_MAX_LENGTH+1];
00363     ARM_CFSTORE_SIZE len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
00364     ARM_CFSTORE_HANDLE_INIT(next);
00365     ARM_CFSTORE_HANDLE_INIT(prev);
00366     ARM_CFSTORE_KEYDESC kdesc;
00367     cfstore_flush_ctx_t* ctx = (cfstore_flush_ctx_t*) context;
00368 
00369     /* check that the mtd is in synchronous mode */
00370     CFSTORE_FENTRYLOG("%s:entered: \r\n", __func__);
00371     memset(&kdesc, 0, sizeof(kdesc));
00372 
00373     CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: entered handler(%s) but not in flushing state (fsm->state=%d)\r\n", __func__, __func__, (int) ctx->fsm.state);
00374     TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flush_fsm_state_flushing, cfstore_flush_utest_msg_g);
00375     /* try to read key; should not be found */
00376     ret = cfstore_test_kv_is_found(cfstore_flush_test_02_kv_data->key_name, &bfound);
00377     if(ret != ARM_DRIVER_OK && ret != ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND){
00378         CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: cfstore_test_kv_is_found() call failed (ret=%d).\r\n", __func__, (int) ret);
00379         TEST_ASSERT_MESSAGE(false, cfstore_flush_utest_msg_g);
00380     }
00381 
00382     if(!bfound)
00383     {
00384         /* first time start up. nothing is stored in cfstore flash. check this is the case */
00385         while(drv->Find(key_name_query, prev, next) == ARM_DRIVER_OK)
00386         {
00387             CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: have found an entry in cfstore when none should be present", __func__);
00388             TEST_ASSERT_MESSAGE(false, cfstore_flush_utest_msg_g);
00389         }
00390         /* no entries found, which is correct.
00391          * store a value */
00392         len = strlen(cfstore_flush_test_02_kv_data->value);
00393         ret = cfstore_test_create(cfstore_flush_test_02_kv_data->key_name, cfstore_flush_test_02_kv_data->value, &len, &kdesc);
00394         CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error:1: failed to write kv data (ret=%d).\r\n", __func__, (int) ret);
00395         TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
00396         /* flush to flash */
00397         ret = drv->Flush();
00398         CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to flush data to cfstore flash (ret=%d).\r\n", __func__, (int) ret);
00399         TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
00400         /* revert to CFSTORE_LOG if more trace required */
00401         CFSTORE_DBGLOG("FLUSH: Success pending for new KV creation (name=%s, value=%s)\n", cfstore_flush_test_02_kv_data->key_name, cfstore_flush_test_02_kv_data->value);
00402     } else {
00403         /*read the value, increment by 1 and write value back */
00404         len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
00405         ret = cfstore_test_read(cfstore_flush_test_02_kv_data->key_name, value, &len);
00406         CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to read kv data (ret=%d).\r\n", __func__, (int) ret);
00407         TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
00408 
00409         ivalue = atoi(value);
00410         /* revert to CFSTORE_LOG if more trace required */
00411         CFSTORE_DBGLOG("FLUSH: Read KV from flash (name=%s, value=%d)\n", cfstore_flush_test_02_kv_data->key_name, (int) ivalue);
00412         /* increment value */
00413         ++ivalue;
00414         snprintf(value, CFSTORE_KEY_NAME_MAX_LENGTH+1, "%d", (int) ivalue);
00415         len = strlen(value);
00416         ret = cfstore_test_write(cfstore_flush_test_02_kv_data->key_name, value, &len);
00417         CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write kv data (ret=%d).\r\n", __func__, (int) ret);
00418         TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
00419 
00420         /* flush to flash */
00421         ret = drv->Flush();
00422         CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to flush data to cfstore flash (ret=%d).\r\n", __func__, (int) ret);
00423         TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
00424         /* revert to CFSTORE_LOG if more trace required */
00425         CFSTORE_DBGLOG("FLUSH: Success pending for new KV value to flash (name=%s, value=%d)\n", cfstore_flush_test_02_kv_data->key_name, (int) ivalue);
00426     }
00427     return;
00428 }
00429 
00430 
00431 /* brief    callback handler when in state flushing */
00432 static void cfstore_flush_fsm_flushing(void* context)
00433 {
00434     cfstore_flush_ctx_t* ctx = (cfstore_flush_ctx_t*) context;
00435 
00436     CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
00437     CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: entered handler(%s) but not in flushing state (fsm->state=%d)\r\n", __func__, __func__, (int) ctx->fsm.state);
00438     TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flush_fsm_state_flushing, cfstore_flush_utest_msg_g);
00439     CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: cmd_code code (%d) is not as expected (%d)\r\n", __func__, ctx->cmd_code, CFSTORE_OPCODE_FLUSH);
00440     TEST_ASSERT_MESSAGE(ctx->cmd_code == CFSTORE_OPCODE_FLUSH, cfstore_flush_utest_msg_g);
00441     CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%d\r\n", __func__, (int) ctx->status);
00442     TEST_ASSERT_MESSAGE(ctx->status >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
00443     /* only change state if status >= 0*/
00444     if(ctx->status >= 0){
00445         /* revert to CFSTORE_LOG if more trace required */
00446         CFSTORE_DBGLOG("FLUSH: Successfully flushed data to flash.%s", "\n");
00447         cfstore_flush_fsm_state_set(&ctx->fsm, cfstore_flush_fsm_state_uninitializing, ctx);
00448     }
00449     return;
00450 }
00451 
00452 /* static void cfstore_flush_fsm_flush_on_exit(void* context){ (void) context;} */
00453 
00454 
00455 /* @brief  fsm handler called on entry to uninitializing state */
00456 static void cfstore_flush_fsm_uninit_on_entry(void* context)
00457 {
00458     int32_t ret = ARM_DRIVER_ERROR;
00459     cfstore_flush_ctx_t* ctx = (cfstore_flush_ctx_t*) context;
00460     const ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
00461 
00462     /* check that the mtd is in synchronous mode */
00463     CFSTORE_FENTRYLOG("%s:entered: \r\n", __func__);
00464     CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: entered handler(%s) but not in uninitializing state (fsm->state=%d)\r\n", __func__, __func__, (int) ctx->fsm.state);
00465     TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flush_fsm_state_uninitializing, cfstore_flush_utest_msg_g);
00466     ret = drv->Uninitialize();
00467     CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to uninitialize CFSTORE (ret=%d)\r\n", __func__, (int) ret);
00468     TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
00469     return;
00470 }
00471 
00472 /* brief    callback handler when in state uninitializing */
00473 static void cfstore_flush_fsm_uninitializing(void* context)
00474 {
00475     cfstore_flush_ctx_t* ctx = (cfstore_flush_ctx_t*) context;
00476 
00477     CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
00478     CFSTORE_DBGLOG("%s:ctx->status=%d, ctx->loops_done=%d\r\n", __func__, (int) ctx->status, (int) ctx->loops_done);
00479     CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: entered handler(%s) but not in uninitializing state (fsm->state=%d)\r\n", __func__, __func__, (int) ctx->fsm.state);
00480     TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flush_fsm_state_uninitializing, cfstore_flush_utest_msg_g);
00481     CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: cmd_code code (%d) is not as expected (%d)\r\n", __func__, ctx->cmd_code, CFSTORE_OPCODE_UNINITIALIZE);
00482     TEST_ASSERT_MESSAGE(ctx->cmd_code == CFSTORE_OPCODE_UNINITIALIZE, cfstore_flush_utest_msg_g);
00483     CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%d\r\n", __func__, (int) ctx->status);
00484     TEST_ASSERT_MESSAGE(ctx->status >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
00485     /* only change state if status >= 0*/
00486     if(ctx->status >= ARM_DRIVER_OK){
00487         ++ctx->loops_done;
00488         if(ctx->loops_done < CFSTORE_FLUSH_FSM_LOOPS){
00489             cfstore_flush_fsm_state_set(&ctx->fsm, cfstore_flush_fsm_state_initializing, ctx);
00490         } else {
00491             /* move to init state */
00492             cfstore_flush_fsm_state_set(&ctx->fsm, cfstore_flush_fsm_state_stopped, ctx);
00493         }
00494     }
00495     return;
00496 }
00497 
00498 /* static void cfstore_flush_fsm_uninit_on_exit(void* context) {(void)context;} */
00499 
00500 
00501 
00502 /* handler functions while in state */
00503 static cfstore_flush_fsm_handler cfstore_flush_fsm[cfstore_flush_fsm_state_max][cfstore_flush_fsm_event_max] =
00504 {
00505 /* state\event:         init_done                           flush_done                      unint_done */
00506 /* stopped          */  {cfstore_flush_fsm_null,            cfstore_flush_fsm_null,         cfstore_flush_fsm_null              },
00507 /* initialising     */  {cfstore_flush_fsm_initializing,    cfstore_flush_fsm_null,         cfstore_flush_fsm_null              },
00508 /* flushing         */  {cfstore_flush_fsm_null,            cfstore_flush_fsm_flushing,     cfstore_flush_fsm_null              },
00509 /* uninitializing   */  {cfstore_flush_fsm_null,            cfstore_flush_fsm_null,         cfstore_flush_fsm_uninitializing    }
00510 };
00511 
00512 
00513 /* handler functions for entering the state*/
00514 static cfstore_flush_fsm_handler cfstore_flush_fsm_on_entry[cfstore_flush_fsm_state_max] =
00515 {
00516     cfstore_flush_fsm_stop_on_entry,
00517     cfstore_flush_fsm_init_on_entry,
00518     cfstore_flush_fsm_flush_on_entry,
00519     cfstore_flush_fsm_uninit_on_entry
00520 };
00521 
00522 /* handler functions for exiting state, currently none used */
00523 static cfstore_flush_fsm_handler cfstore_flush_fsm_on_exit[cfstore_flush_fsm_state_max] =
00524 {
00525     cfstore_flush_fsm_null,
00526     cfstore_flush_fsm_null,
00527     cfstore_flush_fsm_null,
00528     cfstore_flush_fsm_null
00529 };
00530 
00531 
00532 /* @brief   inject event into fsm */
00533 static void cfstore_flush_fsm_state_handle_event(cfstore_fsm_t* fsm, cfstore_flush_fsm_event_t event, void* context)
00534 {
00535     cfstore_flush_ctx_t* ctx = (cfstore_flush_ctx_t*) context;
00536 
00537     CFSTORE_FENTRYLOG("%s:entered: fsm=%p, state=(%s), event=%d (%s), ctx=%p\r\n", __func__, fsm, cfstore_flush_state_str[fsm->state], (int) event, cfstore_flush_event_str[event], ctx);
00538     CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: invalid event (%d)\r\n", __func__, (int) event);
00539     TEST_ASSERT_MESSAGE(event < cfstore_flush_fsm_event_max, cfstore_flush_utest_msg_g);
00540     fsm->event = event;
00541     if(cfstore_flush_fsm[fsm->state][fsm->event] != NULL){
00542         cfstore_flush_fsm[fsm->state][fsm->event](ctx);
00543     }
00544 
00545     /* do not clear context data set by caller as it may be used later
00546      *  fsm->event = cfstore_flush_fsm_event_max;
00547      *  ctx->status = 0;
00548      *  ctx->cmd_code =  (FlashJournal_OpCode_t)((int) FLASH_JOURNAL_OPCODE_RESET+1);
00549      */
00550     return;
00551 }
00552 
00553 
00554 /* @brief   function to move to new fsm state, calling state exit function for old state and entry function for new state */
00555 static void cfstore_flush_fsm_state_set(cfstore_fsm_t* fsm, cfstore_flush_fsm_state_t new_state, void* ctx)
00556 {
00557     #ifdef CFSTORE_DEBUG
00558     cfstore_flush_fsm_state_t old_state = fsm->state;
00559     #endif
00560 
00561     CFSTORE_FENTRYLOG("%s:entered: fsm=%p, ctx=%p\r\n", __func__, fsm, ctx);
00562     #ifdef CFSTORE_DEBUG
00563     CFSTORE_DBGLOG("%s:FSM:REQ RX:%s:%s\r\n", __func__, cfstore_flush_state_str[fsm->state], cfstore_flush_state_str[new_state]);
00564     #endif
00565     TEST_ASSERT_MESSAGE(fsm != NULL, "fsm is not a valid pointer");
00566     TEST_ASSERT_MESSAGE(new_state < cfstore_flush_fsm_state_max, "new_state is not a valid state");
00567     TEST_ASSERT_MESSAGE(ctx != NULL, "ctx is not a valid pointer");
00568     TEST_ASSERT_MESSAGE(fsm->state < cfstore_flush_fsm_state_max, "fsm->state is not a valid state");
00569 
00570     if(cfstore_flush_fsm_on_exit[fsm->state] != NULL){
00571         cfstore_flush_fsm_on_exit[fsm->state](ctx);
00572     }
00573     fsm->state = new_state;
00574     if(cfstore_flush_fsm_on_entry[new_state] != NULL){
00575         cfstore_flush_fsm_on_entry[new_state](ctx);
00576     }
00577     #ifdef CFSTORE_DEBUG
00578     CFSTORE_DBGLOG("%s:FSM:REQ DONE fsm=%p, fsm->state (old_state)=%s, new_state=%s, ctx=%p\r\n", __func__, fsm, cfstore_flush_state_str[old_state], cfstore_flush_state_str[new_state], ctx);
00579     #endif
00580     return;
00581 }
00582 
00583 
00584 /* @brief   asynchronous test 01 */
00585 static control_t cfstore_flush_test_02_k64f(void)
00586 {
00587     cfstore_flush_ctx_t* ctx = cfstore_flush_ctx_get();
00588     ARM_CFSTORE_CAPABILITIES caps;
00589     const ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
00590 
00591     CFSTORE_FENTRYLOG("%s:entered: \r\n", __func__);
00592     memset(&caps, 0, sizeof(caps));
00593     caps = drv->GetCapabilities();
00594     if(caps.asynchronous_ops == false){
00595         /* This is a async mode only test. If this test is not built for sync mode, then skip testing return true
00596          * This means the test will conveniently pass when run in CI as part of async mode testing */
00597         CFSTORE_LOG("*** Skipping test as binary built for flash journal sync mode, and this test is async-only%s", "\n");
00598         return CaseNext;
00599     }
00600 
00601     cfstore_flush_ctx_init(ctx);
00602     cfstore_flush_fsm_state_set(&ctx->fsm, cfstore_flush_fsm_state_initializing, ctx);
00603     return CaseTimeout(CFSTORE_FLUSH_GREENTEA_TIMEOUT_S*1000);
00604 }
00605 
00606 /* report whether built/configured for flash sync or async mode */
00607 static control_t cfstore_flush_test_00(const size_t call_count)
00608 {
00609     int32_t ret = ARM_DRIVER_ERROR;
00610 
00611     (void) call_count;
00612     ret = cfstore_test_startup();
00613     CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to perform test startup (ret=%d).\n", __func__, (int) ret);
00614     TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
00615     return CaseNext;
00616 }
00617 
00618 /// @cond CFSTORE_DOXYGEN_DISABLE
00619 utest::v1::status_t greentea_setup(const size_t number_of_cases)
00620 {
00621     GREENTEA_SETUP(CFSTORE_FLUSH_GREENTEA_TIMEOUT_S, "default_auto");
00622     return greentea_test_setup_handler(number_of_cases);
00623 }
00624 
00625 Case cases[] = {
00626         Case("FLUSH_test_00", cfstore_flush_test_00),
00627         Case("FLUSH_test_01", cfstore_flush_test_02_k64f),
00628 };
00629 
00630 
00631 /* Declare your test specification with a custom setup handler */
00632 Specification specification(greentea_setup, cases);
00633 
00634 int main()
00635 {
00636     return !Harness::run(specification);
00637 }
00638 /// @endcond
00639 
00640 
00641 #endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM