Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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 */
Generated on Tue Jul 12 2022 13:54:39 by
