test_efuse.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <errno.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include "unity.h"
  7. #include "esp_log.h"
  8. #include <string.h>
  9. #include "esp_efuse.h"
  10. #include "esp_efuse_table.h"
  11. #include "esp_efuse_utility.h"
  12. #include "esp_efuse_test_table.h"
  13. #include "esp32/rom/efuse.h"
  14. #include "bootloader_random.h"
  15. #include "freertos/FreeRTOS.h"
  16. #include "freertos/task.h"
  17. #include "freertos/semphr.h"
  18. #include "test_utils.h"
  19. #include "sdkconfig.h"
  20. static const char* TAG = "efuse_test";
  21. static void test_read_blob(void)
  22. {
  23. esp_efuse_utility_update_virt_blocks();
  24. esp_efuse_utility_debug_dump_blocks();
  25. uint8_t mac[6];
  26. ESP_LOGI(TAG, "1. Read MAC address");
  27. memset(mac, 0, sizeof(mac));
  28. TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, &mac, sizeof(mac) * 8));
  29. TEST_ASSERT_EQUAL_INT(sizeof(mac) * 8, esp_efuse_get_field_size(ESP_EFUSE_MAC_FACTORY));
  30. ESP_LOGI(TAG, "MAC: %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  31. #if CONFIG_IDF_TARGET_ESP32
  32. ESP_LOGI(TAG, "2. Check CRC by MAC");
  33. uint8_t crc;
  34. TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY_CRC, &crc, 8));
  35. TEST_ASSERT_EQUAL_HEX8(crc, esp_crc8(mac, sizeof(mac)));
  36. #endif // CONFIG_IDF_TARGET_ESP32
  37. ESP_LOGI(TAG, "3. Test check args");
  38. uint32_t test_var;
  39. TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, NULL, 1));
  40. TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, &test_var, 0));
  41. uint8_t half_byte;
  42. TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, &half_byte, 4));
  43. TEST_ASSERT_EQUAL_HEX8(mac[0]&0x0F, half_byte);
  44. uint8_t buff[7] = {0x59};
  45. TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, &buff, sizeof(buff) * 8));
  46. TEST_ASSERT_TRUE_MESSAGE(memcmp(mac, buff, sizeof(mac)) == 0, "Operation read blob is not success");
  47. TEST_ASSERT_EQUAL_HEX8(0, buff[6]);
  48. }
  49. TEST_CASE("efuse test read_field_blob", "[efuse]")
  50. {
  51. test_read_blob();
  52. }
  53. static void test_read_cnt(void)
  54. {
  55. esp_efuse_utility_update_virt_blocks();
  56. esp_efuse_utility_debug_dump_blocks();
  57. ESP_LOGI(TAG, "1. Test check args");
  58. size_t cnt;
  59. TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_read_field_cnt(ESP_EFUSE_MAC_FACTORY, NULL));
  60. ESP_LOGI(TAG, "2. Read MAC address");
  61. uint8_t mac[6];
  62. memset(mac, 0, sizeof(mac));
  63. TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, &mac, 48));
  64. TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_MAC_FACTORY, &cnt));
  65. size_t cnt_summ = 0;
  66. for (int i = 0; i < sizeof(mac); ++i) {
  67. cnt_summ += __builtin_popcount(mac[i]);
  68. }
  69. TEST_ASSERT_EQUAL_INT(cnt_summ, cnt);
  70. }
  71. TEST_CASE("efuse test read_field_cnt", "[efuse]")
  72. {
  73. test_read_cnt();
  74. }
  75. // If using efuse is real, then turn off writing tests.
  76. #ifdef CONFIG_EFUSE_VIRTUAL
  77. static void test_write_blob(void)
  78. {
  79. esp_efuse_coding_scheme_t scheme = esp_efuse_get_coding_scheme(EFUSE_BLK1);
  80. esp_efuse_utility_erase_virt_blocks();
  81. esp_efuse_utility_debug_dump_blocks();
  82. ESP_LOGI(TAG, "1. Test check args");
  83. uint16_t test1_len_8 = 0x5FAA;
  84. TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_write_field_blob(ESP_EFUSE_MAC_FACTORY, &test1_len_8, 0));
  85. TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_write_field_blob(ESP_EFUSE_TEST1_LEN_8, NULL, 8));
  86. TEST_ASSERT_EQUAL_HEX16(0x5FAA, test1_len_8);
  87. ESP_LOGI(TAG, "2. Test write operation");
  88. TEST_ESP_OK(esp_efuse_write_field_blob(ESP_EFUSE_TEST1_LEN_8, &test1_len_8, 7));
  89. TEST_ESP_ERR(ESP_ERR_EFUSE_REPEATED_PROG, esp_efuse_write_field_blob(ESP_EFUSE_TEST1_LEN_8, &test1_len_8, 9));
  90. uint16_t val_read1 = 0;
  91. TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST1_LEN_8, &val_read1, 8));
  92. TEST_ASSERT_EQUAL_HEX16(test1_len_8&((1 << 7) - 1), val_read1);
  93. uint16_t test1_len_8_hi = test1_len_8 & ~((1 << 7) - 1);
  94. if (scheme == EFUSE_CODING_SCHEME_NONE) {
  95. TEST_ESP_OK(esp_efuse_write_field_blob(ESP_EFUSE_TEST1_LEN_8, &test1_len_8_hi, 8));
  96. } else {
  97. TEST_ESP_ERR(ESP_ERR_CODING, esp_efuse_write_field_blob(ESP_EFUSE_TEST1_LEN_8, &test1_len_8_hi, 8));
  98. }
  99. TEST_ESP_ERR(ESP_ERR_EFUSE_REPEATED_PROG, esp_efuse_write_field_blob(ESP_EFUSE_TEST1_LEN_8, &test1_len_8, 8));
  100. val_read1 = 0;
  101. TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST1_LEN_8, &val_read1, 16));
  102. if (scheme == EFUSE_CODING_SCHEME_NONE) {
  103. TEST_ASSERT_EQUAL_HEX16(test1_len_8&0x00FF, val_read1);
  104. } else {
  105. TEST_ASSERT_EQUAL_HEX16(test1_len_8&0x007F, val_read1);
  106. }
  107. if (scheme != EFUSE_CODING_SCHEME_NONE) {
  108. esp_efuse_utility_erase_virt_blocks();
  109. ESP_LOGI(TAG, "erase virt blocks");
  110. }
  111. uint16_t test2_len_16 = 0xAA55;
  112. uint32_t val_32 = test2_len_16;
  113. TEST_ESP_OK(esp_efuse_write_field_blob(ESP_EFUSE_TEST2_LEN_16, &val_32, 17));
  114. TEST_ESP_ERR(ESP_ERR_EFUSE_REPEATED_PROG, esp_efuse_write_field_blob(ESP_EFUSE_TEST2_LEN_16, &test2_len_16, 16));
  115. uint16_t test_16 = 0;
  116. TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST2_LEN_16, &test_16, 16));
  117. TEST_ASSERT_EQUAL_HEX16(test2_len_16, test_16);
  118. ESP_LOGI(TAG, "3. Test field with one bit");
  119. uint8_t test5_len_1;
  120. TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test5_len_1, 1));
  121. TEST_ASSERT_EQUAL_HEX8(0, test5_len_1);
  122. test5_len_1 = 0;
  123. TEST_ESP_OK(esp_efuse_write_field_blob(ESP_EFUSE_TEST5_LEN_1, &test5_len_1, 1));
  124. TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test5_len_1, 1));
  125. TEST_ASSERT_EQUAL_HEX8(0, test5_len_1);
  126. test5_len_1 = 1;
  127. TEST_ESP_OK(esp_efuse_write_field_blob(ESP_EFUSE_TEST5_LEN_1, &test5_len_1, 1));
  128. TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test5_len_1, 1));
  129. TEST_ASSERT_EQUAL_HEX8(1, test5_len_1);
  130. test5_len_1 = 1;
  131. TEST_ESP_ERR(ESP_ERR_EFUSE_REPEATED_PROG, esp_efuse_write_field_blob(ESP_EFUSE_TEST5_LEN_1, &test5_len_1, 1));
  132. esp_efuse_utility_debug_dump_blocks();
  133. }
  134. TEST_CASE("efuse test write_field_blob", "[efuse]")
  135. {
  136. test_write_blob();
  137. }
  138. static void test_write_cnt(void)
  139. {
  140. esp_efuse_coding_scheme_t scheme = esp_efuse_get_coding_scheme(EFUSE_BLK1);
  141. esp_efuse_utility_erase_virt_blocks();
  142. esp_efuse_utility_debug_dump_blocks();
  143. ESP_LOGI(TAG, "1. Test check args");
  144. size_t test3_len_6 = 5;
  145. TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_write_field_cnt(ESP_EFUSE_MAC_FACTORY, 0));
  146. TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_write_field_cnt(NULL, 5));
  147. TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_write_field_cnt(ESP_EFUSE_TEST3_LEN_6, 0));
  148. ESP_LOGI(TAG, "2. Test write operation");
  149. TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_TEST3_LEN_6, &test3_len_6));
  150. TEST_ASSERT_EQUAL_INT(0, test3_len_6);
  151. TEST_ESP_OK(esp_efuse_write_field_cnt(ESP_EFUSE_TEST3_LEN_6, 1));
  152. TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_TEST3_LEN_6, &test3_len_6));
  153. TEST_ASSERT_EQUAL_INT(1, test3_len_6);
  154. if (scheme == EFUSE_CODING_SCHEME_NONE) {
  155. TEST_ESP_OK(esp_efuse_write_field_cnt(ESP_EFUSE_TEST3_LEN_6, 1));
  156. } else {
  157. esp_efuse_utility_erase_virt_blocks();
  158. ESP_LOGI(TAG, "erase virt blocks");
  159. TEST_ESP_OK(esp_efuse_write_field_cnt(ESP_EFUSE_TEST3_LEN_6, 2));
  160. }
  161. TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_TEST3_LEN_6, &test3_len_6));
  162. TEST_ASSERT_EQUAL_INT(2, test3_len_6);
  163. if (scheme == EFUSE_CODING_SCHEME_NONE) {
  164. TEST_ESP_OK(esp_efuse_write_field_cnt(ESP_EFUSE_TEST3_LEN_6, 3));
  165. } else {
  166. esp_efuse_utility_erase_virt_blocks();
  167. ESP_LOGI(TAG, "erase virt blocks");
  168. TEST_ESP_OK(esp_efuse_write_field_cnt(ESP_EFUSE_TEST3_LEN_6, 5));
  169. }
  170. TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_TEST3_LEN_6, &test3_len_6));
  171. TEST_ASSERT_EQUAL_INT(5, test3_len_6);
  172. esp_efuse_utility_debug_dump_blocks();
  173. ESP_LOGI(TAG, "3. Test field is full set");
  174. int max_bits = esp_efuse_get_field_size(ESP_EFUSE_TEST4_LEN_182);
  175. size_t test4_len_182;
  176. esp_efuse_utility_debug_dump_blocks();
  177. for (int i = 0; i < max_bits / 26; ++i) {
  178. ESP_LOGD(TAG, "# %d", i);
  179. if (scheme == EFUSE_CODING_SCHEME_NONE) {
  180. TEST_ESP_OK(esp_efuse_write_field_cnt(ESP_EFUSE_TEST4_LEN_182, 26));
  181. } else {
  182. esp_efuse_utility_erase_virt_blocks();
  183. TEST_ESP_OK(esp_efuse_write_field_cnt(ESP_EFUSE_TEST4_LEN_182, (i + 1) * 26));
  184. }
  185. TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_TEST4_LEN_182, &test4_len_182));
  186. esp_efuse_utility_debug_dump_blocks();
  187. TEST_ASSERT_EQUAL_INT((i + 1) * 26, test4_len_182);
  188. }
  189. esp_efuse_utility_debug_dump_blocks();
  190. ESP_LOGI(TAG, "4. Test field ESP_EFUSE_TEST4_LEN_182 is full");
  191. TEST_ESP_ERR(ESP_ERR_EFUSE_CNT_IS_FULL, esp_efuse_write_field_cnt(ESP_EFUSE_TEST4_LEN_182, 1));
  192. ESP_LOGI(TAG, "3. Test field with one bit");
  193. size_t test5_len_1;
  194. TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_TEST5_LEN_1, &test5_len_1));
  195. TEST_ASSERT_EQUAL_HEX8(0, test5_len_1);
  196. TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test5_len_1, 1));
  197. TEST_ASSERT_EQUAL_HEX8(0, test5_len_1);
  198. if (scheme != EFUSE_CODING_SCHEME_NONE) {
  199. esp_efuse_utility_erase_virt_blocks();
  200. ESP_LOGI(TAG, "erase virt blocks");
  201. }
  202. test5_len_1 = 1;
  203. TEST_ESP_OK(esp_efuse_write_field_cnt(ESP_EFUSE_TEST5_LEN_1, test5_len_1));
  204. TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_TEST5_LEN_1, &test5_len_1));
  205. TEST_ASSERT_EQUAL_HEX8(1, test5_len_1);
  206. TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test5_len_1, 1));
  207. TEST_ASSERT_EQUAL_HEX8(1, test5_len_1);
  208. test5_len_1 = 1;
  209. TEST_ESP_ERR(ESP_ERR_EFUSE_CNT_IS_FULL, esp_efuse_write_field_cnt(ESP_EFUSE_TEST5_LEN_1, test5_len_1));
  210. esp_efuse_utility_debug_dump_blocks();
  211. ESP_LOGI(TAG, "4. Test field test2_len_16");
  212. size_t test2_len_16 = 11;
  213. TEST_ESP_OK(esp_efuse_write_field_cnt(ESP_EFUSE_TEST2_LEN_16, test2_len_16));
  214. TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_TEST2_LEN_16, &test2_len_16));
  215. TEST_ASSERT_EQUAL_HEX16(11, test2_len_16);
  216. TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST2_LEN_16, &test2_len_16, 16));
  217. TEST_ASSERT_EQUAL_HEX16(0x07FF, test2_len_16);
  218. esp_efuse_utility_debug_dump_blocks();
  219. }
  220. TEST_CASE("efuse test write_field_cnt", "[efuse]")
  221. {
  222. test_write_cnt();
  223. }
  224. void cut_tail_arr(uint8_t *arr, int num_used_bits, size_t count_bits)
  225. {
  226. if ((num_used_bits + count_bits) % 8) {
  227. int start_used_item = (num_used_bits - 1) / 8;
  228. int last_used_item = ((num_used_bits + count_bits) - 1) / 8;
  229. int shift = 0;
  230. int mask = num_used_bits + count_bits;
  231. if (last_used_item == start_used_item) {
  232. shift = (num_used_bits) % 8;
  233. mask = count_bits;
  234. }
  235. arr[last_used_item] &= ((1 << (mask % 8)) - 1) << shift;
  236. }
  237. }
  238. void cut_start_arr(uint8_t *arr, size_t num_used_bits)
  239. {
  240. if (num_used_bits % 8) {
  241. int start_used_item = (num_used_bits - 1) / 8;
  242. arr[start_used_item] &= ~((1 << (num_used_bits % 8)) - 1);
  243. }
  244. }
  245. void get_part_arr(uint8_t *arr_in, uint8_t *arr_out, int num_used_bits, int count_bits)
  246. {
  247. int num_items = esp_efuse_utility_get_number_of_items(num_used_bits + count_bits, 8);
  248. memcpy(arr_out, arr_in, num_items);
  249. memset(arr_out, 0, num_used_bits / 8);
  250. cut_start_arr(arr_out, num_used_bits);
  251. cut_tail_arr(arr_out, num_used_bits, count_bits);
  252. }
  253. void fill_part_arr(uint8_t *arr_in, uint8_t *arr_out, int count_bits)
  254. {
  255. int num_items = esp_efuse_utility_get_number_of_items(count_bits, 8);
  256. memcpy(arr_out, arr_in, num_items);
  257. cut_tail_arr(arr_out, 0, count_bits);
  258. }
  259. // Writes a random array to efuse, then reads and compares it.
  260. void test_blob(const esp_efuse_desc_t* field[], uint8_t *arr_w, uint8_t *arr_r, uint8_t *arr_temp, int arr_size, size_t field_size)
  261. {
  262. ESP_LOG_BUFFER_HEX_LEVEL(TAG, arr_w, arr_size, ESP_LOG_INFO);
  263. TEST_ESP_OK(esp_efuse_write_field_blob(field, arr_w, field_size));
  264. memset(arr_r, 0, arr_size);
  265. TEST_ESP_OK(esp_efuse_read_field_blob(field, arr_r, field_size));
  266. ESP_LOG_BUFFER_HEX_LEVEL(TAG, arr_r, arr_size, ESP_LOG_INFO);
  267. esp_efuse_utility_debug_dump_blocks();
  268. TEST_ASSERT_TRUE_MESSAGE(memcmp(arr_w, arr_r, arr_size) == 0, "Operation write/read blob is not success");
  269. int count_once = 0;
  270. for (int i = 0; i < arr_size; ++i) {
  271. count_once += __builtin_popcount(arr_w[i]);
  272. }
  273. size_t num_bits_r = 0;
  274. TEST_ESP_OK(esp_efuse_read_field_cnt(field, &num_bits_r));
  275. TEST_ASSERT_EQUAL_INT(count_once, num_bits_r);
  276. size_t num_bits_w = field_size - count_once;
  277. if (num_bits_w == 0) {
  278. esp_efuse_utility_erase_virt_blocks();
  279. num_bits_w = field_size;
  280. }
  281. TEST_ESP_OK(esp_efuse_write_field_cnt(field, num_bits_w));
  282. TEST_ESP_OK(esp_efuse_read_field_cnt(field, &num_bits_r));
  283. esp_efuse_utility_debug_dump_blocks();
  284. TEST_ASSERT_EQUAL_INT(field_size, num_bits_r);
  285. memset(arr_r, 0, arr_size);
  286. TEST_ESP_OK(esp_efuse_read_field_blob(field, arr_r, field_size));
  287. memset(arr_temp, 0xFF, arr_size);
  288. cut_tail_arr(arr_temp, 0, field_size);
  289. esp_efuse_utility_debug_dump_blocks();
  290. TEST_ASSERT_TRUE_MESSAGE(memcmp(arr_temp, arr_r, arr_size) == 0, "Operation write/read blob is not success");
  291. }
  292. // Records a random number of bits (as "1") in the efuse field, then reads and compares.
  293. void test_cnt_part(const esp_efuse_desc_t* field[], uint8_t *arr_r, int arr_size, size_t field_size)
  294. {
  295. size_t num_bits_r = 0;
  296. TEST_ESP_OK(esp_efuse_read_field_cnt(field, &num_bits_r));
  297. TEST_ASSERT_EQUAL_INT(0, num_bits_r);
  298. TEST_ESP_OK(esp_efuse_write_field_cnt(field, field_size));
  299. TEST_ESP_OK(esp_efuse_read_field_cnt(field, &num_bits_r));
  300. TEST_ASSERT_EQUAL_INT(field_size, num_bits_r);
  301. esp_efuse_utility_erase_virt_blocks();
  302. int num_bits_summ_r = 0;
  303. int num_bits_w = 0;
  304. while(field_size > num_bits_summ_r) {
  305. num_bits_w = 0;
  306. while(num_bits_w == 0 || (num_bits_summ_r + num_bits_w) > field_size) {
  307. bootloader_random_enable();
  308. bootloader_fill_random(&num_bits_w, 1);
  309. bootloader_random_disable();
  310. num_bits_w = num_bits_w * field_size / 255;
  311. if (num_bits_w != 0 && (num_bits_summ_r + num_bits_w) <= field_size) {
  312. break;
  313. }
  314. }
  315. TEST_ESP_OK(esp_efuse_write_field_cnt(field, num_bits_w));
  316. TEST_ESP_OK(esp_efuse_read_field_cnt(field, &num_bits_r));
  317. num_bits_summ_r += num_bits_w;
  318. TEST_ASSERT_EQUAL_INT(num_bits_summ_r, num_bits_r);
  319. memset(arr_r, 0, arr_size);
  320. TEST_ESP_OK(esp_efuse_read_field_blob(field, arr_r, field_size));
  321. int count_once = 0;
  322. for (int i = 0; i < arr_size; ++i) {
  323. count_once += __builtin_popcount(arr_r[i]);
  324. }
  325. TEST_ASSERT_EQUAL_INT(num_bits_summ_r, count_once);
  326. ESP_LOGI(TAG, "Once bits=%d, step=%d", num_bits_summ_r, num_bits_w);
  327. }
  328. esp_efuse_utility_debug_dump_blocks();
  329. }
  330. // From a random array takes a random number of bits and write to efuse, it repeats until the entire length of the field is written down.
  331. void test_blob_part(const esp_efuse_desc_t* field[], uint8_t *arr_w, uint8_t *arr_r, uint8_t *arr_temp, int arr_size, size_t field_size)
  332. {
  333. esp_efuse_utility_debug_dump_blocks();
  334. int num_bits_summ_r = 0;
  335. int num_bits_w = 0;
  336. memset(arr_w, 0, arr_size);
  337. bootloader_random_enable();
  338. bootloader_fill_random(arr_w, arr_size);
  339. bootloader_random_disable();
  340. ESP_LOG_BUFFER_HEX_LEVEL(TAG, arr_w, arr_size, ESP_LOG_INFO);
  341. while(field_size > num_bits_summ_r) {
  342. num_bits_w = 0;
  343. while(num_bits_w == 0 || (num_bits_summ_r + num_bits_w) > field_size) {
  344. bootloader_random_enable();
  345. bootloader_fill_random(&num_bits_w, 1);
  346. bootloader_random_disable();
  347. num_bits_w = num_bits_w * field_size / 255;
  348. if (num_bits_w != 0 && (num_bits_summ_r + num_bits_w) <= field_size) {
  349. break;
  350. }
  351. }
  352. ESP_LOGI(TAG, "Summ bits=%d, step=%d", num_bits_summ_r, num_bits_w);
  353. memset(arr_temp, 0, arr_size);
  354. get_part_arr(arr_w, arr_temp, num_bits_summ_r, num_bits_w);
  355. ESP_LOG_BUFFER_HEX_LEVEL(TAG, arr_temp, arr_size, ESP_LOG_INFO);
  356. TEST_ESP_OK(esp_efuse_write_field_blob(field, arr_temp, field_size));
  357. memset(arr_r, 0, arr_size);
  358. TEST_ESP_OK(esp_efuse_read_field_blob(field, arr_r, field_size));
  359. ESP_LOG_BUFFER_HEX_LEVEL(TAG, arr_r, arr_size, ESP_LOG_INFO);
  360. esp_efuse_utility_debug_dump_blocks();
  361. num_bits_summ_r += num_bits_w;
  362. memset(arr_temp, 0, arr_size);
  363. fill_part_arr(arr_w, arr_temp, num_bits_summ_r);
  364. ESP_LOG_BUFFER_HEX_LEVEL(TAG, arr_temp, arr_size, ESP_LOG_INFO);
  365. TEST_ASSERT_TRUE_MESSAGE(memcmp(arr_temp, arr_r, arr_size) == 0, "Operation write/read blob is not success");
  366. }
  367. }
  368. void check_efuse_table_test(int cycle)
  369. {
  370. int num_test = 0;
  371. while(1) {
  372. const esp_efuse_desc_t** field;
  373. switch (num_test++) {
  374. case 0: field = ESP_EFUSE_TEST1_LEN_8; break;
  375. case 1: field = ESP_EFUSE_TEST2_LEN_16; break;
  376. case 2: field = ESP_EFUSE_TEST3_LEN_6; break;
  377. case 3: field = ESP_EFUSE_TEST4_LEN_182; break;
  378. case 4: field = ESP_EFUSE_TEST5_LEN_1; break;
  379. case 5: field = ESP_EFUSE_TEST6_LEN_17; break;
  380. default:
  381. return;
  382. break;
  383. }
  384. size_t field_size = esp_efuse_get_field_size(field);
  385. int arr_size = esp_efuse_utility_get_number_of_items(field_size, 8);
  386. uint8_t *arr_w = (uint8_t *) malloc(arr_size);
  387. uint8_t *arr_r = (uint8_t *) malloc(arr_size);
  388. uint8_t *arr_temp = (uint8_t *) malloc(arr_size);
  389. ESP_LOGI(TAG, "Test#%d", num_test);
  390. for (int c = 1; c <= cycle; ++c) {
  391. ESP_LOGI(TAG, "Cycle#%d/%d", c, cycle);
  392. memset(arr_w, 0, arr_size);
  393. bootloader_random_enable();
  394. bootloader_fill_random(arr_w, arr_size);
  395. bootloader_random_disable();
  396. cut_tail_arr(arr_w, 0, field_size);
  397. esp_efuse_utility_erase_virt_blocks();
  398. ESP_LOGI(TAG, "1) blob write/read");
  399. test_blob(field, arr_w, arr_r, arr_temp, arr_size, field_size);
  400. esp_efuse_utility_erase_virt_blocks();
  401. ESP_LOGI(TAG, "2) cnt part write/read");
  402. test_cnt_part(field, arr_r, arr_size, field_size);
  403. esp_efuse_utility_erase_virt_blocks();
  404. ESP_LOGI(TAG, "3) blob part write/read");
  405. test_blob_part(field, arr_w, arr_r, arr_temp, arr_size, field_size);
  406. }
  407. free(arr_temp);
  408. free(arr_r);
  409. free(arr_w);
  410. }
  411. }
  412. TEST_CASE("efuse esp_efuse_table_test", "[efuse]")
  413. {
  414. esp_efuse_coding_scheme_t coding_scheme = esp_efuse_get_coding_scheme(EFUSE_BLK2);
  415. if (coding_scheme == EFUSE_CODING_SCHEME_NONE) {
  416. check_efuse_table_test(2);
  417. } else {
  418. ESP_LOGI(TAG, "This test is applicable only to the EFUSE_CODING_SCHEME_NONE. Skip this test.");
  419. }
  420. }
  421. TEST_CASE("Test esp_efuse_read_block esp_efuse_write_block functions", "[efuse]")
  422. {
  423. int count_useful_reg = 0;
  424. esp_efuse_coding_scheme_t coding_scheme = esp_efuse_get_coding_scheme(EFUSE_BLK2);
  425. if (coding_scheme == EFUSE_CODING_SCHEME_NONE) {
  426. printf("EFUSE_CODING_SCHEME_NONE\n");
  427. count_useful_reg = 8;
  428. }
  429. #if CONFIG_IDF_TARGET_ESP32
  430. if (coding_scheme == EFUSE_CODING_SCHEME_3_4) {
  431. printf("EFUSE_CODING_SCHEME_3_4\n");
  432. count_useful_reg = 6;
  433. } else if (coding_scheme == EFUSE_CODING_SCHEME_REPEAT) {
  434. printf("EFUSE_CODING_SCHEME_REPEAT\n");
  435. count_useful_reg = 4;
  436. }
  437. #elif CONFIG_IDF_TARGET_ESP32S2BETA
  438. if (coding_scheme == EFUSE_CODING_SCHEME_RS) {
  439. printf("EFUSE_CODING_SCHEME_RS\n");
  440. count_useful_reg = 8;
  441. }
  442. #endif
  443. esp_efuse_utility_reset();
  444. esp_efuse_utility_erase_virt_blocks();
  445. uint8_t src_key[32] = { 0 };
  446. uint8_t dst_key[32] = { 0 };
  447. int offset_in_bits = 0;
  448. for (int i = 0; i < count_useful_reg * 4; ++i) {
  449. src_key[i] = 0xAB + i;
  450. }
  451. TEST_ESP_OK(esp_efuse_write_block(EFUSE_BLK2, src_key, offset_in_bits, count_useful_reg * 32));
  452. TEST_ESP_OK(esp_efuse_read_block(EFUSE_BLK2, dst_key, offset_in_bits, count_useful_reg * 32));
  453. esp_efuse_utility_debug_dump_blocks();
  454. TEST_ASSERT_EQUAL_HEX8_ARRAY(src_key, dst_key, sizeof(src_key));
  455. esp_efuse_utility_erase_virt_blocks();
  456. memset(src_key, 0, sizeof(src_key));
  457. memset(dst_key, 0, sizeof(dst_key));
  458. offset_in_bits = count_useful_reg * 32 / 2;
  459. for (int i = 0; i < count_useful_reg * 4 / 2; ++i) {
  460. src_key[i] = 0xCD + i;
  461. }
  462. TEST_ESP_OK(esp_efuse_write_block(EFUSE_BLK2, src_key, offset_in_bits, count_useful_reg * 32 / 2));
  463. TEST_ESP_OK(esp_efuse_read_block(EFUSE_BLK2, dst_key, offset_in_bits, count_useful_reg * 32 / 2));
  464. esp_efuse_utility_debug_dump_blocks();
  465. TEST_ASSERT_EQUAL_HEX8_ARRAY(src_key, dst_key, count_useful_reg * 4 / 2);
  466. esp_efuse_utility_erase_virt_blocks();
  467. }
  468. TEST_CASE("Test Bits are not empty. Write operation is forbidden", "[efuse]")
  469. {
  470. esp_efuse_utility_update_virt_blocks();
  471. esp_efuse_utility_debug_dump_blocks();
  472. int count_useful_reg = 0;
  473. uint8_t r_buff[32];
  474. int st_offset = -1;
  475. int num_block;
  476. for (num_block = EFUSE_BLK1; num_block < 4; ++num_block) {
  477. memset(r_buff, 0, sizeof(r_buff));
  478. esp_efuse_coding_scheme_t coding_scheme = esp_efuse_get_coding_scheme(num_block);
  479. if (coding_scheme == EFUSE_CODING_SCHEME_NONE) {
  480. printf("EFUSE_CODING_SCHEME_NONE. The test is not applicable.\n");
  481. count_useful_reg = 8;
  482. return;
  483. }
  484. #if CONFIG_IDF_TARGET_ESP32
  485. if (coding_scheme == EFUSE_CODING_SCHEME_3_4) {
  486. printf("EFUSE_CODING_SCHEME_3_4\n");
  487. count_useful_reg = 6;
  488. } else if (coding_scheme == EFUSE_CODING_SCHEME_REPEAT) {
  489. printf("EFUSE_CODING_SCHEME_REPEAT\n");
  490. count_useful_reg = 4;
  491. }
  492. #elif CONFIG_IDF_TARGET_ESP32S2BETA
  493. if (coding_scheme == EFUSE_CODING_SCHEME_RS) {
  494. printf("EFUSE_CODING_SCHEME_RS\n");
  495. if (num_block == EFUSE_BLK1) {
  496. count_useful_reg = 6;
  497. } else {
  498. count_useful_reg = 8;
  499. }
  500. }
  501. #endif
  502. TEST_ESP_OK(esp_efuse_read_block(num_block, r_buff, 0, count_useful_reg * 32));
  503. for (int i = 0; i < count_useful_reg * 4; ++i) {
  504. if (r_buff[i] != 0) {
  505. // found used byte
  506. for (int j = 0; j < 8; ++j) {
  507. if ((r_buff[i] & (1 << j)) == 0) {
  508. // found empty bit into this byte
  509. st_offset = i * 8 + j;
  510. printf("Byte = 0x%02x. offset is = %d\n", r_buff[i], st_offset);
  511. break;
  512. }
  513. }
  514. if (st_offset != -1) {
  515. break;
  516. }
  517. }
  518. }
  519. if (st_offset != -1) {
  520. break;
  521. }
  522. }
  523. if (st_offset != -1) {
  524. // write 1 bit to empty place.
  525. uint8_t val = 1;
  526. TEST_ESP_ERR(ESP_ERR_CODING, esp_efuse_write_block(num_block, &val, st_offset, 1));
  527. } else {
  528. printf("Test skipped. It is not applicable, the device has no written bits.");
  529. }
  530. }
  531. #ifndef CONFIG_FREERTOS_UNICORE
  532. static const int delay_ms = 2000;
  533. static xSemaphoreHandle sema;
  534. static void task1(void* arg)
  535. {
  536. TEST_ESP_OK(esp_efuse_batch_write_begin());
  537. ESP_LOGI(TAG, "Start work in batch mode");
  538. xSemaphoreGive(sema);
  539. vTaskDelay((delay_ms + 100) / portTICK_PERIOD_MS);
  540. ESP_LOGI(TAG, "Finish work in batch mode");
  541. TEST_ESP_OK(esp_efuse_batch_write_cancel());
  542. vTaskDelete(NULL);
  543. }
  544. static void task2(void* arg)
  545. {
  546. xSemaphoreTake(sema, portMAX_DELAY);
  547. uint8_t mac[6];
  548. int64_t t1 = esp_timer_get_time();
  549. TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, &mac, sizeof(mac) * 8));
  550. int64_t t2 = esp_timer_get_time();
  551. int diff_ms = (t2 - t1) / 1000;
  552. TEST_ASSERT_GREATER_THAN(delay_ms, diff_ms);
  553. ESP_LOGI(TAG, "read MAC address: %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  554. xSemaphoreGive(sema);
  555. vTaskDelete(NULL);
  556. }
  557. static void task3(void* arg)
  558. {
  559. xSemaphoreTake(sema, portMAX_DELAY);
  560. size_t test3_len_6 = 2;
  561. int64_t t1 = esp_timer_get_time();
  562. TEST_ESP_OK(esp_efuse_write_field_cnt(ESP_EFUSE_TEST3_LEN_6, test3_len_6));
  563. TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_TEST3_LEN_6, &test3_len_6));
  564. int64_t t2 = esp_timer_get_time();
  565. ESP_LOGI(TAG, "write&read test3_len_6: %d", test3_len_6);
  566. int diff_ms = (t2 - t1) / 1000;
  567. TEST_ASSERT_GREATER_THAN(delay_ms, diff_ms);
  568. TEST_ASSERT_EQUAL_INT(2, test3_len_6);
  569. xSemaphoreGive(sema);
  570. vTaskDelete(NULL);
  571. }
  572. TEST_CASE("Batch mode is thread-safe", "[efuse]")
  573. {
  574. // Batch mode blocks work with efuse on other tasks.
  575. esp_efuse_utility_update_virt_blocks();
  576. esp_efuse_utility_debug_dump_blocks();
  577. sema = xSemaphoreCreateBinary();
  578. printf("\n");
  579. xTaskCreatePinnedToCore(task1, "task1", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
  580. xTaskCreatePinnedToCore(task2, "task2", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, NULL, 1);
  581. vTaskDelay(3000 / portTICK_PERIOD_MS);
  582. xSemaphoreTake(sema, portMAX_DELAY);
  583. esp_efuse_utility_reset();
  584. esp_efuse_utility_erase_virt_blocks();
  585. printf("\n");
  586. xTaskCreatePinnedToCore(task1, "task1", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
  587. xTaskCreatePinnedToCore(task3, "task3", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, NULL, 1);
  588. vTaskDelay(3000 / portTICK_PERIOD_MS);
  589. xSemaphoreTake(sema, portMAX_DELAY);
  590. printf("\n");
  591. vSemaphoreDelete(sema);
  592. esp_efuse_utility_reset();
  593. esp_efuse_utility_erase_virt_blocks();
  594. }
  595. #endif // #ifndef CONFIG_FREERTOS_UNICORE
  596. #endif // #ifdef CONFIG_EFUSE_VIRTUAL