app_trace.c 13 KB

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