esp_efuse_api.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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. #else
  24. #include <sys/lock.h>
  25. static _lock_t s_efuse_lock;
  26. #define EFUSE_LOCK_ACQUIRE() _lock_acquire(&s_efuse_lock)
  27. #define EFUSE_LOCK_RELEASE() _lock_release(&s_efuse_lock)
  28. #endif
  29. // Public API functions
  30. // read value from EFUSE, writing it into an array
  31. esp_err_t esp_efuse_read_field_blob(const esp_efuse_desc_t* field[], void* dst, size_t dst_size_bits)
  32. {
  33. EFUSE_LOCK_ACQUIRE();
  34. esp_err_t err = ESP_OK;
  35. if (field == NULL || dst == NULL || dst_size_bits == 0) {
  36. err = ESP_ERR_INVALID_ARG;
  37. } else {
  38. memset((uint8_t *)dst, 0, esp_efuse_utility_get_number_of_items(dst_size_bits, 8));
  39. err = esp_efuse_utility_process(field, dst, dst_size_bits, esp_efuse_utility_fill_buff);
  40. }
  41. EFUSE_LOCK_RELEASE();
  42. return err;
  43. }
  44. // read number of bits programmed as "1" in the particular field
  45. esp_err_t esp_efuse_read_field_cnt(const esp_efuse_desc_t* field[], size_t* out_cnt)
  46. {
  47. EFUSE_LOCK_ACQUIRE();
  48. esp_err_t err = ESP_OK;
  49. if (field == NULL || out_cnt == NULL) {
  50. err = ESP_ERR_INVALID_ARG;
  51. } else {
  52. *out_cnt = 0;
  53. err = esp_efuse_utility_process(field, out_cnt, 0, esp_efuse_utility_count_once);
  54. }
  55. EFUSE_LOCK_RELEASE();
  56. return err;
  57. }
  58. // write array to EFUSE
  59. esp_err_t esp_efuse_write_field_blob(const esp_efuse_desc_t* field[], const void* src, size_t src_size_bits)
  60. {
  61. EFUSE_LOCK_ACQUIRE();
  62. esp_err_t err = ESP_OK;
  63. if (field == NULL || src == NULL || src_size_bits == 0) {
  64. err = ESP_ERR_INVALID_ARG;
  65. } else {
  66. esp_efuse_utility_reset();
  67. err = esp_efuse_utility_process(field, (void*)src, src_size_bits, esp_efuse_utility_write_blob);
  68. if (err == ESP_OK) {
  69. err = esp_efuse_utility_apply_new_coding_scheme();
  70. if (err == ESP_OK) {
  71. esp_efuse_utility_burn_efuses();
  72. }
  73. }
  74. esp_efuse_utility_reset();
  75. }
  76. EFUSE_LOCK_RELEASE();
  77. return err;
  78. }
  79. // program cnt bits to "1"
  80. esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt)
  81. {
  82. EFUSE_LOCK_ACQUIRE();
  83. esp_err_t err = ESP_OK;
  84. if (field == NULL || cnt == 0) {
  85. err = ESP_ERR_INVALID_ARG;
  86. } else {
  87. esp_efuse_utility_reset();
  88. err = esp_efuse_utility_process(field, &cnt, 0, esp_efuse_utility_write_cnt);
  89. if (cnt != 0) {
  90. ESP_LOGE(TAG, "The required number of bits can not be set. [Not set %d]", cnt);
  91. err = ESP_ERR_EFUSE_CNT_IS_FULL;
  92. }
  93. if (err == ESP_OK_EFUSE_CNT || err == ESP_OK) {
  94. err = esp_efuse_utility_apply_new_coding_scheme();
  95. if (err == ESP_OK) {
  96. esp_efuse_utility_burn_efuses();
  97. }
  98. }
  99. esp_efuse_utility_reset();
  100. }
  101. EFUSE_LOCK_RELEASE();
  102. return err;
  103. }
  104. // Sets a write protection for the whole block.
  105. esp_err_t esp_efuse_set_write_protect(esp_efuse_block_t blk)
  106. {
  107. if (blk == EFUSE_BLK1) {
  108. return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_BLK1, 1);
  109. } else if (blk == EFUSE_BLK2) {
  110. return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_BLK2, 1);
  111. } else if (blk == EFUSE_BLK3) {
  112. return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_BLK3, 1);
  113. }
  114. return ESP_ERR_NOT_SUPPORTED;
  115. }
  116. // read protect for blk.
  117. esp_err_t esp_efuse_set_read_protect(esp_efuse_block_t blk)
  118. {
  119. if (blk == EFUSE_BLK1) {
  120. return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_BLK1, 1);
  121. } else if (blk == EFUSE_BLK2) {
  122. return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_BLK2, 1);
  123. } else if (blk == EFUSE_BLK3) {
  124. return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_BLK3, 1);
  125. }
  126. return ESP_ERR_NOT_SUPPORTED;
  127. }
  128. // get the length of the field in bits
  129. int esp_efuse_get_field_size(const esp_efuse_desc_t* field[])
  130. {
  131. int bits_counter = 0;
  132. if (field != NULL) {
  133. int i = 0;
  134. while (field[i] != NULL) {
  135. bits_counter += field[i]->bit_count;
  136. ++i;
  137. }
  138. }
  139. return bits_counter;
  140. }
  141. // reading efuse register.
  142. uint32_t esp_efuse_read_reg(esp_efuse_block_t blk, unsigned int num_reg)
  143. {
  144. EFUSE_LOCK_ACQUIRE();
  145. uint32_t ret_val = esp_efuse_utility_read_reg(blk, num_reg);
  146. EFUSE_LOCK_RELEASE();
  147. return ret_val;
  148. }
  149. // writing efuse register.
  150. esp_err_t esp_efuse_write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint32_t val)
  151. {
  152. EFUSE_LOCK_ACQUIRE();
  153. esp_efuse_utility_reset();
  154. esp_err_t err = esp_efuse_utility_write_reg(blk, num_reg, val);
  155. if (err == ESP_OK) {
  156. err = esp_efuse_utility_apply_new_coding_scheme();
  157. if (err == ESP_OK) {
  158. esp_efuse_utility_burn_efuses();
  159. }
  160. }
  161. esp_efuse_utility_reset();
  162. EFUSE_LOCK_RELEASE();
  163. return err;
  164. }
  165. // get efuse coding_scheme.
  166. esp_efuse_coding_scheme_t esp_efuse_get_coding_scheme(esp_efuse_block_t blk)
  167. {
  168. esp_efuse_coding_scheme_t scheme;
  169. if (blk == EFUSE_BLK0) {
  170. scheme = EFUSE_CODING_SCHEME_NONE;
  171. } else {
  172. uint32_t coding_scheme = REG_GET_FIELD(EFUSE_BLK0_RDATA6_REG, EFUSE_CODING_SCHEME);
  173. if (coding_scheme == EFUSE_CODING_SCHEME_VAL_NONE ||
  174. coding_scheme == (EFUSE_CODING_SCHEME_VAL_34 | EFUSE_CODING_SCHEME_VAL_REPEAT)) {
  175. scheme = EFUSE_CODING_SCHEME_NONE;
  176. } else if (coding_scheme == EFUSE_CODING_SCHEME_VAL_34) {
  177. scheme = EFUSE_CODING_SCHEME_3_4;
  178. } else {
  179. scheme = EFUSE_CODING_SCHEME_REPEAT;
  180. }
  181. }
  182. ESP_LOGD(TAG, "coding scheme %d", scheme);
  183. return scheme;
  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_BLK3 || 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_BLK3 || 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. }