BA
/
BaBoRo1
Embed:
(wiki syntax)
Show/hide line numbers
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 */
Generated on Tue Jul 12 2022 12:22:16 by
