core_dump_uart.c 5.7 KB

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