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