Marco Mayer / Mbed OS Queue
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ns_nvm_helper.c Source File

ns_nvm_helper.c

00001 /*
00002  * Copyright (c) 2016 ARM Limited. All rights reserved.
00003  */
00004 
00005 #include <string.h>
00006 #include <ns_types.h>
00007 #include <nsdynmemLIB.h>
00008 #include "ns_list.h"
00009 #include "platform/arm_hal_nvm.h"
00010 #include "ns_nvm_helper.h"
00011 
00012 #define TRACE_GROUP "nnvm"
00013 
00014 /* NVM operations */
00015 #define NS_NVM_NONE         0x00
00016 #define NS_NVM_INIT         0x01
00017 #define NS_NVM_KEY_CREATE   0x02
00018 #define NS_NVM_KEY_READ     0x03
00019 #define NS_NVM_KEY_WRITE    0x04
00020 #define NS_NVM_FLUSH        0x05
00021 #define NS_NVM_KEY_DELETE   0x06
00022 
00023 typedef struct {
00024     ns_nvm_callback *callback;
00025     const char *client_key_name;
00026     void *client_context;
00027     int operation;
00028     uint8_t *buffer;
00029     uint16_t *buffer_len;
00030     void *original_request;
00031     ns_list_link_t link;
00032 } ns_nvm_request_t;
00033 
00034 static bool ns_nvm_initialized = false;
00035 static bool ns_nvm_operation_in_progress = false;
00036 
00037 static ns_nvm_request_t *ns_nvm_create_request(ns_nvm_callback *callback, void *context, const char *key_name, uint8_t *buf, uint16_t *buf_len, uint8_t operation);
00038 static int ns_nvm_operation_start(ns_nvm_request_t *request);
00039 static int ns_nvm_operation_continue(ns_nvm_request_t *request, bool free_request);
00040 static void ns_nvm_operation_end(ns_nvm_request_t *ns_nvm_request_ptr, int client_retval);
00041 
00042 static NS_LIST_DEFINE(ns_nvm_request_list, ns_nvm_request_t, link);
00043 
00044 /*
00045  * Callback from platform NVM adaptation
00046  */
00047 void ns_nvm_callback_func(platform_nvm_status status, void *args)
00048 {
00049     ns_nvm_request_t *ns_nvm_request_ptr = (ns_nvm_request_t*)args;
00050     int client_retval = NS_NVM_OK;
00051 
00052     if (status == PLATFORM_NVM_ERROR) {
00053         client_retval = NS_NVM_ERROR;
00054     } else if (status == PLATFORM_NVM_KEY_NOT_FOUND) {
00055         client_retval = NS_NVM_DATA_NOT_FOUND;
00056     }
00057 
00058     switch(ns_nvm_request_ptr->operation) {
00059         case NS_NVM_INIT:
00060             ns_nvm_operation_continue(ns_nvm_request_ptr->original_request, true);
00061             ns_dyn_mem_free(ns_nvm_request_ptr);
00062             break;
00063         case NS_NVM_FLUSH:
00064         case NS_NVM_KEY_READ:
00065             ns_nvm_operation_end(ns_nvm_request_ptr, client_retval);
00066             break;
00067         case NS_NVM_KEY_CREATE:
00068             if (status == PLATFORM_NVM_OK) {
00069                 ns_nvm_request_ptr->operation = NS_NVM_KEY_WRITE;
00070                 platform_nvm_write(ns_nvm_callback_func, ns_nvm_request_ptr->client_key_name, ns_nvm_request_ptr->buffer, ns_nvm_request_ptr->buffer_len, ns_nvm_request_ptr);
00071             } else {
00072                 ns_nvm_operation_end(ns_nvm_request_ptr, client_retval);
00073             }
00074             break;
00075         case NS_NVM_KEY_DELETE:
00076         case NS_NVM_KEY_WRITE:
00077             if (status == PLATFORM_NVM_OK) {
00078                 // write ok, flush the changes
00079                 ns_nvm_request_ptr->operation = NS_NVM_FLUSH;
00080                 platform_nvm_flush(ns_nvm_callback_func, ns_nvm_request_ptr);
00081             } else {
00082                 // write failed, inform client
00083                 ns_nvm_operation_end(ns_nvm_request_ptr, client_retval);
00084             }
00085             break;
00086     }
00087 }
00088 
00089 int ns_nvm_key_delete(ns_nvm_callback *callback, const char *key_name, void *context)
00090 {
00091     if (!callback || !key_name) {
00092         return NS_NVM_ERROR;
00093     }
00094     ns_nvm_request_t *ns_nvm_request_ptr = ns_nvm_create_request(callback, context, key_name, NULL, NULL, NS_NVM_KEY_DELETE);
00095     return ns_nvm_operation_start(ns_nvm_request_ptr);
00096 }
00097 
00098 int ns_nvm_data_read(ns_nvm_callback *callback, const char *key_name, uint8_t *buf, uint16_t *buf_len, void *context)
00099 {
00100     if (!callback || !key_name || !buf || !buf_len) {
00101         return NS_NVM_ERROR;
00102     }
00103     ns_nvm_request_t *ns_nvm_request_ptr = ns_nvm_create_request(callback, context, key_name, buf, buf_len, NS_NVM_KEY_READ);
00104     return ns_nvm_operation_start(ns_nvm_request_ptr);
00105 }
00106 
00107 int ns_nvm_data_write(ns_nvm_callback *callback, const char *key_name, uint8_t *buf, uint16_t *buf_len, void *context)
00108 {
00109     if (!callback || !key_name || !buf || !buf_len) {
00110         return NS_NVM_ERROR;
00111     }
00112     ns_nvm_request_t *ns_nvm_request_ptr = ns_nvm_create_request(callback, context, key_name, buf, buf_len, NS_NVM_KEY_WRITE);
00113     return ns_nvm_operation_start(ns_nvm_request_ptr);
00114 }
00115 
00116 static int ns_nvm_operation_start(ns_nvm_request_t *nvm_request)
00117 {
00118     int ret = NS_NVM_OK;
00119     platform_nvm_status pnvm_status;
00120 
00121     if (!nvm_request) {
00122         return NS_NVM_MEMORY;
00123     }
00124     if (ns_nvm_initialized == true) {
00125         // NVM already initialized, continue directly
00126         if (!ns_nvm_operation_in_progress) {
00127             ret = ns_nvm_operation_continue(nvm_request, true);
00128         } else {
00129             // add request to list and handle when existing calls has been handled.
00130             ns_list_add_to_end(&ns_nvm_request_list, nvm_request);
00131         }
00132     } else {
00133         ns_nvm_request_t *ns_nvm_request_ptr = ns_nvm_create_request(NULL, NULL, NULL, NULL, NULL, NS_NVM_INIT);
00134         if (!ns_nvm_request_ptr) {
00135             ns_dyn_mem_free(nvm_request);
00136             ns_dyn_mem_free(ns_nvm_request_ptr);
00137             return NS_NVM_MEMORY;
00138         }
00139         ns_nvm_request_ptr->original_request = nvm_request;
00140         pnvm_status = platform_nvm_init(ns_nvm_callback_func, ns_nvm_request_ptr);
00141         if (pnvm_status != PLATFORM_NVM_OK) {
00142             ns_dyn_mem_free(nvm_request);
00143             ns_dyn_mem_free(ns_nvm_request_ptr);
00144             return NS_NVM_ERROR;
00145         }
00146         ns_list_init(&ns_nvm_request_list);
00147         ns_nvm_initialized = true;
00148         ns_nvm_operation_in_progress = true;
00149     }
00150     return ret;
00151 }
00152 
00153 static ns_nvm_request_t *ns_nvm_create_request(ns_nvm_callback *callback, void *context, const char *key_name, uint8_t *buf, uint16_t *buf_len, uint8_t operation)
00154 {
00155     ns_nvm_request_t *ns_nvm_request_ptr = ns_dyn_mem_temporary_alloc(sizeof(ns_nvm_request_t));
00156     if (!ns_nvm_request_ptr) {
00157         return NULL;
00158     }
00159     ns_nvm_request_ptr->client_context = context;
00160     ns_nvm_request_ptr->callback = callback;
00161     ns_nvm_request_ptr->client_key_name = key_name;
00162     ns_nvm_request_ptr->operation = operation;
00163     ns_nvm_request_ptr->buffer = buf;
00164     ns_nvm_request_ptr->buffer_len = buf_len;
00165 
00166     return ns_nvm_request_ptr;
00167 }
00168 
00169 static int ns_nvm_operation_continue(ns_nvm_request_t *request, bool free_request)
00170 {
00171     platform_nvm_status ret = PLATFORM_NVM_OK;
00172 
00173     ns_nvm_operation_in_progress = true;
00174     switch(request->operation) {
00175         case NS_NVM_KEY_WRITE:
00176             request->operation = NS_NVM_KEY_CREATE;
00177             ret = platform_nvm_key_create(ns_nvm_callback_func, request->client_key_name, *request->buffer_len, 0, request);
00178             break;
00179         case NS_NVM_KEY_READ:
00180             ret = platform_nvm_read(ns_nvm_callback_func, request->client_key_name, request->buffer, request->buffer_len, request);
00181             break;
00182         case NS_NVM_KEY_DELETE:
00183             ret = platform_nvm_key_delete(ns_nvm_callback_func, request->client_key_name, request);
00184             break;
00185     }
00186 
00187     if (ret != PLATFORM_NVM_OK) {
00188         if (free_request == true) {
00189             // free request if requested
00190             ns_dyn_mem_free(request);
00191         }
00192         ns_nvm_operation_in_progress = false;
00193         return NS_NVM_ERROR;
00194     }
00195 
00196     return NS_NVM_OK;
00197 }
00198 
00199 static void ns_nvm_operation_end(ns_nvm_request_t *ns_nvm_request_ptr, int client_retval)
00200 {
00201     ns_nvm_request_ptr->callback(client_retval, ns_nvm_request_ptr->client_context);
00202     ns_dyn_mem_free(ns_nvm_request_ptr);
00203     ns_nvm_operation_in_progress = false;
00204 
00205     ns_list_foreach_safe(ns_nvm_request_t, pending_req, &ns_nvm_request_list) {
00206         // there are pending requests to be processed
00207         ns_list_remove(&ns_nvm_request_list, pending_req);
00208         int ret = ns_nvm_operation_continue(pending_req, false);
00209         if (ret != NS_NVM_OK) {
00210             ns_nvm_operation_end(pending_req, ret);
00211         } else {
00212             break;
00213         }
00214     }
00215 }