app_trace_util.c 6.0 KB

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