1 /* efuse example
2
3 This example code is in the Public Domain (or CC0 licensed, at your option.)
4
5 Unless required by applicable law or agreed to in writing, this
6 software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7 CONDITIONS OF ANY KIND, either express or implied.
8 */
9
10 #include <stdio.h>
11 #include "freertos/FreeRTOS.h"
12 #include "freertos/task.h"
13 #include "esp_err.h"
14 #include "esp_log.h"
15 #include "esp_efuse.h"
16 #include "esp_efuse_table.h"
17 #include "esp_efuse_custom_table.h"
18 #include "sdkconfig.h"
19
20 static const char* TAG = "example";
21
22
23 typedef struct {
24 uint8_t module_version; /*!< Module version: length 8 bits */
25 uint8_t device_role; /*!< Device role: length 3 bits */
26 uint8_t setting_1; /*!< Setting 1: length 6 bits */
27 uint8_t setting_2; /*!< Setting 2: length 5 bits */
28 size_t custom_secure_version; /*!< Custom secure version: length 16 bits */
29 uint16_t reserv; /*!< Reserv */
30 } device_desc_t;
31
32
print_device_desc(device_desc_t * desc)33 static void print_device_desc(device_desc_t *desc)
34 {
35 ESP_LOGI(TAG, "module_version = %d", desc->module_version);
36 if (desc->device_role == 0) {
37 ESP_LOGI(TAG, "device_role = None");
38 } else if (desc->device_role == 1) {
39 ESP_LOGI(TAG, "device_role = Master");
40 } else if (desc->device_role == 2) {
41 ESP_LOGI(TAG, "device_role = Slave");
42 } else {
43 ESP_LOGI(TAG, "device_role = Not supported");
44 }
45 ESP_LOGI(TAG, "setting_1 = %d", desc->setting_1);
46 ESP_LOGI(TAG, "setting_2 = %d", desc->setting_2);
47 ESP_LOGI(TAG, "custom_secure_version = %d", desc->custom_secure_version);
48 }
49
50
read_device_desc_efuse_fields(device_desc_t * desc)51 static void read_device_desc_efuse_fields(device_desc_t *desc)
52 {
53 ESP_ERROR_CHECK(esp_efuse_read_field_blob(ESP_EFUSE_MODULE_VERSION, &desc->module_version, 8));
54 ESP_ERROR_CHECK(esp_efuse_read_field_blob(ESP_EFUSE_DEVICE_ROLE, &desc->device_role, 3));
55 ESP_ERROR_CHECK(esp_efuse_read_field_blob(ESP_EFUSE_SETTING_1, &desc->setting_1, 6));
56 ESP_ERROR_CHECK(esp_efuse_read_field_blob(ESP_EFUSE_SETTING_2, &desc->setting_2, 5));
57 ESP_ERROR_CHECK(esp_efuse_read_field_cnt(ESP_EFUSE_CUSTOM_SECURE_VERSION, &desc->custom_secure_version));
58 print_device_desc(desc);
59 }
60
61
read_efuse_fields(device_desc_t * desc)62 static void read_efuse_fields(device_desc_t *desc)
63 {
64 ESP_LOGI(TAG, "read efuse fields");
65
66 uint8_t mac[6];
67 ESP_ERROR_CHECK(esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, &mac, sizeof(mac) * 8));
68 ESP_LOGI(TAG, "1. read MAC address: %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
69
70 size_t secure_version = 0;
71 ESP_ERROR_CHECK(esp_efuse_read_field_cnt(ESP_EFUSE_SECURE_VERSION, &secure_version));
72 ESP_LOGI(TAG, "2. read secure_version: %d", secure_version);
73
74 ESP_LOGI(TAG, "3. read custom fields");
75 read_device_desc_efuse_fields(desc);
76 }
77
78
79 #ifdef CONFIG_EFUSE_VIRTUAL
write_efuse_fields(device_desc_t * desc,esp_efuse_coding_scheme_t coding_scheme)80 static void write_efuse_fields(device_desc_t *desc, esp_efuse_coding_scheme_t coding_scheme)
81 {
82 #if CONFIG_IDF_TARGET_ESP32
83 const esp_efuse_coding_scheme_t coding_scheme_for_batch_mode = EFUSE_CODING_SCHEME_3_4;
84 #else
85 const esp_efuse_coding_scheme_t coding_scheme_for_batch_mode = EFUSE_CODING_SCHEME_RS;
86 #endif
87
88 ESP_LOGI(TAG, "write custom efuse fields");
89 if (coding_scheme == coding_scheme_for_batch_mode) {
90 ESP_LOGI(TAG, "In the case of 3/4 or RS coding scheme, you cannot write efuse fields separately");
91 ESP_LOGI(TAG, "You should use the batch mode of writing fields for this");
92 ESP_ERROR_CHECK(esp_efuse_batch_write_begin());
93 }
94
95 ESP_ERROR_CHECK(esp_efuse_write_field_blob(ESP_EFUSE_MODULE_VERSION, &desc->module_version, 8));
96 ESP_ERROR_CHECK(esp_efuse_write_field_blob(ESP_EFUSE_DEVICE_ROLE, &desc->device_role, 3));
97 ESP_ERROR_CHECK(esp_efuse_write_field_blob(ESP_EFUSE_SETTING_1, &desc->setting_1, 6));
98 ESP_ERROR_CHECK(esp_efuse_write_field_blob(ESP_EFUSE_SETTING_2, &desc->setting_2, 5));
99 ESP_ERROR_CHECK(esp_efuse_write_field_cnt(ESP_EFUSE_CUSTOM_SECURE_VERSION, desc->custom_secure_version));
100
101 if (coding_scheme == coding_scheme_for_batch_mode) {
102 ESP_ERROR_CHECK(esp_efuse_batch_write_commit());
103 }
104 }
105 #endif // CONFIG_EFUSE_VIRTUAL
106
107
get_coding_scheme(void)108 static esp_efuse_coding_scheme_t get_coding_scheme(void)
109 {
110 // The coding scheme is used for EFUSE_BLK1, EFUSE_BLK2 and EFUSE_BLK3.
111 // We use EFUSE_BLK3 (custom block) to verify it.
112 esp_efuse_coding_scheme_t coding_scheme = esp_efuse_get_coding_scheme(EFUSE_BLK3);
113 if (coding_scheme == EFUSE_CODING_SCHEME_NONE) {
114 ESP_LOGI(TAG, "Coding Scheme NONE");
115 #if CONFIG_IDF_TARGET_ESP32
116 } else if (coding_scheme == EFUSE_CODING_SCHEME_3_4) {
117 ESP_LOGI(TAG, "Coding Scheme 3/4");
118 } else {
119 ESP_LOGI(TAG, "Coding Scheme REPEAT");
120 }
121 #else
122 } else if (coding_scheme == EFUSE_CODING_SCHEME_RS) {
123 ESP_LOGI(TAG, "Coding Scheme RS (Reed-Solomon coding)");
124 }
125 #endif
126 return coding_scheme;
127 }
128
129
app_main(void)130 void app_main(void)
131 {
132 ESP_LOGI(TAG, "Start eFuse example");
133
134 esp_efuse_coding_scheme_t coding_scheme = get_coding_scheme();
135 (void) coding_scheme;
136
137 device_desc_t device_desc = { 0 };
138 read_efuse_fields(&device_desc);
139
140 ESP_LOGW(TAG, "This example does not burn any efuse in reality only virtually");
141 #ifdef CONFIG_EFUSE_VIRTUAL
142 ESP_LOGW(TAG, "Write operations in efuse fields are performed virtually");
143 if (device_desc.device_role == 0) {
144 device_desc.module_version = 1;
145 device_desc.device_role = 2;
146 device_desc.setting_1 = 3;
147 device_desc.setting_2 = 4;
148 device_desc.custom_secure_version = 5;
149 write_efuse_fields(&device_desc, coding_scheme);
150 read_device_desc_efuse_fields(&device_desc);
151 }
152 #else
153 ESP_LOGW(TAG, "The part of the code that writes efuse fields is disabled");
154 #endif
155
156 ESP_LOGI(TAG, "Done");
157 }
158