core_dump_uart.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. // Copyright 2015-2019 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. #include <string.h>
  14. #include "soc/uart_periph.h"
  15. #include "soc/gpio_periph.h"
  16. #include "driver/gpio.h"
  17. #include "esp_core_dump_types.h"
  18. #include "esp_core_dump_port.h"
  19. #include "esp_core_dump_common.h"
  20. #include "esp_rom_sys.h"
  21. const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_uart";
  22. #if CONFIG_ESP_COREDUMP_ENABLE_TO_UART
  23. /* This function exists on every board, thus, we don't need to specify
  24. * explicitly the header for each board. */
  25. int esp_clk_cpu_freq(void);
  26. static void esp_core_dump_b64_encode(const uint8_t *src, uint32_t src_len, uint8_t *dst) {
  27. const static DRAM_ATTR char b64[] =
  28. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  29. int i, j, a, b, c;
  30. for (i = j = 0; i < src_len; i += 3) {
  31. a = src[i];
  32. b = i + 1 >= src_len ? 0 : src[i + 1];
  33. c = i + 2 >= src_len ? 0 : src[i + 2];
  34. dst[j++] = b64[a >> 2];
  35. dst[j++] = b64[((a & 3) << 4) | (b >> 4)];
  36. if (i + 1 < src_len) {
  37. dst[j++] = b64[(b & 0x0F) << 2 | (c >> 6)];
  38. }
  39. if (i + 2 < src_len) {
  40. dst[j++] = b64[c & 0x3F];
  41. }
  42. }
  43. while (j % 4 != 0) {
  44. dst[j++] = '=';
  45. }
  46. dst[j++] = '\0';
  47. }
  48. static esp_err_t esp_core_dump_uart_write_start(core_dump_write_data_t *priv)
  49. {
  50. esp_err_t err = ESP_OK;
  51. core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv;
  52. ESP_COREDUMP_ASSERT(priv != NULL);
  53. esp_core_dump_checksum_init(&wr_data->checksum_ctx);
  54. esp_rom_printf(DRAM_STR("================= CORE DUMP START =================\r\n"));
  55. return err;
  56. }
  57. static esp_err_t esp_core_dump_uart_write_prepare(core_dump_write_data_t *priv, uint32_t *data_len)
  58. {
  59. ESP_COREDUMP_ASSERT(data_len != NULL);
  60. *data_len += esp_core_dump_checksum_size();
  61. return ESP_OK;
  62. }
  63. static esp_err_t esp_core_dump_uart_write_end(core_dump_write_data_t *priv)
  64. {
  65. esp_err_t err = ESP_OK;
  66. char buf[64 + 4] = { 0 };
  67. core_dump_checksum_bytes cs_addr = NULL;
  68. core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv;
  69. if (wr_data) {
  70. size_t cs_len = esp_core_dump_checksum_finish(wr_data->checksum_ctx, &cs_addr);
  71. wr_data->off += cs_len;
  72. esp_core_dump_b64_encode((const uint8_t *)cs_addr, cs_len, (uint8_t*)&buf[0]);
  73. esp_rom_printf(DRAM_STR("%s\r\n"), buf);
  74. }
  75. esp_rom_printf(DRAM_STR("================= CORE DUMP END =================\r\n"));
  76. if (cs_addr) {
  77. esp_core_dump_print_checksum(DRAM_STR("Coredump checksum"), cs_addr);
  78. }
  79. return err;
  80. }
  81. static esp_err_t esp_core_dump_uart_write_data(core_dump_write_data_t *priv, void * data, uint32_t data_len)
  82. {
  83. esp_err_t err = ESP_OK;
  84. char buf[64 + 4] = { 0 };
  85. char *addr = data;
  86. char *end = addr + data_len;
  87. core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv;
  88. ESP_COREDUMP_ASSERT(data != NULL);
  89. while (addr < end) {
  90. size_t len = end - addr;
  91. if (len > 48) len = 48;
  92. /* Copy to stack to avoid alignment restrictions. */
  93. char *tmp = buf + (sizeof(buf) - len);
  94. memcpy(tmp, addr, len);
  95. esp_core_dump_b64_encode((const uint8_t *)tmp, len, (uint8_t *)buf);
  96. addr += len;
  97. esp_rom_printf(DRAM_STR("%s\r\n"), buf);
  98. }
  99. if (wr_data) {
  100. wr_data->off += data_len;
  101. esp_core_dump_checksum_update(wr_data->checksum_ctx, data, data_len);
  102. }
  103. return err;
  104. }
  105. static int esp_core_dump_uart_get_char(void) {
  106. int i = -1;
  107. uint32_t reg = (READ_PERI_REG(UART_STATUS_REG(0)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT;
  108. if (reg) {
  109. i = READ_PERI_REG(UART_FIFO_REG(0));
  110. }
  111. return i;
  112. }
  113. void esp_core_dump_to_uart(panic_info_t *info)
  114. {
  115. core_dump_write_data_t wr_data = { 0 };
  116. core_dump_write_config_t wr_cfg = {
  117. .prepare = esp_core_dump_uart_write_prepare,
  118. .start = esp_core_dump_uart_write_start,
  119. .end = esp_core_dump_uart_write_end,
  120. .write = esp_core_dump_uart_write_data,
  121. .priv = (void*)&wr_data
  122. };
  123. uint32_t tm_end = 0;
  124. uint32_t tm_cur = 0;
  125. int ch = 0;
  126. // TODO: move chip dependent code to portable part
  127. //Make sure txd/rxd are enabled
  128. // use direct reg access instead of gpio_pullup_dis which can cause exception when flash cache is disabled
  129. REG_CLR_BIT(GPIO_PIN_REG_1, FUN_PU);
  130. PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_U0RXD);
  131. PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_U0TXD);
  132. ESP_COREDUMP_LOGI("Press Enter to print core dump to UART...");
  133. const int cpu_ticks_per_ms = esp_clk_cpu_freq() / 1000;
  134. tm_end = esp_cpu_get_ccount() / cpu_ticks_per_ms + CONFIG_ESP_COREDUMP_UART_DELAY;
  135. ch = esp_core_dump_uart_get_char();
  136. while (!(ch == '\n' || ch == '\r')) {
  137. tm_cur = esp_cpu_get_ccount() / cpu_ticks_per_ms;
  138. if (tm_cur >= tm_end){
  139. break;
  140. }
  141. ch = esp_core_dump_uart_get_char();
  142. }
  143. ESP_COREDUMP_LOGI("Print core dump to uart...");
  144. esp_core_dump_write(info, &wr_cfg);
  145. ESP_COREDUMP_LOGI("Core dump has been written to uart.");
  146. }
  147. void esp_core_dump_init(void)
  148. {
  149. ESP_COREDUMP_LOGI("Init core dump to UART");
  150. }
  151. #endif