app_trace_util.c 6.2 KB

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