WORKS

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Revision:
1:55a6170b404f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbd_os/features/FEATURE_COMMON_PAL/nanostack-libservice/source/nvmHelper/ns_nvm_helper.c	Sat Sep 17 16:32:05 2016 +0000
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ */
+
+#include <string.h>
+#include <ns_types.h>
+#include <nsdynmemLIB.h>
+#define HAVE_DEBUG
+#include "ns_trace.h"
+#include "ns_list.h"
+#include "platform/arm_hal_nvm.h"
+#include "ns_nvm_helper.h"
+
+#define TRACE_GROUP "nnvm"
+
+/* NVM operations */
+#define NS_NVM_NONE         0x00
+#define NS_NVM_INIT         0x01
+#define NS_NVM_KEY_CREATE   0x02
+#define NS_NVM_KEY_READ     0x03
+#define NS_NVM_KEY_WRITE    0x04
+#define NS_NVM_FLUSH        0x05
+#define NS_NVM_KEY_DELETE   0x06
+
+typedef struct {
+    ns_nvm_callback *callback;
+    const char *client_key_name;
+    void *client_context;
+    int operation;
+    uint8_t *buffer;
+    uint16_t *buffer_len;
+    void *original_request;
+    ns_list_link_t link;
+} ns_nvm_request_t;
+
+static bool ns_nvm_initialized = false;
+static bool ns_nvm_operation_in_progress = false;
+
+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);
+static int ns_nvm_operation_start(ns_nvm_request_t *request);
+static int ns_nvm_operation_continue(ns_nvm_request_t *request, bool free_request);
+static void ns_nvm_operation_end(ns_nvm_request_t *ns_nvm_request_ptr, int client_retval);
+
+static NS_LIST_DEFINE(ns_nvm_request_list, ns_nvm_request_t, link);
+
+/*
+ * Callback from platform NVM adaptation
+ */
+void ns_nvm_callback_func(platform_nvm_status status, void *args)
+{
+    ns_nvm_request_t *ns_nvm_request_ptr = (ns_nvm_request_t*)args;
+    int client_retval = NS_NVM_OK;
+
+    if (status == PLATFORM_NVM_ERROR) {
+        client_retval = NS_NVM_ERROR;
+    } else if (status == PLATFORM_NVM_KEY_NOT_FOUND) {
+        client_retval = NS_NVM_DATA_NOT_FOUND;
+    }
+
+    switch(ns_nvm_request_ptr->operation) {
+        case NS_NVM_INIT:
+            ns_nvm_operation_continue(ns_nvm_request_ptr->original_request, true);
+            ns_dyn_mem_free(ns_nvm_request_ptr);
+            break;
+        case NS_NVM_FLUSH:
+        case NS_NVM_KEY_READ:
+            ns_nvm_operation_end(ns_nvm_request_ptr, client_retval);
+            break;
+        case NS_NVM_KEY_CREATE:
+            if (status == PLATFORM_NVM_OK) {
+                ns_nvm_request_ptr->operation = NS_NVM_KEY_WRITE;
+                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);
+            } else {
+                ns_nvm_operation_end(ns_nvm_request_ptr, client_retval);
+            }
+            break;
+        case NS_NVM_KEY_DELETE:
+        case NS_NVM_KEY_WRITE:
+            if (status == PLATFORM_NVM_OK) {
+                // write ok, flush the changes
+                ns_nvm_request_ptr->operation = NS_NVM_FLUSH;
+                platform_nvm_flush(ns_nvm_callback_func, ns_nvm_request_ptr);
+            } else {
+                // write failed, inform client
+                ns_nvm_operation_end(ns_nvm_request_ptr, client_retval);
+            }
+            break;
+    }
+}
+
+int ns_nvm_key_delete(ns_nvm_callback *callback, const char *key_name, void *context)
+{
+    if (!callback || !key_name) {
+        return NS_NVM_ERROR;
+    }
+    tr_debug("ns_nvm_key_delete() key=%s, ctx=%p", key_name, context);
+    ns_nvm_request_t *ns_nvm_request_ptr = ns_nvm_create_request(callback, context, key_name, NULL, NULL, NS_NVM_KEY_DELETE);
+    return ns_nvm_operation_start(ns_nvm_request_ptr);
+}
+
+int ns_nvm_data_read(ns_nvm_callback *callback, const char *key_name, uint8_t *buf, uint16_t *buf_len, void *context)
+{
+    if (!callback || !key_name || !buf || !buf_len) {
+        return NS_NVM_ERROR;
+    }
+    tr_debug("ns_nvm_data_read() key=%s, len=%d, ctx=%p", key_name, (int)*buf_len, context);
+    ns_nvm_request_t *ns_nvm_request_ptr = ns_nvm_create_request(callback, context, key_name, buf, buf_len, NS_NVM_KEY_READ);
+    return ns_nvm_operation_start(ns_nvm_request_ptr);
+}
+
+int ns_nvm_data_write(ns_nvm_callback *callback, const char *key_name, uint8_t *buf, uint16_t *buf_len, void *context)
+{
+    if (!callback || !key_name || !buf || !buf_len) {
+        return NS_NVM_ERROR;
+    }
+    tr_debug("ns_nvm_data_write() key=%s, len=%d, ctx=%p", key_name, (int)*buf_len, context);
+    ns_nvm_request_t *ns_nvm_request_ptr = ns_nvm_create_request(callback, context, key_name, buf, buf_len, NS_NVM_KEY_WRITE);
+    return ns_nvm_operation_start(ns_nvm_request_ptr);
+}
+
+static int ns_nvm_operation_start(ns_nvm_request_t *nvm_request)
+{
+    int ret = NS_NVM_OK;
+    platform_nvm_status pnvm_status;
+
+    if (!nvm_request) {
+        return NS_NVM_MEMORY;
+    }
+    if (ns_nvm_initialized == true) {
+        // NVM already initialized, continue directly
+        if (!ns_nvm_operation_in_progress) {
+            ret = ns_nvm_operation_continue(nvm_request, true);
+        } else {
+            // add request to list and handle when existing calls has been handled.
+            ns_list_add_to_end(&ns_nvm_request_list, nvm_request);
+        }
+    } else {
+        ns_nvm_request_t *ns_nvm_request_ptr = ns_nvm_create_request(NULL, NULL, NULL, NULL, NULL, NS_NVM_INIT);
+        if (!ns_nvm_request_ptr) {
+            ns_dyn_mem_free(nvm_request);
+            ns_dyn_mem_free(ns_nvm_request_ptr);
+            return NS_NVM_MEMORY;
+        }
+        ns_nvm_request_ptr->original_request = nvm_request;
+        pnvm_status = platform_nvm_init(ns_nvm_callback_func, ns_nvm_request_ptr);
+        if (pnvm_status != PLATFORM_NVM_OK) {
+            ns_dyn_mem_free(nvm_request);
+            ns_dyn_mem_free(ns_nvm_request_ptr);
+            return NS_NVM_ERROR;
+        }
+        ns_list_init(&ns_nvm_request_list);
+        ns_nvm_initialized = true;
+        ns_nvm_operation_in_progress = true;
+    }
+    return ret;
+}
+
+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)
+{
+    ns_nvm_request_t *ns_nvm_request_ptr = ns_dyn_mem_temporary_alloc(sizeof(ns_nvm_request_t));
+    if (!ns_nvm_request_ptr) {
+        return NULL;
+    }
+    ns_nvm_request_ptr->client_context = context;
+    ns_nvm_request_ptr->callback = callback;
+    ns_nvm_request_ptr->client_key_name = key_name;
+    ns_nvm_request_ptr->operation = operation;
+    ns_nvm_request_ptr->buffer = buf;
+    ns_nvm_request_ptr->buffer_len = buf_len;
+
+    return ns_nvm_request_ptr;
+}
+
+static int ns_nvm_operation_continue(ns_nvm_request_t *request, bool free_request)
+{
+    platform_nvm_status ret = PLATFORM_NVM_OK;
+
+    ns_nvm_operation_in_progress = true;
+    switch(request->operation) {
+        case NS_NVM_KEY_WRITE:
+            request->operation = NS_NVM_KEY_CREATE;
+            ret = platform_nvm_key_create(ns_nvm_callback_func, request->client_key_name, *request->buffer_len, 0, request);
+            break;
+        case NS_NVM_KEY_READ:
+            ret = platform_nvm_read(ns_nvm_callback_func, request->client_key_name, request->buffer, request->buffer_len, request);
+            break;
+        case NS_NVM_KEY_DELETE:
+            ret = platform_nvm_key_delete(ns_nvm_callback_func, request->client_key_name, request);
+            break;
+    }
+
+    if (ret != PLATFORM_NVM_OK) {
+        if (free_request == true) {
+            // free request if requested
+            ns_dyn_mem_free(request);
+        }
+        ns_nvm_operation_in_progress = false;
+        return NS_NVM_ERROR;
+    }
+
+    return NS_NVM_OK;
+}
+
+static void ns_nvm_operation_end(ns_nvm_request_t *ns_nvm_request_ptr, int client_retval)
+{
+    ns_nvm_request_ptr->callback(client_retval, ns_nvm_request_ptr->client_context);
+    ns_dyn_mem_free(ns_nvm_request_ptr);
+    ns_nvm_operation_in_progress = false;
+
+    ns_list_foreach_safe(ns_nvm_request_t, pending_req, &ns_nvm_request_list) {
+        // there are pending requests to be processed
+        ns_list_remove(&ns_nvm_request_list, pending_req);
+        int ret = ns_nvm_operation_continue(pending_req, false);
+        if (ret != NS_NVM_OK) {
+            ns_nvm_operation_end(pending_req, ret);
+        } else {
+            break;
+        }
+    }
+}