xflash_dump.cpp 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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 "xflash.h"
  7. bool xfdump_check_state()
  8. {
  9. uint32_t magic;
  10. XFLASH_SPI_ENTER();
  11. xflash_rd_data(DUMP_OFFSET + offsetof(dump_t, header.magic),
  12. (uint8_t*)&magic, sizeof(magic));
  13. return magic == DUMP_MAGIC;
  14. }
  15. bool xfdump_check_crash()
  16. {
  17. // check_state will call SPI_ENTER for us
  18. if(!xfdump_check_state())
  19. return false;
  20. uint8_t crash;
  21. xflash_rd_data(DUMP_OFFSET + offsetof(dump_t, header.crash),
  22. (uint8_t*)&crash, sizeof(crash));
  23. return crash;
  24. }
  25. void xfdump_reset()
  26. {
  27. XFLASH_SPI_ENTER();
  28. xflash_enable_wr();
  29. xflash_sector_erase(DUMP_OFFSET + offsetof(dump_t, header.magic));
  30. xflash_wait_busy();
  31. }
  32. static void xfdump_erase()
  33. {
  34. XFLASH_SPI_ENTER();
  35. for(uint32_t addr = DUMP_OFFSET;
  36. addr < DUMP_OFFSET + DUMP_SIZE;
  37. addr += 4096)
  38. {
  39. xflash_enable_wr();
  40. xflash_sector_erase(DUMP_OFFSET);
  41. xflash_wait_busy();
  42. }
  43. }
  44. static void xfdump_dump_core(dump_header_t& hdr, uint32_t addr, uint8_t* buf, uint16_t cnt)
  45. {
  46. XFLASH_SPI_ENTER();
  47. // start by clearing all sectors (we need all of them in any case)
  48. xfdump_erase();
  49. // write header
  50. static_assert(sizeof(hdr) < 256, "header is larger than a single page write");
  51. xflash_enable_wr();
  52. xflash_page_program(DUMP_OFFSET, (uint8_t*)&hdr, sizeof(hdr));
  53. xflash_wait_busy();
  54. // write data
  55. static_assert(sizeof(dump_t::data) <= RAMEND, "dump area size insufficient");
  56. xflash_multipage_program(addr, buf, cnt);
  57. }
  58. void xfdump_dump()
  59. {
  60. dump_header_t buf;
  61. buf.magic = DUMP_MAGIC;
  62. buf.regs_present = false;
  63. buf.crash = false;
  64. // write sram only
  65. xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data.sram),
  66. (uint8_t*)RAMSTART, RAMSIZE);
  67. }
  68. void xfdump_full_dump_and_reset(bool crash)
  69. {
  70. dump_header_t buf;
  71. buf.magic = DUMP_MAGIC;
  72. buf.regs_present = true;
  73. buf.crash = crash;
  74. // disable interrupts for a cleaner register dump
  75. cli();
  76. // write all addressable ranges (this will trash bidirectional registers)
  77. xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data), 0, RAMEND);
  78. // force a reset soon
  79. wdt_enable(0);
  80. while(true);
  81. }
  82. #endif