Select one of the symbols to view example projects that use it.
 
Outline
#include <sys/param.h>
#include <string.h>
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_cpu.h"
#include "esp_app_trace_membufs_proto.h"
esp_tracedata_hdr_t
esp_hostdata_hdr_t
#define ESP_APPTRACE_USR_BLOCK_CORE
#define ESP_APPTRACE_USR_BLOCK_LEN
#define ESP_APPTRACE_USR_DATA_LEN_MAX
#define ESP_APPTRACE_USR_BLOCK_CORE
#define ESP_APPTRACE_USR_BLOCK_LEN
#define ESP_APPTRACE_USR_DATA_LEN_MAX
#define ESP_APPTRACE_USR_BLOCK_RAW_SZ
#define ESP_APPTRACE_INBLOCK_MARKER
#define ESP_APPTRACE_INBLOCK_MARKER_UPD
#define ESP_APPTRACE_INBLOCK
TAG
esp_apptrace_membufs_init(esp_apptrace_membufs_proto_data_t *, const esp_apptrace_mem_block_t *)
esp_apptrace_membufs_down_buffer_config(esp_apptrace_membufs_proto_data_t *, uint8_t *, uint32_t)
esp_apptrace_membufs_swap(esp_apptrace_membufs_proto_data_t *)
esp_apptrace_membufs_swap_waitus(esp_apptrace_membufs_proto_data_t *, esp_apptrace_tmo_t *)
esp_apptrace_membufs_down_buffer_get(esp_apptrace_membufs_proto_data_t *, uint32_t *, esp_apptrace_tmo_t *)
esp_apptrace_membufs_down_buffer_put(esp_apptrace_membufs_proto_data_t *, uint8_t *, esp_apptrace_tmo_t *)
esp_apptrace_membufs_down_buffer_write_nolock(esp_apptrace_membufs_proto_data_t *, uint8_t *, uint32_t)
esp_apptrace_membufs_wait4buf(esp_apptrace_membufs_proto_data_t *, uint16_t, esp_apptrace_tmo_t *, int *)
esp_apptrace_membufs_pkt_start(uint8_t *, uint16_t)
esp_apptrace_membufs_pkt_end(uint8_t *)
esp_apptrace_membufs_up_buffer_get(esp_apptrace_membufs_proto_data_t *, uint32_t, esp_apptrace_tmo_t *)
esp_apptrace_membufs_up_buffer_put(esp_apptrace_membufs_proto_data_t *, uint8_t *, esp_apptrace_tmo_t *)
esp_apptrace_membufs_flush_nolock(esp_apptrace_membufs_proto_data_t *, uint32_t, esp_apptrace_tmo_t *)
Files
loading (4/5)...
SourceVuESP-IDF Framework and ExamplesESP-IDFcomponents/app_trace/app_trace_membufs_proto.c
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/* * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 OR MIT *//* ... */ #include <sys/param.h> #include <string.h> #include "sdkconfig.h" #include "esp_log.h" #include "esp_cpu.h" #include "esp_app_trace_membufs_proto.h"6 includes /** Trace data header. Every user data chunk is prepended with this header. * User allocates block with esp_apptrace_buffer_get and then fills it with data, * in multithreading environment it can happen that tasks gets buffer and then gets interrupted, * so it is possible that user data are incomplete when memory block is exposed to the host. * In this case host SW will see that wr_sz < block_sz and will report error. *//* ... */ typedef struct { #if CONFIG_APPTRACE_SV_ENABLE uint8_t block_sz; // size of allocated block for user data uint8_t wr_sz; // size of actually written data/* ... */ #else uint16_t block_sz; // size of allocated block for user data uint16_t wr_sz; // size of actually written data/* ... */ #endif }{ ... } esp_tracedata_hdr_t; /** TODO: docs *//* ... */ typedef struct { uint16_t block_sz; // size of allocated block for user data }{ ... } esp_hostdata_hdr_t; #if CONFIG_APPTRACE_SV_ENABLE #define ESP_APPTRACE_USR_BLOCK_CORE(_cid_) (0) #define ESP_APPTRACE_USR_BLOCK_LEN(_v_) (_v_) #define ESP_APPTRACE_USR_DATA_LEN_MAX(_hw_data_) 255UL/* ... */ #else #define ESP_APPTRACE_USR_BLOCK_CORE(_cid_) ((_cid_) << 15) #define ESP_APPTRACE_USR_BLOCK_LEN(_v_) (~(1 << 15) & (_v_)) #define ESP_APPTRACE_USR_DATA_LEN_MAX(_hw_data_) (ESP_APPTRACE_INBLOCK(_hw_data_)->sz - sizeof(esp_tracedata_hdr_t))/* ... */ #endif #define ESP_APPTRACE_USR_BLOCK_RAW_SZ(_s_) ((_s_) + sizeof(esp_tracedata_hdr_t)) #define ESP_APPTRACE_INBLOCK_MARKER(_hw_data_) ((_hw_data_)->state.markers[(_hw_data_)->state.in_block % 2]) #define ESP_APPTRACE_INBLOCK_MARKER_UPD(_hw_data_, _v_) do {(_hw_data_)->state.markers[(_hw_data_)->state.in_block % 2] += (_v_);}while(0) #define ESP_APPTRACE_INBLOCK(_hw_data_) (&(_hw_data_)->blocks[(_hw_data_)->state.in_block % 2]) const static char *TAG = "esp_apptrace"; static uint32_t esp_apptrace_membufs_down_buffer_write_nolock(esp_apptrace_membufs_proto_data_t *proto, uint8_t *data, uint32_t size); esp_err_t esp_apptrace_membufs_init(esp_apptrace_membufs_proto_data_t *proto, const esp_apptrace_mem_block_t blocks_cfg[2]) { // disabled by default esp_apptrace_rb_init(&proto->rb_down, NULL, 0); // membufs proto init for (unsigned i = 0; i < 2; i++) { proto->blocks[i].start = blocks_cfg[i].start; proto->blocks[i].sz = blocks_cfg[i].sz; proto->state.markers[i] = 0; }{...} proto->state.in_block = 0; #if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0 esp_apptrace_rb_init(&proto->rb_pend, proto->pending_data, sizeof(proto->pending_data));/* ... */ #endif return ESP_OK; }{ ... } void esp_apptrace_membufs_down_buffer_config(esp_apptrace_membufs_proto_data_t *data, uint8_t *buf, uint32_t size) { esp_apptrace_rb_init(&data->rb_down, buf, size); }{ ... } // assumed to be protected by caller from multi-core/thread access static esp_err_t esp_apptrace_membufs_swap(esp_apptrace_membufs_proto_data_t *proto) { int prev_block_num = proto->state.in_block % 2; int new_block_num = prev_block_num ? (0) : (1); esp_err_t res = ESP_OK; res = proto->hw->swap_start(proto->state.in_block); if (res != ESP_OK) { return res; }{...} proto->state.markers[new_block_num] = 0; // switch to new block proto->state.in_block++; proto->hw->swap(new_block_num); // handle data from host esp_hostdata_hdr_t *hdr = (esp_hostdata_hdr_t *)proto->blocks[new_block_num].start; // ESP_APPTRACE_LOGV("Host data %d, sz %d @ %p", proto->hw->host_data_pending(), hdr->block_sz, hdr); if (proto->hw->host_data_pending() && hdr->block_sz > 0) { // TODO: add support for multiple blocks from host, currently there is no need for that uint8_t *p = proto->blocks[new_block_num].start + proto->blocks[new_block_num].sz; ESP_APPTRACE_LOGD("Recvd %" PRIu16 " bytes from host (@ %p) [%x %x %x %x %x %x %x %x .. %x %x %x %x %x %x %x %x]", hdr->block_sz, proto->blocks[new_block_num].start, *(proto->blocks[new_block_num].start+0), *(proto->blocks[new_block_num].start+1), *(proto->blocks[new_block_num].start+2), *(proto->blocks[new_block_num].start+3), *(proto->blocks[new_block_num].start+4), *(proto->blocks[new_block_num].start+5), *(proto->blocks[new_block_num].start+6), *(proto->blocks[new_block_num].start+7), *(p-8), *(p-7), *(p-6), *(p-5), *(p-4), *(p-3), *(p-2), *(p-1)); uint32_t sz = esp_apptrace_membufs_down_buffer_write_nolock(proto, (uint8_t *)(hdr+1), hdr->block_sz); if (sz != hdr->block_sz) { ESP_APPTRACE_LOGE("Failed to write %" PRIu32 " bytes to down buffer (%" PRIu16 " %" PRIu32 ")!", hdr->block_sz - sz, hdr->block_sz, sz); }{...} hdr->block_sz = 0; }{...} #if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0 // copy pending data to block if any while (proto->state.markers[new_block_num] < proto->blocks[new_block_num].sz) { uint32_t read_sz = esp_apptrace_rb_read_size_get(&proto->rb_pend); if (read_sz == 0) { break; // no more data in pending buffer }{...} if (read_sz > proto->blocks[new_block_num].sz - proto->state.markers[new_block_num]) { read_sz = proto->blocks[new_block_num].sz - proto->state.markers[new_block_num]; }{...} uint8_t *ptr = esp_apptrace_rb_consume(&proto->rb_pend, read_sz); if (!ptr) { assert(false && "Failed to consume pended bytes!!"); break; }{...} ESP_APPTRACE_LOGD("Pump %d pend bytes [%x %x %x %x : %x %x %x %x : %x %x %x %x : %x %x...%x %x]", read_sz, *(ptr+0), *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5), *(ptr+6), *(ptr+7), *(ptr+8), *(ptr+9), *(ptr+10), *(ptr+11), *(ptr+12), *(ptr+13), *(ptr+read_sz-2), *(ptr+read_sz-1)); memcpy(proto->blocks[new_block_num].start + proto->state.markers[new_block_num], ptr, read_sz); proto->state.markers[new_block_num] += read_sz; }{...} #endif/* ... */ proto->hw->swap_end(proto->state.in_block, proto->state.markers[prev_block_num]); return res; }{ ... } static esp_err_t esp_apptrace_membufs_swap_waitus(esp_apptrace_membufs_proto_data_t *proto, esp_apptrace_tmo_t *tmo) { int res; while ((res = esp_apptrace_membufs_swap(proto)) != ESP_OK) { res = esp_apptrace_tmo_check(tmo); if (res != ESP_OK) { break; }{...} }{...} return res; }{ ... } uint8_t *esp_apptrace_membufs_down_buffer_get(esp_apptrace_membufs_proto_data_t *proto, uint32_t *size, esp_apptrace_tmo_t *tmo) { uint8_t *ptr = NULL; while (1) { uint32_t sz = esp_apptrace_rb_read_size_get(&proto->rb_down); if (sz != 0) { *size = MIN(*size, sz); ptr = esp_apptrace_rb_consume(&proto->rb_down, *size); if (!ptr) { assert(false && "Failed to consume bytes from down buffer!"); }{...} break; }{...} // may need to flush if (proto->hw->host_data_pending()) { ESP_APPTRACE_LOGD("force flush"); int res = esp_apptrace_membufs_swap_waitus(proto, tmo); if (res != ESP_OK) { ESP_APPTRACE_LOGE("Failed to switch to another block to recv data from host!"); /*do not return error because data can be in down buffer already*/ }{...} }{...} else { // check tmo only if there is no data from host int res = esp_apptrace_tmo_check(tmo); if (res != ESP_OK) { return NULL; }{...} }{...} }{...} return ptr; }{ ... } esp_err_t esp_apptrace_membufs_down_buffer_put(esp_apptrace_membufs_proto_data_t *proto, uint8_t *ptr, esp_apptrace_tmo_t *tmo) { /* nothing todo */ return ESP_OK; }{ ... } static uint32_t esp_apptrace_membufs_down_buffer_write_nolock(esp_apptrace_membufs_proto_data_t *proto, uint8_t *data, uint32_t size) { uint32_t total_sz = 0; while (total_sz < size) { ESP_APPTRACE_LOGD("esp_apptrace_trax_down_buffer_write_nolock WRS %" PRIu32 "-%" PRIu32 "-%" PRIu32 " %" PRIu32, proto->rb_down.wr, proto->rb_down.rd, proto->rb_down.cur_size, size); uint32_t wr_sz = esp_apptrace_rb_write_size_get(&proto->rb_down); if (wr_sz == 0) { break; }{...} if (wr_sz > size - total_sz) { wr_sz = size - total_sz; }{...} ESP_APPTRACE_LOGD("esp_apptrace_trax_down_buffer_write_nolock wr %" PRIu32, wr_sz); uint8_t *ptr = esp_apptrace_rb_produce(&proto->rb_down, wr_sz); if (!ptr) { assert(false && "Failed to produce bytes to down buffer!"); }{...} ESP_APPTRACE_LOGD("esp_apptrace_trax_down_buffer_write_nolock wr %" PRIu32 " to %p from %p", wr_sz, ptr, data + total_sz + wr_sz); memcpy(ptr, data + total_sz, wr_sz); total_sz += wr_sz; ESP_APPTRACE_LOGD("esp_apptrace_trax_down_buffer_write_nolock wr %" PRIu32 "/%" PRIu32 "", wr_sz, total_sz); }{...} return total_sz; }{ ... } static inline uint8_t *esp_apptrace_membufs_wait4buf(esp_apptrace_membufs_proto_data_t *proto, uint16_t size, esp_apptrace_tmo_t *tmo, int *pended) { uint8_t *ptr = NULL; int res = esp_apptrace_membufs_swap_waitus(proto, tmo); if (res != ESP_OK) { return NULL; }{...} #if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0 // check if we still have pending data if (esp_apptrace_rb_read_size_get(&proto->rb_pend) > 0) { // if after block switch we still have pending data (not all pending data have been pumped to block) // alloc new pending buffer *pended = 1; ptr = esp_apptrace_rb_produce(&proto->rb_pend, size); if (!ptr) { ESP_APPTRACE_LOGE("Failed to alloc pend buf 1: w-r-s %d-%d-%d!", proto->rb_pend.wr, proto->rb_pend.rd, proto->rb_pend.cur_size); }{...} }{...} else #endif { // update block pointers if (ESP_APPTRACE_INBLOCK_MARKER(proto) + size > ESP_APPTRACE_INBLOCK(proto)->sz) { #if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0 *pended = 1; ptr = esp_apptrace_rb_produce(&proto->rb_pend, size); if (ptr == NULL) { ESP_APPTRACE_LOGE("Failed to alloc pend buf 2: w-r-s %d-%d-%d!", proto->rb_pend.wr, proto->rb_pend.rd, proto->rb_pend.cur_size); }{...} #endif/* ... */ }{...} else { *pended = 0; ptr = ESP_APPTRACE_INBLOCK(proto)->start + ESP_APPTRACE_INBLOCK_MARKER(proto); }{...} }{...} return ptr; }{ ... } static inline uint8_t *esp_apptrace_membufs_pkt_start(uint8_t *ptr, uint16_t size) { // it is safe to use esp_cpu_get_core_id() in macro call because arg is used only once inside it ((esp_tracedata_hdr_t *)ptr)->block_sz = ESP_APPTRACE_USR_BLOCK_CORE(esp_cpu_get_core_id()) | size; ((esp_tracedata_hdr_t *)ptr)->wr_sz = 0; return ptr + sizeof(esp_tracedata_hdr_t); }{ ... } static inline void esp_apptrace_membufs_pkt_end(uint8_t *ptr) { esp_tracedata_hdr_t *hdr = (esp_tracedata_hdr_t *)(ptr - sizeof(esp_tracedata_hdr_t)); // update written size hdr->wr_sz = hdr->block_sz; }{ ... } uint8_t *esp_apptrace_membufs_up_buffer_get(esp_apptrace_membufs_proto_data_t *proto, uint32_t size, esp_apptrace_tmo_t *tmo) { uint8_t *buf_ptr = NULL; if (size > ESP_APPTRACE_USR_DATA_LEN_MAX(proto)) { ESP_APPTRACE_LOGE("Too large user data size %" PRIu32 "!", size); return NULL; }{...} // check for data in the pending buffer #if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0 if (esp_apptrace_rb_read_size_get(&proto->rb_pend) > 0) { // if we have buffered data try to switch block esp_apptrace_membufs_swap(proto); // if switch was successful, part or all pended data have been copied to block }{...} if (esp_apptrace_rb_read_size_get(&proto->rb_pend) > 0) { // if we have buffered data alloc new pending buffer ESP_APPTRACE_LOGD("Get %d bytes from PEND buffer", size); buf_ptr = esp_apptrace_rb_produce(&proto->rb_pend, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size)); if (buf_ptr == NULL) { int pended_buf; buf_ptr = esp_apptrace_membufs_wait4buf(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size), tmo, &pended_buf); if (buf_ptr && !pended_buf) { ESP_APPTRACE_LOGD("Get %d bytes from block", size); // update cur block marker ESP_APPTRACE_INBLOCK_MARKER_UPD(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size)); }{...} }{...} }{...} else { #else if (1) { #endif if (ESP_APPTRACE_INBLOCK_MARKER(proto) + ESP_APPTRACE_USR_BLOCK_RAW_SZ(size) > ESP_APPTRACE_INBLOCK(proto)->sz) { #if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0 ESP_APPTRACE_LOGD("Block full. Get %" PRIu32 " bytes from PEND buffer", size); buf_ptr = esp_apptrace_rb_produce(&proto->rb_pend, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));/* ... */ #endif if (buf_ptr == NULL) { int pended_buf; ESP_APPTRACE_LOGD(" full. Get %" PRIu32 " bytes from pend buffer", size); buf_ptr = esp_apptrace_membufs_wait4buf(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size), tmo, &pended_buf); if (buf_ptr && !pended_buf) { ESP_APPTRACE_LOGD("Got %" PRIu32 " bytes from block", size); // update cur block marker ESP_APPTRACE_INBLOCK_MARKER_UPD(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size)); }{...} }{...} }{...} else { ESP_APPTRACE_LOGD("Get %" PRIu32 " bytes from buffer", size); // fit to curr nlock buf_ptr = ESP_APPTRACE_INBLOCK(proto)->start + ESP_APPTRACE_INBLOCK_MARKER(proto); // update cur block marker ESP_APPTRACE_INBLOCK_MARKER_UPD(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size)); }{...} }{...} if (buf_ptr) { buf_ptr = esp_apptrace_membufs_pkt_start(buf_ptr, size); }{...} return buf_ptr; }{ ... } esp_err_t esp_apptrace_membufs_up_buffer_put(esp_apptrace_membufs_proto_data_t *proto, uint8_t *ptr, esp_apptrace_tmo_t *tmo) { esp_apptrace_membufs_pkt_end(ptr); // TODO: mark block as busy in order not to re-use it for other tracing calls until it is completely written // TODO: avoid potential situation when all memory is consumed by low prio tasks which can not complete writing due to // higher prio tasks and the latter can not allocate buffers at all // this is abnormal situation can be detected on host which will receive only uncompleted buffers // workaround: use own memcpy which will kick-off dead tracing calls return ESP_OK; }{ ... } esp_err_t esp_apptrace_membufs_flush_nolock(esp_apptrace_membufs_proto_data_t *proto, uint32_t min_sz, esp_apptrace_tmo_t *tmo) { int res = ESP_OK; if (ESP_APPTRACE_INBLOCK_MARKER(proto) < min_sz) { ESP_APPTRACE_LOGI("Ignore flush request for min %" PRIu32 " bytes. Bytes in block: %" PRIu32, min_sz, ESP_APPTRACE_INBLOCK_MARKER(proto)); return ESP_OK; }{...} // switch block while size of data (including that in pending buffer) is more than min size while (ESP_APPTRACE_INBLOCK_MARKER(proto) > min_sz) { ESP_APPTRACE_LOGD("Try to flush %" PRIu32 " bytes. Wait until block switch for %" PRIi64 " us", ESP_APPTRACE_INBLOCK_MARKER(proto), tmo->tmo); res = esp_apptrace_membufs_swap_waitus(proto, tmo); if (res != ESP_OK) { if (tmo->tmo != ESP_APPTRACE_TMO_INFINITE) ESP_APPTRACE_LOGW("Failed to switch to another block in %lld us!", tmo->tmo); else ESP_APPTRACE_LOGE("Failed to switch to another block in %lld us!", tmo->tmo); return res; }{...} }{...} return res; }{ ... }
Details
Show:
from
Types: Columns:
This file uses the notable symbols shown below. Click anywhere in the file to view more details.