core_dump_flash.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // Copyright 2015-2016 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 "rom/crc.h"
  15. #include "esp_partition.h"
  16. #include "esp_core_dump_priv.h"
  17. const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_flash";
  18. #if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
  19. typedef struct _core_dump_write_flash_data_t
  20. {
  21. uint32_t off; // current offset in partition
  22. core_dump_crc_t crc; // CRC of dumped data
  23. } core_dump_write_flash_data_t;
  24. typedef struct _core_dump_partition_t
  25. {
  26. // core dump partition start
  27. uint32_t start;
  28. // core dump partition size
  29. uint32_t size;
  30. } core_dump_partition_t;
  31. typedef struct _core_dump_flash_config_t
  32. {
  33. // core dump partition config
  34. core_dump_partition_t partition;
  35. // CRC of core dump partition config
  36. core_dump_crc_t partition_config_crc;
  37. } core_dump_flash_config_t;
  38. // core dump flash data
  39. static core_dump_flash_config_t s_core_flash_config;
  40. static inline core_dump_crc_t esp_core_dump_calc_flash_config_crc(void)
  41. {
  42. return crc32_le(0, (uint8_t const *)&s_core_flash_config.partition, sizeof(s_core_flash_config.partition));
  43. }
  44. void esp_core_dump_flash_init()
  45. {
  46. const esp_partition_t *core_part;
  47. ESP_COREDUMP_LOGI("Init core dump to flash");
  48. core_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_COREDUMP, NULL);
  49. if (!core_part) {
  50. ESP_COREDUMP_LOGE("No core dump partition found!");
  51. return;
  52. }
  53. ESP_COREDUMP_LOGI("Found partition '%s' @ %x %d bytes", core_part->label, core_part->address, core_part->size);
  54. s_core_flash_config.partition.start = core_part->address;
  55. s_core_flash_config.partition.size = core_part->size;
  56. s_core_flash_config.partition_config_crc = esp_core_dump_calc_flash_config_crc();
  57. }
  58. static uint32_t esp_core_dump_write_flash_padded(size_t off, uint8_t *data, uint32_t data_size)
  59. {
  60. esp_err_t err;
  61. uint32_t data_len = 0, k, len;
  62. union
  63. {
  64. uint8_t data8[4];
  65. uint32_t data32;
  66. } rom_data;
  67. data_len = (data_size / sizeof(uint32_t)) * sizeof(uint32_t);
  68. assert(off >= s_core_flash_config.partition.start);
  69. assert((off + data_len + (data_size % sizeof(uint32_t) ? sizeof(uint32_t) : 0)) <=
  70. s_core_flash_config.partition.start + s_core_flash_config.partition.size);
  71. err = spi_flash_write(off, data, data_len);
  72. if (err != ESP_OK) {
  73. ESP_COREDUMP_LOGE("Failed to write data to flash (%d)!", err);
  74. return 0;
  75. }
  76. len = data_size % sizeof(uint32_t);
  77. if (len) {
  78. // write last bytes with padding, actual TCB len can be retrieved by esptool from core dump header
  79. rom_data.data32 = 0;
  80. for (k = 0; k < len; k++) {
  81. rom_data.data8[k] = *(data + data_len + k);
  82. }
  83. err = spi_flash_write(off + data_len, &rom_data, sizeof(uint32_t));
  84. if (err != ESP_OK) {
  85. ESP_COREDUMP_LOGE("Failed to finish write data to flash (%d)!", err);
  86. return 0;
  87. }
  88. data_len += sizeof(uint32_t);
  89. }
  90. return data_len;
  91. }
  92. static esp_err_t esp_core_dump_flash_write_prepare(void *priv, uint32_t *data_len)
  93. {
  94. esp_err_t err;
  95. uint32_t sec_num;
  96. core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv;
  97. // check for available space in partition
  98. if ((*data_len + sizeof(uint32_t)) > s_core_flash_config.partition.size) {
  99. ESP_COREDUMP_LOGE("Not enough space to save core dump!");
  100. return ESP_ERR_NO_MEM;
  101. }
  102. // add space for CRC
  103. *data_len += sizeof(core_dump_crc_t);
  104. memset(wr_data, 0, sizeof(*wr_data));
  105. sec_num = *data_len / SPI_FLASH_SEC_SIZE;
  106. if (*data_len % SPI_FLASH_SEC_SIZE) {
  107. sec_num++;
  108. }
  109. assert(sec_num * SPI_FLASH_SEC_SIZE <= s_core_flash_config.partition.size);
  110. err = spi_flash_erase_range(s_core_flash_config.partition.start + 0, sec_num * SPI_FLASH_SEC_SIZE);
  111. if (err != ESP_OK) {
  112. ESP_COREDUMP_LOGE("Failed to erase flash (%d)!", err);
  113. return err;
  114. }
  115. return err;
  116. }
  117. static esp_err_t esp_core_dump_flash_write_word(core_dump_write_flash_data_t *wr_data, uint32_t word)
  118. {
  119. esp_err_t err = ESP_OK;
  120. uint32_t data32 = word;
  121. assert(wr_data->off + sizeof(uint32_t) <= s_core_flash_config.partition.size);
  122. err = spi_flash_write(s_core_flash_config.partition.start + wr_data->off, &data32, sizeof(uint32_t));
  123. if (err != ESP_OK) {
  124. ESP_COREDUMP_LOGE("Failed to write to flash (%d)!", err);
  125. return err;
  126. }
  127. wr_data->off += sizeof(uint32_t);
  128. return err;
  129. }
  130. static esp_err_t esp_core_dump_flash_write_start(void *priv)
  131. {
  132. return ESP_OK;
  133. }
  134. static esp_err_t esp_core_dump_flash_write_end(void *priv)
  135. {
  136. core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv;
  137. #if LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG
  138. union
  139. {
  140. uint8_t data8[16];
  141. uint32_t data32[4];
  142. } rom_data;
  143. esp_err_t err = spi_flash_read(s_core_flash_config.partition.start + 0, &rom_data, sizeof(rom_data));
  144. if (err != ESP_OK) {
  145. ESP_COREDUMP_LOGE("Failed to read flash (%d)!", err);
  146. return err;
  147. } else {
  148. ESP_COREDUMP_LOG_PROCESS("Data from flash:");
  149. for (uint32_t i = 0; i < sizeof(rom_data)/sizeof(rom_data.data32[0]); i++) {
  150. ESP_COREDUMP_LOG_PROCESS("%x", rom_data.data32[i]);
  151. }
  152. }
  153. #endif
  154. // write core dump CRC
  155. ESP_COREDUMP_LOG_PROCESS("Dump data CRC = 0x%x", wr_data->crc);
  156. return esp_core_dump_flash_write_word(wr_data, wr_data->crc);
  157. }
  158. static esp_err_t esp_core_dump_flash_write_data(void *priv, void * data, uint32_t data_len)
  159. {
  160. esp_err_t err = ESP_OK;
  161. core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv;
  162. uint32_t len = esp_core_dump_write_flash_padded(s_core_flash_config.partition.start + wr_data->off, data, data_len);
  163. if (len != data_len) {
  164. return ESP_FAIL;
  165. }
  166. wr_data->off += len;
  167. wr_data->crc = crc32_le(wr_data->crc, data, data_len);
  168. return err;
  169. }
  170. void esp_core_dump_to_flash(XtExcFrame *frame)
  171. {
  172. core_dump_write_config_t wr_cfg;
  173. core_dump_write_flash_data_t wr_data;
  174. core_dump_crc_t crc = esp_core_dump_calc_flash_config_crc();
  175. if (s_core_flash_config.partition_config_crc != crc) {
  176. ESP_COREDUMP_LOGE("Core dump flash config is corrupted! CRC=0x%x instead of 0x%x", crc, s_core_flash_config.partition_config_crc);
  177. return;
  178. }
  179. // check that partition can hold at least core dump data length
  180. if (s_core_flash_config.partition.start == 0 || s_core_flash_config.partition.size < sizeof(uint32_t)) {
  181. ESP_COREDUMP_LOGE("Invalid flash partition config!");
  182. return;
  183. }
  184. /* init non-OS flash access critical section */
  185. spi_flash_guard_set(&g_flash_guard_no_os_ops);
  186. memset(&wr_cfg, 0, sizeof(wr_cfg));
  187. wr_cfg.prepare = esp_core_dump_flash_write_prepare;
  188. wr_cfg.start = esp_core_dump_flash_write_start;
  189. wr_cfg.end = esp_core_dump_flash_write_end;
  190. wr_cfg.write = esp_core_dump_flash_write_data;
  191. wr_cfg.priv = &wr_data;
  192. ESP_COREDUMP_LOGI("Save core dump to flash...");
  193. esp_core_dump_write((void*)frame, &wr_cfg);
  194. ESP_COREDUMP_LOGI("Core dump has been saved to flash.");
  195. }
  196. #endif