ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

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