joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

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