nvs.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #include "kbf/nvs.h"
  2. #include <esp_log.h>
  3. #include <nvs_flash.h>
  4. #include "kbf/macros.h"
  5. using namespace kbf;
  6. using std::string;
  7. static constexpr const char *TAG = "nvs";
  8. static std::atomic<bool> initialized = {false};
  9. void nvs::init() {
  10. ESP_LOGD(TAG, "init()");
  11. if (initialized) {
  12. ESP_LOGW(TAG, "NVS already initialized");
  13. return;
  14. }
  15. esp_err_t err = nvs_flash_init();
  16. if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
  17. erase();
  18. err = nvs_flash_init();
  19. }
  20. CHECK(err);
  21. initialized = true;
  22. }
  23. void nvs::erase() {
  24. ESP_LOGW(TAG, "erasing flash");
  25. CHECK(nvs_flash_erase());
  26. initialized = false;
  27. }
  28. nvs::NVS::NVS(const string &name) : name(name) {
  29. ESP_LOGD(TAG, "NVS(\"%s\")", name.c_str());
  30. if (!initialized) {
  31. init();
  32. }
  33. CHECK(nvs_open(name.c_str(), NVS_READWRITE, &handle));
  34. }
  35. nvs::NVS::~NVS() {
  36. ESP_LOGD(TAG, "~NVS(\"%s\")", name.c_str());
  37. nvs_close(handle);
  38. }
  39. static bool checkReadError(const string &key, const string &value, esp_err_t err) {
  40. switch (err) {
  41. case ESP_OK:
  42. ESP_LOGD(TAG, "read %s from %s", value.c_str(), key.c_str());
  43. return true;
  44. case ESP_ERR_NVS_NOT_FOUND:
  45. ESP_LOGW(TAG, "key not found: %s", key.c_str());
  46. return false;
  47. default:
  48. CHECK(err); // this will always fail
  49. return false; // but the compiler cries anyway
  50. }
  51. }
  52. template<>
  53. bool nvs::NVS::read<int8_t>(const string &key, int8_t &value) {
  54. esp_err_t err = nvs_get_i8(handle, key.c_str(), &value);
  55. return checkReadError(key, std::to_string(value), err);
  56. }
  57. template<>
  58. bool nvs::NVS::read<uint8_t>(const string &key, uint8_t &value) {
  59. esp_err_t err = nvs_get_u8(handle, key.c_str(), &value);
  60. return checkReadError(key, std::to_string(value), err);
  61. }
  62. template<>
  63. bool nvs::NVS::read<int16_t>(const string &key, int16_t &value) {
  64. esp_err_t err = nvs_get_i16(handle, key.c_str(), &value);
  65. return checkReadError(key, std::to_string(value), err);
  66. }
  67. template<>
  68. bool nvs::NVS::read<uint16_t>(const string &key, uint16_t &value) {
  69. esp_err_t err = nvs_get_u16(handle, key.c_str(), &value);
  70. return checkReadError(key, std::to_string(value), err);
  71. }
  72. template<>
  73. bool nvs::NVS::read<int32_t>(const string &key, int32_t &value) {
  74. esp_err_t err = nvs_get_i32(handle, key.c_str(), &value);
  75. return checkReadError(key, std::to_string(value), err);
  76. }
  77. template<>
  78. bool nvs::NVS::read<uint32_t>(const string &key, uint32_t &value) {
  79. esp_err_t err = nvs_get_u32(handle, key.c_str(), &value);
  80. return checkReadError(key, std::to_string(value), err);
  81. }
  82. template<>
  83. bool nvs::NVS::read<string>(const string &key, string &value) {
  84. size_t size = 0;
  85. esp_err_t err = nvs_get_blob(handle, key.c_str(), nullptr, &size);
  86. if (!checkReadError(key, value, err)) return false;
  87. if (size == 0) return false;
  88. char data[size];
  89. err = nvs_get_blob(handle, key.c_str(), data, &size);
  90. if (!checkReadError(key, value, err)) return false;
  91. value = string(data, size - 1);
  92. return true;
  93. }
  94. template<>
  95. void nvs::NVS::write<int8_t>(const string &key, int8_t &value) {
  96. ESP_LOGD(TAG, "writing %d to %s", value, key.c_str());
  97. CHECK(nvs_set_i8(handle, key.c_str(), value));
  98. CHECK(nvs_commit(handle));
  99. }
  100. template<>
  101. void nvs::NVS::write<uint8_t>(const string &key, uint8_t &value) {
  102. ESP_LOGD(TAG, "writing %d to %s", value, key.c_str());
  103. CHECK(nvs_set_u8(handle, key.c_str(), value));
  104. CHECK(nvs_commit(handle));
  105. }
  106. template<>
  107. void nvs::NVS::write<int16_t>(const string &key, int16_t &value) {
  108. ESP_LOGD(TAG, "writing %d to %s", value, key.c_str());
  109. CHECK(nvs_set_i16(handle, key.c_str(), value));
  110. CHECK(nvs_commit(handle));
  111. }
  112. template<>
  113. void nvs::NVS::write<uint16_t>(const string &key, uint16_t &value) {
  114. ESP_LOGD(TAG, "writing %d to %s", value, key.c_str());
  115. CHECK(nvs_set_u16(handle, key.c_str(), value));
  116. CHECK(nvs_commit(handle));
  117. }
  118. template<>
  119. void nvs::NVS::write<int32_t>(const string &key, int32_t &value) {
  120. ESP_LOGD(TAG, "writing %d to %s", value, key.c_str());
  121. CHECK(nvs_set_i32(handle, key.c_str(), value));
  122. CHECK(nvs_commit(handle));
  123. }
  124. template<>
  125. void nvs::NVS::write<uint32_t>(const string &key, uint32_t &value) {
  126. ESP_LOGD(TAG, "writing %u to %s", value, key.c_str());
  127. CHECK(nvs_set_u32(handle, key.c_str(), value));
  128. CHECK(nvs_commit(handle));
  129. }
  130. template<>
  131. void nvs::NVS::write<string>(const string &key, string &value) {
  132. ESP_LOGD(TAG, "writing %s to %s", value.c_str(), key.c_str());
  133. CHECK(nvs_set_blob(handle, key.c_str(), value.data(), value.size() + 1));
  134. CHECK(nvs_commit(handle));
  135. }