xflash_dump.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #include <stddef.h>
  2. #include <avr/wdt.h>
  3. #include <avr/interrupt.h>
  4. #include "xflash_dump.h"
  5. #ifdef XFLASH_DUMP
  6. #include "asm.h"
  7. #include "xflash.h"
  8. #include "Marlin.h" // for softReset
  9. bool xfdump_check_state(dump_crash_reason* reason)
  10. {
  11. uint32_t magic;
  12. XFLASH_SPI_ENTER();
  13. xflash_rd_data(DUMP_OFFSET + offsetof(dump_t, header.magic),
  14. (uint8_t*)&magic, sizeof(magic));
  15. if (magic != DUMP_MAGIC)
  16. return false;
  17. if (reason)
  18. {
  19. xflash_rd_data(DUMP_OFFSET + offsetof(dump_t, header.crash_reason),
  20. (uint8_t*)reason, sizeof(*reason));
  21. }
  22. return true;
  23. }
  24. void xfdump_reset()
  25. {
  26. XFLASH_SPI_ENTER();
  27. xflash_enable_wr();
  28. xflash_sector_erase(DUMP_OFFSET + offsetof(dump_t, header.magic));
  29. xflash_wait_busy();
  30. }
  31. static void xfdump_erase()
  32. {
  33. for(uint32_t addr = DUMP_OFFSET;
  34. addr < DUMP_OFFSET + DUMP_SIZE;
  35. addr += 4096)
  36. {
  37. xflash_enable_wr();
  38. xflash_sector_erase(DUMP_OFFSET);
  39. xflash_wait_busy();
  40. }
  41. }
  42. static void __attribute__((noinline)) xfdump_dump_core(dump_header_t& hdr, uint32_t addr, uint8_t* buf, uint16_t cnt)
  43. {
  44. XFLASH_SPI_ENTER();
  45. // start by clearing all sectors (we need all of them in any case)
  46. xfdump_erase();
  47. // sample SP/PC
  48. hdr.sp = SP;
  49. GETPC(&hdr.pc);
  50. // write header
  51. static_assert(sizeof(hdr) <= 256, "header is larger than a single page write");
  52. xflash_enable_wr();
  53. xflash_page_program(DUMP_OFFSET, (uint8_t*)&hdr, sizeof(hdr));
  54. xflash_wait_busy();
  55. // write data
  56. static_assert(sizeof(dump_t::data) <= RAMEND+1, "dump area size insufficient");
  57. xflash_multipage_program(addr, buf, cnt);
  58. }
  59. void xfdump_dump()
  60. {
  61. dump_header_t buf;
  62. buf.magic = DUMP_MAGIC;
  63. buf.regs_present = false;
  64. buf.crash_reason = (uint8_t)dump_crash_reason::manual;
  65. // write sram only
  66. xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data.sram),
  67. (uint8_t*)RAMSTART, RAMSIZE);
  68. }
  69. void xfdump_full_dump_and_reset(dump_crash_reason reason)
  70. {
  71. dump_header_t buf;
  72. buf.magic = DUMP_MAGIC;
  73. buf.regs_present = true;
  74. buf.crash_reason = (uint8_t)reason;
  75. // disable interrupts for a cleaner register dump
  76. cli();
  77. // ensure there's always enough time (with some margin) to dump
  78. // dump time on w25x20cl: ~150ms
  79. wdt_enable(WDTO_500MS);
  80. // write all addressable ranges (this will trash bidirectional registers)
  81. xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data), 0, RAMEND+1);
  82. // force a reset even sooner
  83. softReset();
  84. }
  85. #endif