takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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