SEGGER_RTT_esp.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. /*
  2. * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "string.h"
  7. #include "freertos/FreeRTOS.h"
  8. #include "SEGGER_RTT.h"
  9. #include "SEGGER_SYSVIEW.h"
  10. #include "SEGGER_SYSVIEW_Conf.h"
  11. #include "esp_app_trace.h"
  12. #include "esp_log.h"
  13. #include "esp_cpu.h"
  14. #include "esp_private/startup_internal.h"
  15. const static char *TAG = "segger_rtt";
  16. #define SYSVIEW_EVENTS_BUF_SZ 255U
  17. // size of down channel data buf
  18. #define SYSVIEW_DOWN_BUF_SIZE 32
  19. #define SEGGER_STOP_WAIT_TMO 1000000 //us
  20. #if CONFIG_APPTRACE_SV_BUF_WAIT_TMO == -1
  21. #define SEGGER_HOST_WAIT_TMO ESP_APPTRACE_TMO_INFINITE
  22. #else
  23. #define SEGGER_HOST_WAIT_TMO CONFIG_APPTRACE_SV_BUF_WAIT_TMO
  24. #endif
  25. static uint8_t s_events_buf[SYSVIEW_EVENTS_BUF_SZ];
  26. static uint16_t s_events_buf_filled;
  27. static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE];
  28. #if CONFIG_APPTRACE_SV_DEST_UART
  29. #define ESP_APPTRACE_DEST_SYSVIEW ESP_APPTRACE_DEST_UART
  30. #if CONFIG_APPTRACE_SV_DEST_CPU_0 || CONFIG_FREERTOS_UNICORE
  31. #define APPTRACE_SV_DEST_CPU 0
  32. #else
  33. #define APPTRACE_SV_DEST_CPU 1
  34. #endif // CONFIG_APPTRACE_SV_DEST_CPU_0
  35. #elif CONFIG_APPTRACE_SV_DEST_JTAG || (CONFIG_APPTRACE_ENABLE && CONFIG_APPTRACE_DEST_UART_NONE)
  36. #define ESP_APPTRACE_DEST_SYSVIEW ESP_APPTRACE_DEST_TRAX
  37. #endif
  38. /*********************************************************************
  39. *
  40. * Public code
  41. *
  42. **********************************************************************
  43. */
  44. /*********************************************************************
  45. *
  46. * SEGGER_RTT_ESP_FlushNoLock()
  47. *
  48. * Function description
  49. * Flushes buffered events.
  50. *
  51. * Parameters
  52. * min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. TRAX destinations only.
  53. * tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
  54. *
  55. * Return value
  56. * None.
  57. */
  58. void SEGGER_RTT_ESP_FlushNoLock(unsigned long min_sz, unsigned long tmo)
  59. {
  60. esp_err_t res;
  61. if (s_events_buf_filled > 0) {
  62. res = esp_apptrace_write(ESP_APPTRACE_DEST_SYSVIEW, s_events_buf, s_events_buf_filled, tmo);
  63. if (res != ESP_OK) {
  64. ESP_LOGE(TAG, "Failed to flush buffered events (%d)!", res);
  65. }
  66. }
  67. // flush even if we failed to write buffered events, because no new events will be sent after STOP
  68. res = esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_SYSVIEW, min_sz, tmo);
  69. if (res != ESP_OK) {
  70. ESP_LOGE(TAG, "Failed to flush apptrace data (%d)!", res);
  71. }
  72. s_events_buf_filled = 0;
  73. }
  74. /*********************************************************************
  75. *
  76. * SEGGER_RTT_ESP_Flush()
  77. *
  78. * Function description
  79. * Flushes buffered events.
  80. *
  81. * Parameters
  82. * min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. TRAX destinations only.
  83. * tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
  84. *
  85. * Return value
  86. * None.
  87. */
  88. void SEGGER_RTT_ESP_Flush(unsigned long min_sz, unsigned long tmo)
  89. {
  90. SEGGER_SYSVIEW_LOCK();
  91. SEGGER_RTT_ESP_FlushNoLock(min_sz, tmo);
  92. SEGGER_SYSVIEW_UNLOCK();
  93. }
  94. /*********************************************************************
  95. *
  96. * SEGGER_RTT_ReadNoLock()
  97. *
  98. * Function description
  99. * Reads characters from SEGGER real-time-terminal control block
  100. * which have been previously stored by the host.
  101. * Do not lock against interrupts and multiple access.
  102. *
  103. * Parameters
  104. * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal").
  105. * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
  106. * BufferSize Size of the target application buffer.
  107. *
  108. * Return value
  109. * Number of bytes that have been read.
  110. */
  111. unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) {
  112. uint32_t size = BufferSize;
  113. esp_err_t res = esp_apptrace_read(ESP_APPTRACE_DEST_SYSVIEW, pData, &size, 0);
  114. if (res != ESP_OK) {
  115. return 0;
  116. }
  117. return size;
  118. }
  119. /*********************************************************************
  120. *
  121. * SEGGER_RTT_WriteSkipNoLock
  122. *
  123. * Function description
  124. * Stores a specified number of characters in SEGGER RTT
  125. * control block which is then read by the host.
  126. * SEGGER_RTT_WriteSkipNoLock does not lock the application and
  127. * skips all data, if the data does not fit into the buffer.
  128. *
  129. * Parameters
  130. * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
  131. * pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
  132. * NumBytes Number of bytes to be stored in the SEGGER RTT control block.
  133. *
  134. * Return value
  135. * Number of bytes which have been stored in the "Up"-buffer.
  136. *
  137. * Notes
  138. * (1) If there is not enough space in the "Up"-buffer, all data is dropped.
  139. * (2) For performance reasons this function does not call Init()
  140. * and may only be called after RTT has been initialized.
  141. * Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
  142. */
  143. unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
  144. uint8_t *pbuf = (uint8_t *)pBuffer;
  145. uint8_t event_id = *pbuf;
  146. #if CONFIG_APPTRACE_SV_DEST_UART
  147. if (
  148. (APPTRACE_SV_DEST_CPU != esp_cpu_get_core_id()) &&
  149. (
  150. (event_id == SYSVIEW_EVTID_ISR_ENTER) ||
  151. (event_id == SYSVIEW_EVTID_ISR_EXIT) ||
  152. (event_id == SYSVIEW_EVTID_TASK_START_EXEC) ||
  153. (event_id == SYSVIEW_EVTID_TASK_STOP_EXEC) ||
  154. (event_id == SYSVIEW_EVTID_TASK_START_READY) ||
  155. (event_id == SYSVIEW_EVTID_TASK_STOP_READY) ||
  156. (event_id == SYSVIEW_EVTID_MARK_START) ||
  157. (event_id == SYSVIEW_EVTID_MARK_STOP) ||
  158. (event_id == SYSVIEW_EVTID_TIMER_ENTER) ||
  159. (event_id == SYSVIEW_EVTID_TIMER_EXIT) ||
  160. (event_id == SYSVIEW_EVTID_STACK_INFO) ||
  161. (event_id == SYSVIEW_EVTID_MODULEDESC)
  162. )
  163. ){
  164. return NumBytes;
  165. }
  166. // This is workaround for SystemView!
  167. // Without this line SystemView will hangs on when heap tracing enabled.
  168. if(event_id == SYSVIEW_EVTID_MODULEDESC){
  169. return NumBytes;
  170. }
  171. #endif // CONFIG_APPTRACE_SV_DEST_UART
  172. if (NumBytes > SYSVIEW_EVENTS_BUF_SZ) {
  173. ESP_LOGE(TAG, "Too large event %u bytes!", NumBytes);
  174. return 0;
  175. }
  176. #if CONFIG_APPTRACE_SV_DEST_JTAG
  177. if (esp_cpu_get_core_id()) { // dual core specific code
  178. // use the highest - 1 bit of event ID to indicate core ID
  179. // the highest bit can not be used due to event ID encoding method
  180. // this reduces supported ID range to [0..63] (for 1 byte IDs) plus [128..16383] (for 2 bytes IDs)
  181. if (*pbuf & 0x80) { // 2 bytes ID
  182. *(pbuf + 1) |= (1 << 6);
  183. } else if (NumBytes != 10 || *pbuf != 0) { // ignore sync sequence
  184. *pbuf |= (1 << 6);
  185. }
  186. }
  187. #endif // CONFIG_APPTRACE_SV_DEST_JTAG
  188. #if CONFIG_APPTRACE_SV_DEST_JTAG
  189. if (s_events_buf_filled + NumBytes > SYSVIEW_EVENTS_BUF_SZ) {
  190. esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_SYSVIEW, s_events_buf, s_events_buf_filled, SEGGER_HOST_WAIT_TMO);
  191. if (res != ESP_OK) {
  192. return 0; // skip current data buffer only, accumulated events are kept
  193. }
  194. s_events_buf_filled = 0;
  195. }
  196. #endif
  197. memcpy(&s_events_buf[s_events_buf_filled], pBuffer, NumBytes);
  198. s_events_buf_filled += NumBytes;
  199. #if CONFIG_APPTRACE_SV_DEST_UART
  200. esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_SYSVIEW, pBuffer, NumBytes, SEGGER_HOST_WAIT_TMO);
  201. if (res != ESP_OK)
  202. {
  203. return 0; // skip current data buffer only, accumulated events are kept
  204. }
  205. s_events_buf_filled = 0;
  206. #endif
  207. if (event_id == SYSVIEW_EVTID_TRACE_STOP)
  208. {
  209. SEGGER_RTT_ESP_FlushNoLock(0, SEGGER_STOP_WAIT_TMO);
  210. }
  211. return NumBytes;
  212. }
  213. /*********************************************************************
  214. *
  215. * SEGGER_RTT_ConfigUpBuffer
  216. *
  217. * Function description
  218. * Run-time configuration of a specific up-buffer (T->H).
  219. * Buffer to be configured is specified by index.
  220. * This includes: Buffer address, size, name, flags, ...
  221. *
  222. * Parameters
  223. * BufferIndex Index of the buffer to configure.
  224. * sName Pointer to a constant name string.
  225. * pBuffer Pointer to a buffer to be used.
  226. * BufferSize Size of the buffer.
  227. * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
  228. *
  229. * Return value
  230. * >= 0 - O.K.
  231. * < 0 - Error
  232. *
  233. * Additional information
  234. * Buffer 0 is configured on compile-time.
  235. * May only be called once per buffer.
  236. * Buffer name and flags can be reconfigured using the appropriate functions.
  237. */
  238. int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
  239. s_events_buf_filled = 0;
  240. return 0;
  241. }
  242. /*********************************************************************
  243. *
  244. * SEGGER_RTT_ConfigDownBuffer
  245. *
  246. * Function description
  247. * Run-time configuration of a specific down-buffer (H->T).
  248. * Buffer to be configured is specified by index.
  249. * This includes: Buffer address, size, name, flags, ...
  250. *
  251. * Parameters
  252. * BufferIndex Index of the buffer to configure.
  253. * sName Pointer to a constant name string.
  254. * pBuffer Pointer to a buffer to be used.
  255. * BufferSize Size of the buffer.
  256. * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
  257. *
  258. * Return value
  259. * >= 0 O.K.
  260. * < 0 Error
  261. *
  262. * Additional information
  263. * Buffer 0 is configured on compile-time.
  264. * May only be called once per buffer.
  265. * Buffer name and flags can be reconfigured using the appropriate functions.
  266. */
  267. int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
  268. esp_apptrace_down_buffer_config(s_down_buf, sizeof(s_down_buf));
  269. return 0;
  270. }
  271. /*************************** Init hook ****************************
  272. *
  273. * This init function is placed here because this port file will be
  274. * linked whenever SystemView is used.
  275. */
  276. ESP_SYSTEM_INIT_FN(sysview_init, BIT(0), 120)
  277. {
  278. SEGGER_SYSVIEW_Conf();
  279. return ESP_OK;
  280. }
  281. /*************************** End of file ****************************/