esp_efuse_api.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. // Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include "esp_efuse.h"
  14. #include "esp_efuse_utility.h"
  15. #include "soc/efuse_periph.h"
  16. #include "assert.h"
  17. #include "sdkconfig.h"
  18. #include "esp_efuse_table.h"
  19. const static char *TAG = "efuse";
  20. #if defined(BOOTLOADER_BUILD)
  21. #define EFUSE_LOCK_ACQUIRE()
  22. #define EFUSE_LOCK_RELEASE()
  23. #define EFUSE_LOCK_ACQUIRE_RECURSIVE()
  24. #define EFUSE_LOCK_RELEASE_RECURSIVE()
  25. #else
  26. #include <sys/lock.h>
  27. static _lock_t s_efuse_lock;
  28. #define EFUSE_LOCK_ACQUIRE() _lock_acquire(&s_efuse_lock)
  29. #define EFUSE_LOCK_RELEASE() _lock_release(&s_efuse_lock)
  30. #define EFUSE_LOCK_ACQUIRE_RECURSIVE() _lock_acquire_recursive(&s_efuse_lock)
  31. #define EFUSE_LOCK_RELEASE_RECURSIVE() _lock_release_recursive(&s_efuse_lock)
  32. #endif
  33. static bool s_batch_writing_mode = false;
  34. // Public API functions
  35. // read value from EFUSE, writing it into an array
  36. esp_err_t esp_efuse_read_field_blob(const esp_efuse_desc_t* field[], void* dst, size_t dst_size_bits)
  37. {
  38. EFUSE_LOCK_ACQUIRE();
  39. esp_err_t err = ESP_OK;
  40. if (field == NULL || dst == NULL || dst_size_bits == 0) {
  41. err = ESP_ERR_INVALID_ARG;
  42. } else {
  43. memset((uint8_t *)dst, 0, esp_efuse_utility_get_number_of_items(dst_size_bits, 8));
  44. err = esp_efuse_utility_process(field, dst, dst_size_bits, esp_efuse_utility_fill_buff);
  45. }
  46. EFUSE_LOCK_RELEASE();
  47. return err;
  48. }
  49. bool esp_efuse_read_field_bit(const esp_efuse_desc_t *field[])
  50. {
  51. uint8_t value = 0;
  52. esp_err_t err = esp_efuse_read_field_blob(field, &value, 1);
  53. assert(err == ESP_OK);
  54. return (err == ESP_OK) && value;
  55. }
  56. // read number of bits programmed as "1" in the particular field
  57. esp_err_t esp_efuse_read_field_cnt(const esp_efuse_desc_t* field[], size_t* out_cnt)
  58. {
  59. EFUSE_LOCK_ACQUIRE();
  60. esp_err_t err = ESP_OK;
  61. if (field == NULL || out_cnt == NULL) {
  62. err = ESP_ERR_INVALID_ARG;
  63. } else {
  64. *out_cnt = 0;
  65. err = esp_efuse_utility_process(field, out_cnt, 0, esp_efuse_utility_count_once);
  66. }
  67. EFUSE_LOCK_RELEASE();
  68. return err;
  69. }
  70. // write array to EFUSE
  71. esp_err_t esp_efuse_write_field_blob(const esp_efuse_desc_t* field[], const void* src, size_t src_size_bits)
  72. {
  73. EFUSE_LOCK_ACQUIRE_RECURSIVE();
  74. esp_err_t err = ESP_OK;
  75. if (field == NULL || src == NULL || src_size_bits == 0) {
  76. err = ESP_ERR_INVALID_ARG;
  77. } else {
  78. if (s_batch_writing_mode == false) {
  79. esp_efuse_utility_reset();
  80. }
  81. err = esp_efuse_utility_process(field, (void*)src, src_size_bits, esp_efuse_utility_write_blob);
  82. if (s_batch_writing_mode == false) {
  83. if (err == ESP_OK) {
  84. err = esp_efuse_utility_apply_new_coding_scheme();
  85. if (err == ESP_OK) {
  86. esp_efuse_utility_burn_efuses();
  87. }
  88. }
  89. esp_efuse_utility_reset();
  90. }
  91. }
  92. EFUSE_LOCK_RELEASE_RECURSIVE();
  93. return err;
  94. }
  95. // program cnt bits to "1"
  96. esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt)
  97. {
  98. EFUSE_LOCK_ACQUIRE_RECURSIVE();
  99. esp_err_t err = ESP_OK;
  100. if (field == NULL || cnt == 0) {
  101. err = ESP_ERR_INVALID_ARG;
  102. } else {
  103. if (s_batch_writing_mode == false) {
  104. esp_efuse_utility_reset();
  105. }
  106. err = esp_efuse_utility_process(field, &cnt, 0, esp_efuse_utility_write_cnt);
  107. if (cnt != 0) {
  108. ESP_LOGE(TAG, "The required number of bits can not be set. [Not set %d]", cnt);
  109. err = ESP_ERR_EFUSE_CNT_IS_FULL;
  110. }
  111. if (err == ESP_OK_EFUSE_CNT) {
  112. err = ESP_OK;
  113. }
  114. if (s_batch_writing_mode == false) {
  115. if (err == ESP_OK) {
  116. err = esp_efuse_utility_apply_new_coding_scheme();
  117. if (err == ESP_OK) {
  118. esp_efuse_utility_burn_efuses();
  119. }
  120. }
  121. esp_efuse_utility_reset();
  122. }
  123. }
  124. EFUSE_LOCK_RELEASE_RECURSIVE();
  125. return err;
  126. }
  127. esp_err_t esp_efuse_write_field_bit(const esp_efuse_desc_t* field[])
  128. {
  129. esp_err_t err;
  130. uint8_t existing = 0;
  131. const uint8_t one = 1;
  132. if (field == NULL || field[0]->bit_count != 1) {
  133. return ESP_ERR_INVALID_ARG;
  134. }
  135. /* Check existing value. esp_efuse_write_field_blob() also checks this, but will log an error */
  136. err = esp_efuse_read_field_blob(field, &existing, 1);
  137. if (err != ESP_OK || existing) {
  138. return err; // Error reading, or the bit is already written and we can no-op this
  139. }
  140. return esp_efuse_write_field_blob(field, &one, 1);
  141. }
  142. // get the length of the field in bits
  143. int esp_efuse_get_field_size(const esp_efuse_desc_t* field[])
  144. {
  145. int bits_counter = 0;
  146. if (field != NULL) {
  147. int i = 0;
  148. while (field[i] != NULL) {
  149. bits_counter += field[i]->bit_count;
  150. ++i;
  151. }
  152. }
  153. return bits_counter;
  154. }
  155. // reading efuse register.
  156. uint32_t esp_efuse_read_reg(esp_efuse_block_t blk, unsigned int num_reg)
  157. {
  158. EFUSE_LOCK_ACQUIRE();
  159. uint32_t ret_val = esp_efuse_utility_read_reg(blk, num_reg);
  160. EFUSE_LOCK_RELEASE();
  161. return ret_val;
  162. }
  163. // writing efuse register.
  164. esp_err_t esp_efuse_write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint32_t val)
  165. {
  166. EFUSE_LOCK_ACQUIRE_RECURSIVE();
  167. if (s_batch_writing_mode == false) {
  168. esp_efuse_utility_reset();
  169. }
  170. esp_err_t err = esp_efuse_utility_write_reg(blk, num_reg, val);
  171. if (s_batch_writing_mode == false) {
  172. if (err == ESP_OK) {
  173. err = esp_efuse_utility_apply_new_coding_scheme();
  174. if (err == ESP_OK) {
  175. esp_efuse_utility_burn_efuses();
  176. }
  177. }
  178. esp_efuse_utility_reset();
  179. }
  180. EFUSE_LOCK_RELEASE_RECURSIVE();
  181. return err;
  182. }
  183. // This function reads the key from the efuse block, starting at the offset and the required size.
  184. esp_err_t esp_efuse_read_block(esp_efuse_block_t blk, void* dst_key, size_t offset_in_bits, size_t size_bits)
  185. {
  186. esp_err_t err = ESP_OK;
  187. if (blk == EFUSE_BLK0 || blk >= EFUSE_BLK_MAX || dst_key == NULL || size_bits == 0) {
  188. err = ESP_ERR_INVALID_ARG;
  189. } else {
  190. const esp_efuse_desc_t field_desc[] = {
  191. {blk, offset_in_bits, size_bits},
  192. };
  193. const esp_efuse_desc_t* field[] = {
  194. &field_desc[0],
  195. NULL
  196. };
  197. err = esp_efuse_read_field_blob(field, dst_key, size_bits);
  198. }
  199. return err;
  200. }
  201. // This function writes the key from the efuse block, starting at the offset and the required size.
  202. esp_err_t esp_efuse_write_block(esp_efuse_block_t blk, const void* src_key, size_t offset_in_bits, size_t size_bits)
  203. {
  204. esp_err_t err = ESP_OK;
  205. if (blk == EFUSE_BLK0 || blk >= EFUSE_BLK_MAX || src_key == NULL || size_bits == 0) {
  206. err = ESP_ERR_INVALID_ARG;
  207. } else {
  208. const esp_efuse_desc_t field_desc[] = {
  209. {blk, offset_in_bits, size_bits},
  210. };
  211. const esp_efuse_desc_t* field[] = {
  212. &field_desc[0],
  213. NULL
  214. };
  215. err = esp_efuse_write_field_blob(field, src_key, size_bits);
  216. }
  217. return err;
  218. }
  219. esp_err_t esp_efuse_batch_write_begin(void)
  220. {
  221. EFUSE_LOCK_ACQUIRE();
  222. s_batch_writing_mode = true;
  223. esp_efuse_utility_reset();
  224. ESP_LOGI(TAG, "Batch mode of writing fields is enabled");
  225. return ESP_OK;
  226. }
  227. esp_err_t esp_efuse_batch_write_cancel(void)
  228. {
  229. if (s_batch_writing_mode == true) {
  230. s_batch_writing_mode = false;
  231. esp_efuse_utility_reset();
  232. ESP_LOGI(TAG, "Batch mode of writing fields is disabled");
  233. EFUSE_LOCK_RELEASE();
  234. return ESP_OK;
  235. } else {
  236. return ESP_ERR_INVALID_STATE;
  237. }
  238. }
  239. esp_err_t esp_efuse_batch_write_commit(void)
  240. {
  241. if (s_batch_writing_mode == false) {
  242. return ESP_ERR_INVALID_STATE;
  243. } else {
  244. esp_err_t err = esp_efuse_utility_apply_new_coding_scheme();
  245. if (err == ESP_OK) {
  246. esp_efuse_utility_burn_efuses();
  247. }
  248. esp_efuse_batch_write_cancel();
  249. return err;
  250. }
  251. }