storage_manager.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. $License:
  3. Copyright (C) 2011-2012 InvenSense Corporation, All Rights Reserved.
  4. See included License.txt for License information.
  5. $
  6. */
  7. /**
  8. * @defgroup Storage_Manager storage_manager
  9. * @brief Motion Library - Stores Data for functions.
  10. *
  11. *
  12. * @{
  13. * @file storage_manager.c
  14. * @brief Load and Store Manager.
  15. */
  16. #include <string.h>
  17. #include "storage_manager.h"
  18. #include "log.h"
  19. #include "ml_math_func.h"
  20. #include "mlmath.h"
  21. /* Must be changed if the format of storage changes */
  22. #define DEFAULT_KEY 29681
  23. typedef inv_error_t (*load_func_t)(const unsigned char *data);
  24. typedef inv_error_t (*save_func_t)(unsigned char *data);
  25. /** Max number of entites that can be stored */
  26. #define NUM_STORAGE_BOXES 20
  27. struct data_header_t {
  28. long size;
  29. uint32_t checksum;
  30. unsigned int key;
  31. };
  32. struct data_storage_t {
  33. int num; /**< Number of differnt save entities */
  34. size_t total_size; /**< Size in bytes to store non volatile data */
  35. load_func_t load[NUM_STORAGE_BOXES]; /**< Callback to load data */
  36. save_func_t save[NUM_STORAGE_BOXES]; /**< Callback to save data */
  37. struct data_header_t hd[NUM_STORAGE_BOXES]; /**< Header info for each entity */
  38. };
  39. static struct data_storage_t ds;
  40. /** Should be called once before using any of the storage methods. Typically
  41. * called first by inv_init_mpl().*/
  42. void inv_init_storage_manager()
  43. {
  44. memset(&ds, 0, sizeof(ds));
  45. ds.total_size = sizeof(struct data_header_t);
  46. }
  47. /** Used to register your mechanism to load and store non-volative data. This should typical be
  48. * called during the enable function for your feature.
  49. * @param[in] load_func function pointer you will use to receive data that was stored for you.
  50. * @param[in] save_func function pointer you will use to save any data you want saved to
  51. * non-volatile memory between runs.
  52. * @param[in] size The size in bytes of the amount of data you want loaded and saved.
  53. * @param[in] key The key associated with your data type should be unique across MPL.
  54. * The key should change when your type of data for storage changes.
  55. * @return Returns INV_SUCCESS if successful or an error code if not.
  56. */
  57. inv_error_t inv_register_load_store(inv_error_t (*load_func)(const unsigned char *data),
  58. inv_error_t (*save_func)(unsigned char *data), size_t size, unsigned int key)
  59. {
  60. int kk;
  61. // Check if this has been registered already
  62. for (kk=0; kk<ds.num; ++kk) {
  63. if (key == ds.hd[kk].key) {
  64. return INV_ERROR_INVALID_PARAMETER;
  65. }
  66. }
  67. // Make sure there is room
  68. if (ds.num >= NUM_STORAGE_BOXES) {
  69. return INV_ERROR_INVALID_PARAMETER;
  70. }
  71. // Add to list
  72. ds.hd[ds.num].key = key;
  73. ds.hd[ds.num].size = size;
  74. ds.load[ds.num] = load_func;
  75. ds.save[ds.num] = save_func;
  76. ds.total_size += size + sizeof(struct data_header_t);
  77. ds.num++;
  78. return INV_SUCCESS;
  79. }
  80. /** Returns the memory size needed to perform a store
  81. * @param[out] size Size in bytes of memory needed to store.
  82. * @return Returns INV_SUCCESS if successful or an error code if not.
  83. */
  84. inv_error_t inv_get_mpl_state_size(size_t *size)
  85. {
  86. *size = ds.total_size;
  87. return INV_SUCCESS;
  88. }
  89. /** @internal
  90. * Finds key in ds.hd[] array and returns location
  91. * @return location where key exists in array, -1 if not found.
  92. */
  93. static int inv_find_entry(unsigned int key)
  94. {
  95. int kk;
  96. for (kk=0; kk<ds.num; ++kk) {
  97. if (key == ds.hd[kk].key) {
  98. return kk;
  99. }
  100. }
  101. return -1;
  102. }
  103. /** This function takes a block of data that has been saved in non-volatile memory and pushes
  104. * to the proper locations. Multiple error checks are performed on the data.
  105. * @param[in] data Data that was saved to be loaded up by MPL
  106. * @param[in] length Length of data vector in bytes
  107. * @return Returns INV_SUCCESS if successful or an error code if not.
  108. */
  109. inv_error_t inv_load_mpl_states(const unsigned char *data, size_t length)
  110. {
  111. struct data_header_t *hd;
  112. int entry;
  113. uint32_t checksum;
  114. long len;
  115. len = length; // Important so we get negative numbers
  116. if (len < sizeof(struct data_header_t))
  117. return INV_ERROR_CALIBRATION_LOAD; // No data
  118. hd = (struct data_header_t *)data;
  119. if (hd->key != DEFAULT_KEY)
  120. return INV_ERROR_CALIBRATION_LOAD; // Key changed or data corruption
  121. len = MIN(hd->size, len);
  122. len = hd->size;
  123. len -= sizeof(struct data_header_t);
  124. data += sizeof(struct data_header_t);
  125. checksum = inv_checksum(data, len);
  126. if (checksum != hd->checksum)
  127. return INV_ERROR_CALIBRATION_LOAD; // Data corruption
  128. while (len > (long)sizeof(struct data_header_t)) {
  129. hd = (struct data_header_t *)data;
  130. entry = inv_find_entry(hd->key);
  131. data += sizeof(struct data_header_t);
  132. len -= sizeof(struct data_header_t);
  133. if (entry >= 0 && len >= hd->size) {
  134. if (hd->size == ds.hd[entry].size) {
  135. checksum = inv_checksum(data, hd->size);
  136. if (checksum == hd->checksum) {
  137. ds.load[entry](data);
  138. } else {
  139. return INV_ERROR_CALIBRATION_LOAD;
  140. }
  141. }
  142. }
  143. len -= hd->size;
  144. if (len >= 0)
  145. data = data + hd->size;
  146. }
  147. return INV_SUCCESS;
  148. }
  149. /** This function fills up a block of memory to be stored in non-volatile memory.
  150. * @param[out] data Place to store data, size of sz, must be at least size
  151. * returned by inv_get_mpl_state_size()
  152. * @param[in] sz Size of data.
  153. * @return Returns INV_SUCCESS if successful or an error code if not.
  154. */
  155. inv_error_t inv_save_mpl_states(unsigned char *data, size_t sz)
  156. {
  157. unsigned char *cur;
  158. int kk;
  159. struct data_header_t *hd;
  160. if (sz >= ds.total_size) {
  161. cur = data + sizeof(struct data_header_t);
  162. for (kk = 0; kk < ds.num; ++kk) {
  163. hd = (struct data_header_t *)cur;
  164. cur += sizeof(struct data_header_t);
  165. ds.save[kk](cur);
  166. hd->checksum = inv_checksum(cur, ds.hd[kk].size);
  167. hd->size = ds.hd[kk].size;
  168. hd->key = ds.hd[kk].key;
  169. cur += ds.hd[kk].size;
  170. }
  171. } else {
  172. return INV_ERROR_CALIBRATION_LOAD;
  173. }
  174. hd = (struct data_header_t *)data;
  175. hd->checksum = inv_checksum(data + sizeof(struct data_header_t),
  176. ds.total_size - sizeof(struct data_header_t));
  177. hd->key = DEFAULT_KEY;
  178. hd->size = ds.total_size;
  179. return INV_SUCCESS;
  180. }
  181. /**
  182. * @}
  183. */