port_uart.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /*
  2. * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "soc/soc.h"
  7. #include "esp_log.h"
  8. #include "esp_cpu.h"
  9. #include "esp_app_trace_port.h"
  10. #include "driver/uart.h"
  11. #include "hal/uart_ll.h"
  12. #include "string.h"
  13. #include "driver/gpio.h"
  14. #define APPTRACE_DEST_UART (CONFIG_APPTRACE_DEST_UART0 | CONFIG_APPTRACE_DEST_UART1 | CONFIG_APPTRACE_DEST_UART2)
  15. #define APP_TRACE_MAX_TX_BUFF_UART CONFIG_APPTRACE_UART_TX_BUFF_SIZE
  16. #define APP_TRACE_MAX_TX_MSG_UART CONFIG_APPTRACE_UART_TX_MSG_SIZE
  17. /** UART HW transport data */
  18. typedef struct {
  19. uint8_t inited;
  20. #if CONFIG_APPTRACE_LOCK_ENABLE
  21. esp_apptrace_lock_t lock; // sync lock
  22. #endif
  23. uart_port_t port_num;
  24. // TX data ring buffer
  25. uint8_t *tx_data_buff;
  26. int32_t tx_data_buff_in;
  27. int32_t tx_data_buff_out;
  28. // TX message buffer
  29. uint8_t *tx_msg_buff;
  30. uint32_t tx_msg_buff_size;
  31. // RX message buffer
  32. uint8_t *down_buffer;
  33. uint32_t down_buffer_size;
  34. // Buffer overflow flags
  35. bool message_buff_overflow;
  36. bool circular_buff_overflow;
  37. } esp_apptrace_uart_data_t;
  38. #if APPTRACE_DEST_UART
  39. static esp_err_t esp_apptrace_uart_init(esp_apptrace_uart_data_t *hw_data);
  40. static esp_err_t esp_apptrace_uart_flush(esp_apptrace_uart_data_t *hw_data, esp_apptrace_tmo_t *tmo);
  41. static esp_err_t esp_apptrace_uart_flush_nolock(esp_apptrace_uart_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo);
  42. static uint8_t *esp_apptrace_uart_up_buffer_get(esp_apptrace_uart_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo);
  43. static esp_err_t esp_apptrace_uart_up_buffer_put(esp_apptrace_uart_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
  44. static void esp_apptrace_uart_down_buffer_config(esp_apptrace_uart_data_t *hw_data, uint8_t *buf, uint32_t size);
  45. static uint8_t *esp_apptrace_uart_down_buffer_get(esp_apptrace_uart_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo);
  46. static esp_err_t esp_apptrace_uart_down_buffer_put(esp_apptrace_uart_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
  47. static bool esp_apptrace_uart_host_is_connected(esp_apptrace_uart_data_t *hw_data);
  48. #endif // APPTRACE_DEST_UART
  49. const static char *TAG = "esp_apptrace_uart";
  50. esp_apptrace_hw_t *esp_apptrace_uart_hw_get(int num, void **data)
  51. {
  52. ESP_LOGD(TAG,"esp_apptrace_uart_hw_get - %i", num);
  53. #if APPTRACE_DEST_UART
  54. static esp_apptrace_uart_data_t s_uart_hw_data = {
  55. };
  56. static esp_apptrace_hw_t s_uart_hw = {
  57. .init = (esp_err_t (*)(void *))esp_apptrace_uart_init,
  58. .get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_uart_up_buffer_get,
  59. .put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_up_buffer_put,
  60. .flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_uart_flush_nolock,
  61. .flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_uart_flush,
  62. .down_buffer_config = (void (*)(void *, uint8_t *, uint32_t ))esp_apptrace_uart_down_buffer_config,
  63. .get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_down_buffer_get,
  64. .put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_down_buffer_put,
  65. .host_is_connected = (bool (*)(void *))esp_apptrace_uart_host_is_connected,
  66. };
  67. s_uart_hw_data.port_num = num;
  68. *data = &s_uart_hw_data;
  69. return &s_uart_hw;
  70. #else
  71. return NULL;
  72. #endif
  73. }
  74. #if APPTRACE_DEST_UART
  75. static esp_err_t esp_apptrace_uart_lock(esp_apptrace_uart_data_t *hw_data, esp_apptrace_tmo_t *tmo)
  76. {
  77. #if CONFIG_APPTRACE_LOCK_ENABLE
  78. esp_err_t ret = esp_apptrace_lock_take(&hw_data->lock, tmo);
  79. if (ret != ESP_OK) {
  80. return ESP_FAIL;
  81. }
  82. #endif
  83. return ESP_OK;
  84. }
  85. static esp_err_t esp_apptrace_uart_unlock(esp_apptrace_uart_data_t *hw_data)
  86. {
  87. esp_err_t ret = ESP_OK;
  88. #if CONFIG_APPTRACE_LOCK_ENABLE
  89. ret = esp_apptrace_lock_give(&hw_data->lock);
  90. #endif
  91. return ret;
  92. }
  93. static inline void esp_apptrace_uart_hw_init(void)
  94. {
  95. ESP_APPTRACE_LOGI("Initialized UART on CPU%d", esp_cpu_get_core_id());
  96. }
  97. /*****************************************************************************************/
  98. /***************************** Apptrace HW iface *****************************************/
  99. /*****************************************************************************************/
  100. static esp_err_t esp_apptrace_send_uart_data(esp_apptrace_uart_data_t *hw_data, const char *data, uint32_t size, esp_apptrace_tmo_t *tmo)
  101. {
  102. esp_err_t res = esp_apptrace_uart_lock(hw_data, tmo);
  103. if (res != ESP_OK) {
  104. return res;
  105. }
  106. // We store current out position to handle it without lock
  107. volatile int32_t out_position = hw_data->tx_data_buff_out;
  108. int len_free = APP_TRACE_MAX_TX_BUFF_UART - (hw_data->tx_data_buff_in - out_position);
  109. if (out_position > hw_data->tx_data_buff_in) {
  110. len_free = out_position - hw_data->tx_data_buff_in;
  111. }
  112. int check_len = APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_in;
  113. if (size <= len_free)
  114. {
  115. if ( check_len >= size) {
  116. memcpy(&hw_data->tx_data_buff[hw_data->tx_data_buff_in], data, size);
  117. hw_data->tx_data_buff_in += size;
  118. } else {
  119. memcpy(&hw_data->tx_data_buff[hw_data->tx_data_buff_in], data, APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_in);
  120. memcpy(&hw_data->tx_data_buff[0], &data[APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_in], size - (APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_in));
  121. hw_data->tx_data_buff_in = size - (APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_in);
  122. }
  123. if (hw_data->tx_data_buff_in >= APP_TRACE_MAX_TX_BUFF_UART) {
  124. hw_data->tx_data_buff_in = 0;
  125. }
  126. } else {
  127. hw_data->circular_buff_overflow = true;
  128. }
  129. if (esp_apptrace_uart_unlock(hw_data) != ESP_OK) {
  130. assert(false && "Failed to unlock apptrace data!");
  131. }
  132. return ESP_OK;
  133. }
  134. static void send_buff_data(esp_apptrace_uart_data_t *hw_data, esp_apptrace_tmo_t *tmo)
  135. {
  136. if (hw_data->tx_data_buff_in == hw_data->tx_data_buff_out) {
  137. return;
  138. }
  139. // We store current in position to handle it without lock
  140. volatile int32_t in_position = hw_data->tx_data_buff_in;
  141. if (in_position > hw_data->tx_data_buff_out) {
  142. int bytes_sent = uart_write_bytes(hw_data->port_num, &hw_data->tx_data_buff[hw_data->tx_data_buff_out], in_position - hw_data->tx_data_buff_out);
  143. hw_data->tx_data_buff_out += bytes_sent;
  144. } else {
  145. int bytes_sent = uart_write_bytes(hw_data->port_num, &hw_data->tx_data_buff[hw_data->tx_data_buff_out], APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_out);
  146. hw_data->tx_data_buff_out += bytes_sent;
  147. if (hw_data->tx_data_buff_out >= APP_TRACE_MAX_TX_BUFF_UART) {
  148. hw_data->tx_data_buff_out = 0;
  149. }
  150. }
  151. }
  152. #define APP_TRACE_UART_STOP_WAIT_TMO 1000000 //us
  153. static void esp_apptrace_send_uart_tx_task(void *arg)
  154. {
  155. esp_apptrace_uart_data_t *hw_data = (esp_apptrace_uart_data_t *)arg;
  156. esp_apptrace_tmo_t tmo;
  157. esp_apptrace_tmo_init(&tmo, APP_TRACE_UART_STOP_WAIT_TMO);
  158. vTaskDelay(10);
  159. while (1) {
  160. send_buff_data(hw_data, &tmo);
  161. vTaskDelay(10);
  162. if (hw_data->circular_buff_overflow == true)
  163. {
  164. hw_data->circular_buff_overflow = false;
  165. ESP_LOGE(TAG, "Buffer overflow. Please increase UART baudrate, or increase UART TX ring buffer size in menuconfig.");
  166. }
  167. if (hw_data->message_buff_overflow == true)
  168. {
  169. hw_data->message_buff_overflow = false;
  170. ESP_LOGE(TAG, "Message size more then message buffer!");
  171. }
  172. }
  173. }
  174. static const int APP_TRACE_UART_RX_BUF_SIZE = 4024;
  175. static esp_err_t esp_apptrace_uart_init(esp_apptrace_uart_data_t *hw_data)
  176. {
  177. int core_id = esp_cpu_get_core_id();
  178. if (core_id == 0) {
  179. hw_data->tx_data_buff = (uint8_t *)heap_caps_malloc(APP_TRACE_MAX_TX_BUFF_UART, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
  180. if (hw_data->tx_data_buff == NULL){
  181. return ESP_ERR_NO_MEM;
  182. }
  183. hw_data->tx_data_buff_in = 0;
  184. hw_data->tx_data_buff_out = 0;
  185. hw_data->tx_msg_buff = (uint8_t *)heap_caps_malloc(APP_TRACE_MAX_TX_MSG_UART, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
  186. if (hw_data->tx_msg_buff == NULL)
  187. {
  188. return ESP_ERR_NO_MEM;
  189. }
  190. hw_data->tx_msg_buff_size = 0;
  191. hw_data->down_buffer_size = 0;
  192. hw_data->message_buff_overflow = false;
  193. hw_data->circular_buff_overflow = false;
  194. const uart_config_t uart_config = {
  195. .baud_rate = CONFIG_APPTRACE_UART_BAUDRATE,
  196. .data_bits = UART_DATA_8_BITS,
  197. .parity = UART_PARITY_DISABLE,
  198. .stop_bits = UART_STOP_BITS_1,
  199. .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
  200. .source_clk = UART_SCLK_DEFAULT,
  201. };
  202. ESP_LOGI(TAG, "UART baud rate: %i", CONFIG_APPTRACE_UART_BAUDRATE);
  203. // We won't use a buffer for sending data.
  204. esp_err_t err = uart_driver_install(hw_data->port_num, APP_TRACE_UART_RX_BUF_SIZE, APP_TRACE_UART_RX_BUF_SIZE, 0, NULL, 0);
  205. assert((err == ESP_OK) && "Not possible to install UART. Please check and change menuconfig parameters!");
  206. err = uart_param_config(hw_data->port_num, &uart_config);
  207. assert((err == ESP_OK) && "Not possible to configure UART. Please check and change menuconfig parameters!");
  208. err = uart_set_pin(hw_data->port_num, CONFIG_APPTRACE_UART_TX_GPIO, CONFIG_APPTRACE_UART_RX_GPIO, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
  209. assert((err == ESP_OK) && "Not possible to configure UART RX/TX pins. Please check and change menuconfig parameters!");
  210. int uart_prio = CONFIG_APPTRACE_UART_TASK_PRIO;
  211. if (uart_prio >= (configMAX_PRIORITIES-1)) uart_prio = configMAX_PRIORITIES - 1;
  212. err = xTaskCreate(esp_apptrace_send_uart_tx_task, "app_trace_uart_tx_task", 2500, hw_data, uart_prio, NULL);
  213. assert((err == pdPASS) && "Not possible to configure UART. Not possible to create task!");
  214. #if CONFIG_APPTRACE_LOCK_ENABLE
  215. esp_apptrace_lock_init(&hw_data->lock);
  216. #endif
  217. }
  218. // init UART on this CPU
  219. esp_apptrace_uart_hw_init();
  220. hw_data->inited |= 1 << core_id;
  221. return ESP_OK;
  222. }
  223. static uint8_t *esp_apptrace_uart_up_buffer_get(esp_apptrace_uart_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo)
  224. {
  225. uint8_t *ptr;
  226. if (size > APP_TRACE_MAX_TX_MSG_UART) {
  227. hw_data->message_buff_overflow = true;
  228. return NULL;
  229. }
  230. if (hw_data->tx_msg_buff_size != 0)
  231. {
  232. // A previous message was not sent.
  233. return NULL;
  234. }
  235. esp_err_t res = esp_apptrace_uart_lock(hw_data, tmo);
  236. if (res != ESP_OK) {
  237. return NULL;
  238. }
  239. ptr = hw_data->tx_msg_buff;
  240. hw_data->tx_msg_buff_size = size;
  241. // now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
  242. if (esp_apptrace_uart_unlock(hw_data) != ESP_OK) {
  243. assert(false && "Failed to unlock apptrace data!");
  244. }
  245. return ptr;
  246. }
  247. static esp_err_t esp_apptrace_uart_up_buffer_put(esp_apptrace_uart_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
  248. {
  249. esp_err_t res = esp_apptrace_send_uart_data(hw_data, (const char *)ptr, hw_data->tx_msg_buff_size, tmo);
  250. // Clear size to indicate that we've sent data
  251. hw_data->tx_msg_buff_size = 0;
  252. return res;
  253. }
  254. static void esp_apptrace_uart_down_buffer_config(esp_apptrace_uart_data_t *hw_data, uint8_t *buf, uint32_t size)
  255. {
  256. hw_data->down_buffer = (uint8_t *)malloc(size);
  257. if (hw_data->down_buffer == NULL){
  258. assert(false && "Failed to allocate apptrace uart down buffer!");
  259. }
  260. hw_data->down_buffer_size = size;
  261. }
  262. static uint8_t *esp_apptrace_uart_down_buffer_get(esp_apptrace_uart_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo)
  263. {
  264. uint8_t *ptr = NULL;
  265. if (*size > hw_data->down_buffer_size) {
  266. return NULL;
  267. }
  268. esp_err_t res = esp_apptrace_uart_lock(hw_data, tmo);
  269. if (res != ESP_OK) {
  270. return NULL;
  271. }
  272. size_t uart_fifolen = 0;
  273. uart_get_buffered_data_len(hw_data->port_num, &uart_fifolen);
  274. if (uart_fifolen > 0) {
  275. if (*size < uart_fifolen) {
  276. uart_fifolen = *size;
  277. }
  278. *size = uart_fifolen;
  279. ptr = hw_data->down_buffer;
  280. *size =uart_read_bytes(hw_data->port_num, ptr, uart_fifolen, 0);
  281. }
  282. if (esp_apptrace_uart_unlock(hw_data) != ESP_OK) {
  283. assert(false && "Failed to unlock apptrace data!");
  284. }
  285. return ptr;
  286. }
  287. static esp_err_t esp_apptrace_uart_down_buffer_put(esp_apptrace_uart_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
  288. {
  289. return ESP_OK;
  290. }
  291. static bool esp_apptrace_uart_host_is_connected(esp_apptrace_uart_data_t *hw_data)
  292. {
  293. return hw_data->inited & 1;
  294. }
  295. static esp_err_t esp_apptrace_uart_flush_nolock(esp_apptrace_uart_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
  296. {
  297. return ESP_OK;
  298. }
  299. static esp_err_t esp_apptrace_uart_flush(esp_apptrace_uart_data_t *hw_data, esp_apptrace_tmo_t *tmo)
  300. {
  301. return ESP_OK;
  302. }
  303. #endif // APPTRACE_DEST_UART