EL4121 Embedded System / mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers thread_nvm_store.c Source File

thread_nvm_store.c

00001 /*
00002  * Copyright (c) 2017, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: BSD-3-Clause
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holder nor the
00014  *    names of its contributors may be used to endorse or promote products
00015  *    derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 /*
00030  * \file thread_nvm_store.c
00031  *
00032  */
00033 
00034 #include "thread_nvm_store.h"
00035 #include "ns_trace.h"
00036 #include <string.h>
00037 #include <stdio.h>
00038 #include "ns_file_system.h"
00039 #include "thread_config.h"
00040 
00041 #define TRACE_GROUP "tnvm"
00042 #define FAST_DATA_FILE "f_d"
00043 #define FAST_DATA_WORD_SIZE 4
00044 #define FAST_DATA_VERSION 1
00045 
00046 static const char* thread_nvm_store_get_root_path(void);
00047 static int root_path_valid();
00048 static int thread_nvm_store_fast_data_read_version(uint32_t* version);
00049 static int thread_nvm_store_fast_data_create(void);
00050 static int thread_nvm_store_read(const char *file_name, void *data, uint32_t data_size);
00051 static int thread_nvm_store_write(const char *file_name, void *data, uint32_t data_size);
00052 static void create_fast_data_path (char* fast_data_path);
00053 static int thread_nvm_store_fast_data_save(thread_nvm_fast_data_t* fast_data_to_set);
00054 static int thread_nvm_store_all_counters_store(uint32_t mac_frame_counter, uint32_t mle_frame_counter, uint32_t seq_counter);
00055 
00056 #define MAX_ROOT_PATH_LEN 100
00057 
00058 #define FAST_DATA_STRING_LEN (strlen(FAST_DATA_FILE)+strlen(thread_nvm_store_get_root_path())+1)
00059 
00060 thread_nvm_fast_data_t cached_fast_data;
00061 
00062 static const char* thread_nvm_store_get_root_path(void)
00063 {
00064     char* path = ns_file_system_get_root_path();
00065     if (NULL==path) {
00066         return "";
00067     }
00068     return path;
00069 }
00070 
00071 static int root_path_valid() {
00072     if (NULL==thread_nvm_store_get_root_path())
00073         return 0;
00074     int path_len = strlen(thread_nvm_store_get_root_path());
00075     if(path_len==0 || path_len>MAX_ROOT_PATH_LEN) {
00076         return 0;
00077     }
00078     return 1;
00079 }
00080 
00081 int thread_nvm_store_init(void)
00082 {
00083     uint32_t version=0;
00084 
00085     if (!root_path_valid()) {
00086         return THREAD_NVM_FILE_ROOT_PATH_INVALID;
00087     }
00088 
00089     int ret = thread_nvm_store_fast_data_read_version(&version);
00090     if(THREAD_NVM_FILE_READ_ERROR==ret) {
00091         tr_info("need to create a new fastdata");
00092         return thread_nvm_store_fast_data_create();
00093     }
00094 
00095     if (version!=FAST_DATA_VERSION) {
00096         //handle new version format here
00097         //if version is different do the reformatting and save new format.....
00098         tr_info("Fast data version mismatch %u\n", (unsigned int)version);
00099     }
00100     return 0;
00101 }
00102 
00103 int thread_nvm_store_seq_counter_store(uint32_t network_seq_counter)
00104 {
00105     int ret = THREAD_NVM_FILE_SUCCESS;
00106     if (cached_fast_data.seq_counter!=network_seq_counter) {
00107         ret = thread_nvm_store_all_counters_store(cached_fast_data.mac_frame_counter, cached_fast_data.mle_frame_counter, network_seq_counter);
00108         cached_fast_data.seq_counter=network_seq_counter;
00109     }
00110     return ret;
00111 }
00112 
00113 int thread_nvm_store_fast_data_check_and_store(uint32_t mac_frame_counter, uint32_t mle_frame_counter, uint32_t network_seq_counter)
00114 {
00115     int ret = THREAD_NVM_FILE_SUCCESS;
00116     if( ((int)(mac_frame_counter - cached_fast_data.mac_frame_counter) > MAC_FRAME_COUNTER_LIMIT) ||
00117         ((int)(mle_frame_counter - cached_fast_data.mle_frame_counter) > MLE_FRAME_COUNTER_LIMIT) ||
00118         cached_fast_data.seq_counter!=network_seq_counter) {
00119             ret = thread_nvm_store_all_counters_store(mac_frame_counter, mle_frame_counter, network_seq_counter);
00120             cached_fast_data.mac_frame_counter = mac_frame_counter;
00121             cached_fast_data.mle_frame_counter = mle_frame_counter;
00122             cached_fast_data.seq_counter=network_seq_counter;
00123     }
00124     return ret;
00125 }
00126 
00127 
00128 int thread_nvm_store_frame_counters_check_and_store(uint32_t mac_frame_counter, uint32_t mle_frame_counter)
00129 {
00130     int ret = THREAD_NVM_FILE_SUCCESS;
00131     if( ((int)(mac_frame_counter - cached_fast_data.mac_frame_counter) > MAC_FRAME_COUNTER_LIMIT) ||
00132         ((int)(mle_frame_counter - cached_fast_data.mle_frame_counter) > MLE_FRAME_COUNTER_LIMIT)) {
00133             ret = thread_nvm_store_all_counters_store(mac_frame_counter, mle_frame_counter, cached_fast_data.seq_counter);
00134             cached_fast_data.mac_frame_counter = mac_frame_counter;
00135             cached_fast_data.mle_frame_counter = mle_frame_counter;
00136     }
00137     return ret;
00138 }
00139 
00140 static int thread_nvm_store_all_counters_store(uint32_t mac_frame_counter, uint32_t mle_frame_counter, uint32_t network_seq_counter)
00141 {
00142     thread_nvm_fast_data_t fast_data;
00143     fast_data.mac_frame_counter = mac_frame_counter;
00144     fast_data.mle_frame_counter = mle_frame_counter;
00145     fast_data.seq_counter = network_seq_counter;
00146     fast_data.version = FAST_DATA_VERSION;
00147     if (root_path_valid()) {
00148         return thread_nvm_store_fast_data_save(&fast_data);
00149     }
00150     else{
00151         return THREAD_NVM_FILE_ROOT_PATH_INVALID;
00152     }
00153 }
00154 
00155 int thread_nvm_store_fast_data_store(thread_nvm_fast_data_t* fast_data)
00156 {
00157     cached_fast_data.mac_frame_counter = fast_data->mac_frame_counter;
00158     cached_fast_data.mle_frame_counter = fast_data->mle_frame_counter;
00159     cached_fast_data.seq_counter = fast_data->seq_counter;
00160 
00161     if (root_path_valid()) {
00162         fast_data->version=FAST_DATA_VERSION;
00163         return thread_nvm_store_fast_data_save(fast_data);
00164     }
00165     else {
00166         return THREAD_NVM_FILE_ROOT_PATH_INVALID;
00167     }
00168 }
00169 
00170 static void create_fast_data_path (char* fast_data_path)
00171 {
00172     strcpy(fast_data_path, thread_nvm_store_get_root_path());
00173     strcat(fast_data_path, FAST_DATA_FILE);
00174 }
00175 
00176 static int thread_nvm_store_fast_data_read_version(uint32_t* version)
00177 {
00178     thread_nvm_fast_data_t fast_data;
00179     char fast_data_path[FAST_DATA_STRING_LEN];
00180     create_fast_data_path(fast_data_path);
00181 
00182     int ret = thread_nvm_store_read(fast_data_path, &fast_data, FAST_DATA_WORD_SIZE*4);
00183 
00184     if(ret<0) {
00185         return THREAD_NVM_FILE_READ_ERROR;
00186     }
00187     *version = fast_data.version;
00188     return THREAD_NVM_FILE_SUCCESS;
00189 }
00190 
00191 static int thread_nvm_store_fast_data_create(void)
00192 {
00193     thread_nvm_fast_data_t fast_data;
00194     memset(&fast_data, 0, FAST_DATA_WORD_SIZE*4);
00195     fast_data.version = FAST_DATA_VERSION;
00196     char fast_data_path[FAST_DATA_STRING_LEN];
00197     create_fast_data_path(fast_data_path);
00198     return thread_nvm_store_write(fast_data_path, &fast_data, FAST_DATA_WORD_SIZE*4);
00199 }
00200 
00201 int thread_nvm_store_fast_data_read(thread_nvm_fast_data_t* fast_data)
00202 {
00203     int ret = THREAD_NVM_FILE_SUCCESS;
00204     if (root_path_valid()) {
00205         char fast_data_path[FAST_DATA_STRING_LEN];
00206         create_fast_data_path(fast_data_path);
00207         ret = thread_nvm_store_read(fast_data_path, fast_data, FAST_DATA_WORD_SIZE*4);
00208     }
00209     else {
00210         fast_data->mac_frame_counter = cached_fast_data.mac_frame_counter;
00211         fast_data->mle_frame_counter = cached_fast_data.mle_frame_counter;
00212         fast_data->seq_counter = cached_fast_data.seq_counter;
00213     }
00214     return ret;
00215 }
00216 
00217 static int thread_nvm_store_fast_data_save(thread_nvm_fast_data_t* fast_data_to_set)
00218 {
00219     char fast_data_path[FAST_DATA_STRING_LEN];
00220     create_fast_data_path(fast_data_path);
00221     return thread_nvm_store_write(fast_data_path, fast_data_to_set, FAST_DATA_WORD_SIZE*4);
00222 }
00223 
00224 static int thread_nvm_store_write(const char *file_name, void *data, uint32_t data_size)
00225 {
00226     FILE *fp = fopen(file_name, "w");
00227     if(fp == NULL) {
00228         return THREAD_NVM_FILE_CANNOT_OPEN;
00229     }
00230     size_t n_bytes = fwrite(data, 1, data_size, fp);
00231     fclose(fp);
00232     if (n_bytes!=data_size) {
00233         tr_error("NVM write failed");
00234         return THREAD_NVM_FILE_WRITE_ERROR;
00235     }
00236     else {
00237         return THREAD_NVM_FILE_SUCCESS;
00238     }
00239 }
00240 
00241 // returns 0 when ok
00242 static int thread_nvm_store_read(const char *file_name, void *data, uint32_t data_size)
00243 {
00244     FILE *fp = fopen(file_name, "r");
00245     if(fp == NULL) {
00246         return THREAD_NVM_FILE_CANNOT_OPEN;
00247     }
00248     size_t n_bytes = fread(data, 1, data_size, fp);
00249     fclose(fp);
00250     if (n_bytes!=data_size) {
00251         tr_error("NVM read failed");
00252         return THREAD_NVM_FILE_READ_ERROR;
00253     }
00254     else {
00255         return THREAD_NVM_FILE_SUCCESS; // return how many bytes was written.
00256     }
00257 }