app_trace.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  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 "esp_log.h"
  8. #include "esp_app_trace.h"
  9. #include "esp_app_trace_port.h"
  10. #ifdef CONFIG_APPTRACE_DEST_UART0
  11. #define ESP_APPTRACE_DEST_UART_NUM 0
  12. #elif CONFIG_APPTRACE_DEST_UART1
  13. #define ESP_APPTRACE_DEST_UART_NUM 1
  14. #elif CONFIG_APPTRACE_DEST_UART2
  15. #define ESP_APPTRACE_DEST_UART_NUM 2
  16. #elif CONFIG_APPTRACE_DEST_USB_CDC
  17. #define ESP_APPTRACE_DEST_UART_NUM 10
  18. #else
  19. #define ESP_APPTRACE_DEST_UART_NUM 0
  20. #endif
  21. #define ESP_APPTRACE_MAX_VPRINTF_ARGS 256
  22. #define ESP_APPTRACE_HOST_BUF_SIZE 256
  23. #define ESP_APPTRACE_PRINT_LOCK 0
  24. const static char *TAG = "esp_apptrace";
  25. /** tracing module internal data */
  26. typedef struct {
  27. esp_apptrace_hw_t *hw;
  28. void *hw_data;
  29. } esp_apptrace_channel_t;
  30. static esp_apptrace_channel_t s_trace_channels[ESP_APPTRACE_DEST_MAX];
  31. static bool s_inited;
  32. esp_err_t esp_apptrace_init(void)
  33. {
  34. int res;
  35. esp_apptrace_hw_t *hw = NULL;
  36. void *hw_data = NULL;
  37. // 'esp_apptrace_init()' is called on every core, so ensure to do main initialization only once
  38. if (cpu_hal_get_core_id() == 0) {
  39. memset(&s_trace_channels, 0, sizeof(s_trace_channels));
  40. hw = esp_apptrace_jtag_hw_get(&hw_data);
  41. ESP_APPTRACE_LOGD("HW interface %p", hw);
  42. if (hw != NULL) {
  43. s_trace_channels[ESP_APPTRACE_DEST_JTAG].hw = hw;
  44. s_trace_channels[ESP_APPTRACE_DEST_JTAG].hw_data = hw_data;
  45. }
  46. hw = esp_apptrace_uart_hw_get(ESP_APPTRACE_DEST_UART_NUM, &hw_data);
  47. if (hw != NULL) {
  48. s_trace_channels[ESP_APPTRACE_DEST_UART].hw = hw;
  49. s_trace_channels[ESP_APPTRACE_DEST_UART].hw_data = hw_data;
  50. }
  51. s_inited = true;
  52. }
  53. // esp_apptrace_init() is called on every core, so initialize trace channel on every core
  54. for (int i = 0; i < sizeof(s_trace_channels) / sizeof(s_trace_channels[0]); i++) {
  55. esp_apptrace_channel_t *ch = &s_trace_channels[i];
  56. if (ch->hw) {
  57. res = ch->hw->init(ch->hw_data);
  58. if (res != ESP_OK) {
  59. ESP_APPTRACE_LOGE("Failed to init trace channel HW interface (%d)!", res);
  60. return res;
  61. }
  62. }
  63. }
  64. return ESP_OK;
  65. }
  66. void esp_apptrace_down_buffer_config(uint8_t *buf, uint32_t size)
  67. {
  68. esp_apptrace_channel_t *ch;
  69. if (!s_inited) {
  70. return;
  71. }
  72. // currently down buffer is supported for JTAG interface only
  73. // TODO: one more argument should be added to this function to specify HW inteface: JTAG, UART0 etc
  74. ch = &s_trace_channels[ESP_APPTRACE_DEST_JTAG];
  75. if (ch->hw != NULL) {
  76. if (ch->hw->down_buffer_config != NULL) {
  77. ch->hw->down_buffer_config(ch->hw_data, buf, size);
  78. }
  79. } else {
  80. ESP_APPTRACE_LOGD("Trace destination for JTAG not supported!");
  81. }
  82. ch = &s_trace_channels[ESP_APPTRACE_DEST_UART];
  83. if (ch->hw != NULL) {
  84. if (ch->hw->down_buffer_config != NULL) {
  85. ch->hw->down_buffer_config(ch->hw_data, buf, size);
  86. }
  87. } else {
  88. ESP_APPTRACE_LOGD("Trace destination for UART not supported!");
  89. }
  90. }
  91. uint8_t *esp_apptrace_down_buffer_get(esp_apptrace_dest_t dest, uint32_t *size, uint32_t user_tmo)
  92. {
  93. esp_apptrace_tmo_t tmo;
  94. esp_apptrace_channel_t *ch;
  95. ESP_APPTRACE_LOGV("%s(): enter", __func__);
  96. if (dest >= ESP_APPTRACE_DEST_MAX) {
  97. return NULL;
  98. }
  99. if (size == NULL || *size == 0) {
  100. return NULL;
  101. }
  102. if (!s_inited) {
  103. return NULL;
  104. }
  105. ch = &s_trace_channels[dest];
  106. if (ch->hw == NULL) {
  107. ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
  108. return NULL;
  109. }
  110. if (ch->hw->get_down_buffer == NULL) {
  111. return NULL;
  112. }
  113. esp_apptrace_tmo_init(&tmo, user_tmo);
  114. return ch->hw->get_down_buffer(ch->hw_data, size, &tmo);
  115. }
  116. esp_err_t esp_apptrace_down_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t user_tmo)
  117. {
  118. esp_apptrace_tmo_t tmo;
  119. esp_apptrace_channel_t *ch;
  120. ESP_APPTRACE_LOGV("%s(): enter", __func__);
  121. if (dest >= ESP_APPTRACE_DEST_MAX) {
  122. return ESP_ERR_INVALID_ARG;
  123. }
  124. if (ptr == NULL) {
  125. return ESP_ERR_INVALID_ARG;
  126. }
  127. if (!s_inited) {
  128. return ESP_ERR_INVALID_STATE;
  129. }
  130. ch = &s_trace_channels[dest];
  131. if (ch->hw == NULL) {
  132. ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
  133. return ESP_ERR_NOT_SUPPORTED;
  134. }
  135. if (ch->hw->get_down_buffer == NULL) {
  136. return ESP_ERR_NOT_SUPPORTED;
  137. }
  138. esp_apptrace_tmo_init(&tmo, user_tmo);
  139. return ch->hw->put_down_buffer(ch->hw_data, ptr, &tmo);
  140. }
  141. esp_err_t esp_apptrace_read(esp_apptrace_dest_t dest, void *buf, uint32_t *size, uint32_t user_tmo)
  142. {
  143. int res = ESP_OK;
  144. esp_apptrace_tmo_t tmo;
  145. esp_apptrace_channel_t *ch;
  146. ESP_APPTRACE_LOGV("%s(): enter", __func__);
  147. if (dest >= ESP_APPTRACE_DEST_MAX) {
  148. return ESP_ERR_INVALID_ARG;
  149. }
  150. if (buf == NULL || size == NULL || *size == 0) {
  151. return ESP_ERR_INVALID_ARG;
  152. }
  153. if (!s_inited) {
  154. return ESP_ERR_INVALID_STATE;
  155. }
  156. ch = &s_trace_channels[dest];
  157. if (ch->hw == NULL) {
  158. ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
  159. return ESP_ERR_NOT_SUPPORTED;
  160. }
  161. if (ch->hw->get_down_buffer == NULL || ch->hw->put_down_buffer == NULL) {
  162. return ESP_ERR_NOT_SUPPORTED;
  163. }
  164. //TODO: callback system
  165. esp_apptrace_tmo_init(&tmo, user_tmo);
  166. uint32_t act_sz = *size;
  167. *size = 0;
  168. uint8_t *ptr = ch->hw->get_down_buffer(ch->hw_data, &act_sz, &tmo);
  169. if (ptr && act_sz > 0) {
  170. ESP_APPTRACE_LOGD("Read %d bytes from host", act_sz);
  171. memcpy(buf, ptr, act_sz);
  172. res = ch->hw->put_down_buffer(ch->hw_data, ptr, &tmo);
  173. *size = act_sz;
  174. } else {
  175. res = ESP_ERR_TIMEOUT;
  176. }
  177. return res;
  178. }
  179. uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, uint32_t size, uint32_t user_tmo)
  180. {
  181. esp_apptrace_tmo_t tmo;
  182. esp_apptrace_channel_t *ch;
  183. ESP_APPTRACE_LOGV("%s(): enter", __func__);
  184. if (dest >= ESP_APPTRACE_DEST_MAX) {
  185. return NULL;
  186. }
  187. if (size == 0) {
  188. return NULL;
  189. }
  190. if (!s_inited) {
  191. return NULL;
  192. }
  193. ch = &s_trace_channels[dest];
  194. if (ch->hw == NULL) {
  195. ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
  196. return NULL;
  197. }
  198. if (ch->hw->get_up_buffer == NULL) {
  199. return NULL;
  200. }
  201. esp_apptrace_tmo_init(&tmo, user_tmo);
  202. return ch->hw->get_up_buffer(ch->hw_data, size, &tmo);
  203. }
  204. esp_err_t esp_apptrace_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t user_tmo)
  205. {
  206. esp_apptrace_tmo_t tmo;
  207. esp_apptrace_channel_t *ch;
  208. ESP_APPTRACE_LOGV("%s(): enter", __func__);
  209. if (dest >= ESP_APPTRACE_DEST_MAX) {
  210. return ESP_ERR_INVALID_ARG;
  211. }
  212. if (ptr == NULL) {
  213. return ESP_ERR_INVALID_ARG;
  214. }
  215. if (!s_inited) {
  216. return ESP_ERR_INVALID_STATE;
  217. }
  218. ch = &s_trace_channels[dest];
  219. if (ch->hw == NULL) {
  220. ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
  221. return ESP_ERR_NOT_SUPPORTED;
  222. }
  223. if (ch->hw->put_up_buffer == NULL) {
  224. return ESP_ERR_NOT_SUPPORTED;
  225. }
  226. esp_apptrace_tmo_init(&tmo, user_tmo);
  227. return ch->hw->put_up_buffer(ch->hw_data, ptr, &tmo);
  228. }
  229. esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, const void *data, uint32_t size, uint32_t user_tmo)
  230. {
  231. uint8_t *ptr = NULL;
  232. esp_apptrace_tmo_t tmo;
  233. esp_apptrace_channel_t *ch;
  234. ESP_APPTRACE_LOGV("%s(): enter", __func__);
  235. if (dest >= ESP_APPTRACE_DEST_MAX) {
  236. return ESP_ERR_INVALID_ARG;
  237. }
  238. if (data == NULL || size == 0) {
  239. return ESP_ERR_INVALID_ARG;
  240. }
  241. if (!s_inited) {
  242. return ESP_ERR_INVALID_STATE;
  243. }
  244. ch = &s_trace_channels[dest];
  245. if (ch->hw == NULL) {
  246. ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
  247. return ESP_ERR_NOT_SUPPORTED;
  248. }
  249. if (ch->hw->get_up_buffer == NULL || ch->hw->put_up_buffer == NULL) {
  250. return ESP_ERR_NOT_SUPPORTED;
  251. }
  252. esp_apptrace_tmo_init(&tmo, user_tmo);
  253. ptr = ch->hw->get_up_buffer(ch->hw_data, size, &tmo);
  254. if (ptr == NULL) {
  255. return ESP_ERR_NO_MEM;
  256. }
  257. // actually can be suspended here by higher prio tasks/ISRs
  258. //TODO: use own memcpy with dead trace calls kick-off algo and tmo expiration check
  259. memcpy(ptr, data, size);
  260. // now indicate that this buffer is ready to be sent off to host
  261. return ch->hw->put_up_buffer(ch->hw_data, ptr, &tmo);
  262. }
  263. int esp_apptrace_vprintf_to(esp_apptrace_dest_t dest, uint32_t user_tmo, const char *fmt, va_list ap)
  264. {
  265. uint16_t nargs = 0;
  266. uint8_t *pout, *p = (uint8_t *)fmt;
  267. esp_apptrace_tmo_t tmo;
  268. esp_apptrace_channel_t *ch;
  269. ESP_APPTRACE_LOGV("%s(): enter", __func__);
  270. if (dest >= ESP_APPTRACE_DEST_MAX) {
  271. return -1;
  272. }
  273. if (fmt == NULL) {
  274. return -1;
  275. }
  276. if (!s_inited) {
  277. return -1;
  278. }
  279. ch = &s_trace_channels[dest];
  280. if (ch->hw == NULL) {
  281. ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
  282. return -1;
  283. }
  284. if (ch->hw->get_up_buffer == NULL || ch->hw->put_up_buffer == NULL) {
  285. return -1;
  286. }
  287. esp_apptrace_tmo_init(&tmo, user_tmo);
  288. ESP_APPTRACE_LOGD("fmt %x", fmt);
  289. while ((p = (uint8_t *)strchr((char *)p, '%')) && nargs < ESP_APPTRACE_MAX_VPRINTF_ARGS) {
  290. p++;
  291. if (*p != '%' && *p != 0) {
  292. nargs++;
  293. }
  294. }
  295. ESP_APPTRACE_LOGD("nargs = %d", nargs);
  296. if (p) {
  297. ESP_APPTRACE_LOGE("Failed to store all printf args!");
  298. }
  299. pout = ch->hw->get_up_buffer(ch->hw_data, 1 + sizeof(char *) + nargs * sizeof(uint32_t), &tmo);
  300. if (pout == NULL) {
  301. ESP_APPTRACE_LOGE("Failed to get buffer!");
  302. return -1;
  303. }
  304. p = pout;
  305. *pout = nargs;
  306. pout++;
  307. *(const char **)pout = fmt;
  308. pout += sizeof(char *);
  309. while (nargs-- > 0) {
  310. uint32_t arg = va_arg(ap, uint32_t);
  311. *(uint32_t *)pout = arg;
  312. pout += sizeof(uint32_t);
  313. ESP_APPTRACE_LOGD("arg %x", arg);
  314. }
  315. int ret = ch->hw->put_up_buffer(ch->hw_data, p, &tmo);
  316. if (ret != ESP_OK) {
  317. ESP_APPTRACE_LOGE("Failed to put printf buf (%d)!", ret);
  318. return -1;
  319. }
  320. return (pout - p);
  321. }
  322. int esp_apptrace_vprintf(const char *fmt, va_list ap)
  323. {
  324. return esp_apptrace_vprintf_to(ESP_APPTRACE_DEST_JTAG, 0, fmt, ap);
  325. }
  326. esp_err_t esp_apptrace_flush_nolock(esp_apptrace_dest_t dest, uint32_t min_sz, uint32_t usr_tmo)
  327. {
  328. esp_apptrace_tmo_t tmo;
  329. esp_apptrace_channel_t *ch;
  330. ESP_APPTRACE_LOGV("%s(): enter", __func__);
  331. if (dest >= ESP_APPTRACE_DEST_MAX) {
  332. return ESP_ERR_INVALID_ARG;
  333. }
  334. if (!s_inited) {
  335. return ESP_ERR_INVALID_STATE;
  336. }
  337. ch = &s_trace_channels[dest];
  338. if (ch->hw == NULL) {
  339. ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
  340. return ESP_ERR_NOT_SUPPORTED;
  341. }
  342. if (ch->hw->flush_up_buffer_nolock == NULL) {
  343. return ESP_ERR_NOT_SUPPORTED;
  344. }
  345. esp_apptrace_tmo_init(&tmo, usr_tmo);
  346. return ch->hw->flush_up_buffer_nolock(ch->hw_data, min_sz, &tmo);
  347. }
  348. esp_err_t esp_apptrace_flush(esp_apptrace_dest_t dest, uint32_t usr_tmo)
  349. {
  350. esp_apptrace_tmo_t tmo;
  351. esp_apptrace_channel_t *ch;
  352. ESP_APPTRACE_LOGV("%s(): enter", __func__);
  353. if (dest >= ESP_APPTRACE_DEST_MAX) {
  354. return ESP_ERR_INVALID_ARG;
  355. }
  356. if (!s_inited) {
  357. return ESP_ERR_INVALID_STATE;
  358. }
  359. ch = &s_trace_channels[dest];
  360. if (ch->hw == NULL) {
  361. ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
  362. return ESP_ERR_NOT_SUPPORTED;
  363. }
  364. if (ch->hw->flush_up_buffer == NULL) {
  365. return ESP_ERR_NOT_SUPPORTED;
  366. }
  367. esp_apptrace_tmo_init(&tmo, usr_tmo);
  368. return ch->hw->flush_up_buffer(ch->hw_data, &tmo);
  369. }
  370. bool esp_apptrace_host_is_connected(esp_apptrace_dest_t dest)
  371. {
  372. esp_apptrace_channel_t *ch;
  373. ESP_APPTRACE_LOGV("%s(): enter", __func__);
  374. if (dest >= ESP_APPTRACE_DEST_MAX) {
  375. return false;
  376. }
  377. if (!s_inited) {
  378. return false;
  379. }
  380. ch = &s_trace_channels[dest];
  381. if (ch->hw == NULL) {
  382. ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
  383. return false;
  384. }
  385. if (ch->hw->host_is_connected == NULL) {
  386. return false;
  387. }
  388. return ch->hw->host_is_connected(ch->hw_data);
  389. }
  390. #if !CONFIG_APPTRACE_DEST_JTAG
  391. esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
  392. {
  393. return NULL;
  394. }
  395. #endif