1 /*
2 * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #ifndef ESP_APP_TRACE_UTIL_H_
7 #define ESP_APP_TRACE_UTIL_H_
8
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12
13 #include "freertos/FreeRTOS.h"
14 #include "esp_err.h"
15 #include "esp_timer.h"
16
17 /** Infinite waiting timeout */
18 #define ESP_APPTRACE_TMO_INFINITE ((uint32_t)-1)
19
20 /** Structure which holds data necessary for measuring time intervals.
21 *
22 * After initialization via esp_apptrace_tmo_init() user needs to call esp_apptrace_tmo_check()
23 * periodically to check timeout for expiration.
24 */
25 typedef struct {
26 int64_t start; ///< time interval start (in us)
27 int64_t tmo; ///< timeout value (in us)
28 int64_t elapsed; ///< elapsed time (in us)
29 } esp_apptrace_tmo_t;
30
31 /**
32 * @brief Initializes timeout structure.
33 *
34 * @param tmo Pointer to timeout structure to be initialized.
35 * @param user_tmo Timeout value (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
36 */
esp_apptrace_tmo_init(esp_apptrace_tmo_t * tmo,uint32_t user_tmo)37 static inline void esp_apptrace_tmo_init(esp_apptrace_tmo_t *tmo, uint32_t user_tmo)
38 {
39 tmo->start = esp_timer_get_time();
40 tmo->tmo = user_tmo == ESP_APPTRACE_TMO_INFINITE ? (int64_t)-1 : (int64_t)user_tmo;
41 tmo->elapsed = 0;
42 }
43
44 /**
45 * @brief Checks timeout for expiration.
46 *
47 * @param tmo Pointer to timeout structure.
48 *
49 * @return number of remaining us till tmo.
50 */
51 esp_err_t esp_apptrace_tmo_check(esp_apptrace_tmo_t *tmo);
52
esp_apptrace_tmo_remaining_us(esp_apptrace_tmo_t * tmo)53 static inline uint32_t esp_apptrace_tmo_remaining_us(esp_apptrace_tmo_t *tmo)
54 {
55 return tmo->tmo != (int64_t)-1 ? (tmo->elapsed - tmo->tmo) : ESP_APPTRACE_TMO_INFINITE;
56 }
57
58 /** Tracing module synchronization lock */
59 typedef struct {
60 portMUX_TYPE mux;
61 unsigned int_state;
62 } esp_apptrace_lock_t;
63
64 /**
65 * @brief Initializes lock structure.
66 *
67 * @param lock Pointer to lock structure to be initialized.
68 */
esp_apptrace_lock_init(esp_apptrace_lock_t * lock)69 static inline void esp_apptrace_lock_init(esp_apptrace_lock_t *lock)
70 {
71 portMUX_INITIALIZE(&lock->mux);
72 lock->int_state = 0;
73 }
74
75 /**
76 * @brief Tries to acquire lock in specified time period.
77 *
78 * @param lock Pointer to lock structure.
79 * @param tmo Pointer to timeout struct.
80 *
81 * @return ESP_OK on success, otherwise \see esp_err_t
82 */
83 esp_err_t esp_apptrace_lock_take(esp_apptrace_lock_t *lock, esp_apptrace_tmo_t *tmo);
84
85 /**
86 * @brief Releases lock.
87 *
88 * @param lock Pointer to lock structure.
89 *
90 * @return ESP_OK on success, otherwise \see esp_err_t
91 */
92 esp_err_t esp_apptrace_lock_give(esp_apptrace_lock_t *lock);
93
94 /** Ring buffer control structure.
95 *
96 * @note For purposes of application tracing module if there is no enough space for user data and write pointer can be wrapped
97 * current ring buffer size can be temporarily shrinked in order to provide buffer with requested size.
98 */
99 typedef struct {
100 uint8_t *data; ///< pointer to data storage
101 volatile uint32_t size; ///< size of data storage
102 volatile uint32_t cur_size; ///< current size of data storage
103 volatile uint32_t rd; ///< read pointer
104 volatile uint32_t wr; ///< write pointer
105 } esp_apptrace_rb_t;
106
107 /**
108 * @brief Initializes ring buffer control structure.
109 *
110 * @param rb Pointer to ring buffer structure to be initialized.
111 * @param data Pointer to buffer to be used as ring buffer's data storage.
112 * @param size Size of buffer to be used as ring buffer's data storage.
113 */
esp_apptrace_rb_init(esp_apptrace_rb_t * rb,uint8_t * data,uint32_t size)114 static inline void esp_apptrace_rb_init(esp_apptrace_rb_t *rb, uint8_t *data, uint32_t size)
115 {
116 rb->data = data;
117 rb->size = rb->cur_size = size;
118 rb->rd = 0;
119 rb->wr = 0;
120 }
121
122 /**
123 * @brief Allocates memory chunk in ring buffer.
124 *
125 * @param rb Pointer to ring buffer structure.
126 * @param size Size of the memory to allocate.
127 *
128 * @return Pointer to the allocated memory or NULL in case of failure.
129 */
130 uint8_t *esp_apptrace_rb_produce(esp_apptrace_rb_t *rb, uint32_t size);
131
132 /**
133 * @brief Consumes memory chunk in ring buffer.
134 *
135 * @param rb Pointer to ring buffer structure.
136 * @param size Size of the memory to consume.
137 *
138 * @return Pointer to consumed memory chunk or NULL in case of failure.
139 */
140 uint8_t *esp_apptrace_rb_consume(esp_apptrace_rb_t *rb, uint32_t size);
141
142 /**
143 * @brief Gets size of memory which can consumed with single call to esp_apptrace_rb_consume().
144 *
145 * @param rb Pointer to ring buffer structure.
146 *
147 * @return Size of memory which can consumed.
148 *
149 * @note Due to read pointer wrapping returned size can be less then the total size of available data.
150 */
151 uint32_t esp_apptrace_rb_read_size_get(esp_apptrace_rb_t *rb);
152
153 /**
154 * @brief Gets size of memory which can produced with single call to esp_apptrace_rb_produce().
155 *
156 * @param rb Pointer to ring buffer structure.
157 *
158 * @return Size of memory which can produced.
159 *
160 * @note Due to write pointer wrapping returned size can be less then the total size of available data.
161 */
162 uint32_t esp_apptrace_rb_write_size_get(esp_apptrace_rb_t *rb);
163
164 int esp_apptrace_log_lock(void);
165 void esp_apptrace_log_unlock(void);
166
167 #define ESP_APPTRACE_LOG( format, ... ) \
168 do { \
169 esp_apptrace_log_lock(); \
170 esp_rom_printf(format, ##__VA_ARGS__); \
171 esp_apptrace_log_unlock(); \
172 } while(0)
173
174 #define ESP_APPTRACE_LOG_LEV( _L_, level, format, ... ) \
175 do { \
176 if (LOG_LOCAL_LEVEL >= level) { \
177 ESP_APPTRACE_LOG(LOG_FORMAT(_L_, format), esp_log_early_timestamp(), TAG, ##__VA_ARGS__); \
178 } \
179 } while(0)
180
181 #define ESP_APPTRACE_LOGE( format, ... ) ESP_APPTRACE_LOG_LEV(E, ESP_LOG_ERROR, format, ##__VA_ARGS__)
182 #define ESP_APPTRACE_LOGW( format, ... ) ESP_APPTRACE_LOG_LEV(W, ESP_LOG_WARN, format, ##__VA_ARGS__)
183 #define ESP_APPTRACE_LOGI( format, ... ) ESP_APPTRACE_LOG_LEV(I, ESP_LOG_INFO, format, ##__VA_ARGS__)
184 #define ESP_APPTRACE_LOGD( format, ... ) ESP_APPTRACE_LOG_LEV(D, ESP_LOG_DEBUG, format, ##__VA_ARGS__)
185 #define ESP_APPTRACE_LOGV( format, ... ) ESP_APPTRACE_LOG_LEV(V, ESP_LOG_VERBOSE, format, ##__VA_ARGS__)
186 #define ESP_APPTRACE_LOGO( format, ... ) ESP_APPTRACE_LOG_LEV(E, ESP_LOG_NONE, format, ##__VA_ARGS__)
187
188 #ifdef __cplusplus
189 }
190 #endif
191
192 #endif //ESP_APP_TRACE_UTIL_H_
193