esp_efuse_api.c 8.5 KB

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