app_trace_util.c
1 // Copyright 2017 Espressif Systems (Shanghai) PTE LTD 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 #include "freertos/FreeRTOS.h" 16 #include "freertos/task.h" 17 #include "esp_app_trace_util.h" 18 #include "sdkconfig.h" 19 #if CONFIG_IDF_TARGET_ESP32 20 #include "esp32/clk.h" 21 #elif CONFIG_IDF_TARGET_ESP32S2 22 #include "esp32s2/clk.h" 23 #elif CONFIG_IDF_TARGET_ESP32S3 24 #include "esp32s3/clk.h" 25 #endif 26 27 /////////////////////////////////////////////////////////////////////////////// 28 ///////////////////////////////// TIMEOUT ///////////////////////////////////// 29 /////////////////////////////////////////////////////////////////////////////// 30 31 #define ESP_APPTRACE_CPUTICKS2US(_t_, _cpu_freq_) ((_t_)/(_cpu_freq_/1000000)) 32 #define ESP_APPTRACE_US2CPUTICKS(_t_, _cpu_freq_) ((_t_)*(_cpu_freq_/1000000)) 33 34 esp_err_t esp_apptrace_tmo_check(esp_apptrace_tmo_t *tmo) 35 { 36 int cpu_freq = esp_clk_cpu_freq(); 37 if (tmo->tmo != ESP_APPTRACE_TMO_INFINITE) { 38 unsigned cur = portGET_RUN_TIME_COUNTER_VALUE(); 39 if (tmo->start <= cur) { 40 tmo->elapsed = ESP_APPTRACE_CPUTICKS2US(cur - tmo->start, cpu_freq); 41 } else { 42 tmo->elapsed = ESP_APPTRACE_CPUTICKS2US(0xFFFFFFFF - tmo->start + cur, cpu_freq); 43 } 44 if (tmo->elapsed >= tmo->tmo) { 45 return ESP_ERR_TIMEOUT; 46 } 47 } 48 return ESP_OK; 49 } 50 51 /////////////////////////////////////////////////////////////////////////////// 52 ///////////////////////////////// LOCK //////////////////////////////////////// 53 /////////////////////////////////////////////////////////////////////////////// 54 55 esp_err_t esp_apptrace_lock_take(esp_apptrace_lock_t *lock, esp_apptrace_tmo_t *tmo) 56 { 57 int res; 58 59 while (1) { 60 // do not overwrite lock->int_state before we actually acquired the mux 61 unsigned int_state = portENTER_CRITICAL_NESTED(); 62 // FIXME: if mux is busy it is not good idea to loop during the whole tmo with disabled IRQs. 63 // So we check mux state using zero tmo, restore IRQs and let others tasks/IRQs to run on this CPU 64 // while we are doing our own tmo check. 65 #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG 66 bool success = vPortCPUAcquireMutexTimeout(&lock->mux, 0, __FUNCTION__, __LINE__); 67 #else 68 bool success = vPortCPUAcquireMutexTimeout(&lock->mux, 0); 69 #endif 70 if (success) { 71 lock->int_state = int_state; 72 return ESP_OK; 73 } 74 portEXIT_CRITICAL_NESTED(int_state); 75 // we can be preempted from this place till the next call (above) to portENTER_CRITICAL_NESTED() 76 res = esp_apptrace_tmo_check(tmo); 77 if (res != ESP_OK) { 78 break; 79 } 80 } 81 return res; 82 } 83 84 esp_err_t esp_apptrace_lock_give(esp_apptrace_lock_t *lock) 85 { 86 // save lock's irq state value for this CPU 87 unsigned int_state = lock->int_state; 88 // after call to the following func we can not be sure that lock->int_state 89 // is not overwritten by other CPU who has acquired the mux just after we released it. See esp_apptrace_lock_take(). 90 #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG 91 vPortCPUReleaseMutex(&lock->mux, __FUNCTION__, __LINE__); 92 #else 93 vPortCPUReleaseMutex(&lock->mux); 94 #endif 95 portEXIT_CRITICAL_NESTED(int_state); 96 return ESP_OK; 97 } 98 99 /////////////////////////////////////////////////////////////////////////////// 100 ////////////////////////////// RING BUFFER //////////////////////////////////// 101 /////////////////////////////////////////////////////////////////////////////// 102 103 uint8_t *esp_apptrace_rb_produce(esp_apptrace_rb_t *rb, uint32_t size) 104 { 105 uint8_t *ptr = rb->data + rb->wr; 106 // check for avalable space 107 if (rb->rd <= rb->wr) { 108 // |?R......W??| 109 if (rb->wr + size >= rb->size) { 110 if (rb->rd == 0) { 111 return NULL; // cannot wrap wr 112 } 113 if (rb->wr + size == rb->size) { 114 rb->wr = 0; 115 } else { 116 // check if we can wrap wr earlier to get space for requested size 117 if (size > rb->rd - 1) { 118 return NULL; // cannot wrap wr 119 } 120 // shrink buffer a bit, full size will be restored at rd wrapping 121 rb->cur_size = rb->wr; 122 rb->wr = 0; 123 ptr = rb->data; 124 if (rb->rd == rb->cur_size) { 125 rb->rd = 0; 126 if (rb->cur_size < rb->size) { 127 rb->cur_size = rb->size; 128 } 129 } 130 rb->wr += size; 131 } 132 } else { 133 rb->wr += size; 134 } 135 } else { 136 // |?W......R??| 137 if (size > rb->rd - rb->wr - 1) { 138 return NULL; 139 } 140 rb->wr += size; 141 } 142 return ptr; 143 } 144 145 uint8_t *esp_apptrace_rb_consume(esp_apptrace_rb_t *rb, uint32_t size) 146 { 147 uint8_t *ptr = rb->data + rb->rd; 148 if (rb->rd <= rb->wr) { 149 // |?R......W??| 150 if (rb->rd + size > rb->wr) { 151 return NULL; 152 } 153 rb->rd += size; 154 } else { 155 // |?W......R??| 156 if (rb->rd + size > rb->cur_size) { 157 return NULL; 158 } else if (rb->rd + size == rb->cur_size) { 159 // restore full size usage 160 if (rb->cur_size < rb->size) { 161 rb->cur_size = rb->size; 162 } 163 rb->rd = 0; 164 } else { 165 rb->rd += size; 166 } 167 } 168 return ptr; 169 } 170 171 uint32_t esp_apptrace_rb_read_size_get(esp_apptrace_rb_t *rb) 172 { 173 uint32_t size = 0; 174 if (rb->rd <= rb->wr) { 175 // |?R......W??| 176 size = rb->wr - rb->rd; 177 } else { 178 // |?W......R??| 179 size = rb->cur_size - rb->rd; 180 } 181 return size; 182 } 183 184 uint32_t esp_apptrace_rb_write_size_get(esp_apptrace_rb_t *rb) 185 { 186 uint32_t size = 0; 187 if (rb->rd <= rb->wr) { 188 // |?R......W??| 189 size = rb->size - rb->wr; 190 if (size && rb->rd == 0) { 191 size--; 192 } 193 } else { 194 // |?W......R??| 195 size = rb->rd - rb->wr - 1; 196 } 197 return size; 198 }