Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers nvm_ram.c Source File

nvm_ram.c

00001 /*
00002  * Copyright (c) 2016, ARM Limited, All Rights Reserved.
00003  */
00004 
00005 #ifdef MBED_CONF_NANOSTACK_HAL_NVM_CFSTORE
00006 #  if MBED_CONF_NANOSTACK_HAL_NVM_CFSTORE
00007 #    define IGNORE_SIMULATED_NVM_STORAGE
00008 #  else
00009 #    undef IGNORE_SIMULATED_NVM_STORAGE
00010 #  endif
00011 #endif
00012 
00013 /*
00014  * Define flag IGNORE_SIMULATED_NVM_STORAGE to ignore usage of simulated NVM and use 
00015  * platform specific NVM instead.
00016  */
00017 #ifndef IGNORE_SIMULATED_NVM_STORAGE
00018 
00019 #include <stdlib.h>
00020 #include <string.h>
00021 #include "ns_types.h"
00022 #include "ns_list.h"
00023 #include "nsdynmemLIB.h"
00024 #include "eventOS_event_timer.h"
00025 #include "platform/arm_hal_nvm.h"
00026 
00027 #include "ns_trace.h"
00028 #define TRACE_GROUP "rnvm"
00029 
00030 /**
00031 * NVM to RAM/heap, targeted for testing.
00032 * Key/values are stored to ns_list. Otherwise functionality should be similar to
00033 * nanostack configuration-store adaptation.
00034 */
00035 
00036 #define NVM_RAM_STANDARD_MALLOC
00037 #ifdef NVM_RAM_STANDARD_MALLOC
00038 #define ALLOC malloc
00039 #define FREE free
00040 #else
00041 #define ALLOC ns_dyn_mem_alloc
00042 #define FREE ns_dyn_mem_free
00043 #endif
00044 
00045 /*
00046  * Data entry stored to NVM
00047  */
00048 typedef struct {
00049     char *key;
00050     uint8_t *data;
00051     uint32_t data_len;
00052     ns_list_link_t link;
00053 } nvm_data_entry_t;
00054 
00055 /*
00056  * Client request to NVM
00057  */
00058 typedef struct {
00059     nvm_callback *client_cb;            // callback provided by client
00060     void *client_context;               // context provided by client
00061     void *client_buffer;             // buffer provided by client
00062     uint16_t *client_buffer_len;        // buffer length provided by client
00063     platform_nvm_status client_status;  // status to be returned to client
00064     ns_list_link_t link;
00065 } nvm_client_req_t;
00066 
00067 /*
00068  * NVM context
00069  */
00070 typedef struct {
00071     timeout_t *callback_timer;              // timer handle for informing client
00072     bool is_initialized;
00073 } nvm_context_t;
00074 
00075 static NS_LIST_DEFINE(nvm_entry_list, nvm_data_entry_t, link);
00076 static NS_LIST_DEFINE(nvm_client_req_list, nvm_client_req_t, link);
00077 
00078 static nvm_context_t *nvm_context_ptr = NULL;
00079 
00080 static void nvm_ram_timer_start(void *ctx);
00081 static void nvm_ram_free_entry(nvm_data_entry_t *entry);
00082 
00083 
00084 static platform_nvm_status create_client_request(nvm_callback *callback, void *context, void *buf, uint16_t *buf_len, platform_nvm_status status)
00085 {
00086     nvm_client_req_t *nvm_client_req_ptr;
00087     nvm_client_req_ptr = ALLOC(sizeof(nvm_client_req_t));
00088     if (!nvm_client_req_ptr) {
00089         return PLATFORM_NVM_ERROR;
00090     }
00091     nvm_client_req_ptr->client_cb = callback;
00092     nvm_client_req_ptr->client_context = context;
00093     nvm_client_req_ptr->client_buffer = buf;
00094     nvm_client_req_ptr->client_buffer_len = buf_len;
00095     nvm_client_req_ptr->client_status = status;
00096     ns_list_add_to_end(&nvm_client_req_list, nvm_client_req_ptr);
00097 
00098     if (nvm_context_ptr->callback_timer == NULL) {
00099         nvm_ram_timer_start(nvm_client_req_ptr);
00100     }
00101 
00102     return PLATFORM_NVM_OK;
00103 }
00104 
00105 platform_nvm_status platform_nvm_init(nvm_callback *callback, void *context)
00106 {
00107     if (nvm_context_ptr == NULL) {
00108         nvm_context_ptr = ALLOC(sizeof(nvm_context_t));
00109         if (!nvm_context_ptr) {
00110             return PLATFORM_NVM_ERROR;
00111         }
00112         nvm_context_ptr->callback_timer = NULL;
00113         nvm_context_ptr->is_initialized = true;
00114         ns_list_init(&nvm_entry_list);
00115         ns_list_init(&nvm_client_req_list);
00116     } else {
00117         if (nvm_context_ptr->is_initialized == true) {
00118             return PLATFORM_NVM_ERROR;
00119         }
00120     }
00121 
00122     return create_client_request(callback, context, NULL, NULL, PLATFORM_NVM_OK);
00123 }
00124 
00125 platform_nvm_status platform_nvm_finalize(nvm_callback *callback, void *context)
00126 {
00127     platform_nvm_status ret;
00128     if (nvm_context_ptr->is_initialized == false) {
00129         return PLATFORM_NVM_ERROR;
00130     }
00131 
00132     ret = create_client_request(callback, context, NULL, NULL, PLATFORM_NVM_OK);
00133     if (ret == PLATFORM_NVM_OK) {
00134         nvm_context_ptr->is_initialized = false;
00135     }
00136 
00137     return ret;
00138 }
00139 
00140 platform_nvm_status platform_nvm_key_create(nvm_callback *callback, const char *key_name, uint16_t value_len, uint32_t flags, void *context)
00141 {
00142     (void)flags;
00143     tr_debug("platform_nvm_key_create() %s len=%d", key_name, (int)value_len);
00144 
00145     ns_list_foreach(nvm_data_entry_t, current_entry, &nvm_entry_list) {
00146         if (strcmp(current_entry->key, key_name)==0) {
00147             // resizing existing key
00148             ns_list_remove(&nvm_entry_list, current_entry);
00149             nvm_ram_free_entry(current_entry);
00150             break;
00151         }
00152     }
00153 
00154     nvm_data_entry_t *entry = ALLOC(sizeof(nvm_data_entry_t));
00155     if (!entry) {
00156         return PLATFORM_NVM_ERROR;
00157     }
00158     memset(entry, 0, sizeof(nvm_data_entry_t));
00159     size_t key_len = strlen(key_name) + 1;
00160     entry->key = ALLOC(key_len);
00161     if (!entry->key) {
00162         FREE(entry);
00163         return PLATFORM_NVM_ERROR;
00164     }
00165     memcpy(entry->key, key_name, key_len);
00166     entry->data_len = value_len;
00167     entry->data = ALLOC(value_len);
00168     if (!entry->data) {
00169         FREE(entry->key);
00170         FREE(entry);
00171         return PLATFORM_NVM_ERROR;
00172     }
00173 
00174     ns_list_add_to_end(&nvm_entry_list, entry);
00175 
00176     return create_client_request(callback, context, NULL, NULL, PLATFORM_NVM_OK);
00177 }
00178 
00179 platform_nvm_status platform_nvm_key_delete(nvm_callback *callback, const char *key_name, void *context)
00180 {
00181     platform_nvm_status client_status = PLATFORM_NVM_KEY_NOT_FOUND;
00182     tr_debug("platform_nvm_key_delete() %s", key_name);
00183 
00184     ns_list_foreach(nvm_data_entry_t, current_entry, &nvm_entry_list) {
00185         if (strcmp(current_entry->key, key_name)==0) {
00186             client_status = PLATFORM_NVM_OK;
00187             ns_list_remove(&nvm_entry_list, current_entry);
00188             nvm_ram_free_entry(current_entry);
00189             break;
00190         }
00191     }
00192 
00193     return create_client_request(callback, context, NULL, NULL, client_status);
00194 }
00195 
00196 platform_nvm_status platform_nvm_write(nvm_callback *callback, const char *key_name, const void *data, uint16_t *data_len, void *context)
00197 {
00198     platform_nvm_status client_status = PLATFORM_NVM_KEY_NOT_FOUND;
00199     tr_debug("platform_nvm_write() %s len=%d", key_name, (int)*data_len);
00200 
00201     ns_list_foreach(nvm_data_entry_t, current_entry, &nvm_entry_list) {
00202         if (strcmp(current_entry->key, key_name)==0) {
00203             if (current_entry->data_len >= *data_len) {
00204                 memcpy(current_entry->data, data, *data_len);
00205             } else {
00206                 memcpy(current_entry->data, data, current_entry->data_len);
00207                 *data_len = current_entry->data_len;
00208             }
00209             client_status = PLATFORM_NVM_OK;
00210             break;
00211         }
00212     }
00213 
00214     return create_client_request(callback, context, (void*)data, data_len, client_status);
00215 }
00216 
00217 platform_nvm_status platform_nvm_read(nvm_callback *callback, const char *key_name, void *buf, uint16_t *buf_len, void *context)
00218 {
00219     platform_nvm_status client_status = PLATFORM_NVM_KEY_NOT_FOUND;
00220     tr_debug("platform_nvm_read() %s len=%d", key_name, (int)*buf_len);
00221 
00222     ns_list_foreach(nvm_data_entry_t, current_entry, &nvm_entry_list) {
00223         if (strcmp(current_entry->key, key_name)==0) {
00224             if (*buf_len >= current_entry->data_len) {
00225                 memcpy(buf, current_entry->data, current_entry->data_len);
00226                 *buf_len = current_entry->data_len;
00227             } else {
00228                 memcpy(buf, current_entry->data, *buf_len);
00229             }
00230             client_status = PLATFORM_NVM_OK;
00231             break;
00232         }
00233     }
00234 
00235     return create_client_request(callback, context, buf, buf_len, client_status);
00236 }
00237 
00238 platform_nvm_status platform_nvm_flush(nvm_callback *callback, void *context)
00239 {
00240     tr_debug("platform_nvm_flush()");
00241     return create_client_request(callback, context, NULL, NULL, PLATFORM_NVM_OK);
00242 }
00243 
00244 static void nvm_ram_timer_cb(void *args)
00245 {
00246     nvm_client_req_t *nvm_client_req_ptr = (nvm_client_req_t *)args;
00247     nvm_client_req_ptr->client_cb(nvm_client_req_ptr->client_status, nvm_client_req_ptr->client_context);
00248     ns_list_remove(&nvm_client_req_list, nvm_client_req_ptr);
00249     FREE(nvm_client_req_ptr);
00250 
00251     nvm_context_ptr->callback_timer = NULL;
00252 
00253     if (!ns_list_is_empty(&nvm_client_req_list)) {
00254         // there are more client requests to process
00255         nvm_client_req_ptr = ns_list_get_first(&nvm_client_req_list);
00256         nvm_ram_timer_start(nvm_client_req_ptr);
00257     }
00258 }
00259 
00260 static void nvm_ram_timer_start(void *ctx)
00261 {
00262     nvm_context_ptr->callback_timer = eventOS_timeout_ms(nvm_ram_timer_cb, 50, ctx);
00263 }
00264 
00265 static void nvm_ram_free_entry(nvm_data_entry_t *entry)
00266 {
00267     FREE(entry->key);
00268     FREE(entry->data);
00269     FREE(entry);
00270 }
00271 
00272 #endif /* IGNORE_SIMULATED_NVM_STORAGE */