www.pudn.com > MPL.zip > storage_manager.c, change:2016-04-15,size:6790b


/* 
 $License: 
    Copyright (C) 2011-2012 InvenSense Corporation, All Rights Reserved. 
    See included License.txt for License information. 
 $ 
 */ 
 
/** 
 *   @defgroup  Storage_Manager storage_manager 
 *   @brief     Motion Library - Stores Data for functions. 
 * 
 * 
 *   @{ 
 *       @file storage_manager.c 
 *       @brief Load and Store Manager. 
 */ 
 
#include <string.h> 
 
#include "storage_manager.h" 
#include "log.h" 
#include "ml_math_func.h" 
#include "mlmath.h" 
 
/* Must be changed if the format of storage changes */ 
#define DEFAULT_KEY 29681 
 
typedef inv_error_t (*load_func_t)(const unsigned char *data); 
typedef inv_error_t (*save_func_t)(unsigned char *data); 
/** Max number of entites that can be stored */ 
#define NUM_STORAGE_BOXES 20 
 
struct data_header_t { 
    long size; 
    uint32_t checksum; 
    unsigned int key; 
}; 
 
struct data_storage_t { 
    int num; /**< Number of differnt save entities */ 
    size_t total_size; /**< Size in bytes to store non volatile data */ 
    load_func_t load[NUM_STORAGE_BOXES]; /**< Callback to load data */ 
    save_func_t save[NUM_STORAGE_BOXES]; /**< Callback to save data */ 
    struct data_header_t hd[NUM_STORAGE_BOXES]; /**< Header info for each entity */ 
}; 
static struct data_storage_t ds; 
 
/** Should be called once before using any of the storage methods. Typically 
* called first by inv_init_mpl().*/ 
void inv_init_storage_manager() 
{ 
    memset(&ds, 0, sizeof(ds)); 
    ds.total_size = sizeof(struct data_header_t); 
} 
 
/** Used to register your mechanism to load and store non-volative data. This should typical be 
* called during the enable function for your feature. 
* @param[in] load_func function pointer you will use to receive data that was stored for you. 
* @param[in] save_func function pointer you will use to save any data you want saved to 
*            non-volatile memory between runs. 
* @param[in] size The size in bytes of the amount of data you want loaded and saved. 
* @param[in] key The key associated with your data type should be unique across MPL. 
*                    The key should change when your type of data for storage changes. 
* @return Returns INV_SUCCESS if successful or an error code if not. 
*/ 
inv_error_t inv_register_load_store(inv_error_t (*load_func)(const unsigned char *data), 
                                    inv_error_t (*save_func)(unsigned char *data), size_t size, unsigned int key) 
{ 
    int kk; 
    // Check if this has been registered already 
    for (kk=0; kk<ds.num; ++kk) { 
        if (key == ds.hd[kk].key) { 
            return INV_ERROR_INVALID_PARAMETER; 
        } 
    } 
    // Make sure there is room 
    if (ds.num >= NUM_STORAGE_BOXES) { 
        return INV_ERROR_INVALID_PARAMETER; 
    } 
    // Add to list 
    ds.hd[ds.num].key = key; 
    ds.hd[ds.num].size = size; 
    ds.load[ds.num] = load_func; 
    ds.save[ds.num] = save_func; 
    ds.total_size += size + sizeof(struct data_header_t); 
    ds.num++; 
 
    return INV_SUCCESS; 
} 
 
/** Returns the memory size needed to perform a store 
* @param[out] size Size in bytes of memory needed to store. 
* @return Returns INV_SUCCESS if successful or an error code if not. 
*/ 
inv_error_t inv_get_mpl_state_size(size_t *size) 
{ 
    *size = ds.total_size; 
    return INV_SUCCESS; 
} 
 
/** @internal 
 * Finds key in ds.hd[] array and returns location 
 * @return location where key exists in array, -1 if not found. 
 */ 
static int inv_find_entry(unsigned int key) 
{ 
    int kk; 
    for (kk=0; kk<ds.num; ++kk) { 
        if (key == ds.hd[kk].key) { 
            return kk; 
        } 
    } 
    return -1; 
} 
 
/** This function takes a block of data that has been saved in non-volatile memory and pushes 
* to the proper locations. Multiple error checks are performed on the data. 
* @param[in] data Data that was saved to be loaded up by MPL 
* @param[in] length Length of data vector in bytes 
* @return Returns INV_SUCCESS if successful or an error code if not. 
*/ 
inv_error_t inv_load_mpl_states(const unsigned char *data, size_t length) 
{ 
    struct data_header_t *hd; 
    int entry; 
    uint32_t checksum; 
    long len; 
 
    len = length; // Important so we get negative numbers 
    if (len < sizeof(struct data_header_t)) 
        return INV_ERROR_CALIBRATION_LOAD;	// No data 
    hd = (struct data_header_t *)data; 
    if (hd->key != DEFAULT_KEY) 
        return INV_ERROR_CALIBRATION_LOAD;	// Key changed or data corruption 
    len = MIN(hd->size, len); 
    len = hd->size; 
    len -= sizeof(struct data_header_t); 
    data += sizeof(struct data_header_t); 
    checksum = inv_checksum(data, len); 
    if (checksum != hd->checksum) 
        return INV_ERROR_CALIBRATION_LOAD;	// Data corruption 
 
    while (len > (long)sizeof(struct data_header_t)) { 
        hd = (struct data_header_t *)data; 
        entry = inv_find_entry(hd->key); 
        data += sizeof(struct data_header_t); 
        len -= sizeof(struct data_header_t); 
        if (entry >= 0 && len >= hd->size) { 
            if (hd->size == ds.hd[entry].size) { 
                checksum = inv_checksum(data, hd->size); 
                if (checksum == hd->checksum) { 
                    ds.load[entry](data); 
                } else { 
                    return INV_ERROR_CALIBRATION_LOAD; 
                } 
            } 
        } 
        len -= hd->size; 
        if (len >= 0) 
            data = data + hd->size; 
    } 
 
    return INV_SUCCESS; 
} 
 
/** This function fills up a block of memory to be stored in non-volatile memory. 
* @param[out] data Place to store data, size of sz, must be at least size 
*                  returned by inv_get_mpl_state_size() 
* @param[in] sz Size of data. 
* @return Returns INV_SUCCESS if successful or an error code if not. 
*/ 
inv_error_t inv_save_mpl_states(unsigned char *data, size_t sz) 
{ 
    unsigned char *cur; 
    int kk; 
    struct data_header_t *hd; 
 
    if (sz >= ds.total_size) { 
        cur = data + sizeof(struct data_header_t); 
        for (kk = 0; kk < ds.num; ++kk) { 
            hd = (struct data_header_t *)cur; 
            cur += sizeof(struct data_header_t); 
            ds.save[kk](cur); 
            hd->checksum = inv_checksum(cur, ds.hd[kk].size); 
            hd->size = ds.hd[kk].size; 
            hd->key = ds.hd[kk].key; 
            cur += ds.hd[kk].size; 
        } 
    } else { 
        return INV_ERROR_CALIBRATION_LOAD; 
    } 
 
    hd = (struct data_header_t *)data; 
    hd->checksum = inv_checksum(data + sizeof(struct data_header_t), 
                                ds.total_size - sizeof(struct data_header_t)); 
    hd->key = DEFAULT_KEY; 
    hd->size = ds.total_size; 
 
    return INV_SUCCESS; 
} 
 
/** 
 * @} 
 */