Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers nvm_ram.c Source File

nvm_ram.c

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